/*
 * 사이트 CSS 한 장. 프레임워크가 없으니 스코프도 없습니다 —
 * 클래스 접두로 가릅니다: m- 메인 · p- 포트폴리오 · b- 블로그. 공용은 접두 없이.
 */
:root {
  color-scheme: light;

  --bg:     #ffffff;
  --bg-2:   #f7f8f9;
  --fg:     #0b0d10;
  --fg-2:   #424952;
  /* 흐린 글자. 이 사이트가 쓰던 값입니다 — 흰 배경에서 3.89:1 이라 본문 기준(4.5:1)에는
     미달합니다. template 기본값은 #6a7078(5.00:1)이고, 대비를 올리려면 그 값으로 바꾸면 됩니다.
     여기 값이 보이는 곳은 code 모드 화면(홈·작업)뿐입니다 — 블로그처럼 템플릿이 그리는
     화면은 굽기의 `themeStyle` 이 `mutedOn()` 으로 4.5:1 을 넘는 값을 계산해 덮습니다. */
  --fg-3:   #7a828d;
  --line:   #e3e6ea;
  --line-2: #f0f2f4;
  /* 포인트는 하나만. 조사한 사이트들이 전부 한 색으로 버팁니다.
     먹빛 남색 — 흰 배경 대비 10.03:1. 본문 기준선(4.5)에 겨우 걸치던
     파랑(#2f6df6, 4.53:1)보다 두 배 넘게 또렷합니다. */
  --accent: #25436b;

  /* 표제와 본문을 나눕니다 — Paperlogy 는 굵은 한 벌이라 제목 전용입니다.
     이 둘은 site.config.mjs 의 theme.display/theme.body 와 같아야 합니다. 굽기는 블로그처럼
     템플릿이 그리는 화면에 그 설정값으로 --display/--sans 를 내므로, 어긋나면 code 모드
     화면(홈·작업)과 블로그의 글꼴이 갈립니다. */
  --display: Paperlogy, -apple-system, system-ui, sans-serif;
  --sans: NanumBarunGothic, -apple-system, BlinkMacSystemFont, system-ui, 'Apple SD Gothic Neo', sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;

  /* 본문 폭 — 관리자에서 고르면 굽기가 `--body-w` 를 덮어씁니다.
     여기 값은 site.config.mjs 의 theme.bodyWidth 와 같아야 합니다 — 어긋나면
     아무것도 안 고른 사이트가 처음 뜰 때 말없이 다른 폭으로 나옵니다.
     (여기 있던 `--max: 1180px` 는 부르는 곳이 한 군데도 없던 죽은 값이라 걷어냈습니다) */
  --body-w: 1240px;
  --pad: clamp(1.25rem, 4vw, 2.5rem);

  /* 0.15~0.22s. 그 이상은 굼떠 보입니다 */
  --t: 0.18s cubic-bezier(0.2, 0.9, 0.2, 1);
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}



/*
 * 본문·표제 = Pretendard Variable. 선언은 `/assets/fonts.css` 에 있고, 그 파일은 npm 의
 * `pretendard` 패키지에서 `tools/sync-vendor.mjs` 가 만듭니다. 92벌로 잘려 있고
 * `unicode-range` 가 붙어 있어 화면에 실제로 나온 글자의 조각만 내려옵니다.
 * 가변 글꼴이라 한 벌이 굵기 45~920 을 다 덮어, 표제도 본문도 같은 글꼴에 font-weight 만 다릅니다.
 *
 * 글꼴은 npm 패키지에서만 옵니다 — 공개 템플릿이라 글꼴을 같이 싣는 것은 재배포이고,
 * npm 패키지는 LICENSE 를 같이 주므로 그 조건을 지킬 수 있습니다.
 * 직접 받은 글꼴은 `public/assets/fonts.local.css` 를 읽으세요.
 */


/*
 * 고정폭 = JetBrains Mono(라틴) + 나눔고딕코딩(한글). 선언은 `/assets/fonts.css` 에 있습니다.
 * 400·700 두 벌뿐입니다 — 여기서 500·600 을 선언하면 `fonts.css` 가 안 부르는 파일이라
 * 출처가 기록되지 않고, 재배포 근거가 없는 글꼴은 안 싣는다는 규칙에 걸립니다.
 * 브라우저가 500→400, 600→700 으로 고르므로 두 벌로도 보이는 것은 같습니다.
 */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.7;
  /* 한글은 단어 중간에서 끊기면 읽는 리듬이 깨집니다 */
  word-break: keep-all;
  overflow-wrap: anywhere;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; }

/* ══ 메인 ══════════════════════════════════════════════
   왼쪽에 문구, 오른쪽에 새싹. 가운데 좁은 칼럼에 모으지 않고 화면 폭을 씁니다.
   이름과 직무 나열은 왼쪽 위 구석에 작게 — 표제가 주인공이어야 합니다. */
body { overflow-x: hidden; }

.m-page {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  align-items: center;
  gap: clamp(1.5rem, 4vw, 4rem);
  padding: clamp(2.5rem, 6vh, 4.5rem) clamp(1.5rem, 6vw, 6rem);
}

/* 이름·직무 — 절대배치로 구석에 박습니다. 흐름에 넣으면 표제를 밀어냅니다 */
.m-id {
  position: absolute;
  top: clamp(2rem, 5vh, 3.5rem); left: clamp(1.5rem, 6vw, 6rem);
  margin: 0;
}
.m-name { margin: 0; font-size: 0.95rem; font-weight: 600; letter-spacing: -0.01em; }
.m-roles {
  margin: 0.35rem 0 0; font-size: 0.76rem; color: var(--fg-3);
  letter-spacing: 0.14em;
}

.m-copy { position: relative; z-index: 1; }
.m-lines { margin: 0; }

.m-line {
  display: block;
  /* 받침·디센더가 잘리지 않게. 음수 마진으로 줄 높이는 그대로 둡니다 */
  padding-block: 0.08em; margin-block: -0.08em;
}
.m-line > span { display: block; }

/* 두 줄의 크기와 굵기를 벌려야 첫 줄이 먼저 읽힙니다 */
.m-l1 {
  font-size: clamp(2.6rem, 7.2vw, 7rem);
  font-weight: 800; line-height: 1.15; letter-spacing: -0.035em;
}
.m-l2 {
  margin-top: 0.15em;
  font-size: clamp(1.4rem, 3.6vw, 3.2rem);
  font-weight: 500; line-height: 1.3; letter-spacing: -0.03em;
  color: var(--fg-2);
}


/* 알약 버튼이 아니라 텍스트 링크 + 밑줄 — 조사한 개발자 사이트들의 방식 */
.m-links { display: flex; flex-wrap: wrap; gap: clamp(1.5rem, 3vw, 2.75rem); margin-top: clamp(2.25rem, 5vh, 3.5rem); }
.m-links a {
  display: inline-flex; align-items: center; gap: 0.6rem;
  font-size: 1rem; text-decoration: none; color: var(--fg);
  padding-bottom: 0.5rem; border-bottom: 1px solid var(--line);
  transition: border-color var(--t), color var(--t);
}
.m-links a svg { flex: none; transition: transform var(--t); }
.m-links a:hover { border-color: var(--fg); }
.m-links a:hover svg { transform: translateX(0.3rem); }

.m-scene { margin: 0; justify-self: center; width: min(100%, 15rem); }
.m-scene svg { display: block; width: 100%; height: auto; }


/* ── 폰 ───────────────────────────────────────────────
   시안 구성 그대로. 데스크톱은 좌우 두 칸이지만 폰은 위아래 네 칸입니다:
   이름 · 표제 · 새싹(가운데) · 링크(바닥).

   `.m-copy` 를 display:contents 로 풀어 h1 과 nav 를 부모 그리드의 직접 자식으로
   만듭니다. 그래야 그 둘 사이에 새싹을 끼워 넣을 수 있습니다 — 마크업은 안 건드리고. */
@media (max-width: 860px) {
  .m-page {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto 1fr auto;
    align-items: stretch;
    align-content: stretch;
    gap: 0;
    padding: clamp(1.75rem, 4.5vh, 2.75rem) 1.5rem clamp(1.75rem, 4.5vh, 3rem);
  }
  .m-copy { display: contents; }
  /* 흐름 안으로 되돌립니다. 절대배치로 두면 나머지가 세로 가운데로 몰려
     이름과 표제 사이에 200px 짜리 빈칸이 생깁니다(390x844 에서 실측). */
  .m-id    { position: static; grid-row: 1; }
  .m-lines { grid-row: 2; margin-top: clamp(1.75rem, 5vh, 3rem); }
  .m-scene { grid-row: 3; }
  .m-links { grid-row: 4; }

  /* 폰에서는 vw 가 기준입니다. 고정 하한만 두면 화면이 넓어져도 글자가 안 큽니다 */
  .m-l1 { font-size: clamp(2.9rem, 12.5vw, 4.25rem); }
  .m-l2 { font-size: clamp(1.2rem, 5.4vw, 1.7rem); }

  /* 남는 높이는 새싹 칸(1fr)이 가져갑니다. 화면이 길든 짧든 빈칸이 한 군데로 모입니다 */
  .m-scene { width: min(100%, 14rem); justify-self: center; align-self: center; }

  /* 가로로 붙이지 않고 행으로 쌓습니다. 밑줄은 시안대로 글자 폭만큼만.
     위아래 여백을 줘서 손가락이 닿는 높이(44px 이상)를 만듭니다. */
  .m-links {
    display: flex; flex-direction: column; align-items: flex-start;
    gap: 0.75rem; margin-top: clamp(1.5rem, 4vh, 2.5rem);
  }
  .m-links a { font-size: 1.05rem; padding: 0.6rem 0 0.55rem; }
}
.m-scene[hidden] { display: none; }

/* ── 그리기·써지기 ────────────────────────────────────
   기본 CSS 가 최종 상태입니다. 애니메이션은 no-preference 안쪽에만 둡니다 —
   반대로 짜면 모션을 끈 사람에게 빈 화면이 나갑니다. */
.m-draw path { stroke-dasharray: 1; stroke-dashoffset: 0; }
/* 지면선은 아주 얇게. `non-scaling-stroke` 라 뷰박스 배율과 무관하게 0.8px 로 그려지고,
   대시도 화면 픽셀로 잡힙니다 — 안마다 뷰박스 폭이 달라 유닛으로 주면 굵기가 갈립니다. */
