/* REPLAYD website.
 *
 * The accent is the app's own: Palette.cs paints #FF8000 on dark and #964B00 on
 * light, the light one taken down until it clears 4.5:1 on white. The site uses
 * the same two so the page and the window agree -- when the app's orange moves,
 * these move with it, and so do the rgba() glow values below, which are the
 * same RGB with an alpha.
 */

:root {
  --bg: #ffffff;
  --bg-soft: #f6f6f7;
  --bg-card: #ffffff;
  --fg: #1b1b1e;
  --fg-dim: #5c5c66;
  --accent: #964b00;
  --accent-glow: rgba(150, 75, 0, 0.14);
  --accent-soft: rgba(150, 75, 0, 0.06);
  --edge: rgba(128, 128, 128, 0.28);
  --radius: 10px;
  --measure: 68ch;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #131316;
    --bg-soft: #1a1a1f;
    --bg-card: #17171c;
    --fg: #ebebeb;
    --fg-dim: #96969b;
    --accent: #ff8000;
    --accent-glow: rgba(255, 128, 0, 0.18);
    --accent-soft: rgba(255, 128, 0, 0.07);
    --edge: rgba(128, 128, 128, 0.30);
  }
}

*, *::before, *::after { box-sizing: border-box; }

/* The accent washes are body backgrounds rather than pseudo-elements. A pseudo
   with z-index:-1 once sat under a header that has backdrop-filter, and the two
   together put the sticky header a few hundred pixels down the page --
   backdrop-filter makes a stacking context and a negative z-index child is
   exactly what that breaks. A background image has no stacking to get wrong.
   (The hero's animated layer gets away with a pseudo because .hero isolates
   its own stacking context; see there.)

   Three washes rather than one, so the page has weather all the way down
   instead of a single spotlight and then flatness: the hero, a faint answer on
   the right around the middle, and a low glow rising to meet the closing
   download button. The last is anchored to the bottom, so it sits behind the
   final CTA on every page regardless of length. */
body {
  margin: 0;
  background:
    radial-gradient(900px 480px at 16% 170px, var(--accent-glow), transparent 70%),
    radial-gradient(760px 520px at 108% 46%, var(--accent-soft), transparent 70%),
    radial-gradient(1000px 420px at 50% calc(100% + 130px), var(--accent-glow), transparent 72%),
    var(--bg);
  background-repeat: no-repeat;
  color: var(--fg);
  font: 16px/1.6 system-ui, "Segoe UI", -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: 940px; margin: 0 auto; padding: 0 24px; }

/* --- header --- */

header {
  border-bottom: 1px solid var(--edge);
  position: sticky; top: 0;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(8px);
  z-index: 10;
}
header .wrap { display: flex; align-items: center; gap: 28px; height: 74px; }

/* The mark is the whole brand -- there is no wordmark beside it, so the logo
   carries the name and its alt text has to say it. */
.brand { display: flex; align-items: center; text-decoration: none; }
.brand img { display: block; width: 46px; height: 46px; }

/* --- hero --- */

/* padding-top/bottom rather than the shorthand. `padding: 92px 0 72px` zeroed
   the 24px sides .wrap sets, which nothing showed on a wide screen and which
   put the text flat against both edges on a phone. */
/* isolation:isolate is what makes the z-index:-1 layer safe this time: it
   fences the pseudo inside the hero's own stacking context, so it can sit
   behind the text without ever getting under the sticky header -- which is the
   bug the last attempt at this had. */
.hero { padding-top: 92px; padding-bottom: 68px; position: relative; isolation: isolate; }

/* A slow drift of the accent behind the headline, over the static wash the
   body paints. Transform only, so it stays on the compositor, and it breathes
   rather than moves -- decoration should be felt, not watched. */
.hero::before {
  content: "";
  position: absolute; z-index: -1; pointer-events: none;
  top: -120px; left: -15%; width: 75%; height: 130%;
  background: radial-gradient(closest-side at 35% 45%, var(--accent-glow), transparent);
  animation: hero-drift 16s ease-in-out infinite alternate;
}
@keyframes hero-drift {
  from { transform: translate3d(-3%, -2%, 0) scale(1); }
  to   { transform: translate3d(6%, 4%, 0) scale(1.18); }
}
@media (prefers-reduced-motion: reduce) {
  .hero::before { animation: none; }
}

.hero h1 {
  font-size: clamp(2.1rem, 6vw, 3.5rem);
  line-height: 1.08; margin: 0 0 22px; letter-spacing: -0.025em;
}
.hero p.lede {
  font-size: 1.16rem; color: var(--fg-dim);
  max-width: var(--measure); margin: 0 0 34px;
}

.cta { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }

