/* =========================================================
   medium.hot — structure faithfully rebuilt from press-room.kr
   (visual design is intentionally neutral; to be redesigned)
   Vanilla. No jQuery / skrollr / AOS.
   ========================================================= */

@import url('https://fonts.googleapis.com/css2?family=Gothic+A1:wght@300;400;500;700&display=swap');

:root {
  --bg: #000000;
  --fg: #f3efe6;
  --muted: #8c887f;
  --pad: 20px;
  --heroTop: clamp(46px, calc(8vh - 10px), 74px);   /* hero top (−10px); character rises into this margin */
  --maxw: 1080px;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --z-header: 50;
  --z-cloud: 10;   /* below .mainWrap (35) so grid covers clouds on scroll */
  --z-text: 9;
  --z-stage: 8;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  background: var(--bg);
  color: var(--fg);
  font-family: 'Gothic A1', system-ui, sans-serif;
  font-weight: 400;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  transition: background .5s ease;
}
a { color: inherit; text-decoration: none; display: inline-block; }
img { vertical-align: bottom; max-width: 100%; }
ul { list-style: none; }
::selection { background: var(--fg); color: var(--bg); }
:focus-visible { outline: 2px solid var(--fg); outline-offset: 3px; }

/* language toggle: EN visible by default, KO when body.lang-ko */
body:not(.lang-ko) .ko { display: none; }
body.lang-ko .en { display: none; }

/* =========================================================
   HEADER
   ========================================================= */
