/*
 * The SkyDOPS mark and page furniture, shared by every public page.
 *
 * ⚠ ONE DEFINITION, ON PURPOSE. The maintenance page previously carried a
 * hand-written copy of these animations and it was WRONG in three ways at once
 * — `blink` had the wrong duty cycle, `scanSweep` swept the wrong range, and
 * `lockSnapTight` (the reticle snapping shut, which is the mark's whole idea)
 * was missing entirely. It looked plausible in isolation and nothing like the
 * landing page. Copies of an animation drift; this file is the source.
 *
 * The values are the design export's own. Change them here or not at all.
 */

/* --- the animations ------------------------------------------------------ */
@keyframes blink { 0%,49% { opacity: 1 } 50%,100% { opacity: .15 } }
@keyframes lockSnapTight {
  0%   { transform: translate(-50%,-50%) scale(2.1); opacity: 0 }
  12%  { opacity: 1 }
  100% { transform: translate(-50%,-50%) scale(1); opacity: 1 }
}
@keyframes scanSweep {
  0%   { top: 0%;  opacity: 0 }
  12%  { opacity: 1 }
  82%  { opacity: 1 }
  100% { top: 100%; opacity: 0 }
}
@keyframes skydrift {
  0%,100% { transform: translate3d(-3%, 0, 0) scale(1) }
  50%     { transform: translate3d(4%, 2%, 0) scale(1.09) }
}
@keyframes skyfloat {
  0%,100% { transform: translate3d(3%, 1%, 0) scale(1.06) }
  50%     { transform: translate3d(-5%, -3%, 0) scale(.94) }
}

/* --- the wordmark -------------------------------------------------------- */
/* ⚠ text-decoration:none BELONGS HERE, not on the one page that links it. The
   login page makes the mark an anchor, which pulls in the browser's underline —
   and it lands under a wordmark whose glyphs are painted through a gradient
   with a transparent fill, so the rule is drawn in the anchor's colour and
   reads as a stray bar. Any page that links the mark later gets this for free. */
.sky-mark { display:flex; align-items:center; justify-content:center;
  gap:clamp(10px,1.8vw,18px); font-size:clamp(38px,8.2vw,88px); line-height:1;
  text-decoration:none }

.sky-mark .dot { flex:none; width:.22em; height:.22em; border-radius:50%;
  background:#2fe08a; box-shadow:0 0 .2em .02em rgba(47,224,138,.75);
  animation:blink 2.4s steps(1,end) infinite;
  animation-play-state:var(--sky-play, running) }

/* ⚠ THE GRADIENT IS ON ONE ELEMENT SPANNING THE WHOLE WORD. The SVG version
   of this mark painted "SKYD" and "PS" as two <text> nodes, each with its own
   fill="url(#grad)" — and an objectBoundingBox gradient restarts per element,
   so the P and S came out a different colour from the rest of the word. One
   element, one gradient, one continuous ramp. */
