/* Board page: sits on top of landing.css tokens/typography. */
.board-main {
  /* width is load-bearing: body.gallery-page / body.landing-page are flex
     columns so the sticky banner shares the viewport, and on a flex item
     `margin: 0 auto` turns off cross-axis stretch — without this the block
     collapses to its content width. */
  width: 100%;
  /* Same measure as the landing page, which shares this header and footer: the
     board was the narrower page on the site for no reason, and the roadmap's
     four columns need the room. Panels that are mostly prose cap themselves
     below this so their lines stay readable. */
  max-width: 72rem;
  margin: 0 auto;
  padding: 3rem 1.25rem 4rem;
}

/* No cap on the body. Capping it while the title and summary above kept the
   card's full width left a ragged column of empty space down the right of every
   opened notice -- the card, not the paragraph, is what a reader sees the edge
   of. If the measure ever needs limiting it has to be the whole card. */

.board__title {
  font-size: clamp(1.75rem, 4vw, 2.5rem);
  margin: 0 0 1.5rem;
}

.board__tabs {
  display: flex;
  gap: 0.5rem;
  border-bottom: 1px solid var(--line, rgba(128, 128, 128, 0.3));
  margin-bottom: 1.5rem;
}

.board__tab {
  appearance: none;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  color: inherit;
  cursor: pointer;
  font: inherit;
  padding: 0.6rem 0.9rem;
  opacity: 0.65;
}

.board__tab[aria-selected="true"] {
  border-bottom-color: currentColor;
  opacity: 1;
}

.board__filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1.25rem;
}

.board__filter {
  appearance: none;
  background: none;
  border: 1px solid var(--line, rgba(128, 128, 128, 0.35));
  border-radius: 999px;
  color: inherit;
  cursor: pointer;
  font: inherit;
  font-size: 0.85rem;
  padding: 0.35rem 0.85rem;
  opacity: 0.75;
}

.board__filter[aria-selected="true"] {
  border-color: currentColor;
  opacity: 1;
}

.board__badge--maintenance {
  border-color: #c2410c;
  color: #c2410c;
}

.board__panel[hidden] {
  display: none;
}

.board__error {
  border-radius: 0.5rem;
  background: rgba(220, 60, 60, 0.12);
  padding: 0.75rem 1rem;
  margin-bottom: 1rem;
}

.board__admin {
  border: 1px solid var(--line, rgba(128, 128, 128, 0.3));
  border-radius: 0.75rem;
  margin-bottom: 2rem;
  padding: 1.25rem;
}

.board__form {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.board__label {
  font-size: 0.85rem;
  opacity: 0.75;
}

.board__input,
.board__textarea {
  background: transparent;
  border: 1px solid var(--line, rgba(128, 128, 128, 0.35));
  border-radius: 0.5rem;
  color: inherit;
  font: inherit;
  padding: 0.55rem 0.7rem;
  width: 100%;
}

.board__textarea {
  resize: vertical;
}

.board__check {
  align-items: center;
  display: flex;
  gap: 0.5rem;
  font-size: 0.9rem;
}

.board__form-actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

/* Theme tokens, not currentColor: `background: currentColor` painted the
   button in the surrounding text colour, which made the dialog's close button
   a dark blob on a dark surface. */
.board__button {
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-accent);
  cursor: pointer;
  font: inherit;
  font-weight: 600;
  padding: 0.45rem 1.1rem;
}

.board__button:hover {
  background: var(--accent-hover, var(--accent));
}

.board__button--ghost {
  background: transparent;
  border-color: var(--border-strong, var(--border));
  color: inherit;
  font-weight: 400;
}

.board__button--ghost:hover {
  background: var(--btn-bg-hover, transparent);
}

.board__list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.board__item {
  border: 1px solid var(--line, rgba(128, 128, 128, 0.25));
  border-radius: 0.75rem;
  padding: 1rem 1.15rem;
  /* Anchor for the stretched toggle below. */
  position: relative;
  transition: background-color 0.15s var(--ease-out, ease);
}

/* Only a notice with a body is openable, so only that one lights up -- a hover
   highlight on a row that does nothing when clicked is a promise it can't keep. */
.board__item:has(.board__item-toggle):hover {
  background: var(--surface-raised, rgba(128, 128, 128, 0.12));
  border-color: var(--border-strong, var(--border));
}

.board__item-toggle {
  cursor: pointer;
}

