/* 포케팀 SSR 공통 스타일 (WEB-DESIGN-SYSTEM.md, ADR-1035 §1·§10)
   mount 경로(/static/v1/...)의 버전 세그먼트는 자산이 바뀌는 배포에서만
   올린다(빌드 도구 없이 수동 캐시 무효화).

   이 웹 MVP는 앱 DESIGN-SYSTEM.md의 토큰을 공유하지 않는다 — 별도 팔레트다
   (WEB-DESIGN-SYSTEM.md §0). 값은 그 문서 §1~§3과 목업(mockup_src/*.dc.html)을
   정본으로 옮겼다. 목업에는 있지만 WEB-DESIGN-SYSTEM.md §5가 컴포넌트로
   정의하지 않은 것(스테퍼 `.stepper`, 출발 약속 토글 행 `.toggle-row`)은
   기존 토큰(색·spacing·radius)만 재사용해 이 파일에서 새로 이름 붙였다 —
   §5 표에 없는 이름이라고 취향으로 넣은 값이 아니다(TICKET-163).

   이 파일은 화면별 티켓(A2 온보딩=TICKET-162, H1 레이드 만들기=TICKET-163
   등)이 공유한다 — `:root` 토큰은 한 벌만 있으면 되므로 화면마다 새로
   선언하지 않는다. **같은 이름(`.field-group`·`.btn` 등)을 화면마다 다른
   의미로 다시 정의하면 병합 때 캐스케이드 충돌이 난다**(develop 7756a94
   리베이스에서 실제로 발생 — TICKET-163 재작업 보고
   `doc/reports/TICKET-163/<이 커밋 시각>-backend-dev-rework.md` 참고).
   그래서 이 파일은 두 원칙을 따른다: (1) 여러 화면이 같은 시각적 의미로
   쓰는 것(색·spacing·`.field`·`.disclaimer-footer` 등)만 공용 이름을 쓰고
   (2) 화면 전용 레이아웃 패턴은 화면을 식별할 수 있는 이름을 쓴다
   (`.field-stack`은 H1 전용 flex column, `.field-group`은 A2 전용
   margin 기반 — 이름이 비슷해 보이지만 다른 레이아웃이라 합치지 않았다).

   2026-09-26 TICKET-212 — 다크 리스킨(`doc/design/a2/design-system-v1/`,
   기준: A2 다크 디자인 시스템). 원본 `tokens.css`·`components.css`는
   클래스 이름이 이 파일과 다르다(예: `.btn--primary` vs `.btn-primary`).
   화면별 구조 변경은 이 티켓 범위 밖이라 **클래스 이름은 그대로 두고
   `:root` 토큰 값과 이 값을 참조하는 규칙의 색·글꼴만** 원본 문서의
   값으로 바꿨다 — 이름을 원본과 맞추는 리네이밍은 하지 않는다(기존
   매크로·화면 JS가 이 클래스 이름을 그대로 참조한다). 원본에만 있고
   여기 대응이 없는 컴포넌트(좌석 원 `.seats`/트레이너 리스트
   `.roster`·`.row`/팀 선택 `.team-pick`/범용 `sheet()`·`code_card()`
   매크로 등)는 전부 이 티켓의 "범위 밖" 목록(리스트 통일·좌석 원 요약·
   하단 독·헤더 진행 막대·팀 색 점)에 걸리거나 기존 매크로(`bottom_sheet.html`
   의 시트, `.checklist-item`의 체크 등)와 기능이 겹쳐 새로 추가하지
   않았다 — 쓰이지 않는 매크로를 미리 심어 두면 나중에 어느 쪽이 정본인지
   헷갈리는 대가가 더 크다고 판단했다(보고서 참고).

   2026-09-27 TICKET-255 — 디자인 정본이 `doc/design/current/`로 교체되며
   `tokens.css`(값만 유효, 화면 배치는 screens/*.html)가 처음으로 이
   리포에 파일 그대로 들어왔다(`app/assets/web/tokens.css`, base.html이
   이 파일보다 먼저 링크한다). 아래 `:root`는 그 파일과의 관계를 셋으로
   나눈다 — ① **이름·값이 완전히 같은 변수**(`--color-bg`·`--color-surface`
   ·`--color-team-*`·`--font-display`·`--font-number`·`--color-scrim`·
   `--space-1~6`·`--space-8`·`--radius-sm`·`--radius-btn`·`--radius-input`)는
   여기서 **지웠다** — 같은 이름을 이 파일에서 또 선언하면 값이 서로를
   가리키는 자기참조가 돼 무효가 된다(CSS 커스텀 프로퍼티 사이클 규칙),
   그래서 tokens.css 쪽 선언만 남긴다. ② **이름은 다르지만 값이 같은
   변수**(예: `--color-text-primary`=`--color-text`)는 값을 `var(--color-text)`
   같은 참조로 바꿨다 — 기존 화면 마크업·JS가 이 리포 고유 이름
   (`--color-text-primary` 등)을 그대로 쓰므로 리네이밍은 하지 않는다(위
   TICKET-212 원칙과 동일). ③ **tokens.css에 대응이 없는 값**(예:
   `--color-border-strong`·`--color-primary-hover`·`--radius-lg`—18px는
   실제로 doc/design/current/screens/*.html의 카드·시트 여러 곳에서 그대로
   확인돼 유지, `--size-button-md/sm/xl` 등)은 손대지 않고 남긴다(헌장 §9
   "디자인에 없는 값은 스펙/기존 값 유지"와 같은 원칙).

   실측 드리프트 2건은 tokens.css 값으로 고쳤다(둘 다 이 리포가 옛 a2-v1
   크기를 그대로 쓰고 있던 것): `--size-button-lg`를 56px(v1)에서
   tokens.css `--size-btn` 52px로(주석 "v1 56 → 52" — doc/design/current/
   screens/A2.html·H2.html 등 실제 버튼은 전부 52px 렌더값으로 확인),
   `--min-touch-target`을 tokens.css `--size-touch`(44px, 값은 같지만 이제
   참조로 통일). `.field` 입력 높이(48→52px)는 tokens.css에 대응 토큰이
   없어(입력 전용 크기 토큰 없음) 아래 5.9절에서 실측값으로 직접 바꿨다.

   `--dock-h`는 예외다 — tokens.css가 `128px` 기본값을 선언하지만, 이
   리포는 화면마다 `var(--dock-h, <화면별 실측 폴백>)`로 dock_height.js가
   아직 못 잰 순간의 폴백을 다르게 쓴다(72/96/112/174px, 각 `.page-*`
   규칙 참고). tokens.css의 128px가 :root에 그대로 있으면 "정의는 됐지만
   틀린 가짜값"이 돼 각 화면의 `var(--dock-h, 폴백)`이 폴백 대신 이 128을
   써버린다(CSS `var()`는 프로퍼티가 "존재하지 않을 때만" 폴백을 쓴다) —
   그래서 아래 `--dock-h: unset;`으로 tokens.css의 선언을 무효화해 각
   화면이 원래 폴백을 쓰게 되돌린다. `dock_height.js`가 인라인
   스타일(`documentElement.style.setProperty`)로 실측값을 넣으면 그 값이
   어차피 이 :root 선언보다 특정도가 높아 이긴다 — 즉 이 unset은 "JS가
   돌기 전 잠깐"에만 영향을 준다. */

