/* Reset defaults */
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html,
body {
  background: #00D532;   /* whole page is this green */
}

/* Allow the page to scroll vertically only, and stop the mobile overscroll
   "bounce" that reveals the green page background at the top/bottom. */
html {
  overflow-x: hidden;
  overscroll-behavior: none;
}
body {
  overscroll-behavior: none;
}

/* Keep the whole experience a centered mobile-width column. On desktop the page
   does NOT stretch wide — it stays at mobile width, centered, with the page
   green showing on either side. `container-type: inline-size` makes this column
   the reference for all the `cqw` (container-width) units used throughout the
   layout, so on a phone (column == viewport) 1cqw == 1vw and nothing changes,
   while on desktop everything keys off the capped column width instead of the
   full viewport. */
:root {
  /* Content width: fill the whole screen on phones (no green side bars, even on
     the largest ones like the iPhone Pro Max), but cap it on desktop so the page
     stays a centered phone-width column instead of stretching wide. 500px sits a
     little above the widest phones so they all still go edge-to-edge, and gives
     desktop a slightly larger-than-a-phone view. */
  --app-w: min(100vw, 500px);
}
.app {
  position: relative;
  z-index: 1;                 /* sit above the decorative side panels */
  width: 100%;
  max-width: var(--app-w);
  margin-inline: auto;
  container-type: inline-size;
}

/* Decorative comic panels flanking the centered column on desktop. They are
   transparent PNGs (black line art), so the page green shows through and they
   read as green panels. Fixed + full height so they frame the site while it
   scrolls; anchored to the outer edges and tucked BEHIND the .app column, so
   their inner edge meets the column with no top/bottom cropping. Hidden on
   phones/tablets where the column fills the screen (no side space). */
.side-panel {
  position: fixed;
  top: 0;
  height: 100vh;
  /* Exactly the green gap between the screen edge and the centered column, so
     the panel butts up to the column and never slides behind it. As the window
     narrows the gap shrinks and object-fit: cover simply CROPS the inner side —
     the panel's outer edge stays pinned, so it's cut, not moved. */
  width: calc((100vw - var(--app-w)) / 2);
  object-fit: cover;
  z-index: 0;
  pointer-events: none;       /* purely decorative — never block taps */
  user-select: none;
  -webkit-user-drag: none;
  display: none;
}
/* Pin each panel's OUTER edge to the screen edge; the cut happens on the inner
   side toward the middle column. */
.side-panel-left  { left: 0;  object-position: left center; }
.side-panel-right { right: 0; object-position: right center; }
@media (min-width: 768px) {
  .side-panel { display: block; }
}

/* Hidden (but rendered) switch for triggering iOS haptics — kept off-screen */
.haptic-toggle {
  position: fixed;
  left: -100px;
  bottom: 0;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
  z-index: -1;
}

/* First screen: the video hero. Its size is driven ENTIRELY by the column
   WIDTH (via the video's aspect ratio), NOT by the viewport height — so
   shortening the window never shrinks the video. Like the rest of the fixed
   mobile-width column, the page simply gets cut off / scrolled when the window
   is too short. (Width-driven also means the mobile address bar toggling never
   resizes it, so there's no scroll jitter.) */