.m-ground { stroke: var(--line); stroke-width: 0.8; stroke-dasharray: 3 4; }
/* 잎 외곽선만 한 단계 연하게. 줄기는 본문색 그대로 둬서 그림의 중심이 흐려지지 않게 합니다 */
.s-leaf { stroke: #5b636e; }
/* 모션을 끈 사람에게 나가는 최종 상태 — 칠이 다 된 그림 */
.m-wash > * { opacity: 1; }
/* 번짐은 제 가운데서 퍼집니다. 도형마다 제 박스를 쓰도록 fill-box */
.m-w { transform-box: fill-box; transform-origin: center; }

@media (prefers-reduced-motion: no-preference) {
  /* 표제와 이름은 애니메이션 없이 바로 보입니다 — 읽을 것이 먼저 있어야 합니다.
     그려지는 것은 새싹뿐이고, 링크만 뒤따라 뜹니다. */
  .play .m-links { animation: m-fade 0.6s var(--ease) 0.75s both; }

  /* 지면 → 줄기 → 잎. 점선은 대시 패턴이 따로 있어 불투명도로만 냅니다 */
  .play .m-ground { animation: m-fade-in 0.9s ease-out 0.4s both; }
  .play .s-d      { animation: m-draw 0.55s ease-out both; animation-delay: calc(0.85s + var(--d) * 0.42s); }

  /* 선이 1.9s 에 다 그려집니다. 2.3s 에 시작하면 0.4s 가 비어 끊겨 보였습니다 */
  .play .m-w { animation: m-bleed 1.5s cubic-bezier(0.22, 1, 0.36, 1) both; animation-delay: calc(1.95s + var(--w) * 0.55s); }
}

@keyframes m-fade    { from { opacity: 0; transform: translateY(0.6rem); } }
@keyframes m-fade-in { from { opacity: 0; } }
/*
 * 선이 나타나기 전에는 투명하게 둡니다. `stroke-linecap: round` 가 길이 0인 대시에도
 * 둥근 마개를 그려서, 아직 안 그려진 선마다 점이 하나씩 찍힙니다 — 별자리처럼 보였습니다.
 */
@keyframes m-draw {
  from { stroke-dashoffset: 1; opacity: 0; }
  6%   { opacity: 1; }
  to   { stroke-dashoffset: 0; opacity: 1; }
}
/* 번짐 — 작게 시작해 퍼지며 진해집니다. blur 필터는 픽셀 면적에 비례해 비싸서 안 씁니다 */
@keyframes m-bleed { from { opacity: 0; transform: scale(0.45); } }


/* ══ 공용 껍데기 ═══════════════════════════════════════
   메인은 껍데기가 없습니다(화면 전체가 한 장입니다). 포트폴리오·블로그만 씁니다. */
/**
 * 본문 폭은 `--body-w` 하나가 정합니다(관리자 「공통 → 콘텐츠」, 굽기의 `themeStyle`).
 * 「화면 폭」을 고르면 그 값이 `none` 으로 나가 제한이 통째로 풀립니다. 헤더만 제 스위치를
 * 갖습니다(`.s-head.s-w-wide`, templates/header.css).
 *
 * 폭에 `--w` 를 쓰지 않습니다 — `pages/main.html` 의 잎이 같은 이름을 애니메이션 지연으로
 * 쓰는데 폴백이 없어, `:root` 에 길이가 들어오면 `calc(1.95s + 1240px * 0.55s)` 가 되어
 * 애니메이션이 조용히 안 돕니다.
 */
.wrap { max-width: var(--body-w, 1240px); margin: 0 auto; padding-inline: clamp(1.5rem, 5vw, 2.5rem); }

.s-head {
  position: sticky; top: 0; z-index: 10;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(8px);
  border-bottom: 1px solid var(--line-2);
}
.s-head > div { display: flex; align-items: center; justify-content: space-between; height: 66px; }
/* 글자 크기 — `--hd-size`(공통>헤더의 knob, 기본 1)가 셋을 같이 움직입니다:
   여기, 아래의 `.s-nav a`, 그리고 드로어의 링크(`templates/header.css`). 따로 두면 어긋납니다 */
.s-name { font-weight: 700; font-size: calc(1.05rem * var(--hd-size, 1)); letter-spacing: -0.02em; text-decoration: none; }
/* 글·작업 상세에서는 이름 자리가 곧 「돌아갈 곳」입니다 — `.s-name` 을 대체합니다.
   자리·크기·무게를 그대로 물려받아 헤더의 리듬이 안 흔들립니다.
   블로그 전용이 아니라 여기(공용) 에 둡니다 — 작업 상세는 blog.css 를 안 싣습니다.
   화살표와 글자 사이는 공백 한 칸(≈4px)이 너무 좁습니다. gap 으로 벌려 둘이 따로 보이게 합니다. */
.s-name.s-back { white-space: nowrap; display: inline-flex; align-items: baseline; gap: .5rem; }
.s-nav { display: flex; gap: clamp(1rem, 3vw, 2rem); }
.s-nav a {
  /* 한글 라벨이라 모노를 쓰지 않습니다 — 모노엔 한글이 없어 그 글자만 딴 글꼴로 떨어집니다.
     색은 --fg-2 다. --fg-3 은 흰 배경에서 대비 3.89:1 로, 14px 일반 문자 기준(4.5:1)에 미달합니다. */
  font-size: calc(0.96rem * var(--hd-size, 1)); font-weight: 500; letter-spacing: -0.01em;
  color: var(--fg-2); text-decoration: none; transition: color var(--t);
}
.s-nav a:hover { color: var(--fg); }
/* 지금 보고 있는 곳은 굵기까지 올립니다 — 색 하나로는 약합니다 */
.s-nav a[aria-current='page'] { color: var(--fg); font-weight: 700; }
/* 어느 화면에 있는지 — 색만으로는 약해서 점을 찍습니다 */
.s-nav a[aria-current='page']::before { content: '// '; font-family: var(--mono); font-size: 0.8em; color: var(--fg-3); }

/* 문단 바로가기 — 포트폴리오에만 있습니다. 이름과 사이트 내비 사이 남는 공간 가운데에 둡니다.
   라벨이 전부 영문이라 모노를 씁니다(절 번호 라벨과 같은 결). 한글이 섞이면 모노를 쓰면 안 됩니다. */
.s-jump { display: flex; flex: 1; justify-content: center; gap: clamp(0.85rem, 2.1vw, 1.9rem); }
.s-jump a {
  font-family: var(--mono); font-size: 0.86rem; font-weight: 500; white-space: nowrap;
  color: var(--fg-2); text-decoration: none; transition: color var(--t);
}
.s-jump a:hover { color: var(--fg); }

/* 좁은 화면에서는 한 줄에 다 못 들어갑니다(407px 에서 445px 까지 뻗어 가로 스크롤이 생겼습니다).
   둘째 줄로 내리고 그 줄만 옆으로 밀어 보게 합니다. */
@media (max-width: 1080px) {
  .s-head > div { flex-wrap: wrap; height: auto; padding-top: 0.8rem; }
  .s-name { order: 1; }
  .s-nav  { order: 2; }
  .s-jump {
    order: 3; flex: 0 0 100%; justify-content: flex-start;
    gap: 1.15rem; padding: 0.75rem 0 0.7rem;
    overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
  }
  .s-jump::-webkit-scrollbar { display: none; }
}

/* 헤더가 sticky 라, 앵커로 뛰면 절 제목이 헤더 밑에 깔립니다.
   좁은 화면은 내비가 둘째 줄로 내려가 헤더가 66 → 89px 로 높아집니다 */
.p-sec, .p-contact { scroll-margin-top: 84px; }
@media (max-width: 1080px) { .p-sec, .p-contact { scroll-margin-top: 106px; } }
/* 첫 절은 위에 헤더가 붙어 있어 9vh(407px 화면에서 76px)가 빈칸으로 남습니다 */
@media (max-width: 1080px) { .p-sec:first-of-type { padding-top: 2rem; } }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }

.s-foot {
  margin-top: clamp(2.5rem, 6vh, 4rem); border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; gap: 0.75rem 1.5rem; justify-content: space-between;
  padding: 1.75rem 0 2.5rem;
  font-size: 0.8rem; color: var(--fg-2);
}
.s-foot a { color: inherit; text-decoration: none; }
.s-foot a:hover { color: var(--fg); }


/* ══ 포트폴리오 ════════════════════════════════════════
   뼈대는 yjyoon.dev 를 실측해 옮겼습니다:
   컨테이너 1100 · 절 간격 96 · 제목 칸 280 + gap 56 · 설명 max 640 · 기간 칸 140.
   색과 활자는 우리 것입니다 — 그쪽은 다크에 네이버 녹색입니다. */
.p-sec { padding-block: clamp(3.5rem, 9vh, 6rem); border-top: 1px solid var(--line); }
.p-sec:first-of-type { border-top: 0; }

/* 설명은 번호가 아니라 제목과 같은 행에서 시작합니다.
   번호·제목을 감싼 div 를 display:contents 로 풀어 셋을 직접 배치합니다. */
.p-head {
  display: grid; grid-template-columns: 320px minmax(0, 1fr);
  grid-template-rows: auto auto; gap: 0 56px;
  /* 절 머리와 첫 덩어리 사이 — 좁으면 제목이 내용에 붙어 절이 안 갈립니다 */
  align-items: start; margin-bottom: clamp(4.5rem, 9vh, 7.5rem);
}
.p-head > div:first-child { display: contents; }
.p-num { grid-column: 1; grid-row: 1; }
.p-head h2 { grid-column: 1; grid-row: 2; }
/* 표제·이름은 Paperlogy(800). 굵기를 따로 안 줘도 굵습니다 */
.p-head h2, .p-co-name, .p-tl-title, .b-top h1, .m-l1, .m-l2 { font-family: var(--display); }
/* 설명은 제목에 세로 가운데로 맞춥니다 — 한 줄일 때 위에 붙으면 제목만 아래로 처집니다.
   소개 절의 긴 블록(.p-about)은 예외입니다. 가운데로 맞추면 제목이 한복판에 뜹니다. */
.p-lead, .p-about { grid-column: 2; grid-row: 2; }
.p-lead  { align-self: center; }
.p-steps { grid-column: 1; grid-row: 3; }
.p-head:has(.p-steps) .p-about { grid-row: 2 / span 2; }
.p-about { align-self: start; }
/* 위계를 만드는 것은 제목 크기가 아니라 모노로 찍은 번호입니다 */
.p-num {
  display: block; margin-bottom: 0.7rem;
  font-family: var(--mono); font-size: 0.86rem; font-weight: 600; letter-spacing: 0.06em;
  color: var(--fg-3);
}
.p-num b { color: var(--fg); font-weight: 700; }
.p-head h2 { position: relative; margin: 0; padding-left: 0.5em;
             font-size: clamp(2.1rem, 4vw, 3rem); font-weight: 800; letter-spacing: -0.035em; line-height: 1.2; }
/* 절 제목 앞 세로 바. em 으로 잡아 제목이 커지고 작아질 때 두께·높이·간격이 같이 따라갑니다 */
.p-head h2::before {
  content: ''; position: absolute; left: 0; top: 0.14em; bottom: 0.14em;
  width: 0.18em; background: #000;
}
.p-lead { margin: 0; max-width: 680px; font-size: 1.08rem; line-height: 1.65; color: var(--fg-2); }

/* 경력·활동 행 — 기간은 고정폭 모노라 자릿수가 맞아야 열이 안 흔들립니다 */
.p-rows { list-style: none; margin: 0; padding: 0; }
.p-row {
  display: grid; grid-template-columns: 140px minmax(0, 1fr); gap: 32px;
  border-top: 1px solid var(--line); padding: 28px 0;
}
.p-when { font-family: var(--mono); font-size: 0.82rem; color: var(--fg-3); font-variant-numeric: tabular-nums; }
.p-what { margin: 0; font-size: 1.05rem; font-weight: 700; letter-spacing: -0.02em; display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: baseline; }
.p-what .org { font-weight: 400; color: var(--fg-3); font-size: 0.95rem; }
.p-note { margin: 0.55rem 0 0; color: var(--fg-2); line-height: 1.75; }
/* 목록(내용)과 기술 태그는 성격이 다릅니다 — 여기만 크게 벌립니다 */
.p-tags { margin: 2.1rem 0 0; display: flex; flex-wrap: wrap; gap: 0.45rem; }
.p-tags span {
  font-size: 0.86rem; color: var(--fg-3);
  border: 1px solid var(--line); border-radius: 999px; padding: 0.26rem 0.72rem;
}

.p-more { font-size: 0.85rem; color: var(--fg-3); text-decoration: none; }
.p-more:hover { color: var(--fg); }

/* 제목 칸이 320px 고정이라 1080px 밑에서는 설명 칸이 좁아져 두 단이 안 맞습니다.
   .p-head 만 다른 절보다 먼저 접습니다 — 나머지(경력 행·격자)는 860px 까지 버팁니다. */
@media (max-width: 1080px) {
  /* 행·열 지정을 풀어야 합니다. 넓은 화면용으로 grid-row 2/3 를 못 박아 뒀는데,
     한 칸짜리 격자에서 그대로 두면 빈 행이 생기고 순서가 뒤엉킵니다. */
  .p-head {
    grid-template-columns: 1fr; grid-template-rows: none;
    display: flex; flex-direction: column; gap: 0.7rem;
    margin-bottom: clamp(2rem, 5vh, 3rem);
  }
  .p-head > div:first-child { display: contents; }
  .p-num, .p-head h2, .p-lead, .p-about, .p-steps { grid-column: auto; grid-row: auto; }
  .p-num     { order: 1; }
  .p-head h2 { order: 2; }
  .p-lead, .p-about { align-self: stretch; }
  /* 폰에서는 제목 바로 아래, 가운데. 맨 밑으로 보내면 스크롤 끝에서야 나와
     「지나온 길」이라는 뜻이 안 살고, 왼쪽 정렬하면 한쪽에 쏠립니다. */
  .p-steps   { order: 3; margin: 1.5rem auto 0.5rem; width: 220px; }
  .p-lead, .p-about { order: 4; }
  .p-steps > li { height: 64px; }
}

@media (max-width: 860px) {

  .p-row  { grid-template-columns: 1fr; gap: 0.5rem; }
  /* 소개 본문은 폭이 좁아지면 22.7px 이 과합니다 */
  .p-about p { font-size: 1.18rem; line-height: 1.75; }
}


/* ══ 블로그 ════════════════════════════════════════════
   hoseung.me 실측: 목록 폭 700 · 요약 14px · 날짜 12px 모노.
   행 사이 구분선이 0px 이었습니다 — 「너무 텍스트만 있어 지루합니다」의 정체.
   그래서 헤어라인과 대표 이미지를 더합니다. */