:root {
  /* 2026-09-26 TICKET-212 — 라이트 → 다크(A2) 전환. 배경 자체가 어두워지므로
     폼 컨트롤·스크롤바도 다크 배색이 자연스럽다(옛 `light only`는 밝은
     테마가 OS 다크모드에 반전되는 것을 막기 위한 값이었다, TICKET-163). */
  color-scheme: dark;

  /* 배경 — --color-bg/--color-surface는 tokens.css와 이름·값이 같아
     지웠다(위 TICKET-255 주석 ① — 같은 이름을 여기서 또 선언하면 자기
     참조가 된다). --color-surface-muted만 이름이 달라 별칭으로 남긴다. */
  --color-surface-muted: var(--color-surface-2);

  /* 텍스트 */
  --color-text-primary: var(--color-text);
  --color-text-secondary: var(--color-text-2);
  --color-text-muted: var(--color-text-3);

  /* 테두리 */
  --color-border: var(--color-line);
  --color-border-strong: #3a4568; /* tokens.css에 대응 없음 — 기존 값 유지 */
  --color-border-dashed: var(--color-seat-empty);

  /* 주 강조색(하늘색 = "누를 수 있음") */
  --color-primary: var(--color-action);
  --color-primary-hover: #29b8d6; /* tokens.css에 대응 없음 — 기존 값 유지 */
  --color-primary-surface: #12313d; /* tokens.css에 대응 없음(코드 카드 전용 톤) — 기존 값 유지 */
  --color-primary-border: var(--color-action);
  /* 밝은 하늘색 배경 위 글자(대비 9.5:1) — 라이트 테마에서 흰 글자였던
     자리(.btn-primary 등)를 전부 이 값으로 바꿨다. 흰 글자를 그대로 두면
     이 배경에서 대비가 부족하다. */
  --color-on-primary: var(--color-on-action);

  /* 팀 점(PRD-012/AC-56·AC-57, WEB-DESIGN-SYSTEM.md §1 — TICKET-215) —
     tokens.css `--color-team-*`와 이름·값이 완전히 같아(TICKET-255) 위
     TICKET-255 주석 ①에 따라 지웠다. 화면 마크로·JS는 그대로
     `--color-team-blue` 등을 쓰고, 그 값은 이제 tokens.css가 공급한다. */

  /* 카카오 로그인 버튼 (브랜드 고정값 — 라이트/다크 공통으로 바뀌지 않는다) */
  --color-kakao-bg: var(--color-kakao);
  --color-kakao-text: var(--color-on-kakao);

  /* 출발 약속(패스 세이브) 강조 박스 — 앰버(urgent) 계열, "시간·준비 중"에
     쓰는 색과 같은 역할. 2026-09-26 TICKET-237이 디자인 v2.1 토큰과 값을
     맞췄고(#3A2A12/#FFB547), TICKET-255에서 tokens.css `--color-urgent*`
     참조로 바꿨다(값은 그대로, 참조만 도입). border는 tokens.css에 대응
     토큰이 따로 없어 기존 값을 유지한다(헌장 §9 "디자인에 없는 값은
     스펙/기존 값 유지"). */
  --color-promise-bg: var(--color-urgent-bg);
  --color-promise-text: var(--color-urgent);
  --color-promise-border: #7a5a22;

  /* 비활성 */
  --color-disabled-bg: var(--color-surface-2);
  --color-disabled-text: var(--color-text-disabled);

  /* 배지 — "준비 중"류는 앰버(urgent), "확정"류는 하늘색(action) 배경이라
     글자는 --color-on-primary(어두운 글자)로 바꿨다(위 흰 글자 대비 문제와
     같은 이유). --color-badge-recruiting-bg/--color-pending-bg(#2a2013)는
     --color-urgent-bg(#3a2a12)와 색상은 같은 계열이지만 실측값이 달라
     (배지는 더 어두운 변형) tokens.css로 별칭하지 않고 유지한다. */
  --color-badge-recruiting-bg: #2a2013;
  --color-badge-recruiting-text: var(--color-urgent);
  --color-badge-confirmed-bg: var(--color-action);
  --color-badge-confirmed-text: var(--color-on-action);
  --color-badge-inprogress-bg: var(--color-line);
  --color-badge-inprogress-text: var(--color-text);
  --color-ready-bg: var(--color-action);
  --color-ready-text: var(--color-on-action);
  --color-pending-bg: #2a2013;
  --color-pending-text: var(--color-urgent);

  /* 경고/예외 배너 — 빨강(danger, "해산만"에 쓰는 색과 같은 계열).
     --color-warn-bg(#2e1416)는 tokens.css에 대응 토큰이 없어 유지한다. */
  --color-warn-bg: #2e1416;
  --color-warn-text: var(--color-danger-text);
  --color-warn-border: var(--color-danger);

  /* 스크림 — tokens.css --color-scrim과 이름·값이 같아 지웠다(TICKET-255,
     위 주석 ①). */

  /* 타이포그래피 — 본문은 Gothic A1, 헤드라인은 Black Han Sans, 숫자
     전용(타이머·트레이너 코드·인원 등, 아래 해당 규칙에서 개별 지정)은
     Chakra Petch(WEB-DESIGN-SYSTEM.md §3). 로드는 base.html 참고. 크기·
     줄높이는 기존 화면 레이아웃이 이 값에 맞춰져 있어 바꾸지 않았다
     (TICKET-212 범위 — "모습만 교체"). **굵기는 400으로 낮췄다** — Black Han
     Sans는 Google Fonts에 굵기 400 한 가지만 있어 700을 요청하면 브라우저가
     합성 굵게(faux bold)를 만드는데, 헤드리스 Chrome(맥OS)에서 이 폰트의
     일부 한글 글자(예: "들")가 합성 굵게 상태에서만 깨져 렌더링되는 것을
     실측했다(TICKET-212 검증, `doc/reports/TICKET-212/` minimal2.png류
     재현). Black Han Sans 자체가 이미 두꺼운 디스플레이 서체라 400으로도
     시각적 굵기 차이가 크지 않다.
     --font-display/--font-number는 tokens.css와 이름·값이 같아 지웠다
     (TICKET-255, 주석 ①). --font-family-base는 이름이 달라(tokens.css
     `--font-body`) 별칭으로 남긴다. */
  --font-family-base: var(--font-body);
  --text-display: 400 22px/1.3 var(--font-display);
  --text-title: 400 18px/1.4 var(--font-display);
  --text-body-lg: 500 16px/1.5 var(--font-family-base);
  --text-body: 400 14px/1.5 var(--font-family-base);
  --text-caption: 400 13px/1.4 var(--font-family-base);
  --text-micro: 500 12px/1.3 var(--font-family-base);

  /* 스페이싱 — --space-1~6·--space-8은 tokens.css와 이름·값이 같아 지웠다
     (TICKET-255, 주석 ①). --space-10(40px)은 tokens.css에 없어 유지한다. */
  --space-10: 40px;

  /* 반경·그림자 — --radius-sm(10)·--radius-btn(16)·--radius-input(14)은
     tokens.css와 이름·값이 같아 지웠다(TICKET-255, 주석 ①). --radius-md는
     이름이 달라(tokens.css --radius-input과 값 동일) 별칭으로 남긴다.
     --radius-lg(18px)는 tokens.css --radius-card(16)와 다른 값인데,
     doc/design/current/screens/A2.html·P1.html·H2-1.html의 실제 카드
     (`.card`/필드 카드)·시트 안 코드 카드가 여전히 18px를 쓰는 것을
     TICKET-255에서 재확인해 유지한다(tokens.css --radius-card 16은 R2
     주최자 강조 카드 등 다른 컴포넌트 몫 — 화면별 이식 티켓(256~258)이
     실제 마크업을 옮기며 구분한다). 그림자는 밝은 배경 전제였던 알파값을
     어두운 배경에서도 보이도록 올렸다. */
  --radius-md: var(--radius-input);
  --radius-lg: 18px;
  --radius-pill: 999px;
  --radius-sheet-top: var(--radius-sheet) var(--radius-sheet) 0 0;
  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.4), 0 2px 8px rgba(0, 0, 0, 0.35);
  --shadow-sheet: 0 -4px 20px rgba(0, 0, 0, 0.5);

  /* 버튼 높이 — --size-button-lg는 tokens.css --size-btn(52px, 주석
     "v1 56 → 52")로 실측 드리프트를 고쳤다(위 TICKET-255 큰 주석 참고,
     doc/design/current/screens/A2.html·H2.html 등 실제 버튼 렌더값 52px로
     확인). --size-button-xl/md/sm은 tokens.css에 대응이 없어 유지한다
     (각각 다른 용도로 이미 쓰이고 있어 임의로 52/56에 흡수하지 않는다).
     --min-touch-target은 tokens.css --size-touch와 값(44px)이 같아 별칭. */
  --size-button-lg: var(--size-btn);
  --size-button-xl: 64px;
  --size-button-md: 48px;
  --size-button-sm: 32px;
  --min-touch-target: var(--size-touch);

  /* tokens.css가 --dock-h:128px를 선언하지만 이 리포는 화면별 실측 폴백을
     쓴다 — 위 큰 주석 "TICKET-255 ... --dock-h는 예외다" 참고. */
  --dock-h: unset;
}

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

/* [hidden] 속성이 항상 이긴다(TICKET-163 QA 반려 09-25 22:57 재작업) — 컴포넌트
   규칙(`.info-box--promise` 등)이 `display`를 무조건 지정하면 그 규칙이
   브라우저 기본 `[hidden]{display:none}`과 특정도(0,1,0)가 같아 author
   스타일이 이겨 버린다. 폼 컨트롤 JS(`raid_new.js` 등)가 표준 `hidden`
   프로퍼티만 토글하는 패턴을 계속 쓸 것이므로, 개별 컴포넌트 셀렉터마다
   `:not([hidden])`을 붙이는 대신 여기 전역 규칙 하나로 항상 이기게 고정한다. */
[hidden] {
  display: none !important;
}

/* ── 더블탭 확대 방지 (TICKET-232, PRD-012/AC-62, WEB-DESIGN-SYSTEM.md v2.1
   §0 "버튼·카드 요소에는 touch-action: manipulation") ──
   여기 나열한 것은 이 파일에 이미 있는 버튼·카드류 컴포넌트 클래스 전부다
   (화면별 이름을 유지하는 파일 머리말 원칙에 따라 v2.1 원본 클래스명이
   아니라 이 파일의 기존 이름을 쓴다). `touch-action: manipulation`은
   더블탭 확대·팬 지연만 없애고 **두 손가락 핀치 확대는 그대로 둔다** —
   `user-scalable=no`/`maximum-scale`과는 다른 메커니즘(브라우저 표준 동작,
   AC-62가 명시적으로 요구하는 구분). */
button,
a,
.btn,
.checklist-item,
.consent-row,
.toggle-row,
.code-card,
.seat-tile,
.link-card,
.applicant-row,
.segmented__btn,
.stepper__btn,
.copy-icon-btn,
.reason-radio-item,
.notify-line__ask-btn,
.team-pick__option,
.host-header,
.info-box,
.status-bar-pinned,
.host-bottom-fixed {
  touch-action: manipulation;
}

/* ── "앱처럼" 공통 항목 1/2 (PRD-012/AC-63, TICKET-249) ──
   `overscroll-behavior: none` — 스크롤 끝에서 튕기며 전체 페이지가
   당겨지는(pull-to-refresh) 브라우저 기본 동작을 막는다. `-webkit-text-
   size-adjust: 100%` — 아이폰 사파리가 화면 회전 시 폰트를 임의로 키우는
   동작(디자인 크기가 어긋나 보임)을 막는다. 두 손가락 핀치 확대 자체는
   건드리지 않는다(AC-62와 같은 원칙, `<meta viewport>`에 user-scalable을
   넣지 않는다 — base.html 참고). */
html {
  overscroll-behavior: none;
  -webkit-text-size-adjust: 100%;
}
body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text-primary);
  font: var(--text-body);
  font-family: var(--font-family-base);
  /* 100dvh 미지원 브라우저 폴백 — 뒤에 선언한 100dvh가 지원 시 덮어쓴다
     (WEB-DESIGN-SYSTEM.md §4, 인앱브라우저 주소창 높이 변화 대응). */
  min-height: 100vh;
  min-height: 100dvh;
  overscroll-behavior: none;
  /* ── "앱처럼" 공통 항목 1 (PRD-012/AC-63, TICKET-249) ── 길게 누름 시
     브라우저 기본 선택 팝업(복사·검색 등)이 뜨면 웹뷰 티가 난다. 기본은
     선택 금지, 예외 셋(트레이너 코드 숫자 `.code-value`, 파티 링크 주소
     `.link-card__url`, 입력칸 input/textarea)만 아래에서 되돌린다 —
     인앱 브라우저에서 `navigator.clipboard` [복사] 버튼이 정책상 막히는
     사례가 있어(TICKET-186 근거) 길게 눌러 직접 복사하는 경로를 남겨야
     한다. `user-select`는 상속되는 속성이라 body 한 곳에서 막으면 화면
     전체(레이드 밖 로그인·랜딩 포함)에 적용된다. */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}
.code-value,
.link-card__url,
input,
textarea {
  -webkit-user-select: text;
  user-select: text;
  -webkit-touch-callout: default;
}

a {
  color: var(--color-primary);
}
a:hover {
  color: var(--color-primary-hover);
}

