/* The pre-game screens. 「协议启动！」 over BATTLE_CHECK (ui/protocolBoot.js): the official battleReady/* sprites and settle/common_logo on one
   1920×1080 stage. --px is one design px, fitted to the viewport (positions and sizes measured from the event's
   footage, video 7:43–7:51; [ASSUMED] the timings, estimated frame by frame). Timeline: the ship zooms out of the screen (0–1 s), the panel flashes up (1–1.45 s), and
   it holds until BATTLE_CHECK ends; then it fades (.is-leaving, BOOT_LEAVE_MS).
   PR #643 (frame by frame, video 7:43.3–7:46): from black the ship builds up out of torn blocks, near white (0.1–0.4 s),
   shrinks into the ring as it darkens (to 1.2 s); the panel comes with a teal wash over the screen (1.2–1.9 s), the cards
   open out from their avatars, white first, 协议启动！ settles from large, 正在连接… last (1.9 s). */
.pbx {
  --px: min(.01rem, calc(100vw / 1920), calc(100vh / 1080));
  --teal: #3fd6b4;
  --teal-deep: #0c2a25;
  position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; overflow: hidden; pointer-events: none;
  background: radial-gradient(ellipse at 50% 42%, #0d2621, #040b0a 70%);
}
.pbx.is-leaving { animation: pbx-out 350ms ease-in forwards; }
.pbx__stage { position: relative; width: calc(1920 * var(--px)); height: calc(1080 * var(--px)); }
.pbx__stage > *, .pbx__scene > * { position: absolute; }
.pbx__scene { inset: 0; animation: pbx-in 200ms 1200ms ease-out both; }
.pbx::after { content: ''; position: absolute; inset: 0; pointer-events: none; mix-blend-mode: screen; opacity: 0;
  background: radial-gradient(ellipse at 50% 45%, rgba(150, 255, 225, .7), rgba(63, 214, 180, .45) 70%); animation: pbx-wash 700ms 1200ms ease-out forwards; }
/* behind: the two mountains (top left, bottom right), the contour map and the ring around the ship, the mark above */
.pbx__mtn { opacity: .55; }
.pbx__mtn--1 { left: calc(-60 * var(--px)); top: calc(-40 * var(--px)); width: calc(750 * var(--px)); }
.pbx__mtn--2 { right: calc(-40 * var(--px)); bottom: calc(-60 * var(--px)); width: calc(560 * var(--px)); }
.pbx__terrain, .pbx__logo { display: block; background: var(--teal); -webkit-mask: var(--src) center / 100% 100% no-repeat; mask: var(--src) center / 100% 100% no-repeat; }
.pbx__terrain { left: calc(365 * var(--px)); top: calc(-8 * var(--px)); width: calc(1190 * var(--px)); height: calc(916 * var(--px)); opacity: .3; }
.pbx__ring { left: calc(525 * var(--px)); top: calc(15 * var(--px)); width: calc(870 * var(--px)); height: calc(870 * var(--px)); opacity: .55; }
.pbx__logo { left: calc(705 * var(--px)); top: calc(277 * var(--px)); width: calc(247 * var(--px)); height: calc(125 * var(--px)); opacity: .7; }
.pbx__cross { left: calc((var(--x) - 30) * var(--px)); top: calc((var(--y) - 30) * var(--px)); width: calc(60 * var(--px)); height: calc(60 * var(--px));
  background: linear-gradient(var(--teal), var(--teal)) center / 100% calc(3 * var(--px)) no-repeat,
    linear-gradient(var(--teal), var(--teal)) center / calc(3 * var(--px)) 100% no-repeat; opacity: .8; }
/* the Rhodes Island ship (battleReady/rhodes 299×500, ×1.35, turned 53°): out of the whole screen in bright teal into the middle */
.pbx__ship { left: calc(773 * var(--px)); top: calc(112 * var(--px)); width: calc(404 * var(--px)); height: calc(675 * var(--px));
  transform: rotate(53deg); will-change: transform, opacity; animation: pbx-ship 1100ms 100ms cubic-bezier(.4, 0, .3, 1) both; }
/* transform and opacity only, so it runs on the compositor while the match screen sets up its scene under it (the main
   thread is busy ~0.7 s right then): the near-white build-up is a brightened copy fading out, torn sideways a step at a
   time */
.pbx__shipimg { display: block; width: 100%; height: 100%; }
.pbx__shipimg--hot { position: absolute; inset: 0; filter: brightness(2.6) saturate(.3); will-change: transform, opacity;
  animation: pbx-hot 900ms 100ms linear both, pbx-tear 320ms 100ms steps(1, end) both; }
.pbx__lines { inset: 0; width: 100%; height: 100%; overflow: visible; }
.pbx__lines line { stroke: var(--teal); stroke-width: 3; stroke-dasharray: 1; stroke-dashoffset: 1; animation: pbx-draw 300ms calc(1250ms + var(--i) * 60ms) ease-out forwards; }
.pbx__node, .pbx__anchor { fill: var(--teal); opacity: 0; animation: pbx-show 150ms calc(1400ms + var(--i) * 60ms) forwards; }
.pbx__anchor { fill: var(--teal-deep); stroke: var(--teal); stroke-width: 4; }
/* the doctors' cards: a teal bar, the number / COMPLETE / ✓ and the avatar at the inner end (01 / 03 left, 02 / 04 right) */
.pbx__card {
  left: calc(var(--x) * var(--px)); top: calc(var(--y) * var(--px)); width: calc(515 * var(--px)); height: calc(127 * var(--px));
  display: flex; align-items: center; justify-content: flex-end; gap: calc(14 * var(--px)); padding: 0 calc(4 * var(--px));
  background: linear-gradient(90deg, rgba(63, 214, 180, .78), rgba(63, 214, 180, .95)); color: var(--teal-deep);
  transform-origin: 100% 50%; animation: pbx-card 420ms calc(1200ms + var(--i) * 40ms) cubic-bezier(.2, .8, .2, 1) both;
}
.pbx__card--r { flex-direction: row-reverse; background: linear-gradient(270deg, rgba(63, 214, 180, .78), rgba(63, 214, 180, .95)); transform-origin: 0 50%; }
.pbx__card--c { transform-origin: 50% 50%; }
/* a solo run: the one card under the ring, the words lower (the footage, video 7:50) */
.pbx--solo .pbx__title { top: calc(805 * var(--px)); }
.pbx--solo .pbx__sub { top: calc(938 * var(--px)); }
.pbx__txt { display: grid; justify-items: end; line-height: 1; }
.pbx__card--r .pbx__txt { justify-items: start; }
.pbx__num { font-family: var(--font-display); font-size: calc(54 * var(--px)); font-weight: 700; }
.pbx__done { font-family: var(--font-display); font-size: calc(16 * var(--px)); letter-spacing: .06em; margin-top: calc(2 * var(--px)); }
.pbx__check { display: grid; place-items: center; width: calc(26 * var(--px)); height: calc(26 * var(--px)); margin-top: calc(10 * var(--px));
  background: var(--teal-deep); color: #fff; }
.pbx__check .icon { width: 80%; height: 80%; }
.pbx__face { flex: none; width: calc(119 * var(--px)); height: calc(119 * var(--px)); border: calc(2 * var(--px)) solid #e9fffa; background: var(--teal-deep); overflow: hidden; }
.pbx__face .pavatar { --pa: 100%; width: 100%; height: 100%; }
.pbx__face .pavatar__img, .pbx__face img { width: 100%; height: 100%; object-fit: cover; }
/* 协议启动！ / STRONGHOLD PROTOCOL / 正在连接… */
.pbx__title { left: 0; right: 0; top: calc(705 * var(--px)); margin: 0; text-align: center; font-size: calc(66 * var(--px)); font-weight: 900;
  letter-spacing: .04em; color: var(--teal); text-shadow: 0 0 calc(18 * var(--px)) rgba(63, 214, 180, .45); animation: pbx-title 420ms 1200ms cubic-bezier(.2, .8, .2, 1) both; }
.pbx__sub { left: calc(782 * var(--px)); top: calc(838 * var(--px)); width: calc(356 * var(--px)); height: calc(30 * var(--px)); display: grid; place-items: center;
  background: var(--teal); color: var(--teal-deep); font-family: var(--font-display); font-size: calc(20 * var(--px)); letter-spacing: .08em;
  animation: pbx-in 200ms 1300ms both; }
.pbx__conn { right: calc(165 * var(--px)); top: calc(995 * var(--px)); font-size: calc(26 * var(--px)); color: rgba(63, 214, 180, .7); animation: pbx-in 200ms 1900ms both; }
.pbx__dots::after { content: '…'; display: inline-block; width: 1.2em; overflow: hidden; vertical-align: bottom; animation: pbx-dots 1.2s steps(4, end) infinite; }
.pbx__veil { inset: 0; position: absolute; background: #000; animation: pbx-veil 160ms 60ms ease-out both; }
@keyframes pbx-veil { from { opacity: 1; } to { opacity: 0; } }
@keyframes pbx-in { from { opacity: 0; } }
@keyframes pbx-show { to { opacity: 1; } }
@keyframes pbx-out { to { opacity: 0; } }
@keyframes pbx-wash { 0% { opacity: 1; } 30% { opacity: .75; } 100% { opacity: 0; } }
@keyframes pbx-ship {
  0% { transform: rotate(53deg) scale(4.4); opacity: 0; }
  8% { opacity: 1; }
  30% { transform: rotate(53deg) scale(3.5); }
  100% { transform: rotate(53deg) scale(1); opacity: .6; }
}
@keyframes pbx-hot { 0% { opacity: 0; } 10%, 40% { opacity: 1; } 75%, 100% { opacity: 0; } }
@keyframes pbx-tear {
  0% { transform: translateX(-4%); } 20% { transform: translateX(3%); } 40% { transform: translateX(-2%); }
  60% { transform: translateX(1.2%); } 80% { transform: translateX(-.5%); } 100% { transform: none; }
}
@keyframes pbx-draw { to { stroke-dashoffset: 0; } }
@keyframes pbx-card { 0% { opacity: 0; transform: scaleX(.55); filter: brightness(2.4) saturate(.25); } 30% { opacity: 1; } 60% { filter: brightness(1.5) saturate(.6); } 100% { opacity: 1; transform: none; filter: none; } }
@keyframes pbx-title { 0% { opacity: 0; transform: scale(1.3); filter: brightness(2) blur(3px); } 40% { opacity: 1; } 100% { transform: none; filter: none; } }
@keyframes pbx-dots { from { width: 0; } to { width: 1.2em; } }
@media (prefers-reduced-motion: reduce) {
  .pbx, .pbx *, .pbx *::after { animation: none; }
  .pbx::after { display: none; }
  .pbx__ship { opacity: .6; }
  .pbx__shipimg--hot { display: none; }
  .pbx__lines line { stroke-dashoffset: 0; animation: none; }
  .pbx__node, .pbx__anchor { opacity: 1; }
  .pbx__veil { opacity: 0; }
}

/* 「请选择策略」 (ui/turnBanner.js, the band draft when the pick becomes the player's; video 7:18–7:20): over a dimmed
   screen a light-grey band slides in from the left (the STRONGHOLD PROTOCOL mark, the contour map, the ship's outline),
   a teal fill wipes over it with 请选择策略 and the ring, the robot's square beside it; then it folds shut (1.7 s). */
.tbanner {
  --px: min(.01rem, calc(100vw / 1920), calc(100vh / 1080));
  --teal: #52d6b0;
  --ink: #0b1f1b;
  position: fixed; inset: 0; z-index: 70; pointer-events: none;
}
.tbanner__dim { position: absolute; inset: 0; background: rgba(0, 0, 0, .55); animation: tbanner-dim 1700ms linear both; }
.tbanner__band { position: absolute; left: 0; right: 0; top: calc(50% - 110 * var(--px)); height: calc(220 * var(--px)); display: flex;
  gap: calc(12 * var(--px)); padding-right: calc(15 * var(--px)); transform-origin: 50% 50%; animation: tbanner-band 1700ms cubic-bezier(.2, .7, .2, 1) both; }
.tbanner__bar { position: relative; flex: 1; overflow: hidden; }
.tbanner__grey, .tbanner__teal { position: absolute; inset: 0; overflow: hidden; }
.tbanner__grey { background: #c6c7c9; color: #4a4c4f; }
.tbanner__teal { background: var(--teal); color: var(--ink); clip-path: inset(0 100% 0 0); animation: tbanner-wipe 1700ms cubic-bezier(.5, 0, .2, 1) both; }
.tbanner__topo, .tbanner__ship, .tbanner__logo, .tbanner__ring { position: absolute; display: block; background: currentColor;
  -webkit-mask: var(--src) center / 100% 100% no-repeat; mask: var(--src) center / 100% 100% no-repeat; }
.tbanner__topo { left: 0; top: calc(-120 * var(--px)); width: calc(1190 * var(--px)); height: calc(916 * var(--px)); opacity: .22; }
.tbanner__ship { right: calc(120 * var(--px)); top: calc(-260 * var(--px)); width: calc(290 * var(--px)); height: calc(487 * var(--px)); transform: rotate(53deg); opacity: .45; }
.tbanner__logo { left: calc(40 * var(--px)); top: calc(-5 * var(--px)); width: calc(455 * var(--px)); height: calc(230 * var(--px)); color: #3c3e41; }
.tbanner__ring { right: calc(120 * var(--px)); top: calc(-10 * var(--px)); width: calc(240 * var(--px)); height: calc(240 * var(--px)); opacity: .85; }
.tbanner__text { position: absolute; right: calc(390 * var(--px)); top: calc(58 * var(--px)); font-size: calc(56 * var(--px)); font-weight: 900; letter-spacing: .04em;
  white-space: nowrap; animation: tbanner-text 1700ms ease-out both; }
.tbanner__sub { position: absolute; right: calc(390 * var(--px)); top: calc(138 * var(--px)); width: calc(310 * var(--px)); height: calc(22 * var(--px));
  display: grid; place-items: center end; padding-right: calc(10 * var(--px)); background: var(--ink); color: var(--teal);
  font-family: var(--font-display); font-size: calc(14 * var(--px)); letter-spacing: .08em; animation: tbanner-text 1700ms ease-out 50ms both; }
.tbanner__cross { position: absolute; width: calc(30 * var(--px)); height: calc(30 * var(--px)); opacity: .6;
  background: linear-gradient(currentColor, currentColor) center / 100% calc(2 * var(--px)) no-repeat,
    linear-gradient(currentColor, currentColor) center / calc(2 * var(--px)) 100% no-repeat; }
.tbanner__cross--tl { left: calc(18 * var(--px)); top: calc(18 * var(--px)); }
.tbanner__cross--bl { left: calc(18 * var(--px)); bottom: calc(18 * var(--px)); }
.tbanner__cross--tr { right: calc(18 * var(--px)); top: calc(18 * var(--px)); }
.tbanner__cross--br { right: calc(18 * var(--px)); bottom: calc(18 * var(--px)); }
.tbanner__bot { flex: none; width: calc(250 * var(--px)); display: grid; place-items: center; background: #0f1f1d;
  box-shadow: inset 0 0 calc(30 * var(--px)) rgba(82, 214, 176, .25); }
.tbanner__head { width: calc(120 * var(--px)); height: auto; image-rendering: pixelated; }
@keyframes tbanner-dim { 0% { opacity: 0; } 9% { opacity: 1; } 91% { opacity: 1; } 100% { opacity: 0; } }
/* PR #643's motion: the band shoots in and keeps drifting right until it folds shut; the teal fill wipes over it
   with an ease in and out; the words slide in from the left and drift on with it; the ring turns as it comes up; the
   robot's square pops first. */
@keyframes tbanner-band {
  0% { transform: translateX(-46%); opacity: 0; } 4% { opacity: 1; } 12% { transform: translateX(-1.6%); }
  90% { transform: translateX(1.2%) scaleY(1); opacity: 1; } 97% { transform: translateX(1.2%) scaleY(.06); opacity: 1; }
  100% { transform: translateX(1.2%) scaleY(0); opacity: 0; }
}
@keyframes tbanner-wipe { 0%, 34% { clip-path: inset(0 100% 0 0); } 62%, 100% { clip-path: inset(0); } }
@keyframes tbanner-text { 0%, 46% { opacity: 0; transform: translateX(calc(-60 * var(--px))); } 64% { opacity: 1; transform: none; }
  100% { opacity: 1; transform: translateX(calc(20 * var(--px))); } }
@keyframes tbanner-ring { 0%, 40% { opacity: 0; transform: rotate(-150deg); } 70% { opacity: .85; } 100% { opacity: .85; transform: rotate(30deg); } }
@keyframes tbanner-bot { 0%, 4% { opacity: 0; transform: scale(.4); } 12% { opacity: 1; transform: scale(1); } }
.tbanner__teal .tbanner__ring { animation: tbanner-ring 1700ms ease-out both; }
.tbanner__bot { animation: tbanner-bot 1700ms cubic-bezier(.3, 1.5, .5, 1) both; }
@media (prefers-reduced-motion: reduce) {
  .tbanner { display: none; }
}
