/* 시각 언어의 사실 출처는 docs/reference/ui.md 다. 값을 여기서 새로 정하지 않는다. */

:root {
  /* 브라우저가 기본 위젯(체크상자, 파일 고르기, 스크롤바)을 무슨 모드로 그릴지
     안다. 이것을 빼면 어두운 화면에 밝은 체크상자만 남는다 */
  color-scheme: light dark;

  /* 바탕. 페이지와 칸·단추가 함께 쓴다 */
  --bg: #fff;
  /* 액센트 위에 얹는 글자 */
  --on-accent: #fff;

  --ink: #221e1b;
  --ink-muted: #56524a;
  /* 아래 둘은 본문보다 작은 글자에 쓴다. 그래도 배경과 4.5:1 아래로 내려가지 않는다.
     시각·글쓴이·설명이 이 색이고, 그것들이 안 읽히면 목록이 제목만 남는다 */
  --ink-soft: #605b54;
  --ink-faint: #6f6a63;

  --accent: #bc4a1d;
  --accent-hover: #96380f;
  --wash: #f5e3d9;

  --surface: #f4f2ef;
  --line: #ddd9d3;
  /* 칸과 단추의 테두리. 그 테두리가 곧 "여기를 누른다" 는 유일한 표시라서, 선을
     가르는 --line 보다 진하다. 배경과 3:1 을 지킨다 */
  --line-control: #8d887f;
  --line-soft: #ece9e3;
  --line-faint: #f0ede7;

  --anon: #c6c1b9;

  --badge-owner-text: #8f3a20;
  --badge-owner-line: #d09b83;
  --badge-admin-text: #7d5a12;
  --badge-admin-line: #cfae66;

  --radius-badge: 3px;
  --radius-control: 6px;

  /* 클릭 대상의 최소 높이 */
  --tap: 44px;
  /* 글 아래 줄줄이 서는 조치 단추의 높이. 폼의 단추와 달리 여럿이 한 줄에 서므로
     44px 로 두면 본문보다 단추가 더 큰 자리를 차지한다. WCAG 2.2 AA 의 24px 위다 */
  --tap-compact: 32px;

  --font-title: "Hahmlet", "Apple Myungjo", "Nanum Myeongjo", serif;
  --font-body: "IBM Plex Sans KR", "Apple SD Gothic Neo", system-ui, sans-serif;
}

/* 어두운 모드. 보는 사람의 시스템 설정을 따른다. 화면 안의 전환 스위치는 두지 않는다.
   설정이 두 군데가 되면 어느 쪽이 이기는지 사람이 외워야 한다.

   값만 바꾼다. 아래의 규칙은 전부 토큰을 거치므로 이 블록 하나로 끝난다. 색을 직접
   적은 규칙이 하나라도 있으면 그 자리만 밝은 채로 남는다.

   대비 기준은 밝은 모드와 같다. 글자는 배경과 4.5:1, 칸과 단추의 테두리는 3:1 이다. */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #16130f;
    /* 액센트가 밝아서 그 위의 글자는 어두워야 한다. 흰 글자면 3.3:1 로 떨어진다 */
    --on-accent: #16130f;

    --ink: #ece7df;
    --ink-muted: #c4bdb2;
    --ink-soft: #a9a297;
    --ink-faint: #968f85;

    /* 어두운 바탕에서는 액센트도 밝아야 링크로 읽힌다. 밝은 모드의 감색을 그대로
       쓰면 4.5:1 아래로 내려간다 */
    --accent: #e26a3a;
    --accent-hover: #ea7f52;
    --wash: #3a2418;

    --surface: #201c17;
    --line: #35302a;
    --line-control: #7a736a;
    --line-soft: #2a251f;
    --line-faint: #241f1a;

    --anon: #4a453e;

    --badge-owner-text: #e8a68d;
    --badge-owner-line: #7a4b39;
    --badge-admin-text: #e5c07b;
    --badge-admin-line: #6f5a2c;
  }
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
  margin: 0;
  font-family: var(--font-title);
  font-weight: 600;
  line-height: 1.3;
}

h1 {
  font-size: 1.6rem;
}
h2 {
  font-size: 1.15rem;
}

p {
  margin: 0;
}

a {
  color: var(--accent);
  text-decoration: none;
}
a:hover {
  color: var(--accent-hover);
  text-decoration: underline;
}

/* 형제 간격은 flex/grid 의 gap 으로 만든다. margin 으로 만들지 않는다 */
.stack {
  display: flex;
  flex-direction: column;
}
/* 방향을 못 박는다. 적지 않으면 label 처럼 스스로 column 을 정하는 요소에 .row 를
   붙였을 때 그쪽이 이긴다. 체크상자와 그 글이 위아래로 갈라져 있었다 */