.b-top { padding-block: clamp(2.5rem, 6vh, 4rem) clamp(1.5rem, 4vh, 2.25rem); }
.b-top h1 { margin: 0; font-size: clamp(1.6rem, 4vw, 2.1rem); font-weight: 800; letter-spacing: -0.035em; }
/* 「5편」 — 숫자만 모노로 보이게 하려다 편 자가 딴 글꼴로 떨어집니다. 전부 산세 + 고정폭 숫자 */
.b-count { margin: 0.6rem 0 0; font-size: 0.82rem; color: var(--fg-3); font-variant-numeric: tabular-nums; }



/* ══ 경력 타임라인 ═════════════════════════════════════
   yjyoon.dev 경력 절의 장치입니다. 회사 한 덩어리 안에 세로 점선이 흐르고
   항목마다 점이 찍힙니다. 지금 있는 자리는 채운 점, 지나온 자리는 빈 점.

   평평한 행 목록으로 옮기면 「한 회사 안에서 자리를 옮겼습니다」는 정보가 사라집니다.
   그게 이 장치가 하는 일입니다 — 들여쓰기가 소속을 말합니다. */
.p-co { display: grid; grid-template-columns: 140px 64px minmax(0, 1fr); gap: 32px;
        border-top: 1px solid var(--line); padding: 44px 0; align-items: start; }
.p-head + .p-co { border-top: 0; padding-top: 0; }

.p-co-when { font-family: var(--mono); font-size: 0.88rem; line-height: 1.6; color: var(--fg-3); font-variant-numeric: tabular-nums; }
/* 회사 타일 — 128px 파일을 64px 로. 여백은 여기서 줍니다(이미지엔 안 넣습니다) */
.p-logo { width: 64px; aspect-ratio: 1; border: 1px solid var(--line); border-radius: 10px;
          display: grid; place-items: center; background: var(--bg);
          font-size: 0.72rem; font-weight: 800; letter-spacing: -0.02em; color: var(--fg-2); overflow: hidden; }
.p-logo img { width: 100%; height: 100%; object-fit: contain; padding: 7px; }
/* 면을 꽉 채우는 로고(테두리까지 색이 차는 사각형)는 여백 없이 모서리까지 */
.p-logo[data-bleed] { border-color: transparent; }
.p-logo[data-bleed] img { padding: 0; object-fit: cover; }
/* 획이 가늘어 흰 바탕에서 뜨는 로고(잉크 3%대·대비 3.7:1 수준)에만
   아주 엷은 바탕을 깝니다. 로고 색은 그대로 두면서 땅이 생겨 획이 떠오릅니다. */
.p-logo[data-tint] { background: #f4f7fa; border-color: #e6ebf1; }

/* 서비스 — 글줄 옆에 놓이는 링크. 높이만 맞추고 폭은 자유입니다.
   정사각에 가두면 가로로 긴 워드마크가 안 읽힙니다. */
/* 서비스 로고는 항목 제목 줄 안에 삽니다. 설명 아래에 따로 달면 겉돕니다 —
   시안에서 그 자리는 프로젝트 이름이 차지하고 있고, 로고가 곧 그 이름입니다. */
.p-tl-title { display: inline-flex; align-items: center; gap: 0.5rem; }
.p-tl-logo { display: block; width: auto; height: 23px; }
.p-tl-logo[data-symbol] { height: 20px; }   /* 심볼은 면이 꽉 차 무거우므로 낮춥니다 */
 /* flex gap 과 ::after 의 margin 이 둘 다 들어가면 화살표가 두 칸 밀려납니다.
    로고와 글자 사이 간격만 gap 이 맡고, 화살표는 margin 으로 붙입니다. */
.p-tl-title a { text-decoration: none; display: inline-flex; align-items: center; gap: 0.34rem;
                border-bottom: 1px solid transparent; transition: border-color var(--t); }
.p-tl-title a.p-arrow::after { margin-left: -0.06em; }
.p-tl-title a:hover { border-color: var(--line); }
/* 화살표는 글자가 아니라 SVG 다. `content:'↗'` 는 글꼴마다 모양이 다르고,
   그 글자가 없는 글꼴이면 통째로 딴 글꼴로 떨어져 굵기가 어긋납니다.
   마스크로 넣어 `currentColor` 를 그대로 따르게 합니다. */
.p-arrow::after {
  content: ''; display: inline-block; vertical-align: middle;
  width: 0.72em; height: 0.72em; margin-left: 0.16em;
  background-color: currentColor; opacity: 0.6;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17 17 7M9 7h8v8'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17 17 7M9 7h8v8'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-size: contain; mask-size: contain;
}
.p-tl-title a, .p-co-name a { /* ↗ 는 .p-arrow 가 붙은 자리에만 */ }

/* 도입처처럼 항목에 딸린 바깥 링크 — 라벨을 달아 무엇인지 밝힙니다 */
.p-refs { margin: 0.8rem 0 0; display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 1rem; }
.p-refs > b { font-family: var(--mono); font-size: 0.78rem; font-weight: 600; color: var(--fg-3); }
.p-ref { display: inline-flex; align-items: center; gap: 0.4rem; text-decoration: none;
         font-size: 0.92rem; color: var(--fg-2);
         border-bottom: 1px solid var(--line-2); transition: border-color var(--t); }
.p-ref:hover { border-color: var(--fg-3); }
.p-ref img { display: block; width: auto; height: 17px; }
.p-co-name { margin: 0 0 1.4rem; font-size: 1.75rem; font-weight: 800; letter-spacing: -0.03em; }
.p-co-name a { text-decoration: none; }

/* 지금은 다른 이름이 된 회사 — 사실을 덧붙이되 회사명보다 뒤에 둡니다 */
.p-now-at { font-size: 0.78rem; font-weight: 500; color: var(--fg-3); }
.p-now-at::before { content: '· '; }

/* 점선 한 줄이 항목 전체를 관통합니다. 마커는 그 위에 음수 왼쪽으로 얹습니다 */
.p-tl { list-style: none; margin: 0; padding: 0 0 0 1.5rem; border-left: 1px dashed var(--line); }
/* 항목 사이가 붙으면 어디까지가 한 프로젝트인지 안 보입니다 */
.p-tl > li { position: relative; padding-bottom: 2.9rem; }
.p-tl > li:last-child { padding-bottom: 0; }
/* 점은 정원이어야 합니다. flex/grid 안에서 늘어나지 않도록 aspect-ratio 로 못 박습니다 */
.p-tl > li::before {
  content: ''; position: absolute; left: calc(-1.5rem - 7px); top: 0.42rem; z-index: 1;
  width: 14px; height: 14px; aspect-ratio: 1; border-radius: 50%;
  background: var(--bg); border: 2px solid var(--line); box-sizing: border-box;
}
/* 지금 있는 자리 — 채운 점 */
.p-tl > li[data-now]::before { background: var(--accent); border-color: var(--accent); }

/* 파동 — 점 아래에서 퍼져 나가며 사라집니다. 점 자체는 안 움직입니다 */
.p-tl > li[data-now]::after {
  content: ''; position: absolute; left: calc(-1.5rem - 7px); top: 0.42rem;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--accent); opacity: 0;
}
@media (prefers-reduced-motion: no-preference) {
  .p-tl > li[data-now]::after { animation: p-pulse 1.5s cubic-bezier(0.22, 1, 0.36, 1) infinite; }
}
@keyframes p-pulse {
  0%        { transform: scale(1);   opacity: 0.42; }
  70%, 100% { transform: scale(2.8); opacity: 0; }
}

.p-tl-head { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.p-tl-title { margin: 0; font-size: 1.28rem; font-weight: 700; letter-spacing: -0.02em; }
.p-tl-when { margin-left: auto; font-family: var(--mono); font-size: 0.88rem; color: var(--fg-3); font-variant-numeric: tabular-nums; }
/* 상태 딱지 — 「현재」(포인트색)와 달리 중립. 사실을 덧붙이는 것이지 강조가 아닙니다 */
.p-tag-off {
  font-family: var(--mono); font-size: 0.74rem; color: var(--fg-3);
  border: 1px solid var(--line); border-radius: 999px; padding: 0.12rem 0.55rem; line-height: 1.6;
}
.p-badge { font-size: 0.7rem; font-weight: 600; color: var(--accent);
           border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
           border-radius: 999px; padding: 0.1rem 0.5rem; line-height: 1.6; }
/* 직무는 모노 + 포인트색. 영문이라 모노가 안전합니다 */
.p-role { margin: 0.45rem 0 0; font-family: var(--mono); font-size: 0.92rem; color: var(--accent); }
.p-tl p.p-do { margin: 0.9rem 0 0; font-size: 1.08rem; line-height: 1.65; }
.p-tl ul { list-style: none; margin: 0.6rem 0 0; padding: 0; }
.p-tl ul li { position: relative; padding-left: 1.05rem; color: var(--fg-2);
               font-size: 1.08rem; line-height: 1.6; margin-top: 0.15rem; }
.p-tl ul li:first-child { margin-top: 0; }
.p-tl ul li::before { content: '-'; position: absolute; left: 0; color: var(--fg-3); }

@media (max-width: 860px) {
  /* 로고·회사명·기간이 각각 다른 행으로 흩어지면 무엇의 기간인지 안 읽힙니다.
     `order:-1` 로 기간만 앞세우면 자동 배치가 로고를 다음 행으로 밀어내 셋이 3단이 됐습니다.
     div 를 contents 로 풀어 회사명을 직접 grid item 으로 올리고
     [로고][회사명 / 기간] 한 덩어리로 묶습니다. 타임라인만 전체 폭으로 내려갑니다. */
  .p-co { grid-template-columns: 56px minmax(0, 1fr); gap: 0 1rem; }
  .p-co > div:last-child { display: contents; }
  .p-logo    { grid-column: 1; grid-row: 1 / span 2; align-self: start; width: 56px; }
  .p-co-name { grid-column: 2; grid-row: 1; margin: 0; }
  .p-co-when { grid-column: 2; grid-row: 2; }
  .p-tl      { grid-column: 1 / -1; grid-row: 3; margin-top: 2.1rem; }
  .p-tl-when { margin-left: 0; width: 100%; }
}


/* ══ 소개 절 ═══════════════════════════════════════════
   거쳐 온 자리는 타임라인이 아니라 한 줄 흐름입니다 — 네 자리를 순서대로 지나왔다는
   사실만 말하면 되고, 각 자리에 딸린 내용은 아래 경력 절이 이미 갖고 있습니다. */
/* 나눔바른고딕은 x높이가 0.500 이라 Pretendard(0.530)와 같은 px 에서 6% 작아 보입니다.
   소개는 이 절의 주인공이라 한 단계 더 키웁니다 — 21px. */
.p-about p { margin: 0 0 1.35rem; font-size: 1.42rem; line-height: 1.78; color: var(--fg-2); }
/* 라벨(.p-tech-head)도 <p> 라 마지막 문단으로 잡힙니다 — 그걸 빼야
   라벨과 칩 사이 간격이 삽니다 */
.p-about p:last-of-type:not(.p-tech-head) { margin-bottom: 0; }
.p-about strong { font-weight: 600; color: var(--fg); }
/* 시안의 형광펜 — 밑에 깔리는 띠라 글자를 가리지 않습니다 */
/* 형광 띠 — 글자 아래쪽에만 깔려 획을 안 가립니다. 굵기까지 같이 줍니다 */
.p-hi { font-weight: 700; color: var(--fg);
        background: linear-gradient(transparent 56%, color-mix(in srgb, var(--accent) 22%, transparent) 0); }

/* ══ 발자국 ════════════════════════════════════════════
   소개 절 왼쪽 빈 칸에 세로로 내려갑니다. 좌우로 번갈아 놓고 살짝 비틉니다 — 한 줄로 곧게
   찍으면 걸음이 아니라 점선이 됩니다.

   치수는 아래 SVG(.p-trail)의 좌표와 맞물려 있어 하나를 고치면 둘 다 고쳐야 합니다:
     칸 높이 76px · 홀수 왼쪽 8px · 짝수 왼쪽 48px · 발 너비 22px
     → 발 중심 x = 19 / 59,  중심 y = 38 · 114 · 190 · 266 */
.p-steps { list-style: none; margin: 2.5rem 0 0; padding: 0; position: relative; }
.p-steps > li {
  position: relative; z-index: 1; display: flex; align-items: center; gap: 1rem;
  height: 76px; padding-left: 8px;
}
.p-steps > li:nth-of-type(even) { padding-left: 48px; }

.p-foot { flex: none; width: 22px; height: 29px; color: var(--fg-3); }
.p-foot svg { display: block; width: 100%; height: 100%; fill: currentColor; }
/* 180° 돌려 발끝을 아래로. 거기에 좌우로 살짝 더 비틉니다 */
.p-steps > li:nth-of-type(odd)  .p-foot { transform: rotate(171deg); }
.p-steps > li:nth-of-type(even) .p-foot { transform: scaleX(-1) rotate(171deg); }
.p-steps > li[data-now] .p-foot { color: var(--accent); }

/* 발자국 사이를 잇는 점선 곡선 */
.p-trail { position: absolute; left: 0; top: 0; width: 80px; height: 304px; pointer-events: none; }
.p-trail path {
  fill: none; stroke: var(--fg-3); stroke-width: 1.9;
  stroke-dasharray: 2 7; stroke-linecap: round; opacity: 0.75;
}

.p-steps b {
  font-family: var(--mono); font-size: 0.82rem; font-weight: 600; letter-spacing: 0.02em;
  color: var(--fg-2); white-space: nowrap;
}
.p-steps > li[data-now] b { color: var(--accent); font-weight: 700; }
.p-steps em {
  font-style: normal; font-size: 0.72rem; font-weight: 600; color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius: 999px; padding: 0.1rem 0.5rem;
}

/* 한 발씩 걷습니다 — 곡선이 먼저 그려지고 그 끝에 발이 찍힙니다 */
@media (prefers-reduced-motion: no-preference) {
  .p-steps > li { animation: p-step 0.42s cubic-bezier(0.22, 1, 0.36, 1) both;
                  animation-delay: calc(0.2s + var(--i) * 0.62s); }
  /* 점선은 대시 패턴이 따로 있어 dashoffset 으로는 「그려지게」 못 합니다.
     위에서 아래로 잘라 보이는 clip-path 로 걷는 방향을 냅니다. */
  .p-trail path { animation: p-trail 0.5s ease-out both;
                  animation-delay: calc(0.34s + var(--i) * 0.62s); }
  .p-steps > li[data-now] .p-foot { animation: p-foot-now 2.6s ease-out infinite;
                                    animation-delay: calc(2.4s); }
}
@keyframes p-step  { from { opacity: 0; transform: translate(-12px, -10px) scale(0.86); } }
@keyframes p-trail { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 -4% 0); } }
@keyframes p-foot-now {
  0%, 70%, 100% { opacity: 1; }
  35%           { opacity: 0.4; }
}

