/* main.css — Rivian Sound Tracks
   Dark cinematic page; amber accents; overlay typography via clamp(). */

:root {
  --bg: #0E0F10;
  --amber: #F5A623;
  --ink: #F4F0E8;
  --font: -apple-system, BlinkMacSystemFont, "Inter", "Helvetica Neue", Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }

html {
  background: var(--bg);
  scroll-behavior: auto; /* JS drives smooth scrolling where wanted */
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
}

::selection { background: var(--amber); color: var(--bg); }

/* ---------- fixed layers (bottom → top) ---------- */

#frame-canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  /* opacity is scrubbed per frame from scroll; a transition here would lag it */
}

#overlay {
  position: fixed;
  inset: 0;
  z-index: 10;
  pointer-events: none;
  /* opacity is scrubbed per frame from scroll; a transition here would lag it */
}

.ch {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  opacity: 0;
  will-change: opacity;
}

.ch [data-depth] { will-change: transform; }

.title {
  margin: 0.4em 0;
  font-size: clamp(3.2rem, 11vw, 9rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-shadow: 0 4px 40px rgba(0, 0, 0, 0.45);
}

.caption {
  margin: 0;
  font-size: clamp(2.2rem, 6.5vw, 5rem);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-shadow: 0 4px 32px rgba(0, 0, 0, 0.5);
}

.micro {
  margin: 0 0 1.5rem;
  font-size: clamp(0.72rem, 1.15vw, 0.9rem);
  font-weight: 600;
  letter-spacing: 0.45em;
  text-transform: uppercase;
  color: rgba(244, 240, 232, 0.88);
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.65), 0 0 2px rgba(0, 0, 0, 0.4);
}

.micro.locale { margin: 1.2rem 0 0; }

.micro.tagline { color: #fff; }

.hint {
  position: absolute;
  bottom: 7vh;
  left: 0;
  right: 0;
  margin: 0;
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.35em;
  text-transform: uppercase;
  color: rgba(244, 240, 232, 0.7);
}

.hint-arrow {
  display: inline-block;
  animation: hint-bob 1.8s ease-in-out infinite;
}

@keyframes hint-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(5px); }
}

/* ---------- chapter progress rail ---------- */

#rail {
  position: fixed;
  right: 26px;
  top: 50%;
  transform: translateY(-50%);
  height: 38vh;
  width: 10px;
  z-index: 20;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  pointer-events: none;
  /* opacity is scrubbed per frame from scroll; a transition here would lag it */
}

#rail::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  background: rgba(255, 255, 255, 0.14);
}

.rail-fill {
  position: absolute;
  top: 0;
  left: 50%;
  width: 1px;
  height: 0%;
  background: var(--amber);
}

.dot {
  position: relative;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.28);
  transition: background 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
}

.dot.on {
  background: var(--amber);
  transform: scale(1.4);
  box-shadow: 0 0 12px rgba(245, 166, 35, 0.65);
}

/* ---------- skip button ---------- */

#skip-btn {
  position: fixed;
  right: 26px;
  bottom: 26px;
  z-index: 30;
  padding: 10px 18px;
  border: 1px solid rgba(245, 166, 35, 0.55);
  border-radius: 999px;
  background: rgba(14, 15, 16, 0.55);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: var(--amber);
  font-family: var(--font);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
  transition: opacity 0.35s ease, transform 0.35s ease, background 0.2s ease, color 0.2s ease;
}

#skip-btn.is-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

#skip-btn:hover { background: var(--amber); color: var(--bg); }
#skip-btn:focus-visible { outline: 2px solid var(--amber); outline-offset: 3px; }

/* ---------- dashboard handoff ---------- */

/* The reveal is scrubbed from scroll in main.js, which writes opacity and
   transform every frame. No transition here on purpose: a CSS timer would keep
   animating after the scroll had already moved on, which is what made the
   handoff read as a cut and let both layers sit on screen at once when you
   scrolled back and forth across the threshold. */
#dashboard-root {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 100vh;
  height: 100dvh;
  z-index: 40;
  opacity: 0;
  pointer-events: none;
  transform: scale(1.012);
  will-change: opacity, transform;
}

/* The footer keeps its box at all times — hiding it with display:none shortened
   the document exactly at the handoff, so scrollY/max jumped and the scrollbar
   lurched. main.js fades it instead, per frame: no transition, because this is
   a page whose whole thesis is that nothing here runs on a timer. */

body.cockpit #skip-btn {
  opacity: 0;
  pointer-events: none;
}

/* ---------- scroll track + footer ---------- */

