/* ============================================================
   FAJAR MANPOWER — PRELOADER
   Full-screen brand splash. The logo reads as an empty vessel
   and gold liquid rises inside it, with a rippling surface,
   looping until the page finishes loading.

   The shape comes from a CSS mask of the transparent logo PNG,
   so the fill is clipped to the letterforms themselves — nothing
   is drawn outside the mark.

   Loaded FIRST on every page so the splash paints immediately,
   before Bootstrap / fonts / hero imagery arrive.
   ============================================================ */

:root {
  --pl-bg:        #101c28;
  --pl-gold:      #e6c063;
  --pl-gold-lite: #f5da96;
  --pl-gold-deep: #c08f36;
  --pl-speed:     3.2s;   /* one full rise + drain cycle */
}

/* Lock scrolling while the splash is up. Set by an inline <head> script on
   <html> so it applies from the very first paint. */
html.is-loading,
html.is-loading body {
  overflow: hidden;
}


/* ------------------------------------------------------------
   Overlay
   ------------------------------------------------------------ */

.preloader {
  position: fixed;
  inset: 0;
  z-index: 99999;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 42px;
  background-color: var(--pl-bg);
  /* Faint lift behind the mark so the flat navy doesn't read dead. */
  background-image: radial-gradient(ellipse at 50% 47%,
      rgba(230, 192, 99, 0.09) 0%,
      rgba(230, 192, 99, 0) 62%);
  transition: opacity 0.7s ease, visibility 0.7s ease, transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Exit state — added by JS once the window has loaded. */
.preloader.is-hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}


/* ------------------------------------------------------------
   Logo vessel

     .pl-ghost  — the plain artwork, dimmed: the empty vessel
     .pl-mark   — the logo shape punched out with a mask, so the
                  .pl-liquid inside it only paints where there's ink

   The ghost is a real <img>, not a masked layer, on purpose: mask
   images are origin-restricted, so they don't load when a page is
   opened straight off disk over file://. If that happens the fill
   is lost but the mark still reads, instead of going blank.
   ------------------------------------------------------------ */

.pl-stage {
  position: relative;
  width: min(430px, 76vw);
  /* Matches assets/images/logo.png (1456 x 430). */
  aspect-ratio: 1456 / 430;
}

.pl-ghost {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0.17;
  user-select: none;
  -webkit-user-drag: none;
}

.pl-mark {
  position: absolute;
  inset: 0;
  overflow: hidden;
  /* Fades in over the first beat so that if the mask PNG is still in flight
     on the very first paint, the momentarily-unmasked box isn't visible.
     Kept off .pl-stage on purpose: a stacking context there would cut
     .pl-sheen off from the overlay backdrop it blends against. */
  animation: pl-mark-in 0.45s ease 0.12s both;
  -webkit-mask-image: url("../images/logo.png");
  mask-image: url("../images/logo.png");
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
}

/* The liquid body. Height is the fill level; the keyframes drive it. */
.pl-liquid {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 6%;
  background: linear-gradient(180deg,
      var(--pl-gold-lite) 0%,
      var(--pl-gold) 42%,
      var(--pl-gold-deep) 100%);
  animation: pl-rise var(--pl-speed) cubic-bezier(0.55, 0.06, 0.32, 1) infinite;
}

/* Two wave crests ride the surface. Each is a repeating SVG wave twice the
   stage width, drifting sideways at a different speed so the surface never
   reads as a single looping tile. Their solid lower half butts flush against
   the liquid body (bottom: 100%), so the join is invisible. */
.pl-liquid::before,
.pl-liquid::after {
  content: "";
  position: absolute;
  left: -50%;
  width: 200%;
  height: 13%;
  bottom: 100%;
  background-repeat: repeat-x;
  /* One tile = 25% of this element = 50% of the stage. */
  background-size: 25% 100%;
}

.pl-liquid::before {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 24' preserveAspectRatio='none'%3E%3Cpath d='M0 16 Q 15 0 30 16 T 60 16 T 90 16 T 120 16 V24 H0 Z' fill='%23f5da96'/%3E%3C/svg%3E");
  animation: pl-wave 2.6s linear infinite;
}

.pl-liquid::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 24' preserveAspectRatio='none'%3E%3Cpath d='M0 13 Q 15 24 30 13 T 60 13 T 90 13 T 120 13 V24 H0 Z' fill='%23e0b955'/%3E%3C/svg%3E");
  opacity: 0.75;
  animation: pl-wave 3.7s linear infinite reverse;
}

