/* 타이포: 그로테스크 1종(Pretendard), 웨이트 2개(400/800).
   색: 청록 필드 1 + 잉크 1 + 흰 판 1. 그 외 없다.

   **사진은 항상 흰 판 위에 올린다.** 채도 높은 배경이 사진에 닿으면
   피부톤 인지가 흔들린다 — 배경은 사진 옆에 있을 뿐 뒤에 있지 않다.
   "폰 사진 같다"가 나오면 기능이 아니라 톤을 고친다. */

:root {
  --surface: #33c6c6;                    /* 공개 페이지 필드 */
  --plate:  #ffffff;                     /* 사진과 본문이 놓이는 판 */
  --ink:    #101112;                     /* 판 위의 글자 */
  --on-field: #101112;                   /* 필드 위에 직접 놓이는 글자 */
  --paper:  #f6f4f1;                     /* 관리자 화면 — 필드를 쓰지 않는다 */
  --hair:   rgba(16, 17, 18, 0.14);      /* 판 안의 실선 */
  --field-hair: rgba(16, 17, 18, 0.22);  /* 필드 위의 실선 */
  --font: "Pretendard Variable", Pretendard, system-ui, "Apple SD Gothic Neo",
          "Malgun Gothic", sans-serif;
  --gap: clamp(14px, 4vw, 28px);
  --col: 780px;                          /* 1단 본문 */
  --wide: 1120px;                        /* 비대칭·엇갈림이 필요한 절 */
  /* 액자(헤더·푸터)의 최대 폭. 화면이 이보다 좁으면 창 모서리에 붙고,
     넓으면 여기서 멈춘다 — 초광폭 모니터에서 로고·메뉴가 화면 끝으로
     날아가 시야에서 사라지지 않게 한다. 본문 기둥(--wide)보다 한 뼘 넓어
     액자와 본문의 층위가 눈에 남는다. */
  --frame: 1520px;
  /* 기본 이징은 힘이 없다. 들어오는 것은 전부 ease-out 으로 처음이 빠르게 움직인다.
     ease-in 은 쓰지 않는다 — 사용자가 가장 집중해서 보는 첫 순간을 늦추기 때문이다. */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
}

/* 테마는 하나다 — 밝은 청록, 언제나. (2026-08-05 사용자 결정)
   다크 모드 분기(#0d4646 필드)를 두었었지만, OS 설정에 따라 브랜드 색이 달라지는 것을
   원치 않아 걷어냈다. 판은 원래 흰색 고정이었으므로 사진·피부톤에는 변화가 없다.
   `color-scheme: light` 로 브라우저 기본 위젯(날짜 입력 등)도 밝게 고정한다 —
   안 그러면 다크 OS 에서 폼 컨트롤만 검게 떠서 판 위에서 겉돈다. */
:root { color-scheme: light; }

* { box-sizing: border-box; }

/* 스크롤바 자리를 항상 확보한다. 안 하면 짧은 페이지(홈)와 긴 페이지(/info) 사이를
   오갈 때 중앙 기둥과 우측 헤더 항목이 스크롤바 폭만큼 밀려 — 페이지마다 로고·메뉴
   위치가 몇 px 씩 다르게 보였다. */
html { margin: 0; scrollbar-gutter: stable; }
body {
  margin: 0;
  background: var(--paper);       /* 관리자. 공개 페이지는 아래에서 필드로 덮는다 */
  color: var(--ink);
  font-family: var(--font);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
}

img, video { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }
:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; }

/* ---- 공개 페이지 -------------------------------------------------------

   구성 원칙: 같은 레이아웃을 두 번 쓰지 않는다.
   한 폭짜리 프로즈 블록을 여덟 번 반복하면 색이 아무리 좋아도 템플릿으로 읽힌다.
   절마다 자기 형태가 있다 (포털 / 레일 / 비대칭 / 사다리 / 필드조판 / 영수증 / 2단 / 엇갈림 / CTA).

   모서리는 전부 직각 하나로 통일한다. 둥근 버튼과 각진 판을 섞지 않는다.
   글자가 필드 위에 직접 놓이는 곳은 '기준' 절 하나뿐이다.                        */

body.landing { background: var(--surface); color: var(--on-field); }
body.landing main {
  max-width: var(--wide); margin: 0 auto; padding: 0 var(--gap);
}
body.landing > .site-header, body.landing > .site-footer { color: var(--on-field); }
body.landing section { margin-bottom: clamp(56px, 13vw, 120px); }
/* 홈은 화면을 채우는 포스터다. 히어로를 560px 띠에 가두면 큰 화면(1080p)에서
   내용이 위로 몰리고 아래 절반이 죽은 공간이 되며, © 가 바닥이 아니라 화면
   중간에 뜬다 — 실제로 그렇게 보였다. 헤더~푸터 사이에 히어로를 정중앙 배치하고
   푸터를 진짜 바닥에 붙인다. */
body.home { min-height: 100dvh; display: flex; flex-direction: column; }
/* flex 아이템의 auto 마진은 stretch 를 풀어 내용 폭으로 쪼그라뜨린다 (page--empty 와 동일) */
body.home > * { width: 100%; }
body.home main { flex: 1 0 auto; display: grid; align-content: center; }
body.home section { margin-bottom: 0; }
body.home .portal { min-height: 0; }   /* 세로 중앙은 main 이 맡는다 */

/* --- 상단 바 -----------------------------------------------------------
   최소한으로. 목차는 랜딩의 포털이 갖는다. 한 줄을 넘지 않는다. */
.site-header {
  display: flex; align-items: center; justify-content: flex-end; gap: var(--gap);
  /* 상하 여백을 좌우와 따로 잡는다. 좌우 여백을 그대로 주면
     헤더가 100px 을 넘어 화면의 1할을 먹는다. */
  padding: clamp(10px, 2vw, 16px) var(--gap);
  /* 화면 크기에 반응하는 액자: --frame 까지는 창 모서리, 그 위로는 고정 폭 중앙.
     본문 기둥(1120px)에 그대로 넣으면 로고가 가운데쯤 떠 보이고,
     무한정 모서리로 보내면 초광폭에서 시야 밖으로 사라진다. 둘 다 겪었다. */
  max-width: var(--frame); margin: 0 auto;
}
.wordmark { display: flex; align-items: center; gap: 0.55em; margin-right: auto; }
.wordmark-lines {
  /* 홈 포털과 같은 비율 — 표식 잉크가 3줄 묶음보다 살짝 크다 (표식 ≈ 글자크기 × 3.07). */
  display: grid; gap: 0; line-height: 1.05; letter-spacing: 0.06em;
  font-weight: 800; font-size: 0.58rem;
}
.wordmark-lines span { display: block; }
/* 홈은 화면 가운데에 큰 워드마크가 이미 있다. 같은 이름을 두 번 쓰지 않는다. */
body.home .wordmark-lines { display: none; }
/* 표식은 어디에 놓이든 자기가 놓인 자리의 글자 크기를 따른다.
   viewBox 만 있는 인라인 SVG 라서 크기를 반드시 여기서 준다 (안 주면 화면을 덮는다). */
.mark-svg { width: 20px; height: 20px; display: block; flex: 0 0 auto; }
/* 헤더는 표식만 선다. 글자 정렬선이 사라졌으니 크기만 잡으면 된다.
   좌우 음수 마진은 SVG 안 가로 여백을 상쇄해 잉크가 액자 모서리에 서게 한다. */
.site-header .wordmark .mark-svg {
  width: 34px; height: 34px;
  margin-left: -0.16em; margin-right: -0.16em;
}
@media (max-width: 640px) {
  .site-header .wordmark .mark-svg { width: 24px; height: 24px; }
  .wordmark-lines { font-size: 0.5rem; }
}
/*
  헤더의 두 항목은 성격이 다르다 — 설정과 행동.
  크기는 같게 두고, 구분은 **밑줄과 농도**가 한다:
  문의는 굵은 밑줄을 달고 온전한 농도로, 언어는 선택되지 않은 쪽이 물러난다.
  행동은 모서리에 선다 — 마우스를 던져도 닿는 자리라 누르는 것을 거기 둔다.
*/
.header-inquiry {
  font-weight: 800; font-size: 0.82rem; letter-spacing: 0.02em;
  /* 밑줄을 평소에는 달지 않는다. 밑줄이 있으면 같은 크기여도 KR/EN 보다 커 보인다.
     대신 손이 닿을 때 나타난다 — 링크라는 사실은 그때 말해주면 된다. */
  display: inline-block;
  transition: transform 160ms var(--ease-out), text-decoration-color 160ms var(--ease-out);
  text-decoration: underline; text-decoration-color: transparent;
  text-underline-offset: 0.3em; text-decoration-thickness: 2px;
}
@media (hover: hover) and (pointer: fine) {
  .header-inquiry:hover { text-decoration-color: currentColor; }
}
/* 눌리는 것은 눌린 티가 나야 한다. 화면이 손을 듣고 있다는 신호다. */
.header-inquiry:active { transform: scale(0.96); }

.lang-toggle {
  display: flex; gap: 0.3em; font-weight: 800; font-size: 0.82rem;
  margin-right: -0.4em;      /* 문의와 한 덩어리로 붙인다 */
}
/* 손가락은 글자 크기가 아니라 면적을 누른다. 보이는 크기는 그대로 두고
   누를 수 있는 면적만 넓힌다 (여백은 음수 마진으로 되돌려 레이아웃을 안 민다). */
.lang-toggle a, .header-inquiry {
  padding: 0.95em 0.55em; margin: -0.95em -0.55em;
}
.lang-toggle a { opacity: 0.5; transition: opacity 160ms var(--ease-out); }
.lang-toggle a[aria-current] { opacity: 1; }
@media (hover: hover) and (pointer: fine) { .lang-toggle a:hover { opacity: 1; } }

/* --- 판 ----------------------------------------------------------------
   사진은 반드시 이 안에 있다. 판은 언제나 흰색이다 (다크 모드에서도).
   전시장의 벽은 어두워져도 인화지는 그대로다. 피부톤이 기준이라 이건 안 바꾼다. */
.plate {
  display: block; background: var(--plate); color: var(--ink);
  padding: clamp(14px, 3.4vw, 26px);
}
.plate img { width: 100%; }
.plate--hero { margin: 0 0 clamp(56px, 13vw, 120px); padding: clamp(10px, 2.4vw, 18px); }

/* --- 진입: 전면 스택 타이포 -------------------------------------------
   히어로는 첫 화면 안에서 끝난다. 목차가 접히면 그건 목차가 아니다.
   100dvh 를 쓴다 (100vh 는 iOS 주소창 때문에 튄다). */
.portal {
  display: grid; align-content: center; justify-items: center;
  min-height: min(68dvh, 560px); text-align: center;
  padding: clamp(16px, 5vw, 44px) 0 clamp(20px, 5vw, 44px);
}
/* 표식은 기둥 왼쪽에 걸리고, 글자는 한 줄에서 시작해 한 줄로 끝난다. */
.portal-block {
  display: flex; align-items: flex-start; gap: clamp(12px, 3vw, 24px);
  width: max-content; max-width: 100%; text-align: left;
}
.portal-stack { display: grid; gap: clamp(24px, 6vw, 44px); }
.portal-mark { display: block; flex: 0 0 auto; }
.portal-mark .mark-svg {
  /* 헤더와 같은 계산, line-height 0.92 기준: 높이 3.073em · translateY −0.157em.
     좌우 음수 마진은 viewBox 가로 여백 상쇄 — 잉크가 정렬선에 선다. */
  width: 3.073em; height: 3.073em;
  font-size: var(--portal-size);
  transform: translateY(-0.157em);
  margin-left: -0.423em; margin-right: -0.423em;
}

.wordmark-big {
  display: grid; gap: 0; margin: 0;
  font-size: var(--portal-size); font-weight: 800;
  line-height: 0.92; letter-spacing: -0.03em;
}

/*
  이름과 목차는 **같은 크기**다.
  굵기와 색이 같으니 크기까지 벌리면 위계가 아니라 고함이 된다.
  구분은 표식(이름 옆에만)·대문자(이름만)·간격(한 칸)이 한다.
*/
:root { --portal-size: clamp(1.25rem, 5.2vw, 2.2rem); }

.portal-nav {
  display: grid; gap: 0.12em; justify-items: start;
  font-size: var(--portal-size);
}
.portal-nav a {
  font-weight: 800; letter-spacing: -0.03em; line-height: 1.05;
  padding: 0.16em 0; /* 누를 면적. 밑줄 위치는 ::after 가 따로 잡는다 */
  /* 목차는 순서를 갖는다. 한 칸씩 들어오면서 그 사실을 형태로 말한다. */
  opacity: 0; transform: translateY(10px);
  animation: rise 520ms var(--ease-out) forwards;
  animation-delay: calc(var(--i, 0) * 120ms + 80ms);
}
@keyframes rise { to { opacity: 1; transform: none; } }

/* 밑줄이 왼쪽에서 자란다. 색을 바꾸는 것보다 방향이 있는 편이 손끝에 붙는다. */
.portal-nav a { position: relative; }
.portal-nav a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -0.12em; height: 2px;
  background: currentColor; transform: scaleX(0); transform-origin: left;
  transition: transform 220ms var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .portal-nav a:hover::after { transform: scaleX(1); }
}

