/* Armony Flow — visual language follows Apple's Liquid Glass (HIG, 2025):
   the photo is the content layer; controls float above it on glass, monochrome,
   and the glass is used only for the functional layer. */

:root {
  /* iOS dark-mode label and fill colors */
  --label: #fff;
  --label-2: rgba(235, 235, 245, 0.6);
  --label-3: rgba(235, 235, 245, 0.3);
  --fill: rgba(118, 118, 128, 0.24);
  --fill-2: rgba(118, 118, 128, 0.16);
  --separator: rgba(84, 84, 88, 0.65);

  /* motion: the iOS sheet curve and a gentle spring for selection */
  --ease-sheet: cubic-bezier(0.32, 0.72, 0, 1);
  --ease-spring: cubic-bezier(0.34, 1.3, 0.64, 1);

  /* everything scales with the shorter side of the screen: phone-sized on phones,
     comfortably large on a TV across the room */
  --btn: clamp(44px, 4.4vmin, 66px);
  --icon: calc(var(--btn) * 0.46);
  --edge: clamp(16px, 2.6vmin, 44px);
  --safe-top: max(var(--edge), env(safe-area-inset-top));
  --safe-right: max(var(--edge), env(safe-area-inset-right));
  --safe-bottom: max(var(--edge), env(safe-area-inset-bottom));
  --safe-left: max(var(--edge), env(safe-area-inset-left));
  --panel-font: clamp(15px, 0.9vmin + 8px, 19px);
  --screen-h: 100vh;
}
/* the visible height, without Safari's bars */
@supports (height: 100dvh) { :root { --screen-h: 100dvh; } }

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

html, body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #000;
  color: var(--label);
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", Inter, system-ui, "Segoe UI", Roboto, sans-serif;
  font-feature-settings: "cv11", "ss01"; /* Inter: straight-sided a and single-storey forms, closer to SF */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body.idle, body.idle * { cursor: none !important; }

button { font: inherit; color: inherit; -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
button:focus-visible { outline: 2px solid var(--label); outline-offset: 3px; }
svg { fill: currentColor; }
svg .stroke { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* ---------- Slides ---------- */
#stage { position: fixed; inset: 0; overflow: hidden; }

.slide {
  position: absolute;
  inset: 0;
  overflow: hidden;
  opacity: 0;
  transition: opacity 3s ease-in-out;
  will-change: opacity;
  transform: translateZ(0);
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}
.slide.visible { opacity: 1; }

.slide img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform-origin: center;
  will-change: transform;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

/* iPad/Safari: make the fullscreen document fill everything, with no bars */
:fullscreen { width: 100%; height: 100%; background: #000; }
:-webkit-full-screen { width: 100%; height: 100%; background: #000; }
.no-fullscreen #fsBtn { display: none; }
::backdrop { background: #000; }

.vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse at center, transparent 55%, rgba(0, 0, 0, 0.35) 100%);
}

/* ---------- Frame mode ----------
   A still photo in a mat, like a framed print. The window in the mat is cut once for the
   screen and never changes: photos fill it (cover, as in full screen) and only the photo
   crossfades. Its shape follows the screen within 1.4–1.7, so the margins stay close to
   even without cropping much; the bottom margin is a little wider, as framers do.
   The clock sits under the window, like the pencil line under a print. */
.frame {
  --mat: clamp(28px, 10vmin, 160px);
  --mat-top: var(--mat);
  --mat-bottom: calc(var(--mat) * 1.25);
  --avail-w: calc(100vw - var(--mat) * 2);
  --avail-h: calc(var(--screen-h) - var(--mat-top) - var(--mat-bottom));
  --win-w: min(var(--avail-w), var(--avail-h) * 1.7);
  --win-h: min(var(--avail-h), var(--win-w) / 1.4);
  --win-left: calc((100vw - var(--win-w)) / 2);
  --win-top: calc(var(--mat-top) + (var(--avail-h) - var(--win-h)) / 2);
  --paper: #e9e7e2;
  --bevel: #f9f8f5;
  --ink: #1d1d1f;
  --ink-2: rgba(29, 29, 31, 0.6);
}
.frame[data-mat="dark"] {
  --paper: #1c1c1e;
  --bevel: #2c2c2e;
  --ink: #fff;
  --ink-2: rgba(235, 235, 245, 0.6);
}

#stage { background-color: #000; transition: background-color 0.5s ease; }
.frame #stage {
  background-color: var(--paper);
  /* light falls from above: a touch brighter at the top of the mat */
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(0, 0, 0, 0.04));
}
.frame .vignette { display: none; }

.frame .slide,
.mat-window {
  inset: auto;
  top: var(--win-top);
  left: var(--win-left);
  width: var(--win-w);
  height: var(--win-h);
}
.frame .slide img { will-change: auto; }
/* the bevelled edge of the mat around the window, and its shadow falling onto the photo;
   it stays put while the photos change underneath */
.mat-window { display: none; position: absolute; pointer-events: none; }
.frame .mat-window {
  display: block;
  box-shadow:
    0 0 0 max(2px, 0.28vmin) var(--bevel),
    inset 0 max(1px, 0.2vmin) max(3px, 0.6vmin) rgba(0, 0, 0, 0.35);
}

/* switching frame mode on or off: the photo fades out, the layout changes, it fades back in */
#stage.switching .slide { transition-duration: 0.45s; }
#stage.switching.hiding .slide { opacity: 0; }

/* ---------- Liquid Glass ----------
   Clear variant for controls over the photo (HIG: "components that float above media").
   The ::before draws the specular rim: brighter where light hits the top-left edge. */
.glass {
  position: relative;
  isolation: isolate;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.05)),
    rgba(0, 0, 0, 0.14);
  -webkit-backdrop-filter: blur(14px) saturate(1.8);
  backdrop-filter: blur(14px) saturate(1.8);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.28), 0 1px 3px rgba(0, 0, 0, 0.18);
}
.glass::before,
#panel::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(140deg,
    rgba(255, 255, 255, 0.6) 0%,
    rgba(255, 255, 255, 0.12) 30%,
    rgba(255, 255, 255, 0.04) 60%,
    rgba(255, 255, 255, 0.28) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
  z-index: 2;
}

