/*
 * 기존에는 스타일이 네 군데(body 인라인 style, <body> 안의 <style>, span의
 * 인라인 style, SVG 속성)에 흩어져 있었고 .air 셀렉터가 두 번 정의돼 있었다.
 * 여기 한 파일로 모았다.
 *
 * 색은 전부 커스텀 프로퍼티로 뺐다. 라이트 값을 :root에 두고, 다크 값은
 *   1) OS가 다크이고 사용자가 라이트로 고정하지 않은 경우
 *   2) 사용자가 다크로 고정한 경우
 * 두 곳에서 덮어쓴다. 두 블록의 내용은 같지만, 미디어 쿼리 안과 밖을 하나의
 * 셀렉터 목록으로 합칠 수 없어 불가피하게 중복된다.
 */

:root {
  color-scheme: light;

  --surface: #ffffff;
  --surface-raised: #ffffff;
  --ink: #272727;
  --ink-soft: #6b6b6b;
  --border: #dddddd;

  --control-bg: #272727;
  --control-fg: #ffffff;
  --control-active: #6b6b6b;

  --focus: #2f6fed;
  --backdrop: rgb(0 0 0 / 35%);
  --danger: #c0392b;

  /* 차트 색. 계열이 하나뿐이라 한 색만 쓴다.
     대비 실측: #2a78d6 on #ffffff = 4.42:1 (마크 기준 3:1 통과).
     0인 시간대는 데이터가 아니라 바닥선이므로 흐린 회색을 쓴다. */
  --series-1: #2a78d6;
  --series-empty: #e4e6ea;

  /* 에어컨 본체 그림은 테마와 무관하게 항상 흰색이다. 그 위에 얹히는 온도
     텍스트까지 --ink로 칠하면 다크 모드에서 흰 글자가 흰 본체 위에 놓여
     사라진다. 기기 위에 올라가는 글자는 테마와 무관하게 어두운 색으로 고정한다.
     (나중에 어두운 색 기기 에셋을 넣는다면 이 값도 기기별로 바꿔야 한다) */
  --on-device-ink: #272727;

  /* 바람 그래픽은 흰 배경 위에 얹히도록 그려진 반투명 이미지다. 어두운
     배경에서는 그대로 두면 밝은 회색 판때기처럼 보인다. */
  --air-blend: normal;

  /* 에어컨 그림의 크기. 아래 오프셋이 전부 이 값에 비례하므로 이 한 줄만
     바꾸면 전체가 함께 늘어나고 줄어든다. 화면 폭과 높이 양쪽으로 제한해
     가로 모드의 낮은 화면에서도 잘리지 않게 한다. */
  --aircon-width: clamp(200px, min(92vw, 66vh), 460px);

  /* aircon0.png(2067x1181) 안에서 기기 본체가 실제로 차지하는 세로 구간.
     이미지 위아래에 투명 여백이 있어서, 텍스트를 이미지 기준으로 놓으면
     허공에 뜬다. 알파 채널을 측정해 얻은 값이다.
       불투명 영역 y 323~761  ->  323/2067 = 0.1563, 761/2067 = 0.3682
     폭에 대한 비율로 두었으므로 크기가 달라져도 그대로 맞는다. */
  --device-top: calc(var(--aircon-width) * 0.1563);
  --device-height: calc(var(--aircon-width) * 0.2119);

  /* 팬 위치. 원래는 350px 기준으로 손으로 맞춘 픽셀값(102px / 114px)이었다. */
  --fan-offset: calc(var(--aircon-width) * 0.2914);
  --fan-flip-offset: calc(var(--aircon-width) * 0.3257);

  /* 안내 문구는 기기 위쪽 여백에 놓는다(본체 바깥). */
  --who-top: calc(var(--aircon-width) * 0.0686);
  --notice-top: calc(var(--aircon-width) * 0.0114);

  --radius: 6px;
  --footer-height: 44px;
}

