/* Hallmark · macrostructure: Narrative Workflow (14) · genre: atmospheric
 * hero: H6 Photographic · knobs: image=full-bleed, caption=overlaid, text=left-bias
 * nav: N5 Floating pill · footer: Ft5 Statement
 * features: F4 Step sequence · knobs: numbering=01/02/03, layout=vertical stack, connector=line
 * theme: in-game palette (crates/web/index.html :root) — not a catalog theme
 * pre-emit critique: P5 H4 E4 S5 R4 V5
 * contrast: pass (40–41) · slop: pass (42–45) · honest: pass (46) · chrome: pass (47)
 * tokens: pass (48) · responsive: pass (49) · mobile: pass (34, 49, 50–55)
 *
 * 팔레트·9-슬라이스 실측값은 crates/web/index.html에서 그대로 가져왔다 —
 * 랜딩과 게임이 다른 색을 쓰면 클릭한 순간 다른 제품이 된다.
 */

/* ── 도트 글자 ────────────────────────────────────────────
   5×7 비트맵이라 **9의 배수 크기에서만 또렷하다.** 18px과 27px만 쓴다.
   그리고 문단은 도트로 쓰지 않는다 — 라벨·버튼·수치만 도트가 맡는다. */
@font-face{ font-family:pix; font-display:block; src:url(static/pix.woff2) format("woff2") }

:root{
  /* 면 */
  --ground:#141b33; --deep:#0a0e1c; --ink:#1a1030;
  /* 글자 — `--body`와 `--sub`는 종전에 본문·리드에 하드코딩돼 있던 값이다.
     `--on-accent`는 순수 #fff이었다 (게이트 7). 앵커 색조로 살짝 눕힌다. */
  --text:#f3ecdc; --body:#ded6c4; --sub:#cfc7b6; --dim:#98a2bd;
  --accent:#ff2e83; --on-accent:#fff6fa;
  /* 선 — `--rule`은 어두운 `--deep` 위에서 쓴다. 밝은 `--ground` 위에서는
     대비가 1.19:1까지 떨어져 **선이 안 보였다**(실측). 그 위에서는
     `--rule-lift`를 쓴다. */
  --rule:#22284a; --rule-lift:#454d7d; --rule-ink:#2a2050;
  /* 마스크 전용 불투명 — 색이 아니라 알파 채널 스텐실이다 */
  --stencil:#000;
  --scrim-strong:rgba(10,14,28,.96);
  --scrim-deep:rgba(10,14,28,.92);
  --scrim-mid:rgba(10,14,28,.86);
  --scrim-soft:rgba(10,14,28,.74);
  --scrim-low:rgba(10,14,28,.35);
  --scrim-edge:rgba(10,14,28,.72);
  --scrim-fade:rgba(10,14,28,.9);
  --scrim-panel:rgba(10,14,28,.6);
  --overlay-nav:rgba(10,14,28,.9);
  --overlay-sticky:rgba(10,14,28,.82);
  --shadow-float:rgba(10,14,28,.35);
  --shadow-face:rgba(10,14,28,.85);
  --ease-out:cubic-bezier(.16,1,.3,1);
  --dur-short:180ms;

  --font-pix:pix, ui-monospace, monospace;
  --font-display:var(--font-pix);
  --font-ui:system-ui, -apple-system, "Segoe UI", sans-serif;

  /* 4pt 스케일. 여백·간격은 전부 여기서만 고른다 (게이트 24).
     ⚠️ 9-슬라이스 `border-width`는 여기 해당되지 않는다 — 그 숫자는
     `part_fit.py`가 그림에서 잰 값이라 바꾸면 프레임이 깨진다. */
  --space-3xs:4px;  --space-2xs:8px;  --space-xs:12px; --space-sm:16px;
  --space-md:24px;  --space-lg:32px;  --space-xl:48px; --space-2xl:64px;
  --space-3xl:96px; --space-4xl:112px;

  --wrap:1120px;
}
*{ box-sizing:border-box }
/* 게이트 34 — 모든 폭에서 가로 스크롤 금지. `hidden`이 아니라 `clip`이다
   (`clip`은 자손의 sticky/fixed를 살려 둔다). */
