/* DESIGN.md(Airbnb 디자인 분석)를 이 앱에 옮긴 공통 스타일.
   - 흰 캔버스 + 잉크(#222) 텍스트, 강조색은 Rausch(#ff385c) 하나만.
   - 모서리는 전부 둥글게, 그림자는 한 단계만.
   - 폰트는 Pretendard(_head.html에서 CDN 로드). 못 받으면 시스템 스택으로 폴백.

   근무 코드 색(D/E/N/OFF/S)은 DESIGN.md에 없는 확장이다. 원문은 강조색 하나만 쓰는
   마켓플레이스 스펙이지만, 듀티표는 근무 종류가 한눈에 구분돼야 해서 톤을 낮춘
   칩 색을 따로 정의했다. 텍스트는 전부 잉크 쪽으로 눌러 원본 톤을 유지.

   ── 모션에 대해 ──
   이 앱은 사실상 아이폰 전용이라, 손가락으로 만지는 것이 화면에서 물리적으로
   반응해야 "앱 같다". 원칙 셋:
     1. 누르면 즉시 줄어든다(--t-fast). 손이 닿은 순간의 반응은 빨라야 한다.
     2. 떼면 천천히 돌아온다(--t-base + 스프링). 여기가 "샤악" 하는 부분.
     3. 큰 것이 움직일수록 오래 걸린다. 시트(--t-sheet) > 카드 > 칩.
   시간 값과 이징은 아래 토큰 한 곳에만 있다. 감이 안 맞으면 여기만 고칠 것. */

:root {
  --primary: #ff385c;
  --primary-active: #e00b41;
  --ink: #222222;
  --body: #3f3f3f;
  --muted: #6a6a6a;
  --muted-soft: #929292;
  --hairline: #dddddd;
  --hairline-soft: #ebebeb;
  --canvas: #ffffff;
  --surface-soft: #f7f7f7;
  --surface-strong: #f2f2f2;
  --error: #c13515;

  /* 반투명 상단바용. 배경이 비쳐 보이면서 흐려지는 아이폰식 유리 느낌 */
  --canvas-blur: rgba(255, 255, 255, 0.72);
  --scrim: rgba(0, 0, 0, 0.32);
  /* 리플(탭한 자리에서 퍼지는 원)과 카드 광택. 밝은 화면에선 검정을 옅게 얹는다 */
  --ripple: rgba(0, 0, 0, 0.13);
  --sheen: rgba(255, 255, 255, 0.55);

  --r-xs: 4px; --r-sm: 8px; --r-md: 14px; --r-lg: 20px; --r-xl: 32px; --r-full: 9999px;
  --s-xs: 4px; --s-sm: 8px; --s-md: 12px; --s-base: 16px; --s-lg: 24px; --s-xl: 32px;

  --shadow: rgba(0,0,0,0.02) 0 0 0 1px, rgba(0,0,0,0.04) 0 2px 6px 0, rgba(0,0,0,0.1) 0 4px 8px 0;
  --shadow-lift: rgba(0,0,0,0.03) 0 0 0 1px, rgba(0,0,0,0.06) 0 8px 20px -4px, rgba(0,0,0,0.10) 0 16px 32px -8px;
  --shadow-sheet: rgba(0,0,0,0.12) 0 -8px 40px -4px, rgba(0,0,0,0.06) 0 -2px 8px 0;

  /* CDN이 등록하는 family 이름은 'Pretendard Variable'이다(가변 폰트라 이름이 다름).
     'Pretendard'를 앞에 두면 아무것도 매치되지 않고 지나칠 뿐이라 무해하지만,
     로컬에 정적 Pretendard가 설치된 기기에서는 그쪽이 쓰이게 해준다. */
  --font: 'Pretendard Variable', Pretendard, Inter, 'Apple SD Gothic Neo',
          -apple-system, system-ui, 'Malgun Gothic', Roboto, 'Helvetica Neue', sans-serif;

  /* ── 모션 토큰 ── */
  /* 감속 곡선. 빠르게 출발해 길게 멈춘다 = "스으윽" */
  --e-out: cubic-bezier(0.22, 1, 0.36, 1);
  /* 끝에서 살짝 넘어갔다 돌아온다 = "샤악". 눌렀다 뗄 때/뭐가 나타날 때 */
  --e-spring: cubic-bezier(0.34, 1.42, 0.64, 1);
  --e-inout: cubic-bezier(0.65, 0, 0.35, 1);

  --t-fast: 0.14s;    /* 눌리는 순간 */
  --t-base: 0.28s;    /* 보통의 상태 변화 */
  --t-slow: 0.44s;    /* 카드가 나타나기 */
  --t-sheet: 0.48s;   /* 아래에서 올라오는 시트 */
}

