/* Instrument Sans, served from this site (no request to another company, and it arrives with the page). */
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400 600;
  font-display: block; /* the font is preloaded and tiny: wait for it rather than flash a different one */
  src: url(fonts/instrument-sans-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400 600;
  font-display: block; /* the font is preloaded and tiny: wait for it rather than flash a different one */
  src: url(fonts/instrument-sans-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* The glow behind the gallery takes the open wallpaper's color, and fades between them.
   It lives on the gallery alone (not inherited), so fading it never re-styles the rest of the page. */
@property --glow {
  syntax: "<color>";
  inherits: false;
  initial-value: #4f7bff;
}

:root {
  --bg: #0e1030;
  --fg: #ffffff;
  --ch: clamp(240px, calc(100svh - 250px), 1000px);
  --rw: 1320; /* screen width and height in pixels, set from the page's script */
  --rh: 2868;
  /* The wallpaper is never taller than the room the gallery really has (the script measures it into --ch-max). */
  --ch-eff: min(var(--ch), var(--ch-max, 9999px));
  --cw: min(calc(var(--ch-eff) * var(--rw) / var(--rh)), 78vw);
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
}

* { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  background: #0b0d1c;
  transition: background-color 900ms ease;
}
/* In the gallery the whole page, including the strips Safari shows above and below it, takes the open wallpaper's color. */
html:has(body[data-zone="gallery"]) { background: var(--bg); }

body {
  margin: 0;
  overflow-x: clip; /* nothing may push the page wider than the screen: that makes the phone zoom out */
  background-color: #0b0d1c; /* solid on purpose: Safari tints its bars from it */
  color: #fff;
  font-family: "Instrument Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  letter-spacing: -0.01em;
}

/* ---------- opening: color field, clock, three lines ---------- */

/* The opening is ordinary page content. The colour field rides along behind the clock and the three lines (sticky, not
   pinned to the screen), then scrolls away with them, and the gallery takes over. */
.opening { position: relative; }
.field-wrap {
  position: sticky;
  top: 0;
  z-index: 0;
  height: 100svh;
  height: 100lvh;
  margin-bottom: -100svh;
  margin-bottom: -100lvh;
  overflow: hidden;
}
.field {
  display: block;
  width: 100%;
  height: 100%;
  animation: field-in 2200ms ease both;
}
/* fine grain over the field, so the soft colour never bands */
.field-wrap::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: var(--grain);
  background-size: 160px 160px;
  mix-blend-mode: overlay;
  opacity: 0.16;
}

@keyframes field-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes clock-in {
  from { opacity: 0; filter: blur(16px); transform: translateY(1.5vh); }
  to { opacity: 1; filter: blur(0); transform: none; }
}

.hero {
  position: relative;
  z-index: 2;
  min-height: 100svh;
  display: grid;
  place-items: center;
  text-align: center;
}

.clock {
  animation: clock-in 2000ms var(--ease) 900ms both;
}
.clock-date {
  margin: 0;
  font-size: clamp(16px, 2.2vw, 24px);
  font-weight: 500;
  opacity: 0.85;
}
.clock-time {
  margin: 0;
  --clock: min(40vw, 62svh);
  font-size: calc(var(--clock) * var(--fit, 1));
  font-weight: 500;
  line-height: 0.95;
  letter-spacing: -0.05em;
  font-variant-numeric: tabular-nums;
}
/* AM / PM sits small beside the numbers, like on a lock screen. */
.ampm {
  margin-left: 0.1em;
  font-size: 0.16em;
  font-weight: 500;
  letter-spacing: 0;
  opacity: 0.85;
}

.cue {
  position: absolute;
  bottom: calc(28px + env(safe-area-inset-bottom));
  left: 0;
  right: 0;
  margin: 0;
  font-size: 14px;
  opacity: 0;
  animation: cue-in 1200ms ease 3200ms forwards;
}
@keyframes cue-in { to { opacity: 0.6; } }

.about {
  position: relative;
  z-index: 2;
  padding: 0 clamp(24px, 8vw, 120px);
  text-align: center;
}
.line {
  min-height: 55svh;
  display: grid;
  place-items: center;
  margin: 0 auto;
  max-width: 22ch;
  font-size: clamp(30px, 5vw, 60px);
  font-weight: 500;
  line-height: 1.12;
  letter-spacing: -0.03em;
  text-wrap: balance;
  opacity: 0.15;
}

/* ---------- gallery ---------- */

/* The wrapper is the scrolling part: as tall as the biggest the screen gets, filled with the wallpaper's colour.
   The gallery itself is pinned to the top of the screen and is exactly as tall as what you can see
   (the script measures it), so the header can never end up over the tabs and no strip shows below it. */
.gallery-wrap {
  position: relative;
  z-index: 3;
  height: max(100lvh, var(--gh, 100lvh));
  background-color: var(--bg);
  transition: background-color 900ms ease;
}
.gallery {
  position: sticky;
  top: 0;
  z-index: 3;
  height: var(--gh, 100svh);
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto; /* the middle row never grows past the screen, so nothing is cut off */
  padding-top: 78px; /* clear of the fixed header (wordmark and Lock screen preview) */
  background-color: var(--bg);
  background-image: radial-gradient(70% 52% at 50% 50%, color-mix(in srgb, var(--glow) 30%, transparent), transparent 74%);
  color: var(--fg);
  transition: background-color 900ms ease, color 900ms ease, --glow 900ms ease;
}
.tabs, .foot { position: relative; z-index: 1; }

/* Sections of the gallery (Essentials, Navy) */
.tabs {
  display: flex;
  justify-content: center;
  gap: 22px;
  padding: 0 20px 20px; /* room below, so the tabs never touch the wallpapers */
}
.tabs button {
  font: inherit;
  font-size: 14px;
  color: inherit;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 999px;
  padding: 8px 18px;
  cursor: pointer;
  opacity: 0.6;
  transition: opacity 300ms ease, background-color 300ms ease, color 300ms ease, border-color 900ms ease;
}
.tabs button:hover { opacity: 1; }
.tabs button[aria-pressed="true"] {
  opacity: 1;
  border-color: color-mix(in srgb, var(--fg) 7%, transparent);
}

/* ---------- top bar ---------- */

.bar {
  position: absolute; /* scrolls with the page, like apple.com's top bar; the gallery has its own copy */
  top: 0;
  left: 0;
  right: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 24px clamp(20px, 4vw, 40px);
  color: #fff;
  pointer-events: none;
  transition: color 600ms ease;
}
.bar > * { pointer-events: auto; }
.gallery .bar { color: var(--fg); }
body[data-zone="intro"] .toggle {
  opacity: 0;
  pointer-events: none;
  visibility: hidden; /* not just see-through: a hidden blur costs nothing while the colour field moves */
  transition: opacity 400ms ease, visibility 0s linear 400ms;
}

.mark {
  font-size: 20px;
  font-weight: 500;
  letter-spacing: -0.03em;
  color: inherit;
  text-decoration: none;
}

.toggle {
  font: inherit;
  font-size: 14px;
  color: inherit;
  background: transparent;
  border: 1px solid color-mix(in srgb, var(--fg) 35%, transparent);
  border-radius: 999px;
  padding: 8px 16px;
  cursor: pointer;
  transition: opacity 400ms ease, background-color 300ms ease, color 300ms ease, border-color 900ms ease;
}
.toggle[aria-pressed="true"] {
  background: var(--fg);
  color: var(--bg);
  border-color: var(--fg);
}

.stage {
  position: relative; /* so card positions are measured from the stage itself */
  display: flex;
  align-items: center;
  gap: clamp(16px, 3vw, 40px);
  padding-inline: calc(50% - var(--cw) / 2);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}
.stage::-webkit-scrollbar { display: none; }

.card {
  position: relative;
  flex: none;
  width: var(--cw);
  aspect-ratio: var(--rw) / var(--rh);
  padding: 0;
  border: 0;
  border-radius: calc(var(--cw) * 0.14);
  font: inherit;
  overflow: hidden;
  background: transparent;
  scroll-snap-align: center;
  container-type: inline-size;
  cursor: pointer;
  /* --d is how many places away from the open wallpaper this one is: the farther, the smaller and fainter */
  --d: 1;
  opacity: max(0.14, calc(1 - var(--d) * 0.3));
  transform: scale(max(0.74, calc(1 - var(--d) * 0.07)));
  transition: transform 600ms var(--ease), opacity 600ms var(--ease);
}
.card[aria-current="true"] {
  opacity: 1;
  transform: scale(1);
  cursor: zoom-in;
}

/* Once the full-size picture is ready, the open wallpaper is a real image on top of the preview:
   that is what lets the phone offer "Save to Photos" when you press and hold it. */
.card .card-img {
  position: absolute;
  inset: 0;
  display: none;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.card .card-img.on { display: block; }

/* Wallpapers drift in when a section opens */
@keyframes card-enter {
  from { opacity: 0; transform: translateY(18px) scale(0.9); }
}
.card.enter { animation: card-enter 800ms var(--ease) backwards; }

.card canvas {
  display: block;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 260ms ease; /* a wallpaper fades in when it is ready */
}
.card canvas.ready { opacity: 1; }

/* lock screen preview */
.lock {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 7cqw;
  opacity: 0;
  pointer-events: none;
  transition: opacity 350ms ease;
}
body[data-lock="on"] .lock { opacity: 1; }

.island {
  width: 28cqw;
  height: 8cqw;
  border-radius: 8cqw;
  background: #000;
}
body[data-device="android"] .island {
  width: 5cqw;
  height: 5cqw;
  margin-top: 1cqw;
  border-radius: 50%;
}
.date {
  margin-top: 13cqw;
  font-size: 5.4cqw;
  font-weight: 500;
  opacity: 0.85;
}
.time {
  margin-top: 1cqw;
  font-size: 27cqw;
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.04em;
}
.lock[data-ink="light"] { color: #fff; }
.lock[data-ink="dark"] { color: #111; }

.foot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 0 20px calc(28px + env(safe-area-inset-bottom));
  text-align: center;
}

.name {
  margin: 0;
  font-size: clamp(22px, 3vw, 28px);
  font-weight: 500;
  letter-spacing: -0.025em;
}

.download {
  font: inherit;
  font-size: 15px;
  font-weight: 500;
  color: var(--bg);
  background: var(--fg);
  border: 0;
  border-radius: 999px;
  padding: 13px 28px;
  cursor: pointer;
  transition: opacity 200ms ease, color 900ms ease, background-color 900ms ease;
}
.download:hover { opacity: 0.85; }
.download:disabled { opacity: 0.6; cursor: progress; }

/* The size picker is hidden for now: phones and foldables are sized automatically, computers get iPhone size.
   The picker and its code are kept, so it can come back (for example as a small "other devices" link). */
.spec {
  display: none;
  align-items: center;
  gap: 10px;
  margin: 0;
  font-size: 13px;
}
.spec label { opacity: 0.55; }
.spec select {
  font: inherit;
  color: inherit;
  background: transparent;
  border: 1px solid color-mix(in srgb, var(--fg) 30%, transparent);
  border-radius: 999px;
  padding: 6px 12px;
  max-width: 62vw;
  cursor: pointer;
  transition: border-color 900ms ease;
}
.spec select option { color: #15151a; background: #fff; }

:focus-visible {
  outline: 2px solid var(--fg);
  outline-offset: 3px;
}
.card:focus-visible { outline-offset: -4px; }

@media (max-width: 600px) {
  :root { --ch: clamp(240px, calc(100svh - 320px), 700px); }
  .bar { padding-block: 18px; }
  .clock-time { --clock: min(46vw, 62svh); }
}

/* ---------- full-screen viewer ---------- */

body.viewing { overflow: hidden; }

.viewer {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  background: var(--bg);
  opacity: 0;
  transition: opacity 600ms ease;
}
.viewer[hidden] { display: none; }
.viewer.open { opacity: 1; }

/* The picture keeps the exact shape of the chosen screen, as large as the window allows. */
.viewer-frame {
  position: relative;
  width: min(100vw, calc(100svh * var(--rw) / var(--rh)));
  aspect-ratio: var(--rw) / var(--rh);
  container-type: inline-size;
  /* No touch-action override and no drag blocking here: the phone's own press-and-hold menu must stay available. */
  overflow: hidden;
  transform: scale(0.94);
  /* The script starts it on top of the wallpaper you tapped, so it unfolds from there. */
  transition: transform 700ms var(--ease), border-radius 700ms var(--ease);
}
.viewer.open .viewer-frame { transform: none; }

/* Two pictures sit on top of each other: the next one fades in slowly over the one before. */
.vimg {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transform: scale(1.035);
  transition: opacity 900ms ease, transform 1400ms var(--ease);
}
.vimg.shown { opacity: 1; transform: none; }
/* the lock screen clock always sits above the pictures */
.viewer-frame .lock { z-index: 5; }

.viewer-close {
  position: absolute;
  top: max(16px, env(safe-area-inset-top));
  left: 16px;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  color: var(--fg);
  background: color-mix(in srgb, var(--bg) 55%, transparent);
  border: 1px solid color-mix(in srgb, var(--fg) 35%, transparent);
  border-radius: 50%;
  cursor: pointer;
  transition: opacity 300ms ease;
}

.viewer-lock {
  position: absolute;
  top: max(16px, env(safe-area-inset-top));
  right: 16px;
  color: var(--fg);
  background: color-mix(in srgb, var(--bg) 55%, transparent);
  transition: opacity 300ms ease, background-color 300ms ease, color 300ms ease;
}
.viewer.chrome-hidden .viewer-lock { opacity: 0; pointer-events: none; }
/* On a computer the picture sits in the middle of the window: give it an edge so you can see its shape. */
@media (pointer: fine) {
  .viewer-frame { border-radius: 44px; box-shadow: 0 0 0 1px color-mix(in srgb, var(--fg) 16%, transparent); }
}

.viewer-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: max(22px, env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  color: var(--fg);
  text-shadow: 0 1px 12px color-mix(in srgb, var(--bg) 80%, transparent);
  transition: opacity 300ms ease;
}
.viewer-name { margin: 0; font-size: 22px; font-weight: 500; letter-spacing: -0.025em; }
.viewer-hint { margin: 0; font-size: 13px; opacity: 0.75; }
.viewer.chrome-hidden .viewer-bar,
.viewer.chrome-hidden .viewer-close { opacity: 0; pointer-events: none; }
@media (pointer: fine) { .viewer-hint { display: none; } }

/* Short screens (a phone held sideways): smaller phone, name and button on one row. */
@media (max-height: 520px) {
  :root { --ch: calc(100svh - 184px); }
  .tabs { gap: 14px; padding-bottom: 8px; }
  .tabs button { padding: 4px 14px; font-size: 13px; }
  .bar { padding-block: 14px; }
  .gallery { padding-top: 56px; }
  .foot {
    flex-direction: row;
    justify-content: center;
    gap: 20px;
    padding-bottom: 12px;
  }
  .name { font-size: 20px; }
  .download { padding: 10px 22px; }
  .clock-time { --clock: min(30vw, 52svh); }
  .line { min-height: 80svh; font-size: clamp(24px, 4vw, 40px); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 1ms !important; }
  .stage { scroll-behavior: auto; }
}

/* ---------- Liquid Glass ----------
   Every button is translucent glass: it blurs and tints whatever is behind it, has a bright edge
   along the top where light catches it, and a soft shadow. It adapts to light and dark wallpapers. */

:root {
  --glass-tint: rgba(255, 255, 255, 0.04);
  --glass-tint-strong: rgba(255, 255, 255, 0.07);
  --glass-edge: rgba(255, 255, 255, 0.025);
  --glass-hi: rgba(255, 255, 255, 0.09);
  --glass-shine: rgba(255, 255, 255, 0.025);
  --glass-shadow: rgba(0, 0, 0, 0);
}
:root[data-tone="light"] {
  --glass-tint: rgba(255, 255, 255, 0.12);
  --glass-tint-strong: rgba(255, 255, 255, 0.2);
  --glass-edge: rgba(255, 255, 255, 0.14);
  --glass-hi: rgba(255, 255, 255, 0.34);
  --glass-shine: rgba(255, 255, 255, 0.08);
  --glass-shadow: rgba(30, 45, 80, 0);
}

.toggle:not(.viewer-lock),
.glass-group,
.download { position: relative; }
/* (the close and lock buttons in the full-screen view keep their own absolute position) */

.toggle,
.glass-group,
.download,
.viewer-close {
  isolation: isolate;
  color: var(--fg);
  background: linear-gradient(180deg, var(--glass-tint-strong), var(--glass-tint));
  border: 1px solid var(--glass-edge);
  -webkit-backdrop-filter: blur(16px) saturate(1.1);
  backdrop-filter: blur(16px) saturate(1.1);
  box-shadow:
    inset 0 0.5px 0 var(--glass-hi);
  transition: transform 250ms var(--ease), background 300ms ease, box-shadow 300ms ease, border-color 600ms ease, color 600ms ease, opacity 400ms ease;
}
/* the shine: a soft highlight across the top left, as if a window were reflected in it */
.toggle::before,
.glass-group::before,
.download::before,
.viewer-close::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  background: radial-gradient(130% 170% at 16% -25%, var(--glass-shine), transparent 56%);
}
.toggle:hover,
.download:hover,
.viewer-close:hover {
  transform: translateY(-1px);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.06));
}
:root[data-tone="light"] .toggle:hover,
:root[data-tone="light"] .download:hover,
:root[data-tone="light"] .viewer-close:hover {
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.2));
}
.toggle:active,
.download:active,
.viewer-close:active { transform: scale(0.96); }