/* --- 인사 --------------------------------------------------------------
   이름과 목차 사이. 사이트 전체에서 한 번뿐이다.
   양옆이 굵은 대문자라 여기만 소문자·400 으로 둔다 — 이 페이지에서 목소리를 낮추는
   유일한 자리이고, 그 낙차가 곧 이 줄의 존재 이유다.

   **모션 순서는 시각 순서와 다르다.** 목차가 먼저 들어오고 인사가 뒤따른다 —
   위에 있다고 먼저 움직이면 사용자가 목차를 기다리게 된다.
   인사는 곁말이라 늦게 도착해도 되지만 목차는 이 화면의 일이다.
   말줄임표가 시킨 대로, 'hello' 다음에 한 박자 쉰다. 반복하지 않는다. */
.hello {
  /* 색을 새로 들이지 않는다 — 잉크의 농도만 낮춰서 목소리를 낮춘다.
     양옆 800 대문자는 온전한 잉크, 여기만 눌러 쓴 잉크다. */
  margin: 0; font-size: clamp(1rem, 3.2vw, 1.35rem); font-weight: 400;
  letter-spacing: -0.01em; color: rgba(16, 17, 18, 0.88);
}
/* 글자 단위 시차. 덩어리 출발 시각(--t)은 마크업이, 글자 간격은 여기가 정한다.
   말은 또렷하게 도착하지 않는다 — 블러가 걷히며 초점이 맞는다. */
.hello .ch {
  display: inline-block; white-space: pre;
  opacity: 0; transform: translateY(6px); filter: blur(1.5px);
  animation: hello-rise 420ms var(--ease-out) forwards;
  animation-delay: calc(var(--t, 0ms) + var(--i, 0) * 55ms);
}
/* 말줄임표는 글자가 아니라 뜸이다 — 한 점씩 느리게 찍힌다. */
.hello-g:nth-child(2) .ch { animation-delay: calc(var(--t, 0ms) + var(--i, 0) * 300ms); }
@keyframes hello-rise { to { opacity: 1; transform: none; filter: blur(0); } }

@media (prefers-reduced-motion: reduce) {
  .hello .ch { opacity: 1; transform: none; filter: none; }
}

/* --- 레일: 가로 스크롤 슬롯 -------------------------------------------
   남은 날짜를 작업물보다 먼저 놓는다. 한정은 연출이 아니라 초과 수주를 안 한다는 증거다.
   숫자를 세게 하지 않는다. 남은 자리는 점, 마감은 취소선. */
.rail {
  display: flex; gap: clamp(18px, 5vw, 40px);
  overflow-x: auto; scroll-snap-type: x proximity;
  padding: clamp(14px, 3vw, 20px) 0;
  border-top: 1px solid var(--field-hair); border-bottom: 1px solid var(--field-hair);
  font-size: 0.82rem; font-weight: 800; letter-spacing: 0.02em;
  scrollbar-width: none;
  transition: opacity 420ms var(--ease-out);
}
.js-reveal .rail { opacity: 0; }
.rail::-webkit-scrollbar { display: none; }
.js-reveal .rail.is-in { opacity: 1; }
.rail:empty { display: none; }
.rail .slot {
  display: grid; grid-template-rows: 1.2em auto auto; gap: 0.35em;
  justify-items: center; scroll-snap-align: start; flex: 0 0 auto;
}
.slot-year { font-size: 0.72rem; opacity: 0.7; }
.slot-year:empty { visibility: hidden; }
.slot-month { font-size: 1.15rem; line-height: 1; }
.slot-dots { display: flex; gap: 0.3em; }
.slot-dots .dot { width: 0.5em; height: 0.5em; border-radius: 50%; background: currentColor; }
/* 이미 나간 자리는 테두리만 남는다. 몇 자리 중 몇인지가 한눈에 보인다. */
.slot-dots .dot.is-taken { background: none; box-shadow: inset 0 0 0 1.5px currentColor; opacity: 0.4; }
.slot-closed { font-size: 0.72rem; opacity: 0.72; }
.slot.is-closed .slot-month { opacity: 0.62; text-decoration: line-through; }

/* --- 장(章) ------------------------------------------------------------
   포털 목차 세 항목이 그대로 본문의 뼈대가 된다. 제목은 목차와 같은 표기로 둔다. */
body.landing .chapter { margin-bottom: clamp(72px, 16vw, 144px); scroll-margin-top: 24px; }
.chapter-title {
  margin: 0 0 clamp(24px, 5vw, 40px);
  font-size: clamp(1.6rem, 5.5vw, 2.4rem); font-weight: 800; letter-spacing: -0.02em;
}
body.landing .chapter section:last-child { margin-bottom: 0; }

/* --- 작가: 비대칭 오프셋 ----------------------------------------------
   초상이 왼쪽으로 물러나고 글이 오른쪽에서 겹쳐 들어온다.
   모바일에서는 겹침을 풀고 한 단으로 세운다 (겹친 채로 좁아지면 글이 사진을 먹는다). */
.split { display: grid; gap: var(--gap); }
.split-text .prose { max-width: 62ch; }
@media (min-width: 860px) {
  .split { grid-template-columns: 6fr 7fr; align-items: start; gap: 0; }
  .split-asset { grid-column: 1; padding-top: clamp(24px, 4vw, 56px); }
  .split-text {
    grid-column: 2; margin-left: clamp(-72px, -5vw, -24px);
    z-index: 1;   /* 판이 겹치는 유일한 곳. 그래서 여기에만 z-index 를 쓴다 */
  }
  /* 초상이 아직 없을 때. 겹칠 상대가 없으면 겹치지 않는다. */
  .split--solo { grid-template-columns: minmax(0, 62ch); }
  .split--solo .split-text { grid-column: 1; margin-left: 0; }
}

/* --- 판의 폭과 자리 ----------------------------------------------------
   판을 전부 같은 폭으로 두면 흰 직사각형이 줄지어 서고, 색이 아무리 좋아도 템플릿으로 읽힌다.
   글 길이에 맞는 폭을 주고 자리를 어긋나게 둔다. 여백이 구성의 일부가 된다. */
@media (min-width: 860px) {
  .ladder  { max-width: 46rem; margin-left: 8%; }
  #faq     { max-width: 40rem; }
  .receipt { max-width: 34rem; margin-left: auto; }   /* 영수증은 좁아야 영수증이다 */
  .duo     { max-width: none; }                        /* 2단은 넓은 폭을 그대로 쓴다 */
  .bare    { padding-left: 4%; }

  /* Das PRODUKT 는 제목과 영수증이 **같은 줄에서 시작한다.**
     제목만 왼쪽 위에 두고 영수증을 오른쪽 아래에 떨어뜨리면 둘이 대각선으로 멀어져
     관계가 안 읽히고, 왼쪽 절반이 그냥 빈 자리가 된다. 비대칭은 남기되 축을 맞춘다. */
  body.produkt main {
    display: grid;
    grid-template-columns: minmax(0, 20rem) minmax(0, 34rem);
    column-gap: clamp(32px, 6vw, 88px);
    justify-content: space-between; align-items: start;
  }
  body.produkt .page-head { grid-column: 1; grid-row: 1; }
  /* 좌우 마진만 지운다 — 아래 여백까지 지우면 영수증과 안내 판이 붙는다. */
  body.produkt #tiers {
    grid-column: 2; grid-row: 1 / span 2; max-width: none;
    margin: 0 0 clamp(56px, 13vw, 120px);
  }
  body.produkt #notice, body.produkt .cta { grid-column: 1 / -1; }
}

/* --- 과정: 사다리 ------------------------------------------------------ */
.ladder .prose--steps ol { margin: 0; padding: 0; list-style: none; counter-reset: step; }
/* 그리드를 쓰지 않는다. <li> 안의 맨텍스트가 익명 그리드 아이템이 되어
   열이 하나 더 생기고, 좁은 화면에서 설명이 세로로 찢어진다.
   번호는 절대 위치로 빼고 본문은 그냥 흐르게 둔다. */
.ladder .prose--steps li {
  counter-increment: step; position: relative;
  padding: 0.75em 0 0.75em 2.9em;
}
.ladder .prose--steps li + li { border-top: 1px solid var(--hair); }
.ladder .prose--steps li::before {
  content: counter(step, decimal-leading-zero);
  position: absolute; left: 0; top: 0.75em;
  font-weight: 800; opacity: 0.35; font-variant-numeric: tabular-nums;
}
/* 시드 문구가 <b> 로 단계 이름을 감싼다. 좁으면 이름이 위에, 넓으면 왼쪽에 선다. */
.ladder .prose--steps li b { display: block; font-weight: 800; }
@media (min-width: 620px) {
  .ladder .prose--steps li b {
    display: inline-block; width: 9em; vertical-align: top; padding-right: 0.6em;
  }
}

/* --- 기준: 필드 위 직접 조판 ------------------------------------------
   이 페이지에서 판을 쓰지 않는 유일한 곳. 크게 쓰는 것도 여기 한 번뿐이다.
   두 번 크게 쓰면 아무것도 크지 않다. */
.bare { color: var(--on-field); }
.statement {
  margin: 0 0 clamp(20px, 5vw, 36px);
  font-size: clamp(1.6rem, 6.4vw, 3.1rem);
  font-weight: 800; line-height: 1.14; letter-spacing: -0.03em;
  max-width: 18ch;
}
.bare-foot { display: grid; gap: 1em; align-items: start; }
.bare-foot .prose { max-width: 52ch; }
@media (min-width: 860px) {
  .bare-foot { grid-template-columns: minmax(0, 52ch) max-content; gap: clamp(24px, 5vw, 64px); }
}

/* --- 상품: 영수증 판 ---------------------------------------------------
   가격을 숨기지도, 표로 늘어놓지도 않는다. 한 장이면 끝난다. */
.receipt { display: grid; gap: clamp(18px, 4vw, 28px); }
.receipt-body ul { margin: 0.8em 0 0; padding: 0; list-style: none; }
.receipt-body li { padding: 0.5em 0; border-top: 1px solid var(--hair); }
.receipt-body li b { display: block; font-weight: 800; }
.receipt .price {
  margin: 0.2em 0 0; font-size: clamp(1.5rem, 5vw, 2.1rem);
  font-weight: 800; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
}
.receipt-tiers { border-top: 1px solid var(--hair); padding-top: clamp(14px, 3vw, 20px); }
.receipt-tiers strong { font-weight: 800; }

.disclose summary {
  cursor: pointer; font-weight: 800; font-size: 0.8rem;
  letter-spacing: 0.14em; text-transform: uppercase;
  padding: 0.7em 0; border-top: 1px solid var(--hair); list-style: none;
}
.disclose summary::-webkit-details-marker { display: none; }
.disclose summary::after { content: " +"; opacity: 0.45; }
.disclose[open] summary::after { content: " –"; }
.disclose ul { margin: 0 0 1em; padding-left: 1.1em; }

/* --- 안내: 2단 판 ------------------------------------------------------ */
.duo { display: grid; gap: clamp(20px, 5vw, 44px); }
.duo .prose { max-width: 60ch; }
.duo-aside h4 { margin: 0 0 0.6em; font-size: 0.95rem; font-weight: 800; }
.duo-aside li b { display: block; font-weight: 800; }
@media (min-width: 860px) { .duo { grid-template-columns: 1fr 1fr; } }

/* 빈 상태 판. 두 문장이 1120px 폭에 놓이면 오른쪽이 통째로 빈다. */
.empty-plate { max-width: 38rem; display: grid; gap: clamp(16px, 4vw, 24px); justify-items: start; }
/* 빈 상태. 포트폴리오가 비어 있으면 방문자는 '실적이 없나'로 읽는다.
   그래서 '아직 없음'이 아니라 **의도된 여백**으로 보여야 한다.
   판을 늘리지 않는다 — 판 안이 비면 그건 여백이 아니라 미완성이다.
   대신 페이지가 화면을 채우고, 판은 자기 내용만큼만 차지한다. */
body.page--empty { min-height: 100dvh; display: flex; flex-direction: column; }
body.page--empty main { flex: 1 0 auto; }   /* 푸터가 화면 아래에 붙는다 */
/* flex 아이템에 `margin: 0 auto` 가 걸리면 stretch 가 풀려 **내용 폭으로 쪼그라든다.**
   헤더가 307px 로 줄어 가운데로 몰렸다 (정상 1120px). 폭을 되돌려주면
   max-width + auto 마진이 블록 때와 같게 동작한다. */
body.page--empty > * { width: 100%; }

/* --- 작업: 엇갈린 판 ---------------------------------------------------
   판 폭과 들여쓰기가 세 칸 주기로 바뀐다. 스크롤에 리듬이 생기고,
   같은 크기 카드가 줄지어 선 격자를 피한다. */
.stagger { display: grid; gap: clamp(28px, 7vw, 72px); }
.plate--work .cap { display: grid; gap: 0.15em; padding: 0.9em 0.2em 0.2em; }
.plate--work .cap b { font-weight: 800; letter-spacing: -0.01em; }
.plate--work .cap i { font-style: normal; opacity: 0.55; font-size: 0.88rem; }
.plate--work img { transition: opacity 260ms var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .plate--work:hover img { opacity: 0.88; }
}
@media (min-width: 860px) {
  .stagger .plate--work { width: 82%; }
  .stagger .plate--work[style*="--i:1"] { width: 62%; margin-left: auto; }
  .stagger .plate--work[style*="--i:2"] { width: 72%; margin-left: 14%; }
}