.mainHeader {
  position: fixed; top: 0; left: 0; width: 100%;
  padding: 14px var(--pad);
  display: flex; align-items: center; justify-content: space-between;
  z-index: var(--z-header);
  color: #fff;                       /* colour logo can't use difference blend */
}
.mainHeader a { color: #fff; }
.mainHeader .menuWeb a, .mainHeader .lang { text-shadow: 0 1px 8px rgba(0,0,0,.45); }
/* 히어로(.heroBrand)와 동일한 스케일 — 상세페이지에서 캐릭터 크기가 달라지지 않도록
   px 고정 대신 같은 clamp를 쓰고 스프라이트를 em으로 잡는다(모바일까지 자동 일치). */
/* 위치도 .heroBrand와 동일한 수식 — 상세 헤더엔 .brand 하나뿐이라 fixed로 빼도
   레이아웃에 영향이 없다. 0.62em은 아래 font-size(= 히어로와 같은 clamp) 기준. */
.brand { display: flex; align-items: center; line-height: 0;
  font-size: clamp(40px, 2.2vw + 37px, 71px);
  position: fixed; z-index: var(--z-header);
  left: calc(var(--pad) + 10px); top: calc(var(--heroTop) - 0.62em + 12px); }
/* real 3D turntable from a sprite sheet (24 frames of the head rotated around Y).
   em-sized: frame 1.725em -> sheet 24*1.725=41.4em, hover 25*1.725=43.125em. */
.brandLogo {
  width: 1.725em; height: 1.725em; display: block;
  background-image: url(../img/logo_sprite.png);
  background-repeat: no-repeat;
  background-size: 41.4em 1.725em;
  background-position: 0 0;
  animation: logoTurn 3s infinite;              /* idle: hold, then full turn */
  transform-origin: 50% 55%;
  transition: transform 0.18s ease;
}
@keyframes logoTurn {
  0%   { background-position: 0 0; animation-timing-function: steps(1, end); }
  76%  { background-position: 0 0; animation-timing-function: steps(24, end); }
  100% { background-position: -41.4em 0; }
}
/* hover: no spin — just swap to the tongue-out expression (hover sheet frame 24)
   and cock the head slightly, like the reference. */
.brand:hover .brandLogo {
  background-image: url(../img/logo_hover_sprite.png);
  background-size: 43.125em 1.725em;            /* 25 frames * 1.725em */
  background-position: -41.4em 0;               /* frame 24 = tongue-out front */
  animation: none;                              /* stop the idle turntable */
  transform: rotate(-9deg);                     /* cocked / crooked */
}
@media (prefers-reduced-motion: reduce) { .brandLogo { animation: none; } }
.menuWeb { display: flex; gap: 26px; align-items: center; }
.menuWeb a { font-size: 16px; position: relative; }
.menuWeb a::after {
  content: ''; position: absolute; left: 0; bottom: -2px; width: 100%; height: 1px;
  background: currentColor; transform: scaleX(0); transform-origin: left;
  transition: transform .4s var(--ease);
}
.menuWeb a:hover::after, .menuWeb a[aria-current="page"]::after { transform: scaleX(1); }
.lang { cursor: pointer; font-size: 16px; letter-spacing: .05em; }

/* mobile menu */
.menuBtn { display: none; width: 26px; height: 16px; position: relative; cursor: pointer; }
.menuBtn span { position: absolute; left: 0; width: 100%; height: 1.5px; background: currentColor; transition: .3s var(--ease); }
.menuBtn span:nth-child(1) { top: 0; }
.menuBtn span:nth-child(2) { top: 50%; transform: translateY(-50%); }
.menuBtn span:nth-child(3) { bottom: 0; }
.menuBtn.open span:nth-child(1) { top: 50%; transform: translateY(-50%) rotate(45deg); }
.menuBtn.open span:nth-child(2) { opacity: 0; }
.menuBtn.open span:nth-child(3) { bottom: 50%; transform: translateY(50%) rotate(-45deg); }

.menuM {
  position: fixed; inset: 0; background: var(--bg); color: var(--fg);
  z-index: 49; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 8px;
  transform: translateY(-100%); transition: transform .5s var(--ease); visibility: hidden;
}
.menuM.open { transform: none; visibility: visible; }
.menuM a { font-size: 34px; font-weight: 500; padding: 8px; }

/* =========================================================
   PARALLAX HERO
   ========================================================= */
.parallax { position: relative; height: 100vh; min-height: 560px; overflow: hidden; }

/* jun.works-style editorial intro: running paragraph as the hero */
.heroText {
  position: fixed; top: 0; left: 0; width: 100%;
  padding: var(--heroTop) var(--pad) 0 calc(var(--pad) + 20px); z-index: var(--z-text);
  pointer-events: none;                 /* only links/clients are interactive */
  transition: filter .5s ease;          /* opacity/transform are scroll-linked (smooth) */
  will-change: transform, opacity;
}
.heroText a, .heroText .cn { pointer-events: auto; }
.heroText.blur { filter: blur(6px); }

/* 3D character = FIXED (persistent header identity on scroll), positioned at the
   bio's first line. The bio's first line is text-indented so it flows to the
   character's right; the rest of the paragraph wraps full-width. em-sized (font
   matches the bio) so it scales together. */
.heroBrand {
  position: fixed; left: calc(var(--pad) + 10px); top: calc(var(--heroTop) - 0.62em + 12px);
  z-index: var(--z-header); pointer-events: auto; line-height: 0;
  font-size: clamp(40px, 2.2vw + 37px, 71px);   /* same scale as .bio */
}
.bioLogo {
  display: block; width: 1.725em; height: 1.725em;
  background-image: url(../img/logo_sprite.png);
  background-repeat: no-repeat;
  background-size: 41.4em 1.725em;           /* 24 frames * 1.725em */
  background-position: 0 0;
  animation: bioTurn 3s infinite;            /* idle: hold, then one full turn */
  transform-origin: 50% 55%;
  transition: transform 0.18s ease;
}
@keyframes bioTurn {
  0%   { background-position: 0 0; animation-timing-function: steps(1, end); }
  76%  { background-position: 0 0; animation-timing-function: steps(24, end); }
  100% { background-position: -41.4em 0; }
}
.heroBrand:hover .bioLogo {              /* hover: tongue-out + cocked, no spin */
  background-image: url(../img/logo_hover_sprite.png);
  background-size: 43.125em 1.725em;         /* 25 frames * 1.725em */
  background-position: -41.4em 0;            /* frame 24 = tongue-out */
  animation: none;
  transform: rotate(-9deg);
}
@media (prefers-reduced-motion: reduce) { .bioLogo { animation: none; } }

.bio {
  max-width: calc(50% + 10em + 5px); text-align: left;
  text-indent: 1.55em;                   /* first line only — flows past the character */
  /* gentle slope: stays ~large as the window narrows (wraps to more lines
     instead of shrinking), so no big empty space at ~half width */
  font-weight: 500; font-size: clamp(36px, 1.98vw + 33.3px, 63.9px); line-height: 1.18;
  letter-spacing: -0.02em; text-wrap: pretty;
  transform: scaleX(1.05); transform-origin: left top;   /* 장평 +5% (font is not variable) */
}
.bio .tm { white-space: nowrap; }
.bio sup { font-size: .55em; vertical-align: super; line-height: 0; }
.bio a { display: inline; text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
.bio a:hover { background: var(--fg); color: var(--bg); text-decoration: none; }
.bio .now { color: var(--muted); }
.bio .more { color: var(--muted); }

/* hover-reveal client thumbnails (jun.works signature) */
.cn { position: relative; text-decoration: underline; text-underline-offset: 3px; text-decoration-style: dotted; cursor: help; }
.cn .cnimg {
  position: absolute; left: 0; bottom: 128%; top: auto; transform: scale(.94); transform-origin: left bottom;
  width: 168px; aspect-ratio: 4/5; opacity: 0; pointer-events: none; z-index: 30;
  transition: opacity .25s var(--ease), transform .25s var(--ease);
  box-shadow: 0 18px 40px rgba(20,17,15,.45); border-radius: 2px; overflow: hidden;
}
.cn .cnimg img { display: block; width: 100%; height: 100%; object-fit: cover; }  /* block: ignore the .bio text-indent inherited into the tooltip, which shoved the image ~1.55em right */
.cn:hover .cnimg { opacity: 1; transform: scale(1); }

/* email link: hover reveals the address + a "click to copy" hint (same reveal motif as
   the client thumbnails). Font + 장평 match the hero: inherits Gothic A1 and the
   .bio scaleX(1.05) is left to apply, so the tooltip carries the same +5% 장평. */
.bio a.mail { position: relative; }
.mail .copytip {
  position: absolute; left: 0; bottom: 150%;
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: max-content;
  text-indent: 0;                        /* cancel the .bio first-line indent inherited into the tooltip */
  background: var(--fg); color: var(--bg); text-decoration: none;
  padding: 7px 11px; border-radius: 4px; white-space: nowrap;
  font-size: 19px; letter-spacing: .01em; line-height: 1.2;
  box-shadow: 0 14px 34px rgba(20,17,15,.45);
  opacity: 0; transform: translateY(6px) scale(.98);
  transform-origin: left bottom; pointer-events: none; z-index: 30;
  transition: opacity .22s var(--ease), transform .22s var(--ease);
}
.mail .copytip em {
  font-style: normal; font-size: 12px; letter-spacing: .01em; color: var(--muted);
}
.mail:hover .copytip { opacity: 1; transform: translateY(0) scale(1); }

/* press-room "tree" interaction, rebuilt with fire.
   Row of flames at the bottom; JS drives parallax `top` + grow-on-scroll. */
.fireRow {
  position: absolute; bottom: 10px; left: 50%; transform: translateX(-50%);
  width: 100%; padding: 0 var(--pad); z-index: 20;   /* in front of hero text (9) */
  display: flex; justify-content: space-around; align-items: flex-end;
  pointer-events: none;
}
.flame {
  position: relative;                 /* JS sets `top` for parallax rise */
  line-height: 1; font-size: 92px;
  transform-origin: 50% 100%;         /* breathe from the base (stays grounded) */
  transition: top .8s ease, font-size .8s ease;   /* glide top/size; leave transform to the animation */
  will-change: top, font-size, transform;
  user-select: none;
  animation: breathe 7s ease-in-out infinite;   /* big grow / shrink */
}
/* different periods + scattered phases -> the "biggest" jumps around (not a
   left-to-right wave); the mismatched periods keep it from ever repeating. */
.fireRow .flame:nth-child(1) { animation-duration: 6.5s; animation-delay: -1.0s; }
.fireRow .flame:nth-child(2) { animation-duration: 8.2s; animation-delay: -4.3s; }
.fireRow .flame:nth-child(3) { animation-duration: 5.8s; animation-delay: -2.6s; }
.fireRow .flame:nth-child(4) { animation-duration: 7.4s; animation-delay: -0.4s; }
.fireRow .flame:nth-child(5) { animation-duration: 6.9s; animation-delay: -3.7s; }
@keyframes breathe {
  0%, 100% { transform: scale(0.72); }
  50%      { transform: scale(1.15); }
}
@media (prefers-reduced-motion: reduce) { .flame { animation: none; } }
/* three stacked layers (red base + orange + yellow overlay), pixel-aligned
   because all three PNGs are rendered in the same frame. Each sizes with
   font-size so the JS scale/rise still drives the whole flame. */
.flame img { display: block; width: 1.1em; height: auto; transform-origin: 50% 100%; }
.flame .fl-red { position: relative; }              /* base defines the box */
.flame .fl-org, .flame .fl-yel { position: absolute; left: 0; top: 0; }
/* soft purple glow + grounding shadow */
.flame { filter: drop-shadow(0 5px 12px rgba(0,0,0,.35)) drop-shadow(0 0 17px rgba(155,70,225,.50)); }

/* independent burn per layer: red licks least/slowest, yellow most/fastest,
   so the three colours never move together. */
.flame .fl-red { animation: burnRed 2.3s ease-in-out infinite; }
.flame .fl-org { animation: burnOrg 1.7s ease-in-out infinite; }
.flame .fl-yel { animation: burnYel 1.25s ease-in-out infinite; }
/* per-flame phase offsets so the five flames burn out of sync */
.fireRow .flame:nth-child(1) img { animation-delay: -0.20s; }
.fireRow .flame:nth-child(2) img { animation-delay: -0.90s; }
.fireRow .flame:nth-child(3) img { animation-delay: -1.40s; }
.fireRow .flame:nth-child(4) img { animation-delay: -0.55s; }
.fireRow .flame:nth-child(5) img { animation-delay: -1.75s; }

@keyframes burnRed {
  0%,100% { transform: scaleY(1)    scaleX(1)    skewX(0deg); }
  25%     { transform: scaleY(1.05) scaleX(0.98) skewX(1.1deg); }
  55%     { transform: scaleY(0.98) scaleX(1.015) skewX(-0.8deg); }
  80%     { transform: scaleY(1.03) scaleX(0.99) skewX(0.6deg); }
}
@keyframes burnOrg {
  0%,100% { transform: scaleY(1)    scaleX(1)    skewX(0deg);    filter: brightness(1); }
  20%     { transform: scaleY(1.10) scaleX(0.955) skewX(-2.4deg);filter: brightness(1.08); }
  48%     { transform: scaleY(0.955) scaleX(1.03) skewX(1.5deg); filter: brightness(0.95); }
  72%     { transform: scaleY(1.07) scaleX(0.975) skewX(-1.7deg);filter: brightness(1.05); }
}
@keyframes burnYel {
  0%,100% { transform: scaleY(1)    scaleX(1)    skewX(0deg);    filter: brightness(1); }
  16%     { transform: scaleY(1.16) scaleX(0.925) skewX(3.4deg); filter: brightness(1.18); }
  40%     { transform: scaleY(0.925) scaleX(1.055) skewX(-2.2deg);filter: brightness(0.9); }
  64%     { transform: scaleY(1.11) scaleX(0.95) skewX(2.8deg);  filter: brightness(1.12); }
  85%     { transform: scaleY(0.97) scaleX(1.02) skewX(-1.3deg); filter: brightness(0.96); }
}
@media (prefers-reduced-motion: reduce) { .flame img { animation: none; } }

/* gooey purple liquid — metaball droplets rising near the flame bases.
   The #goo filter (blur + alpha threshold) makes overlapping drops merge. */
.liquid {
  position: absolute; top: 0; bottom: 0; left: 0; width: 100%;  /* full hero height */
  z-index: 18;                    /* behind flames (20), above hero text (9) */
  pointer-events: none; overflow: hidden;
  /* #goo merges overlapping blobs; the trailing drop-shadow adds a soft glow */
  filter: url(#goo) drop-shadow(0 0 10px rgba(168,56,235,.55));
}
.goo-defs { position: absolute; }
/* small blobs: born clumped inside the flame (translateX 0 -> overlapping =
   one gooey mass), then fan out to their own --dx path as they rise, so they
   split off into individual droplets. Each has its own speed (duration). */
.liquid .drop {
  position: absolute; bottom: 42px;
  /* --ls (set by JS) shrinks the droplets with the flames on narrow screens; defaults to 1 on desktop */
  width: calc(var(--s) * var(--ls, 1)); height: calc(var(--s) * var(--ls, 1));
  margin-left: calc(var(--s) * var(--ls, 1) / -2);   /* centre on its left% so they overlap at birth */
  border-radius: 50%;
  /* default: flame's mid purple (#a838eb) */
  background: radial-gradient(circle at 36% 30%, #d49bf6 0%, #a838eb 42%, #8022cf 74%, #5c168f 100%);
  animation-name: rise; animation-timing-function: linear;
  animation-iteration-count: infinite;
}
/* brighter lavender variant — mixed in randomly */
.liquid .drop.bright {
  background: radial-gradient(circle at 36% 30%, #f4e2ff 0%, #d29bf4 30%, #9c47df 64%, #5c18a6 100%);
}
/* brightest = inner flame colour (pale lavender) */
.liquid .drop.light {
  background: radial-gradient(circle at 36% 30%, #fdf6ff 0%, #ecccff 34%, #c98cf0 68%, #9a58d6 100%);
}
/* born clumped in the flame and stay stuck together (viscous) until just above
   it, then quickly fan out to --dx so they're FULLY separated below mid-screen;
   afterwards each droplet rises straight up. Solid/crisp (no opacity fade). */
@keyframes rise {
  0%   { transform: translate(0, 6px) scale(0.84); }
  6%   { transform: translate(0, -4vh) scale(1); }             /* thick clump emerges */
  13%  { transform: translate(0, -11vh) scale(1); }            /* brief viscous stick */
  25%  { transform: translate(var(--dx,0), -25vh) scale(0.96); }  /* fanned out fast (low on screen) */
  100% { transform: translate(var(--dx,0), -104vh) scale(0.9); }  /* individual rise, off the top */
}
@media (prefers-reduced-motion: reduce) { .liquid { display: none; } }

/* pixel down-arrows in the gaps between the flames; hard 1s blink (no fade) */
.arrowRow {
  position: absolute; bottom: 20px; left: 0; width: 100%;
  padding: 0 calc(var(--pad) + 22px);      /* +2px inset vs bio edge: end arrows always hit the margin, so they read tighter than the ragged-right text */
  z-index: 15;                             /* behind flames (20), in front of text (9) */
  display: flex; justify-content: space-between; align-items: center;
  pointer-events: none;
}
.pixArrow {
  width: 63px; height: 38px;               /* 1.5x; SVG aspect 454.7:272.8 ≈ 1.667:1 */
  background: url(../img/pixarrow.svg) center / contain no-repeat;
  image-rendering: pixelated;
  animation: blink 1s steps(1) infinite;   /* on 0.5s / off 0.5s, hard cut */
}
@keyframes blink { 0% { opacity: 1; } 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .pixArrow { animation: none; } }

/* =========================================================
   WORK GRID  (.col = press-room .col-55)
   ========================================================= */
.mainWrap { position: relative; z-index: 35; background: var(--bg); padding: 0 10px; }
.imgWrap {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  padding-top: 50px;
}
.col {
  width: 25%; padding: 10px; float: none;   /* web: 4 columns */
}
.col a { display: block; overflow: hidden; aspect-ratio: 4 / 5; background: #000000; }
.col a img, .col a video { width: 100%; height: 100%; object-fit: cover; }
.col .title { font-size: 15px; line-height: 1.2; padding-top: 10px; padding-bottom: 26px; color: var(--fg); font-weight: 700; transform: scaleX(1.05); transform-origin: left; }
/* 카드 카테고리만 --muted(#8c887f)보다 10% 밝게 — 썸네일 아래라 잘 안 보였음.
   --muted 자체는 크레딧·캡션·푸터에서도 쓰여 전역 변경 대신 여기만 올린다. */
.col .title .cat { color: #9a968c; font-weight: 400; }


/* scroll reveal (AOS replacement) */
.reveal { opacity: 0; transform: translateY(22px); }
.reveal.in { opacity: 1; transform: none; transition: opacity .8s var(--ease), transform .8s var(--ease); }

/* =========================================================
   DETAIL PAGE
   ========================================================= */
.content { padding-top: 0; }
.detailWrap { max-width: var(--maxw); margin: 0 auto; padding: 0 var(--pad); }
.detailHead { padding: clamp(120px, 20vh, 220px) 0 clamp(6px, 1vw, 12px); text-align: left; }
.detailHead h1 { font-weight: 400; font-size: clamp(28px, 4.82vw, 67px); line-height: .92; letter-spacing: -0.02em; transform: scaleX(1.05); transform-origin: left; }  /* −15%, −10%, −10%; 장평 +5% — match hero (left-aligned, origin left) */
.detailHead .sub { color: var(--muted); font-size: 16px; margin-top: 16px; letter-spacing: -0.02em; transform: scaleX(1.05); transform-origin: left; }

/* pre-composed layout images (designed on the site's black bg) run full-width, stacked with
   no gap — vertical spacing is built into each canvas, so images flow seamlessly. */
.work-stack { display: flex; flex-direction: column; gap: 0; }
.work-stack img, .work-stack video { width: 100%; height: auto; display: block; }

/* horizontal row group (info.txt `rows:`) — assets sit side by side, equal widths.
   default fills the column; info.txt `rowbleed: N` widens it N% past the column (inline style).
   stacks vertically on mobile. */
.work-row { display: flex; gap: 16px; align-items: flex-start; }
.work-row > img, .work-row > video { flex: 1 1 0; min-width: 0; width: 100%; }
/* light-on-black clips: drop the black bg so overlapping/aligned items coexist cleanly */
.work-row.blend-screen > img, .work-row.blend-screen > video { mix-blend-mode: screen; }
@media (max-width: 760px) {
  .work-row { flex-direction: column; width: 100% !important; margin-inline: 0 !important; gap: 10px; }
  .work-row > * { transform: none !important; }
}

/* video projects (e.g. Visla reels): lay the clips side by side, height-capped,
   so vertical 9:16 videos are viewable at a glance instead of a tall scroll.
   flex-wrap => 2-up on desktop, stacks to 1-up on narrow screens. */
/* captioned video clips — shared by Visla 2-up (.vids) and Bonnae full-width stack.
   base: full-width clip (video + caption below); caption text style matches the site. */
.work-stack .clip { display: flex; flex-direction: column; gap: 14px; }
.work-stack .clip video { width: 100%; height: auto; display: block; }
.work-stack:not(.vids) > .clip + .clip { margin-top: clamp(40px, 6vw, 72px); }  /* space between stacked clips */
/* info.txt에 gap을 적었으면 그 값만 쓴다 — 위 기본 여백이 더해져 두 배가 되는 걸 막음 */
.work-stack.gapped > .clip + .clip { margin-top: 0; }
.work-stack figcaption { max-width: 46ch; }
.work-stack .ct { display: block; font-size: 15px; font-weight: 700; color: var(--fg); letter-spacing: -0.02em; transform: scaleX(1.05); transform-origin: left; }  /* match site 장평 */
.work-stack .cdate { font-weight: 400; font-size: 13px; color: var(--muted); letter-spacing: -0.02em; }  /* 업로드 날짜 — 제목 옆 */
.work-stack .cd { display: block; margin-top: 5px; font-size: 14px; line-height: 1.6; color: var(--muted); letter-spacing: -0.02em; transform: scaleX(1.05); transform-origin: left; }
.work-stack .clink { display: inline-block; margin-top: 9px; font-size: 13px; font-weight: 500; color: var(--fg); border-bottom: 1px solid var(--muted); padding-bottom: 1px; transition: opacity .2s; }
.work-stack .clink:hover { opacity: 0.6; }

/* `pair`: width-based 2-up on PC (each clip half-width, natural aspect), stacks on mobile.
   for mixed/horizontal clips where a full-width vertical video would be too tall (Bonnae). */
.work-stack.pair { flex-direction: row; flex-wrap: wrap; column-gap: 40px; row-gap: 48px; align-items: flex-start; }
.work-stack.pair .clip { flex: 1 1 320px; min-width: 0; }
@media (max-width: 760px) {
  .work-stack.pair { flex-direction: column; }
  .work-stack.pair .clip { flex: 1 1 auto; }
}

/* Visla 2-up override: mirror the credits grid (gap 40 + col-6 flex 1 1 320px) so the two
   clips align to the Credits / About column left edges above them. */
.work-stack.vids { flex-direction: row; flex-wrap: wrap; column-gap: 40px; row-gap: 64px; align-items: flex-start; }
.work-stack.vids .clip { flex: 1 1 320px; min-width: 0; align-items: flex-start; }
.work-stack.vids .clip video { width: auto; height: min(72vh, 760px); max-width: 100%; border-radius: 2px; }
.work-stack.vids figcaption { max-width: min(41vh, 428px); }  /* 영상 폭에 맞춰 캡션 줄바꿈(≈2줄) */
/* 클립이 하나뿐인 프로젝트(단일 영상 포스터)는 높이 기준으로 잡힌 영상이 칼럼 왼쪽에
   붙어 보인다 — 이때만 가운데로. 클립이 2개 이상인 Visla 등은 영향 없음. */
.work-stack.vids > .clip:only-child { flex: 1 1 100%; align-items: center; }
@media (max-width: 640px) {
  .work-stack.vids .clip video { height: auto; width: 100%; }
  .work-stack.vids .clip { width: 100%; }
}

.credits { display: flex; flex-wrap: wrap; gap: 40px; padding: 0 0 clamp(30px, 5vw, 60px); margin-top: clamp(4px, 0.6vw, 8px); }
.credits .col-6 { flex: 1 1 320px; }
.credits h2 { font-size: 13px; letter-spacing: -0.02em; text-transform: uppercase; color: var(--muted); margin-bottom: 8px; font-weight: 500; transform: scaleX(1.05); transform-origin: left; }  /* 장평 +5% + 자간 좁게 — match hero */
.credits p { font-size: 16px; line-height: 1.7; max-width: 46ch; letter-spacing: -0.02em; transform: scaleX(1.05); transform-origin: left; }  /* 장평 +5% + 자간 — match hero (left-aligned) */

/* 가로 패딩은 .detailWrap과 동일해야 한다 — 없으면 본문 칼럼보다 20px씩 넓게 나오고,
   모바일에선 화면 끝에 붙어 바깥으로 매단 화살표가 overflow-x:hidden에 잘린다. */
.detailNav { display: flex; justify-content: space-between; border-top: 1px solid rgba(255,255,255,.14); padding: 30px var(--pad); max-width: var(--maxw); margin: 0 auto; }
/* 이전/다음 프로젝트 — 라벨(크고 밝게) 위, 프로젝트명(작고 흐리게) 아래. next는 우측 정렬.
   화살표는 라벨 안에서 absolute로 바깥에 매달아 라벨 박스 폭에 안 들어간다 →
   Previous의 P / Next의 마지막 t가 아래 제목과 같은 정렬선에 선다. */
.detailNav a { font-size: 16px; display: flex; flex-direction: column; gap: 5px; max-width: 46%; }
.detailNav .navNext { align-items: flex-end; text-align: right; margin-left: auto; }
.detailNav .navLabel { position: relative; letter-spacing: -0.02em; transform: scaleX(1.05); transform-origin: left; }
.detailNav .navNext .navLabel { transform-origin: right; }
.detailNav .navArrow { position: absolute; top: 0; }
.detailNav .navPrev .navArrow { right: 100%; padding-right: .3em; }
.detailNav .navNext .navArrow { left: 100%; padding-left: .3em; }
.detailNav .navTitle { font-size: 14.3px; color: var(--muted); letter-spacing: -0.02em; }  /* 13px +10% */
.detailNav a:hover .navLabel { text-decoration: underline; text-underline-offset: 4px; }
@media (max-width: 600px) { .detailNav a { font-size: 14px; } .detailNav .navTitle { font-size: 13.2px; } }

/* =========================================================
   ABOUT
   ========================================================= */
.about { max-width: var(--maxw); margin: 0 auto; padding: clamp(140px, 22vh, 260px) var(--pad) clamp(60px,10vh,120px); }
.about h1 { font-weight: 400; font-size: clamp(32px, 5.5vw, 72px); line-height: 1.05; letter-spacing: -0.02em; text-align: center; }
.about .lead { max-width: 60ch; margin: clamp(40px,6vw,80px) auto 0; font-size: clamp(17px,1.6vw,20px); line-height: 1.7; text-align: center; }
.about .cols { display: flex; flex-wrap: wrap; gap: 48px; margin-top: clamp(50px,8vw,110px); }
.about .cols section { flex: 1 1 280px; }
.about .cols h2 { font-size: 13px; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); margin-bottom: 16px; font-weight: 500; }
.about .cols li, .about .cols p { font-size: 16px; line-height: 1.8; }

/* =========================================================
   FOOTER
   ========================================================= */
footer { padding: clamp(50px,8vw,90px) var(--pad) 0; }
/* text-transform 없음 — 적힌 대로 대소문자 유지(이메일은 소문자 그대로). */
.copyright {
  text-align: center; font-size: 14px; letter-spacing: .04em;
  padding: 20px; padding-bottom: 40px; color: var(--muted); line-height: 1.9;
}
/* 인스타·이메일 링크 — 흐린 푸터 안에서 눌리는 곳임이 보이도록 밑줄, hover에 밝게 */
.copyright a { color: inherit; text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: rgba(255,255,255,.28); transition: color .2s; }
.copyright a:hover { color: var(--fg); text-decoration-color: currentColor; }
/* 모바일 푸터: 저작권 한 줄 + 이메일 한 줄로 딱 두 줄. 좌우 패딩을 걷고(footer가 이미
   var(--pad)를 가짐) 폰트를 뷰포트에 연동해 어느 폭에서도 첫 줄이 안 접히게 한다. */
@media (max-width: 600px) {
  footer .copyright { font-size: clamp(10px, 2.85vw, 14px); letter-spacing: .02em;
    padding-left: 0; padding-right: 0; }
}

/* toast — shown when an email address is copied to the clipboard */
.toast {
  position: fixed; left: 50%; bottom: 32px; transform: translate(-50%, 12px);
  background: var(--fg); color: var(--bg);
  font-size: 14px; letter-spacing: .01em; padding: 11px 18px; border-radius: 4px;
  box-shadow: 0 12px 30px rgba(0,0,0,.4); max-width: calc(100vw - 32px);
  opacity: 0; pointer-events: none; z-index: 9998;   /* below the custom cursor (9999) */
  transition: opacity .3s var(--ease), transform .3s var(--ease);
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }

/* =========================================================
   RESPONSIVE  (press-room: 5col → fewer)
   ========================================================= */
@media (max-width: 1024px) {
  .col { width: 50%; }                                 /* tablet: 2 columns */
}
@media (max-width: 768px) {
  .menuWeb .navlink { display: none; }
  .menuBtn { display: block; }
  .credits { gap: 24px; }
}
@media (max-width: 600px) {
  .col { width: 100%; }                                /* mobile: 1 column */
  /* --- MOBILE HERO (isolated here; desktop/tablet use the base clamps, untouched) ---
     character stays ×1.11 of the bio so it seats at the first line. */
  /* right pad compensates the bio's scaleX(1.05) overflow (origin:left) so the
     VISIBLE right margin equals the 15.4px left across the whole mobile range */
  .heroText { padding-left: 15.4px; padding-right: calc(15px + 4.7vw); }
  /* height-aware (like tablet): the old vw-only size left a huge empty gap on tall phones
     (looked too small) and overflowed the flames on short ones. Tie it to vh so tall phones
     fill and short phones shrink; min(…,vw) guards the narrow end from over-wrapping. */
  .bio { max-width: none; font-size: clamp(19px, min(2.9vh + 2.5px, 6.8vw), 30px); line-height: 1.16; }
  /* seat vertically on line 1: the base `top` uses a fixed +12px that over-drops the
     character at mobile font sizes (measured +0.21em below the line vs desktop's −0.10em).
     `--heroTop − 0.445em` reproduces the desktop em-relative offset across the mobile range. */
  .heroBrand, .brand { font-size: clamp(21.1px, min(3.22vh + 2.78px, 7.55vw), 33.3px); left: 11.7px; top: calc(var(--heroTop) - 0.445em); }  /* stays ×1.11 of bio, seated at line start. .brand = 상세 헤더, 히어로와 동일하게 */
  .cn .cnimg { width: 130px; }
  /* align the flame + arrow rows to the text's 15.4px side margins.
     space-between pins the outer flames/arrows to those edges (base uses space-around,
     which floats them further in). NB: each flame PNG carries ~12% transparent margin,
     so the visible flame still sits a touch inside the 15.4px box edge. */
  .fireRow { padding: 0 15.4px; justify-content: space-between; }
  /* six pixel arrows overflow the row at a fixed 63px — scale them to fit the phone width */
  /* mobile: lift the arrows to sit just ABOVE the flames. Flame height scales with
     viewport width (JS flameBase ≈ width×0.092×1.2, box 1.1em), so the offset tracks
     it in vw — keeps a steady gap above the (now 20%-bigger) flame tops on any phone. */
  .arrowRow { padding: 0 17px; bottom: calc(20px + 19vw); z-index: 22; }
  .pixArrow { width: 25.76px; height: 15.46px; }      /* −20%, −30%, then +15% */
}

/* --- TABLET HERO (601–1024px) ---
   The base clamps size the bio to viewport WIDTH, but here the binding constraint is
   HEIGHT: the flame row is pinned ~152px from the bottom, so at the base font (48–54px)
   the paragraph runs straight through the flames — worst in landscape (short height).
   Fix: size the hero to viewport HEIGHT (vh) so the paragraph always clears the flames
   with a steady gap — smaller in short landscape, larger on tall portrait. Character
   tracks the bio ×1.11 and reuses the mobile seating (base +12px over-drops it here too). */
@media (min-width: 601px) and (max-width: 1024px) {
  /* min(height-driven, width-driven): height keeps the paragraph clear of the flames,
     width guards narrow tablets (e.g. 640w) where extra wrapping would still overflow. */
  /* fill the column (base max-width leaves an inconsistent right margin: full at 768,
     ~95px at 1024). padding-right absorbs the bio's scaleX(1.05) overflow so the text's
     VISIBLE right edge lands at viewport−40 at every width — a symmetric 40/40 margin
     matching the left, and matching the arrow row. */
  .heroText { padding-right: calc(4.76vw + 36px); }
  .bio { font-size: clamp(30px, min(2.18vh + 19.2px, 5.2vw), 47px); max-width: none; }
  .heroBrand, .brand { font-size: clamp(33px, min(2.42vh + 21.3px, 5.77vw), 52px); top: calc(var(--heroTop) - 0.445em); }
  /* arrows vs flames: on tablet the 6 arrows' outer pair sit inside the outer flames, so
     size alone can't clear them (arrow centre is within the flame). Lift the whole row to
     sit just ABOVE the flame tops (mobile relationship) → zero overlap through the breathe
     cycle. Bottom tracks flame height (flames ≈ 0.10·w, so ~15vw) with a floor for the
     narrow end where flameBase() clamps to 72px. Arrows sized in proportion to the flames. */
  .arrowRow { bottom: calc(28px + max(108px, 15vw)); z-index: 22;
              padding-left: calc(var(--pad) + 22px); padding-right: calc(var(--pad) + 22px); }  /* 42px: +2px inset vs text so it doesn't read tighter than the ragged-right text */
  .pixArrow { width: clamp(44px, 6.05vw, 63.8px); height: auto; aspect-ratio: 454.7 / 272.8; }  /* +10% */
}

/* --- TABLET LANDSCAPE only (short height, e.g. 1024×768) ---
   The vh-driven font bottoms out here (~36px) so the bio reads undersized on the wide
   screen. Flame gap is generous (~195px), so bump the font (~40px, matching portrait
   tablets) via a steeper vh slope, and lower the arrow row to open room for the taller
   paragraph — arrows still clear the flame tops. */
@media (min-width: 601px) and (max-width: 1024px) and (orientation: landscape) {
  /* steeper vh slope than portrait (uses the extra landscape gap) but tuned so it stays
     safe at short heights too: ~39px at 1024×768, ~33px at 1024×600. min(…,5.2vw) guards
     narrower landscapes where extra wrapping would collide. */
  .bio { font-size: clamp(33.6px, min(3.75vh + 12.2px, 5.46vw), 46px); }      /* +5% (≈41px @1024×768) */
  .heroBrand, .brand { font-size: clamp(37.3px, min(4.16vh + 13.5px, 6.06vw), 51px); }
  .arrowRow { bottom: calc(20px + max(84px, 11vw)); }   /* flames slightly shorter here, so arrows drop with them, still between the taller bio and the flame tops */
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
  .reveal { opacity: 1; transform: none; }
  .flame { top: 0 !important; }
}

/* =========================================================
   CUSTOM CURSOR (jun.works style: black-filled, white-outlined arrow)
   ========================================================= */
@media (hover: hover) and (pointer: fine) {
  * { cursor: none !important; }   /* hide native; single JS cursor everywhere */
}

/* JS-driven custom cursor — uniform 56px everywhere (no browser size cap) */
.bigcursor { position: fixed; left: 0; top: 0; z-index: 9999; pointer-events: none; opacity: 0; }
.bigcursor.ready { opacity: 1; }
.bigcursor i {
  display: block; width: 56px; height: 56px; margin: -1px 0 0 -1px;  /* align arrow tip to pointer */
  background: url(../img/cursor-arrow-px.svg) center / contain no-repeat;  /* pixel-art arrow, white fill — visible on dark bg */
  image-rendering: pixelated;   /* keep the pixel steps crisp when scaled up */
}
/* hover over interactive targets (thumbnails, links, buttons) — swap the arrow for a
   pixel-art pointing hand in the same style. margin re-aligns the hotspot to the fingertip. */
.bigcursor.inv i { background-image: url(../img/cursor-hand-px.svg); margin: -1px 0 0 -14px; }  /* ~9% smaller than the arrow via extra viewBox padding, so it reads the same visual size */

/* ---------- 한글 조판 ----------
   사이트 시그니처는 라틴 기준 장평 scaleX(1.05) + 자간 -0.02em인데, 한글은 글자폭이
   이미 꽉 차 있어 장평을 늘리면 넓고 헐거워 보인다 → 한글만 장평 기본(100%) + 자간을
   라틴보다 더 좁게. 대상은 build.py가 한글을 감지해 .kr을 붙여준 요소.
   .ln.kr  : 장평이 부모(<p>)에 걸려 있어 역수 scaleX(1/1.05)로 상쇄한다.
   .ct/.cd : 장평이 자기 자신에 걸려 있어 transform을 끄면 된다. */
:root { --kr-tracking: -0.06em; }

.ln { display: block; }                     /* about 본문을 줄 단위 블록으로 — 한글 줄만 따로 조판 */
.ln.gap { margin-top: 1.7em; margin-top: 1lh; }   /* info.txt의 빈 줄 = 빈 줄 하나 높이 */
.ln.kr { transform: scaleX(0.952381); transform-origin: left; letter-spacing: var(--kr-tracking); }
.work-stack .ct.kr, .work-stack .cd.kr { transform: none; letter-spacing: var(--kr-tracking); }
