:root {
  --bg: #F4F5F7;
  --surface: #FFFFFF;
  --surface-alt: #F8F9FB;
  --border: #E5E7EC;
  --border-strong: #CDD2DA;
  --ink: #0F1420;
  --ink-soft: #3B4254;
  --ink-mute: #6B7388;
  --ink-faint: #9AA1B2;
  /* 브랜드 컬러(mjc 확정 2026-07-29) — ★메인은 진초록 #004023.
     tokens.js 와 반드시 같은 값을 유지해야 한다(같은 색을 두 곳에서 관리 중). */
  --blue: #004023;
  --blue-dark: #002B18;
  --blue-soft: #E3EBE6;
  --blue-tint: #F2F7F4;
  --green: #2F9E6A;
  --green-soft: #E7F5EE;
  --yellow: #FCEF5A;
  --yellow-ink: #4A4200;
  --navy: #023570;
  --amber: #C77700;
  --amber-soft: #FFF4DD;
  --red: #D03B3B;
  --red-soft: #FCE7E7;
  --violet: #6B47C9;
  --violet-soft: #EFEAFC;
  --pending-soft: #EEF0F4;
  --font-sans: "Pretendard","Pretendard Variable",-apple-system,BlinkMacSystemFont,"Apple SD Gothic Neo","Segoe UI",Roboto,sans-serif;
  --font-mono: "JetBrains Mono","SF Mono",Menlo,Consolas,monospace;
}
* { box-sizing: border-box; }
/* ★스크롤 끝에서 문서 전체가 딸려 움직이는 것(고무줄/bounce)을 막는다 — 2026-08-26.
   증상(mjc 신고): 「앱 아래 푸터 부분이 «같이 움직인다» — 고정시켜 달라」. 반장앱에서,
   ★«위아래로 쓸 때» 난다(mjc 확인). 즉 자리가 틀린 것이 아니라 «움직이는» 것이 문제였다.
   원인: 안쪽 스크롤(.scroll-area)이 끝에 닿으면 스크롤이 바깥(문서)으로 «넘어가»(scroll
   chaining), iOS WKWebView 가 문서를 고무줄처럼 튕긴다. 그때 화면 아래에 붙어 있어야 할
   탭바가 문서와 함께 밀렸다 돌아온다.
   ★탭바에 position 을 주지 않는다 — 탭바는 이미 제자리에 있다(.frame 이 flex column 이고
     위 형제가 flex:1 이라 자동으로 맨 아래). 실측으로 확인했다(375x812, 짧은 내용에서
     탭바 bottom=812, 아래 빈 공간 0). 움직이는 것이 문제지 «자리»가 문제가 아니다.
     position:fixed 로 고치면 .frame 의 가운데 정렬(max-width 420)을 벗어나 넓은 화면에서
     탭바만 화면 폭으로 늘어난다. 그 길로 가지 말 것.
   ★«당겨서 새로고침»을 죽이지 않는다 — 이 앱에는 그 기능이 없다(2026-08-26 전수 확인:
     touchstart·touchmove 핸들러 0건, pull-to-refresh 구현 0건, 새로고침은 전부 버튼). */