/* ---------- 다크 모드 ----------
   DESIGN.md에는 없는 의도적 확장이다. 원문은 흰 캔버스 전제의 마켓플레이스
   스펙인데, 이 앱은 나이트 근무자가 새벽에 보는 화면이라 흰 배경이 그대로
   눈부심이 된다. 색의 역할(잉크/헤어라인/강조 하나)은 그대로 두고 값만 뒤집었다.

   칩 색은 값을 새로 만들어야 했다. 밝은 파스텔 배경(#fff4e5 등)은 어두운
   화면에서 그대로 형광등이 된다. 어두운 바탕 + 밝은 글자로 뒤집되, 근무별
   색상(주황/분홍/보라/초록/회색)은 유지해서 밝을 때와 같은 감각으로 읽히게 했다.

   [data-theme]이 없으면 OS 설정을 따르고, 사용자가 토글을 누르면 그 값이 이긴다. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { color-scheme: dark; }
  :root:not([data-theme="light"]) {
    --primary: #ff5a76; --primary-active: #ff7d93;
    --ink: #f2f2f3; --body: #d5d5d8; --muted: #9d9da4; --muted-soft: #74747b;
    --hairline: #3a3a41; --hairline-soft: #2b2b31;
    --canvas: #151518; --surface-soft: #1e1e23; --surface-strong: #292930;
    --error: #ff8168;
    --canvas-blur: rgba(21, 21, 24, 0.72);
    --scrim: rgba(0, 0, 0, 0.55);
    --ripple: rgba(255, 255, 255, 0.16);
    --sheen: rgba(255, 255, 255, 0.07);
    --shadow: rgba(0,0,0,0.5) 0 2px 8px 0, rgba(255,255,255,0.04) 0 0 0 1px;
    --shadow-lift: rgba(0,0,0,0.6) 0 8px 24px -4px, rgba(255,255,255,0.06) 0 0 0 1px;
    --shadow-sheet: rgba(0,0,0,0.7) 0 -8px 40px -4px, rgba(255,255,255,0.06) 0 0 0 1px;
    --d-bg: #3b2a12; --d-fg: #f2bd7e;
    --e-bg: #3f1d27; --e-fg: #ff9fb6;
    --n-bg: #262151; --n-fg: #b7aeff;
    --s-bg: #17331f; --s-fg: #82d9a4;
    --off-bg: #2a2a30; --off-fg: #a3a3aa;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --primary: #ff5a76; --primary-active: #ff7d93;
  --ink: #f2f2f3; --body: #d5d5d8; --muted: #9d9da4; --muted-soft: #74747b;
  --hairline: #3a3a41; --hairline-soft: #2b2b31;
  --canvas: #151518; --surface-soft: #1e1e23; --surface-strong: #292930;
  --error: #ff8168;
  --canvas-blur: rgba(21, 21, 24, 0.72);
  --scrim: rgba(0, 0, 0, 0.55);
  --ripple: rgba(255, 255, 255, 0.16);
  --sheen: rgba(255, 255, 255, 0.07);
  --shadow: rgba(0,0,0,0.5) 0 2px 8px 0, rgba(255,255,255,0.04) 0 0 0 1px;
  --shadow-lift: rgba(0,0,0,0.6) 0 8px 24px -4px, rgba(255,255,255,0.06) 0 0 0 1px;
  --shadow-sheet: rgba(0,0,0,0.7) 0 -8px 40px -4px, rgba(255,255,255,0.06) 0 0 0 1px;
  --d-bg: #3b2a12; --d-fg: #f2bd7e;
  --e-bg: #3f1d27; --e-fg: #ff9fb6;
  --n-bg: #262151; --n-fg: #b7aeff;
  --s-bg: #17331f; --s-fg: #82d9a4;
  --off-bg: #2a2a30; --off-fg: #a3a3aa;
}
/* 라이트 모드 칩 색 (다크 블록보다 먼저 선언되면 덮이므로 :root 기본값으로 둔다) */
:root {
  --d-bg: #fff4e5; --d-fg: #9a5b0d;
  --e-bg: #ffe9ee; --e-fg: #b0234a;
  --n-bg: #eeebff; --n-fg: #4b3fa6;
  --s-bg: #e7f6ec; --s-fg: #1f7a46;
  --off-bg: #f2f2f2; --off-fg: #6a6a6a;
}

/* 테마를 토글한 순간에만 색이 녹아 넘어가게 한다(_head.html이 0.38초 붙였다 뗀다).
   상시로 켜두면 페이지를 처음 그릴 때도 전환이 걸려서 흰 화면이 스며 나온다. */
.theme-morph, .theme-morph * ,
.theme-morph *::before, .theme-morph *::after {
  transition: background-color 0.3s var(--e-inout),
              border-color 0.3s var(--e-inout),
              color 0.3s var(--e-inout) !important;
}

* { -webkit-tap-highlight-color: transparent; box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.5;
  color: var(--ink);
  background: var(--canvas);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Pretendard는 자간이 시스템 폰트보다 살짝 넓어서 한글 문장이 헐거워 보인다 */
  letter-spacing: -0.01em;
  /* 아이폰에서 스크롤 끝에 닿았을 때 페이지 전체가 튕기며 흰 띠가 보이는 걸 막는다 */
  overscroll-behavior-y: none;
}

/* ---------- 진입 애니메이션 ----------
   화면이 통째로 완성된 채로 나타나면 정적인 문서처럼 느껴진다. 요소들이 아주 살짝
   아래에서 떠오르면 같은 화면도 "열렸다"는 감각이 된다. JS 없이 CSS animation으로만
   돌리므로 스크립트가 실패해도 내용이 숨겨지는 사고가 없다.

   --i(순번)를 인라인 style로 주면 차례로 올라온다. 없으면 0으로 쳐서 동시에 뜬다. */
@keyframes rise {
  from { opacity: 0; transform: translate3d(0, 14px, 0); }
  to   { opacity: 1; transform: none; }
}
@keyframes pop {
  from { opacity: 0; transform: scale(0.86); }
  to   { opacity: 1; transform: none; }
}
@keyframes fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.rise { animation: rise var(--t-slow) var(--e-out) both;
        animation-delay: calc(var(--i, 0) * 45ms); }