/* The chevron stays the real control -- one button, one label, one focus stop --
   but its hit area covers the card, so the click lands wherever the eye is. */
.board__item-toggle::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}


.board__item-head {
  align-items: baseline;
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  justify-content: space-between;
}

/* Hierarchy from size and weight, not from the display serif: that face has no
   Hangul, so Korean titles fall through to whatever serif the OS happens to
   have — a face nobody chose. */
.board__item-title {
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.3;
  margin: 0;
}

.board__item-meta {
  font-size: 0.8rem;
  opacity: 0.6;
}

.board__badge {
  border: 1px solid currentColor;
  border-radius: 999px;
  font-size: 0.7rem;
  margin-left: 0.4rem;
  padding: 0.1rem 0.5rem;
}

/* Hairline rule, the same device the cards and tab bar already use, so the
   body reads as a continuation of the notice rather than a second card. */
.board__item-body {
  margin: 0.85rem 0 0;
  padding-top: 0.85rem;
  border-top: 1px solid var(--line, rgba(128, 128, 128, 0.25));
  white-space: pre-wrap;
  color: var(--fg);
  /* Above the stretched toggle: expanded text has to stay selectable rather
     than close the notice it belongs to. */
  position: relative;
  z-index: 1;
}

.board__item-actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.85rem;
  /* Above the stretched toggle, or 수정/삭제 would just open the notice. */
  position: relative;
  z-index: 1;
}

.board__empty,
.board__loading {
  opacity: 0.7;
}

/* Summary line in the list. A body, when there is one, expands underneath on
   demand, so the list stays scannable however long a notice is. */
.board__item-summary {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  margin: 0.5rem 0 0;
}

.board__item-summary-text {
  flex: 1;
  margin: 0;
  font-size: 0.9375rem;
  font-weight: 400;
  /* The summary is the notice as far as most readers are concerned; only the
     date beside it is metadata. */
  color: var(--fg);
}

.board__item-toggle {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  margin: -0.25rem -0.35rem 0 0;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: none;
  color: inherit;
  cursor: pointer;
  opacity: 0.55;
  transition: opacity 0.15s ease, background 0.15s ease;
}

.board__item-toggle svg {
  transition: transform 0.15s ease;
}

.board__item-toggle:hover,
.board__item-toggle:focus-visible {
  opacity: 1;
  background: var(--btn-bg-hover, rgba(128, 128, 128, 0.12));
}

.board__item-toggle[aria-expanded="true"] svg {
  transform: rotate(180deg);
}

@media (prefers-reduced-motion: reduce) {
  .board__item-toggle,
  .board__item-toggle svg {
    transition: none;
  }
}

.board__item-body[hidden] {
  display: none;
}

/* Tenant notices view — mounted inside gallery `.main` / `#media-grid`.
   `.main` remains the only scroll container (body.gallery-page owns viewport). */
.media-grid.media-grid--notices {
  display: block;
  grid-template-columns: none;
  gap: 0;
}

.media-grid--notices .notices-view {
  max-width: 56rem;
  margin: 0 auto;
  padding: 0 0 2rem;
}

.media-grid--notices .board__list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}


/* Notices toolbar — the editor is opened on demand, so the write button is the
   only owner control on screen until it is. */
.notices-view__toolbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 1rem;
}

.notices-view__toolbar[hidden] {
  display: none;
}

/* The editor names what it is editing, because it opens in the place of the
   card being edited and would otherwise be indistinguishable from a new one. */
.board__admin-title {
  margin: 0 0 0.85rem;
  font-size: 1rem;
  font-weight: 600;
}

/* 1:1 inquiry tab: list, thread detail, and the create form. */
.inquiry__toolbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 1rem;
}

.inquiry__notice {
  margin: 0 0 1rem;
  color: var(--muted);
}

.inquiry__item {
  border-bottom: 1px solid var(--border);
  padding: 0.85rem 0.6rem;
  border-radius: 0.5rem;
  position: relative;
  transition: background-color 0.15s var(--ease-out, ease);
}

.inquiry__item:hover {
  background: var(--surface-raised, rgba(128, 128, 128, 0.12));
}

/* Same trick as the notice card: the title button is the only focus stop, its
   hit area is the whole row -- including the author/date line under it. */