main {
  max-width: 480px;
  margin: 0 auto;
  padding: var(--space-6) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

h1.text-display {
  font: var(--text-display);
  margin: 0 0 var(--space-5);
}

/* ── 5.1 버튼 .btn / .btn-primary (A2 온보딩이 정착시킨 표기, TICKET-162) ──
   border-radius는 TICKET-212에서 --radius-sm(10)→--radius-btn(16)으로
   올렸다(tokens.css 버튼 모서리 값, 모습만 교체). */
.btn {
  display: block;
  width: 100%;
  height: var(--size-button-lg);
  border: none;
  border-radius: var(--radius-btn);
  font: var(--text-body-lg);
  /* TICKET-255 — `--text-body-lg`의 굵기(500)는 doc/design/current/의 실제
     버튼 어디와도 안 맞는다(주 버튼 800, 보조/텍스트 버튼 700 — screens/
     H2-1.html "취소"·A3.html "로그아웃"·S0.html "보조 버튼" 전부 700, 주 버튼·
     danger는 800). 이 스코프 밖(주최자/참여자/끝난 파티 화면별 CSS,
     raid_h.css 등)은 이미 각자 `font-weight: 800`을 지역적으로 덮어써
     왔으므로 영향이 없다 — 여기 base 값은 그 스코프 CSS가 없는 화면
     (A1/A2/A3/랜딩/약관, 아래 `.btn-primary`/`.btn-danger` 참고)의 실제
     `.btn-outline`류(보조/텍스트 버튼, 700 유지)를 위한 것이다. */
  font-weight: 700;
  cursor: pointer;
}
/* ── "앱처럼" 공통 항목 3 (PRD-012/AC-63, TICKET-249) ── 네이티브 앱의
   눌림 피드백. `button` 전체(체크리스트·카피 아이콘 등 `.btn`이 아닌
   것 포함) + 버튼 모양 링크(`<a class="btn ...">`, 랜딩·H1 오류 링크 등).
   비활성(aria-disabled) 상태는 눌러도 아무 일이 없어 피드백을 주지
   않는다 — 위 `.btn-primary[aria-disabled]` 등 회색조 규칙과 이중으로
   "눌렸다"는 착시를 주지 않기 위함. */
button:active:not([aria-disabled='true']),
.btn:active:not([aria-disabled='true']) {
  transform: scale(0.97);
  opacity: 0.9;
}
.btn-primary {
  background: var(--color-primary);
  /* TICKET-212 — 밝은 하늘색 배경 위 흰 글자는 대비가 부족해 어두운 글자로 바꿨다. */
  color: var(--color-on-primary);
  /* TICKET-255 — 주 버튼은 어디서나 800(위 `.btn` 주석 참고). */
  font-weight: 800;
}
.btn-primary:hover {
  background: var(--color-primary-hover);
}
/* disabled는 네이티브 disabled 대신 aria-disabled를 쓴다(WEB-DESIGN-SYSTEM.md
   §5.1 — 스크린리더가 버튼 존재를 계속 읽게). 클릭 무시는 호출하는 화면의
   JS가 `aria-disabled` 값을 확인해 처리한다(onboarding.html 참고, H1은 아예
   핸들러를 안 붙인다 — AC-4c 범위). */
.btn-primary[aria-disabled='true'] {
  background: var(--color-disabled-bg);
  color: var(--color-disabled-text);
  cursor: not-allowed;
}
/* 2차 CTA(outline) — 표 "default(outline)" 행, 예: H1-1 "취소" (TICKET-168) */
.btn-outline {
  background: var(--color-surface);
  color: var(--color-primary);
  border: 1.5px solid var(--color-primary);
}
/* 동작이 아직 연결되지 않은 outline 버튼(TICKET-185 H2 "이 인원으로 마감" —
   AC-10 범위 밖) — `.btn-primary[aria-disabled]`와 같은 회색조로 "아직
   눌러도 반응 없음"을 시각적으로도 드러낸다. */
.btn-outline[aria-disabled='true'] {
  background: var(--color-disabled-bg);
  color: var(--color-disabled-text);
  border-color: var(--color-disabled-bg);
  cursor: not-allowed;
}
/* 되돌릴 수 없는 동작 확정 버튼(danger) — 표 "danger" 행(2026-09-26 신설).
   지금은 H2/H3 "파티 해산" 바텀시트의 [해산하기]에만 쓴다(TICKET-168은
   시트 매크로만 만들고 이 버튼을 쓰는 화면은 별도 티켓). */
.btn-danger {
  /* TICKET-255 — doc/design/current/screens/H2-1.html "해산하기"는 52px
     (다른 주 버튼과 같은 `--size-btn`)이지 48px(`--size-button-md`)가
     아니다 — S0 스타일 타일의 56px는 데스크톱 축척 예시라 실제 화면
     렌더값(52)을 따른다(위 `--size-button-lg` 주석과 같은 근거). */
  height: var(--size-btn);
  background: var(--color-warn-border);
  color: #ffffff;
  font-weight: 800;
}
.btn-danger:hover {
  filter: brightness(0.94);
}

/* ── 5.2 체크리스트 아이템 .checklist-item (H1, TICKET-163) ─────────── */
.checklist-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 48px;
  padding: 0 var(--space-4);
  border-radius: var(--radius-input);
  font: var(--text-body);
}
.checklist-item input[type='checkbox'] {
  width: 22px;
  height: 22px;
  margin: 0;
  flex-shrink: 0;
  /* TICKET-256 — 디자인 `current/screens/P1.html` 37행 `.ck input`
     실측(`accent-color:#3DD5F3`)에 맞춘다. 이전엔 이 선언이 없어
     브라우저 기본 파란 계열 체크박스로 보였다(H1도 같은 클래스를 써서
     함께 정정된다, 회귀 아님 — 오히려 그쪽도 원래 브랜드색이어야 했다). */
  accent-color: var(--color-primary);
}
.checklist-item.is-locked {
  background: var(--color-surface-muted);
  opacity: 0.5;
  color: var(--color-text-muted);
}
.checklist-item.is-unlocked {
  background: var(--color-surface-muted);
  color: var(--color-text-primary);
}
.checklist-item.is-checked {
  background: var(--color-primary-surface);
  color: var(--color-text-primary);
}

/* A2 동의 체크박스 행 — §5.2 `.checklist-item`의 배경 토큰만 재사용한
   단순 변형(순차 잠금 없음, WEB-SCREEN-raid-mvp.md §4.16, TICKET-162). */
.consent-list {
  margin-bottom: var(--space-6);
}
.consent-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--min-touch-target);
  background: var(--color-surface-muted);
  border-radius: var(--radius-input);
  padding: 0 var(--space-4);
  margin-bottom: var(--space-2);
  font: var(--text-body);
}
.consent-row input[type='checkbox'] {
  width: 20px;
  height: 20px;
  accent-color: var(--color-primary);
}
.consent-row a {
  color: var(--color-primary);
}

/* H1 "패스 세이브 적용" 체크 — 라벨+체크박스 조합만 여기서 재사용한다.
   행 배경·배치는 TICKET-182부터 `.pact-box__row`(아래)가 담당한다(옛
   `.consent-row--split`는 그 역할을 `.pact-box__row`에 넘기고 삭제). */
.consent-row__check {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  cursor: pointer;
}

/* H1 "패스 세이브 적용" 한 덩어리 박스(`.pact-box`, 검토 v2 7항, TICKET-182)
   — 체크 행과 최소 출발 인원 입력을 같은 `--color-surface-muted` 패널
   안에 이어붙인다(옛 amber `.info-box--promise`는 여기서 더 쓰지 않는다,
   P1/P5 재노출 전용으로만 남긴다). 배경·모서리는 이 박스 하나가 갖고
   내부 행은 배경 없이 패딩만 나눈다 — 시각적으로 분리된 두 박스가 아니라
   한 덩어리로 보이게 하기 위해서다(경계선도 두지 않는다). */
.pact-box {
  background: var(--color-surface-muted);
  border-radius: var(--radius-input);
  padding: var(--space-4);
}
.pact-box__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: var(--min-touch-target);
}
.pact-box__min-departure {
  margin-top: var(--space-3);
}

/* ── 5.6 배지 .badge (준비중 변형, H1 거다이맥스 — TICKET-163) ────── */
.badge {
  display: inline-block;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  font: var(--text-micro);
}
.badge--pending {
  background: var(--color-pending-bg);
  color: var(--color-pending-text);
}
/* 준비 완료 배지(§5.6 "준비 상태 배지" 표, P4 좌석 타일 전용, TICKET-197). */
.badge--ready {
  background: var(--color-ready-bg);
  color: var(--color-ready-text);
}

/* 상태별 배지 변형(§5.6 표, TICKET-185에서 처음 실사용 — 값은 :root
   `--color-badge-*` 세 쌍을 그대로 옮긴다, `.badge--pending`과 같은 명명). */
.badge--recruiting {
  background: var(--color-badge-recruiting-bg);
  color: var(--color-badge-recruiting-text);
}
.badge--confirmed {
  background: var(--color-badge-confirmed-bg);
  color: var(--color-badge-confirmed-text);
}
.badge--inprogress {
  background: var(--color-badge-inprogress-bg);
  color: var(--color-badge-inprogress-text);
}
/* "레이드 완료" 배지(R2, TICKET-208) — 전용 토큰을 새로 만들지 않고
   `--color-badge-confirmed-*`를 재사용한다(완료도 "정상 종료" 계열
   색상이면 충분, 새 디자인 토큰 추가는 이 티켓 범위 밖). */
.badge--ended {
  background: var(--color-badge-confirmed-bg);
  color: var(--color-badge-confirmed-text);
}

/* R1 결과 선택 리스트(§4.11 "옵션 탭=제출", TICKET-208) — 세로로 쌓인
   `.btn btn-outline` 목록. 라디오형(`.reason-radio-item`)과 달리 탭 즉시
   제출이라 입력 요소가 없다, 새 컴포넌트 클래스를 만들지 않고 버튼
   간격만 준다. */
.sheet-result-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
/* "못 들어갔다면" 그룹 캡션(§4.11 "아래쪽에 작게", TICKET-214) — 새
   색상·타이포 토큰을 만들지 않고 기존 캡션 토큰만 재사용한다. */
.sheet-result-list__caption {
  margin: var(--space-2) 0 0;
  font: var(--text-caption);
  color: var(--color-text-3);
}
/* "못 들어갔다면" 3옵션 — 위 "이겼어요!"/"아쉽게 졌어요"보다 낮은
   시각적 무게(§4.11 "아래쪽에 작게"). `.btn`의 100% 너비·큰 높이는
   그대로 두고 높이만 줄인다(터치 타겟은 --size-button-sm이 이미 다른
   화면에서 쓰는 최소값, line ~914 참고). */
.btn-outline--compact {
  height: var(--size-button-sm);
  font: var(--text-caption);
}
/* 결과 선택 버튼 색(TICKET-257, 디자인 정본 screens/H5.html·R1.html
   `.eq`/`.rchip` 그대로 이식 — tokens.css 주석 "--color-surface-2:
   구분선·비활성 버튼·스테퍼 버튼·결과 버튼"이 이 용도로 이미 예약해 둔
   토큰이다). 기존 `.btn-outline`(강조 파랑 테두리)과 달리 승/패·못
   들어감 버튼은 전부 같은 무게의 중립색이다 — 강조가 필요 없는 "결과
   선택"이라 액션 색을 쓰지 않는다. */
.result-grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2);
}
.btn-result {
  background: var(--color-surface-2);
  border: 1px solid var(--color-line);
  color: var(--color-text);
}
.btn-result--compact {
  height: var(--size-chip);
  background: var(--color-bg);
  border: 1px solid var(--color-line);
  color: var(--color-text-2);
  font: var(--text-meta);
  font-weight: 700;
  line-height: 1.3;
}

/* ── 5.7 세그먼트 컨트롤 .segmented (H1, TICKET-163) ─────────────── */
.segmented {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-1);
}
.segmented__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  height: var(--size-button-md);
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  font: var(--text-body);
  font-weight: 500;
  cursor: pointer;
}
.segmented__btn.is-selected {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-on-primary); /* TICKET-212 — 흰 글자 대비 문제, .btn-primary와 동일 */
  font-weight: 700;
}
/* 거다이맥스(AC-5) — §5.1 disabled 버튼 스타일 재사용 */
.segmented__btn.is-disabled {
  background: var(--color-disabled-bg);
  border-color: var(--color-disabled-bg);
  color: var(--color-disabled-text);
  cursor: not-allowed;
}

/* ── 5.8 정보 박스 .info-box (base=A2/TICKET-162, --promise 변형=H1/TICKET-163) ── */
.info-box {
  padding: var(--space-4);
  border-radius: var(--radius-input);
  background: var(--color-surface-muted);
  color: var(--color-text-secondary);
  font: var(--text-body);
}
.info-box.warn {
  background: var(--color-warn-bg);
  color: var(--color-warn-text);
  border: 1px solid var(--color-warn-border);
  margin-bottom: var(--space-4);
}
.info-box--promise {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  background: var(--color-promise-bg);
  color: var(--color-promise-text);
  border: 1px solid var(--color-promise-border);
}
.info-box__text {
  margin: 0;
  font: var(--text-caption);
  line-height: 1.5;
}

/* ── 5.9 입력 필드 .field (공용 — A2·H1 둘 다 쓴다) ─────────────── */
.field {
  display: block;
  width: 100%;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-input);
  /* TICKET-255 — doc/design/current/screens/A2.html·A3.html·H1.html의
     텍스트 입력은 전부 52px다(tokens.css에는 입력 전용 크기 토큰이 없어
     실측값을 직접 쓴다, 옛 48px는 a2-v1 값). */
  min-height: 52px;
  padding: 0 var(--space-4);
  font: var(--text-body);
  /* TICKET-232, PRD-012/AC-62 — `--text-body`가 14px라 iOS Safari가 포커스
     시 자동으로 확대한다(16px 미만 입력 글자 크기의 표준 동작). `font:`
     단축 속성 다음에 오는 개별 속성이 이겨 크기만 16px로 올리고
     글꼴·줄높이는 --text-body 값을 그대로 유지한다. */
  font-size: 16px;
  color: var(--color-text-primary);
}
.field:focus {
  border-color: var(--color-primary);
  outline: none;
}
.field[aria-invalid='true'] {
  border-color: var(--color-warn-border);
}
.field:disabled {
  color: var(--color-text-muted);
}

