/* ═══ Shared navigation (all pages) — burger + mobile menu markup lives in the
   HTML; assets/nav.js only toggles open/closed state and manages focus. ═══ */
.nav-burger{display:none;position:relative;width:44px;height:44px;border:0;background:transparent;cursor:pointer;padding:0;margin-left:2px}
.nav-burger span{position:absolute;left:11px;right:11px;height:1.5px;background:var(--ink);transition:transform .35s var(--ease)}
.nav-burger span:nth-child(1){top:17px}
.nav-burger span:nth-child(2){top:26px}
nav.on-dark .nav-burger span{background:#f7f6f2}
.nav-burger[aria-expanded="true"] span:nth-child(1){transform:translateY(4.5px) rotate(45deg)}
.nav-burger[aria-expanded="true"] span:nth-child(2){transform:translateY(-4.5px) rotate(-45deg)}

/* full-height panel below the fixed 72px nav; links centered as a column */
.mobile-menu{position:fixed;top:72px;left:0;right:0;z-index:99;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:clamp(20px,4.5vh,38px);height:calc(100vh - 72px);height:calc(100dvh - 72px);background:rgba(247,246,242,.98);backdrop-filter:blur(14px);padding:0 var(--pad);visibility:hidden;opacity:0;transform:translateY(-8px);transition:opacity .3s var(--ease),transform .3s var(--ease),visibility 0s .3s}
.mobile-menu.open{visibility:visible;opacity:1;transform:none;transition:opacity .3s var(--ease),transform .3s var(--ease)}
/* centered on text content — overrides .roll's small uppercase treatment */
.mobile-menu a{font-family:var(--serif);font-size:clamp(26px,4vh,34px);letter-spacing:-.01em;text-transform:none;color:var(--ink);padding:10px 14px}
body.menu-open{overflow:hidden}

/* letter-roll clip wrapper (added by nav.js so links can grow to 44px targets
   while the roll animation still clips at the text box) */
.roll-clip{display:inline-flex;overflow:hidden}
html.js .roll[data-roll-ready="true"]{overflow:visible}
html.js .nav-links .roll{min-height:44px;align-items:center}
/* letter-roll also on keyboard focus (desktop + mobile links) */
.roll:focus-visible .ch{transform:translateY(-100%)}

@media(max-width:860px){html.js .nav-burger{display:block}}
@media(min-width:861px){.mobile-menu{display:none!important}}
@media(prefers-reduced-motion:reduce){
  .nav-burger span,.mobile-menu{transition:none}
  .roll:hover .ch,.roll:focus-visible .ch{transform:none}
}

/* ═══ No-JS fallback (≤860px): burger stays hidden, desktop links reflow into
   wrapped rows inside the fixed-height nav — fits 320px with no overflow ═══ */
@media(max-width:860px){
  html:not(.js) .nav-links .roll{display:inline-flex}
  html:not(.js) nav{flex-wrap:wrap;height:auto;min-height:72px;padding-top:10px;padding-bottom:10px;row-gap:2px;background:rgba(247,246,242,.96)}
  html:not(.js) .nav-links{flex-wrap:wrap;justify-content:flex-end;column-gap:14px;row-gap:2px}
  html:not(.js) .nav-contact{padding:8px 14px}
  html:not(.js) .mobile-menu{display:none}
}

/* ═══ 공통 접근성 (전 페이지 공유) ═══ */
.skip-link{position:fixed;top:-100px;left:16px;z-index:200;background:var(--ink);color:var(--bg);padding:12px 20px;border-radius:100px;font-size:var(--text-label);letter-spacing:.08em;transition:top .2s}
.skip-link:focus{top:12px}
a:focus-visible,button:focus-visible{outline:2px solid currentColor;outline-offset:3px}
#main-content{outline:none}
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{scroll-behavior:auto!important;animation-iteration-count:1!important}
}

/* 스크린리더 전용 */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ═══ Current-page navigation state — aria-current="page" on the exact page;
   .active marks the Projects item as the parent section on detail pages ═══ */
