.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: fixed;
  top: var(--space-3);
  left: var(--space-3);
  z-index: var(--z-toast);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--color-text);
  color: var(--color-surface);
  font-weight: 700;
  text-decoration: none;
  transform: translateY(calc(-100% - var(--space-6)));
  transition: transform var(--motion-micro) var(--ease-out);
}

.skip-link:focus-visible {
  transform: translateY(0);
}

.app-layout {
  min-height: 100dvh;
}

#appMain {
  min-height: 100dvh;
  padding-bottom: calc(var(--nav-mobile) + var(--space-8) + env(safe-area-inset-bottom, 0px));
}

.screen {
  width: min(100%, var(--content-max));
  min-height: 100dvh;
  margin: 0 auto;
  padding: var(--space-6) var(--space-4) var(--space-12);
}

.route-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-2) 0 var(--space-8);
}

/* 네 개 라우트 헤더 전부에 적용된다. flex 자식의 기본 min-width는 auto라, 띄어쓰기가 적은 한글
   제목이 폭을 그대로 붙잡아 오른쪽 아이콘 버튼(홈의 검색 등)을 화면 밖으로 밀어낸다.
   29rem 미만에서는 홈을 제외한 헤더가 세로로 바뀌므로(아래 미디어 쿼리) 그 폭에서는 홈에만
   영향이 있고, 그 위에서는 줄어들지 않는 .vault-ribbon(기본 flex 항목)을 가진 헤더도 함께 보호한다.
   대가로 극단적 확대에서 .vault-switcher의 보관함 이름이 잘릴 수 있는데, 화면을 뚫는 쪽보다 낫다. */
.route-header > *:first-child {
  min-width: 0;
}

.route-eyebrow,
.route-title,
.route-description,
.section-kicker,
.content-section h2,
.settings-group h2,
.add-details-heading h2 {
  margin: 0;
}

.route-eyebrow,
.section-kicker {
  color: var(--color-brand-700);
  font-size: var(--text-caption);
  font-weight: 750;
}

.route-title {
  margin-top: var(--space-1);
  font-size: var(--text-h1);
  font-weight: 800;
  letter-spacing: var(--tracking-heading);
  line-height: var(--leading-heading);
  text-wrap: balance;
}

.route-description {
  max-width: 52ch;
  margin-top: var(--space-2);
  color: var(--color-text-secondary);
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body);
  line-height: var(--leading-body);
  text-wrap: balance;
}

.login-lede,
.privacy-note,
.field-hint,
.settings-copy {
  text-wrap: balance;
}

.field-hint {
  letter-spacing: var(--tracking-body);
  line-height: var(--leading-body);
}

.text-nowrap {
  white-space: nowrap;
}

.status-line {
  min-height: calc(var(--leading-body) * 1em);
  margin: var(--space-3) 0 0;
  color: var(--color-text-secondary);
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body);
  line-height: var(--leading-body);
}

.status-line[data-tone="error"],
.status-line.error {
  color: var(--color-error);
  font-weight: 650;
}

.status-line[data-tone="success"] {
  color: var(--color-success);
  font-weight: 650;
}

.link-button {
  min-height: var(--control-min);
  padding: var(--space-2);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-brand-700);
  font-weight: 750;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.link-button:active {
  background-image: linear-gradient(var(--state-pressed-tint), var(--state-pressed-tint));
}

.link-button:disabled,
.link-button[aria-disabled="true"] {
  cursor: not-allowed;
  opacity: var(--state-disabled-opacity);
}

.stack {
  display: grid;
  gap: var(--space-4);
}

.field-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-3);
}

.optional-label {
  color: var(--color-text-secondary);
  font-weight: 500;
  letter-spacing: var(--tracking-body);
}

.input-with-icon,
.url-field,
.search-field {
  position: relative;
  display: flex;
  min-width: 0;
  flex: 1;
  align-items: center;
}

:where(.input-with-icon, .url-field, .search-field) > .icon {
  position: absolute;
  left: var(--space-4);
  z-index: 1;
  color: var(--color-text-secondary);
  pointer-events: none;
}

:where(.input-with-icon, .url-field, .search-field) input {
  padding-left: calc(var(--space-8) + var(--space-2));
}

.compact-action {
  flex: 0 0 auto;
}

.connectivity-banner {
  position: fixed;
  top: var(--space-3);
  right: var(--space-3);
  left: var(--space-3);
  z-index: var(--z-banner);
  display: flex;
  width: min(calc(100% - (var(--space-6))), 42rem);
  align-items: center;
  gap: var(--space-3);
  margin: 0 auto;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--color-warning-soft);
  color: var(--color-warning);
  box-shadow: var(--shadow-floating);
  font-size: var(--text-body-sm);
  font-weight: 650;
}

.login-screen {
  display: grid;
  align-content: center;
  padding-top: var(--space-10);
  padding-bottom: var(--space-10);
}

.login-story {
  display: none;
}

.login-panel {
  display: grid;
  width: min(100%, 30rem);
  gap: var(--space-5);
  margin: 0 auto;
  padding: var(--space-6);
  border-radius: var(--radius-xl);
  background: var(--surface-raised);
  box-shadow: var(--shadow-paper);
}

.login-hero {
  display: grid;
  gap: var(--space-4);
}

.login-brand {
  margin-bottom: var(--space-3);
}

