/* 모바일 껍데기 — 사람이 보는 모든 화면이 함께 쓰는 것만 담는다.
   지금은 셋이다: **하단 탭 바**·**전체 메뉴**·**바텀 시트**.

   ⚠ **왜 skin.css 가 아닌가:** 화면마다 싣는 껍데기가 다르다(실측 2026-08-24).
   공통 모바일 규칙을 한 파일에 두고 화면 전수가 이 파일을 싣는지 테스트한다.
   그래야 마크업만 있고 규칙이 빠진 화면이 생기지 않는다.

   ⚠ **이 파일은 혼자 선다.** skin.css 의 --gold 류가 없는 화면에서도 색이 나와야 하므로
   되돌림 값을 아래 :root 에 적어 둔다. **정본은 skin.css 이고 여기 것은 되돌림이다** —
   두 곳이 갈리면 skin.css 를 따른다(var(--gold, …) 가 그렇게 동작한다). */

/* 「화면 고정」의 셋째 층 — 두 번 탭해서 키우는 길을 막는다.
   정본 설명은 `web/lib/zoom-lock.js` 머리말에 있다(층 셋이 서로를 대신하지 못하는 까닭).

   ⚠ **`manipulation` 이 아니라 `pan-x pan-y` 다.** `manipulation` 은 더블탭만 끄고
      **핀치는 그대로 허용한다** — 이름만 보고 고르면 반만 막힌다.
   ⚠ **두 축을 다 적는다.** 한 축만 적으면 그 반대 방향 스크롤이 죽는다(가로 스크롤
      표가 도감·계산 탭에 있다).
   ⚠ 이 규칙만으로는 **아이폰의 핀치가 안 막힌다** — 사파리는 문서 수준 핀치를
      touch-action 으로 안 넘긴다. 그 몫은 zoom-lock.js 의 제스처 차단이 진다. */
html, body { touch-action: pan-x pan-y; }

:root {
  --m-gold: #c8a24c;
  --m-dim: #b3974d;   /* skin.css 의 --gold-dim 과 같은 값을 유지한다(대비 AA) */
  --m-muted: #9a8e76;
  --m-cream: #e6dcc4;
  --m-line: #3b3122;
  /* 44px 은 손가락 하나의 최소 크기다(애플·구글 지침이 같은 값을 쓴다).
     2026-08-07 실측: 계산 탭 터치 대상 61개 중 52개가 이 값 미만이었다. */
  --m-touch: 44px;
  /* 하단 탭 바의 높이. **이 값 하나에서 둘이 파생된다** — 탭 바 자신의 높이와
     본문 아래 여백. 따로 적었더니 탭 바가 66px 인데 여백이 52px 이라 14px 이
     가려졌다(2026-08-07 실측). min-height 가 아니라 height 인 이유도 그것이다:
     내용에 따라 자라면 여백이 다시 어긋난다. */
  --m-tabbar: 56px;
  /* 좁은 화면 퀵슬롯 시트의 칸 영역 높이. **시트 높이와 페이지 끝 여백이 이 값 하나에서
     파생된다**(위 `--m-tabbar` 와 같은 이유). 키 큰 화면에서 칸 두 줄(126px), 짧은 화면에서는
     화면 높이를 따라 줄되 한 줄(61px) 밑으로는 안 간다 — 실측(2026-09-16): 고정으로 두 줄이면
     375×667 에서 내용 몫이 40%, 320×640 에서 31% 였다. ⚠ 높이 중단점을 더하지 않는다
     (중단점은 폭 다섯뿐이다, `tests/mobile.test.js`). */
  --m-sheet-slots: clamp(61px, 15vh, 126px);
}

/* 전투 결과의 열을 한 글자씩 접지 않고 표 안에서 가로로 읽는다. */
.combat-target-table { max-width: 100%; overflow-x: auto; }
.combat-target-table th, .combat-target-table td { white-space: nowrap; }

/* ── 모바일 전체 메뉴 ──────────────────────────────────────────────────────
   하단에는 반복해서 쓰는 다섯 화면만 두고, 나머지는 머리말의 이 메뉴에서 연다.
   마크업과 링크 정본은 web/lib/site-nav.js, 열림 상태는 web/mobile-nav.js 가 쓴다. */
.mobilemenu-toggle { display: none; }
.mobilemenu {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 90;
}
.mobilemenu-panel {
  position: relative;
  z-index: 1;
  width: min(88vw, 360px);
  height: 100vh;
  height: 100dvh;
  margin-left: auto;
  overflow-y: auto;
  box-sizing: border-box;
  transform: translateX(100%);
  transition: transform 260ms ease;
  border-left: 1px solid var(--gold-dim, var(--m-dim));
  background:
    radial-gradient(circle at 100% 0, #8d6e321f, transparent 42%),
    #15110c;
  color: var(--cream, var(--m-cream));
  box-shadow: -16px 0 42px #000b;
}
.mobilemenu.open .mobilemenu-panel { transform: translateX(0); }
body.mobilemenu-open { overflow: hidden; }

.mobilemenu-backdrop {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  min-width: var(--m-touch);
  min-height: var(--m-touch);
  margin: 0;
  padding: 0;
  border: 0;
  background: #000b;
  opacity: 0;
  transition: opacity 220ms ease;
  cursor: pointer;
}
.mobilemenu.open .mobilemenu-backdrop { opacity: 1; }
.mobilemenu-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 64px;
  padding: max(8px, env(safe-area-inset-top, 0px)) 14px 8px 22px;
  border-bottom: 1px solid var(--line, var(--m-line));
}
/* 전체 메뉴 안의 전역 검색(site-nav.js 사이트검색HTML, 2026-09-05). 머리말의 폼은
   폰 폭에서 숨긴다(아래 720px 블록) — 두 개가 보이면 어느 것이 진짜인지 모른다. */
