/* Serenity support site.
   Palette and motion lifted from the app so the pages and the product are
   recognisably the same thing: colours from Theme.swift, and the breathing
   period and the three drift periods from Motion.swift. */

:root {
  --ground: #070b18;
  --ground-deep: #04060f;
  --surface: #141b2e;
  --surface-raised: #1c2438;
  --line: rgba(189, 194, 255, 0.12);
  --line-strong: rgba(189, 194, 255, 0.22);
  --text: #e2e7fb;
  --dim: #8b93b4;
  --faint: #5c6483;
  --accent: #bdc2ff;
  --glow: #818cf8;

  /* Motion.breathDuration and Motion.driftDurations, verbatim. */
  --breath: 6.5s;
  --drift-a: 41s;
  --drift-b: 57s;
  --drift-c: 73s;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  padding: 0 24px 96px;
  background: var(--ground);
  color: var(--text);
  font: 16px/1.65 -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* ---- Ambient wash -------------------------------------------------------
   Three soft radial gradients on periods with no small common multiple, so
   the background never visibly repeats. The app builds its wash the same way
   and for the same reason.

   Built the boring way on purpose — this block used to be three of Safari's
   best-known rendering traps at once. It sat at z-index -1 (negative-z fixed
   elements vanish behind the body background in some WebKit versions, so now
   the wash is z-index 0 under a z-index 1 .wrap); it hung 25% outside the
   viewport (iOS Safari counts oversized fixed elements toward page overflow,
   which lets the whole page pan sideways); and it ran filter: blur(20px) on
   vmax-sized layers (blur on large fixed elements is WebKit's most reliable
   source of flicker and white-box artifacts, and the gradients already fade
   to transparent, so the blur bought nothing visible). The container now
   clips at exactly the viewport, where clipping cannot be seen. */

.ambient {
  position: fixed;
  top: 0; right: 0; bottom: 0; left: 0;
  overflow: hidden;
  z-index: 0;
  pointer-events: none;
}

.ambient span {
  position: absolute;
  display: block;
  border-radius: 50%;
  opacity: 0.55;
  will-change: transform;
}

.ambient .a {
  width: 62vmax; height: 62vmax; top: -18vmax; left: -12vmax;
  background: radial-gradient(circle, rgba(129,140,248,.22) 0%, transparent 62%);
  animation: drift-a var(--drift-a) ease-in-out infinite alternate;
}
.ambient .b {
  width: 54vmax; height: 54vmax; top: 12vh; right: -18vmax;
  background: radial-gradient(circle, rgba(94,234,212,.13) 0%, transparent 62%);
  animation: drift-b var(--drift-b) ease-in-out infinite alternate;
}
.ambient .c {
  width: 70vmax; height: 70vmax; bottom: -28vmax; left: 10vw;
  background: radial-gradient(circle, rgba(189,194,255,.10) 0%, transparent 62%);
  animation: drift-c var(--drift-c) ease-in-out infinite alternate;
}

@keyframes drift-a { from { transform: translate3d(0,0,0)      scale(1);    }
                     to   { transform: translate3d(5vw,7vh,0)  scale(1.12); } }
@keyframes drift-b { from { transform: translate3d(0,0,0)      scale(1.08); }
                     to   { transform: translate3d(-6vw,4vh,0) scale(1);    } }
@keyframes drift-c { from { transform: translate3d(0,0,0)      scale(1);    }
                     to   { transform: translate3d(4vw,-6vh,0) scale(1.15); } }

.wrap { max-width: 760px; margin: 0 auto; position: relative; z-index: 1; }

/* ---- Header -------------------------------------------------------------
   The icon breathes on the app's own 6.5s clock — slower than resting breath,
   which is the whole point of that number. */

header { text-align: center; padding: 92px 0 8px; }

.mark { position: relative; display: inline-block; line-height: 0; }

.mark::before {
  content: "";
  position: absolute;
  top: -46%; right: -46%; bottom: -46%; left: -46%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(129,140,248,.55) 0%, transparent 68%);
  animation: breathe var(--breath) ease-in-out infinite alternate;
  z-index: -1;
}