/* A2 전용 폼 레이아웃(margin 기반, TICKET-162) — H1의 `.field-stack`(flex,
   아래)과 이름이 비슷하지만 다른 컴포넌트다, 위 파일 머리말 참고. */
.field-group {
  margin-bottom: var(--space-5);
}
.field-group label {
  display: block;
  font: var(--text-body-lg);
  margin-bottom: var(--space-2);
}
.field-caption {
  font: var(--text-caption);
  color: var(--color-text-muted);
  margin: var(--space-2) 0 0;
}

/* ── 5.10 고지 푸터 .disclaimer-footer (공용) ────────────────────── */
.disclaimer-footer {
  font: var(--text-micro);
  color: var(--color-text-muted);
  text-align: center;
  padding: var(--space-4) var(--space-4) var(--space-6);
}
.disclaimer-footer p {
  margin: 0;
}

/* ── H1 전용 폼 레이아웃(flex column, TICKET-163) — §5 표에 없는 화면
   배치 유틸. A2의 `.field-group`(margin 기반, 위)과는 다른 컴포넌트라
   이름을 `.field-stack`으로 나눴다(develop 7756a94 리베이스 충돌 해소,
   TICKET-163 재작업). ── */
.page-title {
  margin: 0;
  font: var(--text-display);
}
.field-stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.field-label {
  font: var(--text-body);
  font-weight: 500;
  color: var(--color-text-primary);
}
.field-hint {
  font: var(--text-caption);
  color: var(--color-text-muted);
}

/* ── 스테퍼 .stepper (WEB-DESIGN-SYSTEM.md §5가 이름 붙이지 않은 컴포넌트 —
   목업 mockup_src/Main.dc.html 인원·최소 출발 인원 컨트롤의 값을 기존
   토큰으로 옮겼다, TICKET-163) ── */
.stepper {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}
.stepper__btn {
  width: 52px;
  height: 52px;
  border-radius: var(--radius-input);
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface);
  font-size: 24px;
  line-height: 1;
  color: var(--color-text-primary);
  cursor: pointer;
}
.stepper__btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}
.stepper__value {
  min-width: 56px;
  text-align: center;
  font-size: 28px;
  font-weight: 700;
  font-family: var(--font-number); /* TICKET-212 — 숫자 전용 글꼴(WEB-DESIGN-SYSTEM.md §3) */
}
/* 인원 스테퍼 라벨 열 — 라벨과 "최대 N명" 캡션(`.field-hint` 재사용)을
   세로로 쌓아 왼쪽에 두고 스테퍼를 오른쪽으로 미는 한 줄 레이아웃
   (WEB-SCREEN-raid-mvp.md §4.1 3번, TICKET-180). 최소 출발 인원(아래
   `.stepper--compact`)의 인라인 라벨과는 배치가 달라 별도 클래스로 뒀다. */
.stepper__label-col {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex-grow: 1;
}
.stepper__label {
  font: var(--text-body-lg);
  font-weight: 500;
  color: var(--color-text-primary);
}
.stepper__label-sub {
  font-weight: 400;
  color: var(--color-text-muted);
}
/* 최소 출발 인원 — H1 `.pact-box__min-departure`(위) 안에 얹히는 소형
   변형. TICKET-182부터 이 패널이 amber(`--color-promise-*`)가 아니라
   muted 패널 위에 놓이므로 색을 중립 텍스트/테두리 토큰으로 바꿨다(옛
   promise 색은 P1/P5 강조 박스 전용으로 남긴다). */
.stepper--compact {
  gap: var(--space-3);
}
.stepper--compact .stepper__label {
  flex-grow: 1;
  font: var(--text-body);
  font-weight: 700;
  color: var(--color-text-primary);
}
.stepper--compact .stepper__label-sub {
  font: var(--text-caption);
  font-weight: 400;
}
.stepper__btn--sm {
  width: 40px;
  height: 40px;
  font-size: 20px;
  color: var(--color-text-primary);
  border-color: var(--color-border-strong);
}
.stepper__value--sm {
  min-width: 32px;
  font-size: 20px;
  color: var(--color-text-primary);
  font-family: var(--font-number); /* TICKET-212 — 숫자 전용 글꼴 */
}

/* ── 토글 행 .toggle-row (WEB-DESIGN-SYSTEM.md §5가 이름 붙이지 않은
   컴포넌트 — .field와 같은 표면·테두리 토큰을 재사용, TICKET-163). H1의
   패스 세이브 체크는 TICKET-180·182를 거쳐 `.pact-box__row`(위)로 옮겼고,
   이 클래스는 H1-1 시트의 "수정" 행에 남아 있다(TICKET-182 — "인원이 다
   차면 알림 받기" 토글은 H2로 옮겨가며 이 화면에서 빠졌다). ── */
.toggle-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 48px;
  padding: 0 var(--space-3);
  border-radius: var(--radius-input);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  font: var(--text-body-lg);
  cursor: pointer;
}
.toggle-row input[type='checkbox'] {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
}

/* ── 5.12 도움말 말풍선 .tooltip-popover (WEB-DESIGN-SYSTEM.md §5.12,
   TICKET-180) — H1의 "패스 세이브 적용" (!) 버튼 전용. 버튼은 시각 24px
   원형 아이콘(테두리+아이콘)에 44px 히트 영역을 패딩으로 확보하고,
   말풍선은 버튼 아래·오른쪽 정렬로 뜬다(raid_new.js가 hidden 토글). ── */
.tooltip-anchor {
  position: relative;
  flex-shrink: 0;
}
.tooltip-trigger {
  width: var(--min-touch-target);
  height: var(--min-touch-target);
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
}
.tooltip-trigger span {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 1px solid var(--color-text-muted);
  color: var(--color-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  font: var(--text-caption);
  font-weight: 700;
}
.tooltip-popover {
  position: absolute;
  right: 0;
  top: calc(100% + var(--space-2));
  z-index: 20;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  padding: var(--space-4);
  font: var(--text-body);
  color: var(--color-text-primary);
  /* 부수 수정(TICKET-180 QA 관찰, doc/reports/TICKET-180/0245-qa.md) —
     `.tooltip-anchor`가 44px 히트 영역 버튼 하나뿐이라 containing block
     폭도 44px다. `width`가 `auto`인 채 `right:0`만 주면 shrink-to-fit
     계산이 이 44px 폭을 기준 삼아 실제 렌더 폭이 45~62px까지 줄어들어
     글자가 세로로 쪼개졌다. `width: max-content`로 콘텐츠 기준 폭을 먼저
     구하고 `max-width`로만 상한을 걸어 이 문제를 없앤다. */
  width: max-content;
  max-width: min(280px, calc(100vw - var(--space-4) * 2));
}
.tooltip-popover strong {
  color: var(--color-promise-text);
}

/* ── 5.5 바텀시트 .bottom-sheet (공용 매크로, WEB-DESIGN-SYSTEM.md §5.5,
   TICKET-168) — 구조·닫힘 동작만 담당하고 시각은 다듬지 않는다(사용자 지시
   2026-09-26 "구조·동작 먼저, 모양은 나중"). 화면은 macros/bottom_sheet.html
   두 매크로로만 이 마크업을 낸다. ── */
.bottom-sheet-scrim {
  position: fixed;
  inset: 0;
  background: var(--color-scrim);
  display: flex;
  align-items: flex-end;
  z-index: 100;
}
.bottom-sheet {
  position: relative;
  width: 100%;
  max-width: 480px;
  margin: 0 auto;
  background: var(--color-surface);
  border-radius: var(--radius-sheet-top);
  box-shadow: var(--shadow-sheet);
  /* TICKET-255 — doc/design/current/screens/H2-1.html 실측(12px 24px 16px)로
     고쳤다(옛 24px 20px는 핸들 바가 없던 시절 값 — 핸들이 위쪽 공간을
     대신 차지하므로 top 패딩을 줄인다). */
  padding: var(--space-3) var(--space-6) var(--space-4);
}
/* TICKET-255 — 일반형 시트 상단 핸들 바(S0 "일반 시트" 예시, 실측
   doc/design/current/screens/H2-1.html "정말 해산할까요?" 시트: 36×4,
   radius 2, `--color-line` 배경, 가운데 정렬). 강제형(forced_sheet)은
   DOM에 이 요소가 아예 없다(S0 "강제 시트: 핸들·닫기 없음") — 매크로가
   dismissible_sheet에만 렌더한다. */
.bottom-sheet__handle {
  display: block;
  width: 36px;
  height: 4px;
  border-radius: 2px;
  background: var(--color-border);
  margin: 0 auto var(--space-4); /* margin:auto가 가운데 정렬(부모가 flex가 아니라 align-self는 불필요) */
}
.bottom-sheet__close {
  /* 일반형 전용(§5.5) — 우상단 닫기 아이콘, 시각 24px + 패딩으로 44px
     히트영역(`--min-touch-target`). 강제형은 DOM에 이 버튼이 없다.
     색은 TICKET-255에서 --color-text-muted(#7F89A6/text-3)→
     --color-text-secondary(#A7B0C8/text-2)로 고쳤다 — doc/design/current/
     screens/H2-1.html 닫기 아이콘 stroke가 #A7B0C8이다. */
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  color: var(--color-text-secondary);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
}
.bottom-sheet__title {
  margin: 0 0 var(--space-4);
  font: var(--text-title);
  padding-right: var(--space-8); /* 닫기 아이콘과 겹치지 않게 */
}
.bottom-sheet__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* ── P3 강제 시트 전용 컴포넌트(§4.8 순서: 헤드라인+타이머 → 코드 카드 →
   안내 → 완료 버튼, TICKET-186) — WEB-DESIGN-SYSTEM.md에 번호가 없어
   기존 토큰만 재사용해 이름 붙였다(§0 관례, TICKET-163 선례와 동일). 구조·
   동작 먼저, 모양은 나중(§5.5 주석과 같은 사용자 지시). ── */
.sheet-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.sheet-title-sm {
  font: var(--text-body-lg);
  font-weight: 700;
  color: var(--color-text-secondary);
}
.timer {
  font: var(--text-title);
  font-family: var(--font-number); /* TICKET-212 — 타이머 숫자는 Chakra Petch */
  font-weight: 700; /* Chakra Petch는 600·700 두 굵기를 로드했으니(base.html)
    합성 굵게 문제가 없다 — --text-title이 위에서 400으로 낮아진 것과 별개로
    숫자는 원래 디자인대로 굵게 유지한다. */
  font-variant-numeric: tabular-nums;
  color: var(--color-promise-text);
  background: var(--color-promise-bg);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
}
/* AC-70(TICKET-237, 공통) — 청록 배경 강조 하단은 정확히 세 곳(P2 프렌드
   추가·주최자 초대 H2·참여자 초대 도착 R1)뿐이다. 최소 높이 200px, 배경은
   `--color-primary-surface`(코드 카드와 같은 톤 — 새 색을 만들지 않는다). */
.raid-emphasis-block {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-4);
  min-height: 200px;
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--color-primary-surface);
}
.code-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-8) var(--space-3);
  border-radius: var(--radius-lg);
  border: 1.5px solid var(--color-primary);
  background: var(--color-primary-surface);
  width: 100%;
  text-align: center;
  font-family: inherit;
  cursor: pointer;
}
.code-label {
  font: var(--text-body);
  color: var(--color-text-secondary);
}
.code-value {
  font: var(--text-display);
  font-family: var(--font-number); /* TICKET-212 — 트레이너 코드 숫자는 Chakra Petch */
  font-weight: 700; /* .timer와 같은 이유 — Chakra Petch 700은 합성 굵게가 아니다 */
  letter-spacing: 3px;
  color: var(--color-text-primary);
}
.code-hint {
  font: var(--text-caption);
  font-weight: 700;
  color: var(--color-primary);
}
.guide-line {
  font: var(--text-body);
  color: var(--color-text-secondary);
  text-align: center;
}

