/* 'Noto Sans KR' — sitewide body/UI font. Self-hosted as a single variable-
   weight file (font-weight: 100 900 below lets the browser pick any weight
   in that range from it, so both the site's 400/700 uses are covered without
   shipping two separate files). Subset down from the original ~23,000-glyph
   file to ~11,800: the CJK Han block (~8,100 Chinese characters, unused on a
   Korean-only site) is dropped while every modern Hangul syllable, Latin
   letter/number, and common punctuation mark stays — nothing a person could
   actually type here goes missing. That took it from 5.2MB to 1.8MB. */
@font-face {
  font-family: 'Noto Sans KR';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('fonts/NotoSansKR-Variable.woff') format('woff');
}

/* 'Cafe24 Ssurround' — heading/display font (replaces Jua), used for
   prominent headings/numbers only (see --font-heading below), not body text.
   Self-hosted: only one weight was supplied, so it's used at its natural
   weight rather than a specific 400/700 pairing. */
@font-face {
  font-family: 'Cafe24Ssurround';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/Cafe24Ssurround.woff') format('woff');
}

:root {
  --color-base: #f9c2c4;
  --color-base-deep: #f3a6a9;
  --color-sub: #8a747a;
  --color-sub-light: #b89aa0;

  --color-bg: #fff9f7;
  --color-bg-mid: #fdf3f6; /* page-background gradient stop, matching the reference exactly */
  --color-bg-deep: #fbeef4; /* page-background gradient stop, matching the reference exactly */
  --color-bg-elevated: #ffffff;
  --color-text: #4a3b3f;
  --color-white: #ffffff;

  --radius-lg: 24px;
  --radius-md: 16px;
  --radius-full: 999px;

  /* Tinted (not grey) shadows built from --color-base's RGB (249,194,196) —
     this is the biggest single ingredient in the "soft glow" look: cards seem
     to glow gently in the site's own pink rather than casting an ordinary
     neutral shadow. Three weights mirror how the reference design escalates
     shadow strength with a card's visual prominence. */
  --shadow-soft: 0 8px 20px rgba(244, 168, 195, 0.22);
  --shadow-glow: 0 16px 40px rgba(244, 168, 195, 0.4);
  --shadow-pill: 0 4px 10px rgba(244, 168, 195, 0.4);

  /* Heading/number font — Noto Sans KR stays the default body/UI font
     everywhere; this is opted into deliberately for a handful of prominent
     spots (page titles, section headings, D-day numbers) the same way the
     reference design pairs a display font with a plain body font instead of
     using one typeface for everything. */
  --font-heading: 'Cafe24Ssurround', 'Noto Sans KR', sans-serif;
}

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

html {
  margin: 0;
  padding: 0;
  /* Plain fallback, not a gradient: html and body can end up different
     heights (a `min-height: 100%` percentage on body resolving against an
     auto-height html is genuinely ambiguous per spec — this is what actually
     caused it, confirmed via devtools showing html and body at different
     computed heights). If they only had TWO SEPARATE COPIES of the gradient
     each stretched to their own height, any leftover sliver of html peeking
     out below body would show a mismatched, independently-scaled gradient —
     a visible seam. A flat color close to the gradient's tail can't create
     that seam even if html ends up taller than body. */
  background: var(--color-bg-deep);
  min-height: 100vh;
}

/* "Sticky footer" layout: body is at least viewport-tall and lays its children
   out in a column. .page-content gets flex: 1, so it immediately claims all the
   leftover vertical space on first paint — before any page's JS has fetched or
   rendered a single thing. That means the footer's position is fixed relative
   to the viewport bottom from the very start; it doesn't shift when a page's
   content grows in after loading (e.g. the calendar filling with day cells),
   which is what made it visibly jump once the page-load reveal animation gave
   that moment enough time to actually be seen. Content taller than the viewport
   still simply grows past this reserved space and the page scrolls normally. */