/* ---------- Start screen ---------- */
#start {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: #000;
  z-index: 10;
}
/* the first landscape, blurred and dimmed, waiting behind the title */
.start-bg {
  position: absolute;
  inset: -10%;
  background: center / cover no-repeat;
  filter: blur(36px) saturate(1.4) brightness(0.55);
  opacity: 0;
  transform: scale(1.08);
  transition: opacity 1.6s ease;
}
.start-bg.ready { opacity: 1; }

.start-content {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 0 24px;
}
.start-title {
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", Inter, system-ui, sans-serif;
  font-size: clamp(44px, 8vmin, 96px);
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 1;
  text-shadow: 0 2px 30px rgba(0, 0, 0, 0.3);
}
.start-tagline {
  margin-top: 0.7em;
  font-size: clamp(17px, 1.6vmin + 9px, 24px);
  letter-spacing: -0.01em;
  color: var(--label-2);
}
.start-btn {
  margin-top: clamp(28px, 5vmin, 56px);
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  min-height: 52px;
  padding: 0 1.6em 0 1.25em;
  font-size: clamp(17px, 0.8vmin + 12px, 21px);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: #000;
  background: #fff;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
  transition: transform 0.35s var(--ease-spring), opacity 0.3s ease;
}
.start-btn svg { width: 1.1em; height: 1.1em; }
.start-btn:active { transform: scale(0.95); }
.start-status {
  min-height: 1.4em;
  margin-top: 16px;
  font-size: 15px;
  color: var(--label-2);
}

/* the one orchestrated moment: title and button step back, the photo comes into focus */
#start.revealing .start-content {
  opacity: 0;
  transform: scale(0.96);
  transition: opacity 0.5s ease, transform 0.8s var(--ease-sheet);
}
#start.revealing .start-bg {
  filter: blur(0) saturate(1) brightness(1);
  transform: scale(1);
  transition: filter 1.4s var(--ease-sheet), transform 1.4s var(--ease-sheet);
}
#start.gone { opacity: 0; pointer-events: none; transition: opacity 0.9s ease 0.5s; }
#start[hidden] { display: none; }

/* ---------- Controls layer (auto-hide) ---------- */
#ui {
  position: fixed;
  inset: auto 0 0 0;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 16px;
  padding: calc(var(--edge) * 2.5) var(--safe-right) var(--safe-bottom) var(--safe-left);
  /* dimming behind clear glass so the controls stay legible over bright photos */
  background: linear-gradient(to top, rgba(0, 0, 0, 0.42), rgba(0, 0, 0, 0.12) 60%, transparent);
  transition: opacity 0.6s ease, visibility 0s linear 0s;
  z-index: 5;
}
/* visibility: hidden takes the controls (and their blur) out of compositing; with only
   opacity 0 the browser keeps re-blurring the animated photo on every frame */
body.idle #ui { opacity: 0; visibility: hidden; transition: opacity 0.8s ease, visibility 0s linear 0.8s; }

