@font-face {
  font-family: 'Rubik';
  src: url('/assets/Fonts/Rubik/Rubik-VariableFont_wght.ttf') format('truetype-variations');
  font-weight: 300 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Rubik';
  src: url('/assets/Fonts/Rubik/Rubik-Italic-VariableFont_wght.ttf') format('truetype-variations');
  font-weight: 300 900;
  font-style: italic;
  font-display: swap;
}

:root {
  --brand-blue: #005DAC;
  --brand-blue-light: #0072D1;
  --brand-blue-dark: #00365E;
  --brand-orange: #FF5500;
  --brand-orange-dark: #CC4400;
  --brand-amber: #FFA300;
  --brand-white: #FFFFFF;
  --brand-gray-dark: #575756;
  --brand-gray-light: #DADADA;
  --brand-gradient: linear-gradient(160deg, var(--brand-blue-light) 0%, var(--brand-blue) 45%, var(--brand-blue-dark) 100%);
  --brand-gradient-warm: radial-gradient(circle at 88% 10%, rgba(255, 163, 0, 0.35) 0%, rgba(255, 163, 0, 0) 42%);
  --accent-gradient: linear-gradient(135deg, var(--brand-orange) 0%, var(--brand-amber) 100%);
  --pattern-dots: radial-gradient(rgba(0, 93, 172, 0.14) 1.5px, transparent 1.5px);
  --font-family-brand: 'Rubik', 'Arial', sans-serif;
}

html, body {
  margin: 0;
  padding: 0;
  overflow: hidden;
  width: 100%;
  height: 100%;
  background: #000;
  font-family: var(--font-family-brand);
}

/* Plain <video> now (no 8th Wall FullWindowCanvas pipeline module sizing it for us) - object-fit
   cover fills the screen the same way that did. */
#camerafeed {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #000; /* shows briefly before the stream's first frame paints */
}
/* Most devices mirror the front camera by default - flips it back for the live view. The
   capture compositor (ar.js) does its own equivalent flip when drawing frames, so saved/shared
   photos come out un-mirrored too, not just what's on screen. */
#camerafeed.mirrored {
  transform: scaleX(-1);
}

/* checko's sequence + timed popups/reaction bubbles - fixed and centred over the camera feed
   (not placed in 3D world space). See checkoOverlay.js. */
#checko-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 5;
  pointer-events: none; /* purely decorative now (no pinch-to-scale) - never intercepts taps */
}
#checko-overlay.hidden {
  /* display:none (not opacity) so it's also skipped by the capture compositor's drawImage - not
     that it draws checko today, but keeps the same convention as #ar-logo.hidden etc. */
  display: none;
}
#checko-canvas {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: var(--checko-size);
  aspect-ratio: 1 / 1;
}

#ar-logo {
  position: fixed;
  /* Some margin in from the very top/right edges, not flush against them - keeps it comfortably
     inside the capture crop in back-camera mode too, not just repositioned inside the frame
     border like it is once selfie mode starts. */
  top: max(32px, calc(env(safe-area-inset-top) + 16px));
  right: max(12px, calc(env(safe-area-inset-right) + 8px));
  /* clamp(), not a fixed 60px - logo.png's aspect ratio (~2.4:1) turns a fixed height into a
     fixed width too, which on narrow phones pushed past the left logo (or off the screen edge
     entirely) since neither logo's box shrank with the viewport. Scales down below ~430px wide. */
  height: clamp(38px, 14vw, 60px);
  width: auto;
  pointer-events: none;
  z-index: 20;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.4));
}
#ar-logo.hidden {
  /* display:none (not opacity) so getBoundingClientRect() collapses to zero size - the capture
     compositor (ar.js) skips drawing the logo whenever that happens, so this removes it from
     both the live selfie view AND anything captured while in selfie mode, not just the former. */
  display: none;
}

#ar-logo-2 {
  position: fixed;
  top: max(32px, calc(env(safe-area-inset-top) + 16px));
  left: max(12px, calc(env(safe-area-inset-left) + 8px));
  height: clamp(38px, 14vw, 60px);
  width: auto;
  pointer-events: none;
  z-index: 20;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.4));
}
#ar-logo-2.hidden {
  display: none; /* see #ar-logo.hidden - same reasoning, applies to the capture compositor too */
}

#selfie-frame-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  /* contain, not cover: keeps the whole decorative border visible instead of cropping its
     left/right edges off on phone aspect ratios narrower than the artwork's. */
  object-fit: contain;
  pointer-events: none;
  z-index: 15;
  transition: opacity 0.3s ease;
}
#selfie-frame-overlay.hidden {
  opacity: 0;
}

