/* ═══════════════════════════════════════════
   Portfolio — 공통 + index.html (벤토 그리드)
   토큰(:root)은 css/tokens.css 에 있습니다. 먼저 불러야 동작합니다.
   ═══════════════════════════════════════════ */

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.65;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  word-break: normal;
}

/* keep-all 은 한국어를 위한 것입니다 — 단어 중간에서 줄이 끊기지 않게 합니다.
   일본어에는 띄어쓰기가 없어서 keep-all 을 걸면 문장 하나가 통째로 안 끊기는
   덩어리가 되고, 좁은 화면에서 타일을 밀어내 가로 스크롤이 생깁니다.
   (390px 일본어에서 51px 넘쳤습니다) 그래서 한국어에만 걸어 둡니다. */
html[lang="ko"] body { word-break: keep-all; }

h1 { margin: 0; font-weight: 800; letter-spacing: -.045em; line-height: 1; }
p  { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
/* 폼 요소는 두지 않으면 브라우저 기본 UI 폰트로 빠집니다 */
button, input, select, textarea { font-family: inherit; }

/* 일본어 자형은 따로 받습니다 — 이유는 css/tokens.css 의 --font-ja 주석에.
   html[lang="ja"] 가 아니라 :lang(ja) 를 쓰는 것은, 영어 화면에 남아 있는
   언어 전환 버튼의 「日本語」 조각까지 같이 잡아 주기 때문입니다.
   위 폼 요소 규칙보다 뒤에 두어야 버튼 안 글자에도 적용됩니다. */
:lang(ja) { font-family: var(--font-ja); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.skip-link {
  position: absolute; left: 50%; top: -100px; transform: translateX(-50%);
  z-index: 200; padding: 12px 20px; background: var(--ink); color: #fff;
  border-radius: 0 0 10px 10px; transition: top .2s;
}
.skip-link:focus { top: 0; }

/* 화면에서는 감추고 스크린리더에만 읽히는 글씨 */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.page {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: clamp(20px, 4vw, 46px) clamp(16px, 3vw, 28px) 56px;
}

/* ─────────── 언어 전환 ─────────── */
.topbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 14px;
}

.lang {
  display: flex;
  gap: 3px;
  padding: 5px;
  background: var(--tile);
  border: 1px solid var(--line);
  border-radius: 999px;
  box-shadow: 0 8px 22px -16px rgba(25, 23, 19, .45);
}

.lang__btn {
  appearance: none;
  -webkit-appearance: none;
  border: 0;
  cursor: pointer;
  padding: 7px 16px;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -.01em;
  line-height: 1;
  transition: background .18s, color .18s;
}
.lang__btn:hover { background: var(--paper); color: var(--ink); }
.lang__btn[aria-pressed="true"] { background: var(--ink); color: #fff; }

/* ─────────── 벤토 그리드 ─────────── */
.bento {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--gap);
}

.tile {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 26px 28px;
  background: var(--tile);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: transform .3s var(--ease), box-shadow .3s, border-color .3s;
}
/* [hidden] 이 display:grid/flex 에 지지 않도록 */
[hidden] { display: none !important; }

/* 링크·버튼 역할을 하는 타일만 살짝 떠오르게 */
a.tile:hover,
button.tile:hover {
  transform: translateY(-3px);
  box-shadow: 0 14px 34px -18px rgba(25, 23, 19, .40);
  border-color: #d5cec0;
}

.tile__label {
  margin-bottom: 16px;
  font-size: 11.5px; font-weight: 700;
  letter-spacing: .15em; text-transform: uppercase;
  color: var(--faint);
}

/* ── 이름 타일 ── */
.tile--hero {
  grid-column: span 2;
  grid-row: span 2;
  justify-content: center;
  padding: 40px 38px;
  background:
    radial-gradient(120% 120% at 100% 0%, var(--accent-bg) 0%, transparent 55%),
    var(--tile);
}
.hero__name {
  font-size: clamp(52px, 8vw, 92px);
  margin-bottom: 24px;
}
/* 같은 크기라도 라틴·가타카나 이름은 한글보다 훨씬 넓어져 타일을 넘칩니다.
   언어별로 상한만 낮춰 한 줄에 들어오게 합니다. */
html[lang="en"] .hero__name { font-size: clamp(44px, 5.6vw, 64px); }
html[lang="ja"] .hero__name { font-size: clamp(38px, 5vw, 58px); }
.hero__line {
  font-size: clamp(17px, 2vw, 21px);
  font-weight: 600;
  letter-spacing: -.02em;
  line-height: 1.5;
}
.hero__sub {
  margin-top: 16px;
  font-size: 15px;
  color: var(--muted);
}
.hero__sub em {
  font-style: normal;
  color: var(--accent);
  font-weight: 600;
}

/* ── 지금 ── */
.tile--now { grid-column: span 2; }
.now__state {
  display: flex; align-items: center; gap: 10px;
  font-size: 17px; font-weight: 700; letter-spacing: -.02em;
}
.dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: #16a34a;
  box-shadow: 0 0 0 0 rgba(22, 163, 74, .5);
  animation: pulse 2.4s infinite;
  flex: none;
}
@keyframes pulse {
  70%  { box-shadow: 0 0 0 10px rgba(22, 163, 74, 0); }
  100% { box-shadow: 0 0 0 0  rgba(22, 163, 74, 0); }
}
.now__desc { margin-top: 12px; font-size: 14.5px; color: var(--muted); }

