/* ════════════════════════════════════════════════════════
   SHOEBILL STUDIO — torn paper · cross-stitch · persona cuts
   ════════════════════════════════════════════════════════ */

:root {
  --paper: #d9d4c9;
  --paper-deep: #cdc7ba;
  --ink: #100d0b;
  --ink-soft: #1a1614;
  --red: #a32017;
  --red-bright: #c0392b;
  --red-deep: #7e120d;
  --font-ui: "Jost", sans-serif;
  --font-mono: "DM Mono", monospace;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
  height: 100%;
  overflow: hidden;
  background: var(--ink);
}

body {
  font-family: var(--font-ui);
  color: var(--ink);
  cursor: none;
  user-select: none;
  -webkit-user-select: none;
}

img { -webkit-user-drag: none; }

/* ─────────────── pages ─────────────── */

.page {
  position: fixed;
  inset: 0;
  visibility: hidden;
  overflow: hidden;
  background: var(--paper);
}
.page.is-active { visibility: visible; }
/* PERF: keep the heavy projects page on its own GPU layer so revealing/covering
   it during the 1↔2 transition composites a cached texture instead of repainting
   its bird + blocks + text each frame. (Inactive pages are visibility:hidden, so
   this costs a layer only while page-main is on screen.) */
.page--main { transform: translateZ(0); }

/* ── hero composition stage ──
   Page 01 is authored in cqw/cqh (below) relative to THIS box, not the viewport,
   so the whole composition scales by one factor and never distorts. On desktop
   the box is locked to the screen's aspect ratio (set as --sa-num in JS) and
   fitted into the window, centred — at full screen it equals the viewport (so
   it's pixel-identical to before on any monitor); when the window is narrowed
   the extra space simply becomes more of the beige .paper behind it.
   On phones (≤640px) the @media fit is skipped, so it just fills the viewport
   and the existing phone layout (in the max-width:640px block) takes over. */
.hero-stage {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 100%;
  height: 100%;
  container-type: size;
}
@media (min-width: 641px) {
  /* fill the full viewport WIDTH; only letterbox vertically once the window is
     narrower than the screen aspect. So at full screen / full tab the stage
     equals the viewport (original look — bird flush with the beige blocks), and
     only a reduced/narrow window scales the whole composition down. */
  .hero-stage {
    height: min(100vh, calc(100vw / var(--sa-num, 1.7778)));
    /* own GPU layer so revealing the hero on a transition (esp. page 2→1)
       composites a cached texture instead of re-painting its sub-layers */
    transform: translateZ(0);
  }
}

/* very subtle wall texture on the beige areas */
.paper {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(rgba(217, 212, 201, 0.9), rgba(217, 212, 201, 0.9)),
    url("assets/tex-wall-stucco.jpg") center / cover;
}
.paper::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 70% 60% at 50% 45%, rgba(255, 252, 244, 0.18), transparent 75%),
    radial-gradient(ellipse 60% 50% at 10% 85%, rgba(110, 100, 84, 0.1), transparent 70%);
}

/* black stepped masses — EXACT silhouettes extracted from the mockups */
.blocks-tex {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(rgba(10, 8, 6, 0.42), rgba(10, 8, 6, 0.42)),
    url("assets/tex-paper-black.jpg") center / cover;
  mask-size: 100% 100%;
  -webkit-mask-size: 100% 100%;
  mask-repeat: no-repeat;
  -webkit-mask-repeat: no-repeat;
}
.blocks-tex--hero {
  /* page one: deep black with a subtle real crumpled-paper grain */
  background:
    linear-gradient(rgba(9, 7, 6, 0.8), rgba(9, 7, 6, 0.8)),
    url("assets/tex-black-big.jpg") 41% 50% / cover; /* nudged left */
  mask-image: url("assets/mask-hero.png");
  -webkit-mask-image: url("assets/mask-hero.png");
  z-index: 1;
}
.blocks-tex--projects {
  mask-image: url("assets/mask-projects.png");
  -webkit-mask-image: url("assets/mask-projects.png");
}

/* ─────────────── hero · page 01 ─────────────── */

/* the bird body lives only inside the black blocks… */
.hero-bird-clip {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  mask-image: url("assets/mask-hero.png");
  -webkit-mask-image: url("assets/mask-hero.png");
  mask-size: 100% 100%;
  -webkit-mask-size: 100% 100%;
  mask-repeat: no-repeat;
  -webkit-mask-repeat: no-repeat;
}
/* …while the head peeks out over the beige paper */
.hero-bird-head {
  position: absolute;
  z-index: 3;
  pointer-events: none;
}
.hero-bird-body,
.hero-bird-head {
  position: absolute;
  left: 32cqw;
  /* --bird-top is computed in JS (updateHeroStageFit) from the stage aspect so
     the bird's bottom always lands on the grid's beige edge, at any desktop
     width. The phone layout overrides this with its own top below. */
  top: var(--bird-top, 1cqh);
  width: 68cqw;
}
.hero-bird-body .hero-bird-img,
.hero-bird-head .hero-bird-img {
  display: block;
  width: 100%;
}
.hero-bird-img { filter: brightness(0.94) contrast(1.06) saturate(0.72); }

/* hotspot over the ACTUAL bird (opaque pixels span 26%–67% of this box) */
.head-hotspot {
  position: absolute;
  left: 25%;
  top: 2%;
  width: 44%;
  height: 84%;
  pointer-events: auto;
  cursor: none;
  z-index: 2;
}
/* the head image must not capture the hover — only the hotspot does */
.hero-bird-head .hero-bird-img { pointer-events: none; }

/* glitch layers — both masked to the bird so red never spills onto the paper:
   .glitch-a = grainy red field over the whole bird,
   .glitch-b = jumping brighter-red glitch bars */
.glitch-a,
.glitch-b {
  position: absolute;
  inset: 0;
  visibility: hidden; /* hidden = not painted, but can still fade out */
  opacity: 0;
  /* quick fade-out when the cursor leaves; visibility flips after the fade */
  transition: opacity 0.35s ease, visibility 0s linear 0.35s;
  pointer-events: none;
  /* PERF: no always-on will-change here. These layers are visibility:hidden when
     idle, but a permanent will-change kept two masked, blended backing stores
     (incl. the feTurbulence noise) rasterized at all times — overhead the
     compositor carried through every hero transition. Promotion is applied only
     in the active (hover / .glitching) states below. */
  mask-image: url("assets/bird-p1-head.png");
  -webkit-mask-image: url("assets/bird-p1-head.png");
  mask-size: 100% 100%;
  -webkit-mask-size: 100% 100%;
  mask-repeat: no-repeat;
  -webkit-mask-repeat: no-repeat;
}
/* grainy red: noise multiplied into a red gradient, multiplied over the bird */
.glitch-a {
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='1' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)'/%3E%3C/svg%3E"),
    linear-gradient(#d11b0e, #8e1109);
  background-size: 170px 170px, 100% 100%;
  background-blend-mode: multiply; /* static — baked into the bg raster, fine */
  /* PERF: mix-blend-mode removed — a live blend on an animating, masked layer
     forced a backdrop re-composite every frame (a big part of the hover lag).
     Now a plain semi-transparent grain overlay; opacity is tuned on hover. */
}
/* bright-red slice that jumps around for the glitch flicker */
.glitch-b {
  background: #f2473a;
  /* PERF: mix-blend-mode:screen removed (same reason as above). A static band
     that is jumped around with transform (see glitch-bars) — GPU-cheap. */
  clip-path: inset(34% 0 46% 0);
}
/* same glitch on the body — masked to the body png instead of the head */
.glitch-body {
  mask-image: url("assets/bird-p1-body.png");
  -webkit-mask-image: url("assets/bird-p1-body.png");
}
/* hovering the head hotspot glitches the WHOLE bird (head + body) */
.page--hero:has(.head-hotspot:hover) .glitch-a {
  visibility: visible;
  opacity: 0.5; /* lower now that it's a plain overlay (was multiply-blended) */
  transition: opacity 0.25s ease, visibility 0s; /* quick ease-in */
  animation: glitch-grain 0.34s linear infinite;
}
.page--hero:has(.head-hotspot:hover) .glitch-b {
  visibility: visible;
  opacity: 0.55;
  transition: opacity 0.25s ease, visibility 0s;
  animation: glitch-bars 0.48s linear infinite;
}
/* touch: tap toggles .glitching (JS) since there is no hover */
.page--hero.glitching .glitch-a {
  visibility: visible;
  opacity: 0.5;
  transition: opacity 0.25s ease, visibility 0s;
  animation: glitch-grain 0.34s linear infinite;
}
.page--hero.glitching .glitch-b {
  visibility: visible;
  opacity: 0.55;
  transition: opacity 0.25s ease, visibility 0s;
  animation: glitch-bars 0.48s linear infinite;
}
/* promote only while actually glitching (hover / tap) — smooth animation
   without the permanent idle layer cost */