.row {
  display: flex;
  flex-direction: row;
  align-items: center;
}
.gap-1 {
  gap: 0.35rem;
}
.gap-2 {
  gap: 0.7rem;
}
.gap-3 {
  gap: 1.2rem;
}
.grow {
  flex: 1;
}
.wrap {
  flex-wrap: wrap;
}
/* 체크상자 한 줄처럼 글자만 있는 것도 손가락이 닿는 높이를 지킨다 */
.tap {
  min-height: var(--tap);
}
/* 초대 주소처럼 띄어쓰기 없이 긴 문자열. 줄을 넘기지 않으면 가로로 화면을 밀어낸다 */
.breakable {
  word-break: break-all;
}
/* 테두리 없는 묶음. fieldset 의 기본 테두리와 안쪽 여백을 지운다 */
.group {
  border: none;
  padding: 0;
}
.group > legend {
  padding: 0;
}

.page {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  max-width: 46rem;
  padding: 1.5rem 1.25rem 3rem;
  margin: 0 auto;
}

/* 게시판 목록이 붙는 화면은 한 단 더 넓다. 46rem 은 좌측 목록을 세우면 본문이 좁다 */
.page.wide {
  max-width: 62rem;
}

/* 넓게 보기. 계정 화면에서 켜면 <html> 에 표시가 붙는다.
   특성도가 (0,3,0) 이라 (0,2,0) 인 `.page.wide` 를 순서와 상관없이 이긴다.
   안쪽 여백은 그대로 둔다. 지우면 글자가 창 모서리에 붙는다 */
:root[data-width="full"] .page {
  max-width: none;
}

/* 커뮤니티와 게시판 화면은 게시판 목록을 왼쪽에 세운다 */
.with-nav {
  display: grid;
  grid-template-columns: 13rem minmax(0, 1fr);
  gap: 1.5rem;
  align-items: start;
}

.board-nav {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  position: sticky;
  top: 1rem;
}

/* 좌측 목록의 묶음 제목 */
.nav-heading {
  padding: 0 0.5rem 0.3rem;
  border-bottom: 1px solid var(--line-soft);
  color: var(--ink-soft);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.04em;
}

