/* ==========================================================================
   Commeet design system

   Palette, typography and component shapes follow the PCSS site
   (POSTECH Computer Scientist Search): crimson primary, slate-navy for
   secondary actions and headings, light-gray page on white cards, and the
   dark POSTECH footer.
   ========================================================================== */

:root {
  /* Brand crimson, background/button role - rgba(200, 1, 80) */
  --color-primary: #c80150;
  --color-primary-hover: #c2326c;
  --color-primary-dark: #aa003c;
  --color-primary-pale: rgba(200, 1, 80, 0.08);
  --color-primary-pale-2: rgba(200, 1, 80, 0.16);
  --color-primary-rgb: 200, 1, 80;

  /* Crimson family, text/icon/link role. Equal to --color-primary in light
     mode; re-tuned independently in dark mode, since a color that reads
     well as a solid button background rarely also reads well as text on a
     dark page (opposite contrast requirements). */
  --color-accent: #c80150;

  /* Slate navy - secondary buttons, and (via the pale variants) selected /
     hover chrome such as the active nav link or a picked respondent filter.
     Used more broadly than just headings, so the page doesn't read as
     "crimson everywhere" - navy carries the UI-chrome / selection states. */
  --color-navy: #34495e;
  --color-navy-hover: #2c3e50;
  --color-navy-pale: rgba(52, 73, 94, 0.08);
  --color-navy-pale-2: rgba(52, 73, 94, 0.16);

  /* Slate-navy family, heading/label text role - same split rationale as
     --color-accent above. */
  --color-heading: #34495e;

  --color-accent-yellow: #f5c344;

  --color-warning-bg: #fdf3d9;
  --color-warning-border: #f0dfa8;
  --color-warning-text: #7a5b0a;

  --color-danger: #c62828;
  --color-danger-hover: #a91d1d;
  --color-danger-bg: #ffebee;
  --color-danger-border: #ef9a9a;
  --color-danger-text: #c62828;
  --color-danger-rgb: 198, 40, 40; /* same in dark mode too - --color-danger doesn't change between themes */
  --color-success: #2e7d32;

  --color-bg: #f9f9f9;
  --color-surface: #ffffff;
  --color-surface-2: #f1f3f5;
  --color-surface-3: #e9ecef;
  --color-border: #ddd;
  --color-border-light: #eee;
  --color-input-border: #ccc;
  --color-grid-faint-border: #f4f4f4;

  --color-text: #333;
  --color-text-muted: #666;
  --color-text-faint: #999;
  --color-text-rgb: 51, 51, 51;
  --color-text-on-primary: #ffffff;
  --color-neutral-text: #495057;

  /* Dark POSTECH footer - deliberately the same in both site themes: it
     carries the official POSTECH mark and always stays dark. */
  --color-footer-bg: #2b2b2b;
  --color-footer-text: #aaa;
  --color-footer-muted: #999;
  --color-footer-link: #bbb;
  --color-footer-copy: #666;
  --color-footer-border: #444;

  --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.1);
  --shadow-lg: 0 8px 30px rgba(0, 0, 0, 0.2);

  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 8px;
  --radius-pill: 999px;

  --header-height: 72px;
  --container-width: 1400px;

  /* Availability grid sizing - overridden on small screens so more days fit */
  --grid-label-w: 64px;
  --grid-col-min: 64px;
  --grid-head-h: 56px;
  --grid-row-h: 16px;

  --font-sans: 'Noto Sans KR', 'Pretendard', -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;
}

/* ==========================================================================
   Dark mode

   Redefines the tokens above for a dark palette (contrast-checked against
   WCAG 2.1 AA - see contrast.py used while designing this). Applied
   automatically when the OS prefers dark, unless the user has explicitly
   picked "light" via the header toggle; always applied when the user has
   explicitly picked "dark". See static/js/ui.js for the toggle itself.
   ========================================================================== */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
  /* Crimson stays the button/background role - kept close to the light
     value since white-on-button contrast doesn't depend on page background,
     just brightened slightly for a bit more pop against the dark page.
     Hover inverts to *darker* (not lighter, unlike light mode) because the
     base is already near the ceiling for readable white text on top. */
  --color-primary: #d4176e;
  --color-primary-hover: #b8104f;
  --color-primary-dark: #ffb3cc; /* now a foreground value: badge/chip text on a dark pale wash */
  --color-primary-pale: rgba(255, 111, 156, 0.14);
  --color-primary-pale-2: rgba(255, 111, 156, 0.22);
  --color-primary-rgb: 255, 111, 156;

  --color-accent: #ff6f9c; /* links/icons/text on the dark page - 6.97:1 against --color-bg */

  --color-navy: #4a6178;
  --color-navy-hover: #5a7288;
  --color-navy-pale: rgba(148, 178, 204, 0.14);
  --color-navy-pale-2: rgba(148, 178, 204, 0.22);

  --color-heading: #c3d3e3; /* light steel-blue - headings need to be bright, not navy-dark, on a dark page */

  --color-accent-yellow: #f5c344;

  --color-warning-bg: #3d3116;
  --color-warning-border: #6b551f;
  --color-warning-text: #f2c675;

  --color-danger: #c62828;
  --color-danger-hover: #a91d1d;
  --color-danger-bg: #3a1a1e;
  --color-danger-border: #5c2328;
  --color-danger-text: #ff6b6f;
  --color-success: #2e7d32;

  --color-bg: #12151b;
  --color-surface: #1b1f27;
  --color-surface-2: #242933;
  --color-surface-3: #2d323d;
  --color-border: #333944;
  --color-border-light: #2a2f38;
  --color-input-border: #3d4450;
  --color-grid-faint-border: rgba(255, 255, 255, 0.05);

  --color-text: #eef0f3;
  --color-text-muted: #a8adb8;
  --color-text-faint: #8b909b;
  --color-text-rgb: 238, 240, 243;
  --color-text-on-primary: #ffffff;
  --color-neutral-text: #c7ccd3;

  --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.28);
  --shadow-md: 0 4px 14px rgba(0, 0, 0, 0.4);
  --shadow-lg: 0 12px 36px rgba(0, 0, 0, 0.55);
  }
}

:root[data-theme="dark"] {
  /* Crimson stays the button/background role - kept close to the light
     value since white-on-button contrast doesn't depend on page background,
     just brightened slightly for a bit more pop against the dark page.
     Hover inverts to *darker* (not lighter, unlike light mode) because the
     base is already near the ceiling for readable white text on top. */
  --color-primary: #d4176e;
  --color-primary-hover: #b8104f;
  --color-primary-dark: #ffb3cc; /* now a foreground value: badge/chip text on a dark pale wash */
  --color-primary-pale: rgba(255, 111, 156, 0.14);
  --color-primary-pale-2: rgba(255, 111, 156, 0.22);
  --color-primary-rgb: 255, 111, 156;

  --color-accent: #ff6f9c; /* links/icons/text on the dark page - 6.97:1 against --color-bg */

  --color-navy: #4a6178;
  --color-navy-hover: #5a7288;
  --color-navy-pale: rgba(148, 178, 204, 0.14);
  --color-navy-pale-2: rgba(148, 178, 204, 0.22);

  --color-heading: #c3d3e3; /* light steel-blue - headings need to be bright, not navy-dark, on a dark page */

  --color-accent-yellow: #f5c344;

  --color-warning-bg: #3d3116;
  --color-warning-border: #6b551f;
  --color-warning-text: #f2c675;

  --color-danger: #c62828;
  --color-danger-hover: #a91d1d;
  --color-danger-bg: #3a1a1e;
  --color-danger-border: #5c2328;
  --color-danger-text: #ff6b6f;
  --color-success: #2e7d32;

  --color-bg: #12151b;
  --color-surface: #1b1f27;
  --color-surface-2: #242933;
  --color-surface-3: #2d323d;
  --color-border: #333944;
  --color-border-light: #2a2f38;
  --color-input-border: #3d4450;
  --color-grid-faint-border: rgba(255, 255, 255, 0.05);

  --color-text: #eef0f3;
  --color-text-muted: #a8adb8;
  --color-text-faint: #8b909b;
  --color-text-rgb: 238, 240, 243;
  --color-text-on-primary: #ffffff;
  --color-neutral-text: #c7ccd3;

  --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.28);
  --shadow-md: 0 4px 14px rgba(0, 0, 0, 0.4);
  --shadow-lg: 0 12px 36px rgba(0, 0, 0, 0.55);
}


* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
}

/* 스크롤바를 항상 보이게.
 *
 * macOS의 오버레이 스크롤바는 스크롤하는 동안에만 나타나서, 목록이 더
 * 있는지(응답자 목록, 면담 기록 폼, 격자) 알 수 없다는 지적이 있었습니다.
 * WebKit/Chromium은 ::-webkit-scrollbar를 정의하는 순간 오버레이 대신
 * 항상 보이는 자체 스크롤바를 씁니다. Firefox는 강제로 상시 표시할 방법이
 * 없어 색·굵기만 맞춥니다. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--color-border) transparent;
}
::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
::-webkit-scrollbar-track {
  background: transparent;
}
::-webkit-scrollbar-thumb {
  background: var(--color-border);
  border-radius: 5px;
  /* 트랙과 사이를 띄워 가는 막대처럼 보이게 */
  border: 2px solid transparent;
  background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--color-text-faint);
  background-clip: padding-box;
}

/* hidden 속성이 항상 먹도록.
 *
 * 브라우저 기본은 `[hidden] { display: none }` 인데, display를 지정한 클래스
 * 규칙(.btn의 inline-flex 등)이 우선순위에서 이겨 버립니다. 그래서 JS에서
 * `el.hidden = true`로 감춘 것이 화면에는 그대로 남아 있었습니다 - 저장 전
 * 면담 기록에서 "신청서 열기"가 계속 보여 누르면 없는 기록을 열려다 오류가
 * 났고, 응답자별 입력칸도 같은 이유로 남아 있었습니다. */
[hidden] {
  display: none !important;
}

body {
  font-family: var(--font-sans);
  background-color: var(--color-bg);
  color: var(--color-text);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
  overflow-wrap: break-word;
}

main {
  flex: 1;
}

a {
  color: var(--color-accent);
  text-decoration: none;
}
a:hover {
  color: var(--color-primary-dark);
  text-decoration: underline;
}

h1, h2, h3, h4 {
  margin: 0 0 10px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--color-heading);
}

p {
  margin: 0 0 12px;
  line-height: 1.6;
  color: var(--color-text-muted);
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

button {
  font-family: inherit;
}

img {
  max-width: 100%;
}

.container {
  max-width: var(--container-width);
  margin: 0 auto;
  padding: 0 20px;
  width: 100%;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
}

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: none;
  border-radius: var(--radius-md);
  padding: 11px 18px;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
  transition: background-color 0.2s, color 0.2s;
  white-space: nowrap;
  line-height: 1.2;
  text-decoration: none;
}
.btn:hover {
  text-decoration: none;
}
.btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.btn-primary {
  background-color: var(--color-primary);
  color: var(--color-text-on-primary);
}
.btn-primary:hover:not(:disabled) {
  background-color: var(--color-primary-hover);
  color: #fff;
}

.btn-secondary {
  background-color: var(--color-navy);
  color: #fff;
}
.btn-secondary:hover:not(:disabled) {
  background-color: var(--color-navy-hover);
  color: #fff;
}

.btn-ghost {
  background-color: var(--color-surface-2);
  color: var(--color-neutral-text);
}
.btn-ghost:hover:not(:disabled) {
  background-color: var(--color-surface-3);
  color: var(--color-neutral-text);
}
.btn-ghost.active {
  background-color: var(--color-primary);
  color: #fff;
}

.btn-danger {
  background-color: var(--color-danger);
  color: #fff;
}
.btn-danger:hover:not(:disabled) {
  background-color: var(--color-danger-hover);
  color: #fff;
}

.btn-sm {
  padding: 8px 15px;
  font-size: 13px;
}

.btn-icon {
  padding: 7px;
  min-width: 32px;
  border-radius: var(--radius-md);
  background: transparent;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  line-height: 1;
}
.btn-icon:hover {
  background-color: var(--color-surface-2);
  color: var(--color-text);
}

.btn-block {
  width: 100%;
}

/* ==========================================================================
   Forms
   ========================================================================== */

.field {
  margin-bottom: 14px;
}
.field label {
  display: block;
  font-size: 14px;
  font-weight: 700;
  margin-bottom: 6px;
  color: var(--color-heading);
}
.field .hint {
  font-size: 12px;
  color: var(--color-text-muted);
  margin-top: 5px;
  line-height: 1.5;
}

.input,
select.input,
textarea.input {
  width: 100%;
  padding: 10px;
  border: 1px solid var(--color-input-border);
  border-radius: var(--radius-md);
  font-size: 15px;
  font-family: inherit;
  color: var(--color-text);
  background-color: var(--color-surface);
  transition: border-color 0.2s, box-shadow 0.2s;
}
.input:focus,
select.input:focus,
textarea.input:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-pale);
}
.input:disabled {
  background-color: var(--color-surface-2);
  color: var(--color-text-faint);
}
textarea.input {
  resize: vertical;
  min-height: 72px;
}

.input-row {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
}
.input-row .input {
  flex: 1;
  min-width: 140px;
}

.checkbox-row {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  font-size: 14px;
  color: var(--color-text);
  cursor: pointer;
  margin-bottom: 10px;
  line-height: 1.5;
}
.checkbox-row input[type="checkbox"] {
  margin-top: 3px;
  accent-color: var(--color-primary);
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}
.checkbox-row .checkbox-copy .desc {
  color: var(--color-text-faint);
  font-size: 12px;
  margin-top: 2px;
}

.toggle-group {
  display: inline-flex;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 3px;
  background-color: var(--color-surface);
}
.toggle-group button {
  border: none;
  background: transparent;
  padding: 7px 16px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 700;
  color: var(--color-text-muted);
  cursor: pointer;
  transition: background-color 0.2s, color 0.2s;
}
.toggle-group button.active {
  background-color: var(--color-navy);
  color: #fff;
}

