/* ============================================================
   INTELLICAMP — amplified motion layer
   Loaded after style.css. Deleting this file returns the site
   to the calmer baseline.
   ============================================================ */

/* ---------- 1. Page-load: the logo signals itself in ----------
   Each stroke of the mark arrives lit and pulses as it draws, colour
   blooms outward from the centre, the wordmark resolves out of blur
   behind a blinking caret, then the whole lockup flies to the header
   slot as the panel clears. 3.7s total.

   Timeline — change one, check the rest:
     0.00  frame outline draws                    (0.9s, --dur from JS)
     0.55  glyph strokes draw + glow, 0.2s apart  (0.55s each)
     1.45  plate blooms scale(0.6) -> 1           (0.75s)
     1.70  strokes flip to --ink                  (0.4s)
     2.00  letters resolve out of blur, 0.06s apart
     2.00  caret appears, blinks 3x
     2.80  hairline rule expands                  (0.6s -> ends 3.40)
     3.20  caret retires
     3.45  BOOT_TRAVEL: lockup flies, bar + rule fade
     3.70  panel faded out                                          */

.boot {
  position: fixed;
  inset: 0;
  z-index: 99999;
  background: var(--ink);
  display: grid;
  place-items: center;
  transition: opacity 0.5s ease;
}

.boot.is-out { opacity: 0; pointer-events: none; }

.boot__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.4rem;
}

/* stacked: mark centred above, wordmark spanning the viewport below */
.boot__lockup {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(14px, 2.6vw, 30px);
  transform-origin: 50% 50%;
  transition: transform 0.75s cubic-bezier(0.76, 0, 0.24, 1);
  will-change: transform;
}

.boot__line {
  display: flex;
  align-items: flex-end;
}

/* --- the mark --- */
.boot__mark {
  width: clamp(88px, 13vw, 180px);
  height: clamp(88px, 13vw, 180px);
  flex-shrink: 0;
  overflow: visible;
}

.boot__mark .frame,
.boot__mark .glyph {
  fill: none;
  stroke: var(--accent-ink);
  stroke-linecap: round;
  stroke-linejoin: round;
  /* --len is measured per path in motion.js */
  stroke-dasharray: var(--len, 400);
  stroke-dashoffset: var(--len, 400);
  animation: boot-draw var(--dur, 0.9s) cubic-bezier(0.65, 0, 0.35, 1)
    var(--d, 0s) forwards;
}

.boot__mark .frame { stroke-width: 4; }
.boot__mark .glyph { stroke-width: 5.5; }

@keyframes boot-draw { to { stroke-dashoffset: 0; } }

/* colour blooms outward from the centre once the outline is complete */
.boot__mark .plate {
  fill: var(--accent-ink);
  opacity: 0;
  transform-origin: center;
  transform: scale(0.6);
  animation: boot-fill 0.75s var(--ease) 1.45s forwards;
}

@keyframes boot-fill { to { opacity: 1; transform: scale(1); } }

/* Each stroke arrives lit: the glow rides the same --d delay as the draw,
   so a stroke pulses while it is being written and settles as the next one
   starts. Tied to --accent-rgb so a custom accent glows in its own colour. */
@keyframes boot-glow {
  0%, 100% { filter: drop-shadow(0 0 0 rgba(var(--accent-rgb), 0)); }
  50% { filter: drop-shadow(0 0 10px rgba(var(--accent-rgb), 0.75)); }
}

/* the glyph flips to dark once the plate is behind it */
.boot__mark .glyph {
  animation:
    boot-draw var(--dur, 0.6s) cubic-bezier(0.65, 0, 0.35, 1) var(--d, 0s) forwards,
    boot-glow 1.1s ease-in-out var(--d, 0s),
    boot-glyph-dark 0.4s ease 1.7s forwards;
}

@keyframes boot-glyph-dark { to { stroke: var(--ink); } }

/* --- the wordmark types in --- */
.boot__word {
  display: flex;
  font-family: var(--font-display);
  /* font-size is measured and set in motion.js so the word spans ~80vw */
  font-size: 6rem;
  font-weight: 700;
  letter-spacing: -0.05em;
  color: var(--paper);
  line-height: 0.95;
  white-space: nowrap;
}

/* letters resolve out of blur rather than sliding up */
.boot__word i {
  font-style: normal;
  opacity: 0;
  filter: blur(9px);
  transform: translateY(4px);
  animation: boot-char 0.5s var(--ease) forwards;
  animation-delay: calc(2s + var(--i) * 0.06s);
}

.boot__word i.dot { color: var(--accent-ink); }

@keyframes boot-char { to { opacity: 1; filter: blur(0); transform: none; } }