/* ── 5.11 진행 단계 표시기 .progress-steps (참여자 화면 전용, AC-48,
   TICKET-168) ── */
.progress-steps {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
}
.progress-steps__step {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  text-align: center;
  position: relative;
}
.progress-steps__step:not(:last-child)::after {
  /* 연결선 — 다음 원 중앙까지 이어지는 가로선 */
  content: '';
  position: absolute;
  top: 12px;
  left: 50%;
  width: 100%;
  height: 2px;
  background: var(--color-border-strong);
  z-index: 0;
}
.progress-steps__step.is-complete:not(:last-child)::after {
  background: var(--color-primary);
}
.progress-steps__circle {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font: var(--text-micro);
  font-weight: 700;
  color: var(--color-text-muted);
  background: var(--color-surface);
  border: 2px solid var(--color-border-strong);
  position: relative;
  z-index: 1;
}
.progress-steps__step.is-complete .progress-steps__circle {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-on-primary); /* TICKET-212 — 흰 글자 대비 문제, .btn-primary와 동일 */
}
.progress-steps__step.is-current .progress-steps__circle {
  border-color: var(--color-promise-border);
  color: var(--color-promise-border);
  font-weight: 700;
}
.progress-steps__label {
  font: var(--text-micro);
  color: var(--color-text-muted);
}
.progress-steps__step.is-current .progress-steps__label {
  color: var(--color-text-primary);
  font-weight: 700;
}

/* ── 한 줄 칸 .single-line-slot (§WEB-SCREEN-raid-mvp.md §2.2 항목 2,
   TICKET-168) — 높이를 고정해 P1(문구)·P2 이후(진행 표시기)가 서로 바뀌어도
   그 아래 요소가 움직이지 않게 한다. ── */
.single-line-slot {
  min-height: var(--min-touch-target);
  display: flex;
  align-items: center;
  font: var(--text-body);
  color: var(--color-text-secondary);
}

/* ── 참여자 공통 헤더 .participant-header (§WEB-SCREEN-raid-mvp.md §2.2 항목 1,
   TICKET-168) — 레이드명 + 주최자 정보 줄만(배지·인원수는 좌석 그리드
   제목에서 낸다, 중복 방지). ── */
.participant-header {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.participant-header__raid-name {
  margin: 0;
  font: var(--text-title);
}
.participant-header__host {
  margin: 0;
  font: var(--text-caption);
  color: var(--color-text-muted);
}

/* ── 팀 색 점 .team-dot (WEB-DESIGN-SYSTEM.md §1·§5.4, PRD-012/AC-57,
   TICKET-220) — 트레이너 이름 앞에 붙는 점. 상태(준비 완료 등)와 무관하게
   팀 색만 나타낸다. 크기 10px(리스트 행·헤더 기본)/8px(압축 좌석 그리드,
   §5.4 "팀 점 10(리스트)/8(압축 변형 쓸 때)"). ── */
.team-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
  vertical-align: middle;
  margin-right: 4px;
}
.team-dot--blue { background: var(--color-team-blue); }
.team-dot--red { background: var(--color-team-red); }
.team-dot--yellow { background: var(--color-team-yellow); }
.team-dot--none { background: var(--color-team-none); }
/* 빈 자리 점선 원 자리표시자(TICKET-257, macros/seat_grid.html
   `show_empty_dot`) — 팀이 없는 빈 자리에서 다른 행과 이름 시작 위치를
   맞춘다(디자인 `screens/H2.html` 빈 자리 `.dot{border:1.5px dashed}`).
   `--color-border-dashed`는 이미 `--color-seat-empty`(#4A5578)의 별칭. */
.team-dot--empty {
  background: none;
  border: 1.5px dashed var(--color-border-dashed);
  box-sizing: border-box;
}
.seat-tile--compact .team-dot {
  width: 8px;
  height: 8px;
  margin-right: 2px;
}

/* ── 좌석/멤버 그리드 .seat-grid / .seat-tile (§WEB-DESIGN-SYSTEM.md §5.3,
   §WEB-SCREEN-raid-mvp.md §2.2 항목 3, TICKET-168) ── */
.seat-grid-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.seat-grid__title {
  margin: 0;
  font: var(--text-body-lg);
}
.seat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
  gap: var(--space-3);
}
.seat-tile {
  position: relative;
  min-width: 64px;
  min-height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-2);
  border-radius: var(--radius-input);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  overflow: hidden;
  /* AC-60(TICKET-253) 강조 해제가 부드럽게 보이도록 — 아래 .is-new-join. */
  transition: background-color 0.6s ease, border-color 0.6s ease;
}
.seat-tile__name-row {
  /* 팀 점 + 이름을 한 줄로 묶는 래퍼(TICKET-220) — 부모(.seat-tile--compact)의
     flex-direction: column과 무관하게 점·이름이 항상 같은 행에 나란히
     보이도록 한다(상태 오버레이 `extra`는 이 래퍼 밖, 기존 위치 유지). */
  display: inline-flex;
  align-items: center;
  min-width: 0;
  max-width: 100%;
}
.seat-tile__label {
  font: var(--text-caption);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  min-width: 0;
}
.seat-tile.is-me {
  background: var(--color-primary-surface);
  border: 1.5px solid var(--color-primary);
}
.seat-tile.is-empty {
  background: var(--color-bg);
  border: 1px dashed var(--color-border-dashed);
  color: var(--color-text-muted);
}
.seat-tile.is-absent {
  background: var(--color-bg);
  border: 1px dashed var(--color-border-dashed);
  color: var(--color-text-muted);
}
.seat-tile.is-absent .seat-tile__label {
  color: var(--color-text-muted);
}
/* AC-60(TICKET-253) — H2에서 새로 합류한 참여자 행을 몇 초간 강조한다.
   디자인은 아직 확정 전(사용자가 정리 중)이라 기존 토큰(.is-me와 같은
   값)만 쓰는 최소 표현 — 클래스는 `raid_party_h2.js`가 붙이고 뗀다.
   최종 모양은 디자인 확정 후 다시 입힌다(헌장 §9). */
.seat-tile.is-new-join {
  background: var(--color-primary-surface);
  border: 1.5px solid var(--color-primary);
}

/* ── H3 리스트 레이아웃 .seat-grid--list / .seat-tile--split
   (WEB-DESIGN-SYSTEM.md §5.10 `.roster__check`, PRD-012/AC-29·AC-57,
   TICKET-220 QA 반려 재작업 `doc/reports/TICKET-220/20260926-0910-qa.md`)

   `.seat-tile__ready-badge`(우상단 절대위치 오버레이)는 "받음 표시"
   버튼처럼 타일 폭을 넘길 수 있는 콘텐츠를 얹으면 이름·팀 점을 완전히
   덮는다(coveredFraction: 1 실측) — 오버레이 대신 [팀 점+이름] … [오른쪽
   칸] 좌우 배치로 바꿔 구조적으로 겹치지 않게 한다.

   3~4열 그리드(§5.3/§5.16) 타일 폭(~90~180px)으로는 이름과 오른쪽 칸이
   동시에 들어갈 공간이 없다 — 처음엔 `.seat-tile--compact.seat-tile--split`
   (열→행 전환)로 시도했으나 실측 결과 `flex: 1 1 auto; min-width: 0`인
   이름이 오른쪽 칸(고정 폭 텍스트/버튼)에 밀려 폭 0으로 사라졌다(3열
   소파티에서도 재현). 그래서 `list_layout=True`는 그리드 대신 **항상
   1열 전체 폭 리스트**를 쓴다(H2가 순번·신청 시각 때문에 6명 이상도
   1열을 유지하는 것, §5.4 "예외"와 같은 이유의 연장) — `extra`를 쓰는
   다른 화면(P2·P4)은 영향받지 않는다. ── */
.seat-grid--list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.seat-tile--split {
  justify-content: space-between;
  gap: var(--space-3);
}
.seat-tile--split .seat-tile__name-row {
  flex: 1 1 auto;
  min-width: 0;
}
.seat-tile--split .seat-tile__label {
  text-align: left;
}
.seat-tile__right {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  /* 상태 글자("준비 중")+"받음 표시" 버튼처럼 오른쪽 칸에 두 요소를 나란히
     담는 화면(H3, TICKET-227)을 위한 간격 — 요소가 하나뿐인 화면(P4 등
     `right`를 안 쓰는 화면)은 자식이 하나라 gap이 렌더에 영향을 주지 않는다. */
  gap: var(--space-2);
}

/* ── 6명 이상 2열 목록 .seat-grid--two-col (AC-64 v3 정정, TICKET-237,
   `macros/seat_grid.html` two_column 인자 전용) — H2·P3가 6명 이상일 때
   주최자(pin_full) 한 행만 전체 폭으로 남기고 나머지를 2열로 접는다
   (A2-HostRecruit11/A2-Waiting11 참고). 그리드 트랙 안에서도 이름이
   말줄임되도록 타일 자체에 `min-width: 0`을 준다(그리드 아이템 기본값
   `min-width: auto`는 내용 폭만큼 트랙을 밀어 넘쳐서 ellipsis가 무효화된다). */
.seat-grid--two-col {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--space-3);
  row-gap: var(--space-2);
  margin-top: var(--space-2);
}
.seat-grid--two-col .seat-tile--split {
  min-width: 0;
  min-height: 44px;
  gap: var(--space-2);
}
.seat-grid--two-col .seat-tile__right {
  font-size: 12px;
}

/* ── P4 좌석 타일 오버레이 — 준비 배지·코드 복사 아이콘
   (§WEB-SCREEN-raid-mvp.md §4.9/§2.2 3번, PRD-012/AC-24b, TICKET-197) ── */