/* frame.png is fully transparent outside its border stroke, so object-fit:contain's letterbox
   gaps (top/bottom, on phone aspect ratios narrower than the artwork's) would otherwise just
   show raw camera feed. These sit behind the frame image and fill exactly those gaps - their
   height/position is computed in ar.js (updateSelfieBars) to match the actual contain math. */
.selfie-frame-bar {
  position: fixed;
  left: 0;
  width: 100%;
  background: #000;
  pointer-events: none;
  z-index: 14;
  transition: opacity 0.3s ease;
}
.selfie-frame-bar.hidden {
  opacity: 0;
}

/* --- START SCREEN ---
   Plain brand-gradient background - logos, the checko glow+intro sequence, tagline and footer
   are all separate live elements below, positioned independently instead of baked into one
   background image. */
#start-screen {
  position: fixed; top: 0; left: 0; width: 100%; height: 100%;
  background: var(--brand-gradient);
  /* justify-content:flex-start (not flex-end) - #start-screen-content below now bottom-anchors
     itself via margin-top:auto instead, which derives its position from #start-tagline's actual
     rendered height rather than two independent fixed guesses that could coincidentally collide
     on some device regardless of how generous either number was. */
  display: flex; flex-direction: column; justify-content: flex-start; align-items: center; z-index: 2000;
  /* #start-footer-text now flows right after #start-screen-content (see its own comment) rather
     than being independently bottom-anchored, so this only needs to clear the true screen edge
     (plus any home-indicator/gesture-bar inset), not the button. */
  padding: 24px; padding-bottom: max(24px, calc(env(safe-area-inset-bottom) + 12px));
  box-sizing: border-box;
  /* Safety net, not the primary fix (#start-character-wrap sizing to available height is) - if
     content ever still doesn't fit on some extreme screen, it scrolls instead of silently
     clipping the footer off past the bottom edge. */
  overflow-y: auto;
}

/* Logos - same placement as the in-experience ones (#ar-logo/#ar-logo-2: same top offset, same
   60px height, opposite corners). */
#start-logo {
  position: absolute;
  top: max(32px, calc(env(safe-area-inset-top) + 16px));
  right: max(12px, calc(env(safe-area-inset-right) + 8px));
  height: clamp(38px, 14vw, 60px);
  width: auto;
  pointer-events: none;
  z-index: 3;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.4));
}
#start-logo-2 {
  position: absolute;
  top: max(32px, calc(env(safe-area-inset-top) + 16px));
  left: max(12px, calc(env(safe-area-inset-left) + 8px));
  height: clamp(38px, 14vw, 60px);
  width: auto;
  pointer-events: none;
  z-index: 3;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.4));
}

/* Normal-flow wrapper (not absolute) reserving the character's on-screen space - sized by
   min(320px, 78vw, 42vh), so on a SHORT screen it shrinks with available height instead of a
   fixed vh offset elsewhere pushing later content (tagline/button/footer) past the bottom edge.
   char-bg/start-sequence/loader are all absolutely positioned WITHIN this wrapper so they
   overlap each other (glow behind character, same spot), while the wrapper itself just takes
   its place in the normal flow like any other item. */
#start-character-wrap {
  position: relative;
  width: min(320px, 78vw, 42vh);
  aspect-ratio: 1 / 1;
  flex-shrink: 0;
  margin-top: 21vh;
}
/* Glow + particle backdrop, centred behind the checko intro sequence, bigger than it so it
   radiates outward. */
#char-bg {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 115%;
  pointer-events: none;
  z-index: -1;
}
/* A <canvas> (drawImage'd into from ar.js), not an <img> whose src gets swapped - the main
   placement sequence already proved that approach out (see sequenceTexture.js): a canvas blit
   is pure pixel-copy with no image-decode/layout/reflow pipeline behind it, unlike reassigning
   an <img>'s src ~18x/sec, which was the actual source of an earlier lag issue here. */
#start-sequence {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  z-index: 0;
  will-change: contents;
}
/* Shown in the same spot while the frames are still preloading - see initStartSequence() in
   ar.js, which hides this the moment they're all ready. The launch button itself stays
   interactive the whole time; this only covers the animation's own slot. */
#start-sequence-loader {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  z-index: 0;
}
#start-sequence-loader.hidden {
  display: none;
}

#start-tagline {
  width: 90%;
  margin: 3vh auto 0;
  flex-shrink: 0;
  color: var(--brand-white);
  text-align: center;
  font-size: clamp(1.1em, 4.2vw, 1.6em);
  font-weight: 450;
  line-height: 1.35;
  position: relative;
  z-index: 2;
}