/* --- 컨택: 전면 CTA ----------------------------------------------------
   문의는 이 페이지의 유일한 행동이다. 그래서 버튼도 하나뿐이다. */
.cta {
  display: grid; justify-items: center; text-align: center; gap: 0.8em;
  padding: clamp(40px, 10vw, 96px) 0 clamp(24px, 6vw, 48px);
  border-top: 1px solid var(--field-hair); color: var(--on-field);
}
.cta .prose { max-width: 46ch; }

/* --- 공통 활자 --------------------------------------------------------- */
.label {
  margin: 0 0 0.9em; font-size: 0.76rem; font-weight: 800;
  letter-spacing: 0.16em; text-transform: uppercase; opacity: 0.55;
}
.prose { font-size: 0.98rem; line-height: 1.75; max-width: 65ch; }
.prose p { margin: 0 0 1em; }
.prose p:last-child { margin-bottom: 0; }
.prose--small { font-size: 0.86rem; line-height: 1.7; opacity: 0.7; }
.prose--faq dt { font-weight: 800; margin-top: 1.1em; }
.prose--faq dd { margin: 0.2em 0 0; opacity: 0.75; }

/* --- 버튼 -------------------------------------------------------------
   눌렀을 때 살짝 들어간다. 화면이 손을 듣고 있다는 신호는 이거 하나면 충분하다. */
.btn {
  display: inline-block; padding: 0.75em 1.5em;
  border: 2px solid currentColor; font-weight: 800; font-size: 0.85rem;
  letter-spacing: 0.06em; text-transform: uppercase; white-space: nowrap;
  transition: transform 160ms var(--ease-out),
              background-color 200ms ease, color 200ms ease;
}
.btn:active { transform: scale(0.97); }
/* 눌리지 않는 버튼은 눌리지 않게 보여야 한다. 색이 같으면 누르고 나서야 알게 된다. */
.btn:disabled { opacity: 0.3; cursor: default; }
.btn:disabled:active { transform: none; }
.btn--solid { background: var(--ink); color: var(--plate); border-color: var(--ink); }
@media (hover: hover) and (pointer: fine) {
  .btn:hover { background: var(--on-field); color: var(--surface); }
  .btn--solid:hover { background: transparent; color: var(--on-field); border-color: var(--on-field); }
}

/* --- 스크롤 리빌 -------------------------------------------------------
   판이 아래에서 걷히듯 올라온다. 사진은 판 안에 있으므로 판만 움직이면 된다.
   한 번만 일어난다 (되돌아왔을 때 다시 나타나면 효과가 아니라 버그로 읽힌다).
   transform / opacity / clip-path 만 건드린다. 레이아웃을 다시 계산시키지 않는다. */
.js-reveal .reveal {
  opacity: 0; transform: translateY(16px); clip-path: inset(0 0 10% 0);
  transition: opacity 560ms var(--ease-out),
              transform 560ms var(--ease-out),
              clip-path 560ms var(--ease-out);
}
.js-reveal .reveal.is-in { opacity: 1; transform: none; clip-path: inset(0 0 0 0); }

/* 움직임을 원치 않는 사람에게는 아무것도 움직이지 않는다. 대신 전부 보인다.
   (전역 kill 만 두면 리빌 요소가 opacity:0 인 채로 남아 페이지가 비어 보인다.) */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
  .js-reveal .reveal { opacity: 1; transform: none; clip-path: none; }
  .rail { opacity: 1; }
  .portal-nav a { opacity: 1; transform: none; }
}

/* --- 상세 페이지 뼈대 --------------------------------------------------
   Die INFO / Das PRODUKT / Das FOTOBUCH / 문의 / 표준 / 스토리가 같은 틀을 쓴다.
   목차에서 넘어왔을 때 같은 집이라는 감각은 제목 위치와 여백이 만든다. */
.page-head { padding: clamp(24px, 8vw, 72px) 0 clamp(20px, 5vw, 40px); }
.page-title {
  margin: 0; font-size: clamp(1.8rem, 7vw, 3.2rem);
  font-weight: 800; letter-spacing: -0.03em; line-height: 1;
}

/* 페이지 끝에는 다음 목적지가 하나. 막다른 길을 만들지 않는다. */
.page-next {
  display: flex; justify-content: flex-end;
  padding: clamp(32px, 8vw, 72px) 0 clamp(24px, 6vw, 48px);
  border-top: 1px solid var(--field-hair);
}
.page-next a {
  font-size: clamp(1.05rem, 4vw, 1.5rem); font-weight: 800; letter-spacing: -0.01em;
  position: relative;
}
.page-next a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -0.12em; height: 2px;
  background: currentColor; transform: scaleX(0); transform-origin: left;
  transition: transform 220ms var(--ease-out);
}
@media (hover: hover) and (pointer: fine) { .page-next a:hover::after { transform: scaleX(1); } }

/* --- 표준 문서 ---------------------------------------------------------
   문서는 문서처럼 보여야 한다. 이 페이지의 목적이 "지킬 것을 공개한다"이므로
   조판이 곧 신뢰다. 랜딩 본문보다 크고 느슨하게 둔다. */
.doc-portal { padding: clamp(16px, 5vw, 40px) 0 clamp(32px, 8vw, 64px); }
.doc-portal .statement { max-width: 22ch; }
.doc-portal .prose { max-width: 54ch; }
.doc-index {
  display: grid; gap: 0.1em; justify-items: start;
  margin-top: clamp(20px, 5vw, 36px);
  font-size: clamp(1rem, 3.6vw, 1.35rem); font-weight: 800;
}
.doc-index a {
  opacity: 0; transform: translateY(10px);
  animation: rise 520ms var(--ease-out) forwards;
  animation-delay: calc(var(--i, 0) * 60ms + 80ms);
}
.js-reveal .doc-index a { text-decoration: underline; text-underline-offset: 0.22em; }

.doc {
  max-width: 44rem; margin-bottom: clamp(32px, 8vw, 64px);
  padding: clamp(24px, 5vw, 48px);
  scroll-margin-top: 16px;
}
/* 문서 안의 조판. 마크다운이 만드는 태그를 직접 잡는다. */
.doc h1 {
  margin: 0 0 0.6em; font-size: clamp(1.4rem, 5vw, 2rem);
  font-weight: 800; letter-spacing: -0.02em; line-height: 1.15;
}
/* 문서 제목은 판 위에 붙어 따라온다. 두세 화면짜리 문서를 읽는 동안
   '지금 어느 문서인지'가 화면에서 사라지면 안 된다. */
.doc > h1:first-child {
  position: sticky; top: 0; z-index: 1;
  background: var(--plate);
  margin: calc(clamp(20px, 5vw, 40px) * -1) calc(clamp(20px, 5vw, 40px) * -1) 0;
  padding: clamp(20px, 5vw, 40px) clamp(20px, 5vw, 40px) 0.6em;
}
/* 다음 문서로. 판 안에서 마지막에 오는 한 줄이라 위에 선을 하나 둔다. */
.doc-next {
  margin: clamp(24px, 5vw, 40px) 0 0; padding-top: 1em;
  border-top: 1px solid var(--hair); font-weight: 800;
}
.doc-next a { text-decoration: underline; text-underline-offset: 0.24em; }

.doc h2 {
  margin: 2.2em 0 0.7em; padding-top: 0.9em; border-top: 1px solid var(--hair);
  font-size: 1.05rem; font-weight: 800; letter-spacing: -0.01em;
}
.doc h3, .doc h4 { margin: 1.6em 0 0.5em; font-size: 0.95rem; font-weight: 800; }
.doc p, .doc li { font-size: 0.96rem; line-height: 1.8; }
.doc p { margin: 0 0 1em; max-width: 62ch; }
.doc ul, .doc ol { margin: 0 0 1.2em; padding-left: 1.2em; max-width: 62ch; }
.doc li { margin-bottom: 0.4em; }
.doc strong { font-weight: 800; }
.doc code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.86em; background: rgba(16, 17, 18, 0.06); padding: 0.1em 0.35em;
}
/* 서두의 인용은 문서의 성격을 말한다. 본문보다 물러나되 읽히긴 해야 한다. */
.doc blockquote {
  margin: 0 0 1.6em; padding-left: 1em; border-left: 2px solid var(--hair);
  font-size: 0.88rem; line-height: 1.7; opacity: 0.72; max-width: 58ch;
}
.doc blockquote p:last-child { margin-bottom: 0; }
/* 표는 계약 조건이 들어가는 자리다. 읽다가 줄을 놓치면 안 된다. */
.doc table { margin: 0 0 1.4em; font-size: 0.92rem; }
.doc th, .doc td { padding: 0.55em 0.9em 0.55em 0; border-bottom: 1px solid var(--hair); }
.doc th { font-weight: 800; text-align: left; }
.doc table { display: block; overflow-x: auto; }

/* --- 문의 폼 -----------------------------------------------------------
   폼은 판 위에 올린다. 채도 높은 필드 위에서는 입력칸의 대비를 맞출 수 없다.
   라벨은 입력칸 위에. placeholder 를 라벨로 쓰지 않는다 — 입력을 시작하면 사라진다. */
.inquiry-form { display: grid; gap: clamp(20px, 5vw, 32px); }
.field-group { display: grid; gap: 1.45rem; }
/* 16개 필드가 한 줄로 흐르면 '길다'는 인상만 남는다. 묶고 이름을 붙이면
   같은 개수여도 네 덩어리로 읽힌다. 라벨을 늘리는 것이 아니라 덩어리를 만드는 일이다. */
.field-title {
  margin: 0; font-size: 0.72rem; font-weight: 800; letter-spacing: 0.14em;
  text-transform: uppercase; opacity: 0.45;
  padding-bottom: 0.5rem; border-bottom: 1px solid var(--hair);
}
.field-group + .field-group { margin-top: clamp(4px, 1vw, 10px); }
/* 짝인 값은 나란히 둔다 (예식일·시간, 도시·국가). 폼이 두 줄 짧아지고 관계도 드러난다. */
.field-pair { display: grid; gap: 1.45rem; }
@media (min-width: 560px) { .field-pair { grid-template-columns: 1fr 1fr; } }
/* 라벨은 자기 입력칸에 붙어 있어야 한다. 사이가 벌어지면 그 틈이 '빈 줄'로 읽혀
   칸이 비어 보이고, 어느 라벨이 어느 칸의 것인지도 흐려진다. */