.login-logo {
  font-size: var(--text-h2);
}

.login-heading {
  max-width: 14ch;
  margin: 0;
  font-size: var(--text-h1);
  font-weight: 750;
  letter-spacing: var(--tracking-heading);
  line-height: var(--leading-heading);
  text-wrap: balance;
}

.login-lede {
  max-width: 38ch;
  margin: 0;
  color: var(--color-text-secondary);
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body);
  line-height: var(--leading-body);
}

.auth-form {
  gap: var(--space-4);
}

.auth-submit {
  width: 100%;
  min-height: var(--control-lg);
  margin-top: var(--space-1);
}

.auth-switch {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  margin: 0;
  color: var(--color-text-secondary);
  font-size: var(--text-body-sm);
}

.privacy-note {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  margin: 0;
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border-subtle);
  color: var(--color-text-secondary);
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-caption);
  line-height: var(--leading-caption);
}

.privacy-note .icon {
  color: var(--color-success);
}

.home-header {
  align-items: center;
}

.vault-title-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.vault-switcher {
  width: auto;
  max-width: min(72vw, 30rem);
  min-height: var(--control-min);
  padding: 0 calc(var(--space-8) + var(--space-2)) 0 0;
  border: 0;
  background-color: transparent;
  color: var(--color-text);
  font-size: var(--text-h1);
  font-weight: 750;
  letter-spacing: var(--tracking-heading);
}

/* 홈 요약 스트립: 헤더 바로 아래에서 "오늘/이번 주말에 뭘 하면 되는지"에 먼저 답한다.
   .search-row와 같은 세로 리듬을 쓰지만 표면을 한 단 올려(surface-raised + 얇은 테두리)
   화면에서 가장 먼저 읽히게 한다. 색을 키우거나 그림자를 얹어 소리치지는 않는다. */
.home-summary {
  margin-bottom: var(--space-5);
}

/* 타일은 최대 세 개다. repeat(auto-fit, minmax(0, 1fr))은 최소 트랙이 0이라 반복 횟수가
   브라우저마다 흔들리므로, 항목 수만큼 열을 만들고 각 열을 minmax(0, 1fr)로 잘라
   360px에서도 넘치지 않고 가로 스크롤도 생기지 않게 한다. */
.summary-tiles {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.summary-tile {
  min-width: 0;
}

/* 타일이 하나뿐일 때 화면 폭 전체로 늘어나 숫자 하나가 배너처럼 보이는 것을 막는다. */
.summary-tile:only-child {
  max-width: 20rem;
}

.summary-tile-button {
  display: grid;
  width: 100%;
  min-width: 0;
  min-height: var(--control-min);
  align-content: start;
  gap: var(--space-1);
  padding: var(--space-3);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-lg);
  background: var(--surface-raised);
  color: var(--color-text);
  text-align: left;
  transition:
    background-color var(--motion-micro) var(--ease-out),
    border-color var(--motion-micro) var(--ease-out);
}

.summary-tile-count {
  color: var(--color-brand-700);
  font-size: var(--text-h2);
  font-weight: 750;
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-heading);
  line-height: var(--leading-tight);
}

.summary-tile-label {
  color: var(--color-text);
  font-size: var(--text-body-sm);
  font-weight: 750;
  letter-spacing: var(--tracking-body);
  line-height: var(--leading-snug);
}

/* 힌트는 보조 정보다. 세 타일이 104px 폭까지 좁아지는 360px에서 세 줄로 흐르지 않게
   두 줄에서 자르고, 360px·375px처럼 흔한 폭에서는 감추지 않고 한 줄로 줄인다(아래 24rem 규칙). */
.summary-tile-hint {
  display: -webkit-box;
  overflow: hidden;
  color: var(--color-text-secondary);
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-caption);
  line-height: var(--leading-caption);
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.summary-tile-button:active {
  background-image: linear-gradient(var(--state-pressed-tint), var(--state-pressed-tint));
}

/* 360px·375px 안드로이드/아이폰은 한국에서 가장 흔한 폭이다. 타일 셋을 나란히 두면 캡션 한 줄에
   다섯 글자밖에 안 들어가 날짜가 잘리고 aria-label과 어긋난다. 그래서 세로로 쌓되, 그냥 쌓으면
   요약 줄이 314px까지 자라 정작 저장한 카드가 첫 화면 밖으로 밀린다(측정값: 그리드 top 874px,
   화면 높이 844px). 쌓은 타일은 숫자·라벨을 한 줄에 붙이고 힌트를 그 아래 한 줄로 눌러 담는다. */
@media (max-width: 30rem) {
  .summary-tiles {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    gap: var(--space-1);
  }

  .summary-tile:only-child {
    max-width: none;
  }

  .summary-tile-button {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: baseline;
    gap: 0 var(--space-2);
    padding: var(--space-2) var(--space-3);
  }

  .summary-tile-count {
    grid-row: 1;
    font-size: var(--text-h3);
  }

  .summary-tile-label {
    grid-row: 1;
  }

  .summary-tile-hint {
    grid-column: 1 / -1;
    grid-row: 2;
    -webkit-line-clamp: 2;
  }
}

/* 코스 개수를 아직 모르는 자리표시자. 숫자를 주장하지 않고 자리만 지켜, 답이 도착할 때 화면이
   흔들리지 않게 한다. 누를 수 없는 표시이므로 커서도 기본값으로 둔다. */