/* Track length is the cheapest smoothness lever there is: it divides the
   picture change per pixel of scroll without touching pacing. At 600vh a single
   flick moved the film far enough that the fastest stretch changed more than
   plain-scrolling a static page would — which is exactly what reads as a jerk.
   900vh is still well short of the reference page's own 11,230px.

   Held at 900vh through the switch to a single 361-frame take. Fewer frames
   than the old four-clip cut, but the number that matters is total picture
   change over the whole film, and that barely moved (2585 vs ~2717 mean-grey),
   so the same track is now marginally gentler per pixel than it was before. */
#scroll-track {
  position: relative;
  height: 900vh;
  z-index: 1;
}

#site-footer {
  position: relative;
  z-index: 60;
  padding: 16px 24px;
  background: #0A0B0C;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  text-align: center;
}

#site-footer p {
  margin: 0;
  font-size: 12px;
  letter-spacing: 0.08em;
  color: rgba(244, 240, 232, 0.45);
}

/* ---------- reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
    animation: none !important;
  }
}

/* ---------- cockpit: dash surround + anchored live screen ---------- */
/* Stage keeps the 2752x1536 photo's aspect and covers the viewport, so the
   screen-anchor percentages always map to the same spot on the dash photo. */
#cockpit-stage {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: max(100vw, calc(100vh * 1.77778));
  height: max(100vh, calc(100vw / 1.77778));
}

#cockpit-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* dim the physical dash so the live screen reads as the hero;
   vignette is centered on the screen area, dash stays clearly visible */
#cockpit-stage::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 68% 62% at 49.9% 51%,
              rgba(4, 6, 8, 0.10) 40%,
              rgba(4, 6, 8, 0.34) 74%,
              rgba(4, 6, 8, 0.52) 100%);
  pointer-events: none;
  z-index: 1;
}

#screen-anchor {
  z-index: 2;
}

/* glass rect of the center display within the K4b cockpit photo */
#screen-anchor {
  position: absolute;
  left: 18.6%;
  top: 23.65%;
  width: 62.0%;
  height: 54.7%;
}

/* embedded mode: the UI fills the physical glass exactly; the photo bezel
   provides the frame, so drop the module's own letterbox + glow chrome */
#screen-anchor .rvn-screen {
  width: 100% !important;
  height: 100% !important;
  max-width: none;
  aspect-ratio: auto;
  border: none;
  box-shadow: none;
  border-radius: 1.4vw;
}

/* ---------- Academix x Rivian brand lockup ---------- */
.brand-lockup {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.9em;
  margin-top: 1.6rem;
  opacity: 0.92;
}

.brand-lockup .lockup-academix {
  height: clamp(20px, 2.4vw, 30px);
  width: auto;
  display: block;
}

.brand-lockup .lockup-x {
  color: #C9CDD1;
  font-size: clamp(14px, 1.4vw, 18px);
  font-weight: 300;
}

.brand-lockup .lockup-rivian {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  color: #E8EAEC;
  font-weight: 700;
  letter-spacing: 0.34em;
  font-size: clamp(13px, 1.5vw, 19px);
  padding-left: 0.1em;
}

.brand-lockup .lockup-rivian svg {
  width: clamp(18px, 2vw, 26px);
  height: clamp(18px, 2vw, 26px);
}

#site-footer .footer-lockup {
  margin: 0 0 0.9rem;
  opacity: 0.85;
}

#site-footer .footer-lockup .lockup-academix { height: 22px; }
#site-footer .footer-lockup .lockup-rivian { font-size: 14px; }
#site-footer .footer-lockup .lockup-rivian svg { width: 19px; height: 19px; }

/* simulated finger tap on the dock's music button */
@keyframes rvn-haptic-tap {
  0%   { transform: scale(1); box-shadow: 0 0 0 0 rgba(245, 166, 35, 0); }
  30%  { transform: scale(0.78); box-shadow: 0 0 0 4px rgba(245, 166, 35, 0.45); }
  60%  { transform: scale(1.06); box-shadow: 0 0 0 14px rgba(245, 166, 35, 0); }
  100% { transform: scale(1); box-shadow: 0 0 0 18px rgba(245, 166, 35, 0); }
}

#dashboard-root .rvn-haptic-press {
  animation: rvn-haptic-tap 0.6s ease-out;
  border-radius: 50%;
}