.nav-boards {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

/* 접힌 줄의 손잡이. 넓은 화면에는 없다. 목록이 왼쪽에 그대로 서기 때문이다 */
.nav-summary {
  display: none;
  gap: 0.5rem;
  justify-content: flex-start;
  min-height: var(--tap);
}

/* 접힌 줄이 말하는 지금 자리. 빵부스러기 노릇을 함께 한다 */
.nav-here {
  color: var(--ink);
  font-size: 0.9rem;
  font-weight: 500;
  text-align: left;
}

.nav-summary .nav-heading {
  border-bottom: none;
  padding: 0;
}

/* 좁은 화면에서는 목록이 본문 위로 올라온다.
   이 블록은 .board-nav 정의보다 뒤에 와야 한다. 앞에 두면 특정성이 같아 아래의
   position: sticky 가 이기고, 겹침이 그대로 남는다 */
@media (max-width: 46rem) {
  .with-nav {
    grid-template-columns: minmax(0, 1fr);
  }

  /* 한 단이 되면 sticky 를 푼다. 그대로 두면 목록이 화면에 붙어 있고 본문이 그 아래를
     지나가 글자끼리 겹쳐 그려진다 */
  .board-nav {
    position: static;
    gap: 0;
  }

  /* 접고 펴는 것은 여기서만 있는 일이다. 화면 폭을 아는 자리를 CSS 하나로 둔다 */
  .nav-summary {
    display: flex;
    border: 1px solid var(--line-control);
    border-radius: var(--radius-control);
    padding: 0 0.7rem;
  }

  .board-nav[data-open="false"] .nav-body {
    display: none;
  }

  .nav-body {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    /* 게시판이 스무 개면 목록만으로 첫 화면이 다 찬다. 높이를 묶고 목록 안에서
       스크롤하게 해 본문이 화면에 함께 들어오게 한다 */
    max-height: 45vh;
    overflow-y: auto;
    /* 잘린 것이 아니라 더 있다는 신호 */
    border-bottom: 1px solid var(--line-soft);
    padding: 0.6rem 0;
  }
}

.nav-group {
  display: flex;
  flex-direction: column;
}

/* 카테고리 이름은 버튼이다. 눌러서 접고 편다 */
.nav-toggle {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  justify-content: flex-start;
  background: none;
  border: none;
  padding: 0 0.5rem;
  color: var(--ink-soft);
  font-size: 0.85rem;
  font-weight: 600;
}
.nav-toggle:hover:not(:disabled) {
  background: none;
  color: var(--accent-hover);
}

/* 관리 패널의 한 묶음. 카테고리 하나와 그 안의 게시판이 함께 선다 */
.structure-group {
  border-top: 1px solid var(--line-soft);
  padding-top: 0.6rem;
}

/* 접는 묶음의 손잡이. `.menu`(⋯)와 `.editor`(카테고리·게시판)가 함께 쓴다.
   summary 는 기본으로 삼각형 표식을 달고 세로로 쌓인다. 그것을 여기서 한 번만 지운다 */
details > summary {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: var(--tap-compact);
  border-radius: var(--radius-control);
  padding: 0 0.5rem;
  list-style: none;
  cursor: pointer;
  font-size: 0.82rem;
  font-weight: 500;
}
details > summary::-webkit-details-marker {
  display: none;
}

/* 카테고리와 게시판의 편집 줄. 이름만 보이고, 눌러야 편집 칸이 열린다.
   스무 개의 폼을 펼쳐 두면 관리 화면이 어디부터 보아야 할지 알 수 없는 벽이 된다.
   화면의 다른 폼들과 같은 규칙이다. 폼은 눌러야 열린다 */
.editor > summary {
  display: flex;
  padding-left: 0.4rem;
  font-size: 1em;
}
.editor > summary:hover {
  background: var(--line-soft);
}

/* 펼침 표시는 좌측 목록의 카테고리와 같은 갈매기다. 열리면 아래를 가리킨다 */
.editor > summary .icon {
  color: var(--ink-faint);
}
.editor[open] > summary .icon {
  transform: rotate(90deg);
}

/* 편집 칸은 이름보다 한 단 안으로 들어간다. 어느 줄의 칸인지 보이게 한다 */
.editor-body {
  padding: 0.4rem 0 0.6rem 1.45rem;
}

.structure-board {
  padding-left: 1.2rem;
}

/* 칸이 좁아지면 함께 줄어든다. 기본 너비가 남아 있으면 줄마다 단추가 흩어진다 */
.structure-group input[type="text"],
.structure-group select {
  min-width: 6rem;
  flex: 1;
}

/* 주소는 고칠 수 없는 값이라 짧게 둔다 */
.structure-board .slug {
  flex: 0 0 auto;
  color: var(--ink-faint);
  font-size: 0.8rem;
}

/* 목록 줄·빵부스러기의 작은 메타 글자. 인라인 font-size 를 대신한다 */
.meta {
  color: var(--ink-faint);
  font-size: 0.8rem;
}

/* 눈에는 보이지 않고 스크린리더만 읽는 글자. display:none 과 visibility:hidden 은
   스크린리더도 함께 건너뛰므로 쓰지 못한다 */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* 목록의 익명 글쓴이 이름.
   닉네임은 자유 문자열이라 "익명3" 을 자기 닉으로 삼을 수 있다. 목록에는 아바타가 없어
   글씨 모양이 진짜 익명 글을 가리는 유일한 단서다.
   opacity 로 흐리게 하지 않는다. .meta 가 이미 옅은 색이라 거기서 더 낮추면 대비가
   AA 아래로 떨어진다. 기울임만으로 가른다. */
.anon-name {
  font-style: italic;
}

/* 이 화면이 무엇 아래에 있는지. 커뮤니티 링크는 좌측 목록이 맡는다 */
.crumbs {
  color: var(--ink-soft);
  font-size: 0.85rem;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 1.2rem;
  border-bottom: 1px solid var(--line);
  padding: 0 1.5rem;
  height: var(--tap);
}

.site-nav a {
  display: flex;
  align-items: center;
  height: 100%;
  color: var(--ink-muted);
  font-weight: 500;
}
.site-nav a:hover {
  color: var(--accent-hover);
  text-decoration: none;
}

.muted {
  color: var(--ink-muted);
}
.soft {
  color: var(--ink-soft);
}
.faint {
  color: var(--ink-faint);
}
.error {
  color: var(--accent-hover);
}

.panel {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-control);
  padding: 0.9rem;
}

/* 글 */

/* 줄바꿈을 그대로 보인다. 글쓴이가 나눈 문단을 화면이 한 덩어리로 붙이지 않는다.
   긴 낱말 하나가 가로 스크롤을 만들지 않게 함께 끊는다 */
.post-body {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  margin: 0;
}