.hero {
  position: relative;
  width: 100cqw;
  /* Full viewport height so the video is fit to the screen and its bottom sits
     at the bottom of the window (the "SCROLL" cue shows). svh (not dvh) keeps it
     stable while the mobile address bar shows/hides. */
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  background: #00D532;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* The video frame IS the video's content box (same aspect ratio) and is the
   query container + positioning context for all overlays, which are placed as
   % / cqw of it. It's sized to CONTAIN within the hero — capped at the column
   width, but shrunk to the viewport height when the window is short — so the
   whole video (top to the bottom "SCROLL" cue) always fits on screen. */
.video-frame {
  position: relative;
  width: min(100cqw, calc(100vh * 1616 / 3512));
  width: min(100cqw, calc(100svh * 1616 / 3512));
  aspect-ratio: 1616 / 3512;
  container-type: size;
}

/* Video fills the frame exactly (frame aspect == video aspect) */
.hero-video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Second screen: the painting background revealed on scroll.
   The green margin-top pushes the painting (and everything on it) down so it
   doesn't peek under the first screen on mobile — the gap shows the same green
   as the hero, so the seam is invisible. */
.scroll-page {
  position: relative;
  z-index: 1;                 /* below the straddling green divider */
  overflow: hidden;
  margin-top: 11vh;            /* green gap after the hero (trimmed a bit) */
  background-color: #23408f;   /* fallback blue while the image loads */
}

/* The painting lives on its own oversized layer (bleeds past the edges) so it
   can be nudged around with phone tilt without exposing the edges. */
.scroll-bg {
  position: absolute;
  inset: -100px;   /* extra bleed so the bigger parallax never shows edges */
  z-index: 0;
  background-image: url('images/background.png');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  will-change: transform;
  pointer-events: none;
}

/* Centered column that holds the notes (mobile-shaped on any screen) */
.scroll-stage {
  position: relative;
  z-index: 1;
  max-width: 640px;         /* larger notes */
  margin: 0 auto;
  padding: 15vh 12px 0;     /* space above so the notes sit lower on the painting */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1vh;                 /* notes sit close together */
}

/* Main note: paper image with the animated text laid over it.
   aspect-ratio matches the image's actual content bounds (804 x 1134 — the
   paper plus its full soft bottom shadow, stopping just before the empty
   transparent padding) so the shadow shows in full instead of being sliced off
   in a hard line, with no wasted gap below. The second note is pulled up to sit
   on top of this shadow (see .note-blank-wrap). */
.note-wrap {
  position: relative;
  z-index: 1;
  width: 100%;
  aspect-ratio: 804 / 1134;
  overflow: hidden;
}
.note-paper {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: auto;
}
/* The handwriting gif is proportionally taller than the paper, so it is
   scaled down and centered to land within the paper's lined area,
   just below the sticky and above the torn bottom edge. */
.note-text {
  position: absolute;
  top: -3%;
  left: 6.5%;
  width: 87%;
  height: auto;
  pointer-events: none;
}

/* Second torn note with the EXPLORE button centered on it.
   Pulled up to overlap the bottom shadow of the note above and layered on top
   (z-index) so it sits ON the shadow rather than being pushed far below it. */
.note-blank-wrap {
  position: relative;
  z-index: 2;
  width: 100%;
  margin-top: -35%;
  animation: explore-bounce 2.4s ease-in-out infinite;
}
.note-blank {
  display: block;
  width: 100%;
  height: auto;
}
.explore {
  position: absolute;
  top: 35%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 85%;
  height: auto;
  cursor: pointer;
}
/* Gently hop the note + EXPLORE button (see .note-blank-wrap) up every couple
   of seconds to hint it's a tappable button. */
@keyframes explore-bounce {
  0%,  40%, 100% { transform: translateY(0); }
  8%             { transform: translateY(-5%); }    /* hop up */
  18%            { transform: translateY(0); }       /* land */
  25%            { transform: translateY(-2.5%); }   /* smaller second hop */
  33%            { transform: translateY(0); }       /* settle */
}
@media (prefers-reduced-motion: reduce) {
  .note-blank-wrap { animation: none; }
}

/* Green scalloped band straddling the seam between page 2 (blue painting) and
   page 3 (white paper). It rides ABOVE both pages (z-index 3) and is pulled up
   into the blue and down over the white in equal measure, so its top notches
   reveal the blue painting and its bottom notches reveal the white page. The
   image is ~2.424:1, so at 100cqw wide its height is ~41cqw; half of that (~21cqw)
   of negative margin on each side centres the seam on the band. */
.page-divider {
  display: block;
  position: relative;
  z-index: 3;
  width: 100%;
  height: auto;
  margin-top: -21cqw;      /* top notches cross up onto the blue painting */
  margin-bottom: -21cqw;   /* pull the white page up behind the bottom notches */
  pointer-events: none;
}

/* Third screen: white paper texture. Painting on top, torn note directly
   underneath — a simple stacked flow using width-proportional units, so the
   whole thing scales as one unit and never drifts when the page is scaled. */
.paper-page {
  position: relative;
  z-index: 2;                  /* below the divider, above the blue page */
  min-height: 100vh;
  min-height: 100svh;
  overflow: hidden;
  background-color: #f2f1ec;   /* fallback while the texture loads */
  background-image: url('images/paper-bg.png');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 17svh;          /* shift the whole page-3 group further down */
}

/* Artwork carousel on a circular ring.
   .art-stage keeps the old painting's footprint (so the note stays put); the
   active piece sits centered in it, the rest are spaced 60deg apart around a
   big circle whose center is far below. Clicking an arrow rotates the ring. */
.art-stage {
  position: relative;
  width: 120%;
  max-width: 720px;
  aspect-ratio: 954 / 1162;
  /* Drag/swipe the paintings to swivel the ring. pan-y keeps vertical scrolling
     working while a horizontal swipe rotates. */
  touch-action: pan-y;
  cursor: grab;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
.art-stage.dragging { cursor: grabbing; }
.art-item {
  -webkit-user-drag: none;
  user-drag: none;
}
.art-ring {
  position: absolute;
  left: 50%;
  top: calc(50% + 155cqw);     /* rotation center, 155cqw below the active spot */
  width: 0;
  height: 0;
  transform-origin: 0 0;
  transform: rotate(var(--ring-rot, 0deg));
  transition: transform 0.85s cubic-bezier(0.6, 0, 0.25, 1);
  will-change: transform;
}
/* While an arrow is held, step at a constant linear speed so the ring whirs
   continuously instead of easing in/out on every step. Duration matches the
   JS REPEAT_MS so velocity stays even. */
.art-ring.spinning {
  transition: transform 0.26s linear;
}
.art-item {
  position: absolute;
  left: 0;
  top: 0;
  width: 120cqw;
  max-width: 720px;
  height: auto;
  transform-origin: 0 0;
  /* place on the ring at angle --a, radius 155cqw, centered on that point */
  transform: rotate(var(--a)) translateY(-155cqw) translate(-50%, -50%);
}

/* The torn note follows directly underneath the painting */
.paper-note-wrap {
  position: relative;          /* positioning context for the arrows */
  width: 150%;
  margin-top: -55%;            /* pull the note up toward the painting
                                  (overlaps the transparent shadow areas) */
  overflow: hidden;
  z-index: 1;                  /* sit above the green footer so the note's torn
                                  edge + baked shadow fall onto the green */
}

/* Green footer at the very bottom of page 3: the webpage green laid over the
   white paper, carrying the IMAGINARY FRIENDS ™ badge.
   Layering (bottom -> top): green band (::before, z0) is tucked up behind the
   note so the note's torn edge + soft shadow (z1) fall onto it; the badge
   (z2) rides ABOVE the note so it stays crisp right below the torn edge. */
.paper-footer {
  position: relative;          /* no z-index: children layer in the root stack */
  width: 100%;
  margin-top: -60cqw;          /* raise the green well up behind the torn edge */
  padding: 28cqw 0 14cqw;      /* top padding lands the badge just below the edge */
  display: flex;
  justify-content: center;
  align-items: center;
}
.paper-footer::before {        /* the green band itself, below the note */
  content: "";
  position: absolute;
  inset: 0;
  background: #00D532;         /* the webpage green */
  z-index: 0;
}
.footer-logo {
  position: relative;
  z-index: 2;                  /* above the note + its shadow, so it stays crisp */
  width: 90%;                  /* much larger badge */
  max-width: 560px;
  height: auto;
}
.paper-note {
  display: block;
  width: 114%;                 /* lined paper runs edge to edge */
  margin-left: -7%;            /* keep it centered */
  height: auto;
}

/* Prev / next arrows on the note, at the screen sides just below the torn
   top edge (positioned as % of the note, so they scale with it). */
.paper-arrow {
  position: absolute;
  top: 18%;             /* on the note's first blue line */
  z-index: 2;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  /* Stop iOS Safari's long-press image callout (Save to Photos / Copy / the
     magnified preview) and any text/selection popups while holding to spin. */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  touch-action: manipulation;
}
.paper-arrow img {
  display: block;
  width: 100%;
  height: auto;
  /* The long-press callout targets the <img>; make it non-interactive so the
     press lands on the <button> instead (a button has no Save-to-Photos menu),
     and block image drag/selection for good measure. */
  pointer-events: none;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-user-drag: none;
  user-drag: none;
}
/* Note-wrap is 150% wide, so 23% of it lands ~10% in from each viewport edge */
.paper-arrow-left  { left: 23%;  width: 13cqw; max-width: 74px; }
.paper-arrow-right { right: 23%; width: 13cqw; max-width: 74px; }

/* Gentle rightward "tap me" nudge on the next arrow, played in sync with the
   idle peek hint (triggered from script.js) so it hints there's more work to
   see. It is removed for good once the user first interacts with the arrows. */
.paper-arrow-right.hint img {
  animation: arrow-nudge-right 0.9s ease-in-out;
}
@keyframes arrow-nudge-right {
  0%, 40%, 100% { transform: translateX(0); }
  20%           { transform: translateX(28%); }
  60%           { transform: translateX(18%); }
  80%           { transform: translateX(0); }
}

/* Animated INQUIRE button, centered between the arrows on the first blue line.
   The gif is a full phone-sized transparent canvas with the button ~56% down,
   so we crop to just that button via background-size/position. */
.inquire {
  position: absolute;
  top: 22%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 3;
  width: 34cqw;
  aspect-ratio: 478 / 215;     /* taller window so the button's top isn't clipped */
  background-image: url('images/inquire.gif');
  background-repeat: no-repeat;
  background-size: 278% auto;   /* scale so the button (36% of gif) fills width */
  background-position: center 56%;
  cursor: pointer;
}

/* Painting description — the source is a full phone-sized transparent canvas
   with the text in the middle, so we render it at viewport width and shift it
   up so the star row lands just below the INQUIRE button. One per painting,
   all stacked in the same spot; only the `.on` one (matching the selected
   painting) is visible. It cross-fades quickly as the ring turns. */
.description {
  position: absolute;
  top: -79cqw;             /* pulled up so the star row sits just below INQUIRE */
  left: 50%;
  transform: translateX(-50%);
  width: 100cqw;
  height: auto;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.18s ease;
}
.description.on {
  opacity: 1;
}

/* Static artwork centered in the big middle box of the video.
   Positioned as % of the video frame so it stays locked to the video. */
.card-stage {
  position: absolute;
  z-index: 9;
  left: 49.3%;
  top:  45%;
  width: 80%;
  aspect-ratio: 1 / 1;
  transform: translate(-50%, -50%);
}

.card-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 0;   /* square corners */
}

/* Paper-note frame animation, played on top of the card (see script.js).
   Container is hidden between plays; inside, all 8 frames are stacked and the
   script toggles which one is visible (opacity) for smooth playback. */
.note-anim {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  z-index: 2;
  /* scale up so the open note (frame 8) covers the card but stays
     within the black outline */
  transform: scale(1.12);
  transform-origin: center center;
}
.note-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  will-change: opacity;
}
.note-frame.on {
  opacity: 1;
}

