/* ===== LUHTUNE — full cycle intro build ===== */
:root {
    --bg-default: #0d0d0e;
    --ink-default: #d4d1c5;
    --bg: var(--bg-default);
    --ink: var(--ink-default);
    --title-mask-image: none;
    --ease-out: cubic-bezier(.22,1,.36,1);
    --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
    --theme-trans: background-color 0.72s var(--ease-in-out),
                   color 0.72s var(--ease-in-out),
                   border-color 0.72s var(--ease-in-out);
  }

  * { margin: 0; padding: 0; box-sizing: border-box; }
  html, body { width: 100%; height: 100%; overflow: hidden; -webkit-font-smoothing: antialiased; }
  body {
    background: var(--bg);
    color: var(--ink);
    font-family: "Inter", ui-sans-serif, system-ui, sans-serif;
    font-weight: 400;
    transition: var(--theme-trans);
    user-select: none;
    -webkit-user-select: none;
  }
  a { color: inherit; text-decoration: none; }

  .logo {
    position: fixed; top: 32px; left: 40px; z-index: 100;
    font-family: "Big Shoulders Display", sans-serif;
    font-weight: 900; font-size: 26px; letter-spacing: 0.02em; line-height: 0.9;
    transition: var(--theme-trans);
  }
  .logo-link { pointer-events: auto; display: inline-block; cursor: pointer; }

  .top-right {
    position: fixed; top: 34px; right: 40px; z-index: 100;
    font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; font-weight: 500;
  }
  .top-right a { position: relative; padding-bottom: 3px; cursor: pointer; }
  .top-right a::after { content: ""; position: absolute; bottom: 0; left: 0; width: 100%; height: 1px; background: currentColor; }

  .slider-indicator {
    position: fixed; top: 34px; left: 50%; transform: translateX(-50%); z-index: 100;
    display: flex; align-items: center; gap: 14px;
    font-size: 10px; letter-spacing: 0.15em; font-weight: 500; font-variant-numeric: tabular-nums;
  }
  .slider-indicator .tick-row { display: flex; gap: 3px; align-items: center; pointer-events: auto; }
  .slider-indicator .tick {
    width: 1px; height: 10px; background: var(--ink); opacity: 0.35;
    transition: opacity 0.38s var(--ease-out), height 0.38s var(--ease-out), background-color 0.65s var(--ease-in-out);
    cursor: pointer;
  }
  .slider-indicator .tick.active { opacity: 1; height: 14px; }
  .slider-indicator .counter-wrap { display: flex; align-items: center; gap: 10px; opacity: 0; transition: opacity 0.28s var(--ease-out); }
  .slider-indicator .counter-wrap.show { opacity: 1; }
  .slider-indicator .counter-box { display: inline-block; padding: 2px 6px; border: 1px solid var(--ink); min-width: 28px; text-align: center; transition: border-color 0.6s var(--ease-in-out); }

  .bottom-left, .bottom-right {
    position: fixed; bottom: 28px; z-index: 100;
    font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; font-weight: 500; line-height: 1.6;
  }
  .bottom-left { left: 40px; }
  .bottom-right { right: 40px; text-align: right; }
  .bottom-right a { display: block; position: relative; cursor: pointer; }
  .bottom-right a::before { content: ""; position: absolute; bottom: -2px; right: 0; width: 0; height: 1px; background: currentColor; transition: width 0.35s var(--ease-out); }
  .bottom-right a:hover::before { width: 100%; }

  .stage {
    position: fixed; inset: 0; z-index: 1; overflow: hidden;
  }
  #gl {
    position: absolute; inset: 0; width: 100%; height: 100%; display: block;
    z-index: 1; pointer-events: auto;
  }

  .project-title {
    position: fixed; top: 50%; left: 0; width: 100%; transform: translateY(-50%);
    z-index: 20;
    font-family: "Big Shoulders Display", sans-serif;
    font-weight: 900; line-height: 0.85; letter-spacing: 0.01em; text-transform: uppercase; text-align: center;
    font-size: clamp(5.5rem, 12vw, 13rem);
    color: var(--ink);
    opacity: 0;
    pointer-events: none;
    white-space: nowrap;
    text-shadow: 0 10px 34px rgba(0,0,0,0.26);
    transition: color 0.62s var(--ease-in-out), opacity 0.36s var(--ease-out), transform 0.56s var(--ease-out);
  }
  body.mode-project .project-title { opacity: 0.78; color: color-mix(in srgb, var(--ink) 82%, transparent); filter: drop-shadow(0 12px 26px rgba(0,0,0,.28)); }
  .project-title .title-line { display: block; line-height: 0.82; }
  .project-title .title-line-small { font-size: 0.52em; letter-spacing: 0.055em; margin-bottom: -0.04em; opacity: 0.84; }
  .project-title .title-line-big { font-size: 1em; }
  .project-title .title-line-single { font-size: 0.92em; }
  .project-title .letter-space { display: inline-block; width: 0.20em; }

  .project-title .letter-wrap { display: inline-block; overflow: hidden; vertical-align: bottom; line-height: 0.85; }
  .project-title .letter-inner { display: inline-block; transform: translate3d(0, 110%, 0); transition: transform 0.50s var(--ease-out); will-change: transform; }
  body.title-on .project-title .letter-inner { transform: translate3d(0,0,0); }

  .center-explore {
    position: fixed; bottom: 44px; left: 50%; transform: translateX(-50%); z-index: 90;
    text-align: center; font-size: 12px; letter-spacing: 0.02em; line-height: 14px; pointer-events: none;
  }
  .center-explore .line-w { display: inline-block; pointer-events: auto; }
  .center-explore .line-item { display: block; overflow: hidden; position: relative; }
  .center-explore .line-item-inner { display: inline-flex; align-items:center; gap:7px; transform: translate3d(0,101%,0); transition: transform 0.46s var(--ease-out); position: relative; padding-bottom: 4px; }
  .center-explore .explore-arrow { display:inline-block; font-size: 11px; line-height:1; transform: translate3d(0,1px,0); transition: transform .32s var(--ease-out); }
  .center-explore a:hover .explore-arrow { transform: translate3d(3px,-2px,0); }
  .center-explore .line-item-inner::after { content: ""; position: absolute; left: 0; bottom: 0; width: 100%; height: 1px; background: currentColor; }

  .center-cross { display: none; }
  .center-cross .c-line-wrap { height: 34px; width: 3px; overflow: hidden; margin: 9px auto 0; position: relative; }
  .center-cross .c-line { position: absolute; left: 0; top: 0; width: 1px; height: 100%; border-right: 1px solid var(--ink); transform: translate3d(0,-110%,0); transition: transform 0.50s var(--ease-out), border-color 0.62s var(--ease-in-out); }
  .center-cross .c-symbol-wrap { margin-top: 13px; width: 14px; height: 14px; overflow: hidden; }
  .center-cross .c-symbol { transform: translate3d(0,110%,0); transition: transform 0.50s var(--ease-out); }
  .center-cross svg { display: block; }

  .left-info { position: fixed; bottom: 47px; left: 50%; transform: translateX(-100%); font-size: 10px; line-height: 12px; letter-spacing: 0.02em; z-index: 90; padding-right: 24px; pointer-events: none; }
  .left-info .row { display: flex; overflow: hidden; }
  .left-info .row + .row { margin-top: 2px; }
  .left-info .row-inner { display: flex; transform: translate3d(0,-101%,0); transition: transform 0.50s var(--ease-out); }
  .left-info .col-letter { width: 30px; font-size: 10px; opacity: 0.55; text-transform: uppercase; font-weight: 500; letter-spacing: 0.08em; }
  .left-info .col-label { width: 130px; opacity: 0.6; text-transform: uppercase; font-weight: 500; letter-spacing: 0.08em; }
  .left-info .col-value { width: 250px; opacity: 1; text-transform: uppercase; font-weight: 500; letter-spacing: 0.08em; }

  .right-desc { position: fixed; bottom: 48px; left: calc(50% + 24px); font-size: 10px; line-height: 14px; letter-spacing: 0.02em; z-index: 90; pointer-events: none; padding-left: 120px; text-transform: uppercase; font-weight: 500; opacity: 0.85; }
  .right-desc .line { overflow: hidden; }
  .right-desc .line-inner { display: block; transform: translate3d(0,-101%,0); transition: transform 0.50s var(--ease-out); }

  body.meta-on .center-explore .line-item-inner,
  body.meta-on .center-cross .c-line,
  body.meta-on .center-cross .c-symbol,
  body.meta-on .left-info .row-inner,
  body.meta-on .right-desc .line-inner { transform: translate3d(0,0,0); }

  /* =====================================================================
     CINEMATIC INTRO — letters only
     The WebGL card behind the intro is sized and positioned to fill the
     screen-space gap between the two word-divs. The intro layer here is
     just text and a transparent spacer; everything visible inside the gap
     is rendered by Three.js through the alpha-transparent canvas underneath.
     ===================================================================== */
  .intro {
    position: fixed;
    inset: 0;
    z-index: 9998;
    color: var(--ink-default);
    /* Solid background INITIALLY — covers the WebGL canvas while the
       letters are sliding in. Once the gap "opens" we'll fade this to
       transparent so the card behind shows through, but only the card
       (the rest of the WebGL scene has no other cards visible during intro). */
    background: var(--bg-default);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    transition: opacity 0.45s var(--ease-out), background-color 0.45s var(--ease-out), visibility 0s 0.45s;
    pointer-events: none; /* the canvas underneath should never receive intro clicks */
  }
  .intro.is-revealing-card {
    background: transparent;
  }
  .intro.done {
    opacity: 0;
    visibility: hidden;
  }

  .intro-row {
    display: flex;
    align-items: center;
    justify-content: center;
    white-space: nowrap;
    font-family: "Big Shoulders Display", sans-serif;
    font-weight: 900;
    font-size: clamp(5rem, 14vw, 14rem);
    line-height: 0.85;
    letter-spacing: 0.01em;
    position: relative;
  }

  .intro-word {
    display: flex;
    overflow: hidden;
    transition: transform 1.2s var(--ease-in-out);
    /* Letters and their own background fill above/below the gap area.
       The word divs themselves are solid (background: var(--bg-default))
       so they cover the WebGL canvas above and below the gap during the
       intro — only the spacer area is see-through. */
    background: var(--bg-default);
  }
  .intro.is-spreading .intro-word-start { transform: translateX(-0.05em); }
  .intro.is-spreading .intro-word-end { transform: translateX(0.05em); }

  .intro-letter {
    display: inline-block;
    transform: translateY(110%);
    transition: transform 0.9s var(--ease-out);
    will-change: transform;
  }
  .intro-letter:nth-child(1) { transition-delay: 0.00s; }
  .intro-letter:nth-child(2) { transition-delay: 0.04s; }
  .intro-letter:nth-child(3) { transition-delay: 0.08s; }
  .intro-letter:nth-child(4) { transition-delay: 0.12s; }
  .intro.is-letters-in .intro-letter { transform: translateY(0); }

  /* Spacer reserves the gap width in the layout. Starts at 0, grows to
     final width during the "open" phase. The WebGL card behind reads this
     element's bounding rect to size and position itself. */
  .intro-gap-spacer {
    width: 0;
    height: 0.85em;
    transition: width 1.0s var(--ease-in-out);
    pointer-events: none;
    /* Transparent — the WebGL card shows through this rect. */
    background: transparent;
    /* Margin matches the original intro-gap margin so spacing feels right. */
    margin: 0 0.12em;
    flex-shrink: 0;
  }
  .intro.is-gap-open .intro-gap-spacer { width: 1.15em; }

  /* When letters fly out: fast, no stagger, all leave together up. */
  .intro.is-finishing .intro-row .intro-letter {
    transform: translateY(-130%);
    transition: transform 0.4s var(--ease-in-out);
    transition-delay: 0s;
  }
  .intro.is-finishing .intro-word {
    /* Word-div backgrounds stay solid until is-finishing — at that point
       the WebGL card is going to grow to fill the screen, so we need the
       word backgrounds to disappear too or they'd cover the zooming card. */
    background: transparent;
  }

  @media (max-width: 900px), (pointer: coarse) {
    .intro { display: none !important; }
  }

  @media (max-width: 1200px) {
    .right-desc { padding-left: 60px; }
    .left-info { padding-right: 12px; }
    .left-info .col-label { width: 90px; }
    .left-info .col-value { width: 180px; }
  }
  @media (max-width: 900px) {
    .logo { top: 20px; left: 20px; font-size: 22px; }
    .top-right { top: 22px; right: 20px; }
    .bottom-left, .bottom-right { bottom: 20px; }
    .bottom-left { left: 20px; }
    .bottom-right { right: 20px; }
    .project-title { font-size: clamp(4rem, 18vw, 8rem); opacity: 0; }
    body.mode-project .project-title { opacity: 0.72; }
    .left-info, .right-desc { position: fixed; left: 20px; right: 20px; width: auto; transform: none; padding: 0; }
    .left-info { bottom: 110px; }
    .left-info .col-letter { width: 22px; }
    .left-info .col-label { width: 70px; }
    .left-info .col-value { width: auto; flex: 1; }
    .right-desc { bottom: 78px; padding: 0; }
    .right-desc .line-inner { text-align: left; }
    .center-explore { bottom: 44px; }
    .center-cross { display: none; }
  }