header img {
  width: 112px; height: 112px; border-radius: 26px;
  box-shadow: 0 22px 50px rgba(0,0,0,.55);
  animation: breathe-mark var(--breath) ease-in-out infinite alternate;
}

@keyframes breathe      { from { transform: scale(1);    opacity: .55; }
                          to   { transform: scale(1.14); opacity: .95; } }
@keyframes breathe-mark { from { transform: scale(1); }
                          to   { transform: scale(1.035); } }

h1 {
  font-size: clamp(28px, 6vw, 38px);
  font-weight: 300;
  letter-spacing: -0.6px;
  margin: 26px 0 8px;
}

.tagline { color: var(--dim); margin: 0 0 8px; font-size: 17px; }

.nav { text-align: center; margin: 20px 0 0; font-size: 15px; }
.nav a { margin: 0 10px; }

.badges {
  display: flex; flex-wrap: wrap; gap: 8px;
  justify-content: center; margin: 26px 0 0; padding: 0; list-style: none;
}
.badges li {
  color: var(--dim);
  font-size: 12.5px; letter-spacing: .4px;
  border: 1px solid var(--line);
  background: rgba(20,27,46,.5);
  border-radius: 999px; padding: 6px 14px;
}

/* ---- Type ---------------------------------------------------------------- */

h2 {
  font-size: 20px; font-weight: 600; margin: 52px 0 14px;
  padding-top: 30px; border-top: 1px solid var(--line);
}
h3 { font-size: 16px; font-weight: 600; margin: 26px 0 6px; color: var(--text); }

p, li { color: var(--dim); }
/* Long unbreakable runs (settings paths, emails) must fold rather than push
   the page sideways on a 320px screen. */
p, li, em, code, a { overflow-wrap: break-word; }
p { margin: 0 0 14px; }
ul { padding-left: 22px; margin: 0 0 14px; }
li { margin-bottom: 7px; }
strong { color: var(--text); font-weight: 600; }

a { color: var(--accent); text-decoration: none; border-bottom: 1px solid rgba(189,194,255,.35); }
a:hover { border-bottom-color: var(--accent); }
a:focus-visible, summary:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px;
}

.card {
  background: rgba(20, 27, 46, .55);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 18px 22px;
  margin: 0 0 14px;
}
.card p:last-child { margin-bottom: 0; }

code {
  background: rgba(189,194,255,.09); padding: 2px 6px;
  border-radius: 5px; font-size: 14px; color: var(--accent);
}

/* ---- Screenshot gallery -------------------------------------------------
   A scroll-snapping row. It bleeds past the text column on wide screens so
   the phones have room without the prose getting wider than it should be. */

.shots {
  display: flex;
  gap: 22px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding: 6px 24px 26px;
  margin: 0 -24px;
  scrollbar-width: thin;
  scrollbar-color: var(--line-strong) transparent;
}
.shots::-webkit-scrollbar { height: 8px; }
.shots::-webkit-scrollbar-thumb {
  background: var(--line-strong); border-radius: 99px;
}

.shot {
  flex: 0 0 auto;
  width: 232px;
  margin: 0;              /* figure carries 1em 40px from the UA sheet */
  scroll-snap-align: center;
  text-align: center;
}

.shot img {
  width: 100%; height: auto; display: block;
  /* Slightly inside the device's own corner radius. The WebP already has
     transparent corners, so this is invisible there; it exists for the JPEG
     fallback, which has none. */
  border-radius: 21px;
  filter: drop-shadow(0 26px 40px rgba(0,0,0,.6));
  transition: transform .5s cubic-bezier(.22,.9,.3,1);
}

/* Guarded because iOS applies :hover on tap and keeps it — an un-guarded
   hover transform leaves a phone floating 8px high after every touch. */