/* Normal flow now (not absolute), right after #start-screen-content - guarantees it can never
   overlap the button regardless of device/font-size quirks, since flow elements never overlap
   by definition (unlike two independently bottom-anchored elements, which could still coincide
   under the right combination of screen height and system font size even with a fixed pixel
   floor). align-self:flex-start keeps it pinned to the left edge despite #start-screen's own
   align-items:center. */
#start-footer-text {
  align-self: flex-start;
  margin: 12px 0 0 24px;
  color: var(--brand-white);
  font-weight: 450;
  font-size: 1em;
  z-index: 3;
}
#start-screen-content {
  position: relative; z-index: 1;
  width: 100%; max-width: 420px;
  color: var(--brand-white);
  display: flex; flex-direction: column;
  justify-content: center; align-items: center; text-align: center;
  box-sizing: border-box;
  /* Pushed to the bottom of #start-screen by filling all space above it, however tall
     #start-tagline actually rendered - see #start-screen's justify-content comment. */
  margin-top: auto;
  flex-shrink: 0;
  /* Reserves the launch button's own height so the loading dots (much shorter) centre in the
     same spot instead of sitting lower once #start-screen-interactive swaps out for #loading -
     both anchor to this box's vertical centre rather than shifting the whole block's height. */
  min-height: calc(min(260px, 68vw) * 149 / 509);
}
.brand-heading {
  font-size: clamp(1.6em, 5.5vw, 2.4em); margin: 0 0 4vh; font-weight: 700;
  line-height: 1.3; color: var(--brand-blue);
}

.brand-button-3d {
  padding: 16px 36px; font-size: clamp(1em, 4.5vw, 1.15em); font-weight: 600;
  color: var(--brand-white); background: var(--accent-gradient);
  border: none; border-radius: 12px; cursor: pointer;
  box-shadow: 0 4px 14px rgba(255, 85, 0, 0.4);
  transition: filter 0.15s ease-out, transform 0.15s ease-out, box-shadow 0.15s ease-out;
}
.brand-button-3d:hover {
  filter: brightness(0.94);
  box-shadow: 0 6px 18px rgba(255, 85, 0, 0.45);
}
.brand-button-3d:active {
  transform: scale(0.97);
  box-shadow: 0 2px 8px rgba(255, 85, 0, 0.35);
}
.brand-button-3d:disabled {
  opacity: 0.6;
  cursor: default;
}

/* Launch AR button: pre-designed pill graphic (text/icon baked in) rather than a CSS button -
   background-image, no text content. Aspect ratio matches the cropped source art (509x149). */
.launch-ar-button {
  width: min(260px, 68vw);
  aspect-ratio: 509 / 149;
  background-color: transparent;
  background-image: url(/assets/launch-button.png);
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  border: none;
  cursor: pointer;
  padding: 0;
  transition: filter 0.15s ease-out;
  animation: pulseButton 1.8s ease-in-out infinite;
}
.launch-ar-button:hover { filter: brightness(0.96); }
.launch-ar-button:active { transform: scale(0.97); animation-play-state: paused; }
.launch-ar-button:disabled { opacity: 0.6; cursor: default; animation: none; }
@keyframes pulseButton {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.06); }
}

.preload-progress {
  margin: 12px 0 0;
  font-size: 0.9em;
  color: var(--brand-white);
}

/* --- DOT LOADER --- */
.custom-loader-container {
  display: flex; justify-content: center; align-items: center;
  width: 100%; min-height: 120px;
}
/* On the start screen specifically, the loader (dots + progress text) needs to stay shorter than
   the launch button's own height - #start-screen-content's min-height reserves exactly that much
   space so both states share one vertical centre, but only works if the loader's own content
   doesn't demand more than that reservation (the shared 120px above was taller than the button,
   which pushed the whole block - and the dots with it - up past where the button sits). */
#loading.custom-loader-container {
  min-height: 50px;
}
.dot {
  width: 14px; height: 14px;
  margin: 0 6px;
  border-radius: 50%;
  animation: bounceDot 1.4s infinite ease-in-out both;
}
#start-screen .dot:nth-child(odd),
#loading-global .dot:nth-child(odd) {
  background: var(--accent-gradient);
}
#start-screen .dot:nth-child(even),
#loading-global .dot:nth-child(even) {
  background: linear-gradient(135deg, var(--brand-blue-light), var(--brand-blue));
}
.custom-loader-container.global {
  position: fixed; top: 0; left: 0; width: 100%; height: 100%;
  background-color: rgba(0, 0, 0, 0.65); z-index: 3000;
}
.dot:nth-child(1) { animation-delay: -0.32s; }
.dot:nth-child(2) { animation-delay: -0.16s; }
.dot:nth-child(3) { animation-delay: 0s; }
.dot:nth-child(4) { animation-delay: 0.16s; }
@keyframes bounceDot {
  0%, 80%, 100% { transform: scale(0.7); opacity: 0.6; }
  40% { transform: scale(1.0); opacity: 1; }
}