/* =====================================================================
   ABOUT / MOBILE FALLBACK
   ===================================================================== */
.about-panel {
  position: fixed;
  inset: 0;
  z-index: 500;
  background: color-mix(in srgb, var(--bg) 94%, black);
  color: var(--ink);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .42s var(--ease-out), visibility 0s .42s;
}

body.about-open .about-panel {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity .42s var(--ease-out), visibility 0s;
}

.about-panel-inner {
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(760px, calc(100vw - 80px));
  transform: translate(-50%, -46%);
  transition: transform .5s var(--ease-out);
}

body.about-open .about-panel-inner {
  transform: translate(-50%, -50%);
}

.about-kicker,
.mobile-kicker,
.mobile-role,
.mobile-note {
  font-size: 10px;
  line-height: 1.3;
  letter-spacing: .14em;
  text-transform: uppercase;
  font-weight: 700;
  opacity: .75;
}

.about-panel h1,
.mobile-about h1 {
  font-family: "Big Shoulders Display", sans-serif;
  font-size: clamp(52px, 8vw, 116px);
  line-height: .86;
  text-transform: uppercase;
  letter-spacing: .01em;
  margin: 18px 0 24px;
}

.about-panel p {
  max-width: 680px;
  font-size: 16px;
  line-height: 1.55;
  margin-bottom: 16px;
}

