/* KEZ_WORKS Infinite Canvas — design tokens & global styles */

/* ===== WEBFONTS ===== */
/* 본문 sans — Paperlogy (한글 전체 포함). 원본→woff2 변환: scripts/build-fonts.py */
@font-face{font-family:'Paperlogy';src:url('fonts/Paperlogy-4Regular.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Paperlogy';src:url('fonts/Paperlogy-5Medium.woff2') format('woff2');font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:'Paperlogy';src:url('fonts/Paperlogy-6SemiBold.woff2') format('woff2');font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:'Paperlogy';src:url('fonts/Paperlogy-7Bold.woff2') format('woff2');font-weight:700;font-style:normal;font-display:swap}
/* 장식 mono — Mona(모나체, SIL OFL 1.1 / Monad ABXY). 픽셀 폰트: upm 1000 = 10px 설계.
   라틴·기호만 서브셋했으므로 한글은 스택 다음의 Paperlogy로 폴백된다. */
@font-face{font-family:'Mona';src:url('fonts/Mona10.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Mona';src:url('fonts/Mona10-Bold.woff2') format('woff2');font-weight:700;font-style:normal;font-display:swap}
/* 루프 밴드 코드 레일 전용 — Departure Mono(SIL OFL). 아래에서만 쓰여 preload는 걸지 않는다 */
@font-face{font-family:'Departure Mono';src:url('fonts/DepartureMono-Regular.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}

:root{
/* ===== PRIMITIVE / color ===== */
--color-white:#FFFFFF;--color-gray-050:#F5F4F9;--color-gray-300:#D9D9D9;--color-gray-500:#A5A5A5;--color-gray-800:#656565;--color-gray-950:#1C1B20;--color-ink-rgb:101,101,101;--color-red-500:#EA5147;
/* ===== PRIMITIVE / font family ===== */
--font-sans:'Paperlogy',-apple-system,BlinkMacSystemFont,sans-serif;
/* Mona는 라틴 전용 서브셋 — 한글 글리프는 Paperlogy가 이어받는다 */
--font-mono:'Mona','Paperlogy',ui-monospace,'SF Mono',Menlo,monospace;
/* ===== SEMANTIC / color role ===== */
--bg-canvas:var(--color-gray-050);--grid-line:var(--color-gray-300);
/* editorial line(연필선 디바이더): 레일 --line(강) / 가로 룰 --line-soft(중) / 컬럼 --line-grid(약) — kezworks-redesign 디바이더 토큰 명칭 준거 (--line-soft는 3단 위계를 위한 이 프로젝트 확장) */
--line:rgba(var(--color-ink-rgb),.5);--line-soft:rgba(var(--color-ink-rgb),.25);--line-grid:rgba(var(--color-ink-rgb),.14);--surface:var(--color-white);--surface-sub:var(--color-gray-050);--surface-hatch:rgba(var(--color-ink-rgb),.09);
/* blueprint 면 토큰 (kezworks-redesign 준거): 카드 면은 흰 종이가 아니라 캔버스와 같은 도면지(--bg #f5f4f9)라
   카드가 "떠 있는 판"이 아니라 "테두리로 구획된 영역"으로 읽힌다. --surface-warm은 이미지 웰 밑에 까는 색. */
--surface-paper:var(--color-gray-050);--surface-warm:#E6E5EA;
/* 어두운 배경 전제로 그려진 이미지(글로우 심볼 등)용 미디어 서피스 — stack.mediaSurface:'dark'에서만 쓴다.
   투명 PNG가 그대로 비치므로 빈칸 해치 대신 단색으로 깐다 (해치면 심볼 위로 줄무늬가 올라온다) */
--surface-media-dark:var(--color-gray-950);--text-primary:var(--color-gray-800);--text-secondary:var(--color-gray-500);--accent:var(--color-red-500);
--ticket-surface:var(--color-white);--ticket-text:var(--color-gray-800);--ticket-text-dim:rgba(var(--color-ink-rgb),.55);--ticket-line:rgba(var(--color-ink-rgb),.18);--ticket-line-strong:rgba(var(--color-ink-rgb),.42);
/* ===== SEMANTIC / elevation ===== */
--elev-rest:0 2px 8px rgba(var(--color-ink-rgb),.10);--elev-hover:0 6px 20px rgba(var(--color-ink-rgb),.16);--elev-focus:0 12px 36px rgba(var(--color-ink-rgb),.22);
/* ===== SEMANTIC / radius ===== */
/* 제도 도면 언어(CardXL/CardS) 전면 적용 — 도면 위 "시트"(카드·파일·티켓·확대창·썸네일)는 전부 직각.
   레퍼런스(kezworks-redesign)도 디자인 표면은 전부 각지고 라운딩은 스크롤바·스켈레톤 같은 유틸에만 남는다.
   칩·버튼·내비게이터(HUD 유틸)만 소반경 유지 (2026-08-04 하린 지시: 야금야금 말고 토큰 차원에서 일괄). */
--radius-chip:4px;--radius-ticket:var(--radius-card);--radius-btn:6px;--radius-panel:8px;--radius-card:0;--radius-pile:0;--radius-hair:1px;--radius-nav:2px;--radius-round:50%;
/* ===== SEMANTIC / blueprint chrome (제도 도면 카드 크롬 — Card.jsx·CatalogPanel.jsx 공용) ===== */
/* 오프셋 시트 밀림 / 시트 면색(솔리드 면 쉐도우 — 하린 지시로 라인이 아니라 면) / 코너 정합 마크 한 변·돌출량 / mono 주석 바 높이 */
--bp-sheet:4px;--bp-sheet-fill:rgba(var(--color-ink-rgb),.22);--bp-mark:14px;--bp-mark-out:-7px;--bp-bar-h:18px;
/* ===== SEMANTIC / pattern ===== */
--pattern-barcode:repeating-linear-gradient(90deg,var(--ticket-text) 0 2px,transparent 2px 4px,var(--ticket-text) 4px 7px,transparent 7px 9px,var(--ticket-text) 9px 10px,transparent 10px 14px);
--pattern-hatch:repeating-linear-gradient(45deg,var(--surface-sub) 0 12px,var(--surface-hatch) 12px 24px);
/* 연필선 grain 알파 마스크 — mask-size 120px 120px로 사용. kezworks-redesign globals.css 이식. 비활성화: --line-grain: none */
--line-grain:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='2' seed='8' stitchTiles='stitch'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='gamma' amplitude='1' exponent='1.4' offset='0'/%3E%3C/feComponentTransfer%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.85 0.07'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23g)'/%3E%3C/svg%3E");
/* ===== SEMANTIC / type role (weight size/line-height family) ===== */
/* 아래 두 토큰만 size가 자리 표시자다 — 나머지는 적힌 값이 그대로 그려진다.
   히어로와 존 타이틀은 크기를 뷰포트·서체 메트릭에서 런타임에 역산하기 때문이고(measureHeroEm·measureZT),
   그래서 weight·line-height·family를 여기서 바꾸면 실측 프로브와 렌더가 함께 따라온다.
   프로브가 이 토큰을 읽지 않고 서체 이름을 따로 알면 서체 교체 시 격자 정합이 무너진다 — 갈라놓지 말 것. */
--type-hero:700 96px/.94 var(--font-sans);        /* size는 자리 표시 — computeD0가 뷰포트 폭에서 산출 */
--type-zone-title:600 48px/1 var(--font-sans);    /* size는 자리 표시 — measureZT가 캡하이트=격자 2칸(48px)이 되는 px를 역산 */
--type-zone-desc:400 12px/24px var(--font-sans); /* 설명 1행 = 격자 1칸 */
--type-stack-title:500 14px/1.3 var(--font-sans);
--type-stack-meta:400 12px/1.4 var(--font-sans);
--type-stack-period:400 11px/1.4 var(--font-mono);
--type-card-title:500 14px/1.3 var(--font-sans);
--type-card-heading:600 14px/1.3 var(--font-sans);
--type-card-meta:400 12px/1.4 var(--font-sans);
--type-card-body:400 13px/1.6 var(--font-sans);
--type-card-title-code:500 14px/1.3 var(--font-mono);
--type-chip:400 10px/1.2 var(--font-mono);
--type-code:400 11px/1.4 var(--font-mono);
--type-lb-arrow:400 16px/1.4 var(--font-mono); /* 확대창 좌우 색인 글리프 — --type-code보다 한 단계 큰 유일한 자리 */
--type-crumb:400 13px/1.2 var(--font-sans);
--type-viewer-title:600 17px/1.3 var(--font-sans);
--type-chrome-link:400 12px/1.4 var(--font-sans);
--type-nav-meta:400 10px/1.2 var(--font-mono);
--type-crumb-sep:400 11px/1.2 var(--font-sans);
--type-cv-org:600 19px/1.24 var(--font-sans);
--type-ticket-val:500 13px/1.5 var(--font-mono);
--type-ticket-val-lg:500 14px/1.6 var(--font-mono);
--type-ticket-val-sm:500 12px/1.6 var(--font-mono);
--type-ticket-slogan:700 48px/1.04 var(--font-sans);
--type-ticket-slogan-sm:700 32px/1.06 var(--font-sans);
--type-ticket-seat:700 30px/1.15 var(--font-mono);
--type-ticket-seat-sm:700 26px/1.15 var(--font-mono);
--type-ticket-brand:700 20px/1 var(--font-sans);
--type-ticket-brand-sm:700 18px/1 var(--font-sans);
--type-ticket-arrow:700 16px/1 var(--font-sans);
--type-tear-label:400 20px/1.2 var(--font-mono);
--type-tear-label-sm:400 18px/1.2 var(--font-mono);
/* 직접 타이핑하는 칸은 본문 서체로 — 한 필드 안에서 영문(픽셀)·한글(본문)이 섞이지 않게 한다 */
--type-field-input:400 14px/1.5 var(--font-sans);
--type-field-body:400 14px/1.7 var(--font-sans);
--type-field-note:400 13px/1.5 var(--font-mono); /* 표시 전용(입력 아님) — 픽셀 유지 */
--type-btn:600 13px/1 var(--font-sans);
/* ===== SEMANTIC / tracking ===== */
/* mono 대문자 라벨만 벌리고, 디스플레이 조판은 커질수록 좁힌다. font 축약형이 letter-spacing을
   담지 못해 --type-* 와 짝을 이루는 별도 토큰으로 둔다 (짝: cv-org·zone-title·hero). */
--tracking-wide:.08em;--tracking-brand:.04em;--tracking-cv-org:-.012em;--tracking-zone-title:-.02em;--tracking-hero:-.035em;
/* ===== SEMANTIC / motion ===== */
--spring-dur:.9s;--spring-ease:linear(0,.13 5.6%,.35 11.1%,.56 16.7%,.71 22.2%,.82 27.8%,.89 33.3%,.94 38.9%,.962 44.4%,.978 50%,.988 55.6%,.996 66.7%,.999 77.8%,1);
--easing:cubic-bezier(0.6,0,0.6,1); /* 디바이더 드로우 이징 — kezworks-redesign 준거 */
}
html,body{margin:0;padding:0;height:100%;overflow:hidden;background:var(--bg-canvas);overscroll-behavior:none}
/* touch-action은 상속되지 않음 — 터치가 카드/패널 위에서 시작되면 브라우저가 pointercancel로 팬을 끊어버리므로 캔버스 내 전 요소에 지정 (폼 입력만 예외) */
div[data-screen-label="Infinite Canvas"],div[data-screen-label="Infinite Canvas"] *{touch-action:none}
div[data-screen-label="Infinite Canvas"] input,div[data-screen-label="Infinite Canvas"] textarea{touch-action:auto}
a{color:var(--text-primary)}a:hover{color:var(--text-primary)}
@keyframes ants{to{stroke-dashoffset:-70}}
@keyframes backline{0%,100%{transform:scaleX(1)}50%{transform:scaleX(.5)}}
@keyframes backhead{0%,100%{transform:translateX(0)}50%{transform:translateX(7px)}}
@keyframes fadein{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
@keyframes boxpopA{0%{transform:scale(.8);opacity:0}27%{opacity:0}65%{transform:scale(1.1);opacity:1}100%{transform:scale(1);opacity:1}}
@keyframes formdrop{0%{transform:translateY(-420px) scale(.7);opacity:0}20%{opacity:0}100%{transform:translateY(0) scale(1);opacity:1}}
@keyframes boxpopB{0%{transform:scale(.8);opacity:0}27%{opacity:0}65%{transform:scale(1.1);opacity:1}100%{transform:scale(1);opacity:1}}
@keyframes flyx{0%{left:2%;opacity:0}12%{opacity:1}82%{opacity:1}100%{left:98%;opacity:0}}
@keyframes blink{0%,48%{opacity:1}49%,100%{opacity:0}}
/* style-hover 대응 — dc-runtime importantify()와 동일 계약: 인라인 스타일(색·투명도)을 :hover 클래스가 이겨야 함 */
/* harness-allow(H4): dc-runtime의 style-hover는 !important로 인라인을 이기는 계약 — 프로토타입 동작 1:1 재현 목적 */
.hov-text:hover{color:var(--text-primary) !important}
/* harness-allow(H4): dc-runtime의 style-hover는 !important로 인라인을 이기는 계약 — 프로토타입 동작 1:1 재현 목적 */
.hov-dim:hover{opacity:.86 !important}
/* 메일 폼의 빈칸 채우기 글자 — 입력한 글자(--text-primary)보다 확실히 옅게. 브라우저 기본 투명도는 끈다 */
.fld::placeholder{color:var(--text-secondary);opacity:1}
/* 화면 밖 구역의 무한 반복 애니(행진개미·비행기·타이핑 커서)를 멈춘다 — IntersectionObserver가 토글.
   animation-play-state는 상속되지 않으므로 자손 전체를 후손 선택자로 잡는다. */
/* harness-allow(H4): 각 애니의 play-state 선언을 일일이 이겨야 하는 전역 킬스위치 — 우선순위 조정으로는 대체 불가 */
.anim-off *{animation-play-state:paused !important}
/* 내부 스크롤은 평소 숨겨 도면의 선을 방해하지 않는다. 포인터 근접·휠·스크롤 때만
   React 리렌더 없이 kz-scrollbar-show가 붙고, 기존 선·면 토큰으로만 thumb을 그린다. */
.kz-scrollbar{scrollbar-width:none;scrollbar-color:transparent transparent}
.kz-scrollbar::-webkit-scrollbar{width:0;height:0}
.kz-scrollbar.kz-scrollbar-show{scrollbar-width:thin;scrollbar-color:var(--line-soft) transparent}
.kz-scrollbar.kz-scrollbar-show::-webkit-scrollbar{width:8px;height:8px}
.kz-scrollbar.kz-scrollbar-show::-webkit-scrollbar-track{background:transparent}
.kz-scrollbar.kz-scrollbar-show::-webkit-scrollbar-thumb{background:var(--line-soft);border:2px solid transparent;background-clip:padding-box;border-radius:var(--radius-hair)}
/* 카드 제도 도면 크롬 — 프레임 테두리·상단 주석 바. 호버하면 테두리·주석·제목이 accent로 전환된다.
   색은 인라인이 아니라 이 클래스에만 둔다 (인라인이면 :hover가 못 이겨 !important가 필요해진다). */
/* 면 쉐도우는 별도 div가 아니라 카드 컴포지션 그룹(프레임) 자체의 box-shadow — 솔리드 오프셋 슬래브.
   내부 요소에 라인 사각형을 따로 그려 넣던 조립(2026-08-04 이전)은 그림자가 겉돌아 폐기. */
.kz-card-frame{border:1px solid var(--text-primary);box-shadow:var(--bp-sheet) var(--bp-sheet) 0 var(--bp-sheet-fill);transition:border-color 160ms ease-out}
.kz-card-frame:hover{border-color:var(--accent)}
.kz-card-bar{border-bottom:1px solid var(--line-soft);color:var(--text-secondary);transition:color 160ms ease-out,border-color 160ms ease-out}
.kz-card-frame:hover .kz-card-bar{color:var(--accent);border-bottom-color:var(--accent)}
.kz-card-frame:hover .kz-card-title{color:var(--accent)}
/* 태그 칩 — 레퍼런스 Tag(S) 그대로: 각진 1px 잉크 테두리, 본문 서체. 카드 호버 시 테두리·글자가 같이 accent로 */
.kz-tag{display:inline-flex;align-items:center;border:1px solid var(--text-primary);color:var(--text-primary);padding:1px 5px;font:var(--type-card-meta);white-space:nowrap;transition:border-color 160ms ease-out,color 160ms ease-out}
.kz-card-frame:hover .kz-tag{border-color:var(--accent);color:var(--accent)}
/* 타이핑 캔버스(루프 이음매 밴드 장식) — kezworks-redesign LandingTypingCanvas.module.css 이식.
   CSS Modules가 없으므로 클래스명만 바꾸고 셀렉터 구조는 그대로. 다만 컨테이너가 flex 자식이 아니라
   절대배치 박스 안에 들어가므로 flex:1 대신 height:100%로 부모 박스를 채운다. */
.kz-typing-container{position:relative;width:100%;height:100%;overflow:hidden}
.kz-typing-canvas{display:block;width:100%;height:100%;-webkit-mask-image:linear-gradient(to bottom,transparent 0%,black 8%,black 92%,transparent 100%);mask-image:linear-gradient(to bottom,transparent 0%,black 8%,black 92%,transparent 100%)}
/* 세로쓰기: 글자는 똑바로 선 채 아래로 흐르고 컬럼이 오른쪽으로 늘어난다(회전 없음).
   컬럼이 쌓이는 축이 가로이므로 페이드도 좌우로 건다. */
.kz-typing-container[data-orientation='vertical'] .kz-typing-canvas{-webkit-mask-image:linear-gradient(to right,transparent 0%,black 8%,black 92%,transparent 100%);mask-image:linear-gradient(to right,transparent 0%,black 8%,black 92%,transparent 100%)}
