/**
 * Otto Björkland Portfolio Engine v3 — Base & Scenery Architecture
 * Normalize, typography, background scenery, canvas, bokeh orbs, hero stage
 */

*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  -webkit-tap-highlight-color: transparent !important;
}

html, body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: fixed;
  background-color: var(--bg-arctic);
  color: var(--text-main);
  font-family: var(--font-sans, 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  user-select: none;
  -webkit-user-select: none;
}

/* ---------------------------------------------------- */
/* BACKGROUND ATMOSPHERE: ORGANIC FROST & BOKEH         */
/* ---------------------------------------------------- */
.ambient-scenery {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background: radial-gradient(
    circle at 50% 20%,
    rgba(220, 238, 255, 0.6) 0%,
    rgba(242, 245, 249, 0.8) 50%,
    #f2f5f9 100%
  );
  transition: opacity 0.8s ease;
}

body.scrolled .ambient-scenery {
  opacity: 0.85;
}

/* Background Frost Canvas: Stays crisp & clearly visible in both hero and jukebox view */
#bg-frost-canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 1;
  opacity: 0;
  transition: opacity 1.6s ease;
}

#bg-frost-canvas.is-formed {
  opacity: 0.72;
}

/* Background depth of field: in the conveyor the sharp frost cross-fades to
   its defocused twin and the bokeh grows softer, over the same 0.9 s. */
#bg-frost-soft {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 1;
  opacity: 0;
  transition: opacity 0.9s ease;
}

body.scrolled #bg-frost-soft.is-formed {
  opacity: 0.8;
}

body.scrolled #bg-frost-canvas.is-formed {
  opacity: 0;
  transition-duration: 0.9s;
}

.ambient-scenery {
  transform: scale(1);
  transition: opacity 0.9s ease, transform 0.9s cubic-bezier(0.4, 0, 0.2, 1);
}

body.scrolled .ambient-scenery {
  transform: scale(1.12);
}

body.scrolled .bokeh-orb {
  opacity: 0.7;
}

.bokeh-orb {
  transition: opacity 0.9s ease;
  mix-blend-mode: normal;
}

/* Bokeh Particle Light Flares: Slow, Gentle Organic Floating & Breathing Scale */
.bokeh-orb {
  position: absolute;
  border-radius: 50%;
  /* Softness is baked into the gradient; a blur filter here re-rendered every
     frame of the drift animation. */
  background: radial-gradient(
    circle closest-side,
    rgba(255, 146, 52, 0.36) 0%,
    rgba(255, 162, 76, 0.24) 30%,
    rgba(255, 186, 116, 0.10) 62%,
    rgba(255, 200, 140, 0) 100%
  );
  pointer-events: none;
  z-index: 2;
  will-change: transform;
}

/* Fallback spots if scripting is off; normally an inline script in
   index.html scatters the orbs randomly (spread out) on every visit. */
.bokeh-orb-1 { top: 10%; left: 7%; }
.bokeh-orb-3 { top: 8%; right: 9%; }
.bokeh-orb-4 { top: 70%; left: 4%; }
.bokeh-orb-2 { top: 74%; right: 7%; }

.bokeh-orb-1 {
  animation: orb-drift-1 18s infinite ease-in-out alternate;
}

.bokeh-orb-2 {
  animation: orb-drift-2 24s infinite ease-in-out alternate;
}

.bokeh-orb-3 {
  animation: orb-drift-3 20s infinite ease-in-out alternate;
}

.bokeh-orb-4 {
  animation: orb-drift-4 22s infinite ease-in-out alternate;
}

@keyframes orb-drift-1 {
  0%   { transform: translate3d(0, 0, 0) scale(0.88); }
  35%  { transform: translate3d(45px, -30px, 0) scale(1.15); }
  70%  { transform: translate3d(15px, 25px, 0) scale(0.94); }
  100% { transform: translate3d(-35px, -15px, 0) scale(1.22); }
}