html,body{ overflow-x:clip }
html{ scroll-behavior:smooth }
body{
  margin:0; background:var(--deep); color:var(--text);
  font-family:var(--font-ui); font-size:17px; line-height:1.65;
  -webkit-text-size-adjust:100%;
}
img{ max-width:100%; display:block }
a{ color:inherit }

/* 키보드로 오는 사람에게도 지금 어디에 있는지 보여야 한다 (게이트 26).
   ⚠️ 포커스 링은 **즉시** 나타난다 — transition을 걸지 않는다. */
:focus-visible{
  outline:2px solid var(--accent); outline-offset:2px; border-radius:1px;
}

/* ── 9-슬라이스 부품 ──────────────────────────────────────
   ⚠️ border-image 두께는 **내용 상자를 먹는다.** 안쪽 여백을 따로 준다. */
.panel{ border:20px solid transparent;
  border-image:url(static/ui/panel.webp) 15 fill / 20px / 0 stretch }
.talk{ border:18px solid transparent;
  border-image:url(static/ui/talk.webp) 27 fill / 18px / 0 stretch }
.chip{ border:14px solid transparent; display:inline-block;
  border-image:url(static/ui/chip.webp) 11 fill / 14px / 0 stretch }
.badge{ border:10px solid transparent; display:inline-block;
  border-image:url(static/ui/badge.webp) 13 fill / 10px / 0 stretch }

/* ── 버튼 ─────────────────────────────────────────────── */
.btn{
  border:14px solid transparent; display:inline-block;
  border-image:url(static/ui/btn.webp) 21 fill / 14px / 0 stretch;
  font-family:var(--font-pix); font-size:18px; letter-spacing:0;
  -webkit-font-smoothing:none; color:var(--text);
  text-decoration:none; padding:0 var(--space-xs); line-height:2;
  /* ⚠️ 게이트 49 — 클릭 대상은 **한 줄짜리 물건이다.** 320px에서 헤더
     "PLAY FREE"가 두 줄로 접혀 버튼이 고장 난 것처럼 보였다(실측). */
  white-space:nowrap;
  transition:transform var(--dur-short) var(--ease-out);
}
.btn:hover{ transform:translateY(-2px) }
.btn:active{ transform:translateY(0) }
.btn--go{ color:var(--on-accent); text-shadow:0 0 14px var(--accent) }
.btn--ghost{ border-image-source:url(static/ui/well.webp); color:var(--dim) }

.wrap{ max-width:var(--wrap); margin:0 auto; padding:0 var(--space-md) }

.label{
  font-family:var(--font-pix); font-size:18px; letter-spacing:0;
  -webkit-font-smoothing:none; color:var(--accent);
  display:block; margin-bottom:var(--space-sm);
}
h2{
  font-size:clamp(28px,4vw,42px); line-height:1.2; margin:0 0 var(--space-sm);
  font-weight:700; letter-spacing:-.02em;
  /* 게이트 51 — 긴 합성어가 좁은 화면을 넘지 않게 */
  overflow-wrap:anywhere; min-width:0;
}
h3{ font-size:21px; margin:0 0 var(--space-2xs); font-weight:700 }
body.landing h2{ font-family:var(--font-display); font-weight:400; letter-spacing:0 }
body.landing h3{ font-family:var(--font-display); font-weight:400; letter-spacing:0 }
p{ margin:0 0 var(--space-sm); color:var(--body) }
.dim{ color:var(--dim) }