/* Icons overlaid inside the two boxes at the bottom of the video.
   Positions are % of the frame; sizes use cqw (1cqw = 1% of the frame width)
   so they stay locked to the drawn boxes as the video scales. */
.badge {
  position: absolute;
  z-index: 10;
  transform: translate(-50%, -50%);   /* anchor by center */
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.badge img {
  display: block;
  width: auto;
  height: auto;
}

/* Left box: Instagram */
.badge-instagram {
  left: 27%;
  top:  75.5%;
}
.badge-instagram img { height: 33cqw; }

/* Right box: sound */
.badge-sound {
  left: 71%;
  top:  75.5%;
}
.badge-sound .sound-icon { height: 25cqw; }

/* Pink X over the speaker; hidden once music plays */
.badge-sound .mute-sign {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, calc(-50% + 2cqw));
  height: 40cqw;
}
.badge-sound.playing .mute-sign {
  opacity: 0;
}

/* --- EXPLORE gallery iframe overlay (keeps the music playing on the page
   behind it, since opening it never navigates away) --- */
.ex-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: none;
  background: #00D532;   /* page green shows either side of the centered gallery */
}
.ex-overlay.open { display: block; }
/* The gallery is centered at the same mobile width as the rest of the site so it
   doesn't stretch across a desktop screen. */