body {
  margin: 0;
  padding: 0;
  /* The real gradient — lives only here, on the element that actually wraps
     all visible content (nav + page-content + footer) via the flex layout
     below, so it's the one whose height reliably matches the page's real
     content length. */
  background: linear-gradient(180deg, var(--color-bg) 0%, var(--color-bg-mid) 40%, var(--color-bg-deep) 100%);
  color: var(--color-text);
  font-family: 'Noto Sans KR', sans-serif;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.site-nav {
  flex-shrink: 0;
}

.page-content {
  flex: 1 0 auto;
}

.site-footer {
  flex-shrink: 0;
  transition: opacity 0.3s ease-out, transform 0.3s ease-out;
}

/* Same reveal pattern as .page-content — applied in each page's HTML from the
   start, then removed by JS at the same moment page-content's is, so the
   footer fades + rises in together with the content above it instead of
   just sitting there the whole time while the content above animates in. */
.site-footer.content-loading {
  opacity: 0;
  transform: translateY(10px);
}

a {
  color: inherit;
  text-decoration: none;
}

/* ---------- Top navigation ---------- */

.site-nav {
  position: sticky;
  top: 0;
  z-index: 100;
  display: grid;
  /* Both side columns share the leftover space equally (1fr each), which keeps
     the centre menu centred in the viewport while there's room. The min-content
     floor is what makes it degrade nicely: the right column can never shrink
     below the width its icons and buttons actually need, so once the window
     gets tight it stops giving ground and the left column keeps shrinking
     instead — sliding the menu gradually leftwards rather than letting the two
     sides collide. */
  grid-template-columns: minmax(min-content, 1fr) minmax(0, auto) minmax(min-content, 1fr);
  align-items: center;
  /* clamp(최소, 화면비례, 최대) = 화면이 좁아질수록 값이 부드럽게 줄어듦.
     예전엔 특정 폭에서 한 번에 확 줄여서 메뉴가 튀었는데, 이렇게 하면
     크기도 위치도 끊김 없이 서서히 변함. */
  gap: clamp(8px, 0.9vw, 12px);
  padding: 14px clamp(14px, 1.6vw, 24px);
  /* Translucent + blurred instead of solid white — content scrolling behind
     the sticky nav shows through softly rather than disappearing abruptly
     under a flat bar. Falls back to solid white automatically wherever
     backdrop-filter isn't supported, since the rgba background alone still
     reads fine without the blur. */
  background: rgba(255, 255, 255, 0.75);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 2px 20px rgba(244, 168, 195, 0.18);
}

.site-nav .site-nav-logo {
  grid-column: 1;
  justify-self: start;
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

.site-nav .site-nav-logo img {
  height: clamp(30px, 2.7vw, 38px);
  width: auto;
  display: block;
}

.site-nav .site-nav-links {
  grid-column: 2;
  justify-self: center;
  display: flex;
  align-items: center;
  gap: 6px;
  /* Last-resort horizontal clipping if the menu ever outgrows its track.
     overflow-y is pinned to hidden because leaving it at visible would make the
     browser compute it to auto and show a stray vertical scrollbar. */
  overflow-x: auto;
  overflow-y: hidden;
  background: #fff5f8;
  box-shadow: inset 0 0 0 1px rgba(244, 168, 195, 0.3);
  border-radius: var(--radius-full);
  padding: 6px;
}

.site-nav .site-nav-right {
  grid-column: 3;
  justify-self: end;
  display: flex;
  align-items: center;
  gap: clamp(6px, 0.8vw, 10px);
  /* No overflow here on purpose: setting overflow-x alone makes the browser
     compute overflow-y to auto as well, which turned this into a tiny scroll
     box and popped a scrollbar when a button was focused. Keeping it visible
     also lets the grid measure its real width (see min-content below). */
  flex-shrink: 0;
}

.site-nav .social-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: clamp(28px, 2.3vw, 34px);
  height: clamp(28px, 2.3vw, 34px);
  padding: 0;
  border-radius: 10px;
  overflow: hidden;
  background: #fdf1f1;
  flex-shrink: 0;
  transition: transform .1s ease;
}

.site-nav .social-icon:hover {
  transform: scale(1.08);
}

.site-nav .social-icon img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.site-nav .social-icon svg {
  width: clamp(16px, 1.35vw, 19px);
  height: clamp(16px, 1.35vw, 19px);
  color: var(--color-base-deep);
}

.site-nav a {
  flex-shrink: 0;
  padding: 10px 18px;
  font-size: 14px;
  font-weight: 600;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--color-sub);
  white-space: nowrap;
  transition: background .15s, color .15s;
}