.chip-input {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 8px;
  border: 1px solid var(--color-input-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
}
.chip-input input {
  border: none;
  outline: none;
  flex: 1;
  min-width: 130px;
  font-size: 14px;
  padding: 5px;
  font-family: inherit;
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background-color: var(--color-primary-pale);
  color: var(--color-primary-dark);
  border-radius: var(--radius-sm);
  padding: 4px 6px 4px 10px;
  font-size: 13px;
  font-weight: 700;
}
.chip button {
  border: none;
  background: transparent;
  color: inherit;
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
  padding: 0 2px;
}

.contact-picker {
  position: relative;
  margin-top: 6px;
}
.contact-picker-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 20;
  width: 360px;
  max-width: 90vw;
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: 10px;
}
.contact-picker-dropdown .input {
  margin-bottom: 6px;
}
.contact-picker-filters {
  max-height: 140px;
  overflow-y: auto;
  padding: 6px 8px;
  margin-bottom: 6px;
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-sm);
  background-color: var(--color-surface-2);
}
.contact-picker-filters .contact-filter-group {
  margin-bottom: 6px;
}
.contact-picker-filters .checkbox-row {
  margin: 0 10px 4px 0 !important;
}
.contact-picker-filters .checkbox-copy {
  font-size: 12px;
}
.contact-picker-list {
  max-height: 300px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.contact-picker-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  text-align: left;
  padding: 7px 8px;
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-text);
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
}
.contact-picker-row:hover {
  background-color: var(--color-primary-pale);
}
.contact-picker-name {
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.contact-picker-email {
  color: var(--color-text-faint);
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dow-toggle-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.dow-toggle {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 1px solid var(--color-border);
  background-color: var(--color-surface);
  color: var(--color-text);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  transition: background-color 0.2s, border-color 0.2s, color 0.2s;
}
.dow-toggle.active {
  background-color: var(--color-primary);
  border-color: var(--color-primary);
  color: #fff;
}

.form-error {
  color: var(--color-danger-text);
  font-size: 13px;
  margin: -4px 0 12px;
  min-height: 1em;
  line-height: 1.5;
}

.expandable {
  border-top: 1px solid var(--color-border-light);
  padding-top: 14px;
  margin-top: 6px;
}
.expandable summary {
  cursor: pointer;
  font-weight: 700;
  font-size: 14px;
  color: var(--color-heading);
  list-style: none;
  display: flex;
  align-items: center;
  gap: 6px;
}
.expandable summary::-webkit-details-marker {
  display: none;
}
.expandable summary::before {
  content: '▸';
  color: var(--color-accent);
  transition: transform 0.2s;
}
.expandable[open] summary::before {
  transform: rotate(90deg);
}
.expandable .expandable-body {
  padding-top: 14px;
}

/* ==========================================================================
   Header
   ========================================================================== */

.site-header {
  background-color: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  position: sticky;
  top: 0;
  z-index: 40;
}
.site-header .container {
  min-height: var(--header-height);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-top: 10px;
  padding-bottom: 10px;
}

.header-logos {
  display: flex;
  align-items: center;
  gap: 16px;
  min-width: 0;
}
/* Sized so the crimson wordmark (the top ~60% of the signature; the rest is
   the university line) sits comfortably against the "Commeet" title next to it,
   rather than towering over it. */
.header-logo-left img {
  height: 26px;
  width: auto;
  display: block;
  /* Without this the flex row squeezes the image horizontally on narrow
     screens, distorting the wordmark instead of just letting it be small. */
  flex-shrink: 0;
}
.header-logo-left {
  flex-shrink: 0;
  display: flex;
}
/* Two versions of the POSTECH signature: the crimson wordmark is identical
   in both, only the neutral "Pohang University of Science and Technology"
   line differs - dark ink on light backgrounds, light ink on dark ones.
   Swapping the asset keeps the mark itself untouched, which the earlier
   white-plate workaround could not do. */
.header-logo-left .logo-dark {
  display: none;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .header-logo-left .logo-light {
    display: none;
  }
  :root:not([data-theme="light"]) .header-logo-left .logo-dark {
    display: block;
  }
}
:root[data-theme="dark"] .header-logo-left .logo-light {
  display: none;
}
:root[data-theme="dark"] .header-logo-left .logo-dark {
  display: block;
}
:root[data-theme="light"] .header-logo-left .logo-light {
  display: block;
}
:root[data-theme="light"] .header-logo-left .logo-dark {
  display: none;
}
.header-divider {
  width: 1px;
  height: 28px;
  background-color: var(--color-border);
  flex-shrink: 0;
}

.theme-toggle-btn {
  color: var(--color-text-muted);
}
.theme-toggle-btn .theme-icon-sun {
  display: none;
}
.theme-toggle-btn .theme-icon-moon {
  display: block;
}
:root[data-theme="dark"] .theme-toggle-btn .theme-icon-sun {
  display: block;
}
:root[data-theme="dark"] .theme-toggle-btn .theme-icon-moon {
  display: none;
}

.brand {
  display: flex;
  align-items: baseline;
  gap: 9px;
  min-width: 0;
}
.brand:hover {
  text-decoration: none;
}
.brand-mark {
  font-size: 25px;
  font-weight: 800;
  color: var(--color-accent);
  letter-spacing: -0.02em;
  line-height: 1;
}
.brand-sub {
  font-size: 12px;
  color: var(--color-text-muted);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.nav-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
.nav-links {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-right: 6px;
}
.nav-links a {
  padding: 8px 13px;
  border-radius: var(--radius-md);
  color: var(--color-heading);
  font-weight: 700;
  font-size: 14px;
}
.nav-links a:hover,
.nav-links a.active {
  background-color: var(--color-navy-pale);
  color: var(--color-heading);
  text-decoration: none;
}

.avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background-color: var(--color-navy);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 14px;
  flex-shrink: 0;
}
.avatar.sm {
  width: 28px;
  height: 28px;
  font-size: 12px;
}

.user-menu {
  position: relative;
}
.user-menu-trigger {
  display: flex;
  align-items: center;
  gap: 8px;
  background-color: var(--color-surface-2);
  border: none;
  border-radius: var(--radius-pill);
  padding: 4px 14px 4px 4px;
  cursor: pointer;
  transition: background-color 0.2s;
}
.user-menu-trigger:hover {
  background-color: var(--color-surface-3);
}
.user-menu-name {
  font-size: 14px;
  font-weight: 700;
  color: var(--color-heading);
  max-width: 130px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.user-menu-dropdown {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  min-width: 180px;
  padding: 6px;
  display: none;
  z-index: 50;
}
.user-menu-dropdown.open {
  display: block;
}
.user-menu-dropdown a,
.user-menu-dropdown button {
  display: block;
  width: 100%;
  text-align: left;
  padding: 10px;
  border-radius: var(--radius-md);
  border: none;
  background: transparent;
  color: var(--color-text);
  font-size: 14px;
  cursor: pointer;
  font-family: inherit;
}
.user-menu-dropdown a:hover,
.user-menu-dropdown button:hover {
  background-color: var(--color-primary-pale);
  color: var(--color-primary-dark);
  text-decoration: none;
}

/* ==========================================================================
   Footer - POSTECH official look
   ========================================================================== */

.site-footer {
  background-color: var(--color-footer-bg);
  color: var(--color-footer-text);
  width: 100%;
  padding: 40px 0;
  margin-top: auto;
  border-top: 1px solid var(--color-footer-border);
}
.footer-inner {
  max-width: var(--container-width);
  margin: 0 auto;
  padding: 0 20px;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 30px;
}

.footer-left {
  flex: 1;
  min-width: 300px;
}
.footer-title {
  color: #fff;
  font-weight: 700;
  font-size: 14px;
  margin-bottom: 15px;
  text-transform: uppercase;
}
.footer-info {
  font-size: 12px;
  line-height: 1.6;
  color: var(--color-footer-muted);
}
.footer-info p {
  margin: 4px 0;
  color: inherit;
  font-size: inherit;
}
.footer-info a {
  color: var(--color-footer-link);
  text-decoration: none;
  transition: color 0.3s;
}
.footer-info a:hover {
  color: #fff;
  text-decoration: underline;
}
.footer-credit {
  font-size: 12px;
  color: var(--color-footer-muted);
  margin: 8px 0 0;
}
.footer-links {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 10px;
  font-size: 12px;
}
.footer-links a {
  color: var(--color-footer-link);
}
.footer-links a:hover {
  color: #fff;
}
.copyright {
  margin-top: 20px;
  font-size: 11px;
  color: var(--color-footer-copy);
}

.footer-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 15px;
}
.footer-logos {
  display: flex;
  align-items: center;
  gap: 15px;
}
.footer-logo-img {
  height: 20px;
  width: auto;
  opacity: 0.9;
}
.footer-logo-text {
  width: 150px;
  height: auto;
  opacity: 0.8;
}
.footer-privacy {
  margin-top: 15px;
  font-size: 12px;
  color: #ddd;
  text-decoration: none;
  font-weight: 700;
  opacity: 0.9;
}
.footer-privacy:hover {
  color: #fff;
}

/* ==========================================================================
   Cards / surfaces
   ========================================================================== */

.card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.card-pad {
  padding: 20px;
}

.auth-card {
  max-width: 460px;
  margin: 40px auto 60px;
  padding: 24px;
}
.auth-card h1 {
  text-align: center;
  color: var(--color-accent);
  font-size: 24px;
  margin: 6px 0 14px;
}
.auth-card .subtitle {
  text-align: center;
  margin-bottom: 22px;
  font-size: 14px;
}
.auth-switch {
  text-align: center;
  font-size: 13px;
  margin-top: 14px;
  color: var(--color-text-muted);
  line-height: 1.6;
}
.auth-switch a {
  font-weight: 700;
}

/* Informational / error panels, as used across PCSS pages */
.notice {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 14px 18px;
  margin: 0 0 18px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);
  line-height: 1.6;
  font-size: 14px;
}
.notice b,
.notice strong {
  color: var(--color-accent);
}
.notice p {
  margin: 0;
  font-size: inherit;
}
.notice p + p {
  margin-top: 6px;
}

.error-msg {
  background-color: var(--color-danger-bg);
  color: var(--color-danger-text);
  border: 1px solid var(--color-danger-border);
  padding: 14px 18px;
  margin: 0 0 18px;
  border-radius: var(--radius-lg);
  font-weight: 700;
  font-size: 14px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);
  line-height: 1.6;
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  border-radius: var(--radius-sm);
  font-size: 11px;
  font-weight: 700;
  background-color: var(--color-primary-pale);
  color: var(--color-primary-dark);
  white-space: nowrap;
}
.badge-muted {
  background-color: var(--color-surface-2);
  color: var(--color-text-muted);
}

/* ==========================================================================
   Dialogs
   ========================================================================== */

.dialog-backdrop {
  position: fixed;
  inset: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: none;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 100;
}
.dialog-backdrop.open {
  display: flex;
}
.dialog {
  background-color: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  width: 100%;
  max-width: 520px;
  max-height: 88vh;
  overflow-y: auto;
  padding: 22px;
}
.dialog.dialog-sm {
  max-width: 400px;
}
.dialog.dialog-md {
  max-width: 640px;
}
.dialog.dialog-lg {
  max-width: 840px;
}

/* 크게 쓰는 창 (면담 기록 폼). `max-height`가 아니라 `height`인 것은 의도적입니다 -
   내용이 많든 적든 항상 같은 크기여서, 참석자가 늘거나 줄어도 창이 출렁이지
   않고 안쪽이 스크롤됩니다 (.rec-form-body 참고). */
.dialog.dialog-xl {
  width: 92vw;
  max-width: 1300px;
  height: 85vh;
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.dialog.dialog-xl .dialog-header {
  flex-shrink: 0;
}

/* Side-by-side layout for the "새 일정 만들기" dialog, so the date-picker
   calendar (tall) sits next to the invite/advanced-options fields instead
   of stacking everything into one long scroll. Collapses back to a single
   column below the breakpoint - guests, without the right column's fields,
   naturally end up narrower there anyway, which is fine unstacked. */
.ne-columns {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 28px;
  align-items: start;
}
.ne-col {
  min-width: 0;
}
@media (max-width: 700px) {
  .ne-columns {
    grid-template-columns: 1fr;
  }
}
.dialog-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 16px;
}
.dialog-header h2 {
  font-size: 18px;
  margin: 0;
}
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 20px;
  flex-wrap: wrap;
}

/* ==========================================================================
   Snackbar
   ========================================================================== */

#snackbar-root {
  position: fixed;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 200;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
  width: calc(100% - 40px);
  max-width: 420px;
  pointer-events: none;
}
.snackbar {
  background-color: var(--color-navy);
  color: #fff;
  padding: 12px 18px;
  border-radius: var(--radius-md);
  font-size: 14px;
  box-shadow: var(--shadow-md);
  animation: snackbar-in 0.15s ease-out;
  text-align: center;
  line-height: 1.5;
}
.snackbar.error {
  background-color: var(--color-danger);
}
.snackbar.success {
  background-color: var(--color-success);
}
@keyframes snackbar-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ==========================================================================
   Landing page
   ========================================================================== */

.hero {
  padding: 60px 0 40px;
  text-align: center;
}
.hero .badge {
  margin-bottom: 18px;
  font-size: 12px;
  padding: 5px 12px;
}
.hero h1 {
  font-size: 40px;
  max-width: 720px;
  margin: 0 auto 16px;
  color: var(--color-heading);
  line-height: 1.35;
}
.hero .subtitle {
  font-size: 16px;
  max-width: 560px;
  margin: 0 auto 26px;
}
.hero .cta-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}
.hero .cta-row .btn {
  padding: 14px 30px;
  font-size: 16px;
}
.hero .cta-caption {
  font-size: 13px;
  color: var(--color-text-faint);
}

.section {
  padding: 50px 0;
}
.section-title {
  text-align: center;
  font-size: 26px;
  margin-bottom: 8px;
}
.section-subtitle {
  text-align: center;
  max-width: 560px;
  margin: 0 auto 34px;
}