.summary-tile[data-pending] .summary-tile-button {
  cursor: default;
}

.summary-tile[data-pending] .summary-tile-count {
  width: 2.5ch;
  height: 1em;
  border-radius: var(--radius-control);
}

/* 요약 타일을 눌렀을 때 대상이 이미 화면에 보이면 스크롤도, 포커스 링도 나타나지 않는다.
   눌렀다는 사실이 보이지 않으면 죽은 버튼처럼 느껴지므로 대상에 짧게 강조를 남긴다. */
@keyframes summary-target-flash {
  from {
    box-shadow: 0 0 0 var(--focus-ring-width) var(--color-brand-500);
  }

  to {
    box-shadow: 0 0 0 var(--focus-ring-width) transparent;
  }
}

/* 강조는 애니메이션에 의존하지 않는다. prefers-reduced-motion에서 duration이 0.01ms로 눌리므로
   애니메이션만 쓰면 모션을 줄인 사용자에게는 누른 흔적이 전혀 남지 않는다. 정적인 링을 먼저
   켜고, 모션이 허용된 환경에서만 서서히 사라지게 한다. */
.summary-target-flash {
  border-radius: var(--radius-control);
  box-shadow: 0 0 0 var(--focus-ring-width) var(--color-brand-500);
}

@media (prefers-reduced-motion: no-preference) {
  .summary-target-flash {
    animation: summary-target-flash 1.2s var(--ease-out) 1;
  }
}

.search-row,
.paste-row,
.inline-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.search-row {
  margin-bottom: var(--space-5);
  padding: var(--space-3);
  border-radius: var(--radius-lg);
  background: var(--surface-sunken);
  box-shadow: var(--shadow-sunken);
}

.discovery-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.discovery-toolbar .chip-row {
  min-width: 0;
  flex: 1;
}

.chip .icon {
  width: var(--space-4);
  height: var(--space-4);
}

.chip:not([aria-pressed="true"]) > [data-icon="check"],
.chip:not([aria-pressed="true"]) > .icon:first-child {
  display: none;
}

.card-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5) var(--space-4);
}

.item-card {
  position: relative;
  display: grid;
  min-width: 0;
  gap: var(--space-2);
  padding: 0;
  border: 0;
  border-radius: var(--radius-lg);
  background: transparent;
  color: var(--color-text);
  text-align: left;
}

.card-thumb-wrap {
  position: relative;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-lg);
  background: var(--color-brand-100);
  box-shadow: var(--shadow-paper);
  isolation: isolate;
  transition: transform var(--motion-standard) var(--ease-out), box-shadow var(--motion-standard) var(--ease-out);
}

.card-thumb-wrap::after {
  position: absolute;
  right: var(--space-3);
  bottom: 0;
  width: var(--space-5);
  height: var(--space-8);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  background: var(--color-brand-500);
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 78%, 0 100%);
  content: "";
  opacity: 0;
  transform: translateY(var(--space-3));
  transition: opacity var(--motion-standard) var(--ease-out), transform var(--motion-standard) var(--ease-out);
}

.item-card[data-checked="true"] .card-thumb-wrap::after {
  opacity: 1;
  transform: translateY(0);
}

.item-card[data-checked="true"] {
  background-image: linear-gradient(var(--state-selected-tint), var(--state-selected-tint));
}

.card-thumb {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 사진을 못 구한 링크는 사이트 아이콘을 작게 가운데 둔다. 늘린 흐린 사진처럼 보이지 않게 한다(#17). */
.card-thumb-wrap[data-thumb-kind="icon"],
.dialog-hero[data-thumb-kind="icon"] {
  background: var(--color-surface-soft);
}

.card-thumb.card-thumb--icon,
.dialog-thumb.dialog-thumb--icon {
  /* 퍼센트 padding은 위아래 값도 컨테이너의 "너비" 기준으로 계산된다(CSS 명세).
     대표 사진 hero는 16:8이라 padding 방식이면 세로 padding 합이 실제 높이를 넘어서서
     아이콘이 아예 안 보였다(#17 리뷰). width/height는 각자 자기 축 기준으로 계산되므로
     비율이 달라도 넘치지 않는다.
     선택자를 base 클래스와 묶은 복합 선택자로 쓴 것도 의도적이다(#17 재리뷰). .card-thumb·
     .dialog-thumb가 각각 object-fit: cover를 갖고 있어서, 클래스 하나짜리 선택자로만 두면 두
     선택자의 명시도가 같아 "파일에 나중에 나오는 규칙이 이긴다"는 우연에 기댄다 — 실제로
     .dialog-thumb가 이 규칙보다 아래에 있어서 cover가 이겨 아이콘이 잘렸었다. 두 클래스를 함께
     요구하면 명시도가 더 높아져 순서가 바뀌어도 항상 이 규칙이 이긴다. */
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 100%;
  height: 100%;
  max-width: 48%;
  max-height: 48%;
  object-fit: contain;
}

.thumb-fallback {
  display: grid;
  width: 100%;
  height: 100%;
  place-items: center;
  background: radial-gradient(circle at 28% 22%, var(--surface-raised), transparent 34%), linear-gradient(145deg, var(--color-brand-100), var(--color-canvas-deep));
  color: var(--color-brand-700);
}

.thumb-fallback[data-platform="youtube"] { background: linear-gradient(145deg, var(--color-error-soft), var(--color-canvas-deep)); color: var(--color-error); }
.thumb-fallback[data-platform="naver"] { background: linear-gradient(145deg, var(--color-success-soft), var(--color-canvas-deep)); color: var(--color-success); }
.thumb-fallback[data-platform="web"] { background: linear-gradient(145deg, var(--color-surface-soft), var(--color-canvas-deep)); color: var(--color-text-secondary); }

.fallback-monogram {
  font-size: var(--text-h1);
  font-weight: 750;
}

.platform-badge,
.reminder-flag {
  display: inline-flex;
  min-height: 1.75rem;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-round);
  font-size: var(--text-caption);
  font-weight: 750;
}

.platform-badge {
  position: absolute;
  top: var(--space-3);
  left: var(--space-3);
  border: 1px solid var(--color-border-strong);
  background: var(--surface-overlay);
  color: var(--color-text);
  box-shadow: var(--shadow-paper);
}

.reminder-flag {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  background: var(--color-text);
  color: var(--color-surface);
}
.item-status-badge {
  position: absolute;
  right: var(--space-3);
  bottom: var(--space-3);
  display: inline-flex;
  min-height: 1.75rem;
  align-items: center;
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-round);
  background: var(--surface-overlay);
  color: var(--color-text);
  font-size: var(--text-caption);
  font-weight: 700;
}

