/* ╔══════════════════════════════════════════════════════════════════════════╗
   ║  Forge Loader                                                            ║
   ║  Branded loading overlay ported from DriftApp's LoadingScreen +          ║
   ║  component-library v2 LoadingSpinner (large). Timeline:                  ║
   ║    enter  — spinner scales 0→1, 0.5s overshoot bezier; arc fades in      ║
   ║             0.3s (delayed 0.3s) while spinning at 1 turn/s linear        ║
   ║    hold   — until the page triggers exit (default 1600ms from mount)     ║
   ║    exit   — arc fades out 0.3s; spinner scales 1→0, 0.5s back-in         ║
   ║             bezier delayed 0.15s                                         ║
   ║    reveal — overlay fades 0.6s ease, then content fades in 0.6s ease     ║
   ║  Driven by /assets/forge-loader.js.                                      ║
   ╚══════════════════════════════════════════════════════════════════════════╝ */

/* Real cross-document page transitions (Chromium 126+). The browser holds a
   snapshot of the old page until the new one is ready to paint, so the loader
   overlay persists across a hard navigation instead of the page flashing white
   between routes. Both the old and new document opt in here; the JS in
   forge-loader.js gates it to loader-covered navigations only (login ↔ home),
   so ordinary page-to-page navigation is unaffected. Progressive enhancement —
   unsupported browsers simply navigate as before. */
@view-transition { navigation: auto; }

/* Treat the loader overlay as ONE persistent element across the navigation. With
   the transition animation suppressed, the new (live, spinning) overlay takes
   over from the old (frozen) snapshot the instant the destination is ready — no
   white gap, no second "enter", no crossfade ghosting. */
.forge-loader-overlay { view-transition-name: forge-loader; }
::view-transition-old(forge-loader),
::view-transition-new(forge-loader) { animation: none; mix-blend-mode: normal; }

.forge-loader-overlay {
  position: fixed;
  inset: 0;
  background-color: var(--surface-page-default, #f7f9f8);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
  opacity: 1;
  transition: opacity 0.6s ease;
}
.forge-loader-overlay.fade-out {
  opacity: 0;
  pointer-events: none;
}

/* Spinner root — logo with the arc ring around it (the ::after). Sized to
   the component library's "large" variant: 64px logo, 20px gap, 6px stroke. */
.forge-loader {
  --spinner-color: var(--border-primary-default, #00ae8e);
  --spinner-stroke: 6px;
  --spinner-logo-size: 64px;
  --spinner-gap: 20px;
  --spinner-speed: 1s;

  position: relative;
  display: flex;
  padding: var(--spinner-gap);
}
/* Enter — scale-up overshoot. Scoped to the enter state so the "spin" (resume)
   state can mount at full size without replaying it. */
.forge-loader[data-animation="enter"] {
  animation: forge-loader-enter 0.5s cubic-bezier(0.39, 1.63, 0.55, 1.01) forwards;
}
/* Resume state — the spinner already entered on the previous route (a loader-
   covered navigation), so it mounts at full size, arc visible, already spinning,
   with NO enter scale/fade. Makes a hard navigation read as one continuous loader. */
.forge-loader[data-animation="spin"]::after {
  opacity: 1;
  animation: forge-loader-spin var(--spinner-speed) infinite linear 0s;
}

/* Arc: conic-gradient ring with a rounded cap (the radial dot at top),
   masked down to a ring of --spinner-stroke width. */
.forge-loader::after {
  content: "";
  position: absolute;
  inset: 0;
  width: 100%;
  opacity: 0;
  aspect-ratio: 1;
  border-radius: 50%;
  background:
    radial-gradient(farthest-side, var(--spinner-color) 80%, #0000)
      top / var(--spinner-stroke) var(--spinner-stroke) no-repeat,
    conic-gradient(#0000 65%, var(--spinner-color));
  -webkit-mask: radial-gradient(farthest-side, #0000 calc(100% - var(--spinner-stroke)), #000 0);
  mask: radial-gradient(farthest-side, #0000 calc(100% - var(--spinner-stroke)), #000 0);
}

.forge-loader[data-animation="enter"]::after {
  animation:
    forge-loader-fade-in 0.3s forwards linear 0.3s,
    forge-loader-spin var(--spinner-speed) infinite linear 0s;
}

.forge-loader[data-animation="exit"] {
  animation: forge-loader-exit 0.5s cubic-bezier(0.45, -0.01, 0.61, -0.63) forwards 0.15s;
}
.forge-loader[data-animation="exit"]::after {
  animation:
    forge-loader-fade-out 0.3s forwards linear 0s,
    forge-loader-spin 1s infinite linear 0s;
}

.forge-loader-logo {
  width: var(--spinner-logo-size);
  height: var(--spinner-logo-size);
}
.forge-loader-logo .forge-loader-logo-base   { fill: var(--logo-secondary-default, #213538); }
.forge-loader-logo .forge-loader-logo-accent { fill: var(--logo-primary-default, #00AE8E); }

@keyframes forge-loader-enter {
  from { transform: scale(0); }
  to   { transform: scale(1); }
}
@keyframes forge-loader-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes forge-loader-spin {
  100% { transform: rotate(1turn); }
}
@keyframes forge-loader-fade-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}
@keyframes forge-loader-exit {
  from { transform: scale(1); }
  to   { transform: scale(0); }
}

/* Scroll lock — block scrolling for the loader's full lifecycle so the page
   behind the overlay can't be scrolled and then revealed mid-scroll. Locked
   both while the overlay is mounted (covers every entry point, incl. the enter-
   only logout spinner) AND through the content-reveal phase, since the
   `forge-loading` class persists until the very end of the sequence. Targets
   both the root and body to catch whichever element owns the document scroll. */
html:has(.forge-loader-overlay),
body:has(.forge-loader-overlay),
html:has(body.forge-loading),
body.forge-loading {
  overflow: hidden;
}

/* Content reveal — mirrors DriftApp's AppShell: content sits at opacity 0
   while the loader runs, then fades in 0.6s ease AFTER the overlay has
   fully faded out (sequential, not simultaneous). Pages opt their content
   in via the .forge-loader-content class; the Forge sidebar (whose markup
   is generated by forge-sidebar.js) is included here directly. */
body.forge-loading .forge-loader-content,
body.forge-loading .forge-sidebar {
  opacity: 0;
  transition: opacity 0.6s ease;
}
body.forge-loading.forge-revealing .forge-loader-content,
body.forge-loading.forge-revealing .forge-sidebar {
  opacity: 1;
}
