/* 두레박 — 도구 축 (디자인 가이드 §6.16 신설분) */

/* ── 브레드크럼 (도구 페이지 상단 — .back-link 와 같은 자리, 둘을 함께 쓰지 않는다)
   nowrap + 링크 flex:none 이 한 묶음이다: wrap 이면 축소보다 줄바꿈이 먼저라 말줄임이 발동하지 않고,
   nowrap 만 두면 링크가 먼저 찌그러져 터치 타깃이 무너진다(§2-5 실측). 줄어드는 것은 .here 뿐이다. ── */
.crumbs { display: flex; flex-wrap: nowrap; align-items: center; gap: 4px;
  margin: 0; padding: 0; font-size: var(--fs-aux); color: var(--label-2); }
.crumbs a { display: inline-flex; align-items: center; min-height: 44px; color: var(--tint); font-weight: 600; }
.crumbs a, .crumbs .sep { flex: none; }
.crumbs a:hover { text-decoration: none; }
.crumbs .sep { color: var(--faint); }
/* 현재 항목만 줄어든다. inline-flex 로 두면 계산된 display 가 flex 가 되어 text-overflow 가
   적용되지 않는다(텍스트가 … 없이 잘린다 — §2-5). 44px 터치 높이는 line-height 가 만든다. */