.site-nav a:hover {
  background: #ffffff;
}

.site-nav a.site-nav-logo,
.site-nav a.site-nav-logo:hover {
  background: transparent;
  padding: 0;
}

.site-nav a.active {
  background: #ffffff;
  color: var(--color-base-deep);
  font-weight: 700;
  padding: 10px 20px;
  box-shadow: var(--shadow-pill);
}

.nav-login-btn {
  font-size: clamp(0.75rem, 0.35vw + 0.55rem, 0.85rem);
  padding: 7px clamp(11px, 1vw, 14px);
}

.broadcast-toggle,
.nav-text-btn {
  white-space: nowrap; /* never wrap the label to a second line — shrink instead */
}

.broadcast-toggle .bc-label-short {
  display: none; /* only shown once the nav gets too tight for the full label */
}

.broadcast-toggle {
  background: linear-gradient(135deg, var(--color-base), #ffd9e6);
  color: #ffffff;
  border-color: var(--color-base);
  font-size: 14px;
  font-weight: 700;
  box-shadow: var(--shadow-pill);
}

.broadcast-toggle:hover {
  border-color: var(--color-base-deep);
  box-shadow: 0 6px 16px rgba(244, 168, 195, 0.5);
}

#btnBroadcastMode.active {
  background: #ff6b6b;
  color: #ffffff;
  border-color: #ff6b6b;
}

/* On very small phones the quick menu's own row gets crowded too (four social
   icons plus the admin buttons), so drop the broadcast label to a bare ON/OFF. */
@media (max-width: 480px) {
  .broadcast-toggle,
  .nav-text-btn {
    font-size: 0.8rem;
    padding: 6px 10px;
  }
  .broadcast-toggle .bc-label-full {
    display: none;
  }
  .broadcast-toggle .bc-label-short {
    display: inline;
  }
}

.nav-lock-btn {
  box-sizing: border-box;
  width: clamp(32px, 2.7vw, 38px);
  height: clamp(32px, 2.7vw, 38px);
  min-width: clamp(32px, 2.7vw, 38px);
  padding: 0;
  margin: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  font-size: 1.1rem;
  border-radius: 10px;
  flex-shrink: 0;
}