/* 1) OS가 다크. 단, 사용자가 라이트로 고정했다면 적용하지 않는다. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --surface: #14161a;
    --surface-raised: #1d2026;
    --ink: #e8eaed;
    --ink-soft: #a0a6b0;
    --border: #333842;

    /* 어두운 배경에서는 버튼을 밝게 뒤집어야 대비가 확보된다. */
    --control-bg: #e8eaed;
    --control-fg: #14161a;
    --control-active: #b8bec8;

    --focus: #79a6ff;
    --backdrop: rgb(0 0 0 / 60%);
    --danger: #ff8a80;

    /* 어두운 배경용 같은 계열 단계. #3987e5 on #1d2026 = 4.48:1 */
    --series-1: #3987e5;
    --series-empty: #2b3038;

    /* screen 합성으로 바람이 배경을 덮는 대신 빛을 더하게 만든다. */
    --air-blend: screen;
  }
}

/* 2) 사용자가 다크로 고정. OS 설정과 무관하게 이긴다. */
:root[data-theme="dark"] {
  color-scheme: dark;

  --surface: #14161a;
  --surface-raised: #1d2026;
  --ink: #e8eaed;
  --ink-soft: #a0a6b0;
  --border: #333842;

  --control-bg: #e8eaed;
  --control-fg: #14161a;
  --control-active: #b8bec8;

  --focus: #79a6ff;
  --backdrop: rgb(0 0 0 / 60%);
  --danger: #ff8a80;

  --series-1: #3987e5;
  --series-empty: #2b3038;

  --air-blend: screen;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  /* 하단 고정 푸터에 내용이 가리지 않도록 여유를 두고, 노치가 있는 기기에서는
     안전 영역만큼 더 확보한다. */
  padding: 12px 12px calc(var(--footer-height) + 16px + env(safe-area-inset-bottom, 0px));
  background: var(--surface);
  color: var(--ink);
  font-family:
    system-ui, -apple-system, "Segoe UI", "Noto Sans KR", "Noto Sans JP", "Noto Sans SC",
    "Noto Sans TC", sans-serif;
  transition:
    background-color 0.2s,
    color 0.2s;
}

/* 화면에서는 숨기지만 스크린 리더에는 읽히는 텍스트.
   문서에 h1이 없어 아웃라인이 <h4>부터 시작하던 문제를 해결한다. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

main {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(8px, 2.5vh, 20px);
}

/* ------------------------------------------------------------ 에어컨 */

.aircon-box {
  position: relative;
  display: flex;
  justify-content: center;
  width: var(--aircon-width);
}

.aircon {
  width: var(--aircon-width);
  max-width: 100%;
  height: auto;
}

.aircon-fan,
.air {
  position: absolute;
  top: 0;
}

.aircon-fan {
  transform: translateY(var(--fan-offset)) scaleY(1);
  transition: transform 1s;
}

.aircon-fan.is-spinning {
  transform: translateY(var(--fan-flip-offset)) scaleY(-1);
}