.steps-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 20px;
}
.step-card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: 24px 20px;
  text-align: center;
}
.step-card h3 {
  font-size: 17px;
}
.step-number {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background-color: var(--color-primary);
  color: #fff;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 12px;
}

.faq-item {
  border-bottom: 1px solid var(--color-border);
  background-color: var(--color-surface);
  padding: 0 16px;
}
.faq-item:first-of-type {
  border-top: 1px solid var(--color-border);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
.faq-item:last-of-type {
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}
.faq-item summary {
  cursor: pointer;
  padding: 16px 0;
  font-weight: 700;
  font-size: 15px;
  color: var(--color-heading);
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}
.faq-item summary::-webkit-details-marker {
  display: none;
}
.faq-item summary::after {
  content: '+';
  color: var(--color-accent);
  font-size: 20px;
  flex-shrink: 0;
}
.faq-item[open] summary::after {
  content: '\2212';
}
.faq-item p {
  padding: 0 0 16px;
  font-size: 14px;
  margin: 0;
}

/* ==========================================================================
   Dashboard / folders
   ========================================================================== */

.dashboard-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 28px 0 18px;
  flex-wrap: wrap;
  gap: 12px;
}
.dashboard-head h1 {
  font-size: 26px;
}

.folder-block {
  margin-bottom: 10px;
  background-color: var(--color-surface);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.folder-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 16px;
  cursor: pointer;
  border-bottom: 1px solid var(--color-border-light);
}
.folder-header .folder-chevron {
  transition: transform 0.2s;
  color: var(--color-text-faint);
  flex-shrink: 0;
}
.folder-header.collapsed {
  border-bottom-color: transparent;
}
.folder-header.collapsed .folder-chevron {
  transform: rotate(-90deg);
}
.folder-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  padding: 5px 12px;
  border-radius: var(--radius-sm);
  font-size: 14px;
  color: var(--color-heading);
  min-width: 0;
}
.folder-chip .dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
}
.folder-count {
  color: var(--color-text-faint);
  font-size: 13px;
  flex-shrink: 0;
}
.folder-body {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 14px;
  padding: 16px;
}
.folder-body.collapsed {
  display: none;
}
.folder-body.archived .event-card {
  opacity: 0.72;
}
.empty-folder {
  color: var(--color-text-faint);
  font-size: 14px;
  padding: 4px;
}

.event-card {
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-lg);
  padding: 16px;
  background-color: var(--color-surface);
  display: flex;
  flex-direction: column;
  gap: 6px;
  transition: transform 0.2s, box-shadow 0.2s;
}
.event-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}
.event-card .event-card-top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 8px;
}
/* Clamped to two lines so a long name can't make one card taller than its
   neighbours; the full name is still the link's text (and its tooltip). */
.event-card-title {
  font-weight: 700;
  font-size: 15px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.event-card-title a {
  color: var(--color-heading);
}
.event-card-title a:hover {
  color: var(--color-accent);
}
.event-card-meta {
  font-size: 13px;
  color: var(--color-text-faint);
}
.event-card-created {
  font-size: 12px;
  color: var(--color-text-faint);
  margin-top: 2px;
}
/* `margin-top: auto` pushes the buttons to the card's bottom edge. Cards are
   grid items stretched to a shared row height, so this lines the action rows
   up across the row no matter how many lines each title takes. */
.event-card-actions {
  display: flex;
  gap: 5px;
  margin-top: auto;
  padding-top: 10px;
  flex-wrap: wrap;
}

/* List view: one compact full-width row per event instead of the default
   grid of cards. Toggled from the dashboard header; the choice is
   remembered in localStorage (see dashboard.js). */
.folder-body.view-list {
  grid-template-columns: minmax(0, 1fr);
  gap: 8px;
}
.folder-body.view-list .event-card {
  flex-direction: row;
  align-items: center;
  gap: 14px;
  padding: 10px 14px;
}
.folder-body.view-list .event-card-top {
  flex: 1;
  min-width: 0;
}
.folder-body.view-list .event-card-actions {
  margin-top: 0;
  padding-top: 0;
  flex-wrap: nowrap;
  flex-shrink: 0;
}
/* Drag handle leads the row, so the grips line up down the left edge. */
.folder-body.view-list .event-card-grip {
  flex-shrink: 0;
  margin-right: 2px;
}

@media (max-width: 700px) {
  /* Too narrow to keep the row layout readable - fall back to stacked. */
  .folder-body.view-list .event-card {
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
  }
  .folder-body.view-list .event-card-actions {
    margin-top: 8px;
    flex-wrap: wrap;
  }
}

.event-card-top-right {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

/* Dedicated drag handle for moving a card between folders - deliberately
   separate from the rest of the card so grabbing it never fights with the
   title link, action buttons or the folder <select> underneath. */
.event-card-grip {
  display: grid;
  grid-template-columns: repeat(2, 3px);
  grid-template-rows: repeat(3, 3px);
  gap: 2px;
  width: 12px;
  height: 15px;
  padding: 4px;
  cursor: grab;
  touch-action: none;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}
.event-card-grip i {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background-color: var(--color-text-faint);
  font-style: normal;
}
.event-card-grip:hover {
  background-color: var(--color-surface-2);
}
.event-card-grip:hover i {
  background-color: var(--color-text-muted);
}
.event-card-grip:active {
  cursor: grabbing;
}

.folder-drag-ghost {
  position: fixed;
  top: 0;
  left: 0;
  transform: translate(-50%, -50%);
  background-color: var(--color-navy);
  color: #fff;
  padding: 7px 16px;
  border-radius: var(--radius-pill);
  font-size: 13px;
  font-weight: 700;
  box-shadow: var(--shadow-lg);
  pointer-events: none;
  z-index: 500;
  white-space: nowrap;
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.folder-block.drop-target {
  outline: 2px solid var(--color-primary-dark);
  outline-offset: -2px;
  background-color: var(--color-primary-pale);
}

.speed-dial {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 30;
  display: none;
}
.speed-dial .btn {
  border-radius: var(--radius-pill);
  padding: 14px 22px;
  box-shadow: var(--shadow-md);
}

/* ==========================================================================
   Event page - availability grid
   ========================================================================== */

.event-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  margin: 26px 0 16px;
  flex-wrap: wrap;
}
.event-header h1 {
  font-size: 24px;
  margin-bottom: 4px;
}
.event-header .event-meta {
  font-size: 14px;
  color: var(--color-text-muted);
}
.event-header-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}

/* The host's single most important action on this page - deliberately
   bigger and louder than the utility buttons (link/invite/edit/delete)
   next to it, with a slow breathing glow to draw the eye without being
   obnoxious. Its own class (not .btn/.btn-primary) so its size and motion
   don't leak onto any other button. */
.btn-finalize {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 13px 22px;
  border-radius: var(--radius-pill);
  background-color: var(--color-primary);
  color: #fff;
  font-size: 15px;
  font-weight: 800;
  text-decoration: none;
  white-space: nowrap;
  border: none;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(var(--color-primary-rgb), 0.4);
  transition: background-color 0.15s, transform 0.15s, box-shadow 0.15s;
  animation: finalize-pulse 2.6s ease-in-out infinite;
}
/* 라벨이 "최적 배정 계산하기"(122px)와 "확정 내용 보기/수정"(126px) 사이를
   오갑니다. 넓은 쪽을 미리 잡아 두어야 확정 전후로 이 버튼과 왼쪽 버튼들이
   흔들리지 않습니다. 문구를 바꾸면 이 값도 다시 재야 합니다. */
#finalize-link-label {
  display: inline-block;
  min-width: 126px;
  text-align: center;
}
.btn-finalize:hover {
  background-color: var(--color-primary-hover);
  color: #fff;
  text-decoration: none;
  transform: translateY(-1px);
  animation-play-state: paused;
  box-shadow: 0 6px 20px rgba(var(--color-primary-rgb), 0.5);
}
.btn-finalize:active {
  transform: translateY(0);
}
.btn-finalize svg {
  flex-shrink: 0;
}
@keyframes finalize-pulse {
  0%, 100% {
    box-shadow: 0 4px 14px rgba(var(--color-primary-rgb), 0.4), 0 0 0 0 rgba(var(--color-primary-rgb), 0.45);
  }
  50% {
    box-shadow: 0 4px 14px rgba(var(--color-primary-rgb), 0.4), 0 0 0 8px rgba(var(--color-primary-rgb), 0);
  }
}
@media (prefers-reduced-motion: reduce) {
  .btn-finalize {
    animation: none;
  }
}

.event-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 20px;
  /* stretch (not flex-start) so the sidebar column is forced to the same
     height as the calendar column - that height then bounds the
     respondents list below, instead of a long respondent list growing the
     whole page taller than the calendar. */
  align-items: stretch;
  /* 페이지 하단 여백은 컨테이너가 담당합니다. 여기에 두면 아래에 오는
     면담 기록 카드까지 밀어내 캘린더와 사이가 벌어집니다. */
  padding-bottom: 0;
}

.grid-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.grid-toolbar-left,
.grid-toolbar-right {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}

.legend {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--color-text-muted);
  flex-wrap: wrap;
}
.legend-ramp {
  display: flex;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 1px solid var(--color-border);
}
.legend-ramp span {
  width: 16px;
  height: 12px;
}
.legend-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-left: 6px;
}
.legend-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
  flex-shrink: 0;
}
.legend-swatch.available-swatch {
  background-color: var(--color-primary);
}
.legend-swatch.if-needed-swatch {
  background-color: var(--color-accent-yellow);
}

.term-help {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface);
  padding: 12px 16px;
  margin-bottom: 14px;
  font-size: 13px;
  box-shadow: var(--shadow-sm);
}
.term-help summary {
  cursor: pointer;
  font-weight: 700;
  color: var(--color-accent);
  list-style: none;
  display: flex;
  align-items: center;
  gap: 6px;
}
.term-help summary::-webkit-details-marker {
  display: none;
}
.term-help summary::before {
  content: 'ⓘ';
  font-size: 14px;
}
.term-help-body {
  margin: 14px 0 0;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 9px 14px;
  align-items: baseline;
}
/* Prose variant of .term-help-body, for explanations that read as
   paragraphs/steps rather than a term/definition table. */
.term-help-body-plain {
  margin-top: 12px;
  color: var(--color-text-muted);
  line-height: 1.7;
}
.term-help-body-plain > p {
  margin: 0 0 10px;
}
.finalize-explain-list {
  margin: 0;
  padding-left: 20px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.finalize-explain-list strong {
  color: var(--color-heading);
}
.term-help-body dt {
  display: flex;
  align-items: center;
  gap: 6px;
  font-weight: 700;
  white-space: nowrap;
  color: var(--color-heading);
}
.term-help-body dd {
  margin: 0;
  color: var(--color-text-muted);
  line-height: 1.6;
}
.term-help-note {
  margin: 12px 0 0;
  padding-top: 10px;
  border-top: 1px solid var(--color-border-light);
  font-size: 12px;
  color: var(--color-text-faint);
}

.grid-scroll {
  /* Horizontal only: the grid is never height-capped on the page - a longer
     day just makes a taller page (see syncCalendarHeight). */
  overflow-x: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface);
  box-shadow: var(--shadow-sm);
  -webkit-overflow-scrolling: touch;
}
.avail-grid {
  display: grid;
  user-select: none;
  min-width: 100%;
}
/* While painting availability, a touch drag must mark cells rather than
   scroll the page. Only applied in edit mode so normal scrolling still works. */
.avail-grid.editing .grid-cell {
  touch-action: none;
}
.avail-grid-corner {
  position: sticky;
  left: 0;
  top: 0;
  background-color: var(--color-surface);
  z-index: 3;
}
.day-col-header {
  text-align: center;
  /* Centred in the (taller) header row rather than sitting flush against
     the first time row, so the date has breathing room beneath it. */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 6px 4px 10px;
  border-bottom: 1px solid var(--color-border);
  border-left: 1px solid var(--color-border-light);
  position: sticky;
  top: 0;
  background-color: var(--color-surface);
  z-index: 2;
}
.day-col-header .dow {
  font-size: 11px;
  color: var(--color-text-faint);
  font-weight: 700;
}
.day-col-header .dnum {
  font-size: 15px;
  font-weight: 700;
  color: var(--color-heading);
}
.time-row-label {
  font-size: 11px;
  color: var(--color-text-faint);
  text-align: right;
  padding: 0 8px;
  position: sticky;
  left: 0;
  background-color: var(--color-surface);
  white-space: nowrap;
  z-index: 1;
}
.grid-cell {
  border-left: 1px solid var(--color-border-light);
  border-top: 1px solid var(--color-grid-faint-border);
  position: relative;
  min-height: 0;
  cursor: pointer;
  background-color: var(--color-surface);
}
.grid-cell.hour-mark {
  border-top: 1px solid var(--color-border);
}
.grid-cell.available {
  background-color: var(--color-primary);
}
.grid-cell.if-needed {
  background-color: var(--color-accent-yellow);
}
.grid-cell.dim {
  opacity: 0.25;
}
.grid-cell.own-preview {
  outline: 2px solid var(--color-primary-dark);
  outline-offset: -2px;
}
/* 편집 중 주최자가 표시한 시간. 칸의 선택색(배경)과 겹쳐도 보이도록 흰
   테두리를 두른 점을 씁니다. ::after는 calendar-busy가 쓰므로 ::before. */
.grid-cell.host-avail::before,
.grid-cell.host-ifneeded::before {
  content: "";
  position: absolute;
  top: 2px;
  right: 2px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--color-navy);
  box-shadow: 0 0 0 1.5px var(--color-surface);
  pointer-events: none;
}
.grid-cell.host-ifneeded::before {
  background: var(--color-surface);
  box-shadow: 0 0 0 1.5px var(--color-navy);
}
/* 편집 바 범례의 같은 점 */
.host-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--color-navy);
  vertical-align: 1px;
  margin-left: 6px;
}
.host-dot-soft {
  background: transparent;
  box-shadow: inset 0 0 0 1.5px var(--color-navy);
}