.pop  { animation: pop var(--t-base) var(--e-spring) both;
        animation-delay: calc(var(--i, 0) * 22ms); }

/* ---------- 리플 (app.js가 탭한 자리에 심는다) ---------- */
/* 버튼을 누른 자리에서 원이 퍼진다. 눌렸다는 걸 색 변화보다 확실하게 알려주고,
   무엇보다 "샤악" 하는 그 느낌 자체가 여기서 나온다. */
.ripples { position: relative; overflow: hidden; }
.ripple-ink {
  position: absolute; border-radius: var(--r-full);
  background: var(--ripple); pointer-events: none;
  transform: scale(0); opacity: 1;
  animation: ripple 0.55s var(--e-out) forwards;
}
@keyframes ripple {
  to { transform: scale(1); opacity: 0; }
}

/* ---------- 상단 내비 ---------- */
.nav {
  display: flex; align-items: center; gap: var(--s-base);
  height: 80px; padding: 0 var(--s-xl);
  /* 아이폰 가로 노치(가로모드)에서 브랜드가 잘리지 않게 */
  padding-left: max(var(--s-xl), env(safe-area-inset-left));
  padding-right: max(var(--s-xl), env(safe-area-inset-right));
  background: var(--canvas-blur);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid var(--hairline);
  position: sticky; top: 0; z-index: 40;
  transition: box-shadow var(--t-base) var(--e-out),
              border-color var(--t-base) var(--e-out);
}
/* 스크롤을 내리면 내용 위로 떠오른다(_head.html이 .lifted를 붙인다) */
.nav.lifted { box-shadow: var(--shadow); border-color: transparent; }
.nav .brand {
  font-size: 20px; font-weight: 700; letter-spacing: -0.4px;
  color: var(--primary); margin-right: auto; white-space: nowrap;
  animation: rise var(--t-slow) var(--e-out) both;
}
.nav .brand small {
  display: block; font-size: 13px; font-weight: 500;
  color: var(--muted); letter-spacing: -0.2px;
}
.nav a, .nav button.linkish {
  position: relative; overflow: hidden;
  font-size: 14px; font-weight: 500; color: var(--ink);
  text-decoration: none; padding: 10px 14px; border-radius: var(--r-full);
  border: none; background: transparent; cursor: pointer; white-space: nowrap;
  transition: background-color var(--t-fast) var(--e-out),
              transform var(--t-base) var(--e-spring);
}
.nav a:hover, .nav button.linkish:hover { background: var(--surface-strong); }
.nav a:active, .nav button.linkish:active {
  transform: scale(0.93); transition-duration: var(--t-fast);
}

/* 폰에서 상단바에 안 들어가는 메뉴를 여는 ⋯ 버튼.
   393px에 브랜드 + 토글 + 링크 5개는 물리적으로 안 들어가서 글자가 잘렸다.
   매일 누르는 둘(만날 시간/내 일정)만 남기고 나머지는 여기로 내렸다. */
.more-btn {
  display: none; position: relative; overflow: hidden;
  width: 38px; height: 38px; flex: none; padding: 0;
  border: 1px solid var(--hairline); border-radius: var(--r-full);
  background: var(--canvas); color: var(--ink); cursor: pointer;
  font-size: 17px; line-height: 1;
  align-items: center; justify-content: center;
  transition: background-color var(--t-fast) var(--e-out),
              transform var(--t-base) var(--e-spring);
}
.more-btn:active { transform: scale(0.88); transition-duration: var(--t-fast); }

/* 메뉴 시트 안의 줄들 */
.menu-item {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--s-base) var(--s-md); margin: 0 calc(var(--s-md) * -1);
  border-radius: var(--r-md); text-decoration: none; color: var(--ink);
  font-size: 16px; font-weight: 600;
  transition: background-color var(--t-fast) var(--e-out),
              transform var(--t-base) var(--e-spring);
}
.menu-item small { font-size: 13px; font-weight: 400; color: var(--muted); }
.menu-item:hover { background: var(--surface-soft); }
.menu-item:active { transform: scale(0.98); background: var(--surface-strong); }

/* 테마 토글 버튼 */
.theme-btn {
  position: relative; overflow: hidden;
  width: 38px; height: 38px; flex: none; padding: 0;
  border: 1px solid var(--hairline); border-radius: var(--r-full);
  background: var(--canvas); color: var(--ink); cursor: pointer;
  font-size: 15px; line-height: 1;
  transition: background-color var(--t-fast) var(--e-out),
              transform var(--t-base) var(--e-spring),
              border-color var(--t-base) var(--e-out);
}
.theme-btn:hover { background: var(--surface-strong); }
.theme-btn:active { transform: scale(0.88); transition-duration: var(--t-fast); }
/* 해/달 아이콘이 바뀔 때 한 바퀴 돈다 */
.theme-btn.spin { animation: spin-swap 0.45s var(--e-out); }
@keyframes spin-swap {
  from { transform: rotate(-160deg) scale(0.5); opacity: 0.2; }
  to   { transform: none; opacity: 1; }
}