.detail-status-badge {
  position: static;
  margin-right: auto;
  box-shadow: none;
}

.want-badge {
  position: absolute;
  bottom: var(--space-3);
  left: var(--space-3);
  display: inline-flex;
  min-height: 1.75rem;
  align-items: center;
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-round);
  background: var(--surface-overlay);
  color: var(--color-text);
  font-size: var(--text-caption);
  font-weight: 700;
}

.want-badge[data-mutual='true'] {
  border-color: var(--color-text);
  background: var(--color-text);
  color: var(--color-surface);
}

.dialog-want-state {
  margin: 0;
  color: var(--color-text-secondary);
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body);
  line-height: var(--leading-body);
}

/* 카드 스택: 자체 테두리·표면을 가진 카드를 겹치는 표면 없이 세로로 쌓는 컨테이너.
   .row-list와 달리 표면/그림자/overflow가 없고, 열을 minmax(0, 1fr)로 고정해
   긴 라벨이 있어도 카드가 화면 폭을 넘지 않는다. */
.card-stack {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
}

.course-card {
  display: grid;
  /* 한글 본문에 word-break: keep-all을 적용하면서 띄어쓰기 없는 긴 제목이 하나의 토큰이 됐다.
     암시적 auto 트랙은 그 토큰의 min-content 폭을 그대로 따라가므로, 형제 컨테이너
     (.card-stack, .card-grid, .course-stops)와 동일하게 트랙을 화면 폭에 고정한다. */
  grid-template-columns: minmax(0, 1fr);
  min-width: 0;
  gap: var(--space-2);
  padding: var(--space-4);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-lg);
  background: var(--surface-raised);
}

.course-title {
  margin: 0;
  font-size: var(--text-body);
  font-weight: 750;
  letter-spacing: var(--tracking-body);
  line-height: var(--leading-snug);
}

.course-mutual {
  margin: 0;
  color: var(--color-text-secondary);
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body);
  line-height: var(--leading-body);
}

.course-stops {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  min-width: 0;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.course-stop {
  display: flex;
  width: 100%;
  min-width: 0;
  min-height: var(--control-min);
  align-items: center;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border-control);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  color: var(--color-text);
  font: inherit;
  letter-spacing: var(--tracking-control);
  line-height: var(--leading-control);
  text-align: left;
  cursor: pointer;
}