.air {
  visibility: hidden;
  /* .air.is-blowing의 reveal 애니메이션이 opacity를 직접 제어하므로
     밝기 조절은 opacity가 아니라 합성 모드로 한다. */
  mix-blend-mode: var(--air-blend);
  /* 바람 이미지는 흰 배경으로 스며들도록 그려져 있어서, 어두운 배경에서는
     아래쪽 경계가 각진 판때기처럼 드러난다. 알파를 직접 떨어뜨려 어느
     배경에서든 자연스럽게 사라지게 한다. */
  -webkit-mask-image: linear-gradient(to bottom, #000 45%, transparent 92%);
  mask-image: linear-gradient(to bottom, #000 45%, transparent 92%);
}

.air.is-blowing {
  visibility: visible;
  animation: reveal 2s infinite forwards;
}

/* 온풍기 전용 본체와 함께 쓸 때는 공통 바람 그래픽에 따뜻한 색을 입힌다. */
:root.has-heater-body .air {
  filter: sepia(1) saturate(1.6);
}

@keyframes reveal {
  0% {
    clip-path: inset(0 0 100% 0);
    opacity: 0.9;
  }
  50% {
    opacity: 0.7;
  }
  100% {
    clip-path: inset(0 0 0 0);
    opacity: 0;
  }
}

/* 어지러움이나 전정기관 문제가 있는 사용자를 위해 움직임을 줄인다. */
@media (prefers-reduced-motion: reduce) {
  body,
  .aircon-fan,
  .air.is-blowing,
  .notice,
  .who,
  .icon-button,
  .pill,
  .link {
    transition: none;
    animation: none;
  }
}

/* ------------------------------------------------------------ 텍스트 */

.temp,
.who,
.notice {
  position: absolute;
  left: 0;
  right: 0;
  margin: 0;
  text-align: center;
  pointer-events: none;
}

.temp {
  /* 기기 본체 구간을 그대로 차지하고 그 안에서 가운데 정렬한다.
     top 한 값으로 맞추면 글자 크기가 바뀔 때마다 어긋나지만, 이렇게 하면
     폰트가 커지든 작아지든 언제나 본체 세로 정중앙에 온다. */
  top: var(--device-top);
  height: var(--device-height);
  display: flex;
  align-items: center;
  justify-content: center;
  /* 정중앙보다 살짝 위로. box-sizing: border-box라 이 패딩만큼 콘텐츠 상자가
     아래에서 줄고, 그 안에서 가운데 정렬되므로 글자는 절반인 10px 올라간다.
     비율이 아니라 고정값이라 기기가 작아질수록 상대적으로 더 많이 올라간다
     (아래 실측 참고). 의도한 것이다. */
  padding-bottom: 20px;
  /* 이 글자만 에어컨 본체(항상 흰색) 위에 얹힌다. */
  color: var(--on-device-ink);
  font-size: clamp(16px, calc(var(--aircon-width) * 0.058), 28px);
  font-weight: 700;
}

.who {
  top: var(--who-top);
  font-size: clamp(10px, calc(var(--aircon-width) * 0.032), 12px);
}

.notice {
  top: var(--notice-top);
  font-size: clamp(10px, calc(var(--aircon-width) * 0.032), 12px);
  color: var(--ink-soft);
}

.who,
.notice {
  opacity: 1;
  transition: opacity 0.6s;
}

.who.is-faded,
.notice.is-faded {
  opacity: 0;
}

/* ------------------------------------------------------------ 컨트롤 */

.controls {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px;
}

.icon-button,
.pill,
.link,
.select,
.tab {
  font: inherit;
  cursor: pointer;
  border-radius: var(--radius);
  /* 모바일에서 +/- 를 연타하면 브라우저가 그걸 더블탭으로 읽고 화면을
     확대해 버린다. 온도를 두 칸 올리려는 사람에게는 확대가 재앙이다.
     manipulation은 더블탭 확대와 그에 딸린 300ms 지연만 끄고, 손가락 두
     개로 하는 핀치 확대는 그대로 남긴다 -- user-scalable=no 로 확대를
     통째로 막는 것과는 다르다. 그건 접근성을 해친다. */
  touch-action: manipulation;
  transition:
    background-color 0.2s,
    color 0.2s,
    border-color 0.2s;
}

.icon-button,
.pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  /* 최소 터치 타깃 크기. 기존 버튼은 padding 5px짜리라 모바일에서 누르기 어려웠다. */
  min-width: 44px;
  min-height: 44px;
  padding: 8px 14px;
  border: 0;
  background: var(--control-bg);
  color: var(--control-fg);
}

.icon-button:active,
.pill:active {
  background: var(--control-active);
}

.icon-button:disabled,
.pill:disabled {
  /* 닉네임을 정하기 전에는 버튼이 살아 있는 것처럼 보이지만 실제로는 아무
     동작도 하지 않았다. 이제 disabled로 그 사실이 눈에 보이고 키보드
     탐색에서도 건너뛰어진다. */
  opacity: 0.35;
  cursor: not-allowed;
}

.icon-button .icon-sound-off {
  display: none;
}

.icon-button.is-muted .icon-sound-on {
  display: none;
}

.icon-button.is-muted .icon-sound-off {
  display: inline;
}

.pill.is-active {
  background: linear-gradient(45deg, #ffc1c1, #fbdbab, #ffffcc, #bafbba, #bbe8ff, #dcbefd, #ffb7ff);
  /* 파스텔 그라디언트라 라이트/다크 어느 쪽에서도 검은 글자가 잘 읽힌다. */
  color: #101010;
}

/* 키보드 사용자를 위한 포커스 표시. 기존 마크업에는 전혀 없었다. */
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* ------------------------------------------------------------ 푸터 */

.footer {
  position: fixed;
  inset: auto 0 0 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px;
  min-height: var(--footer-height);
  padding: 6px 10px calc(6px + env(safe-area-inset-bottom, 0px));
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: blur(6px);
  border-top: 1px solid var(--border);
}

.link {
  padding: 6px;
  border: 0;
  background: none;
  color: var(--ink-soft);
  font-size: 0.75rem;
  text-decoration: underline;
}

.select {
  padding: 5px 6px;
  border: 1px solid var(--border);
  background: var(--surface-raised);
  color: var(--ink);
  font-size: 0.75rem;
}

/* ------------------------------------------------------------ 다이얼로그 */

.dialog {
  width: min(320px, calc(100vw - 32px));
  padding: 20px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-raised);
  color: var(--ink);
  font-size: 0.85rem;
}

.dialog::backdrop {
  background: var(--backdrop);
}

.dialog form {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.dialog p {
  margin: 0 0 8px;
  line-height: 1.5;
}

.field-label {
  font-weight: 600;
}

/* 쓸 수 없는 문자만 넣어서 이름이 통째로 비었을 때. role="alert"라 화면
   낭독기도 읽는다. */
.field-error {
  margin: 0;
  color: var(--danger);
  font-size: 0.8rem;
}

/* 닫기 버튼이 왼쪽에 쪼그려 붙어 있었다. dialog 안에서 button은 inline이라
   글자 폭만큼만 차지한다. 닉네임 모달의 "시작"은 form이 flex column이라
   저절로 꽉 찼는데, 통계·정보 모달의 닫기는 dialog 직계 자식이라 그 규칙을
   못 받았다. 같은 모양이 되도록 폭을 맞춘다. */
.dialog > [data-close-dialog] {
  display: block;
  width: 100%;
  margin-top: 14px;
}

.dialog input {
  min-height: 44px;
  padding: 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  /* iOS Safari는 16px 미만 입력란에 포커스하면 화면을 확대한다. */
  font-size: 16px;
}

/* ------------------------------------------------------------ 좁은 화면 */

@media (max-width: 380px) {
  .footer {
    gap: 6px;
  }

  .link,
  .select {
    font-size: 0.7rem;
  }
}

/* ------------------------------------------------------------ 통계 */

.dialog-stats {
  width: min(420px, calc(100vw - 32px));
  max-height: min(78vh, 680px);
  overflow-y: auto;
}

.footer-online {
  color: var(--ink-soft);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
}

.stat-online {
  margin: 0 0 4px;
  font-size: 1.1rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.stat-block {
  margin-top: 18px;
}

.stat-heading {
  margin: 0 0 8px;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--ink-soft);
}

.stat-note {
  margin: 6px 0 0;
  color: var(--ink-soft);
  font-size: 0.7rem;
}

.stat-mine {
  display: flex;
  justify-content: space-between;
  margin: 0 0 4px;
  font-variant-numeric: tabular-nums;
}

/* 탭 */

.tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 8px;
}

.tab {
  flex: 1;
  min-height: 34px;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: none;
  color: var(--ink-soft);
  font: inherit;
  font-size: 0.75rem;
  cursor: pointer;
}

.tab.is-selected {
  border-color: transparent;
  background: var(--control-bg);
  color: var(--control-fg);
}

/* 순위 / 최근 기록 */

.rank-list,
.recent-list {
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.8rem;
}

.rank-row,
.recent-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 5px 0;
  border-bottom: 1px solid var(--border);
}