header{
  position:sticky; top:0; z-index:50;
  background:var(--overlay-sticky); backdrop-filter:blur(10px);
  border-bottom:1px solid var(--rule);
}
body.landing header{
  position:fixed; top:16px; left:50%;
  width:min(calc(100% - 32px),640px); transform:translateX(-50%);
  background:var(--overlay-nav); backdrop-filter:blur(10px);
  border:1px solid var(--rule-lift); border-radius:999px;
  box-shadow:0 10px 28px var(--shadow-float);
}
.bar{
  max-width:var(--wrap); margin:0 auto;
  padding:var(--space-xs) var(--space-md);
  /* 게이트 36 — 높이가 다른 것들이 한 줄에 서면 중앙을 명시한다 */
  display:flex; align-items:center; justify-content:space-between; gap:var(--space-sm);
}
body.landing .bar{ width:100%; max-width:none; padding:var(--space-2xs) var(--space-xs) }
.mark{
  font-family:var(--font-pix); font-size:18px; letter-spacing:0;
  -webkit-font-smoothing:none; text-decoration:none; white-space:nowrap;
  line-height:1;
}
.mark b{ color:var(--accent); font-weight:400 }

/* ⚠️ 320px에서 워드마크(132px) + 버튼(160px) + 여백(48px) = 340px 로
   **20px 넘쳤다.** `nowrap`만 걸면 접히는 대신 잘린다 — 게이트 49의
   1순위 수정은 "라벨을 줄인다"이다. 헤더에서만 PLAY FREE → PLAY. */
.lbl-short{ display:none }
@media(max-width:420px){
  .bar{ padding:var(--space-xs) var(--space-sm) }
  .bar .lbl-full{ display:none }
  .bar .lbl-short{ display:inline }
}

/* ══ 히어로 — H6 Photographic ══════════════════════════
   아무도 없는 스트리밍 방. 그가 아직 없다는 것이 곧 카피다. */
.hero{ position:relative; overflow:hidden; min-height:min(88vh,760px); display:flex }
.hero__bg{
  position:absolute; inset:0; background:url(static/hero.webp) center 38%/cover no-repeat;
  filter:saturate(.9);
}
.hero__scrim{
  position:absolute; inset:0;
  background:
    linear-gradient(100deg, var(--scrim-strong) 0%, var(--scrim-mid) 42%, var(--scrim-low) 72%, var(--scrim-edge) 100%),
    radial-gradient(120% 80% at 50% 120%, var(--scrim-fade), transparent 60%);
}
/* 게이트 44 — 아래 여백이 위보다 두꺼워야 히어로가 다음 섹션에 얹힌다 */
.hero__in{
  position:relative; max-width:var(--wrap); margin:0 auto;
  padding:var(--space-2xl) var(--space-md) var(--space-3xl);
  display:flex; align-items:center; width:100%;
}
.hero__copy{ max-width:600px }
.title{
  font-family:var(--font-pix); font-size:36px; letter-spacing:0;
  -webkit-font-smoothing:none; margin:0 0 var(--space-md); line-height:1.3;
}
.title b{ color:var(--accent); font-weight:400 }
.hero h1{
  font-size:clamp(32px,5.2vw,56px); line-height:1.08; margin:0 0 var(--space-md);
  font-weight:700; letter-spacing:-.025em; overflow-wrap:anywhere; min-width:0;
}
.hero .sub{ font-size:clamp(18px,2.2vw,22px); color:var(--sub); margin:0 0 var(--space-lg) }
.cta{ display:flex; gap:var(--space-sm); flex-wrap:wrap; align-items:center }
.hero__note{ margin-top:var(--space-md); font-size:14px; color:var(--dim) }
.hero__route{
  display:flex; gap:var(--space-xs); align-items:center; flex-wrap:wrap;
  margin:var(--space-md) 0 0; color:var(--dim);
  font-family:var(--font-pix); font-size:14px; -webkit-font-smoothing:none;
}
.hero__route span{ color:var(--accent) }