@keyframes orb-drift-2 {
  0%   { transform: translate3d(0, 0, 0) scale(1.1); }
  40%  { transform: translate3d(-50px, 35px, 0) scale(0.85); }
  75%  { transform: translate3d(30px, -45px, 0) scale(1.2); }
  100% { transform: translate3d(-20px, 20px, 0) scale(0.98); }
}

@keyframes orb-drift-3 {
  0%   { transform: translate3d(0, 0, 0) scale(0.92); }
  50%  { transform: translate3d(-40px, -35px, 0) scale(1.24); }
  100% { transform: translate3d(35px, 30px, 0) scale(0.86); }
}

@keyframes orb-drift-4 {
  0%   { transform: translate3d(0, 0, 0) scale(1.05); }
  45%  { transform: translate3d(30px, 40px, 0) scale(0.82); }
  85%  { transform: translate3d(-25px, -20px, 0) scale(1.18); }
  100% { transform: translate3d(10px, 15px, 0) scale(0.95); }
}

/* Warm Spotlight Cursor (Accurately Centered) */
.cursor-spotlight {
  position: fixed;
  top: 0;
  left: 0;
  width: 320px;
  height: 320px;
  border-radius: 50%;
  pointer-events: none;
  z-index: 25;
  background: radial-gradient(
    circle closest-side,
    rgba(255, 128, 40, 0.14) 0%,
    rgba(255, 160, 80, 0.07) 40%,
    rgba(255, 200, 150, 0.02) 70%,
    rgba(255, 220, 180, 0) 100%
  );
  transform: translate3d(-500px, -500px, 0);
  will-change: transform;
  transition: opacity 0.3s ease;
}

@media (hover: none), (pointer: coarse) {
  .cursor-spotlight { display: none; }
}

/* ---------------------------------------------------- */
/* PHASE 0: HERO VIEW ("Otto Björkland" Largest Scale)  */
/* ---------------------------------------------------- */
.hero-stage {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  z-index: 5;
  pointer-events: none;
  padding: 0 24px;
  will-change: transform, opacity;
  transition: opacity 0.25s ease-out;
}

/* Opened from a project link: the hero must never appear (see index.html). */
body.deep-link-boot .hero-stage {
  display: none !important;
}

body.scrolled .hero-stage,
body.card-inspected .hero-stage,
body.modal-open .hero-stage {
  opacity: 0 !important;
  visibility: hidden !important;
  pointer-events: none !important;
  transform: translate3d(0, -35px, 0) scale(0.96) !important;
}

.hero-title-giant {
  font-size: clamp(3.8rem, 10.5vw, 9.5rem);
  font-weight: 900;
  letter-spacing: -0.045em;
  line-height: 0.92;
  color: #0b1320;
  text-shadow: 0 10px 40px rgba(11, 19, 32, 0.06);
  margin-bottom: 24px;
  pointer-events: auto;
  cursor: default;
  position: relative;
  display: inline-block;
  transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1), text-shadow 0.4s ease, letter-spacing 0.4s ease;
}

.hero-title-giant:hover {
  transform: translateY(-3px) scale(1.012);
  letter-spacing: -0.040em;
  text-shadow:
    0 16px 50px rgba(11, 19, 32, 0.12),
    0 0 45px rgba(255, 77, 21, 0.18);
  color: #050a12;
}

.hero-subtitle-block {
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
  margin-top: 24px;
  margin-bottom: 44px;
}

.hero-tag {
  font-family: 'JetBrains Mono', monospace;
  font-size: clamp(10px, 1.3vw, 14.5px);
  font-weight: 700;
  letter-spacing: 0.06em;
  color: #334155;
  text-transform: uppercase;
  padding: 10px 28px;
  border-radius: 999px;
  position: relative;
  overflow: hidden;
  display: inline-block;
  white-space: nowrap;

  /* Unified frost material */
  background: var(--glass-fill);
  backdrop-filter: var(--glass-backdrop);
  -webkit-backdrop-filter: var(--glass-backdrop);
  border: var(--glass-border);
  box-shadow: var(--glass-shadow-sm), var(--glass-rim);
}

.hero-tag .hero-tag-text {
  position: relative;
  z-index: 2;
}