#credits {
  display: flex;
  flex-direction: column;
  gap: 0.35em;
  min-width: 0;
  font-size: clamp(12px, 0.7vmin + 7px, 16px);
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.5);
}
.credit {
  display: flex;
  align-items: center;
  gap: 0.45em;
  min-width: 0;
  white-space: nowrap;
}
.credit svg { width: 1.05em; height: 1.05em; flex-shrink: 0; opacity: 0.8; }
.credit a {
  color: var(--label);
  font-weight: 500;
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  flex-shrink: 1;
  min-width: 2em;
}
.credit a:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.credit .meta { color: rgba(255, 255, 255, 0.68); overflow: hidden; text-overflow: ellipsis; flex-shrink: 2; }

#controls { display: flex; gap: calc(var(--btn) * 0.28); flex-shrink: 0; align-items: center; }

.capsule {
  display: flex;
  align-items: center;
  gap: calc(var(--btn) * 0.04);
  padding: calc(var(--btn) * 0.1);
  border-radius: 999px;
}
.capsule button {
  position: relative;
  z-index: 1;
  width: var(--btn);
  height: var(--btn);
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--label);
  cursor: pointer;
  transition: background 0.2s ease, transform 0.4s var(--ease-spring);
}
.capsule button svg { width: var(--icon); height: var(--icon); filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.15)); }
.capsule button.primary { width: calc(var(--btn) * 1.15); }
.capsule button.primary svg { width: calc(var(--icon) * 1.3); height: calc(var(--icon) * 1.3); }
/* press state: the glass lights up under the finger and the glyph dips */
.capsule button:active { background: rgba(255, 255, 255, 0.2); transform: scale(0.88); }
.capsule button[aria-expanded="true"] { background: rgba(255, 255, 255, 0.24); }
/* sleep timer running: a pill with a moon and the time left */
.capsule button.sleep-btn {
  width: auto;
  display: flex;
  gap: 0.35em;
  padding: 0 calc(var(--btn) * 0.3) 0 calc(var(--btn) * 0.24);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.16);
  font: inherit;
  font-size: calc(var(--icon) * 0.62);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.capsule button.sleep-btn[hidden] { display: none; }
.capsule button.sleep-btn svg { width: calc(var(--icon) * 0.8); height: calc(var(--icon) * 0.8); }

/* favorite heart, next to the credits */
.credits-row { display: flex; align-items: center; gap: 0.5em; min-width: 0; }
.fav-btn {
  flex-shrink: 0;
  width: calc(var(--btn) * 0.8);
  height: calc(var(--btn) * 0.8);
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--label);
  cursor: pointer;
  filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.45));
  transition: transform 0.4s var(--ease-spring);
}
.fav-btn svg { width: 58%; height: 58%; }
.fav-btn .i-heart-fill { display: none; }
.fav-btn[aria-pressed="true"] .i-heart { display: none; }
.fav-btn[aria-pressed="true"] .i-heart-fill { display: block; animation: heart-pop 0.45s var(--ease-spring); }
.fav-btn:active { transform: scale(0.85); }
@keyframes heart-pop { 0% { transform: scale(0.6); } 60% { transform: scale(1.18); } }

/* Clock in the spirit of the iOS 26 Lock Screen: white numerals with the date just above.
   Roboto Flex is a variable font, so "large" is a genuinely condensed, taller design
   (width and figure-height axes) rather than stretched glyphs. */
.clock {
  --base: clamp(64px, min(36vw, 22vh), 340px);
  --scale: 1;
  --clock-size: calc(var(--base) * var(--scale));
  --wdth: 100;
  --wght: 560;
  --ytfi: 738;
  --track: -0.025em;
  position: fixed;
  top: calc(var(--safe-top) + 1.5vh);
  z-index: 4;
  display: flex;
  flex-direction: column;
  pointer-events: none;
  color: #fff;
  font-family: "Roboto Flex", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
}
.clock[hidden] { display: none; }
.clock[data-size="small"] { --scale: 0.58; --wght: 600; }
/* tall and narrow, like the adaptive Lock Screen clock */
.clock[data-size="large"] {
  --clock-size: clamp(120px, min(70vw, 48vh), 620px);
  --wdth: 28;
  --wght: 440;
  --ytfi: 788;
  --track: 0em;
}
.clock[data-pos="left"] { left: var(--safe-left); align-items: flex-start; }
.clock[data-pos="center"] { left: 0; right: 0; align-items: center; }
.clock[data-pos="right"] { right: var(--safe-right); align-items: flex-end; }
/* a desk clock: centered and a size up */
.clock[data-pos="middle"] {
  --base: clamp(72px, min(36vw, 27vh), 420px);
  inset: 0;
  align-items: center;
  justify-content: center;
}
.clock[data-pos="middle"][data-size="large"] { --clock-size: clamp(140px, min(72vw, 60vh), 700px); }