/* blinking caret that retires once typing finishes */
.boot__caret {
  width: 2px;
  align-self: stretch;
  margin-left: 4px;
  background: var(--accent);
  opacity: 0;
  /* Kept from the original build sequence. Retimed to the blur reveal:
     appears as the first letter resolves (2s), blinks three times, and
     retires as the last one lands (3.2s). caret-off is listed last so it
     wins over the blink where the two overlap. */
  animation:
    boot-caret-on 0.1s linear 2s forwards,
    boot-blink 0.7s steps(1) 2s 3,
    boot-caret-off 0.2s linear 3.2s forwards;
}

@keyframes boot-caret-on { to { opacity: 1; } }
@keyframes boot-caret-off { to { opacity: 0; } }
@keyframes boot-blink { 50% { opacity: 0; } }

/* --- hairline rule under the lockup --- */
.boot__rule {
  height: 1px;
  width: 80vw;
  background: var(--line);
  transform: scaleX(0);
  transform-origin: 50% 50%;
  animation: boot-rule 0.6s var(--ease) 2.8s forwards;
  transition: opacity 0.3s ease;
}

@keyframes boot-rule { to { transform: scaleX(1); } }

.boot.is-leaving .boot__rule,
.boot.is-leaving .boot__bar { opacity: 0; }

/* --- progress bar --- */
.boot__bar {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 3px;
  width: 100%;
  background: linear-gradient(90deg, var(--accent), var(--sky), var(--violet));
  transform: scaleX(0);
  transform-origin: 0 50%;
  /* runs the full length of the loader — keep in step with BOOT_TRAVEL */
  animation: boot-bar 3.45s cubic-bezier(0.4, 0, 0.2, 1) forwards;
  transition: opacity 0.3s ease;
}

@keyframes boot-bar { to { transform: scaleX(1); } }

/* Hold the page still while the loader is up */
body.is-loading { overflow: hidden; }

/* Cursor now lives in theme.css / theme.js so it can support
   selectable shapes and stackable effects. */

/* ---------- 3. Stronger reveals ---------- */
[data-reveal] {
  transform: translateY(70px);
  transition: opacity 0.9s var(--ease), transform 1.05s var(--ease),
    filter 0.55s ease;
  filter: blur(3px);
}

/* Clear the blur early so text never renders ghosted mid-transition */
[data-reveal].is-in { filter: none; }
[data-reveal="left"] { transform: translateX(-90px); }
[data-reveal="right"] { transform: translateX(90px); }
[data-reveal="scale"] { transform: scale(0.86) translateY(50px); }

/* Heading clip-wipe */
[data-wipe] {
  clip-path: inset(0 100% 0 0);
  transition: clip-path 1.1s cubic-bezier(0.76, 0, 0.24, 1);
}

[data-wipe].is-in { clip-path: inset(0 0 0 0); }

/* Char-by-char section headings */
.char {
  display: inline-block;
  transform: translateY(100%) rotate(8deg);
  opacity: 0;
  transition: transform 0.75s var(--ease), opacity 0.6s ease;
  transition-delay: calc(var(--c) * 0.022s);
}

.char-wrap.is-in .char { transform: none; opacity: 1; }
.char-line { display: inline-block; overflow: hidden; vertical-align: bottom; }

/* Each word is its own nowrap box so a per-character split cannot break a
   heading mid-word. Overflow clips the characters as they rise, the same
   masking .char-line gives the line. */
.char-word {
  display: inline-block;
  white-space: nowrap;
  overflow: hidden;
  vertical-align: bottom;
  /* room for descenders, which the clip would otherwise cut */
  padding-bottom: 0.12em;
}

/* ---------- 4. Scroll-velocity skew ---------- */
[data-skew] {
  transform: skewY(var(--skew, 0deg));
  transition: transform 0.35s var(--ease);
  will-change: transform;
}

/* ---------- 5. Magnetic buttons ---------- */
/* the magnetic pull no longer touches .btn, so neither the paint hint nor the
   transform transition belongs on it */
.socials a, .totop {
  will-change: transform;
}

/* ---------- 6. Card 3D tilt ---------- */
.grid, .quotes { perspective: 1400px; }

.card, .quote {
  transform-style: preserve-3d;
  will-change: transform;
}

.card.is-tilting, .quote.is-tilting {
  transition: transform 0.12s ease-out, border-color 0.4s ease;
}

/* ---------- 7. Work tiles: heavier motion ---------- */
.work__item .work__canvas { transition: transform 1.2s var(--ease); }
.work__item:hover .work__canvas { transform: scale(1.14) rotate(1.5deg); }

.work__item h3 {
  transition: transform 0.55s var(--ease);
}

.work__item:hover h3 { transform: translateY(-6px); }