.hero-scroll-prompt {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #94a3b8;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.prompt-desktop {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  animation: bounce-cue 2.4s infinite ease-in-out;
}

.prompt-mobile {
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  animation: bounce-cue 2.4s infinite ease-in-out;
}

.scroll-mouse-icon {
  width: 22px;
  height: 34px;
  border-radius: 12px;
  border: 2px solid #94a3b8;
  position: relative;
}

.scroll-mouse-icon::after {
  content: "";
  position: absolute;
  top: 6px;
  left: 50%;
  transform: translateX(-50%);
  width: 3px;
  height: 7px;
  background: #ff4d15;
  border-radius: 2px;
  animation: wheel-nudge 1.6s infinite ease-in-out;
}

.swipe-hand-icon {
  position: relative;
  color: #ff4d15;
  animation: swipe-gesture 2.2s infinite ease-in-out;
}

@keyframes swipe-gesture {
  0% { transform: translateY(6px); opacity: 0.7; }
  50% { transform: translateY(-8px); opacity: 1; }
  100% { transform: translateY(6px); opacity: 0.7; }
}

@keyframes wheel-nudge {
  0% { transform: translate(-50%, 0); opacity: 1; }
  100% { transform: translate(-50%, 8px); opacity: 0; }
}

@keyframes bounce-cue {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(8px); }
}

/* Hero Privacy Note: Italic, subtle note at bottom of hero stage */
.hero-privacy-note {
  position: absolute;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  width: 90%;
  max-width: 600px;
  text-align: center;
  margin: 0;
  font-style: italic;
  font-size: 12px;
  line-height: 1.4;
  color: #64748b;
  letter-spacing: 0.01em;
  pointer-events: none;
  opacity: 0.85;
}

/* Mobile Adjustments for Hero Stage */
@media (max-width: 768px) {
  .hero-title-giant {
    font-size: 3.2rem;
  }

  .hero-tag {
    padding: 7px 16px;
    font-size: 9.5px;
    letter-spacing: 0.04em;
  }

  .prompt-desktop {
    display: none;
  }

  .prompt-mobile {
    display: flex;
  }

  .hero-privacy-note {
    bottom: 16px;
    font-size: 10.5px;
    line-height: 1.35;
    width: 88%;
  }
}

/* The title's line break is decided by screen width, never by which font has
   loaded: the fallback font is narrower, so a font-dependent wrap made the
   title jump from one row to two as Plus Jakarta Sans arrived. */
@media (max-width: 520px) {
  .hero-title-giant .hero-word {
    display: block;
  }
}

@media (min-width: 521px) {
  .hero-title-giant {
    white-space: nowrap;
  }
}

/* Showcase: the background is the deepest layer, so it must never be sharper
   than the panels in front of it. The panels start fully defocused, so the
   background defocuses almost immediately (0.35 s instead of 0.9 s). */
body.stage-intro #bg-frost-soft.is-formed,
body.stage-intro #bg-frost-canvas.is-formed,
body.stage-intro .ambient-scenery,
body.stage-intro .bokeh-orb {
  transition-duration: 0.2s;
}

/* The hero cue follows the INPUT, not the width: touch devices (phones AND
   tablets, incl. iPads) get the swipe hand, mouse devices the scroll mouse. */
html.is-touch .prompt-desktop { display: none; }
html.is-touch .prompt-mobile { display: flex; }
html:not(.is-touch) .prompt-desktop { display: flex; }
html:not(.is-touch) .prompt-mobile { display: none; }

/* Big screens (index.html head script sets html.ui-scaled + --ui-scale):
   the page is laid out at <= 2048x1280-like size and scaled up to fill the
   screen, so 2K/4K look like the 2048x1280 design instead of tiny. Every
   viewport-unit size in the CSS is capped by a px value that it always
   reaches at these sizes, so they need no conversion. */
html.ui-scaled body {
  width: calc(100% / var(--ui-scale));
  height: calc(100% / var(--ui-scale));
  transform: scale(var(--ui-scale));
  transform-origin: 0 0;
}
