/* 생성되는 파일: tools/gamebuild.mjs 가 portal/src/css/*.css 로 만든다. 이 파일은 고치지 않는다. .css 파일을 고치고 다시 빌드한다. */
/* ---- 00-theme.css ---- */
/* 테마 세 가지 (docs/style.md, "테마"): MEDIUM 이 기본(:root 에 둔다), DAY 는 밝은 바탕, NIGHT 는 깊은 바탕이다.
   <html data-theme> 은 <head> 의 스크립트가 localStorage 'fiafia.theme' 을 보고 정한다. 강조색으로 칠한 면 위의 글자는 늘 짙은 자두색(--on-accent)이다.
   2026-10-27 화사한 꽃 디자인 (주인: "포털 디자인도 화사하게 하라", 같은 날 "앞으로 지시하면 화사한 꽃처럼 해야 한다. 파스텔 톤은 하지 마라"):
   MEDIUM 은 짙은 자홍빛 보라에서 장미로 번지는 바탕과 장미 빛 번짐, 장르 색은 하늘·주황·해바라기·보라·잎 초록·자홍의 선명한 색, 그림 칸 타일은 채도 88-95 %.
   DAY 는 밝은 분홍·크림 바탕에 선명한 강조색, NIGHT 는 깊은 밤색에 선명한 강조색. 글자 대비는 모든 테마에서 4.5 이상 (가장 낮은 것: MEDIUM 장르 태그 action 4.87).
   그 전 (같은 날 오전) 은 맑은 라벤더, 그 전 (2026-10-25) 은 탁한 보랏빛 황혼의 파스텔이었다. */
:root {
  --on-accent: #3a0a2e;
  --bg1: #4a0f6e; --bg2: #64137e; --bg3: #8a1668; --bgc: #561173;
  --glow: #ff4f9a40; /* 위 오른쪽의 장미 빛 번짐 (10-base.css 의 body) */
  --panel: #6a1a8c; --line: #c45cff;
  --text: #fff7fb; --muted: #ffe9f5; --dim: #f6d6ee;
  --accent: #ff4f9a; --accent-soft: #c2185b; --accent-ink: #fff0f6;
  --shadow: #1a003355; --no-bg: #4a0f6ee6; --index-bg: #4a0f6ee6;
  --scrim: #1a0030b8; /* 휴대폰의 장르 Drawer 뒤를 덮는 어둠 (47-drawer.css) */
  --thumb-hi: #ffffff26; --thumb-base: #561173;
  /* 테마별 그림 칸의 채도 / 밝기 (색조는 카드 자신의 --h 다). 오른쪽 아래 끝을 --tile-rose 쪽으로 --tile-mix 만큼 물들인다.
     기록: 2026-10-25 56/64/50/54 %, 2026-10-27 오전 68/70/62/62 %, 같은 날 화사한 꽃 디자인 92/60/88/48 % */
  --ts1: 92%; --tl1: 60%; --ts2: 88%; --tl2: 48%; --tile-rose: #ff4f9a; --tile-mix: 42%; --tile-spark: #fff6e0e6;
  --track: #8a3ab0; --track-ring: #c45cff;
  --font: ui-rounded, "SF Pro Rounded", "Hiragino Maru Gothic ProN", "Arial Rounded MT Bold", "Varela Round", system-ui, sans-serif;
  color-scheme: dark;
}
/* 장르의 강조색 묶음 (tone, portal/categories.json 의 장르마다 하나. 2026-10-25 에 장르가 14개가 되어 장르 이름 대신 묶음 이름을 쓴다):
   shooter (Shoot 'em Up, Space Shooters), action (Platformers, Run & Race, Adventure), cafe (Food & Cafe), arcade (Maze Arcade, Reflex & Rhythm),
   puzzle (Logic Puzzles, Match & Merge), sports (Ball Sports, Table & Lanes), strategy (Cards & Tactics, Defense & Conquest), new (New 줄), tag (태그 화면).
   새 묶음을 더하면 세 테마 모두에 적는다 (tools/gamecheck.mjs portal 이 장르의 tone 마다 [data-tone] 규칙이 있는지 본다) */