/* ---------- 레이아웃 ---------- */
.wrap {
  max-width: 760px; margin: 0 auto;
  padding: var(--s-xl) var(--s-lg) 64px;
  /* 아이폰 홈 인디케이터 자리를 비워둔다 */
  padding-bottom: calc(64px + env(safe-area-inset-bottom));
}
.wrap-narrow { max-width: 420px; }
.page-title {
  font-size: 22px; font-weight: 700; letter-spacing: -0.6px; margin: 0 0 var(--s-xs);
  animation: rise var(--t-slow) var(--e-out) both; animation-delay: 30ms;
}
.page-sub {
  font-size: 14px; color: var(--muted); margin: 0 0 var(--s-lg);
  animation: rise var(--t-slow) var(--e-out) both; animation-delay: 60ms;
}

/* ---------- 버튼 ---------- */
.btn {
  position: relative; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center;
  height: 48px; padding: 0 var(--s-lg); border-radius: var(--r-md);
  font-family: var(--font); font-size: 16px; font-weight: 600;
  letter-spacing: -0.3px;
  border: none; cursor: pointer; text-decoration: none;
  transition: transform var(--t-base) var(--e-spring),
              background-color var(--t-fast) var(--e-out),
              box-shadow var(--t-base) var(--e-out),
              opacity var(--t-base) var(--e-out);
}
.btn:active { transform: scale(0.96); transition-duration: var(--t-fast); }
.btn-primary { background: var(--primary); color: #fff; box-shadow: 0 4px 14px -4px rgba(255,56,92,0.5); }
.btn-primary:active { background: var(--primary-active); box-shadow: 0 2px 6px -2px rgba(255,56,92,0.5); }
.btn-primary:disabled {
  background: var(--surface-strong); color: var(--muted-soft);
  box-shadow: none; cursor: not-allowed; transform: none;
}
.btn-secondary { background: var(--canvas); color: var(--ink); border: 1px solid var(--ink); }
.btn-block { width: 100%; }

/* 오래 걸리는 요청(사진 업로드는 격자 검출 + 806칸 자르기 + 806칸 추론을 요청
   안에서 다 한다) 동안 버튼이 그대로면 눌린 건지 멈춘 건지 알 수 없어서 사람이
   다시 누른다. 글자를 바꾸고 앞에 도는 링을 붙인다. */
.btn.loading { pointer-events: none; opacity: 0.75; }
.btn.loading::before {
  content: ''; width: 16px; height: 16px; margin-right: 10px; flex: none;
  border: 2px solid currentColor; border-top-color: transparent;
  border-radius: var(--r-full);
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- 폼 ---------- */
.field { margin-bottom: var(--s-base); }
.field label { display: block; font-size: 14px; font-weight: 600; color: var(--muted); margin-bottom: var(--s-sm); }
.field input, .field select {
  width: 100%; height: 56px; padding: 0 var(--s-md);
  font-family: var(--font); font-size: 16px; color: var(--ink);
  background: var(--canvas); border: 1px solid var(--hairline); border-radius: var(--r-md);
  transition: border-color var(--t-base) var(--e-out),
              box-shadow var(--t-base) var(--e-out);
}
.field input[type="file"] { padding: var(--s-md); height: auto; }
/* 테두리 굵기를 바꾸면 글자가 1px 밀려서 덜컥거린다. 굵기는 두고 그림자로 강조. */
.field input:focus, .field select:focus {
  outline: none; border-color: var(--ink);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ink) 12%, transparent);
}
.row { display: flex; gap: var(--s-md); }
.row > * { flex: 1; }
.error {
  color: var(--error); font-size: 14px; margin-top: var(--s-base);
  white-space: pre-wrap; padding: var(--s-md); border-radius: var(--r-md);
  background: color-mix(in srgb, var(--error) 9%, var(--canvas));
  animation: rise var(--t-base) var(--e-out) both;
}

/* ---------- 근무 칩 ---------- */
.chip {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 34px; height: 26px; padding: 0 var(--s-sm);
  border-radius: var(--r-full); font-size: 13px; font-weight: 700;
  letter-spacing: -0.2px;
  background: var(--surface-strong); color: var(--muted);
  transition: transform var(--t-base) var(--e-spring),
              background-color var(--t-base) var(--e-out),
              color var(--t-base) var(--e-out);
}
.chip-D { background: var(--d-bg); color: var(--d-fg); }
.chip-E { background: var(--e-bg); color: var(--e-fg); }
.chip-N { background: var(--n-bg); color: var(--n-fg); }
.chip-S { background: var(--s-bg); color: var(--s-fg); }
.chip-OFF { background: var(--off-bg); color: var(--off-fg); }
/* 근무를 고쳐서 값이 바뀐 칩. 바뀌었다는 걸 눈으로 잡아준다 */
.chip.changed { animation: chip-swap 0.5s var(--e-spring); }
@keyframes chip-swap {
  0%   { transform: scale(0.4) rotate(-8deg); opacity: 0.3; }
  60%  { transform: scale(1.18) rotate(2deg); opacity: 1; }
  100% { transform: none; }
}

/* ---------- 오늘/내일 카드 ----------
   매일 보는 화면에서 실제로 궁금한 건 "나 오늘 뭐야" 하나다. 달력을 훑기 전에
   이게 먼저 눈에 들어와야 해서 맨 위에 크게 놓는다. 특히 폰에서는 스크롤 없이
   이 카드만 보고 끝나는 게 정상 사용이다.

   칩 색을 카드 배경 전체로 확장했다. 칩 하나만 있을 때보다 색 면적이 커져서
   화면을 켜자마자 색으로 근무를 알아채게 된다(D=주황, N=보라 식으로). */