.nav-links a[aria-current="page"],.nav-links a.active,
.mobile-menu a[aria-current="page"],.mobile-menu a.active{color:var(--ink)}

/* ═══ Scroll cable — a small kinetic sculpture on the LEFT edge: a matte bob
   hangs on a slack ~1.25px cable ~56px in, starting below the hero. It follows
   scroll with spring inertia; the cable's slack (a gentle downward+lateral sag)
   stretches with speed and settles with ONE damped oscillation; the bob
   compresses into a socket at the page foot. Idle at ~24% opacity, fades to
   full while scrolling and back after ~1s. Decorative (aria-hidden /
   pointer-events:none), monochrome, dark-zone + reduced-motion aware. ═══ */
#scroll-thread{position:fixed;top:0;left:30px;width:26px;height:100%;z-index:90;pointer-events:none;
  opacity:.24;transition:opacity .7s ease;
  --st-wire:rgba(16,16,16,.2);--st-bob:#2c2c2b;--st-bob-hi:rgba(255,255,255,.16);
  --st-bob-sh:rgba(16,16,16,.26);--st-socket:rgba(16,16,16,.24)}
#scroll-thread.awake{opacity:1;transition:opacity .28s ease}
#scroll-thread.on-dark{--st-wire:rgba(249,248,244,.72);--st-bob:#faf9f5;--st-bob-hi:rgba(255,255,255,.55);
  --st-bob-sh:rgba(0,0,0,.55);--st-socket:rgba(249,248,244,.64)}
#scroll-thread svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible;display:block}
.st-wire{fill:none;stroke:var(--st-wire);stroke-width:1.25;stroke-linecap:round;transition:stroke .55s linear}
.st-socket{fill:none;stroke:var(--st-socket);stroke-width:1.25;transition:stroke .55s linear}
.st-anchor{fill:var(--st-wire);transition:fill .55s linear}
.st-bob{position:absolute;top:0;left:0;width:10px;height:10px;will-change:transform}
.st-bob i{display:block;width:100%;height:100%;border-radius:50%;background:var(--st-bob);
  box-shadow:0 1px 2px var(--st-bob-sh),inset 0 .5px 0 var(--st-bob-hi);
  transition:background .55s linear,box-shadow .55s linear}
.st-bob.settle i{animation:st-settle .5s cubic-bezier(.22,1,.36,1)}
@keyframes st-settle{0%{transform:scale(1,1)}28%{transform:scale(1.22,.74)}60%{transform:scale(.97,1.05)}100%{transform:scale(1,1)}}
@media(max-width:640px){#scroll-thread{display:none}}
@media(prefers-reduced-motion:reduce){#scroll-thread,#scroll-thread.awake{transition:none}.st-bob.settle i{animation:none}.st-wire,.st-bob i,.st-socket,.st-anchor{transition:none}}

/* ═══ Wire zone — a dedicated left lane for the scroll cable, reserved in the
   grid so the cable never crosses content. The left content inset grows to a
   floor that clears the cable (cable sits ~43px in); the RIGHT inset is left
   untouched, so this rebalances proportions (a larger left margin) rather than
   translating the whole page. On wide viewports the centered rail already
   exceeds the floor, so nothing moves. The cable is hidden ≤640px, so the
   reserve collapses back to the normal inset there. Full-bleed dark/light zone
   backgrounds stay edge-to-edge — only their inner content is inset. ═══ */
:root{--rail-l:max(88px,var(--rail,var(--pad,24px)))}
@media(max-width:640px){:root{--rail-l:var(--rail,var(--pad,24px))}}
body section,body .hero,body .reflect-sec,body .statement-sec,body .ladder-sec,
body .ov-sec,body .about-sec,body .works-head,body .stack,body .contact-band,
body .page-head,body .filter-row,body .grid-wrap{padding-left:var(--rail-l)}
body .next-band{margin-left:var(--rail-l)}