@media (max-width: 767px) {
  /* padding-bottom deliberately left out here - the shorthand above used to reset it back to
     16px on every phone-width screen (i.e. basically all real devices), silently overriding the
     40vh set on #start-screen itself regardless of what that value was changed to. */
  #start-screen { padding: 16px; padding-bottom: max(24px, calc(env(safe-area-inset-bottom) + 12px)); }
  #start-screen-content { border-radius: 16px; padding: 24px; }
}

/* --- AR OVERLAY UI --- */
.selfie-prompt {
  position: fixed;
  left: 50%;
  bottom: 100px;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 16px 20px;
  border-radius: 16px;
  background: rgba(0, 0, 0, 0.65);
  color: #fff;
  font-size: 14px;
  text-align: center;
  max-width: 80vw;
  transition: opacity 0.3s ease;
  z-index: 25;
}
.selfie-prompt p {
  margin: 0;
}
.selfie-prompt.hidden {
  opacity: 0;
  pointer-events: none;
}

/* --- CAPTURE BUTTON ---
   Photo only (no video/recording state), and only ever shown in front-camera/selfie mode -
   see #controls.hidden, toggled off by swapToFrontCamera(). Pre-designed pill graphic, same
   pattern as .launch-ar-button: background-image, no text/icon content of its own. */
#controls {
  position: fixed; bottom: 5%; width: 100%;
  display: flex; justify-content: center; align-items: center; z-index: 999;
  transition: opacity 0.3s ease;
}
#controls.hidden { opacity: 0; pointer-events: none; }
.take-selfie-button {
  width: min(280px, 74vw);
  aspect-ratio: 512 / 167;
  background-color: transparent;
  background-image: url(/assets/take-selfie-button.png);
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  border: none;
  cursor: pointer;
  padding: 0;
  transition: transform 0.15s ease-out, filter 0.15s ease-out;
}
.take-selfie-button:hover { filter: brightness(0.96); }
.take-selfie-button:active { transform: scale(0.97); }

/* --- PREVIEW POPUPS --- */
.preview-container {
  position: fixed; top: 0; left: 0; width: 100%; height: 100%;
  z-index: 2500; background-color: rgba(0,0,0,0.5); backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  display: flex; justify-content: center; align-items: center; padding: 10px; box-sizing: border-box;
}
.preview-popup-3d {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 12px;
  width: auto; max-width: 400px; height: 80vh; max-height: 80vh;
  background: var(--brand-gradient-warm), var(--brand-gradient); color: var(--brand-white);
  border-radius: 20px; padding: 12px; box-sizing: border-box;
  box-shadow: 0 12px 32px rgba(0,0,0,0.45);
}
.preview-media-wrapper {
  /* The 9:16 ratio belongs to the actual captured content (it's genuinely 9:16 now - see
     compute9x16CropRect in ar.js), not the whole card. An explicit width (100%) let the popup's
     max-height squeeze this shorter than a true 9:16 box whenever the button row + gaps + padding
     didn't leave enough room, and object-fit:cover cropped the difference off the photo to
     compensate. Height-driven instead (flex-grow within the now-definite-height popup) with
     width derived from the ratio, so it can never be compressed off-ratio - only its size changes.
  */
  flex: 1 1 auto; width: auto; max-width: 100%; aspect-ratio: 9 / 16; min-height: 0;
  border-radius: 14px; overflow: hidden;
}
#preview-video, #preview-image { width: 100%; height: 100%; object-fit: cover; }
.close-preview-button {
  position: absolute; top: -14px; right: -14px; width: 36px; height: 36px;
  background: var(--brand-white); color: var(--brand-blue); border: none;
  border-radius: 50%; font-size: 20px; font-weight: 600;
  display: flex; align-items: center; justify-content: center; line-height: 1;
  cursor: pointer; z-index: 2505; transition: all 0.15s ease;
  box-shadow: 0 2px 8px rgba(0,0,0,0.3);
}
.close-preview-button:active { transform: scale(0.92); }
.popup-actions {
  display: flex; justify-content: center; gap: 12px; width: 100%;
}
.popup-button {
  font-size: 0.95em; padding: 12px 24px; flex-grow: 0;
}
.popup-button.secondary {
  background: var(--brand-white); color: var(--brand-blue);
  box-shadow: none;
  border: 1.5px solid var(--brand-gray-light);
}
.popup-button.secondary:hover { background: var(--brand-gray-light); }
.popup-button.secondary:active { transform: scale(0.97); }

@media (max-width: 767px) {
  #controls { bottom: 4%; }
}