/* 본문은 줄 단위로 그려진다. 빈 줄도 자리를 차지해야 원문과 같아 보인다 */
.post-body p {
  margin: 0;
  min-height: 1lh;
}

/* 올린 이미지가 화면을 넘지 않게 한다. 세로도 제한해 긴 이미지가 글을 밀어내지 않는다 */
.post-image {
  max-width: 100%;
  max-height: 30rem;
  border-radius: 0.5rem;
  margin: 0.5rem 0;
}

/* 대댓글은 한 단만 들어간다. 깊이를 열지 않으므로 단도 하나뿐이다 */
.list > li.reply {
  padding-left: 1.6rem;
  border-left: 2px solid var(--line-faint);
}

/* 글과 댓글은 세로로 쌓인다. 한 줄에 붙이는 목록과 달리 위쪽에 맞춘다 */
.list > li:has(.post-body) {
  align-items: stretch;
}

/* 목록 */
.list {
  display: flex;
  flex-direction: column;
  list-style: none;
  padding: 0;
  margin: 0;
}

.list > li {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  min-height: 2.25rem;
  border-bottom: 1px solid var(--line-faint);
  padding: 0.45rem 0.5rem;
  border-radius: var(--radius-control);
}

.list > li:last-child {
  border-bottom: none;
}

/* 세는 값(조회·개추)을 오른쪽 고정 폭 열로 세운다.
   메타를 가운뎃점으로 이어 붙이면 0 인 값이 빠지는 규칙 때문에 줄마다 조각 수가 달라,
   같은 뜻의 숫자가 매 줄 다른 자리에 선다. 세로로 훑을 축이 없어진다.

   0 을 적지 않는 규칙은 그대로다. 빈 칸이 곧 "셀 것이 없다" 다. 눈에는 빈 칸이지만
   스크린리더에는 이름이 필요하므로 숫자 앞에 `.visually-hidden` 으로 열 이름을 싣는다 */
.metric {
  display: flex;
  justify-content: flex-end;
  width: 3.5rem;
  flex: none;
  color: var(--ink-faint);
  font-size: 0.8rem;
  /* 숫자 폭이 고정이라 자릿수가 늘어도 열이 흔들리지 않는다 */
  font-variant-numeric: tabular-nums;
}

/* 숫자 열이 붙는 줄의 링크는 가로로 선다. 줄 전체가 누를 자리라는 규칙을 지키려면
   숫자도 링크 안에 있어야 한다 */
.card-link.metered {
  flex-direction: row;
  align-items: center;
  gap: 0.8rem;
}

/* 목록 위의 열 이름. 줄과 같은 간격·같은 안쪽 여백이라야 숫자와 세로로 맞는다 */
.list-head {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  border-bottom: 1px solid var(--line);
  padding: 0 0.5rem 0.35rem;
}

.list-head .metric {
  color: var(--ink-soft);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.04em;
}

/* 좁은 화면에서는 열 하나만 남긴다. 둘을 두면 390px 에서 제목을 너무 밀어낸다.
   display:none 은 스크린리더까지 지워 개추 수가 아예 사라지므로, 자리만 없애고
   글자는 남긴다. 사라진 열이 남기는 gap 은 음수 여백으로 되돌린다 */
@media (max-width: 46rem) {
  .metric.upvotes {
    width: 0;
    margin-left: -0.8rem;
    overflow: hidden;
    clip-path: inset(50%);
  }
}

/* 마지막으로 들른 뒤 올라온 글.
   알림 목록의 안 읽음(`.list > li.unread`)과 같은 규칙이다. 색 하나로만 가르지 않는다.
   글자로도 실어야 하는 표시라 화면이 `.visually-hidden` 을 함께 낸다 */
.list > li.fresh {
  border-left: 3px solid var(--accent);
  padding-left: 0.75rem;
}

/* 이미 지난 글의 제목. 새 글보다 한 단 물러난다.
   흐리게가 아니라 덜 굵게 가른다. `--ink-muted` 는 배경과 4.5:1 위다 */
.card-title.seen {
  color: var(--ink-muted);
  font-weight: 500;
}

/* 좌측 목록의 "새 글 있음" 점.
   점만으로 가르지 않도록 화면이 `.visually-hidden` 으로 "새 글" 을 함께 낸다 */
.new-dot {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
}

/* 목록을 기다리는 동안 세우는 줄 골격.
   "불러오는 중…" 한 줄로 두면 목록이 들어오는 순간 화면이 그만큼 튄다 */
.skeleton {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  flex: 1;
}

