:root {
  --bg: #070907;
  --panel: #0c100c;
  --line: #1c261c;
  --fg: #c8d3c8;
  --dim: #5f6f5f;
  --green: #3dff8a;
  --amber: #ffb547;
  --red: #ff5f56;
  --mono: "JetBrains Mono", "Pretendard", monospace;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html { word-break: keep-all; scroll-padding-top: 72px; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; } /* no mobile text inflation */
body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--mono);
  font-size: 15px;
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
}
body::after { /* scanlines */
  content: ""; position: fixed; inset: 0; pointer-events: none;
  background: repeating-linear-gradient(0deg, rgba(0,0,0,.18) 0 1px, transparent 1px 3px);
}
html.m-pending main { visibility: hidden; } /* until motion.js runs its entrances (see <head>) */
#bg-field { position: fixed; inset: 0; width: 100%; height: 100%; z-index: -1; pointer-events: none; } /* backdrop.js */
a { color: inherit; text-decoration: none; }
.wrap { max-width: 1080px; margin: 0 auto; padding: 0 28px; }
.g { color: var(--green); } .a { color: var(--amber); } .d { color: var(--dim); } .r { color: var(--red); }

header { border-bottom: 1px solid var(--line); position: sticky; top: 0; background: rgba(7,9,7,.92); z-index: 2; }
header .scroll-progress { position: absolute; left: 0; right: 0; bottom: -1px; height: 1px; background: var(--green); box-shadow: 0 0 8px rgba(61,255,138,.6); transform: scaleX(0); transform-origin: 0 50%; }
header .wrap { display: flex; justify-content: space-between; align-items: center; height: 60px; }
/* SVG logo (symbol #graylab-logo in index.html): mark, "Gray" and "Lab" each take their own colour. */
.logo { display: block; height: 24px; width: auto; --lg-mark: #fff; --lg-gray: #fff; --lg-lab: #fff; }
.hdr-right { display: flex; align-items: center; gap: 28px; }
nav { display: flex; gap: 28px; font-size: 13px; color: var(--dim); }
nav a::before { content: "./"; color: var(--line); }
nav a:hover { color: var(--fg); }

.lang { display: flex; align-items: center; border: 1px solid var(--line); border-radius: 4px; overflow: hidden; font-size: 12px; }
.lang button { background: none; border: 0; color: var(--dim); font: inherit; letter-spacing: .06em; padding: 3px 10px; cursor: pointer; }
.lang button + button { border-left: 1px solid var(--line); }
.lang button:hover { color: var(--fg); }
.lang button[aria-pressed="true"] { background: var(--green); color: var(--bg); font-weight: 600; }
.lang button:focus-visible { outline: 1px solid var(--amber); outline-offset: -1px; }

.term { border: 1px solid var(--line); background: var(--panel); border-radius: 6px; overflow: hidden; }
.term-bar { display: flex; align-items: center; gap: 8px; padding: 10px 14px; border-bottom: 1px solid var(--line); font-size: 12px; color: var(--dim); }
.term-bar i { width: 11px; height: 11px; border-radius: 50%; display: inline-block; }
.term-bar i:nth-child(1) { background: var(--red); } .term-bar i:nth-child(2) { background: var(--amber); } .term-bar i:nth-child(3) { background: var(--green); }
.term-bar b { margin-left: 10px; font-weight: 400; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.term-body { padding: 28px 30px 34px; }

.hero { padding: 72px 0 56px; }
.hero .term { background: rgba(12,16,12,.84); } /* lets the backdrop terrain glow through */
/* the boot sequence clips the wrapper div, not the <svg>: WebKit ignores clip-path on a filtered root <svg> */
.banner { width: min(100%, 420px); margin: 10px 0 24px; --lg-mark: var(--green); --lg-gray: var(--green); --lg-lab: var(--green); }
.banner svg { display: block; width: 100%; height: auto; filter: drop-shadow(0 0 12px rgba(61,255,138,.35)); }
.prompt::before, .sh-cmd::before { content: "graylab@seoul:~$ "; color: var(--green); }
.hero h1, .hero .sh-h1 { font-family: "Pretendard", sans-serif; font-size: clamp(30px, 4.6vw, 52px); line-height: 1.25; font-weight: 800; color: #eef5ee; margin: 18px 0 14px; letter-spacing: -0.02em; }
.hero h1 em, .hero .sh-h1 em { font-style: normal; color: var(--green); }
.cursor { display: inline-block; width: .6em; height: 1.1em; background: var(--green); vertical-align: -0.15em; animation: blink 1s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }

/* interactive hero shell (hero-shell.js) — click the terminal, type help */
.hero .term.interactive .term-body { cursor: text; }
.hero .term.interactive:focus { outline: none; } /* tabindex -1: only there to keep clicks in the pane */
.hero .term.live { border-color: rgba(61,255,138,.35); }
/* the pane keeps the height the hero has when the shell starts; typed output scrolls inside */
.hero .term.interactive .term-body { height: var(--term-h, auto); overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
.hero .term.measuring .term-body { height: auto; overflow: hidden; } /* sizing pass (hero-shell.js) */
.hero .term.measuring .sh-out { display: none; }
/* clear blanks the hero block too; it returns when the terminal loses focus */
.hero .term-body.cleared > .prompt,
.hero .term-body.cleared > .banner,
.hero .term-body.cleared > h1,
.hero .term-body.cleared > .d,
.hero .term-body.cleared > br { display: none; }
.sh-in { display: flex; align-items: baseline; }
.sh-in::before { white-space: pre; } /* keeps the space after "$", as on the static .prompt lines */
.sh-in:focus-within::before { color: var(--amber); }
/* hero-shell.js sets the width to the typed text's, so the idle cursor sits right behind it */
.sh-input { flex: 0 1 auto; min-width: 0; margin: 0; border: 0; background: none; padding: 0; color: var(--fg); font: inherit; caret-color: var(--green); }
.sh-input:focus { outline: none; }
/* the block cursor blinks on the idle prompt and steps aside for the caret while typing */
.sh-in:focus-within .cursor { display: none; }
.hero .term.sh-wait .sh-in { opacity: 0; pointer-events: none; } /* prompt waits for the boot sequence */
.sh-out > .ln { white-space: pre-wrap; } /* keeps the ls columns lined up without side-scrolling */
.sh-out .rd { font-family: "Pretendard", sans-serif; margin: 4px 0 2px; }
.sh-out .rd-head b { font-size: 19px; color: #eef5ee; }
.sh-out .rd-head .en { margin-left: 10px; color: var(--green); font-family: var(--mono); font-size: 12px; letter-spacing: .06em; }
.sh-out .rd p { font-size: 15px; color: #a9b6a9; line-height: 1.7; margin: 8px 0 10px; max-width: 66ch; }
.sh-out .rd p em { font-style: normal; font-weight: 600; color: var(--green); }
.sh-out .rd ul { list-style: none; font-size: 13px; }
.sh-out .rd li::before { content: "+ "; color: var(--green); }
.sh-out .flag { color: #fff; overflow-wrap: anywhere; } /* one long token: let it break on phones */

section { padding: 64px 0; border-top: 1px dashed var(--line); }
.sec-title { font-size: 13px; color: var(--dim); margin-bottom: 28px; }
.sec-title b { color: var(--amber); font-weight: 600; }
h2 { font-family: "Pretendard", sans-serif; font-size: 30px; line-height: 1.35; color: #eef5ee; font-weight: 800; letter-spacing: -0.02em; margin-bottom: 30px; }

table.ls { width: 100%; border-collapse: collapse; font-size: 13px; margin-bottom: 34px; }
table.ls td { padding: 4px 18px 4px 0; white-space: nowrap; }
table.ls td:last-child { width: 100%; }

.svc { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; }
.card { border: 1px solid var(--line); background: var(--panel); padding: 26px 26px 28px; position: relative; transition: border-color .3s; }
.card::after { content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity .3s;
  background: radial-gradient(280px circle at var(--mx, 50%) var(--my, 50%), rgba(61,255,138,.07), transparent 70%); }
.card:hover { border-color: rgba(61,255,138,.3); }
.card:hover::after { opacity: 1; }
.card .id { font-size: 12px; color: var(--dim); }
.card h3 { font-family: "Pretendard", sans-serif; font-size: 21px; color: #eef5ee; margin: 6px 0 4px; }
.card .en { color: var(--green); font-size: 12px; letter-spacing: .06em; }
.card p { font-family: "Pretendard", sans-serif; font-size: 15px; color: #a9b6a9; margin: 14px 0 16px; line-height: 1.7; }
.card p em { font-style: normal; font-weight: 600; color: var(--green); }
.card ul { list-style: none; font-size: 13px; }
.card li::before { content: "+ "; color: var(--green); }
.card.ai { border-color: rgba(61,255,138,.45); box-shadow: 0 0 0 1px rgba(61,255,138,.08), 0 0 40px rgba(61,255,138,.06) inset; }
.card.ai:hover { border-color: rgba(61,255,138,.7); }
.card.ai .tag { position: absolute; top: 22px; right: 22px; font-size: 11px; color: var(--bg); background: var(--green); padding: 1px 8px; }

.neo { border: 1px solid var(--line); background: var(--panel); border-radius: 6px; overflow: hidden; }
.neo-frame { position: relative; aspect-ratio: 21 / 9; min-height: 320px; }
#neo-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; opacity: 0; transition: opacity .6s; }
.neo.live #neo-canvas { opacity: 1; }
.neo.live .neo-fallback { display: none; }
.neo-fallback { position: absolute; inset: 0; display: grid; place-items: center; padding: 18px; }
.neo-fallback img { width: 100%; height: 100%; object-fit: contain; }
.neo-note { margin-top: 14px; font-family: "Pretendard", sans-serif; font-size: 14px; line-height: 1.7; color: #a9b6a9; }

.log { font-size: 13px; }
.log div { padding: 2px 0 2px 10ch; text-indent: -10ch; } /* wrapped lines hang under the tag, past "[T+00:00] " */
.term-bar .live { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; color: var(--red); font-size: 11px; letter-spacing: .08em; }
.term-bar .live::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--red); box-shadow: 0 0 8px var(--red); animation: blink 1.2s steps(1) infinite; }
/* incident.js adds .armed (hidden) then .play once the log scrolls into view */
.log.armed > div { opacity: 0; }
.log.play > div { animation: log-type .7s steps(32, end) calc(var(--i, 0) * 550ms) both; }
.log.play .r { animation: alert-flash .8s steps(1) .7s 3; }
@keyframes log-type { from { opacity: 1; clip-path: inset(0 100% 0 0); } to { opacity: 1; clip-path: inset(0 0 0 0); } }
@keyframes alert-flash { 50% { background: var(--red); color: var(--bg); } }

.contact { display: grid; grid-template-columns: 1.2fr 1fr; gap: 24px; align-items: stretch; }
.contact .big { font-family: "Pretendard", sans-serif; font-size: 34px; color: #eef5ee; font-weight: 800; line-height: 1.3; letter-spacing: -0.02em; }
.kv { font-size: 14px; }
.kv div { display: flex; justify-content: space-between; gap: 24px; border-bottom: 1px dashed var(--line); padding: 10px 0; }
.kv div > :last-child { text-align: right; }
.kv div span:first-child { color: var(--dim); }

/* --- 04 · clicking the address expands the map once (it stays open) --- */
/* Until it is opened the row reads as a button: dotted underline + filled "지도 열기 ↓" chip on hover. */
.kv .loc { cursor: pointer; }
.kv .loc:focus { outline: none; }
.kv .loc:focus-visible { outline: 1px dashed rgba(61,255,138,.5); outline-offset: 4px; }
/* address + chip side by side: the address wraps within its own box, the chip never drops to its own line */
.kv .loc > :last-child { display: flex; align-items: center; justify-content: flex-end; gap: 10px; }
.kv .loc [data-i18n="contact.location"] { text-decoration: underline dotted transparent; text-underline-offset: 4px; transition: color .25s, text-decoration-color .25s; }
.map-hint { flex: none; display: inline-flex; align-items: center; gap: 5px; font-size: 11px; color: var(--fg); border: 1px solid rgba(61,255,138,.35); border-radius: 3px; padding: 1px 8px; white-space: nowrap; transition: opacity .4s, color .25s, background-color .25s, border-color .25s, box-shadow .25s, transform .15s; }
.map-hint::after { content: "↓"; color: var(--green); transition: color .25s, transform .25s; }
#contact:not(.opened) .loc:is(:hover, :focus-visible) [data-i18n="contact.location"] { color: var(--green); text-decoration-color: rgba(61,255,138,.6); }
#contact:not(.opened) .loc:is(:hover, :focus-visible) .map-hint { color: var(--bg); background: var(--green); border-color: var(--green); box-shadow: 0 0 12px rgba(61,255,138,.35); }
#contact:not(.opened) .loc:is(:hover, :focus-visible) .map-hint::after { color: var(--bg); transform: translateY(2px); }
#contact:not(.opened) .loc:active .map-hint { transform: scale(.96); }
#contact.opened .kv .loc { cursor: default; }
#contact.opened .map-hint { opacity: 0; }
#locmap { display: grid; grid-template-rows: 0fr; margin-top: 0; transition: grid-template-rows .9s cubic-bezier(.22,1,.36,1), margin-top .9s cubic-bezier(.22,1,.36,1); }
#locmap.open { grid-template-rows: 1fr; margin-top: 26px; }
.map-panel { position: relative; min-height: 0; overflow: hidden; border: 1px solid var(--line); border-radius: 6px; background: rgba(12,16,12,.88); opacity: 0; transform: translateY(12px); transition: opacity .55s .2s, transform .55s .2s; }
#locmap.open .map-panel { opacity: 1; transform: none; }
.map-panel .term-bar .mp-note { margin-left: auto; padding-left: 10px; font-family: "Pretendard", sans-serif; font-size: 11px; white-space: nowrap; flex: none; }
/* bottom-right overlay link out to Naver Map: same chip as .map-hint, fades in after the map draws */
.mp-ext { position: absolute; right: 14px; bottom: 14px; display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--fg); background: rgba(10,15,10,.85); border: 1px solid rgba(61,255,138,.35); border-radius: 3px; padding: 4px 10px; white-space: nowrap; backdrop-filter: blur(2px); opacity: 0; visibility: hidden; translate: 0 6px; transition: opacity .5s 1.6s, translate .5s 1.6s, visibility 0s 1.6s, scale .15s, color .25s, background-color .25s, border-color .25s, box-shadow .25s; }
.mp-ext::after { content: "↗"; color: var(--green); transition: color .25s, transform .25s; }
#locmap.open .mp-ext { opacity: 1; visibility: visible; translate: none; }
.mp-ext:is(:hover, :focus-visible) { color: var(--bg); background: var(--green); border-color: var(--green); box-shadow: 0 0 12px rgba(61,255,138,.35); outline: none; }
.mp-ext:is(:hover, :focus-visible)::after { color: var(--bg); transform: translate(2px, -2px); }
.mp-ext:active { scale: .96; }

.mp-svg { display: block; width: 100%; height: auto; }
.mp-svg text { font-family: "Pretendard", sans-serif; }
.mp-bg { fill: #0a0f0a; }
.mp-alley path { stroke: #2c382d; stroke-width: 1.3; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.mp-road2 path { stroke: #3e4c3f; stroke-width: 3; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.mp-road1 path { stroke: #566755; stroke-width: 6.5; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.mp-road1 .ow { stroke-width: 4; } /* one carriageway of a divided road */
.mp-lines path { stroke-width: 3.6; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.mp-l3 { stroke: #ff8f3e; } .mp-l5 { stroke: #9d7ce6; } .mp-l8 { stroke: #e85f9d; }
.mp-glow { stroke-width: 9; opacity: 0; transition: opacity .8s var(--d,0s); }
#locmap.open .mp-glow { opacity: .16; }
.mp-cross line { stroke: rgba(61,255,138,.14); stroke-width: 1; stroke-dasharray: 3 7; }

/* draw-in choreography: pathLength=1 paths unstroke with staggered delays */
.mp-draw { stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset 1.4s cubic-bezier(.25,.6,.3,1) var(--d,0s); }
#locmap.open .mp-draw { stroke-dashoffset: 0; }
.mp-st { opacity: 0; transition: opacity .55s 1.15s; }
#locmap.open .mp-st { opacity: 1; }

.mp-dot { fill: #0a0f0a; stroke-width: 2.4; }
.mp-dotw { stroke: #f0f4ec; } .mp-dot3 { stroke: #ff8f3e; } .mp-dot5 { stroke: #9d7ce6; } .mp-dot8 { stroke: #e85f9d; }
.mp-bd circle { fill: #eef2ea; }
.mp-bd text { font-size: 10px; font-weight: 800; text-anchor: middle; dominant-baseline: central; }
.mp-bd3 text { fill: #d96f14; } .mp-bd5 text { fill: #7d5bd0; } .mp-bd8 text { fill: #d13b7e; }
.mp-name { fill: #dfe6dc; font-size: 13px; font-weight: 600; paint-order: stroke; stroke: #0a0f0a; stroke-width: 4px; stroke-linejoin: round; }

.mp-pin { opacity: 0; transform-box: fill-box; transform-origin: 50% 90%; }
#locmap.open .mp-pin { animation: mp-drop .6s cubic-bezier(.34,1.56,.64,1) 1.5s both; }
.mp-pindr { fill: var(--green); filter: drop-shadow(0 0 10px rgba(61,255,138,.45)); }
.mp-bldg { fill: #071207; }
.mp-pinname { fill: #eef5ee; font-size: 12.5px; font-weight: 800; letter-spacing: .08em; text-anchor: middle; paint-order: stroke; stroke: #0a0f0a; stroke-width: 4px; stroke-linejoin: round; }
.mp-ring { fill: none; stroke: var(--green); stroke-width: 1.6; opacity: 0; transform-box: fill-box; transform-origin: center; }
#locmap.open .mp-ring { animation: mp-ping 2.6s cubic-bezier(.2,.6,.35,1) 2.1s infinite; }
#locmap.open .mp-ring-b { animation-delay: 3.4s; }
@keyframes mp-drop { from { opacity: 0; transform: translateY(-16px) scale(.65); } to { opacity: 1; transform: none; } }
@keyframes mp-ping { 0% { transform: scale(.35); opacity: .65; } 75%,100% { transform: scale(2.7); opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  #locmap, .map-panel, .mp-glow, .mp-st, .mp-draw, .mp-ext { transition-duration: .001s; }
  #locmap.open .mp-pin { animation: none; opacity: 1; }
  .mp-ring { display: none; }
}

footer { border-top: 1px solid var(--line); padding: 28px 0 40px; font-size: 12px; color: var(--dim); }
footer .wrap { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 10px; }

.br-m { display: none; } /* line break shown only on narrow screens */

@media (max-width: 800px) {
  nav { display: none; }
  .svc, .contact { grid-template-columns: 1fr; }
  .contact .big { font-size: clamp(20px, 6vw, 34px); }
  .br-m { display: inline; }
  .neo-frame { aspect-ratio: auto; height: 300px; }
  table.ls td:nth-child(-n+3) { display: none; }
  table.ls td:last-child { white-space: normal; } /* the comment wraps instead of pushing the page sideways */
  .mp-ext { right: 8px; bottom: 8px; font-size: 11px; padding: 2px 8px; } /* the map is short here; keep the chip off the stations */
  .sh-out .cols { display: none; } /* the shell drops the same columns the ls table does */
  h2 { font-size: 26px; }
}

/* phones: tighter gutters and a short prompt so commands stay on one line */
@media (max-width: 480px) {
  .wrap { padding: 0 20px; }
  .hero { padding: 40px 0 44px; }
  .hero .term-body { padding: 22px 18px 26px; font-size: 13px; }
  .hero .term-body > .d { padding-left: 2ch; text-indent: -2ch; } /* wrapped "# …" comments hang under the text */
  #ir .term-body { padding: 22px 18px 26px; }
  .hero .prompt::before, .hero .sh-cmd::before { content: "~$ "; } /* the title bar still names graylab@seoul */
  .kv div { flex-direction: column; gap: 4px; }
  .kv div > :last-child { text-align: left; }
  .kv .loc > :last-child { justify-content: space-between; }
}
