---
import CopyCommand from "./CopyCommand.astro";
import type { Content } from "../i18n/content";

interface Props {
  c: Content["hero"];
  ui: Content["ui"];
}
const { c, ui } = Astro.props;
---

{/*
  3D 는 배경이다. 액자에 가두지 않는다.

  한 번 액자 안에 넣었다가 되돌렸다. lusion.co 에서 가져온 "3D 는 액자 안,
  텍스트는 액자 밖"은 3D 자체가 상품일 때의 규칙이다. 그 스튜디오는 3D 를
  팔기 때문에 액자가 쇼케이스 프레임으로 정당하다.
  배경으로 쓸 때는 규칙이 다르다 — 주인공이 아니라 공간을 만드는 재질이고,
  그래서 대비를 낮추고 글자에 자리를 내준다.

  처음 배경으로 깔았을 때 실패한 이유는 배치가 아니라 둘이었다.
  판이 정면이라 프레넬이 0 이어서 아무것도 안 보였고(three.md §2),
  헤드라인이 112px 이라 그나마 보이는 것과도 싸웠다. 둘 다 고쳤다.
*/}
<section class="full hero">
  <div class="hero-bg" aria-hidden="true">
    {/* WebGL 이 없으면 이 그라디언트가 폴백이 아니라 결과물이다 */}
    <div class="hero-fallback"></div>
    <canvas id="hero-canvas" class="hero-canvas"></canvas>
    {/* 글자가 앉는 자리만 눌러준다. 배경이 균일하게 밝으면 본문 대비가 무너진다 */}
    <div class="hero-scrim"></div>
  </div>

  <div class="hero-grid">
    <h1 class="hero-title">{c.h1}</h1>

    <div class="hero-aside">
      <p class="lead hero-lead">{c.lead}</p>
      <CopyCommand
        command={c.install}
        copyLabel={ui.copy}
        copiedLabel={ui.copied}
        note={c.installNote}
      />
      <p class="hero-links">
        {c.links.map((l) => <a class="link-grow" href={l.href}>{l.label}</a>)}
      </p>
    </div>
  </div>
</section>

<style>
  .hero {
    grid-column: full;
    position: relative;
    isolation: isolate;
    overflow: clip;
    min-height: min(78dvh, 46rem);
    display: grid;
    align-content: center;
    padding-block: calc(var(--header-h) + var(--space-6)) var(--space-7);
  }

  /* ---- 배경 ------------------------------------------------ */
  .hero-bg {
    position: absolute;
    /* 패럴랙스로 내려가는 만큼 위아래에 여유를 둔다.
       inset: 0 이면 배경이 내려간 자리에 검은 띠가 생긴다 */
    inset: -4rem 0;
    z-index: -1;
    pointer-events: none;
    /* 아래로 갈수록 지운다. black 은 색이 아니라 마스크 알파다.
       없으면 히어로 하단에서 배경이 가로선으로
       뚝 끊겨 다음 섹션과 두 장의 종이처럼 보인다. */
    -webkit-mask-image: linear-gradient(to bottom, black 0%, black 82%, transparent 100%);
    mask-image: linear-gradient(to bottom, black 0%, black 82%, transparent 100%);
  }
  .hero-fallback,
  .hero-canvas,
  .hero-scrim {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
  }
  .hero-fallback {
    background:
      radial-gradient(52% 62% at 24% 26%,
        color-mix(in oklab, var(--accent) 30%, transparent), transparent 68%),
      radial-gradient(46% 58% at 82% 62%,
        color-mix(in oklab, var(--glow-2) 26%, transparent), transparent 66%);
  }
  .hero-canvas { opacity: 0; transition: opacity 1.2s var(--ease-soft); }
  .hero-canvas.is-live { opacity: 1; }

  /* 왼쪽 위(글자가 앉는 쪽)를 눌러 대비를 만든다. 오른쪽 아래는 열어둔다 */
  .hero-scrim {
    background:
      linear-gradient(100deg,
        color-mix(in oklab, var(--surface) 88%, transparent) 0%,
        color-mix(in oklab, var(--surface) 62%, transparent) 42%,
        transparent 78%),
      linear-gradient(to bottom,
        color-mix(in oklab, var(--surface) 72%, transparent) 0%,
        transparent 28%);
  }

  /* ---- 글자 ------------------------------------------------ */
  .hero-grid {
    max-width: 1180px;
    width: 100%;
    margin-inline: auto;
    padding-inline: var(--gutter);
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: var(--space-5) var(--space-6);
    align-items: center;
  }

  .hero-title {
    font-size: clamp(var(--step-2), 1.1rem + 2.6vw, var(--step-4));
    line-height: 1.12;
    letter-spacing: var(--tracking-display);
    max-width: 16ch;
    margin: 0;
  }
  [lang="en"] .hero-title { max-width: 18ch; line-height: 1.04; }

  .hero-aside { display: grid; gap: var(--space-3); align-content: center; }
  .hero-lead {
    margin: 0;
    max-width: 30em;
    color: var(--ink);
    opacity: 0.86;
  }
  .hero-links {
    display: flex;
    gap: var(--space-4);
    margin: 0;
    font-size: var(--step-0);
    color: var(--ink-muted);
  }

  @media (max-width: 900px) {
    /* min-height 를 걸지 않는다. 콘텐츠가 390px 인데 736px 을 씌우면
       여백이 화면의 41% 를 먹고, 다음 섹션이 화면 밖으로 밀려나
       스크롤할 것이 있다는 단서까지 사라진다. */
    .hero { min-height: 0; }
    .hero-grid { grid-template-columns: 1fr; gap: var(--space-5); }
    .hero-title { max-width: 100%; }
    /* 세로 화면에서는 글자가 위쪽 절반을 다 쓴다. 가로 방향 스크림으로는
       덮이지 않으므로 위에서 아래로 누른다 */
    .hero-scrim {
      background: linear-gradient(to bottom,
        color-mix(in oklab, var(--surface) 86%, transparent) 0%,
        color-mix(in oklab, var(--surface) 58%, transparent) 52%,
        transparent 86%);
    }
  }