.mobilemenu-search { padding: 12px 14px 4px; }
.mobilemenu-search input {
  width: 100%; box-sizing: border-box; min-height: var(--m-touch);
  font: inherit; font-size: 16px;   /* iOS 확대 방지 */
  color: var(--cream, var(--m-cream));
  background: #0b0907; border: 1px solid var(--line, var(--m-line)); border-radius: 2px;
  padding: 8px 12px;
}
.mobilemenu-search input:focus-visible { outline: none; border-color: var(--gold, var(--m-gold)); }
.mobilemenu-head strong {
  color: var(--gold, var(--m-gold));
  font-size: 16px;
  letter-spacing: .12em;
}
.mobilemenu-close,
.mobilemenu-toggle {
  appearance: none;
  border: 1px solid transparent;
  background: transparent;
  color: var(--cream, var(--m-cream));
  font: inherit;
  cursor: pointer;
}
.mobilemenu-close {
  display: grid;
  place-items: center;
  min-width: var(--m-touch);
  min-height: var(--m-touch);
  padding: 0;
  font-size: 30px;
  font-weight: 300;
  line-height: 1;
}
.mobilemenu-list,
.mobilemenu-sublist {
  margin: 0;
  padding: 0;
  list-style: none;
}
.mobilemenu-list { padding: 10px 14px calc(28px + env(safe-area-inset-bottom, 0px)); }
.mobilemenu-group {
  padding: 11px 4px 13px;
  border-bottom: 1px solid #ffffff12;
}
.mobilemenu-group-single { padding-block: 7px; }
.mobilemenu-group:last-child { border-bottom: 0; }
.mobilemenu-group-title {
  margin: 0 10px 5px;
  color: var(--gold-dim, var(--m-dim));
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .14em;
}
.mobilemenu-link {
  display: flex;
  align-items: center;
  min-height: var(--m-touch);
  padding: 0 10px;
  border-radius: 2px;
  color: var(--cream, var(--m-cream));
  font-size: 14px;
  text-decoration: none;
}
.mobilemenu-link:hover { background: #ffffff0b; color: var(--gold, var(--m-gold)); }
.mobilemenu-link[aria-current="page"] {
  background: #c8a24c14;
  color: var(--gold, var(--m-gold));
  box-shadow: inset 2px 0 var(--gold, var(--m-gold));
}
.mobilemenu-link-main { color: var(--gold, var(--m-gold)); font-weight: 700; }
.mobilemenu-toggle-icon { display: grid; gap: 5px; width: 22px; }
.mobilemenu-toggle-icon i {
  display: block;
  height: 1px;
  background: currentColor;
  box-shadow: 0 0 5px #c8a24c55;
}
.mobilemenu-toggle:focus-visible,
.mobilemenu-close:focus-visible,
.mobilemenu-link:focus-visible {
  outline: 2px solid var(--gold, var(--m-gold));
  outline-offset: 2px;
}

@media (max-width: 720px) {
  /* 머리말 검색은 폰에서 접는다 — 전체 메뉴 안의 `.mobilemenu-search` 가 대신한다. */
  .bg3-header > .siteq { display: none; }
  /* 도감 빵부스러기·색인 힌트는 글줄 링크라 손가락 크기가 안 나온다(mobile-measure: 아이템 쪽 3 · 클래스 쪽 2 · 색인 1). */
  .cx-crumbs a, .cx-index-hint a { display: inline-flex; align-items: center; min-height: var(--m-touch); }
  .mobilemenu-toggle {
    display: grid;
    place-items: center;
    order: 1;
    min-width: var(--m-touch);
    min-height: var(--m-touch);
    margin-left: auto;
    padding: 0 10px;
  }
  .mobilemenu {
    display: block;
    visibility: hidden;
    pointer-events: none;
    transition: visibility 0s linear 260ms;
  }
  .mobilemenu.open {
    visibility: visible;
    pointer-events: auto;
    transition-delay: 0s;
  }
  /* 햄버거는 로고와 같은 첫 줄의 오른쪽 끝에 놓인다. 화면별 설정은 원래 차례를 지킨다. */
}

@media (prefers-reduced-motion: reduce) {
  .mobilemenu-panel,
  .mobilemenu-backdrop { transition: none; }
}

/* ── 하단 탭 바 (A1) ──────────────────────────────────────────────────────
   데스크톱에는 안 뜬다 — 헤더 링크가 이미 그 일을 하고, 아래를 가리면 손해다.
   375px 에서 헤더 링크가 「4인 파 / 티」로 줄바꿈되던 것을 이것이 대신한다.

   ⚠ **열 수를 손으로 적지 않는다.** `repeat(3, 1fr)` 로 적어 뒀다가 탭이
   5개로 늘었을 때(2026-08-12 게시판·프로필) 2행이 됐고, 상자는 56px 고정이라
   **게시판·프로필이 화면 밖으로 밀려 안 눌렸다.** 정본은 web/lib/site-nav.js 의
   `화면탭` 이고, 여기서는 개수를 아예 안 안다. */
.tabbar { display: none; }

@media (max-width: 720px) {
  .tabbar {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
    /* 홈 인디케이터가 있는 기기에서 마지막 줄이 가려진다. */
    height: calc(var(--m-tabbar) + env(safe-area-inset-bottom, 0px));
    background: #100e0a;
    box-sizing: border-box;

    /* ⚠ **다른 스타일시트의 nav 규칙을 되돌린다.** style.css:5 가
       `header, nav { padding: var(--gap); border-bottom: … }` 를 걸어서, 아이템
       화면에서는 탭 바가 위 12px 을 먹고 링크가 44px 로 줄었다(2026-08-07 실측:
       바 56 · 링크 44 · 위 12px 은 눌러도 안 먹음). 화면마다 nav 규칙이 다르므로
       여기서 통째로 못박는다 — 값을 물려받지 않는다. */
    margin: 0;
    padding: 0 0 env(safe-area-inset-bottom, 0px);
    border: 0;
    /* style.css 의 `nav { gap: 8px }` 도 샜다 — 아이템 화면만 칸 사이가 8px 벌어져
       링크 폭이 120 대 125 로 갈렸다(리뷰 실측). 격자가 폭을 정하므로 0 이 맞다. */
    gap: 0;
    border-top: 1px solid var(--gold-dim, var(--m-dim));
  }
  .tabbar a {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 2px;
    /* ⚠ height: 100% 를 쓰면 격자 칸 안에서 42px 로 줄어든다(2026-08-07 실측) —
       바 위쪽 14px 을 눌러도 안 먹었다. 격자의 기본 stretch 에 맡기고 최소만 못박는다. */
    min-height: var(--m-touch); line-height: 1.3;
    font-size: 11px; text-decoration: none;
    color: var(--muted, var(--m-muted));
  }
  .tabbar a.on { color: var(--gold, var(--m-gold)); }
  .tabbar .ti { font-size: 17px; line-height: 1; }
  .srcall summary, .item-monsters summary { min-height: var(--m-touch); }

  /* 탭 바가 덮는 만큼 본문 아래를 비운다 — 마지막 줄이 가리면 안 된다.
     **탭 바 높이와 같은 변수에서 나온다.** 따로 적으면 조용히 어긋난다. */
  body { padding-bottom: calc(var(--m-tabbar) + env(safe-area-inset-bottom, 0px)); }

  /* 헤더의 화면 이동 링크는 탭 바와 **같은 말**이라 감춘다.
     ⚠ 스포일러 방지 체크박스와 「출처와 라이선스」는 **남긴다** — 탭 바가 그 일을 안 한다.
     ⚠ **`header p a[href="./build.html"]` 를 지웠다**(2026-08-27). 아이템 화면이
        `<header><p><a>` 이던 시절의 규칙인데 마크업이 `<nav class="sitetabs">` 로
        옮겨 간 뒤로 **이미 일치가 0이었다**(main 판으로 확인). 주소가 `/build` 로
        바뀌면서 영영 못 맞게 되므로 같이 치운다 — 윗줄이 그 일을 이미 한다.
     ⚠ **CSS 가 주소를 글자째 물면 링크를 고칠 때 조용히 죽는다.** 아래 그물이
        `web/*.css` 전체에 `a[href=...]` 가 다시 생기는지 잰다
        (tests/site-nav.test.js). */
  .bg3-header {
    min-height: 68px;
    padding: 12px 20px;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto 44px 44px;
    gap: 6px;
    align-items: center;
    text-align: left;
  }
  /* 보조 정보 유무와 언어별 CSS가 상단 조작부를 밀지 않도록 칸을 정한다. */
  .bg3-header h1 { font-size: 20px; grid-area: 1 / 1; min-width: 0; }
  .bg3-header .sitebrand { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; line-height: 44px; }
  .bg3-header > .locale-switch,
  .bg3-header > [data-locale-switch] { grid-area: 1 / 2; margin: 0; }
  .bg3-header > .notification-mobile { grid-area: 1 / 3; margin: 0; width: 44px; height: 44px; padding: 0; }
  .bg3-header > .mobilemenu-toggle { grid-area: 1 / 4; margin: 0; width: 44px; height: 44px; padding: 0; }
  .bg3-header > .hdrfresh,
  .bg3-header > .hdrstats,
  .bg3-header > .cx-fresh,
  .bg3-header > .spoilerfree { grid-column: 1 / -1; }
  .bg3-header nav.sitetabs { display: none; }
  .bg3-header > .hdrfresh,
  .bg3-header > .hdrstats,
  .bg3-header > .cx-fresh {
    display: block;
    order: 2; width: 100%; white-space: normal;
  }
  .bg3-header > .spoilerfree {
    order: 3; flex-basis: 100%; width: 100%; margin-left: 0; padding-bottom: 0;
  }
}

@media (max-width: 620px) {
  .bg3-header { padding-inline: 14px; gap: 4px; }
  .bg3-header .sitebrand { font-size: 20px; }
}

/* ── 바텀 시트 (web/lib/sheet.js) ─────────────────────────────────────────
   「따로 보는 것」 셋이 같이 쓴다: 태그 필터 · 길게 누른 툴팁 · 아이템 상세.
   데스크톱에서는 가운데 창으로, 모바일에서는 아래에서 올라오는 시트로 뜬다. */
.bsheet {
  padding: 0;
  max-width: 560px;
  width: calc(100vw - 24px);
  max-height: 82vh;
  border: 1px solid var(--gold-dim, var(--m-dim));
  background: #17130d;
  color: var(--cream, var(--m-cream));
}
.bsheet::backdrop { background: #000a; }

.bsheet-grab { display: none; }

.bsheet-head {
  padding: 12px 16px 8px;
  font-size: 13px;
  letter-spacing: .16em;
  color: var(--gold-dim, var(--m-dim));
  border-bottom: 1px solid var(--line, var(--m-line));
}

.bsheet-body { padding: 12px 16px; overflow-y: auto; max-height: 62vh; }

/* ⚠ 모양을 **여기서 다 준다.** 예전에는 마크업이 `.btn ghost` 를 달고 나오고 여기는
   `:not(.btn)` 으로 되돌림을 뒀는데, 그 조건이 참인 적이 없어서 정작 .btn 이 없는
   아이템 화면에 브라우저 기본 회색 단추가 떴다(리뷰 M-1). 세 화면이 다 이 파일을
   싣고 이 파일이 마지막에 실리므로 여기 하나면 셋 다 같은 모양이 된다. */
.bsheet-close {
  display: block;
  width: calc(100% - 32px);
  margin: 8px 16px 16px;
  min-height: var(--m-touch);
  border: 1px solid var(--gold-dim, var(--m-dim));
  background: transparent;
  color: var(--cream, var(--m-cream));
  font: inherit;
  cursor: pointer;
}
.bsheet-close:hover { background: #ffffff10; }

@media (max-width: 720px) {
  /* 아래에서 올라온다. 좌우를 꽉 채우고 아래 모서리를 붙인다. */
  .bsheet {
    width: 100vw;
    max-width: none;
    max-height: 88vh;
    margin: auto auto 0;
    border-width: 1px 0 0;
  }
  .bsheet-body { max-height: 68vh; }
  /* 손잡이 — 「위로 끌 수 있다」가 아니라 「아래에서 올라온 것이다」를 말한다. */
  .bsheet-grab {
    display: block;
    width: 40px; height: 4px;
    margin: 8px auto 0;
    border-radius: 2px;
    background: var(--gold-dim, var(--m-dim));
  }
}

/* ── 태그 필터를 바텀 시트로 (A4) ─────────────────────────────────────────
   태그가 416종이라 인라인 <details> 를 펴면 목록이 화면 밖으로 밀린다.
   시안이 바텀 시트를 쓴 이유다 — 목록을 보면서 좁힌다.

   ⚠ **이 부품은 두 곳에 붙는다** — 아이템 화면의 #tagbar 와 빌더 고르기 창의
   #pickerfilter(web/build.js). 그래서 규칙을 style.css(아이템 화면만 싣는다)가
   아니라 여기 둔다. 처음에 style.css 에 뒀더니 build.html 에서 **데스크톱에도 중복
   단추가 떴다**(리뷰 C-1, 2026-08-07). 겨눔도 페이지 id 가 아니라 모듈이 붙이는
   .tagfilter 다 — CLAUDE.md 「공유 어휘는 문자열이 아니라 모듈로」와 같은 자리다.
   tests/mobile.test.js 의 「두 곳에 붙는 부품의 CSS」가 이 규칙을 강제한다.

   ⚠ **`>` 가 이 규칙의 핵심이다.** `.tagpicker { display: none }` 로 적으면 시트
   안으로 옮긴 뒤에도 안 보여서 눌러도 빈 시트가 뜬다. 마운트의 **직계**만 겨눈다. */
.tagsheetopen { display: none; }

@media (max-width: 720px) {
  .tagsheetopen { display: inline-block; min-height: var(--m-touch); }
  .tagfilter > .tagpicker { display: none; }
  /* 목록을 40vh 상자에 가두면 폰에서 한 번에 9개밖에 안 보인다(2026-08-07 실측).
     목록이 아이템 화면의 본문이다 — 페이지가 스크롤하게 둔다. */
  #list { max-height: none; }
  /* 시트 안의 태그 목록은 시트가 이미 스크롤한다 — 이중 스크롤을 없앤다. */
  .bsheet .taglist { max-height: none; overflow: visible; }

  /* 능력 태그 필터를 목록 **위**로 올린다(③, 2026-08-16).
     `.vgrid`(style.css:28)의 직계 셋은 DOM 순서가 필터 → 목록 → 태그필터라서
     (web/items.html:50·:101·:111) 폰에서는 **거르개 하나가 1,183개 목록 아래**에
     있었다. 슬롯·등급·막과 검색창은 이미 위에 있으니 아래로 밀리던 것은 이것 하나다.
     ⚠ **DOM 을 안 옮기고 order 로 한다.** `#tagbar` 가 필터 칸 밖에 있는 것은
     넓은 화면에서 판 전체 폭을 받아 4열로 펴지게 하려는 의도다(items.html:106-110).
     DOM 을 옮기면 그 의도가 깨진다.
     ⚠ 셋 다 명시한다 — order 기본값이 0 이라 하나만 주면 나머지와의 관계가
     안 정해진다. 이 셋은 `.vgrid` 안에만 있고 `.vgrid` 는 아이템 화면에만 있다. */
  .vgrid > .vfilters { order: 1; }
  .vgrid > #tagbar   { order: 2; }
  .vgrid > main      { order: 3; }
}

/* ── 터치 대상 (B3) ───────────────────────────────────────────────────────
   2026-08-07 실측(375×812): 계산 탭 터치 대상 61개 중 **52개**가 44px 미만이었고,
   그중에 **주 내비게이션인 탭(35px)** 이 있었다. 삭제 ✕ 는 23×25px, 체크박스는 13px.

   ⚠ 글자 크기는 안 건드린다 — 누르는 자리만 넓힌다. 글자를 키우면 한 줄에 안 들어가
   줄바꿈이 나고, 그것이 다시 배치를 흔든다.

   두 화면 세계를 다 덮으려고 여기 둔다: 빌드·파티는 skin.css 의 .tab/.btn/.del,
   아이템 화면은 style.css 의 .chip 과 맨 select/input 이다. */
@media (max-width: 720px) {
  /* 탭 모양으로 생긴 것 전부. .acttab 은 막별 계획의 1·2·3막 탭이다 —
     전수로 재고서야 빠진 것을 알았다(2026-08-07). 눈으로 훑지 말고 재서 찾을 것. */
  /* .stab 은 아이템 화면의 검색 탭 넷이다(⑤b). 전수로 재고서야 빠진 것을 알았다 —
     ⑤a 의 .acttab 과 같은 자리다. **눈으로 훑지 말고 재서 찾을 것.** */
  button.tab, button.mktab, button.hbtab, button.acttab, button.stab {
    min-height: var(--m-touch); padding-inline: 14px;
  }
  /* 게시판 편집기 툴바 단추(`web/lib/editor/toolbar.js`). 새로 생긴 `cursor: pointer`
     자리라 tests/mobile.test.js 의 전수 검사가 곧바로 물었다 — 위 주석들과 같은 자리. */
  button.bbe-btn { min-height: var(--m-touch); }
  /* 엔티티 픽커 탭·칸(`web/lib/editor/picker.js`, Task 8). 같은 전수 검사가 새 버튼을
     곧바로 물었다 — 자리를 나열하는 방식 자체가 그렇다(위 주석들과 같은 사고). */
  button.bbe-picktab, button.bbe-pickcell { min-height: var(--m-touch); }
  /* 아이콘 폴더 제목·장비 일괄 버튼(`web/lib/editor/render.js`, `picker.js`).
     둘 다 새로 생긴 포인터 대상이라 접힌 폴더와 묶음 삽입을 모바일에서도 쉽게 누른다. */
  .bb-icon-folder-title, button.bbe-pickbulkbtn { min-height: var(--m-touch); }
  /* 목차에 넣을 제목 고르기(`web/lib/editor/index.js` 의 `목차편집HTML`, 2026-08-29).
     같은 전수 검사가 또 곧바로 물었다 — **자리를 나열하는 방식이라 새 단추는 늘
     한 번 걸린다.** 그게 이 그물의 값이다(빠진 것을 사람이 기억하지 않는다). */
  button.bbe-tocpick { min-height: var(--m-touch); }
  /* ⚠ **모바일에는 hover 가 없다**(2차 스펙 §1-4, Task 8). 데스크톱에서 손잡이와
     삽입 「+」는 `opacity: 0` 으로 숨어 있다가 hover 에 드러나는데, 터치에는 그
     상태가 없어 **영영 안 보인다.** 늘 드러내고 터치 대상 크기도 준다. */
  .bbe-handle, .bbe-insbtn { opacity: 1; }
  button.bbe-hbtn, button.bbe-insbtn { min-height: var(--m-touch); min-width: var(--m-touch); }
  /* 삽입 메뉴 항목(Task 10). 위 주석들과 같은 자리 — 전수 검사가 곧바로 문다. */
  button.bbe-mi { min-height: var(--m-touch); }
  button.bbe-kind { min-height: var(--m-touch); }
  /* ⚠ .fchip 은 .chip 과 **다른 클래스다** — 선택자 `.chip` 이 안 걸린다. 아이템
     화면의 슬롯·등급·막 필터 칩이고, 높이가 없어 12px×1.65 + 안여백 8 + 테두리 2
     ≈ 30px 이었다(style.css:49-56). **.acttab·.stab 에 이어 세 번째로 샌 자리다.**
     위 두 주석이 「눈으로 훑지 말고 재서 찾을 것」이라 적고도 또 났으니, 이제
     tests/mobile.test.js 의 「누른다고 선언한 것에 44px 이 걸렸나」가 전수로 잡는다 —
     이 목록에 이름을 더하는 것을 사람이 기억할 일이 아니다. */
  /* .roundtab 은 라운드 계획의 라운드 단추다(2026-09-02, skin.css). 누르는 자리라 같이 든다.
     ⚠ `.rcard` 는 그것을 대신한 **라운드 카드**다(2026-09-15, 시안 3a). 데스크톱에서는
     `min-height: 84px`(기대 피해·아이콘·자원 핍 3단)인데, 좁은 화면에서는 그 3단이
     한 줄에 안 들어가므로 여기서 손가락 크기까지만 내린다 — 3b 시안의 60px 카드와
     같은 방향이다. `.roundtab` 은 아직 쓰는 자리가 있어 그대로 둔다. */
  .btn, .btn.ghost, .chip, .fchip, .roundtab, .rcard, .mtcard, .segbtn, .rcname, .foelist button, .condchip,
  .turnhit, .turnonhit, .turnx, .mxcell,
  .scenarioload, .scenariodel { min-height: var(--m-touch); }

  /* ── ② 행동 줄 — 시안 3b 의 압축 꼴 ────────────────────────────────────
     ⚠ **A2 의 9열이 이 폭에 안 들어간다**(실측 2026-09-16, 390px: 줄이 486px 라 문서가
     506px 까지 옆으로 샜다). 시안 3b 는 줄을 이렇게 접는다:
         아이콘 · 이름 ················ 기대 · ✕
         비용 핍 · 굴림 배지 · 범위 문장
         명중 × 맞으면
     열 머리글은 이 폭에 안 들어가 감춘다. 「전부 치명타면」은 **시안 3b 의 줄에 없다** —
     지우는 게 아니라 ③ 결과의 총합과 펼친 식(「기대 = 명중% × 맞으면 + 치명 보너스」)에
     그대로 있다. */
  .turnhead { display: none; }
  .simplan .turnitem {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) 6px;
  }
  /* 격자 자리 지정을 걷는다 — 안 걷으면 flex 안에서 아무 뜻이 없고 다음 사람이 헷갈린다. */
  .simplan .turnitem > * { grid-column: auto; grid-row: auto; }
  .simplan .turnitem .frame { flex: 0 0 40px; order: 1; }
  .simplan .turnitem .turnname { flex: 1 1 auto; min-width: 0; order: 2; }
  .simplan .turnitem .turndmg { flex: 0 0 auto; order: 3; }
  .simplan .turnitem .turnx { flex: 0 0 auto; order: 4; }
  .simplan .turnitem .turncost { flex: 1 1 100%; order: 5; }
  .simplan .turnitem .turnhit { order: 6; }
  .simplan .turnitem .op1 { order: 7; }
  .simplan .turnitem .turnonhit { order: 8; }
  .simplan .turnitem .op2, .simplan .turnitem .turncrit { display: none; }
  /* 적 여럿의 줄 — 「공격 대상」 고르기는 접힌 줄의 마지막 한 줄을 통째로 쓴다. */
  .simplan .turnitem .mttarget { flex: 1 1 100%; order: 9; }

  /* ── 시안 3b — 좁은 화면의 배치 ───────────────────────────────────────────
     ① 위에 고정 · 라운드 카드 가로줄 · 퀵슬롯은 화면 아래 시트.

     ⚠⚠ **고정과 시트는 빌더에서만**(`#panel`). 게시판 공개 미리보기(`#boardpreview`)도 같은
       패널을 그리는데, 글 본문 안에서 화면에 붙는 바·떠 있는 시트는 **글을 가린다**
       (CLAUDE.md 층 지도의 「게시판 공개 미리보기」 줄 — 같은 패널이니 같이 된다가 거짓인 자리).

     ⚠ 고정이 조용히 안 붙는 조건이 둘이다(실측 2026-09-16, 390px 실브라우저로 재고 정했다):
       · 조상에 `overflow`·`transform` 이 있으면 안 붙는다 — `typography.test.js` 「붙는 줄의
         조상」 목록에 `.simwrap`·`#panel` 을 넣어 문다.
       · `.simwrap` 의 `container-type` 은 fixed 의 기준 상자가 **안 된다**(스크롤 0·1500 에서 둘 다
         바닥 844 로 붙는 것을 쟀다). */

  /* D2 — 라운드 카드는 한 줄로 흐르고 옆으로 민다(시안: 60px × N · 스크롤바 숨김).
     ⚠ `overflow` 는 **`.rcards` 자신에만** 건다 — ① 고정 바의 조상이 되면 조용히 안 붙는다.
     미리보기에서도 한 줄이 낫다(글 폭에서 카드가 여러 줄로 쌓이지 않는다) — 그래서 `#panel` 로
     좁히지 않는다. */
  .rcards { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .rcards::-webkit-scrollbar { display: none; }
  .rcard, .rcard.before { flex: 0 0 60px; min-width: 60px; min-height: 66px; padding: 6px; }
  .rcard.add, .rcard.del { flex: 0 0 40px; min-width: 40px; }
  .rcard .rtop { flex-wrap: wrap; }
  .rcard .rdmg { font-size: var(--fs-base); }
  .rcard .ricon { width: 14px; height: 14px; }
  .rcard .rbot { flex-wrap: wrap; }
  .rcard .rleft { margin-left: 0; white-space: normal; }

  /* D1 — ① 을 위에 고정한다(시안 3b: 이름·AC·HP · 프리셋 · 명중 굴림 + 칩).
     ⚠ **칸(`.simgrid`)을 flex 열로 바꾼다.** 한 열 격자에서는 칸마다 **제 줄 높이**라, 엔진에
       따라 sticky 가 움직일 여백이 없을 수 있다(격자 칸의 기준 상자가 격자 영역이냐 격자 전체냐가
       엔진마다 갈린다). flex 칸의 기준 상자는 **칸 전체**라 끝까지 붙는다. `order` 는 flex 에서도
       그대로 먹어 ①②③ 차례가 산다. */
  #panel .simgrid { display: flex; flex-direction: column; align-items: stretch; }
  /* ① 카드는 두 겹으로 풀린다 — 고정 바가 **칸의 자식**이어야 칸 끝까지 붙는다. 풀린 카드의
     테두리·바탕은 두 겹이 나눠 입는다. */
  #panel .simfoe { display: contents; }
  #panel .simfoepin, #panel .simfoemore, #panel .mtfoes { order: 1; }
  #panel .simfoepin {
    position: sticky; top: 0; z-index: 30;
    /* 줄은 flex 로 흘린다 — 이름줄 · 프리셋 줄 · 「명중 굴림 + 칩」 줄(시안 3b 의 세 줄).
       격자로 두 열을 박으면 320px 기기에서 이름줄이 칸을 넘는다. */
    display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
    padding: 10px 14px 8px;
    /* 불투명 — 밑으로 지나가는 계획이 글자와 겹치면 안 된다. */
    background: #16110c; border: 1px solid var(--gold-dim);
  }
  #panel .simfoepin .simhead { flex: 1 1 auto; min-width: 0; margin: 0; }
  #panel .simfoepin .simfoetop { flex: 0 0 auto; margin: 0 0 0 auto; gap: 10px; }
  /* 고정 바의 첫 줄은 시안 3b 처럼 **「AC 12 · 체력 45」 한 줄**이다. 데스크톱 카드의 큰 AC(34px)와
     그 위의 「AC」 꼬리표를 그대로 두면 이 줄만 43px 이었다(실측) — 꼬리표를 수 옆으로 눕히고
     수를 줄인다. 같은 칸·같은 id 라 `writeTurnNumbers` 가 갈아 끼우는 자리는 그대로다. */
  #panel .simfoepin .simfoetop > div:first-child { display: flex; align-items: baseline; gap: 4px; }
  #panel .simfoepin .simack { margin: 0; }
  #panel .simfoepin .simac { font-size: var(--fs-num-md); line-height: 1; }
  /* 체력도 같은 줄에 눕힌다 — 라벨·값·막대가 세로로 쌓여 43px 이던 것(실측). 막대는 짧게 곁에 선다. */
  #panel .simfoepin .simhp { display: flex; align-items: center; gap: 4px; }
  #panel .simfoepin .simhp .v { font-size: var(--fs-num-md); line-height: 1; }
  #panel .simfoepin .simhp .hpbar { width: 40px; margin: 0; }
  #panel .simfoepin .targetpresets {
    flex: 1 1 100%; margin: 0;
    display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 2px;
  }
  /* ⚠ **고정 바의 프리셋은 이름만 싣는다** — 시안 3b 가 그렇게 정했다(3a 카드에만 「AC · 체력」
     부제가 있다). 실측(2026-09-16, 390px): 부제까지 실으면 다섯 칸이 네 줄로 접혀 **프리셋 줄만
     85px** 이었고 고정 바가 204px 로 화면의 4분의 1을 먹었다. 값은 사라지지 않는다 — 고르면 바로
     위 이름줄의 AC·체력이 그 값으로 바뀐다. */
  #panel .simfoepin .preset .psub { display: none; }
  /* 좁은 칸에서 이름이 **낱말 가운데서** 끊겼다(「가장 강 / 한 적」·「직접 입 / 력」, 실측). 띄어쓰기에서만 끊는다. */
  #panel .simfoepin .preset .pname { word-break: keep-all; }
  #panel .simfoepin .rollseg { flex: 0 0 auto; margin: 0; }
  /* 칩은 굴림 곁 남은 폭에서 한 줄로 옆으로 민다 — 칩이 늘어도 고정 바가 자라지 않는다. */
  #panel .simfoepin .condchips {
    flex: 1 1 0; min-width: 0; margin: 0;
    flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
  }
  #panel .simfoepin .condchips::-webkit-scrollbar { display: none; }
  #panel .simfoepin .condchip { flex: 0 0 auto; }
  #panel .simfoemore { padding: 0 14px; border: 1px solid var(--gold-dim); background: #16110c; }
  /* 좁은 화면에선 검색·세부 조정이 한 줄 접기 뒤에 선다(시안 3b 의 ① 아래엔 아무것도 없다). */
  #panel .foefold > summary { display: flex; }
  /* ⚠ **빌드 탭 줄의 고정을 푼다 — 계산 탭 · 좁은 화면에서만.** 사용자가 정했다(2026-09-16):
     둘 다 붙이면 고정 영역이 화면 절반에 가깝다(탭 줄 136px · ① 고정 바 · 시트 · 탭 바 56px).
     데스크톱은 그대로 붙는다 — `typography.test.js` 「탭줄은 미디어 쿼리 밖에서 붙는다」가 지키는
     그 결함(데스크톱에서만 안 붙던 것)과 자리가 다르다. 다른 탭으로 가려면 맨 위로 올린다. */
  body:has(#panel .simwrap) .tabs { position: static; }

  /* D5 — 퀵슬롯은 화면 아래 **떠 있는 시트**다(시안 3b: 손잡이 · 제목과 탭 · 칸).
     사이트 탭 바 **위에** 뜬다 — 그 높이는 탭 바와 같은 변수에서 파생한다(숫자를 두 번 안 적는다). */
  #panel .hbsheet {
    position: fixed; left: 0; right: 0; z-index: 31;
    bottom: calc(var(--m-tabbar) + env(safe-area-inset-bottom, 0px));
    display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 0 8px;
    padding: 6px 12px 10px;
    background: #100c08; border-top: 1px solid #5a4a2a; box-shadow: 0 -12px 30px rgba(0, 0, 0, .6);
  }
  /* 손잡이 — 그림은 40×4 막대지만 **누르는 자리는 44px** 다. 시트 위 가장자리에 반쯤 걸쳐
     세워 시트의 높이를 안 먹는다. */
  #panel .hbhandle {
    display: block; position: absolute; top: calc(var(--m-touch) / -2); left: 50%;
    width: 88px; min-height: var(--m-touch); margin: 0 0 0 -44px; padding: 0;
    background: none; border: 0; cursor: pointer;
  }
  #panel .hbhandle::before {
    content: ''; display: block; width: 40px; height: 4px; margin: 0 auto;
    border-radius: 2px; background: #5a4a2a;
  }
  /* 제목·탭은 한 줄, 칸은 그 아래 — `.hb` 를 풀어 둘을 시트의 격자에 바로 앉힌다. */
  #panel .hbsheet > .sub { grid-column: 1; margin: 0; font-size: var(--fs-xs); }
  #panel .hbsheet .hb { display: contents; }
  #panel .hbsheet .hbtabs { grid-column: 2; grid-row: 1; margin: 0; transform: none; }
  #panel .hbsheet .hbslots {
    grid-column: 1 / -1; margin-top: 6px;
    /* 두 줄까지 보이고 나머지는 시트 안에서 민다 — 시트가 화면을 다 덮지 않는다. */
    max-height: var(--m-sheet-slots); overflow-y: auto; overscroll-behavior-y: contain;
  }
  /* 직업 주문은 효과·시전 레벨·변형 고르기가 함께 온다. 아이콘은 그대로 두고
     모든 칸을 같은 폭으로 넓힌다 — 특정 주문만 여러 열을 차지하지 않는다. */
  body:has(#panel .hbtab.on[data-hbtab="class"]) {
    --m-sheet-slots: clamp(240px, 30vh, 280px);
  }
  #panel .hbsheet:has(.hbtab.on[data-hbtab="class"]) {
    --hb-cell: clamp(88px, calc((100vw - 32px) / 3), 128px);
  }
  :is(#panel, #boardpreviewpanel) .hbsheet:has(.hbtab.on[data-hbtab="class"]) .hbslotwrap {
    display: flex; flex-direction: column; align-items: center; align-self: start;
    height: auto; padding: 0; gap: 2px;
  }
  :is(#panel, #boardpreviewpanel) .hbsheet:has(.hbtab.on[data-hbtab="class"]) .hbslotwrap > .hbcast,
  :is(#panel, #boardpreviewpanel) .hbsheet:has(.hbtab.on[data-hbtab="class"]) .hbslotwrap > .hbval,
  :is(#panel, #boardpreviewpanel) .hbsheet:has(.hbtab.on[data-hbtab="class"]) .hbslotwrap > .hbsustain {
    position: static; flex-shrink: 0;
  }
  /* 공개 계산은 글 안에 남긴다. 패널 폭에서 테두리 2px·칸 사이 8px를 빼 세 열을 나눈다. */
  #boardpreviewpanel .hb {
    display: flex; flex-direction: column; gap: 6px; padding: 12px 0;
  }
  #boardpreviewpanel .hbtabs { order: -1; margin: 0; transform: none; }
  #boardpreviewpanel .hbsheet:has(.hbtab.on[data-hbtab="class"]) {
    --hb-cell: calc((100cqw - 10px) / 3);
  }
  #panel .hbsheet.folded .hbslots { display: none; }
  /* 시트가 덮는 만큼 **페이지 끝**을 비운다 — 탭 바 여백(`body` 위)과 같은 자리에 더한다.
     ⚠⚠ 처음엔 `.simwrap` 아래를 비웠는데 **틀렸다**(실측 2026-09-16, 390px): 시트는 화면에 떠
       있으니 계산 칸 뒤의 **사이트 바닥글**(출처와 라이선스 · 개인정보처리방침 · 이용약관)까지
       덮는다. 맨 아래로 내려도 그 링크들이 시트 뒤(610~788px)에 갇혀 누를 수 없었다.
       덮는 것이 페이지 끝이니 비우는 것도 페이지 끝이다. */
  body:has(#panel .hbsheet) {
    padding-bottom: calc(var(--m-tabbar) + env(safe-area-inset-bottom, 0px)
      + var(--m-touch) + var(--m-sheet-slots) + 28px);
  }
  body:has(#panel .hbsheet.folded) {
    padding-bottom: calc(var(--m-tabbar) + env(safe-area-inset-bottom, 0px) + var(--m-touch) + 28px);
  }

  /* CookieHub 는 CDN 스크립트가 이 파일 뒤에 스타일을 주입한다.
     실측 2026-09-04(320×568): 닫기 33×34px·주요 단추 39px·간격 12px.
     단추는 44px로 올리고 간격을 4px로 줄여, 세 단추 묶음은 141px에서
     140px로 오히려 1px 줄어들게 한다. `!important` 는 나중에 든 CDN 규칙을 이기기 위해 필요하다. */
  .ch2-dialog-actions-vertical { gap: 4px !important; }
  .ch2-dialog-actions-vertical .ch2-btn {
    box-sizing: border-box !important;
    min-height: var(--m-touch) !important;
  }
  .ch2-dialog-close-btn {
    box-sizing: border-box !important;
    min-width: var(--m-touch) !important;
    min-height: var(--m-touch) !important;
  }

  /* 전수 판정으로 드러난 나머지(2026-08-16). `cursor: pointer` 를 선언한 자리를 전부
     뽑아 실제 하한을 하나씩 계산했고, 그중 44px 에 못 미치던 것들이다. 괄호 안은
     고치기 전 계산값 —— **재서 나온 값이지 눈으로 본 값이 아니다.**

     ⚠ `min-height` 는 **하한**이다. `.conds label`·`.formtoggle` 둘은 문장 길이가
     게임 데이터마다 달라 실제 줄 수를 CSS 만으로 못 정했다(「모름」). 그래도 한 줄
     기준 하한이 각각 ≈19.8px·≈41.1px 라 44 미만이 될 수 있고, 하한을 거는 것은
     내용이 길 때 아무 일도 안 하므로 안전하다 —— **「미달이었다」고 주장하는 것이
     아니라 「44 밑으로는 안 내려가게」 한다.** */
  .tagpicker summary { min-height: var(--m-touch); }   /* ≈24.2px */
  .acctbtn           { min-height: var(--m-touch); }   /* ≈31.8px */
  .calcfold > summary{ min-height: var(--m-touch); }   /* 32px 명시였다 */
  .effunread summary { min-height: var(--m-touch); }   /* ≈19.8px */
  #list button.item-row,
  #list button.spell-row,
  .buildlist button.build-row,
  .buildlist button.party-row,
  .pickerlist button.picker-row,
  .pickerlist button.build-choice,
  button.partyslot-main,
  /* 클라우드 문서 픽커 행(`.cdpickrow`, 20차 스타일 핫픽스 2026-08-25) — 위
     `.build-row`/`.picker-row` 와 같은 자리. 전수 검사(아래 「누른다고 선언한
     것」)가 `cursor: pointer` 를 보고 곧바로 물었다. */
  button.cdpickrow { min-height: var(--m-touch); }
  .setchip           { min-height: var(--m-touch); }   /* ≈27.8px */
  .steps li.goto     { min-height: var(--m-touch); }   /* ≈27.8px */
  .sustaindrop       { min-height: var(--m-touch); }   /* ≈11.9px — 가장 작았다 */
  .formtoggle        { min-height: var(--m-touch); }   /* 모름. 위 ⚠ 참고. 야수 변신
                                                          스위치 하나뿐이라 개수 축이 없다 */
  .del { min-width: var(--m-touch); min-height: var(--m-touch); }

  select,
  input[type="search"],
  input[type="text"] { min-height: var(--m-touch); }

  /* ⚠ **여기만 글자 크기를 건드린다 — 이 블록 머리말의 「글자 크기는 안 건드린다」에
     대한 예외다.** 까닭이 배치가 아니라 브라우저 동작이라서다: iOS 사파리는 글자가
     **16px 미만인 글 입력칸에 포커스가 가면 페이지를 확대하고 되돌리지 않는다.**

     실측(2026-08-23, CSS 소스 판정 — 뷰포트는 못 잰다):
       skin.css   `input, select, textarea { font: inherit }` → 본문 14px 을 물려받는다
       style.css  `#itemfilter/#spellfilter input[type=search]`·`.tagtools …` → 13px
     즉 **글을 넣는 칸이 전부 미달**이었다. 데스크톱 14px 체계(인게임 재현)는 그대로
     두고 좁은 화면에서만 16px 로 올린다.

     ⚠ **id·class 로 박힌 13px 을 이기려면 그 선택자를 그대로 다시 적어야 한다** —
     미디어 쿼리는 구체성을 안 올린다. 아래 셋이 그것이다.
     ⚠ **체크박스·라디오·range 는 넣지 않는다** — 확대를 안 일으키고, 위 20px 규칙과
     싸운다.
     ⚠ **실기기 확인이 남았다** — 이 저장소의 에이전트는 모바일 뷰포트를 못 잰다. */
  input[type="search"], input[type="text"], input[type="number"],
  input[type="email"], input[type="password"], input[type="tel"], input[type="url"],
  select, textarea,
  #itemfilter input[type="search"],
  #spellfilter input[type="search"],
  .tagtools input[type="search"],
  /* ⚠ 레벨 설명 칸(panels/class.js 의 <textarea class="lvnote">). skin.css:396 이
     클래스로 13px 을 박아서 위 맨 `textarea` 줄(구체성 0,0,1)이 못 이긴다 —
     **재검수가 잡은 실물**이고, 손으로 쥔 마크업 목록 밖이라 그물도 놓쳤다. */
  .lvnote { font-size: 16px; }
  /* 상위 슬롯 선택기도 select 라서 10px 데스크톱 규칙을 되받는다. 작은 글자는
     iOS 가 포커스 때 화면을 확대하고, 모바일에서는 선택기 자체가 터치 대상이다. */
  /* ⚠ 글자만 키우면 상자를 넘는다 — 높이 변수를 같이 올린다(`skin.css` 의
     `--hbcast-h` 머리말). 변수는 **`.hbslotwrap`(부모)** 에 건다.
     ⚠⚠ **값은 `--m-touch` 다 — 24px 이 아니다.** 아래 「`select … { min-height: var(--m-touch) }`」
     규칙이 이 select 에도 걸려 실제 높이는 44px 인데, 변수가 24px 이면 칸은 24px 만 비워
     둔다 — 레벨 고르기만 달린 칸에서 select 가 칸 바닥을 **20px 넘고**, 「＋ 유지」가 있는 칸에선
     select 와 단추가 **16px 겹쳤다**(헤드리스 크롬 500px 실측 2026-09-14, 눈가림 검수가 짚음).
     높이 정본이 둘이 되면 이렇게 갈린다 — 변수가 그 규칙과 같은 수를 읽게 한다.
     `tests/hotbar-grid.test.js` 가 「변수 ≥ select 최소 높이」를 소스에서 문다. */
  .hbslotwrap { --hbcast-h: var(--m-touch); }
  .hbslotwrap:has(> .hbsustain) { --hbsustain-h: var(--m-touch); }

  /* ⚠⚠ **칸 폭(46px)을 안 넘긴다 — 넘기면 격자가 깨진다.**
     16px 글자로 「1레벨」+화살표는 46px 에 안 들어간다. 넓혀서 풀려다 두 번 틀렸다:
       ① 선택기만 60px 로 키움 → 줄바꿈되는 칸끼리 **포개졌다**(자리를 차지하는
          것은 `.hbslotwrap` 인데 자식만 키웠다)
       ② 칸까지 60px 로 키움  → 셋이 붙어 **한 덩어리**로 보이고 아이콘 격자와 어긋났다
     **화살표를 뺀다.** 46px 안에 글자가 온전히 들어가고 아이콘과 정확히 맞는다 —
     모바일은 상자 전체가 탭 대상이라 데스크톱만큼 화살표에 안 기댄다. */
  .hbcast select {
    width: var(--hb-cell); height: var(--hbcast-h); font-size: 16px;
    padding: 0 2px; line-height: var(--hbcast-h);
    text-align: center; background-image: none;
  }

  /* AC 슬라이더는 34px 이었다. 끌어야 하는 것이라 더 중요하다. */
  .acslider input[type="range"] { min-height: var(--m-touch); }

  /* 체크박스는 13px 이었다. 상자를 키우고 **라벨 전체**가 누르는 자리가 되게 한다 —
     <label> 안의 체크박스는 라벨 아무 데나 눌러도 켜진다.
     .dummytag 은 계산 탭의 목표 성질 태그·상태 14개다(2026-08-07 실측).
     .pfchoice 는 공개 프로필 편집 폼의 아바타·테마·역할 라디오/체크박스다
     (계정 3-2 Task 7, web/lib/profile-editor.js). */
  .spoilerfree, .raretoggle, .taggroup label, .dummytag, .pfchoice {
    display: flex; align-items: center; min-height: var(--m-touch);
  }
  .spoilerfree input[type="checkbox"],
  .raretoggle input[type="checkbox"],
  .taggroup label input[type="checkbox"],
  .dummytag input[type="checkbox"],
  .pfchoice input { width: 20px; height: 20px; flex: none; }

  /* ⚠ **길게 누르면 iOS 가 선택 콜아웃을 띄워 제스처를 가져간다** — 그러면
     pointercancel 이 와서 판정이 취소되고 시트가 안 뜬다. 툴팁이 붙는 칸에서만
     끈다(글을 고르는 것이 뜻이 있는 자리는 안 건드린다). 리뷰 M-6. */
  /* ⚠ **attachTooltip 이 겨누는 것과 같은 것을 겨눈다** — [data-key]·[data-id] 다.
     클래스로 적었더니 .gchip(툴팁 칸이 아니다)은 헛돌고 고르기 목록의
     `#pickerlist li[data-id]`(attachTooltip 의 두 뿌리 중 하나)가 빠졌다 — 리뷰가
     잡았다. 어휘를 두 벌 적지 않고 그쪽 선택자를 그대로 쓴다. */
  #panel [data-key], #panel [data-id], #pickerlist [data-id] {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
  }
}