html, body { margin: 0; padding: 0; overscroll-behavior: none; background: #11151F; color: var(--ink); font-family: var(--font-sans); -webkit-font-smoothing: antialiased; font-size: 15px; letter-spacing: -0.01em; }
/* ★높이 단위를 .frame 과 맞춘다 — 2026-08-26.
   .frame 은 height:100dvh 인데 여기만 100vh 였다. iOS 사파리에서 주소창이 보일 때
   100vh > 100dvh 라 #root 가 프레임보다 커지고, 페이지가 조금 스크롤되면서
   ★탭바 아래로 body 배경(#11151F, 거의 검정)이 드러난다.
   ★원인 «확정» 전이다 — mjc 신고(앱 하단 푸터가 같이 움직인다)의 원인이 이것이라고
     단정하지 않는다. 다만 같은 파일 안에서 한쪽은 vh, 한쪽은 dvh 로 재는 것은 어느 쪽이
     맞든 그 자체로 어긋난 것이라 먼저 맞춘다. 나중에 「이걸로 고쳐진 게 맞나」를 판단할 수
     있도록 이 주석을 남긴다.
   ★두 줄인 이유: dvh 를 모르는 구형 WebView 는 첫 줄(vh)을 쓰고, 아는 브라우저는 뒤가 이긴다.
     한 줄로 줄이지 말 것 — 현장 기기에 구형 아이폰이 섞여 있다(OrientationGate 주석 참고). */
#root { min-height: 100vh; min-height: 100dvh; }
.frame {
  max-width: 420px;
  margin: 0 auto;
  height: 100vh;              /* 폴백 */
  height: 100dvh;             /* iOS Safari의 동적 뷰포트 (주소창 빼고) */
  background: var(--bg);
  position: relative;
  overflow: hidden;           /* 프레임 자체는 스크롤 안 함 */
  display: flex;
  flex-direction: column;
  /* iOS 노치/상태바 세이프에어리어 — 헤더가 상태바에 겹치고 뒤로가기 버튼이 안 눌리는 문제 해결.
     안드로이드는 env(safe-area-inset-top)=0 이라 무영향. box-sizing:border-box 라 높이(100dvh) 안에서 처리됨. */
  padding-top: env(safe-area-inset-top);
}

/* flex 컬럼 화면 root(오버레이 화면 등)가 내용 높이로 부풀어 내부 스크롤이 막히는 flexbox 버그 방지.
   min-height 기본값(auto)이면 스크롤 컨테이너가 프레임 높이 이하로 수축하지 못해 overflow:auto 가 작동하지 않는다. */
.frame > * { min-height: 0; }

/* 앱 프레임 «안»에 겹쳐 뜨는 화면(오버레이)의 뿌리.
   ★.frame 을 다시 쓰면 안 된다 — 안쪽 .frame 은 세로 flex 컨테이너의 아이템이 되는데,
   .frame 의 `margin: 0 auto` 때문에 가로 auto margin 이 남는 공간을 다 먹어 stretch 가
   취소되고 «내용 크기»로 쪼그라든다. 2026-08-25 실측: 바깥 390px 안에서 안쪽이 99.7px.
   반장앱 배정 근로자 화면이 그렇게 깨져 보였다(mjc 신고).
   그래서 여기서는 max-width·margin 을 두지 않고 부모를 그대로 채운다 — 폭 제한은 이미
   바깥 .frame 이 하고 있으므로 두 번 할 이유가 없다. */
.overlay-frame {
  flex: 1;                    /* 부모(.frame)의 남은 높이를 채운다 — 100dvh 를 다시 잡지 않는다 */
  min-height: 0;              /* 안쪽 .scroll-area 가 스스로 스크롤하게(넘침 방지) */
  display: flex;
  flex-direction: column;
  background: var(--bg);
  overflow: hidden;           /* 뿌리는 스크롤하지 않는다(.frame 과 같은 규칙) */
}

/* 탭이 있는 화면(home/history/me)의 스크롤 영역 */
.scroll-area {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  display: flex;
  flex-direction: column;
}
button { font-family: var(--font-sans); }
.btn { display: flex; align-items: center; justify-content: center; gap: 8px; border: none; cursor: pointer; font-weight: 700; }
.btn-primary { background: var(--blue); color: #fff; box-shadow: 0 4px 14px rgba(0,64,35,0.32); }
.btn-ghost { background: #fff; border: 1px solid var(--border); color: var(--ink); }
.pill { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; height: 22px; }
.pill-green { background: var(--green-soft); color: var(--green); }
.pill-blue  { background: var(--blue-soft); color: var(--blue-dark); }
.pill-amber { background: var(--amber-soft); color: var(--amber); }
.pill-red   { background: var(--red-soft); color: var(--red); }
.pill-neutral { background: var(--pending-soft); color: var(--ink-soft); }
@keyframes scanline { 0%,100% { top: 12px; } 50% { top: calc(100% - 14px); } }
@keyframes pulse { 0%,100% { opacity: 0.6; } 50% { opacity: 1; } }
@keyframes pop { from { transform: scale(0.6); opacity: 0; } to { transform: scale(1); opacity: 1; } }
@keyframes spin { to { transform: rotate(360deg); } }
.spin { animation: spin 0.9s linear infinite; }
.qr-box { position: relative; width: 260px; height: 260px; border-radius: 24px; overflow: hidden; background: linear-gradient(135deg, #1a2334, #0f1420); }
#qr-reader { width: 100% !important; }
#qr-reader video { border-radius: 18px; }

/* 전화 로그인 invisible reCAPTCHA 배지 숨김 — 우하단에 떠서 하단 탭바(MY)를 가려 조작 불가 문제 해결.
   구글 약관: 배지를 숨기면 reCAPTCHA 안내 문구를 사용자 흐름에 노출해야 함(전화 로그인 화면에 표기). */
.grecaptcha-badge { visibility: hidden; }

/* [mjc 2026-08-07] iOS(WKWebView) date/time/month 입력 정렬 통일 — 취업요청 «근무 가능 시작일»에서
   값 텍스트가 다른 입력칸과 크기가 다르고 상하 중앙·좌측 끝이 안 맞던 문제.
   iOS 는 값 텍스트를 자체 셰도 요소(::-webkit-date-and-time-value)로 그려 기본이 가운데 정렬 + 고유 여백이다.
   데이터 흐름: 인라인 WebkitAppearance:none(각 화면, #439 방식)이 네이티브 껍데기를 끄고,
   여기 전역 규칙이 값 텍스트를 «좌측 정렬 + 여백 0 + 입력칸 높이에 맞춘 세로 중앙»으로 맞춘다.
   ★이 블록을 지우면 iOS 에서 날짜 입력 정렬이 다시 어긋난다(안드로이드·데스크톱은 영향 없음). */
input::-webkit-date-and-time-value { text-align: left; margin: 0; line-height: normal; }
input[type="date"], input[type="time"], input[type="month"] {
  -webkit-appearance: none; appearance: none;
  display: flex; align-items: center;
}

/* [2026-09-21] 늦게 받는 화면(QR 스캐너)을 못 받았을 때의 안내 — ScreenLoadBoundary.jsx.
   배포되면 옛 화면 파일이 서버에서 사라져, 앱을 켜 둔 근로자가 스캔을 누르면 실패한다.
   앱이 스스로 한 번 다시 받아 보고, 그래도 안 되면 이 자리가 «무엇을 하면 되는지» 를 말한다.
   ★프레임을 채운다 — 좁게 그리면 빈 화면 위에 글자만 떠서 «고장» 으로 읽힌다. */
.screenLoadFail {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 16px; padding: 24px; text-align: center;
}
.screenLoadFailText { margin: 0; font-size: 15px; line-height: 1.6; color: #3A4256; }
.screenLoadFailBack {
  min-height: 44px; padding: 0 20px; border: 1px solid #CBD2E0; border-radius: 10px;
  background: #fff; color: #3A4256; font-size: 15px; font-family: inherit; cursor: pointer;
}