.inquiry-form label { display: grid; gap: 0.1rem; font-size: 0.82rem; }
.inquiry-form input, .inquiry-form textarea, .inquiry-form select {
  font: inherit; font-size: 1rem; color: var(--ink);
  /* 위는 좁게, 아래는 넓게. 밑줄이 라벨에서 멀면 그 사이가 '빈 줄'로 읽혀
     칸이 비어 보인다. 가까운 것은 붙이고 먼 것은 뗀다. */
  padding: 0.15rem 0 0.5rem; background: none;
  border: 0; border-bottom: 1.5px solid var(--hair);
  transition: border-color 180ms var(--ease-out);
}
.inquiry-form input:focus, .inquiry-form textarea:focus, .inquiry-form select:focus {
  outline: none; border-bottom-color: var(--ink);
}
.inquiry-form textarea { resize: vertical; }
.inquiry-form label.error input { border-bottom-color: #c0281f; }

.inquiry-form .options { margin: 0; padding: 0; border: 0; }
.inquiry-form .options legend { padding: 0 0 0.6rem; font-size: 0.82rem; }
.inquiry-form .check {
  display: flex; align-items: flex-start; gap: 0.55rem;
  font-size: 0.92rem; line-height: 1.5; padding: 0.3rem 0;
}
.inquiry-form .check input { width: 1rem; height: 1rem; margin-top: 0.2rem; flex: 0 0 auto; }
/* 동의는 예약의 필수 조건이다. 옵션 체크와 같은 무게로 보이면 안 된다. */
.inquiry-form .consent {
  padding: 0.9rem 0 0; border-top: 1px solid var(--hair); font-weight: 800;
}
.inquiry-form button { justify-self: start; cursor: pointer; border-width: 2px; }
.inquiry-form .error { color: #c0281f; font-weight: 800; font-size: 0.9rem; }

/* --- 가까운 예약 가능일 ------------------------------------------------
   한도가 하루 단위라 '남은 달'이 아니라 열려 있는 날짜를 낸다.
   누르면 폼의 예식일이 채워진다. 달력을 뒤지게 만들지 않는다. */
/* 레일은 한 줄이다. 폰에서 줄바꿈되면 레일이 아니라 목록이 되고,
   '가까운 며칠'이라는 인상이 '빼곡한 달력'으로 바뀐다. 넘치면 옆으로 민다. */
/* --- 문의: 케어라벨 -----------------------------------------------------
   마르지엘라 라인 넘버. 0-23 격자에서 번호가 서비스의 이름표다.
   흰 라벨 한 장 — 격자 / 범례 / 가능일이 실선으로 나뉜 세 단이다.
   공개 화면은 잉크 단색을 지킨다. 색은 관리자 화면의 일이다. */
/* 이 페이지는 폼 하나다. 그래서 판도 하나다.
   예약(케어라벨)과 연락처가 다른 판에 서면 폭도 정렬도 어긋나 두 개의 떠 있는 카드가 된다.
   제목과 같은 왼쪽 축에 세운다 — 한 기둥이어야 한 장으로 읽힌다. */
.taglabel {
  --plate-pad: clamp(20px, 5vw, 40px);
  display: grid; gap: clamp(16px, 3.5vw, 24px);
  max-width: 40rem; margin: 0;
  padding: var(--plate-pad);
}
/* 예약과 연락처 사이. 판을 나누는 대신 실선 하나가 절을 가른다. */
.taglabel .inquiry-form {
  border-top: 1px solid var(--hair);
  padding-top: clamp(18px, 4vw, 28px);
}
/* 라벨의 첫 줄 — 예식 일시. 아래 모든 예약의 기준(앵커)이라 맨 위에 선다.
   입력은 상자가 아니라 밑줄이다. 라벨에 펜으로 적어 넣듯. */
/* --- 예식일: 라벨의 머리 띠 ---------------------------------------------
   상자를 나누지 않는다. 같은 폭의 흰 판 두 장은 분리가 아니라 조각으로 읽힌다.
   케어라벨은 머리와 몸통이 한 장에 있는 물건이므로, 바탕을 바꿔 층을 만든다.
   띠 전체가 달력을 여는 과녁이다 — 폰에서 손가락이 찾아 헤매지 않는다. */
.wedday {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: 0.3em 1.2em; text-align: left; cursor: pointer;
  /* 판의 안여백을 밀어내고 모서리까지 닿는다. 띠는 판의 일부이지 그 안의 상자가 아니다. */
  margin: calc(var(--plate-pad) * -1) calc(var(--plate-pad) * -1) 0;
  padding: clamp(15px, 3vw, 22px) var(--plate-pad);
  font: inherit; color: var(--ink);
  background: var(--paper); border: none; border-bottom: 1px solid var(--hair);
  transition: box-shadow 160ms var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .wedday:hover { box-shadow: inset 0 0 0 99em rgba(16, 17, 18, 0.028); }
}
.wedday:active { box-shadow: inset 0 0 0 99em rgba(16, 17, 18, 0.055); }
.wedday:focus-visible { outline: 3px solid var(--ink); outline-offset: -3px; }
/* 한글에는 대문자가 없다. 자간과 농도만으로 값과 구분한다. */
.wedday-key { font-size: 0.92rem; font-weight: 800; letter-spacing: 0.02em; opacity: 0.5; }
/* 라벨과 같은 크기다. 위계는 크기가 아니라 농도가 잡는다 —
   라벨은 물러나고(50%) 값은 온전한 잉크로 선다. */
.wedday-val {
  font-size: 0.92rem; font-weight: 800;
  letter-spacing: 0.02em; font-variant-numeric: tabular-nums;
}
/* 고르기 전에는 초대장의 빈 칸처럼 밑줄만 있다. */
.wedday-val:not(.is-set) {
  opacity: 0.42; border-bottom: 2px solid var(--hair); padding-bottom: 0.1em;
}
.wedday-time { font-style: normal; opacity: 0.6; margin-left: 0.5em; }

/* 순서는 흐림으로 강제하지 않는다. 첫 화면이 흐리면 대기가 아니라 고장으로 읽힌다.
   주문은 예식 일시가 정해진 뒤에 존재한다 — 아예 없다가 아래로 펼쳐진다. */
.tag-body { display: grid; gap: clamp(16px, 3.5vw, 24px); }
.taglabel.is-locked .tag-body { display: none; }
.tag-body.is-in { animation: unfold 420ms var(--ease-out); }
@keyframes unfold { from { opacity: 0; transform: translateY(10px); } }
@media (prefers-reduced-motion: reduce) { .tag-body.is-in { animation: none; } }

.tag-grid {
  display: grid; grid-template-columns: repeat(12, 1fr); row-gap: 0.55em;
  text-align: center; font-variant-numeric: tabular-nums;
}
@media (max-width: 560px) { .tag-grid { grid-template-columns: repeat(8, 1fr); } }
.tagno {
  position: relative; display: block; line-height: 1.6;
  font-size: clamp(0.85rem, 2.4vw, 1.05rem);
  color: rgba(16, 17, 18, 0.34); font-weight: 400;
}
.tagno b { font-weight: inherit; }
.tagno.is-live { color: var(--ink); font-weight: 800; cursor: pointer; }
.tagno input { position: absolute; opacity: 0; pointer-events: none; }
/* 고른 번호에 타원이 둘린다 — 라벨에 펜으로 표시하듯. */
.tagno.is-live::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 2em; height: 1.82em;
  transform: translate(-50%, -50%) rotate(-5deg) scale(0.85);
  /* 획도 글자를 따라 줄어야 한다. 2px 로 못박으면 화면이 좁아질수록 링만 두꺼워져
     타원이 옆으로 눌려 보인다. 휴대폰에서 유독 납작해 보이던 것이 이것이다. */
  border: 0.14em solid var(--ink); border-radius: 50%;
  opacity: 0; transition: opacity 160ms var(--ease-out), transform 160ms var(--ease-out);
}
.tagno.is-live:has(input:checked)::after {
  opacity: 1; transform: translate(-50%, -50%) rotate(-5deg) scale(1);
}
.tagno.is-live:has(input:focus-visible) { outline: 3px solid var(--ink); outline-offset: 2px; }
/* 이름이 붙은 격자 — 문의 폼에는 **고를 수 있는 것만** 선다.
   0-23 은 라인 넘버이지 고르는 물건이 아니라서 Die INFO 로 갔다.

   케어라벨의 얼굴은 유지한다: **번호가 위, 이름이 아래.** 세로로 쌓으면 목록이 되고,
   목록은 라벨이 아니다. 종목이 늘면 저절로 접힌다 (`auto-fit`). */
/* 범례의 얼굴 그대로 한 줄에 눕는다: `3 아이폰 스냅  4 2부 스냅  5 야외 스냅`.
   준비 중인 라인도 같이 서서 물러나 있다. 좁으면 접힌다. */
.tag-grid--named {
  display: flex; flex-wrap: wrap; gap: 0.5em 1.6em;
  font-size: 0.85rem; font-weight: 800;
}
/* `.tagno` 는 자기 `clamp` 크기를 갖는다 (0-23 격자에서 화면에 맞춰 커지라고).
   컨테이너에만 크기를 주면 그 clamp 가 이긴다 - 실제로 16.8px 로 커져 있었다.
   범례는 커지지 않는다. 항목에 직접 못박는다. */
.tag-grid--named .tagno {
  padding: 0.15em 0 0.15em 0.1em; line-height: 1.6; white-space: nowrap;
  font-size: 0.85rem; font-weight: 800;
}
.tag-grid--named .tagno b {
  margin-right: 0.45em; opacity: 0.45; font-variant-numeric: tabular-nums;
}
.tag-grid--named .tagno-name { word-break: keep-all; }
.tag-grid--named .tagno.is-off { opacity: 0.38; font-weight: 400; cursor: default; }
/* 타원은 **번호에만** 두른다. 이름까지 감싸면 그건 표시가 아니라 상자다. */
.tag-grid--named .tagno.is-live::after {
  left: 0.45em; width: 1.5em; height: 1.45em;
}

/* 한 줄이 한 종목이다: 켜기 · 이름 · 언제 · 바꾸기.
   켠 곳과 잡는 곳이 같은 줄에 있어야 헷갈리지 않는다. */
.svc-list {
  margin: 0; padding: 0; list-style: none;
  border-top: 1px solid var(--hair);
}
.svc-row {
  display: flex; align-items: center; gap: 0.6em;
  padding: 0.7em 0.1em; border-bottom: 1px solid var(--hair);
  font-size: 0.9rem;
}
.svc-pick {
  display: flex; align-items: center; gap: 0.5em;
  flex: 1 1 auto; min-width: 0; font-weight: 800; cursor: pointer;
}
.svc-row.is-off .svc-pick { cursor: default; opacity: 0.38; font-weight: 400; }
.svc-pick b { opacity: 0.45; font-variant-numeric: tabular-nums; }
.svc-pick input { width: 1.05em; height: 1.05em; accent-color: var(--ink); }
/* 언제인지가 이 줄의 값이다. 없으면 무엇을 해야 하는지 대신 선다. */
.svc-when {
  flex: 0 1 auto; font-size: 0.85em; font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.svc-when.is-ask { opacity: 0.55; }
/* 받을 수 없는 줄. 날짜가 있던 자리에 사정이 대신 선다. */
.svc-when.is-blocked { color: var(--bad, #b3261e); opacity: 1; font-weight: 600; }
.svc-row.is-off .svc-when { opacity: 0.38; }
.svc-edit {
  flex: 0 0 auto; padding: 0.35em 0.7em; font: inherit; font-size: 0.85em;
  background: none; border: 1px solid var(--hair); border-radius: 2px;
  cursor: pointer; color: inherit; white-space: nowrap;
}
.svc-edit:hover, .svc-edit:focus-visible { border-color: var(--ink); }

/* 요약 줄 = 종목 하나의 예약. 눌러서 그 종목만 다시 고른다. */
.sumline {
  display: block; width: 100%; padding: 0.35em 0; text-align: left;
  background: none; border: 0; font: inherit; color: inherit; cursor: pointer;
}
.sumline + .sumline { border-top: 1px solid var(--hair); }
.sumline:hover .sumno, .sumline:focus-visible .sumno { opacity: 1; }

/* 예식장 후보. 입력칸 바로 아래 붙어서, 고르면 사라진다. */
.venue-hits {
  margin: 0 0 clamp(12px, 2.5vw, 18px); padding: 0; list-style: none;
  border: 1px solid var(--hair); border-radius: 2px; background: var(--surface);
  max-height: 15em; overflow-y: auto;
}
.venue-hits li + li { border-top: 1px solid var(--hair); }
.venue-hit {
  display: block; width: 100%; padding: 0.7em 0.8em; text-align: left;
  background: none; border: 0; cursor: pointer; font: inherit; color: inherit;
}
.venue-hit:hover, .venue-hit:focus-visible { background: rgba(16, 17, 18, 0.05); }
.venue-hit b { display: block; font-weight: 800; }
/* 못 찾았을 때. 목록 자리에 그대로 서서 다음에 할 일을 말한다. */
.venue-none { padding: 0.7em 0.8em; font-size: 0.9em; opacity: 0.72; }
/* 그 다음 차례가 된 주소 칸. 선 하나로만 말한다. */
.inquiry-form label.is-next input { border-bottom-color: var(--ink); }
/* 주소는 고르는 근거다. 이름만 같은 곳이 여럿이라 이 줄이 없으면 못 고른다. */
.venue-hit span { display: block; font-size: 0.85em; opacity: 0.62; }

.tag-key {
  margin: 0; padding-top: clamp(12px, 2.5vw, 18px); list-style: none;
  border-top: 1px solid var(--hair);
  display: flex; flex-wrap: wrap; gap: 0.5em 1.6em;
  font-size: 0.85rem; font-weight: 800;
}
.tag-key li { cursor: pointer; }
.tag-key b { margin-right: 0.45em; opacity: 0.45; font-variant-numeric: tabular-nums; }
/* 준비 중인 라인 — 이름은 남되 물러난다. 지운 게 아니라 아직인 것이다. */
.tag-key li.is-off { cursor: default; opacity: 0.38; font-weight: 400; }
/* 예식 일시가 없으면 달을 고를 수 없다. **누를 수 있어 보이면 누른다** —
   그리고 아무 일도 안 일어나면 화면이 고장 난 것으로 보인다. */
.taglabel.is-waiting .tag-months { opacity: 0.34; pointer-events: none; }

/* 라벨의 아랫단 — 앞으로 열두 달. 예식은 1년 앞서 잡히므로 '가까운 날짜'가 아니라
   달이 선다. 남은 주말은 게이지가 말하고, 숫자는 읽게 하지 않는다. */
.tag-months {
  border-top: 1px solid var(--hair); padding-top: clamp(12px, 2.5vw, 18px);
  display: grid; grid-template-columns: repeat(12, 1fr); gap: 2px;
}
@media (max-width: 560px) { .tag-months { grid-template-columns: repeat(6, 1fr); row-gap: 12px; } }
.month-tag {
  display: grid; gap: 0.3em; justify-items: center;
  font: inherit; font-weight: 800; padding: 0.35em 0.2em; cursor: pointer;
  background: none; color: var(--ink); border: 2px solid transparent;
  font-variant-numeric: tabular-nums;
  transition: transform 160ms var(--ease-out), border-color 160ms var(--ease-out);
}
.month-tag:active { transform: scale(0.96); }
.month-tag.on { border-color: var(--ink); }
.month-tag.is-closed { cursor: default; opacity: 0.4; }
/* 멀수록 확정성이 떨어진다 — 다음 해, 그다음 해 순으로 숫자가 물러난다. */
.month-tag.ydist-1 .month-num { opacity: 0.62; }
.month-tag.ydist-2 .month-num { opacity: 0.4; }
.month-tag.is-closed .month-num { text-decoration: line-through; }
.month-year { font-size: 0.62rem; font-weight: 400; opacity: 0.55; min-height: 1em; line-height: 1; }
.month-num { font-size: 1.05rem; line-height: 1; }
.month-meter {
  display: block; width: 2.2em; height: 2px; background: var(--hair);
}
.month-meter i { display: block; height: 100%; background: var(--ink); }
.tag-hint { margin: 0; font-size: 0.78rem; opacity: 0.66; }
.tag-hint.is-error { opacity: 1; color: #b3261e; font-weight: 800; }
/* 고른 것이 라벨의 마지막 줄에 적힌다 — 서비스 · 예식일 · 시간. 비어 있으면 줄도 없다. */
.tag-summary { margin: 0; font-weight: 800; font-size: 0.92rem; font-variant-numeric: tabular-nums; line-height: 2; }
/* 주문서의 번호도 격자에서처럼 타원이 두른다 — 같은 표기, 같은 사물. */
.tag-summary .sumno {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.9em; height: 1.72em; margin-right: 0.45em;
  border: 0.14em solid var(--ink); border-radius: 50%;
  font-style: normal; font-weight: 800; font-size: 0.85em;
  /* 타원의 세로 중심이 글자 엑스하이트 중심에 서야 한다. 깊게 내리면 줄에서 처져 보인다. */
  vertical-align: 0.1em;
}
.tag-summary:empty { display: none; }
.tag-summary:not(:empty) { border-top: 1px solid var(--hair); padding-top: clamp(12px, 2.5vw, 18px); }

/* 달을 누르면 뜨는 작은 달력. 판 위의 잉크 — 라벨과 같은 언어를 쓴다. */
/* .plate 의 display:block 이 dialog 기본 숨김을 덮는다. 닫힌 창은 없는 창이다. */
dialog.daypick:not([open]) { display: none; }
dialog.daypick {
  border: none; margin: auto;
  width: min(22rem, calc(100vw - 32px));
  padding: clamp(20px, 4vw, 28px);
  /* 뒤 판도 흰색이라 윤곽이 없으면 종이 두 장이 붙어 보인다. 그림자가 층을 가른다. */
  box-shadow: 0 24px 64px rgba(16, 17, 18, 0.35);
}
/* 뒤가 물러나야 달력이 선다 — 어둡게 누르고 흐린다. 겹친 숫자들이 읽히지 않게. */
dialog.daypick::backdrop {
  background: rgba(16, 17, 18, 0.55);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
/* 무엇의 일정을 잡는 창인지 먼저 말한다. 그 아래 달이 좌우로 넘어간다. */
.daypick-for {
  margin: 0 0 0.2em; font-weight: 800; font-size: 0.78rem;
  letter-spacing: 0.06em; text-transform: uppercase; opacity: 0.5;
}
.daypick-title {
  display: flex; align-items: center; gap: 0.5em;
  margin: 0 0 0.9em; font-weight: 800; font-variant-numeric: tabular-nums;
}
.daypick-title span { margin-right: auto; }
.daypick-nav {
  font: inherit; font-size: 1.2rem; line-height: 1; color: var(--ink);
  background: none; border: none; cursor: pointer; padding: 0.1em 0.35em;
  transition: transform 160ms var(--ease-out);
}
.daypick-nav:active { transform: scale(0.9); }
.daypick-nav:disabled { opacity: 0.22; cursor: default; }
.daypick-grid {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px;
  text-align: center; font-variant-numeric: tabular-nums;
}
.daypick-grid b { font-size: 0.66rem; font-weight: 400; opacity: 0.5; padding-bottom: 0.5em; }
.daypick-grid button {
  font: inherit; font-weight: 800; font-size: 0.9rem; padding: 0.4em 0;
  background: none; color: var(--ink); border: 2px solid transparent; cursor: pointer;
  transition: border-color 120ms var(--ease-out);
}
.daypick-grid button:disabled { opacity: 0.28; text-decoration: line-through; cursor: default; }
.daypick-grid button.on { border-color: var(--ink); }
.daypick-time {
  display: flex; align-items: center; gap: 0.7em;
  margin: 1.1em 0; font-weight: 800; font-size: 0.85rem;
}
/* 시간은 10분 단위다. 브라우저 기본 다이얼이 1분까지 내려가서 직접 세운 선택기다. */
.timesel { display: inline-flex; align-items: baseline; gap: 0.15em; }
.timesel b { font-weight: 800; opacity: 0.4; }
.timesel select {
  font: inherit; font-weight: 800; color: var(--ink); background: none;
  border: none; border-bottom: 2px solid var(--hair); padding: 0.15em 0.1em;
  font-variant-numeric: tabular-nums; cursor: pointer;
}
.timesel select:focus { outline: none; border-bottom-color: var(--ink); }
.daypick-actions { display: flex; justify-content: flex-end; gap: 0.7em; margin: 0; }
/* 선택이 실리면 창 안에 적힌다 — 창이 열린 채로도 무엇이 담겼는지 보인다. */
.daypick-note {
  margin: 0 0 0.8em; min-height: 1.2em;
  font-weight: 800; font-size: 0.85rem; font-variant-numeric: tabular-nums;
}
.daypick-note.is-error { color: #b3261e; font-variant-numeric: normal; }

/* --- 앨범 -------------------------------------------------------------
   모바일 우선. 그리드 전체가 한 장의 판 위에 놓인다 —
   채도 높은 필드가 사진에 닿으면 피부톤 인지가 흔들린다. */
.album-head { padding: clamp(24px, 8vw, 64px) 0 clamp(16px, 4vw, 28px); }
.album-expiry { margin: 0.6em 0 0; font-size: 0.84rem; font-weight: 800; opacity: 0.75; }

.album-tabs { display: flex; gap: 0.4em; margin: 0 0 var(--gap); }
.album-tabs button {
  font: inherit; font-size: 0.78rem; font-weight: 800;
  letter-spacing: 0.14em; text-transform: uppercase;
  padding: 0.6em 1.1em; cursor: pointer;
  background: none; color: var(--on-field);
  border: 2px solid currentColor; opacity: 0.5;
  transition: opacity 180ms var(--ease-out), transform 160ms var(--ease-out);
}
.album-tabs button.on { opacity: 1; }
.album-tabs button:active { transform: scale(0.97); }

/* 판 안쪽 여백은 사진 사이 간격과 같게 둔다. 액자 여백이 균일해야 판으로 읽힌다. */
.sheet { padding: 4px; margin-bottom: var(--gap); }
.photo-grid {
  display: grid; gap: 4px;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
.photo-grid figure { margin: 0; position: relative; }
.photo-grid img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; }
.photo-grid figure.selected img { outline: 3px solid var(--ink); outline-offset: -3px; }
.photo-grid .heart {
  position: absolute; right: 6px; bottom: 6px;
  border: 0; background: none; cursor: pointer; padding: 4px;
  opacity: 0.45; transition: opacity 180ms var(--ease-out), transform 160ms var(--ease-out);
}
.photo-grid .heart::before {
  content: "♥"; color: #fff; font-size: 1.1rem; line-height: 1;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}
.photo-grid .heart.on { opacity: 1; }
.photo-grid .heart:active { transform: scale(0.9); }

.video-list { display: grid; gap: 4px; }
.video-list video { width: 100%; display: block; }

/* 하객 뷰에는 다운로드 UI 자체가 없다. 서버도 같은 판정을 한다. */
body.guest .album-actions { display: none; }
.album-actions {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-bottom: clamp(40px, 10vw, 80px);
}

/* 크레딧 — 절제해서. 광고처럼 보이면 실패다. */
.credits { max-width: 32rem; }
.credits ul { list-style: none; margin: 0; padding: 0; }
.credits li {
  display: grid; grid-template-columns: 7em 1fr; gap: 0.6em;
  padding: 0.5em 0; font-size: 0.9rem;
}
.credits li + li { border-top: 1px solid var(--hair); }
.credit-role {
  font-size: 0.72rem; font-weight: 800; letter-spacing: 0.1em;
  text-transform: uppercase; opacity: 0.5; padding-top: 0.25em;
}
.credits .own { opacity: 0.55; }
.credits a { text-decoration: underline; text-underline-offset: 0.22em; }

/* --- 스토리 (한 예식 한 페이지) ---------------------------------------
   격자를 쓰지 않는다. 이야기는 세로로 읽히는 것이지 훑는 것이 아니다. */
.story-lede {
  margin: 0 0 clamp(24px, 6vw, 44px); max-width: 46ch;
  font-size: clamp(1.05rem, 3.4vw, 1.3rem); line-height: 1.6;
}
.story-body { display: grid; gap: clamp(16px, 4vw, 32px); }
@media (min-width: 860px) {
  .story-body { max-width: 52rem; margin-left: 6%; }
}

.site-footer {
  max-width: var(--frame); margin: 0 auto; padding: var(--gap);
  display: grid; gap: 0.8em; font-size: 0.8rem;
}
.site-footer p { margin: 0; opacity: 0.72; }

/* ---- 관리자 (/studio) --------------------------------------------------
   장식할 이유는 없지만 **매일 여는 화면**이다. 읽는 데 드는 힘을 줄이는 것까지가
   여기서 하는 일이고, 그 이상은 하지 않는다.

   공개 화면의 청록 필드를 쓰지 않는다. 관리자는 사진을 판단하는 화면이라
   채도 있는 배경이 피부톤 인지를 흔든다. 종이색 위에 흰 판, 잉크. 그게 전부다. */

/* 관리자도 랜딩과 같은 언어를 쓴다 — 청록 필드 위에 흰 판.
   같은 토큰(`--surface` / `--plate` / `--on-field`)을 그대로 쓰므로 라이트·다크
   양쪽이 자동으로 따라온다.

   **예외는 사진을 판단하는 화면이다** (셀렉 · 검수 · 블라인드 · 사진 그리드).
   채도 높은 배경이 사진에 닿으면 피부톤 인지가 흔들린다. 그 화면들은 판을 넓게 깔아
   사진 주변을 중성으로 유지하고, 필드는 가장자리에만 남는다. 브랜드보다 이쪽이 먼저다. */
body.studio { background: var(--surface); color: var(--on-field); min-height: 100dvh; }
.studio-main { padding: 16px; max-width: 1400px; }
@media (min-width: 700px) { .studio-main { padding: 28px 24px 64px; } }
/* 로그인만 예외 — 문(門)은 화면 가운데에 놓인다. */
body.studio-door .studio-main { padding: 0; max-width: none; }

.studio-header {
  display: flex; gap: 0.2em; padding: 4px 8px; overflow-x: auto;
  border-bottom: 1px solid var(--field-hair); position: sticky; top: 0; z-index: 5;
  background: var(--surface); scrollbar-width: none;
}
.studio-header::-webkit-scrollbar { display: none; }
/* 헤더는 언제나 필드 위다. `body.studio ... a` 계열보다 특이성이 높아야 한다 —
   낮으면 사진 판단 화면(글자색이 잉크)에서 청록 위에 잉크가 얹혀 안 읽힌다.
   실제로 그렇게 됐다 (대비 1.78). */
body.studio .studio-header a {
  white-space: nowrap; padding: 12px 10px;      /* 폰에서 누를 수 있는 크기 */
  font-size: 0.85rem; text-decoration: none; color: var(--on-field); opacity: 0.62;
  border-bottom: 2px solid transparent;
}
body.studio .studio-header a:hover { opacity: 1; }
/* 지금 어디에 있는지 표시한다. 없으면 매번 주소창을 본다. */
body.studio .studio-header a[aria-current="page"] {
  opacity: 1; font-weight: 800; border-bottom-color: var(--on-field);
}
/* 매일 여는 것과 가끔 여는 것을 가른다. 열한 개가 같은 무게로 놓이면
   자주 쓰는 다섯 개를 찾는 데 매번 눈이 열한 개를 훑는다. */
.studio-header .nav-sep {
  align-self: center; width: 1px; height: 16px; margin: 0 8px;
  background: var(--on-field); opacity: 0.2; flex: 0 0 auto;
}
body.studio .studio-header .nav-rare { opacity: 0.42; }
body.studio .studio-header .nav-rare:hover,
body.studio .studio-header .nav-rare[aria-current="page"] { opacity: 1; }
.studio-out { margin-left: auto; }

/* --- 인박스 -------------------------------------------------------------
   첫 화면은 '지금 할 일'이다. 숫자가 0인 줄은 물러나고 1 이상만 앞으로 나온다.
   다섯 줄이 같은 무게로 놓이면 매일 다섯 줄을 다 읽게 된다. */
/* --- 화면의 머리 ---------------------------------------------------------
   **모든 관리 화면이 같은 머리를 쓴다.** 화면마다 제목을 새로 만들면 열한 개 화면이
   열한 개 언어가 되고, 그러면 사람은 매번 "여기는 어떻게 읽는 곳인가"부터 다시 배운다.

   제목 한 줄, 그 아래 지금 상태 한 줄, 오른쪽에 그 화면의 주된 동작 하나.
   판 위가 아니라 필드 위에 놓인다 — 부르는 말은 필드 위에, 읽을 것은 판 위에. */
.st-head {
  display: flex; align-items: flex-end; flex-wrap: wrap; gap: 8px 20px;
  margin: 4px 0 20px;
}
.st-head h1 {
  margin: 0; font-size: clamp(1.5rem, 5vw, 2.1rem); line-height: 1.1;
  letter-spacing: -0.02em;
}
/* 지금 상태. 숫자가 섞이므로 자릿수를 고정한다 — 줄이 흔들리면 훑을 수가 없다. */
.st-sub { margin: 0; font-size: 0.88rem; opacity: 0.6; font-variant-numeric: tabular-nums; }
.st-head .st-sub { padding-bottom: 3px; }
/* 그 화면에서 가장 자주 누르는 것 하나. 여럿이면 아무것도 강조되지 않는다. */
.st-act { margin-left: auto; display: flex; gap: 8px; align-items: center; }
.st-act a { font-size: 0.85rem; text-decoration: underline; text-underline-offset: 0.2em; }

.q {
  display: grid; grid-template-columns: 2.6rem 1fr; gap: 0 14px;
  align-items: start; padding: 16px 0; border-top: 1px solid var(--field-hair);
}
.q-count {
  margin: 0; font-size: 1.5rem; font-weight: 800; line-height: 1.05;
  font-variant-numeric: tabular-nums; text-align: right;
}
.q-body h2 {
  margin: 0 0 2px; font-size: 0.95rem; font-weight: 800; letter-spacing: -0.01em;
  text-transform: none;                          /* 대문자 라벨을 늘리지 않는다 */
}
.q-note { margin: 0; font-size: 0.82rem; opacity: 0.45; }

/* 0 인 큐. 지워버리지 않는다 — 어제 있었는지 오늘 없는지 알아야 한다. */
.q--empty { padding: 10px 0; }
.q--empty .q-count { opacity: 0.22; font-size: 1.1rem; }
.q--empty .q-body h2 { font-weight: 400; opacity: 0.5; font-size: 0.85rem; }

.q ul { list-style: none; padding: 0; margin: 8px 0 0; display: grid; gap: 1px; }
.q li {
  /* 판 위에서는 색을 다시 정한다. 필드 글자색(밝은 크림)을 그대로 상속하면
     흰 판 위에 흰 글자가 된다. 실제로 그렇게 됐다. */
  background: var(--plate); color: var(--ink); padding: 11px 14px;
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  min-height: 44px;                              /* 폰에서 누를 수 있는 크기 */
}
.q li a { color: var(--ink); }
.q-name { font-weight: 800; color: var(--ink); text-decoration: none; }
a.q-name:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.q-meta { font-size: 0.82rem; opacity: 0.55; }
.q-age { margin-left: auto; font-size: 0.82rem; opacity: 0.5; font-variant-numeric: tabular-nums; }
/* 24시간 초과 미응답. 색은 여기 하나에만 쓴다. */
.q li.overdue { box-shadow: inset 3px 0 0 #c0281f; }
.q li.overdue .q-age { color: #c0281f; opacity: 1; font-weight: 800; }
.q li button { font: inherit; font-size: 0.8rem; padding: 6px 12px; margin-left: auto; }

/* --- 필드 위의 관리자 공통 요소 ---------------------------------------
   본문 덩어리는 전부 흰 판 위에 놓는다. 필드 위에 직접 놓는 것은 제목과 라벨뿐이다.
   랜딩과 같은 규칙이다 — 읽을 것은 판 위에, 부르는 말은 필드 위에. */
body.studio h1 { letter-spacing: -0.02em; }
body.studio .muted { opacity: 0.6; }
/* 본문 링크만 주변 색을 따른다. 헤더까지 걸면 필드 위 글자가 잉크로 바뀐다. */
body.studio .studio-main a { color: inherit; }
/* 판 안으로 들어간 글자는 전부 잉크로 되돌린다. 상속으로 두면 대비가 무너진다. */
body.studio .studio-main > section,
body.studio .studio-main > form,
body.studio table { color: var(--ink); }
/* 서비스 번호 태그 — 번호가 이름표, 색이 유형이다. 문의 목록·캘린더 공용. */
.svc {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.6em; height: 1.6em; border-radius: 50%;
  background: var(--svc, #666); color: #fff;
  font-style: normal; font-weight: 800; font-size: 0.78rem; line-height: 1;
  margin-right: 0.35em; vertical-align: middle;
}
/* 가예약(문의)은 아직 확정이 아니다 — 속이 비고 테두리만 색을 갖는다. */
.svc.is-tentative { background: #fff; color: var(--svc, #666); box-shadow: inset 0 0 0 2px var(--svc, #666); }
.cal td.day .svc-row { display: block; margin-top: 2px; }
.cal td.day .svc { width: 1.4em; height: 1.4em; font-size: 0.68rem; margin-right: 2px; }
.cal-legend .svc { margin-left: 0.8em; }
body.studio .studio-main > section a,
body.studio table a { color: var(--ink); }

/* 판. 관리 화면의 섹션 하나가 판 하나다. */
body.studio .studio-main > section,
body.studio .studio-main > form,
body.studio .doc-body {
  background: var(--plate); color: var(--ink);
  padding: clamp(16px, 3vw, 22px); margin-bottom: 14px;
}
body.studio .studio-main > section h2 { margin-top: 0; }
/* 인박스의 큐는 자기 리듬이 있다. 판을 두 번 씌우지 않는다. */
body.studio .studio-main > section.q { background: none; color: inherit; padding: 16px 0; }
body.studio .studio-main > section.q.q--empty { padding: 10px 0; }

body.studio table { background: var(--plate); color: var(--ink); }
body.studio input, body.studio select, body.studio textarea, body.studio button {
  font: inherit; color: var(--ink); background: var(--plate);
  border: 1px solid var(--hair); padding: 8px 10px;
}
body.studio button { cursor: pointer; font-weight: 800; }
body.studio button:hover { background: var(--ink); color: var(--plate); border-color: var(--ink); }
body.studio button:disabled { opacity: 0.4; cursor: default; }
body.studio button:disabled:hover { background: var(--plate); color: var(--ink); }

/* 필드 위에 직접 놓인 경고·안내. 청록 위의 빨강은 읽히지 않는다 (대비 1.8).
   판 위로 올리고 왼쪽에 막대 하나 — 인박스의 미응답 표시와 같은 언어다. */
body.studio .studio-main > .error,
body.studio .studio-main > .bad,
body.studio .studio-main > .hint {
  background: var(--plate); color: var(--ink);
  padding: 12px 14px; margin: 0 0 14px;
  box-shadow: inset 3px 0 0 var(--ink);
}
body.studio .studio-main > .error,
body.studio .studio-main > .bad { box-shadow: inset 3px 0 0 #c0281f; }

/* --- 사진을 판단하는 화면 ---------------------------------------------
   셀렉 · 검수 · 블라인드. 사진 주변이 중성이어야 피부톤을 볼 수 있다.
   판을 화면 끝까지 깔고, 필드는 헤더에만 남긴다. */
body.studio.judging { background: var(--paper); color: var(--ink); }
body.studio.judging .studio-header {
  background: var(--surface); border-bottom-color: var(--field-hair);
}
body.studio.judging .sel-head { border-bottom-color: var(--hair); }
body.studio.judging .studio-main > section { background: none; padding: 0; }

table { width: 100%; border-collapse: collapse; }
td, th { padding: 8px 6px; border-bottom: 1px solid var(--hair); text-align: left; }
/* 표의 머리글은 데이터가 아니다. 물러나 있어야 아래 줄이 먼저 읽힌다. */
body.studio th {
  font-size: 0.76rem; font-weight: 700; letter-spacing: 0.02em;
  opacity: 0.5; white-space: nowrap;
}
body.studio td { vertical-align: top; }
/* 숫자 칸은 오른쪽으로 맞추고 자릿수를 고정한다. 세로로 훑을 수 있어야 표다. */
body.studio td.num, body.studio th.num { text-align: right; font-variant-numeric: tabular-nums; }
body.studio td.when { white-space: nowrap; font-variant-numeric: tabular-nums; }
/* 표가 좁은 화면에서 페이지 전체를 밀지 않게 한다. 관리 화면은 폰에서 돈다. */
.scroll-x { overflow-x: auto; }

/* 빈 상태. **0 은 빈 화면이 아니라 도달한 상태다** — 그렇게 말해야 사람이 안심한다.
   화면마다 다른 말로 비어 있다고 하면, 비었다는 사실보다 화면이 먼저 눈에 띈다. */
.empty-note { margin: 0; padding: 18px 0; opacity: 0.55; font-size: 0.9rem; }

/* 줄의 둘째 줄. 훑을 때는 안 걸리고, 필요하면 거기 있다.
   칸을 늘리는 대신 이걸 쓴다 — 칸이 늘면 폰에서 표가 옆으로 밀리고, 밀린 표는 안 읽힌다. */
.row-sub { display: block; margin-top: 2px; font-size: 0.78rem; opacity: 0.5; }
/* 표 안의 폼은 줄 하나로 눕는다. 세로로 서면 그 줄만 두 배 높아진다. */
body.studio table form { display: inline; }
body.studio table button { font-size: 0.8rem; padding: 4px 10px; }

/* 한 줄에 놓이는 동작들. 첫 번째가 주된 것이고 나머지는 곁이다. */
.actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 14px; }
.actions .ghost { background: none; border: 1px solid var(--hair); font-weight: 400; }

.error { color: #c0281f; }
/* --- 관리자 문(門) -----------------------------------------------------
   /studio 중 외부인이 볼 수 있는 유일한 화면. 여기만 공개 화면과 같은 언어를 쓴다.
   나머지 관리자 화면은 예쁠 이유가 없지만, 문은 브랜드다. */
body.studio.studio-door,
body.studio-door {
  background: var(--surface); color: var(--on-field);
  min-height: 100dvh; display: grid; align-items: center;
}
.door { width: 100%; padding: var(--gap); }
.door-plate {
  background: var(--plate); color: var(--ink);
  max-width: 22rem; margin: 0 auto;
  padding: clamp(28px, 6vw, 44px);
  display: grid; gap: clamp(20px, 4vw, 28px);
}
.door-mark .mark-svg { width: 2.2rem; height: 2.2rem; }
.door-title {
  margin: 0; font-size: 0.78rem; font-weight: 800;
  letter-spacing: 0.22em; opacity: 0.45;
}
.door-form { display: grid; gap: 1.1rem; }
.door-form label { display: grid; gap: 0.4rem; }
.door-form label span { font-size: 0.78rem; opacity: 0.6; }
.door-form input {
  font: inherit; font-size: 1rem; color: var(--ink);
  padding: 0.55rem 0; background: none;
  border: 0; border-bottom: 1.5px solid var(--hair);
  transition: border-color 180ms var(--ease-out);
}
.door-form input:focus { outline: none; border-bottom-color: var(--ink); }
.door-form button { justify-self: start; margin-top: 0.4rem; cursor: pointer; }
.door-form .error { margin: 0; font-size: 0.85rem; font-weight: 800; }

/* 캘린더 — 4상태. 액센트 0 원칙은 고객 접점에만 적용한다.
   관리자는 한눈에 구분되는 것이 우선이다. */

.cal-title { display: flex; align-items: center; gap: 0.6em; }
.cal-count { font-size: 0.8rem; font-weight: 400; opacity: 0.6; margin-left: auto; }
.cal-nav { padding: 0 0.4em; opacity: 0.5; }
.cal-slots { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 0 0 16px; }
.cal-slots input { width: 4rem; font: inherit; }
.cal-remaining.closed { color: #c0281f; font-weight: 600; }

.cal { table-layout: fixed; }
.cal th { font-size: 0.75rem; opacity: 0.5; text-align: center; }
.cal td.day {
  height: 64px; vertical-align: top; text-align: left; cursor: pointer;
  font-size: 0.75rem; line-height: 1.3;
}
.cal td.empty { background: none; cursor: default; }
.cal td.day .num { display: block; font-size: 0.85rem; }
.cal td.day .mark { display: block; opacity: 0.75; word-break: break-all; }
.cal td.day.pending { opacity: 0.4; }
.cal td.day.today .num { text-decoration: underline; }

.cal td.day.open      { background: none; }
.cal td.day.tentative { background: #fdf3d8; }
.cal td.day.blocked   { background: #e4e2de; color: rgba(23,23,26,0.45); cursor: pointer; }
/* 일부예약과 마감을 구분한다. 자리가 남았는지가 한눈에 보여야 한다. */
.cal td.day.partial   { background: #cfd8e8; cursor: default; }
.cal td.day.full      { background: #1f2c47; color: #f6f4f1; cursor: default; }
.cal td.day .cap { float: right; font-size: 0.7rem; opacity: 0.6; font-variant-numeric: tabular-nums; }

.cal-legend { font-size: 0.8rem; opacity: 0.7; margin: 12px 0 28px; }
.swatch {
  display: inline-block; width: 0.8em; height: 0.8em; margin: 0 0.3em 0 1em;
  border: 1px solid var(--hair); vertical-align: -1px;
}
.swatch.open { background: var(--paper); }
.swatch.tentative { background: #fdf3d8; }
.swatch.blocked { background: #e4e2de; }
.swatch.partial { background: #cfd8e8; }
.swatch.full { background: #1f2c47; }

/* 달력 아래 문의 목록. **예약과 섞지 않는다** - 하나는 잡힌 자리이고
   하나는 아직 아무것도 아니다. 색과 무게로 그 차이를 유지한다. */
.cal-inquiries { margin-top: 28px; }
.cal-inquiries h2 small { font-weight: 400; opacity: 0.55; margin-left: 0.5em; }
.q-day { padding: 10px 0; border-bottom: 1px solid var(--field-hair, #ddd); }
.q-day h3 { margin: 0 0 6px; font-size: 0.9rem; opacity: 0.62; }
.q-list { margin: 0; padding: 0; list-style: none; }
.q-list li { display: flex; align-items: center; gap: 0.5em; padding: 4px 0; }
.q-meta { font-size: 0.85em; opacity: 0.6; }
/* 달력 칸의 '문의 n' 은 이제 아래 목록으로 데려가는 과녁이다. */
a.mark { text-decoration: none; }
a.mark:hover, a.mark:focus-visible { text-decoration: underline; }

.cal-bookings .booking {
  display: grid; gap: 8px; max-width: 30rem;
  padding: 12px 0; border-bottom: 1px solid var(--hair);
}
.cal-bookings label { display: grid; gap: 4px; font-size: 0.8rem; opacity: 0.7; }
.cal-bookings label.check { display: flex; gap: 6px; align-items: center; }

.cal-hint { margin: 6px 0 0; font-size: 0.8rem; opacity: 0.6; }
/* 날짜 입력은 브라우저 기본 폭이 좁아 값이 잘린다. 폰에서 한 줄을 다 쓴다. */
.cal-slots input[type="date"] { min-width: 10.5rem; }
.cal-slots { display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: end; }
.cal-slots label { display: grid; gap: 4px; font-size: 0.82rem; }
.cal-bookings input { font: inherit; padding: 6px 0; border: 0; border-bottom: 1px solid var(--hair); background: none; }
.cal-bookings .contact { margin: 0; font-size: 0.8rem; opacity: 0.6; }
.cal-speed { margin-top: 32px; }

/* 문의 상세 — 폰에서 확인 → 회신 → 상태 변경까지 여기서 끝난다. */
.filters { display: flex; flex-wrap: wrap; gap: 0.8em; margin-bottom: 16px; font-size: 0.85rem; }
.filters a { opacity: 0.5; }
.filters a.on { opacity: 1; font-weight: 600; text-decoration: underline; }
.filters .sep { opacity: 0.3; }

tr.overdue td { color: #c0281f; font-weight: 600; }   /* 24시간 초과 미응답 */

.tag { font-size: 0.7rem; opacity: 0.5; vertical-align: middle; }
.ok { color: #1f5c3a; }
.hint { font-size: 0.85rem; opacity: 0.6; }

.detail { margin-bottom: 32px; padding-bottom: 20px; border-bottom: 1px solid var(--hair); }
.detail h2 { font-size: 0.95rem; text-transform: uppercase; letter-spacing: 0.06em; }
.detail dl { display: grid; grid-template-columns: 6.5rem 1fr; gap: 6px 12px; margin: 0; font-size: 0.9rem; }
.detail dt { opacity: 0.5; }
.detail dd { margin: 0; }
.detail .message { white-space: pre-wrap; margin-top: 16px; }
.detail form { display: grid; gap: 8px; max-width: 40rem; margin-bottom: 12px; }
.detail label { display: grid; gap: 4px; font-size: 0.8rem; opacity: 0.7; }
.detail input, .detail textarea, .detail select {
  font: inherit; padding: 6px; border: 1px solid var(--hair); background: #fff; color: inherit;
}
.detail button { justify-self: start; font: inherit; padding: 6px 14px; }
.history { list-style: none; padding: 0; font-size: 0.8rem; opacity: 0.6; }
.history li { padding: 3px 0; }

/* 콘텐츠 관리 — 한/영을 나란히. 비어 있는 쪽이 눈에 띄어야 한다. */
.content-row { display: grid; gap: 8px; border: 0; border-bottom: 1px solid var(--hair);
               padding: 10px 0; margin: 0; max-width: 46rem; }
.content-row legend { font-size: 0.75rem; opacity: 0.5; padding: 0; }
.content-row label, .mail-tpl label { display: grid; gap: 4px; font-size: 0.75rem; opacity: 0.7; }
.content-row textarea, .mail-tpl textarea, .mail-tpl input, .mail-tpl select {
  font: inherit; padding: 6px; border: 1px solid var(--hair); background: #fff; color: inherit;
}
.content-row.incomplete legend { color: #c0281f; opacity: 1; }

/* 문구 묶음. 접힌 상태가 기본이라 목록이 한 화면에 들어온다. */
.content-group { border-bottom: 1px solid var(--hair); }
.content-group summary {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 14px 2px; cursor: pointer; font-weight: 800;
  list-style: none;                     /* 기본 삼각형 대신 아래 표식을 쓴다 */
}
.content-group summary::-webkit-details-marker { display: none; }
.content-group summary::before {
  content: "+"; font-weight: 400; width: 1em; opacity: 0.5;
}
.content-group[open] > summary::before { content: "−"; }
.content-group[open] > summary { border-bottom: 1px solid var(--hair); }
.content-count { font-weight: 400; opacity: 0.45; font-variant-numeric: tabular-nums; }
/* 비어 있는 칸이 있으면 눈에 걸리게 둔다. 접혀 있어도 이 줄은 보인다. */
.content-missing { margin-left: auto; font-size: 0.8rem; font-weight: 800; color: #c0281f; }
.mail-tpl { display: grid; gap: 8px; max-width: 46rem; padding: 10px 0;
            border-bottom: 1px solid var(--hair); }
.mail-tpl.incomplete { background: #fdf3d8; }
.mail-tpl button { justify-self: start; font: inherit; padding: 6px 14px; }

/* --- E1 셀렉 -----------------------------------------------------------
   마우스 없이 끝나는 화면. 한 번에 한 그룹만 보이고, 손은 키보드에 있다.
   관리자 화면이라 예쁠 이유는 없지만 **빠를 이유는 있다** — 1000장을 30분에 넘긴다. */
/* 사진을 판단하는 화면(셀렉·검수·블라인드)의 머리. 사진이 주인공이라 머리는 낮게 깐다. */
.sel-head {
  display: flex; align-items: center; flex-wrap: wrap; gap: 12px 20px;
  padding-bottom: 12px; border-bottom: 1px solid var(--hair); margin-bottom: 12px;
}
.sel-head h1 { margin: 0; font-size: 1.1rem; }
.sel-head form { margin: 0; }
.sel-head a { margin-left: auto; text-decoration: underline; font-size: 0.85rem; }
.sel-progress { margin: 0; font-size: 0.9rem; font-variant-numeric: tabular-nums; }
.sel-progress b { font-size: 1.1rem; }
.sel-progress.bad { color: #c0281f; }   /* 저장이 실패해 화면을 되돌렸다 */

/* 단축키는 화면에 둔다. 외우기 전까지 필요하고, 외운 뒤에는 눈에 안 들어온다. */
.sel-keys { margin: 0 0 16px; font-size: 0.8rem; opacity: 0.6; }
.sel-keys b {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  background: rgba(16, 17, 18, 0.08); padding: 0.1em 0.4em;
}

/* 한 번에 한 그룹. 스크롤로 훑는 화면이 아니라 넘기는 화면이다. */
.sel-group { display: none; }
.sel-group.on { display: block; }
.sel-count { margin: 0 0 8px; font-size: 0.8rem; opacity: 0.55; font-variant-numeric: tabular-nums; }

/* 유사컷은 가로로 늘어놓는다. 같은 순간을 나란히 봐야 고를 수 있다. */
.sel-strip {
  display: flex; gap: 8px; overflow-x: auto; padding-bottom: 8px;
  scroll-snap-type: x proximity;
}
.sel-cut {
  margin: 0; position: relative; flex: 0 0 auto; scroll-snap-align: start;
  width: min(52vw, 420px); background: #e9e7e4;
}
.sel-cut img { width: 100%; aspect-ratio: 3 / 2; object-fit: contain; background: #e9e7e4; }
/* 지금 보고 있는 컷. 굵은 테두리 하나로 표시한다 — 색을 늘리지 않는다. */
.sel-cut.on { outline: 3px solid var(--ink); outline-offset: -3px; }
.sel-cut.is-picked img { opacity: 1; }
.sel-cut.is-rejected img { opacity: 0.28; }   /* 버린 것도 남는다. 지우지 않는다 */
/* 취향에서 뺀 컷은 덜 죽인다. 기술 실패는 다시 볼 일이 없지만 이쪽은 나중에
   되돌아볼 판단이고, 무엇보다 **둘이 같아 보이면 잘못 누른 것을 알 수 없다.** */
.sel-cut.why-taste img { opacity: 0.52; }

.sel-cut figcaption {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; justify-content: space-between; align-items: center;
  padding: 4px 8px; font-size: 0.8rem; font-weight: 800;
  color: #fff; background: rgba(16, 17, 18, 0.55);
}
.sel-cut figcaption:empty { display: none; }
.sel-stage { margin-bottom: 24px; }

/* 승격 그리드 — 관리 화면에서도 썸네일만 본다. 원본은 내려보내지 않는다. */
.promote-grid { display: grid; gap: 10px; margin: 12px 0;
                grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
.promote-grid figure { margin: 0; }
.promote-grid img { width: 100%; aspect-ratio: 3/2; object-fit: cover; opacity: 0.45; }
.promote-grid figure.on img { opacity: 1; }
.promote-grid figcaption { display: flex; gap: 10px; font-size: 0.72rem; opacity: 0.7; }
.promote-grid figcaption label { display: flex; gap: 3px; align-items: center; }

/* --- E2-8 보정 검수 -----------------------------------------------------
   전/후를 **같은 자리에** 겹친다. 나란히 놓으면 눈이 두 곳을 오가느라
   미세한 톤 차이를 못 본다. 판단이 되는 화면이어야 승인 단계가 형식이 안 된다. */
.rt-run { padding-bottom: 16px; border-bottom: 1px solid var(--hair); margin-bottom: 16px; }
.rt-run h2 { margin: 0 0 6px; font-size: 0.95rem; }
.rt-run p { margin: 0 0 10px; font-size: 0.9rem; }
.rt-run form { display: flex; gap: 8px; flex-wrap: wrap; margin: 0 0 12px; }
.rt-run button { font: inherit; padding: 8px 16px; }
.rt-runs { border-collapse: collapse; font-size: 0.8rem; font-variant-numeric: tabular-nums; }
.rt-runs th, .rt-runs td { padding: 3px 12px 3px 0; text-align: left; font-weight: 400; }
.rt-runs th { opacity: 0.55; }

/* 한 번에 한 장. 넘기는 화면이지 훑는 화면이 아니다. */
.rt-shot { display: none; margin: 0; }
.rt-shot.on { display: block; }
.rt-frame {
  position: relative; display: block; background: #e9e7e4;
  max-width: min(100%, 1100px);
  /* 길게 눌러 보정 전을 볼 때 iOS 가 이미지 저장 메뉴를 띄우면 손이 끊긴다 */
  -webkit-touch-callout: none; user-select: none;
}
.rt-frame img { display: block; width: 100%; aspect-ratio: 3 / 2; object-fit: contain; }
/* 보정 전은 위에 깔아두고 평소에는 숨긴다. 바꿔치기가 즉시 일어나야 비교가 된다. */
.rt-before { position: absolute; inset: 0; height: 100%; visibility: hidden; }
.rt-stage.peek .rt-before { visibility: visible; }

.rt-shot figcaption {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 8px 2px; font-size: 0.8rem;
}
.rt-pos { font-variant-numeric: tabular-nums; opacity: 0.55; }
.rt-mark { font-weight: 800; }
.rt-shot.is-approved .rt-mark { color: #1f7a4d; }
.rt-hint { margin-left: auto; opacity: 0.5; }
/* 승인한 것은 테두리 하나로 표시한다 — 색을 늘리지 않는다. */
.rt-shot.is-approved .rt-frame { outline: 3px solid #1f7a4d; outline-offset: -3px; }

/* --- E3-2 블라인드 A/B ---------------------------------------------------
   두 장을 **같은 크기로** 놓는다. 한쪽이 크면 그쪽이 좋아 보인다 — 그것만으로
   최종 지표가 틀어진다. 그림 자체가 버튼이라 손가락이 한 번만 움직인다. */
.bl-pair { display: grid; gap: 10px; grid-template-columns: 1fr 1fr; margin: 0 0 12px; }
@media (max-width: 640px) { .bl-pair { grid-template-columns: 1fr; } }
.bl-side {
  position: relative; display: block; padding: 0; border: 0; background: #e9e7e4;
  cursor: pointer; font: inherit;
}
.bl-side img { display: block; width: 100%; aspect-ratio: 3 / 2; object-fit: contain; }
.bl-side span {
  position: absolute; left: 0; top: 0; padding: 4px 10px;
  font-size: 0.8rem; font-weight: 800; color: #fff; background: rgba(16, 17, 18, 0.55);
}
.bl-side:focus-visible { outline: 3px solid var(--ink); outline-offset: -3px; }
.bl-skip { font: inherit; padding: 10px 18px; }

/* --- E3 지표 -------------------------------------------------------------
   셋의 무게가 다르다. 블라인드가 최종, ΔE 는 방향만 보는 계기판, 수정률은 실무.
   ΔE 를 크게 두면 그 숫자를 좇게 되고, 그건 취향이 아니라 유사도를 좇는 것이다. */
/* 판 하나의 제목. 부연은 제목 옆에 작게 붙는다 — 아래로 내리면 본문과 섞인다. */
body.studio .studio-main > section h2 { margin: 0 0 10px; font-size: 0.95rem; }
body.studio .studio-main > section h2 small {
  font-weight: 400; opacity: 0.5; margin-left: 8px; font-size: 0.8rem;
}
body.studio .studio-main > section form { margin: 0; }
.mt-big { margin: 0 0 10px; font-size: 2rem; font-weight: 800;
          font-variant-numeric: tabular-nums; line-height: 1.1; }
.mt-big.good { color: #1f7a4d; }
.mt-big small { display: block; font-size: 0.8rem; font-weight: 400; opacity: 0.6; }

/* --- S6-1 촬영 조건 역산 --------------------------------------------------
   표가 근거고 이 목록이 결론이다. 결론을 표보다 위에, 눈에 띄게 둔다. */
/* 샷리스트는 예식장에서 한 손으로 읽는다. 체크 상자를 손가락 크기로 키운다. */
.sl-plan h3 { margin: 16px 0 6px; font-size: 0.9rem; }
.sl-plan h3 small { font-weight: 400; opacity: 0.55; margin-left: 8px; }
.sl-plan td { vertical-align: top; }
.sl-plan label { display: block; padding: 4px 0; cursor: pointer; }
.sl-plan input[type=checkbox] { width: 20px; height: 20px; margin-right: 8px;
                                vertical-align: -4px; }
.sl-fixed { margin: 0 0 10px; padding-left: 18px; font-size: 0.9rem; }
.sl-fixed li { margin-bottom: 4px; }

.sl-says { margin: 0 0 10px; padding-left: 18px; }
.sl-says li { margin-bottom: 6px; line-height: 1.5; }
.sl-says .muted { font-size: 0.85rem; }

/* --- W6-4 설정 -----------------------------------------------------------
   값과 출처와 설명이 한 줄 안에 있어야 한다. 설명을 접어두면 아무도 안 펼친다. */
.settings { max-width: 640px; }
.set-row { display: grid; grid-template-columns: minmax(9rem, 14rem) 1fr; gap: 4px 16px;
           align-items: center; padding: 12px 0; border-bottom: 1px solid var(--hair); }
.set-row label { font-weight: 600; }
.set-row input { font: inherit; padding: 8px 10px; width: 100%; max-width: 300px; }
.set-row input[type=number] { max-width: 110px; text-align: right;
                              font-variant-numeric: tabular-nums; }
/* 설명은 접어 둔다. 다섯 줄이 다 펼쳐져 있으면 고칠 칸을 찾는 데 시간이 든다.
   접히되 **한 번의 클릭 안에** 있어야 한다 — 다른 화면으로 보내면 아무도 안 읽는다. */
.set-row details { grid-column: 1 / -1; font-size: 0.82rem; opacity: 0.7; }
/* 설정의 상태 목록 — 이름과 값이 한 줄에 선다. 세로로 늘어놓으면 열 줄이 스무 줄이 된다. */
.detail { display: grid; grid-template-columns: minmax(7rem, auto) 1fr; gap: 6px 16px; margin: 0; }
.detail dt { opacity: 0.5; font-size: 0.85rem; }
.detail dd { margin: 0; }
.how { margin-top: 14px; font-size: 0.85rem; }
.how summary { cursor: pointer; opacity: 0.6; }
.how p { margin: 8px 0 0; line-height: 1.6; opacity: 0.8; }

/* 되돌리기 어려운 것이 있는 구역. 판 안에서 조용히, 그러나 구분되게. */
.danger { border-top: 2px solid #eec9c5; }
.set-row summary { cursor: pointer; opacity: 0.6; }
.set-row details p { margin: 6px 0 0; line-height: 1.6; }
.set-unit { margin-left: 6px; opacity: 0.6; font-size: 0.85rem; white-space: nowrap; }
.set-src { margin-left: 6px; font-size: 0.75rem; font-weight: 400; opacity: 0.55; }

/* --- 화면의 목적 · 흐름 ---------------------------------------------------
   기능 목록은 사람을 가르치지 않는다. "안 하면 이렇게 된다"가 가르친다.
   그래서 대가(cost) 줄을 흐리게 두지 않고 색으로 세운다. */
/* 화면의 목적. **접힌 채로 연다** — 매일 쓰는 사람에게 같은 설명을 매번 펼쳐 보이면
   화면의 첫 줄이 제목이 아니라 안내가 된다. 필드 위 글자라 색은 필드 기준으로 잡는다. */
.studio-why { margin: 0 0 14px; font-size: 0.85rem; }
.studio-why summary { cursor: pointer; opacity: 0.55; }
.studio-why[open] summary { opacity: 0.8; margin-bottom: 6px; }
.studio-why p { margin: 0 0 4px; line-height: 1.6; opacity: 0.75; max-width: 62ch; }
.studio-why .studio-cost { opacity: 0.6; }

.lr-funnel { display: flex; flex-wrap: wrap; gap: 18px; margin: 0 0 12px; padding: 0;
             list-style: none; }
.lr-funnel li { min-width: 96px; }
.lr-funnel b { display: block; font-size: 1.6rem; font-variant-numeric: tabular-nums; }
.lr-funnel span { font-size: 0.8rem; opacity: 0.6; }
.lr-funnel .lr-keep b { color: #1f7a4d; }

.lr-strip, .lr-pair { display: flex; gap: 10px; overflow-x: auto; padding-bottom: 6px; }
.lr-strip figure, .lr-pair figure { margin: 0; flex: 0 0 auto; }
.lr-strip img { height: 150px; width: auto; display: block; opacity: 0.35;
                filter: grayscale(1); }
.lr-strip .keep img { opacity: 1; filter: none; outline: 3px solid #1f7a4d; }
.lr-strip figcaption, .lr-pair figcaption { font-size: 0.78rem; opacity: 0.6;
                                            margin-top: 4px; }
.lr-strip .keep figcaption { color: #1f7a4d; opacity: 1; font-weight: 700; }
.lr-pair img { height: 220px; width: auto; display: block; }

.lr-stage { margin: 26px 0 8px; font-size: 0.8rem; letter-spacing: 0.08em;
            text-transform: uppercase; opacity: 0.5; }
.lr-card { padding: 12px 0; border-bottom: 1px solid var(--hair); }
.lr-card h3 { margin: 0 0 6px; font-size: 1rem; }
.lr-card h3 small { font-weight: 400; opacity: 0.5; margin-left: 6px; font-size: 0.78rem; }
.lr-card p { margin: 0 0 4px; line-height: 1.6; }
.lr-card .lr-why { opacity: 0.85; }
.lr-card .lr-cost { color: #8a5a12; font-size: 0.88rem; }

/* --- 앨범 목록의 상태 ------------------------------------------------------
   눌러야 풀리는 것(bad)과 기다리면 풀리는 것(wait)을 같은 색으로 두면
   기다려도 되는 일에 사람이 매달린다. 색이 곧 지시다. */
/* 상태 배지. **색이 곧 지시다** — 눌러야 풀리는 것(bad)과 기다리면 풀리는 것(wait)을
   같은 색으로 두면 기다려도 되는 일에 사람이 매달린다. 앨범 목록에서 시작해
   상태를 말하는 곳이면 어디서나 같은 뜻으로 쓴다. */
.badge { display: inline-block; padding: 2px 8px; border-radius: 2px;
         font-size: 0.8rem; white-space: nowrap; border: 1px solid transparent; }
.badge.bad  { background: #fbeae8; color: #a3231a; border-color: #eec9c5; }
.badge.wait { background: #f2f4f7; color: #4a5568; border-color: #dfe3e8; }
.badge.todo { background: #fdf4e3; color: #8a5a12; border-color: #eeddb8; }
.badge.ok   { background: #eaf5ee; color: #1f7a4d; border-color: #cbe4d5; }
.badge.idle { background: none; color: #7a7a7a; border-color: var(--hair); }
/* 그 줄에서 지금 할 일. 배지 옆에 붙고, 눌러야 하는 것에는 버튼이 함께 선다. */
.todo { font-size: 0.85rem; line-height: 1.5; }
.todo button { font: inherit; font-size: 0.8rem; padding: 2px 8px; margin-left: 6px; }

/* --- 감사 로그 ------------------------------------------------------------
   읽으러 오는 화면이 아니라 사고 뒤에 찾으러 오는 화면이다. 시각과 대상이 먼저다. */
.au-detail { max-width: 380px; word-break: break-all; opacity: 0.75; }
.au-ip { opacity: 0.5; font-size: 0.8rem; }

/* 2단계 안내. 문(門)에 있는 유일한 설명이라 작게, 그러나 읽히게. */
.door-note { margin: 14px 0 0; font-size: 0.78rem; line-height: 1.6; opacity: 0.6; }

/* --- S6-2 촬영 코칭 (웹) ---------------------------------------------------
   뷰파인더가 화면 전부다. 그 위에 얹는 것은 가장자리 몇 개뿐 —
   오버레이가 시선을 뺏으면 순간을 놓치고, 그러면 코칭이 촬영을 방해한 것이 된다. */
body.capture { background: #000; }
body.capture .studio-main { padding: 0; max-width: none; }
/* 헤더는 카메라 화면 위에 얹히되 물러나 있는다. 촬영 중에 메뉴가 눈에 들어올 이유가 없다.
   **다만 장면 칩과 겹치면 안 된다** — 겹치면 장면을 바꾸려다 메뉴를 누른다. */
body.capture .studio-header { position: absolute; opacity: 0.25; z-index: 3; }
body.capture .studio-header:hover { opacity: 1; }
body.capture .studio-why { display: none; }   /* 카메라 화면에는 안내를 얹지 않는다 */

.cap-stage { position: fixed; inset: 0; overflow: hidden; }
.cap-stage #cam,
.cap-stage #guide { position: absolute; inset: 0; width: 100%; height: 100%; }
/* **찍히는 프레임을 통째로 보여준다.** 화면을 채우려고 자르면 촬영자가 맞춘 틀과
   실제로 찍히는 사진이 달라진다. 위아래 검은 띠는 기본 카메라 앱과 같은 모습이다. */
.cap-stage #cam { object-fit: contain; background: #000; }

.cap-top { position: absolute; top: 0; left: 0; right: 0; padding: 64px 12px 0;
           display: flex; gap: 8px; align-items: flex-start; }
.cap-bottom { position: absolute; left: 0; right: 0; bottom: 0; padding: 0 12px 28px;
              display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }

.cap-chip { font: inherit; color: #fff; background: rgba(0, 0, 0, 0.45);
            border: 0; border-radius: 999px; padding: 8px 14px; cursor: pointer;
            display: flex; gap: 8px; align-items: baseline; }
.cap-chip span { font-size: 0.78rem; opacity: 0.7; }
.cap-toggle { margin-left: auto; font-size: 0.8rem; }
.cap-toggle[aria-pressed="false"] { opacity: 0.45; }

/* 힌트. 굵고 짧게 — 곁눈으로 읽는 글자다. */
.cap-hints { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.cap-hints li { font-size: 1.15rem; font-weight: 800; color: #fff;
                background: rgba(0, 0, 0, 0.55); border-radius: 999px; padding: 8px 16px; }
.cap-state, .cap-source { margin: 0; color: rgba(255, 255, 255, 0.75); font-size: 0.75rem; }
/* 오류는 폰 화면에서 읽혀야 한다. 개발자 도구를 붙일 수 없는 곳이다. */
.cap-state.is-bad { color: #fff; background: #c0281f; padding: 8px 12px; border-radius: 8px;
                    font-size: 0.85rem; line-height: 1.5; max-width: 100%; word-break: break-all; }

.cap-debug { margin: 0; color: rgba(255, 255, 255, 0.85); font-size: 0.7rem;
             background: rgba(0, 0, 0, 0.5); padding: 6px 10px; border-radius: 6px;
             font-variant-numeric: tabular-nums; }
.cap-start { font: inherit; font-weight: 800; color: #111; background: #fff;
             border: 0; border-radius: 999px; padding: 14px 24px; cursor: pointer; }

/* 장면 고르기. 구간과 장면은 서버가 준 것을 그대로 쓴다. */
.cap-sheet { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.75);
             overflow-y: auto; padding: 60px 16px 40px; }
.cap-sheet-body { max-width: 520px; margin: 0 auto; color: #fff; }
.cap-sheet h3 { margin: 20px 0 8px; font-size: 0.85rem; opacity: 0.6; }
.sheet-note { margin: 0 0 8px; font-size: 0.8rem; opacity: 0.55; line-height: 1.6; }
.sheet-shot { display: block; width: 100%; text-align: left; font: inherit; color: #fff;
              background: rgba(255, 255, 255, 0.08); border: 0; border-radius: 10px;
              padding: 12px 14px; margin-bottom: 6px; cursor: pointer; }
.sheet-shot span { display: block; font-size: 0.78rem; opacity: 0.6; margin-top: 2px; }