.seat-tile__ready-badge {
  position: absolute;
  top: 4px;
  right: 4px;
}
/* ── H3 좌석 타일 "받음 표시" 대신 체크 버튼 (계약 raid.md §2-14,
   PRD-012/AC-29, TICKET-211) — §5.10 "off(미확인)" 표: 작은 버튼
   (`--color-surface-2` 배경 + `--color-text`), 시각 크기(32px)와 무관하게
   44px 히트 영역 확보. 2026-09-26 QA 반려 재작업 때 이 자리를
   `.badge.badge--pending`(앰버, 상태색)에서 이 중립 버튼으로 완전히
   바꿨었는데(§5.10 "off는 상태색이 아니라 버튼"), 같은 날 실기기
   재현에서 "행에 상태 자체가 안 보인다"는 관찰이 다시 나와(PL 재지시,
   `doc/reports/SESSION-20260926/1400-user-staging-realdevice-test.md`
   원문 9번) `.badge--pending`("준비 중")을 **버튼 옆에 별도로 되살렸다**
   (TICKET-227) — 이번엔 "상태색 배지 하나로 클릭까지 겸함"이 아니라
   "상태 글자 + 대신-체크 버튼"을 나란히 두는 것이라 §5.10이 금지한
   모양(off 상태를 통째로 상태색 배지로 대체)과 다르다. #}
.btn-sm {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--size-button-sm);
  padding: 0 var(--space-3);
  border: none;
  border-radius: var(--radius-sm);
  background: var(--color-surface-muted);
  color: var(--color-text-primary);
  font: var(--text-micro);
  white-space: nowrap;
  cursor: pointer;
}
.btn-sm::after {
  /* §6 최소 터치 타겟 44px 확보 — `.copy-icon-btn`과 같은 원칙(32px 시각
     크기 유지, 히트 영역만 보이지 않게 넓힘). */
  content: '';
  position: absolute;
  inset: -6px;
}
.host-check-btn:disabled {
  cursor: default;
  opacity: 0.6;
}
.copy-icon-btn {
  position: absolute;
  bottom: 4px;
  right: 4px;
  width: var(--size-button-sm);
  height: var(--size-button-sm);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  border: 1px solid var(--color-primary);
  color: var(--color-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
}
.copy-icon-btn::after {
  /* §6 최소 터치 타겟 44px 확보 — 32px(--size-button-sm) 시각 크기는 좁은
     타일 안에 맞추고, 히트 영역만 보이지 않게 넓힌다(.bottom-sheet__close와
     같은 원칙, §5.5). */
  content: '';
  position: absolute;
  inset: -6px;
}
.copy-icon-btn--compact {
  bottom: 2px;
  right: 2px;
}

/* ── 5.16 압축 좌석 그리드 .seat-tile--compact (7~11명 대형 파티,
   WEB-DESIGN-SYSTEM.md §5.16, §2.6, TICKET-197에서 첫 실사용) ── */
.seat-grid--compact {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-2);
}
.seat-tile--compact {
  position: relative;
  height: 56px;
  border-radius: var(--radius-sm);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  font: var(--text-caption);
  overflow: hidden;
}
.seat-tile--compact.is-me {
  background: var(--color-primary-surface);
  border: 1.5px solid var(--color-primary);
}
.seat-tile--compact .name {
  max-width: 90%;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.seat-tile--compact.is-expanded {
  /* 이름 탭 확장(§5.16 "탭하면 전체 이름을 짧게 보여준다") — 말줄임을
     풀고 인접 타일 위로 살짝 겹쳐 보이게 한다(raid_party_p4.js). */
  overflow: visible;
  z-index: 2;
}
.seat-tile--compact.is-expanded .name {
  overflow: visible;
  white-space: normal;
  max-width: none;
  background: var(--color-surface);
  box-shadow: var(--shadow-card);
  padding: 2px 4px;
  border-radius: var(--radius-sm);
}
.seat-tile--compact .status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
}
.seat-tile--compact .status-dot.ready {
  background: var(--color-ready-bg);
}
.seat-tile--compact .status-dot.pending {
  background: var(--color-pending-bg);
}

/* P2 페이지 세로 간격 — 헤더·진행 표시·알림 줄·그리드가 순서대로
   쌓인다(§2.2 공통 틀). 하단 고정 상태 바(`.status-bar-pinned`, AC-53,
   TICKET-219)가 이 티켓으로 생겨 `.page-h2`와 같은 padding-bottom을
   잡는다(TICKET-204 시점 주석은 이 값이 없던 이유였다 — 이제 아래에서
   덮어쓴다). */
/* TICKET-232, PRD-012/AC-62 — 하드코딩 88px 대신 dock_height.js가 실측해
   넣는 `--dock-h`를 쓴다(독 문구가 줄바꿈되는 등 실제 높이가 88px를
   넘으면 마지막 행이 가려지는 게 원래 버그였다). `var(--dock-h, 72px)`의
   72px는 스크립트가 못 도는 경우를 위한 옛 값 그대로의 폴백
   (72 + --space-4(16) = 88, 기존과 동일). */
.page-p2 {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding-bottom: calc(var(--space-4) + var(--dock-h, 72px));
}

/* P3(기반 화면)도 같은 이유로 하단 여백을 둔다 — 실제로는 강제 시트가
   화면을 덮어 사용자에게 안 보이지만(§5.1 "P3(기반) — P2와 동일 기반"),
   시트가 닫히는 극히 짧은 순간에도 레이아웃이 튀지 않게 한다. */
.page-p3 {
  padding-bottom: calc(var(--space-4) + var(--dock-h, 72px));
}

/* P4 페이지 세로 간격 — 헤더·진행 표시·그리드·안내 카드가 순서대로
   쌓인다(§2.2 공통 틀). `.page-h2`와 같은 패턴(TICKET-197) + 하단 고정
   상태 바(AC-53, TICKET-219) 여백. */
.page-p4 {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding-bottom: calc(var(--space-4) + var(--dock-h, 72px));
}

/* ── 참여자용 하단 고정 상태 바 `.status-bar-pinned` (WEB-DESIGN-SYSTEM.md
   §5.1, PRD-012/AC-53, TICKET-219) — P2·P3(기반)·P4 공용. 버튼을 담지
   않는다(macros/bottom_dock.html 머리말 참고, 담는 화면은 `.host-bottom-
   fixed`를 쓴다). ── */
.status-bar-pinned {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  max-width: 480px;
  margin: 0 auto;
  box-sizing: border-box;
  background: var(--color-surface);
  border-radius: var(--radius-sheet-top);
  box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.35);
  /* 하단 패딩에 env(safe-area-inset-bottom) 추가(TICKET-232, PRD-012/AC-62)
     — 홈 인디케이터가 있는 기기에서 이 값만큼 아래로 더 띄워야 독 글자가
     인디케이터에 안 눌린다. base.html의 viewport-fit=cover 없이는 이 값이
     항상 0으로 계산돼 조용히 아무 효과가 없다(주석만으론 안 보이는 함정). */
  padding: var(--space-5) var(--space-6) calc(var(--space-6) + env(safe-area-inset-bottom));
  /* TICKET-219 재작업(AC-53 3번째 상태 "초대 대기 시한 초과") — 문장 아래
     [파티 나가기] 버튼이 붙는 P3/P4 한정 상태가 생겨, 자식이 여러 개일 때
     간격이 필요해졌다(DockSpec "문장→버튼 간격 20px", §5.1). 자식이
     하나뿐인 기존 상태(P2 등)는 gap이 적용될 대상이 없어 영향 없다. */
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  z-index: 10;
}
.status-bar-pinned__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}
.status-bar-pinned__line {
  font: var(--text-body-lg);
  font-weight: 800;
  margin: 0;
}
.status-bar-pinned__count {
  font-family: var(--font-number);
  font-weight: 700;
  font-size: 20px;
  color: var(--color-text-primary);
  flex-shrink: 0;
}
.status-bar-pinned__count-total {
  color: var(--color-text-muted);
}
/* 독 타이머 인라인 색(오른쪽 숫자가 시간이면 앰버, WEB-DESIGN-SYSTEM.md
   §5.1) — `.timer`(P3 코드 카드용 칩 배경)와 달리 문장 안에 인라인으로
   들어가 배경 없이 글자색만 바꾼다. `.status-bar-pinned`(P2/P3/P4)·
   `.host-bottom-fixed`(H3) 양쪽에서 공유하는 유틸리티 클래스라 두 접두사
   중 어느 쪽에도 속하지 않는 독립 이름을 썼다(raid_dock_timer.js가
   `[data-dock-timer]`로 찾아 세는 요소와 항상 짝을 이룬다). */
.dock-timer {
  font-family: var(--font-number);
  font-weight: 700;
  color: var(--color-promise-text);
  font-variant-numeric: tabular-nums;
}

/* ── 호스트 공통 헤더 .host-header (§WEB-SCREEN-raid-mvp.md §2.1, TICKET-185)
   — 참여자용 `.participant-header`와 달리 배지+인원 수 줄을 포함한다(호스트
   화면은 좌석 그리드 제목이 없어 인원 수를 낼 자리가 따로 없다). ── */
.host-header {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.host-header__meta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.host-header__count {
  font: var(--text-body-lg);
}
.host-header__title {
  margin: 0;
  font: var(--text-display);
}
.host-header__host {
  margin: 0;
  font: var(--text-caption);
  color: var(--color-text-muted);
}

/* ── H2 링크 카드·복사·알림 한 줄 (WEB-SCREEN-raid-mvp.md §4.3, TICKET-185,
   PRD-012/AC-52) — 모양은 미리보기(doc/design/preview/H2-notify-permission.html)
   구조를 이 리포 토큰으로 옮겼다. ── */
.link-card {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
}
.link-card__thumb {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  background: var(--color-primary-surface);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  flex-shrink: 0;
}
.link-card__text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  overflow: hidden;
}
.link-card__title {
  font: var(--text-body);
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.link-card__url {
  font: var(--text-caption);
  color: var(--color-text-muted);
  /* 탭 시 복사(2026-09-26 추가) — 커서만 바꾸고 밑줄 등 링크 스타일은
     주지 않는다(§4.3 원문 "링크 카드"는 이 텍스트를 앵커로 보지 않는다). */
  cursor: pointer;
}
/* 첫 진입 1회 안내 캡션 — `.field-hint`와 같은 텍스트 토큰이지만 가운데
   정렬이 달라 별도 클래스로 둔다. */
.link-first-visit-hint {
  font: var(--text-caption);
  color: var(--color-text-muted);
  text-align: center;
  margin: 0;
}
/* P1-1 신청 완료 시트 버튼 행(§4.6, TICKET-202) — `.btn`은 기본 `width:100%`
   블록이라(§5.1) 두 버튼을 나란히 두려면 컨테이너가 flex + 자식 폭 재정의를
   해줘야 한다. */
.apply-complete-actions {
  display: flex;
  gap: var(--space-3);
}
.apply-complete-actions .btn {
  width: auto;
  flex: 1;
}
.notify-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-input);
  background: var(--color-surface-muted);
  font: var(--text-body);
}
.notify-line--on {
  color: var(--color-primary);
  font-weight: 700;
}
.notify-line__ask-btn {
  height: var(--size-button-md);
  padding: 0 var(--space-4);
  border-radius: var(--radius-sm);
  border: none;
  background: var(--color-primary);
  color: var(--color-on-primary); /* TICKET-212 — 흰 글자 대비 문제, .btn-primary와 동일 */
  font: var(--text-body);
  font-weight: 700;
  cursor: pointer;
  flex-shrink: 0;
}
/* AC-68(TICKET-237) — [레이드 만들기]·[참여하기] 버튼 위/아래 알림 허용
   안내 한 줄. `.notify-line`(H2 인라인 줄, 클릭 배선 있던 옛 UI)과 달리
   버튼 자체가 클릭 지점이라 이 줄은 순수 텍스트다. */
.notify-inline-hint {
  font: var(--text-caption);
  color: var(--color-text-secondary);
  text-align: center;
}
.notify-inline-hint--sub {
  color: var(--color-warn-text);
}

/* ── 호스트 화면 하단 고정 영역 .host-bottom-fixed (WEB-SCREEN-raid-mvp.md
   §4.3 7번, TICKET-185) — 참여자용 `.status-bar-pinned`(§53, 별도 티켓)와
   달리 버튼을 담는다. `.page-h2`가 이 높이만큼 하단 패딩을 미리 잡아둬
   본문 마지막 요소가 가려지지 않게 한다. ── */
.host-bottom-fixed {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  max-width: 480px;
  margin: 0 auto;
  background: var(--color-bg);
  border-top: 1px solid var(--color-border);
  /* env(safe-area-inset-bottom) 추가 — `.status-bar-pinned`와 같은 이유
     (TICKET-232, PRD-012/AC-62). */
  padding: var(--space-3) var(--space-5) calc(var(--space-4) + env(safe-area-inset-bottom));
  z-index: 10;
}
/* 하단 독 상태 한 줄(H3은 AC-53/TICKET-219, H2는 AC-52 2026-09-26 확장/
   TICKET-226) — `.host-bottom-fixed` 자체(버튼 레이아웃)는 건드리지 않고
   이 줄만 얹는 화면에서 선택적으로 쓴다. */
