/* ============================================
   Showcase — shared styles
   All app pages link this file. Per-page <style>
   blocks override --accent, set the background
   gradient, and add any unique layout.
   ============================================ */

/* ── TOKENS ── */
:root {
  --bg:           #f5f5f7;
  --surface:      #ffffff;
  --surface-2:    #f0f0f5;
  --text:         #1d1d1f;
  --text-muted:   #6e6e73;
  --accent:       #0071e3;
  --accent-hover: #0077ed;
  --border:       rgba(0,0,0,0.08);
  --shadow:       0 4px 24px rgba(0,0,0,0.06);
  --shadow-lg:    0 20px 60px rgba(0,0,0,0.12);
  --radius-card:  20px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:           #000000;
    --surface:      #1c1c1e;
    --surface-2:    #2c2c2e;
    --text:         #f5f5f7;
    --text-muted:   #a1a1a6;
    --accent:       #0a84ff;
    --accent-hover: #409cff;
    --border:       rgba(255,255,255,0.10);
    --shadow:       0 4px 24px rgba(0,0,0,0.4);
    --shadow-lg:    0 20px 60px rgba(0,0,0,0.6);
  }
}

/* ── RESET ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; }

/* ── FOCUS ── */
/* Single global :focus-visible ring so keyboard users always see where
   they are.  Uses --accent so it picks up each page's brand colour;
   2px outline + 2px offset reads on light, dark, and gradient bgs. */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}
.btn:focus-visible,
.app-card:focus-visible,
.carousel-nav:focus-visible,
.screenshot-card-inner:focus-visible {
  outline-offset: 3px;
}


/* ── TYPE ── Fraunces (display) over Space Grotesk (text), self-hosted.
   Both variable, latin + latin-ext only, carrying Google's own
   unicode-ranges so a visitor fetches just the subset they need. */