/* the Lock screen preview toggle: when on, the glass glows a little brighter instead of turning solid */
.toggle[aria-pressed="true"] {
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.06));
  color: var(--fg);
  border-color: var(--glass-edge);
}
:root[data-tone="light"] .toggle[aria-pressed="true"] {
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.34), rgba(255, 255, 255, 0.24));
}

.toggle { padding: 9px 18px; }

.download {
  padding: 13px 32px;
  font-weight: 500;
}
.download:hover { opacity: 1; }
.download:disabled { opacity: 0.7; transform: none; }

.viewer-close,
.viewer-lock { background-color: transparent; }

/* the three sections sit in one glass capsule; the open one is a brighter glass pill inside it */
.glass-group {
  display: inline-flex;
  gap: 10px;
  padding: 5px;
  border-radius: 999px;
}
.tabs button {
  position: relative;
  color: var(--fg);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 999px;
  padding: 9px 20px;
  opacity: 0.72;
  transition: opacity 300ms ease, background 300ms ease, box-shadow 300ms ease, border-color 400ms ease, color 600ms ease;
}
.tabs button:hover { opacity: 1; }
.tabs button[aria-pressed="true"],
.tabs button.under-thumb { opacity: 1; }

/* The moving glass pill: it sits under the labels, follows a finger dragged along the bar,
   and settles on the nearest tab with a small overshoot. */