.skeleton > span {
  height: 0.7rem;
  border-radius: var(--radius-badge);
  background: var(--line-soft);
}

.skeleton > span.short {
  height: 0.6rem;
  width: 30%;
}

/* 좌측 목록의 줄은 본문 목록보다 촘촘하다. 한 화면에 더 담아야 한다 */
.nav-list > li {
  min-height: 2rem;
  border-bottom: none;
  padding: 0.2rem 0.5rem;
}

/* 좌측 목록의 현재 위치. 라우터가 붙이는 aria-current 하나를 표시의 출처로 쓴다.
   클래스와 속성 둘로 표시하면 한쪽만 갱신되는 순간이 생긴다 */
.nav-list > li:has(> a[aria-current="page"]) {
  background: var(--wash);
}

/* 이름과 표시가 한 줄에 서는 링크. 좌측 목록의 게시판 줄이 쓴다 */
.card-link.row-link {
  flex-direction: row;
  align-items: center;
  gap: 0.4rem;
}

/* 커뮤니티 목록의 한 줄은 통째로 클릭 대상이다 */
.card-link {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  flex: 1;
  color: inherit;
}
.card-link:hover {
  text-decoration: none;
}
.card-link:hover .card-title {
  color: var(--accent-hover);
}

/* 갈 곳 없는 줄도 모양을 맞추려 같은 클래스를 쓴다. 누를 수 없는 것이 눌리는 것처럼
   반응하면 안 되므로 손 모양과 밑줄만 되돌린다 */
span.card-link {
  cursor: default;
}
span.card-link:hover .card-title {
  color: inherit;
}
.card-title {
  font-family: var(--font-title);
  font-weight: 600;
  color: var(--ink);
}
/* .card-title 뒤에 온다. 앞에 두면 글꼴 규칙이 색을 다시 덮는다 */
span.card-link .card-title {
  color: var(--ink-faint);
}

/* 댓글 목록 앞의 머리. 개수와 쓰는 자리가 한 줄에 선다 */
.comments-head {
  border-bottom: 1px solid var(--line);
  padding-bottom: 0.4rem;
}

/* 개추가 되돌릴 수 없다는 사전 고지. 단추 줄 다음에 제 줄로 선다 */
.vote-notice {
  flex-basis: 100%;
}

/* 검색 결과 줄의 본문 발췌. 제목과 메타 사이에 한 줄로 선다 */
.snippet {
  color: var(--ink-muted);
  font-size: 0.85rem;
  line-height: 1.5;
}

/* 발췌 안에서 찾은 말. 색만으로 가르지 않도록 굵기도 함께 올린다.
   브라우저 기본 mark 는 노란 바탕에 검은 글씨라 어두운 모드에서 홀로 밝게 남는다 */
mark {
  background: var(--wash);
  color: var(--badge-owner-text);
  border-radius: var(--radius-badge);
  padding: 0 0.1rem;
  font-weight: 600;
}

/* 쓰다 만 글이 남았음을 알리는 줄. 폼이 닫힌 자리에 선다.
   알림의 안 읽음·글타래의 flash 와 같이 왼쪽 표시를 함께 둔다. 색만으로 가르지 않는다 */
.draft-resume {
  background: var(--wash);
  border: 1px solid var(--badge-owner-line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-control);
  padding: 0.7rem 0.9rem;
}

/* 배지 */
.badge {
  display: inline-flex;
  align-items: center;
  border: 1px solid;
  border-radius: var(--radius-badge);
  padding: 0 0.4rem;
  font-size: 0.72rem;
  font-weight: 500;
  line-height: 1.5rem;
  white-space: nowrap;
}

.badge-owner {
  color: var(--badge-owner-text);
  border-color: var(--badge-owner-line);
}

/* 읽은 뒤 붙은 댓글 수. 글 전체의 댓글 수(`.count`)와 다른 값이라 모양도 다르다.
   `.badge` 의 `border` 단축 속성이 테두리 색을 되돌리므로 그 뒤에 와야 한다 */
.badge-new {
  color: var(--badge-owner-text);
  border-color: var(--badge-owner-line);
}
.badge-admin {
  color: var(--badge-admin-text);
  border-color: var(--badge-admin-line);
}
.badge-other {
  color: var(--ink-soft);
  border-color: var(--line);
}

/* 아바타. 익명 아바타는 계정별로 다르게 하지 않는다 */
.avatar {
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  object-fit: cover;
  background: var(--line-soft);
  flex: none;
}
.avatar-anon {
  background: var(--anon);
}
/* 사진을 올리지 않은 멤버. 익명의 빈 원과 구분된다 */
.avatar-initial {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--wash);
  color: var(--ink-muted);
  font-size: 0.9rem;
  font-weight: 600;
}