.inquiry__open::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.inquiry__open {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.inquiry__item-title {
  font-weight: 600;
}

.inquiry__item-meta {
  display: flex;
  gap: 0.75rem;
  margin-top: 0.3rem;
  color: var(--muted);
  font-size: 0.85rem;
}

.inquiry__badge {
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.05rem 0.5rem;
  font-size: 0.75rem;
  white-space: nowrap;
}

.inquiry__badge--answered {
  border-color: var(--accent);
  color: var(--accent);
}

.inquiry__badge--closed {
  color: var(--muted);
}

/* The secret marker is the one badge that is not a status, so it reads quieter
   than the status pill sitting next to it. */
.inquiry__badge--secret {
  border-style: dashed;
  color: var(--muted);
}

.board__more {
  display: block;
  width: 100%;
  margin-top: 0.75rem;
}

.inquiry__detail-title {
  margin: 0.75rem 0;
}

.inquiry__ops {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 1rem;
}

/* The label and the button carry short fixed words; only the select may give
   up width. Without this the flex line squeezes them into stacked characters. */
.inquiry__ops .board__label,
.inquiry__ops .board__button {
  flex: 0 0 auto;
  white-space: nowrap;
  margin: 0;
}

.inquiry__ops .board__input {
  flex: 0 1 12rem;
  width: auto;
}

.inquiry__thread {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.inquiry__message {
  border: 1px solid var(--border);
  border-radius: 0.6rem;
  padding: 0.75rem 0.9rem;
}

.inquiry__message--operator {
  border-color: var(--accent);
}

.inquiry__message-head {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  /* Brief said --text-muted; this codebase's muted-foreground token is
     --muted (see theme.css), which the Task 5 styles above already use. */
  color: var(--muted);
  font-size: 0.85rem;
}

.inquiry__message-body {
  margin: 0.4rem 0 0;
  white-space: pre-wrap;
}

.inquiry__reply,
.inquiry__form {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 1rem;
}

/* The column stretches its children, which would give a one-word submit button
   the full width of the thread. */
.inquiry__reply .board__button {
  align-self: flex-start;
}

.board__rich-editor {
  margin: 0 0 0.75rem;
  min-height: 12rem;
}

.board__editor-fallback {
  margin: 0 0 0.5rem;
  color: var(--muted);
  font-size: 0.9rem;
}

.toastui-editor-defaultUI,
.toastui-editor-contents,
.toastui-editor-contents h1,
.toastui-editor-contents h2,
.toastui-editor-contents h3,
.toastui-editor-contents p,
.toastui-editor-contents li,
.toastui-editor-contents table {
  font-family: var(--font-body);
}

.board__item-body .toastui-editor-contents,
.inquiry__message-body .toastui-editor-contents {
  font-size: 0.95rem;
}

/* Roadmap ------------------------------------------------------------- */

.roadmap__toolbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 12px;
}

.roadmap__columns {
  display: grid;
  /* The four pipeline stages side by side on a wide screen, folding to two and
     then one as it narrows. The column headers stay at every width, so the
     status of a group is never ambiguous. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
}

@media (max-width: 900px) {
  .roadmap__columns {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 560px) {
  .roadmap__columns {
    grid-template-columns: minmax(0, 1fr);
  }
}

.roadmap__column-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 10px;
  font-size: 0.95rem;
}

.roadmap__count {
  font-size: 0.8rem;
  opacity: 0.7;
}

.roadmap__column-empty {
  margin: 0;
  padding: 12px 0;
  font-size: 0.85rem;
  opacity: 0.6;
}

.roadmap__card {
  position: relative;
  margin-bottom: 10px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
}

.roadmap__card--openable:hover {
  border-color: var(--accent);
}

/* One stretched control: the whole card is the hit area, the button is the
   only focus stop and the only accessible name. */
.roadmap__open {
  position: absolute;
  inset: 0;
  width: 100%;
  border: 0;
  border-radius: 10px;
  background: transparent;
  cursor: pointer;
}

.roadmap__card-title {
  margin: 0 0 6px;
  font-size: 0.95rem;
}

.roadmap__card-summary {
  margin: 0;
  font-size: 0.85rem;
  opacity: 0.85;
}

/* Badges and the "more to read" cue share one line -- the target on the left,
   the cue on the right -- so a card costs one row for both instead of two. */
.roadmap__card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 10px;
}

/* Nothing on either side: no row at all, and no stray margin under the card. */
.roadmap__card-foot:has(.roadmap__card-badges:empty):not(:has(.roadmap__more)) {
  display: none;
}

/* The row owns the spacing now, so its children stop adding their own. */
.roadmap__card-foot .roadmap__badge {
  margin-top: 0;
}

.roadmap__card-foot .roadmap__more {
  margin: 0;
}

/* Progress is its own axis, so it reads as a measure rather than a status: a
   thin track under the summary, with the number beside it for anyone who cannot
   judge a bar by eye. */
.roadmap__progress {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
}

.roadmap__progress-track {
  flex: 1;
  height: 4px;
  border-radius: 999px;
  background: var(--chip-bg, rgba(127, 127, 127, 0.15));
  overflow: hidden;
}

.roadmap__progress-fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--accent);
}