.glass-group { touch-action: pan-y; user-select: none; -webkit-user-select: none; }
.glass-thumb {
  position: absolute;
  top: 5px;
  bottom: 5px;
  left: 0;
  width: 0;
  border-radius: 999px;
  pointer-events: none;
  z-index: 0;
  transform: translateX(var(--tx, 0px)) scale(var(--sc, 1));
  transition: transform 520ms cubic-bezier(0.3, 1.35, 0.4, 1), width 520ms cubic-bezier(0.3, 1.35, 0.4, 1), box-shadow 300ms ease, background 300ms ease;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.06));
  border: 1px solid var(--glass-edge);
  box-shadow: inset 0 0.5px 0 var(--glass-hi);
}
:root[data-tone="light"] .glass-thumb { background: linear-gradient(180deg, var(--glass-tint-strong), var(--glass-tint)); }
.glass-thumb::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(130% 170% at 16% -25%, var(--glass-shine), transparent 56%);
}
/* pressed: brighter and a little bigger, like a drop of glass under a finger */
.glass-thumb.dragging {
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.13), rgba(255, 255, 255, 0.08));
  box-shadow: inset 0 0.5px 0 var(--glass-hi);
}
:root[data-tone="light"] .glass-thumb.dragging { background: linear-gradient(180deg, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0.3)); }
.tabs button { z-index: 1; }