.p-about .p-tech-head, .p-tech-head {
  display: flex; align-items: center; gap: 0.9rem; margin: 2.75rem 0 1.75rem;
  font-family: var(--mono); font-size: 0.74rem; letter-spacing: 0.08em; color: var(--fg-3);
}
.p-tech-head::after { content: ''; flex: 1; height: 1px; background: var(--line); }
.p-techs { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem;
           grid-template-columns: repeat(auto-fill, minmax(10.5rem, 1fr)); }
.p-tech { display: flex; align-items: center; gap: 0.7rem;
          border: 1px solid var(--line); border-radius: 11px; padding: 0.85rem 1rem; }
.p-tech svg { flex: none; display: block; }
.p-tech span { font-family: var(--mono); font-size: 0.94rem; color: var(--fg); }

@media (max-width: 860px) {
  .p-techs { grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr)); }
}


/* ══ 사이드 프로젝트 격자 ═══════════════════════════════
   목록이 아니라 격자입니다. 스무 개가 넘으면 행으로 쌓는 것보다 한눈에 들어옵니다. */
.p-count { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.7rem;
           margin: 0 0 1.1rem; font-family: var(--mono); font-size: 0.86rem; color: var(--fg-3); }
.p-count b { color: var(--accent); font-weight: 700; }

.p-grid { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.7rem;
          grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); }
/* 지금은 링크가 없습니다 — 어디로도 안 가므로 hover 로 눌릴 것처럼 굴지 않습니다.
   링크가 붙으면 a 로 바꾸고 :hover 를 되살립니다. */
.p-grid > li > * {
  display: flex; align-items: center; gap: 0.75rem; height: 100%;
  border: 1px solid var(--line); border-radius: 12px; padding: 0.8rem 0.95rem;
  text-decoration: none; transition: border-color var(--t), transform var(--t);
}
.p-grid a:hover { border-color: var(--fg-3); transform: translateY(-1px); }
/* 자리표시 타일 — 글자 하나를 색 배경에 얹습니다. 실제 아이콘이 생기면 img 로 갈아끼웁니다 */
.p-ico { flex: none; width: 34px; height: 34px; aspect-ratio: 1; border-radius: 9px;
         display: grid; place-items: center; color: #fff;
         font-weight: 800; font-size: 0.95rem; letter-spacing: -0.02em; }
.p-ico img { width: 100%; height: 100%; object-fit: contain; border-radius: inherit; }
.p-grid span { font-size: 0.98rem; font-weight: 600; letter-spacing: -0.02em; color: var(--fg); }
.p-grid [data-soon] { border-style: dashed; }
.p-grid [data-soon] .p-ico { background: var(--bg-2); color: var(--fg-3); }
.p-grid [data-soon] span { color: var(--fg-3); font-weight: 500; }


/* ══ 그 외 이력 ════════════════════════════════════════
   그룹마다 모노 번호 + 라벨 + 헤어라인. 행은 「항목 — 강조 — 연도」 세 조각. */
.p-group { display: flex; align-items: center; gap: 0.9rem; margin: 2.6rem 0 0.2rem;
           font-family: var(--mono); font-size: 0.84rem; color: var(--fg-3); }
.p-group:first-of-type { margin-top: 0; }
.p-group b { color: var(--accent); font-weight: 700; }
.p-group span { color: var(--fg-2); }
.p-group::after { content: ''; flex: 1; height: 1px; background: var(--line); }

.p-hl { list-style: none; margin: 0; padding: 0; }
.p-hl li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem;
           border-bottom: 1px solid var(--line-2); padding: 0.95rem 0; }
.p-hl li::before { content: '·'; color: var(--fg-3); margin-right: 0.15rem; }
/* <p> 라 브라우저 기본 마진(1em)이 붙습니다 — flex 직계라 그게 행 높이를 키웁니다 */
.p-hl .t { margin: 0; font-size: 1.05rem; font-weight: 600; letter-spacing: -0.02em; }
.p-hl .k { font-size: 1rem; font-weight: 700; color: var(--accent); }
/* 과정명과 기관명이 붙어 있으면 한 낱말로 읽힙니다 — 사이를 벌립니다 */
.p-hl .org { margin-left: 0.85rem; font-size: 0.92rem; color: var(--fg-3); }
/* 이수 과목은 문장이 아니라 목록입니다. 기간 왼쪽에 모노로 붙입니다 */
.p-hl .st { margin-left: auto; font-family: var(--mono); font-size: 0.82rem; color: var(--fg-3); }
.p-hl .st + .w { margin-left: 1.6rem; }
.p-hl .w { margin-left: auto; font-family: var(--mono); font-size: 0.86rem; color: var(--fg-3);
           font-variant-numeric: tabular-nums; }
/* 이수 과목 같은 부연은 줄을 바꿔 통째로 내립니다 */
.p-hl .d { flex: 0 0 100%; margin: 0.3rem 0 0; font-size: 0.94rem; line-height: 1.6; color: var(--fg-2); }

@media (max-width: 860px) {
  .p-grid { grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); }
  .p-hl .w { margin-left: 0; width: 100%; }
}


/* ══ IT 활동 ═══════════════════════════════════════════
   시안은 활동이 넷이라 4칸 격자가 채워지지만, 우리는 하나입니다.
   하나를 끝까지 만들었습니다는 게 요지이므로 카드 안에 결과물까지 담습니다.
   활동이 늘면 .p-clubs 가 자동으로 여러 칸으로 벌어집니다. */
.p-clubs { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.9rem;
           grid-template-columns: repeat(auto-fill, minmax(23rem, 1fr)); }
.p-club {
  display: block; border: 1px solid var(--line); border-radius: 16px;
  padding: 1.5rem 1.6rem 1.4rem; text-decoration: none;
  transition: border-color var(--t), transform var(--t);
}
.p-club:hover { border-color: var(--fg-3); transform: translateY(-2px); }

.p-club-top { display: flex; align-items: flex-start; gap: 1rem; }
.p-club-logo { flex: none; width: 52px; height: 52px; border-radius: 13px; overflow: hidden;
               display: grid; place-items: center; background: var(--bg); }
.p-club-logo img { width: 100%; height: 100%; object-fit: cover; }
.p-club-name { margin: 0; font-family: var(--display); font-size: 1.35rem; font-weight: 800; letter-spacing: -0.02em; }
.p-club-role { margin: 0.25rem 0 0; font-family: var(--mono); font-size: 0.86rem; color: var(--accent); }
/* 기수는 오른쪽 위로 — 시안과 같은 자리 */
.p-club-gi { margin-left: auto; font-family: var(--mono); font-size: 0.78rem; color: var(--fg-3);
             border: 1px solid var(--line); border-radius: 999px; padding: 0.22rem 0.66rem; white-space: nowrap; }

/* 결과물 — 활동과 한 장 안에 두되 선으로 가릅니다 */
.p-club-out { display: flex; align-items: flex-start; gap: 0.85rem;
              margin-top: 1.25rem; padding-top: 1.25rem; border-top: 1px solid var(--line-2); }
.p-club-out img { flex: none; width: 38px; height: 38px; border-radius: 10px; }
.p-club-out h4 { margin: 0; font-size: 1.05rem; font-weight: 700; letter-spacing: -0.02em; }
.p-club-out p { margin: 0.3rem 0 0; font-size: 0.96rem; line-height: 1.6; color: var(--fg-2); }
.p-club-out b { font-family: var(--mono); font-size: 0.78rem; font-weight: 600; color: var(--fg-3); }

@media (max-width: 860px) {
  .p-clubs { grid-template-columns: 1fr; }
  .p-club { padding: 1.25rem 1.15rem; }
}


/* ══ 연락하기 ══════════════════════════════════════════
   마지막에 오는 것은 「더 볼 것」이 아니라 「연락처」다. 주소 하나를 크게 놓고
   나머지는 작게 — 눌러야 할 것이 무엇인지 한눈에 보이게 합니다. */
/* 여기부터는 내용이 아니라 연락처입니다 — 헤어라인이 아니라 진한 선으로 끊습니다 */
.p-contact { border-top: 1px solid var(--fg); padding: clamp(3.5rem, 8vh, 6rem) 0 clamp(3rem, 6vh, 4.5rem); }
.p-contact .wrap { padding-inline: clamp(1.5rem, 5vw, 2.5rem); }
.p-mail {
  display: inline-block; font-family: var(--display); font-weight: 800;
  font-size: clamp(1.9rem, 4.6vw, 3.2rem); letter-spacing: -0.03em; line-height: 1.15;
  color: var(--fg); text-decoration: none;
  border-bottom: 3px solid var(--fg); padding-bottom: 0.12em;
  transition: color var(--t), border-color var(--t);
}
.p-mail:hover { color: var(--accent); }

.p-contact-bot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
                 gap: 1.25rem; margin-top: clamp(1.75rem, 4vh, 2.75rem); }
.p-copy { margin: 0; font-family: var(--mono); font-size: 0.78rem; color: var(--fg-3); }
.p-links { display: flex; gap: 0.6rem; }
.p-links a {
  width: 52px; height: 52px; border: 1px solid var(--line); border-radius: 13px;
  display: grid; place-items: center; color: var(--fg-2);
  transition: border-color var(--t), color var(--t), transform var(--t);
}
.p-links a:hover { border-color: var(--fg-3); color: var(--fg); transform: translateY(-1px); }
.p-links svg { width: 23px; height: 23px; display: block; fill: currentColor; }

/* 좁아지면 아이콘이 옆이 아니라 아래로 내려옵니다. column-reverse 면 저작권보다
   위로 올라가는데, 아이콘이 먼저 오면 「눌러라」가 먼저 읽혀 순서가 뒤집힙니다. */
@media (max-width: 860px) {
  .p-contact-bot { flex-direction: column; align-items: flex-start; gap: 1.6rem; }
}


/* 발자국 규칙이 파일 끝에 붙어 있어서 위쪽 미디어쿼리를 덮어씁니다.
   같은 특정도면 뒤엣것이 이기기 때문입니다 — 좁은 화면 규칙을 여기 다시 둡니다. */