/* 히어로 인물 — 표정이 조용히 바뀐다. 12종이 이미 있으니 안 쓸 이유가 없다.
   ⚠️ **폭으로 크기를 잡으면 안 된다.** 세로로 긴 인물이라 폭에 맞추는 순간
   히어로 높이를 넘겨 머리가 잘렸다. 상자를 히어로 높이에 붙이고
   그림은 높이 기준으로 맞춘다. */
.hero__her{
  position:absolute; right:max(-40px,-4vw); top:0; bottom:0; width:min(46vw,520px);
  pointer-events:none; mask-image:linear-gradient(to bottom,var(--stencil) 78%,transparent 99%);
}
.hero__her img{
  position:absolute; right:0; bottom:0; height:100%; width:auto; max-width:none;
  object-fit:contain; object-position:bottom right; opacity:0;
  filter:drop-shadow(-24px 0 60px var(--shadow-face));
}
.hero__her img.on{ opacity:1 }
/* ⚠️ 좁은 화면에서는 인물을 **내린다.** 흐리게 깔아 봤더니 얼굴이 제목·버튼
   바로 뒤에 앉아 둘 다 안 읽혔다. 배경(빈 방)만으로도 충분하고, 얼굴은
   바로 아래 로스터에서 여섯 번 나온다. 공유 카드(og:image)도 얼굴이다. */
@media(max-width:900px){
  .hero__her{ display:none }
  .hero{ min-height:min(84vh,680px) }
  .hero__bg{ background-position:64% 42% }
  .hero__scrim{
    background:
      linear-gradient(180deg, var(--scrim-deep) 0%, var(--scrim-soft) 46%, var(--scrim-fade) 100%);
  }
  .hero__in{
    padding:var(--space-4xl) var(--space-md) var(--space-2xl);
    align-items:flex-start;
  }
}

/* ══ 지금 플레이 가능 스트립 ═══════════════════════════ */
.strip{ background:var(--ground); border-block:1px solid var(--rule) }
.strip__in{
  max-width:var(--wrap); margin:0 auto;
  padding:var(--space-md);
  display:flex; gap:var(--space-xs) var(--space-lg); flex-wrap:wrap; align-items:center;
}
.strip .chip{ font-family:var(--font-pix); font-size:18px; -webkit-font-smoothing:none }
.strip .say{ color:var(--dim); font-size:15px }

/* ══ 섹션 리듬 ════════════════════════════════════════
   ⚠️ 종전에는 다섯 섹션이 전부 `padding:96px 0`이었다 — 게이트 9가 잡는
   "리듬 없음"이다. 섹션마다 다르게 준다. 조인 것과 벌린 것이 있어야 한다. */
section{ padding:var(--space-3xl) 0; scroll-margin-top:96px }
#comments{ padding:var(--space-3xl) 0 var(--space-xl) }
#how{ padding:var(--space-xl) 0 var(--space-3xl) }
#roster{ padding:var(--space-2xl) 0 var(--space-xl) }
#stage{ padding:var(--space-3xl) 0 var(--space-4xl) }
.section--tint{ background:var(--ground) }
.lede{ font-size:19px; max-width:68ch }

/* ══ 댓글 ═════════════════════════════════════════════
   Slay the Princess는 이 자리에 언론 리뷰를 넣는다. 우리는 리뷰가 없다.
   대신 **게임이 쓴 그의 댓글창**을 넣는다 — 없는 신뢰를 빌리는 대신
   있는 물건(글)을 보여주는 쪽이다. 출처는 아래에 분명히 밝힌다.

   9-슬라이스 대사 상자를 쓰는 자리는 페이지에서 여기 하나뿐이다. 댓글이
   실제로 대사라서 그렇고, 세 덩어리가 서로 다른 모양이어야 하기 때문이다. */