/* 입력 */
label {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--ink-muted);
}

input[type="text"],
textarea,
select {
  min-height: var(--tap);
  border: 1px solid var(--line-control);
  border-radius: var(--radius-control);
  padding: 0.6rem 0.7rem;
  background: var(--bg);
  color: var(--ink);
  font-family: inherit;
  font-size: 15px;
}

textarea {
  min-height: 5rem;
  resize: vertical;
}

input::placeholder,
textarea::placeholder {
  color: var(--ink-faint);
}

input:focus-visible,
textarea:focus-visible,
select:focus-visible,
button:focus-visible,
a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.hint {
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--ink-soft);
}

/* 키보드로 들어온 사람이 좌측 목록 스무 줄을 지나지 않고 본문으로 간다.
   초점을 받기 전까지는 화면 밖에 둔다 */
.skip-link {
  position: absolute;
  left: -9999px;
  z-index: 10;
  background: var(--bg);
  border: 1px solid var(--line-control);
  border-radius: var(--radius-control);
  padding: 0.6rem 0.9rem;
}
.skip-link:focus {
  left: 0.5rem;
  top: 0.5rem;
}

/* 버튼 */
button,
a.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  min-height: var(--tap);
  border: 1px solid var(--line-control);
  border-radius: var(--radius-control);
  padding: 0 0.9rem;
  background: var(--bg);
  color: var(--ink);
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
}

button:hover:not(:disabled),
a.button:hover {
  border-color: var(--ink-faint);
  text-decoration: none;
}

button.primary,
a.button.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
button.primary:hover:not(:disabled),
a.button.primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

/* 네비게이션의 링크 색 규칙이 단추 모양을 덮지 않게 한다. 같은 특성이면 뒤에 온
   쪽이 이기므로, 이 규칙은 .site-nav a 정의보다 뒤에 있어야 한다 */
.site-nav a.button {
  height: auto;
  color: var(--ink);
}
.site-nav a.button.primary {
  color: var(--on-accent);
}

/* 로그인 흐름이 남긴 문구를 앱 위에 한 줄로 놓는다 */
.banner {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  border-bottom: 1px solid var(--line);
  background: var(--line-soft);
  padding: 0.5rem 1.5rem;
}

button:disabled {
  color: var(--ink-faint);
  cursor: not-allowed;
}

/* 강조 버튼도 잠기면 강조를 잃는다. 색만 흐려지면 눌리는 것처럼 보인다 */
button.primary:disabled {
  background: var(--line-soft);
  border-color: var(--line);
}

/* 선택지를 라디오 대신 카드로 보인다 */
.choice {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  flex: 1;
  min-height: var(--tap);
  border: 1px solid var(--line-control);
  border-radius: var(--radius-control);
  padding: 0.7rem 0.8rem;
  background: var(--bg);
  cursor: pointer;
  font-weight: 400;
  color: var(--ink);
}

.choice.selected {
  background: var(--wash);
  border-color: var(--badge-owner-line);
}

.choice input {
  margin: 0.35rem 0 0;
  accent-color: var(--accent);
}

.choice-title {
  font-weight: 500;
}