@media (max-width: 1080px) {
  /* 가운데로 와야 하는 것은 박스가 아니라 발자국 열입니다.
     li 는 [발자국][라벨] 이라 라벨이 박스 폭을 만듭니다. margin:auto 로 박스를 가운데 두면
     발자국은 왼쪽 끝에 몰립니다 — 407px 에서 발 중심이 화면 중앙보다 55.7px 왼쪽이었습니다.
     발 중심 x 는 점선 SVG 좌표에 묶여 있습니다: 홀수 19 · 짝수 59 → 두 열의 중간 39. */
  .p-steps { width: max-content; margin: 1.75rem 0 0.5rem;
             margin-left: max(0px, calc(50% - 39px)); }
  .p-steps > li { height: 64px; }
  /* 칸 높이가 76 → 64 로 줄면 발 중심도 따라 올라갑니다. 점선 SVG 도 같이 줄입니다 */
  /* height 와 transform 을 둘 다 주면 축소가 두 번 먹어 점선이 발과 어긋납니다.
     기본 높이(304)를 두고 transform 만 줍니다 — 64/76 = 0.842 */
  .p-trail { transform: scale(1, 0.842); transform-origin: top left; }
}


/* ── 좁은 화면의 활자 위계 ──────────────────────────────
   절 제목만 clamp 로 줄어들고 회사명은 고정이라 386px 에서 33.6px 대 28px 로 붙습니다.
   위는 덜 줄이고 아래를 더 줄여 「절 > 회사 > 항목」 위계를 되살립니다.
   이 블록이 파일 맨 끝에 있는 이유: 앞쪽 미디어쿼리에 두면 뒤의 본문 규칙에 집니다. */
@media (max-width: 860px) {
  .p-head h2   { font-size: 2.5rem; }    /* 40.0 — 하한을 올립니다 */
  .p-co-name   { font-size: 1.45rem; }   /* 23.2 */
  .p-tl-title  { font-size: 1.15rem; }   /* 18.4 */
  .p-about p   { font-size: 1.15rem; line-height: 1.75; }
  .p-lead      { font-size: 1.02rem; }
  /* 서비스명과 본문이 붙어 보인 진짜 원인은 간격이었습니다. 크기를 줄였더니 정작
     읽어야 할 본문이 모바일 하한 아래로 내려갔습니다 — 16px 이 여유가 아니라 하한입니다.
     구분은 아래 「그룹 간격」 블록이 만듭니다. */
  .p-tl p.p-do { font-size: 1rem; }      /* 16 */
  .p-tl ul li  { font-size: 1rem; }      /* 16 */
  .p-club-name { font-size: 1.15rem; }
  .p-hl .t     { font-size: 1rem; }
}


/* ── 실제 안드로이드 폰에서 깨진 것들 ────────────────────
   좁은 폭에서 `margin-left:auto` 로 오른쪽에 붙이던 것들이 줄바꿈되며 제자리를
   잃습니다. 폰에서는 가로로 밀어내지 않고 세로로 쌓습니다. */
@media (max-width: 860px) {
  /* 교육·자격증 행 — flex 로 감싸면 불릿만 남고 제목이 다음 줄로 떨어집니다 */
  .p-hl li { display: block; padding: 1.1rem 0; }
  .p-hl li::before { display: none; }
  .p-hl .t   { display: block; }
  .p-hl .org { display: inline; margin-left: 0.5rem; }
  .p-hl .st  { display: block; margin: 0.45rem 0 0; }
  /* `.p-hl .st + .w`(0,3,0) 가 파일 위쪽에 있어 `.p-hl .w`(0,2,0) 로는 못 덮습니다.
     가로 배치용 들여쓰기 1.6rem 이 세로로 쌓인 뒤에도 남아 기간만 밀려 보였습니다. */
  .p-hl .w,
  .p-hl .st + .w { display: block; margin: 0.3rem 0 0; width: auto; }

  /* 이름이 긴 것(「PostgreSQL」처럼)이 두 줄로 접히며 칸 높이가 제각각이 됩니다 */
  .p-techs { grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); }
  .p-tech span { white-space: nowrap; font-size: 0.88rem; }
  .p-tech { padding: 0.75rem 0.85rem; gap: 0.55rem; }
}


/* 회사 기간 — 폰에서는 한 줄로. `2024.11 —` / `재직중` 두 줄로 끊기면
   날짜가 깨진 것처럼 보입니다. <br> 자리에 공백을 넣어 이어 붙입니다. */
@media (max-width: 860px) {
  .p-co-when { white-space: nowrap; }
  .p-co-when br { display: none; }
  .p-co-when br + * , .p-co-when br { font-size: inherit; }
}


/* ── 한글이 섞인 자리에는 모노를 쓰지 않습니다 ──────────────
   JetBrains Mono 는 라틴 전용이라 한글 음절만 시스템 폴백으로 떨어지고,
   한 줄 안에서 글꼴이 갈립니다(같은 40px 에서 `재직중대` 가 모노 스택 138.4px,
   본문 글꼴 142.7px — 다른 글꼴이 쓰이고 있다는 증거).
   `.s-nav` 주석에 이미 적어 둔 규칙을 나머지 여덟 곳에도 적용합니다.
   라틴 전용인 .p-num · .p-tl-when · .p-role · .p-group b · .s-jump 는
     모노를 유지합니다 — 거기선 모노가 제 몫(숫자 정렬)을 합니다. */
.p-co-when,
.p-refs > b,
.p-tag-off,
.p-about .p-tech-head, .p-tech-head,
.p-group span,
.p-hl .w, .p-hl .st + .w,
.p-club-gi,
.p-club-out b {
  font-family: var(--sans);
  font-variant-numeric: tabular-nums;
}


/* ── 폰: 정렬선과 그룹 간격 ──────────────────────────────
   데스크톱은 날짜가 가로 전용 열(회사기간 x=40 · 서비스기간 x=1030)에 있어
   읽는 열에 본문 한 급만 남습니다. 860px 아래에서 그 열이 세로로 접히며
   메타가 읽는 흐름 한복판으로 들어온 것이 가독성 저하의 근본 원인입니다. */
@media (max-width: 860px) {
  /* 정렬선 — 타임라인 본문을 회사명과 같은 x 로 맞춥니다. 지금은 자식(49)이
     부모(96)보다 47px 바깥으로 나와 소속이 거꾸로 읽힙니다.
     레일은 로고 중심(24 + 56/2 = 52)에 세웁니다.
     레일(.p-tl 의 padding-left)·점(::before)·파동(::after) 이 한 좌표에
       묶여 있습니다. 하나를 고치면 셋을 같이 고쳐야 합니다. */
  /* 28(마진) + 1(점선 테두리) + 43(패딩) = 본문 x=96, 회사명과 정확히 같은 자리 */
  .p-tl { margin-left: 28px; padding-left: 43px; }   /* 레일 x=52 · 본문 x=96 */
  .p-tl > li::before,
  .p-tl > li[data-now]::after { left: calc(-43px - 7px); }

  /* 날짜는 제 줄을 갖습니다. 제목 줄에 붙이면 한 행이 줄지만 사용자 판정으로
     개행 쪽이 더 읽힙니다 — 서비스명(18.4 표제)과 날짜(14.08 모노)가 한 줄에
     섞이면 둘 다 인지하기 어려워집니다. `margin-left:auto` 만 풀어 왼쪽에 세웁니다. */
  .p-tl-when { margin-left: 0; width: 100%; }

  /* 그룹은 크기가 아니라 간격이 만듭니다. 직전 판은 8·7·14·10 이라 전부 비슷해
     어디서 메타가 끝나고 본문이 시작하는지 알 수 없었습니다.
     그룹 안 5 ↔ 경계 20 — 경계가 그룹 안의 4배여야 근접성 그룹이 생깁니다. */
  .p-role      { margin-top: 0.3rem; font-size: 0.88rem; }  /* 14.08 — 메타 한 급 */
  .p-tl p.p-do { margin-top: 1.25rem; }                     /* 메타 → 본문 경계 20 */

  /* 짧은 고아 줄 방지(요약 마지막 줄이 첫 줄의 29% 였습니다). 미지원은 조용히 무시 */
  .p-tl p.p-do, .p-tl ul li { text-wrap: pretty; }

  /* 기술 칩 — 본문 x=96 로 옮기며 폭이 287px 로 줄어 칩이 두 줄로 넘칩니다.
     칩은 읽는 글이 아니라 훑는 표식이라 본문 하한(16px)을 따르지 않아도 됩니다. */
  .p-tags span { font-size: 0.8rem; padding: 0.22rem 0.6rem; }   /* 13.76 → 12.8 */
  .p-tags { gap: 0.36rem; margin-top: 1.7rem; }

  /* 「그 외」 날짜가 13.76 로 스택(13.12)보다 커서 위계가 뒤집혀 있었습니다.
     날짜는 가장 부차적인 정보다 — 제목 16 > 기관 14.72 > 스택 13.12 > 날짜 12.48 */
  .p-hl .w, .p-hl .st + .w { font-size: 0.78rem; }   /* 13.76 → 12.48 */
  .p-hl .p-ing, .p-hl .st + .p-ing { font-size: 1.05rem; }
}


/* ── `~ing` — 끝나지 않은 것들 ───────────────────────────
   「2022 — 지금」처럼 딱딱한 날짜 대신 씁니다. 손글씨체라 본문과 결이 달라
   「끝나는 날짜가 아니다」라는 신호가 바로 읽힙니다.
   선언은 `/assets/fonts.local.css`(이서윤체)에 있습니다. */
.p-ing,
.p-hl .p-ing,
.p-hl .st + .p-ing {
  font-family: 'LeeSeoyun', var(--sans);
  font-size: 1.12rem; letter-spacing: 0.02em; color: var(--fg-2);
}

/* 취미 줄 뒤에 붙는 작은 표식. 색은 넣지 않습니다 — 본문 색을 그대로 물려받습니다 */
.p-emo {
  width: 1.15em; height: 1.15em; vertical-align: -0.22em; margin-left: 0.4rem;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}


/* ══ 블로그 목록 — 사진 없이 ════════════════════════════
   사진을 빼면 모든 행이 같은 무게가 되어 심심해집니다. 사진이 하던
   「눈이 걸리는 자리」를 활자 대비 · 리듬 · 호버 셋이 대신합니다.

   ## 줄 사이의 선은 여기 없습니다
   예전에는 `.b-item` 에 `border-top` 을, 마지막 줄에 `border-bottom` 을 전역으로 걸었습니다.
   목록이 한 가지 모양이던 시절의 규칙입니다. 갈래가 열두 벌이 된 지금은 **갈래마다 제 선을
   갖습니다**(`templates/blog.css`) — 전역으로 걸면 열한 벌에 남의 선이 하나씩 더 그어집니다.
   카드 갈래(외곽선·호수)에서는 네모난 선이 둥근 모서리 밖으로 삐져나오고, 장부는
   「연도 라벨 다음 줄에만」이라는 규칙이 깨지고, 매거진·피드는 맨 윗선이 두 겹이 됐습니다.
   선을 되살리고 싶으면 그 갈래의 파일에 적으세요. 여기 걸면 열두 벌이 전부 따라옵니다. */
.b-list { list-style: none; margin: 0; padding: 0; }
.b-item > a {
  display: grid; grid-template-columns: 2.7rem minmax(0, 1fr) auto;
  align-items: baseline; gap: 0 1.3rem; padding: 1.15rem 0;
  text-decoration: none; color: inherit; opacity: 1;
  transition: background-color var(--t);
}
.b-item > a:hover { opacity: 1; background: var(--bg-2); }

/* 번호 — 이 사이트가 절에 쓰는 `01 About` 과 같은 어휘. 평소엔 선 색만큼 흐리다가
   호버에서 포인트색으로 물듭니다. 「어디를 보고 있는지」를 색 하나로 말합니다. */
.b-no {
  font-family: var(--mono); font-size: 0.82rem; letter-spacing: 0.04em;
  color: var(--line); font-variant-numeric: tabular-nums;
  transition: color var(--t);
}
.b-item > a:hover .b-no { color: var(--accent); }