.clock-date {
  font-size: max(15px, calc(var(--base) * 0.2 * min(1, var(--scale) + 0.25)));
  font-weight: 600;
  font-variation-settings: "wdth" 100, "opsz" 24;
  letter-spacing: 0;
  color: rgba(255, 255, 255, 0.92);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.16), 0 4px 18px rgba(0, 0, 0, 0.28);
  margin-bottom: calc(var(--clock-size) * -0.04);
}
.clock-time {
  font-size: var(--clock-size);
  font-weight: var(--wght);
  font-variation-settings: "wdth" var(--wdth), "YTFI" var(--ytfi), "opsz" 144;
  line-height: 1.05;
  letter-spacing: var(--track);
  color: #fff;
  /* a close shadow for the edge and a long, soft one for depth over bright photos */
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.16), 0 12px 48px rgba(0, 0, 0, 0.26);
}

/* Frame mode: the clock is a single line printed on the mat under the window, like the
   pencil line under a print, lined up with the window's left edge, center or right edge.
   It never takes space from the photo. In the middle of the screen it stays over the photo. */
.frame .clock:not([data-pos="middle"]) {
  --cap: max(15px, var(--mat) * 0.42);
  top: calc(var(--win-top) + var(--win-h) + var(--mat) * 0.3);
  left: var(--win-left);
  right: auto;
  width: var(--win-w);
  flex-direction: row;
  align-items: baseline;
  gap: 0.55em;
  font-size: var(--cap);
}
.frame .clock[data-size="small"]:not([data-pos="middle"]) { --cap: max(13px, var(--mat) * 0.32); }
.frame .clock[data-size="large"]:not([data-pos="middle"]) { --cap: max(18px, var(--mat) * 0.56); }
.frame .clock[data-pos="left"] { justify-content: flex-start; }
.frame .clock[data-pos="center"] { justify-content: center; }
.frame .clock[data-pos="right"] { justify-content: flex-end; }
.frame .clock:not([data-pos="middle"]) .clock-time {
  order: 1;
  font-size: 1em;
  font-weight: 500;
  font-variation-settings: "wdth" 100, "opsz" 32;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-shadow: none;
}
.frame .clock:not([data-pos="middle"]) .clock-date {
  order: 2;
  margin: 0;
  font-size: max(11px, 0.5em);
  font-weight: 500;
  color: var(--ink-2);
  text-shadow: none;
}
.clock-time, .clock-date { transition: color 0.5s ease; }
/* the controls share the bottom of the mat: the clock line steps aside while they show,
   but stays while the panel is open, so changes to it can be seen */
.frame .clock:not([data-pos="middle"]) { transition: opacity 0.8s ease; }
.frame:not(.idle):not(.panel-open):not(.receiver) .clock:not([data-pos="middle"]) { opacity: 0; transition-duration: 0.3s; }

/* glass pill that confirms an action for a moment */
.toast {
  position: fixed;
  top: var(--safe-top);
  left: 50%;
  z-index: 30;
  max-width: calc(100vw - 32px);
  padding: 0.7em 1.3em;
  border-radius: 999px;
  font-size: 15px;
  font-weight: 500;
  text-align: center;
  opacity: 0;
  transform: translate(-50%, -12px) scale(0.96);
  transition: opacity 0.3s ease, transform 0.45s var(--ease-spring);
  pointer-events: none;
}
.toast.show { opacity: 1; transform: translate(-50%, 0) scale(1); }
.toast[hidden] { display: none; }

/* sleep timer: the screen fades to black, then waits for a tap */
.sleep-shade {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: grid;
  place-items: center;
  background: #000;
  opacity: 0;
  transition-property: opacity;
  transition-timing-function: linear;
  pointer-events: none;
}
.sleep-shade[hidden] { display: none; }
.sleep-shade.dark { opacity: 1; }
.sleep-shade.asleep { pointer-events: auto; cursor: pointer; }
.sleep-shade p { font-size: 17px; color: var(--label-3); opacity: 0; transition: opacity 2s ease 1s; }
.sleep-shade.asleep p { opacity: 1; }

/* ---------- Settings panel ----------
   Regular Liquid Glass: it holds a lot of text, so it blurs and darkens more (HIG). */