.rank-row:last-child,
.recent-row:last-child {
  border-bottom: 0;
}

.rank-place {
  width: 1.4em;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}

.rank-name,
.recent-name {
  flex: 1;
  overflow-wrap: anywhere;
}

.rank-count,
.recent-temp {
  font-variant-numeric: tabular-nums;
}

.rank-empty {
  padding: 10px 0;
  color: var(--ink-soft);
  font-size: 0.75rem;
}

/* 방향은 화살표 모양과 위치로 읽힌다. 색은 보조일 뿐이고,
   의미는 요소의 aria-label이 따로 전달한다. */
.recent-arrow {
  font-size: 0.65rem;
  color: var(--ink-soft);
}

.recent-time {
  color: var(--ink-soft);
  font-size: 0.7rem;
  white-space: nowrap;
}

.recent-list {
  max-height: 240px;
  overflow-y: auto;
}

/* 시간대별 활동 차트 */

.chart {
  display: block;
  width: 100%;
  height: 72px;
}

/* 막대 사이는 테두리가 아니라 배경색 여백으로 구분한다(렌더러가 폭에서 2px를 뺀다). */
.chart .bar {
  fill: var(--series-1);
}

/* 축은 눈에 띄면 안 된다. 실선 hairline 하나로 0의 위치만 알려준다. */
.chart .chart-baseline {
  stroke: var(--series-empty);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

.chart .bar:hover,
.chart .bar:focus-visible {
  /* 값을 가리지 않도록 색은 그대로 두고 테두리만 준다. */
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* ------------------------------------------------------------ 관리 화면 */

.admin {
  max-width: 900px;
  margin: 0 auto;
  padding-bottom: 40px;
}

.admin-title {
  margin: 16px 0;
  font-size: 1.1rem;
}

.admin-auth {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: 8px;
  margin-bottom: 12px;
}

.admin-auth input {
  flex: 1;
  min-width: 220px;
  min-height: 44px;
  padding: 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 16px;
}

.admin-status {
  margin: 0 0 12px;
  color: var(--ink-soft);
  font-size: 0.8rem;
}

.admin-status.is-error {
  color: #c0392b;
}

:root[data-theme="dark"] .admin-status.is-error {
  color: #ff8a80;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .admin-status.is-error {
    color: #ff8a80;
  }
}

.admin-table {
  width: 100%;
  margin-bottom: 20px;
  border-collapse: collapse;
  font-size: 0.8rem;
}

.admin-table th,
.admin-table td {
  padding: 7px 8px;
  border-bottom: 1px solid var(--border);
  text-align: left;
  vertical-align: middle;
}

.admin-table th {
  color: var(--ink-soft);
  font-size: 0.7rem;
  font-weight: 600;
}

.admin-table .mono {
  font-family: ui-monospace, "SFMono-Regular", "Consolas", monospace;
  font-size: 0.75rem;
}

.admin-empty {
  color: var(--ink-soft);
}

/* 색은 :root의 --danger 하나로 모았다. 예전에는 라이트/다크 값을 여기서
   세 블록에 나눠 적고 있었는데, 오류 문구가 같은 색을 쓰게 되면서 같은
   리터럴이 여섯 번 나올 판이었다. */
.link.is-danger {
  color: var(--danger);
}

/* ------------------------------------------------------------ 확인 화면 */

.dialog-verify {
  width: min(340px, calc(100vw - 32px));
  text-align: center;
}

/* 캐릭터는 장식이다. 문구가 정보를 전달하고 이미지는 분위기만 맡는다.
   그래서 alt는 비워 두고(마크업 참고) 스크린 리더가 건너뛰게 한다. */
.verify-character {
  display: block;
  width: 180px;
  height: auto;
  margin: 0 auto 8px;
}

.verify-title {
  margin: 0 0 8px;
  font-size: 0.95rem;
  font-weight: 700;
}

.dialog-verify p {
  margin: 0 0 6px;
  line-height: 1.5;
}

.dialog-verify .pill {
  margin-top: 12px;
}

/* ------------------------------------------------------------ 구형 브라우저 */

/* 평소에는 숨어 있다가, compat 검사나 nomodule 스크립트가 클래스를 달면 나온다.
   <noscript> 안에서는 스크립트가 아예 돌지 않으므로 직접 보이게 한다. */
.legacy-notice {
  display: none;
}

.legacy-notice.is-visible,
.is-legacy .legacy-notice {
  display: block;
  max-width: 34rem;
  margin: 15vh auto;
  padding: 0 20px;
  text-align: center;
  line-height: 1.7;
}

.legacy-notice h1 {
  margin-bottom: 12px;
  font-size: 1.2rem;
}

/* 이 화면을 보는 브라우저는 CSS 커스텀 프로퍼티도 모를 수 있다(IE11).
   var()를 이해하지 못하면 선언 전체를 버리므로, 앞에 리터럴 색을 하나 둬서
   그쪽이 남게 한다. 하필 IE를 위한 화면에서 IE가 못 읽는 문법만 쓰면
   글자색이 통째로 빠진다. rem, vh, max-width는 IE11도 이해한다. */
.legacy-notice p {
  margin: 6px 0;
  color: #6b6b6b;
  /* biome-ignore lint/suspicious/noDuplicateProperties: 위 리터럴 색은 IE11용
     폴백이다. 중복이 바로 이 규칙이 노리는 동작이라 지우면 안 된다. */
  color: var(--ink-soft);
  font-size: 0.85rem;
}

.legacy-notice .legacy-hint {
  font-size: 0.75rem;
}

/* 캐릭터. 화면 폭이 좁으면 줄어들되 원본보다 커지지는 않게 한다.
   width/height 속성을 마크업에 적어 뒀으므로 로드 전에도 자리를 차지한다. */
.legacy-character {
  display: block;
  width: 180px;
  max-width: 60%;
  height: auto;
  margin: 0 auto 8px;
}

/* 지원되지 않는 브라우저에는 앱을 아예 보여주지 않는다. 반쯤 동작하는 화면을
   내놓으면 사용자는 무엇이 문제인지 알 수 없다. */
/* 특이도만으로 충분하다. .is-legacy가 붙으면 각 규칙이 원래 것을 이긴다.
   dialog는 UA 스타일시트가 display를 정하지만 작성자 스타일이 우선한다. */
.is-legacy main,
.is-legacy .footer,
.is-legacy dialog {
  display: none;
}

/* ---------------------------------------------------------------- 오류 화면 */

/* 서버가 404/500 등에 내주는 한 장짜리 페이지(src/server/error-page.ts).
   앱과 같은 스타일시트를 쓰므로 색과 글꼴이 저절로 맞고, 다크 모드도
   :root 토큰을 그대로 따라간다. 그 화면에는 스크립트가 없다 -- CSP가
   인라인 스크립트를 막고 있고, 애초에 필요도 없다. */

/* body는 하단 고정 푸터를 전제로 아래쪽 여백을 크게 잡는다. 오류 화면에는
   푸터가 없으므로 그 여백을 되돌린다. */
.error-body {
  padding-bottom: 12px;
}

.error-page {
  max-width: 30rem;
  margin: 12vh auto;
  padding: 0 20px;
  text-align: center;
  line-height: 1.7;
}

.error-character {
  display: block;
  width: 200px;
  max-width: 60%;
  height: auto;
  margin: 0 auto;
}

.error-page h1 {
  margin: 4px 0 8px;
  font-size: 1.2rem;
}

.error-page p {
  margin: 6px 0;
  color: var(--ink-soft);
  font-size: 0.9rem;
}

/* 숫자는 크게 두되 제목보다 앞서지 않게 흐린 색으로 둔다. 무엇이 잘못됐는지는
   아래 문장이 알려주고, 코드는 개발자에게만 의미가 있다.
   .error-page p 와 같은 요소라서 셀렉터를 한 단계 더 붙여야 이긴다. */
.error-page .error-status {
  margin: 0;
  font-size: 2rem;
  font-weight: 700;
  letter-spacing: 0.05em;
}

.error-home {
  display: inline-block;
  margin-top: 12px;
  padding: 8px 18px;
  border-radius: 999px;
  background: var(--control-bg);
  color: var(--control-fg);
  font-size: 0.9rem;
  text-decoration: none;
}

.error-home:hover {
  background: var(--control-active);
}

/* ------------------------------------------------------------ 마지막 */

/* hidden 속성은 UA 스타일시트에서 display:none이지만, .pill 같은 작성자 규칙의
   display:inline-flex가 같은 특이도로 이를 덮어버린다(실제로 확인 화면의
   "다시 시도" 버튼이 숨겨지지 않았다). 같은 특이도에서는 뒤에 온 규칙이
   이기므로 이 파일 맨 끝에 둔다. */
[hidden] {
  display: none;
}
