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

interface Props { c: Content["materials"]; }
const { c } = Astro.props;

/* 변위 지도 두 장. 가장자리에서 안쪽으로 미는 값만 담고 가운데는 중립(128)이다.
   `#` 이 data URI 를 끊으므로 색은 rgb() 로 적는다. */
const W = 216;
const H = 72;
const map = (vertical: boolean, from: string, to: string) => {
  const dir = vertical ? 'x1="0" y1="0" x2="0" y2="1"' : 'x1="0" y1="0" x2="1" y2="0"';
  const svg =
    `<svg xmlns="http://www.w3.org/2000/svg" width="${W}" height="${H}">` +
    `<defs><linearGradient id="g" ${dir}>` +
    `<stop offset="0" stop-color="${from}"/>` +
    `<stop offset="0.30" stop-color="rgb(128,128,128)"/>` +
    `<stop offset="0.70" stop-color="rgb(128,128,128)"/>` +
    `<stop offset="1" stop-color="${to}"/>` +
    `</linearGradient></defs>` +
    `<rect width="${W}" height="${H}" fill="url(#g)"/></svg>`;
  return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;
};
const MAP_X = map(false, "rgb(255,128,128)", "rgb(0,128,128)");
const MAP_Y = map(true, "rgb(128,255,128)", "rgb(128,0,128)");
---

{/*
  이 섹션은 한동안 "필터로 재질 만들기" 였다 — 추상 사각형에 그레인·굴절·듀오톤.
  화면에서 아무 말도 하지 않았다. 필터가 실제로 값을 하는 자리는 질감이 아니라
  **실무에서 반복되는 네 가지 수작업**이고, 넷 다 이 스킬의 프리플라이트 항목이다.
  왼쪽이 문제, 오른쪽이 같은 소재에 선언 하나만 얹은 것이다.
*/}
<section class="section materials has-bg" aria-labelledby="mat-h">
  <BgPhoto variant="refraction" mode="fixed" opacity={0.9} />
  <p class="eyebrow reveal">{c.eyebrow}</p>
  <h2 id="mat-h" class="reveal">{c.h2}</h2>
  <p class="lead mat-lead reveal">{c.lead}</p>

  <div class="full stage glass">
    <span class="rim" aria-hidden="true"></span>
    <div class="stage-fallback" aria-hidden="true"></div>
    {/* GPU 가 만드는 배경. WebGL 이 없으면 위 그라디언트가 그대로 결과물이다 */}
    <canvas id="mat-canvas" class="stage-canvas" aria-hidden="true"></canvas>

    <ol role="list" class="fdemos">
      {
        c.demos.map((d, i) => (
          <li class="fdemo reveal" style={`--reveal-delay:${i * 70}ms`}>
            <h3 class="fd-name">{d.name}</h3>

            <div class="fd-pair">
              {[false, true].map((on) => (
                <figure class="fd-side">
                  <FilterArt kind={d.id} on={on} />
                  <figcaption class:list={["fd-tag", "mono", on ? "is-good" : "is-bad"]}>
                    {on ? d.afterLabel : d.beforeLabel}
                  </figcaption>
                </figure>
              ))}
            </div>

            <div class="fd-text">
              <p class="fd-problem">{d.problem}</p>
              <p class="fd-how muted">{d.how}</p>
              <p class="fd-verdict mono">{d.verdict}</p>
            </div>
          </li>
        ))
      }
    </ol>
  </div>
</section>