/* CookieHub의 허용·거부·저장 단추는 같은 명암을 쓴다. CDN이 뒤에 삽입한
   테마·hover 규칙보다 우선하여 작은 글씨도 읽히게 한다(전체 화면 크기). */
.ch2-container .ch2-btn-primary,
.ch2-container .ch2-btn-secondary {
  color: #201b14 !important;
  background: #f4ead7 !important;
}
.ch2-container .ch2-btn-primary:focus-visible,
.ch2-container .ch2-btn-secondary:focus-visible {
  outline: 3px solid #201b14 !important;
  outline-offset: -4px !important;
}

/* CookieHub의 동의 설정은 배너에서 처리하고, 평상시 화면을 가리는
   좌하단 플로팅 설정 버튼은 숨긴다. 다른 동의 UI는 유지한다.

   ⚠ **겨누는 것은 `.ch2-icon` 하나다 — 뿌리(`.ch2.ch2-region-g0`)가 아니다.**
      뿌리를 숨기면 그 안의 동의 배너(`#ch2-dialog`)까지 같이 사라지는데,
      CookieHub 는 배너를 띄우면서 `body` 에 `overflow: hidden` 을 **인라인으로**
      건다. 그래서 배너만 안 보이고 잠금은 그대로 남아 **페이지 스크롤이 영영
      잠긴다** — 배너가 `pointer-events: none` 이라 눌러서 풀 수도 없다.
      실측 2026-09-09(운영 · 안드로이드 393px): 뿌리를 숨긴 판에서 스와이프 뒤
      `scrollY` 가 **0** 이었고, 동의 단추를 스크립트로 눌러야만 602 로 풀렸다.
      `.ch2-icon` 은 배너가 떠 있는 동안 `display: none` 이라 이 규칙이
      배너 동작에 닿지 않는다. */