.course-stop-label {
  display: block;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.course-stop:hover {
  border-color: var(--color-border-strong);
  background-image: linear-gradient(var(--state-hover-tint), var(--state-hover-tint));
}

.course-stop:active {
  background-image: linear-gradient(var(--state-pressed-tint), var(--state-pressed-tint));
}

.course-stop:disabled,
.course-stop[aria-disabled="true"] {
  cursor: not-allowed;
  opacity: var(--state-disabled-opacity);
}

.reminder-flag .icon {
  width: var(--space-4);
  height: var(--space-4);
}

.card-body {
  display: grid;
  gap: var(--space-1);
  padding: 0 var(--space-1);
}

.card-title,
.card-place,
.card-meta {
  margin: 0;
}

.card-title {
  display: -webkit-box;
  overflow: hidden;
  font-size: var(--text-body);
  font-weight: 750;
  letter-spacing: var(--tracking-body);
  line-height: var(--leading-snug);
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.card-place,
.card-meta {
  overflow: hidden;
  color: var(--color-text-secondary);
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body);
  line-height: var(--leading-snug);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 장소는 "어디로 가면 되는지"를 답하는 한 줄이라 제목 다음의 두 번째 위계를 갖는다.
   색은 보조색을 유지하되 굵기만 한 단 올려 .card-meta와 구분한다. */
.card-place {
  font-weight: 600;
}

.home-state {
  margin-top: var(--space-6);
}

/* 상태 언어 통일: 첫 사용 · 필터 결과 없음 · 실패 · 섹션별 빈 상태가 같은 표면 단계, 같은 아이콘
   처리, 같은 여백 스케일, 같은 글줄 폭을 쓴다. ID 목록이 아니라 컴포넌트 클래스에 붙여야
   새 화면(알림·통지 등)이 자동으로 같은 가족이 된다. `#homeLoading`은 스켈레톤 그리드라 이
   가족이 아니며, `[data-tone]` 패널은 배경과 글자색까지 바뀐다. */
.status-panel {
  border: 1px solid var(--color-border-subtle);
}

.status-panel .status-panel-copy {
  max-width: 34ch;
}

.status-panel .status-panel-icon {
  color: var(--color-text-secondary);
}

/* 톤이 있는 패널(오류·성공·경고)은 패널이 정한 글자색을 아이콘도 함께 쓴다. 위 규칙이 (0,2,0)이라
   design-system.css의 [data-tone] 색을 눌러, 홈 오류만 빨갛고 알림 오류는 회색인 상태였다. */
.status-panel[data-tone] .status-panel-icon {
  color: currentColor;
}

#homeEmpty .status-panel-icon {
  color: var(--color-brand-700);
}

/* 스켈레톤도 같은 가족이다. 카드 한 장과 동일한 모서리·간격을 써서
   "불러오는 중"이 빈 화면이나 실패로 오해되지 않게 한다. */
.skeleton-card {
  gap: var(--space-2);
}

.skeleton-card .skeleton-media {
  border-radius: var(--radius-lg);
}

.skeleton-card .skeleton-line {
  height: var(--space-3);
  border-radius: var(--radius-sm);
}

.skeleton-card .skeleton-line:not(.skeleton-line-short) {
  width: 88%;
}

.add-header {
  align-items: flex-end;
}

.add-workspace {
  display: grid;
  gap: var(--space-5);
}

.add-capture-panel,
.add-details-panel {
  min-width: 0;
  padding: var(--space-5);
  border-radius: var(--radius-xl);
  background: var(--surface-raised);
  box-shadow: var(--shadow-paper);
}

.paste-row {
  align-items: stretch;
}

.preview-card,
.preview-skeleton {
  display: grid;
  overflow: hidden;
  margin-top: var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--surface-sunken);
}

.preview-thumb-wrap,
.preview-skeleton > .skeleton-media {
  position: relative;
  aspect-ratio: 16 / 9;
}

.preview-thumb-wrap img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.preview-body,
.preview-skeleton-copy {
  position: relative;
  display: grid;
  gap: var(--space-2);
  padding: var(--space-5);
}

.preview-body .platform-badge {
  position: static;
  width: fit-content;
  box-shadow: none;
}

.preview-title-input {
  min-height: var(--control-min);
  padding: var(--space-1) 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  font-size: var(--text-h3);
  font-weight: 750;
  letter-spacing: var(--tracking-heading);
}

.preview-summary,
.preview-domain {
  margin: 0;
  color: var(--color-text-secondary);
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body);
  line-height: var(--leading-body);
}

.preview-summary {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
}

.preview-domain {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
}

.preview-skeleton .button-quiet {
  margin: 0 var(--space-5) var(--space-5);
  justify-self: start;
}

.add-details-heading {
  display: grid;
  gap: var(--space-1);
  padding-bottom: var(--space-2);
}

.add-details-heading h2,
.content-section h2,
.settings-group h2 {
  font-size: var(--text-h2);
  letter-spacing: var(--tracking-heading);
  line-height: var(--leading-heading);
}

.schedule-fieldset {
  display: grid;
  gap: var(--space-2);
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.save-item-button {
  width: 100%;
  min-height: var(--control-lg);
  margin-top: var(--space-2);
}

.content-section {
  display: grid;
  gap: var(--space-4);
  padding: var(--space-6) 0;
  border-top: 1px solid var(--color-border-subtle);
}

.section-heading-row {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: var(--space-3);
}

.row-list {
  display: grid;
  gap: 0;
  overflow: hidden;
  border-radius: var(--radius-xl);
  background: var(--surface-raised);
  box-shadow: var(--shadow-paper);
}

.row-list:empty {
  display: none;
}

/* 행 컴포넌트(.row-item/.row-icon/.row-main/.row-title/.row-sub)는 design-system.css가 소유한다.
   여기에는 앱 레이아웃 차원의 조합만 둔다. */

/* #resurfaceList의 행은 아이콘도 보조 액션도 없이 제목/부제만 쌓는 버튼이라 한 열로 접는다. */
.resurface-row {
  grid-template-columns: minmax(0, 1fr);
  width: 100%;
  border-top: 0;
  border-right: 0;
  border-left: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.row-actions {
  display: flex;
  flex: 0 0 auto;
  gap: var(--space-2);
}

/* 컴팩트 상태 패널(#resurfaceEmpty, #alarmsEmpty, #notificationsEmpty)은 이미 섹션 안에 들어가 있으므로
   여백을 한 단 줄인다. 표면·모서리·아이콘 처리는 큰 상태 패널과 같은 가족을 유지한다. */
.compact-status {
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  padding: var(--space-5);
}

.compact-status > :not(.status-panel-icon) {
  grid-column: 2;
}

.row-skeleton-icon {
  width: var(--control-min);
  height: var(--control-min);
}

.settings-layout {
  display: grid;
  gap: var(--space-4);
}

.settings-group {
  display: grid;
  align-content: start;
  gap: var(--space-4);
  min-width: 0;
  padding: var(--space-5);
  border-radius: var(--radius-xl);
  background: var(--surface-raised);
  box-shadow: var(--shadow-paper);
}

.settings-group-heading {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.settings-icon {
  display: grid;
  width: var(--control-min);
  height: var(--control-min);
  flex: 0 0 auto;
  place-items: center;
  border-radius: var(--radius-md);
  background: var(--color-brand-50);
  color: var(--color-brand-700);
}

.settings-value,
.settings-copy {
  margin: 0;
  color: var(--color-text-secondary);
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body);
  line-height: var(--leading-body);
}

.account-email {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--surface-sunken);
  box-shadow: var(--shadow-sunken);
  font-family: var(--font-mono);
  overflow-wrap: anywhere;
}

.settings-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) 0;
  border-top: 1px solid var(--color-border-subtle);
  font-size: var(--text-body-sm);
}