/* where the screen cannot blur what is behind (older browsers), or the person asked for less transparency */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .toggle, .glass-group, .download, .viewer-close { background: rgba(40, 48, 80, 0.72); }
  :root[data-tone="light"] .toggle, :root[data-tone="light"] .glass-group, :root[data-tone="light"] .download, :root[data-tone="light"] .viewer-close { background: rgba(255, 255, 255, 0.85); }
}
@media (prefers-reduced-transparency: reduce) {
  .toggle, .glass-group, .download, .viewer-close {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: rgba(40, 48, 80, 0.85);
  }
  :root[data-tone="light"] .toggle, :root[data-tone="light"] .glass-group, :root[data-tone="light"] .download, :root[data-tone="light"] .viewer-close { background: rgba(255, 255, 255, 0.92); }
}

/* the glass buttons in the short, sideways phone layout stay compact */
@media (max-height: 520px) {
  .download { padding: 10px 24px; }
  .glass-group { gap: 6px; padding: 4px; }
  .tabs button { padding: 5px 14px; }
}


/* ---- "How to turn on Depth Effect": a quiet link under the Download button, and the card it opens ---- */
.howto {
  font: inherit;
  font-size: 13px;
  color: var(--fg);
  opacity: 0.72;
  background: none;
  border: 0;
  padding: 4px 8px;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: opacity 250ms ease;
}
.howto:hover { opacity: 1; }
.howto[hidden] { display: inline-block; visibility: hidden; } /* keeps its space, so the wallpapers never change size between sections */