.grid-cell.calendar-busy::after {
  content: '';
  position: absolute;
  inset: 1px;
  background: repeating-linear-gradient(135deg, rgba(var(--color-text-rgb), 0.18) 0 4px, transparent 4px 8px);
  pointer-events: none;
}

.month-grid-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  margin-bottom: 4px;
}
.month-grid-weekdays span {
  text-align: center;
  font-size: 11px;
  font-weight: 700;
  color: var(--color-text-faint);
}

.month-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
}
.month-cell {
  aspect-ratio: 1;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  cursor: pointer;
  background-color: var(--color-surface);
  font-family: inherit;
  color: var(--color-text);
}
.month-cell:hover {
  border-color: var(--color-primary);
}
/* 지난 날짜. 이미 선택된 날짜는 지났어도 눌러서 뺄 수 있어야 하므로
   (new-event.js renderCalendar) disabled가 붙지 않습니다. */
.month-cell:disabled {
  cursor: not-allowed;
  color: var(--color-text-faint);
  background-color: var(--color-surface-2);
  border-color: var(--color-border-light);
}
.month-cell:disabled:hover {
  border-color: var(--color-border-light);
}
.month-cell.available {
  background-color: var(--color-primary);
  color: #fff;
  border-color: var(--color-primary);
}
/* 오늘 날짜. 테두리(border)가 아니라 안쪽 링을 쓰는 이유는, 선택된 칸은
   이미 크림슨으로 꽉 차 있어 테두리 색이 묻히기 때문입니다. 선택 여부와
   상관없이 항상 보이게 링 색만 바꿔 줍니다. 칸 크기는 그대로라 달을
   넘겨도 격자가 흔들리지 않습니다. */
.month-cell.today {
  font-weight: 800;
  box-shadow: inset 0 0 0 2px var(--color-primary);
}
.month-cell.available.today {
  box-shadow: inset 0 0 0 2px #fff;
}
/* Leading/trailing padding cells (days from the previous/next month) need
   the same aspect-ratio as a real .month-cell - without it, CSS Grid's
   auto row-sizing collapses any row made up entirely of padding cells
   (e.g. a wholly-padded 6th row) to near-zero height instead of matching
   the other rows, which is what let the calendar's total height - and with
   it the "새 일정 만들기" dialog - still change between months even after
   padding out to a fixed cell count. */
.month-cell-empty {
  aspect-ratio: 1;
}

/* Right-hand column: the "가능한 시간 입력" call to action sits directly
   above the respondents card, sharing its full width - close enough to the
   calendar to read as acting on it, and far more visible than it was as a
   small button lost among the toolbar's filter toggles. */
.sidebar-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}
.respond-cta {
  width: 100%;
  justify-content: center;
  flex-shrink: 0;
  margin-bottom: 10px;
  padding: 11px 16px;
  font-size: 15px;
  font-weight: 700;
}
.sidebar-card {
  padding: 16px;
  display: flex;
  flex-direction: column;
  /* 내용만큼만 차지합니다.
     예전에는 flex:1로 늘려 캘린더 높이를 채웠는데, 응답자가 두세 명뿐이면
     카드 안이 텅 비고 "초대 보내기"가 저 아래에 뚝 떨어져 보였습니다.
     목록이 길어질 때 캘린더보다 커지지 않게 막는 것은 이 늘리기가 아니라
     #respondents-list의 max-height(event-grid.js syncRespondentListHeight)가
     맡고 있으므로, 늘리지 않아도 넘칠 일은 없습니다. */
  flex: 0 1 auto;
  min-height: 0;
}
.sidebar-card h3 {
  font-size: 13px;
  letter-spacing: 0.03em;
  color: var(--color-text-faint);
  text-transform: uppercase;
}
.sidebar-heading-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 12px;
  flex-shrink: 0;
}
.sidebar-heading-row .btn {
  flex-shrink: 0;
}
#respondents-list {
  /* 남은 자리를 채우지 않고 명단 길이만큼만 - 그래야 바로 아래 버튼이
     목록에 붙어 나옵니다. 길어지면 JS가 걸어 주는 max-height 안에서
     스크롤합니다. */
  flex: 0 1 auto;
  min-height: 40px;
  overflow-y: auto;
}
/* 초대만 받고 아직 응답하지 않은 사람 - 응답자 아래 회색 구역. */
.respondent-pending-head {
  margin: 10px 0 4px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--color-text-faint);
  text-transform: uppercase;
  border-top: 1px solid var(--color-border-light);
  padding-top: 10px;
}
.respondent-row.respondent-pending {
  opacity: 0.6;
  cursor: default;
}
.respondent-pending-tag {
  margin-left: 6px;
  font-size: 10px;
  padding: 1px 6px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-border);
  color: var(--color-text-faint);
}

/* 응답자 목록에서 내 줄 표시. 이름과 붙되 이름 자체보다는 흐리게 - 찾기 위한
   표지이지 이름의 일부가 아닙니다. */
.respondent-me {
  margin-left: 3px;
  font-weight: 600;
  color: var(--color-primary);
}

.respondent-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 6px;
  border-radius: var(--radius-md);
  cursor: pointer;
  font-size: 14px;
}
.respondent-row:hover {
  background-color: var(--color-surface-2);
}
.respondent-row.selected {
  background-color: var(--color-navy-pale);
}
.respondent-row .name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.respondent-row .edit-icon {
  opacity: 0;
  color: var(--color-text-faint);
}
.respondent-row:hover .edit-icon {
  opacity: 1;
}

.switch {
  position: relative;
  width: 36px;
  height: 20px;
  flex-shrink: 0;
}
.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}
.switch .track {
  position: absolute;
  inset: 0;
  background-color: var(--color-input-border);
  border-radius: var(--radius-pill);
  transition: background-color 0.2s;
  cursor: pointer;
}
.switch .track::before {
  content: '';
  position: absolute;
  width: 16px;
  height: 16px;
  left: 2px;
  top: 2px;
  background-color: #fff;
  border-radius: 50%;
  transition: transform 0.2s;
}
.switch input:checked + .track {
  background-color: var(--color-primary);
}
.switch input:checked + .track::before {
  transform: translateX(16px);
}

/* 시간대 안내줄 - 격자 바로 위, 조용한 한 줄. */
/* 미응답 초대자 칩 - 점선 테두리 + 작은 배지로 "직접 배정 전용"임을 표시. */
.cal-chip-pending {
  border-style: dashed;
  opacity: 0.85;
}
.cal-chip-tag {
  font-size: 9px;
  font-weight: 700;
  margin-left: 4px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--color-border-light);
  color: var(--color-text-muted);
  vertical-align: 1px;
}

.tz-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin: 6px 0 8px;
  font-size: 12.5px;
  color: var(--color-text-muted);
}
.tz-select-wrap {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.tz-select-wrap select {
  max-width: 240px;
  font-size: 12.5px;
  padding: 3px 6px;
}

.edit-bar {
  position: sticky;
  bottom: 0;
  /* 격자가 화면보다 길면 아래쪽 행들이 이 막대 **밑으로** 지나갑니다.
     그런데 시간 라벨 열(.time-row-label, z-index 1)과 날짜 머리글
     (.day-col-header, z-index 2)은 자기 z-index를 갖는 반면 이 막대는
     z-index가 auto라, 스크롤하면 흰 배경의 라벨 열이 막대 위에 덧그려져
     "가능" 버튼 왼쪽이 잘려 보였습니다. 격자에서 가장 높은 값(모서리 칸
     z-index 3)보다 위로 올리되, 헤더(40)와 다이얼로그(100 이상) 아래에
     둡니다. */
  z-index: 5;
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: 12px 14px;
  margin-top: 14px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.edit-bar-left {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.edit-hint {
  font-size: 12px;
  color: var(--color-text-muted);
}

.week-nav {
  display: flex;
  align-items: center;
  gap: 6px;
  font-weight: 700;
  font-size: 14px;
  color: var(--color-heading);
}
/* Same reasoning as .cal-page-label: a fixed slot keeps the ‹ › arrows and
   the "이번 주" button from shifting as the week range's digits change
   (e.g. "9/7 - 9/13" vs "12/28 - 1/3"). */
#week-label {
  flex: 0 0 96px;
  text-align: center;
  white-space: nowrap;
}

.access-denied {
  text-align: center;
  padding: 70px 20px;
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.access-denied .icon {
  font-size: 38px;
  margin-bottom: 12px;
}

.guest-banner {
  background-color: var(--color-warning-bg);
  border: 1px solid var(--color-warning-border);
  color: var(--color-warning-text);
  border-radius: var(--radius-lg);
  padding: 11px 15px;
  font-size: 13px;
  margin-bottom: 16px;
  line-height: 1.6;
}

/* ==========================================================================
   Settings
   ========================================================================== */

.settings-section {
  padding: 22px 0;
  border-bottom: 1px solid var(--color-border);
}
.settings-section:last-child {
  border-bottom: none;
}
.settings-section h2 {
  font-size: 17px;
}
.settings-section .section-desc {
  max-width: 620px;
  font-size: 14px;
}

.calendar-account-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-lg);
  margin-bottom: 10px;
  background-color: var(--color-surface);
  flex-wrap: wrap;
}
.calendar-account-row .info {
  flex: 1;
  min-width: 160px;
}
.calendar-account-row .info .email {
  font-weight: 700;
  font-size: 14px;
  color: var(--color-heading);
}
.sub-calendar-list {
  margin: 10px 0 14px 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.sub-calendar-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: 13px;
  color: var(--color-text-muted);
}

.perm-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  margin-top: 12px;
}
.perm-table th, .perm-table td {
  text-align: left;
  padding: 10px;
  border-bottom: 1px solid var(--color-border-light);
  color: var(--color-text-muted);
}
.perm-table th {
  color: var(--color-heading);
  font-size: 12px;
  background-color: var(--color-surface-2);
}

/* ==========================================================================
   Contacts
   ========================================================================== */

/* Two columns: the add/search/filter tools stay in a narrow left rail while
   the saved contacts fill the rest of the width. Previously everything was
   stacked in a 640px column, which left wide empty margins and pushed the
   list far down the page. */
.contacts-layout {
  display: grid;
  grid-template-columns: 330px minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}
.contacts-side {
  position: sticky;
  top: 16px;
  min-width: 0;
}
.contacts-main {
  min-width: 0;
}
/* The list itself flows into as many columns as the width allows, so a long
   roster stays short vertically instead of running one-per-row. */
#contacts-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(310px, 1fr));
  gap: 8px;
  align-items: start;
}
#contacts-list .empty-state {
  grid-column: 1 / -1;
}
/* Search hits render as .contact-row too but sit in a plain (non-grid)
   container, so they still need their own spacing. */
#search-results .contact-row {
  margin-bottom: 8px;
}
/* List view: one full-width row per contact instead of the auto-fill grid. */
#contacts-list.view-list {
  grid-template-columns: minmax(0, 1fr);
}
#contacts-list.view-list .contact-row {
  flex-wrap: nowrap;
}
#contacts-list.view-list .contact-actions {
  flex-shrink: 0;
}

/* Compact inline sort picker used in the dashboard / 연락처 list headers. */
/* Must out-specify `select.input { width: 100% }` above (element+class beats
   a lone class), or the picker stretches to fill its row and pushes the
   view toggle onto the next line. Sized to sit next to .toggle-group as a
   peer control rather than as a form field. */
select.list-sort-select {
  width: auto;
  min-width: 0;
  flex: 0 0 auto;
  /* 9px vertical lands the same 37px box height as .toggle-group beside it. */
  padding: 9px 30px 9px 12px;
  font-size: 13px;
  font-weight: 700;
  color: var(--color-text-muted);
  border-color: var(--color-border);
  border-radius: var(--radius-md);
}
/* Heading stays left; the sort picker and view toggle pair up on the right. */
.contacts-main-head .list-sort-select {
  margin-left: auto;
}

/* The card being dragged stays visible but clearly "lifted" while its
   placeholder position updates live underneath the pointer. */
.card-dragging {
  opacity: 0.45;
  outline: 2px dashed var(--color-primary);
  outline-offset: -2px;
}

.contact-grip {
  flex-shrink: 0;
}

.contacts-main-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

/* Optional roster fields on the add/edit forms - two per row so the block
   stays compact instead of becoming a long stack of single inputs. */
.contact-form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 0 12px;
}
.contact-memo-row span:last-child {
  white-space: pre-line;
  text-align: right;
}

@media (max-width: 560px) {
  #contacts-list.view-list .contact-row {
    flex-wrap: wrap;
  }
}

@media (max-width: 900px) {
  .contacts-layout {
    grid-template-columns: minmax(0, 1fr);
  }
  .contacts-side {
    position: static;
  }
}

.contact-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface);
}
.contact-main {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  flex: 1;
}
.contact-main .avatar {
  flex-shrink: 0;
}
.contact-row .info {
  flex: 1;
  min-width: 0;
}
.contact-row .name {
  font-weight: 700;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--color-heading);
  min-width: 0;
}
/* Name truncates instead of wrapping, so the badge stays on the same line
   and every card's text block is the same height. */
.contact-name-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.contact-row .name .badge {
  flex-shrink: 0;
}
/* Long addresses would otherwise break mid-word ("qwer@postec / h.ac.kr")
   and blow the card's height out; the full value is in the title tooltip
   and the 자세히 dialog. */
.contact-row .email {
  font-size: 12px;
  color: var(--color-text-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.contact-actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}
.contact-row .detail {
  font-size: 12px;
  color: var(--color-text-faint);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Grid view stacks the card: identity block on top, actions as a full-width
   row pinned to the bottom. Cards stretch to a shared row height (they're
   grid items), so `margin-top: auto` lines every card's buttons up. */
#contacts-list:not(.view-list) .contact-row {
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
  padding: 14px;
}
#contacts-list:not(.view-list) .contact-actions {
  margin-top: auto;
  padding-top: 10px;
  border-top: 1px solid var(--color-border-light);
}
#contacts-list:not(.view-list) .contact-actions .btn {
  flex: 1;
  justify-content: center;
}