@media (hover: hover) {
  .shot:hover img { transform: translateY(-8px) scale(1.015); }
}

.shot figcaption {
  color: var(--faint);
  font-size: 13.5px; line-height: 1.5;
  margin-top: 16px; padding: 0 4px;
}

.hint {
  color: var(--faint); font-size: 13px; text-align: center;
  margin: -10px 0 0;
}

/* On a wide screen the phones should not be trapped inside a 760px prose
   column. Full-bleed the row and inset the padding so the first phone still
   lines up with the text above it. body has overflow-x: hidden, which absorbs
   the scrollbar width that 100vw does not account for. */
@media (min-width: 900px) {
  .shots {
    /* Negative margins, not margin-left:50% + translateX(-50%). The transform
       moves the paint but leaves the layout box where it was, which pushed
       scrollWidth to 1920px on a 1280px viewport — a horizontally scrolling
       page, which is exactly what a full-bleed row must never cause. */
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    padding-left: max(24px, calc((100vw - 1180px) / 2));
    padding-right: max(24px, calc((100vw - 1180px) / 2));
  }
  .shot { width: 258px; }
  .shot img { border-radius: 23px; }
}

/* ---- FAQ ----------------------------------------------------------------- */

.faq {
  background: rgba(20, 27, 46, .5);
  border: 1px solid var(--line);
  border-radius: 16px;
  margin: 0 0 10px;
  overflow: hidden;
  transition: border-color .3s ease, background .3s ease;
}
.faq[open] { border-color: var(--line-strong); background: rgba(20,27,46,.72); }
.faq:hover { border-color: var(--line-strong); }

.faq summary {
  cursor: pointer; list-style: none;
  padding: 17px 52px 17px 22px;
  position: relative;
  color: var(--text); font-weight: 600; font-size: 15.5px;
}
.faq summary::-webkit-details-marker { display: none; }

.faq summary::after {
  content: "";
  position: absolute; right: 24px; top: 50%;
  width: 9px; height: 9px;
  border-right: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: translateY(-70%) rotate(45deg);
  transition: transform .3s cubic-bezier(.22,.9,.3,1);
}
.faq[open] summary::after { transform: translateY(-25%) rotate(-135deg); }

.faq .body { padding: 0 22px 18px; }
/* On [open] so it replays each time a question is opened, in every engine —
   unscoped it ran exactly once, at load, while the body was still hidden. */
.faq[open] .body { animation: unfold .35s ease both; }
.faq .body p:last-child { margin-bottom: 0; }

@keyframes unfold {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

/* ---- Scroll reveal ------------------------------------------------------
   Opt-in: the class is only added by script, so with JS off everything is
   simply visible rather than permanently invisible. */

.js .reveal { opacity: 0; transform: translateY(18px); }
.js .reveal.in {
  opacity: 1; transform: none;
  transition: opacity .7s ease, transform .7s cubic-bezier(.22,.9,.3,1);
}

footer {
  margin-top: 64px; padding-top: 24px; border-top: 1px solid var(--line);
  color: var(--faint); font-size: 14px; text-align: center;
}

@media (max-width: 520px) {
  header { padding-top: 56px; }
  header img { width: 92px; height: 92px; }
  .shot { width: 200px; }
  .shot img { border-radius: 18px; }
}

/* ---- Reduce Motion ------------------------------------------------------
   The app holds the breathing glow steady when Reduce Motion is on, and says
   so on this page. It would be a poor advertisement for that if the page
   itself kept moving. Everything stops; nothing disappears. */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .ambient span,
  .mark::before,
  header img { animation: none !important; }
  .mark::before { opacity: .75; }
  .shot img, .faq, .faq summary::after { transition: none !important; }
  .shot:hover img { transform: none; }
  .faq .body { animation: none; }
  .js .reveal { opacity: 1; transform: none; }
}