@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  /* Relative to this stylesheet (/apps/shared.css), so it resolves to
     /apps/fonts/ from the index at the root and from every app page. */
  src: url('fonts/fraunces-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: 'Fraunces';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  /* Relative to this stylesheet (/apps/shared.css), so it resolves to
     /apps/fonts/ from the index at the root and from every app page. */
  src: url('fonts/fraunces-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-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  /* Relative to this stylesheet (/apps/shared.css), so it resolves to
     /apps/fonts/ from the index at the root and from every app page. */
  src: url('fonts/spacegrotesk-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: 'Space Grotesk';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  /* Relative to this stylesheet (/apps/shared.css), so it resolves to
     /apps/fonts/ from the index at the root and from every app page. */
  src: url('fonts/spacegrotesk-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-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --font-display: 'Fraunces', Georgia, 'Times New Roman', serif;
  --font-text:    'Space Grotesk', -apple-system, BlinkMacSystemFont,
                  system-ui, 'Helvetica Neue', Arial, sans-serif;
}

/* opsz is set per level rather than left to font-optical-sizing, because
   font-variation-settings (needed for SOFT/WONK) overrides automatic
   optical sizing and would otherwise pin every heading to one size. */
h1, h2, h3 {
  font-family: var(--font-display);
  font-optical-sizing: auto;
}
h1 { font-variation-settings: 'SOFT' 40, 'WONK' 1, 'opsz' 96; }
h2 { font-variation-settings: 'SOFT' 40, 'WONK' 1, 'opsz' 48; }
h3 { font-variation-settings: 'SOFT' 40, 'WONK' 1, 'opsz' 20; }

/* The uppercase eyebrows are labels, not headings — they stay in the text
   face, where the wide tracking still reads. Both happen to be h2s. */
.screenshots h2,
.section-label {
  font-family: var(--font-text);
  font-variation-settings: normal;
}

body {
  font-family: var(--font-text);
  font-size: 17px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  min-height: 100vh;
}

/* ── LINKS ──
   Site-wide replacement for the browser-default underline: a hairline
   border-bottom in the link colour. Sits a hair below the baseline so
   descenders aren't clipped, fades on hover. Container classes that
   Scoped to actual prose contexts: paragraphs, long-form `.post-body`,
   and feature-list items.  Buttons, nav, app cards, h2 anchors etc.
   inherit the default browser `text-decoration: none` so they stay
   clean without needing an opt-out. */
a {
  color: var(--accent);
  text-decoration: none;
}
p a,
.post-body a,
.features-list li a {
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  padding-bottom: 1px;
  transition: border-color 0.15s ease;
}
p a:hover,
.post-body a:hover,
.features-list li a:hover {
  border-bottom-color: var(--accent);
}

/* ── TOP NAV ── */
.topnav {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 28px;
  height: 52px;
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border-bottom: 1px solid var(--border);
}

.topnav-home {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--accent);
  text-decoration: none;
  border-bottom: none;
  padding-bottom: 0;
  transition: opacity 0.15s;
}
.topnav-home:hover { opacity: 0.72; border-bottom-color: transparent; }

.topnav-home svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

.topnav-sep {
  color: var(--text-muted);
  font-size: 14px;
  opacity: 0.5;
  user-select: none;
}

.topnav-title {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--text-muted);
}

/* ── MAIN CONTAINER ── */
main {
  max-width: 980px;
  margin: 0 auto;
  padding: 0 24px;
}

/* ── HERO ── */
.hero {
  text-align: center;
  padding: 92px 0 72px;
}

/* Polaroid-style frame around the hero icon — the wrap is a rounded
   square (white in light mode, elevated dark gray in dark mode), the
   icon sits inside it with a small inset.  Matches the framed-icon
   look PastePlop had baked into its source PNG. */
.app-icon-wrap {
  margin: 0 auto 28px;
  width: 130px;
  height: 130px;
  padding: 12px;
  background: #ffffff;
  border-radius: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  box-shadow:
    var(--shadow-lg),
    0 0 0 1px rgba(0,0,0,0.06);
}

@media (prefers-color-scheme: dark) {
  .app-icon-wrap {
    /* Elevated material — slightly lighter than typical dark surfaces
       so the frame still reads as a card lifted off the page bg.
       The hairline flips to a subtle white edge for definition. */
    background: #1c1c1e;
    box-shadow:
      var(--shadow-lg),
      0 0 0 1px rgba(255,255,255,0.08),
      inset 0 1px 0 rgba(255,255,255,0.06);
  }
}

.app-icon-wrap svg,
.app-icon-wrap img {
  width: 120px;
  height: 120px;
  border-radius: 27px;
  display: block;
  box-shadow: none;
}

.hero h1 {
  font-size: clamp(52px, 8vw, 72px);
  font-weight: 700;
  letter-spacing: -0.02em;
  /* line-height needs to be ≥ 1.1 so descenders on p / g / y don't
     get cropped — pages that use background-clip: text are especially
     prone to clipping the gradient at the line-box bottom. */
  line-height: 1.1;
  padding-bottom: 0.05em;
  margin-bottom: 18px;
  /* default — pages override with gradient text */
  color: var(--text);
}

.hero .tagline {
  font-size: clamp(17px, 2.4vw, 21px);
  font-weight: 400;
  color: var(--text-muted);
  max-width: 580px;
  margin: 0 auto 44px;
  letter-spacing: -0.01em;
  line-height: 1.45;
}

.hero-cta {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin-bottom: 18px;
  flex-wrap: wrap;
}

.requirements {
  font-size: 13px;
  color: var(--text-muted);
  opacity: 0.65;
  margin-top: 4px;
}

/* Quiet bundle pointer under a buy-button row. A step more present than
   .requirements (no opacity knock-down) so the link reads as an offer
   rather than fine print, but still clearly secondary to the buttons. */
.bundle-note {
  font-size: 14px;
  color: var(--text-muted);
  margin-top: -4px;
  margin-bottom: 6px;
}

/* ── BUTTONS ── */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 13px 28px;
  font-size: 16px;
  font-weight: 500;
  font-family: inherit;
  text-decoration: none;
  border-bottom: none;
  border-radius: 980px;
  transition: transform 0.18s ease, box-shadow 0.18s ease, background 0.15s ease;
  cursor: pointer;
  border: none;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

.btn-primary {
  background: var(--accent);
  color: #ffffff;
  box-shadow: 0 4px 20px rgba(0,0,0,0.18);
}
.btn-primary:hover {
  background: var(--accent-hover);
  transform: translateY(-1px);
  box-shadow: 0 8px 28px rgba(0,0,0,0.22);
}

.btn-disabled, .btn-disabled:hover {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  color: color-mix(in srgb, var(--accent) 70%, transparent);
  box-shadow: none;
  cursor: not-allowed;
  transform: none;
}

.btn-ghost {
  /* White fill (rather than transparent) so the secondary
     "free trial" download reads as a solid button. Text is the
     accent darkened toward near-black so it stays legible on
     white in dark mode too, where --accent is a light tint. */
  background: #ffffff;
  color: color-mix(in srgb, var(--accent) 70%, #111418);
  border: 1.5px solid color-mix(in srgb, var(--accent) 35%, transparent);
}
.btn-ghost:hover {
  background: #eef1f6;
  border-color: var(--accent);
  transform: translateY(-1px);
}

/* ── DARK-MODE BUTTON LABELS ──
   Each page flips --accent from a saturated colour to a light tint for dark
   mode, so `.btn-primary`'s white label ends up on a light ground. Measured
   across all 24 pages that use this sheet, every one failed WCAG AA — worst
   was NoteLess at 1.62:1, ListenUp 1.75:1. A near-black label on the same
   tint clears AA everywhere (worst case 5.19:1, FilePop).

   .btn-ghost has the same problem from the other direction: its background is
   hard-coded white in both themes, and the 70%-accent text goes too pale once
   --accent is a dark-mode tint (3.02:1 on NoteLess). Pulling the mix to 50%
   toward near-black clears AA (worst 5.02:1) and keeps the accent hue.

   Pages that already handle this themselves (NoteLess sets its own dark label,
   StyleBop swaps in a dark gradient that white passes on) override these by
   virtue of their page <style> loading after this file. */
@media (prefers-color-scheme: dark) {
  .btn-primary,
  .btn-primary:hover { color: #0d1117; }
  .btn-ghost,
  .btn-ghost:hover { color: color-mix(in srgb, var(--accent) 50%, #111418); }
}


/* ── SVG SHOWCASE ILLUSTRATION ──
   Fills the same content column as everything else in <main> (980px cap
   less main's 24px gutters = 932px). It used to sit at 860px with its own
   16px padding, which put the hero figure 52px in from the edges of the
   feature grid and CTA blocks directly below it — a visible step in the
   left/right margin on every app page. Keep this flush with main. */
.showcase {
  margin: 0 auto 64px;
  max-width: none;
  padding: 0;
}
.showcase svg,
.showcase img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 16px;
}

/* ── SCREENSHOT RAIL (shared) ──
   Structure is identical across every app page; the only per-app variation is
   the card's shadow/background tint, exposed via the --shot-* custom
   properties (defaults below = the neutral blue). A page that wants its accent
   tint sets --shot-shadow / --shot-shadow-dark (and optionally --shot-bg*) in
   its :root. */
.screenshots {
  position: relative;
  width: 100vw;
  margin: 80px calc(50% - 50vw) 60px;
  padding: 0;
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent 0%, #000 12%, #000 88%, transparent 100%);
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 12%, #000 88%, transparent 100%);
}
.screenshots h2 {
  text-align: center;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
  opacity: 0.7;
  margin-bottom: 24px;
}
.screenshot-rail {
  display: flex;
  gap: 32px;
  padding: 60px 50vw 80px 50vw;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.screenshot-rail::-webkit-scrollbar { display: none; }
.screenshot-card {
  flex: 0 0 auto;
  /* Matches main's content column exactly (980px cap less 24px gutters,
     or the viewport less those gutters below the cap) so the centred card
     lines up with the feature grid above it. Was min(900px, 90vw), which
     landed 16px inside the column on desktop and 9px outside it on phones. */
  width: min(932px, calc(100vw - 48px));
  scroll-snap-align: center;
  scroll-snap-stop: always;
}
.screenshot-card-inner {
  border-radius: 18px;
  overflow: hidden;
  background: var(--shot-bg, rgba(255,255,255,0.6));
  box-shadow: var(--shot-shadow,
    0 30px 60px -20px rgba(20,40,90,0.30),
    0 10px 24px -10px rgba(20,40,90,0.18),
    0 0 0 1px rgba(0,0,0,0.06));
}
@media (prefers-color-scheme: dark) {
  .screenshot-card-inner {
    background: var(--shot-bg-dark, rgba(255,255,255,0.04));
    box-shadow: var(--shot-shadow-dark,
      0 30px 60px -20px rgba(0,0,0,0.55),
      0 10px 24px -10px rgba(0,0,0,0.40),
      0 0 0 1px rgba(255,255,255,0.10));
  }
}
.screenshot-card-inner img,
.screenshot-card-inner video {
  display: block;
  width: 100%;
  height: auto;
}
@supports (animation-timeline: view()) {
  .screenshot-card-inner {
    animation: screenshotFocus linear both;
    animation-timeline: view(inline);
    animation-range: cover 10% cover 90%;
  }
  @keyframes screenshotFocus {
    0%, 100% { transform: scale(0.88); filter: blur(3px) brightness(0.6) saturate(0.8); }
    50%      { transform: scale(1);    filter: blur(0) brightness(1) saturate(1); }
  }
}

/* Tap-to-zoom hint — wired up by shared.js for screenshot carousels */
.screenshot-card-inner.is-zoomable { cursor: zoom-in; position: relative; }

/* Corner zoom badge — visible only on touch devices so desktop users
   keep the clean cursor:zoom-in hint while mobile users see something
   tappable. */
.zoom-hint {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: rgba(0,0,0,0.55);
  color: #fff;
  display: none;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  z-index: 4;
}
.zoom-hint svg { width: 14px; height: 14px; }

/* Carousel prev/next buttons — injected by shared.js, shown only on
   touch where the horizontal-scroll affordance is otherwise invisible. */
.carousel-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 5;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid rgba(0,0,0,0.10);
  background: rgba(255,255,255,0.85);
  color: #1d1d1f;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 0;
  appearance: none;
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(0,0,0,0.12);
  -webkit-backdrop-filter: blur(20px);
  backdrop-filter: blur(20px);
  transition: transform 0.15s, opacity 0.15s;
}
.carousel-nav:active { transform: translateY(-50%) scale(0.94); }
/* Hug the centered card (max 900px wide) rather than the far screen
   edges: sit just outside each card edge on wide viewports, clamping to
   a 16px edge inset once the card goes full-width on narrow screens. */
.carousel-nav--prev { left: max(16px, calc(50vw - 512px)); }
.carousel-nav--next { right: max(16px, calc(50vw - 512px)); }
.carousel-nav svg { width: 14px; height: 14px; }
@media (prefers-color-scheme: dark) {
  .carousel-nav {
    background: rgba(40,40,46,0.85);
    color: #f5f5f7;
    border-color: rgba(255,255,255,0.10);
  }
  .zoom-hint { background: rgba(255,255,255,0.18); }
}

/* Show on real touch devices OR on narrow viewports — covers Chrome
   DevTools' mobile emulator, which doesn't always flip the (hover: none)
   media feature even with the device toolbar engaged. */
@media (hover: none), (max-width: 820px) {
  .carousel-nav { display: flex; }
  .screenshot-card-inner.is-zoomable .zoom-hint { display: flex; }
  /* Drop the edge fade on mobile — with the card near full-width it just
     clips the visible screenshot instead of hinting at off-screen cards. */
  .screenshots { -webkit-mask-image: none; mask-image: none; }
}

/* Desktop (hover-capable, wide): the arrows stay hidden until the visitor
   hovers the carousel, then fade in — so the rail reads clean at rest but
   is obviously steppable on approach. Keyboard focus reveals them too. */
@media (hover: hover) and (min-width: 821px) {
  .carousel-nav {
    display: flex;
    opacity: 0;
    pointer-events: none;
  }
  .screenshots:hover .carousel-nav,
  .screenshots:focus-within .carousel-nav {
    opacity: 1;
    pointer-events: auto;
  }
}

/* An arrow with nowhere to go is disabled by shared.js. It has to out-rank
   the two rules above — `.screenshots:hover .carousel-nav` is (0,3,0), so a
   bare `.carousel-nav:disabled` at (0,2,0) would lose and the arrow would
   reappear on hover — hence the compound selectors. */
.carousel-nav:disabled,
.screenshots:hover .carousel-nav:disabled,
.screenshots:focus-within .carousel-nav:disabled {
  opacity: 0;
  pointer-events: none;
}

/* ── MOBILE GUARD ──
   Injected by shared.js wireMobileGuard() on Mac-only app pages when
   the visitor is on iOS / iPadOS / Android.  A small chip above each
   download CTA explaining the app is Mac-only, with a mailto link to
   email the URL to themselves.  Tinted with the page's own --accent
   so it picks up each app's brand color. */
.mobile-guard {
  display: block;
  max-width: 480px;
  margin: 0 auto 16px;
  padding: 12px 18px;
  border-radius: 14px;
  background: color-mix(in srgb, var(--accent) 8%, var(--surface) 92%);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  color: var(--text);
  font-size: 13.5px;
  line-height: 1.45;
  text-align: center;
}
.mobile-guard a {
  color: var(--accent);
  font-weight: 500;
  /* No text-decoration here — the site-wide `p a` rule already adds a
     hairline border-bottom underline. Setting `text-decoration: underline`
     on top of that produces a double underline. */
}

/* ── SITE FOOTER ──
   Single canonical footer for the homepage AND every app page.
   Three slots: "Made on a Mac." · social icons · copyright.
   Picks up each page's --accent for link hover & icon focus.
   Full page width (no max-width cap) — was 1060px/centered here but
   already full-width via a per-page override on the homepage; made
   the shared rule match so every page is consistent by default. */
.site-footer {
  max-width: none;
  margin: 0;
  padding: 24px 32px 52px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  font-size: 13px;
  color: var(--text-muted);
}
@media (max-width: 700px) {
  .site-footer { padding: 24px 20px 40px; }
}
.site-footer a { color: var(--accent); text-decoration: none; }
.site-footer a:hover { text-decoration: underline; }
.site-footer .social {
  display: inline-flex;
  gap: 14px;
  align-items: center;
}
.site-footer .social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px; height: 28px;
  border-radius: 8px;
  color: var(--text-muted);
  transition: color 0.15s, background 0.15s;
}
.site-footer .social a:hover {
  color: var(--text);
  background: var(--surface);
  text-decoration: none;
}
.site-footer .social svg {
  width: 15px; height: 15px;
  display: block;
}

/* ── SECTION LABEL ──
   Used as an <h2> on detail pages so screen-reader heading nav can
   jump to the features block.  Visual treatment is the same uppercase
   eyebrow as before — explicitly reset h2's default margins. */
.section-label {
  text-align: center;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
  opacity: 0.6;
  margin: 0 0 28px;
}

/* ── FEATURES: HERO CARDS (3-column) ── */
.features-hero {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 18px;
  padding: 36px 0 20px;
}

.feature-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 32px 28px;
  box-shadow: var(--shadow);
  transition: transform 0.22s ease, box-shadow 0.22s ease;
}

.feature-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}

.feature-icon {
  width: 46px;
  height: 46px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  font-weight: 600;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-radius: 12px;
  margin-bottom: 18px;
}

.feature-card h3 {
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-bottom: 8px;
  color: var(--text);
}

.feature-card p {
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--text-muted);
}