.sheet {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgba(6, 8, 16, 0.5);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  opacity: 0;
  transition: opacity 300ms ease;
}
.sheet[hidden] { display: none; }
.sheet.open { opacity: 1; }
.sheet-card {
  position: relative;
  width: min(440px, 100%);
  max-height: 100%;
  overflow-y: auto;
  padding: 30px 26px 26px;
  border-radius: 30px;
  color: #fff;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.09)), rgba(18, 22, 40, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.2);
  -webkit-backdrop-filter: blur(30px) saturate(1.6);
  backdrop-filter: blur(30px) saturate(1.6);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4);
  transform: translateY(14px) scale(0.98);
  transition: transform 420ms cubic-bezier(0.3, 1.2, 0.4, 1);
}
.sheet.open .sheet-card { transform: none; }
.sheet h2 { margin: 0 36px 8px 0; font-size: 22px; font-weight: 500; letter-spacing: -0.025em; }
.sheet-lead { margin: 0 0 18px; font-size: 14px; line-height: 1.5; opacity: 0.78; }
.sheet-steps { margin: 0; padding: 0; list-style: none; counter-reset: step; display: grid; gap: 14px; }
.sheet-steps li { position: relative; padding-left: 38px; font-size: 15px; line-height: 1.45; counter-increment: step; }
.sheet-steps li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-size: 13px;
  font-weight: 600;
  background: rgba(255, 255, 255, 0.16);
  border: 1px solid rgba(255, 255, 255, 0.22);
}
.sheet-steps b { font-weight: 600; }
.sheet-note { margin: 20px 0 0; padding-top: 16px; border-top: 1px solid rgba(255, 255, 255, 0.14); font-size: 13px; line-height: 1.5; opacity: 0.7; }
.sheet-close {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  color: #fff;
  background: rgba(255, 255, 255, 0.14);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  cursor: pointer;
}
@media (prefers-reduced-motion: reduce) {
  .sheet, .sheet-card { transition: none; }
}