/* ---------- mobile portrait: cockpit fills the device, clean full view ---------- */
@media (max-width: 820px) and (orientation: portrait) {
  /* the dash photo becomes a dimmed backdrop; the UI takes the whole screen */
  #cockpit-stage {
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    transform: none;
  }

  #cockpit-bg { object-fit: cover; }

  #cockpit-stage::after {
    background: rgba(4, 6, 8, 0.6);
  }

  #screen-anchor {
    left: 0 !important;
    top: 0 !important;
    width: 100% !important;
    height: 100% !important;
    padding: env(safe-area-inset-top) env(safe-area-inset-right)
             env(safe-area-inset-bottom) env(safe-area-inset-left);
    box-sizing: border-box;
  }

  #screen-anchor .rvn-screen { border-radius: 0; }

  .brand-lockup { gap: 0.6em; }
  .brand-lockup .lockup-academix { height: 17px; }
  .brand-lockup .lockup-rivian { font-size: 12px; letter-spacing: 0.28em; }

  #skip-btn { right: 12px; bottom: 12px; }
  #rail { display: none; }
}

/* ---------- portrait: its own layout, not the landscape one made narrow ----------
   A blind critic put this side by side with Rivian's own drive-mode sheet and
   picked theirs, for a specific reason: our panels kept their landscape
   composition and were simply cropped. The tell was the drive-mode card sitting
   at a hard-coded 252x370 on every portrait phone — identical at 390x844 and at
   430x932, so a bigger phone bought nothing. These rules give portrait a grid
   of its own: the card sizes to the screen, the settings rows go two-up instead
   of leaving ~180px of dead space between a label and its meter, and the type
   comes up off the 10px floor now that there is room for it. */
@media (max-width: 820px) and (orientation: portrait) {
  /* sized against .rvn-viewport, its actual containing block — cqw would be the
     whole dashboard including the rail, which overflowed it to the right */
  #dashboard-root .rvn-card {
    width: auto;
    max-width: 420px;
    left: 14px;
    right: 14px;
    /* clears the floating status pill, which draws above the card */
    top: 48px;
    max-height: calc(100% - 62px);
    padding: 14px 14px 12px;
  }

  /* The drive scene is a landscape composition in two co-registered layers: a
     skyline SVG and the car plate on top of it. Sized to COVER a tall panel,
     both were scaled to the height and cropped hard on width — under half the
     car was on screen with its centre off to the right.

     Both layers move together into a band near the bottom, sized to the panel
     width plus a little overscan, so the whole vehicle is in frame and the two
     layers still line up. Move one without the other and the picture splits. */
  #dashboard-root .rvn-home .rvn-backdrop,
  #dashboard-root .rvn-scene-stage {
    top: auto;
    bottom: 9%;
    left: 50%;
    width: 124%;
    min-width: 0;
    min-height: 0;
    height: auto;
    aspect-ratio: 2752 / 1536;
    transform: translateX(-50%);
  }

  #dashboard-root .rvn-home .rvn-backdrop svg {
    width: 100%;
    height: 100%;
  }

  /* two-up: kills the empty middle of each row and halves the card's height */
  #dashboard-root .rvn-rows {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
  }

  #dashboard-root .rvn-row { padding: 9px 11px; }
  #dashboard-root .rvn-row-name { font-size: 12px; }
  #dashboard-root .rvn-row-value { font-size: 14px; }
  #dashboard-root .rvn-tile { min-height: 66px; }
  #dashboard-root .rvn-tile-label { font-size: 13px; }
  #dashboard-root .rvn-tab { font-size: 15.5px; }
  #dashboard-root .rvn-height-title { font-size: 12px; }
  #dashboard-root .rvn-height-value { font-size: 14px; }

  /* The map is authored 16:9. Letterboxing it to fit a portrait panel put every
     label on screen but shrank them to ~5px in a mostly-empty panel — complete
     and unreadable. Full-bleed keeps them at their authored size, which is what
     a zoomed-in nav view looks like anyway; labels outside the frame are simply
     off-map. Anchored left so your own vehicle marker stays in view rather than
     centring on empty basin.
     KNOWN LIMIT: a portrait-native map asset is the real fix here. */
  #dashboard-root .rvn-nav .rvn-backdrop svg {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 22% 50%;
  }

  #dashboard-root .rvn-media {
    display: flex !important;
    flex-direction: column;
    gap: 18px;
    padding: 18px 16px 12px;
    overflow: hidden;
  }

  /* only the playlist list scrolls internally; swipes anywhere else move the page.
     The playlist takes whatever height is left rather than a fixed 32dvh: with
     both children flex:none the column could total more than the panel, which
     ran the last track rows off the bottom of a 667px-tall phone. */
  #dashboard-root .rvn-playlist-scroll {
    max-height: none;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    /* a swipe that runs off the end of the list must not start scrolling the
       page out of the cockpit behind it */
    overscroll-behavior: contain;
  }

  #dashboard-root .rvn-media-left { flex: none; }

  /* Art is the one elastic block above the playlist, so it decides how much
     room "Up Next" gets. At 30cqh a 600px-tall phone gave the art 180px and
     left the list 90px — about one and a half rows, which reads as broken
     rather than scrollable. 22cqh keeps the artwork generous on tall phones
     and yields real estate back on short ones. */
  #dashboard-root .rvn-art { width: min(272px, 22cqh, 58cqw); }

  #dashboard-root .rvn-playlist {
    flex: 1 1 auto;
    min-height: 0;
  }

  /* dock: keep temps + core apps, drop the secondary clusters */
  #dashboard-root .rvn-hvac-btn,
  #dashboard-root .rvn-vol-btn,
  #dashboard-root .rvn-dock-sep,
  #dashboard-root [data-rvn-dock="camera"] {
    display: none !important;
  }

  /* The dock is absolutely centred, so it takes no width in the bar's flex
     flow — at 390px it sat on top of both temp pills. Portrait keeps the
     driver temps only and gives the dock the rest of the row in normal flow. */
  #dashboard-root .rvn-bottom { padding: 0 10px; gap: 8px; }
  #dashboard-root .rvn-bottom .rvn-temp-pill ~ .rvn-temp-pill { display: none; }
  #dashboard-root .rvn-bottom-spacer { display: none; }

  #dashboard-root .rvn-dock {
    position: static;
    transform: none;
    flex: 1;
    min-width: 0;
    justify-content: center;
    gap: 10px;
  }

  /* Vehicle panel is a side-by-side flex row sized for a landscape screen:
     the 340/560 car stage alone is ~285px wide, so on a 390px phone the whole
     right-hand column ran off the edge ("Launch (", "ODOM", "28"). Stack it,
     same as the media panel above. */
  #dashboard-root .rvn-vehicle {
    flex-direction: column;
    gap: 14px;
    padding: 16px 14px;
    justify-content: flex-start;
    overflow-y: auto;
  }

  #dashboard-root .rvn-veh-stage {
    height: auto;
    width: min(58%, 190px);
    flex: none;
  }

  #dashboard-root .rvn-veh-side {
    width: 100%;
    gap: 10px;
  }

  #dashboard-root .rvn-veh-stats { grid-template-columns: 1fr 1fr; }
}