.nav-lock-btn svg {
  display: block;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

.page-content {
  max-width: 900px;
  width: calc(100% - 32px);
  margin: 24px auto 40px;
  padding: 28px 24px 40px;
  background: #ffffff;
  border-radius: 28px;
  border: 1px solid #f4e2e2;
  box-shadow: var(--shadow-soft);
  transition: opacity 0.3s ease-out, transform 0.3s ease-out;
}

/* Applied in a page's HTML from the start, then removed by JS right after the
   first data-driven render finishes — so the white card and its content fade
   + rise in together as one motion, instead of the empty card sitting there
   first and the content snapping in separately once data arrives. */
.page-content.content-loading {
  opacity: 0;
  transform: translateY(10px);
}

/* ---------- Generic pieces reused across pages ---------- */

.btn {
  font-family: 'Noto Sans KR', sans-serif;
  color: var(--color-sub);
  background: var(--color-bg-elevated);
  border: 2px solid var(--color-base);
  border-radius: var(--radius-full);
  padding: 8px 16px;
  cursor: pointer;
  transition: transform .1s ease, border-color .1s ease;
}

.btn:hover {
  border-color: var(--color-base-deep);
}

.btn:active {
  transform: translateY(2px);
}

.card {
  background: var(--color-bg-elevated);
  border: 2px solid var(--color-base);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
  padding: 20px;
}

@keyframes modalBackdropFadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes modalPopIn {
  from { opacity: 0; transform: translateY(14px) scale(0.97); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(74, 54, 54, 0.35);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
  /* Replaying this on every open is what makes popups feel gradual instead of
     snapping on — a CSS `animation` (unlike `transition`) automatically
     restarts each time the element re-enters the render tree, which is
     exactly what happens when JS flips `display: none` to `flex`. No JS
     changes needed anywhere the many modals get shown/hidden across the site. */
  animation: modalBackdropFadeIn 0.18s ease-out;
}

.modal {
  background: #ffffff;
  border: 2px solid var(--color-base);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
  padding: 20px;
  width: 90%;
  max-width: 420px;
  max-height: 85vh;
  overflow-y: auto;
  color: var(--color-text);
  animation: modalPopIn 0.22s cubic-bezier(0.16, 1, 0.3, 1);
}

.modal h2 {
  margin-top: 0;
  color: var(--color-base-deep);
  font-weight: normal;
  font-family: var(--font-heading);
}

.modal label {
  display: block;
  margin: 12px 0 6px;
  color: var(--color-sub);
  font-size: 0.9rem;
}

.modal input[type=text],
.modal input[type=time],
.modal input[type=password],
.modal textarea {
  width: 100%;
  padding: 8px 12px;
  border-radius: var(--radius-md);
  border: 2px solid var(--color-base);
  background: #fff9f8;
  color: var(--color-text);
  font-family: 'Noto Sans KR', sans-serif;
}

.modal .modal-actions {
  display: flex;
  gap: 8px;
  margin-top: 16px;
  justify-content: flex-end;
}

.login-error {
  color: #c94f4f;
  margin-top: 8px;
  font-size: 0.85rem;
}


/* ---------- Mobile: collapse nav links/social/lock into a quick menu ---------- */

.quick-menu-toggle {
  display: none; /* only revealed by the collapse breakpoint below */
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--color-base-deep);
  cursor: pointer;
  flex-shrink: 0;
}

/* Base nav values above now match the reference's exact fixed pixels (14px
   font, 6px gaps) rather than scaling continuously with viewport width, so
   this zone restores the safety margin that scaling used to provide —
   without it, the same overlap issue fixed earlier would come back on
   tablet-ish widths, before the nav collapses into the hamburger menu below. */
@media (max-width: 1150px) and (min-width: 851px) {
  .site-nav .site-nav-links {
    gap: 3px;
    padding: 4px;
  }
  .site-nav a {
    padding: 8px 12px;
    font-size: 12px;
  }
  .site-nav a.active {
    padding: 8px 13px;
  }
}

/* Below this the row genuinely can't hold logo + menu + social + admin buttons
   at any readable size, so everything past the logo folds into the quick menu. */
@media (max-width: 850px) {
  .site-nav {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0;
    padding: 10px 14px;
  }

  .quick-menu-toggle {
    display: inline-flex;
  }

  .site-nav .site-nav-links,
  .site-nav .site-nav-right {
    display: none;
    flex-basis: 100%;
    width: 100%;
    justify-content: center;
    justify-self: auto;
    margin-top: 12px;
    background: none;
    padding: 0;
  }

  .site-nav .site-nav-links {
    flex-wrap: wrap;
    background: #f1f1f4;
    border-radius: var(--radius-md);
    padding: 8px;
  }

  .site-nav .site-nav-right {
    flex-wrap: wrap;
    gap: 10px;
  }

  .site-nav .site-nav-right #btnLoginToggle {
    margin-left: auto;
  }

  .site-nav.menu-open .site-nav-links,
  .site-nav.menu-open .site-nav-right {
    display: flex;
  }
}

/* ---------- Legal pages (terms / privacy) ---------- */

.legal-page {
  max-width: 760px;
  line-height: 1.7;
  color: var(--color-text);
}

.legal-page h1 {
  color: var(--color-base-deep);
  margin-bottom: 20px;
}

.legal-page h2 {
  color: var(--color-base-deep);
  font-size: 1.1rem;
  margin: 28px 0 10px;
}

.legal-page p {
  margin: 0 0 12px;
}

.legal-page ul,
.legal-page ol {
  margin: 0 0 12px;
  padding-left: 22px;
}

.legal-page li {
  margin-bottom: 6px;
}

.legal-page a {
  color: var(--color-base-deep);
}

.legal-page hr {
  border: none;
  border-top: 1px solid #f4e2e2;
  margin: 24px 0;
}

/* ---------- Footer ---------- */

.site-footer {
  max-width: 900px;
  margin: 0 auto 32px;
  padding: 0 24px;
  text-align: center;
  color: var(--color-sub-light);
  font-size: 0.8rem;
}

/* Covers every link in the footer (이용약관/개인정보처리방침 AND the email
   line below) — previously only .site-footer-links a was set, so the email
   link fell through to the plain inherited --color-sub-light instead of
   matching the other links, showing as a visibly lighter line. */