.about-links,
.mobile-links {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 18px;
  margin-top: 28px;
}

.about-links a,
.mobile-links a {
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  border-bottom: 1px solid currentColor;
  padding-bottom: 4px;
}

.about-close {
  position: fixed;
  top: 34px;
  right: 40px;
  z-index: 520;
  appearance: none;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 10px;
  letter-spacing: .12em;
  text-transform: uppercase;
  cursor: pointer;
  border-bottom: 1px solid currentColor;
  padding-bottom: 3px;
}

.mobile-about {
  display: none;
}

/* Mobile intentionally bypasses the WebGL portfolio.
   The desktop gallery uses hover/click/wheel interactions that are bad on phones. */
@media (max-width: 900px), (pointer: coarse) {
  html, body {
    height: auto;
    min-height: 100%;
    overflow: auto;
    user-select: text;
    -webkit-user-select: text;
    background: #0d0d0e;
  }

  .stage,
  #gl,
  .project-title,
  .slider-indicator,
  .top-right,
  .bottom-left,
  .bottom-right,
  .left-info,
  .right-desc,
  .center-explore,
  .center-cross,
  .about-panel {
    display: none !important;
  }

  .load {
    display: none !important;
  }

  .logo {
    position: fixed;
    top: 22px;
    left: 22px;
    z-index: 20;
    font-size: 24px;
    color: #d4d1c5;
  }

  .mobile-about {
    display: block;
    min-height: 100vh;
    background:
      radial-gradient(circle at 20% 10%, rgba(90, 184, 255, .16), transparent 34%),
      radial-gradient(circle at 80% 20%, rgba(255, 77, 61, .13), transparent 30%),
      #0d0d0e;
    color: #d4d1c5;
    padding: 92px 24px 44px;
  }

  .mobile-shell {
    max-width: 560px;
    margin: 0 auto;
  }

  .mobile-about h1 {
    font-size: clamp(56px, 18vw, 96px);
    margin-bottom: 10px;
  }

  .mobile-role {
    color: #5ab8ff;
    margin-bottom: 30px;
  }

  .mobile-about p {
    font-size: 15px;
    line-height: 1.58;
    margin: 0 0 18px;
    color: color-mix(in srgb, #d4d1c5 88%, transparent);
  }

  .mobile-projects {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 28px 0;
  }

  .mobile-projects span {
    border: 1px solid rgba(212, 209, 197, .22);
    border-radius: 999px;
    padding: 8px 10px;
    font-size: 10px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: color-mix(in srgb, #d4d1c5 84%, transparent);
  }

  .mobile-links {
    margin-top: 26px;
  }

  .mobile-note {
    margin-top: 32px !important;
    color: #5ab8ff !important;
  }
}


.about-small {
  font-size: 13px !important;
  opacity: .78;
}

.mobile-projects a {
  border: 1px solid rgba(212, 209, 197, .22);
  border-radius: 999px;
  padding: 8px 10px;
  font-size: 10px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: color-mix(in srgb, #d4d1c5 84%, transparent);
  text-decoration: none;
}

.mobile-projects a:hover {
  border-color: rgba(90, 184, 255, .7);
  color: #5ab8ff;
}

/* Desktop cards default grayscale in WebGL shader; color restores on hover/focus. */