/* ---------- mobile landscape: same full-device treatment as portrait ----------
   Phones are 844–932px wide on their side, so the portrait rules above (gated
   at max-width 820px) never matched a rotated phone. It fell through to the
   desktop cockpit, where the stage is sized max(100vh, 100vw/1.7778) — 475px
   tall on a 390px viewport — and the anchored glass rect left the dashboard
   with ~260px of height, pushing its bottom dock off the screen entirely.
   Bounded on width as well as height: height alone would also catch an
   ordinary desktop window snapped short (say 1280x480), which should keep the
   photographic cockpit. Tablets in landscape stay out by height.

   The 430px ceiling deliberately matches the dashboard's own compaction query
   in dashboard.css. When full-bleed reached 520px but compaction stopped at
   430px, the 431-520px band ran a full-width screen with desktop-sized
   internals and clipped the media panel. Every phone in landscape is <=430px
   tall, so nothing real is lost; taller short windows keep the inset cockpit,
   which is designed for exactly that shape. Keep these two numbers equal. */
@media (max-width: 1024px) and (orientation: landscape) and (max-height: 430px) {
  #cockpit-stage {
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    transform: none;
  }

  #cockpit-bg { object-fit: cover; }

  #cockpit-stage::after { background: rgba(4, 6, 8, 0.6); }

  #screen-anchor {
    left: 0 !important;
    top: 0 !important;
    width: 100% !important;
    height: 100% !important;
    /* the notch/home-indicator live on the long edges when rotated */
    padding: env(safe-area-inset-top) env(safe-area-inset-right)
             env(safe-area-inset-bottom) env(safe-area-inset-left);
    box-sizing: border-box;
  }

  #screen-anchor .rvn-screen { border-radius: 0; }

  #rail { display: none; }
  #skip-btn { right: 12px; bottom: 12px; padding: 7px 13px; font-size: 11px; }

  /* the hero stack has to clear a 390px-tall stage */
  .title { font-size: clamp(2.4rem, 8vh, 4.4rem); }
  .caption { font-size: clamp(1.6rem, 6vh, 3.2rem); }
  .micro { margin-bottom: 0.9rem; }
  .micro.locale { margin-top: 0.7rem; }
  .brand-lockup { margin-top: 0.9rem; gap: 0.6em; }
  .brand-lockup .lockup-academix { height: 17px; }
  .brand-lockup .lockup-rivian { font-size: 12px; letter-spacing: 0.28em; }
  .hint { bottom: 4vh; }
}
