/* Premium feedback pass: quiet surfaces, readable hierarchy, one bright event at a time. */
.stage {
  isolation: isolate;
  background: #190424 !important;
}
.stage:before {
  content: "";
  position: absolute;
  z-index: 1;
  inset: 8px;
  pointer-events: none;
  border: 1px solid #ebd1f916;
  border-radius: 10px;
  box-shadow:
    inset 0 0 0 1px #0f0315aa,
    inset 0 0 44px #b46ed716;
}
.stage canvas {
  position: relative;
  z-index: 0;
}
.stage .toast,
.stage .tip,
.stage .impact-flash {
  z-index: 4;
}
.game-mode .boss-banner {
  position: relative;
  overflow: hidden;
}
/* 배너 전체 폭을 도는 무한 스윕이 있었다. 쓸어가는 그라디언트는 #e0b3f611,
   알파 7%인데 배너 배경은 96% 불투명이라 화면에서 사실상 보이지 않았다.
   그 대가로 전투 내내 배너 폭만 한 합성 레이어가 고정 승격되고 부모의
   overflow 클립이 계속 살아 있었다. 눈에 보이는 것 대비 비용이 가장 나빴다. */
.game-mode .boss-banner > * {
  position: relative;
  z-index: 1;
}
.phase {
  letter-spacing: 0.12em !important;
  color: #d0abe5 !important;
}
.boss-name b {
  font-variant-numeric: tabular-nums;
}
.meter {
  position: relative;
  border-radius: 999px !important;
}
.meter i {
  border-radius: inherit;
}
.meter:after {
  content: "";
  position: absolute;
  inset: 1px;
  background: repeating-linear-gradient(
    90deg,
    transparent 0 18%,
    #16041f66 18.5% 19.5%,
    transparent 20%
  );
  pointer-events: none;
}
.combo-readout {
  min-height: 15px;
  font-size: 11px !important;
  letter-spacing: 0.11em !important;
}
.combo-readout.hot {
  color: #fff0bb !important;
  text-shadow:
    0 0 12px #f0c768,
    0 0 26px #d595f2 !important;
  animation: comboIgnite 0.28s ease-out;
}
.blaze-card {
  overflow: visible !important;
  border-radius: 3px;
}
.blaze-card:before {
  opacity: 0.8 !important;
}
.blaze-card[data-heat="0"]:before {
  opacity: 0.28 !important;
}
.blaze-card[data-heat="3"] {
  animation: constellationCrown 1.1s ease-in-out infinite;
}
.blaze-card[data-heat="3"]:before {
  animation: starBreathe 1.1s ease-in-out infinite !important;
}
.blaze-card small {
  font-variant-numeric: tabular-nums;
}
.blaze-card b {
  font-variant-numeric: tabular-nums;
}
.title-sequence:before {
  opacity: 0.82 !important;
}
.title-sequence:after {
  opacity: 0.5;
}
.title-wordmark {
  width: min(510px, 92%) !important;
  max-height: 142px;
  object-fit: contain;
  image-rendering: auto !important;
  filter: drop-shadow(0 5px 0 #17041f) drop-shadow(0 0 13px #f4cd78aa)
    drop-shadow(0 0 32px #daa2f477) !important;
}
.title-copy:before {
  content: "";
  width: min(360px, 72%);
  height: 1px;
  margin: 0 0 12px;
  background: linear-gradient(
    90deg,
    transparent,
    #f7d889,
    #eacef9,
    #f7d889,
    transparent
  );
  box-shadow: 0 0 12px #f1c96d88;
  opacity: 0;
  animation: titleFade 0.35s ease 0.84s forwards;
}
.title-kicker {
  padding: 4px 9px;
  border-top: 1px solid #eacdf944;
  border-bottom: 1px solid #eacdf944;
  text-shadow: 0 0 10px #dba7f4;
}
.title-copy p {
  max-width: 430px !important;
  margin-bottom: 20px !important;
}
/* .title-enter 규칙이 여기 있었다 — 「별빛 점화」 타이틀(ig-*)로 마크업이
   바뀐 뒤 이 클래스를 만드는 곳이 저장소에 없어 걷었다(2026-08-23 실측:
   dawn.js의 버튼 목록에 문자열로만 남는다). */
.survivor-hub {
  background:
    radial-gradient(circle at 80% 6%, #aa61cd29, transparent 26%),
    linear-gradient(160deg, #2a073ced, #15041def) !important;
}
.hub-topbar {
  padding: 4px 0 13px !important;
}
.hub-mission {
  border-width: 1px !important;
}
.hub-mission:before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    120deg,
    transparent 20%,
    #ffe6a510 37%,
    transparent 48%
  );
  transform: translateX(-100%);
  animation: missionSweep 7s ease-in-out infinite;
}
.hub-mission-copy,
.hub-start {
  position: relative;
}
.hub-start {
  letter-spacing: 0.05em;
}
.hub-resource {
  border-radius: 3px;
}
.hub-quick {
  position: relative;
  overflow: hidden;
  border-radius: 3px !important;
}
.hub-quick:after {
  content: "";
  position: absolute;
  inset: auto 10px 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, #e9caf9, transparent);
  opacity: 0;
  transition: opacity 0.18s;
}
.hub-quick:hover:after {
  opacity: 1;
}
.hub-party-slot {
  box-shadow: inset 0 0 10px #dba6f41a;
}
.hub-record {
  border-radius: 0 3px 3px 0;
}
.roster-unit,
.party-chip,
.deploy-unit,
.choice-card {
  transition:
    transform 0.16s ease,
    border-color 0.16s ease,
    box-shadow 0.16s ease,
    background 0.16s ease;
}
.roster-unit:hover,
.party-chip:hover,
.deploy-unit:hover,
.choice-card:hover {
  transform: translateY(-2px);
  border-color: #ebd1f9 !important;
  box-shadow:
    0 6px 16px #09020c99,
    0 0 0 1px #ebd1f924 !important;
}
.roster-unit.selected,
.party-chip.active,
.deploy-unit.selected {
  transform: translateY(-2px);
}
.outcome-cut {
  position: relative;
  overflow: hidden;
  border-color: #ad77cb !important;
  background-color: #20062df2 !important;
  box-shadow:
    0 18px 44px #08010bbb,
    0 0 0 1px #f3d27a22 !important;
}
.outcome-cut:before {
  content: "";
  position: absolute;
  inset: -40%;
  pointer-events: none;
  background:
    radial-gradient(circle, #fff3bb20 0 2%, transparent 2.4%),
    radial-gradient(circle, #e5c1f718 0 1.5%, transparent 2.2%);
  background-size:
    53px 47px,
    71px 67px;
  transform: rotate(14deg);
  animation: outcomeDrift 14s linear infinite;
}
.outcome-cut > * {
  position: relative;
  z-index: 1;
}
.outcome-constellation {
  display: flex;
  justify-content: center;
  gap: 13px;
  height: 24px;
  margin: 0 0 6px;
  color: #ffe7a5;
  font-size: 18px;
  letter-spacing: 0.25em;
  text-shadow: 0 0 12px #f1c96d;
}
.outcome-constellation i {
  font-style: normal;
  /* ✦✧★✧✦ 글자를 도트 사다리(star-24)로. 글자는 투명하게 남겨
     레이아웃·판독기를 그대로 두고 그림만 얹는다 — 정수 배율(24)만 쓴다
     (2026-08-22 작화 납품 §4-6). 짝수 번째(✧ 자리)는 저휘도 벌. */
  width: 24px;
  height: 24px;
  background: url("../assets/library/icons/star/star-24.png") center no-repeat;
  image-rendering: pixelated;
  color: transparent;
  text-shadow: none;
  animation: outcomeStar 1.9s ease-in-out infinite;
}
.outcome-constellation i:nth-child(even) {
  background-image: url("../assets/library/icons/star/star-dim-24.png");
}
.outcome-constellation i:nth-child(2) {
  animation-delay: 0.18s;
}
.outcome-constellation i:nth-child(3) {
  animation-delay: 0.36s;
}
.outcome-constellation i:nth-child(4) {
  animation-delay: 0.54s;
}
.outcome-constellation i:nth-child(5) {
  animation-delay: 0.72s;
}
.outcome-cut h2 {
  color: #fff1bf !important;
  text-shadow: 0 0 19px #e8bd6088;
}
.outcome-cut .tag {
  color: #ecd3fa !important;
  letter-spacing: 0.17em;
}
.result-card {
  border-color: #9c68b9 !important;
  background: linear-gradient(145deg, #320946, #20062d) !important;
  box-shadow: inset 0 0 0 1px #fff0bb0c;
}
.result-medal,
.result-metric img {
  filter: drop-shadow(0 0 7px #e1bc6c88) !important;
}
.result-metric {
  color: #d6b6e8 !important;
}
.result-metric b {
  color: #ffe4a2 !important;
}
.outcome-cut.win button {
  border-color: #ffe2a0 !important;
  background: linear-gradient(#f2d480, #c38b45) !important;
  color: #1b1430 !important;
}
.outcome-cut.fail button {
  border-color: #d5abec !important;
  background: linear-gradient(#6d328c, #4f186d) !important;
}
@keyframes comboIgnite {
  45% {
    transform: scale(1.14);
    filter: brightness(1.38);
  }
}
@keyframes constellationCrown {
  50% {
    box-shadow:
      0 3px 0 #08010cbb,
      0 0 28px #f3cd7688,
      0 0 52px #d596f255;
  }
}
/* `filter`는 단축 속성이라 여기서 brightness만 쓰면 기반 규칙의 blur(0.3px)이
   통째로 교체된다 — 반주기마다 부드러움이 깜빡 꺼지고 있었다(연출 버그이자
   매 프레임 필터 재계산 비용). 밝기는 blur를 유지한 채 얹고, 최대 열기에서만
   도는 애니메이션이므로 값 자체는 그대로 둔다. */
@keyframes starBreathe {
  50% {
    transform: scale(1.16) translateY(-4px);
    filter: blur(0.3px) brightness(1.3);
  }
}
@keyframes missionSweep {
  35%,
  100% {
    transform: translateX(100%);
  }
}
@keyframes outcomeDrift {
  to {
    transform: rotate(14deg) translate(54px, -36px);
  }
}
@keyframes outcomeStar {
  50% {
    transform: translateY(-4px) scale(1.24);
    filter: brightness(1.32);
  }
}
@media (max-width: 680px) {
  .title-wordmark {
    width: min(420px, 94%) !important;
  }
  .title-copy:before {
    margin-bottom: 8px;
  }
  .outcome-cut {
    padding: 38px 17px 23px !important;
  }
  .result-card {
    grid-template-columns: 54px 1fr !important;
  }
  .result-medal {
    width: 48px !important;
    height: 48px !important;
  }
}

/* A home-screen layout, not a splash poster: constellation progress lives on
   the left, while the next objective and the three-step play loop stay next
   to the primary action. */
.title-mode main {
  width: min(920px, calc(100vw - 28px));
  padding: 0;
}
.title-mode .stage {
  height: min(700px, calc(100dvh - 20px));
  border-radius: 20px;
}
.title-mode canvas {
  display: none;
}
.title-mode .title-sequence {
  grid-template-columns: 54% 46%;
}
.title-mode .title-constellation {
  inset: 0 auto 0 0;
  width: 54%;
  height: 100%;
  border-right: 1px solid #daa5f42b;
  background:
    radial-gradient(circle at 50% 27%, #e0b3f616, transparent 35%),
    linear-gradient(90deg, #21062e4d, transparent);
}
.title-mode .title-sky-map {
  top: 2%;
  height: 54%;
}
.title-mode .title-wordmark {
  width: min(410px, 98%) !important;
  max-height: 108px;
  margin-bottom: 3px;
}
.title-mode .title-kicker {
  margin-bottom: 16px;
}
.title-mode .title-enter {
  width: 100%;
  min-height: 48px;
  animation-delay: 1.5s;
}
.title-help {
  margin-top: 9px;
  padding: 4px 8px !important;
  border: 0 !important;
  background: transparent !important;
  color: #d1abe6 !important;
  box-shadow: none !important;
  font-size: 10px !important;
  opacity: 0;
  animation: titleFade 0.3s ease 1.66s forwards;
}
.title-help b {
  margin-left: 4px;
  color: #ffe3a1;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.title-help:hover {
  color: #f9f2fd !important;
  transform: translateY(-1px);
}
/* Signature. It arrives last, after the CTA and the tutorial line, so it reads
   as the closing beat of the entry sequence rather than as another thing to
   look at. Wide letter-spacing at a small size and low contrast keeps it in
   the same register as the kicker above the wordmark. */
.title-credit {
  display: block;
  margin-top: 22px;
  color: var(--mist, #938aa4);
  opacity: 0;
  font-size: 8px;
  letter-spacing: 0.32em;
  text-indent: 0.32em;
  animation: titleFade 0.5s ease 1.85s forwards;
}
.title-credit b {
  color: #c9b489;
  font-weight: 600;
}
@media (prefers-reduced-motion: reduce) {
  .title-credit {
    animation: none;
    opacity: 0.72;
  }
}
@media (max-width: 720px) {
  .title-mode main {
    width: calc(100vw - 12px);
  }
  .title-mode .stage {
    height: calc(100dvh - 12px);
    border-radius: 12px;
  }
  .title-mode .title-sequence {
    display: block;
  }
  .title-mode .title-constellation {
    width: 100%;
    height: 43%;
    border-right: 0;
    border-bottom: 1px solid #daa5f424;
  }
  .title-mode .title-sky-map {
    top: -4%;
    height: 74%;
  }
  .title-mode .title-copy {
    position: absolute;
    inset: 43% 0 0;
    width: 100%;
    min-height: 0;
    justify-content: flex-start;
    padding: 8px 15px 10px;
  }
  .title-mode .title-wordmark {
    width: min(320px, 78%) !important;
    max-height: 68px;
    margin: 0;
  }
  .title-mode .title-kicker {
    display: none;
  }
  .title-mode .title-enter {
    min-height: 42px;
  }
  .title-help {
    margin-top: 4px;
  }
}

/* Campaign map: a single constellation, not a list of isolated cards. */
.constellation-map-scene {
  padding: 0 !important;
  place-content: stretch !important;
  background: #0f0315f5 !important;
}
.constellation-map-shell {
  width: min(760px, 100%);
  min-height: 100%;
  margin: auto;
  padding: 18px 20px 14px;
  display: flex;
  flex-direction: column;
  background:
    radial-gradient(circle at 52% 8%, #7e3b9b33, transparent 33%),
    linear-gradient(160deg, #270737, #120319 76%);
}
.constellation-map-head {
  display: flex;
  justify-content: space-between;
  align-items: end;
  gap: 15px;
  padding: 4px 2px 13px;
  border-bottom: 1px solid #8f61a955;
}
.constellation-map-head h2 {
  margin: 3px 0 0 !important;
  color: #fff0c5 !important;
  font-size: 28px !important;
}
.constellation-map-head p {
  max-width: 230px;
  margin: 0 !important;
  color: #ceace3 !important;
  font-size: 10px !important;
  line-height: 1.5;
  text-align: right;
}
.constellation-map {
  position: relative;
  flex: 1;
  /* 500px was a hard floor, but the head (73) and foot (73) and the shell's
     padding (32) leave only 450px inside the 628px column at 1280x720.  The
     shell came out 677px tall, the overlay clips, and the footer's back /
     training / replay buttons were cut off with no way to scroll to them.
     `flex: 1` already hands the map every pixel that is actually spare, so
     the floor only needs to stop it collapsing on very short windows. */
  min-height: 240px;
  overflow: hidden;
}
.constellation-map:before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    radial-gradient(circle, #f7e3a7aa 0 1px, transparent 1.6px),
    radial-gradient(circle, #e4bff788 0 0.8px, transparent 1.4px);
  background-size:
    97px 113px,
    167px 149px;
  opacity: 0.32;
}
.constellation-map:after {
  content: "";
  position: absolute;
  inset: 12% 5%;
  pointer-events: none;
  background: radial-gradient(ellipse at 49% 45%, #cc82f017, transparent 46%);
}
.constellation-route {
  position: absolute;
  z-index: 1;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.constellation-route path {
  fill: none;
  stroke: #b67ed4;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 4 8;
  filter: drop-shadow(0 0 5px #d190f199);
}
.constellation-route .future {
  stroke: #9263aa66;
  stroke-dasharray: 2 11;
}
.constellation-node {
  position: absolute;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 9px;
  width: 184px;
  padding: 7px 9px 7px 7px;
  border: 1px solid #9562b2 !important;
  border-radius: 7px !important;
  background: linear-gradient(105deg, #300844f4, #20062de8) !important;
  color: #f8effd !important;
  text-align: left;
  box-shadow: 0 8px 18px #09010c99 !important;
  transform: translate(-50%, -50%);
  cursor: pointer;
}
.constellation-node:hover,
.constellation-node.active {
  border-color: #ffe2a0 !important;
  box-shadow:
    0 0 0 1px #ffe2a044,
    0 10px 22px #09020cbf,
    0 0 21px #dba7f444 !important;
  --node-y: -53%;
}
/* 가장자리 카드가 안쪽으로 열리게 하던 보정은 더 이상 필요 없다. 노드가
   호버에서 커지지 않으므로 잘릴 것 자체가 없다 — 펼침은 하단 서랍이 맡는다. */
.constellation-node.locked {
  border-color: #6d4384 !important;
  background: #1a0525d9 !important;
  color: #a884bc !important;
  cursor: default;
  filter: saturate(0.45);
}
.constellation-node.locked:hover {
  border-color: #6d4384 !important;
  box-shadow: 0 8px 18px #09010c99 !important;
  transform: translate(-50%, -50%);
}
.constellation-node .stage-star {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 46px;
  height: 46px;
  border: 1px solid #e9c66f;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    #fff2bc 0 7%,
    #d9a952 12% 22%,
    #313565 29% 48%,
    #1b0526 70%
  );
  color: #fff8d5;
  font-size: 20px;
  box-shadow:
    0 0 0 4px #e6c36518,
    0 0 17px #f0c66d77;
}
.constellation-node.locked .stage-star {
  border-color: #89629e;
  background: radial-gradient(
    circle,
    #bb95d0 0 7%,
    #6f4684 12% 23%,
    #310944 29% 48%,
    #15041d 70%
  );
  color: #c5a8d5;
  box-shadow: 0 0 0 4px #a981be0d;
}
.constellation-node .stage-copy {
  min-width: 0;
}
.constellation-node small {
  display: block;
  color: #d7b5ea;
  font-size: 8px;
  letter-spacing: 0.12em;
}
.constellation-node b {
  display: block;
  margin: 1px 0;
  color: #fff0c5;
  font-size: 16px;
  letter-spacing: 0.08em;
}
.constellation-node strong {
  display: block;
  margin: 1px 0 2px;
  color: #f1e0fb;
  font-size: 10px;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.constellation-node span {
  display: block;
  color: #d1b3e2;
  font-size: 9px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.constellation-node.locked b {
  color: #c5acd3;
}
.constellation-node.locked strong {
  color: #a884bc;
}
.constellation-node.locked span {
  color: #8f6ea1;
}
.constellation-node .node-status {
  margin-left: auto;
  color: #ffe1a0;
  font-size: 10px;
}
.constellation-node.locked .node-status {
  color: #9977ac;
}
.constellation-node.s1 {
  left: 16%;
  top: 75%;
}
.constellation-node.s2 {
  left: 34%;
  top: 53%;
}
.constellation-node.s3 {
  left: 57%;
  top: 31%;
}
.constellation-node.s4 {
  left: 78%;
  top: 48%;
}
.constellation-node.s5 {
  left: 72%;
  top: 75%;
}
/* Seven stars per world no longer fit the old five-card layout inside the
   game column: every node rests as a small star chip, and only the hovered
   or keyboard-focused star expands into its full description card. */
.constellation-map-scene .constellation-node {
  flex-direction: column;
  gap: 3px;
  width: 68px;
  padding: 6px 5px 5px;
}
.constellation-map-scene .constellation-node .stage-star {
  width: 30px;
  height: 30px;
  font-size: 13px;
}
.constellation-map-scene .constellation-node .stage-copy {
  width: 100%;
  text-align: center;
}
.constellation-map-scene .constellation-node small,
.constellation-map-scene .constellation-node .stage-copy span,
.constellation-map-scene .constellation-node .node-status {
  display: none;
}
.constellation-map-scene .constellation-node b {
  margin: 0;
  font-size: 12px;
  white-space: nowrap;
}
.constellation-map-scene .constellation-node strong {
  display: none;
}
/* 호버로 184px까지 펼치던 규칙은 §3에서 하단 서랍으로 대체됐다. 펼침이 한
   곳으로 모이면 가장자리 노드가 지도 밖으로 잘리는 문제가 구조적으로
   사라지고, 설명문도 9px에서 10px로 올라간다. 호버에는 테두리만 남긴다. */
.constellation-map-scene .constellation-node:hover,
.constellation-map-scene .constellation-node:focus-visible {
  width: 54px;
  flex-direction: column;
}
.constellation-map-scene .constellation-node--legacy-hover {
  z-index: 5;
  flex-direction: row;
  gap: 9px;
  width: 184px;
  padding: 7px 9px 7px 7px;
}
.constellation-map-scene .constellation-node:hover .stage-copy,
.constellation-map-scene .constellation-node:focus-visible .stage-copy {
  text-align: left;
}
.constellation-map-scene .constellation-node:hover small,
.constellation-map-scene .constellation-node:focus-visible small,
.constellation-map-scene .constellation-node:hover .stage-copy span,
.constellation-map-scene .constellation-node:focus-visible .stage-copy span,
.constellation-map-scene .constellation-node:hover .node-status,
.constellation-map-scene .constellation-node:focus-visible .node-status {
  display: block;
}
.constellation-map-scene .constellation-node:hover b,
.constellation-map-scene .constellation-node:focus-visible b {
  margin: 1px 0;
  font-size: 16px;
}
.constellation-map-scene .constellation-node:hover strong,
.constellation-map-scene .constellation-node:focus-visible strong {
  display: block;
}
.constellation-map-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding-top: 12px;
  border-top: 1px solid #8f61a944;
  color: #ceace3;
  font-size: 10px;
}
.constellation-map-foot button {
  min-width: 112px;
}
.constellation-training {
  border-color: #9464af !important;
  background: #300845 !important;
  color: #e0c2f1 !important;
}
.constellation-training:hover {
  border-color: #ebd1f9 !important;
}
@media (max-width: 680px) {
  .constellation-map-shell {
    padding: 12px 10px;
  }
  .constellation-map-head h2 {
    font-size: 24px !important;
  }
  .constellation-map-head p {
    font-size: 9px;
  }
  .constellation-map {
    min-height: 470px;
  }
  .constellation-node {
    width: 156px;
    gap: 6px;
    padding: 6px;
  }
  .constellation-node .stage-star {
    width: 38px;
    height: 38px;
    font-size: 16px;
  }
  .constellation-node b {
    font-size: 14px;
  }
  .constellation-node span {
    font-size: 8px;
  }
  .constellation-node.s1 {
    left: 27%;
    top: 78%;
  }
  .constellation-node.s2 {
    left: 42%;
    top: 57%;
  }
  .constellation-node.s3 {
    left: 61%;
    top: 34%;
  }
  .constellation-node.s4 {
    left: 68%;
    top: 53%;
  }
  .constellation-node.s5 {
    left: 57%;
    top: 76%;
  }
}

/* First-session onboarding lives on the actual 1-1 table. */
.onboarding-card {
  position: absolute;
  z-index: 8;
  left: 16px;
  bottom: 16px;
  width: min(320px, calc(100% - 32px));
  padding: 12px 13px 11px;
  border: 1px solid #ce99ea;
  background: linear-gradient(145deg, #320946f5, #1c0528f4);
  box-shadow:
    0 9px 26px #09010cb8,
    0 0 0 1px #ffe3a522;
}
.onboarding-card:before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    110deg,
    transparent 35%,
    #efdafa12 48%,
    transparent 61%
  );
  animation: onboardingSweep 3.8s ease-in-out infinite;
}
.onboarding-card > * {
  position: relative;
  z-index: 1;
}
.onboarding-helper {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 8px 0 6px;
}
.onboarding-helper img {
  width: 30px;
  height: 30px;
  object-fit: contain;
  image-rendering: pixelated;
  filter: drop-shadow(0 0 7px #ffe49a99);
}
.onboarding-helper b {
  display: block;
  color: #ffe5a8;
  font-size: 11px;
}
.onboarding-helper small {
  display: block;
  margin-top: 2px;
  color: #cfa7e5;
  font-size: 8px;
}
.onboarding-kicker {
  display: flex;
  justify-content: space-between;
  color: #e6c6f8;
  font-size: 9px;
  letter-spacing: 0.12em;
}
.onboarding-kicker b {
  color: #ffe2a0;
}
.onboarding-card h3 {
  margin: 7px 0 5px;
  color: #fff1c4;
  font-size: 15px;
}
.onboarding-card p {
  margin: 0;
  color: #d9bfe8;
  font-size: 10px;
  line-height: 1.55;
}
.onboarding-progress {
  display: flex;
  gap: 4px;
  margin: 10px 0 0;
}
.onboarding-progress i {
  width: 22px;
  height: 3px;
  background: #693486;
}
.onboarding-progress i.active {
  background: #f1ca72;
  box-shadow: 0 0 7px #f0c66d;
}
.onboarding-card button {
  width: 100%;
  margin-top: 10px;
  padding: 8px !important;
  border-color: #ffe1a0 !important;
  background: linear-gradient(#f0d17e, #bd8744) !important;
  color: #1b1430 !important;
  font-size: 11px !important;
}
.onboarding-card.waiting {
  border-color: #f0ca72;
  box-shadow:
    0 9px 26px #09010cb8,
    0 0 20px #f0ca7255;
}
.onboarding-card.complete {
  border-color: #f4d38b;
  animation: onboardingComplete 0.5s ease-out;
}
.onboarding-card.complete h3 {
  color: #fff7d7;
}
@keyframes onboardingSweep {
  45%,
  100% {
    transform: translateX(100%);
  }
}
@keyframes onboardingComplete {
  50% {
    transform: translateY(-4px) scale(1.03);
    filter: brightness(1.2);
  }
}
@media (max-width: 680px) {
  .onboarding-card {
    left: 10px;
    bottom: 10px;
    width: min(292px, calc(100% - 20px));
    padding: 10px;
  }
  .onboarding-card h3 {
    font-size: 13px;
  }
  .onboarding-card p {
    font-size: 9px;
  }
}

/* Guided explanations use the lower dialogue lane. The table remains visible
   and the practice button removes the banner before input is restored. */
.onboarding-dock {
  position: absolute;
  z-index: 7;
  inset: 0;
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
  padding: 0 0 14px 14px;
  pointer-events: none;
}
.onboarding-dock:empty {
  display: none;
}
body.onboarding-locked canvas {
  pointer-events: none;
}
.onboarding-dock .onboarding-card {
  position: relative;
  z-index: 8;
  left: auto;
  bottom: auto;
  width: calc(100% - 24px);
  max-height: 174px;
  padding: 9px 13px 9px;
  margin: 0;
  overflow-x: hidden;
  overflow-y: auto;
  pointer-events: auto;
  border-width: 1px;
  box-shadow:
    0 9px 26px #000c,
    0 0 0 1px #ffe3a533,
    0 0 16px #ca82ee26;
  transition:
    transform 0.35s ease,
    opacity 0.35s ease;
}
.onboarding-dock .onboarding-card.table-live {
  align-self: end;
  transform: translateY(7px);
  transform-origin: bottom left;
  opacity: 0.72;
}
.onboarding-dock .onboarding-card p {
  font-size: 10px;
  line-height: 1.52;
}
.onboarding-dock .onboarding-helper {
  position: absolute;
  top: 9px;
  right: 13px;
  margin: 0;
}
.onboarding-dock .onboarding-helper img,
.onboarding-dock .onboarding-helper small {
  display: none;
}
.onboarding-dock .onboarding-helper b {
  color: #cfc2d7;
  font-size: 8px;
  letter-spacing: 0.04em;
}
.onboarding-dock .onboarding-kicker {
  min-height: 12px;
  padding-right: 102px;
}
.onboarding-dock .onboarding-card h3 {
  margin: 5px 0 3px;
  font-size: 13px;
}
.onboarding-dock .onboarding-progress {
  margin-top: 6px;
}
.onboarding-dock .onboarding-card button {
  margin-top: 6px;
  padding: 6px !important;
}
.onboarding-dock .onboarding-progress i {
  flex: 1;
  width: auto;
}
.onboarding-card.onboarding-enter {
  animation: onboardingPanelIn 0.46s cubic-bezier(0.16, 0.86, 0.3, 1) both;
}
.onboarding-enter .onboarding-kicker,
.onboarding-enter .onboarding-helper,
.onboarding-enter h3,
.onboarding-enter .onboarding-progress {
  opacity: 0;
  animation: onboardingLineIn 0.32s ease-out both;
}
.onboarding-enter .onboarding-kicker {
  animation-delay: 0.08s;
}
.onboarding-enter .onboarding-helper {
  animation-delay: 0.16s;
}
.onboarding-enter h3 {
  animation-delay: 0.24s;
}
.onboarding-enter .onboarding-progress {
  animation-delay: 0.34s;
}
.onboarding-copy {
  min-height: 3.24em;
}
.onboarding-word {
  display: inline-block;
  opacity: 0;
  animation: onboardingWordIn 0.18s ease-out both;
  animation-delay: calc(0.34s + var(--word) * 0.028s);
}
.onboarding-enter button {
  opacity: 0;
  transform: translateY(4px);
  animation: onboardingButtonIn 0.26s ease-out var(--reveal-delay, 900ms) both;
}
.onboarding-enter button:disabled {
  cursor: wait;
}
@keyframes onboardingPanelIn {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@keyframes onboardingLineIn {
  from {
    opacity: 0;
    transform: translateY(5px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@keyframes onboardingWordIn {
  from {
    opacity: 0;
    transform: translateY(3px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@keyframes onboardingButtonIn {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@media (max-width: 760px) {
  .game-mode .onboarding-dock {
    padding: 0 0 10px 10px;
  }
  .onboarding-dock .onboarding-card {
    width: calc(100% - 20px);
    max-height: 162px;
    padding: 9px 10px 9px;
  }
  .onboarding-dock .onboarding-card.table-live {
    transform: translateY(5px);
  }
  .onboarding-dock .onboarding-helper {
    top: 8px;
    right: 10px;
  }
  .onboarding-dock .onboarding-card h3 {
    font-size: 13px;
  }
  .onboarding-dock .onboarding-card p {
    font-size: 10px;
  }
  .onboarding-dock .onboarding-card button {
    margin-top: 7px;
  }
  .onboarding-dock .onboarding-progress {
    margin-top: 7px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .onboarding-card.onboarding-enter,
  .onboarding-enter .onboarding-kicker,
  .onboarding-enter .onboarding-helper,
  .onboarding-enter h3,
  .onboarding-enter .onboarding-progress,
  .onboarding-word,
  .onboarding-enter button {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

/* The title opens on the star-guardians rebuilding a constellation. Keep the
   scene hopeful and readable; enemies belong beyond the start button. */
.title-scene {
  background: #1a0424 !important;
}
.title-sequence {
  background:
    radial-gradient(ellipse at 50% 14%, #d49bf342 0%, transparent 32%),
    radial-gradient(ellipse at 50% 46%, #725cc62e 0%, transparent 45%),
    linear-gradient(180deg, #34094a 0%, #260635 50%, #120319 100%) !important;
}
.title-sequence:before {
  background:
    linear-gradient(180deg, #20062d26 0%, #19042394 65%, #0a020edd 100%),
    radial-gradient(circle at 50% 18%, #ffeab71f 0 1px, transparent 2px),
    url("../assets/library/brand/video-title-card.png") center/cover !important;
  filter: hue-rotate(24deg) saturate(0.58) brightness(0.72) !important;
  opacity: 0.46 !important;
}
.title-sequence:after {
  background:
    linear-gradient(90deg, transparent 8%, #ecd1f90d 50%, transparent 92%),
    repeating-linear-gradient(0deg, #f1e0fb04 0 1px, transparent 1px 5px) !important;
  opacity: 0.38;
}
.title-stars {
  z-index: 0;
}
.title-stars i {
  width: 2px;
  height: 2px;
  border-radius: 50%;
  background: #fff3c7 !important;
  box-shadow:
    0 0 7px #fff4c9,
    0 0 14px #d79ff3 !important;
}
.title-dawn {
  position: absolute;
  z-index: 0;
  left: 50%;
  top: -16%;
  width: min(760px, 95vw);
  height: 52%;
  border-radius: 50%;
  background: radial-gradient(
    ellipse,
    #fff0b32b 0%,
    #d79ff318 37%,
    transparent 70%
  );
  transform: translateX(-50%);
  animation: titleDawn 5.8s ease-in-out infinite;
}
.title-constellation {
  position: absolute;
  z-index: 2;
  inset: 0 0 auto;
  height: min(58vh, 420px);
  height: min(58dvh, 420px);
  pointer-events: none;
}
.title-sky-map {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.title-constellation-line {
  fill: none;
  stroke: #f2dffb;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 900;
  stroke-dashoffset: 900;
  filter: drop-shadow(0 0 6px #d9a2f4);
  opacity: 0.72;
  animation: titleConstellationDraw 1.25s cubic-bezier(0.22, 0.78, 0.22, 1)
    0.12s forwards;
}
.title-constellation-line.line-cross {
  stroke: #ffe6a2;
  animation-delay: 0.38s;
}
.title-constellation-line.line-spine {
  animation-delay: 0.62s;
}
.title-constellation-nodes circle {
  fill: #fff5c9;
  stroke: #e1b7f6;
  stroke-width: 2;
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  filter: drop-shadow(0 0 8px #fff0a4) drop-shadow(0 0 12px #d498f2);
  animation: titleConstellationStar 0.5s steps(3) 0.82s forwards;
}
.title-constellation-nodes circle:nth-child(2),
.title-constellation-nodes circle:nth-child(5) {
  animation-delay: 0.95s;
}
.title-constellation-nodes circle:nth-child(3),
.title-constellation-nodes circle:nth-child(6) {
  animation-delay: 1.08s;
}
.title-shooting-star {
  position: absolute;
  z-index: 3;
  top: 11%;
  left: 12%;
  width: 132px;
  height: 2px;
  border-radius: 99px;
  background: linear-gradient(90deg, transparent, #f7ecfd 66%, #fff8d4);
  box-shadow: 0 0 8px #e1b7f6;
  opacity: 0;
  transform: rotate(-20deg);
  animation: titleShootingStar 5.6s ease-in-out 1.5s infinite;
}
@keyframes titleShootingStar {
  0%,
  64% {
    opacity: 0;
    transform: translate(-80px, 40px) rotate(-20deg);
  }
  68% {
    opacity: 0.9;
  }
  86%,
  100% {
    opacity: 0;
    transform: translate(210px, -104px) rotate(-20deg);
  }
}
.title-copy {
  width: min(560px, 100%);
  padding: 0 24px 28px;
}
.title-copy:before {
  display: none;
}
.title-wordmark {
  width: min(470px, 88%) !important;
  max-height: 116px;
  margin-bottom: 6px;
  filter: drop-shadow(0 4px 0 #17041f) drop-shadow(0 0 12px #f4cd78aa)
    drop-shadow(0 0 26px #daa2f466) !important;
  animation-delay: 1.12s;
}
.title-kicker {
  margin-bottom: 5px;
  padding: 3px 9px;
  animation-delay: 1.28s;
}
.title-copy p {
  max-width: 460px !important;
  margin-bottom: 13px !important;
  color: #f6ebfc !important;
  animation-delay: 1.36s;
}
.title-enter {
  animation-delay: 1.48s;
  overflow: hidden;
}
@keyframes titleConstellationDraw {
  to {
    stroke-dashoffset: 0;
  }
}
@keyframes titleConstellationStar {
  0% {
    opacity: 0;
    transform: scale(0.2);
  }
  70% {
    opacity: 1;
    transform: scale(1.8);
  }
  100% {
    opacity: 1;
    transform: scale(1);
  }
}
@keyframes titleDawn {
  50% {
    opacity: 0.72;
    transform: translateX(-50%) scale(1.06);
  }
}
@media (max-width: 680px) {
  .title-constellation {
    height: min(54dvh, 370px);
  }
  .title-copy {
    padding: 0 14px 18px;
  }
  .title-wordmark {
    width: min(390px, 86%) !important;
    max-height: 94px;
  }
  .title-copy p {
    margin-bottom: 9px !important;
    font-size: 10px !important;
  }
  .title-enter {
    min-width: 230px !important;
  }
}

/* ---------------------------------------------------------------------
   Title pass (VFX_POLISH_SPEC 1): the three guardian portraits, the route
   list, the mission card and the play loop are gone. What is left has to hold
   the screen by itself, so the constellation becomes the subject instead of
   the backdrop: it traces node to node, each node lights as the line reaches
   it, and afterwards both breathe slowly so a parked title never goes dead.
   Entry order stays dark sky - stars - figure - wordmark - CTA, all inside
   two seconds, and #enterHub keeps its 1080ms ready timing.
   --------------------------------------------------------------------- */
/* One centred column. The two-column split was left over from the version
   that had portraits and a route list on the left; with those gone the screen
   reads better as a single stack sitting inside the constellation, which now
   runs full bleed behind it. */
.title-mode .title-sequence {
  grid-template-columns: minmax(0, 1fr);
  place-items: center;
  align-items: center;
}
.title-mode .title-constellation {
  position: absolute !important;
  z-index: 1 !important;
  inset: 0 !important;
  width: 100% !important;
  height: 100% !important;
  background: none !important;
  border-right: 0 !important;
}
.title-mode .title-sky-map {
  /* Keep the celestial dome below the frame edge instead of pinning its crown
     to the bezel; the title stack stays independently positioned. */
  top: 4%;
  left: 0;
  width: 100%;
  height: 88%;
  opacity: 1;
}
.title-mode .title-constellation-line {
  stroke-width: 2.6;
  opacity: 0.95;
}
.title-mode .title-constellation-nodes circle {
  filter: drop-shadow(0 0 9px #fff4bb) drop-shadow(0 0 22px #d79ff3);
}
.title-mode .title-dome-arc {
  stroke-width: 1.6;
  opacity: 0.66 !important;
}
.title-mode .title-dome-ticks line {
  stroke-width: 1.6;
}
.title-mode .title-sky-dust circle {
  fill: #faf3fe;
}
.title-mode .title-shooting-star {
  top: 9%;
  left: 8%;
  width: 150px;
}
/* A soft well under the type so the sky never fights the wordmark. */
.title-mode .title-copy {
  position: relative;
  z-index: 6 !important;
  grid-column: 1 !important;
  width: min(660px, 92%) !important;
  /* sits a touch above centre: the optical middle reads lower than the true one */
  margin-bottom: 12vh;
  padding: 30px 28px !important;
  text-align: center;
  align-content: center;
  justify-items: center;
}
.title-mode .title-copy::after {
  position: absolute;
  z-index: -1;
  content: "";
  inset: 2% -20% -6%;
  background: radial-gradient(
    ellipse at 50% 58%,
    #0d0212e8 0%,
    #0d0212b8 40%,
    transparent 70%
  );
  pointer-events: none;
}
.title-mode .title-wordmark {
  width: min(600px, 94%) !important;
  max-height: 200px;
  margin-bottom: 26px;
  filter: drop-shadow(0 3px 0 #0d0212) drop-shadow(0 0 6px #ffeec6)
    drop-shadow(0 0 18px #f4cd7899) !important;
  animation:
    titleLogo 0.66s cubic-bezier(0.18, 0.88, 0.23, 1.22) 1.12s forwards,
    titleWordmarkGlow 5s ease-in-out 1.9s infinite !important;
}
@keyframes titleWordmarkGlow {
  0%,
  100% {
    filter: drop-shadow(0 3px 0 #0d0212) drop-shadow(0 0 6px #ffeec6)
      drop-shadow(0 0 18px #f4cd7899);
  }
  50% {
    filter: drop-shadow(0 3px 0 #0d0212) drop-shadow(0 0 8px #fff8e6)
      drop-shadow(0 0 26px #ffd98ebb);
  }
}
.title-mode .title-kicker {
  margin: 0 0 44px !important;
  padding-top: 18px;
  border-top: 1px solid #daa5f42e;
  color: #938aa4 !important;
  font-size: 10px !important;
  letter-spacing: 0.3em !important;
  white-space: nowrap;
  text-shadow: none !important;
}
.title-mode .title-enter {
  min-width: 300px !important;
  padding: 17px 34px !important;
  font-size: 18px !important;
  letter-spacing: 0.05em;
  animation-delay: 1.34s;
}
.title-mode .title-enter img {
  width: 23px;
  height: 23px;
}
.title-mode .title-help {
  margin-top: 30px !important;
  font-size: 11px !important;
  white-space: nowrap;
}
.title-mode .title-help b {
  white-space: nowrap;
}
@media (max-height: 760px) {
  .title-mode .title-wordmark {
    max-height: 148px;
    margin-bottom: 18px;
  }
  .title-mode .title-kicker {
    margin-bottom: 32px !important;
    padding-top: 13px;
  }
  .title-mode .title-help {
    margin-top: 22px !important;
  }
  .title-chart {
    margin-bottom: 22px;
  }
  .title-mode .title-copy {
    margin-bottom: 9vh;
  }
  .title-mode .title-enter {
    min-width: 270px !important;
    padding: 14px 28px !important;
    font-size: 16px !important;
  }
  .title-mode .title-copy {
    margin-bottom: 5vh;
    padding: 20px 24px !important;
  }
}
.title-constellation-line {
  stroke-dasharray: 1200;
  stroke-dashoffset: 1200;
  animation:
    titleConstellationDraw 0.82s cubic-bezier(0.3, 0.72, 0.24, 1) 0.16s forwards,
    titleSkyBreath 7s ease-in-out 1.9s infinite;
}
.title-constellation-line.line-head {
  stroke: #ffe6a2;
  animation-delay: 1.06s, 2.7s;
}
.title-constellation-line.line-sword {
  stroke: #e8d4ff;
  stroke-width: 1.6 !important;
  opacity: 0.6 !important;
  animation-delay: 1.34s, 3.1s;
}
/* Orion's nebula sits under the sword; it is the one soft mass in an
   otherwise linear figure, which is what makes the sky look deep. */
.title-sky-nebula {
  opacity: 0;
  animation:
    titleNebulaIn 1.5s ease-out 1.5s forwards,
    titleNebulaDrift 9s ease-in-out 3s infinite;
}
.title-sky-halo {
  display: none;
}
/* SVG 자식은 개별 합성 레이어를 받지 못한다. 여기에 transform을 걸면 매
   프레임 SVG 지오메트리가 메인 스레드에서 다시 계산되고, 이 먼지가 32개라
   타이틀 화면 스타일 재계산 15%의 대부분이 여기서 나왔다. 먼지의 반지름은
   1.1~1.6px이라 scale(1.12)이 실제로 바꾸는 건 0.2px 미만 — 화면에서 구분되지
   않는다. 깜빡임은 불투명도만 남기고, 그마저도 셋 중 하나만 돌린다. 캔버스
   별밭도 이미 다섯 중 하나 비율로 반짝인다. */
.title-sky-dust circle {
  fill: #f6ebfd;
  opacity: 0;
  animation: titleDustIn 1.4s ease-out 0.9s forwards;
}
.title-sky-dust circle:nth-child(3n + 1) {
  animation:
    titleDustIn 1.4s ease-out 0.9s forwards,
    titleSkyDust 3.4s ease-in-out var(--td, 2s) infinite;
}
@keyframes titleSkyDust {
  0%,
  100% {
    opacity: 0.82;
  }
  50% {
    opacity: 1;
  }
}
@keyframes titleNebulaIn {
  to {
    opacity: 1;
  }
}
@keyframes titleDustIn {
  to {
    opacity: 0.85;
  }
}
@keyframes titleNebulaDrift {
  50% {
    transform: scale(1.14);
    opacity: 0.78;
  }
}
.title-constellation-line.line-cross {
  animation-delay: 0.72s, 2.3s;
}
.title-constellation-line.line-cross-b {
  animation-delay: 0.9s, 2.45s;
}
.title-constellation-line.line-spine {
  animation-delay: 1.04s, 2.6s;
}
.title-constellation-nodes circle {
  animation:
    titleConstellationStar 0.42s steps(3) forwards,
    titleSkyNode 4.6s ease-in-out infinite;
  animation-delay: var(--sd, 0.5s), var(--td, 2s) !important;
}
@keyframes titleSkyBreath {
  0%,
  100% {
    opacity: 0.86;
  }
  50% {
    opacity: 1;
  }
}
@keyframes titleSkyNode {
  0%,
  100% {
    opacity: 0.82;
    transform: scale(1);
  }
  50% {
    opacity: 1;
    transform: scale(1.12);
  }
}
@media (prefers-reduced-motion: reduce) {
  .title-constellation-line {
    animation: none !important;
    stroke-dashoffset: 0 !important;
    opacity: 0.8 !important;
  }
  .title-constellation-nodes circle {
    animation: none !important;
    opacity: 1 !important;
  }
  .title-shooting-star,
  .title-sky-nebula,
  .title-sky-halo,
  .title-sky-dust circle,
  .title-sky-dust circle:nth-child(3n + 1),
  .title-dawn,
  .title-stars i {
    animation: none !important;
  }
  .title-wordmark,
  .title-kicker,
  .title-enter,
  .title-help {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}

/* Star-chart header: two hairlines with ticks and the figure's name between
   them. It gives the band above STELLA BALL something to hold without adding
   another block of copy, and reads as the label an observatory would print. */
.title-chart {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  margin-bottom: 30px;
  opacity: 0;
  animation: titleFade 0.5s ease 0.98s forwards;
}
.title-chart i {
  position: relative;
  flex: 1 1 auto;
  height: 1px;
  background: linear-gradient(90deg, transparent, #daa5f45e, transparent);
}
.title-chart i::before,
.title-chart i::after {
  position: absolute;
  top: -3px;
  content: "";
  width: 1px;
  height: 7px;
  background: #daa5f466;
}
.title-chart i::before {
  left: 26%;
}
.title-chart i::after {
  right: 26%;
}
.title-chart small {
  color: #d2cedb;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.3em;
  white-space: nowrap;
  text-shadow: 0 0 10px #daa5f455;
}
@media (max-height: 760px) {
  .title-chart {
    margin-bottom: 14px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .title-chart {
    animation: none !important;
    opacity: 1 !important;
  }
}

/* The dome: one wide arc with graduation ticks across the top band. It gives
   the space above the wordmark structure without another line of copy, and it
   is the one straight-edged instrument on a screen made of stars. */
.title-dome-arc {
  fill: none;
  stroke: #daa5f4;
  stroke-width: 1.2;
  stroke-dasharray: 1400;
  stroke-dashoffset: 1400;
  opacity: 0.34;
  animation: titleConstellationDraw 1.6s cubic-bezier(0.3, 0.7, 0.2, 1) 0.3s
    forwards;
}
.title-dome-ticks line {
  stroke: #daa5f4;
  stroke-width: 1.2;
  opacity: 0;
  animation: titleDomeTick 0.8s ease-out 1s forwards;
}
.title-dome-ticks line:nth-child(4n + 1) {
  stroke: #f4d17c;
  animation-delay: 1.2s;
}
@keyframes titleDomeTick {
  to {
    opacity: 0.8;
  }
}
@media (prefers-reduced-motion: reduce) {
  .title-dome-arc {
    animation: none !important;
    stroke-dashoffset: 0 !important;
  }
  .title-dome-ticks line {
    animation: none !important;
    opacity: 0.8 !important;
  }
}

/* Measured on the live screen: three soft layers were stacking in the middle of
   the frame — a full-height sheen band at 50% width, the dawn glow spilling
   across the top, and the nebula sitting right behind the type. Together they
   read as fog, so each one steps back. */
.title-mode .title-sequence::after {
  opacity: 0.12 !important;
}
.title-mode .title-dawn {
  top: -14% !important;
  opacity: 0.34 !important;
}
.title-mode .title-sky-nebula {
  opacity: 0.5;
}
.title-mode .title-sequence::before {
  filter: saturate(0.55) brightness(0.98) !important;
}
@keyframes titleNebulaDrift {
  50% {
    transform: scale(1.1);
    opacity: 0.62;
  }
}

/* 수업용 정지 신호. 유성이 결정 지점에 닿으면 판이 멈추고 이 한 줄이 뜬다.
   독은 flex-end라 카드와 같은 자리에 쌓이므로, 카드가 없는 실습 중에만
   보이는 이 신호는 판 가운데 아래쪽에 따로 세운다. */
.teach-hold {
  position: absolute;
  left: 50%;
  bottom: 20%;
  transform: translateX(-50%);
  z-index: 9;
  pointer-events: none;
  padding: 9px 16px;
  border: 1px solid #503870;
  border-radius: 3px;
  background: #0a0410eb;
  box-shadow:
    0 0 0 1px #0e0616,
    0 6px 18px #07020c99;
  color: #d2cedb;
  font:
    700 13px/1.5 "Galmuri11",
    ui-monospace,
    monospace;
  letter-spacing: 0.02em;
  white-space: nowrap;
  /* 기본값이 보이는 상태여야 한다. 등장 애니메이션의 끝값에 기대면 탭이
     가려져 있거나 애니메이션이 중간에 끊긴 순간에 신호가 통째로 사라지고,
     판만 멈춘 화면이 남는다. */
  opacity: 1;
  animation: teachHoldIn 0.16s steps(2) 1;
}
.teach-hold b {
  color: #ffd2a0;
}
/* 지금 눌러야 한다는 것만 전한다. 계속 깜빡이면 읽는 대신 기다리게 된다. */
/* 등장은 위치만 움직인다. 불투명도를 애니메이션에 넣으면 진행 중인 값이
   기본값을 덮어, 프레임이 멈춘 순간(가려진 탭 등)에 0%에 갇혀 신호가
   통째로 사라진다. 판만 멈춘 화면이 남으면 그건 안내가 아니라 고장이다. */
@keyframes teachHoldIn {
  0% {
    transform: translateX(-50%) translateY(4px);
  }
  100% {
    transform: translateX(-50%) translateY(0);
  }
}
@media (prefers-reduced-motion: reduce) {
  .teach-hold {
    animation: none;
  }
}

/* ---------------------------------------------------------------------
   ENDING — 8-1 closes the campaign, so it does not get the ordinary win
   card. The palette follows OUTER_OBSERVER_INTRO_SPEC section 4: the
   entity stays teal-ash and low contrast, and the one warm accent is the
   apricot the reclaimed constellations already own, used on the count of
   stars returned rather than on the thing outside the window.
   --------------------------------------------------------------------- */
.outcome-cut.ending {
  border-color: #5d4a76;
  background-color: #0c0314f2;
  background-image: radial-gradient(
    ellipse 70% 50% at 50% 0%,
    #3a23575c,
    transparent 70%
  );
}
.outcome-cut.ending h2 {
  color: #d2cedb;
}
.ending-lines {
  margin: 14px auto 18px;
  max-width: 44ch;
  display: grid;
  gap: 7px;
}
.ending-lines p {
  color: #a69eb4;
  line-height: 1.7;
}
.ending-lines b {
  color: #d2cedb;
  letter-spacing: 0.08em;
}
.ending-metrics {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px 22px;
  margin-bottom: 18px;
}
.ending-metrics span {
  display: grid;
  gap: 2px;
  min-width: 92px;
  padding: 8px 12px;
  border: 1px solid #46345d;
  background: #11041fcc;
  color: #887e9a;
  font-size: 11px;
}
.ending-metrics b {
  color: #ffd2a0;
  font-size: 15px;
}