#panel {
  position: fixed;
  right: var(--safe-right);
  bottom: calc(var(--safe-bottom) + var(--btn) * 1.2 + 14px);
  width: clamp(360px, 25em, 480px);
  /* fixed height, so switching tabs doesn't make the panel jump */
  height: min(44em, calc(100dvh - var(--safe-top) - var(--safe-bottom) - var(--btn) * 1.2 - 14px));
  display: flex;
  flex-direction: column;
  font-size: var(--panel-font);
  letter-spacing: -0.01em;
  border-radius: 1.9em;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0) 30%),
    rgba(30, 30, 34, 0.62);
  -webkit-backdrop-filter: blur(44px) saturate(1.8);
  backdrop-filter: blur(44px) saturate(1.8);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.2);
  overflow: hidden;
  z-index: 6;
  transform-origin: calc(100% - var(--btn) * 3) 100%; /* grows out of the playlist button */
  animation: panel-in 0.5s var(--ease-sheet);
}
#panel[hidden] { display: none; }
#panel.closing { animation: panel-out 0.22s ease-in forwards; }
@keyframes panel-in { from { opacity: 0; transform: scale(0.9) translateY(16px); } }
@keyframes panel-out { to { opacity: 0; transform: scale(0.94) translateY(10px); } }

.grabber { display: none; }

.panel-head {
  display: flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.75em 0.75em 0.5em;
  flex-shrink: 0;
}

.icon-btn {
  flex-shrink: 0;
  width: 2.3em;
  height: 2.3em;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: var(--fill);
  color: var(--label-2);
  cursor: pointer;
  transition: transform 0.4s var(--ease-spring), background 0.2s ease;
}
.icon-btn svg { width: 0.95em; height: 0.95em; }
.icon-btn svg .stroke { stroke-width: 2.6; }
.icon-btn:active { transform: scale(0.88); }

/* segmented control with a sliding thumb; --count options, --index selected (set in JS) */
.segmented {
  position: relative;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  padding: 2px;
  border-radius: 999px;
  background: var(--fill);
}
.segmented .thumb {
  position: absolute;
  top: 2px;
  bottom: 2px;
  left: 2px;
  width: calc((100% - 4px) / var(--count, 2));
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.22);
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.18), inset 0 0.5px 0 rgba(255, 255, 255, 0.4);
  transform: translateX(calc(var(--index, 0) * 100%));
  transition: transform 0.45s var(--ease-spring);
}
.segmented button {
  position: relative;
  z-index: 1;
  min-height: 2.15em;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--label-2);
  font-weight: 500;
  cursor: pointer;
  transition: color 0.25s ease;
}
.segmented button[aria-selected="true"],
.segmented button[aria-pressed="true"] { color: var(--label); font-weight: 600; }
.tabs { flex: 1; }
.tab { font-size: 0.92em; }
.picker { width: 100%; }
.picker.icons button { min-height: 2.5em; }
.picker.icons svg { width: 1.7em; height: 1.7em; }
.picker.icons svg .stroke { stroke-width: 1.5; }
.clock-options { flex-direction: column; align-items: stretch; gap: 0.5em; }
.picker button { min-height: 2.3em; font-size: 0.88em; font-variant-numeric: tabular-nums; }
.lang button { min-width: 2.5em; font-size: 0.8em; letter-spacing: 0.02em; }

/* the only scroll container in the panel; its edges fade like iOS scroll edge effects */
.panel-body {
  position: relative; /* offsetParent for scrolling to the current track */
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 0.6em 0.9em 1.2em;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 0.8em, #000 calc(100% - 1.4em), transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 0.8em, #000 calc(100% - 1.4em), transparent);
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.2) transparent;
}

/* style cards: artwork tile with the name underneath, like albums in Apple Music */
.music-cards {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 0.55em;
}
.photo-cards {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1em 0.7em;
}
.music-card, .photo-card {
  display: flex;
  flex-direction: column;
  gap: 0.45em;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
}
.art {
  position: relative;
  display: grid;
  place-items: center;
  width: 100%;
  overflow: hidden;
  border-radius: 0.95em; /* concentric with the panel corner */
  transition: transform 0.4s var(--ease-spring), box-shadow 0.25s ease;
}
.music-card .art {
  aspect-ratio: 1;
  /* Control Center module: translucent tile, white glyph; the active one turns solid white */
  background: rgba(255, 255, 255, 0.1);
  box-shadow: inset 0 0.5px 0 rgba(255, 255, 255, 0.25);
  color: var(--label);
  transition: transform 0.4s var(--ease-spring), background 0.25s ease, color 0.25s ease;
}
.music-card .art svg { width: 44%; height: 44%; }
.music-card .art svg .stroke { stroke-width: 1.8; }
.music-card .art svg .thin { stroke-width: 1.4; }
.photo-card .art { aspect-ratio: 4 / 3; background: var(--fill-2); }
.photo-card .art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* "Everything" is the odd one out: give it the full width */
.photo-card:last-child:nth-child(odd) { grid-column: span 2; }
.photo-card:last-child:nth-child(odd) .art { aspect-ratio: 21 / 8; }