.settings-row > span:first-child {
  display: grid;
  gap: var(--space-1);
}

.settings-row small {
  color: var(--color-text-secondary);
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-caption);
  line-height: var(--leading-caption);
}

.settings-row .settings-value {
  grid-column: 1;
}

.settings-row .button-small {
  grid-row: 1 / span 2;
  grid-column: 2;
}

.toggle-row {
  grid-template-columns: minmax(0, 1fr) auto;
}

/* 스위치: 보이는 트랙은 작게(1.875rem) 유지하되 실제 조작 영역은 --control-min을 채운다.
   트랙과 손잡이는 모두 pseudo-element로 그리고, 이동 거리는 선언한 지오메트리에서 계산한다. */
.switch-input {
  --switch-track-height: 1.875rem;
  --switch-thumb-size: 1.25rem;
  --switch-thumb-inset: var(--space-1);
  --switch-thumb-travel: calc(
    var(--control-lg) - (var(--switch-thumb-inset) * 2) - var(--switch-thumb-size)
  );

  position: relative;
  width: var(--control-lg);
  min-width: var(--control-lg);
  height: var(--control-min);
  min-height: var(--control-min);
  padding: 0;
  border: 0;
  background: transparent;
  appearance: none;
  cursor: pointer;
}

.switch-input::before {
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: var(--switch-track-height);
  border: 1px solid var(--color-border-control);
  border-radius: var(--radius-round);
  background: var(--surface-sunken);
  box-shadow: var(--shadow-sunken);
  content: "";
  transform: translateY(-50%);
  transition:
    background-color var(--motion-micro) var(--ease-out),
    border-color var(--motion-micro) var(--ease-out);
}

.switch-input::after {
  position: absolute;
  top: 50%;
  left: var(--switch-thumb-inset);
  width: var(--switch-thumb-size);
  height: var(--switch-thumb-size);
  border-radius: 50%;
  background: var(--surface-raised);
  box-shadow: var(--shadow-paper);
  content: "";
  transform: translateY(-50%);
  transition: transform var(--motion-micro) var(--ease-out);
}

.switch-input:checked::before {
  border-color: var(--color-success);
  background: var(--color-success);
}

.switch-input:checked::after {
  transform: translate(var(--switch-thumb-travel), -50%);
}

.switch-input:disabled {
  cursor: not-allowed;
  opacity: var(--state-disabled-opacity);
}

.shared-form {
  align-items: stretch;
}

.invite-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--color-brand-50);
}

.invite-row > div {
  display: grid;
  min-width: 0;
  gap: var(--space-1);
}

.invite-label {
  color: var(--color-brand-700);
  font-size: var(--text-caption);
  font-weight: 750;
  letter-spacing: var(--tracking-caption);
  line-height: var(--leading-caption);
}

.invite-row code {
  overflow-wrap: anywhere;
  font-family: var(--font-mono);
  font-size: var(--text-caption);
}

.install-card {
  background: linear-gradient(145deg, var(--color-brand-50), var(--surface-raised));
}

.settings-footer {
  display: grid;
  gap: var(--space-2);
  width: min(100%, var(--content-reading));
  margin-top: var(--space-8);
}

.item-dialog {
  position: relative;
}

.dialog-hero {
  position: relative;
  overflow: hidden;
  aspect-ratio: 16 / 8;
  background: var(--color-brand-100);
}

.dialog-thumb {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.dialog-close {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  z-index: 1;
  background: var(--color-text);
  color: var(--color-surface);
}

.dialog-body {
  display: grid;
  gap: var(--space-4);
  padding: var(--space-6) var(--space-5) calc(var(--space-8) + env(safe-area-inset-bottom, 0px));
}

.dialog-header-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}

.dialog-title-input {
  min-height: var(--control-min);
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  font-size: var(--text-h2);
  font-weight: 750;
  letter-spacing: var(--tracking-heading);
  line-height: var(--leading-heading);
}

.dialog-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
}

.dialog-actions .wide {
  grid-column: 1 / -1;
}

.dialog-inline-status {
  margin: 0;
  color: var(--color-text-secondary);
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body);
  line-height: var(--leading-body);
}

/* 콘텐츠 신고와 숨김 해제 (상세 시트 하단).
   신고한 항목은 서버가 숨기고, 숨긴 항목은 카드에서 한눈에 구분돼야 한다. 색은 전부
   design-system.css 토큰이라 라이트/다크 팔레트를 모두 따라간다. */