.btn {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--accent); color: #fff;
  padding: 13px 26px; border-radius: var(--radius);
  font-weight: 600; text-decoration: none; font-size: 15.5px;
  border: 1px solid transparent;
}
.btn:hover { filter: brightness(1.08); }
.btn.secondary {
  background: transparent; color: var(--fg); border-color: var(--edge);
}

/* White rather than currentColor: the mark only ever sits on the accent button,
   where the text is white too. flex:none so a long filename cannot squeeze it. */
.btn svg { width: 20px; height: 20px; fill: #fff; flex: none; }

.meta { color: var(--fg-dim); font-size: 14px; }

/* --- sections --- */

section { padding: 56px 0; border-top: 1px solid var(--edge); }
section h2 {
  font-size: 1.05rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--fg-dim); margin: 0 0 30px; font-weight: 600;
}
.section-lede {
  color: var(--fg-dim); max-width: var(--measure);
  margin: -14px 0 30px; font-size: 15.5px;
}
.section-lede a { color: var(--accent); }

.grid { display: grid; gap: 28px; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.grid h3 { margin: 0 0 8px; font-size: 1.02rem; }
.grid p { margin: 0; color: var(--fg-dim); font-size: 15px; }

/* The three capture modes carry more weight than the feature notes below them,
   so they get an edge and a ground of their own. */
.cards { gap: 20px; }
.card {
  background: var(--bg-card); border: 1px solid var(--edge);
  border-radius: var(--radius); padding: 24px 24px 26px;
  transition: border-color 0.25s ease, transform 0.25s ease;
}
.card:hover {
  border-color: color-mix(in srgb, var(--accent) 45%, var(--edge));
  transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
  .card, .card:hover { transition: none; transform: none; }
}
.card h3 { font-size: 1.15rem; margin-bottom: 10px; }

/* --- the settings spread --- */

/* Column counts that divide the eight cells evenly -- 4, 2, or 1. auto-fit
   picked three on a wide screen, and eight into three leaves an empty ninth
   cell, which this grid paints in the gap colour: a grey hole in the bottom
   row. The gaps-as-borders trick only works when every cell exists. */
.spec-grid {
  display: grid; gap: 1px; background: var(--edge);
  border: 1px solid var(--edge); border-radius: var(--radius);
  overflow: hidden;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (min-width: 880px) {
  .spec-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.spec { background: var(--bg); padding: 22px 24px 24px; }
.spec h3 {
  margin: 0 0 8px; font-size: 0.95rem;
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--accent);
}
.spec p { margin: 0; color: var(--fg-dim); font-size: 14.5px; line-height: 1.55; }

/* --- panels, tables --- */

.panel {
  background: var(--bg-soft); border: 1px solid var(--edge);
  border-radius: var(--radius); padding: 24px 26px;
}

dl.specs { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 10px 22px; }
dl.specs dt { color: var(--fg-dim); font-size: 14.5px; }
dl.specs dd { margin: 0; font-size: 14.5px; }

code, .mono {
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: 0.9em;
}

.closing { text-align: center; }
.closing .cta { justify-content: center; }

.release { margin-bottom: 40px; }
.release h3 { margin: 0 0 4px; font-size: 1.15rem; }
.release .when { color: var(--fg-dim); font-size: 14px; margin: 0 0 12px; }
.release ul { margin: 0; padding-left: 20px; color: var(--fg-dim); }
.release li { margin-bottom: 6px; }

/* --- footer --- */

footer {
  border-top: 1px solid var(--edge); padding: 30px 0 52px;
  color: var(--fg-dim); font-size: 14px;
}
.footer-inner {
  display: flex; align-items: center; gap: 24px; flex-wrap: wrap;
}
.footer-brand { display: flex; align-items: center; gap: 10px; }
.footer-brand img { display: block; opacity: 0.85; }

.footer-links { display: flex; gap: 18px; }
footer a { color: var(--fg-dim); }
footer a:hover { color: var(--fg); }

.socials { margin-left: auto; display: flex; gap: 12px; }
.social {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 10px;
  border: 1px solid var(--edge); background: var(--bg-soft);
  color: var(--fg);
  transition: color 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}
.social svg { width: 20px; height: 20px; fill: currentColor; }
.social:hover {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 45%, var(--edge));
  transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
  .social, .social:hover { transition: none; transform: none; }
}

/* --- narrow --- */

@media (max-width: 620px) {
  .wrap { padding: 0 18px; }
  header .wrap { height: 64px; }
  .brand img { width: 38px; height: 38px; }
  .hero { padding-top: 56px; padding-bottom: 48px; }
  .hero p.lede { font-size: 1.05rem; }
  section { padding: 42px 0; }
  .cta { gap: 14px; }
  .btn { width: 100%; justify-content: center; }
  .socials { margin-left: 0; }
  .spec-grid { grid-template-columns: 1fr; }
}