.page--hero:has(.head-hotspot:hover) .glitch-a,
.page--hero:has(.head-hotspot:hover) .glitch-b,
.page--hero.glitching .glitch-a,
.page--hero.glitching .glitch-b {
  will-change: transform;
}
@keyframes glitch-grain {
  /* PERF: transform-only, GPU-composited (translate3d). FLUID: linear-interpolated
     with extra keyframes + a seamless 0%/100% loop, so the grain field drifts
     smoothly every frame instead of snapping between 2 stepped positions. */
  0%   { transform: translate3d(0, 0, 0); }
  20%  { transform: translate3d(-1%, 0.5%, 0); }
  40%  { transform: translate3d(0.7%, -0.6%, 0); }
  60%  { transform: translate3d(-0.6%, 0.7%, 0); }
  80%  { transform: translate3d(0.9%, -0.3%, 0); }
  100% { transform: translate3d(0, 0, 0); }
}
@keyframes glitch-bars {
  /* PERF: transform-only, GPU-composited — the static red band on .glitch-b is
     displaced around the bird (the mask rides along). FLUID: linear interpolation
     + a 100% keyframe back to the start makes the band glide continuously instead
     of hard-jumping between 5 stepped positions. */
  0%   { transform: translate3d(-3%, -24%, 0); }
  20%  { transform: translate3d(4%, 6%, 0); }
  40%  { transform: translate3d(-2%, 22%, 0); }
  60%  { transform: translate3d(5%, -12%, 0); }
  80%  { transform: translate3d(-4%, 14%, 0); }
  100% { transform: translate3d(-3%, -24%, 0); }
}

.hero-left {
  position: absolute;
  left: 6cqw;
  top: 20cqh;
  width: 34cqw;
  z-index: 4;
}
.hero-name {
  margin-bottom: 0.4cqh;
  color: var(--red);
  font-weight: 800;
  font-style: italic;
  font-size: clamp(13px, 2.5cqh, 27px);
  letter-spacing: 0.16em;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.45);
}
.stitch-title {
  display: block;
  width: 100%;
}
.hero-sub {
  margin-top: 2.4cqh;
  font-family: var(--font-mono);
  font-size: clamp(11px, 2.1cqh, 22px);
  letter-spacing: 0.3em;
  color: var(--red-bright);
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.45);
  white-space: nowrap;
}

.hero-scroll {
  position: absolute;
  left: 6cqw;
  bottom: 8cqh;
  z-index: 4;
  font-weight: 400;
  font-size: clamp(13px, 2.5cqh, 26px);
  line-height: 1.45;
  letter-spacing: 0.04em;
}
.scroll-arrow {
  display: inline-block;
  margin-top: 1vh;
  font-size: 1.15em;
  animation: bob 1.8s ease-in-out infinite;
}
.scroll-arrow--red { color: var(--red); font-weight: 600; }
@keyframes bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(0.5em); }
}

.hero-right {
  position: absolute;
  right: 7cqw;
  bottom: 14cqh;
  z-index: 4;
  text-align: center;
}
/* .motto + .page-num are shared with other pages, so scope the hero overrides
   to the stage (container units) without touching the projects/contact uses */
.hero-stage .motto {
  font-size: clamp(10px, min(2.2cqh, 1.25cqw), 24px);
}
.hero-stage .page-num {
  right: 4.5cqw;
  bottom: 4cqh;
}

.motto {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.45em;
  font-weight: 500;
  font-size: clamp(10px, min(2.2vh, 1.25vw), 24px);
  letter-spacing: 0.18em;
}
.motto em {
  font-style: normal;
  color: var(--red);
  font-size: 0.8em;
}
.maya {
  margin-top: 4cqh;
  font-weight: 400;
  font-size: clamp(10px, min(2cqh, 1.1cqw), 21px);
  line-height: 1.6;
  letter-spacing: 0.05em;
}

.page-num {
  position: absolute;
  right: 4.5vw;
  bottom: 4vh;
  z-index: 4;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.25em;
  opacity: 0.55;
}
.page-num span { color: var(--red); }