.report-section {
  display: grid;
  gap: var(--space-3);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border-subtle);
}

.report-toggle {
  justify-self: start;
  color: var(--color-text-secondary);
}

.report-note {
  margin: 0;
  color: var(--color-text-secondary);
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body);
  line-height: var(--leading-body);
}

.report-panel {
  display: grid;
  gap: var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-md);
  background: var(--color-surface-soft);
}

.report-reasons {
  display: grid;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  border: 0;
}

.report-reasons legend {
  padding: 0 0 var(--space-2);
}

.report-reason {
  display: flex;
  min-height: var(--control-min);
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-2);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  cursor: pointer;
  font-size: var(--text-body);
  line-height: var(--leading-body);
}

.report-reason input {
  width: var(--space-5);
  height: var(--space-5);
  flex: 0 0 auto;
  accent-color: var(--color-brand-500);
}

.report-detail textarea {
  min-height: calc(var(--control-min) * 2);
  resize: vertical;
}

.item-hidden-badge {
  border-color: var(--color-text);
  background: var(--color-text);
  color: var(--color-surface);
}

/* 준비 상태 배지와 숨김 배지가 같은 자리를 다투지 않도록 한 칸 위로 쌓는다. */
.item-card[data-hidden="true"] .item-status-badge:not(.item-hidden-badge) {
  bottom: calc(var(--space-3) + 2.25rem);
}

/* 신고해서 숨긴 항목의 사진은 강조하지 않는다. 배지와 제목은 그대로 읽혀야 한다. */
.item-card[data-hidden="true"] .card-thumb,
.item-card[data-hidden="true"] .thumb-fallback {
  filter: grayscale(1);
  opacity: 0.55;
}

.clipboard-banner,
.global-toast {
  position: fixed;
  right: var(--space-3);
  left: var(--space-3);
  z-index: var(--z-toast);
  width: min(calc(100% - (var(--space-6))), 38rem);
  margin: 0 auto;
}

.clipboard-banner {
  bottom: calc(var(--nav-mobile) + var(--space-4) + env(safe-area-inset-bottom, 0px));
}

.global-toast {
  bottom: calc(var(--nav-mobile) + var(--space-4) + env(safe-area-inset-bottom, 0px));
}

.global-toast[data-tone="error"] {
  background: var(--color-error);
}

.inverse-icon {
  border-color: transparent;
  background: transparent;
  color: var(--color-surface);
}

/* 반전 표면(--color-text 배경) 위의 focus ring.
   --focus-ring-color 기본값이 --color-text이라 토스트·클립보드 배너·다이얼로그 닫기 버튼에서는
   링과 배경이 같은 색이 된다. 표면색으로 뒤집어 두 팔레트 모두에서 대비를 확보한다. */
.toast,
.clipboard-banner,
.dialog-close {
  --focus-ring-color: var(--color-surface);
}

/* .dialog-close는 썸네일 이미지 위에 떠 있어 배경을 예측할 수 없다.
   바깥쪽에 --color-text 헤일로를 덧대 링의 안팎 경계를 어떤 이미지에서도 유지한다. */
.dialog-close:focus-visible {
  box-shadow: 0 0 0 calc(var(--focus-ring-offset) + (var(--focus-ring-width) * 2)) var(--color-text);
}

.tab-bar {
  position: fixed;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: var(--z-sticky);
}

.nav-brand {
  display: none;
}

.nav-add-icon {
  display: grid;
  width: 2.25rem;
  height: 2.25rem;
  place-items: center;
  border-radius: var(--radius-md);
  background: var(--color-brand-500);
  color: var(--color-surface);
  transition: transform var(--motion-micro) var(--ease-out), background-color var(--motion-micro) var(--ease-out);
}

.nav-add[aria-current="page"] .nav-add-icon {
  background: var(--color-brand-700);
}

.tab-badge {
  position: absolute;
  top: var(--space-1);
  left: calc(50% + var(--space-2));
  display: grid;
  min-width: 1.125rem;
  height: 1.125rem;
  place-items: center;
  padding: 0 var(--space-1);
  border: 0.125rem solid var(--color-surface);
  border-radius: var(--radius-round);
  background: var(--color-error);
  color: var(--color-surface);
  font-size: var(--text-caption);
  font-weight: 750;
}

@media (hover: hover) and (pointer: fine) {
  .item-card:hover .card-thumb-wrap {
    box-shadow: var(--shadow-hover);
    transform: translateY(calc(var(--space-1) * -1));
  }

  .link-button:hover {
    background-image: linear-gradient(var(--state-hover-tint), var(--state-hover-tint));
  }

  .summary-tile-button:hover {
    border-color: var(--color-border-strong);
    background-image: linear-gradient(var(--state-hover-tint), var(--state-hover-tint));
  }
}

@media (max-width: 29rem) {
  .paste-row,
  .shared-form {
    align-items: stretch;
    flex-direction: column;
  }

  .paste-row .button-secondary,
  .shared-form .button-secondary {
    width: 100%;
  }

  .route-header {
    flex-direction: column;
  }

  .home-header {
    flex-direction: row;
  }

  .field-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .settings-row:not(.toggle-row) {
    grid-template-columns: minmax(0, 1fr);
  }

  .settings-row:not(.toggle-row) .button-small {
    grid-row: auto;
    grid-column: 1;
    justify-self: start;
  }
}