body > .ch2 .ch2-icon {
  opacity: 0 !important;
  pointer-events: none !important;
  visibility: hidden !important;
}

/* ── 댓글 (3단계 · 익명 허용, 2026-09-09) ────────────────────────────────
   ⚠ **손가락으로 누를 자리를 키운다.** 「수정·삭제·답글」은 데스크톱에서
   `.bdcacts .btn` 의 `padding: 2px 6px` 으로 촘촘한데, 모바일에서는 그대로면
   서로 붙어 오누름이 난다. `--m-touch`(44px)는 이 줄에서 좀 과해 보이므로
   **누르는 자리만** 그 값으로 늘리고 글자 크기는 그대로 둔다.
   ⚠ 익명 칸(이름·비밀번호)도 같이 키운다 — 전역 `input` 규칙(`padding: 5px 8px`)
   은 손대지 않는다. 그건 사이트 전체가 쓰는 자리라 여기서 흔들면 안 된다. */
@media (max-width: 720px) {
  .bdcacts .btn {
    min-height: var(--m-touch);
    padding-left: 10px;
    padding-right: 10px;
  }
  .bdcanon input,
  #boardcommentbody,
  #boardcommentsubmit {
    min-height: var(--m-touch);
  }
  /* 익명 칸 둘이 한 줄에 끼면 각자 너무 좁다 — 좁은 폭에서는 세로로 쌓는다. */
  .bdcanon { flex-direction: column; }
  .bdcanon input { width: 100%; }
  /* 아이콘 고르기(검색칸·결과 칩·여는 단추)도 손가락으로 누른다. 블록을 따로
     두지 않고 위와 **한 미디어 쿼리에** 넣는다 — 같은 폭을 두 번 적으면 한쪽만
     고치는 날이 온다. */
  .bdciconhit,
  #boardcommenticonq,
  #boardcommenticonbtn { min-height: var(--m-touch); }
}