.roadmap__progress-value {
  font-size: 0.75rem;
  opacity: 0.75;
  font-variant-numeric: tabular-nums;
}

/* The cue that a card has more to say. Only cards with a body get it, so the
   board never promises a detail view that is not there. */
.roadmap__more {
  display: flex;
  align-items: center;
  gap: 4px;
  margin: 10px 0 0;
  font-size: 0.8rem;
  opacity: 0.7;
}

.roadmap__card--openable:hover .roadmap__more {
  opacity: 1;
}

.roadmap__badge {
  display: inline-block;
  margin-top: 8px;
  margin-right: 6px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.75rem;
  background: var(--chip-bg, rgba(127, 127, 127, 0.15));
}

/* 대상 배지는 시기 배지와 같은 줄에 서므로 채움이 아니라 테두리로 구분한다.
   새 색을 들이면 테마 둘을 다 맞춰야 하는데, 여기서 필요한 것은 "다른 종류"라는
   신호뿐이다. 테두리이므로 채움용 --chip-bg 가 아니라 테두리 토큰을 쓴다. */
.roadmap__badge--audience {
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--border-strong);
}

.roadmap__dropped {
  margin-top: 20px;
}

.roadmap__dropped-summary {
  cursor: pointer;
  font-size: 0.9rem;
}

.roadmap__dropped-list {
  margin-top: 10px;
}

.roadmap__cap {
  margin-top: 16px;
  font-size: 0.85rem;
  opacity: 0.8;
}

/* A lede under the heading, not a second footer -- no rule of its own, or the
   page ends up with two horizontal lines saying the same thing. */
.roadmap__disclaimer {
  margin: 0 0 20px;
  font-size: 0.85rem;
  line-height: 1.6;
  opacity: 0.75;
}

.roadmap__modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(0, 0, 0, 0.5);
}

.roadmap__modal {
  width: min(680px, 100%);
  max-height: 80vh;
  overflow-y: auto;
  padding: 20px;
  border-radius: 12px;
  background: var(--surface);
}

.roadmap__modal-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.roadmap__modal-title {
  margin: 0;
  font-size: 1.1rem;
}

.roadmap__modal-summary {
  margin: 6px 0 14px;
  font-size: 0.9rem;
  opacity: 0.85;
}

/* Operator controls live here and nowhere else: status, edit, delete, close.
   They wrap rather than squeeze so a long title never crushes them. */
.roadmap__modal-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}

.roadmap__status-select {
  padding: 0.3rem 0.5rem;
  border: 1px solid var(--line, rgba(128, 128, 128, 0.25));
  border-radius: 8px;
  background: var(--surface);
  color: var(--fg);
  font: inherit;
  font-size: 0.85rem;
}

.roadmap__icon-button {
  padding: 0.2rem 0.5rem;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--fg);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}

.roadmap__icon-button:hover {
  background: var(--chip-bg, rgba(127, 127, 127, 0.15));
}

.roadmap__modal-error {
  margin: 10px 0 0;
  color: var(--danger, #c0392b);
  font-size: 0.85rem;
}

/* Shown only after the destructive click, so the question sits where the
   answer is given. */
.roadmap__confirm {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--line, rgba(128, 128, 128, 0.25));
  font-size: 0.9rem;
}

.board__button--danger {
  color: var(--danger, #c0392b);
  border-color: color-mix(in srgb, var(--danger, #c0392b) 35%, transparent);
}

/* Status, target and order are short fields; stacking them full width made the
   form look longer than the work it asks for. */
.roadmap__form-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 0.5rem;
}

.roadmap__field {
  display: flex;
  flex: 1 1 160px;
  flex-direction: column;
}

.roadmap__field--narrow {
  flex: 0 1 110px;
}

.roadmap__form .board__label {
  margin-top: 0.75rem;
}

.roadmap__form-row .board__label {
  margin-top: 0;
}