@media (min-width: 40rem) {
  .screen {
    padding-right: var(--space-6);
    padding-left: var(--space-6);
  }

  .route-header {
    padding-top: var(--space-5);
    padding-bottom: var(--space-10);
  }

  /* 넓은 화면에서는 타일 사이 간격만 한 단 벌린다. 열 구성은 항목 수를 그대로 따른다. */
  .summary-tiles {
    gap: var(--space-3);
  }

  .card-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-6) var(--space-5);
  }

  .add-capture-panel,
  .add-details-panel,
  .settings-group {
    padding: var(--space-6);
  }

  .settings-layout {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .install-card {
    grid-column: 1 / -1;
  }

  .sheet {
    margin: auto;
    border-radius: var(--radius-xl);
  }
}

@media (min-width: 64rem) {
  .app-layout {
    display: grid;
    grid-template-columns: 6.5rem minmax(0, 1fr);
  }

  #appMain {
    grid-column: 2;
    padding-bottom: 0;
  }

  .screen {
    padding: var(--space-10) var(--space-8) var(--space-16);
  }

  .screen[data-route-section='alarms'] {
    max-width: var(--content-reading);
  }

  .login-screen {
    grid-column: 1 / -1;
    grid-template-columns: minmax(0, 1fr) minmax(25rem, 0.72fr);
    align-items: stretch;
    gap: var(--space-10);
    min-height: 100dvh;
    padding: var(--space-8);
  }

  .login-story {
    position: relative;
    display: grid;
    align-content: center;
    gap: var(--space-5);
    overflow: hidden;
    padding: var(--space-12);
    border-radius: var(--radius-xl);
    background: linear-gradient(145deg, var(--color-brand-100), var(--color-canvas-deep));
  }

  .story-ribbon {
    display: grid;
    width: 4.5rem;
    height: 6rem;
    place-items: start center;
    padding-top: var(--space-5);
    background: var(--color-brand-500);
    color: var(--color-surface);
    clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 82%, 0 100%);
  }

  .story-eyebrow,
  .story-title {
    margin: 0;
  }

  .story-eyebrow {
    color: var(--color-brand-700);
    font-size: var(--text-body-sm);
    font-weight: 750;
  }

  .story-title {
    max-width: 12ch;
    font-size: var(--text-display);
    font-weight: 750;
    letter-spacing: var(--tracking-display);
    line-height: var(--leading-display);
  }

  .story-stack {
    display: flex;
    gap: var(--space-2);
  }

  .story-stack span {
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-round);
    background: var(--surface-raised);
    color: var(--color-text-secondary);
    font-size: var(--text-caption);
    font-weight: 750;
  }

  .login-panel {
    align-content: center;
    width: 100%;
    max-width: 34rem;
    padding: var(--space-10);
  }

  .tab-bar {
    top: var(--space-5);
    right: auto;
    bottom: var(--space-5);
    left: var(--space-4);
    display: flex;
    width: 5.5rem;
    flex-direction: column;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3);
    border: 0;
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-floating);
  }

  .nav-brand {
    display: grid;
    justify-items: center;
    gap: var(--space-2);
    margin-bottom: auto;
    color: var(--color-text);
    font-size: var(--text-caption);
    font-weight: 750;
    line-height: var(--leading-tight);
    text-align: center;
  }

  .nav-brand .brand-mark {
    width: var(--control-min);
    height: var(--control-min);
  }

  .app-nav-link {
    min-height: 4rem;
  }

  .tab-badge {
    top: var(--space-2);
    left: calc(50% + var(--space-2));
  }

  .card-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-8) var(--space-6);
  }

  .add-workspace {
    grid-template-columns: minmax(0, 1.08fr) minmax(20rem, 0.92fr);
    align-items: start;
    gap: var(--space-6);
  }

  .add-details-panel {
    position: sticky;
    top: var(--space-8);
  }

  .settings-layout {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .install-card {
    grid-column: auto;
  }

  .clipboard-banner,
  .global-toast {
    right: var(--space-8);
    bottom: var(--space-8);
    left: auto;
    margin: 0;
  }
}

@media (forced-colors: active) {
  .story-ribbon,
  .nav-add-icon,
  .switch-input::before,
  .card-thumb-wrap::after {
    border: 1px solid CanvasText;
  }
}

.bulk-import-open {
  min-height: var(--control-min);
  margin-top: var(--space-2);
  justify-self: start;
}

#bulkImportInput {
  width: 100%;
  min-height: 8rem;
  padding: var(--space-3);
  border: 1px solid var(--color-border-control);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  color: var(--color-text);
  font: inherit;
  letter-spacing: var(--tracking-body);
  line-height: var(--leading-body);
  resize: vertical;
}

#bulkImportDialog .dialog-actions {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-2);
}

#bulkImportDialog .dialog-actions button {
  width: 100%;
}

/* focus ring은 design-system.css의 :where(a, button, input, select, textarea, [tabindex])
   기본 규칙 하나가 전부 담당한다. 여기에 있던 열 개짜리 목록은 같은 선언을 그대로 반복해
   토큰이 갈라지는 순간 어긋나므로 삭제했다. 예외는 .dialog-close 하나뿐이며 위에 따로 있다. */