/* ---------- smooth and accessible ---------- */

/* No grey flash when tapping on iPhone; no double-tap delay on buttons. */
button, a, .card, .tabs, .glass-group { -webkit-tap-highlight-color: transparent; }
button { touch-action: manipulation; }

/* Reading aids: a skip link for keyboard and screen reader users, and text only they hear. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.skip {
  position: fixed;
  top: 10px;
  left: 10px;
  z-index: 300;
  padding: 12px 18px;
  border-radius: 999px;
  color: #fff;
  background: rgba(10, 12, 28, 0.92);
  text-decoration: none;
  transform: translateY(-200%);
}
.skip:focus { transform: none; }

/* Buttons stay small to look at, but their touch area reaches 44 points, as Apple recommends. */
.toggle:not(.viewer-lock)::after,
.tabs button::after,
.howto::after {
  content: "";
  position: absolute;
  inset: -4px 0;
}
.tabs button::after { inset: -7px 0; }
.howto { position: relative; }
.howto::after { inset: -10px -6px; }

/* Words stay easy to read on every wallpaper colour. */
.tabs button { opacity: 0.85; }
.tabs button:hover { opacity: 1; }
.howto { opacity: 0.9; }
.viewer-hint { opacity: 0.88; }

/* People who asked for less motion get a still page: no drifting, fading in or sliding. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
  }
}

/* People who asked for more contrast get firmer glass and edges. */
@media (prefers-contrast: more) {
  :root {
    --glass-tint: rgba(10, 12, 28, 0.55);
    --glass-tint-strong: rgba(10, 12, 28, 0.7);
    --glass-edge: rgba(255, 255, 255, 0.7);
    --glass-hi: rgba(255, 255, 255, 0.7);
  }
  :root[data-tone="light"] {
    --glass-tint: rgba(255, 255, 255, 0.8);
    --glass-tint-strong: rgba(255, 255, 255, 0.92);
    --glass-edge: rgba(20, 22, 40, 0.7);
    --glass-hi: rgba(20, 22, 40, 0.5);
  }
  .tabs button, .howto, .viewer-hint { opacity: 1; }
}

/* Narrow screens: the gallery's one column may never be wider than the screen, and the tabs tighten up to fit. */
.gallery { grid-template-columns: minmax(0, 1fr); }
@media (max-width: 360px) {
  .tabs { padding-inline: 12px; }
  .tabs button { padding-inline: 14px; }
  .glass-group { gap: 4px; }
}