/* Soft light pooled on the surface, sitting OUTSIDE the mask so it can bleed
   past the letterforms instead of ending on their edges. */
.pl-sheen {
  position: absolute;
  left: -6%;
  right: -6%;
  bottom: 6%;
  height: 20%;
  pointer-events: none;
  mix-blend-mode: screen;
  background-image: radial-gradient(ellipse at 50% 100%,
      rgba(255, 214, 128, 0.26) 0%,
      rgba(255, 214, 128, 0) 68%);
  filter: blur(9px);
  animation: pl-sheen-rise var(--pl-speed) cubic-bezier(0.55, 0.06, 0.32, 1) infinite;
}


/* ------------------------------------------------------------
   Progress line
   ------------------------------------------------------------ */

.pl-bar {
  position: relative;
  width: min(180px, 44vw);
  height: 2px;
  border-radius: 2px;
  background: rgba(230, 192, 99, 0.16);
  overflow: hidden;
}

.pl-bar span {
  position: absolute;
  inset: 0;
  display: block;
  border-radius: inherit;
  background: linear-gradient(90deg,
      rgba(230, 192, 99, 0) 0%,
      var(--pl-gold) 50%,
      rgba(230, 192, 99, 0) 100%);
  transform: translateX(-100%);
  animation: pl-bar-slide 2.4s ease-in-out infinite;
}


/* ------------------------------------------------------------
   Keyframes

   pl-rise fills the mark, holds it brimming for a beat, then lets
   the level fall away — so the loop restarts empty without a snap.
   ------------------------------------------------------------ */

@keyframes pl-rise {
  0%   { height: 6%; }
  58%  { height: 100%; }
  74%  { height: 100%; }
  100% { height: 6%; }
}

/* The sheen tracks the surface: same stops and easing as pl-rise, offset by
   the ellipse's own height so the light sits on the waterline. */
@keyframes pl-sheen-rise {
  0%   { bottom: 6%;   opacity: 0.85; }
  58%  { bottom: 100%; opacity: 0.85; }
  74%  { bottom: 100%; opacity: 0.55; }
  100% { bottom: 6%;   opacity: 0.3; }
}

@keyframes pl-mark-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* One tile of horizontal drift — seamless because the tile repeats. */
@keyframes pl-wave {
  from { transform: translateX(0); }
  to   { transform: translateX(-25%); }
}

@keyframes pl-bar-slide {
  0%   { transform: translateX(-100%); }
  50%  { transform: translateX(0); }
  100% { transform: translateX(100%); }
}


/* ------------------------------------------------------------
   Final frame — once loading is done the mark brims full and the
   surface goes still for a beat before the overlay fades away.
   ------------------------------------------------------------ */

/* Dropping the looping animation would normally snap the level back to its
   base height for a frame. initPreloader() avoids that by pinning the current
   level inline first, then releasing it to 100% on the next frame — these
   transitions carry it the rest of the way. */
.preloader.is-complete .pl-liquid {
  animation: none;
  height: 100%;
  transition: height 0.42s cubic-bezier(0.22, 1, 0.36, 1);
}

.preloader.is-complete .pl-liquid::before,
.preloader.is-complete .pl-liquid::after {
  opacity: 0;
  transition: opacity 0.3s ease;
}

.preloader.is-complete .pl-sheen {
  animation: none;
  bottom: 100%;
  opacity: 0;
  transition: bottom 0.42s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.42s ease;
}

.preloader.is-complete .pl-bar span {
  animation: none;
  transform: translateX(0);
}

.preloader.is-complete {
  transform: scale(1.03);
}


/* ------------------------------------------------------------
   Reduced motion — show the mark filled, skip the rise.
   ------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  .pl-mark,
  .pl-liquid,
  .pl-liquid::before,
  .pl-liquid::after,
  .pl-sheen,
  .pl-bar span {
    animation: none !important;
  }

  .preloader { transition: opacity 0.3s ease, visibility 0.3s ease; }
  .preloader.is-complete { transform: none; }
  .pl-liquid { height: 100%; }
  .pl-liquid::before,
  .pl-liquid::after { opacity: 0; }
  .pl-sheen { opacity: 0; }
  .pl-bar span { transform: translateX(0); }
}