.host-bottom-fixed__line {
  font: var(--text-body-lg);
  font-weight: 800;
  margin: 0 0 var(--space-3);
}
/* AC-70(TICKET-237 재작업) — H2가 all_ready 상태(다녀오기 전·후 모두)일
   때 하단 고정 독이 청록 강조로 바뀐다(디자인 A2-HostReady/
   A2-HostReadyActive, 위 838행 주석이 이미 "주최자 초대 H2"를 세 곳 중
   하나로 지정했던 것을 실제로 반영 — 1차분은 이 변형 클래스를 만들고도
   어느 화면에서도 붙이지 않아 qa 반려됐다). `.raid-emphasis-block`과
   배경 색은 같은 토큰을 쓰되(새 색을 만들지 않는다), 겹쳐 쓰지 않고
   별도 변형 클래스로 둔다(위 `.host-bottom-fixed` 주석 참고 — 두 클래스
   병기 시 선언 순서 때문에 레이아웃 규칙이 깨진다). */
.host-bottom-fixed--emphasis {
  background: var(--color-primary-surface);
  min-height: 200px;
  box-sizing: border-box;
}

/* A2/A3 CTA 독 변형 .host-bottom-fixed--sheet (TICKET-258,
   doc/design/current/screens/A2.html·A3.html) — 이 두 화면의 하단 CTA는
   H2/H3의 "줄+border-top"(기본 `.host-bottom-fixed`)이 아니라 S1 "①
   일반 하단" 패널(배경 --color-surface, 위 모서리만 둥글게, 그림자)이다.
   `dock_height.js`는 `.host-bottom-fixed` 선택자로만 실측하므로(TICKET-257
   소관, 이 티켓에서 건드리지 않는다) 새 클래스를 만들지 않고 이 이름을
   그대로 쓰면서 배경·테두리·패딩만 덮어쓴다. 패딩은 tokens.css
   `--dock-pad-top`/`--page-gutter`/`--dock-pad-bottom`(디자인 "14px 24px
   12px"과 정확히 일치)로 기본값의 --space-3/--space-5/--space-4를
   대체한다. */
.host-bottom-fixed--sheet {
  background: var(--color-surface);
  border-top: none;
  border-radius: var(--radius-sheet-top);
  box-shadow: var(--shadow-dock);
  padding: var(--dock-pad-top) var(--page-gutter) calc(var(--dock-pad-bottom) + env(safe-area-inset-bottom));
}
.page-h2 {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  /* TICKET-226 — 독에 상태 한 줄(`.host-bottom-fixed__line`)이 추가돼
     높이가 늘어난 만큼(88px → 128px) 올린다(`.page-h3` §4.17 선례와 같은
     원칙: 독 안 요소가 늘면 이 값을 함께 올린다). TICKET-232 — 하드코딩
     대신 `--dock-h` 실측값을 쓴다(폴백 112px = 옛 128px와 동일,
     `.page-p2` 주석 참고). */
  padding-bottom: calc(var(--space-4) + var(--dock-h, 112px));
}

/* ── H2 신청자 목록 .applicant-list (WEB-SCREEN-raid-mvp.md §4.3 6·10번,
   PRD-012/AC-52, TICKET-226) — `.roster`(§5.4)와 달리 항상 1열이고 순번·
   신청 시각을 보여준다(§5.4 "예외 — H2는 1열을 유지"). ── */
.applicant-list__title {
  margin: 0;
  font: var(--text-body);
  font-weight: 700;
}
/* AC-71(목록 표시 규칙, TICKET-237 재작업) — 목록 이름("파티원"/"파트너")과
   오른쪽 "준비 N/M"을 한 줄에 배치한다(디자인 A2-HostRecruitNew/
   A2-Waiting11의 `.lh` 행과 같은 모양, `--color-text-secondary`가 디자인
   #A7B0C8와 같은 토큰). `seat_grid.html`의 `show_title=False`와 짝 —
   H2·P3 둘 다 이 헤더를 매크로 밖에서 직접 그린다(1차분은 이 헤더 없이
   매크로 내부 고정 제목과 중복 렌더돼 qa 반려됐다). */
.applicant-list__header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}
.applicant-list__ready-count {
  margin: 0;
  font: var(--text-caption);
  color: var(--color-text-secondary);
}
.applicant-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.applicant-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
}
.applicant-row--me {
  background: var(--color-surface);
  font-weight: 700;
}
.applicant-row--empty {
  color: var(--color-text-muted);
}
.applicant-row__index {
  flex-shrink: 0;
  width: 20px;
  text-align: right;
  color: var(--color-text-muted);
  font: var(--text-caption);
  font-variant-numeric: tabular-nums;
}
.applicant-row__name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: var(--text-body);
}
.applicant-row__meta {
  flex-shrink: 0;
  font: var(--text-caption);
  color: var(--color-text-muted);
}
/* 대형 파티(7명 이상, §4.3 10번) — 행을 더 좁게, 부가 설명 문구 없이
   순번·이름·신청 시각만. */
.applicant-list--compact .applicant-row {
  padding: 4px var(--space-3);
  gap: var(--space-2);
}
.applicant-list--compact .applicant-row__name {
  font: var(--text-caption);
}
/* 팀 점 — 압축 변형은 8px(§5.4 "팀 점 10(리스트)/8(압축 변형 쓸 때)").
   `.seat-tile--compact .team-dot`와 같은 값이지만 선택자가 다른 컴포넌트라
   별도로 정의한다(`.applicant-list`는 `.seats`/`.roster` 트리 밖). */
.applicant-list--compact .team-dot {
  width: 8px;
  height: 8px;
  margin-right: 2px;
}

/* ── H3 상단 요약 카드(AC-13b 원문, TICKET-196) — 하단 고정 배치가 아니라
   `.info-box` 위에 상태 한 줄·진행 바를 얹는다(당시엔 "범위 밖"이던 하단
   고정 상태 한 줄과 구분해 둔 것 — AC-53/TICKET-219이 그 하단 고정 독을
   추가하면서 `.page-h3`도 `.page-h2`처럼 고정 영역용 패딩이 필요해졌다,
   아래 padding-bottom). 이 상단 카드 자체는 그대로 문서 흐름 안에 남는다
   — 위·아래 두 곳에 같은 값이 보이는 것은 AC-53 원문이 요구하는 중복이다
   ("H3에서는 '프렌드 신청 N/M · 남은 시간'…", PRD-012 435행). ── */
.page-h3 {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  /* TICKET-221 — 하단 고정 독에 "파티 해산" 링크(`.host-dissolve-link`)가
     추가돼 독 높이가 늘어난 만큼(150px → 190px) 본문 마지막 요소가 가려지지
     않게 올린다(`.page-h2` 88px과 같은 원칙). TICKET-232 — 하드코딩 대신
     `--dock-h` 실측값을 쓴다(폴백 174px = 옛 190px와 동일). */
  padding-bottom: calc(var(--space-4) + var(--dock-h, 174px));
}
.status-line {
  font: var(--text-body-lg);
  font-weight: 700;
  text-align: center;
  margin: 0;
}
.progress-bar {
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--color-border);
  overflow: hidden;
}
.progress-bar__fill {
  height: 100%;
  background: var(--color-primary);
  border-radius: var(--radius-pill);
  transition: width 1s linear;
}

/* "파티 해산" 작은 텍스트 버튼(WEB-SCREEN-raid-mvp.md §4.3 7번·§4.4 3번,
   TICKET-195) — 되돌릴 수 없는 동작이라 danger 톤 텍스트로 미리 구분해
   둔다. 새 버튼 컴포넌트를 만들지 않고 기존 토큰만 조합한다. */
.host-dissolve-link {
  display: block;
  width: 100%;
  margin-top: var(--space-2);
  padding: var(--space-2) 0;
  background: none;
  border: none;
  font: var(--text-caption);
  color: var(--color-warn-text);
  text-decoration: underline;
  text-align: center;
  cursor: pointer;
}

/* A3 "탈퇴" 작은 텍스트 링크(§7.3 3번, TICKET-198) — `.host-dissolve-link`와
   속성이 같은 되돌릴 수 없는 동작이지만, 이름이 다른 화면(파티 해산)을
   가리켜 오해를 살 수 있어 별도 클래스로 둔다. */
.account-withdraw-link {
  display: block;
  width: 100%;
  margin-top: var(--space-2);
  padding: var(--space-2) 0;
  background: none;
  border: none;
  font: var(--text-caption);
  color: var(--color-warn-text);
  text-decoration: underline;
  text-align: center;
  cursor: pointer;
}

/* A3 페이지 레이아웃(§7.3, TICKET-198) — `.page-h2`와 같은 세로 stack.
   TICKET-258 — "저장" 버튼이 하단 고정 독(`.host-bottom-fixed--sheet`)으로
   옮겨져 이제 하단 여백이 필요하다(로그아웃·탈퇴 영역이 독에 가리지
   않도록, `.page-p2` 등과 같은 원리). 폴백 78px = 독 패딩(14+12) + 버튼
   52px(TICKET-255 `--size-btn`). */
.page-a3 {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding-bottom: calc(var(--space-4) + var(--dock-h, 78px));
}

/* A2 온보딩 페이지 레이아웃(TICKET-258, doc/design/current/screens/A2.html)
   — "시작하기" 버튼을 하단 고정 독으로 옮기며 신설. `.page-a3`와 같은
   폴백 계산(78px). */
.onboarding-page {
  display: flex;
  flex-direction: column;
  padding-bottom: calc(var(--space-4) + var(--dock-h, 78px));
}

/* 해산 사유 라디오 목록(§4.17, TICKET-195) — `.consent-row`(§A2)와 같은
   배경 토큰을 재사용한 라디오 변형(체크박스 대신 radio, 단일 선택). */
.reason-radio-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--min-touch-target);
  background: var(--color-surface-muted);
  border-radius: var(--radius-input);
  padding: 0 var(--space-4);
  margin-bottom: var(--space-2);
  font: var(--text-body);
}
.reason-radio-item input[type='radio'] {
  width: 20px;
  height: 20px;
  accent-color: var(--color-primary);
  flex-shrink: 0;
}

/* ── 5.14 인앱 브라우저 안내 배너 .inapp-banner (TICKET-177/AC-27,
   TICKET-179/AC-28) ────────────────────────────────────────────────
   경고성이지만 행동을 막는 게 아니라 안내라서 .info-box warn(빨강)이
   아닌 중립색을 쓴다(WEB-DESIGN-SYSTEM.md §5.14). */
.inapp-banner {
  background: var(--color-surface-muted);
  border-bottom: 1px solid var(--color-border);
  padding: var(--space-4);
  font: var(--text-body);
  color: var(--color-text-primary);
  text-align: center;
}
.inapp-banner .caption {
  font: var(--text-caption);
  color: var(--color-text-muted);
}
/* TICKET-179(AC-28): 시도 가능한 스킴이 없는 조합(당근+iOS)에서 "브라우저로
   열기" 버튼을 눌렀을 때 캡션(더보기 안내)을 강조해 다음 행동을 알려준다 —
   새 컴포넌트가 아니라 기존 캡션에 얹는 상태 변형. */
.inapp-banner .caption.inapp-banner__caption--emphasis {
  color: var(--color-text-primary);
  font-weight: 700;
}