/* Full screen from the Home Screen: the colour reaches behind the status bar and home bar, so the header and the gallery
   make room for the notch (these are zero in a normal Safari tab). */
.bar { padding-top: calc(24px + env(safe-area-inset-top)); }
.gallery { padding-top: calc(78px + env(safe-area-inset-top)); }
@media (max-width: 600px) {
  .bar { padding-top: calc(18px + env(safe-area-inset-top)); }
}
@media (max-height: 520px) {
  .bar { padding-top: calc(14px + env(safe-area-inset-top)); }
  .gallery { padding-top: calc(56px + env(safe-area-inset-top)); }
}

/* Two thin strips at the very top and bottom of the screen. They carry the colour Safari paints its status bar and
   toolbar with: in the opening, the colour field's own top and bottom colour (set live by the script); in the gallery
   the gallery itself does it, so they are removed (display: none, as opacity or pointer-events would still tint). */
.edge {
  position: fixed;
  left: 0;
  right: 0;
  height: 8px;
  z-index: 0;
  pointer-events: none;
  background-color: #0b0d1c;
}
.edge-top { top: 0; }
.edge-bottom { bottom: 0; }
body[data-zone="gallery"] .edge { display: none; }
body[data-zone="gallery"] { background-color: var(--bg); }


/* ---------- from the opening into the selection ---------- */

/* The top edge of the gallery is feathered, not a hard line: the colour field melts into the wallpaper's colour as the
   gallery rises over it. (It sits above the gallery, so at rest it is off screen.) */
.gallery::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: 220px;
  pointer-events: none;
  background: linear-gradient(to bottom,
    transparent 0%,
    color-mix(in srgb, var(--bg) 6%, transparent) 20%,
    color-mix(in srgb, var(--bg) 22%, transparent) 42%,
    color-mix(in srgb, var(--bg) 52%, transparent) 64%,
    color-mix(in srgb, var(--bg) 82%, transparent) 84%,
    var(--bg) 100%);
}

/* Then the selection arrives in order: the tabs settle down from above, the wallpapers rise one after another from the
   open one outward, and the name and button follow. (The script holds everything in the "pre" state until the gallery
   is half way up, and again whenever you scroll back to the opening.) */
.gallery .tabs { transition: opacity 800ms var(--ease) 140ms, transform 900ms var(--ease) 140ms; }
.gallery .foot { transition: opacity 800ms var(--ease) 420ms, transform 900ms var(--ease) 420ms; }
.gallery.pre .tabs { opacity: 0; transform: translateY(-16px); }
.gallery.pre .foot { opacity: 0; transform: translateY(20px); }
.gallery.pre .card { opacity: 0 !important; transform: translateY(54px) scale(0.9) !important; }
@media (prefers-reduced-motion: reduce) {
  .gallery.pre .tabs, .gallery.pre .foot { opacity: 1; transform: none; }
  .gallery.pre .card { opacity: revert !important; transform: revert !important; }
}


/* ---------- compact layout: tabs, a small name, the screen, a small Download, all close together ---------- */
/* Order, top to bottom: header, tabs, the wallpaper's name (small and quiet), the wallpaper, Download (small, centred),
   and on Depth the how-to link under it. Gaps are small and even, so the pieces read as one group. */
.gallery { grid-template-rows: auto auto minmax(0, 1fr) auto; }
.tabs { padding-bottom: 7px; }
.name {
  margin: 0 0 4.2px; /* with the 2px the screen leaves around itself, the name sits the same distance from the tabs and from the screen */
  padding-inline: 20px;
  text-align: center;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.04em;
  line-height: 1.2;
  opacity: 0.78;
  position: relative;
  z-index: 1;
}
.foot {
  gap: 6px;
  padding: 6px 20px calc(14px + env(safe-area-inset-bottom));
}
.download { font-size: 13.5px; padding: 9px 24px; }
.download::after { content: ""; position: absolute; inset: -5px -8px; } /* the touch area stays comfortable */
.howto { font-size: 12px; }

/* the name and the footer arrive with the tabs and the screens */
.gallery .name { transition: opacity 800ms var(--ease) 260ms, transform 900ms var(--ease) 260ms; }
.gallery.pre .name { opacity: 0; transform: translateY(-10px); }
@media (prefers-reduced-motion: reduce) { .gallery.pre .name { opacity: 0.78; transform: none; } }

