/* Phase 9~10 — 앱 셸 · 모달 · 공용 조각.
 *
 * 색은 검정 하나와 그 투명도로만 만든다. 아티스트의 작업이 화면에서 가장 진한
 * 색이어야 하므로, UI 가 색을 쓰면 작품과 경쟁한다. 강조가 필요하면 채도가
 * 아니라 대비(검정 채움)로 준다.
 *
 * 레이아웃 골격은 Tailwind CDN(브라우저 JIT)에 맡기지 않는다. CDN 이 늦게 뜨면
 * 골격 없는 화면이 한 번 그려졌다가 튄다.
 */

:root {
  /* 셸의 치수는 한 단계씩 끊지 않고 화면 폭을 따라 이어서 자란다. 폰과
     데스크톱 사이(태블릿·좁은 창)에서 갑자기 바뀌면 그 폭에서만 어색해진다.
     바만 얇아지고 안의 것이 그대로면 오히려 답답해 보이므로, 안의 치수도
     같은 방식으로 함께 자란다. */
  --rail:     clamp(44px, calc(34.7px + 2.33vw), 60px);
  --topbar:   clamp(46px, calc(39.3px + 1.67vw), 58px);
  --rail-ico: clamp(17px, calc(14.3px + 0.67vw), 21px);
  --rail-h:   clamp(38px, calc(32.7px + 1.33vw), 46px);
  --search-h: clamp(30px, calc(24.7px + 1.33vw), 38px);
  --ctl-h:    clamp(26px, calc(20.7px + 1.33vw), 34px);
  --ctl-fs:   clamp(.68rem, calc(.6rem + 0.3vw), .8rem);
  --avatar:   clamp(24px, calc(18.7px + 1.33vw), 32px);

  --ink: #0b0b0c;
  --bg: #fff;

  /* 검정의 투명도 계단. 선·바탕·글자 모두 여기서 고른다. */
  --ink-90: rgba(11,11,12,.92);
  --ink-60: rgba(11,11,12,.58);
  --ink-40: rgba(11,11,12,.40);
  --ink-25: rgba(11,11,12,.25);
  --line:   rgba(11,11,12,.10);
  --line-2: rgba(11,11,12,.16);
  --wash:   rgba(11,11,12,.045);
  --wash-2: rgba(11,11,12,.075);

  --r-sm: .6rem;
  --r-md: 1rem;
  --r-lg: 1.4rem;
}

/* 넓은 화면에서는 레일이 '아이콘 줄' 에서 '이름이 붙은 목록' 으로 바뀐다.
   이건 치수가 아니라 짜임이 달라지는 지점이라 단계로 끊는다. */
@media (min-width: 1024px) {
  :root {
    --rail:     clamp(190px, 16vw, 216px);
    --topbar:   64px;
    --rail-ico: 22px;
    --rail-h:   46px;
    --search-h: 40px;
    --ctl-h:    38px;
    --ctl-fs:   .78rem;
    --avatar:   36px;
  }
}