.sky-mark .word { font-family:'Space Grotesk',Helvetica,sans-serif; font-size:1em;
  line-height:1; font-weight:700; letter-spacing:.09em;
  background:linear-gradient(96deg,#9a86ff 0%,#6ea8ff 100%);
  -webkit-background-clip:text; background-clip:text;
  color:transparent; -webkit-text-fill-color:transparent;
  display:inline-flex; align-items:baseline }

/* The O opts out of the gradient: it carries the reticle, and a ramp running
   under the red corners muddies both. */
.sky-mark .o { position:relative; display:inline-block; margin:0 .2em;
  color:#8295ff; -webkit-text-fill-color:#8295ff }

/* ⚠ NOT left:50% — THE BOX IS NOT CENTRED ON THE GLYPH. `.word` above sets
   letter-spacing:.09em, and letter-spacing is added AFTER a character, so this
   span is `advance + .09em` wide while the ink occupies only the advance. Its
   midpoint therefore sits half the letter-spacing to the RIGHT of the O itself,
   and a reticle centred on the box reads as offset. Measured before the fix at
   font-size 200px: +18.5px = +0.0462em — half of .09em, as the cause predicts,
   the remaining .0012em being the face's own side-bearing asymmetry. */
.sky-mark .ret { position:absolute; left:calc(50% - .045em); top:50%; width:1.1em; height:1.1em;
  transform:translate(-50%,-50%); pointer-events:none;
  animation:lockSnapTight 3.4s linear infinite;
  animation-play-state:var(--sky-play, running) }
/* ⚠ `> i`, NOT ` i`. The sweep line lives INSIDE .ret, so a descendant
   selector matches it too and gives it this width — and with left:0 and
   right:0 also set, the explicit width wins and the line collapses to a few
   pixels instead of crossing the box. */
.sky-mark .ret > i { position:absolute; width:.28em; height:.28em; border:0 solid #ff2f41;
  filter:drop-shadow(0 0 6px rgba(255,47,65,.95)) }
.sky-mark .ret > i:nth-child(1){ left:0;  top:0;    border-left-width:2.5px; border-top-width:2.5px }
.sky-mark .ret > i:nth-child(2){ right:0; top:0;    border-right-width:2.5px; border-top-width:2.5px }
.sky-mark .ret > i:nth-child(3){ left:0;  bottom:0; border-left-width:2.5px; border-bottom-width:2.5px }
.sky-mark .ret > i:nth-child(4){ right:0; bottom:0; border-right-width:2.5px; border-bottom-width:2.5px }
.sky-mark .sweep { position:absolute; inset:0; overflow:hidden }
.sky-mark .sweep i { position:absolute; left:0; right:0; height:2px;
  background:linear-gradient(90deg,rgba(255,47,65,0),rgba(255,47,65,.95),rgba(255,47,65,0));
  box-shadow:0 0 8px rgba(255,47,65,.7);
  animation:scanSweep 3.4s linear infinite;
  animation-play-state:var(--sky-play, running) }

/* --- the tile icon (the footer mark, and the collapsed dashboard rail) ---- */
.sky-tile { flex:none; width:34px; height:34px; border-radius:9px;
  background:#0a0d16; border:1px solid #1e2334;
  display:flex; align-items:center; justify-content:center; overflow:hidden }
.sky-tile .glyph { position:relative; font-family:'Space Grotesk',Helvetica,sans-serif;
  font-size:17px; font-weight:700; color:#9a86ff }
.sky-tile .ret { position:absolute; left:50%; top:48%; width:1.28em; height:1.28em;
  transform:translate(-50%,-50%) }
.sky-tile .ret > i { position:absolute; width:.34em; height:.34em; border:0 solid #ff2f41 }
.sky-tile .ret > i:nth-child(1){ left:0;  top:0;    border-left-width:2px; border-top-width:2px }
.sky-tile .ret > i:nth-child(2){ right:0; top:0;    border-right-width:2px; border-top-width:2px }
.sky-tile .ret > i:nth-child(3){ left:0;  bottom:0; border-left-width:2px; border-bottom-width:2px }
.sky-tile .ret > i:nth-child(4){ right:0; bottom:0; border-right-width:2px; border-bottom-width:2px }
.sky-tile .sweep { position:absolute; inset:0; overflow:hidden }
.sky-tile .sweep i { position:absolute; left:0; right:0; height:1.5px;
  background:linear-gradient(90deg,rgba(255,47,65,0),rgba(255,47,65,.95),rgba(255,47,65,0));
  animation:scanSweep 3.4s linear infinite;
  animation-play-state:var(--sky-play, running) }

/* --- the page ground: the landing page's grid and ambient glows ----------- */
.sky-ground { position:fixed; inset:0; z-index:0; overflow:hidden;
  background:#0B0614; pointer-events:none }
.sky-ground i { position:absolute; display:block; border:0 }
.sky-ground .glow-a { inset:-20% -10% auto -20%; height:70%;
  background:radial-gradient(50% 50% at 50% 50%, rgba(168,85,247,.20), rgba(168,85,247,0) 70%);
  filter:blur(30px); animation:skydrift 28s ease-in-out infinite;
  animation-play-state:var(--sky-play, running) }
.sky-ground .glow-b { inset:auto -20% -20% -10%; height:70%;
  background:radial-gradient(50% 50% at 50% 50%, rgba(34,211,238,.16), rgba(34,211,238,0) 70%);
  filter:blur(30px); animation:skyfloat 34s ease-in-out infinite;
  animation-play-state:var(--sky-play, running) }
/* The squares. Masked to a soft oval so the page does not end in a hard edge. */
.sky-ground .grid { inset:0;
  background-image:linear-gradient(rgba(168,85,247,.075) 1px, transparent 1px),
                   linear-gradient(90deg, rgba(168,85,247,.075) 1px, transparent 1px);
  background-size:68px 68px;
  -webkit-mask-image:radial-gradient(72% 62% at 50% 45%, #000 0%, rgba(0,0,0,0) 100%);
  mask-image:radial-gradient(72% 62% at 50% 45%, #000 0%, rgba(0,0,0,0) 100%) }

/* The page photograph — the whole ground, at nearly full strength.

   ⚠ NO SCRIM, AND FULL-BLEED ON PURPOSE. It used to be a bottom band fading up
   into #0B0614. Dropping the fade while keeping the band would leave a hard
   horizontal seam across the page where the band starts, so removing the blend
   means the picture has to cover everything.

   ⚠ IT IS STILL THE FIRST CHILD OF .sky-ground, so the grid and both glows lie
   ON TOP of it. Put it last and the photo covers the texture underneath.

   ⚠ WHICH picture is set per page, in the `--sky-photo` custom property, so a
   page states its own image and this rule keeps the one treatment. The default
   is the hero; the login and error pages override it below. */
.sky-ground .photo { inset:0; opacity:.92;
  background-image:var(--sky-photo, url('/images/landing/hero.webp'));
  background-size:cover;
  background-position:var(--sky-photo-pos, center bottom);
  background-repeat:no-repeat }

/* The two pages that carry their own picture.

   ⚠ THE ERROR PAGE ALSO MOVES ITS CROP, and that is not decoration. The band
   is wider than it is tall, so `cover` throws away roughly a third of a 3:2
   photograph — and on the error image the part it threw away was the lightning,
   which is the only thing distinguishing it from the login one. Anchoring it
   lower in the frame keeps the sky. */
/* ⚠ ON THE PHOTO, NOT THE GROUND. The class sits on .sky-ground, and a filter
   there would dim the two glows and the grid as well — the whole page would go
   flat rather than the picture behind it going quieter. */
.sky-wip-bg .photo { filter:brightness(.72) }
.sky-login-bg  { --sky-photo:url('/images/landing/login.webp') }
.sky-error-bg  { --sky-photo:url('/images/landing/error.webp'); --sky-photo-pos:center 28% }

/* --- the login affordance ------------------------------------------------- */
.sky-login { position:fixed; top:16px; right:16px; z-index:50;
  display:inline-flex; align-items:center; gap:7px; padding:8px 15px;
  border-radius:10px; font:600 13px/1 'Space Grotesk','Helvetica Neue',Arial,sans-serif;
  letter-spacing:.02em; text-decoration:none; color:#EDE9FE;
  background:rgba(168,85,247,.14); border:1px solid rgba(168,85,247,.42);
  backdrop-filter:blur(8px);
  transition:background 200ms ease, border-color 200ms ease, color 200ms ease }
.sky-login:hover { background:rgba(168,85,247,.26); border-color:rgba(34,211,238,.6); color:#fff }

/* ⚠ Motion is a preference. The mark still reads perfectly still — the
   reticle simply sits closed instead of snapping shut. */
@media (prefers-reduced-motion: reduce) {
  .sky-mark .dot, .sky-mark .ret, .sky-mark .sweep i,
  .sky-tile .sweep i, .sky-ground .glow-a, .sky-ground .glow-b { animation: none }
}