.contact-filter-group {
  margin-bottom: 10px;
}
.contact-filter-group:last-child {
  margin-bottom: 0;
}
.contact-filter-label {
  font-size: 12px;
  font-weight: 700;
  color: var(--color-text-faint);
  margin-bottom: 6px;
}

/* "연락처에서 선택" 라벨과 "+ 연락처 추가" 버튼을 한 줄에. */
.invite-contacts-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 6px;
}

/* "메일 보내기" 창의 받는 사람 묶음 머리 (응답 여부로 나뉩니다). */
.msg-target-group {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin: 10px 0 6px;
}
.msg-target-group:first-child {
  margin-top: 0;
}
.msg-target-title {
  font-size: 12px;
  font-weight: 700;
  color: var(--color-text-muted);
}
/* 이메일을 몰라 보낼 수 없는 사람 - 목록에는 남기되 흐리게. */
.checkbox-row.msg-target-nomail {
  opacity: 0.55;
}

.invite-contact-list {
  max-height: 260px;
  overflow-y: auto;
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  background-color: var(--color-surface-2);
}

/* ==========================================================================
   Sign-up steps
   ========================================================================== */

.signup-steps {
  display: flex;
  gap: 8px;
  margin: 0 0 20px;
  padding: 0;
  list-style: none;
  font-size: 13px;
}
.signup-steps li {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1;
  color: var(--color-text-faint);
  font-weight: 700;
}
.signup-steps li.active {
  color: var(--color-accent);
}
.signup-steps li.done {
  color: var(--color-text-muted);
}
.signup-steps .step-dot {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  background-color: var(--color-surface-2);
  color: var(--color-text-faint);
  border: 1px solid var(--color-border);
  flex-shrink: 0;
}
.signup-steps li.active .step-dot {
  background-color: var(--color-primary);
  border-color: var(--color-primary);
  color: #fff;
}
.signup-steps li.done .step-dot {
  background-color: var(--color-primary-pale);
  border-color: var(--color-primary-pale-2);
  color: var(--color-accent);
}

.verify-sent {
  background-color: var(--color-surface-2);
  border-radius: var(--radius-md);
  padding: 12px 14px;
  font-size: 13px;
  color: var(--color-text);
  line-height: 1.6;
  margin-bottom: 16px;
}

.code-input {
  text-align: center;
  font-size: 24px;
  letter-spacing: 0.3em;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  padding: 12px;
}

/* ==========================================================================
   Finalize (schedule confirmation)
   ========================================================================== */

.finalize-settings {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin-bottom: 16px;
  align-items: start;
}

/* Side-by-side once a proposal exists: a narrow controls column (editor +
   actions) and a wide column for the calendar, which is the piece that
   actually benefits from extra width. Falling back to `display: grid` here
   (rather than `block`) is what makes finalize.js's `style.display = ""`
   toggle reveal the two-column layout instead of a plain stack. */
.finalize-layout {
  display: grid;
  grid-template-columns: 360px minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}
.finalize-col-left {
  display: flex;
  flex-direction: column;
  gap: 16px;
  position: sticky;
  top: calc(var(--header-height) + 16px);
}
.finalize-col-right {
  min-width: 0;
}

.finalize-summary {
  font-size: 14px;
  color: var(--color-heading);
  margin-bottom: 10px;
}

.finalize-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.assign-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--color-border-light);
}
.assign-row:last-child {
  border-bottom: none;
}
.assign-name {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 160px;
  flex-shrink: 0;
  font-size: 14px;
  font-weight: 700;
  color: var(--color-heading);
}
.assign-row select {
  flex: 1;
  min-width: 0;
}

.meeting-card {
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-md);
  padding: 12px 14px;
  margin-bottom: 8px;
  background-color: var(--color-surface-2);
}
.meeting-card.over {
  border-color: var(--color-danger-border);
  background-color: var(--color-danger-bg);
}
.meeting-time {
  font-weight: 700;
  color: var(--color-heading);
  font-size: 14px;
}
.meeting-people {
  font-size: 13px;
  color: var(--color-text-muted);
  margin-top: 3px;
}
.meeting-count {
  font-size: 12px;
  color: var(--color-text-faint);
  margin-top: 3px;
}
.meeting-card.over .meeting-count {
  color: var(--color-danger-text);
  font-weight: 700;
}

.unassigned-box {
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-md);
  padding: 12px 14px;
  font-size: 13px;
  color: var(--color-text-muted);
}
.unassigned-box strong {
  color: var(--color-heading);
  display: block;
  margin-bottom: 4px;
}

/* Calendar-style visualization of the proposed/confirmed schedule -
   day columns x time rows, meetings rendered as booked blocks, the way
   Google Calendar shows a day/week view. */
.cal-legend {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  font-size: 12px;
  color: var(--color-text-muted);
  margin-bottom: 10px;
}
.cal-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.cal-swatch {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 3px;
  flex-shrink: 0;
}
.cal-swatch-booked {
  background-color: var(--color-primary);
}
.cal-swatch-open {
  background-color: var(--color-surface-2);
  border: 1px dashed var(--color-border);
}
.cal-swatch-none {
  /* 흰 셀: 주최자는 가능하지만 갈 수 있다고 답한 사람이 없는 시간. */
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
}
.cal-swatch-unavailable {
  background-image: repeating-linear-gradient(135deg, var(--color-border) 0 3px, var(--color-surface) 3px 7px);
  border: 1px solid var(--color-border);
}

.cal-grid {
  display: grid;
  min-width: 100%;
}
.cal-corner {
  position: sticky;
  left: 0;
  background-color: var(--color-surface);
  z-index: 3;
  border-bottom: 1px solid var(--color-border);
}
.cal-day-header {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--color-heading);
  border-bottom: 1px solid var(--color-border);
  border-left: 1px solid var(--color-border-light);
  position: sticky;
  top: 0;
  background-color: var(--color-surface);
  z-index: 2;
}
.cal-time-label {
  display: flex;
  align-items: flex-start;
  justify-content: flex-end;
  padding: 3px 8px 0 0;
  font-size: 11px;
  color: var(--color-text-faint);
  position: sticky;
  left: 0;
  background-color: var(--color-surface);
  white-space: nowrap;
}

.cal-cell {
  border-left: 1px solid var(--color-border-light);
  border-top: 1px solid #f4f4f4;
  padding: 3px 5px;
  overflow: hidden;
  font-size: 11px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  transition: outline-color 0.1s, background-color 0.1s;
}
.cal-cell-unavailable {
  background-image: repeating-linear-gradient(135deg, var(--color-surface-2) 0 5px, var(--color-surface) 5px 10px);
}
.cal-cell-open {
  background-color: var(--color-surface-2);
  color: var(--color-text-faint);
  align-items: center;
  justify-content: center;
  text-align: center;
}
.cal-cell-empty {
  background-color: var(--color-surface);
}
.cal-cell-booked {
  background-color: var(--color-primary);
  color: #fff;
  border-radius: var(--radius-sm);
  margin: 1px 2px;
  box-shadow: var(--shadow-sm);
  /* 카드 바탕을 잡으면 그 시간의 참가자 전원이 함께 움직입니다
     (finalize.js startGroupDrag). 이름 칩은 자기 몫만 움직입니다. */
  cursor: grab;
  touch-action: none;
}
.cal-cell-booked:active {
  cursor: grabbing;
}
.cal-cell-booked.cal-cell-over {
  background-color: var(--color-danger);
}
.cal-block-names {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  line-height: 1.3;
}
.cal-block-count {
  opacity: 0.85;
  font-size: 10px;
  margin-top: 2px;
}

/* Drop-target feedback while a chip is being dragged over a cell */
.cal-cell.cal-drop-target {
  outline: 2px solid var(--color-primary-dark);
  outline-offset: -2px;
}
.cal-cell.cal-drop-target.cal-drop-invalid {
  outline-color: var(--color-danger-text);
  background-color: var(--color-danger-bg);
}

/* Drop-target feedback while a chip is dragged over *another participant's
   card* specifically (as opposed to an empty cell) - a swap/take-over, not
   a plain re-assignment. Highlighted on the card itself so it's clear which
   person you're about to trade with. */
.cal-chip.cal-drop-target {
  outline: 2px solid var(--color-primary-dark);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px rgba(var(--color-primary-rgb), 0.25);
}
.cal-chip.cal-drop-target.cal-drop-invalid {
  outline-color: var(--color-danger-text);
  box-shadow: 0 0 0 4px rgba(var(--color-danger-rgb), 0.25);
}

/* Draggable participant card - used both inside booked calendar cells and
   in the unassigned tray. Pointer Events drive the drag so the same code
   works for mouse and touch. */
.cal-chip {
  display: inline-flex;
  align-items: center;
  padding: 2px 7px;
  border-radius: var(--radius-pill);
  font-size: 11px;
  font-weight: 700;
  cursor: grab;
  user-select: none;
  touch-action: none;
  white-space: nowrap;
  transition: transform 0.12s ease, box-shadow 0.12s ease, background-color 0.12s ease;
}
.cal-cell-booked .cal-chip {
  background-color: rgba(255, 255, 255, 0.22);
  color: #fff;
}
.unassigned-tray-chips .cal-chip {
  background-color: var(--color-primary-pale);
  color: var(--color-primary-dark);
  padding: 5px 12px;
  font-size: 12px;
}
/* Clear "you can grab this" feedback: lift + glow on hover, so the whole
   card - not just an icon on one edge - reads as draggable at a glance. */
.cal-chip:hover {
  transform: translateY(-1px);
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.28);
}
.cal-cell-booked .cal-chip:hover {
  background-color: rgba(255, 255, 255, 0.4);
}
.unassigned-tray-chips .cal-chip:hover {
  background-color: var(--color-primary-pale-2);
  box-shadow: 0 3px 10px rgba(var(--color-primary-rgb), 0.3);
}
.cal-chip:active {
  cursor: grabbing;
  transform: translateY(0) scale(0.96);
  box-shadow: none;
}

/* Floating card that follows the pointer during a drag */
.cal-drag-ghost {
  position: fixed;
  top: 0;
  left: 0;
  transform: translate(-50%, -50%);
  background-color: var(--color-navy);
  color: #fff;
  padding: 6px 14px;
  border-radius: var(--radius-pill);
  font-size: 13px;
  font-weight: 700;
  box-shadow: var(--shadow-lg);
  pointer-events: none;
  z-index: 500;
  white-space: nowrap;
}
/* 여러 명을 함께 옮기는 중 - 이름이 늘어나므로 한 줄로 두지 않습니다. */
.cal-drag-ghost-group {
  max-width: 320px;
  white-space: normal;
  text-align: center;
  line-height: 1.4;
}
body.dragging-active {
  cursor: grabbing;
}
body.dragging-active * {
  cursor: grabbing !important;
}

.unassigned-tray {
  margin-top: 14px;
  padding: 12px 14px;
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface-2);
  transition: outline-color 0.1s, background-color 0.1s;
}
.unassigned-tray.cal-drop-target {
  outline: 2px solid var(--color-primary-dark);
  outline-offset: -2px;
  background-color: var(--color-primary-pale);
}
.unassigned-tray-title {
  font-size: 12px;
  font-weight: 700;
  color: var(--color-text-muted);
  margin-bottom: 8px;
}
.unassigned-tray-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* ==========================================================================
   Full calendar page (/calendar) - month view aggregating every event the
   user owns/responded to/is invited to. Deliberately its own class prefix
   (cal-page-*) so it doesn't collide with the small date-picker grid
   (.month-grid/.month-cell) or the finalize page's day/time grid (.cal-grid).
   ========================================================================== */

.cal-page-toolbar {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
/* The current period doubles as the page title, sitting where a static
   heading used to. Being left-aligned in .dashboard-head's space-between
   row, its text can grow ("2026년 9월" -> "2026년 9월 22일 - 25일") without
   nudging the controls on the right, which stay pinned to the right edge. */
.cal-page-label {
  margin: 0;
  white-space: nowrap;
}

.cal-page-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  margin-bottom: 4px;
}
.cal-page-weekday {
  text-align: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--color-text-faint);
  padding: 4px 0;
}

/* Month grid. Every cell is a CSS grid item, and every pill inside it is a
   flex item with nowrap text - both grid and flex items default to a
   content-based min-width/min-height ("min-width: auto"), which lets a long
   nowrap name silently overflow its box and stretch the whole column/row
   instead of eliding, breaking the rectangular grid layout. `min-width: 0`
   (and a hard `height` instead of `min-height`) is what forces the box to
   respect its assigned track size and clip content instead. */