.card-name {
  max-width: 100%;
  padding: 0 0.15em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.87em;
  color: var(--label-2);
  transition: color 0.2s ease;
}
.music-card .card-name { font-size: 0.78em; text-align: center; }

/* selection, monochrome like the rest of the controls */
.music-card[aria-pressed="true"] .art { background: rgba(255, 255, 255, 0.92); color: #000; box-shadow: none; }
[aria-pressed="true"] > .card-name { color: var(--label); font-weight: 600; }
/* photo covers get a checkmark badge, as in Photos */
.photo-card[aria-pressed="true"] .art::after {
  content: '';
  position: absolute;
  right: 0.5em;
  bottom: 0.5em;
  width: 1.45em;
  height: 1.45em;
  border-radius: 50%;
  background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6.5 12.5l3.6 3.6 7.4-8.2' fill='none' stroke='%23000' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 72% no-repeat;
  box-shadow: 0 0 0 1.5px rgba(0, 0, 0, 0.25), 0 2px 6px rgba(0, 0, 0, 0.3);
}
.music-card:active .art, .photo-card:active .art { transform: scale(0.95); }

.list-head.first { margin-top: 0.2em; }
.list-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin: 1.5em 0.2em 0.3em;
  font-size: 1.3em;
  font-weight: 700;
  letter-spacing: -0.02em;
}
#trackCount { font-size: 0.62em; font-weight: 400; letter-spacing: 0; color: var(--label-2); }