.work__item .work__result {
  transition: transform 0.55s var(--ease) 0.05s, opacity 0.4s ease;
}

.work__item:hover .work__result { transform: translateY(-4px); }

/* ---------- 8. Marquee: faster + hover skew ---------- */
.marquee { --speed: 22s; }
.marquee--headline { --speed: 30s; }

.marquee__item {
  transition: color 0.3s ease, transform 0.45s var(--ease);
}

.marquee__item:hover { transform: scale(1.14) rotate(-2deg); }

/* ---------- 8b. Colorful client marquee ---------- */
.marquee--logos {
  position: relative;
  --speed: 30s;
}

/* faint colour bleed behind the strip */
.marquee--logos::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  opacity: 0.5;
  background: linear-gradient(
    90deg,
    rgba(var(--accent-rgb), 0.07),
    rgba(110, 231, 240, 0.07) 25%,
    rgba(var(--violet-rgb), 0.08) 50%,
    rgba(255, 122, 89, 0.07) 75%,
    rgba(255, 209, 102, 0.07)
  );
}

.marquee--logos .marquee__track { position: relative; z-index: 1; }

.marquee--logos .marquee__item {
  --c: var(--accent);
  --lit: 0;
  position: relative;
  color: #4a515c;
  isolation: isolate;
  transform: scale(calc(1 + var(--lit) * 0.07)) translateY(calc(var(--lit) * -3px));
  transition: transform 0.45s var(--ease), filter 0.45s ease, color 0.4s ease;
}

/* the coloured twin, revealed bottom-up by --lit */
.marquee--logos .marquee__item::after {
  content: attr(data-text);
  position: absolute;
  left: 0;
  top: 0;
  white-space: nowrap;
  color: var(--c);
  pointer-events: none;
  clip-path: inset(calc((1 - var(--lit)) * 100%) 0 0 0);
  transition: clip-path 0.5s var(--ease);
}

/* soft halo that only appears when lit */
.marquee--logos .marquee__item::before {
  content: "";
  position: absolute;
  inset: -30% -12%;
  z-index: -1;
  border-radius: 999px;
  background: radial-gradient(60% 70% at 50% 50%, var(--c), transparent 70%);
  opacity: calc(var(--lit) * 0.22);
  filter: blur(22px);
  transition: opacity 0.45s ease;
  pointer-events: none;
}

/* hover overrides the travelling spotlight entirely */
.marquee--logos .marquee__item:hover {
  --lit: 1 !important;
  transform: scale(1.12) translateY(-5px) rotate(-1.8deg);
  filter: drop-shadow(0 8px 20px rgba(0, 0, 0, 0.5));
}

.marquee--logos .marquee__item:hover::after {
  clip-path: inset(0 0 0 0);
}

/* underline that draws in on hover */
.marquee--logos .marquee__item:hover::before {
  opacity: 0.35;
}

/* ---------- 9. Floating ambient orbs ---------- */
@keyframes float-a {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(60px, -50px) scale(1.15); }
}

@keyframes float-b {
  0%, 100% { transform: translate(0, 0) scale(1.1); }
  50% { transform: translate(-70px, 45px) scale(0.9); }
}

.orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(70px);
  pointer-events: none;
  opacity: 0.5;
}

.orb--1 {
  width: 380px; height: 380px;
  background: rgba(var(--p1-rgb), 0.3);
  top: -60px; left: -80px;
  animation: float-a 16s ease-in-out infinite;
}

.orb--2 {
  width: 460px; height: 460px;
  background: rgba(var(--p6-rgb), 0.3);
  top: 40px; right: -120px;
  animation: float-b 20s ease-in-out infinite;
}

/* ---------- 10. Section number counters on scroll ---------- */
.stat strong { transition: transform 0.6s var(--ease); }
.stat:hover strong { transform: scale(1.06); }

/* ---------- 11. Link underline sweep on nav ---------- */
.nav__link::after {
  content: "";
  position: absolute;
  left: 0.8rem;
  right: 0.8rem;
  bottom: 0.35rem;
  height: 1.5px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: 100% 50%;
  transition: transform 0.45s var(--ease);
}

.nav__link { position: relative; }
.nav__link:hover::after { transform: scaleX(1); transform-origin: 0 50%; }

@media (max-width: 1023px) {
  .nav__link::after { display: none; }
}

/* ---------- 12. Respect reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .boot { display: none; }
  .cur, .cur__dot { display: none; }
  .orb { animation: none; }
  .char { transform: none; opacity: 1; }
  [data-wipe] { clip-path: none; }
  [data-reveal] { filter: none; transform: none; }
  .person__role { clip-path: none; }
  .person__ring circle { stroke-dashoffset: 0; }
}