{/*
  필터 정의. 화면에 그려지지 않고 참조만 된다.

  전부 color-interpolation-filters 를 명시한다. 기본값은 linearRGB 인데,
  블렌드와 합성이 씻겨 보인다 — 대부분 sRGB 가 맞다.
  단 하나, 색각 시뮬레이션은 반대다. 색각 변환은 물리적인 빛의 혼합이라
  선형 공간에서 계산해야 실제로 그 사람이 보는 색이 나온다.
*/}
<svg class="visually-hidden" aria-hidden="true" focusable="false">
  <defs>
    <!--
      글자 모양대로 생기는 스크림.
      박스를 그리는 대신 알파를 부풀려 그 모양만 채운다.
      영역을 넉넉히 잡지 않으면 부풀린 만큼 가장자리가 잘린다.
    -->
    <filter id="f-scrim" color-interpolation-filters="sRGB"
            x="-25%" y="-60%" width="150%" height="220%">
      <feMorphology in="SourceAlpha" operator="dilate" radius="4" result="fat" />
      <feGaussianBlur in="fat" stdDeviation="3.5" result="soft" />
      <!-- 블러가 알파를 옅게 만든다. 다시 세우지 않으면 스크림이 비쳐서
           대비가 3.1:1 에서 멈춘다 — 실측으로 확인하고 올린 값이다 -->
      <feComponentTransfer in="soft" result="dense">
        <feFuncA type="linear" slope="4.4" />
      </feComponentTransfer>
      <feFlood flood-color="#04100f" flood-opacity="1" result="ink" />
      <feComposite in="ink" in2="dense" operator="in" result="scrim" />
      <feMerge>
        <feMergeNode in="scrim" />
        <feMergeNode in="SourceGraphic" />
      </feMerge>
    </filter>

    <!--
      적록색약(2형) 시뮬레이션. Brettel–Viénot–Mollon 계열 근사 행렬.
      여기만 linearRGB 다 — sRGB 로 돌리면 감마가 섞여 실제보다 덜 심하게 보인다.
    -->
    <filter id="f-deuter" color-interpolation-filters="linearRGB">
      <feColorMatrix type="matrix"
        values="0.625 0.375 0     0 0
                0.700 0.300 0     0 0
                0     0.300 0.700 0 0
                0     0     0     1 0" />
    </filter>

    <!--
      구이. 커뮤니티에서 가장 많이 만들어지는 필터이고, 값 두 개가 전부다.
      stdDeviation 이 얼마나 멀리서부터 붙을지를, 알파 기울기(18)가
      얼마나 단단하게 잘릴지를 정한다. 기울기를 낮추면 흐릿한 젤리가 된다.
      마지막 atop 이 없으면 블러된 헤일로가 남는다.
    -->
    <filter id="f-goo" color-interpolation-filters="sRGB"
            x="-20%" y="-40%" width="140%" height="180%">
      <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
      <feColorMatrix in="blur" type="matrix" result="goo"
        values="1 0 0 0  0
                0 1 0 0  0
                0 0 1 0  0
                0 0 0 18 -7" />
      <feComposite in="SourceGraphic" in2="goo" operator="atop" />
    </filter>


    <!--
      리퀴드 글래스. 변위 지도는 **노이즈가 아니다** — 유리는 무작위로 휘지 않고
      가장자리에서 안쪽으로 휜다. feTurbulence 로 만들면 지도가 중립값(128)으로
      수렴해 scale 을 아무리 키워도 아무 일도 안 일어난다(실측: 채널차 1.66).

      R 채널이 X, G 채널이 Y 이동량이고 128 이 "움직이지 마라" 다.
      한 장의 그라디언트로 R 과 G 를 따로 만들 수 없으니, 지도 두 장을 놓고
      displacement 를 두 번 건다. 안 쓰는 축은 B(=128 고정)를 물려 0 으로 만든다.

      feImage 의 width/height 는 요소 크기와 같아야 한다 — 자동으로 안 맞춰준다.
      그래서 이 패널만 크기를 고정해 뒀다.
    -->
    <filter id="f-lens" color-interpolation-filters="sRGB"
            x="0" y="0" width="100%" height="100%">
      <feImage href={MAP_X} x="0" y="0" width="216" height="72" result="mx" />
      <feDisplacementMap in="SourceGraphic" in2="mx" scale="30"
                         xChannelSelector="R" yChannelSelector="B" result="dx" />
      <feImage href={MAP_Y} x="0" y="0" width="216" height="72" result="my" />
      <feDisplacementMap in="dx" in2="my" scale="30"
                         xChannelSelector="B" yChannelSelector="G" />
    </filter>
  </defs>
</svg>

<style>
  .mat-lead { margin-bottom: var(--space-6); max-width: var(--measure); }

  .stage {
    position: relative;
    max-width: 1180px;
    margin-inline: auto;
    /* --wide-pad 는 페이지 그리드의 바깥 칼럼을 정의하는 토큰이다(최대 10rem).
       여기에 그대로 쓰면 1440px 화면에서 좌우 160px 씩, 폭 320px 이 사라진다.
       그만큼 오른쪽 설명 칸이 170px 로 줄어 여덟 자마다 줄이 바뀌었다. */
    padding: var(--space-6);
    border-radius: var(--radius-frame);
    overflow: hidden;
    isolation: isolate;
  }
  .stage-fallback,
  .stage-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: -1;
  }
  .stage-fallback {
    background:
      radial-gradient(60% 70% at 22% 20%,
        color-mix(in oklab, var(--accent) 16%, transparent), transparent 70%),
      radial-gradient(56% 64% at 80% 76%,
        color-mix(in oklab, var(--glow-2) 14%, transparent), transparent 68%);
  }
  .stage-canvas { opacity: 0; transition: opacity 1s var(--ease-soft); }
  .stage-canvas.is-live { opacity: 0.55; }

  .fdemos {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: var(--space-6);
  }
  .fdemo + .fdemo { border-top: 1px solid var(--line); padding-top: var(--space-6); }

  /* 데모와 설명을 세로로 쌓으면 한 항목이 320px 을 먹는다.
     넷이면 섹션이 3.1 화면 — 파이프라인 설명보다 길어졌다.
     그림은 왼쪽, 말은 오른쪽에 두면 같은 내용이 절반 높이에 들어간다. */
  .fdemo {
    display: grid;
    grid-template-columns: minmax(0, 584px) minmax(0, 1fr);
    column-gap: var(--space-6);
    align-items: start;
  }
  .fd-name {
    grid-column: 1 / -1;
    font-size: var(--step-1);
    margin-bottom: var(--space-4);
  }
  .fd-problem { color: var(--ink-muted); }

  .fd-pair {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 280px));
    gap: var(--space-3);
  }
  .fd-side { margin: 0; }
  .fd-tag {
    margin: var(--space-2) 0 0;
    font-size: var(--mono-size);
    letter-spacing: 0;
  }
  .is-bad { color: var(--ink-muted); }
  .is-good { color: var(--accent); }

  .fd-text > * + * { margin-top: var(--space-3); }
  .fd-verdict {
    margin: var(--space-2) 0 0;
    font-size: var(--mono-size);
    color: var(--accent);
  }

  @media (max-width: 1080px) {
    .fdemo { grid-template-columns: 1fr; row-gap: var(--space-4); }
  }
  @media (max-width: 720px) {
    .fd-pair { grid-template-columns: 1fr; }
  }
</style>