.hero { display: grid; gap: var(--s-md); margin-bottom: var(--s-xl); }
.hero-card {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column;
  border-radius: var(--r-lg); padding: var(--s-lg);
  border: 1px solid var(--hairline-soft); background: var(--surface-soft);
  color: inherit; text-decoration: none; min-height: 132px;
  animation: rise 0.55s var(--e-out) both;
  transition: transform var(--t-base) var(--e-spring),
              box-shadow var(--t-base) var(--e-out);
}
.hero-card:nth-child(2) { animation-delay: 90ms; }
/* 색 면 위로 비스듬히 지나가는 옅은 광택. 단색 덩어리가 종이가 아니라
   유리처럼 보이게 하는 값싼 방법이다. */
.hero-card::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(135deg, var(--sheen) 0%, transparent 42%);
  opacity: 0.9;
}
.hero-card.tappable { cursor: pointer; }
.hero-card.tappable:active {
  transform: scale(0.975); transition-duration: var(--t-fast);
}
.hero-when {
  font-size: 13px; font-weight: 700; letter-spacing: 0.2px;
  color: var(--muted); text-transform: none;
}
.hero-date { font-size: 15px; font-weight: 500; color: var(--body); }
.hero-date .sun { color: var(--primary); }
/* margin-top:auto 로 코드를 카드 아래쪽에 붙인다. 오늘/내일 카드 높이가 달라도
   큰 글자의 밑선이 맞아서 나란히 놓았을 때 정돈돼 보인다. */
.hero-shift { display: flex; align-items: baseline; gap: var(--s-sm); margin-top: auto; }
.hero-code {
  font-size: 52px; font-weight: 800; line-height: 1; letter-spacing: -2.5px;
  /* 카드가 떠오른 뒤 근무 코드가 한 박자 늦게 튀어나온다 */
  animation: pop 0.5s var(--e-spring) both; animation-delay: 0.2s;
}
.hero-name { font-size: 17px; font-weight: 600; }
.hero-none { margin-top: auto; font-size: 15px; color: var(--muted-soft); }

/* 근무별 카드 톤. 칩과 같은 색 토큰을 쓰되 면적이 넓어지므로 글자는 진한 쪽으로. */
.hero-card.s-D   { background: var(--d-bg); border-color: transparent; }
.hero-card.s-E   { background: var(--e-bg); border-color: transparent; }
.hero-card.s-N   { background: var(--n-bg); border-color: transparent; }
.hero-card.s-S   { background: var(--s-bg); border-color: transparent; }
.hero-card.s-OFF { background: var(--off-bg); border-color: transparent; }
.s-D   .hero-code, .s-D   .hero-name { color: var(--d-fg); }
.s-E   .hero-code, .s-E   .hero-name { color: var(--e-fg); }
.s-N   .hero-code, .s-N   .hero-name { color: var(--n-fg); }
.s-S   .hero-code, .s-S   .hero-name { color: var(--s-fg); }
.s-OFF .hero-code, .s-OFF .hero-name { color: var(--off-fg); }

/* 근무표가 없는 날(달 경계에서 생긴다)은 큰 빈 상자가 화면 위를 차지하지 않게
   한 줄로 눕힌다. 알려줄 내용이 "없다" 하나뿐인데 자리는 제일 크면 이상하다. */
.hero-card.is-empty {
  min-height: 0; flex-direction: row; align-items: center;
  gap: var(--s-sm); flex-wrap: wrap;
}
.hero-card.is-empty .hero-when { margin-right: var(--s-xs); }
.hero-card.is-empty .hero-none { margin-top: 0; margin-left: auto; font-size: 14px; }

/* 내일 카드는 오늘보다 한 단계 작게 - 둘 다 크면 뭐가 오늘인지 헷갈린다 */
.hero-tomorrow { min-height: 108px; }
.hero-tomorrow .hero-code { font-size: 38px; letter-spacing: -1.5px; }
.hero-tomorrow .hero-name { font-size: 15px; }

@media (min-width: 745px) {
  /* 넓은 화면에서는 나란히. 오늘 쪽에 더 넓은 몫을 준다. */
  .hero { grid-template-columns: 1.35fr 1fr; }
  .hero-card.tappable:hover { box-shadow: var(--shadow-lift); transform: translateY(-2px); }
}
@media (max-width: 744px) {
  .hero { gap: var(--s-sm); margin-bottom: var(--s-lg); }
  .hero-card { padding: var(--s-base); border-radius: var(--r-md); min-height: 118px; }
  .hero-code { font-size: 46px; }
  /* 폰에서 내일 카드는 높이를 줄이고 한 줄로 눕힌다. 오늘 카드가 접히지 않고
     화면 첫 화면에 온전히 들어오게 하는 게 우선이다. */
  .hero-tomorrow { min-height: 0; flex-direction: row; align-items: center;
                   gap: var(--s-sm); flex-wrap: wrap; }
  .hero-tomorrow .hero-when { margin-right: var(--s-xs); }
  .hero-tomorrow .hero-shift { margin-top: 0; margin-left: auto; }
  .hero-tomorrow .hero-code { font-size: 26px; letter-spacing: -1px; }
  .hero-tomorrow .hero-none { margin-top: 0; margin-left: auto; font-size: 14px; }
}

/* ---------- 캘린더 ---------- */
/* minmax(0,1fr): 기본값인 1fr은 칸 내용(근무 칩)의 최소 너비 밑으로 안 줄어들어서
   좁은 폰에서 토요일 열이 화면 밖으로 밀려났다. 0을 하한으로 줘서 항상 7열이 들어오게 한다. */
.cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--s-sm); }
.dow {
  text-align: center; font-size: 12px; font-weight: 700; color: var(--muted);
  padding-bottom: var(--s-xs);
  animation: fade var(--t-base) var(--e-out) both;
}
.dow.sun { color: var(--primary); }
.day {
  position: relative; overflow: hidden; min-width: 0;
  aspect-ratio: 1; border-radius: var(--r-md); border: 1px solid var(--hairline-soft);
  background: var(--canvas); padding: var(--s-sm);
  display: flex; flex-direction: column; align-items: center; justify-content: space-between;
  cursor: pointer; user-select: none; -webkit-user-select: none;
  /* 달력이 왼쪽 위부터 차례로 톡톡 떠오른다. --i는 템플릿이 인라인으로 준다. */
  animation: pop var(--t-base) var(--e-spring) both;
  animation-delay: calc(60ms + var(--i, 0) * 12ms);
  transition: box-shadow var(--t-base) var(--e-out),
              border-color var(--t-base) var(--e-out),
              transform var(--t-base) var(--e-spring);
}
.day:hover { box-shadow: var(--shadow); }
.day:active { transform: scale(0.93); transition-duration: var(--t-fast); }
/* 달 시작 전 빈 칸(8월이면 일~금 6칸). 클릭 리스너는 원래 없었지만 .day 라서
   :hover/:active 효과가 그대로 걸려, 눌리는 것처럼 반응해놓고 아무 일도 안 일어났다.
   pointer-events로 아예 손에 안 잡히게 한다 - 있지도 않은 날짜다. */
.day.blank {
  border: none; background: transparent; cursor: default;
  pointer-events: none;
}
.day.blank:active { transform: none; }
.day .num { font-size: 12px; font-weight: 600; color: var(--muted); align-self: flex-start; }
/* 고른 날은 테두리 굵기를 바꾸지 않는다. 1px→2px는 안쪽 내용을 밀어서 덜컥거린다.
   대신 안쪽 그림자로 링을 그린다(자리를 차지하지 않음). */
.day.selected {
  border-color: transparent;
  box-shadow: inset 0 0 0 2px var(--ink), var(--shadow);
}
.day .chip { margin-bottom: var(--s-xs); min-width: 0; max-width: 100%; padding: 0 6px; }

/* 길게 누르는 동안 분홍색이 아래에서 차오른다. 그냥 기다리게 하면 반응이 없는
   것처럼 느껴져서, 얼마나 남았는지를 색 높이로 보여준다.
   차오르는 시간(0.9s)은 calendar.html의 LONG_PRESS_MS(1000)와 맞춰둔 값이다.
   시트가 뜨기 직전에 칸이 가득 차 보이도록 아주 살짝 짧게 잡았다. */
.day::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 100%;
  background: color-mix(in srgb, var(--primary) 20%, transparent);
  transform: scaleY(0); transform-origin: bottom;
  pointer-events: none;
}
.day.pressing { transform: scale(0.95); }
.day.pressing::after { transform: scaleY(1); transition: transform 0.9s linear; }

.legend {
  display: flex; flex-wrap: wrap; gap: var(--s-sm) var(--s-base); margin: var(--s-lg) 0 0;
  animation: rise var(--t-slow) var(--e-out) both; animation-delay: 0.3s;
}
/* 칩과 이름을 한 덩어리로 묶는다. 따로 두면 좁은 폰에서 "OFF"와 "오프"가
   서로 다른 줄로 갈라져서 범례가 아니라 낱말 목록처럼 보인다. */
.legend-item {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; color: var(--muted); white-space: nowrap;
}

/* 달 넘기기 (‹ 2026년 8월 ›) */
.month-nav { display: flex; align-items: center; gap: var(--s-sm); margin-bottom: var(--s-xs); }
.month-nav .page-title { flex: 1; }
.mnav {
  position: relative; overflow: hidden;
  flex: none; width: 40px; height: 40px; display: flex;
  align-items: center; justify-content: center;
  border: 1px solid var(--hairline); border-radius: var(--r-full);
  color: var(--ink); text-decoration: none; font-size: 20px; line-height: 1;
  transition: background-color var(--t-fast) var(--e-out),
              transform var(--t-base) var(--e-spring),
              border-color var(--t-base) var(--e-out);
}
.mnav:hover { background: var(--surface-strong); border-color: var(--ink); }
.mnav:active { transform: scale(0.86); transition-duration: var(--t-fast); }
.mnav.off { color: var(--hairline); border-color: var(--hairline-soft); }
.mnav.off:active { transform: none; }

/* 달을 넘길 때 화면이 옆으로 빠지고, 새 달은 반대편에서 들어온다.
   app.js가 방향을 sessionStorage로 넘겨 다음 페이지에서 이어 그린다. */
@keyframes slide-out-left  { to { opacity: 0; transform: translate3d(-24px, 0, 0); } }
@keyframes slide-out-right { to { opacity: 0; transform: translate3d(24px, 0, 0); } }
@keyframes slide-in-left   { from { opacity: 0; transform: translate3d(-28px, 0, 0); } }
@keyframes slide-in-right  { from { opacity: 0; transform: translate3d(28px, 0, 0); } }
body.leaving-next .wrap { animation: slide-out-left 0.2s var(--e-inout) forwards; }
body.leaving-prev .wrap { animation: slide-out-right 0.2s var(--e-inout) forwards; }
/* 들어올 때는 개별 요소의 rise 애니메이션을 끄고 화면 통째로 밀어 넣는다.
   둘이 겹치면 요소마다 따로 놀아서 어수선하다. */