body {
  background: var(--bg);
  color: var(--ink-90);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection { background: var(--ink); color: #fff; }

/* 링 대신 대비로 초점을 준다 — 파란 기본 아웃라인은 이 화면에서 유일한 색이 된다. */
:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ── 좌측 레일 ─────────────────────────────────────────────────────── */

.app-rail {
  position: fixed;
  top: 0; bottom: 0; left: 0;
  width: var(--rail);
  padding-left: env(safe-area-inset-left);
  padding-bottom: env(safe-area-inset-bottom);
  background: var(--bg);
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  z-index: 40;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.app-rail::-webkit-scrollbar { width: 0; }

.rail-brand {
  height: var(--topbar);
  display: flex; align-items: center; justify-content: center;
  flex: none;
  letter-spacing: -.02em;
}
@media (min-width: 1024px) { .rail-brand { justify-content: flex-start; padding-left: 1.1rem; } }

.rail-item {
  display: flex; align-items: center; gap: .8rem;
  height: var(--rail-h); margin: .1rem .25rem; padding: 0 .45rem;
  border-radius: 11px;
  color: var(--ink-60);
  flex: none;
  transition: background .15s ease, color .15s ease;
}
@media (min-width: 1024px) {
  .rail-item { margin: .1rem .35rem; padding: 0 .85rem; border-radius: 13px; }
}
.rail-item:hover { background: var(--wash); color: var(--ink-90); }
.rail-item.on { background: var(--ink); color: #fff; }
.rail-item svg { width: var(--rail-ico); height: var(--rail-ico); flex: none; margin: 0 auto; }
@media (min-width: 1024px) { .rail-item svg { margin: 0; } }
.rail-label { display: none; font-size: .82rem; font-weight: 600; white-space: nowrap; letter-spacing: -.01em; }
@media (min-width: 1024px) { .rail-label { display: block; } }

.rail-spacer { flex: 1 1 auto; }

/* 상단바 안의 것들은 바 두께를 따라 같이 자란다 — 바만 얇아지면 버튼과
   글씨가 상대적으로 커져 바가 꽉 찬 것처럼 보인다. */
.app-top .btn { height: var(--ctl-h); padding: 0 clamp(.55rem, 1vw, .95rem); font-size: var(--ctl-fs); }
.app-top .btn svg { width: 1em; height: 1em; }
.app-top .avatar-8 { width: var(--avatar); height: var(--avatar); }

/* ── 본문 · 상단바 ─────────────────────────────────────────────────── */

.app-main { margin-left: var(--rail); min-height: 100vh; min-height: 100dvh; }

.app-top {
  /* Tailwind CDN 이 늦게 뜨는 순간에도 바 높이가 흔들리지 않게 직접 적는다. */
  box-sizing: border-box;
  position: sticky; top: 0; z-index: 30;
  height: var(--topbar);
  display: flex; align-items: center; gap: clamp(.35rem, .8vw, .6rem);
  /* 검색창이 바 높이를 꽉 채우면 눌린 것처럼 보인다. 위아래로 숨통을 둔다. */
  padding: clamp(.35rem, .8vw, .6rem) .7rem;
  padding-right: calc(.7rem + env(safe-area-inset-right));
  background: rgba(255,255,255,.82);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--line);
}

.search-wrap { flex: 1 1 auto; min-width: 0; max-width: 680px; margin-right: auto; position: relative; }
input.search-input {
  width: 100%; height: var(--search-h);
  padding: 0 .9rem 0 2.2rem;
  border: 1px solid transparent; border-radius: 999px;
  background: var(--wash);
  color: var(--ink-90);
  font-size: var(--ctl-fs);
  outline: none;
  transition: background .15s ease, border-color .15s ease;
}
input.search-input::placeholder { color: var(--ink-40); }
/* 포커스에 링을 두지 않는다. 바탕과 선만 한 단계 진해진다. */
input.search-input:focus { background: #fff; border-color: var(--line-2); }
input.search-input::-webkit-search-cancel-button { -webkit-appearance: none; }
.search-icon {
  position: absolute; left: clamp(.7rem, 1vw, .85rem); top: 50%; transform: translateY(-50%);
  width: clamp(14px, 1.5vw, 17px); height: clamp(14px, 1.5vw, 17px);
  color: var(--ink-40); pointer-events: none;
}

.app-body { padding: 1.1rem .8rem 4rem; }
@media (min-width: 1024px) { .app-body { padding: 1.6rem 1.5rem 5rem; } }

/* ── 버튼 ──────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  height: 38px; padding: 0 .95rem;
  border: 1px solid transparent; border-radius: 999px;
  font-size: .78rem; font-weight: 700; letter-spacing: -.01em;
  cursor: pointer; white-space: nowrap;
  transition: background .15s ease, color .15s ease, border-color .15s ease, opacity .15s ease;
}
.btn-solid { background: var(--ink); color: #fff; }
.btn-solid:hover { opacity: .84; }
.btn-ghost { background: transparent; color: var(--ink-90); border-color: var(--line-2); }
.btn-ghost:hover { background: var(--wash); }
.btn-quiet { background: var(--wash); color: var(--ink-90); }
.btn-quiet:hover { background: var(--wash-2); }
.btn-lg { height: 50px; padding: 0 1.3rem; font-size: .85rem; border-radius: var(--r-md); }
.btn[disabled] { opacity: .4; cursor: default; }

/* ── 입력 ──────────────────────────────────────────────────────────── */

.field { display: block; }
.field-label {
  display: block; margin-bottom: .4rem;
  font-size: .68rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-40);
}
/* textarea 에 .input 을 달아 쓰는 자리(키트)가 이 규칙에서 빠져 있어
   브라우저 기본 파란 링이 그대로 나왔다. 초점은 링이 아니라 테두리 대비로 준다. */
input.input, textarea.input, textarea.textarea, select.input, input[type='file'].input {
  width: 100%;
  padding: .7rem .85rem;
  border: 1px solid var(--line-2); border-radius: var(--r-sm);
  background: #fff; color: var(--ink-90);
  font-size: .9rem; font-family: inherit;
  outline: none;
  transition: border-color .15s ease, background .15s ease;
}
input.input::placeholder, textarea.input::placeholder,
textarea.textarea::placeholder { color: var(--ink-25); }
input.input:focus, textarea.input:focus, textarea.textarea:focus, select.input:focus {
  border-color: var(--ink); outline: none; box-shadow: none;
}
textarea.textarea { min-height: 110px; resize: vertical; line-height: 1.6; }
.hint { margin-top: .35rem; font-size: .7rem; color: var(--ink-40); }

/* ── 카드 ──────────────────────────────────────────────────────────── */

.surface {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  transition: border-color .18s ease, transform .18s ease;
}
a.surface:hover { border-color: var(--line-2); }

/* ── 겹친 프로필 원(참석자) ────────────────────────────────────────── */

.avstack { display: flex; align-items: center; }
.avstack > * {
  width: 26px; height: 26px; border-radius: 999px;
  border: 2px solid #fff; background: var(--wash-2);
  object-fit: cover; margin-left: -9px; flex: none;
}
.avstack > *:first-child { margin-left: 0; }
.avstack .more {
  display: flex; align-items: center; justify-content: center;
  background: var(--ink); color: #fff; font-size: .58rem; font-weight: 700;
}

/* ── 모달 ──────────────────────────────────────────────────────────── */

/* 가운데 정렬을 align-items 로 하면, 내용이 화면보다 길 때 위쪽이 스크롤로
   닿지 않는 곳으로 밀려난다(플렉스의 오래된 함정). 실제로 폰에서 피드 모달의
   사진 윗부분이 잘려 보이지 않았다. 정렬은 카드의 margin:auto 에 맡긴다. */
.modal-backdrop {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(11,11,12,.42);
  backdrop-filter: blur(3px);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 4vh 1rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  animation: fade .18s ease-out;
}
@keyframes fade { from { opacity: 0 } to { opacity: 1 } }

.modal-card {
  position: relative;
  margin: auto;                /* 위아래 가운데 — 넘치면 위쪽도 스크롤로 닿는다 */
  width: 100%; max-width: 620px;
  background: #fff;
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(11,11,12,.22);
  animation: pop .2s cubic-bezier(.2,.7,.3,1);
}
@keyframes pop { from { transform: scale(.97); opacity: 0 } to { transform: none; opacity: 1 } }

/* 공지처럼 짧은 글은 620px 도 넓다. 한 눈에 담기는 폭으로 줄인다. */
.modal-narrow .modal-card { max-width: 26rem; }
.modal-wide .modal-card { max-width: 880px; display: flex; flex-direction: column;
                          max-height: 92vh; }
.modal-wide .modal-slot { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }

/* 폰에서도 창은 창이다 — 바닥에서 올라오는 시트는 걷어냈다(2026-08-25).
   화면을 반쯤 덮은 시트는 뒤가 살아 있는 것처럼 보이는데 실제로는 아니고,
   내용이 길면 위쪽이 스크롤 밖으로 밀려났다. */
@media (max-width: 640px) {
  .modal-backdrop { padding: 2vh .7rem; }
  .modal-card { max-width: none; }
  .modal-narrow { padding: 1.2rem; }
}

.modal-close {
  position: absolute; top: .75rem; right: .75rem; z-index: 5;
  width: 32px; height: 32px; border: 0; border-radius: 999px;
  background: rgba(255,255,255,.9); color: var(--ink-90);
  font-size: .85rem; line-height: 32px; text-align: center; cursor: pointer;
  backdrop-filter: blur(6px);
  box-shadow: 0 1px 4px rgba(11,11,12,.14);
}
.modal-close:hover { background: #fff; }

body.modal-open { overflow: hidden; }

/* ── 피드 카드 ─────────────────────────────────────────────────────── */

.feed-col { column-gap: 1rem; }
@media (min-width: 720px)  { .feed-col { column-count: 2; } }
@media (min-width: 1100px) { .feed-col { column-count: 3; } }
@media (min-width: 1600px) { .feed-col { column-count: 4; } }
.feed-col > * { break-inside: avoid; margin-bottom: 1rem; }

/* ── 작품 Masonry ──────────────────────────────────────────────────
 * CSS columns 로만 만든다. JS 라이브러리를 쓰면 이미지 로드 순서에 따라 위치를
 * 다시 계산하느라 화면이 튀고, CDN 이 죽으면 아예 안 그려진다.
 * 폭은 열이 정하고 높이는 이미지 비율이 정한다 — 잘라내지 않는다.
 */
.masonry { column-count: 2; column-gap: .7rem; }
@media (min-width: 640px)  { .masonry { column-count: 3; } }
@media (min-width: 1024px) { .masonry { column-count: 4; } }
@media (min-width: 1400px) { .masonry { column-count: 5; } }
@media (min-width: 1800px) { .masonry { column-count: 6; } }
.masonry > * { break-inside: avoid; margin-bottom: .7rem; position: relative; }

/* 작품 위에 글자를 얹지 않는다. 캡션과 작가는 모달에서 읽는다. */
.card {
  position: relative; display: block;
  border-radius: var(--r-md); overflow: hidden;
  background: var(--wash);
  transition: transform .2s cubic-bezier(.2,.7,.3,1);
}
.card img { display: block; width: 100%; height: auto; }
.card::after {
  content: ""; position: absolute; inset: 0;
  background: rgba(11,11,12,0); transition: background .18s ease;
}
.card:hover::after { background: rgba(11,11,12,.14); }

.bm {
  position: absolute; top: .5rem; right: .5rem; z-index: 2;
  width: 2rem; height: 2rem; border: 0; border-radius: 999px;
  background: rgba(255,255,255,.92); color: var(--ink-90);
  font-size: .8rem; line-height: 2rem; text-align: center; cursor: pointer;
  backdrop-filter: blur(6px);
  opacity: 0; transition: opacity .16s ease, background .16s ease;
}
.masonry > *:hover .bm, .bm:focus-visible { opacity: 1; }
.bm.on { background: var(--ink); color: #fff; opacity: 1; }
@media (hover: none) { .bm { opacity: 1; } }   /* 터치 기기는 hover 가 없다 */

/* ── 모임 커버 ─────────────────────────────────────────────────────── */

.cover { position: relative; aspect-ratio: 16 / 9; overflow: hidden; background: var(--ink); }
/* 사진 없이 활자만 넣는 커버는 더 낮게. 검정 덩어리가 카드를 다 먹지 않게 한다. */
.cover-empty { aspect-ratio: 21 / 9; }
.cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* 커버가 없는 모임(자동 생성 정기 모임)은 활자로 채운다. 빈 회색 네모보다 낫다. */
.cover-type {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  color: #fff; text-align: center; letter-spacing: -.02em;
}
.cover-type b { font-size: clamp(1.6rem, 6vw, 2.6rem); font-weight: 800; line-height: 1; }
.cover-type span { margin-top: .5rem; font-size: .68rem; letter-spacing: .3em; opacity: .6; text-transform: uppercase; }

/* ── 배지 ──────────────────────────────────────────────────────────── */

.chip {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .18rem .55rem; border-radius: 999px;
  font-size: .65rem; font-weight: 700; letter-spacing: -.01em;
  border: 1px solid var(--line-2); color: var(--ink-60);
}
.chip-solid { background: var(--ink); color: #fff; border-color: var(--ink); }
.chip-dot { width: 5px; height: 5px; border-radius: 999px; background: currentColor; }

.line-clamp-1, .line-clamp-2, .line-clamp-3 {
  display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden;
}
.line-clamp-1 { -webkit-line-clamp: 1 }
.line-clamp-2 { -webkit-line-clamp: 2 }
.line-clamp-3 { -webkit-line-clamp: 3 }

/* ── Tailwind 회색 정규화 ───────────────────────────────────────────
 * 화면 대부분은 Tailwind CDN 유틸리티로 짜여 있고, 그 회색(gray-*)은 푸른기가
 * 도는 계열이라 우리 검정과 나란히 놓으면 두 종류의 회색이 보인다. 유틸리티를
 * 파일마다 바꾸는 대신 여기서 한 번 토큰으로 접어준다.
 * (규칙 하나로 전 화면이 같은 계단을 쓰게 하는 것이 목적이라 !important 다)
 */
.text-gray-300 { color: var(--ink-25) !important; }
.text-gray-400 { color: var(--ink-40) !important; }
.text-gray-500 { color: var(--ink-60) !important; }
.text-gray-600, .text-gray-700 { color: var(--ink-90) !important; }
.bg-gray-50  { background-color: var(--wash) !important; }
.bg-gray-100 { background-color: var(--wash-2) !important; }
.border, .border-t, .border-b, .border-l, .border-r, .divide-y > * + * {
  border-color: var(--line) !important;
}
.border-2 { border-color: var(--line-2) !important; }
.border-black, .border-2.border-black { border-color: var(--ink) !important; }
/* 파랑은 인스타 링크 하나에만 남아 있었다. 이 화면에서 색은 작품의 몫이다. */
.text-blue-600 { color: var(--ink-90) !important; }
.text-red-500 { color: var(--ink-60) !important; }

/* ── 알림 점 ────────────────────────────────────────────────────────
 * 흑백 화면이라 점 하나만 색을 갖는다. 색이 여기밖에 없으니 시선이 반드시
 * 여기로 온다 — 그게 이 점의 목적이다.
 */
:root { --accent: #ff4d2d; }

.dot {
  position: absolute; top: -2px; right: -2px;
  width: 9px; height: 9px; border-radius: 999px;
  background: var(--accent);
  box-shadow: 0 0 0 2px #fff;
  animation: pulse 1.8s ease-in-out infinite;
}
.dot-avatar { top: -1px; right: -1px; }
@keyframes pulse {
  0%, 100% { transform: scale(1);    opacity: 1 }
  50%      { transform: scale(1.25); opacity: .75 }
}
@media (prefers-reduced-motion: reduce) { .dot { animation: none } }

.rail-icon-wrap { position: relative; display: inline-flex; }
@media (max-width: 1023px) { .rail-icon-wrap { margin: 0 auto } }

/* ── 글쓰기: 좁은 화면에서는 헤더를 떠나 우하단 원형 버튼으로 ──────────
 * 헤더는 검색창이 주인이다. 글쓰기가 그 자리를 나눠 쓰면 검색이 좁아지고
 * 버튼도 작아진다. 폰에서는 아예 내려보내 엄지에 닿는 자리에 둔다.
 */
.btn-cv-short { display: none; }
@media (max-width: 639px) {
  .btn-cv-label { display: none; }
  .btn-cv-short { display: inline; }
  .btn-cv { padding: 0 .6rem; }

  /* 헤더에서는 빠지고 화면 우하단의 FAB 이 대신한다. */
  .btn-write { display: none; }
}

/* 우하단 글쓰기 버튼. 셸 바로 아래에 있어야 화면 기준으로 붙는다 —
   backdrop-filter 가 걸린 헤더 안에 두면 그 헤더가 기준이 되어 엉뚱한 자리로 간다. */
/* 뒤에 오는 규칙이 이긴다 — 예전에는 이 기본값이 미디어쿼리보다 아래 있어서
   폰에서도 display:none 이 이겼고, 그래서 이 버튼은 한 번도 보이지 않았다. */
.fab {
  display: none;
  position: fixed; z-index: 45;
  right: calc(1rem + env(safe-area-inset-right));
  bottom: calc(1rem + env(safe-area-inset-bottom));
  width: 54px; height: 54px; border-radius: 999px;
  align-items: center; justify-content: center;
  background: var(--ink); color: #fff;
  box-shadow: 0 10px 28px rgba(11, 11, 12, .32);
}
.fab svg { width: 24px; height: 24px; }
.fab:active { transform: scale(.96); }
@media (max-width: 639px) { .fab { display: inline-flex; } }

/* ── 토스트 ─────────────────────────────────────────────────────────
 * 알림이 레이아웃을 밀어내면 방금 보던 것이 아래로 내려간다. 화면 위에 잠깐
 * 떠 있다가 스스로 사라지게 두고, 자리는 내주지 않는다.
 */
.toast-wrap {
  position: fixed; z-index: 80;
  left: 50%; transform: translateX(-50%);
  bottom: calc(1.4rem + env(safe-area-inset-bottom));
  display: flex; flex-direction: column; gap: .5rem; align-items: center;
  pointer-events: none;
  width: max-content; max-width: min(90vw, 26rem);
}
.toast {
  background: var(--ink); color: #fff;
  padding: .7rem 1.1rem; border-radius: 999px;
  font-size: .78rem; font-weight: 600; letter-spacing: -.01em;
  box-shadow: 0 10px 30px rgba(11, 11, 12, .3);
  animation: toast-in .28s cubic-bezier(.2, .8, .3, 1);
  text-align: center;
}
.toast.out { animation: toast-out .3s ease-in forwards; }
@keyframes toast-in  { from { opacity: 0; transform: translateY(14px) } to { opacity: 1 } }
@keyframes toast-out { to { opacity: 0; transform: translateY(10px) } }
@media (max-width: 639px) {
  /* 글쓰기 FAB 과 겹치지 않게 살짝 띄운다. */
  .toast-wrap { bottom: calc(4.8rem + env(safe-area-inset-bottom)); }
}
@media (prefers-reduced-motion: reduce) { .toast { animation: none } }

/* ── 로그인 ─────────────────────────────────────────────────────────── */
.login-backdrop {
  position: fixed; inset: 0; z-index: 70;
  background: rgba(11, 11, 12, .45); backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center; padding: 1.2rem;
  animation: fade .18s ease-out;
}
.login-backdrop[hidden] { display: none; }
.login-card {
  width: 100%; max-width: 24rem;
  background: #fff; border-radius: var(--r-lg);
  padding: 1.7rem 1.6rem 1.5rem;
  box-shadow: 0 24px 60px rgba(11, 11, 12, .28);
  animation: pop .2s cubic-bezier(.2, .7, .3, 1);
}

/* ── 작품 모달 ──────────────────────────────────────────────────────
 * 창에 높이를 정해두고 그 안에 그림을 우겨넣으면, 세로로 긴 작품은 위아래가
 * 잘리고 가로로 넓은 작품은 아래가 텅 빈다. 순서를 뒤집는다 —
 * **그림이 크기를 정하고 창이 거기에 맞춘다.**
 *
 *   이미지: 화면 안에 들어갈 만큼만(비율 유지, 잘리지 않음)
 *   창    : 그 이미지 폭에 맞춰 줄어든다(shrink-to-fit)
 *   작가 줄: 언제나 그림 바로 아래. 창이 그림에 붙어 있으니 위치가 흔들리지 않는다
 */
.modal-art { align-items: center; padding: 3vh 3vw; }
.modal-art .modal-card {
  width: auto;                 /* 폭을 채우지 않는다 — 그림이 정한다 */
  max-width: min(96vw, 1100px);
  min-width: min(18rem, 90vw); /* 세로로 아주 긴 그림에서도 캡션이 읽히게 */
  max-height: none; min-height: 0;
  border-radius: var(--r-lg);
  display: block;
}
.modal-art .modal-slot { display: block; }

.artwork-card { display: flex; flex-direction: column; }
.artwork-stage { background: var(--ink); display: flex; justify-content: center; }
.artwork-stage img {
  display: block; width: auto; height: auto;
  max-width: min(96vw, 1100px);
  max-height: 74vh;            /* 아래 작가 줄이 늘 함께 보이도록 남겨둔다 */
  object-fit: contain;
}
.artwork-foot {
  flex: none; background: #fff;
  border-top: 1px solid var(--line);
  padding: .95rem 1.1rem;
  max-height: 26vh; overflow-y: auto;   /* 캡션이 길면 이 줄 안에서만 스크롤 */
}

@media (max-width: 640px) {
  .modal-art { padding: 2vh 3vw; align-items: center; }
  .modal-art .modal-card { border-radius: var(--r-lg); height: auto; animation: pop .2s cubic-bezier(.2,.7,.3,1); }
  .artwork-stage img { max-height: 66vh; max-width: 94vw; }
}

/* 한마디(방명록) — 위쪽의 '정해진 사실'(일시·장소·참석자)과 아래쪽의 '주고받는
   말' 은 성격이 다르다. 선 하나로는 잘 갈리지 않아 바탕을 한 겹 깐다. */
.gbook {
  background: var(--wash);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: .95rem 1rem 1rem;
}
.gbook .input { background: #fff; }

/* ── 모임 카드: 넓은 화면에서는 격자로 ─────────────────────────────── */
.gathering-grid { display: grid; gap: 1rem; }
@media (min-width: 780px)  { .gathering-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1440px) { .gathering-grid { grid-template-columns: repeat(3, 1fr); } }


/* 모달 내용이 바뀌는 동안만 살짝 흐려진다. 창이 닫혔다 열리는 것보다
   눈에 훨씬 덜 걸린다. */
.modal-card.swapping { opacity: .35; transition: opacity .12s ease; }
.modal-card { transition: opacity .16s ease; }

/* 초대자 카드로 옮겨갔을 때 잠깐 표시해 준다 — 어디로 갔는지 알려주는 것이
   스크롤 애니메이션의 목적이다. */
.surface.flash { box-shadow: 0 0 0 2px var(--ink); }
.surface { transition: border-color .18s ease, box-shadow .3s ease; }

/* ── 피드 보기 전환 ─────────────────────────────────────────────────
 * 같은 목록을 네 가지 밀도로 본다. 폰에서 사진 큰 카드가 이어지면 열 개만
 * 넘어가도 훑기가 힘들다. 고른 값은 기기에 남는다(localStorage).
 */
.view-switch { display: inline-flex; gap: .25rem; padding: .25rem; border-radius: 999px; background: var(--wash); }
.view-switch button {
  border: 0; background: none; cursor: pointer;
  padding: .4rem .8rem; border-radius: 999px;
  font: inherit; font-size: .74rem; font-weight: 700; color: var(--ink-40);
}
.view-switch button.on { background: var(--ink); color: #fff; }

/* 카드 — 기본. 사진 그대로, 글 세 줄. */
.feed-list.as-card { column-gap: 1rem; }
@media (min-width: 720px)  { .feed-list.as-card { column-count: 2; } }
@media (min-width: 1100px) { .feed-list.as-card { column-count: 3; } }
@media (min-width: 1600px) { .feed-list.as-card { column-count: 4; } }
.feed-list.as-card > * { break-inside: avoid; margin-bottom: 1rem; }

/* 2열 — 폰에서도 두 칸. 사진은 정사각으로 잘라 줄을 맞춘다. */
.feed-list.as-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: .7rem; }
@media (min-width: 900px)  { .feed-list.as-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1400px) { .feed-list.as-grid { grid-template-columns: repeat(4, 1fr); } }
.feed-list.as-grid .feed-photo img { aspect-ratio: 1 / 1; object-fit: cover; }
.feed-list.as-grid .feed-excerpt, .feed-list.as-grid .feed-author { display: none; }
.feed-list.as-grid .feed-text { padding: .7rem .8rem .9rem; }

/* 제목만 — 한 줄씩. 가장 빠르게 훑는 방식. */
.feed-list.as-title { display: flex; flex-direction: column; }
.feed-list.as-title > * { border-radius: 0; border-width: 0 0 1px 0; }
.feed-list.as-title .feed-photo, .feed-list.as-title .feed-excerpt,
.feed-list.as-title .feed-author { display: none; }
.feed-list.as-title .feed-text { padding: .85rem .2rem; }

/* 사진만 — 격자에 사진만. 글은 열어서 읽는다. */
.feed-list.as-photo { display: grid; grid-template-columns: repeat(2, 1fr); gap: .35rem; }
@media (min-width: 900px)  { .feed-list.as-photo { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1400px) { .feed-list.as-photo { grid-template-columns: repeat(5, 1fr); } }
.feed-list.as-photo > * { border: 0; border-radius: .6rem; }
.feed-list.as-photo .feed-text { display: none; }
.feed-list.as-photo .feed-photo img { aspect-ratio: 1 / 1; object-fit: cover; }
/* 사진이 없는 글은 제목이라도 보여야 한다 — 빈 칸이 되면 안 된다. */
.feed-list.as-photo > *:not(:has(.feed-photo)) .feed-text { display: block; padding: .8rem; }


/* ── 첫 CV 만들기 키트 ───────────────────────────────────────────────
 * 한 번에 하나씩만 묻는다. 창 하나에 열 칸이 있으면 사람은 시작하기 전에
 * 그만둔다. 그래서 이 화면에는 늘 질문 하나와 버튼 둘만 있다.
 */
/* 단계 감추기는 Tailwind CDN 이 늦게 떠도 흔들리면 안 된다 — 다섯 단계가
   한꺼번에 펼쳐진 화면이 한 번이라도 보이면 '망가졌다' 로 읽힌다. */
.kit-step.hidden { display: none; }
.kit .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
                overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }

.kit { position: relative; padding: 1.6rem 1.4rem 1.4rem; }
@media (min-width: 640px) { .kit { padding: 2rem 1.9rem 1.6rem; } }

.kit-dots { display: flex; gap: .3rem; margin-bottom: 1.2rem; }
.kit-dots i { flex: 1 1 0; height: 3px; border-radius: 999px; background: var(--line-2); }
.kit-dots i.on { background: var(--ink); }

.kit-eyebrow { font-size: .68rem; letter-spacing: .22em; text-transform: uppercase;
               color: var(--ink-40); }
.kit-h { margin-top: .5rem; font-size: 1.35rem; font-weight: 900; letter-spacing: -.02em;
         line-height: 1.35; }
.kit-p { margin-top: .55rem; font-size: .82rem; line-height: 1.7; color: var(--ink-60); }
.kit-area { margin-top: 1rem; width: 100%; min-height: 8.5rem; resize: vertical; }
.kit-foot { display: flex; gap: .5rem; margin-top: 1.4rem; }

/* 프로필 사진 — 동그란 자리 하나. 무엇을 넣는 자리인지 모양이 먼저 말한다. */
.kit-pic {
  display: flex; align-items: center; justify-content: center;
  position: relative; overflow: hidden;
  width: 9.5rem; height: 9.5rem; margin: 1.3rem auto 0;
  border-radius: 999px; border: 1px dashed var(--line-2);
  background: var(--wash); cursor: pointer;
}
.kit-pic img { width: 100%; height: 100%; object-fit: cover; }
.kit-pic .kit-pic-hint { position: absolute; font-size: .74rem; color: var(--ink-40); }
.kit-pic.has { border-style: solid; }
.kit-pic.has .kit-pic-hint { display: none; }

.kit-works { margin-top: 1.1rem; display: flex; flex-direction: column; gap: .6rem; }
.kit-work { display: flex; gap: .6rem; align-items: center; }
.kit-shot {
  position: relative; overflow: hidden; flex: none;
  width: 4.6rem; height: 4.6rem; border-radius: var(--r-sm);
  border: 1px dashed var(--line-2); background: var(--wash);
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-40); cursor: pointer;
}
.kit-shot img { width: 100%; height: 100%; object-fit: cover; }
.kit-shot.has { border-style: solid; }
.kit-shot.has span { display: none; }
.kit-work-fields { flex: 1 1 auto; min-width: 0; display: flex; gap: .4rem; }
.kit-work-fields .input { min-width: 0; }
.kit-year { flex: 0 0 5rem; }

/* 올라가는 동안 그 자리에서 돈다 — 화면 위 어딘가가 아니라 누른 자리에서. */
.kit-pic.busy::after, .kit-shot.busy::after {
  content: ""; position: absolute; inset: 0;
  background: rgba(255,255,255,.72);
  background-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 18 18'>\
<circle cx='9' cy='9' r='7' fill='none' stroke='%23999' stroke-width='2' stroke-dasharray='30 14'>\
<animateTransform attributeName='transform' type='rotate' from='0 9 9' to='360 9 9' dur='.8s' repeatCount='indefinite'/>\
</circle></svg>");
  background-repeat: no-repeat; background-position: center;
}

/* 스타일 고르기 — 이름만으로는 무엇인지 모른다. 작은 그림으로 짐작하게 한다. */
.kit-styles { margin-top: 1.1rem; display: grid; gap: .6rem; grid-template-columns: 1fr 1fr; }
.kit-style { position: relative; }
.kit-style-pick {
  width: 100%; text-align: left; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: #fff; padding: .6rem .65rem 2rem;
  display: flex; flex-direction: column; gap: .35rem;
}
.kit-style.on .kit-style-pick { border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
.kit-style-pick b { font-size: .82rem; }
.kit-style-hint { font-size: .68rem; line-height: 1.5; color: var(--ink-40); }
.kit-style-art { display: block; height: 3.4rem; border-radius: var(--r-sm); overflow: hidden; }
.kit-art-t6_finder { background:
  linear-gradient(90deg, #e9e9ec 0 30%, #fff 30% 100%),
  repeating-linear-gradient(180deg, transparent 0 6px, rgba(0,0,0,.06) 6px 7px); }
.kit-art-t3_launcher { background: #111 radial-gradient(circle at 50% 55%, #444 0 6px, transparent 6px)
  no-repeat; }
.kit-art-t1_desktop { background: #b9c3cf;
  background-image: radial-gradient(circle at 22% 30%, #fff 0 7px, transparent 7px),
                    radial-gradient(circle at 52% 62%, #fff 0 7px, transparent 7px); }
.kit-art-t4_marquee { background: #101010;
  background-image: linear-gradient(90deg, #333 0 18%, transparent 18% 26%, #444 26% 52%,
                    transparent 52% 60%, #2b2b2b 60% 88%, transparent 88%); }
/* 새 템플릿의 작은 미리보기 — 이름만으로는 무엇인지 모른다. */
.kit-art-t7_minimal { background: #efeeea;
  background-image: linear-gradient(#131313 1px, transparent 1px),
                    linear-gradient(90deg, rgba(19,19,19,.5) 1px, transparent 1px);
  background-size: 100% 55%, 34% 100%; background-repeat: no-repeat; }
.kit-art-t8_id { background: #000;
  background-image: linear-gradient(#f4f1ea, #f4f1ea), linear-gradient(#333, #333);
  background-size: 62% 84%, 14% 26%;
  background-position: center, center; background-repeat: no-repeat; }
.kit-art-t9_poster { background: #1a1a1a;
  background-image: radial-gradient(circle at 42% 38%, #6a6a6a 0 26%, transparent 27%),
                    linear-gradient(0deg, rgba(0,0,0,.75), transparent 60%); }

.kit-style-more {
  position: absolute; left: .75rem; bottom: .6rem;
  font-size: .66rem; color: var(--ink-40); text-decoration: underline;
  text-underline-offset: .2em; cursor: pointer; background: none; border: 0;
}
.kit-style-more:hover { color: var(--ink-90); }

/* 설명은 키트 위에 겹쳐 뜬다. 창 안의 창이라 바깥 창을 흔들지 않는다. */
.kit-info { position: absolute; inset: 0; z-index: 3;
            display: flex; align-items: center; justify-content: center;
            padding: 1.2rem; background: rgba(255,255,255,.86);
            backdrop-filter: blur(2px); }
.kit-info[hidden] { display: none; }
.kit-info-card { width: 100%; max-width: 22rem; background: #fff;
                 border: 1px solid var(--line); border-radius: var(--r-md);
                 padding: 1.1rem 1.1rem 1rem; box-shadow: 0 18px 40px rgba(11,11,12,.14); }
.kit-info-card b { font-size: .95rem; }
.kit-info-card p { margin-top: .5rem; font-size: .8rem; line-height: 1.75; color: var(--ink-60); }

.kit-loading { padding: 3.5rem 0 3rem; text-align: center; }
.kit-spinner { display: inline-block; width: 34px; height: 34px; border-radius: 999px;
               border: 2px solid var(--line-2); border-top-color: var(--ink);
               animation: kit-spin .8s linear infinite; }
@keyframes kit-spin { to { transform: rotate(360deg); } }

.kit-msg { min-height: 1.2em; margin-top: .7rem; font-size: .74rem; color: var(--ink-60);
           text-align: center; }

@media (prefers-reduced-motion: reduce) { .kit-spinner { animation-duration: 2.4s; } }


/* ── 모임 앨범 ───────────────────────────────────────────────────────
 * 예정된 모임만 있는 화면은 '무슨 자리인지' 를 말해주지 못한다. 지난 자리의
 * 사진 몇 장이 그 일을 대신한다.
 */
.album-grid { display: grid; gap: .35rem;
              grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr)); }
@media (min-width: 640px) { .album-grid { gap: .5rem;
              grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); } }
.album-cell { position: relative; display: block; aspect-ratio: 1 / 1;
              overflow: hidden; border-radius: var(--r-sm); background: var(--wash-2); }
.album-cell img { width: 100%; height: 100%; object-fit: cover;
                  transition: transform .3s cubic-bezier(.2,.7,.3,1); }
.album-cell:hover img { transform: scale(1.04); }
.album-when { position: absolute; left: .4rem; bottom: .35rem;
              font-size: .58rem; letter-spacing: .06em; color: #fff;
              background: rgba(0,0,0,.45); border-radius: 999px; padding: .1rem .38rem;
              backdrop-filter: blur(4px); }
/* 영상은 눌러야 재생된다는 것을 미리 알려준다. */
.album-cell.is-video::after {
  content: "▶"; position: absolute; inset: 0; display: flex;
  align-items: center; justify-content: center;
  font-size: 1.1rem; color: #fff; text-shadow: 0 2px 10px rgba(0,0,0,.6);
  background: rgba(0,0,0,.18);
}

.album-form { margin-top: 1rem; padding: .9rem; border: 1px solid var(--line);
              border-radius: var(--r-md); background: var(--wash); }
.album-form.hidden { display: none; }
.album-form-row { display: flex; gap: .45rem; flex-wrap: wrap; }
.album-form-row + .album-form-row { margin-top: .45rem; }
.album-form-row .input { flex: 1 1 12rem; min-width: 0; background: #fff; }
.album-file { flex: 0 0 auto; cursor: pointer; max-width: 14rem; overflow: hidden;
              text-overflow: ellipsis; white-space: nowrap; background: #fff; }
.album-msg { min-height: 1.1em; margin-top: .45rem; font-size: .72rem; color: var(--ink-60); }

/* 크게 보기 — 사진은 사진대로, 영상은 그 자리에서 재생된다. */
.album-view { display: flex; flex-direction: column; }
.album-stage { background: var(--ink); display: flex; justify-content: center; }
.album-stage img { display: block; width: auto; height: auto;
                   max-width: min(96vw, 1100px); max-height: 74vh; object-fit: contain; }
.album-stage-video { width: min(92vw, 900px); aspect-ratio: 16 / 9; }
.album-stage-video iframe { width: 100%; height: 100%; border: 0; display: block; }
.album-foot { flex: none; background: #fff; border-top: 1px solid var(--line);
              padding: .9rem 1.1rem; display: flex; align-items: center;
              gap: .6rem; flex-wrap: wrap; }
.album-cap { font-size: .84rem; line-height: 1.6; width: 100%; }
.album-meta { font-size: .72rem; color: var(--ink-40); display: flex; gap: .35rem;
              flex-wrap: wrap; align-items: baseline; }
.album-meta b { color: var(--ink-90); font-weight: 700; }
.album-del { margin-left: auto; font-size: .72rem; height: 30px; }
.album-view .album-msg { padding: 0 1.1rem .8rem; background: #fff; }

@media (max-width: 640px) {
  .album-stage img { max-height: 66vh; max-width: 94vw; }
  .album-stage-video { width: 94vw; }
}


/* CV 가 있는 멤버 표시. 이름 옆에 아주 작게 — 카드의 주인공은 사람이다. */
.cv-badge {
  display: inline-flex; align-items: center; height: 16px; padding: 0 .34rem;
  border: 1px solid var(--line-2); border-radius: 999px;
  font-size: .56rem; font-weight: 800; letter-spacing: .08em;
  color: var(--ink-60); flex: none;
}

/* ── CV 쇼케이스 ─────────────────────────────────────────────────────
 * 카드 그림은 스크린샷이 아니라 그 페이지를 작게 띄운 것이다. 그래서 늘
 * 지금 상태이고, 서버에 브라우저를 두거나 바깥 서비스에 맡길 일이 없다.
 */
.sc-filters { display: flex; gap: .35rem; flex-wrap: wrap; }
.sc-chip {
  border: 1px solid var(--line); background: #fff; color: var(--ink-60);
  border-radius: 999px; padding: .34rem .8rem; font-size: .74rem; font-weight: 700;
  cursor: pointer; white-space: nowrap;
}
.sc-chip:hover { border-color: var(--line-2); color: var(--ink-90); }
.sc-chip.on { background: var(--ink); border-color: var(--ink); color: #fff; }

.sc-grid { display: grid; gap: 1rem; grid-template-columns: 1fr; }
@media (min-width: 640px)  { .sc-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .sc-grid { grid-template-columns: repeat(3, 1fr); } }

.sc-card {
  display: block; overflow: hidden; text-decoration: none; color: inherit;
  border: 1px solid var(--line); border-radius: var(--r-md); background: #fff;
  transition: border-color .15s ease, transform .18s cubic-bezier(.2,.7,.3,1),
              box-shadow .18s ease;
}
.sc-card:hover { border-color: var(--line-2); transform: translateY(-2px);
                 box-shadow: 0 12px 30px rgba(11,11,12,.10); }
.sc-card.hidden { display: none; }

/* 그림 자리 — PC 화면(1280×800)의 비율을 그대로 지킨다.
   여기에 height 를 함께 주면 aspect-ratio 가 그 높이에서 너비를 거꾸로
   계산해 상자가 통째로 접힌다(폭 2px 짜리 카드가 그렇게 나왔다). */
.sc-shot {
  position: relative; overflow: hidden; background: var(--wash-2);
  width: 100%; aspect-ratio: 1280 / 800;
  border-bottom: 1px solid var(--line);
}
.sc-shot iframe {
  position: absolute; inset: 0; border: 0;
  transform-origin: top left;
  /* 카드 전체가 링크다 — 안쪽 화면은 눌리지 않는다. */
  pointer-events: none;
  opacity: 0; transition: opacity .25s ease;
}
.sc-shot.ready iframe { opacity: 1; }
/* 뜨기 전에는 그 CV 의 대표 이미지를 깔아둔다. 빈 회색보다 낫다. */
.sc-poster { position: absolute; inset: 0; width: 100%; height: 100%;
             object-fit: cover; filter: blur(1px) saturate(.9); opacity: .5; }
.sc-shot.ready .sc-poster { opacity: 0; transition: opacity .25s ease; }

/* 그리는 중 — 카드가 '다 된 것처럼' 보이다가 갑자기 바뀌는 것이 제일 나쁘다.
   포스터를 덮고 크게 돌린다. 진행률을 아는 척하지는 않는다(알 수 없다). */
.sc-load {
  position: absolute; inset: 0; pointer-events: none;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .8rem;
  background: rgba(248, 248, 247, .82);
}
.sc-load::before {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(100deg,
              rgba(255,255,255,0) 22%, rgba(255,255,255,.75) 50%, rgba(255,255,255,0) 78%);
  background-size: 220% 100%;
  animation: sc-sweep 1.6s ease-in-out infinite;
}
.sc-load i {
  position: relative; width: 38px; height: 38px; border-radius: 50%;
  border: 3px solid rgba(11,11,12,.13); border-top-color: rgba(11,11,12,.62);
  animation: sc-spin .8s linear infinite;
}
.sc-load b {
  position: relative; font-size: .68rem; font-weight: 700; letter-spacing: .1em;
  color: var(--ink-40); text-transform: uppercase;
}
@keyframes sc-sweep { from { background-position: 120% 0 } to { background-position: -60% 0 } }
@keyframes sc-spin { to { transform: rotate(360deg) } }
.sc-shot.ready .sc-load { opacity: 0; transition: opacity .3s ease; }
.sc-shot.ready .sc-load::before { animation: none; }

/* 이미 한 번 그려 본 카드(warm)는 로더를 반 박자 늦게 세운다. 되돌아온
   화면은 대개 캐시에서 곧바로 뜨는데, 그 사이에 로더가 번쩍이면 없느니만
   못하다. 늦게 떠도 안 뜨는 것보다 낫고, 안 뜨면 그게 제일 낫다. */
.sc-shot.warm .sc-load { opacity: 0; animation: sc-appear .2s ease .5s forwards; }
.sc-shot.warm.ready .sc-load { animation: none; opacity: 0; }
@keyframes sc-appear { to { opacity: 1 } }

@media (prefers-reduced-motion: reduce) {
  .sc-load::before { animation: none; }
  .sc-load i { animation: none; border-top-color: rgba(11,11,12,.3); }
}

.sc-foot { display: flex; align-items: center; gap: .6rem; padding: .85rem 1rem; }
.sc-name { font-size: .9rem; font-weight: 800; letter-spacing: -.01em;
           overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sc-sub { margin-top: .1rem; font-size: .72rem; color: var(--ink-40);
          overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sc-kind { margin-left: auto; flex: none; font-size: .66rem; font-weight: 700;
           color: var(--ink-60); background: var(--wash); border-radius: 999px;
           padding: .22rem .55rem; }


/* 쇼케이스의 견본 표시 — 멤버의 CV 와 섞이지 않게. 채우지 않고 글자만. */
.sc-demo {
  margin-left: .4rem; padding: .05rem .3rem; border-radius: 4px;
  font-size: 9px; font-weight: 700; letter-spacing: .06em; vertical-align: middle;
  color: var(--ink-40); border: 1px solid var(--line-2);
}