@media (max-width: 600px) {
  :root { --ch: clamp(240px, calc(100svh - 230px), 820px); }
  .gallery { padding-top: calc(70px + env(safe-area-inset-top)); }
  .tabs { padding-bottom: 7px; }
}
@media (max-height: 520px) {
  .name { font-size: 12px; margin-bottom: 4px; }
  .foot { padding-block: 6px 8px; }
}


/* ---------- a little cheaper to draw ---------- */
.card.hot { will-change: transform, opacity; } /* the open wallpaper and the ones beside it are always ready to move */
.card { contain: layout paint; }


/* ---------- the padlock: lock the phone, and the clock wakes up ---------- */
/* One small round glass button with a padlock. Open padlock = plain picture. Tap it and it clicks shut, like locking an iPhone,
   and the lock screen (camera dot, date, clock) fades in over the picture. Tap again to open it. */
.lock-btn {
  width: 40px;
  height: 40px;
  padding: 0;
  display: grid;
  place-items: center;
  border-radius: 50%;
}
.toggle:not(.viewer-lock).lock-btn::after { inset: -2px; border-radius: 50%; }
.padlock { display: block; overflow: visible; }
.padlock .shackle {
  transform-box: view-box;
  transform-origin: 8.5px 11px;
  transform: translate(-0.4px, -1.6px) rotate(-30deg); /* open: the right side lifted off its notch */
  transition: transform 460ms cubic-bezier(0.3, 1.6, 0.4, 1);
}
.padlock .pbody {
  transform-box: fill-box;
  transform-origin: center;
  fill: currentColor;
  fill-opacity: 0;
  transition: fill-opacity 300ms ease;
}
.padlock .keyhole { fill: rgba(0, 0, 0, 0.55); opacity: 0; transition: opacity 250ms ease; }
.lock-btn[aria-pressed="true"] .shackle { transform: none; } /* shut */
.lock-btn[aria-pressed="true"] .pbody { fill-opacity: 0.9; }
.lock-btn[aria-pressed="true"] .keyhole { opacity: 1; }
.lock-btn.snap .pbody { animation: lock-snap 420ms cubic-bezier(0.3, 1.5, 0.4, 1); }
@keyframes lock-snap { 0% { transform: scale(1); } 35% { transform: scale(0.88); } 100% { transform: scale(1); } }
/* the pressed look from the old text button is not wanted on the round one */
.lock-btn[aria-pressed="true"] { background: linear-gradient(180deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0.07)); }

/* the lock screen wakes up in order: camera dot, date, clock (each fades in, rises and sharpens) */
.lock .island, .lock .date, .lock .time {
  opacity: 0;
  transform: translateY(10px);
  filter: blur(7px);
  transition: opacity 260ms ease, transform 260ms ease, filter 260ms ease;
}
body[data-lock="on"] .lock .island, body[data-lock="on"] .lock .date, body[data-lock="on"] .lock .time {
  opacity: 1;
  transform: none;
  filter: none;
  transition: opacity 650ms var(--ease), transform 750ms var(--ease), filter 650ms var(--ease);
}
body[data-lock="on"] .lock .date { opacity: 0.85; transition-delay: 90ms; }
body[data-lock="on"] .lock .time { transition-delay: 180ms; }


/* ---------- tap the clock and it says the time ---------- */
.clock[role="button"] { cursor: pointer; -webkit-tap-highlight-color: transparent; border-radius: 28px; outline-offset: 10px; }
body[data-lock="on"] .lock .time { pointer-events: auto; cursor: pointer; -webkit-tap-highlight-color: transparent; }
/* while it is speaking, the clock breathes softly */
.clock.speaking .clock-time, .lock .time.speaking { animation: say-pulse 1.3s ease-in-out infinite; }
@keyframes say-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.72; } }

/* the save button is the iPhone share symbol */
.download { display: inline-grid; place-items: center; width: 44px; height: 36px; padding: 0; }
.download .ico { grid-area: 1 / 1; width: 20px; height: 20px; transition: opacity 0.25s ease, transform 0.25s ease; }
.download .check { opacity: 0; transform: scale(0.8); }
.download[data-state="done"] .share { opacity: 0; transform: scale(0.8); }
.download[data-state="done"] .check { opacity: 1; transform: none; }
.download[data-state="busy"] .share { animation: shareBusy 1.1s ease-in-out infinite; }
@keyframes shareBusy { 50% { opacity: 0.35; transform: translateY(-1px); } }
@media (prefers-reduced-motion: reduce) { .download[data-state="busy"] .share { animation: none; opacity: 0.5; } }