.crumbs .here { display: inline-block; line-height: 44px; min-width: 0;
  color: var(--label-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── 입력 필드 (카드 안 블록 — 라벨 축 B, 입력은 축 B 안쪽 전폭) ── */
.field { display: flex; flex-direction: column; gap: 6px; padding: 12px var(--inset); }
/* 카드 안에 성격이 다른 블록(행·필드·강조 행)이 섞이면 .row + .row 하나로는 구분선이 안 채워진다.
   세 조합을 전부 적어야 한다 — 빠진 자리만 선이 없어 렌더에서만 드러난다(§2-4). */
.field + .field, .row + .field, .field + .row { border-top: 0.5px solid var(--sep); }
.field > label { font-size: var(--fs-cap); font-weight: 600; color: var(--label-2); }
.field-in { display: flex; align-items: center; gap: var(--sp-2); }
/* 입력칸 옆에 버튼이 서는 경우(/number-guess/ 확인) — **버튼이 먼저 찌그러진다**: .f-input 이
   width:100% 라 flex 기준폭이 컨테이너 전체이고, 남는 것을 버튼이 뒤집어쓴다. 320px 실측에서
   "확인"이 두 글자가 세로로 감겼다(2026-08-20). 줄어드는 쪽을 입력칸으로 못박는다 —
   .crumbs 가 링크를 flex:none 으로 고정하고 .here 만 줄이는 것과 같은 처리다(6행). */
.field-in .f-input { flex: 1; min-width: 0; }
.field-in .btn { flex: none; white-space: nowrap; }
.f-input { width: 100%; min-height: 46px; padding: 10px 12px;
  border: 1px solid var(--ball-edge); border-radius: var(--r-xs);
  background: var(--bg); color: var(--label);
  font: inherit; font-size: var(--fs-body); font-variant-numeric: tabular-nums; }
.f-input::placeholder { color: var(--label-2); }
.f-input:focus { border-color: var(--tint); }
textarea.f-input { min-height: 168px; resize: vertical; line-height: 1.5; font-variant-numeric: normal; }

/* ── 날짜 3분할 입력 (연·월·일 — 날짜입력 개정 §5-3 · 0808-D34 ⓑ·D35 ⓐ) ────────────
   폭은 값 길이에 맞춘 고정폭이다. flex 로 늘리면 620px 에서 두 자리 숫자에 133px 상자가 된다(실측).
   320px 가용 256 에서 88+64+64+갭 16 = 232 로 성립한다(여유 24).
   새 색·새 크기 단계·새 반경을 만들지 않았다 — 입력 자체는 기존 .f-input 그대로다. */
fieldset.field { border: none; margin: 0; min-width: 0; }   /* fieldset UA 기본값 무력화 */
.date-parts { display: flex; align-items: flex-end; gap: var(--sp-2); }
/* align-items: flex-end 는 라벨 길이가 갈려도 입력 상자의 아랫변을 맞춘다 */
.date-part { display: flex; flex-direction: column; gap: 4px; flex: 0 0 auto; min-width: 0; }
.date-part > label { font-size: var(--fs-cap); font-weight: 600; color: var(--label-2); }
.date-part--y { width: 88px; }
.date-part--m, .date-part--d { width: 64px; }
.date-parts .f-input { width: 100%; text-align: center; }   /* 값이 짧아 가운데 정렬이 안정적이다 */

/* ── 결과 (강조 1행 = §6.4 카운트다운 행과 같은 metrics · 보조 행 = .row) ── */
.res-lead { display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--sp-3); padding: 14px var(--inset); }
.res-lead .rl-label { font-size: var(--fs-body); color: var(--label); }
.res-lead + .row { border-top: 0.5px solid var(--sep); }
.res-lead .rl-value { font-size: var(--fs-num); font-weight: 700; color: var(--label);
  font-variant-numeric: tabular-nums; }
.row .r-value.num { color: var(--label); font-weight: 600; font-variant-numeric: tabular-nums; }
/* 행 제목 뒤 성격 표기 — "세는 나이 (참고)" 처럼 값의 지위를 라벨이 말한다(§7-2) */
.row .r-title .note { color: var(--label-2); font-weight: 400; }
.is-empty { color: var(--faint); }

/* ── 인라인 경고 (§7) — 카드 아래(기본) / 필드 안(평↔㎡ 처럼 입력이 곧 결과인 화면) ── */
.f-error { margin: 0 var(--inset) 12px; padding: 8px 10px;
  background: var(--danger-bg); color: var(--danger);
  border-radius: var(--r-xs); font-size: var(--fs-aux); }
.field .f-error { margin: 0; }   /* .field 가 이미 --inset 패딩을 갖는다 — 이중 들여쓰기 방지 */

/* ── 그룹 안 카드 그리드 (비슷한 도구) — 그룹 헤더 다음이라 위 여백을 지운다 ── */
.group > .game-grid { margin-top: 0; }

/* ── 담은 날짜 행의 삭제 버튼 (D-day — §7-4) ────────────────────────────────
   명세 §4-15 CSS 전문에 없던 자리다. 같은 metrics(44×44 · --tint · :active 트랙)를 쓰는 선언이
   `generator.css` 의 `.record .rec-actions button` 에 이미 있으나 **그 셀렉터를 넓히는 것으로는
   닿지 않는다** — 도구 페이지는 generator.css 를 로드하지 않기 때문이다. 그 블록만 옮기려면
   `.record`·`.mynum-*` 행 어휘가 통째로 따라와야 해서 이관 비용이 이 4줄보다 크다.
   담은 기록(§6.12)이 이미 쓰는 값이므로 새 규칙이 아니라 같은 값을 도구 축에 세운 것이다. */
.dd-del {
  width: 44px; height: 44px; padding: 0; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; background: transparent; color: var(--tint); font-size: 1rem;
}
.dd-del:active { background: var(--track); border-radius: var(--r-xs); }

/* ── 모니터 배치 그림 (/monitor-size/) ────────────────────────────────────────
   §6.16 은 "새 어휘를 만들지 않는다"이고 이것이 그 예외다 — 정면 배치 그림은 행·카드·세그먼트 어느
   것으로도 그릴 수 없다. 대신 **새 색·새 크기 단계는 만들지 않았다**: 면 --tint-soft · 선 --tint ·
   책상 --label-2 · 초과 --danger 로 전부 기존 토큰이고, 다크는 토큰이 알아서 뒤집는다.
   높이를 CSS 가 고정하는 것이 이 블록의 핵심이다: viewBox 는 입력마다 바뀌므로(1대 ↔ 3대 ↔ 세로)
   높이를 내용에 맡기면 값을 칠 때마다 아래 콘텐츠가 밀린다(CLS). SVG 는 이 상자 안에서
   preserveAspectRatio="xMidYMid meet" 로 맞춰 그린다 — 그래서 어떤 배치든 상자 높이는 그대로다. */
.mon-stage { height: 176px; display: flex; align-items: center; justify-content: center; }
.mon-stage svg { display: block; width: 100%; height: 100%; }
.mon-stage__empty { margin: 0; color: var(--label-2); font-size: var(--fs-aux); text-align: center; }
/* 선 굵기는 비확대(non-scaling-stroke)라 cm 좌표계와 무관하게 1.5px 로 그려진다 — 49" 한 대와
   24" 세 대에서 테두리 굵기가 달라 보이지 않는다. */
.mon-panel { fill: var(--tint-soft); stroke: var(--tint); stroke-width: 1.5; }
.mon-label { fill: var(--tint); font-weight: 700; font-variant-numeric: tabular-nums; }
/* 패널 안 실치수(59.8 × 33.6cm) — 인치 라벨과 같은 --tint 라 대비도 같다(면 --tint-soft 위 실측 5.57:1
   라이트 · 5.12:1 다크). 굵기만 한 단 낮춰 "입력한 값(인치)"과 "계산된 값(cm)"의 층을 나눈다. */
.mon-size { fill: var(--tint); font-weight: 600; font-variant-numeric: tabular-nums; }
/* 총 가로폭 치수선 — 그림 위에 얹는 보조 정보라 카드 위 보조 텍스트와 같은 --label-2(실측 6.27:1 라이트 ·
   6.63:1 다크). 선 굵기는 패널 테두리(1.5)보다 얇게 둬서 화면 윤곽과 섞이지 않게 한다. */
.mon-dim { fill: var(--label-2); font-weight: 600; font-variant-numeric: tabular-nums; }
.mon-dim-line { stroke: var(--label-2); stroke-width: 1; }
.mon-desk { fill: var(--label-2); }
.mon-desk.is-over { fill: var(--danger); }
/* 책상 폭 부족 — 색은 보조 신호다. 값 자체가 "19.6cm 모자라요"라고 말한다(WCAG 1.4.1).
   **`.mon-over` 한 단짜리로 쓰면 죽는다**: 이 파일 52행의 `.row .r-value.num`(0,3,0)이 --label 로
   덮어써서 실측 computed color 가 rgb(28,28,30) 이었다. 같은 명시도(0,3,0)로 맞추고 그 뒤에 선언한다. */
.row .r-value.mon-over { color: var(--danger); }
/* 추천 섹션 자리 — 자리만 예약한다(내용은 게이트 후). 높이를 미리 잡아 두면 나중에 카드가 들어와도
   아래가 밀리지 않는다(.ad-slot 이 크기를 미리 잡는 것과 같은 이유 — §6.14). */
.mon-recs {
  min-height: 132px; padding: var(--sp-4) var(--inset);
  display: flex; align-items: center; justify-content: center;
  color: var(--label-2); font-size: var(--fs-cap); text-align: center;
}
.mon-recs p { margin: 0; }

/* ── 소품 스테이지 (/reaction-time/ · /click-speed/) ──────────────────────────
   두 도구가 같은 골격을 쓴다: **화면 하나가 곧 버튼**이고, 그 안의 두 줄(수치 + 안내)이 상태를 말한다.
   .card 로 감싸지 않고 <button> 자체가 카드 면이다 — 안에 행이 없으므로 면을 두 겹 만들 이유가 없다.
   높이를 고정하는 것이 이 블록의 핵심이다: 상태마다 글자 수가 갈리는데 높이를 내용에 맡기면
   신호가 뜰 때마다 아래 결과 카드가 밀린다(CLS).
   색은 상태의 **보조 신호**다 — 같은 자리의 글이 언제나 같은 사실을 말한다(WCAG 1.4.1).
   새 색을 만들지 않았다: 대기 --track · 신호 --tint-fill/--on-tint · 성급 --danger-bg/--danger 로
   전부 기존 토큰이고 다크는 토큰이 뒤집는다. :focus-visible 링은 outline-offset 2px 라 파란 면
   **바깥**(--bg)에 그려져 신호 상태에서도 보인다. */
.play-stage {
  width: 100%; min-height: 208px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  padding: var(--sp-5) var(--inset);
  border: none; border-radius: var(--r-md);
  background: var(--card); color: var(--label);
  text-align: center;
  /* 연타 도구다 — 글자가 드래그로 선택되거나 더블탭으로 확대되면 세는 것 자체가 방해받는다. */
  -webkit-user-select: none; user-select: none;
  touch-action: manipulation;
}
.play-stage__title { font-size: var(--fs-title); font-weight: 800; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
/* 남은 시간이 0.1초 단위로 바뀐다 — tabular-nums 가 아니면 글자폭이 흔들려 문구가 좌우로 떤다. */
.play-stage__note { font-size: var(--fs-aux); color: var(--label-2); font-variant-numeric: tabular-nums; }
.play-stage.is-wait { background: var(--track); }
.play-stage.is-go { background: var(--tint-fill); color: var(--on-tint); }
.play-stage.is-go .play-stage__note { color: var(--on-tint); }
.play-stage.is-early { background: var(--danger-bg); color: var(--danger); }
.play-stage.is-early .play-stage__note { color: var(--danger); }

/* ── 주사위 (/dice/) ──────────────────────────────────────────────────────────
   주사위 눈은 행·칩·볼 어느 어휘로도 그릴 수 없어 그림이 필요하다(.mon-stage 와 같은 판단).
   대신 **새 색·새 크기 단계는 만들지 않았다**: 몸통 --track · 테두리 --sep · 눈 --label 이다.
   트레이 높이는 최악의 경우(320px · 6개 = 두 줄)를 미리 잡는다 — 개수를 바꿀 때마다 아래가 밀리지
   않게. 한 줄 개수 = (카드 콘텐츠 256 + 갭 8) / (주사위 52 + 갭 8) = 4.4 → 4, 그래서 6개면 두 줄이고
   두 줄 높이 = 52×2 + 8 = 112 다(min-height 120 은 그 위 여유). 7개부터 줄이 늘어난다 → DICE_MAX 6. */
/* 동전(.coin-tray)이 같은 트레이를 쓴다 — 알 크기(52px)도 상한(6개)도 같아서 두 벌이 되면 한쪽만
   고쳐지는 자리가 생긴다. **복제하지 않고 그룹 셀렉터로 넓힌다**(엔티티 스위처 .game-switch/.tool-switch
   와 같은 처리 — base.css §6.1). 트레이가 늘면 여기 교대에 이름을 한 줄 더한다. */
.dice-tray, .coin-tray {
  display: flex; flex-wrap: wrap; align-items: center; align-content: center; justify-content: center;
  gap: var(--sp-2); min-height: 120px;
}
.dice-face { width: 52px; height: 52px; flex: none; display: block; }
.dice-body { fill: var(--track); stroke: var(--sep); stroke-width: 1; }
.dice-pip { fill: var(--label); }
/* 빈 트레이 안내 — 주사위·동전·무작위 숫자·낸 숫자가 같은 자리에서 같은 말을 한다. */
.dice-empty, .tray-empty { margin: 0; color: var(--label-2); font-size: var(--fs-aux); text-align: center; }

/* ── 동전 알 (/coin-flip/) ────────────────────────────────────────────────────
   주사위와 달리 SVG 를 쓰지 않는다: 앞뒤를 가르는 표식이 곧 글자라 도형이 필요 없고, viewBox 안의
   글자는 상자 크기가 바뀌면 배율이 따라 움직여 크기를 다시 재야 한다(글자는 px 로 그리는 편이 안전하다).
   지름은 주사위와 같은 52px — 같은 트레이를 쓰므로 두 줄 계산도 그대로다.
   **면은 보조 신호이고 뜻은 글자가 말한다**(WCAG 1.4.1). 그래도 두 면이 눈으로 갈려야 동전으로
   읽히는데, 첫 안(앞 --track · 뒤 --bg)이 **라이트에서 사실상 같은 색이었다**: --track 은
   rgba(120,120,128,0.12)이라 흰 카드 위에서 rgb(239,239,240)로 앉고 --bg 는 rgb(239,243,245)라
   차이가 (0,4,5) 였다(실측 2026-08-20 · 다크에서는 rgb(50,50,50) 대 검정이라 벌어져 있어 라이트만
   깨져 있었다). 채움과 테두리로 가른다 — 앞면은 --label-2 면에 --card 글자, 뒷면은 --card 면에
   --sep 테두리다. 면을 색 이름으로 쓰는 것은 이 파일 .mon-desk(책상 바)와 components.css .toast 의
   선례를 따른 것이고, 새 색은 하나도 만들지 않았다. */
.coin-face {
  width: 52px; height: 52px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--sep); border-radius: 50%;
  background: var(--card); color: var(--label);
  font-size: var(--fs-body); font-weight: 700;
}
.coin-face.is-heads { background: var(--label-2); color: var(--card); border-color: transparent; }

/* ── 알약 묶음 (/number-guess/ 낸 숫자 · /random-number/ 결과) ───────────────
   새 어휘를 만들지 않는다 — 알약 자체는 기존 .pill-val(base.css §6.11)이고 여기서 정하는 것은
   배치와 **예약 높이**뿐이다. 두 줄을 미리 잡는 이유는 첫 결과에서 아래 광고·산문이 밀리지 않게
   하려는 것이고(.dice-tray 와 같은 판단), 두 줄 높이는 알약 한 줄(패딩 3+3 + 13.6×1.45 ≈ 25.7)
   두 개와 갭 8 로 59.4 다 → 60. 세 줄째부터는 자리가 늘어나는데 그건 사용자가 누른 결과다. */
.pill-wrap {
  display: flex; flex-wrap: wrap; align-content: flex-start;
  gap: var(--sp-2); min-height: 60px;
}

/* ── 타자 제시문·입력칸 (/typing-speed/) ──────────────────────────────────────
   제시문 높이를 두 줄로 미리 잡는다 — 문장마다 길이가 갈리는데 높이를 내용에 맡기면 문장을 바꿀
   때마다 아래 입력칸과 결과가 밀린다. em 이라 글자 크기를 따라가고 매직 넘버가 없다.
   **두 줄인 것은 실측값이다**: 320px(clientWidth 305 · 카드 콘텐츠 241)에서 여덟 문장 중 가장 긴
   것("숫자 12345 와 영문 typing 이 섞인 문장이에요.")이 2줄 54px 이고 나머지는 1줄이다(2026-08-20).
   첫 안은 세 줄이었는데 대부분의 문장에서 한 줄이 빈 채로 남았다. 문장을 더할 때 이 하한을 다시 잰다.
   입력칸은 **`textarea.f-input--type` 로 적는다**: 17행의 `textarea.f-input`(0,1,1)이 min-height
   168px 를 걸어 두어 한 단짜리 `.f-input--type`(0,1,0)은 조용히 죽는다. 같은 명시도로 맞추고 뒤에
   선언한다(.mon-over 가 같은 함정에 걸렸던 자리 — 105행).
   100px 은 세 줄 높이다(17×1.5×3 = 76.5 + 패딩 20 + 테두리 2 = 98.5). 손잡이(resize)는 없앤다 —
   늘리면 아래가 밀리고, 세 줄이면 제시문 한 문장이 그대로 들어간다. */
.type-prompt { margin: 0; font-size: var(--fs-body); line-height: 1.6; min-height: calc(1.6em * 2); }
textarea.f-input--type { min-height: 100px; resize: none; }

/* ── 사다리 그림 (/ladder/) — 2026-08-21 재설계 ──────────────────────────────
   높이를 CSS 가 고정한다 — 참가자 수가 바뀔 때마다 상자가 커졌다 작아지면 아래 결과·광고가 밀린다
   (.mon-stage 와 같은 판단). 미리보기 ↔ 공개 전환에서도 같은 높이다.
   **SVG 를 걷고 절대 배치한 상자들로 그린다.** 다리를 직접 놓으려면 자리마다 누를 것이 있어야 하는데,
   SVG 도형을 버튼으로 만들면 포커스·라벨·비활성이 전부 손일이 된다. 상자로 그리면 자리가 진짜
   <button> 이고, 굵기는 px 이라 열 수가 바뀌어도 그대로다(구 SVG 가 non-scaling-stroke 로 얻던 성질).
   좌표는 백분율이다 — i번 기둥 (i+0.5)/n · i번 자리 (i+1)/n. 세로 위치는 JS 가 px 로 준다.
   새 색을 만들지 않았다: 기둥 --label-2 · 자동 다리 --label · **직접 놓은 다리 --tint**(사용자가 건드린
   것만 틴트다 — 틴트 1색 원칙과 어긋나지 않는다: 이 다리는 실제로 누를 수 있는 것이다) · 덮개 --track.
   **기둥에 --sep 를 쓰지 않는 이유는 실측이다**: 흰 카드 위 1.32:1(다크 1.66:1)이라 다리(17:1)만
   떠 보이고 기둥이 사라져 "떠 있는 선분"으로 읽혔다. --label-2 는 6.27:1 이라 기둥이 선다. */
.ladder-stage { height: 324px; display: flex; flex-direction: column; gap: var(--sp-1); }
.ladder-stage .tray-empty { margin: auto; }
.lad { position: relative; width: 100%; flex: none; }
.lad__line { position: absolute; top: 0; bottom: 0; width: 1.5px; margin-left: -0.75px; background: var(--label-2); }
.lad__rung { position: absolute; height: 2px; margin-top: -1px; background: var(--label); border-radius: 1px; }
/* 직접 놓은 다리는 한 단 굵고 틴트다 — 무엇이 내 손인지 그림에서 바로 갈린다. */
.lad__rung.is-mine { height: 3px; margin-top: -1.5px; background: var(--tint); }

/* 덮개 — "여기에 뭔가 놓인다"는 것만 말하고 어디인지는 말하지 않는다. 빗금은 광고 자리와 같은 결이라
   "아직 안 채워진 자리"로 읽힌다(--ad-a/--ad-b 를 그대로 쓴다 — 새 색이 아니다). */
.lad__band {
  position: absolute; left: 0; right: 0;
  border-radius: var(--r-xs);
  background: repeating-linear-gradient(135deg, var(--ad-a) 0 6px, var(--ad-b) 6px 12px);
}
/* 안내 문구는 기둥 위에 얹는다(덮개는 기둥 아래) — 그래야 기둥이 이어져 보이면서 글자는 안 잘린다. */
.lad__band-wrap { position: absolute; left: 0; right: 0; display: flex; align-items: center; justify-content: center; pointer-events: none; }
.lad__band-note { font-size: var(--fs-cap); color: var(--label-2); background: var(--card); padding: 2px 8px; border-radius: var(--r-xs); }

/* 누를 자리 — 칸 하나가 통째로 타깃이다(320px·6명에서 40×40). 점은 "여기 놓을 수 있다"는 표시이고,
   옆에 다리가 이미 있어 놓을 수 없는 자리는 점 없이 비활성이다. */
.lad__slot {
  position: absolute; padding: 0; border: none; background: none;
  display: flex; align-items: center; justify-content: center;
  transform: translateX(-50%); border-radius: var(--r-xs);
}
.lad__slot:active { background: var(--track); }
.lad__slot:disabled { cursor: default; }
.lad__dot { width: 5px; height: 5px; border-radius: 50%; background: var(--faint); }
.lad__slot[aria-pressed="true"] .lad__dot { display: none; }   /* 놓인 자리는 다리 자체가 표시다 */

/* 한 사람의 길 — **다리 위에 얹는 틴트 선이다.** 첫 안은 --tint-soft 를 깔아 덧칠처럼 두려 했는데
   흰 카드 위 실측이 1.16:1(다크 1.15:1)이라 사실상 보이지 않았다 — 그 토큰은 글자를 얹는 배지의 면이지
   혼자 서는 표식이 아니다. 새 색을 만드는 대신 **--tint 로 칠하고 다리보다 굵게(4px) 해서 위에 올린다**:
   6.45:1(다크 5.90:1)이고, 지나간 다리를 덮어 칠하므로 "이 다리를 건넜다"가 그대로 읽힌다. */
/* **모서리를 둥글리지 않는다.** 길은 행마다 조각으로 나뉘어 이어 붙는데, 조각마다 반경을 주면 이음매가
   잘록해져 열네 조각이 점선처럼 보인다(실물 확인에서 잡은 자리 — 화면에서만 드러났다). */
.lad__trace { position: absolute; width: 4px; margin-left: -2px; background: var(--tint); }
.lad__trace-cross { position: absolute; height: 4px; margin-top: -2px; background: var(--tint); }

.lad-labels { display: flex; align-items: center; height: 40px; flex: none; }
.lad-labels span, .lad-labels .lad-name {
  flex: 1 1 0; min-width: 0; text-align: center;
  font-size: var(--fs-cap); color: var(--label-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 공개된 뒤의 위 라벨은 누를 수 있는 이름이다 — 누르면 그 사람의 길이 그려진다. */
.lad-name { min-height: 40px; border: none; background: none; color: var(--tint); font-weight: 600; border-radius: var(--r-xs); }
.lad-name.is-on { background: var(--tint-soft); }
/* 빈 결과 자리 — 사이트 공용 빈 값 표시(—)와 같은 색이다(.is-empty 가 쓰는 --faint).
   **없는 것이 아니라 비어 있는 것**이라 카피로 말하지 않고 표식으로만 둔다(꽝·부정 표현 금지).
   `.lad-labels span`(0,1,1)이 --label-2 를 걸어 두어 한 단짜리로는 죽는다 — 같은 단으로 적는다. */
.lad-labels span.is-blank { color: var(--faint); }
.pill-val .is-blank { color: var(--faint); }

/* ── 이름 칸 묶음 (모임 도구 3종 공용 — 마스터 2026-08-20 검토로 여러 줄 입력에서 교체) ───────
   칸 하나에 이름 하나다. 새 어휘를 만들지 않았다: 칸은 기존 .f-input, 지우기는 담은 날짜의 .dd-del,
   "칸 추가"는 본문 뒤로 링크와 같은 텍스트 버튼(.back-link 계열 metrics)이다.
   첫 칸들은 HTML 에 서 있고 그 뒤로 자라는 칸만 JS 가 만든다 — 자라는 것은 사용자가 친 결과라
   로드 CLS 의 대상이 아니다. */
.nf-field { display: flex; flex-direction: column; gap: var(--sp-2); padding: 12px var(--inset); }
.nf-field + .nf-field { border-top: 0.5px solid var(--sep); }
.nf-field .f-error { margin: 0; }
.nf-box { display: flex; flex-direction: column; gap: var(--sp-2); }
.nf-row { display: flex; align-items: center; gap: var(--sp-2); }
/* 칸이 먼저 줄어든다 — 지우기 버튼은 44px 터치 타깃이라 찌그러지면 안 된다(.field-in 과 같은 처리). */
.nf-row .nf-input { flex: 1; min-width: 0; }
.nf-row .nf-del { flex: none; }
/* 묶음 제목 — <label for> 를 걸 대상이 하나가 아니라 여럿이라 span 이고, 묶음은 role="group" 이
   aria-labelledby 로 이 줄을 가리킨다. 생김새는 .field > label 과 같다. */
.nf-label { font-size: var(--fs-cap); font-weight: 600; color: var(--label-2); }
.nf-add {
  align-self: flex-start; min-height: 40px; padding: 0 2px;
  border: none; background: none; color: var(--tint);
  font-size: var(--fs-aux); font-weight: 600;
}
.nf-add:disabled { color: var(--faint); }

/* ── 하루 스탬프 (/stamp/) ────────────────────────────────────────────
   상태 화면이라 다른 도구와 뼈대가 다르다 — 입력 카드 자리를 "오늘"이 갖고, 결과 카드의 강조 행은
   연속 일수가 쓴다(기획 §4). 새 색·새 크기 단계는 만들지 않았다: 표식 --tint-fill/--on-tint,
   테두리·요일 머리글 --label-2, 점 --label, 오늘 칸 --track 으로 전부 기존 토큰이고 다크는 토큰이 뒤집는다. */

/* 카드 안에서 행 묶음을 담는 <div>(오늘 항목·항목 관리). 구분선(.row + .row)은 형제 사이에만 걸리므로
   묶음의 첫 줄은 부모 밖의 앞 요소와 갈리지 않는다 — 그 한 줄을 여기서 세운다. */
.stamp-rows > :first-child { border-top: 0.5px solid var(--sep); }

/* 오늘 날짜 자리 — 값이 '—' 에서 날짜로 갈릴 때 상자가 12.81 → 93.36px 로 자라며 왼쪽 끝이 움직인다
   (실측 CLS 0.0011 — 게이트 안이지만 없앨 수 있는 시프트다). 가장 긴 값("12월 30일 (일)" 93.36px)을
   미리 잡아 두면 어떤 날짜가 와도 상자가 그대로다. 값은 오른쪽 정렬을 유지한다. */
.row .r-value.stamp-date { min-width: 94px; justify-content: flex-end; }

/* 오늘 항목 줄 — **줄 전체가 버튼이다**(.row.tap). 오른쪽 동그라미만 누르게 하면 44px 타깃이 화면
   끝에 몰려 한 손 조작이 어렵다. 동그라미는 누를 수 없는 상태 표식이고, 상태 자체는 aria-pressed 가 진다.
   찍힘은 색이 아니라 ✓ 의 유무로도 갈린다(WCAG 1.4.1) — 다크에서도 면 색 없이 형태로 읽힌다. */
.stamp-row .r-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.stamp-mark {
  flex: none; margin-left: auto;
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1.5px solid var(--label-2); border-radius: 50%;
  font-size: var(--fs-mini); font-weight: 700; line-height: 1;
}
.stamp-mark.is-on { background: var(--tint-fill); border-color: transparent; color: var(--on-tint); }

/* 횟수 방식 줄 — 누름판(+1)과 되돌리기(−1)가 함께 서야 하는데 **버튼 안에 버튼을 넣을 수 없다**.
   그래서 이 줄만 <div> 로 감싸고 안쪽에 누름판을 둔다. 음수 여백으로 줄의 안쪽 여백까지 덮어서
   체크 줄과 누르는 면적·그림이 같아 보이게 한다(오른쪽만 −1 버튼에 내준다). */
.stamp-row--count, .stamp-row--time { padding-right: var(--sp-2); }
.stamp-tap {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--sp-3);
  margin: -10px 0 -10px calc(var(--inset) * -1);
  padding: 10px 0 10px var(--inset);
  min-height: 44px; border: none; background: none; color: inherit; text-align: left;
}
.stamp-tap:active { background: var(--track); }
/* 진행 표시 — 두 숫자가 같아지는 것이 곧 "찍힘"이라 색 없이도 읽힌다(WCAG 1.4.1). 폭은 최댓값
   ("12/12")에 맞춰 고정한다: 누를 때마다 알약이 넓어졌다 좁아지면 그 옆 이름이 흔들린다. */
.stamp-mark--count {
  width: auto; min-width: 46px; height: 28px; padding: 0 8px; border-radius: var(--r-xs);
  font-variant-numeric: tabular-nums;
}
/* 잰 시간 — 1초마다 숫자가 바뀌는 자리다. **폭을 미리 잡지 않으면 매초 이름 칸이 흔들린다**:
   `9:59` 와 `10:00` 은 글자 수가 달라 알약이 넓어졌다 좁아진다. tabular-nums 로 숫자 폭을 고르게 하고
   min-width 로 최악("1440:00" = 24시간)을 미리 먹어 둔다.
   도는 중에는 틴트 테두리가 선다 — 색만으로 말하지 않고 누름판의 이름(재기 시작/멈춤)이 함께 바뀐다. */
.stamp-mark--time {
  width: auto; min-width: 62px; height: 28px; padding: 0 8px; border-radius: var(--r-xs);
  font-variant-numeric: tabular-nums;
}
/* 재는 중 표시는 **바깥 고리**다(테두리 색이 아니라). 목표를 넘겨 도는 순간 알약이 --tint-fill 로
   채워지는데, 그때 테두리만 --tint 면 면과 같은 색이라 고리가 사라진다 — "도는 중"과 "멈췄고 다 채움"이
   화면에서 구별되지 않았다(실물 확인에서 잡은 자리). 카드색 한 겹을 사이에 끼워 띄우면 채워진 알약
   위에서도 고리가 선다. box-shadow 라 자리를 먹지 않아 매초 갱신에도 줄이 안 밀린다.
   색이 아니라 **고리의 있고 없음**이 신호이고, 누름판의 읽는 이름도 재기 시작/멈춤으로 함께 갈린다. */
.stamp-mark--time.is-run { border-color: var(--tint); color: var(--tint);
  box-shadow: 0 0 0 1.5px var(--card), 0 0 0 3.5px var(--tint); }
.stamp-mark--time.is-run.is-on { color: var(--on-tint); }

.stamp-minus {
  flex: none; width: 40px; height: 40px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; background: transparent; color: var(--tint);
  font-size: var(--fs-body); font-weight: 700; border-radius: var(--r-xs);
}
.stamp-minus:active { background: var(--track); }
.stamp-minus:disabled { color: var(--faint); background: none; }

/* 달 이동 — 라벨은 가운데, 화살표는 양 끝. 44px 타깃이고 비활성이면 눌리지 않는다(이달보다 앞으로는
   갈 수 없다). 새 색을 만들지 않았다: 화살표 --tint(누를 수 있는 것) · 비활성 --faint. */
.cal-nav { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); }
.cal-nav__btn {
  width: 44px; height: 44px; flex: none; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; background: none; color: var(--tint);
  font-size: var(--fs-body); font-weight: 700; border-radius: var(--r-xs);
}
.cal-nav__btn:active { background: var(--track); }
.cal-nav__btn:disabled { color: var(--faint); background: none; }
.cal-nav__label { font-size: var(--fs-cap); font-weight: 600; color: var(--label-2); font-variant-numeric: tabular-nums; }

/* 날짜 상세 — 카드 안 고정 자리다(팝오버가 아니라). 위치 계산도 화면 가장자리 처리도 필요 없고,
   높이를 미리 잡으면 켜고 끌 때 아래가 밀리지 않는다.
   **68px 는 처음 상태의 실측값이다**: 320px 에서 안내 한 줄이 두 줄로 감겨 내용 44 + 상하 패딩 24 다.
   첫 안은 알약 두 줄(60px)로 잡았는데 그러면 안내(68)가 더 높아서 날짜를 누를 때 8px 이 **줄어든다** —
   예약은 처음 상태보다 작으면 안 된다. 항목이 많은 날은 알약이 세 줄이 되며 늘어나는데, 그건 누른 결과다. */
.cal-detail {
  display: flex; flex-wrap: wrap; align-items: center; align-content: flex-start;
  gap: var(--sp-2); min-height: 68px; padding: var(--sp-3) var(--inset);
  border-top: 0.5px solid var(--sep);
}
.cal-detail + .res-lead { border-top: 0.5px solid var(--sep); }
.cal-detail__hint { font-size: var(--fs-aux); color: var(--label-2); }
.cal-detail__day { font-size: var(--fs-aux); font-weight: 700; color: var(--label); font-variant-numeric: tabular-nums; }

/* 첫 방문 — 등록 유도 한 줄 + 예시 3개. 예시도 항목 줄과 같은 .row.tap 이라 44px 타깃이 그대로다.
   "추가"는 `.row .r-value`(0,2,0)가 --label-2 로 칠하는 자리라 같은 단으로 적어야 살아남는다
   (.mon-over 가 걸렸던 함정 — 이 파일 111행). */
.stamp-empty { margin: 0; padding: 12px var(--inset); color: var(--label-2); font-size: var(--fs-aux); }
.row .r-value.stamp-add { color: var(--tint); font-weight: 600; }

/* 기록 파일 안내 — 카드 안 한 줄. .card--pad 가 이미 축 B 여백을 갖는다. */
.stamp-file__note { margin: 0; font-size: var(--fs-aux); color: var(--label-2); }
/* 가져오기 확인 대기 — 되돌릴 수 없는 조작이라 버튼이 경고색으로 갈린다(삭제 확인과 같은 층).
   `.actions .btn`(0,2,0) 이 색을 걸어 두므로 같은 단으로 적는다. */
.actions .btn.is-armed { color: var(--danger); font-weight: 700; }

/* 달력 — 표로 그린다(요일 머리글과 날짜 칸의 관계를 마크업이 말한다). 높이를 미리 잡는 자리가 .cal-box 다:
   격자는 언제나 6주라 안쪽 높이가 고정이지만 표는 JS 가 만들어 붙이므로 그 전까지 상자가 비어 있다.
   **min-height 는 실측값이다**: 320·390·620px 세 폭에서 표가 전부 250.19px 였고(캡션 26.09 + 머리글
   20.09 + 6줄 × 34), 상하 패딩 24 를 더한 상자가 275.19px 다. 276 은 그보다 0.81px 큰 값이라 표가
   들어와도 상자가 자라지 않는다 — **첫 안 271 은 4px 모자라서 표가 붙는 순간 아래가 그만큼 밀렸다**
   (예약이 내용보다 작으면 예약이 아니다). 줄 높이·글자 크기를 바꾸면 다시 잰다.
   border-collapse 를 separate 로 두는 것은 오늘 칸의 둥근 면 때문이다(collapse 면 반경이 적용되지 않는다). */
.cal-box { padding: var(--sp-2) var(--inset) var(--sp-4); }
.row + .cal-box { border-top: 0.5px solid var(--sep); }
.cal-grid { min-height: 226px; }
.cal { width: 100%; table-layout: fixed; border-collapse: separate; border-spacing: 0; }
.cal th { height: 20px; font-size: var(--fs-cap); font-weight: 600; color: var(--label-2); }
.cal td { height: 34px; padding: 0; vertical-align: top; text-align: center; }
/* 칸 자체가 버튼일 때와 아닐 때가 있다(찍힌 것이 있는 날만 누를 수 있다) — 두 경우의 그림이 같아야
   하므로 크롬을 지우고 같은 상자로 맞춘다. */
.cal-cell {
  display: block; width: 100%; height: 34px; padding: 2px 0;
  border: none; background: none; color: inherit; border-radius: var(--r-xs);
}
.cal .cal-d { display: block; line-height: 1.2;
  font-size: var(--fs-cap); color: var(--label); font-variant-numeric: tabular-nums; }
/* 오늘 — 면은 보조 신호이고 날짜 숫자의 굵기가 함께 말한다. */
.cal-cell.is-today { background: var(--track); }
.cal-cell.is-today .cal-d { font-weight: 800; }
/* 앞날 — 찍을 수도 볼 수도 없는 칸이라 한 단 낮춘다. 지운 것이 아니라 낮춘 것이므로 --faint(장식용)가
   아니라 --label-2 를 쓴다(보조 텍스트와 같은 대비). */
.cal-cell.is-future .cal-d { color: var(--label-2); }
/* 상세를 펼쳐 둔 날 — 색이 아니라 테두리로 표시한다(오늘 칸의 면과 겹쳐도 둘이 구분된다). */
.cal-cell.is-sel { box-shadow: inset 0 0 0 1.5px var(--tint); }
button.cal-cell:active { background: var(--track); }
/* 점 — **잘리지 않는다**: max-width 가 한 줄을 5개로 묶고 두 줄이면 10개, 그것이 곧 항목 상한이다.
   그래서 "n개까지만 보이는" 자리가 없다. 높이는 두 줄분(4+2+4)을 늘 잡아 둔다 — 점이 늘어난다고
   날짜 칸이 자라면 달력 전체가 밀린다. */
.cal .cal-dots {
  display: flex; flex-wrap: wrap; justify-content: center; align-content: flex-start;
  gap: 2px; max-width: 28px; min-height: 10px; margin: 2px auto 0;
}
.cal .dot { width: 4px; height: 4px; border-radius: 50%; background: var(--label); }

/* 항목 관리 — 이름 칸이 곧 편집 자리다(따로 "이름 변경" 화면을 만들지 않는다).
   삭제는 한 번 더 묻는다: × 가 "지울까요?"로 바뀌고 그때 다시 눌러야 지워진다. 늘어난 라벨이
   들어갈 폭은 이름 칸이 내준다(flex:1 · min-width:0) — 320px 에서도 줄이 감기지 않는다. */
.stamp-item { gap: var(--sp-2); padding-block: 6px; }
.stamp-item .stamp-name { flex: 1; min-width: 0; }
.dd-del.is-armed {
  width: auto; padding: 0 10px; border-radius: var(--r-xs);
  color: var(--danger); font-size: var(--fs-aux); font-weight: 600; white-space: nowrap;
}

/* ── 허브 카드의 "최근 사용" 배지 (§5-3 · 0808-D28 = ⓑ) ──────────────
   배지는 h3 의 **안쪽 마지막 자식**이다. .game-card 가 flex-column 이라 h3 의 형제로 두면
   별도 행으로 떨어져 카드가 20px 이상 밀린다(components.css 8-12행). 안쪽이면 +1.34px 뿐이다.
   색·크기는 기존 .badge 그대로 — 여기서 만드는 것은 배치 한 줄이다. */
.game-card h3 .badge { margin-left: 6px; vertical-align: middle; }
