/* ═══════════════════════════════════════════════════════════════════════
   Base.css — reset, design tokens, shared utilities.
   Everything tunable lives in :root. Change values here, not further down.
   ═══════════════════════════════════════════════════════════════════════ */

:root{
  /* Tells the browser both schemes are supported, so it renders scrollbars,
     form controls and the canvas to match. ⚠️ .Hero overrides this back to
     `light` further down — the hero is never themed, so its controls must
     keep rendering light even when the OS is dark. */
  color-scheme: light dark;

  /* ── Type ─────────────────────────────────────────────────────────── */
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue",
          Helvetica, Arial, sans-serif;

  /* ── Window geometry — measured from the real myPod app ───────────── */
  --win-w: 620px;   --win-h: 566px;
  --card-w: 350px;  --card-h: 550px;
  --card-inset: 8px;
  --card-radius: 14px;
  --panel-w: 262px;
  --panel-x: 358px;                 /* 620 − 262 */
  --ipod-w: 234px;  --ipod-h: 390px;
  --ipod-top: 85px; --ipod-left: 58px;

  /* Combined bounding box of both windows (myPod + the offset signup card).
     Height is driven by the signup window, which starts at y=391 and runs
     356px tall — well past the myPod window's own 566. Keep this in sync
     with GROUP_W / GROUP_H in Scripts/Main.js. */
  --group-w: 744px; --group-h: 747px;

  /* ── Surfaces ─────────────────────────────────────────────────────── */
  --card-bg: #F3F3F3;
  /* NSColor.tertiaryLabelColor — what the real app paints every traffic light
     with when its window isn't key, and the zoom light always. */
  --tl-off: rgba(0,0,0,.25);
  --ink-50: rgba(0,0,0,.50);
  --ink-25: rgba(0,0,0,.25);
  --ink-10: rgba(0,0,0,.10);

  /* ── Shadows, named for intent ────────────────────────────────────── */
  --shadow-card: 0 2px 8px rgba(0,0,0,.12), 0 8px 20px rgba(0,0,0,.06);
  --shadow-window: 0 12px 32px rgba(0,0,0,.22), 0 40px 80px rgba(0,0,0,.18);

  /* ── Stage scale, written by Main.js ──────────────────────────────── */
  --stage-scale: 1;

  /* ── Layer order — one place, no scattered magic numbers ──────────── */
  --z-wallpaper: 0;
  --z-desktop-icons: 10;
  --z-windows: 20;
  --z-dock: 30;
  --z-menubar: 40;
  --z-tooltip: 50;
  --z-drag: 60;                     /* a dragged icon floats over everything */
  --z-modal: 100;

  /* ── Scrolling page below the hero ────────────────────────────────── */
  --page-bg:   #F5F5F7;
  --footer-bg: #EDEDEF;
  --ink:       #1D1D1F;
  --ink-soft:  #6E6E73;
  --gutter:    clamp(20px, 5vw, 64px);
  --measure:   1240px;

  /* Hero recede. --hero-scale is written per-frame by Main.js.
     ⚠️ Keep --hero-radius at or below 44px: past that the rounded corner
     starts eating the menu-bar logo and the clock. */
  --hero-scale: 1;
  --hero-radius: 30px;
}

/* ── Reset ──────────────────────────────────────────────────────────── */
*, *::before, *::after{ box-sizing: border-box; }

html{
  /* ⚠️ `clip`, not `hidden`. `overflow-x: hidden` silently turns <html> into a
     scroll container, which breaks position:sticky and scroll restoration.
     `clip` clips without any of that, and is the one value allowed to pair
     with `visible` on the other axis. Module 2 and the album scatter both
     bleed past the viewport edge on purpose and rely on this. */
  overflow-x: clip;
  /* Reserve the scrollbar space permanently so opening the video modal
     (which locks scrolling) doesn't shift the whole page sideways. */
  scrollbar-gutter: stable;
  /* What overscroll shows past the end of the page. Matching the footer makes
     rubber-banding at the bottom seamless. */
  background: var(--footer-bg);
}

/* ⚠️ min-height, NOT height. A hard `height: 100%` means everything added
   below the hero overflows a fixed-height box instead of extending the page —
   the page would simply refuse to grow. */
html, body{ min-height: 100%; }

body{
  margin: 0;
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background: var(--page-bg);
  /* `overflow: hidden` used to live here, back when the page was exactly one
     non-scrolling screen. Removing it is what lets the page scroll at all. */
}

h1, p, ul, li, figure{ margin: 0; padding: 0; }
ul{ list-style: none; }
img{ max-width: 100%; display: block; }

/* SVG icons inherit their parent's colour and size by default. */
svg{ fill: none; }

/* The sprite sheet itself must never render or take up space. */
.SpriteSheet{
  position: absolute;
  width: 0; height: 0;
  overflow: hidden;
}

/* ── Utilities ──────────────────────────────────────────────────────── */

/* Visible to screen readers, invisible on screen. */
.VisuallyHidden{
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Honeypot. Positioned off-screen rather than display:none — some spam bots
   deliberately skip fields that are hidden, which would defeat the trap. */
.Honeypot{
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

/* The desktop is a static artifact: nothing in it should look selectable. */
.Desktop{
  -webkit-user-select: none;
          user-select: none;
}

/* …except the signup window, which is the one thing you actually use. */
.Signup{
  -webkit-user-select: auto;
          user-select: auto;
}


/* ── Moving between product pages ───────────────────────────────────────
   Going from one product page to another cross-fades instead of cutting.
   Browsers that support cross-document View Transitions (Chrome, Edge,
   Safari 18.2+) do a real cross-fade: they snapshot the old page, load the
   new one, and blend the two. Page.js scrolls back to the top first, so
   what cross-fades is hero into hero.

   ⚠️ Nothing inside the hero may carry a view-transition-name. Naming an
   element makes it a backdrop root, which would cut the glass inside it
   (the dock, the windows) off from the wallpaper it blurs. The whole-page
   cross-fade needs no names at all.

   Browsers without it (Firefox, at the time of writing) get a short dip
   through black instead: Page.js fades an overlay in before leaving, and
   an inline script in each page's <head> fades it out on arrival — early
   enough that the new page never shows before the overlay does. */
@media (prefers-reduced-motion: no-preference){
  @view-transition{ navigation: auto; }
}
::view-transition-old(root),
::view-transition-new(root){
  animation-duration: .5s;
  animation-timing-function: cubic-bezier(.4, 0, .2, 1);
}

html.is-leaving::after,
html.is-arriving::after{
  content: "";
  position: fixed;
  inset: 0;
  z-index: 2147483647;
  background: #000;
  pointer-events: none;
}
html.is-leaving::after { animation: Page-dipIn  .25s ease-in  both; }
html.is-arriving::after{ animation: Page-dipOut .45s ease-out both; }
@keyframes Page-dipIn { from{ opacity: 0; } to{ opacity: 1; } }
@keyframes Page-dipOut{ from{ opacity: 1; } to{ opacity: 0; } }