body.entered-next .wrap { animation: slide-in-right var(--t-base) var(--e-out) both; }
body.entered-prev .wrap { animation: slide-in-left var(--t-base) var(--e-out) both; }
body.entered-next .wrap *, body.entered-prev .wrap * { animation: none !important; }

/* ---------- 명단 패널 ---------- */
.roster {
  margin-top: var(--s-lg); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); padding: var(--s-lg);
  animation: rise var(--t-base) var(--e-out) both;
}
.roster h2 { font-size: 20px; font-weight: 700; letter-spacing: -0.4px; margin: 0 0 var(--s-base); }
.roster table { width: 100%; border-collapse: collapse; }
.roster td { padding: var(--s-md) var(--s-xs); border-bottom: 1px solid var(--hairline-soft); font-size: 14px; }
.roster td:last-child { text-align: right; }
.roster tr:last-child td { border-bottom: none; }
.roster tr.me td { font-weight: 700; }
.roster tr.me td:first-child { color: var(--primary); }
/* 26명이 한꺼번에 나타나면 벽처럼 보인다. 위에서부터 차례로 흘러들어오게 한다.
   26줄 x 14ms면 마지막 줄이 0.36초 - 기다린다는 느낌이 들기 직전이다. */
.roster tbody tr { animation: rise var(--t-base) var(--e-out) both;
                   animation-delay: calc(var(--i, 0) * 14ms); }

.empty { text-align: center; color: var(--muted); margin-top: 64px;
         animation: rise var(--t-slow) var(--e-out) both; }

/* ---------- 한 줄 일기 ---------- */
/* 날짜를 눌러 명단을 열면 그 안에 같이 뜬다. 근무를 확인하러 들어온 김에
   한 줄 남기는 흐름이라 별도 화면을 만들지 않았다. */
.diary { margin: var(--s-base) 0 0; }
.diary label {
  display: block; font-size: 13px; font-weight: 600;
  color: var(--muted); margin-bottom: var(--s-sm);
}
.diary-row { display: flex; gap: var(--s-sm); }
.diary input {
  flex: 1; min-width: 0; height: 48px; padding: 0 var(--s-md);
  font-family: var(--font); font-size: 15px; color: var(--ink);
  background: var(--canvas); border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  transition: border-color var(--t-base) var(--e-out), box-shadow var(--t-base) var(--e-out);
}
.diary input:focus {
  outline: none; border-color: var(--ink);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ink) 12%, transparent);
}
.diary input::placeholder { color: var(--muted-soft); }
.diary .saved {
  font-size: 12px; color: var(--muted); min-height: 16px; margin-top: 6px;
  transition: opacity var(--t-base) var(--e-out);
}
.diary .saved:not(:empty) { animation: rise 0.3s var(--e-spring) both; }

/* 일기가 있는 날은 달력에 점을 찍는다 */
.day .dot {
  position: absolute; top: 5px; right: 5px;
  width: 5px; height: 5px; border-radius: var(--r-full); background: var(--primary);
  animation: pop var(--t-base) var(--e-spring) both;
}

/* ---------- 아래에서 올라오는 시트 ---------- */
/* 근무 고치기(날짜 길게 누르기) / 일정 추가가 이걸 공유한다.
   인식이 틀렸을 수 있으니 사용자가 바로잡는 통로. 짧게 누르면 명단이 열리고
   길게(1초) 누르면 이 시트가 뜬다 - 실수로 근무를 바꾸면 실제 결근 위험이라
   일부러 눌러 두어야 열리게 했다. */
.editor {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  background: var(--canvas); border-radius: var(--r-xl) var(--r-xl) 0 0;
  box-shadow: var(--shadow-sheet);
  padding: var(--s-base) var(--s-lg) var(--s-xl);
  /* 아이폰 홈 인디케이터에 버튼이 가리지 않게 */
  padding-bottom: calc(var(--s-xl) + env(safe-area-inset-bottom));
  transform: translate3d(0, 100%, 0);
  transition: transform var(--t-sheet) var(--e-out);
  max-width: 560px; margin: 0 auto;
  /* 내용이 많은 시트(일정 추가)가 작은 폰에서 화면 밖으로 넘치면 '추가' 버튼을
     못 누른다. 시트 안에서 스크롤되게 한다. */
  max-height: 88vh; overflow-y: auto;
  overscroll-behavior: contain;   /* 시트 끝에서 뒤 페이지가 같이 스크롤되지 않게 */
  will-change: transform;
}
.editor.open { transform: translate3d(0, 0, 0); }
/* 손가락으로 끌어내리는 중에는 애니메이션을 끄고 손을 그대로 따라간다 */
.editor.dragging { transition: none; }
.editor h2 { font-size: 19px; font-weight: 700; letter-spacing: -0.4px; margin: 0 0 var(--s-xs); }
.editor .hint { font-size: 13px; color: var(--muted); margin: 0 0 var(--s-base); }
/* 시트가 다 올라온 뒤 안쪽 내용이 한 박자 늦게 따라 올라온다 */
.editor.open > *:not(.sheet-grip) {
  animation: rise 0.4s var(--e-out) both;
  animation-delay: calc(0.1s + var(--i, 0) * 35ms);
}