.b-body { min-width: 0; }
.b-title {
  display: block; font-family: var(--display); font-size: 1.3rem; font-weight: 800;
  letter-spacing: -0.03em; line-height: 1.45; color: var(--fg); word-break: keep-all;
}
.b-item > a:hover .b-title { text-decoration: underline; text-underline-offset: 4px; }
/* `--fg-3` 은 흰 배경에서 3.89:1 — 본문 기준(4.5:1)에 미달합니다. 한 단계 진하게 */
.b-date {
  font-family: var(--mono); font-size: 0.8rem; color: #5c646f;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}



/* 좁은 화면 — 날짜를 제목 아래로 내립니다. 한 줄에 두면 제목이 짓눌립니다 */
@media (max-width: 860px) {
  .b-item > a { grid-template-columns: 2.2rem minmax(0, 1fr); gap: 0 0.9rem; padding: 1.05rem 0; }
  .b-date { grid-column: 2; margin-top: 0.4rem; }
  .b-title { font-size: 1.14rem; }
}


/* ══════════════════════════════════════════════════════════════════════
   템플릿으로 굽는 화면 — 관리자의 「홈디자인」에서 템플릿을 고른 화면만 씁니다.

   직접 디자인(기본)인 화면은 `pages/*.html` 을 손으로 고치므로 아래 규칙이 안 쓰입니다.
   지워도 그쪽은 멀쩡합니다.
   ══════════════════════════════════════════════════════════════════════ */

/* ── 메인: 무대 ────────────────────────────────────────────────────────
   첫 화면. 요소는 1240px 판 위의 자리에 섭니다 — 관리자 미리보기에서 끌어 놓은 곳(bake 의 stageHtml).

   board 는 컨테이너라 화면 폭에 맞춰 통째로 줄고 늘어납니다. 좌표와 글자 크기가 전부
   `--u`(판 폭의 1/1240)의 배수라서, 1440 에서 놓은 모양이 1000 에서도 비율 그대로입니다.
   `--u` 는 요소 자신에 정의해야 합니다. 판에 정의하면 cqw 가 판의 바깥 컨테이너를 봅니다.
   좌표 변수는 `--sx --sy --sw --sh` 다. `--w` 는 본문 폭과 손으로 쓴 화면의 애니메이션이 씁니다.
   860px 이하는 판을 버리고 마크업 차례(= y→x 순)대로 쌓습니다. */
.m-stage { position: relative; }
.m-board {
  container-type: inline-size;
  position: relative;
  /* 폭은 `--bw` 가 듭니다 — `none`(화면 꽉 채우기)이 기본, `1240px`(본문 폭)이면 거기서 멈춥니다.
     꽉 채우면 판이 넓어지는 만큼 `--u` 가 커져 높이도 글자도 같이 커집니다.
     좌표와 글자 크기가 전부 1240 기준 배수이기 때문입니다 — 고르는 사람이 아는 값이어야 해서 knob 으로 냈습니다 */
  max-width: var(--bw, none); margin-inline: auto;
  aspect-ratio: 1240 / var(--sh, 600);
}
.m-i {
  --u: calc(100cqw / 1240);
  position: absolute; margin: 0;
  left: calc(var(--sx, 0) * var(--u)); top: calc(var(--sy, 0) * var(--u)); width: calc(var(--sw, 400) * var(--u));
  white-space: pre-line; overflow-wrap: break-word;
}
/* 폭을 끌어 정한 적이 없는 상자는 글자를 감쌉니다 — 짧은 글자에 넓은 네모가 잡히면
   무엇을 고르는지 눈으로 알 수 없습니다. `--sw` 는 그때 최대 폭으로 삽니다(판을 안 넘게) */
/* 판의 오른쪽 끝도 같이 막습니다. `--sw` 는 고를 때의 최대 폭이라, 상자를 오른쪽으로
   옮긴 뒤 글자가 길어지면 그만큼 판 밖으로 흘러나갔습니다(편집기는 보이는 폭으로 막는데
   공개면은 안 막아 둘이 어긋났습니다) */
.m-i[data-w='auto'] { width: max-content;
  max-width: min(calc(var(--sw, 400) * var(--u)), calc(100cqw - var(--sx, 0) * var(--u))); }
/* ── 글자 칸 ────────────────────────────────────────────────────────────
   상자가 고른 칸(data-s)이 크기·줄 높이·자간·글꼴 갈래·색을 함께 정합니다.
   상자마다 다섯 값을 인라인으로 실으면 한 사이트의 결이 상자마다 갈립니다.
   상자가 제 글꼴(--sff)이나 색(--sc)을 정했으면 그것이 이깁니다. */
.m-i[data-s='xl'] {
  font-family: var(--sff, var(--display)); font-weight: 400; letter-spacing: -0.03em;
  font-size: calc(80 * var(--u)); line-height: 1.1; color: var(--sc, var(--fg));
}
.m-i[data-s='display'] {
  font-family: var(--sff, var(--display)); font-weight: 400; letter-spacing: -0.03em;
  font-size: calc(60.8 * var(--u)); line-height: 1.16; color: var(--sc, var(--fg));
}
.m-i[data-s='body'] {
  font-family: var(--sff, var(--sans));
  font-size: max(14px, calc(18.4 * var(--u))); line-height: 1.7; color: var(--sc, var(--fg-2));
}
.m-i[data-s='small'] {
  font-family: var(--sff, var(--sans));
  font-size: max(13px, calc(15.04 * var(--u))); line-height: 1.7; color: var(--sc, var(--fg-2));
}
.m-i[data-s='label'] {
  font-family: var(--sff, var(--mono)); letter-spacing: 0.14em;
  font-size: max(11px, calc(13.12 * var(--u))); line-height: 1.7; color: var(--sc, var(--fg-3));
}

/* 링크가 걸린 글자 — 색은 안 바꿉니다.
   파랑(`--accent`)으로 튀면 브라우저 기본 링크처럼 보이고, 상자가 제 색(`--sc`)을 정해 둔
   자리·그림 위 흰 글자에서는 대비까지 무너집니다. 이 판짜기의 링크 신호는 첫 화면의
   `.m-links` 가 이미 정해 두었습니다 — 밑줄이 옅은 선에서 글자색까지 진해집니다. */
.m-i a { text-decoration: none; border-bottom: 1px solid var(--line-2); padding-bottom: 0.15em;
  transition: border-bottom-color var(--t); }
.m-i a:hover, .m-i a:focus-visible { border-bottom-color: currentColor; }

/* 콘텐츠 영역(글자 판) 밑에 무엇이든 서면 선 하나로 끊습니다.
   사진 자리(.m-shots·.m-slides)는 그림이 경계를 만드므로 선을 안 긋습니다 */
.m-stage + section:not(.m-shots):not(.m-slides) { border-top: 1px solid var(--line); }

/* 대표작 그림을 깐 무대 — 잡지 표지처럼 꽉 채우고 아래쪽만 어둡게 깝니다.
   사진 전체에 막을 씌우면 작업이 죽습니다. 글자는 전부 흰색으로 */
/* 배경 그림만 있고 글자 판이 없으면 자식이 전부 absolute 라 높이가 0 이 됩니다 —
   그림을 깔고 글자를 다 끄면 화면에서 통째로 사라졌습니다.
   판이 있을 때는 판이 높이를 정하므로 이 최솟값에 안 걸립니다 */
.m-stage.has-img { overflow: hidden; background: var(--fg); min-height: calc(var(--sh, 600) * 1px); }
.m-stage.has-img:has(.m-board) { min-height: 0; }
.m-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.m-stage.has-img::after {
  content: ''; position: absolute; inset: auto 0 0; height: 52%; pointer-events: none;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.9) 0%, rgba(0, 0, 0, 0.72) 28%, rgba(0, 0, 0, 0) 100%);
}
.m-stage.has-img .m-board { z-index: 1; color: #fff; }
/* 그림 위에서는 흰 글자가 기본 — 다만 상자가 색을 정했으면 그것이 이깁니다 */
.m-stage.has-img .m-i { color: var(--sc, #fff); }
.m-stage.has-img .m-i:is([data-s='body'], [data-s='small'], [data-s='label']) { color: var(--sc, rgba(255, 255, 255, 0.82)); }
.m-stage.has-img .m-i a { border-bottom-color: rgba(255, 255, 255, 0.5); }
/* 윗줄이 `.m-i a:hover`(0,2,1)보다 명시도가 높아(0,3,1) 그림 위에서는 hover 가 안 먹었습니다.
   같은 무게로 한 번 더 적어 줍니다 — 흰 글자색까지 밑줄이 또렷해집니다 */
.m-stage.has-img .m-i a:hover,
.m-stage.has-img .m-i a:focus-visible { border-bottom-color: currentColor; }

/* ── 메인: 사진 ───────────────────────────────────────────────────────
   사진은 두 자리에 각자 삽니다 — 세로로 잇는 `.m-shots` 와 배너 `.m-slides`.
   어느 것이 서고 어느 차례냐는 목록(`sections`)이 듭니다 — 템플릿에서 파생하면
   배치를 한 번 손대 `custom` 으로 튀는 순간 배너가 말없이 세로 더미가 됩니다.

   포트폴리오 상세의 `.wk-stack` 을 쓰지 않습니다. 그쪽은 간격·모서리가 `--wk-*`
   knob(포트폴리오 설정)에 묶여 있어, 메인 간격이 남의 설정을 따라 움직입니다. */
/* knob 넷은 인라인 변수로 실려 옵니다(bake 의 `shotsHtml`) — 값이 마크업이 아니라
   변수라 관리자가 끌면 창이 그 자리에서 바뀝니다.

   본문 폭(1240px)으로 안 가둡니다. 가두면 「좌우 간격 0」이 끝까지 안 가고 창이
   1240 보다 넓은 만큼 양쪽에 얇게 남습니다.
   폭을 정하는 것은 이 자리에서 좌우 간격 하나여야 합니다 — 가두는 값이 하나 더 있으면
   knob 을 0 으로 내려도 왜 안 붙는지 알 길이 없습니다. 배너(.m-slides)도 같은 규약입니다. */
.m-shots {
  display: grid;
  gap: calc(var(--mgap, 0) * 1px);
  padding-top: min(calc(var(--mtop, 0) * 1px), 12vw);
  /* `min(…, 12vw)` 로 묶습니다 — 좌우 간격은 200px 까지 올라가는데 360px 폰에서는
     좌우 합 400px 이 콘텐츠 폭을 0 으로 만들어 사진이 통째로 사라졌습니다 */
  padding-inline: min(calc(var(--mside, 0) * 1px), 12vw);
}
.m-shots > img {
  display: block; width: 100%; height: auto;
  border-radius: calc(var(--mradius, 0) * 1px);
}

/* ── 슬라이드 — 자바스크립트 0바이트 ──────────────────────────────────
   바탕은 `scroll-snap` 입니다: 어느 브라우저에서나 밀기·휠·키보드·터치로 넘어가고
   `scroll-snap-stop: always` 가 한 번에 한 장씩만 넘어가게 잡습니다.

   점(`::scroll-marker`)과 화살표(`::scroll-button()`)는 CSS Overflow 5 라
   2026-09 현재 크롬·엣지 135+ 만 압니다. 그래서 스크롤바를 기본으로 남깁니다 —
   점이 안 뜨는 브라우저에서 「뒤에 더 있습니다」를 알릴 길이 그것뿐입니다. 점이 뜨는
   브라우저에서만 스크롤바를 숨깁니다(아래 @supports). */
/* 높이는 칸(section) 이 듭니다. 레일에 직접 주면 `scroll-marker-group` 이 점 줄 자리로
   16px 을 떼어 가면서 칸이 레일보다 짧아져, 배너 아래가 그만큼 잘렸습니다.
   칸이 높이를 들고 레일이 그것을 채우면 떼어 가는 자리가 칸 안에서 해결됩니다 */
/* 높이는 슬라이더가 말한 px 그대로입니다.
   예전에 `min(…, 78vh)` 로 덮어 두었더니 창 높이에 따라 582px 쯤에서 잘려, 그 위로는
   끌어도 화면이 안 바뀌었습니다 — knob 이 값대로 반영되지 않으면 버그로 보입니다.
   좁은 화면에서는 판(`.m-board`)이 그러듯 화면 폭에 맞춰 같이 줄입니다(아래 @media). */
.m-slides { position: relative; overflow: hidden; background: var(--fg);
  height: calc(var(--sh, 480) * 1px); }
.m-slides .m-rail {
  display: flex; height: 100%;
  overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory; scroll-behavior: smooth;
  scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, 0.45) transparent;
}
.m-slides .m-rail:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.m-slide {
  flex: 0 0 100%; width: 100%; height: 100%; object-fit: cover;
  scroll-snap-align: center; scroll-snap-stop: always;
}
@media (prefers-reduced-motion: reduce) { .m-slides .m-rail { scroll-behavior: auto } }

/* 덤 ① 점 — 지금 몇 번째인지, 몇 장인지. 누르면 그 장으로 갑니다 */
@supports selector(::scroll-marker) {
  .m-slides .m-rail { scrollbar-width: none; scroll-marker-group: after; }
  .m-slides .m-rail::-webkit-scrollbar { display: none; }
  /* 어두운 알약을 깔고 그 위에 점을 놓습니다 — 밝은 사진 위에서 흰 점만 두면 사라집니다.
     배너 위에 띄웁니다: 여백 셈으로 높이를 0 으로 맞추려 했더니 배너 아래가 16px 잘렸습니다.
     자리를 띄우면 셈이 아예 없어 어떤 글자 크기에서도 안 잘립니다 */
  .m-slides .m-rail::scroll-marker-group {
    position: absolute; left: 50%; bottom: 0.9rem; translate: -50% 0; z-index: 1;
    display: flex; justify-content: center; align-items: center; gap: 0.5rem;
    width: max-content; height: 1.75rem; padding-inline: 0.75rem;
    border-radius: 999px; background: rgba(0, 0, 0, 0.42);
  }
  .m-slide::scroll-marker {
    content: ''; width: 7px; height: 7px; border-radius: 50%; cursor: pointer;
    background: rgba(255, 255, 255, 0.5); border: 0; transition: background 0.15s;
  }
  .m-slide::scroll-marker:hover { background: rgba(255, 255, 255, 0.7); }
  .m-slide::scroll-marker:target-current { background: #fff; }
}
/* 덤 ② 화살표 — 마지막 장에서는 저절로 꺼집니다(:disabled) */
@supports selector(::scroll-button(right)) {
  .m-slides .m-rail::scroll-button(*) {
    position: absolute; top: 50%; translate: 0 -50%; z-index: 2;
    width: 2.6rem; height: 2.6rem; border: 0; border-radius: 50%; cursor: pointer;
    background: rgba(0, 0, 0, 0.42); color: #fff; font-size: 1.4rem; line-height: 1;
  }
  .m-slides .m-rail::scroll-button(*):hover { background: rgba(0, 0, 0, 0.66); }
  .m-slides .m-rail::scroll-button(*):disabled { opacity: 0; pointer-events: none; }
  .m-slides .m-rail::scroll-button(left) { content: '\2039'; left: 1rem; }
  .m-slides .m-rail::scroll-button(right) { content: '\203A'; right: 1rem; }
}


@media (max-width: 860px) {
  .m-board {
    container-type: normal; aspect-ratio: auto;
    display: flex; flex-wrap: wrap; align-content: center; column-gap: 1.5rem; row-gap: 1rem;
    padding: clamp(2.5rem, 9vh, 4rem) clamp(1.5rem, 5vw, 2.5rem);
  }
  .m-i { position: static; flex: 0 0 100%; width: auto; }
  /* 링크 둘은 쌓지 않고 한 줄에 — 차례가 붙어 있으면 나란히 섭니다 */
  /* 링크 상자는 쌓지 않고 한 줄에 — 차례가 붙어 있으면 나란히 섭니다 */
  .m-i:has(a) { flex: 0 0 auto; margin-top: 0.5rem; }
  /* 판을 버렸으므로 판 단위(--u)가 뜻을 잃습니다. 칸마다 손으로 정한 값으로 갑니다 */
  .m-i[data-s='xl'] { font-size: clamp(2.2rem, 8vw, 3rem); }
  .m-i[data-s='display'] { font-size: clamp(1.9rem, 7vw, 2.6rem); }
  .m-i[data-s='body'] { font-size: 1rem; }
  .m-i[data-s='small'] { font-size: 0.94rem; }
  .m-i[data-s='label'] { font-size: 0.82rem; }
  .m-board { min-height: min(72vh, 560px); }
  /* 그림 무대 — 폰에서도 표지 높이를 지키고 글자는 아래에 모읍니다 */
  .m-stage.has-img .m-board { min-height: min(72vh, 620px); align-content: flex-end; }
  /* 배너 — 넓은 화면에서 정한 px 를 폰에 그대로 쓰면 첫 화면을 통째로 차지합니다.
     판과 같은 규약으로 1240 기준 비율을 유지한 채 화면 폭에 맞춰 줄입니다 */
  .m-slides { height: calc(var(--sh, 480) * 100vw / 1240); }
}
/* 푸터의 얇은 변형 — 다 보고 난 자리에서 푸터가 화면을 반이나 차지하면 안 됩니다.
   푸터 본체가 여기 있으니 변형도 여기 둡니다. blog.css 에 두면 블로그 밖에서는 안 먹어
   포트폴리오 푸터가 클래스만 붙은 채 184px 로 두꺼웠습니다. */
/* 블로그의 푸터 — 포트폴리오와 같은 물건(.p-contact) 이되 얇게.
   포트폴리오 푸터는 이메일이 목적지라 크지만, 글을 다 읽은 자리에서는 그게 글보다 커 보입니다.
   윗선·색·아이콘 상자는 그대로 둡니다 — 무드를 맞추는 것은 그쪽이지 높이가 아닙니다. */
.p-contact.is-slim { padding: .65rem 0; }                       /* 96px → 약 53px */
.p-contact.is-slim .p-contact-bot { margin-top: 0; }
.p-contact.is-slim .p-copy { font-size: .72rem; }  /* --fg-3 는 3.88:1 로 미달 */
.p-contact.is-slim .p-links a { width: 32px; height: 32px; border-radius: 9px; }
.p-contact.is-slim .p-links svg { width: 16px; height: 16px; }
/* 좁은 화면에서도 한 줄로 — 포트폴리오는 세로로 쌓지만 얇은 푸터는 쌓으면 다시 두꺼워집니다 */
@media (max-width: 860px) {
  .p-contact.is-slim .p-contact-bot { flex-direction: row; align-items: center; gap: 1rem; }
}


/* ══ 작업 카드 ═══════════════════════════════════════════
   그리드와 벽돌쌓기가 같은 카드를 씁니다. 다른 것은 담는 그릇뿐입니다. */
.w-cards { list-style: none; margin: 0; padding: 0; }
.w-card { display: block; text-decoration: none; }
.w-card figure { margin: 0; }
/* 그림을 자르는 상자는 캡션을 품지 않습니다 — `<figure>` 에 걸면 그 안의 캡션까지 잘립니다.
   캡션은 그림에 딸린 것이라 `<figure>` 안에 있고, 자르기는 이 상자가 맡습니다. */
.w-card .w-shot { display: block; overflow: hidden; background: var(--bg-2); }
/* 커버를 아직 안 올린 작업 — 빈 상자는 높이가 0 이라 카드가 캡션만 남고 무너집니다.
   자리를 지키고 조용히 비워 둡니다(줄이 들쭉날쭉하면 눈이 제목을 따라가다 걸립니다) */
.w-card .w-shot:empty { aspect-ratio: 4 / 5; }
.w-card img { display: block; width: 100%; transition: transform 0.5s var(--ease); }
.w-card:hover img, .w-card:focus-visible img { transform: scale(1.02); }
.w-card figcaption { display: flex; justify-content: space-between; gap: 1rem; padding-top: 0.7rem; font-size: 0.9rem; }
.w-title { color: var(--fg); }
.w-kind { color: var(--fg-3); }

/* 메인의 대표작 — 세 점을 가로로. 여기서는 비율을 맞춰 자릅니다(줄이 서야 해서) */
.sec-grid { padding-block: clamp(2.5rem, 7vh, 5rem) clamp(3rem, 8vh, 5rem); }
/* 아직 아무것도 없을 때 — 맨 문장으로 떠 있으면 고장처럼 보입니다.
   점선 테두리로 자리는 여기라고 말해 주되, 색은 흐리게 두어 내용과 안 겨룹니다 */
.w-none {
  margin: 0; padding: clamp(2rem, 6vh, 3.5rem) 1.25rem; text-align: center;
  border: 1px dashed var(--line); border-radius: 2px;
  color: var(--fg-3); font-size: 0.94rem; line-height: 1.7;
}
.w-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1rem, 2.4vw, 2.4rem); }
.sec-grid .w-card .w-shot { aspect-ratio: 4 / 5; }
.sec-grid .w-card img { height: 100%; object-fit: cover; }
.sec-grid-more { margin: clamp(1.75rem, 4vh, 2.5rem) 0 0; font-size: 0.95rem; }
.sec-grid-more a { text-decoration: none; padding-bottom: 0.35rem; border-bottom: 1px solid var(--line); }
.sec-grid-more a:hover { border-color: var(--fg); }

/* ══ 메인: 맺음말 ══════════════════════════════════════
   작업 밑에 오는 마지막 절. 이 절이 있으면 푸터가 얇아집니다(bake 의 `foot: 'slim'`) —
   그래서 주소를 크게 두는 몫이 여기로 넘어옵니다. 한 화면에 큰 주소가 둘이면 안 됩니다.
   끊는 선은 헤어라인입니다. 진한 선은 푸터(`.p-contact`)의 것이라 여기서 쓰면 둘이 겹쳐 보입니다. */
.sec-about { border-top: 1px solid var(--line); padding-block: clamp(3rem, 8vh, 5rem) clamp(3rem, 7vh, 4.5rem); }
.sec-about-say {
  margin: 0 0 clamp(1.25rem, 3.5vh, 2rem); max-width: 30em;
  /* 주소가 없는 사이트(`email: ''`)에서는 이 한 문장이 절의 전부입니다 — 밑 여백이 남으면
     아무것도 없는 95px 공백이 생깁니다. 뒤에 아무도 없으면 여백도 없앱니다 */
  font-size: clamp(1rem, 2.1vw, 1.2rem); line-height: 1.7; color: var(--fg-2);
}
/* 주소는 푸터의 `.p-mail` 과 같은 물건이되 한 단계 작습니다 — 밑에 얇은 푸터가 또 오기 때문입니다 */
.sec-about-mail {
  display: inline-block; font-family: var(--display);
  font-size: clamp(1.5rem, 3.6vw, 2.4rem); letter-spacing: -0.03em; line-height: 1.15;
  color: var(--fg); text-decoration: none;
  border-bottom: 2px solid var(--fg); padding-bottom: 0.12em;
  transition: color var(--t), border-color var(--t);
}
.sec-about-mail:hover { color: var(--accent); border-bottom-color: currentColor; }
.sec-about-say:last-child { margin-bottom: 0; }

/* 작업 목록(`.works-top`·`.works-brick`)의 옛 규칙은 여기 없습니다 —
   목록은 `templates/portfolio.css` 의 `.pf` 가, 머리(「작업 / 9편」)는 `templates/header.css` 의 `.lh` 가 넘겨받았습니다.
   굽기가 더는 이 이름을 안 씁니다(bake.mjs 의 `worksPage` 참고). */

/* ══ 작업 상세 — 커버 → 제목·사실 → 모듈을 세로로 ════════
   베한스가 하는 방식입니다. 설명은 사이사이에 조금만 둡니다 — 주인공은 지면입니다. */
/* ══ 작업 상세 — 무드보드를 세로로 폅니다 ═══════════════════════════════
   디자이너는 글을 쓰지 않습니다. 올린 그림이 곧 내용이고, 이 화면이 하는 일은
   차례대로·원래 비율로·정한 간격으로 쌓는 것뿐입니다. 간격이 0이면 한 장처럼 붙습니다. */
/* 위 여백은 관리자의 「상단 여백」(--wk-top). 팝업(.pf-pop)도 같은 값을 씁니다 */
.wk-top { padding-block: var(--wk-top, clamp(2rem, 6vh, 4rem)) clamp(1rem, 3vh, 2rem); }
.wk-top h1 {
  margin: 0; font-family: var(--display); font-weight: 400;
  font-size: clamp(1.9rem, 5vw, 3.6rem); line-height: 1.14; letter-spacing: -0.02em;
}

/* 그림 폭은 판면 하나로 정합니다 — `--wk-pad` 가 0 이면 화면 끝까지 갑니다.
   세로 간격(--wk-gap)은 관리자 knob 입니다. 기본값은 0 이고, 붙어 있는 쪽이 이 화면의 기본입니다 */
.wk-stack {
  display: grid; gap: var(--wk-gap, 0px);
  padding-inline: var(--wk-pad, 0px);
  padding-bottom: clamp(2rem, 6vh, 4rem);
  max-width: var(--wk-max, 1100px); margin-inline: auto;
}
.wk-shot { display: block; }
.wk-shot img { display: block; width: 100%; height: auto; border-radius: var(--wk-radius, 0px); }

/* ── 확대 — 자바스크립트 없이 주소의 `#` 만으로 ──────────────────────
   `:target` 은 「주소가 이 칸을 가리키는 동안」입니다. 그래서 뒤로가기로 닫히고,
   링크를 복사하면 그 그림이 열린 채로 열립니다. 스크립트가 한 글자도 안 듭니다. */
.wk-zoom {
  position: fixed; inset: 0; z-index: 50; display: none;
  place-items: center; padding: clamp(1rem, 4vw, 3rem);
  background: rgba(0, 0, 0, 0.94);
}
.wk-zoom:target { display: grid; }
.wk-zoom img { max-width: 100%; max-height: 92vh; width: auto; height: auto; display: block; }
/* 닫기는 화면 전체입니다 — 작은 × 를 겨냥하게 하지 않습니다. × 는 어디를 눌러야 하는지 알려 주는 표시 */
.wk-zoom-close { position: absolute; inset: 0; cursor: zoom-out; }
.wk-zoom-close::after {
  content: '×'; position: absolute; top: clamp(0.5rem, 2vw, 1.5rem); right: clamp(0.75rem, 2.5vw, 2rem);
  font-size: 2rem; line-height: 1; color: rgba(255, 255, 255, 0.8);
}
.wk-zoom-no {
  position: absolute; bottom: clamp(0.75rem, 2.5vw, 1.5rem); left: 50%; transform: translateX(-50%);
  font-family: var(--mono); font-size: 0.78rem; color: rgba(255, 255, 255, 0.6);
}

.work-next {
  display: flex; justify-content: space-between; align-items: center; gap: 2rem;
  margin-top: clamp(3rem, 8vh, 6rem); padding-top: clamp(2rem, 5vh, 3.5rem); border-top: 1px solid var(--line);
}
.work-next-label { font-size: 0.85rem; color: var(--fg-3); }
.work-next a { font-family: var(--display); font-size: clamp(1.3rem, 3.2vw, 2.4rem); text-decoration: none; }
.work-next a:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 0.12em; }

