/* ============================================================
   Alfcode — Awwwards/Framer polish layer (site-wide)
   Additive on top of alfcode.css: film grain, gold selection,
   marquee ticker, magnetic buttons, hover physics, image zooms.
   Loaded by every page after alfcode.css.
   ============================================================ */

::selection { background: rgba(230, 197, 82, 0.32); color: #fff; }
[data-theme="light"] ::selection { background: rgba(216, 180, 65, 0.4); color: #122142; }

/* ---- film grain, very quiet ---- */
body::after {
  content: ''; position: fixed; inset: 0; pointer-events: none; z-index: 98;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  opacity: 0.045;
  animation: aww-grain 1.2s steps(6) infinite;
}
[data-theme="light"] body::after { opacity: 0.03; }
@keyframes aww-grain {
  0%, 100% { background-position: 0 0; }
  20% { background-position: -34px 26px; }
  40% { background-position: 22px -41px; }
  60% { background-position: -15px -28px; }
  80% { background-position: 31px 17px; }
}

/* ---- magnetic buttons: transform is driven by JS, keep it smooth ---- */
.btn, .st-btn { will-change: transform; }
.btn.is-magnet, .st-btn.is-magnet { transition: transform .18s cubic-bezier(0.22, 1, 0.36, 1); }

/* ---- work-card hover: media zoom + arrow slide (Framer-style physics) ---- */
.work-card .work-media img {
  transition: transform 1s cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform;
}
.work-card:hover .work-media img { transform: scale(1.045); }
.work-card .work-arrow {
  transition: transform .45s cubic-bezier(0.22, 1, 0.36, 1), opacity .3s;
}
.work-card:hover .work-arrow { transform: translate(4px, -4px); }

/* ---- showcase slab hover already tilts; add image life ---- */
.app-slab .mac-screen img, .app-slab .dev-phone img {
  transition: transform 1.1s cubic-bezier(0.16, 1, 0.3, 1);
}
.app-slab:hover .mac-screen img { transform: scale(1.02); }

/* ---- big outlined marquee ticker ---- */
.aww-ticker {
  overflow: hidden;
  padding: clamp(28px, 5vh, 56px) 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  user-select: none;
}
.aww-ticker .row {
  display: flex; width: max-content;
  animation: aww-tick 38s linear infinite;
}
.aww-ticker span {
  font-family: var(--display);
  font-size: clamp(44px, 7vw, 96px);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1;
  white-space: nowrap;
  padding-right: 24px;
  color: transparent;
  -webkit-text-stroke: 1.5px var(--fg-3);
}
.aww-ticker span em {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  color: var(--accent);
  -webkit-text-stroke: 0;
}
.aww-ticker:hover .row { animation-play-state: paused; }
@keyframes aww-tick {
  to { transform: translateX(-50%); }
}

/* ---- gentle parallax targets (JS drives --par) ---- */
[data-par] { transform: translateY(calc(var(--par, 0) * 1px)); will-change: transform; }

@media (prefers-reduced-motion: reduce) {
  body::after { animation: none; }
  .aww-ticker .row { animation: none; }
  .work-card:hover .work-media img, .app-slab:hover .mac-screen img { transform: none; }
}

/* ============================================================
   Two-tone editorial bands (.section-invert)
   A section that flips to the OPPOSITE theme: white bands inside
   the dark site, dark bands inside the light site. All component
   styles ride the same tokens, so everything inside just works.
   ============================================================ */
.section-invert {
  --bg: #f7f6f1;
  --bg-1: #ffffff;
  --bg-2: #f0efe8;
  --bg-3: #e6e4da;
  --fg: #122142;
  --fg-2: #3c4658;
  --fg-3: #545d6b;
  --fg-4: #646b77;
  --line: rgba(18, 33, 66, 0.12);
  --line-2: rgba(18, 33, 66, 0.24);
  --line-3: rgba(18, 33, 66, 0.36);
  --accent: #d8b441;
  --accent-2: #e6c552;
  --accent-ink: #8a6912;
  --accent-deep: #b0892c;
  --cyan: #214c9e;
  --cyan-deep: #173a80;
  --accent-soft: rgba(216, 180, 65, 0.18);
  --cyan-soft: rgba(33, 76, 158, 0.10);
  --glow: rgba(216, 180, 65, 0.30);
  --veil-rgb: 247, 246, 241;
  --scrim: rgba(247, 246, 241, 0.80);
  --scrim-solid: rgba(250, 249, 245, 0.97);
  background: var(--bg);
  color: var(--fg-2);
}
.section-invert .step-label { color: #8a6912; }
[data-theme="light"] .section-invert {
  --bg: #0a0c13;
  --bg-1: #0d1019;
  --bg-2: #121622;
  --bg-3: #191e2c;
  --fg: #f4f6f9;
  --fg-2: #bcc2cc;
  --fg-3: #7b828f;
  --fg-4: #7e8696;
  --line: rgba(255, 255, 255, 0.07);
  --line-2: rgba(255, 255, 255, 0.13);
  --line-3: rgba(255, 255, 255, 0.22);
  --accent: #e6c552;
  --accent-2: #f1d268;
  --accent-ink: #e6c552;
  --accent-deep: #c8a838;
  --cyan: #5b8cf0;
  --cyan-deep: #2f5fc4;
  --accent-soft: rgba(230, 197, 82, 0.14);
  --cyan-soft: rgba(91, 140, 240, 0.13);
  --glow: rgba(230, 197, 82, 0.40);
  --veil-rgb: 5, 5, 5;
  --scrim: rgba(5, 5, 6, 0.72);
  --scrim-solid: rgba(7, 7, 9, 0.96);
  background: var(--bg);
  color: var(--fg-2);
}
[data-theme="light"] .section-invert .step-label { color: var(--accent); }

/* ============================================================
   Vortex finale band (#contact) — a black stage for the particle
   tornado, pinned dark in BOTH themes; content floats above it.
   ============================================================ */
.vortex-band {
  position: relative;
  overflow: hidden;
  background: #05060b;
}
.vortex-band .vortex-stage {
  position: absolute; inset: 0; z-index: 0;
  pointer-events: none;
}
.vortex-band .vortex-stage canvas {
  display: block; width: 100%; height: 100%;
  opacity: 0.82;
}
/* a quiet pool of dark behind the copy so it never fights the waist */
.vortex-band .vortex-stage::after {
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(56% 62% at 50% 42%, rgba(5, 6, 11, 0.82), rgba(5, 6, 11, 0.3) 55%, transparent 76%);
}
.vortex-band > .container { position: relative; z-index: 1; }
.vortex-band h2, .vortex-band .lede, .vortex-band .eyebrow, .vortex-band .contact-meta a {
  text-shadow: 0 2px 22px rgba(0, 0, 0, 0.75), 0 1px 6px rgba(0, 0, 0, 0.6);
}
[data-theme="light"] .vortex-band {
  --bg: #05060b;
  --bg-1: #0d1019;
  --bg-2: #121622;
  --fg: #f4f6f9;
  --fg-2: #bcc2cc;
  --fg-3: #7b828f;
  --line: rgba(255, 255, 255, 0.07);
  --line-2: rgba(255, 255, 255, 0.13);
  --accent: #e6c552;
  --accent-2: #f1d268;
  --accent-ink: #e6c552;
  --accent-deep: #c8a838;
  --accent-soft: rgba(230, 197, 82, 0.14);
  background: #05060b;
  color: var(--fg-2);
}

/* ============================================================
   Mesh footer wordmark — WebGL2 jelly "alfcode" replaces the
   static image when the enhancement boots (.mesh-on).
   ============================================================ */
.footer-wordmark a.mesh-on .footer-wordmark-img { display: none !important; }
.mesh-wordmark {
  position: relative;
  width: 100%; max-width: 560px;
  height: clamp(90px, 16vw, 150px);
  margin: 0 auto;
  cursor: default;
}
.footer-wordmark { transition: opacity .4s ease; }
.footer-wordmark:hover { opacity: 0.8; }
.mesh-wordmark canvas { display: block; width: 100%; height: 100%; }

/* ============================================================
   Hero particle mark — the brand icon as a roaming pixel cloud
   on the hero's right; hover assembles it. Desktop only.
   ============================================================ */
.hero-particle {
  display: none;
  position: absolute;
  right: clamp(0px, 4vw, 90px);
  top: 50%;
  transform: translateY(-52%);
  width: min(30vw, 440px);
  aspect-ratio: 1;
  z-index: 1;
}
.hero-particle canvas { display: block; width: 100%; height: 100%; }
@media (min-width: 1100px) {
  .hero-particle { display: block; }
}