/* grouped list with inset separators */
#trackList { list-style: none; }
#trackList button {
  width: 100%;
  display: grid;
  grid-template-columns: 2.2em 1fr;
  align-items: center;
  text-align: left;
  border: 0;
  border-radius: 0.7em;
  background: none;
  padding: 0 0.6em 0 0;
  cursor: pointer;
  transition: background 0.15s ease;
}
#trackList button:active { background: var(--fill-2); }
#trackList li + li .track-text { box-shadow: inset 0 0.5px 0 var(--separator); }
.track-num {
  justify-self: center;
  font-size: 0.8em;
  font-variant-numeric: tabular-nums;
  color: var(--label-3);
}
.track-text {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.1em;
  min-width: 0;
  min-height: 3.3em;
  padding: 0.55em 0;
}
.track-title { font-size: 0.97em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.track-artist { font-size: 0.82em; color: var(--label-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#trackList .current .track-title { font-weight: 600; }
#trackList .empty { font-size: 0.9em; color: var(--label-2); padding: 0.8em 0.2em; }

/* equalizer on the playing track */
#trackList .current .track-num {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 0.95em;
  color: var(--label);
}
#trackList .current .track-num i {
  width: 3px;
  height: 100%;
  border-radius: 1.5px;
  background: currentColor;
  transform-origin: bottom;
  animation: eq 0.9s ease-in-out infinite alternate;
}
#trackList .current .track-num i:nth-child(2) { animation-delay: -0.3s; animation-duration: 0.7s; }
#trackList .current .track-num i:nth-child(3) { animation-delay: -0.6s; animation-duration: 1.1s; }
@keyframes eq { from { transform: scaleY(0.25); } to { transform: scaleY(1); } }
body.paused #trackList .current .track-num i { animation-play-state: paused; }

/* sliders, iOS style: thin track that fills in white, round white knob */
.slider {
  -webkit-appearance: none;
  appearance: none;
  flex: 1;
  min-width: 0;
  height: 1.8em;
  background: transparent;
  cursor: pointer;
  --fill: 50%;
}
.slider::-webkit-slider-runnable-track {
  height: 0.38em;
  border-radius: 999px;
  background: linear-gradient(to right, var(--label) var(--fill), rgba(255, 255, 255, 0.18) var(--fill));
}
.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 1.45em;
  height: 1.45em;
  margin-top: -0.535em;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3), 0 0 0 0.5px rgba(0, 0, 0, 0.1);
  transition: transform 0.3s var(--ease-spring);
}
.slider:active::-webkit-slider-thumb { transform: scale(1.12); }
.slider::-moz-range-track { height: 0.38em; border-radius: 999px; background: rgba(255, 255, 255, 0.18); }
.slider::-moz-range-progress { height: 0.38em; border-radius: 999px; background: var(--label); }
.slider::-moz-range-thumb { width: 1.45em; height: 1.45em; border: 0; border-radius: 50%; background: #fff; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); }
.slider:focus-visible { outline: none; }
.slider:focus-visible::-webkit-slider-thumb { outline: 2px solid var(--label); outline-offset: 2px; }

.volume-row {
  display: flex;
  align-items: center;
  gap: 0.7em;
  margin: 0.2em 0.2em 1.2em;
  color: var(--label-2);
}
.volume-row svg { width: 1.2em; height: 1.2em; flex-shrink: 0; }

/* nature sounds use the grouped rows below; each sound is a row plus its volume */
.ambient-item + .ambient-item > .row:first-child { box-shadow: inset 0 0.5px 0 var(--separator); }
.ambient-item .row-control { padding-left: 3.55em; } /* the slider lines up with the label */

/* Display tab: grouped rows, like Settings */
.group {
  margin-bottom: 0.9em;
  border-radius: 1em;
  background: rgba(255, 255, 255, 0.07);
  overflow: hidden;
}
.row {
  width: 100%;
  min-height: 3.1em;
  display: flex;
  align-items: center;
  gap: 0.75em;
  padding: 0.35em 0.9em;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
  transition: background 0.15s ease;
}
.row[hidden] { display: none; }
.row + .row:not(.row-control) { box-shadow: inset 0 0.5px 0 var(--separator); }
button.row:active { background: var(--fill-2); }
.row-control { min-height: 0; padding: 0 0.9em 0.9em; cursor: default; }
.row-icon {
  width: 1.9em;
  height: 1.9em;
  flex-shrink: 0;
  display: grid;
  place-items: center;
  border-radius: 0.5em;
  background: rgba(255, 255, 255, 0.14);
}
.row-icon svg { width: 1.15em; height: 1.15em; }
.row-icon svg .stroke { stroke-width: 1.8; }
.row-label { flex: 1; min-width: 0; font-size: 0.97em; }
.row-value { font-size: 0.9em; color: var(--label-2); white-space: nowrap; }
.group-note {
  margin: -0.4em 0.9em 1.2em;
  font-size: 0.8em;
  line-height: 1.4;
  color: var(--label-2);
}
.group-note[hidden] { display: none; }

/* iOS switch */
.switch {
  -webkit-appearance: none;
  appearance: none;
  flex-shrink: 0;
  position: relative;
  width: 3.15em;
  height: 1.9em;
  border-radius: 999px;
  background: rgba(120, 120, 128, 0.32);
  cursor: pointer;
  transition: background 0.25s ease;
}
.switch::before {
  content: '';
  position: absolute;
  top: 0.12em;
  left: 0.12em;
  width: 1.66em;
  height: 1.66em;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15), 0 3px 1px rgba(0, 0, 0, 0.06);
  transition: transform 0.35s var(--ease-spring);
}
.switch:checked { background: #34c759; }
.switch:checked::before { transform: translateX(1.25em); }
.switch:focus-visible { outline: 2px solid var(--label); outline-offset: 2px; }

/* favorites card before there is any favorite */
.photo-card.empty .art svg { width: 26%; height: 26%; color: var(--label-2); }

/* on the TV there is nothing to press */
body.receiver #ui,
body.receiver #panel,
body.receiver #start { display: none; }
body.receiver { cursor: none; }

/* hover only where there is a real pointer; on touch it sticks after a tap */
@media (hover: hover) {
  .capsule button:hover { background: rgba(255, 255, 255, 0.14); }
  .capsule button[aria-expanded="true"]:hover { background: rgba(255, 255, 255, 0.3); }
  .icon-btn:hover { background: rgba(118, 118, 128, 0.36); color: var(--label); }
  .segmented button:hover { color: var(--label); }
  .music-card:hover .art, .photo-card:hover .art { transform: scale(1.03); }
  .music-card[aria-pressed="false"]:hover .art { background: rgba(255, 255, 255, 0.16); }
  .fav-btn:hover { transform: scale(1.08); }
  .music-card:hover .card-name, .photo-card:hover .card-name { color: var(--label); }
  #trackList button:hover { background: var(--fill-2); }
  .start-btn:hover { transform: scale(1.03); }
}

/* Icon states */
.i-play, .i-muted, .i-shrink { display: none; }
body.paused .i-pause { display: none; }
body.paused .i-play { display: block; }
body.muted .i-sound { display: none; }
body.muted .i-muted { display: block; }
body.fullscreen .i-expand { display: none; }
body.fullscreen .i-shrink { display: block; }

/* ---------- Phones, portrait ----------
   Controls centered with the credits under them; the panel becomes a floating sheet
   with a grabber that can be dragged down to dismiss. */
@media (max-width: 600px) and (orientation: portrait) {
  :root { --btn: clamp(42px, 11.5vw, 50px); --panel-font: 16px; }
  #ui { flex-direction: column-reverse; align-items: stretch; gap: 14px; }
  #controls { justify-content: center; gap: clamp(8px, 3vw, 14px); }
  .credits-row { justify-content: center; }
  #credits { align-items: center; }
  .credit { max-width: 100%; }

  #panel {
    left: 8px;
    right: 8px;
    bottom: max(8px, env(safe-area-inset-bottom));
    width: auto;
    height: min(82dvh, 46em);
    border-radius: 2.2em; /* concentric with the phone's screen corners */
    transform-origin: 50% 100%;
    animation: sheet-in 0.55s var(--ease-sheet);
  }
  #panel.closing { animation: sheet-out 0.3s var(--ease-sheet) forwards; }
  #panel.dragging { animation: none; transition: none; }
  .grabber {
    display: block;
    flex-shrink: 0;
    align-self: center;
    width: 36px;
    height: 5px;
    margin: 6px 0 -2px;
    border-radius: 3px;
    background: var(--label-3);
    touch-action: none;
  }
  /* the grabber and header drag the sheet, so the browser must not treat that as scrolling */
  .panel-head { padding-top: 0.6em; touch-action: none; }
  /* a narrower mat, so the print isn't lost in paper on a tall screen */
  .frame { --mat: 6vw; }
}
@keyframes sheet-in { from { transform: translateY(105%); } }
@keyframes sheet-out { to { transform: translateY(105%); } }