/* ── 좁은 화면 ───────────────────────────────────────────
   단을 줄이고 두 칸짜리를 한 칸으로. 표지는 화면 높이를 조금 낮춥니다. */

/* ══ 푸터(푸터) ════════════════════════════════════════
   관리자 「공통 → 푸터」가 정하는 두 벌(메인 / 포트폴리오·블로그)이 여기로 나옵니다.
   판(`.m-board`)·상자(`.m-i`)는 첫 화면의 콘텐츠 영역과 같은 부품입니다 — 끌기·안내선·
   글자 고치기가 그대로 따라옵니다. 섹션이 화면 끝까지 가는 윗선·배경을 맡고, 판은 본문 폭 안에서
   좌표를 듭니다(지금 `.p-contact` 밖 / `.wrap` 안 구조와 같은 모양).

   옛 푸터(`.p-contact`)는 그대로 둡니다 — 「직접 디자인」 조각과 샘플 열 벌이 그것을 씁니다. */
.foot {
  margin-top: calc(var(--fgap, 0) * 1px);
  border-top: calc(var(--fline, 1) * 1px) solid var(--fline-c, var(--fg));
  background: var(--fbg, transparent);
}
/* board 에 좌우 여백을 주지 않습니다. 여백을 주면 좌표 0~1240 이 그 안쪽만 가리켜서,
   요소를 오른쪽 끝으로 끌어도 여백만큼 못 갑니다. 좌표계가 곧 보이는 띠여야 조작과 화면이 맞습니다.
   여백이 필요한 자리는 박스가 제 x 로 잡습니다(시작 배치는 40).
   폭은 생성기가 --foot-w 로 냅니다(bake.mjs 의 footW). 1240 을 넘지 않는 숫자입니다.
   여기서 min() 으로 깎지 않는 이유는 그 주석에 적혀 있습니다.
   좁은 화면(≤860)은 board 를 버리고 세로로 쌓으므로 그쪽에서 여백을 따로 줍니다 */