/* ── SSE 재연결 안내 배너 .raid-sse-reconnect-banner (PRD-012/AC-63,
   TICKET-249) ── `raid_sse.js`가 htmx-sse의 sseError/sseOpen 이벤트만으로
   표시/숨김을 가르는 한 줄. 바텀시트 스크림(z-index 100, §5.5)보다도 위에
   둔다 — 강제 시트가 떠 있는 화면(P2 코드 카드 등)에서도 "지금 실시간
   연결이 끊겼다"는 사실은 가려지면 안 된다. */
.raid-sse-reconnect-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 200;
  padding: var(--space-2) var(--space-4);
  padding-top: calc(var(--space-2) + env(safe-area-inset-top));
  text-align: center;
  font: var(--text-caption);
  color: var(--color-text-secondary);
  background: var(--color-surface-muted);
  border-bottom: 1px solid var(--color-border);
}

/* ── 아이폰 홈 화면 추가 안내 토스트 .ios-home-hint-toast (PRD-012/AC-73,
   TICKET-259) ── `ios_home_hint.js`가 동적으로 만들어 붙이고 일정 시간 뒤
   스스로 뗀다(디자인 정본에 토스트 컴포넌트가 따로 없어 위 `.raid-sse-
   reconnect-banner`와 같은 상단 배너 자리·톤을 재사용 — "스펙과 디자인이
   다른 곳" 참고). `z-index`는 재연결 배너(200)보다 한 단 낮게 둬 "지금
   연결이 끊겼다"는 사실이 항상 이 안내보다 우선 보이게 한다. */
.ios-home-hint-toast {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 190;
  padding: var(--space-2) var(--space-4);
  padding-top: calc(var(--space-2) + env(safe-area-inset-top));
  text-align: center;
  font: var(--text-caption);
  color: var(--color-primary);
  background: var(--color-primary-surface);
  border-bottom: 1px solid var(--color-primary-border);
}

/* ── 팀 선택 .team-pick (A2·A3 전용, WEB-DESIGN-SYSTEM.md §5.9,
   PRD-012/AC-56, TICKET-215) ─────────────────────────────────────────
   3분할 세그먼트(블루/레드/옐로) + 각 칸 팀 점. 선택 사항이라 "선택 안
   함"이 유효 상태다 — 셋 중 하나에도 `.team-pick__option--selected`가
   없는 것이 정상.
   정본(WEB-DESIGN-SYSTEM.md §5.9)은 `--color-surface-2`/`--color-action`을
   말하지만, TICKET-212가 다크 리스킨을 반영하면서 그 두 토큰을 별도
   변수로 만들지 않고 기존 이름(`--color-surface-muted`/`--color-primary`)
   값만 다크 색으로 교체하는 쪽을 택했다(파일 머리말 TICKET-212 절 참고,
   `tokens.css --color-action` 주석이 `--color-primary` 선언 옆에 있다) —
   그래서 이 컴포넌트는 처음 작성 시점의 "임시 대체"가 아니라 이미 정본과
   같은 값을 가리키고 있다(리베이스 후 확인, 값 변경 없음). */
.team-pick {
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}
.team-pick__option {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: 0 var(--space-3);
  border-radius: var(--radius-input);
  background: var(--color-surface-muted);
  border: 2px solid transparent;
  font: var(--text-body);
  color: var(--color-text-primary);
  cursor: pointer;
}
.team-pick__option--selected {
  border-color: var(--color-primary);
}
.team-pick__dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}
.team-pick__dot--blue { background: var(--color-team-blue); }
.team-pick__dot--red { background: var(--color-team-red); }
.team-pick__dot--yellow { background: var(--color-team-yellow); }
.team-pick__caption {
  font: var(--text-caption);
  color: var(--color-text-muted);
  margin: 0 0 var(--space-2);
}
.team-pick__clear {
  display: inline-block;
  font: var(--text-caption);
  color: var(--color-text-secondary);
  background: none;
  border: none;
  padding: 0;
  margin: 0 0 var(--space-5);
  cursor: pointer;
  text-decoration: underline;
}

/* ── 브랜드 로고 .brand-logo (TICKET-239, PRD-012/AC-72 — 로고 50% 투명) ──
   원래 A1/A2/A3/랜딩/약관 5개 화면군 전용이라고 적었으나(레이드 화면은
   TICKET-237 소관이라고 미뤄 둔 상태), 2026-09-27 감사
   (`doc/design/a2/audit-20260927-staging-vs-v3.md` §0-1)에서 그 몫이
   실제로는 빠져 있었다고 확인됐다 — TICKET-244가 레이드 화면(H1~H3/
   P1~R2/E1)에도 이 클래스를 그대로 재사용해 채웠다(`macros/
   raid_logo_header.html`). 이제 전 화면 공통이다.
   `opacity:.5`는 doc/design/a2/screens/*.html 전 화면 공통
   `.logo{opacity:.5 !important}` 규칙을 그대로 옮긴 값이다. 문구는
   디자인 원본이 영문 "poketeam"을 쓰지만, 이 리포는 <title>·랜딩 h1 등
   전부 한글 "포케팀"만 써 왔으므로(문구는 스펙 소관, 헌장 §9) 텍스트는
   기존 관례를 따르고 폰트·투명도만 디자인에서 가져왔다(보고서 "스펙과
   디자인이 다른 곳" 참고). */
.brand-logo {
  display: block;
  /* TICKET-255 — tokens.css --text-logo(400 20px/1 Black Han Sans)와 완전히
     같은 값이라 개별 속성 3개 대신 이 토큰을 직접 참조한다(letter-spacing은
     tokens.css --text-logo에 없는 값이라 아래 별도로 유지). */
  font: var(--text-logo);
  letter-spacing: -0.5px;
  opacity: 0.5;
  color: var(--color-text-primary);
}
/* A1 로그인 전용 대형 로고(screens/A2-Login.html 44px 히어로 배치) */
.brand-logo--hero {
  font-size: 44px;
  letter-spacing: -1px;
}
/* A2/A3/약관처럼 작은 로고가 화면 맨 위 단독 줄로 오는 경우의 여백. */
.brand-logo-row {
  height: var(--topbar-h); /* TICKET-255 — tokens.css 값(48px)과 이미 같아 참조로 통일 */
  display: flex;
  align-items: center;
}

/* ── 레이드 화면 상단 바 계정 영역 (PRD-012/AC-76, TICKET-251) ──
   디자인 v2.1 `.top`(`design-system-v2.1-참고/screens/A2-Apply.html` 63행,
   flex space-between) 그대로 이식. A1~A3·약관(`.brand-logo-row`)은 로고
   단독 줄이라 space-between이 필요 없어 별도 클래스로 둔다 —
   `macros/raid_logo_header.html`이 이 두 클래스를 함께 렌더한다. */
.raid-top {
  height: var(--topbar-h); /* TICKET-255 — tokens.css 값(48px)과 이미 같아 참조로 통일 */
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.raid-top__right {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
/* 디자인 `.me`(A2-Apply.html 63행, 링크 변형: color #A7B0C8·font-weight 700)
   그대로 — AC-76은 로그인/비로그인 두 상태 모두 누를 수 있어야 해서 항상
   링크 변형을 쓴다(디자인은 "주최자 화면" 같은 누를 수 없는 텍스트 변형도
   쓰지만 스펙이 우선, 헌장 §9). `max-width`+ellipsis·44px 높이는 AC-76
   요구사항(디자인 원본엔 없음 — 보고서 "스펙과 디자인이 다른 곳"). 실측
   결과 `text-overflow:ellipsis`를 `display:flex` 요소에 직접 걸면 "…"가
   그려지지 않아(크로미움 확인, flex 포매팅 컨텍스트에서 텍스트가 익명
   flex item이 되며 생기는 문제) 안쪽 `<span>`(`.raid-header-me__label`)
   하나를 더 두고 거기에 ellipsis 3종을 건다 — 바깥 `<a>`는 44px 세로
   중앙 정렬(flex)만 담당한다. */
.raid-header-me {
  height: 44px;
  display: flex;
  align-items: center;
  max-width: 120px;
  font-size: 13px;
  font-weight: 700;
  color: var(--color-text-secondary);
  text-decoration: none;
}
.raid-header-me__label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── 카카오 로그인 버튼 .btn-kakao (WEB-SCREEN-raid-mvp.md §7.1 2번 —
   "카카오로 시작하기", TICKET-239) — 카카오 브랜드 고정색(:root
   --color-kakao-*)은 TICKET-162 때부터 선언만 돼 있었고 실제로 쓰는
   화면이 없었다(login.html이 지금까지 `.btn` 계열 클래스를 하나도 쓰지
   않는 순수 텍스트 링크였다 — 이 티켓에서 처음 실사용). `.btn`의 레이아웃
   (높이·라운드·너비 100%)을 그대로 쓰고 배경·글자색만 override한다. */
.btn-kakao {
  background: var(--color-kakao-bg);
  color: var(--color-kakao-text);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  text-decoration: none;
  font-weight: 800;
}
.btn-kakao:hover {
  filter: brightness(0.96);
}

/* ── 캡션 유틸 .text-caption — login.html·landing/index.html이 이미
   참조하던 클래스인데 정의가 없어(:root `--text-caption` 변수만 있고
   선택자가 없었다) 지금까지 브라우저 기본 스타일로 렌더되던 결함을
   TICKET-239에서 채운다. */
.text-caption {
  font: var(--text-caption);
  color: var(--color-text-muted);
  text-align: center;
}
.text-caption a {
  color: var(--color-text-secondary);
}
/* login.html 소개 문구용 유틸(§7.1 "한 줄 소개") — 기존 `--text-body-lg`
   변수는 여러 컴포넌트가 `font:` 단축 속성으로만 참조했고 독립 클래스가
   없었다. */
.text-body-lg {
  font: var(--text-body-lg);
  color: var(--color-text-secondary);
  margin: 0;
}

/* TICKET-255(디자인 정본 doc/design/current/ 도입) — 계정 화면(A1/A2/A3)은
   raid_h.css 같은 전용 그룹 CSS 파일이 없다(원래도 없었다 — 화면 3개가
   전부 공용 `.field`/`.team-pick`/`.btn` 등 style.css 전역 클래스만 쓴다).
   TICKET-258(끝난 파티·계정 이식)은 이 파일 아래(`.login-page`부터
   맨 끝까지, A1/A2/A3 전용 선택자)와 `raid_e.css`(끝난 파티 E1~E4) 둘을
   담당한다 — 새 그룹 CSS 파일을 만들지 않는다.

   ── A1 로그인 페이지 레이아웃 .login-page (WEB-SCREEN-raid-mvp.md §7.1,
   TICKET-239) — 로고+한 줄 소개를 위에, 카카오 버튼·약관 링크를 아래
   붙이는 히어로 배치(design screens/A2-Login.html 구조를 flex-grow
   스페이서로 옮김). 다른 화면(A2/A3/약관)은 이 클래스를 쓰지 않는다. */
.login-page {
  display: flex;
  flex-direction: column;
  min-height: 60vh;
  gap: var(--space-6);
}
.login-page__hero {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  /* TICKET-258 실측 정정 — doc/design/current/screens/A1.html은 히어로
     상단 여백이 120px(페이지 자체 top padding 0)이다. 이 리포는 `main`이
     이미 --space-6(24px) 상단 패딩을 갖고 있어(전 화면 공통, 손대지
     않는다) 그만큼을 뺀 96px을 남긴다(24+96=120, 실측 일치). tokens.css에
     96px 토큰이 없어 --space-8(32px, 이전 값)이 디자인보다 64px 낮은
     위치에 로고가 뜨는 드리프트를 냈었다 — 값만 정정, 구조는 그대로. */
  margin-top: 96px;
}
.login-page__spacer {
  flex-grow: 1;
}
.login-page__actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
