/*
 * Shared boot / full-viewport loaders - ONE file for splash + React.
 * Linked from index.html (paints before JS) and reused by LoadingState / PageLoader.
 * Change spinner size / colour / boot background here only.
 */
:root {
  --portal-boot-bg: #f3f4f6;
  --portal-boot-spinner-size: 40px;
  --portal-boot-spinner-color: #526c51;
  --portal-boot-spinner-duration: 1s;
  /*
   * Twelve rounded petals around the centre, used as an alpha mask so the petal colour
   * stays themable from --portal-boot-spinner-color instead of baked into an asset.
   */
  --portal-boot-spinner-shape: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><rect x='47' y='24' width='6' height='12' rx='3'/><rect x='47' y='24' width='6' height='12' rx='3' transform='rotate(30 50 50)'/><rect x='47' y='24' width='6' height='12' rx='3' transform='rotate(60 50 50)'/><rect x='47' y='24' width='6' height='12' rx='3' transform='rotate(90 50 50)'/><rect x='47' y='24' width='6' height='12' rx='3' transform='rotate(120 50 50)'/><rect x='47' y='24' width='6' height='12' rx='3' transform='rotate(150 50 50)'/><rect x='47' y='24' width='6' height='12' rx='3' transform='rotate(180 50 50)'/><rect x='47' y='24' width='6' height='12' rx='3' transform='rotate(210 50 50)'/><rect x='47' y='24' width='6' height='12' rx='3' transform='rotate(240 50 50)'/><rect x='47' y='24' width='6' height='12' rx='3' transform='rotate(270 50 50)'/><rect x='47' y='24' width='6' height='12' rx='3' transform='rotate(300 50 50)'/><rect x='47' y='24' width='6' height='12' rx='3' transform='rotate(330 50 50)'/></svg>");
}

#portal-splash,
.portal-loader-center {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

#portal-splash,
.portal-auth-loading {
  background-color: var(--portal-boot-bg);
}

/*
 * The conic gradient fades the petals from the leading edge, and stepping the rotation
 * in twelve jumps lands one petal exactly where the next one starts.
 */
.portal-spinner,
#portal-splash .portal-spinner {
  display: block;
  box-sizing: border-box;
  width: var(--portal-boot-spinner-size);
  height: var(--portal-boot-spinner-size);
  border-radius: 50%;
  background: conic-gradient(var(--portal-boot-spinner-color), transparent 330deg);
  -webkit-mask-image: var(--portal-boot-spinner-shape);
  mask-image: var(--portal-boot-spinner-shape);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  animation: portal-spinner-rotate var(--portal-boot-spinner-duration) steps(12) infinite;
}

.portal-button-spinner {
  width: 1rem;
  height: 1rem;
  flex: 0 0 1rem;
  background: conic-gradient(currentColor, transparent 330deg);
}

/*
 * In-button wait: the spinner sits on top of the faded label instead of beside it, so the
 * button never resizes mid-action. Centred with offsets, not translate, because the
 * rotation keyframe owns `transform`.
 */
.portal-button-loading {
  position: relative;
}

.portal-button-loading > .portal-button-label {
  opacity: 0;
}

.portal-button-loading > .portal-button-spinner {
  position: absolute;
  top: calc(50% - 0.5rem);
  left: calc(50% - 0.5rem);
}

@keyframes portal-spinner-rotate {
  to {
    transform: rotate(360deg);
  }
}

/* Route-chunk wait: same spinner/position, no backdrop so the shell stays visible. */
.portal-page-loader {
  pointer-events: none;
  z-index: 1;
}