.foot > .m-board { max-width: var(--bw, 1240px); }

/* 아이콘 상자 — 지금 `.p-links a` 와 같은 값(52/32px, 테두리 1px, 모서리 25%) */
.foot .m-i[data-k='icon'] {
  width: calc(var(--sw, 52) * var(--u)); aspect-ratio: 1; padding: 0;
  display: grid; place-items: center;
  border: 1px solid var(--line); border-radius: 25%;
  color: var(--fg-2);
  transition: border-color var(--t), color var(--t), transform var(--t);
}
/* 도형이 상자를 꽉 채우는 쪽에 가깝게 — 46% 는 여백이 너무 넓어 로고가 작아 보였습니다. 60% 면 52px 상자에서 로고가 31px 입니다 */
.foot .m-i[data-k='icon'] svg { width: 60%; height: 60%; display: block; fill: currentColor; }
/* 판 밖으로는 안 나갑니다 — 글자 상자의 `max-width` 와 같은 셈입니다(x 가 오른쪽이면 남은 자리만큼만).
   상한이 96 이던 때는 눈에 안 띄었지만 칩은 600 까지 넓어집니다 */
.foot .m-i[data-k='icon'] { max-width: calc(100cqw - var(--sx, 0) * var(--u)); }
/* 「직접 입력」 — 로고가 없는 서비스는 쓴 이름이 곧 그림입니다. 그래서 이 아이콘만
   정사각이 아니다: 폭은 고른 크기가, 높이는 글자가 정합니다. 이름이 길면 말줄임으로 잘립니다.
   (관리자가 새 칩을 놓을 때 이름이 들어갈 만큼 넓게 놓습니다 — 좁히면 「…」만 남습니다) */
.foot .m-i[data-k='icon'][data-svc='link'] { aspect-ratio: auto; }
/* 여백은 글자 상자 안쪽에 줍니다. 바깥 `.m-i` 에 주면 그 `em` 이 물려받은 본문 글자(17px
   고정)라 판이 좁아져도 안 줄고, 굽기의 `CHIP_H` 셈과 11~47% 어긋납니다.
   여기 세 수(글자 15u · 줄 높이 1.1 · 위아래 0.7em)를 고치면 `bake.mjs` 의 `CHIP_H` 도 같이 고칩니다 */
.foot .m-i[data-k='icon'] .m-ico-t {
  display: block; box-sizing: border-box; padding: 0.7em 0.9em;
  font-family: var(--sans); font-weight: 700; font-size: max(12px, calc(15 * var(--u)));
  line-height: 1.1; letter-spacing: -0.02em; text-align: center;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
}
/* 갈 곳이 없는 아이콘 — 링크가 아니라 말하는 도형입니다(굽기가 `<span data-empty>` 로 냅니다).
   테두리를 점선으로 두어 눌러 보기 전에도 「아직 연결 안 됨」이 보입니다 */
.foot .m-i[data-k='icon'][data-empty] { cursor: default; border-style: dashed; }
/* 귀띔은 올리거나 누르면 뜹니다. 누름도 초점이라(`tabindex`) 손가락으로도 뜹니다 —
   방문자에게 JS 0바이트라 여는 일도 CSS 가 합니다 */
.foot .m-i[data-k='icon'][data-empty]::after {
  content: attr(data-tip); position: absolute; left: 50%; bottom: calc(100% + 0.5em); translate: -50% 0;
  padding: 0.35em 0.6em; border-radius: 6px; background: var(--fg); color: var(--bg);
  font-family: var(--sans); font-size: 12px; line-height: 1.3; white-space: nowrap;
  opacity: 0; pointer-events: none; transition: opacity var(--t);
}
.foot .m-i[data-k='icon'][data-empty]:is(:hover, :focus)::after { opacity: 1; }
/* 초점 테두리는 키보드로 왔을 때만 — 눌러서 귀띔을 띄운 자리에 굵은 테두리까지 얹으면
   눌린 것처럼 보입니다. 귀띔은 `:focus` 로 뜨고 테두리는 `:focus-visible` 로만 섭니다 */
.foot .m-i[data-k='icon'][data-empty]:focus { outline: none; }
.foot .m-i[data-k='icon'][data-empty]:focus-visible { outline: 2px solid var(--fg); outline-offset: 2px; }

/* 올리면 모양이 바뀝니다 — accent 가 전경색인 테마(그레이)에서도 보이게 들리고 테두리가 진해집니다 */
.foot .m-i[data-k='icon']:hover,
.foot .m-i[data-k='icon']:focus-visible { border-color: var(--fg); color: var(--fg); transform: translateY(-2px); }
.foot .m-i[data-k='icon']:focus-visible { outline: 2px solid var(--fg); outline-offset: 2px; }
/* 연락처 줄 — 지금 `.p-mail` 의 굵기·밑줄을 칸 위에 얹습니다(밑줄이 두꺼워지는 호버) */
.foot .m-i[data-s='display'] { font-weight: 800; letter-spacing: -0.03em; }
.foot .m-i[data-s='display'] a { border-bottom-width: 3px; border-bottom-color: var(--fg); padding-bottom: 0.12em;
  transition: border-bottom-width var(--t), border-bottom-color var(--t); }
.foot .m-i[data-s='display'] a:hover,
.foot .m-i[data-s='display'] a:focus-visible { border-bottom-width: 5px; }
/* 저작권 줄 — 지금 `.p-copy` 는 자간이 없습니다. 칸(label)의 0.14em 을 푸터에서만 되돌립니다 */
.foot .m-i[data-s='label'] { letter-spacing: 0; }

@media (prefers-reduced-motion: reduce) {
  .foot .m-i[data-k='icon'] { transition: border-color var(--t), color var(--t); }
  .foot .m-i[data-k='icon']:hover { transform: none; }
}

/* 좁은 화면 — 판을 버리고 쌓습니다(무대와 같은 규약).
   순수 y 순이면 아이콘(y180)이 저작권(y195)보다 먼저 섭니다. 굽기가 같은 줄끼리 묶어
   마크업 차례를 내므로 여기서는 흐름만 세웁니다. */
@media (max-width: 860px) {
  .foot > .m-board {
    position: static; aspect-ratio: auto; min-height: 0; max-width: none;
    display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem 0.8rem;
    padding: 2.5rem clamp(1.5rem, 5vw, 2.5rem) 2rem;
  }
  .foot .m-i { position: static; width: auto; max-width: 100%; }
  /* 판을 버린 자리에서 `.m-i` 는 `flex: 0 0 100%` 다(site.css) — flex-basis 가 width 를 이깁니다.
     아이콘에 width 만 주면 한 줄을 통째로 먹고 정사각이라 화면만큼 커집니다(시안에서 342px 로 실측) */
  .foot .m-i[data-s='display'] { flex: 1 0 100%; }
  .foot .m-i[data-k='icon'] { flex: 0 0 auto; width: 40px; margin-top: 0; }
  /* 「직접 입력」 칩은 정사각이 아닙니다 — 폭을 40 으로 못 박으면 이름이 「즈…」로 잘립니다
     (390px 실측). 쌓인 화면에서는 폭을 이름이 정합니다. 다만 긴 이름이 줄을 다 먹으면
     저작권이 서너 줄로 접혀 얇은 푸터가 도로 두꺼워지므로 절반에서 끊습니다 */
  .foot .m-i[data-k='icon'][data-svc='link'] { width: auto; max-width: 50%; }
  /* 무대의 「링크 상자는 나란히」(`.m-i:has(a)`)가 푸터에서는 글자를 아이콘 줄에 끼워 넣습니다 —
     전화번호가 GitHub 옆에 붙어 섭니다(390px 실측). 푸터에서 나란히 서는 것은 아이콘뿐입니다 */
  .foot .m-i:has(a):not([data-k='icon']) { flex: 0 0 100%; margin-top: 0; }
  /* 얇은 푸터는 쌓지 않습니다 — 쌓으면 다시 두꺼워집니다(지금 is-slim 주석과 같은 이유) */
  .foot[data-foot='pages'] > .m-board { padding: 0.65rem clamp(1.5rem, 5vw, 2.5rem); justify-content: space-between; }
  .foot[data-foot='pages'] .m-i[data-k='icon'] { width: 32px; }
  /* 얇은 푸터는 한 줄을 지킵니다: 글자가 남는 자리를 갖고 아이콘이 오른쪽 끝에 섭니다.
     글자에 100% 를 주면 아이콘이 아랫줄로 떨어져 푸터가 두 배가 됩니다(390px 에서 86px 로 실측).
     `1 1 auto` 로는 안 됩니다 — 늘어나기 전에 제 글의 최대 폭으로 자리를 재서, 저작권 한 줄이
     390px 에 안 들어가면 아이콘이 먼저 아랫줄로 밀립니다(실측 86px). `0` 으로 두면 남는 자리를
     받아 그 안에서 글이 접힙니다 */
  .foot[data-foot='pages'] .m-i:not([data-k='icon']) { flex: 1 1 0; }
}