.cal-page-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
  margin-bottom: 24px;
}
.cal-page-cell {
  height: 108px;
  min-width: 0;
  padding: 6px;
  background-color: var(--color-surface);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-sm);
  display: flex;
  flex-direction: column;
  gap: 4px;
  overflow: hidden;
  transition: box-shadow 0.12s ease, border-color 0.12s ease;
}
.cal-page-cell.has-events {
  cursor: pointer;
}
.cal-page-cell.has-events:hover {
  border-color: var(--color-primary);
  box-shadow: var(--shadow-sm);
}
.cal-page-cell.other-month {
  background-color: var(--color-surface-2);
  opacity: 0.6;
}
.cal-page-cell.today .cal-page-cell-date {
  background-color: var(--color-primary);
  color: #fff;
}
.cal-page-cell-date {
  flex-shrink: 0;
  align-self: flex-start;
  font-size: 12px;
  font-weight: 700;
  color: var(--color-text-muted);
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.cal-page-pills {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  overflow: hidden;
}
.cal-page-pill {
  min-width: 0;
  flex-shrink: 0;
  font-size: 11px;
  font-weight: 600;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cal-page-pill.confirmed {
  background-color: var(--color-primary);
  color: #fff;
}
.cal-page-pill.tentative {
  background-color: var(--color-surface-2);
  color: var(--color-text-muted);
  border: 1px dashed var(--color-border);
}
.cal-page-more {
  min-width: 0;
  flex-shrink: 0;
  font-size: 10px;
  color: var(--color-text-faint);
  padding: 0 2px;
}

/* Week / day time-grid views - Google Calendar-style absolutely positioned
   blocks over hour gridlines, so overlapping meetings can sit side by side
   instead of stacking and breaking cell heights the way the month view's
   pills would. */
.cal-page-timeview {
  display: none;
  margin-bottom: 24px;
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.cal-page-timeview.active {
  display: block;
}
.cal-page-tv-header {
  display: grid;
  border-bottom: 1px solid var(--color-border);
  background-color: var(--color-surface);
}
.cal-page-tv-header-cell {
  padding: 8px 4px;
  text-align: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--color-heading);
  border-left: 1px solid var(--color-border-light);
}
.cal-page-tv-header-cell:first-child {
  border-left: none;
}
.cal-page-tv-header-cell.today {
  color: var(--color-primary);
}
.cal-page-tv-header-cell .cal-page-tv-date-num {
  display: block;
  font-size: 15px;
}

.cal-page-tv-allday {
  display: grid;
  border-bottom: 1px solid var(--color-border);
  background-color: var(--color-surface-2);
  min-height: 28px;
}
.cal-page-tv-allday-cell {
  padding: 3px 4px;
  border-left: 1px solid var(--color-border-light);
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  overflow: hidden;
}
.cal-page-tv-allday-cell:first-child {
  border-left: none;
}

/* Everything below the header/all-day rows scrolls together inside a fixed
   viewport height. `.cal-page-tv-scroll` is sized by its one in-flow child
   (`.cal-page-tv-rows`, a 24-row grid = 24 * 48px tall); the time labels and
   day columns are absolutely positioned siblings that stretch to match that
   same height via `inset: 0`, rather than each computing their own height
   in JS. */
.cal-page-tv-body {
  max-height: 620px;
  overflow-y: auto;
}
.cal-page-tv-scroll {
  position: relative;
}
.cal-page-tv-rows {
  display: grid;
  grid-template-rows: repeat(24, 48px);
  margin-left: 44px;
}
.cal-page-tv-hour-row {
  border-top: 1px solid var(--color-grid-faint-border);
}
.cal-page-tv-timelabels {
  position: absolute;
  inset: 0;
  width: 44px;
  pointer-events: none;
}
.cal-page-tv-timelabel {
  position: absolute;
  left: 4px;
  transform: translateY(-50%);
  font-size: 10px;
  color: var(--color-text-faint);
  white-space: nowrap;
}
.cal-page-tv-columns {
  position: absolute;
  inset: 0;
  left: 44px;
  display: grid;
}
.cal-page-tv-column {
  position: relative;
  border-left: 1px solid var(--color-border-light);
  min-width: 0;
}
.cal-page-tv-column:first-child {
  border-left: none;
}

.cal-page-tv-block {
  position: absolute;
  min-width: 0;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  font-size: 11px;
  line-height: 1.25;
  overflow: hidden;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
}
.cal-page-tv-block.confirmed {
  background-color: var(--color-primary);
  color: #fff;
}
.cal-page-tv-block.confirmed:hover {
  background-color: var(--color-primary-hover);
}
.cal-page-tv-block-time {
  display: block;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cal-page-tv-block-title,
.cal-page-tv-block-line {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cal-page-google-row {
  display: flex;
  justify-content: flex-end;
  margin-top: 8px;
}

.cal-page-day-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.cal-page-day-list-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  text-align: left;
  padding: 8px 10px;
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-sm);
  background-color: var(--color-surface);
  font-size: 13px;
  color: var(--color-text);
  cursor: pointer;
}
.cal-page-day-list-item:hover {
  border-color: var(--color-primary);
  background-color: var(--color-primary-pale);
}
.cal-page-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.cal-page-dot.confirmed {
  background-color: var(--color-primary);
}
.cal-page-dot.tentative {
  background-color: var(--color-surface-3);
  border: 1px solid var(--color-border);
}

.cal-detail-row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 0;
  border-bottom: 1px solid var(--color-border-light);
  font-size: 13px;
}
.cal-detail-row:last-child {
  border-bottom: none;
}
.cal-detail-label {
  color: var(--color-text-faint);
  font-weight: 600;
}

@media (max-width: 700px) {
  .cal-page-cell {
    min-height: 64px;
    padding: 4px;
  }
  .cal-page-cell-date {
    font-size: 11px;
    width: 18px;
    height: 18px;
  }
  .cal-page-pill {
    font-size: 9px;
  }
}

/* ==========================================================================
   Misc
   ========================================================================== */

.empty-state {
  text-align: center;
  padding: 50px 20px;
  color: var(--color-text-faint);
  font-size: 14px;
}
.empty-state .icon {
  font-size: 32px;
  margin-bottom: 10px;
}

.spinner {
  width: 20px;
  height: 20px;
  border: 3px solid var(--color-surface-3);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
  display: inline-block;
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

.error-page {
  text-align: center;
  padding: 90px 20px;
}
.error-page h1 {
  font-size: 68px;
  color: var(--color-accent);
  margin-bottom: 6px;
}
.fin-stale {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
}

.error-hint {
  max-width: 460px;
  margin: 10px auto 0;
  color: var(--color-text-muted);
  font-size: 14px;
  line-height: 1.7;
}
.error-page .btn {
  margin-top: 24px;
}

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 1024px) {
  .event-layout {
    grid-template-columns: minmax(0, 1fr);
  }
  .sidebar-col {
    order: -1;
  }
  .sidebar-card {
    /* Stacked layout - the two columns no longer share a stretched height,
       so the respondents list needs its own explicit cap here instead. */
    max-height: 340px;
  }
  #respondents-list {
    min-height: 0;
  }

  .finalize-layout {
    grid-template-columns: minmax(0, 1fr);
  }
  .finalize-col-left {
    position: static;
  }
}

@media (max-width: 768px) {
  .container {
    padding: 0 14px;
  }

  .site-header .container {
    min-height: 60px;
    gap: 10px;
  }
  .header-logo-left img {
    height: 24px;
  }
  .header-divider,
  .brand-sub {
    display: none;
  }
  .brand-mark {
    font-size: 21px;
  }
  .nav-links {
    gap: 0;
    margin-right: 2px;
  }
  .nav-links a {
    padding: 7px 9px;
    font-size: 13px;
  }
  .user-menu-name {
    display: none;
  }
  .user-menu-trigger {
    padding: 4px;
  }

  .hero {
    padding: 40px 0 30px;
  }
  .hero h1 {
    font-size: 28px;
  }
  .hero .subtitle {
    font-size: 15px;
  }
  .section {
    padding: 36px 0;
  }
  .section-title {
    font-size: 22px;
  }

  .dashboard-head h1 {
    font-size: 22px;
  }
  .folder-body {
    grid-template-columns: 1fr;
    padding: 12px;
  }
  .speed-dial {
    display: block;
  }
  /* Leave room for the floating action button */
  .dashboard-head + #folders-root {
    padding-bottom: 70px;
  }

  .event-header h1 {
    font-size: 20px;
  }
  .event-header-actions {
    width: 100%;
  }
  .event-header-actions .btn {
    flex: 1;
    min-width: 0;
  }
  .btn-finalize {
    width: 100%;
    justify-content: center;
    order: -1;
    margin-bottom: 4px;
  }
  /* Narrower columns and taller rows: more days on screen, easier to drag */
  :root {
    --grid-label-w: 46px;
    --grid-col-min: 42px;
    --grid-row-h: 18px;
  }
  .time-row-label {
    padding: 0 5px;
    font-size: 10px;
  }
  .day-col-header .dnum {
    font-size: 13px;
  }

  .term-help-body {
    grid-template-columns: 1fr;
    gap: 4px;
  }
  .term-help-body dd {
    margin-bottom: 10px;
  }

  .finalize-settings {
    grid-template-columns: 1fr;
    gap: 14px;
  }
  .assign-row {
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
  }
  .assign-name {
    min-width: 0;
  }
  .finalize-actions .btn {
    flex: 1;
  }

  .cal-time-label {
    font-size: 10px;
    padding-right: 4px;
  }
  .cal-day-header {
    font-size: 11px;
  }
  .cal-cell {
    font-size: 10px;
    padding: 2px 4px;
  }
  .cal-block-count {
    display: none;
  }
  .cal-chip {
    padding: 1px 5px;
    font-size: 10px;
  }
  .unassigned-tray-chips .cal-chip {
    padding: 4px 10px;
    font-size: 11px;
  }
  .cal-drag-ghost {
    font-size: 12px;
  }

  .edit-bar {
    padding: 10px;
    gap: 8px;
  }
  .edit-bar-left {
    width: 100%;
    justify-content: space-between;
  }
  .edit-hint {
    display: none;
  }
  .edit-bar > div:last-child {
    width: 100%;
  }
  .edit-bar > div:last-child .btn {
    flex: 1;
  }

  .dialog {
    padding: 18px;
    max-height: 92vh;
  }
  .dialog-footer .btn {
    flex: 1;
  }

  .auth-card {
    margin: 20px auto 40px;
    padding: 20px;
  }

  .contact-row,
  .calendar-account-row {
    align-items: flex-start;
  }
  .contact-actions {
    width: 100%;
  }
  .contact-actions .btn {
    flex: 1;
  }

  .perm-table {
    display: block;
    overflow-x: auto;
    white-space: nowrap;
  }

  /* Footer collapses to a centered column, matching the PCSS layout */
  .footer-inner {
    flex-direction: column;
    align-items: center;
    text-align: center;
  }
  .footer-left {
    min-width: 0;
  }
  .footer-links {
    justify-content: center;
  }
  .footer-right {
    align-items: center;
  }
}

/* Below this the header can't fit the POSTECH signature alongside the app's
   own mark and the nav without them colliding, so the signature steps aside.
   It still appears in the footer at every size. */
@media (max-width: 560px) {
  .header-logo-left {
    display: none;
  }
}

@media (max-width: 420px) {
  .brand-mark {
    font-size: 19px;
  }
  .nav-links a {
    padding: 6px 7px;
    font-size: 12px;
  }
  .event-card-actions .btn {
    flex: 1;
  }
}

/* ==========================================================================
   Admin dashboard
   ========================================================================== */

.admin-stat-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 12px;
  margin-bottom: 20px;
}

/* The dashboard used to be one full-width card stacked on another, which
   left a lot of unused width and a very tall page. These rows put the
   wide-content card beside the narrow ones instead. */
.admin-grid {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  gap: 16px;
  margin-bottom: 16px;
  align-items: start;
}
.admin-grid-main {
  /* Chart spans the full height of the two stacked side cards next to it. */
  grid-row: span 2;
}
/* The log table carries more (and wider) columns than the user table, so it
   gets the larger share rather than an even split. */
.admin-grid-tables {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
}
.admin-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}
.admin-card-head h2 {
  font-size: 16px;
  margin: 0;
}