.icon {
  width: 1.05rem;
  height: 1.05rem;
  flex: none;
  stroke: currentColor;
  stroke-width: 1.6;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* 제목 줄에 섞여 서는 작은 아이콘. 글자 크기에 맞춰 줄어든다 */
.icon-inline {
  width: 0.9rem;
  height: 0.9rem;
  color: var(--ink-faint);
}

.count {
  color: var(--accent);
  font-weight: 600;
}

/* 안 읽은 알림은 왼쪽에 표시를 둔다. 색만으로 구별하지 않는다 */
.list > li.unread {
  border-left: 3px solid var(--accent, currentColor);
  padding-left: 0.75rem;
}

/* 개추와 비추. 두 수는 서로를 깎지 않으므로 단추도 나란히 둔다 */
.vote[aria-pressed="true"] {
  background: var(--wash);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}

/* 멤버가 아니거나 자기 글이면 개수만 읽는 자리가 된다. 흐리게만 두면 왜 눌리지
   않는지 알 수 없으므로 커서도 함께 바꾼다 */
.vote:disabled {
  cursor: default;
}

/* 한 줄에 여럿이 서는 조치 단추.
   글·댓글 아래, 멤버 줄, 신고 대기열, 초대 링크, 게시판 관리가 쓴다. 늘 보여야 하는
   것만 밖에 두고 나머지는 `.menu` 안으로 접는다. 여기 서는 단추는 폼의 단추보다 작다 */
.actions button,
.actions a.button,
.actions input[type="text"],
.actions select {
  min-height: var(--tap-compact);
  padding: 0 0.6rem;
  font-size: 0.82rem;
}

/* 접어 두는 조치 묶음. `details` 가 여닫이를 맡으므로 여는 상태를 신호로 들지 않는다.
   ponytail: 바깥을 눌러도 닫히지 않는다. 닫으려면 ⋯ 를 다시 누른다. 문서 전체의
   클릭을 듣는 자리가 생기면 그때 옮긴다 */
.menu {
  position: relative;
}

/* ⋯ 손잡이는 단추처럼 보인다. 공통 손잡이 규칙에 테두리만 얹는다 */
.menu > summary {
  justify-content: center;
  border: 1px solid var(--line-control);
  padding: 0 0.6rem;
}
.menu > summary:hover {
  border-color: var(--ink-faint);
}
.menu[open] > summary {
  background: var(--wash);
  border-color: var(--accent);
}

/* 열린 묶음은 본문 위에 뜬다. 자리를 밀어내면 누를 때마다 아래 댓글이 내려간다 */
.menu-body {
  position: absolute;
  right: 0;
  top: calc(100% + 0.25rem);
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.25rem;
  min-width: 16rem;
  max-width: calc(100vw - 2rem);
  background: var(--bg);
  border: 1px solid var(--line-control);
  border-radius: var(--radius-control);
  padding: 0.4rem;
}

/* 좁은 화면에서는 띄우지 않는다. 16rem 짜리 상자를 ⋯ 오른쪽 끝에 맞춰 띄우면 화면
   왼쪽 밖으로 밀려 나가 잘린다. 자리를 차지하더라도 다 보이는 편이 낫다 */
@media (max-width: 46rem) {
  /* 열린 묶음은 제 줄을 통째로 쓴다. 다른 단추와 한 줄에 두면 그 단추들이 상자 높이에
     맞춰 가운데로 밀려 어느 줄의 것인지 알아볼 수 없다 */
  .menu[open] {
    flex: 1 0 100%;
  }

  .menu-body {
    position: static;
    min-width: 0;
    max-width: none;
    margin-top: 0.25rem;
  }
}

/* 묶음 안에서는 단추가 한 줄을 통째로 쓴다. 글자는 왼쪽에 붙는다 */
.menu-body button,
.menu-body a.button {
  justify-content: flex-start;
  border-color: transparent;
}
.menu-body button:hover:not(:disabled) {
  background: var(--wash);
  border-color: transparent;
}

/* 사유 칸이 열리면 그 줄만 세로로 쌓인다 */
.menu-body .row {
  flex-wrap: wrap;
  gap: 0.25rem;
}
.menu-body input[type="text"],
.menu-body select {
  flex: 1;
  min-width: 0;
}

/* 글자수를 적어 두는 칸.
   표시는 칸 안 오른쪽 끝에 겹쳐 놓는다. 옆에 나란히 세우면 조치 줄처럼 좁은 자리에서
   칸을 그만큼 밀어낸다. 겹치는 만큼 칸의 오른쪽 여백을 넓혀 글자가 표시 밑으로
   들어가지 않게 한다 */
.field {
  position: relative;
  /* inline 이라야 조치 줄에서 단추와 같은 줄에 선다. 블록이면 줄을 통째로 차지해
     옆의 단추가 아래로 밀린다 */
  display: inline-flex;
  vertical-align: middle;
}

.field > input {
  flex: 1;
  min-width: 0;
  padding-right: 3.4rem;
}

.field-count {
  position: absolute;
  right: 0.5rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--ink-faint);
  font-size: 0.75rem;
  /* 숫자 폭이 고정이라 한 자 늘 때마다 표시가 흔들리지 않는다 */
  font-variant-numeric: tabular-nums;
  /* 표시를 눌러도 칸에 초점이 가야 한다 */
  pointer-events: none;
}

/* 최소를 못 채웠거나 최대를 넘긴 칸. 단추가 눌리지 않는 이유가 여기 있다 */
.field-count.short {
  color: var(--ink-muted);
}

/* 접은 묶음 안에서는 칸이 남은 폭을 먹는다. 감싼 상자가 그 자리를 이어받는다 */
.menu-body .field {
  flex: 1;
  min-width: 0;
}

/* 조치 줄의 칸은 위의 `.actions input` 규칙이 여백을 다시 잡는다. 표시 자리를 되돌린다 */
.actions .field > input,
.menu-body .field > input {
  padding-right: 3.4rem;
}