.thread{ display:grid; gap:var(--space-sm); grid-template-columns:repeat(12,minmax(0,1fr)) }
.thread .cmt:nth-child(1){ grid-column:span 7 }
.thread .cmt:nth-child(2){ grid-column:span 5 }
.thread .cmt:nth-child(3){ grid-column:span 4 }
.thread .cmt:nth-child(4){ grid-column:span 8 }
.thread .cmt:nth-child(5){ grid-column:span 3 }
.thread .cmt:nth-child(6){ grid-column:span 5 }
.cmt{ padding:var(--space-3xs) }
.cmt .u{
  font-family:var(--font-pix); font-size:18px; letter-spacing:0;
  -webkit-font-smoothing:none; color:var(--accent); display:block; margin-bottom:var(--space-2xs);
}
.cmt p{ margin:0; font-size:16px }
.cmt .meta{
  font-family:var(--font-pix); font-size:18px; -webkit-font-smoothing:none;
  color:var(--dim); margin-top:var(--space-xs); display:block;
}
.thread__src{ margin-top:var(--space-md); font-size:14px; color:var(--dim) }

.journey{ list-style:none; margin:var(--space-lg) 0 0; padding:0; border-top:1px solid var(--rule-lift) }
.journey li{
  display:grid; grid-template-columns:8ch minmax(0,1fr); gap:var(--space-md);
  padding:var(--space-md) 0; border-bottom:1px solid var(--rule-lift);
}
.journey__mark{ display:flex; flex-direction:column; gap:var(--space-2xs); color:var(--accent) }
.journey__mark span{ font-family:var(--font-pix); font-size:27px; line-height:1; -webkit-font-smoothing:none }
.journey__mark small{ color:var(--dim); font-family:var(--font-pix); font-size:14px; -webkit-font-smoothing:none }
.journey h3{ margin:0 0 var(--space-2xs) }
.journey p{ margin:0; color:var(--body); max-width:70ch }

/* ══ 로스터 ═══════════════════════════════════════════ */
.roster{ display:flex; gap:var(--space-sm); overflow-x:auto; padding:var(--space-3xs) 0 var(--space-sm); scroll-snap-type:x mandatory }
.roster figure{ margin:0; flex:0 0 200px; scroll-snap-align:start }
/* 인물은 가슴께에서 잘려 있다 — 그대로 두면 단면이 보인다. 아래를 흘린다. */
.roster img{ width:100%; mask-image:linear-gradient(to bottom,var(--stencil) 74%,transparent 99%) }
.roster figcaption{
  font-family:var(--font-pix); font-size:18px; letter-spacing:0;
  -webkit-font-smoothing:none; color:var(--dim); margin-top:var(--space-2xs);
}

/* ══ 네트워크 ═════════════════════════════════════════
   앱 넷은 카드가 아니라 **한 줄로 늘어선 띠**다. 위 명세표가 세로 규칙선,
   여기는 가로 구분선 — 두 덩어리가 같은 모양이 되지 않게. */
.apps{
  margin-top:var(--space-lg);
  display:flex; flex-wrap:wrap;
}
.apps .app{
  flex:1 1 200px; min-width:0;
  padding:0 var(--space-md);
  border-left:1px solid var(--rule-lift);
}
.apps .app:first-child{ flex-basis:40%; padding-left:0; border-left:0 }
.apps .n{
  font-family:var(--font-pix); font-size:27px; letter-spacing:0;
  -webkit-font-smoothing:none; display:block; margin-bottom:var(--space-2xs);
}
.apps .app p{ font-size:15px; margin:0; color:var(--dim) }
/* ⚠️ 768px에서 넷이 **3+1로 쪼개져** 마지막 하나가 한 줄을 통째로 먹었다.
   `.feat`에서 고쳤던 고아 문제가 여기서 되살아난 것이다. 중간 폭에서는
   2×2로 접는다 — 그리고 두 번째 줄의 첫 칸은 세로선을 뗀다. */
