/* =====================================================================
   Preloader
   =====================================================================

   Only rendered when <html> has .is-loading, which an inline script adds on the
   first page of a visit. With JavaScript off, none of this exists.

   The overlay sits over a page that has already painted. It is not a gate; the
   content underneath is real, in the DOM, and would be visible the instant this
   element goes away — which matters because everything about this site depends on
   what Google can read.
   ===================================================================== */

.pl {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: grid;
  place-items: center;
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(255,255,255,.07) 0%, transparent 60%),
    linear-gradient(160deg, var(--navy-800) 0%, var(--navy-900) 100%);

  /* The exit. Two things happen at once: the panel lifts away like a cloth being
     drawn off glass, and what is behind it is already there — so the reveal reads
     as the screen being wiped clean rather than a box disappearing. */
  --pl-exit: 620ms;
  transform: translateY(0);
  clip-path: inset(0 0 0 0);
  transition:
    clip-path var(--pl-exit) cubic-bezier(.76, 0, .24, 1),
    opacity 260ms ease var(--pl-exit);

  /* The failsafe. If JavaScript never runs — a syntax error, a blocked file, an
     old browser — this still clears the screen. A loader that can strand a buyer
     on a blank page costs more than it can ever be worth. */
  animation: pl-failsafe 1ms linear 4s forwards;
}

/* JS adds this the moment the page is ready. */
.pl.is-done {
  clip-path: inset(0 0 100% 0);
  opacity: 0;
  pointer-events: none;
}

@keyframes pl-failsafe { to { opacity: 0; visibility: hidden; pointer-events: none; } }

/* While it is up, the page underneath must not scroll behind it. */
html.is-loading, html.is-loading body { overflow: hidden; }

.pl__sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

.pl__stage {
  display: grid;
  justify-items: center;
  gap: .35rem;
  padding-inline: 1.5rem;
  text-align: center;
  animation: pl-in 520ms cubic-bezier(.16, 1, .3, 1) both;
}
@keyframes pl-in {
  from { opacity: 0; transform: translateY(14px) scale(.97); }
  to   { opacity: 1; transform: none; }
}
.pl.is-done .pl__stage {
  /* Leaves a beat before the panel does, so the wipe uncovers a clean screen
     rather than dragging the artwork up with it. */
  opacity: 0;
  transform: translateY(-10px);
  transition: opacity 220ms ease, transform 380ms cubic-bezier(.76, 0, .24, 1);
}

/* ---------- the pack ---------- */

.pl__art { width: 132px; height: auto; }

.pl__pack-body  { fill: var(--brand-2); }
.pl__pack-sheen {
  /* One diagonal highlight across the pack. Plastic reads as plastic because of a
     single hard specular, not because of gradients everywhere. */
  fill: rgba(255,255,255,.14);
  clip-path: polygon(0 0, 46% 0, 20% 100%, 0 100%);
}
.pl__pack-lid   { fill: rgba(255,255,255,.9); }
.pl__pack-slot  { fill: var(--navy-900); opacity: .55; }
.pl__pack-line  { fill: rgba(255,255,255,.32); }
.pl__pack-line--short { fill: rgba(255,255,255,.2); }

.pl__pack {
  transform-origin: 100px 156px;
  animation: pl-pack 2.4s cubic-bezier(.4, 0, .2, 1) infinite;
}
@keyframes pl-pack {
  /* The pack gives slightly as each sheet is pulled — the small physical detail
     that separates this from a logo bouncing on a screen. */
  0%, 100%  { transform: scaleY(1)     translateY(0); }
  14%       { transform: scaleY(.985)  translateY(1.5px); }
  30%       { transform: scaleY(1.005) translateY(-.5px); }
}

/* ---------- the sheets ---------- */

/* The three sheets share one compositing layer. Without this the browser promotes
   and demotes each rect as its animation starts, and on a low-end phone the loop
   visibly stutters on the first cycle — which is the one everybody sees. */
.pl__sheets { will-change: transform; }

.pl__sheet {
  fill: #fff;
  transform-origin: 100px 84px;
  animation: pl-sheet 2.4s cubic-bezier(.33, 0, .2, 1) infinite;
  opacity: 0;
}
/* Three sheets on the same 2.4s cycle, offset by a third, so one is always on its
   way out and the loop has no seam. */
.pl__sheet--2 { animation-delay: -1.6s; }
.pl__sheet--3 { animation-delay: -0.8s; }

@keyframes pl-sheet {
  0%   { transform: translateY(0) scale(.9)  rotate(0deg);   opacity: 0; }
  8%   { opacity: 1; }
  /* out of the slot, catching a little air as it goes */
  38%  { transform: translateY(-52px) scale(1) rotate(-3deg); opacity: 1; }
  58%  { transform: translateY(-70px) scale(1) rotate(2.5deg); opacity: .85; }
  75%  { transform: translateY(-88px) scale(.98) rotate(-1.5deg); opacity: 0; }
  100% { transform: translateY(-88px) scale(.98); opacity: 0; }
}

/* ---------- the wordmark ---------- */

.pl__word {
  margin: 1.35rem 0 0;
  font-size: 1.06rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #fff;
}
.pl__tag {
  margin: .3rem 0 0;
  font-size: .74rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(255,255,255,.5);
}

/* ---------- the line ---------- */

.pl__bar {
  margin-top: 1.5rem;
  width: 148px;
  height: 2px;
  border-radius: 2px;
  background: rgba(255,255,255,.14);
  overflow: hidden;
}
.pl__bar span {
  display: block;
  width: 45%;
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
  animation: pl-bar 1.15s ease-in-out infinite;
}
@keyframes pl-bar {
  /* Deliberately indeterminate. A bar that claims 40% while nothing is being
     measured is a lie the visitor can feel. */
  0%   { transform: translateX(-120%); }
  100% { transform: translateX(320%); }
}

/* ---------- smaller screens ---------- */

@media (max-width: 480px) {
  .pl__art  { width: 108px; }
  .pl__word { font-size: .95rem; letter-spacing: .12em; }
  .pl__bar  { width: 118px; }
}

/* ---------- when motion is unwelcome ----------
   Someone who has asked their system for reduced motion should not be shown a
   loop of sliding artwork. The inline script already skips the loader for them;
   this is the second line of defence, for the case where the class is on the
   element for any other reason. */
@media (prefers-reduced-motion: reduce) {
  .pl { animation: pl-failsafe 1ms linear 120ms forwards; transition: opacity 200ms ease; }
  .pl__stage, .pl__pack, .pl__sheet, .pl__bar span { animation: none; }
  .pl__sheet--1 { opacity: 1; transform: translateY(-52px); }
}
