/*
 * The page: the wallpaper fills the window and the settings float over it
 * at the top right (a sheet under the stage on phones). The glass surfaces
 * keep to the space left of the panel. The material itself is in
 * glass.css.
 */

@property --u { syntax: '<length>'; inherits: true; initial-value: 1px; }

:root {
  --panel-w: 300px;
  --panel-gap: 12px;
  /* The width the floating panel takes from the stage. */
  --panel-space: calc(var(--panel-w) + var(--panel-gap) * 2);
  /* The settings sliding in and out; playground.js glides the surfaces
     with the same timing. */
  --ui-ease: cubic-bezier(0.32, 0.72, 0, 1);
  --ui-time: 420ms;
  --font: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Inter', 'Helvetica Neue', 'PingFang SC', sans-serif;
  color-scheme: dark;
}

html,
body {
  height: 100%;
  margin: 0;
  overflow: hidden;
  background: #0b0c0e;
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
}

body[data-ui="off"] { --panel-space: 0px; }

.view {
  position: fixed;
  inset: 0;
  container-type: size;
  overflow: hidden;
}

/* One Lumno pixel at the size of the space left of the panel: the surfaces
   keep their proportions from a phone with the settings up to a large
   display. */
.stage {
  --u: clamp(0.56px, min((100cqw - var(--panel-space)) / 760, 100cqh / 640), 1.5px);
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: #6f8fc4;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}

/* ---------- The wallpaper ---------- */

.wall {
  position: absolute;
  inset: 0;
  /* Its own layer, so the scene canvas and your own file stay under the glass. */
  z-index: 0;
}

.wall > * {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}

/* A light and dark pair (Tahoe's videos, Apple's other wallpapers): the
   dark one fades in over the light one with the theme. */
.wall .is-pair { position: absolute; inset: 0; }
.wall .is-pair > * { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.wall .is-dark { opacity: 0; transition: opacity 620ms ease; }
.stage[data-theme="dark"] .wall .is-dark { opacity: 1; }
.wall .is-scene { z-index: 1; }

/* The glass's backdrop drawn in WebGL (refract.js), between the wallpaper
   and the surfaces, where backdrop-filter can't take the lens. */
.refraction {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.refraction[hidden] { display: none; }
.wall .is-media { z-index: 2; }
.wall [hidden] { display: none; }

/* ---------- The surfaces ---------- */

.surfaces {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(22 * var(--u));
  padding: calc(24 * var(--u));
  padding-right: calc(24 * var(--u) + var(--panel-space));
  /* Room for the toolbar along the bottom. */
  padding-bottom: calc(24 * var(--u) + 64px);
  pointer-events: none;
}

.surfaces > * {
  /* A dragged surface moves by its offsets. */
  position: relative;
  left: var(--dx, 0px);
  top: var(--dy, 0px);
  pointer-events: auto;
  touch-action: none;
  cursor: grab;
}

.surfaces > [data-dragging] { cursor: grabbing; }

.stage svg {
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.stage svg .fill { fill: currentColor; stroke: none; }

.surfaces button {
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* Search: a pill with a field in it. */
.search {
  display: flex;
  align-items: center;
  gap: calc(10 * var(--u));
  box-sizing: border-box;
  width: min(calc(440 * var(--u)), 100%);
  height: calc(52 * var(--u));
  padding: 0 calc(18 * var(--u));
}

.search svg { flex: none; width: calc(20 * var(--u)); height: calc(20 * var(--u)); }

.search input {
  flex: 1;
  min-width: 0;
  padding: 0;
  border: 0;
  outline: 0;
  background: none;
  color: var(--ink);
  font: 500 calc(16 * var(--u)) / 1 var(--font);
  cursor: text;
  user-select: text;
}

.search input::placeholder { color: var(--ink-2); }

.search kbd {
  flex: none;
  font: 500 calc(12 * var(--u)) / 1 var(--font);
  letter-spacing: 0.04em;
}

/* Now playing: one slab of glass. */
.player {
  box-sizing: border-box;
  width: min(calc(340 * var(--u)), 100%);
  padding: calc(18 * var(--u)) calc(18 * var(--u)) calc(14 * var(--u));
}

.p-top { display: flex; align-items: center; gap: calc(14 * var(--u)); }

.p-art {
  flex: none;
  width: calc(64 * var(--u));
  height: calc(64 * var(--u));
  /* Inner radius = outer radius - padding, so the art and the card share
     one corner center. */
  border-radius: calc(max(4, var(--radius, 28) - 18) * var(--u));
  corner-shape: superellipse(var(--corner-k, 1));
  background:
    radial-gradient(120% 90% at 20% 15%, #ffd6a8 0%, transparent 55%),
    radial-gradient(100% 80% at 85% 80%, #5a7cff 0%, transparent 60%),
    linear-gradient(140deg, #ff7a8a, #8a5cff 55%, #2bc4ff);
  box-shadow: 0 calc(4 * var(--u)) calc(12 * var(--u)) rgb(0 0 0 / 0.16);
}

.p-track { display: grid; gap: calc(3 * var(--u)); min-width: 0; }
.p-track b { font: 600 calc(17 * var(--u)) / 1.2 var(--font); }
.p-track span { font: 500 calc(14 * var(--u)) / 1.2 var(--font); }

.p-time {
  display: flex;
  justify-content: space-between;
  margin-top: calc(16 * var(--u));
  font: 500 calc(11 * var(--u)) / 1 var(--font);
  font-variant-numeric: tabular-nums;
}

.p-progress {
  position: relative;
  display: block;
  height: calc(5 * var(--u));
  margin-top: calc(7 * var(--u));
  border-radius: 99px;
  background: var(--well);
}

.p-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  /* Its own rounded ends: the track doesn't clip (see glass.css). */
  min-width: calc(5 * var(--u));
  border-radius: inherit;
  background: var(--ink-solid);
  opacity: var(--ink-a);
}

.p-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(34 * var(--u));
  margin-top: calc(10 * var(--u));
}

/* Drawn to the proportions of SF Symbols' backward.fill, pause.fill,
   play.fill and forward.fill. A round-joined stroke rounds the triangles;
   its width keeps the corner radius near 9% of each glyph's height, like
   the rx on the pause bars. */
.p-side svg { width: calc(28 * var(--u)); height: calc(28 * var(--u)); }
.p-main svg { width: calc(44 * var(--u)); height: calc(44 * var(--u)); }
.p-controls .solid { fill: currentColor; }
.p-side .solid { stroke-width: 2.6; }
.p-main .solid { stroke-width: 3.8; }
.p-controls button { border-radius: 50%; padding: calc(4 * var(--u)); }
.p-main .is-play { display: none; }
.stage[data-paused] .p-main .is-play { display: block; }
.stage[data-paused] .p-main .is-pause { display: none; }

/* The tint control. */
.tint {
  display: flex;
  align-items: center;
  gap: calc(12 * var(--u));
  box-sizing: border-box;
  width: min(calc(300 * var(--u)), 100%);
  height: calc(48 * var(--u));
  padding: 0 calc(18 * var(--u));
}

.tint-label { font: 600 calc(14 * var(--u)) / 1 var(--font); }

.tint-value {
  min-width: 3.2em;
  text-align: right;
  font: 600 calc(13 * var(--u)) / 1 var(--font);
  font-variant-numeric: tabular-nums;
}

.tint-range {
  --p: 66.6%;
  flex: 1;
  min-width: 0;
  height: calc(28 * var(--u));
  margin: 0;
  background: none;
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
}

.tint-range::-webkit-slider-runnable-track {
  height: calc(6 * var(--u));
  border-radius: 99px;
  background: linear-gradient(90deg, var(--ink-solid) var(--p), var(--well) var(--p));
}

.tint-range::-moz-range-track {
  height: calc(6 * var(--u));
  border-radius: 99px;
  background: linear-gradient(90deg, var(--ink-solid) var(--p), var(--well) var(--p));
}

.tint-range::-webkit-slider-thumb {
  width: calc(24 * var(--u));
  height: calc(24 * var(--u));
  margin-top: calc(-9 * var(--u));
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 0.5px rgb(0 0 0 / 0.08), 0 calc(2 * var(--u)) calc(6 * var(--u)) rgb(0 0 0 / 0.2);
  appearance: none;
  -webkit-appearance: none;
}

.tint-range::-moz-range-thumb {
  width: calc(24 * var(--u));
  height: calc(24 * var(--u));
  border: 0;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 0.5px rgb(0 0 0 / 0.08), 0 calc(2 * var(--u)) calc(6 * var(--u)) rgb(0 0 0 / 0.2);
}

/* The toolbar: one pill along the bottom of the free space, its buttons
   lit on hover rather than glass of their own (glass on glass doubles the
   blur). It is the page's own control, so it keeps a modest size instead
   of growing with the stage, and stays put while the surfaces above it
   can be dragged. */
.toolbar {
  --b: clamp(34px, calc(34 * var(--u)), 40px);
  /* Centred by its margins, and above the surfaces by its place in the
     page. */
  position: absolute;
  left: 0;
  right: var(--panel-space);
  width: max-content;
  margin: 0 auto;
  bottom: 16px;
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 4px;
  border-radius: 999px;
}

.toolbar :is(button, a) {
  position: relative;
  display: grid;
  place-items: center;
  width: var(--b);
  height: var(--b);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: inherit;
  cursor: pointer;
  transition: background-color 160ms ease;
  -webkit-tap-highlight-color: transparent;
}

.toolbar svg { width: 19px; height: 19px; }
.toolbar a svg { width: 17px; height: 17px; }
.toolbar .sep { width: 1px; height: 18px; margin: 0 4px; background: var(--well); }
/* A switch that is off: its icon struck through and dimmed. */
.toolbar svg .off { display: none; }
.toolbar [aria-pressed="false"] svg .off { display: inline; }
.toolbar[class] [aria-pressed="false"] svg.ink { opacity: calc(var(--ink-a) * 0.45); }
.toolbar .moon,
.toolbar .is-play { display: none; }
.stage[data-theme="dark"] .toolbar .sun,
.stage[data-paused] .toolbar .is-pause { display: none; }
.stage[data-theme="dark"] .toolbar .moon,
.stage[data-paused] .toolbar .is-play { display: block; }

/* A tip above each button: what it does and its key. */
.toolbar [data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 14px);
  left: 50%;
  translate: -50% 4px;
  padding: 7px 11px;
  border-radius: 10px;
  background: rgb(24 24 28 / 0.82);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
  box-shadow: inset 0 0 0 0.5px rgb(255 255 255 / 0.12), 0 6px 18px rgb(0 0 0 / 0.2);
  color: rgb(255 255 255 / 0.94);
  font: 500 12px / 1 var(--font);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 140ms ease, translate 140ms ease;
}

@media (hover: hover) {
  .surfaces button:hover,
  .toolbar :is(button, a):hover { background-color: var(--row-hover); }
  .toolbar [data-tip]:hover::after { opacity: 1; translate: -50% 0; transition-delay: 250ms; }
}

.toolbar [data-tip]:focus-visible::after { opacity: 1; translate: -50% 0; }
.surfaces button:active,
.toolbar :is(button, a):active { background-color: var(--row-active); }
.surfaces button:focus-visible,
.toolbar :is(button, a):focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }

/* ---------- Loading and credit ---------- */

/* The loading note, at the top of the space left of the panel. */
.notice {
  position: absolute;
  z-index: 5;
  top: 16px;
  left: calc((100% - var(--panel-space)) / 2);
  translate: -50% 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-radius: 999px;
  background: rgb(24 24 28 / 0.72);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
  box-shadow: inset 0 0 0 0.5px rgb(255 255 255 / 0.14), 0 6px 20px rgb(0 0 0 / 0.2);
  color: rgb(255 255 255 / 0.94);
  font: 500 13px / 1.2 var(--font);
  white-space: nowrap;
  pointer-events: none;
  animation: notice-in 200ms ease;
}

.notice[hidden] { display: none; }
.notice i { display: none; }

.notice[data-busy] i {
  display: block;
  width: 12px;
  height: 12px;
  border: 1.5px solid rgb(255 255 255 / 0.3);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 800ms linear infinite;
}

@keyframes spin { to { rotate: 1turn; } }
@keyframes notice-in { from { opacity: 0; translate: -50% -6px; } }

/* Who made the wallpaper, small, in the corner. */
.credit {
  position: absolute;
  z-index: 4;
  left: 12px;
  bottom: 10px;
  max-width: min(46%, 360px);
  overflow: hidden;
  color: rgb(255 255 255 / 0.82);
  font: 500 11px / 1.3 var(--font);
  text-decoration: none;
  text-overflow: ellipsis;
  text-shadow: 0 1px 2px rgb(0 0 0 / 0.5);
  white-space: nowrap;
}

.credit[href]:hover { color: #fff; text-decoration: underline; }
.credit[hidden] { display: none; }

/* ---------- The settings ---------- */

/* Tweakpane as it comes, floating over the wallpaper; it scrolls when it
   is taller than the window. */
.sidebar {
  position: fixed;
  z-index: 10;
  top: var(--panel-gap);
  right: var(--panel-gap);
  width: var(--panel-w);
  max-height: calc(100% - var(--panel-gap) * 2);
  overflow-y: auto;
  border-radius: 6px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25), 0 12px 40px rgba(0, 0, 0, 0.35);
  scrollbar-width: none;
  overscroll-behavior: contain;
}

.sidebar::-webkit-scrollbar { display: none; }

/* Hidden, it slides out past the window's edge. */
body[data-ui="off"] .sidebar {
  translate: calc(100% + var(--panel-gap)) 0;
  opacity: 0;
  visibility: hidden;
}

body[data-ui-motion] .sidebar {
  transition: translate var(--ui-time) var(--ui-ease), opacity 240ms ease, visibility 0s;
}

body[data-ui-motion][data-ui="off"] .sidebar {
  transition: translate var(--ui-time) var(--ui-ease), opacity 240ms ease 120ms, visibility 0s var(--ui-time);
}

@media (prefers-reduced-motion: reduce) {
  body[data-ui-motion] .sidebar,
  body[data-ui-motion][data-ui="off"] .sidebar { transition: none; }
}

/* Until Tweakpane has loaded from the CDN. */
.sidebar-loading {
  margin: 0;
  padding: 14px 16px;
  background: #1a1c21;
  color: #a8aebb;
  font: 12px / 1.4 ui-monospace, 'SF Mono', Menlo, monospace;
}

.sidebar .tp-rotv {
  --tp-base-background-color: #1a1c21;
  --tp-container-background-color: rgba(255, 255, 255, 0.06);
  --tp-input-background-color: rgba(255, 255, 255, 0.07);
  --tp-label-foreground-color: #a8aebb;
  --tp-monitor-background-color: rgba(0, 0, 0, 0.35);
  --cnt-usz: 22px;
  font-size: 12px;
}

/* The adaptation's live readings, laid out like the panel's own rows. */
.sidebar .readouts { display: grid; gap: 4px; padding: 6px 4px 4px; }
.sidebar .readouts div { display: grid; grid-template-columns: 1fr 1.6fr; align-items: center; min-height: 22px; padding-left: 4px; font: 11px / 1.3 ui-monospace, 'SF Mono', Menlo, monospace; }
.sidebar .readouts span { color: #a8aebb; }
.sidebar .readouts b { padding: 3px 6px; border-radius: 2px; background: rgba(0, 0, 0, 0.35); color: rgba(255, 255, 255, 0.7); font-weight: 400; }

/* ---------- The code ---------- */

.code-dialog {
  box-sizing: border-box;
  width: min(720px, calc(100vw - 32px));
  max-height: min(80dvh, 760px);
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  background: #16171b;
  color: #c9ced8;
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.5);
  font: 13px / 1.5 var(--font);
}

.code-dialog[open] { display: flex; flex-direction: column; }
.code-dialog::backdrop { background: rgba(0, 0, 0, 0.5); }

.code-dialog header {
  display: grid;
  gap: 4px;
  padding: 16px 18px 12px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.code-dialog header b { color: #fff; font-size: 15px; }
.code-note { color: #8a909c; }

.code-dialog pre {
  flex: 1;
  margin: 0;
  padding: 14px 18px;
  overflow: auto;
  color: #dfe3ea;
  font: 12px / 1.6 ui-monospace, 'SF Mono', Menlo, monospace;
  user-select: text;
  -webkit-user-select: text;
}

.code-dialog footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 12px 18px 16px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}

.code-dialog button {
  min-width: 76px;
  padding: 8px 14px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.06);
  color: #e6e9ef;
  font: 500 13px / 1 var(--font);
  cursor: pointer;
}

.code-dialog button[data-action="copy"] { border-color: transparent; background: #e6e9ef; color: #111215; }

/* ---------- Phones ---------- */

/* The stage on top, the settings in a sheet below it. The settings start
   folded away; the toolbar's settings button brings them up. */
@media (max-width: 720px) {
  :root {
    --panel-space: 0px;
    --sheet-full: min(52dvh, 480px);
    --sheet-h: var(--sheet-full);
  }

  body[data-ui="off"] { --sheet-h: 0px; }

  .view { inset: 0 0 var(--sheet-h) 0; }

  /* A phone is narrow, so the surfaces size to its width. */
  .stage { --u: clamp(0.56px, min(100cqw / 420, 100cqh / 600), 1.2px); }

  .sidebar {
    top: auto;
    right: 0;
    bottom: 0;
    left: 0;
    width: auto;
    /* Its full height even while hidden, so it slides rather than
       squashes. */
    height: var(--sheet-full);
    max-height: none;
    box-sizing: border-box;
    padding: 12px 12px calc(12px + env(safe-area-inset-bottom));
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 0;
    background: #111215;
    box-shadow: none;
  }

  body[data-ui="off"] .sidebar { translate: 0 100%; }

  .surfaces { padding-bottom: 72px; }
  body[data-ui="off"] .surfaces { padding-bottom: calc(72px + env(safe-area-inset-bottom)); }
  body[data-ui="off"] .toolbar { bottom: calc(14px + env(safe-area-inset-bottom)); }
  .toolbar { bottom: 12px; }
  .toolbar .sep { margin: 0 2px; }
  .credit { top: 10px; bottom: auto; max-width: 70%; }
  .notice { top: 34px; }
}

@media (pointer: coarse) {
  .sidebar .tp-rotv { --cnt-usz: 30px; font-size: 13px; }
  .sidebar input { font-size: 16px; }
  /* The page doesn't zoom in on the search field. */
  .search input { font-size: max(16px, calc(16 * var(--u))); }
}