/* burger */
.burger {
  position: fixed;
  top: 5vh;
  right: 4.5vw;
  z-index: 60;
  width: 44px;
  height: 34px;
  background: none;
  border: 0;
  cursor: none;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 7px;
}
.burger span {
  display: block;
  height: 3px;
  width: 100%;
  background: var(--ink);
  transition: transform 0.35s cubic-bezier(0.7, 0, 0.2, 1), opacity 0.25s, background 0.3s;
}
.burger.is-light span { background: var(--paper); }
.burger.is-white span { background: #ffffff; }
.burger.is-open span { background: var(--paper); }
.burger.is-open span:nth-child(1) { transform: translateY(10px) rotate(45deg); }
.burger.is-open span:nth-child(2) { opacity: 0; }
.burger.is-open span:nth-child(3) { transform: translateY(-10px) rotate(-45deg); }

/* ─────────────── projects · page 02 ─────────────── */

.proj-bird-stage {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 2;
}
.proj-bird {
  position: absolute;
  left: 50%;
  top: 51%;
  width: min(77vw, 140vh);
  transform: translate(-50%, -50%);
  filter: brightness(0.97) contrast(1.05);
  pointer-events: auto;
  cursor: none;
  transition: transform 0.3s cubic-bezier(0.3, 1, 0.4, 1);
}
/* hovering the bird OR the stitched "PROJECTS" grows it slightly */
.proj-bird.bigger { transform: translate(-50%, -50%) scale(1.06); }
/* reveal: grows slightly, settles, then fully static (smaller + faster) */
.proj-bird-stage.grown .proj-bird {
  animation: bird-reveal 0.78s cubic-bezier(0.22, 0.9, 0.3, 1) both;
}
@keyframes bird-reveal {
  0%   { transform: translate(-50%, -50%) scale(0.97); }
  62%  { transform: translate(-50%, -50%) scale(1.012); }
  100% { transform: translate(-50%, -50%) scale(1); }
}

.stitch-projects {
  position: absolute;
  left: 22vw;
  top: 41vh;
  z-index: 3;
  pointer-events: auto;
  cursor: none;
}

.proj-head {
  position: absolute;
  left: 3vw;
  top: 6vh;
  z-index: 4;
}
.proj-head h1 {
  font-weight: 600;
  font-size: clamp(14px, min(2.7vh, 1.5vw), 30px);
  letter-spacing: 0.06em;
}
.proj-head p {
  margin-top: 0.7vh;
  font-weight: 500;
  font-size: clamp(10px, 1.5vh, 16px);
  letter-spacing: 0.04em;
}

.proj-disciplines {
  position: absolute;
  right: 2vw;
  top: 12vh;
  z-index: 4;
  text-align: left;
}
.proj-disciplines h2 {
  font-weight: 600;
  font-size: clamp(11px, min(2.1vh, 1.18vw), 23px);
  letter-spacing: 0.1em;
  margin-bottom: 2.2vh;
}
.proj-disciplines li {
  list-style: none;
  font-weight: 500;
  font-size: clamp(8px, min(1.7vh, 0.95vw), 18px);
  letter-spacing: 0.08em;
  line-height: 1.72;
}

.proj-motto {
  position: absolute;
  right: 3vw;
  top: 51.5vh;
  z-index: 4;
}

.proj-statement {
  position: absolute;
  left: 3.9vw;
  top: 66.5vh;
  z-index: 4;
  font-weight: 500;
  font-size: clamp(11px, min(2.1vh, 1.18vw), 23px);
  letter-spacing: 0.08em;
  line-height: 1.32;
}

/* scroll-to-discover — bold, hard to miss, jumps to SELECTED */
.proj-scroll {
  position: absolute;
  left: 3.6vw;
  bottom: 4vh;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 1.1vw;
  background: none;
  border: 0;
  cursor: none;
  transition: transform 0.2s ease;
}
.proj-scroll > span:first-child {
  display: inline-block;
  padding: 1.2vh 1.5vw;
  background: var(--ink);
  color: #f3efe6;
  font-weight: 800;
  font-style: italic;
  font-size: clamp(12px, min(2vh, 1.05vw), 20px);
  letter-spacing: 0.14em;
  line-height: 1.18;
  text-align: left;
  clip-path: polygon(0 8%, 97% 0, 100% 90%, 3% 100%);
  box-shadow: 5px 5px 0 var(--red);
}
.proj-scroll .scroll-arrow--red {
  font-size: clamp(26px, 5vh, 52px);
  color: var(--red);
  font-weight: 700;
}
.proj-scroll:hover { transform: translateX(0.4vw) scale(1.04); }

.proj-services {
  position: absolute;
  left: 81vw;
  top: 70.5vh;
  z-index: 4;
  list-style: none;
}
.proj-services li {
  font-weight: 500;
  font-size: clamp(8px, min(1.4vh, 0.78vw), 14px);
  letter-spacing: 0.05em;
  line-height: 1.72;
}

/* ─────────────── combined page 02 · PROJECTS + SELECTED ─────────────── */

.main-scroll {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
  z-index: 3;
  scrollbar-width: thin;
  scrollbar-color: var(--red) transparent;
}
.main-scroll::-webkit-scrollbar { width: 8px; }
.main-scroll::-webkit-scrollbar-thumb { background: var(--red); }

/* projects fills the first viewport; absolute children align to it */
.proj-view {
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: hidden;
}
.works-view {
  position: relative;
  width: 100%;
  min-height: 100vh;
  /* no beige strip below the bar — the contact bar sits flush at the bottom */
  padding-bottom: 0;
  overflow: hidden;
}

.works-head {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: flex-end;
  gap: 4vw;
  padding: 7vh 0 0 4vw;
}
.stitch-selected { display: block; width: 26vw; }
.works-surprise {
  padding-bottom: 1.4vh;
  font-family: var(--font-mono);
  font-size: clamp(11px, 1.9vh, 18px);
  letter-spacing: 0.3em;
  color: var(--ink);
  background: none;
  border: 0;
  cursor: none;
  transition: color 0.2s ease, transform 0.2s ease;
}
.works-surprise:hover { color: var(--red); transform: translateX(0.3vw); }

/* DEMO REELS! — red-outline button at the right corner of the title row */
/* same look as the PLAY!? buttons: ink slab over an offset red slab */
.reels-btn {
  margin-left: auto;
  margin-right: 16vw;
  margin-bottom: 1vh;
  background: none;
  border: 0;
  cursor: none;
  transform: rotate(-5deg);
  transition: transform 0.18s cubic-bezier(0.5, 1.6, 0.4, 1);
}
.reels-btn span {
  position: relative;
  display: inline-block;
  padding: 1.7vh 2.3vw;
  background: var(--ink);
  color: #f3efe6;
  font-weight: 800;
  font-style: italic;
  font-size: clamp(16px, 2.9vh, 30px);
  letter-spacing: 0.06em;
  clip-path: polygon(0 4%, 97% 0, 100% 92%, 3% 100%);
  /* crisp black outline hugging the slanted shape (border gets cut by clip-path) */
  filter:
    drop-shadow(2px 0 0 #000) drop-shadow(-2px 0 0 #000)
    drop-shadow(0 2px 0 #000) drop-shadow(0 -2px 0 #000);
  transition: background 0.18s ease, color 0.18s ease;
}
.reels-btn span::before {
  content: "";
  position: absolute;
  inset: -4px -8px;
  z-index: -1;
  background: var(--red);
  transform: rotate(2.4deg) translate(5px, 5px);
  clip-path: polygon(2% 8%, 98% 0, 100% 88%, 4% 100%, 0 60%);
}
.reels-btn:hover { transform: rotate(-2deg) scale(1.07); }
.reels-btn:hover span { background: var(--red); }

.works-grid {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 7vw;
  row-gap: 11vh;
  width: 86vw;
  margin: 8vh auto 0;
}

.work-frame {
  position: relative;
  aspect-ratio: 16 / 10;
  background: #1b1613;
  box-shadow:
    -14px 14px 0 #0c0a09,
    10px -10px 0 #26201b;
  cursor: none;
  transition: transform 0.2s ease;
}
.work-frame:hover { transform: translateY(-4px); }
/* coverless projects: a plain blank-colour placeholder (no drop UI) */
.work-frame--blank { background: #2a2622; }
.work-frame.has-img { background-size: cover; background-position: center; }
.work-frame.drag-over { outline: 3px dashed var(--red-bright); outline-offset: 6px; }
/* "coming soon" preview frames: cover shows, but they're inert (no hover lift) */
.work-frame--soon:hover { transform: none; }

.work-label {
  position: absolute;
  left: 0;
  bottom: -5.4vh;
  font-weight: 600;
  font-size: clamp(10px, 1.6vh, 16px);
  letter-spacing: 0.26em;
}
.work-label b { color: var(--red); margin-right: 1.2em; font-weight: 600; }

.works-foot { height: 6vh; }

/* contact bottom bar — red/black paper slab closing the SELECTED page */
.contact-bar {
  position: relative;
  margin-top: 11vh;
  padding: 5vh 6vw;
  background:
    linear-gradient(rgba(13, 10, 9, 0.9), rgba(13, 10, 9, 0.9)),
    url("assets/tex-paper-black.jpg") center / cover;
  border-top: 4px solid var(--red);
  display: flex;
  align-items: center;
  gap: 4vw;
  overflow: hidden;
  clip-path: polygon(0 14%, 100% 0, 100% 100%, 0 100%);
}
.contact-bar__title {
  position: relative;
  z-index: 2;
  background: none;
  border: 0;
  cursor: none;
  transform: rotate(-3deg);
  transition: transform 0.18s cubic-bezier(0.5, 1.6, 0.4, 1);
}
.contact-bar__title span {
  display: inline-block;
  padding: 1.5vh 2.6vw;
  background: var(--red);
  color: #f3efe6;
  font-weight: 800;
  font-style: italic;
  font-size: clamp(20px, 4vh, 40px);
  letter-spacing: 0.08em;
  clip-path: polygon(0 10%, 97% 0, 100% 90%, 3% 100%);
  box-shadow: 6px 6px 0 var(--ink);
}
.contact-bar__title:hover { transform: rotate(-1deg) scale(1.06); }
.contact-bar__info { position: relative; z-index: 2; }
.contact-bar__name {
  color: #f3efe6;
  font-weight: 600;
  font-size: clamp(14px, 2.3vh, 24px);
  letter-spacing: 0.1em;
}
.contact-bar__mail {
  display: inline-block;
  margin-top: 1.1vh;
  color: var(--red-bright);
  font-family: var(--font-mono);
  font-size: clamp(11px, 1.8vh, 18px);
  letter-spacing: 0.06em;
  text-decoration: none;
}
.contact-bar__mail:hover { color: #f2473a; }
/* yellow logo, desaturated + faint, sitting in the background to the right */
.contact-bar__logo {
  position: absolute;
  right: 1vw;
  top: 50%;
  transform: translateY(-50%);
  height: 90%;
  opacity: 0.07;
  filter: grayscale(1) brightness(1.4);
  pointer-events: none;
  z-index: 1;
}

/* ─────────────── PLAY!? buttons · persona 5 style ─────────────── */

.play-btn,
.hall-play {
  background: none;
  border: 0;
  cursor: none;
  transition: transform 0.18s cubic-bezier(0.5, 1.6, 0.4, 1);
}
.play-btn {
  position: relative;
  display: block;
  margin: 16vh auto 0;
  transform: rotate(-7deg);
}
.play-btn:hover {
  animation: play-wiggle 0.5s ease-in-out infinite;
  filter: drop-shadow(0 0 16px rgba(192, 57, 43, 0.6));
}
@keyframes play-wiggle {
  0%, 100% { transform: rotate(-6deg) scale(1.08); }
  25%      { transform: rotate(-10deg) scale(1.12) translateY(-3px); }
  50%      { transform: rotate(-4deg) scale(1.1); }
  75%      { transform: rotate(-9deg) scale(1.13) translateY(-2px); }
}
.play-btn.highlight { animation: play-flash 1.1s ease-out; }
@keyframes play-flash {
  0%, 100% { transform: rotate(-7deg) scale(1); filter: none; }
  20%      { transform: rotate(-3deg) scale(1.16); filter: drop-shadow(0 0 22px rgba(192, 57, 43, 0.9)); }
  55%      { transform: rotate(-9deg) scale(1.04); filter: drop-shadow(0 0 10px rgba(192, 57, 43, 0.5)); }
}
.play-btn i,
.hall-play i {
  position: absolute;
  inset: -4px -8px;
  background: var(--red);
  transform: rotate(2.4deg) translate(5px, 5px);
  clip-path: polygon(2% 8%, 98% 0, 100% 88%, 4% 100%, 0 60%);
}
.play-btn span,
.hall-play span {
  position: relative;
  display: inline-block;
  padding: 1.6vh 2.6vw;
  background: var(--ink);
  color: #f3efe6;
  font-family: var(--font-ui);
  font-weight: 800;
  font-style: italic;
  font-size: clamp(20px, 4.2vh, 44px);
  letter-spacing: 0.06em;
  clip-path: polygon(0 4%, 97% 0, 100% 92%, 3% 100%);
}

/* ─────────────── hall · page 04 ─────────────── */

.page--hall { background: #0c0a09; }
#hall-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

.hall-back {
  position: absolute;
  top: 4vh;
  left: 3vw;
  z-index: 8;
  background: none;
  border: 0;
  cursor: none;
  transform: rotate(-3deg);
  transition: transform 0.18s ease;
}
.hall-back span {
  display: inline-block;
  padding: 1.3vh 1.6vw;
  background: var(--ink);
  color: #f3efe6;
  font-weight: 800;
  font-style: italic;
  font-size: clamp(13px, 2.2vh, 22px);
  letter-spacing: 0.1em;
  clip-path: polygon(0 12%, 96% 0, 100% 86%, 5% 100%);
  box-shadow: 4px 4px 0 var(--red);
}
.hall-back:hover { transform: rotate(-1deg) scale(1.06); }

.hall-play {
  position: absolute;
  left: 50%;
  top: 5vh;
  display: none;
  transform: translateX(-50%) rotate(-7deg);
}
.hall-play:hover { transform: translateX(-50%) rotate(-4deg) scale(1.07); }
.hall-play.is-on { display: block; animation: play-pop 0.35s cubic-bezier(0.3, 1.6, 0.4, 1) both; }
@keyframes play-pop {
  from { transform: translateX(-50%) rotate(-14deg) scale(0.4); opacity: 0; }
  to   { transform: translateX(-50%) rotate(-7deg) scale(1); opacity: 1; }
}
/* lively wiggle + red glow while hovering WATCH!? */
.hall-play.is-on:hover {
  animation: watch-wiggle 0.5s ease-in-out infinite;
  filter: drop-shadow(0 0 16px rgba(192, 57, 43, 0.75));
}
@keyframes watch-wiggle {
  0%, 100% { transform: translateX(-50%) rotate(-6deg) scale(1.08); }
  25%      { transform: translateX(-50%) rotate(-10deg) scale(1.12) translateY(-3px); }
  50%      { transform: translateX(-50%) rotate(-3deg) scale(1.1); }
  75%      { transform: translateX(-50%) rotate(-9deg) scale(1.13) translateY(-2px); }
}
/* WATCH over a coming-soon painting → static greyed "COMING SOON" (unclickable):
   drop the red play tab, grey the slab, and kill the hover wiggle/glow */
.hall-play.is-soon i { display: none; }
.hall-play.is-soon span { background: #2a2622; color: #9c948a; }
.hall-play.is-on.is-soon:hover {
  animation: none;
  filter: none;
  transform: translateX(-50%) rotate(-7deg);
}

/* LEAVE! — appears near the door (top, like WATCH!?), exits to SELECTED */
.hall-leave {
  position: absolute;
  left: 50%;
  top: 5vh;
  z-index: 8;
  display: none;
  background: none;
  border: 0;
  cursor: none;
  transform: translateX(-50%) rotate(-7deg);
  transition: transform 0.18s cubic-bezier(0.5, 1.6, 0.4, 1);
}
.hall-leave.is-on { display: block; animation: play-pop 0.35s cubic-bezier(0.3, 1.6, 0.4, 1) both; }
.hall-leave:hover { transform: translateX(-50%) rotate(-4deg) scale(1.07); }
/* same look as the top-left GO BACK */
.hall-leave span {
  display: inline-block;
  padding: 1.3vh 1.8vw;
  background: var(--ink);
  color: #f3efe6;
  font-weight: 800;
  font-style: italic;
  font-size: clamp(13px, 2.2vh, 22px);
  letter-spacing: 0.1em;
  clip-path: polygon(0 12%, 96% 0, 100% 86%, 5% 100%);
  box-shadow: 4px 4px 0 var(--red);
}

.hall-hint {
  position: absolute;
  left: 50%;
  bottom: 4vh;
  z-index: 8;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5vh;
  transform: translateX(-50%) rotate(-2.4deg);
  pointer-events: none;
}
.hall-hint span {
  display: inline-block;
  white-space: nowrap;
  padding: 1.4vh 2.4vw;
  background: var(--ink);
  border: 3px solid var(--red);
  color: #ffffff;
  font-weight: 800;
  font-style: italic;
  font-size: clamp(11px, 2vh, 22px);
  letter-spacing: 0.14em;
  clip-path: polygon(1% 10%, 99% 0, 100% 90%, 0 100%);
  box-shadow: 5px 5px 0 rgba(163, 32, 23, 0.45);
}
/* smaller second line, same chip format */
.hall-hint .hall-hint__sub {
  padding: 0.9vh 1.8vw;
  border-width: 2px;
  font-size: clamp(9px, 1.5vh, 16px);
  letter-spacing: 0.12em;
  box-shadow: 4px 4px 0 rgba(163, 32, 23, 0.4);
}

/* project viewer — replicates the "hall video UI" mockup */
.hall-viewer {
  position: absolute;
  inset: 0;
  z-index: 12;
  display: none;
  align-items: center;
  justify-content: center;
  /* darker red fills one half, split by a diagonal line — behind the star */
  background: linear-gradient(122deg, #4a0c08 0 50%, #0a0807 50% 100%);
  overflow: hidden;
}
.hall-viewer.is-on { display: flex; }

/* big dark-red star, spinning slowly */
.hall-viewer__star {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 160vmin;
  height: 160vmin;
  margin: -80vmin 0 0 -80vmin;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cpolygon fill='%23611009' points='50,2 58,38 86,14 64,44 98,50 64,56 86,86 58,62 50,98 42,62 14,86 36,56 2,50 36,44 14,14 42,38'/%3E%3C/svg%3E") center / contain no-repeat;
  opacity: 0.85;
  animation: star-spin 70s linear infinite;
}
@keyframes star-spin { to { transform: rotate(360deg); } }

.hall-viewer__card {
  position: relative;
  width: min(88vw, 1200px);
  min-height: 0;            /* hug the video + title (descriptions removed) */
  background: rgba(12, 9, 8, 0.82);
  backdrop-filter: blur(2px);
  border-radius: 10px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.8);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 5vh 3vw 4.5vh;
}
.hall-viewer__tag {
  position: absolute;
  top: 3.4vh;
  left: 2.4vw;
  padding: 0.9vh 1.3vw;
  background: #0b0908;
  color: #f3efe6;
  font-weight: 800;
  font-style: italic;
  font-size: clamp(11px, 1.9vh, 19px);
  letter-spacing: 0.18em;
}
.hall-viewer__close {
  position: absolute;
  top: 3.4vh;
  right: 2.4vw;
  background: none;
  border: 0;
  cursor: none;
  color: #f3efe6;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: clamp(11px, 1.9vh, 19px);
  letter-spacing: 0.22em;
  transition: color 0.2s;
}
.hall-viewer__close:hover { color: var(--red-bright); }

.hall-viewer__body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2.6vh;
  text-align: center;
  width: 100%;
}
/* placeholder text removed — only video + title + description show */
.hall-viewer__xxx,
.hall-viewer__note { display: none; }
.hall-viewer__body h3 {
  color: #ffffff;
  font-weight: 800;
  font-size: clamp(16px, 2.8vh, 30px);
  letter-spacing: 0.2em;
}
.hall-viewer__note {
  color: #b6afa5;
  font-size: clamp(11px, 1.8vh, 17px);
  letter-spacing: 0.06em;
  line-height: 1.9;
}
.hall-viewer__note code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: #241a18;
  color: #d7826f;
  padding: 0.25em 0.7em;
  border-radius: 4px;
}
#hall-viewer-video {
  display: none;
  order: -1; /* video sits on top, title below */
  width: min(100%, 1060px);
  max-height: 62vh;
  background: #000;
  border-radius: 4px;
}
.hall-viewer.has-video #hall-viewer-video { display: block; }
.hall-viewer.has-video .hall-viewer__note,
.hall-viewer.has-video .hall-viewer__xxx { display: none; }

/* per-project title + description (same content as the Selections overlay) */
.hall-viewer__desc {
  display: none;
  max-width: 70ch;
  color: #c9c2b8;
  font-size: clamp(11px, 1.75vh, 17px);
  letter-spacing: 0.04em;
  line-height: 1.85;
  text-align: left;
  white-space: pre-line;
}
.hall-viewer.has-info .hall-viewer__desc { display: block; }
.hall-viewer.has-info .hall-viewer__body h3 {
  color: var(--red-bright);
  font-style: italic;
  letter-spacing: 0.12em;
}
.hall-viewer__card { max-height: 90vh; }
.hall-viewer__body { overflow-y: auto; max-height: 84vh; scrollbar-width: thin; scrollbar-color: var(--red) transparent; }

/* ─────────────── overlays · project viewer + demo reels ─────────────── */

.overlay {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(7, 5, 4, 0.94);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s ease, visibility 0s linear 0.3s;
}
.overlay.is-on {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.3s ease, visibility 0s;
}
.overlay__close {
  position: absolute;
  top: 4vh;
  right: 4vw;
  z-index: 2;
  background: none;
  border: 0;
  cursor: none;
  color: var(--red-bright);
  font-size: clamp(26px, 4.6vh, 46px);
  font-weight: 700;
  line-height: 1;
  transition: transform 0.2s ease, color 0.2s ease;
}
.overlay__close:hover { color: #f2473a; transform: rotate(90deg) scale(1.15); }

.overlay__inner {
  width: min(86vw, 1040px);
  max-height: 88vh;
  overflow-y: auto;
  padding: 4vh 0;
  scrollbar-width: thin;
  scrollbar-color: var(--red) transparent;
}
.overlay__inner::-webkit-scrollbar { width: 8px; }
.overlay__inner::-webkit-scrollbar-thumb { background: var(--red); }

#proj-overlay-video {
  display: block;
  width: 100%;
  max-height: 58vh;
  background: #000;
  box-shadow: -12px 12px 0 rgba(163, 32, 23, 0.5);
}
.overlay__title {
  margin-top: 4.2vh;
  color: var(--red-bright);
  font-weight: 800;
  font-style: italic;
  font-size: clamp(22px, 4.4vh, 46px);
  letter-spacing: 0.1em;
}
.overlay__text {
  margin-top: 2.6vh;
  max-width: 72ch;
  color: #d9d4c9;
  font-size: clamp(12px, 1.95vh, 18px);
  letter-spacing: 0.03em;
  line-height: 1.85;
}
/* project stills — stacked full-width below the text */
.overlay__images {
  display: flex;
  flex-direction: column;
  gap: 3vh;
  margin-top: 3.4vh;
}
.overlay__images img {
  display: block;
  width: 100%;
  height: auto;
  box-shadow: -10px 10px 0 rgba(163, 32, 23, 0.4);
}

/* demo reels */
.overlay__inner--reels {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6vh;
  overflow: visible;
}
.stitch-reels { display: block; }
.reels-btns {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4.4vh;
}
.reel-btn {
  background: none;
  border: 0;
  cursor: none;
  transform: rotate(-2deg);
  transition: transform 0.18s cubic-bezier(0.5, 1.6, 0.4, 1);
}
.reel-btn:nth-child(2) { transform: rotate(1.6deg); }
.reel-btn span {
  display: inline-block;
  padding: 1.8vh 3vw;
  background: var(--ink);
  border: 3px solid var(--red);
  color: #f3efe6;
  font-weight: 800;
  font-style: italic;
  font-size: clamp(18px, 3.4vh, 36px);
  letter-spacing: 0.1em;
  clip-path: polygon(0 8%, 97% 0, 100% 90%, 3% 100%);
  box-shadow: 6px 6px 0 rgba(163, 32, 23, 0.45);
  transition: background 0.18s ease, color 0.18s ease;
}
.reel-btn:hover { transform: rotate(0deg) scale(1.08); }
.reel-btn:hover span { background: var(--red); }
.reel-btn small {
  display: block;
  margin-top: 1vh;
  font-family: var(--font-mono);
  font-size: clamp(9px, 1.4vh, 13px);
  letter-spacing: 0.3em;
  color: var(--red-bright);
}
.reel-btn.is-soon span { opacity: 0.55; }

/* ─────────────── contact · page 03 ─────────────── */

/* big tilted black slab anchoring the form, persona-style */
.contact-slab {
  position: absolute;
  right: -6vw;
  top: -8vh;
  width: 64vw;
  height: 120vh;
  background:
    linear-gradient(rgba(10, 8, 6, 0.55), rgba(10, 8, 6, 0.55)),
    url("assets/tex-paper-black.jpg") center / cover;
  clip-path: polygon(22% 0, 100% 0, 100% 100%, 2% 100%, 14% 64%, 6% 30%);
  box-shadow: -14px 0 0 rgba(163, 32, 23, 0.55);
}
/* faint tilted logo watermark on the beige (left) side — stylised, off-centre.
   no z-index: it sits above .paper but behind the slab/×/title in DOM order. */
.contact-logo {
  position: absolute;
  left: -2vw;
  bottom: -7vh;
  height: 68vh;
  width: auto;
  transform: rotate(-13deg);
  opacity: 0.16;
  pointer-events: none;
  user-select: none;
}
.contact-x {
  position: absolute;
  color: var(--red);
  font-weight: 700;
  opacity: 0.8;
  z-index: 2;
}
.contact-x--1 { left: 40vw; top: 12vh; font-size: 5vh; transform: rotate(-12deg); }
.contact-x--2 { left: 7vw; bottom: 10vh; font-size: 3.4vh; transform: rotate(9deg); opacity: 0.45; }

.contact-head {
  position: absolute;
  left: 6vw;
  top: 14vh;
  width: 38vw;
  z-index: 3;
}
.stitch-contact { display: block; width: 100%; }
.contact-mail {
  display: inline-flex;
  align-items: center;
  gap: 0.8em;
  margin-top: 3.6vh;
  padding: 1.2vh 1.4vw;
  background: var(--ink);
  color: #f3efe6;
  font-family: var(--font-mono);
  font-size: clamp(10px, 1.75vh, 17px);
  letter-spacing: 0.12em;
  text-decoration: none;
  cursor: none;
  transform: rotate(-1.6deg);
  clip-path: polygon(0 12%, 98% 0, 100% 86%, 2% 100%);
  box-shadow: 5px 5px 0 var(--red);
  transition: transform 0.2s ease;
}
.contact-mail em { font-style: normal; color: var(--red-bright); font-size: 0.85em; }
.contact-mail:hover { transform: rotate(0.4deg) scale(1.04); }

.contact-form {
  position: absolute;
  right: 7vw;
  top: 13vh;
  width: min(34vw, 560px);
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: 3vh;
}
.cf-field { display: flex; flex-direction: column; gap: 1vh; }
.cf-field span {
  color: #f3efe6;
  font-weight: 800;
  font-style: italic;
  font-size: clamp(11px, 1.9vh, 19px);
  letter-spacing: 0.16em;
}
.cf-field input,
.cf-field textarea {
  background: rgba(243, 239, 230, 0.95);
  border: 3px solid var(--ink);
  outline: none;
  padding: 1.4vh 1vw;
  font-family: var(--font-mono);
  font-size: clamp(11px, 1.8vh, 17px);
  letter-spacing: 0.05em;
  color: var(--ink);
  cursor: none;
  clip-path: polygon(0 6%, 99.4% 0, 100% 94%, 0.6% 100%);
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
  resize: none;
}
.cf-field input:focus,
.cf-field textarea:focus {
  border-color: var(--red-bright);
  box-shadow: 4px 4px 0 rgba(163, 32, 23, 0.55);
}
.cf-field input::placeholder,
.cf-field textarea::placeholder { color: rgba(16, 13, 11, 0.4); }

.send-btn {
  position: relative;
  align-self: flex-end;
  margin-top: 0.6vh;
  background: none;
  border: 0;
  cursor: none;
  transform: rotate(-4deg);
  transition: transform 0.18s cubic-bezier(0.5, 1.6, 0.4, 1);
}
.send-btn:hover { transform: rotate(-2deg) scale(1.08); }
.send-btn i {
  position: absolute;
  inset: -4px -8px;
  background: var(--red);
  transform: rotate(2deg) translate(4px, 4px);
  clip-path: polygon(2% 8%, 98% 0, 100% 88%, 4% 100%, 0 60%);
}
.send-btn span {
  position: relative;
  display: inline-block;
  padding: 1.3vh 2vw;
  background: var(--ink);
  color: #f3efe6;
  font-weight: 800;
  font-style: italic;
  font-size: clamp(16px, 3vh, 32px);
  letter-spacing: 0.08em;
  clip-path: polygon(0 4%, 97% 0, 100% 92%, 3% 100%);
}
.send-btn:disabled { opacity: 0.5; pointer-events: none; }

/* Cloudflare Turnstile widget (between the message field and SEND) */
.cf-turnstile { margin-top: 0.4vh; min-height: 65px; }

/* contact form status line (success / error / sending) */
.cf-status {
  align-self: flex-end;
  margin-top: -0.4vh;
  max-width: 100%;
  text-align: right;
  font-family: var(--font-mono);
  font-size: clamp(11px, 1.7vh, 16px);
  letter-spacing: 0.03em;
  line-height: 1.45;
  min-height: 1.2em;
  color: #cdc6bb;
}
.cf-status--ok  { color: #7bd88f; }
.cf-status--err { color: #ff6b5e; }

.contact-foot {
  position: absolute;
  left: 6vw;
  bottom: 6vh;
  z-index: 3;
  font-weight: 600;
  font-size: clamp(10px, 1.7vh, 17px);
  letter-spacing: 0.2em;
}
.contact-foot em { font-style: normal; color: var(--red); }

/* ─────────────── curtain · radial paper sweep ─────────────── */

.curtain {
  position: fixed;
  inset: 0;
  z-index: 40;
  pointer-events: none;
  visibility: hidden;
}
.curtain.is-on { visibility: visible; }
.curtain svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* PERF: give the sweeping SVG its own GPU layer so its per-frame path repaints
     stay isolated and don't drag the heavy hero backdrop (masked blocks + bird)
     into the repaint each frame. No visual effect (0 translation). The parent
     .curtain is visibility:hidden when idle, so this costs nothing off-transition. */
  transform: translateZ(0);
}

.curtain__banner {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 41;
  transform: translate(-50%, -50%) rotate(-7deg);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6vh;
  opacity: 0;
  pointer-events: none;
}
.curtain__banner.flash { animation: banner-flash 1s ease-out both; }
@keyframes banner-flash {
  0%   { opacity: 0; transform: translate(-65%, -50%) rotate(-7deg); }
  18%  { opacity: 1; }
  70%  { opacity: 1; transform: translate(-46%, -50%) rotate(-7deg); }
  100% { opacity: 0; transform: translate(-38%, -50%) rotate(-7deg); }
}
.curtain__banner span {
  font-weight: 800;
  font-style: italic;
  font-size: 8vh;
  letter-spacing: 0.05em;
  color: var(--red);
  white-space: nowrap;
}
.curtain__banner-ghost {
  color: transparent !important;
  -webkit-text-stroke: 2px rgba(217, 212, 201, 0.55);
  font-size: 5.6vh !important;
}

/* ─────────────── menu ─────────────── */

.menu {
  position: fixed;
  inset: 0;
  z-index: 50;
  visibility: hidden;
  pointer-events: none;
}
.menu.is-open {
  visibility: visible;
  pointer-events: auto;
}
.menu__panel {
  position: absolute;
  top: 0;
  right: 0;
  width: min(560px, 92vw);
  height: 100%;
  background:
    linear-gradient(rgba(13, 10, 9, 0.88), rgba(13, 10, 9, 0.88)),
    url("assets/tex-paper-black.jpg") center / cover;
  clip-path: polygon(8% 0, 100% 0, 100% 100%, 0 100%, 3% 78%, 0.5% 55%, 5% 32%, 2% 14%);
  /* translateZ keeps the panel on its own compositor layer — without it,
     hovering a link re-rasterizes the panel and the clip-path/texture
     flash square for a frame */
  transform: translateX(105%) translateZ(0);
  will-change: transform;
  backface-visibility: hidden;
  transition: transform 0.55s cubic-bezier(0.76, 0, 0.18, 1);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-left: 11%;
}
.menu.is-open .menu__panel { transform: translateX(0) translateZ(0); }
.menu li { list-style: none; }
.menu a {
  display: inline-block;
  position: relative;
  font-weight: 600;
  font-size: clamp(34px, 4.6vh, 54px);
  letter-spacing: 0.06em;
  color: var(--paper);
  text-decoration: none;
  line-height: 1.85;
  cursor: none;
  transition: color 0.25s, transform 0.25s;
}
.menu a i {
  font-style: normal;
  color: var(--red-bright);
  font-size: 0.5em;
  margin-left: 0.6em;
  opacity: 0;
  transition: opacity 0.25s;
  vertical-align: middle;
}
.menu a:hover { color: var(--red-bright); transform: translateX(0.35em) skewX(-6deg); }
.menu a:hover i { opacity: 1; }
/* PLAY!? stays red; hovering it goes darker red */
.menu a.menu-play { color: var(--red-bright); }
.menu a.menu-play:hover { color: var(--red-deep); }
/* the open burger is the close ✕ — turns red on hover */
.burger.is-open:hover span { background: var(--red-bright); }

/* ─────────────── grain + cursor ─────────────── */

.grain {
  position: fixed;
  inset: 0;
  z-index: 80;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' seed='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23g)' opacity='0.6'/%3E%3C/svg%3E");
  background-size: 180px 180px;
  opacity: 0.11;
  mix-blend-mode: multiply;
  /* PERF: grain is now STATIC. The old `grain-shift … infinite` animated
     background-position, which repainted the entire viewport ~3×/sec forever —
     the single biggest constant GPU cost on low-end machines. The film-grain
     texture stays; only the (subtle) shimmer is gone. */
}
/* PERF: while the curtain is sweeping, hide the grain so its mix-blend-mode:
   multiply doesn't force a whole-viewport re-composite on every animation frame.
   Imperceptible — the paper curtain covers the screen during the sweep and the
   grain is only 11% opacity. (.grain follows .curtain in the DOM.) */
.curtain.is-on ~ .grain { visibility: hidden; }

.cursor {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 99;
  color: var(--red-bright);
  font-size: 22px;
  font-weight: 700;
  line-height: 1;
  pointer-events: none;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
  transition: font-size 0.2s ease;
  will-change: transform;
}
.cursor.is-big { font-size: 40px; }

/* hall hint: mouse wording on desktop, touch wording on touch devices.
   gate on (hover: none) too — a touchscreen laptop reports (pointer: coarse)
   but still has a mouse, so it must keep the desktop (mouse) wording.
   selectors are `.hall-hint span.…` so they outrank `.hall-hint span`
   (else the base inline-block always wins and BOTH sets show). */
.hall-hint span.hall-hint__touch { display: none; }
@media (hover: none) and (pointer: coarse) {
  .cursor { display: none; }
  body { cursor: auto; }
  .play-btn, .hall-play, .hall-back, .burger, .menu a, .work-frame { cursor: pointer; }
  .hall-hint span.hall-hint__mouse { display: none; }
  .hall-hint span.hall-hint__touch { display: inline-block; }
}

/* ─────────────── responsive ─────────────── */

@media (max-width: 640px) {
  /* ════════ HERO ════════ */
  .hero-left { left: 6vw; top: 5vh; width: 88vw; z-index: 6; }
  .hero-name { font-size: 4.8vw; letter-spacing: 0.1em; margin-bottom: 0.5vh; }
  .hero-sub { font-size: 3.4vw; letter-spacing: 0.16em; white-space: normal; margin-top: 1.4vh; }
  /* bird way bigger + lower: body fills the rebuilt black skyline (see app.js
     mobileMask "hero") and fades into beige at the bottom so it never hard-crops.
     head (z3, unmasked) peeks over the beige; body (z2) only shows in the black. */
  .hero-bird-body, .hero-bird-head { left: -14vw; top: 34vh; width: 128vw; }
  .head-hotspot { left: 28%; top: 2%; width: 44%; height: 30%; }
  /* scroll cue — red, italic, hard to miss */
  .hero-scroll {
    left: 6vw; bottom: 4vh; z-index: 7;
    color: var(--red); font-weight: 800; font-style: italic;
    font-size: 5vw; line-height: 1.25;
  }
  .hero-scroll .scroll-arrow { color: var(--red); font-size: 1.5em; }
  .hero-right { display: none; }                 /* drop innovation×quality + maya */
  .page-num { font-size: 9px; right: 4vw; bottom: 2.4vh; }

  /* hamburger: white while the hero (now a black top) is the active page;
     reverts to default ink on the other pages, paper when the menu is open */
  body:has(#page-hero.is-active) .burger:not(.is-open) span { background: #fff; }

  /* ════════ PROJECTS ════════ */
  .stitch-projects { left: 7vw; top: 9vh; z-index: 4; }
  .proj-bird { width: 88vw; top: 48%; left: 52%; }
  .proj-head { left: 6vw; top: 1vh; z-index: 5; }
  .proj-head h1 { color: var(--red); font-size: 5.4vw; }
  .proj-head p { color: var(--red); font-size: 3.8vw; }
  .proj-disciplines, .proj-services, .proj-logos { display: none; }
  /* design statement → beige right edge (readable, dark ink) */
  .proj-statement {
    left: auto; right: 3vw; top: 16vh; bottom: auto; width: 38vw; z-index: 5;
    color: var(--ink); font-size: 4.2vw; line-height: 1.18; text-align: right;
    text-shadow: 0 1px 0 rgba(217,212,201,0.7);
  }
  /* creativity × efficiency → lower beige edge, dark ink */
  .proj-motto { right: 3vw; left: auto; top: auto; bottom: 15vh; z-index: 5; align-items: flex-end; }
  .proj-motto span { color: var(--ink); font-size: 3.4vw; }
  .proj-motto em { color: var(--red); }
  /* scroll cue slightly bigger */
  .proj-scroll { left: 5vw; bottom: 3.5vh; gap: 2vw; }
  .proj-scroll > span:first-child { font-size: 4.2vw; }
  .proj-scroll .scroll-arrow--red { font-size: 12vw; }

  /* ════════ SELECTED ════════ */
  /* title left · DEMO REELS to its right · "surprise" small, below the button */
  .works-head { flex-wrap: wrap; align-items: center; gap: 1vh 3vw; padding: 6.5vh 5vw 0; }
  .stitch-selected { width: 44vw; }
  .reels-btn { flex-basis: auto; margin: 0 0 0 auto; }
  .reels-btn span { padding: 1vh 5vw; font-size: 3.8vw; }
  .works-surprise { order: 3; width: 100%; max-width: none; text-align: right;
                    padding: 0; margin: 0.4vh 0 0; font-size: 2.5vw; letter-spacing: 0.12em; line-height: 1.3; }
  /* ONE project per row → bigger, with the desktop offset-shadow border; pulled up
     to fill the gap under the title (a little breathing room left) */
  .works-grid { grid-template-columns: 1fr; row-gap: 8vh; width: 84vw; margin: 3vh auto 0; }
  .work-label { font-size: 3vw; letter-spacing: 0.16em; bottom: -3.4vh; }
  .work-frame__drop strong { font-size: 2.4vw; }
  .work-frame__drop small { font-size: 1.9vw; }
  .play-btn { margin: 9vh auto 0; }
  /* no beige strip below the bar — it sits flush at the very bottom */
  .works-view { padding-bottom: 0; }
  /* contact bar fits the phone, at the very bottom */
  .contact-bar { flex-wrap: wrap; gap: 2vh 4vw; padding: 4vh 6vw; margin-bottom: 0; clip-path: polygon(0 8%, 100% 0, 100% 100%, 0 100%); }
  .contact-bar__title span { font-size: 7vw; padding: 1.2vh 6vw; }
  .contact-bar__info { width: 100%; }
  .contact-bar__name { font-size: 4.4vw; }
  .contact-bar__mail { font-size: 3.4vw; word-break: break-all; }
  .contact-bar__logo { height: 110%; right: -3vw; opacity: 0.06; }

  /* ════════ CONTACT page ════════ */
  .contact-slab { width: 116vw; right: -12vw; clip-path: polygon(0 5%, 100% 0, 100% 100%, 0 100%); }
  .contact-head { left: 5vw; top: 7vh; width: 72vw; z-index: 3; }
  .contact-mail { font-size: 2.8vw; padding: 1.2vh 3vw; }
  .contact-form { right: auto; left: 6vw; top: 32vh; width: 82vw; }
  .cf-field span { color: #f3efe6; }
  .contact-foot { font-size: 2.7vw; bottom: 4vh; color: #d9d4c9; }
  .contact-x { display: none; }
  .contact-logo { display: none; }   /* desktop-only watermark */

  /* ════════ MENU ════════ */
  .menu__panel { width: 100vw; padding-left: 12%; clip-path: none; }
  .menu a { font-size: 8.5vw; line-height: 1.9; }

  /* ════════ overlays ════════ */
  .overlay__inner { width: 90vw; padding: 3vh 0; }
  .overlay__close { top: 2.5vh; right: 5vw; }
  .reel-btn span { font-size: 5vw; padding: 1.4vh 6vw; }

  /* ════════ HALL ════════ */
  .hall-back span, .hall-leave span { font-size: 3.8vw; padding: 1vh 3vw; }
  .hall-play span { font-size: 4vw; padding: 1.2vh 4vw; }
  .hall-hint span { font-size: 3vw; padding: 1vh 3vw; white-space: normal; max-width: 86vw; }
  .hall-hint .hall-hint__sub { font-size: 2.5vw; }

  .curtain__banner span { font-size: 4.4vh; }
}

/* the "rotate your phone" wall is gone — instead, on a portrait phone the whole
   hall page is rotated 90° to landscape (3D view AND its buttons together) and
   the visitor just turns the device. hall.js renders at swapped dims + remaps
   pointer input (see hallRotated/pointerNDC). */
.rotate-hint { display: none; }
@media (max-width: 640px) and (orientation: portrait) {
  .page--hall {
    inset: auto;
    top: 0;
    left: 0;
    width: 100vh;
    height: 100vw;
    transform-origin: 0 0;
    transform: translateX(100vw) rotate(90deg);
  }
  /* the burger sits outside the (rotated) hall page, so it stays portrait-oriented.
     while the hall is open, move it to the portrait BOTTOM-RIGHT — which is the
     TOP-RIGHT once the device is turned to landscape — and rotate it to match. */
  body:has(.page--hall.is-active) .burger {
    top: auto;
    bottom: 4.5vw;
    right: 4.5vw;
    transform: rotate(90deg);
  }

  /* WATCH / project viewer lives INSIDE the rotated hall, so its vh-based height
     caps map to the portrait HEIGHT (= landscape width) and overflow — pushing the
     ✕ CLOSE above the visible area with no way to scroll up to it. Re-cap heights
     to vw (= the visible landscape height). Now that it's just video + title the
     video can own most of the card; the title sits compact below it. */
  .hall-viewer__card { max-height: 92vw; min-height: 0; padding: 5.5vw 5vw; }
  .hall-viewer__body { max-height: 82vw; gap: 3vw; }
  #hall-viewer-video { width: 100%; max-height: 60vw; }
  .hall-viewer__tag { top: 3vw; left: 4vw; padding: 1.2vw 2.4vw; font-size: 3vw; }
  .hall-viewer__close { top: 3vw; right: 4vw; padding: 1.4vw 2vw; font-size: 3.2vw; }
  .hall-viewer__body h3 { font-size: 4vw; letter-spacing: 0.18em; }
}

/* ─────────────── accessibility ───────────────
   Both blocks below are OPT-IN: they only change anything for visitors who
   have enabled "reduce motion" at the OS level, or who navigate by keyboard.
   Default mouse/touch visuals and animations are untouched. */

/* keyboard-only focus ring — does NOT appear on mouse clicks, so the custom
   cursor experience is unchanged for pointer users */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--red-bright);
  outline-offset: 3px;
}

/* respect reduced-motion: neutralize the decorative CSS animations
   (grain flicker, glitch, looping bounces/spins) and instant-ize transitions
   for users who asked their system to minimize motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