.site-footer a {
  color: var(--color-sub);
}

/* The "Contact |" plain text isn't a link, so the fix above (which only
   targets <a>) left it inheriting .site-footer's lighter default color while
   the email link next to it was darker — splitting one line into two colors.
   Coloring the whole paragraph the same way as the links keeps the line
   visually consistent. */
.site-footer p {
  color: var(--color-sub);
}

.site-footer-links {
  margin-bottom: 8px;
}

.site-footer-links span {
  margin: 0 8px;
  color: var(--color-sub-light);
}

/* ---------- Private-event lock icon (used next to event text) ---------- */

.private-lock-icon {
  display: inline-flex;
  align-items: center;
  vertical-align: -2px;
  margin-right: 4px;
}

.private-lock-icon svg {
  display: block;
  width: 14px;
  height: 14px;
}

/* ---------- Installed app mode ----------
   The `pwa-app` class is added by JS (nav-auth.js on most pages, an inline
   check on the schedule page) whenever the site is running in its own
   installed app window rather than a regular browser tab. Re-checking with JS
   on every load — including the reload that login/logout trigger — is what
   keeps this consistent; a CSS-only `display-mode` media query occasionally
   didn't re-apply cleanly right after that reload.
   The installed app is meant to be "just the schedule": the entire top nav
   bar and the legal-page footer disappear. On the schedule page specifically,
   login/logout, 방송 모드 and 멤버 관리 get relocated (via JS) out of the nav
   and into the calendar header next to the Today button before the nav is
   hidden, so they're still reachable. */
html.pwa-app .site-nav,
html.pwa-app .site-footer {
  display: none !important;
}

/* 로그인 버튼(모든 페이지 공용) — 평소엔 .btn 기본값(연한 --color-base) 테두리를
   그대로 물려받고, .btn:hover가 --color-base-deep으로 바꿔주는 동작도 자동으로
   그대로 적용됨. 별도 override 불필요. */

/* ---------- 일정 카드 (공용 컴포넌트) ----------
   일정표 탭의 날짜 팝업과 홈 화면의 일정 팝업이 똑같은 모양을 쓰도록 여기
   한 곳에서 관리함. 두 페이지가 각자 스타일을 따로 두면 조금씩 달라지는
   문제(실제로 있었음)를 방지하는 목적. .day-event-list를 부모로 하는
   .event-row 카드 하나가 이 컴포넌트의 단위. */
.day-event-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 60vh;
  overflow-y: auto;
}

.day-event-list .event-row {
  border: 1px solid #f4e2e2;
  border-radius: 14px;
  background: var(--color-bg);
  padding: 12px 14px;
}

.event-row-inner {
  display: flex;
  align-items: center;
  min-height: 36px;
}

.event-row-content {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 6px;
}

.event-row-title-line {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
}

.event-title {
  font-size: 15px;
  color: var(--color-text);
  font-family: var(--font-heading);
}

.event-time-badge {
  display: inline-block;
  align-self: center;
  padding: 7px 16px;
  border-radius: var(--radius-full);
  background: #ffffff;
  color: var(--color-base-deep);
  font-size: 13px;
  font-weight: 800;
}

/* 관리자 수정/삭제 버튼 — 일정표 탭에서만 실제로 만들어지는 요소(홈은 이
   버튼을 아예 안 만듦). 제목 줄(event-row-title-line) 기준으로 배치해서,
   배너 이미지처럼 카드가 길어져도 버튼이 사진 한가운데로 밀리지 않음. */
.day-event-list .event-row .event-row-actions {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  gap: 4px;
  opacity: 0.9;
}

.day-event-list .event-row .btn-edit,
.day-event-list .event-row .btn-delete {
  padding: 6px 10px;
  border: 1px solid #f4e2e2;
  background: var(--color-bg-elevated);
  border-radius: 8px;
  color: var(--color-sub);
  cursor: pointer;
  font-family: 'Noto Sans KR', sans-serif;
  font-size: 12px;
}

.day-event-list .event-row .btn-edit:hover,
.day-event-list .event-row .btn-delete:hover {
  color: var(--color-base-deep);
  border-color: var(--color-base);
}