/* ── 위치 ── */
.tile--loc { justify-content: flex-start; }
.loc__city {
  font-size: 28px; font-weight: 800; letter-spacing: -.035em; line-height: 1.1;
}
.loc__time {
  margin-top: 6px;
  font-size: 14px; font-weight: 600; color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* ── 경력 ── */
.exp__num {
  font-size: 44px; font-weight: 800; letter-spacing: -.05em; line-height: 1;
  color: var(--accent);
}
.exp__unit {
  font-size: 19px; font-weight: 700; letter-spacing: -.02em;
  margin-left: 3px; color: var(--ink);
}
.exp__desc { margin-top: 8px; font-size: 14px; color: var(--muted); }

/* ── 로고 띠 ── */
.tile--stack { grid-column: span 4; overflow: hidden; }

.stack__head {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 6px;
  margin-bottom: 16px;
}
.stack__head .tile__label { margin-bottom: 0; }

/* 라벨 옆 셰브런 하나 — 글씨는 sr-only 로 남겨 스크린리더에만 읽힙니다 */
.stack__toggle {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none;
  appearance: none; -webkit-appearance: none;
  width: 24px; height: 24px;
  margin: 0; padding: 0;
  background: none;
  border: 0;
  border-radius: 999px;
  color: var(--faint);
  cursor: pointer;
  transition: color .18s, background .18s;
}
.stack__toggle:hover,
.stack__toggle:focus-visible { color: var(--ink); background: var(--paper); }
.stack__chev { display: inline-flex; transition: transform .28s var(--ease); }
.stack__toggle[aria-expanded="true"] .stack__chev { transform: rotate(180deg); }

/* 펼친 전체 목록 */
.stack-all {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 10px;
  animation: stackIn .28s var(--ease) both;
}
.stack-all li {
  display: flex; align-items: center; gap: 9px;
  padding: 11px 13px;
  background: var(--paper);
  border-radius: 12px;
  font-size: 13.5px; font-weight: 600;
}
.stack-all img { width: 21px; height: 21px; object-fit: contain; flex: none; }

@keyframes stackIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

.marquee {
  overflow: hidden;
  /* 양 끝을 부드럽게 사라지게 */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}
/* 아이콘 사이 간격은 --marq-gap 한 곳에서만 정합니다.
   아래 @keyframes slide 가 이 값을 그대로 다시 쓰기 때문입니다. */
.marquee__track {
  --marq-gap: 46px;
  display: flex;
  align-items: center;
  gap: var(--marq-gap);
  width: max-content;
  animation: slide 38s linear infinite;
}
.marquee:hover .marquee__track { animation-play-state: paused; }

/* 왜 -50% 로는 안 되는가 —
   gap 은 항목 "사이"에만 들어가고 마지막 뒤에는 안 붙습니다.
   24개를 복제해 48개가 되면 간격은 48개가 아니라 47개입니다.
   그래서 띠 전체 너비의 절반은 진짜 한 바퀴보다 간격의 절반만큼 짧고,
   그대로 두면 한 바퀴 돌 때마다 그만큼(46px 기준 23px) 옆으로 툭 튑니다.
   모자란 절반을 여기서 더 밀어 주면 이음매가 정확히 맞습니다. */
@keyframes slide { to { transform: translateX(calc(-50% - var(--marq-gap) / 2)); } }

.marquee__track img {
  width: 38px; height: 38px;
  object-fit: contain;
  filter: grayscale(1);
  opacity: .55;
  transition: filter .25s, opacity .25s, transform .25s var(--ease);
}
.marquee__track img.is-thin { width: 46px; height: 46px; }
.marquee__track img:hover {
  filter: none;
  opacity: 1;
  transform: scale(1.22);
}

/* ── 주력 스택 ── */
.tile--focus { grid-column: span 2; }
.focus {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}
.focus li {
  display: flex; align-items: center; gap: 9px;
  padding: 11px 13px;
  background: var(--paper);
  border-radius: 12px;
  font-size: 13.5px; font-weight: 600;
}
.focus img { width: 21px; height: 21px; object-fit: contain; flex: none; }

/* ── 이메일 (index.html 전용 — 클릭하면 주소가 복사되는 어두운 카드) ──
   .mail 은 색과 버튼 초기화만 맡습니다. 자리·여백은 .tile .tile--mail 이 붙입니다.
   .tile 뒤에 와야 어두운 배경이 타일 배경을 덮습니다. */
.mail {
  background: var(--dark);
  border: 1px solid var(--dark);
  color: #fff;
  /* button 기본 모양 제거 */
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  text-align: left;
  font: inherit;
  cursor: pointer;
}
.mail:active { transform: translateY(-1px); }
.mail:hover { border-color: var(--dark); }

.mail__label {
  margin-bottom: 9px;
  font-size: 11.5px; font-weight: 700;
  letter-spacing: .15em; text-transform: uppercase;
  color: rgba(255, 255, 255, .55);
}
.mail__addr {
  font-size: clamp(20px, 2.6vw, 29px);
  /* 큰 글자 한 줄이라 본문 줄간격(body 의 1.65)을 그대로 쓰면
     글자 위아래로 10px 씩 빈 공간이 생깁니다. 제목처럼 좁혀 줍니다. */
  line-height: 1.15;
  font-weight: 800; letter-spacing: -.035em;
  word-break: break-all;
}
.mail__hint {
  display: flex; align-items: center; gap: 8px;
  margin-top: 9px;
  font-size: 13.5px; color: rgba(255, 255, 255, .62);
  transition: color .2s;
}
.copy-ico {
  display: inline-flex; flex: none;
  opacity: .75;
  transition: opacity .2s, transform .25s var(--ease);
}
.mail:hover .copy-ico { opacity: 1; transform: translateY(-1px); }

/* 복사 직후 2초간 */
.is-copied .mail__hint { color: #6ee7a8; }
.is-copied .copy-ico { opacity: 1; }

/* 홈에서의 자리 — .tile 기본 여백(26px)보다 위아래를 조금 줄여
   옆의 링크 타일과 높이를 맞춥니다. approach.html 의 카드는 해당 없습니다. */
.tile--mail {
  grid-column: span 2;
  justify-content: center;
  padding: 21px 28px;
}
.arrow { display: inline-block; transition: transform .25s var(--ease); }
a.tile:hover .arrow,
button.tile:hover .arrow { transform: translateX(5px); }

/* ── 상세 페이지 타일 ── */
/* 주력 스택과 한 줄을 나눠 씁니다 (2 + 2). 통짜 4칸 줄이 연달아 오지 않게 하려는 것입니다. */
.tile--approach {
  grid-column: span 2;
  flex-direction: row;
  align-items: center;
  gap: 18px;
  padding: 24px 28px;
  background:
    radial-gradient(80% 240% at 0% 50%, var(--accent-bg) 0%, transparent 62%),
    var(--tile);
}
.approach__body { flex: 1; min-width: 0; }
.approach__title {
  font-size: 18px; font-weight: 800; letter-spacing: -.03em;
}
.approach__desc {
  margin-top: 4px;
  font-size: 14px; color: var(--muted);
}
.tile--approach .arrow { flex: none; color: var(--accent); font-size: 18px; }

/* ── 링크 타일 ── */
/* 윗줄(.link__head)에 아이콘·이름·화살표가 한 줄로 서고, 아랫줄(.link__desc)에 설명이 붙습니다.
   글씨 크기·굵기를 타일이 아니라 윗줄에 걸어 둔 이유: 타일에 걸면 설명까지 굵어집니다. */
.tile--link {
  /* 1칸씩 — My Apps·GitHub 두 개가 나란히 섭니다 (데스크톱에선 옆의 Email 2칸과 한 줄) */
  justify-content: center;
  gap: 9px;
  padding: 25px 24px;
}
.link__head {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 15.5px; font-weight: 700; letter-spacing: -.01em;
}
.tile--link img { width: 26px; height: 26px; object-fit: contain; flex: none; }
.tile--link .arrow { margin-left: auto; color: var(--faint); }
.link__desc { font-size: 13px; line-height: 1.55; color: var(--muted); }

/* ─────────── 푸터 ─────────── */
.foot {
  margin-top: 34px;
  text-align: center;
  font-size: 13px;
  color: var(--faint);
}

/* ─────────── 반응형 ─────────── */
@media (max-width: 900px) {
  .bento { grid-template-columns: repeat(2, 1fr); }
  .tile--hero  { grid-column: span 2; grid-row: auto; padding: 34px 28px; }
  .tile--now,
  .tile--focus,
  .tile--mail,
  .tile--approach { grid-column: span 2; }
  .tile--stack  { grid-column: span 2; }
  /* 칩 3열은 데스크톱과 같습니다 — 2열로 두면 칩 하나가 393px 이 되어
     같은 화면의 스택 목록(191px)보다 두 배로 넓어집니다. 560px 이하에서 2열로 접힙니다. */
  .focus { grid-template-columns: repeat(3, 1fr); }
  .stack-all { grid-template-columns: repeat(4, 1fr); }
}

@media (max-width: 560px) {
  :root { --gap: 12px; --radius: 18px; }
  .page { padding-bottom: 48px; }
  .bento { grid-template-columns: 1fr; }
  .tile { padding: 22px 22px; }
  .tile--hero,
  .tile--now,
  .tile--loc,
  .tile--exp,
  .tile--stack,
  .tile--focus,
  .tile--mail,
  .tile--approach,
  .tile--link { grid-column: span 1; }
  /* 위 900px 블록의 3열이 여기까지 내려오면 칩이 86px 이 되어 글자가 넘칩니다 */
  .focus { grid-template-columns: repeat(2, 1fr); }
  /* gap 이 아니라 --marq-gap 을 바꿉니다 — 이음매 보정이 같이 따라옵니다 */
  .marquee__track { --marq-gap: 34px; }
  .marquee__track img { width: 32px; height: 32px; }
  .stack-all { grid-template-columns: repeat(2, 1fr); gap: 8px; }
  .stack-all li { padding: 10px 11px; font-size: 12.5px; gap: 7px; }
  .stack__toggle { width: 28px; height: 28px; }
}

/* ─────────── 모션 최소화 ─────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  /* 흐르는 띠 대신 줄바꿈해서 전부 보여준다 */
  .marquee { -webkit-mask-image: none; mask-image: none; }
  .marquee__track { flex-wrap: wrap; width: auto; gap: 26px; }
}