/* 커뮤니티 머리의 검색 칸.
   커뮤니티 아래 모든 화면 위에 선다. 본문보다 앞에 서지만 본문을 밀어내지 않게 얇다 */
.search-box {
  border: 1px solid var(--line-control);
  border-radius: var(--radius-control);
  padding: 0 0.6rem;
  background: var(--bg);
}

.search-box .icon {
  color: var(--ink-faint);
}

/* 칸 자체의 테두리는 지운다. 감싼 상자가 이미 테두리를 그린다 */
.search-box input[type="search"] {
  min-height: 2.25rem;
  border: none;
  background: none;
  padding: 0;
  color: var(--ink);
  font-family: inherit;
  font-size: 0.9rem;
}

/* 브라우저가 검색 칸에 지우기(x) 단추를 그린다. 그 단추는 글자가 끝나는 자리, 곧
   안쪽 여백이 시작하는 곳에 선다. 표시 자리로 비워 둔 여백만큼 x 를 오른쪽으로 밀어야
   표시가 x 의 왼쪽에 온다. 밀지 않으면 순서가 뒤집혀 x 가 안쪽에 갇힌다.

   검색 칸의 표시는 한 글자일 때만 뜬다. 표시가 없는 동안까지 자리를 비워 두면 글자
   끝과 x 사이가 늘 벌어지고 x 도 안쪽으로 밀린 채 남는다. 표시가 있을 때만 건다 */
.search-box .field:has(> .field-count) > input {
  padding-right: 4.6rem;
}
.search-box .field:has(> .field-count) > input::-webkit-search-cancel-button {
  transform: translateX(3.4rem);
}
.search-box .field-count {
  right: 2.3rem;
}

/* 초점 표시는 감싼 상자가 받는다. 안쪽 칸이 따로 받으면 테두리 안에 테두리가 그려진다 */
.search-box input[type="search"]:focus-visible {
  outline: none;
}
.search-box:focus-within {
  border-color: var(--accent);
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* 설정의 갈래 목록.
   링크라서 가운데 클릭과 새 탭이 통하고, 뒤로 가기가 갈래를 되짚는다. 지금 갈래 표시는
   `aria-current` 하나에 건다. 클래스와 속성 둘로 표시하면 한쪽만 갱신되는 순간이 생긴다 */
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem;
  border-bottom: 1px solid var(--line);
}

.tabs a {
  display: inline-flex;
  align-items: center;
  min-height: 2.5rem;
  padding: 0 0.8rem;
  border-bottom: 2px solid transparent;
  color: var(--ink-muted);
  font-size: 0.9rem;
  font-weight: 500;
}
.tabs a:hover {
  color: var(--accent-hover);
  text-decoration: none;
}
.tabs a[aria-current="page"] {
  border-bottom-color: var(--accent);
  color: var(--ink);
  font-weight: 600;
}

/* 목록 아래의 쪽 번호 줄.
   칸이 링크라서 가운데 클릭과 새 탭이 통하고, 뒤로 가기가 보던 쪽으로 되돌아온다.
   지금 쪽 표시는 `.tabs` 와 같이 `aria-current` 하나에 건다.

   칸 크기는 --tap 이 아니라 --tap-compact 다. 번호 열 넷에 화살표 넷이라 44px 로 두면
   좁은 화면에서 줄이 두 줄로 접힌다 */
.pager {
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 0.5rem;
}

.page-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tap-compact);
  min-height: var(--tap-compact);
  padding: 0 0.35rem;
  border-radius: var(--radius-control);
  color: var(--ink-muted);
  font-size: 0.9rem;
  font-variant-numeric: tabular-nums;
}
.page-num:hover {
  background: var(--surface);
  color: var(--accent-hover);
  text-decoration: none;
}
.page-num[aria-current="page"] {
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 600;
}

/* 갈 곳이 없는 화살표. 링크가 아니라 글자만 남으므로 눌리지도, 초점을 받지도 않는다 */
.page-num.off {
  color: var(--ink-faint);
  opacity: 0.45;
}

/* 알림에서 눌러 들어온 댓글. 스크롤만으로는 여러 댓글 가운데 어느 것인지 알 수 없다.
   색만으로 구별하지 않도록 왼쪽 표시를 함께 둔다. 번쩍였다 사라지지 않는다. 놓치면
   다시 볼 방법이 없다 */
.list > li.flash {
  background: var(--wash);
  border-left: 3px solid var(--accent);
  padding-left: 0.75rem;
}
