/* The loading screen: up from the first paint (no script needed) until the client lifts it,
   over everything else. boot.js fills the bar while the client downloads; the client then
   says what it waits for (games/shinobi-society-web/src/io/loading.rs): `data-state` (loading, lifted, error),
   `.status` and `--progress` (0..1). */
#boot {
  --progress: 0;
  position: fixed; inset: 0; z-index: 30; display: grid; place-items: center; overflow: hidden;
  padding: 24px 24px 96px;
  background:
    radial-gradient(55% 45% at 50% 42%, var(--accent-wash), transparent 70%),
    radial-gradient(120% 90% at 50% 0%, var(--lacquer) 0%, var(--ink) 58%) var(--ink);
  color: var(--paper); font: 16px/1.5 var(--face);
  &[data-state=lifted] { opacity: 0; visibility: hidden; pointer-events: none;
    transition: opacity 0.5s ease, visibility 0s linear 0.5s; }
  /* Everything that moves on the loading screen moves by transform or opacity alone, so the
     browser's compositor runs it smoothly while the page's thread is busy loading behind it. */
  .glyph { position: absolute; left: 50%; top: 44%; width: min(70vh, 70vw); height: min(70vh, 70vw);
    transform: translate(-50%, -50%); color: var(--paper); opacity: 0.022; pointer-events: none; }
  .card { position: relative; display: flex; flex-direction: column; align-items: center; text-align: center; }
  .mark { width: 60px; height: 60px; filter: drop-shadow(0 0 18px var(--accent-glow));
    animation: boot-turn 1.8s cubic-bezier(0.7, 0, 0.3, 1) infinite; will-change: transform; }
  h1 { font-family: var(--face); margin: 22px 0 0; font-size: 36px; line-height: 1.1; font-weight: 700; letter-spacing: 0.02em;
    color: var(--paper-bright); }
  .tagline { margin: 6px 0 0; color: var(--muted); font-size: 17px; font-style: italic; }
  .bar {
    position: relative; width: min(320px, 72vw); height: 2px; margin-top: 32px; background: var(--line);
    span { position: absolute; inset: 0; transform-origin: left; transform: scaleX(var(--progress));
      background: linear-gradient(90deg, var(--accent-deep), var(--accent) 60%, var(--accent-hi));
      box-shadow: 0 0 12px var(--accent-glow); transition: transform 0.35s ease-out; will-change: transform; }
    /* The bar's head: a diamond riding its end, moved (not stretched) with it. */
    &::after { content: ""; position: absolute; left: -3px; top: 50%; width: 6px; height: 6px;
      transform: translateX(calc(var(--progress) * min(320px, 72vw))) translateY(-50%) rotate(45deg);
      background: var(--accent-hi); box-shadow: 0 0 10px var(--accent-hi); transition: transform 0.35s ease-out;
      will-change: transform; }
  }
  /* Lifted, the bar does not animate: put up again, it starts from nothing at once. */
  &[data-state=lifted] .bar span, &[data-state=lifted] .bar::after { transition: none; }
  .status { min-height: 1.5em; margin: 14px 0 0; max-width: min(460px, 86vw); color: var(--muted);
    font-size: 15px; font-variant-numeric: tabular-nums; }
  .retry { display: none; margin-top: 22px; }
  &[data-state=error] .mark { animation: none; filter: grayscale(1) opacity(0.45); }
  &[data-state=error] .bar { display: none; }
  &[data-state=error] .status { margin-top: 26px; color: var(--danger); font-size: 16px; }
  &[data-state=error] .retry { display: inline-flex; }
  &[data-state=error] .tip { display: none; }
  .tip {
    position: absolute; left: 50%; bottom: calc(28px + env(safe-area-inset-bottom)); transform: translateX(-50%);
    width: min(620px, 88vw); margin: 0; text-align: center; color: var(--faint); font-size: 15px; line-height: 1.6;
    transition: opacity 0.4s;
    &.fading { opacity: 0; }
    b { margin-right: 10px; }
  }
  @media (prefers-reduced-motion: reduce) {
    .mark { animation-duration: 6s; }
    .bar span, .bar::after, .tip { transition: none; }
  }
}
@keyframes boot-turn { from { transform: rotate(0deg); } to { transform: rotate(90deg); } }