.code-grid { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--s-sm); }
.code-btn {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; height: 68px; padding: 0 2px; cursor: pointer;
  border: 2px solid transparent; border-radius: var(--r-md);
  font-family: var(--font); font-size: 18px; font-weight: 800; letter-spacing: -0.4px;
  transition: transform var(--t-base) var(--e-spring),
              border-color var(--t-base) var(--e-out),
              box-shadow var(--t-base) var(--e-out);
}
.code-btn:active { transform: scale(0.9); transition-duration: var(--t-fast); }
.code-btn small { font-size: 10px; font-weight: 600; opacity: 0.8; }
.code-btn.current { border-color: var(--ink); }
/* 지금 근무가 뭔지 계속 살짝 숨쉬게 해서 다섯 개 중 어느 게 현재인지 놓치지 않게 */
.code-btn.current::after {
  content: ''; position: absolute; inset: -2px; border-radius: var(--r-md);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--ink) 40%, transparent);
  animation: breathe 2.2s var(--e-inout) infinite;
  pointer-events: none;
}
@keyframes breathe {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--ink) 32%, transparent); }
  50%      { box-shadow: 0 0 0 5px transparent; }
}
.code-btn.c-D { background: var(--d-bg); color: var(--d-fg); }
.code-btn.c-E { background: var(--e-bg); color: var(--e-fg); }
.code-btn.c-N { background: var(--n-bg); color: var(--n-fg); }
.code-btn.c-S { background: var(--s-bg); color: var(--s-fg); }
.code-btn.c-OFF { background: var(--off-bg); color: var(--off-fg); }

.scrim {
  position: fixed; inset: 0; z-index: 55; background: var(--scrim);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  opacity: 0; pointer-events: none;
  transition: opacity var(--t-sheet) var(--e-out);
}
.scrim.open { opacity: 1; pointer-events: auto; }

/* 시트를 끌어내릴 수 있다는 걸 알려주는 손잡이 */
.sheet-grip {
  width: 40px; height: 5px; border-radius: var(--r-full);
  background: var(--hairline); margin: 0 auto var(--s-md);
  transition: background-color var(--t-base) var(--e-out), width var(--t-base) var(--e-spring);
}
.editor.dragging .sheet-grip { background: var(--muted); width: 56px; }

/* ---------- 반응형 ---------- */
@media (max-width: 1128px) {
  .wrap { max-width: 640px; }
}
@media (max-width: 744px) {
  .nav {
    height: 64px; gap: var(--s-xs);
    padding-left: max(var(--s-base), env(safe-area-inset-left));
    padding-right: max(var(--s-base), env(safe-area-inset-right));
  }
  .nav .brand { font-size: 17px; }
  .nav .brand small { font-size: 12px; }
  .nav a, .nav button.linkish { padding: 10px 8px; font-size: 13px; }
  /* 자주 안 쓰는 항목은 ⋯ 시트로 내려간다 (위 .more-btn 주석 참조) */
  .nav-extra { display: none; }
  .more-btn { display: flex; }
  .wrap {
    padding: var(--s-lg) var(--s-base) 48px;
    padding-bottom: calc(48px + env(safe-area-inset-bottom));
  }
  .cal { gap: var(--s-xs); }
  .day { border-radius: var(--r-sm); padding: var(--s-xs); }
  .day .num { font-size: 11px; }
  .chip { min-width: 28px; height: 22px; font-size: 11px; padding: 0 var(--s-xs); }
  .day .chip { padding: 0 3px; }
  .page-title { font-size: 20px; }
  /* 명단은 모바일에서 화면 아래 시트로 올라온다.
     hidden 대신 transform으로 여닫아야 미끄러지듯 올라온다(hidden은 즉시 사라짐). */
  /* z-index는 가림막(55)보다 위여야 한다. 예전엔 50이라 시트가 가림막 아래 깔려서
     어두워지고 blur까지 먹었다 - 정작 읽어야 할 명단이 흐려지는 셈이었다.
     근무 고치기 시트(.editor)와 같은 60으로 맞춘다. 둘이 동시에 열리지는 않는다. */
  .roster.sheet {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
    margin: 0; border: none; border-radius: var(--r-xl) var(--r-xl) 0 0;
    background: var(--canvas); box-shadow: var(--shadow-sheet);
    max-height: 72vh; overflow-y: auto; overscroll-behavior: contain;
    padding-bottom: calc(var(--s-xl) + env(safe-area-inset-bottom));
    animation: none;
    transform: translate3d(0, 100%, 0);
    transition: transform var(--t-sheet) var(--e-out);
    will-change: transform;
  }
  .roster.sheet.open { transform: translate3d(0, 0, 0); }
  .roster.sheet.dragging { transition: none; }
  .roster.sheet.dragging .sheet-grip { background: var(--muted); width: 56px; }
}
@media (min-width: 745px) { .sheet-grip { display: none; } }

/* ---------- 움직임을 줄여달라는 설정 ----------
   아이폰 설정 > 손쉬운 사용 > 동작에서 켤 수 있다. 멀미를 느끼는 사람에게
   위 애니메이션은 그대로 고통이라, 켜져 있으면 전부 즉시 전환으로 떨어뜨린다.
   (요소가 안 보이는 사고가 나면 안 되므로 animation은 끄지 않고 0초로 만든다.) */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .editor, .roster.sheet { transition-duration: 0.01ms !important; }
}