</style>


<script>
  /*
    히어로 배경은 셰이더 플레인 하나다. 무거운 씬을 임포트하지 않는다 —
    references/three.md §0 이 권하는 그 구조다.

    한때 여기에도 게이트 씬(유리판 여섯 장)을 깔았는데, 그러면 같은 그림이
    파이프라인 섹션과 페이지에 두 번 나온다. 게이트 은유는 옆에 여섯 단계가
    적힌 그 섹션의 것이고, 여기는 공간을 만드는 재질이면 된다.
  */
  import { mountShaderPlane } from "../lib/shader-plane";

  const canvas = document.getElementById("hero-canvas") as HTMLCanvasElement | null;

  if (canvas) {
    mountShaderPlane({
      canvas,
      pointer: true,
      speed: 0.5,
      colors: { uA: "--accent", uB: "--glow-2" },
      fragment: `
        precision mediump float;
        varying vec2 vUv;
        uniform float uTime; uniform float uAspect;
        uniform vec2 uPointer;
        uniform vec3 uA; uniform vec3 uB;

        float hash(vec2 p) { return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); }
        float noise(vec2 p) {
          vec2 i = floor(p), f = fract(p);
          vec2 u = f * f * (3.0 - 2.0 * f);
          return mix(mix(hash(i), hash(i + vec2(1, 0)), u.x),
                     mix(hash(i + vec2(0, 1)), hash(i + vec2(1, 1)), u.x), u.y);
        }
        float fbm(vec2 p) {
          float v = 0.0, a = 0.5;
          for (int i = 0; i < 5; i++) { v += a * noise(p); p *= 2.03; a *= 0.5; }
          return v;
        }

        void main() {
          vec2 p = vUv; p.x *= uAspect;
          float t = uTime * 0.06;
          vec2 m = uPointer; m.x *= uAspect;

          // 흐름 필드. 두 번 접어서 빛이 유리를 지난 것처럼 늘어지게 만든다.
          vec2 q = vec2(fbm(p * 1.5 + t), fbm(p * 1.5 - t * 0.8 + 4.2));
          vec2 r = vec2(fbm(p * 2.1 + q * 1.6 + t * 0.5),
                        fbm(p * 2.1 + q * 1.6 - t * 0.4 + 1.7));
          float f = fbm(p * 1.2 + r * 1.9);

          // 광원 둘. 포인터를 아주 조금만 따라간다.
          vec2 c1 = mix(vec2(0.30 * uAspect, 0.58), m, 0.14);
          vec2 c2 = vec2(0.80 * uAspect, 0.34);

          float a = smoothstep(1.00, 0.06, distance(p, c1) + f * 0.42);
          float b = smoothstep(0.92, 0.05, distance(p, c2) + r.y * 0.38);

          // 결이 지나간 자리에 얇은 선이 선다. 유리 가장자리의 굴절 대신이다.
          float streak = smoothstep(0.48, 0.52, f) - smoothstep(0.52, 0.58, f);

          vec3 col = uA * a + uB * b * 0.9 + (uA + uB) * 0.5 * streak * 0.16;
          float alpha = clamp(a * 1.05 + b * 0.95 + streak * 0.2, 0.0, 1.0) * 0.8;
          gl_FragColor = vec4(col, alpha);
        }
      `,
    });
  }
</script>