/* ---------- Short screens (phones in landscape) ----------
   The panel becomes a full-height side sheet so nothing gets squeezed. */
@media (max-height: 540px) and (orientation: landscape) {
  :root { --btn: 42px; --edge: 14px; --panel-font: 14px; }
  #ui { padding-top: 28px; }
  #credits { font-size: 12px; }
  #panel {
    top: var(--safe-top);
    bottom: var(--safe-bottom);
    height: auto;
    width: min(420px, 55vw);
    transform-origin: 100% 50%;
  }
  .photo-cards { grid-template-columns: repeat(3, 1fr); }
  .photo-card:last-child:nth-child(odd) { grid-column: auto; }
  .photo-card:last-child:nth-child(odd) .art { aspect-ratio: 4 / 3; }
}

/* ---------- Very small phones (iPhone SE 1st gen, 320px) ---------- */
@media (max-width: 340px) {
  :root { --btn: 38px; --panel-font: 15px; }
  #controls { gap: 6px; }
}

/* ---------- Lite mode (TVs, weak GPUs; see app.js) ----------
   The live blur is redrawn every frame over the moving photo; solid glass costs nothing. */
.lite .glass { background: rgba(40, 40, 44, 0.9); -webkit-backdrop-filter: none; backdrop-filter: none; }
.lite #panel { background: rgb(28, 28, 30); -webkit-backdrop-filter: none; backdrop-filter: none; }
.lite .capsule button svg { filter: none; }

/* ---------- Accessibility settings ---------- */
@media (prefers-reduced-transparency: reduce) {
  .glass { background: rgba(40, 40, 44, 0.94); -webkit-backdrop-filter: none; backdrop-filter: none; }
  #panel { background: rgb(28, 28, 30); -webkit-backdrop-filter: none; backdrop-filter: none; }
}
@media (prefers-contrast: more) {
  :root { --label-2: rgba(235, 235, 245, 0.85); --label-3: rgba(235, 235, 245, 0.6); --separator: rgba(255, 255, 255, 0.4); }
  .glass { background: rgba(20, 20, 22, 0.8); }
  .glass::before, #panel::after { background: rgba(255, 255, 255, 0.5); }
}
@media (prefers-reduced-motion: reduce) {
  .slide { transition-duration: 1s; }
  #panel, #panel.closing { animation: none; }
  #start.revealing .start-bg { transition-duration: 0.01s; }
  #trackList .current .track-num i { animation: none; transform: scaleY(0.6); }
  .segmented .thumb { transition: none; }
  .fav-btn[aria-pressed="true"] .i-heart-fill { animation: none; }
  .toast { transition: opacity 0.2s ease; }
}