#ex-frame {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: min(100vw, var(--app-w));
  height: 100%;
  border: 0;
  display: block;
  background: #EDEDED;
}
/* Overlay's own back/close button — the little torn-paper card, full image so
   its soft shadow fades naturally (no crop). */
.ex-overlay .ex-back {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 24px);
  /* 8px in from the left edge of the centered gallery column (not the viewport) */
  left: calc(50% - min(100vw, var(--app-w)) / 2 + 8px);
  z-index: 1001;
  width: 108px;
  aspect-ratio: 522 / 632;
  border: none;
  padding: 0;
  cursor: pointer;
  background: transparent url('images/back-btn.png') no-repeat center / contain;
  -webkit-tap-highlight-color: transparent;
}

/* --- Painting lightbox: tap a painting on page 3 to enlarge it as large as
   possible over a dimmed page, centered, with the torn-paper X card right
   underneath. The painting can be pinch-zoomed / panned (JS owns the gesture,
   so `touch-action: none` here stops the browser hijacking the pinch). --- */
.art-lightbox {
  position: fixed;
  inset: 0;
  z-index: 1500;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0;
  /* dim the whole website behind the enlarged painting */
  background: rgba(0, 0, 0, 0.85);
  padding: calc(env(safe-area-inset-top, 0px) + 2vh) 2vw
           calc(env(safe-area-inset-bottom, 0px) + 2vh);
  -webkit-tap-highlight-color: transparent;
  touch-action: none;
  overscroll-behavior: none;
  cursor: zoom-out;
}
.art-lightbox.open { display: flex; }