@media (max-width: 1100px) {
  .admin-grid,
  .admin-grid-tables {
    grid-template-columns: minmax(0, 1fr);
  }
  .admin-grid-main {
    grid-row: auto;
  }
}
.admin-stat-card {
  padding: 16px;
  background-color: var(--color-surface);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.admin-stat-value {
  font-size: 26px;
  font-weight: 800;
  color: var(--color-heading);
}
.admin-stat-label {
  font-size: 12px;
  color: var(--color-text-faint);
  margin-top: 2px;
}

.admin-chart-svg {
  width: 100%;
  height: 200px;
  display: block;
}
/* 메인 트래픽 차트는 옆의 두 카드(상태코드+경로) 높이에 맞춰 여유 있게. */
#admin-traffic-chart .admin-chart-svg { height: 300px; }

.admin-chart-gridline {
  stroke: var(--color-grid-faint-border);
  stroke-width: 1;
}
.admin-chart-axis-label {
  fill: var(--color-text-faint);
  font-size: 10px;
}
.admin-chart-bar {
  fill: var(--color-primary);
}

/* ---- 대시보드 확장 (지표 카드 부제·차트 범례·상태/오류/막대 목록) ---- */
.admin-stat-card .admin-stat-label {
  margin-top: 0;
  text-transform: none;
  letter-spacing: 0.02em;
}
.admin-stat-card .admin-stat-value {
  margin-top: 4px;
  font-variant-numeric: tabular-nums;
}
.admin-stat-sub {
  margin-top: 4px;
  font-size: 12px;
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}
.admin-stat-card.danger {
  border-color: color-mix(in srgb, var(--color-danger) 35%, var(--color-border-light));
}
.admin-stat-card.danger .admin-stat-value {
  color: var(--color-danger);
}
.admin-delta {
  font-size: 11px;
  font-weight: 700;
  border-radius: 999px;
  padding: 1px 7px;
  margin-left: 4px;
  white-space: nowrap;
}
.admin-delta.up { color: var(--color-success); background: color-mix(in srgb, var(--color-success) 12%, transparent); }
.admin-delta.down { color: var(--color-danger); background: color-mix(in srgb, var(--color-danger) 10%, transparent); }
.admin-delta.flat { color: var(--color-text-faint); background: var(--color-surface-muted, rgba(0,0,0,0.04)); }

.admin-grid-thirds {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (max-width: 1100px) {
  .admin-grid-thirds { grid-template-columns: minmax(0, 1fr); }
}

.admin-chart-legend {
  display: flex;
  gap: 14px;
  font-size: 12px;
  color: var(--color-text-muted);
  align-items: center;
}
.legend-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 3px;
  margin-right: 5px;
  vertical-align: -1px;
}
.legend-dot.legend-bar { background: var(--color-primary); }
.legend-dot.legend-bar2 { background: var(--color-success); }
.legend-dot.legend-line { background: var(--color-warning, #e8a13c); border-radius: 999px; height: 3px; width: 14px; }
.admin-chart-line {
  fill: none;
  stroke: var(--color-warning, #e8a13c);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
  stroke-linejoin: round;
  opacity: 0.9;
  pointer-events: none;
}
.admin-chart-bar2 { fill: var(--color-success); }
.admin-chart-bar2:hover { fill: color-mix(in srgb, var(--color-success) 80%, #000); }

.admin-subchart { margin-top: 14px; }
.admin-subhead {
  font-size: 13px;
  margin: 0 0 8px;
  color: var(--color-text-muted);
  font-weight: 600;
}
.hint-inline { font-size: 12px; color: var(--color-text-faint); font-weight: 400; }

.admin-hourly {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 96px;
}
.admin-hourly-col {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  min-width: 0;
  height: 100%;
  position: relative;
}
.admin-hourly-bar {
  width: 100%;
  border-radius: 3px 3px 0 0;
  background: color-mix(in srgb, var(--color-primary) 75%, transparent);
  transition: background 0.15s;
}
.admin-hourly-bar:hover { background: var(--color-primary); }
.admin-hourly-label {
  position: absolute;
  bottom: -16px;
  font-size: 10px;
  color: var(--color-text-faint);
  white-space: nowrap;
}
.admin-subchart .admin-hourly { margin-bottom: 18px; }

.admin-status-bar {
  display: flex;
  height: 14px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--color-border-light);
}
.admin-status-seg.s2xx, .legend-dot.s2xx, .admin-status-pill.s2xx { background: var(--color-success); }
.admin-status-seg.s3xx, .legend-dot.s3xx, .admin-status-pill.s3xx { background: var(--color-text-faint); }
.admin-status-seg.s4xx, .legend-dot.s4xx, .admin-status-pill.s4xx { background: var(--color-warning, #e8a13c); }
.admin-status-seg.s5xx, .legend-dot.s5xx, .admin-status-pill.s5xx { background: var(--color-danger); }
.admin-status-legend {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px 12px;
  margin-top: 10px;
  font-size: 12px;
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}
.admin-status-legend b { color: var(--color-heading); font-weight: 700; }
.admin-status-legend em { font-style: normal; color: var(--color-text-faint); }

.admin-status-pill {
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  border-radius: 6px;
  padding: 1px 6px;
  flex: none;
  font-variant-numeric: tabular-nums;
}
.admin-error-row, .admin-slow-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  border-bottom: 1px solid var(--color-border-light);
  font-size: 13px;
}
.admin-error-row:last-child, .admin-slow-row:last-child { border-bottom: none; }
.admin-error-path {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 12px;
}
.admin-error-time {
  color: var(--color-text-faint);
  font-size: 12px;
  flex: none;
  font-variant-numeric: tabular-nums;
}
.admin-method-badge {
  flex: none;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
  border-radius: 5px;
  padding: 1px 5px;
}
.admin-slow-ms {
  flex: none;
  font-weight: 700;
  color: var(--color-heading);
  font-variant-numeric: tabular-nums;
}
.admin-slow-count {
  flex: none;
  color: var(--color-text-faint);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.admin-bar-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 0;
  font-size: 13px;
}
.admin-bar-name {
  flex: 0 0 96px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.admin-bar-track {
  flex: 1;
  height: 8px;
  border-radius: 999px;
  background: var(--color-border-light);
  overflow: hidden;
}
.admin-bar-fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--color-primary);
}
.admin-bar-count {
  flex: none;
  min-width: 52px;
  text-align: right;
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
  font-size: 12px;
}

.admin-chart-bar:hover {
  fill: var(--color-primary-hover);
}

.admin-top-paths {
  max-height: 260px;
  overflow-y: auto;
}
.admin-top-path-row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 5px 0;
  font-size: 13px;
}
.admin-top-path-path {
  font-family: monospace;
  color: var(--color-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.admin-top-path-count {
  color: var(--color-text-faint);
  flex-shrink: 0;
}

/* Capped so a long roster / log scrolls inside its card instead of making
   the whole page grow. */
.admin-user-table-wrap,
.admin-log-table-wrap {
  overflow: auto;
  max-height: 420px;
}
.admin-user-table thead th {
  position: sticky;
  top: 0;
  background-color: var(--color-surface);
  z-index: 1;
}
.admin-user-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.admin-user-table th {
  text-align: left;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-faint);
  padding: 8px 10px;
  border-bottom: 1px solid var(--color-border);
  white-space: nowrap;
}
.admin-user-table td {
  padding: 8px 10px;
  border-bottom: 1px solid var(--color-border-light);
  vertical-align: middle;
  white-space: nowrap;
}
.admin-log-path {
  font-family: monospace;
  font-size: 12px;
}

.admin-log-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: 12px;
  font-size: 13px;
  color: var(--color-text-faint);
}
/* Fixed slot so the 이전/다음 buttons hold still as the page counter grows
   from "1 / 3" to "10 / 30". */
#admin-logs-page-label {
  min-width: 76px;
  text-align: center;
}

.admin-event-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px;
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-md);
  margin-bottom: 6px;
}
.admin-event-name {
  font-weight: 700;
  font-size: 13px;
}
.admin-event-meta {
  font-size: 12px;
  color: var(--color-text-faint);
  margin-top: 2px;
}

/* ==========================================================================
   Event description (plain text or rendered Markdown)
   ========================================================================== */

.ne-desc-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}

.event-description {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface);
  box-shadow: var(--shadow-sm);
  padding: 12px 16px;
  margin-bottom: 14px;
  font-size: 14px;
}
.event-description-body {
  /* 접기(summary)를 없애면서 위 구분선도 함께 - 카드 하나에 내용만 남습니다. */
  margin: 0;
}

/* Shared typography for anything markdown.js renders. */
.md-body {
  color: var(--color-text);
  line-height: 1.7;
  overflow-wrap: anywhere;
}
.md-body > *:first-child {
  margin-top: 0;
}
.md-body > *:last-child {
  margin-bottom: 0;
}
.md-body p {
  margin: 0 0 10px;
}
.md-body h1,
.md-body h2,
.md-body h3,
.md-body h4,
.md-body h5,
.md-body h6 {
  color: var(--color-heading);
  margin: 16px 0 8px;
  line-height: 1.35;
}
.md-body h1 { font-size: 20px; }
.md-body h2 { font-size: 18px; }
.md-body h3 { font-size: 16px; }
.md-body h4,
.md-body h5,
.md-body h6 { font-size: 14px; }
/* Opts back out of the global `ul { list-style: none }` reset - rendered
   markdown is prose, so its lists need real bullets/numbers. */
.md-body ul,
.md-body ol {
  margin: 0 0 10px;
  padding-left: 22px;
}
.md-body ul {
  list-style: disc;
}
.md-body ol {
  list-style: decimal;
}
.md-body li {
  margin-bottom: 4px;
}
.md-body a {
  color: var(--color-accent);
  text-decoration: underline;
}
.md-body code {
  background-color: var(--color-surface-2);
  border-radius: var(--radius-sm);
  padding: 1px 5px;
  font-size: 0.9em;
}
.md-body pre {
  background-color: var(--color-surface-2);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  overflow-x: auto;
  margin: 0 0 10px;
}
.md-body pre code {
  background: none;
  padding: 0;
}
.md-body blockquote {
  margin: 0 0 10px;
  padding: 4px 12px;
  border-left: 3px solid var(--color-border);
  color: var(--color-text-muted);
}
.md-body hr {
  border: none;
  border-top: 1px solid var(--color-border);
  margin: 14px 0;
}
.md-body del {
  color: var(--color-text-faint);
}

/* Live preview under the description textarea in the create/edit dialog. */
.md-preview {
  margin-top: 10px;
  padding: 10px 12px;
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface-2);
  font-size: 13px;
  max-height: 220px;
  overflow-y: auto;
}
.md-preview-label {
  font-size: 11px;
  font-weight: 700;
  color: var(--color-text-faint);
  margin-bottom: 6px;
}

/* ==========================================================================
   면담 기록 / 학생지도비 신청서 폼 다이얼로그
   (일정 페이지의 시간대별 기록에서 열립니다 - record-form.js)
   ========================================================================== */

/* --- form dialog --- */

/* Kept to one line: the meeting title is arbitrary user text, and letting it
   wrap would make the header - and the body below it - a different height
   from one record to the next. */
#rec-form-title {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Scrolls inside the fixed .dialog-xl frame, so the modal itself never
   changes size as attendees or notes are added. */
.rec-form-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding-right: 4px;
}
.rec-form-columns {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 26px;
  align-items: start;
}
.rec-form-col {
  min-width: 0;
}
.rec-section {
  margin-bottom: 22px;
}
.rec-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
}
.rec-section-title {
  font-size: 14px;
  font-weight: 700;
  margin: 0 0 8px;
}
.rec-section-head .rec-section-title {
  margin-bottom: 0;
}
.rec-grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 12px;
}
.rec-form-footer {
  flex-shrink: 0;
}
.rec-footer-spacer {
  flex: 1;
}
.rec-danger {
  color: var(--color-danger);
}

.rec-attendee-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 8px;
}
/* Fixed column widths, so a long name can never widen the 학번 or 소속
   controls out of alignment with the rows above and below. */
.rec-attendee {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) 92px 118px 28px;
  align-items: center;
  gap: 6px;
}
.rec-attendee.is-absent {
  opacity: 0.5;
}
.rec-attendee .input {
  padding: 7px 9px;
  font-size: 13px;
  min-width: 0;
}
.rec-attendee-check {
  display: flex;
  align-items: center;
  justify-content: center;
}
.rec-attendee-remove {
  font-size: 18px;
  line-height: 1;
  color: var(--color-text-faint);
}

/* Must be written as element+class to out-specify `textarea.input`'s
   `min-height: 72px` above, the same trap as .list-sort-select. */
textarea.rec-textarea {
  width: 100%;
  /* Tall by default so the fixed-height dialog isn't half empty for a short
     meeting; it scrolls internally rather than growing the frame. */
  min-height: 220px;
  resize: vertical;
  line-height: 1.6;
  font-family: inherit;
}
textarea.rec-textarea-sm {
  min-height: 76px;
}
/* 면담 내용 네 항목(학업/생활/진로/기타). 공통 칸과 참석자별 칸이 같은
   묶음을 쓰므로 (record-form.js buildNoteFields) 규칙도 하나입니다.
   넷을 세로로 쌓으면 다이얼로그가 너무 길어져 2열로 접습니다. */
.rec-note-fields {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}
.rec-note-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.rec-note-field-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--color-text-muted);
}
@media (max-width: 900px) {
  .rec-note-fields {
    grid-template-columns: minmax(0, 1fr);
  }
}

.rec-note-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.rec-note-label {
  display: block;
  font-size: 12px;
  font-weight: 700;
  color: var(--color-text-muted);
  margin-bottom: 4px;
}

.rec-settlement-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.rec-settlement {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 12px;
}
.rec-settlement-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}
.rec-settlement-aff {
  font-size: 13px;
  font-weight: 700;
}
.rec-settlement-amount {
  font-size: 15px;
  font-weight: 800;
  color: var(--color-primary);
  /* Tabular figures keep the amount from shifting as digits change. */
  font-variant-numeric: tabular-nums;
}
.rec-settlement-calc {
  font-size: 12px;
  color: var(--color-text-faint);
  margin-bottom: 8px;
}
.rec-settlement-fields {
  display: grid;
  grid-template-columns: 130px minmax(0, 1fr);
  gap: 0 12px;
}
.rec-settlement-fields .field label {
  font-size: 11px;
}
.rec-file-row {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.rec-file-name {
  font-size: 12px;
  color: var(--color-text-muted);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rec-signature-canvas {
  display: block;
  width: 100%;
  height: 130px;
  background-color: #fff;
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-md);
  /* Without this, dragging to sign scrolls the dialog on touch devices. */
  touch-action: none;
  cursor: crosshair;
}
.rec-signature-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 6px;
}
.rec-signature-actions .hint {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 760px) {
  .rec-form-columns {
    grid-template-columns: minmax(0, 1fr);
  }
  /* Stacks name over the smaller fields so nothing gets squeezed to a few
     characters wide on a phone. */
  .rec-attendee {
    grid-template-columns: 24px minmax(0, 1fr) 28px;
    grid-template-areas:
      "check name remove"
      ". sid  ."
      ". aff  .";
    gap: 4px 6px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--color-border-light);
  }
  .rec-attendee-check {
    grid-area: check;
  }
  .rec-attendee-name {
    grid-area: name;
  }
  .rec-attendee-sid {
    grid-area: sid;
  }
  .rec-attendee-aff {
    grid-area: aff;
  }
  .rec-attendee-remove {
    grid-area: remove;
  }
  .rec-settlement-fields {
    grid-template-columns: minmax(0, 1fr);
  }
  /* Four footer buttons wrap to two rows on a phone; keeping them compact
     stops the footer from eating the fixed dialog's body height. */
  .rec-form-footer .btn {
    padding: 8px 12px;
    font-size: 13px;
  }
  textarea.rec-textarea {
    min-height: 160px;
  }
}

/* --- 확정 화면의 시간대별 면담 기록 (/e/{id}/finalize 4번 섹션) --------- */