[data-tone="shooter"] { --accent: #4fc3ff; --accent-soft: #1f5fc4; --accent-ink: #f2f9ff; }
[data-tone="action"]  { --accent: #ff7a4a; --accent-soft: #c23b1e; --accent-ink: #fff2ec; }
[data-tone="arcade"]  { --accent: #ffd23f; --accent-soft: #8a5a00; --accent-ink: #fff8de; }
[data-tone="puzzle"]  { --accent: #b07aff; --accent-soft: #6b2fd6; --accent-ink: #f8f2ff; }
[data-tone="sports"]  { --accent: #3ee08f; --accent-soft: #0f7a46; --accent-ink: #eefff6; }
[data-tone="strategy"] { --accent: #ff5fc8; --accent-soft: #b0157a; --accent-ink: #fff0f8; }
[data-tone="cafe"]     { --accent: #ffa23c; --accent-soft: #a8500c; --accent-ink: #fff5ea; }
[data-tone="new"], [data-tone="tag"] { --accent: #ff4f9a; --accent-soft: #c2185b; --accent-ink: #fff0f6; }
/* featured: 맨 위의 주요 게임 (2026-11-01, 큰 배너의 점·멈춤 단추와 "Featured" 줄의 제목·칩). 해바라기 (장르 묶음이 아니다: gamecheck 가 보지 않는다) */
[data-tone="featured"] { --accent: #ffd23f; --accent-soft: #8a5a00; --accent-ink: #fff8de; }

:root[data-theme="day"] {
  --bg1: #fff0f7; --bg2: #fff8e8; --bg3: #f6ecff; --bgc: #fff8e8; --glow: #ff6fb04d;
  --panel: #ffffff; --line: #ffb3d9;
  --text: #3a0a2e; --muted: #5a1050; --dim: #6e2a66;
  --accent-soft: #ffe0ee; --accent-ink: #b0104e;
  --shadow: #ff4f9a33; --no-bg: #ffffffe0; --index-bg: #fff0f7e6; --scrim: #3a0a2e8c;
  --thumb-hi: #ffffff; --thumb-base: #fff8e8;
  --ts1: 95%; --tl1: 72%; --ts2: 92%; --tl2: 62%; --tile-rose: #ff7ab8; --tile-mix: 40%; --tile-spark: #ffffff;
  --track: #ffb3d9; --track-ring: #ff7ab8;
  color-scheme: light;
}
:root[data-theme="day"] [data-tone="shooter"] { --accent-soft: #dcefff; --accent-ink: #0d4f9e; }
:root[data-theme="day"] [data-tone="action"]  { --accent-soft: #ffe2d6; --accent-ink: #a8300c; }
:root[data-theme="day"] [data-tone="arcade"]  { --accent-soft: #fff0b8; --accent-ink: #6e4a00; }
:root[data-theme="day"] [data-tone="puzzle"]  { --accent-soft: #ece0ff; --accent-ink: #5a1fc0; }
:root[data-theme="day"] [data-tone="sports"]  { --accent-soft: #d6f7e6; --accent-ink: #0d6a3c; }
:root[data-theme="day"] [data-tone="strategy"] { --accent-soft: #ffe0f2; --accent-ink: #a0106c; }
:root[data-theme="day"] [data-tone="cafe"]     { --accent-soft: #ffe9d2; --accent-ink: #8a420a; }
:root[data-theme="day"] [data-tone="new"], :root[data-theme="day"] [data-tone="tag"] { --accent-soft: #ffe0ee; --accent-ink: #b0104e; }
:root[data-theme="day"] [data-tone="featured"] { --accent-soft: #fff0b8; --accent-ink: #6e4a00; }

:root[data-theme="night"] {
  --bg1: #160828; --bg2: #22093a; --bg3: #2e0b44; --bgc: #22093a; --glow: #c2185b33;
  --panel: #2c0f48; --line: #6a2a9a;
  --text: #fbefff; --muted: #ecd6ff; --dim: #d0b0ee;
  --accent-soft: #6a0d36; --accent-ink: #ffb3d1;
  --shadow: #00000066; --no-bg: #22093ae6; --index-bg: #1a0830e6; --scrim: #060010c4;
  --thumb-hi: #ffffff12; --thumb-base: #22093a;
  --ts1: 80%; --tl1: 42%; --ts2: 75%; --tl2: 32%; --tile-rose: #a01f6a; --tile-mix: 40%; --tile-spark: #ffe0f0aa;
  --track: #4a1a72; --track-ring: #6a2a9a;
}
:root[data-theme="night"] [data-tone="shooter"] { --accent-soft: #123a7a; --accent-ink: #9fd6ff; }
:root[data-theme="night"] [data-tone="action"]  { --accent-soft: #6a2210; --accent-ink: #ffb79a; }
:root[data-theme="night"] [data-tone="arcade"]  { --accent-soft: #5a4000; --accent-ink: #ffe066; }
:root[data-theme="night"] [data-tone="puzzle"]  { --accent-soft: #3e1a8a; --accent-ink: #d9c2ff; }
:root[data-theme="night"] [data-tone="sports"]  { --accent-soft: #0d4a2c; --accent-ink: #9ff0c8; }
:root[data-theme="night"] [data-tone="strategy"] { --accent-soft: #6a0d4a; --accent-ink: #ffb3e3; }
:root[data-theme="night"] [data-tone="cafe"]     { --accent-soft: #5a2f08; --accent-ink: #ffcf99; }
:root[data-theme="night"] [data-tone="new"], :root[data-theme="night"] [data-tone="tag"] { --accent-soft: #6a0d36; --accent-ink: #ffb3d1; }
:root[data-theme="night"] [data-tone="featured"] { --accent-soft: #5a4000; --accent-ink: #ffe066; }
/* ---- 10-base.css ---- */
* { box-sizing: border-box; }
html { scroll-padding-top: 112px; }  /* 휴대폰에서 붙어 있는 위쪽 막대(약 96) + 틈. 그래서 점프와 키보드 포커스가 그 아래에서 멈춘다 */
@media (min-width: 900px) { html { scroll-padding-top: 150px; } }  /* 넉넉한 데스크탑 막대(약 125) */
html, body { margin: 0; min-height: 100%; }
body { background: radial-gradient(ellipse 70% 520px at 85% 0, var(--glow, transparent), transparent 100%), linear-gradient(180deg, var(--bg1) 0%, var(--bg2) 38%, var(--bg3) 100%); background-color: var(--bgc); color: var(--text); font: 15px/1.5 var(--font); }

.wrap { --pad: clamp(12px, 3vw, 56px); margin: 0 auto; padding: 0 var(--pad) 28px; }  /* 폭 상한 없음: 줄과 카드가 화면 폭 전체를 채운다 */

/* 위쪽 막대는 두 가지로 설계한다. 900 px 미만(휴대폰 = MOBILE)에서는 자리를 아낀다: 아이콘으로 된 얇은 막대로, 1줄에 로고와 둥근 단추 네 개(search, view, info, theme),
   2줄에 장르 칩이 있고, 검색 단추를 누르면 검색 칸이 1줄 위에 열린다 (약 97 px). 900 px 부터(DESKTOP)는 자리가 있어서 넉넉하게 쓴다: 1줄에 큰 로고, 넓은 검색 칸,
   글자가 붙은 조작 단추(BY GENRE | ALL, INFO, DAY | MEDIUM | NIGHT), 2줄에 넓은 글자 링크로 된 장르가 있고 화면에 보이는 장르에 밑줄이 그어진다 (약 125 px). 막대는 화면 맨 위에 붙어 있다. */
.top { position: sticky; top: 0; z-index: 20; display: flex; flex-wrap: wrap; align-items: center; gap: 0 10px; margin: 0 calc(-1 * var(--pad)) 6px; padding: 6px var(--pad) 0;
  background: var(--index-bg); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); border-bottom: 1.5px solid var(--line); }
header { display: contents; }
h1 { order: 1; margin: 0; flex: none; font-size: 21px; line-height: 40px; font-weight: 800; letter-spacing: 3px; color: #d6568c;
  background: linear-gradient(90deg, #ff4f9a, #ffd23f); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.ctrl { order: 4; flex: none; display: flex; align-items: center; gap: 6px; margin-left: auto; }
.index { order: 5; flex: 1 0 100%; }
.search { order: 3; display: none; }
.d-only { display: none !important; }
.top.searching h1, .top.searching .ctrl { display: none; }
.top.searching .search { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 0; }
/* 로고 글자 왼쪽의 파비콘 (주인 2026-10-25: "파비콘 포털 타이틀 좌측에 보여줘."): 글자의 그라데이션은 글자에만 칠해지고 그림은 그대로 보인다. 장식이므로 alt 는 비운다 */
.top h1 { display: flex; align-items: center; gap: 8px; }
.top h1 .brand { flex: none; display: block; width: 28px; height: 28px; }
@media (max-width: 359px) { h1 { font-size: 19px; letter-spacing: 2px; } .top h1 { gap: 6px; } .top h1 .brand { width: 24px; height: 24px; } .ctrl { gap: 5px; } }

@media (min-width: 900px) {
  .m-only { display: none !important; }
  .d-only { display: flex !important; }
  .top { gap: 0 28px; padding: 16px var(--pad) 0; margin-bottom: 14px; }
  h1 { font-size: 32px; line-height: 48px; letter-spacing: 7px; }
  .top h1 { gap: 12px; }
  .top h1 .brand { width: 40px; height: 40px; }
  .search { order: 3; display: block; position: relative; flex: 1 1 320px; max-width: 480px; }
  .ctrl { gap: 16px; }
  .index { padding: 6px 0 0; }
}
@media (min-width: 900px) and (max-width: 1199px) { .top { gap: 0 18px; } .search { flex-basis: 200px; } .ctrl { gap: 10px; } }  /* 좁은 데스크탑 창: 같은 막대를 조금 더 촘촘하게 (여전히 두 줄) */
/* ---- 20-cards.css ---- */
/* 카드 (2026-10-25, 주인: "포털 그림 크기는 그대로 두고 카드 크기만 줄여도 되겠다."): 그림은 그대로 (ALL 96 px, 줄 80-130 px), 카드는 좁게 (ALL 격자 칸 최소 260 -> 140 / 172 / 180 px),
   그림 둘레의 빈 칸은 줄이고 (그림 칸 높이 150 px 고정 -> 위의 배지 띠 + 그림 + 아래 여백), 글 칸의 안쪽 여백도 줄였다. 휴대폰 ALL 은 한 줄에 1장 -> 2장이다. */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px; }
@media (min-width: 600px) { .grid { grid-template-columns: repeat(auto-fill, minmax(172px, 1fr)); gap: 14px; } }
@media (min-width: 900px) { .grid { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 16px; } }
/* 카드는 <div> 다: 제목 링크(.play)의 ::after 가 카드 전체를 덮어서 어디를 눌러도 게임이 열리고, 태그(.tag)는 그 위에 따로 놓인 링크다 (링크 안에 링크를 두지 않는다. 30-render.ts) */
.card { position: relative; isolation: isolate; display: flex; flex-direction: column; border: 1.5px solid var(--line); border-radius: 20px; background: var(--panel);
  color: inherit; overflow: hidden; box-shadow: 0 6px 18px var(--shadow); transition: transform .18s, box-shadow .18s, border-color .18s; }
.card:hover { transform: translateY(-3px); border-color: var(--accent); box-shadow: 0 10px 26px var(--shadow); }
.card:has(.play:focus-visible) { transform: translateY(-3px); border-color: var(--accent); }
.play { color: inherit; text-decoration: none; outline: none; }
.play::after { content: ''; position: absolute; inset: 0; z-index: 1; border-radius: 18.5px; }
.play:focus-visible::after { box-shadow: inset 0 0 0 3px var(--accent-ink); } /* 포커스 고리는 카드 안쪽에 (카드의 overflow: hidden 이 바깥 고리를 자른다) */
/* 그림 칸: 위 띠(--band)에 번호와 HI 배지, 그 아래에 그림, 아래 여백(--foot). 배지와 그림이 겹치지 않는다 (그림은 모서리까지 칠해진 것이 많다).
   BEST 가 보이면(배포본, body.has-best) HI 와 BEST 가 위아래로 두 줄이 되므로 띠도 두 줄이다 */
.thumb { position: relative; display: flex; align-items: flex-end; justify-content: center; --band: 30px; --foot: 10px; padding: var(--band) 0 var(--foot);
  background: radial-gradient(circle at 30% 25%, var(--thumb-hi) 0, transparent 55%), linear-gradient(145deg, hsl(var(--h, 258) var(--ts1) var(--tl1)), hsl(var(--h, 258) var(--ts2) var(--tl2))); }
.has-best .thumb { --band: 53px; }
/* 그림 칸 (2026-10-25): 왼쪽 위는 게임의 색조 그대로 (게임을 색으로 알아본다), 오른쪽 아래는 짝 색조(+35)를 핑크·라벤더(--tile-rose)로 물들인 맑은 파스텔.
   그 위에 작은 반짝이 점 다섯 개와 부드러운 빛 두 개. color-mix 를 모르는 브라우저는 위의 한 줄(예전 그라디언트)을 쓴다 */
@supports (background: color-mix(in oklab, red, blue)) {
  .thumb { background:
    radial-gradient(circle at 14% 72%, var(--tile-spark) 0 1.6px, transparent 2.4px),
    radial-gradient(circle at 84% 30%, var(--tile-spark) 0 2px, transparent 2.8px),
    radial-gradient(circle at 76% 84%, var(--tile-spark) 0 1.3px, transparent 2px),
    radial-gradient(circle at 24% 22%, var(--tile-spark) 0 1.2px, transparent 1.9px),
    radial-gradient(circle at 90% 62%, var(--tile-spark) 0 1px, transparent 1.6px),
    radial-gradient(circle at 30% 25%, var(--thumb-hi) 0, transparent 55%),
    radial-gradient(circle at 78% 88%, color-mix(in oklab, var(--tile-rose) 55%, transparent) 0, transparent 46%),
    linear-gradient(145deg, hsl(var(--h, 258) var(--ts1) var(--tl1)), color-mix(in oklab, hsl(calc(var(--h, 258) + 35) var(--ts2) var(--tl2)), var(--tile-rose) var(--tile-mix))); }
}
/* 카드 그림 칸이 좁으면(휴대폰의 카드) 번호 표의 "No." 를 빼고 네 자리 번호만 보인다. 그래야 오른쪽 위의 HI 표와 겹치지 않는다 (번호가 네 자리가 된 2026-10-24 부터) */
.thumb { container-type: inline-size; }
@container (max-width: 175px) { .np { display: none; } }
@container (max-width: 150px) { .grid .thumb .no, .grid .thumb .hi, .grid .thumb .best { padding: 1px 6px; font-size: 10.5px; letter-spacing: .3px; } } /* 320 px 휴대폰의 ALL 두 줄 카드(약 140 px): 번호와 BEST 사이 4 px 를 지킨다 */ /* 175: 휴대폰 ALL 화면의 두 줄 카드(162-177 px, 2026-10-25 카드를 줄인 뒤)도 번호와 HI·BEST 사이 4 px 를 지킨다 */
.thumb .icon { display: block; flex: none; width: 96px; height: 96px; filter: drop-shadow(0 4px 6px #1d124a33); }
/* 배지: 번호(왼쪽 위), HI 와 BEST (오른쪽 위, 위아래). 누름은 그 밑의 카드 링크로 지나간다 */
.no, .scores { position: absolute; top: 6px; z-index: 2; pointer-events: none; }
.no { left: 6px; }
.scores { right: 6px; display: flex; flex-direction: column; align-items: flex-end; gap: 3px; } /* HI 와 BEST 를 함께 (오른쪽 위, 위아래) */
.no, .hi, .best { padding: 1px 8px; border-radius: 999px; font-size: 11px; line-height: 15px; font-weight: 800; letter-spacing: .5px; white-space: nowrap; }
.no, .hi { background: var(--no-bg); border: 1.5px solid var(--accent); color: var(--accent-ink); }  /* HI: 이 기기의 나의 기록 (카드 번호는 왼쪽 위) */
.best { border: 1.5px solid var(--accent); background: var(--accent); color: var(--on-accent); }  /* BEST: 모든 사람의 최고 기록, HI 바로 아래 (배포본에서만) */
.best[hidden] { display: none; }
.body { display: flex; flex-direction: column; gap: 6px; padding: 9px 11px 11px; flex: 1; }
.title { margin: 0; font-size: 15px; line-height: 20px; font-weight: 800; letter-spacing: .5px; color: var(--text); overflow-wrap: anywhere; } /* 가장 긴 이름(MEADOWMARCH 약 131 px)도 넘치면 잘리지 않고 다음 줄로 */
@media (min-width: 600px) { .grid .title { font-size: 16px; line-height: 21px; letter-spacing: 1px; } } /* 줄 높이를 px 로: 카드 높이가 정수라서 줄 간격이 고르다 */
.desc { margin: 0; color: var(--text); font-size: 13px; line-height: 1.45; flex: 1; word-break: keep-all; }
.nodesc .desc { display: none; }  /* INFO 토글 꺼짐 */
/* ---- 25-rows.css ---- */
/* Netflix 방식의 줄 (BY GENRE 화면): 장르마다 한 줄, 카드는 옆으로 스크롤되는 띠 하나에 놓인다. ALL 화면은 평평한 .grid 를 그대로 쓴다.
   터치 화면에서는 띠를 끝에서 끝까지 쓸어 넘긴다. 마우스를 쓰면 화살표가 띠 양쪽의 자기 칸에 선다 (카드 위에는 절대 놓지 않는다: 빗나간 클릭이 게임을 열면 안 된다). */
.rail { position: relative; margin: 0 calc(-1 * var(--pad)); }
.track { display: flex; gap: 12px; overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain; scroll-snap-type: x proximity; scrollbar-width: none;
  padding: 12px var(--pad) 18px; scroll-padding: 0 var(--pad);
  --gap: 12px; --n: 2.4; --cw: calc((100% - (var(--n) - 1) * var(--gap)) / var(--n)); }  /* 화면에 카드 --n 장, 마지막 카드는 일부만 보인다 (줄이 스크롤된다는 것을 보여 준다) */
/* 카드 수 (2026-10-25 에 카드를 줄였다: 그림은 그대로, 카드만 좁게). 휴대폰은 거의 그대로다: 가장 긴 이름(MEADOWMARCH)이 15 px 로 들어가야 한다 */
@media (max-width: 359px) { .track { --n: 2.2; } }
@media (min-width: 600px) { .track { gap: 14px; --gap: 14px; --n: 3.8; } }
@media (min-width: 900px) { .track { --n: 5; } }
@media (min-width: 1200px) { .track { --n: 6.6; } }
@media (min-width: 1500px) { .track { --n: 7.8; } }
@media (min-width: 1800px) { .track { --n: 9.3; } }
@media (min-width: 2200px) { .track { --n: 11.3; } }
.track::-webkit-scrollbar { display: none; }
.track > .card { flex: 0 0 var(--cw); scroll-snap-align: start; }  /* 모든 줄에서 카드 크기가 같다 (주인 2026-10-25: "모든 줄에서 같은 크기"). 카드가 적은 줄은 오른쪽이 빈다 */
.track > .card:hover, .track > .card:has(.play:focus-visible) { transform: scale(1.05); z-index: 2; }
/* 그림은 예전 크기 그대로 (80-130 px). 그림 칸 = 위 띠 27 (번호, HI) + 그림 + 아래 7. BEST 가 있으면 띠 48 (HI 와 BEST 두 줄) */
.track .thumb { --band: 27px; --foot: 7px; }
.has-best .track .thumb { --band: 48px; }
.track .thumb .icon { width: clamp(80px, 6vw, 130px); height: clamp(80px, 6vw, 130px); }
.track .no, .track .scores { top: 5px; }
.track .no { left: 5px; }
.track .scores { right: 5px; gap: 2px; }
.track .no, .track .hi, .track .best { padding: 1px 6px; font-size: 10.5px; line-height: 14px; letter-spacing: .3px; }
@media (max-width: 380px) { .track .no, .track .hi, .track .best { padding: 1px 5px; letter-spacing: 0; } }
/* 아주 좁은 카드(320 px 휴대폰의 줄, 그림 칸 약 115 px): 번호 표와 HI 표를 더 작게 해서 서로 겹치지 않게 한다 ("No." 는 20-cards.css 의 컨테이너 쿼리가 이미 뺀다) */
@container (max-width: 125px) { .track .no, .track .hi, .track .best { padding: 1px 4px; font-size: 10px; letter-spacing: 0; } }
.track .body { padding: 8px 8px 9px; gap: 5px; }
.track .title { font-size: 15px; letter-spacing: 0; }
@media (min-width: 600px) { .track .title { letter-spacing: .5px; } }
.track .desc { font-size: 12.5px; }
.rail-btn { display: none; }
@media (hover: hover) and (pointer: fine) {
  .rail { display: flex; align-items: stretch; }
  .rail-btn { display: flex; align-items: center; justify-content: center; flex: 0 0 var(--pad); margin: 12px 0 18px; padding: 0; border: 0; border-radius: 12px; cursor: pointer;
    background: transparent; color: var(--dim); transition: background .15s, color .15s; }
  .rail-btn:hover, .rail-btn:focus-visible { background: var(--accent-soft); color: var(--accent-ink); }
  .rail-btn svg { width: 24px; height: 24px; }
  .rail[data-start="1"] .rail-btn.prev, .rail[data-end="1"] .rail-btn.next { visibility: hidden; }  /* 칸은 남아 있다. 그래서 띠가 튀지 않는다 */
  .track { flex: 1 1 0; min-width: 0; padding: 12px 8px 18px; scroll-padding: 0 8px; }
  .track { scroll-snap-type: none; user-select: none; -webkit-user-select: none; }  /* 마우스로 줄을 마음대로 끈다 (46-input-rail-drag.ts): 끈 뒤에 튀어 버릴 스냅은 쓰지 않는다 */
  .track a { -webkit-user-drag: none; }
  .track.dragging { cursor: grabbing; }
  .track.dragging > .card { pointer-events: none; }  /* 끄는 동안에는 hover 로 커지지 않고 pointer 커서도 없다 */
  .track.dragging .tag { pointer-events: none; }
}
@media (prefers-reduced-motion: reduce) { .rail-btn { transition: none; } .track > .card:hover, .track > .card:has(.play:focus-visible) { transform: none; } }
/* ---- 30-tools.css ---- */
/* 위쪽 막대의 조작 단추. 모바일 (900 px 아래): 둥근 아이콘 단추 둘 (search, menu, 48 px). 보기·계정·설명·테마는 메뉴(≡)를 누르면 펼쳐지는 글자 붙은 줄이다
   (주인 2026-10-26: "포털 모바일도 상단에 작은 버튼들이 있다. 수평으로 5개가 한계다. 더 작게 하면 누르기 어렵다", 고른 답: 검색 + 메뉴 하나).
   데스크탑: 나뉜 단추 BY GENRE | ALL, 글자가 붙은 ACCOUNT·INFO 알약 단추, 나뉜 단추 DAY | MEDIUM | NIGHT. 메뉴 칸 .more 는 데스크탑에서 display: contents 라서 단추가 제자리에 있다. */
.ctrl button { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; padding: 0; border: 1.5px solid var(--line); border-radius: 50%;
  background: var(--panel); color: var(--dim); font: inherit; cursor: pointer; touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
.ctrl button svg { width: 20px; height: 20px; flex: none; }
.ctrl button:hover { border-color: var(--accent); color: var(--text); }
.ctrl button:focus-visible, #searchclose:focus-visible { outline: 3px solid var(--accent-ink); outline-offset: 2px; }
.ctrl .lbl { display: none; }
#info[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
#viewbtn .v-rows, #viewbtn[data-view="all"] .v-grid { display: none; }  /* 누르면 바뀌어 갈 화면을 보여 준다: 장르 화면에서는 격자 아이콘, 전체 화면에서는 줄 아이콘 */
#viewbtn[data-view="all"] .v-rows { display: block; }
#themebtn span { display: none; }
:root[data-theme="day"] #themebtn .t-day, :root[data-theme="medium"] #themebtn .t-medium, :root[data-theme="night"] #themebtn .t-night { display: inline-flex; }  /* 지금 쓰는 테마의 아이콘 */
#info .m-lbl, #viewbtn .lbl { display: none; }
.more { display: contents; }
@media (max-width: 899px) {
  .ctrl { position: relative; }
  .ctrl > button { width: 48px; height: 48px; }                 /* 검색, 메뉴: 손가락에 맞게 (44 CSS px 넘게) */
  .ctrl > button svg { width: 22px; height: 22px; }
  #menubtn[aria-expanded="true"] { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
  .more { display: none; position: absolute; top: calc(100% + 8px); right: 0; z-index: 30; flex-direction: column; gap: 6px; min-width: 232px; padding: 8px;
    background: var(--bgc); border: 1.5px solid var(--line); border-radius: 18px; box-shadow: 0 12px 32px rgba(0, 0, 0, 0.38); }
  .menu-open .more { display: flex; }
  .more button { width: 100%; height: 48px; justify-content: flex-start; gap: 12px; padding: 0 16px; border-radius: 14px; color: var(--text);
    font-size: 13px; font-weight: 800; letter-spacing: 1.5px; }
  .more button svg { width: 20px; height: 20px; }
  .more .lbl, .more #themebtn .lbl, .more #info .m-lbl, .more #viewbtn .v-all { display: inline; } /* 메뉴 줄의 글자 (밖의 숨김 규칙이 id 라서 id 로 이긴다) */
  .more #info .d-lbl, .more #viewbtn[data-view="all"] .v-all { display: none; }
  .more #viewbtn[data-view="all"] .v-genre { display: inline; }  /* 누르면 바뀌어 갈 화면의 이름 */
}

@media (min-width: 900px) {
  .ctrl button { height: 44px; width: auto; border-radius: 999px; font-size: 12px; font-weight: 800; letter-spacing: 2px; }
  .views button { min-width: 100px; border-radius: 0; }
  .views button:first-child { border-radius: 999px 0 0 999px; }
  .views button:last-child { border-radius: 0 999px 999px 0; margin-left: -1.5px; min-width: 70px; }
  .views button.on, .themes button[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--on-accent); position: relative; }
  .themes button { gap: 8px; padding: 0 16px 0 14px; border-radius: 0; }
  .themes button .lbl { display: inline; }
  .themes button + button { margin-left: -1.5px; }
  .themes button:first-child { border-radius: 999px 0 0 999px; }
  .themes button:last-child { border-radius: 0 999px 999px 0; }
  .themes button svg { width: 18px; height: 18px; }
  #info { width: auto; padding: 0 20px 0 16px; gap: 10px; border-radius: 999px; }
  #info .lbl { display: inline; }
  #info .m-lbl { display: none; }
}
@media (min-width: 900px) and (max-width: 1199px) {
  .themes button { padding: 0 14px; } .themes button .lbl { display: none; }  /* 좁은 데스크탑 창에서는 아이콘만 */
  .views button { min-width: 84px; } .views button:last-child { min-width: 56px; }
  #info { padding: 0 16px 0 12px; }
}
/* ---- 35-search.css ---- */
/* 번호나 이름으로 검색(#q)과 결과 줄. 모바일: 검색 단추가 위쪽 막대 위에 열 때까지 숨어 있다. 데스크탑: 늘 보이고 돋보기가 붙는다. */
.search input { width: 100%; height: 40px; padding: 0 16px; border: 1.5px solid var(--line); border-radius: 999px; background: var(--panel); color: var(--text);
  font: inherit; font-weight: 700; letter-spacing: 1px; -webkit-appearance: none; appearance: none; }
.search input::placeholder { color: var(--dim); font-weight: 600; letter-spacing: 1px; }
.search input:focus { outline: 3px solid var(--accent-ink); outline-offset: 2px; border-color: var(--accent); }
.search .s-ico { display: none; }
#searchclose { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; padding: 0; border: 1.5px solid var(--line); border-radius: 50%; background: var(--panel); color: var(--dim); cursor: pointer; }
#searchclose svg { width: 20px; height: 20px; }
@media (min-width: 900px) {
  .search .s-ico { display: block; position: absolute; top: 50%; color: var(--dim); pointer-events: none; }
  .search input { height: 46px; padding-left: 46px; font-size: 15px; }
  .search .s-ico { left: 16px; width: 20px; height: 20px; margin-top: -10px; }
}
.found { margin: 4px 0 16px; color: var(--dim); font-size: 13px; font-weight: 800; letter-spacing: 3px; text-transform: uppercase; }
/* ALL 화면의 순서 단추: 번호 / 이름 (나뉜 알약 단추, 누르는 높이 44 px) */
.sortbar { display: flex; justify-content: flex-end; margin: 0 0 14px; }
.sortbar button { min-width: 72px; height: 44px; padding: 0 16px; border: 1.5px solid var(--line); background: var(--panel); color: var(--dim);
  font: inherit; font-size: 12px; font-weight: 800; letter-spacing: 2px; cursor: pointer; touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
.sortbar button:first-child { border-radius: 999px 0 0 999px; }
.sortbar button:last-child { border-radius: 0 999px 999px 0; margin-left: -1.5px; }
.sortbar button:hover { border-color: var(--accent); color: var(--text); }
.sortbar button.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); position: relative; }
.sortbar button:focus-visible { outline: 3px solid var(--accent-ink); outline-offset: 2px; }
/* ---- 40-genres.css ---- */
/* 장르 색인 (태그 화면에서는 태그 색인). 모바일: 위쪽 막대 2줄의 칩(알약 모양), 화면에 보이는 구역의 칩이 채워진다. 데스크탑: 2줄의 넓은 보통 글자 링크, 화면에 보이는 것에 밑줄이 그어진다.
   칩은 띠(.ix-track) 하나에 있고 옆으로 스크롤된다 (장르 15개, 태그 19개: 360 px 휴대폰에도 1280 px PC 에도 다 들어가지 않는다). 더 있는 쪽 끝은 흐려진다.
   마우스 화면에서는 띠 양쪽에 화살표가 있고 (더 있는 쪽에만 보인다), 휠과 끌기로도 민다 (43-ui-rows.ts, 46-input-rail-drag.ts) */
.index { display: flex; align-items: center; min-width: 0; margin: 0; padding: 6px 0 8px; } /* min-width 0: 칩 띠가 넘쳐도 막대 폭을 넘지 않는다 */
.index:empty { display: none; }
.ix-track { position: relative; flex: 1 1 0; min-width: 0; display: flex; gap: 8px; overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain; scrollbar-width: none; scroll-padding: 0 28px; }
.ix-track::-webkit-scrollbar { display: none; }
.index[data-start="1"][data-end="0"] .ix-track { -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent); mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent); }
.index[data-start="0"][data-end="1"] .ix-track { -webkit-mask-image: linear-gradient(90deg, transparent, #000 28px); mask-image: linear-gradient(90deg, transparent, #000 28px); }
.index[data-start="0"][data-end="0"] .ix-track { -webkit-mask-image: linear-gradient(90deg, transparent, #000 28px, #000 calc(100% - 28px), transparent); mask-image: linear-gradient(90deg, transparent, #000 28px, #000 calc(100% - 28px), transparent); }
.index a { flex: 1 0 auto; display: flex; align-items: center; justify-content: center; min-height: 36px; padding: 0 12px; border: 1.5px solid var(--accent); border-radius: 999px;
  background: var(--accent-soft); color: var(--accent-ink); font-size: 12px; font-weight: 800; letter-spacing: 1px; white-space: nowrap; text-decoration: none; text-transform: uppercase; touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
.index a[aria-current="true"] { background: var(--accent); color: var(--on-accent); }
.index a:active { background: var(--accent); color: var(--on-accent); }
.index a:focus-visible { outline: 3px solid var(--accent-ink); outline-offset: -3px; } /* 안쪽 고리: 띠의 overflow 가 바깥 고리를 자른다 */
.ix-btn { display: none; }
@media (max-width: 340px) { .ix-track { gap: 6px; } .index a { padding: 0 8px; font-size: 11px; letter-spacing: 0; } }
@media (hover: hover) and (pointer: fine) {
  .ix-btn { display: flex; flex: 0 0 30px; align-items: center; justify-content: center; height: 36px; padding: 0; border: 0; border-radius: 10px; background: transparent; color: var(--dim); cursor: pointer; }
  .ix-btn:hover { background: var(--panel); color: var(--text); }
  .ix-btn svg { width: 20px; height: 20px; }
  .index[data-start="1"] .ix-btn.prev, .index[data-end="1"] .ix-btn.next { visibility: hidden; }
  .ix-track { user-select: none; -webkit-user-select: none; }
  .ix-track a { -webkit-user-drag: none; }
  .ix-track.dragging { cursor: grabbing; }
  .ix-track.dragging a { pointer-events: none; }
}
@media (min-width: 900px) {
  .index { padding: 4px 0 0; }
  .ix-track { gap: 4px; align-items: center; }
  .index a { flex: 0 0 auto; min-height: 52px; padding: 0 16px; border: 0; border-bottom: 3px solid transparent; border-radius: 0; background: transparent; color: var(--dim); font-size: 13px; letter-spacing: 2px; }
  .index a:hover { color: var(--text); }
  .index a[aria-current="true"] { background: transparent; color: var(--text); border-bottom-color: var(--accent); }
  .index a:active { background: transparent; color: var(--text); }
  .ix-btn { height: 52px; }
}

.genre { margin-bottom: 10px; }
.genre:last-child { margin-bottom: 0; }
.gh:focus { outline: none; }
.gh { display: flex; align-items: center; gap: 10px; margin: 0 0 2px; font-size: 17px; font-weight: 800; letter-spacing: 4px; text-transform: uppercase; color: var(--text); }
.gh::before { content: ''; width: 12px; height: 12px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.gh::after { content: ''; flex: 1; border-top: 2px dotted var(--accent); }
/* 칩을 누르면 뛰어간 장르 제목이 반응한다: 점이 부풀고, 글자가 벌어지며 밝아지고, 점선이 굵어진다 (약 0.9 초). 움직임 줄이기 설정: 색만 잠깐 머문다. */
.gh.pulse { animation: ghTitle .9s ease-out; }
.gh.pulse::before { animation: ghDot .9s ease-out; }
.gh.pulse::after { animation: ghLine .9s ease-out; }
@keyframes ghTitle { 0% { letter-spacing: 4px; color: var(--accent-ink); } 30% { letter-spacing: 7px; color: var(--accent-ink); } 100% { letter-spacing: 4px; color: var(--text); } }
@keyframes ghDot { 0% { transform: scale(1); box-shadow: 0 0 0 4px var(--accent-soft); } 30% { transform: scale(1.5); box-shadow: 0 0 0 10px var(--accent-soft); } 100% { transform: scale(1); box-shadow: 0 0 0 4px var(--accent-soft); } }
@keyframes ghLine { 0% { border-top-width: 5px; border-top-color: var(--accent-ink); } 100% { border-top-width: 2px; border-top-color: var(--accent); } }
@keyframes ghHold { 0%, 85% { color: var(--accent-ink); } 100% { color: var(--text); } }
@media (prefers-reduced-motion: reduce) { .gh.pulse { animation: ghHold 1.2s linear; } .gh.pulse::before, .gh.pulse::after { animation: none; } }
.gn { padding: 0 9px; border-radius: 999px; background: var(--accent-soft); font-size: 11px; letter-spacing: 0; color: var(--accent-ink); }

footer { margin-top: 36px; text-align: center; color: var(--dim); font-size: 12px; font-weight: 600; line-height: 2; }
footer a { color: var(--dim); text-decoration: underline; text-underline-offset: 3px; padding: 6px 4px; } /* 사이트 안내 (about.html, privacy.html): 누르기 쉽게 위아래를 넓힌다 */
@media (prefers-reduced-motion: reduce) { .card, #info::before { transition: none; } .card:hover, .card:has(.play:focus-visible) { transform: none; } }
/* 배너 자리 (portal/src/30-render.ts 의 AD_SLOT): 비어 있으면 자리를 차지하지 않는다. 채워지면 카드와 넉넉히 떨어뜨린다 (실수 클릭을 막는다) */
.adslot:empty { display: none; }
.adslot-end { margin: 40px 0 8px; } /* 포털 맨 아래 (꼬리말 위) 의 배너 자리 (주인 2026-10-26: "포털 가장 하단에 adsense 넣자") */
.adslot { margin: 30px 0 34px; }
.grid + .adslot { margin-top: 30px; }
.grid ~ .grid { margin-top: 12px; } /* ALL 화면은 카드 12장마다 나뉜다: 배너가 없을 때도 줄 사이 간격은 격자의 간격과 같다 (20-cards.css) */
@media (min-width: 600px) { .grid ~ .grid { margin-top: 14px; } }
@media (min-width: 900px) { .grid ~ .grid { margin-top: 16px; } }
/* ---- 45-tags.css ---- */
/* 카드의 태그와 태그 화면 (주인 2026-10-25: "분류를 세세하게 하면 찾기 쉽지 않나" -> "둘 다"). 태그는 누르는 링크(#tag=<id>)다.
   보이는 알약은 22 px 이지만 누르는 자리는 위아래로 5 px, 옆으로 2 px 씩 넓다 (::before, 32 x 알약 폭+4): 줄 사이 간격 10 px 와 알약 사이 5 px 를 서로 나눠 쓰므로 겹치지 않고 카드도 키우지 않는다. */
.sr { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
.tags { position: relative; z-index: 2; display: flex; flex-wrap: wrap; gap: 10px 5px; margin-top: auto; padding-top: 2px; pointer-events: none; } /* 알약 사이의 빈 곳을 누르면 카드 링크로 지나간다 */
.tag { position: relative; pointer-events: auto; display: inline-flex; align-items: center; height: 22px; padding: 0 7px; border-radius: 999px; background: var(--accent-soft);
  color: var(--accent-ink); font-size: 11px; font-weight: 700; letter-spacing: 0; white-space: nowrap; text-decoration: none; touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
.tag::before { content: ''; position: absolute; inset: -5px -2px; border-radius: 999px; }
.tag:hover, .tag[aria-current="true"] { background: var(--accent); color: var(--on-accent); }
.tag:active { background: var(--accent); color: var(--on-accent); }
.tag:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
.track .tag { padding: 0 6px; }
@media (max-width: 599px) { .track .tag { padding: 0 5px; } } /* 휴대폰 줄의 좁은 카드: 태그 둘이 한 줄에 들어가는 일이 많아진다 */
/* ALL, 검색, 태그 화면의 격자: 태그 자리를 두 줄로 잡아 둔다. 그래서 390 px 휴대폰과 PC 에서 카드 높이가 모두 같고 줄 간격이 고르다 (태그가 한 줄인 카드는 아래 줄에 놓인다) */
.grid .tags { min-height: 56px; align-content: flex-end; } /* 위 여백 2 + 알약 22 + 사이 10 + 22 */

/* 태그 화면: 머리글 "Cozy · 7 games" 와 Back 단추 (알약, 누르는 높이 44 px), 그 아래 ALL 과 같은 격자 */
.taghead { display: flex; align-items: center; gap: 12px; margin: 2px 0 14px; }
.back { flex: none; display: inline-flex; align-items: center; gap: 4px; height: 44px; padding: 0 16px 0 10px; border: 1.5px solid var(--line); border-radius: 999px; background: var(--panel); color: var(--text);
  font: inherit; font-size: 12px; font-weight: 800; letter-spacing: 2px; text-transform: uppercase; cursor: pointer; touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
.back svg { width: 18px; height: 18px; }
.back:hover { border-color: var(--accent); }
.back:focus-visible { outline: 3px solid var(--accent-ink); outline-offset: 2px; }
.th { margin: 0; min-width: 0; font-size: 18px; font-weight: 800; letter-spacing: 3px; text-transform: uppercase; color: var(--text); overflow-wrap: break-word; }
.th:focus { outline: none; }
.th .tcount { color: var(--accent-ink); letter-spacing: 1px; text-transform: none; font-size: 15px; }
@media (min-width: 900px) { .taghead { margin: 4px 0 18px; gap: 16px; } .th { font-size: 22px; letter-spacing: 4px; } .th .tcount { font-size: 17px; } }
/* ---- 47-drawer.css ---- */
/* 휴대폰의 장르 Drawer (주인 2026-10-28: "포털 상단의 장르 칩을 모바일에서는 Drawer로 나타나고 선택하면 이동 할 수 있게 하라.", portal/src/49-ui-drawer.ts).
   휴대폰 (아래 @media = 01-config.ts 의 DRAWER_MQ: 900 px 아래의 모바일 막대 가운데 짧은 변이 600 px 아래) 의 BY GENRE 에서는 위 막대 둘째 줄의 장르 칩 띠를 숨기고
   장르 단추 (#genrebtn) 하나를 둔다: 지금 장르의 색 점과 이름, "GENRES", 펼침 표시. 48 px 높이 (위 막대의 검색·메뉴 단추와 같다), 한 줄에 단추 하나.
   태그 화면의 태그 칩 띠, 태블릿과 PC 의 칩 띠는 그대로다. 색은 모두 00-theme.css 의 변수 (장르 tone 의 강조색) 다. */
.gd-btn { display: none; }
@media (max-width: 599px), (max-width: 899px) and (max-height: 599px) {
  html { scroll-padding-top: 120px; } /* 장르 단추 줄이 칩 줄보다 8 px 높다 (위 막대 약 113 px + 틈) */
  .index[data-kind="genres"] { padding: 4px 0 8px; }
  .index[data-kind="genres"] .ix-track, .index[data-kind="genres"] .ix-btn { display: none; }
  .gd-btn { display: flex; flex: 1 1 auto; align-items: center; gap: 10px; min-width: 0; height: 48px; padding: 0 14px 0 16px; border: 1.5px solid var(--accent); border-radius: 999px;
    background: var(--accent-soft); color: var(--accent-ink); font: inherit; font-size: 14px; font-weight: 800; letter-spacing: 1.5px; text-transform: uppercase;
    cursor: pointer; touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
  .gd-btn .gd-dot { flex: none; width: 12px; height: 12px; border-radius: 50%; background: var(--accent); }
  .gd-btn .gd-cur { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left; }
  .gd-btn .gd-all { flex: none; font-size: 12px; letter-spacing: 1.5px; }
  .gd-btn svg { flex: none; width: 18px; height: 18px; margin-left: -4px; }
  .gd-btn:active, .gd-btn[aria-expanded="true"] { background: var(--accent); color: var(--on-accent); }
  .gd-btn:active .gd-dot, .gd-btn[aria-expanded="true"] .gd-dot { background: var(--on-accent); }
  .gd-btn:focus-visible { outline: 3px solid var(--accent-ink); outline-offset: 2px; }
}
@media (max-width: 339px) { .gd-btn .gd-all { display: none; } } /* 아주 좁은 휴대폰: 이름이 더 들어가게 */

/* 판 (<dialog id="gdrawer">): 화면 전체를 덮는 투명한 틀 안에 어두운 덮개 (.gd-scrim, 누르면 닫힌다) 와 아래에서 올라오는 판 (.gd-sheet).
   판의 높이는 내용만큼, 화면 높이 - 40 px 까지 (넘치면 목록이 판 안에서 스크롤된다). 넓으면 (가로 휴대폰) 줄이 여러 열이 된다. 판 폭은 760 px 까지 */
.gdrawer { position: fixed; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none; margin: 0; padding: 0; border: 0; overflow: hidden;
  background: transparent; color: var(--text); font: 15px/1.5 var(--font); }
.gdrawer::backdrop { background: transparent; }
.gd-scrim { position: absolute; inset: 0; background: var(--scrim); opacity: 0; transition: opacity .24s ease-out; }
.gd-sheet { position: absolute; left: 0; right: 0; bottom: 0; margin: 0 auto; max-width: 760px; max-height: calc(100% - 40px); display: flex; flex-direction: column;
  background: var(--bgc); border: 1.5px solid var(--line); border-bottom: 0; border-radius: 24px 24px 0 0; box-shadow: 0 -10px 36px var(--shadow);
  padding-bottom: env(safe-area-inset-bottom, 0px); transform: translateY(100%); transition: transform .24s cubic-bezier(.2, .8, .2, 1); }
.gdrawer.in .gd-scrim { opacity: 1; }
.gdrawer.in .gd-sheet { transform: none; }
.gd-sheet.drag { transition: none; }
.gd-head { position: relative; flex: none; display: flex; align-items: center; gap: 12px; padding: 16px 12px 8px 22px; touch-action: none; }
.gd-grip { position: absolute; top: 7px; left: 50%; width: 44px; height: 5px; margin-left: -22px; border-radius: 3px; background: var(--line); }
.gd-title { flex: 1 1 auto; margin: 0; font-size: 15px; font-weight: 800; letter-spacing: 4px; text-transform: uppercase; color: var(--text); }
.gd-x { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; padding: 0; border: 1.5px solid var(--line); border-radius: 50%;
  background: var(--panel); color: var(--text); cursor: pointer; touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
.gd-x svg { width: 22px; height: 22px; }
.gd-x:focus-visible { outline: 3px solid var(--accent-ink); outline-offset: 2px; }
.gd-list { position: relative; flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; margin: 0; padding: 4px 12px 14px; list-style: none;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 6px 10px; align-content: start; }
.gd-list li { min-width: 0; }
.gd-list a { display: flex; align-items: center; gap: 12px; min-height: 52px; padding: 4px 12px 4px 16px; border: 1.5px solid transparent; border-radius: 16px; color: var(--text);
  font-size: 15px; font-weight: 800; line-height: 1.25; letter-spacing: 1.5px; text-decoration: none; text-transform: uppercase; touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
.gd-list .gd-dot { flex: none; width: 12px; height: 12px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.gd-list .gd-name { flex: 1 1 auto; min-width: 0; }
.gd-list .gd-n { flex: none; min-width: 32px; padding: 1px 9px; border-radius: 999px; background: var(--accent-soft); color: var(--accent-ink); font-size: 12px; letter-spacing: 0; text-align: center; }
.gd-list a:active { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-ink); }
.gd-list a[aria-current="true"] { border-color: var(--accent); background: var(--accent); color: var(--on-accent); }
.gd-list a[aria-current="true"] .gd-dot { background: var(--on-accent); box-shadow: none; }
.gd-list a[aria-current="true"] .gd-n { background: var(--on-accent); color: var(--accent); }
.gd-list a:focus-visible { outline: 3px solid var(--accent-ink); outline-offset: -3px; }
@media (hover: hover) and (pointer: fine) { .gd-list a:hover { border-color: var(--accent); } }
@media (max-height: 599px) { /* 가로 휴대폰: 판을 화면 폭 거의 다 쓰고 (줄 세 열), 머리를 줄인다 */
  .gd-sheet { max-width: none; max-height: calc(100% - 16px); margin: 0 8px; }
  .gd-head { padding: 12px 12px 4px 22px; }
  .gd-list { padding: 2px 12px 10px; gap: 4px 10px; }
  .gd-list a { min-height: 50px; font-size: 14px; letter-spacing: 1px; }
}
html.gd-lock { overflow: hidden; } /* 판이 열린 동안 뒤 페이지는 스크롤되지 않는다 */
@media (prefers-reduced-motion: reduce) { .gd-scrim, .gd-sheet { transition: none; } }
/* ---- 50-cardart.css ---- */
/* 카드 그림 (2026-10-29, 주인: "포털의 카드 디자인이 단조롭고 반복적이다. 게임에 특성에 맞게 카드를 디자인 하라." → "게임 배경을 카드에 넣고, 게임 장르가 아니라
   게임의 독특한 디자인 요소로 틀을 만들어라. 현재 배경은 매스껍다."): 게임이 자기 그림 함수로 그린 카드 장면 (assets/card.webp, tools/cardart.mjs) 이 있는 카드 (.card.art).
   그림 칸: 예전의 색조 그라디언트·반짝이 점 바탕과 icon.svg 대신 그 그림 한 장. 그림은 칸 전체에 가로세로비를 지켜 들어가고 (contain), 남는 자리는 그림의 가장자리 색 (--ce) 이라
   그림의 틀이 이어진다 (칸의 가로세로비는 화면마다 1.15-1.72, 그림은 1.45). 칸의 크기는 그대로다: 자리만 잡는 빈 .icon 이 예전 그림과 같은 크기를 갖는다 (카드 높이와 CLS 가 같다).
   아래 띠 (이름, 설명, 태그) 와 배지 (번호, HI, BEST) 는 그 게임의 색: 띠 --cb, 글자 --ci, 강조 --ca (테두리, 누른 태그, BEST), 태그 바탕 --cc (= --cb 를 --ci 쪽으로 16 %).
   색은 게임이 정하고 (drawCardArt 가 돌려준다), 굽는 도구와 tools/gamecheck.mjs 가 글자 대비 4.5 이상을 본다. 테마 (DAY, MEDIUM, NIGHT) 와 상관없이 같다: 게임의 모습은 하나다 */
.card.art { background: var(--cb); border-color: var(--cb); }
.card.art:hover, .card.art:has(.play:focus-visible) { border-color: var(--ca); }
.card.art .thumb { background: var(--ce); }
.card.art .thumb .icon { filter: none; }
.card.art .thumb .cart { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: contain; }
.card.art .play:focus-visible::after { box-shadow: inset 0 0 0 3px var(--ca); }
.card.art .title, .card.art .desc { color: var(--ci); }
.card.art .no, .card.art .hi { background: var(--cb); border-color: var(--ca); color: var(--ci); }
.card.art .best { background: var(--ca); border-color: var(--ca); color: var(--cb); }
.card.art .tag { background: var(--cc); color: var(--ci); }
.card.art .tag:hover, .card.art .tag[aria-current="true"], .card.art .tag:active { background: var(--ca); color: var(--cb); }
.card.art .tag:focus-visible { outline-color: var(--ca); }
/* ---- 55-phone-text.css ---- */
/* 휴대폰의 작은 글자를 12 CSS px 로 (2026-11-01, CLAUDE.md "휴대폰 글자는 12 CSS px 이상 (11 미만 금지)"). 그 전에는 카드의 번호·HI·BEST 배지가 10-11 px,
   태그가 11 px, 구역 제목 옆의 게임 수가 11 px, 아주 좁은 휴대폰 (340 px 아래) 의 색인 칩이 11 px 였다.
   휴대폰 = 47-drawer.css 의 Drawer 와 같은 조건 (900 px 아래의 모바일 막대 가운데 짧은 변이 600 px 아래: 세로 휴대폰은 폭, 가로 휴대폰은 높이). 태블릿과 PC 는 그대로다.
   배지가 커져도 번호 (왼쪽 위) 와 HI (오른쪽 위) 가 같은 줄에서 겹치지 않게 글자 사이를 0, 옆 여백을 5 px 로 줄였다.
   BEST 는 언제나 둘째 줄 (HI 아래) 이다: HI 가 없어도 둘째 줄에 둔다. 그래서 넓은 BEST 가 번호와 같은 줄에 오지 않는다 (320 px 휴대폰의 좁은 카드).
   배지 높이 20 px (12 px 글자, 줄 15 px): 위 띠 (줄 27 / ALL 30 px, BEST 가 있으면 48 / 53 px) 안에 든다. 카드와 그림 칸의 크기는 그대로다 */
@media (max-width: 599px), (max-width: 899px) and (max-height: 599px) {
  .thumb .no, .thumb .hi, .thumb .best, .track .thumb .no, .track .thumb .hi, .track .thumb .best, .grid .thumb .no, .grid .thumb .hi, .grid .thumb .best {
    padding: 1px 5px; font-size: 12px; line-height: 15px; letter-spacing: 0; }
  .scores .best:first-child { margin-top: 22px; } /* HI 가 없으면 BEST 를 둘째 줄로 (위의 까닭) */
  .tag, .track .tag { font-size: 12px; }
  .gn { font-size: 12px; }
}
@media (max-width: 340px) { .index a { font-size: 12px; } } /* 아주 좁은 휴대폰의 칩 (11 px 였다): 옆 여백 8 px, 글자 사이 0 은 40-genres.css 그대로 */
/* ---- 60-featured.css ---- */
/* 맨 위의 주요 게임 (2026-11-01, 주인: "포털 가장 위에 주요 게임을 홍보하자. 다음 줄에 2차 주요 게임을 나열 한다. 이것은 백오피스에서 선정 한다." 고른 모양 "큰 배너 넘김").
   portal/src/31-render-featured.ts (마크업), 50-ui-hero.ts (넘김). BY GENRE 와 ALL 의 맨 위: 큰 배너 (.hero) -> "Featured" 카드 줄 (.genre#genre-featured, 줄 모양 그대로).
   배너 한 장 (.slide) = 그 게임의 큰 그림 (hero.webp, 가로세로비 900:620, 남는 자리는 그림의 가장자리 색 --ce) + 그 게임의 카드 색 판 (--cb 바탕, --ci 글자, --ca 의 PLAY):
   카드처럼 테마와 상관없다 (게임의 모습은 하나). 글자 대비는 카드와 같이 굽는 도구가 4.5 이상을 본다 (ink on band, band on accent).
   배치: 휴대폰 세로 (600 px 아래) = 그림 위, 판 아래. 600 px 부터 (가로 휴대폰, 태블릿, PC) = 그림 왼쪽 (높이 --hh), 판 오른쪽.
   점 (.hero-dot) 은 누르는 칸 44 px, 멈춤 단추 44 px. 마우스 화면에서만 양쪽 화살표 (줄의 화살표처럼 자기 칸에: 배너 위에 놓지 않는다). 그라디언트·반짝이 점 바탕은 쓰지 않는다. */
.featured { margin: 6px 0 4px; }
.featured[hidden] { display: none; }
.hero { position: relative; margin: 0 0 8px; }
.hero.single { margin-bottom: 18px; } /* 점 줄이 없다: 아래 Featured 줄과 떨어뜨린다 */
.hero-row { position: relative; }
.hero-view { position: relative; overflow: hidden; border-radius: 22px; box-shadow: 0 8px 24px var(--shadow); touch-action: pan-y; isolation: isolate; }
.hero-track { display: flex; transition: transform .5s cubic-bezier(.22, .8, .3, 1); }
.hero-track.drag { transition: none; }
.hero-view.dragging { cursor: grabbing; }
.hero-view.dragging .slide-link { pointer-events: none; }
.slide { position: relative; flex: 0 0 100%; min-width: 0; display: flex; flex-direction: column; background: var(--cb, var(--panel)); color: var(--ci, var(--text)); }
.slide-art { position: relative; flex: none; display: grid; place-items: center; aspect-ratio: 900 / 620; max-height: 38vh; overflow: hidden; background: var(--ce, hsl(var(--h, 258) 80% 46%)); }
.slide-img { display: block; width: 100%; height: 100%; object-fit: contain; -webkit-user-drag: none; user-select: none; -webkit-user-select: none; }
.slide-icon { display: block; width: auto; height: 58%; filter: drop-shadow(0 4px 6px #1d124a33); -webkit-user-drag: none; }
.slide-text { flex: 1 1 auto; display: flex; flex-direction: column; align-items: flex-start; gap: 6px; min-width: 0; padding: 12px 16px 16px; }
.slide-kick { margin: 0; font-size: 12px; line-height: 16px; font-weight: 800; letter-spacing: 1.5px; text-transform: uppercase; }
.slide-title { margin: 0; font-size: 22px; line-height: 1.15; font-weight: 800; letter-spacing: 1px; overflow-wrap: anywhere; }
.slide-link { color: inherit; text-decoration: none; outline: none; }
.slide-link::after { content: ''; position: absolute; inset: 0; z-index: 1; } /* 배너 어디를 눌러도 그 게임 (카드의 .play 와 같다) */
.slide-link:focus-visible::after { box-shadow: inset 0 0 0 4px var(--ca, var(--accent)); border-radius: 22px; }
.slide-desc { margin: 0; font-size: 14px; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.slide-play { display: inline-flex; align-items: center; gap: 8px; margin-top: auto; min-height: 44px; padding: 0 22px 0 18px; border-radius: 999px;
  background: var(--ca, var(--accent)); color: var(--cb, var(--on-accent)); font-size: 15px; font-weight: 800; letter-spacing: 2px; transition: transform .15s; }
.slide-play svg { width: 18px; height: 18px; }
.slide-text > .slide-desc + .slide-play { margin-top: 6px; }
.slide:hover .slide-play, .slide:has(.slide-link:focus-visible) .slide-play { transform: scale(1.05); }
.slide.noart { background: var(--panel); color: var(--text); }
.slide.noart .slide-play { background: var(--accent); color: var(--on-accent); }

/* 멈춤 단추: 그림의 위 왼쪽 (카드 그림의 차분한 모서리). 지금 상태의 그림 (도는 중 = 멈춤 막대, 멈춤 = 세모) */
.hero-pause { position: absolute; top: 10px; left: 10px; z-index: 3; display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 1.5px solid #fff7fbcc;
  border-radius: 50%; background: #22061ad9; color: #fff7fb; cursor: pointer; touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
.hero-pause svg { width: 20px; height: 20px; }
.hero-pause .hp-play, .hero-pause[data-state="paused"] .hp-pause { display: none; }
.hero-pause[data-state="paused"] .hp-play { display: block; }
.hero-pause:hover { background: #22061a; }
.hero-pause:focus-visible { outline: 3px solid #ffd23f; outline-offset: 2px; }

/* 점 (탭): 보이는 점은 작고 누르는 칸은 44 px. 지금 게임은 긴 알약 */
.hero-dots { display: flex; justify-content: center; margin: 2px 0 0; }
.hero-dot { display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 0; background: transparent; cursor: pointer; touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
.hero-dot::before { content: ''; width: 10px; height: 10px; border-radius: 999px; background: var(--dim); transition: width .25s, background .25s; }
.hero-dot[aria-selected="true"]::before { width: 28px; background: var(--accent); }
:root[data-theme="day"] .hero-dot[aria-selected="true"]::before { background: var(--accent-ink); } /* 밝은 바탕: 해바라기 대신 짙은 금빛 (3 이상) */
.hero-dot:focus-visible { outline: 3px solid var(--accent-ink); outline-offset: -6px; border-radius: 999px; }
.hero-arrow { display: none; }

@media (min-width: 600px) {
  .hero { --hh: clamp(170px, min(32vw, 52vh), 280px); }
  .slide { flex-direction: row; }
  .slide-art { height: var(--hh); max-height: none; }
  .slide-text { justify-content: center; gap: 8px; padding: 16px 22px 16px 24px; }
  .slide-title { font-size: 26px; }
  .slide-desc { max-width: 60ch; }
  .slide-play { margin-top: 6px; }
}
@media (min-width: 900px) {
  .hero { --hh: clamp(240px, min(26vw, 48vh), 400px); }
  .slide-text { gap: 10px; padding: 24px clamp(24px, 3vw, 56px); }
  .slide-kick { font-size: 13px; letter-spacing: 2.5px; }
  .slide-title { font-size: clamp(28px, 2.6vw, 46px); letter-spacing: 2px; }
  .slide-desc { font-size: clamp(15px, 1.1vw, 18px); -webkit-line-clamp: 3; line-clamp: 3; }
  .slide-play { min-height: 48px; padding: 0 28px 0 22px; font-size: 16px; }
  .hero-pause { top: 14px; left: 14px; }
}
/* 마우스 화면: 배너 양쪽의 자기 칸에 화살표 (줄의 .rail-btn 과 같은 꼴) */
@media (hover: hover) and (pointer: fine) {
  .hero:not(.single) .hero-row { display: flex; align-items: stretch; margin: 0 calc(-1 * var(--pad)); }
  .hero:not(.single) .hero-view { flex: 1 1 0; min-width: 0; }
  .hero-arrow { display: flex; align-items: center; justify-content: center; flex: 0 0 var(--pad); padding: 0; border: 0; border-radius: 12px; background: transparent; color: var(--dim); cursor: pointer; }
  .hero-arrow:hover, .hero-arrow:focus-visible { background: var(--accent-soft); color: var(--accent-ink); }
  .hero-arrow svg { width: 26px; height: 26px; }
  .hero-view { cursor: grab; }
}
@media (prefers-reduced-motion: reduce) { .hero-track, .hero-dot::before, .slide-play { transition: none; } .slide:hover .slide-play { transform: none; } }