/* ── FEATURES: DETAIL LIST ── */
.features-list {
  padding: 8px 0 80px;
}

.features-list ul {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 0 32px;
  padding: 22px 26px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
}

.features-list li {
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--text-muted);
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}

.features-list li:last-child { border-bottom: none; }

.features-list strong {
  color: var(--text);
  font-weight: 600;
}

.features-list code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 13px;
  background: color-mix(in srgb, var(--text) 8%, transparent);
  padding: 1px 5px;
  border-radius: 4px;
}

/* ── CTA / DOWNLOAD SECTION ── */
.cta-section {
  text-align: center;
  padding: 72px 0;
  border-top: 1px solid var(--border);
}

.cta-section h2 {
  font-size: clamp(30px, 5vw, 44px);
  font-weight: 700;
  letter-spacing: -0.015em;
  margin-bottom: 12px;
  color: var(--text);
}

.cta-section .cta-sub {
  font-size: 17px;
  color: var(--text-muted);
  margin-bottom: 32px;
  max-width: 480px;
  margin-left: auto;
  margin-right: auto;
}

/* ── ON IPHONE AND IPAD band ── copy beside a pair of device shots.
   Collapses to a single column under 860px, where the two shots stay
   side by side rather than stacking further. */
.platform-band {
  display: grid;
  grid-template-columns: 1fr 1.15fr;
  gap: 48px;
  align-items: center;
  padding: 8px 0 44px;
}
.platform-copy h3 {
  font-size: clamp(24px, 3vw, 34px);
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.15;
  color: var(--text);
  margin-bottom: 16px;
}
.platform-copy p {
  font-size: 16px;
  line-height: 1.6;
  color: var(--text-muted);
  margin-bottom: 12px;
}
.platform-copy p:last-child { margin-bottom: 0; }
.platform-shots {
  display: flex;
  align-items: flex-end;
  gap: 20px;
}
/* Each shot sits in its own stacking context so the device's side
   buttons (z-index: -1 pseudo-elements) tuck behind the frame body
   instead of falling behind the page. */