@media(min-width:721px) and (max-width:960px){
  .apps .app{ flex:0 0 50%; }
  .apps .app:nth-child(3){ padding-left:0; border-left:0 }
  .apps .app:nth-child(n+3){ margin-top:var(--space-md) }
}
@media(max-width:720px){
  .apps{ gap:var(--space-md) }
  .apps .app{ flex:1 1 100%; padding:0 0 0 var(--space-sm); border-left:1px solid var(--rule-lift) }
  .apps .app:first-child{ padding-left:var(--space-sm); border-left:1px solid var(--rule-lift) }
}

.stage{ position:relative; overflow:hidden; margin-top:var(--space-2xl) }
.stage__bg{ position:absolute; inset:0; background:url(static/street.webp) center 55%/cover no-repeat }
.stage__scrim{ position:absolute; inset:0; background:linear-gradient(90deg,var(--scrim-strong),var(--scrim-panel)) }
/* ⚠️ 가로 그라디언트는 글이 왼쪽에 몰려 있을 때만 맞다. 좁은 화면에서는
   글이 폭을 다 쓰므로 오른쪽 끝이 알파 0.6 위에 얹혀 상점 조명과 겹쳤다.
   여기서는 균일하게 덮는다 (게이트 40). */
@media(max-width:720px){
  .stage__scrim{ background:var(--scrim-deep) }
}
.stage__in{ position:relative; padding:var(--space-xl) var(--space-2xs) }
.stage__in .lede{ max-width:56ch }

/* ══ 경고 ═════════════════════════════════════════════
   Slay the Princess의 "Don't even think about trying to romance her."
   같은 자리다. 톤을 정하면서 동시에 잘못 온 관객을 돌려보낸다. */
.warn{ text-align:center; padding-block:var(--space-3xl) var(--space-2xl) }
/* ⚠️ 순서 주의 — 아래 `.warn p`가 `.big`도 잡아 문장이 흐려졌었다.
   그래서 `.big`을 뒤에 두고 색을 되돌린다. */
.warn p{ max-width:44ch; margin:0 auto; color:var(--dim) }
.warn .big{
  font-size:clamp(26px,4.4vw,44px); font-weight:700; line-height:1.25;
  margin:0 auto var(--space-sm); max-width:15ch; letter-spacing:-.02em;
  color:var(--text); overflow-wrap:anywhere; min-width:0;
}
body.landing .warn .big{ font-family:var(--font-display); font-weight:400 }

/* ══ 마지막 CTA ═══════════════════════════════════════ */
.end{ text-align:center; padding-block:var(--space-md) var(--space-xl) }
.end .cta{ justify-content:center }
.back{ color:var(--dim); font-family:var(--font-pix); font-size:14px; -webkit-font-smoothing:none; text-decoration:none; white-space:nowrap }
.back:hover{ color:var(--text) }

footer{ background:var(--ink); padding:var(--space-lg) 0; border-top:1px solid var(--rule-ink) }
.foot{ display:flex; gap:var(--space-sm); flex-wrap:wrap; align-items:center; font-size:14px; color:var(--dim) }
.foot a{ text-decoration:none; color:var(--dim); white-space:nowrap }
.foot__statement{ max-width:38ch; margin:0 0 var(--space-md); color:var(--text); font-family:var(--font-display); font-size:20px; line-height:1.3 }
.foot__meta{ display:flex; gap:var(--space-sm); flex-wrap:wrap; align-items:center; font-size:14px; color:var(--dim) }
.foot__meta a{ text-decoration:none; color:var(--dim); white-space:nowrap }
.foot a:hover{ color:var(--text) }
.foot__meta .sp{ margin-left:auto }
body.landing .foot{ display:block }

@media(max-width:720px){
  .thread{ grid-template-columns:minmax(0,1fr) }
  .thread .cmt:nth-child(n){ grid-column:auto }
  .journey li{ grid-template-columns:6ch minmax(0,1fr); gap:var(--space-sm) }
  .apps .app:first-child{ flex-basis:100% }
  .foot__meta .sp{ margin-left:0 }
}

@media(prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto }
  .btn{ transition:none }
}