/* The enlarged painting — as large as possible, centered. transform-origin is
   the top-left so the JS pan/zoom math is simple; a soft drop shadow lifts it
   off the dim. Only opacity is animated on open so it never fights the inline
   transform the pinch/pan code writes. */
.art-lightbox-img {
  max-width: 96vw;
  max-height: 74vh;
  width: auto;
  height: auto;
  transform-origin: 0 0;
  will-change: transform;
  filter: drop-shadow(0 12px 34px rgba(0, 0, 0, 0.55));
  cursor: grab;
  touch-action: none;
  -webkit-user-drag: none;
  user-select: none;
  animation: art-fade 0.25s ease both;
}

/* The torn-paper X card, right below the painting. Its own soft shadow fades
   below the card, so the box uses the image's aspect ratio (never cropped);
   negative margins pull the card up snug under the painting and keep the
   transparent shadow tail from throwing off the vertical centering. It rides
   above the painting (z-index) so a zoomed-in painting can't cover it. */
.art-lightbox-close {
  flex: none;
  width: 34vw;
  max-width: 170px;
  aspect-ratio: 420 / 578;
  margin-top: -4vw;
  margin-bottom: -27vw;
  border: none;
  padding: 0;
  cursor: pointer;
  background: transparent url('images/close-x.png') no-repeat center top / contain;
  -webkit-tap-highlight-color: transparent;
  z-index: 2;
  animation: art-pop 0.3s cubic-bezier(0.2, 0.85, 0.25, 1) both;
}
@media (min-width: 640px) {
  /* on wider screens the card is capped in px, so cap the pull-up in px too */
  .art-lightbox-close { margin-top: -20px; margin-bottom: -134px; }
}

@keyframes art-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes art-pop {
  from { transform: translateY(8px) scale(0.9); opacity: 0; }
  to   { transform: none;                       opacity: 1; }
}