.platform-shot { position: relative; z-index: 0; }
.platform-shot--ipad   { flex: 1 1 68%; }
.platform-shot--iphone { flex: 1 1 32%; }

/* ── DECORATIVE DEVICE CHROME ──
   Pure CSS, no image assets. Purely ambient: it carries no alt text
   and nothing meaningful, so screen readers only ever see the
   screenshot inside it. The captures already include their own
   status bar — and, on iPhone, the Dynamic Island — so the frame
   deliberately draws no notch of its own and would double it. */
.device {
  position: relative;
  padding: var(--bezel);
  background:
    linear-gradient(155deg, #55555c 0%, #26262b 22%, #17171b 55%, #3a3a42 100%);
  border-radius: var(--outer-r);
  box-shadow:
    0 26px 52px -20px rgba(0, 0, 0, 0.5),
    0 3px 8px rgba(0, 0, 0, 0.3),
    inset 0 0 0 1px rgba(255, 255, 255, 0.14);
}
.device picture { display: block; }
.device img {
  display: block;
  width: 100%;
  height: auto;
  background: #000;
  /* Concentric with the outer corner, so the bezel stays even. */
  border-radius: calc(var(--outer-r) - var(--bezel));
}

.device--ipad   { --bezel: 8px; --outer-r: 22px; }
.device--iphone { --bezel: 6px; --outer-r: 32px; }

/* Side buttons. Tucked behind the frame body so they read as part of
   the enclosure rather than tabs stuck onto it. */
.device::before,
.device::after {
  content: "";
  position: absolute;
  z-index: -1;
  background: linear-gradient(180deg, #4a4a52, #22222a);
  border-radius: 2px;
}
/* iPad, landscape: power on the top edge, volume pair on the right. */
.device--ipad::before {
  top: -3px; right: 16%;
  width: 12%; height: 6px;
  border-radius: 3px 3px 0 0;
}
.device--ipad::after {
  right: -3px; top: 14%;
  width: 6px; height: 22%;
  border-radius: 0 3px 3px 0;
  /* Two stacked buttons drawn as one bar with a transparent gap. */
  background:
    linear-gradient(180deg, #4a4a52, #22222a) center top / 100% 44% no-repeat,
    linear-gradient(180deg, #4a4a52, #22222a) center bottom / 100% 44% no-repeat;
}
/* iPhone, portrait: volume pair on the left, power on the right. */
.device--iphone::before {
  left: -3px; top: 20%;
  width: 6px; height: 20%;
  border-radius: 3px 0 0 3px;
  background:
    linear-gradient(180deg, #4a4a52, #22222a) center top / 100% 40% no-repeat,
    linear-gradient(180deg, #4a4a52, #22222a) center bottom / 100% 40% no-repeat;
}
.device--iphone::after {
  right: -3px; top: 26%;
  width: 6px; height: 16%;
  border-radius: 0 3px 3px 0;
}

/* On the near-black dark background the frame's own dark grey loses
   its outer edge, so lift the body a step and strengthen the ring. */
@media (prefers-color-scheme: dark) {
  .device {
    background:
      linear-gradient(155deg, #6a6a74 0%, #34343c 22%, #23232a 55%, #4a4a54 100%);
    box-shadow:
      0 26px 52px -20px rgba(0, 0, 0, 0.75),
      0 3px 8px rgba(0, 0, 0, 0.5),
      inset 0 0 0 1px rgba(255, 255, 255, 0.22);
  }
  .device::before, .device::after {
    background: linear-gradient(180deg, #5c5c68, #33333c);
  }
  .device--ipad::after {
    background:
      linear-gradient(180deg, #5c5c68, #33333c) center top / 100% 44% no-repeat,
      linear-gradient(180deg, #5c5c68, #33333c) center bottom / 100% 44% no-repeat;
  }
  .device--iphone::before {
    background:
      linear-gradient(180deg, #5c5c68, #33333c) center top / 100% 40% no-repeat,
      linear-gradient(180deg, #5c5c68, #33333c) center bottom / 100% 40% no-repeat;
  }
}

/* Buttons are a fussy detail at thumbnail scale — drop them once the
   band goes single-column and the shots shrink. */
@media (max-width: 620px) {
  .device::before, .device::after { display: none; }
}
@media (max-width: 860px) {
  .platform-band { grid-template-columns: 1fr; gap: 32px; }
}

/* ── FOOTER ── */
footer {
  text-align: center;
  padding: 32px 0 28px;
  border-top: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 13px;
}

footer a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: none;
  padding-bottom: 0;
  transition: opacity 0.15s;
}
footer a:hover { opacity: 0.72; border-bottom-color: transparent; }

/* ── WEB APP PREVIEW FRAME ── */
.app-preview-frame {
  margin: 0 0 72px;
  border-radius: 16px;
  overflow: hidden;
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  background: var(--surface);
}

.app-preview-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 14px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}

.app-preview-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
}
.app-preview-dot.red    { background: #ff5f57; }
.app-preview-dot.yellow { background: #febc2e; }
.app-preview-dot.green  { background: #28c840; }

/* ── RESPONSIVE ── */
@media (max-width: 640px) {
  .hero { padding: 60px 0 48px; }
  .hero h1 { font-size: 44px; }
  .hero .tagline { font-size: 17px; }
  .btn { width: 100%; max-width: 280px; justify-content: center; }
  /* When the CTAs stack, the buttons' big drop-shadows merge into one
     continuous halo at the default 12px gap. Give them breathing room. */
  .hero-cta { gap: 22px; }
  .features-hero { padding: 24px 0 12px; gap: 14px; }
  .feature-card { padding: 24px 20px; }
  .features-list ul { padding: 16px 18px; }
  .cta-section { padding: 52px 0; }
}

/* ── DOC PAGES ──
 * shared.css's universal reset zeros every element's margin, so paragraph
 * spacing inside docs.html was visually nil. Restore a vertical rhythm
 * shared by every docs page on the site (chopshop, crosshair, movematic, …).
 * Per-page docs CSS still owns headings, code blocks, tables, callouts.
 */
.doc-content p,
.doc-content ul,
.doc-content ol {
  margin-bottom: 14px;
}

/* ── PRIVACY POLICIES ── */
/* Every privacy page sets `.privacy-wrap p { color: … }` in its own
   <style>, but none declares a margin, and the reset at the top of this
   file zeroes it. That went unnoticed for as long as each section was a
   single paragraph; the moment one has several they run together with no
   gap. Declared here rather than in 30 page-level blocks — the per-page
   rules only set colour, so this isn't overridden. Matches the 14px the
   doc-content lists use above. */
.privacy-wrap p {
  margin: 0 0 14px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition: none !important;
    animation: none !important;
  }
  html { scroll-behavior: auto; }
}