.fin-records-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 4px;
}
.fin-records-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
/* 고정 폭 컬럼: 참석자 이름 길이가 달라도 상태·버튼 열이 흔들리지 않습니다. */
.fin-record-row {
  display: grid;
  /* 상태(금액)·버튼 열은 내용 폭만큼. 고정폭(150px/168px)이던 시절에는
     금액이 길어지면 버튼 밑으로 잘려 들어갔습니다. */
  grid-template-columns: 190px minmax(0, 1fr) max-content max-content;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--color-border-light);
}
.fin-record-row:last-child {
  border-bottom: none;
}
.fin-record-when {
  display: flex;
  align-items: center;
  gap: 6px;
}
.fin-record-time {
  font-size: 13px;
  font-weight: 700;
  color: var(--color-heading);
  white-space: nowrap;
}
/* 참석자가 많아도 한 줄로 - 행 높이가 들쭉날쭉해지지 않게 합니다. */
.fin-record-people {
  font-size: 13px;
  color: var(--color-text-muted);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fin-record-state {
  display: flex;
  align-items: center;
  gap: 8px;
}
.fin-record-amount {
  white-space: nowrap;
  font-size: 13px;
  font-weight: 700;
  color: var(--color-primary);
  font-variant-numeric: tabular-nums;
}
.fin-record-actions {
  display: flex;
  gap: 6px;
  justify-content: flex-end;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.fin-record-row.is-done .fin-record-time {
  color: var(--color-text-muted);
}

@media (max-width: 900px) {
  /* 좁은 화면에서는 시간/참석자 위, 상태/버튼 아래로 접습니다. */
  .fin-record-row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "when   state"
      "people actions";
    gap: 6px 10px;
  }
  .fin-record-when { grid-area: when; }
  .fin-record-people { grid-area: people; }
  .fin-record-state { grid-area: state; justify-content: flex-end; }
  .fin-record-actions { grid-area: actions; }
}

/* 확정/취소 버튼을 페이지 맨 위 헤더로 올렸습니다. 페이지가 길어서 아래쪽에
   두면 배정을 훑고 나서 다시 스크롤해 내려가야 했습니다. */
.finalize-top-actions {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
@media (max-width: 700px) {
  /* 좁은 화면에서는 헤더 액션이 줄바꿈되므로 두 버튼이 한 줄을 채우게 둡니다. */
  .finalize-top-actions {
    width: 100%;
    justify-content: flex-end;
  }
}

/* 연락처 선택 드롭다운을 체크박스 목록으로 바꾸면서 - 한 번에 여러 명을
   고르고, 이미 고른 사람도 체크된 채로 남아 되돌리기 쉽습니다. */
.contact-picker-row.checkbox-row {
  display: flex;
  align-items: center;
  /* .contact-picker-row의 space-between을 되돌립니다. 그 값은 "이름 왼쪽 /
     이메일 오른쪽" 한 줄 배치용이었는데, 체크박스 + 텍스트 두 덩어리가 되면서
     텍스트를 행 오른쪽 끝까지 밀어냈습니다. */
  justify-content: flex-start;
  gap: 8px;
  width: 100%;
  padding: 6px 8px;
  margin: 0;
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.contact-picker-row.checkbox-row:hover {
  background-color: var(--color-surface-2);
}
/* 이름과 이메일을 두 줄로 - 이름 길이가 달라도 이메일 위치가 흔들리지
   않도록 각자 한 줄을 차지합니다. */
.contact-picker-copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* 남은 폭을 채워야 긴 이메일이 말줄임될 자리가 생깁니다. */
  flex: 1;
  min-width: 0;
  gap: 1px;
  text-align: left;
}
.contact-picker-copy .contact-picker-name,
.contact-picker-copy .contact-picker-email {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 참가자 카드를 끌 때, 그 사람이 참석할 수 있는 칸을 전부 표시합니다.
   어디로 옮길 수 있는지 보이지 않으면 유효한 칸을 하나씩 찍어 봐야 합니다. */
.cal-grid.cal-picking .cal-cell {
  /* 후보가 아닌 칸은 눌러 두어 가능한 칸이 도드라지게 합니다. */
  opacity: 0.35;
  transition: opacity 0.12s;
}
.cal-grid.cal-picking .cal-cell-eligible {
  opacity: 1;
  box-shadow: inset 0 0 0 2px var(--color-navy);
}
/* 이미 배정된 칸은 원래 색이 진해서, 후보 표시가 묻히지 않도록
   테두리를 안쪽으로 한 겹 더 줍니다. */
.cal-grid.cal-picking .cal-cell-booked.cal-cell-eligible {
  box-shadow: inset 0 0 0 2px var(--color-navy), inset 0 0 0 4px rgba(255, 255, 255, 0.5);
}
/* 드롭 대상 표시는 후보 표시보다 우선합니다. */
.cal-grid.cal-picking .cal-cell.cal-drop-target {
  opacity: 1;
}

/* 미배정 사유 - 같은 사유끼리 묶어 보여 줍니다. */
.unassigned-reason-row {
  padding: 8px 0;
  border-top: 1px solid var(--color-border-light);
}
.unassigned-reason-row:first-of-type {
  border-top: none;
}
.unassigned-reason-names {
  font-size: 13px;
  font-weight: 700;
  color: var(--color-heading);
}
.unassigned-reason-text {
  font-size: 12px;
  color: var(--color-text-muted);
  margin-top: 2px;
  line-height: 1.5;
}
/* 배정 목록에서 그 사람 줄에 붙는 사유 표시. 크기가 고정이라 이름 길이나
   사유 유무로 줄 높이가 달라지지 않습니다. */
.assign-reason {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  border-radius: 50%;
  background-color: var(--color-warning-bg);
  color: var(--color-warning-text);
  border: 1px solid var(--color-warning-border);
  font-size: 11px;
  font-weight: 700;
  cursor: help;
}

/* 서명 칸 아래 버튼 두 개 (직접 긋기 / 이미지 올리기). 안내 문구 길이가
   파일명에 따라 달라지므로, 버튼 묶음은 줄어들지 않게 고정합니다. */
.rec-signature-buttons {
  display: inline-flex;
  gap: 6px;
  flex-shrink: 0;
}

/* 연락처 일괄 선택/삭제 바 */
.contacts-select-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 10px;
  padding: 0 2px;
}
.contacts-select-all {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: auto;
  margin: 0;
  font-size: 13px;
  white-space: nowrap;
  cursor: pointer;
}
/* 선택 수가 바뀌어도 삭제 버튼이 좌우로 흔들리지 않도록 폭을 잡아 둡니다. */
#contact-selected-count {
  min-width: 82px;
  font-size: 12px;
}
.contacts-delete-selected {
  margin-left: auto;
  /* "선택 삭제"와 "선택 삭제 (12)" 중 넓은 쪽을 미리 확보 */
  min-width: 104px;
  color: var(--color-danger);
}
.contacts-delete-selected:disabled {
  color: var(--color-text-faint);
  cursor: default;
}

/* 카드의 체크박스 - 그립 왼쪽에 붙되 카드 높이에 영향을 주지 않습니다. */
.contact-check {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  margin: 0;
  cursor: pointer;
}
.contact-row.is-selected {
  border-color: var(--color-primary);
  background-color: var(--color-primary-pale);
}

/* 확정 이후 바뀐 배정 목록 (확정 화면 상단) */
.fin-changes-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}
.fin-changes-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
/* 고정 폭 컬럼 - 이름이나 시각 길이가 달라도 "변경 종류" 열이 흔들리지
   않아, 여러 줄을 위아래로 훑어 읽을 수 있습니다. */
.fin-change-row {
  display: grid;
  grid-template-columns: 130px 128px minmax(0, 1fr);
  align-items: center;
  gap: 10px;
  padding: 5px 0;
  font-size: 13px;
}
.fin-change-name {
  font-weight: 700;
  color: var(--color-heading);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fin-change-kind {
  justify-self: start;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}
.fin-change-moved,
.fin-change-party {
  background-color: var(--color-warning-bg);
  color: var(--color-warning-text);
}
.fin-change-added {
  background-color: var(--color-primary-pale-2);
  color: var(--color-primary);
}
.fin-change-removed {
  background-color: var(--color-danger-bg);
  color: var(--color-danger-text);
}
.fin-change-when {
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fin-change-none {
  color: var(--color-text-faint);
}

@media (max-width: 700px) {
  .fin-change-row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "name kind"
      "when when";
    gap: 2px 8px;
  }
  .fin-change-name { grid-area: name; }
  .fin-change-kind { grid-area: kind; justify-self: end; }
  .fin-change-when { grid-area: when; }
}

/* 대시보드 섹션 구분 (내가 만든 일정 / 참여 중인 일정) */
.dashboard-section-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 15px;
  font-weight: 800;
  color: var(--color-heading);
  margin: 26px 0 10px;
}
.dashboard-section-title:first-child {
  margin-top: 6px;
}
.dashboard-section-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 20px;
  padding: 0 6px;
  border-radius: var(--radius-pill);
  background-color: var(--color-surface-3);
  color: var(--color-text-muted);
  font-size: 12px;
  font-weight: 700;
}

/* 참여 중인 일정 카드 - 내 일정과 눈으로 구분되도록 살짝 눌러 둡니다. */
.event-card-readonly {
  background-color: var(--color-surface-2);
}
/* 액션 줄의 높이를 내 일정 카드와 맞춰, 두 종류가 섞여 보여도 카드 높이가
   들쭉날쭉해지지 않게 합니다. */
.event-card-readonly-note {
  display: inline-flex;
  align-items: center;
  padding: 0 4px;
  font-size: 12px;
  color: var(--color-text-faint);
}

/* 휴지통 (/trash) */
.trash-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.trash-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.trash-main {
  min-width: 0;
}
.trash-name {
  font-size: 15px;
  font-weight: 700;
  color: var(--color-heading);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.trash-meta {
  font-size: 12px;
  color: var(--color-text-faint);
  margin-top: 2px;
}
.trash-counts {
  font-size: 13px;
  color: var(--color-text-muted);
  margin-top: 4px;
}
/* 버튼 묶음은 줄어들지 않게 - 일정 이름 길이가 달라도 위치가 고정됩니다. */
.trash-actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}
.trash-purge {
  color: var(--color-danger);
}
.purge-list {
  margin: 0 0 4px;
  padding-left: 20px;
  list-style: disc;
  font-size: 13px;
  color: var(--color-text-muted);
  line-height: 1.8;
}

@media (max-width: 700px) {
  .trash-row {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  .trash-actions {
    justify-content: flex-end;
  }
}

/* 취소/삭제된 일정 링크를 눌렀을 때 나오는 안내 */
.removed-event {
  max-width: 520px;
  margin: 80px auto;
  text-align: center;
}
.removed-event-icon {
  display: flex;
  justify-content: center;
  color: var(--color-text-faint);
  margin-bottom: 14px;
}
.removed-event h1 {
  font-size: 22px;
  margin: 0 0 10px;
}
.removed-event-name {
  font-size: 15px;
  font-weight: 700;
  color: var(--color-heading);
  margin: 0 0 14px;
  word-break: break-word;
}
.removed-event-desc {
  color: var(--color-text-muted);
  line-height: 1.7;
  margin: 0 0 10px;
}
.removed-event-host {
  font-size: 13px;
  color: var(--color-text-faint);
  margin: 0;
}
.removed-event-actions {
  margin-top: 24px;
}
/* 휴지통에서 "취소됨"은 참가자에게 영향이 있었던 일이라 눈에 띄게 둡니다. */
.trash-badge-cancelled {
  background-color: var(--color-warning-bg);
  color: var(--color-warning-text);
}

/* 연락처 다중 선택 - Shift+클릭으로 범위를 고를 때 글자가 함께 드래그
   선택되지 않게 합니다. 다만 이메일은 복사할 일이 많아 그대로 둡니다. */
/* .contact-row는 위쪽 "가입자 검색" 결과에도 쓰이므로, 선택 규칙은 실제
   연락처 목록(#contacts-list) 안쪽에만 적용합니다. */
#contacts-list .contact-row {
  user-select: none;
  /* 카드 아무 곳이나 눌러 선택할 수 있다는 걸 커서로 알립니다. */
  cursor: pointer;
}
#contacts-list .contact-row .email {
  user-select: text;
}
#contacts-list .contact-row input {
  cursor: initial;
}
#contacts-list .contact-row .contact-grip {
  cursor: grab;
}
#contacts-list .contact-row button,
#contacts-list .contact-row a,
#contacts-list .contact-row label {
  cursor: pointer;
}
/* 사용법 안내는 좁은 화면에서 먼저 숨깁니다 - 없어도 클릭은 동작합니다. */
.contacts-select-hint {
  font-size: 12px;
  color: var(--color-text-faint);
  white-space: nowrap;
}
@media (max-width: 900px) {
  .contacts-select-hint {
    display: none;
  }
}

/* ==========================================================================
   POVIS 자동입력 확장 안내 페이지 (/povis-extension)
   ========================================================================== */

.ext-page {
  max-width: 800px;
  padding-top: 32px;
  padding-bottom: 80px;
}
.ext-hero {
  padding: 32px 28px;
}
.ext-eyebrow {
  margin: 0 0 6px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--color-primary);
}
.ext-hero h1 {
  margin: 0 0 12px;
  font-size: 30px;
}
.ext-lead {
  margin: 0;
  font-size: 16px;
  line-height: 1.65;
}
.ext-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 20px;
}
.ext-version {
  font-weight: 500;
  opacity: 0.8;
  font-size: 13px;
}
.ext-note {
  margin: 12px 0 0;
  font-size: 13px;
  color: var(--color-text-muted, #666);
  line-height: 1.6;
}
.ext-section {
  margin-top: 40px;
}
.ext-section h2 {
  font-size: 22px;
  margin: 0 0 16px;
}
.ext-sub {
  font-size: 16px;
  margin: 28px 0 10px;
}
.ext-steps {
  list-style: none;
  counter-reset: ext-step;
  margin: 0;
  padding: 0;
}
.ext-steps > li {
  counter-increment: ext-step;
  position: relative;
  padding: 0 0 22px 48px;
}
.ext-steps > li::before {
  content: counter(ext-step);
  position: absolute;
  left: 0;
  top: 0;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--color-primary);
  color: #fff;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ext-steps h3 {
  margin: 4px 0 6px;
  font-size: 16px;
  font-weight: 600;
}
.ext-steps p,
.ext-list li {
  margin: 0 0 6px;
  line-height: 1.65;
}
.ext-list {
  margin: 0;
  padding-left: 20px;
}
.ext-address {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 8px 0;
}
.ext-address code {
  font-size: 15px;
  padding: 8px 12px;
  border-radius: var(--radius-md);
  background: var(--color-surface-2);
  border: 1px solid var(--color-border);
}
.ext-callout {
  margin-top: 8px;
  padding: 14px 16px;
  border-radius: var(--radius-md);
  background: var(--color-surface-2);
  border-left: 4px solid var(--color-primary);
  line-height: 1.6;
}
.ext-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.ext-table th,
.ext-table td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid var(--color-border);
  vertical-align: top;
}
.ext-table th {
  background: var(--color-surface-2);
}
