/*
Theme Name: Photo Geotag
Theme URI: https://photogeotag.app/
Author: Sandro Gumz
Author URI: https://photogeotag.app/
Description: Marketing site for Photo Geotag — finds photos with no GPS, infers where they were taken from the geotagged shots around them, and asks you to confirm on a map. Ported from the static site in PhotoGeotag/website.
Version: 1.0.0
Requires at least: 6.4
Requires PHP: 8.1
License: Proprietary
Text Domain: photogeotag
*/

/* Everything below is the static site's styles.css, carried over unchanged so
   the rendered result matches the sample exactly. */

/* Photo Geotag — marketing site.
   Tokens come straight from docs/design/design-language.md:
   green #2FD15A certain · amber #FFB020 likely · violet #BF5AF0 uncertain ·
   blue #0A84FF manual · pill #2F363C · ink #16181C · sub #5C626B */

:root {
  --certain: #2fd15a;
  --likely: #ffb020;
  --uncertain: #bf5af0;
  --manual: #0a84ff;
  --pill: #2f363c;
  --ink: #16181c;
  --sub: #5c626b;
  --bg: #f7f7f9;
  --card-radius: 20px;
}

*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", system-ui, sans-serif;
  background: var(--bg);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  line-height: 1.55;
}

.skip {
  position: absolute; left: -999px; top: 8px; z-index: 99;
  background: var(--pill); color: #fff; padding: 8px 14px; border-radius: 10px;
}
.skip:focus { left: 8px; }

/* ------------------------------ nav ------------------------------ */

.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  padding: 12px 0;
  background: rgba(247, 247, 249, .82);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border-bottom: 1px solid rgba(0, 0, 0, .06);
}
/* The bar itself stays full-bleed (position/background/border above); its
   content is pulled back into the same 1280px column as .band and the
   language banner (Task 19 — owner: "align the header and footer to use the
   same max-w for the container"). The flex row that used to live on .nav
   moves here unchanged; nav-mobile.css's #site-nav dropdown panel still
   positions off .nav (the nearest `position` ancestor), not this wrapper, so
   it keeps spanning the full bar underneath it. */
.nav-inner {
  display: flex; align-items: center; gap: 26px;
  max-width: 1280px; margin: 0 auto; padding: 0 26px;
}

.brand {
  display: flex; align-items: center; gap: 9px;
  font-size: 17px; font-weight: 750; letter-spacing: -.3px;
  color: var(--ink); text-decoration: none;
}
/* The mark is the app icon, so it carries its own rounded ground — the artwork
   inside only fills about half the box, where the old bare pin glyph filled the
   whole 26px. 28px puts the pin back at the wordmark's cap height.
   The -1px is optical, not arbitrary: align-items:center centres the mark on
   the wordmark's LINE box, and that box's centre sits below its cap-height
   centre by half the descender, so a mark taller than the caps reads low. */
.brand-mark { width: 28px; height: 28px; display: block; margin-top: -1px; }
.brand-mark svg,
.brand-mark img { width: 100%; height: 100%; display: block; }

/* align-items: center, not the flex default of stretch — the language-switcher
   pill (see header.php, inside #site-nav since Task 12) is 36px tall, and
   stretch was making every plain <a> match that height with its text sitting
   at the top of the stretched box instead of centred against the pill and the
   Download button beside it. Block-level under 900px (nav-mobile.css), where
   align-items no longer applies. */
.nav nav { display: flex; align-items: center; gap: 20px; margin-left: auto; }
.nav nav a {
  color: var(--sub); text-decoration: none; font-size: 14px; font-weight: 600;
}
.nav nav a:hover { color: var(--ink); }

/* ------------------------------ buttons ------------------------------ */

.cta-btn {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--manual); color: #fff; text-decoration: none;
  font-weight: 650; font-size: 15px;
  padding: 12px 22px; border-radius: 13px;
  box-shadow: 0 3px 10px rgba(10, 132, 255, .32);
  transition: transform .15s ease, box-shadow .15s ease;
}
.cta-btn:hover { transform: translateY(-1px); box-shadow: 0 6px 16px rgba(10, 132, 255, .4); }
.cta-btn.small { padding: 8px 16px; font-size: 13.5px; border-radius: 11px; }
.cta-btn.big { padding: 15px 30px; font-size: 17px; border-radius: 15px; }

.cta-ghost {
  display: inline-flex; align-items: center;
  color: var(--ink); text-decoration: none; font-weight: 650; font-size: 15px;
  padding: 12px 18px; border-radius: 13px;
  border: 1.5px solid rgba(22, 24, 28, .22);
  transition: border-color .15s ease;
}
.cta-ghost:hover { border-color: rgba(22, 24, 28, .5); }

/* App Store badge — Apple's official artwork, sized and lifted the same way
   rawtoheic.app / mergehdr.app / filters.app do it, so the network's sites
   present the same download affordance. Replaces the hand-drawn two-button
   lockup (App Store + Mac App Store) the static site used: one Universal
   Purchase listing covers iPhone, iPad and Mac. */
.badge-appstore {
  display: inline-block; line-height: 0;
  border-radius: 12px;
  box-shadow: 0 3px 12px rgba(0, 0, 0, .25);
  transition: transform .15s ease, box-shadow .15s ease;
}
.badge-appstore:hover { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(0, 0, 0, .32); }
.badge-appstore img { display: block; height: 52px; width: auto; }

/* Inside a prose page the badge sits between the intro and the first heading
   and needs room beneath it. The static download page carried this as an inline
   style on the wrapper; as a rule it applies wherever a badge lands in copy. */
.prose .hero-ctas { margin: 6px 0 34px; }

/* section "learn more" links */
.more { margin: 26px 0 0; font-size: 15px; font-weight: 650; }
.more a { color: var(--manual); text-decoration: none; }
.more a:hover { text-decoration: underline; }
.band.dark .more a { color: #6db2ff; }
.hero-ctas.centered { justify-content: center; }

/* ------------------------------ hero ------------------------------ */

.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: flex; align-items: center;
  overflow: hidden;
}

.hero-map { position: absolute; inset: 0; }

.map-svg { position: absolute; inset: 0; width: 100%; height: 100%; }

.track-svg {
  position: absolute; inset: 0; width: 100%; height: 100%;
  overflow: visible; pointer-events: none;
}

.marker-layer { position: absolute; inset: 0; pointer-events: none; }

/* photo thumbnails double as map markers — tiny SVG postcards of the places
   themselves, so the pins read as photos taken there */
.ph-park { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23cfe6f2'/%3E%3Ccircle cx='22' cy='30' r='14' fill='%234e8f4e'/%3E%3Ccircle cx='78' cy='28' r='15' fill='%23568f52'/%3E%3Crect y='52' width='100' height='48' fill='%23d9c9a3'/%3E%3Ccircle cx='50' cy='66' r='16' fill='%238fc3dd'/%3E%3Crect x='46' y='40' width='8' height='22' fill='%23a08c6a'/%3E%3Ccircle cx='50' cy='38' r='6' fill='%23b9a67f'/%3E%3C/svg%3E"); background-size: cover; }
.ph-pond { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23d8ecf7'/%3E%3Crect y='58' width='100' height='42' fill='%237fb7d6'/%3E%3Cpath d='M8,58 Q50,34 92,58' stroke='%23f0ead8' stroke-width='7' fill='none'/%3E%3Ccircle cx='15' cy='40' r='12' fill='%234e8f4e'/%3E%3Ccircle cx='86' cy='38' r='13' fill='%23568f52'/%3E%3C/svg%3E"); background-size: cover; }
.ph-mall { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23bfe0a2'/%3E%3Cpath d='M35,100 L47,20 L53,20 L65,100 Z' fill='%23cbb894'/%3E%3Ccircle cx='20' cy='35' r='16' fill='%23417e43'/%3E%3Ccircle cx='80' cy='35' r='16' fill='%23417e43'/%3E%3Ccircle cx='32' cy='16' r='12' fill='%234e8f4e'/%3E%3Ccircle cx='68' cy='16' r='12' fill='%234e8f4e'/%3E%3C/svg%3E"); background-size: cover; }
.ph-times { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23222a38'/%3E%3Crect x='8' y='12' width='30' height='20' fill='%23ff4d6d'/%3E%3Crect x='55' y='8' width='36' height='24' fill='%2333c1ff'/%3E%3Crect x='12' y='42' width='24' height='16' fill='%23ffd166'/%3E%3Crect x='48' y='40' width='42' height='20' fill='%23a06bf5'/%3E%3Crect x='20' y='68' width='60' height='32' fill='%23151b26'/%3E%3Crect x='30' y='74' width='8' height='26' fill='%23f2e14c'/%3E%3Crect x='55' y='74' width='8' height='26' fill='%23ef7d3a'/%3E%3C/svg%3E"); background-size: cover; }
.ph-rock { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23f7c08b'/%3E%3Crect y='48' width='100' height='52' fill='%23e58f74'/%3E%3Cg fill='%232e3444'%3E%3Crect x='6' y='42' width='11' height='58'/%3E%3Crect x='22' y='30' width='13' height='70'/%3E%3Crect x='40' y='45' width='10' height='55'/%3E%3Cpath d='M58,100 V38 h10 v-8 h4 v8 h6 V100 Z'/%3E%3Cpath d='M63,30 h8 l-4,-14 Z'/%3E%3Crect x='84' y='50' width='10' height='50'/%3E%3C/g%3E%3C/svg%3E"); background-size: cover; }
.ph-flatiron { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23d8e9f4'/%3E%3Cpath d='M50,12 L80,92 L20,92 Z' fill='%23b08a68'/%3E%3Cpath d='M50,12 L50,92' stroke='%23926f52' stroke-width='3'/%3E%3Cg stroke='%23e7d9c8' stroke-width='1.5'%3E%3Cpath d='M40,46 H60'/%3E%3Cpath d='M34,62 H66'/%3E%3Cpath d='M28,78 H72'/%3E%3C/g%3E%3Crect y='92' width='100' height='8' fill='%238e9aa5'/%3E%3C/svg%3E"); background-size: cover; }
.ph-dumbo { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23cfe0ec'/%3E%3Crect y='10' width='26' height='90' fill='%23984f28'/%3E%3Crect x='74' y='10' width='26' height='90' fill='%23904a24'/%3E%3Crect x='26' y='78' width='48' height='22' fill='%236e7b88'/%3E%3Cpath d='M38,30 h24 v48 h-24 Z' fill='%23577089'/%3E%3Cpath d='M43,40 h14 M43,56 h14' stroke='%23cfe0ec' stroke-width='6'/%3E%3Cg fill='%23c98d64'%3E%3Crect x='6' y='20' width='8' height='12'/%3E%3Crect x='6' y='44' width='8' height='12'/%3E%3Crect x='84' y='22' width='8' height='12'/%3E%3Crect x='84' y='46' width='8' height='12'/%3E%3C/g%3E%3C/svg%3E"); background-size: cover; }
.ph-bridge { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23e3ecf5'/%3E%3Crect y='62' width='100' height='38' fill='%23a5762f'/%3E%3Cpath d='M50,10 L10,62 M50,10 L26,62 M50,10 L42,62 M50,10 L58,62 M50,10 L74,62 M50,10 L90,62' stroke='%238b93a3' stroke-width='2'/%3E%3Cpath d='M44,6 h12 v56 h-12 Z' fill='%236b7f95'/%3E%3Cpath d='M47,16 h6 M47,34 h6' stroke='%23e3ecf5' stroke-width='7'/%3E%3C/svg%3E"); background-size: cover; }
.ph-liberty { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23bfe2ec'/%3E%3Crect y='72' width='100' height='28' fill='%238fbdd3'/%3E%3Cpath d='M42,70 L46,32 h8 L58,70 Z' fill='%233da293'/%3E%3Cpath d='M50,20 L45,32 h10 Z' fill='%23349a8e'/%3E%3Cpath d='M57,36 L66,18' stroke='%233da293' stroke-width='4'/%3E%3Ccircle cx='67' cy='16' r='3.5' fill='%23f2c14e'/%3E%3Crect x='38' y='70' width='24' height='10' fill='%23a8b3ac'/%3E%3C/svg%3E"); background-size: cover; }
.ph-bk { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23f4c98f'/%3E%3Crect y='58' width='100' height='42' fill='%236f9fc0'/%3E%3Cg fill='%23394358'%3E%3Crect x='10' y='30' width='9' height='28'/%3E%3Crect x='24' y='22' width='11' height='36'/%3E%3Crect x='40' y='34' width='8' height='24'/%3E%3Crect x='52' y='26' width='10' height='32'/%3E%3Crect x='68' y='36' width='9' height='22'/%3E%3Crect x='82' y='30' width='8' height='28'/%3E%3C/g%3E%3Crect y='94' width='100' height='6' fill='%23806043'/%3E%3C/svg%3E"); background-size: cover; }
/* three more, used by the how-it-works figures and the front-page vignettes */
.ph-fountain { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23dbeaf5'/%3E%3Crect y='64' width='100' height='36' fill='%23cdbf9d'/%3E%3Cellipse cx='50' cy='70' rx='34' ry='9' fill='%2385bad6'/%3E%3Crect x='46' y='36' width='8' height='30' fill='%23b3a17c'/%3E%3Cellipse cx='50' cy='38' rx='16' ry='4' fill='%23b3a17c'/%3E%3Cpath d='M50,10 Q42,26 38,34 M50,10 Q58,26 62,34 M50,8 V34' stroke='%23e6f4fb' stroke-width='3' fill='none' stroke-linecap='round'/%3E%3Ccircle cx='14' cy='30' r='12' fill='%234e8f4e'/%3E%3Ccircle cx='88' cy='28' r='11' fill='%23568f52'/%3E%3C/svg%3E"); background-size: cover; }
.ph-market { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23f3e3c6'/%3E%3Cpath d='M0,30 L100,30 L100,44 L0,44 Z' fill='%23e0524a'/%3E%3Cpath d='M0,44 L100,44 L100,50 L0,50 Z' fill='%23fff'/%3E%3Cpath d='M0,30 Q12,40 25,30 Q37,40 50,30 Q62,40 75,30 Q87,40 100,30' fill='%23f3e3c6'/%3E%3Crect x='10' y='58' width='80' height='30' fill='%23a37b52'/%3E%3Ccircle cx='24' cy='66' r='6' fill='%23f2a93b'/%3E%3Ccircle cx='38' cy='64' r='6' fill='%23e5453a'/%3E%3Ccircle cx='52' cy='66' r='6' fill='%2382b74b'/%3E%3Ccircle cx='66' cy='64' r='6' fill='%23f2a93b'/%3E%3Ccircle cx='80' cy='66' r='6' fill='%239b59b6'/%3E%3C/svg%3E"); background-size: cover; }
.ph-arch { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23d6e7f3'/%3E%3Crect y='74' width='100' height='26' fill='%23b7c6a3'/%3E%3Cpath d='M22,74 V34 a28,28 0 0 1 56,0 V74 H64 V38 a14,14 0 0 0 -28,0 V74 Z' fill='%23d9cdb6'/%3E%3Cpath d='M28,50 h8 M64,50 h8' stroke='%23b8a98c' stroke-width='3'/%3E%3Ccircle cx='10' cy='60' r='9' fill='%234e8f4e'/%3E%3Ccircle cx='91' cy='58' r='9' fill='%23568f52'/%3E%3C/svg%3E"); background-size: cover; }

.pin {
  position: absolute; border-radius: 50%;
  border: 3.5px solid #fff;
  box-shadow: 0 3px 12px rgba(0, 0, 0, .4);
  transform: translate(-50%, -50%);
  background-size: cover;
}

/* anchor: photo that already has GPS — green ring */
.pin.anchor { width: 52px; height: 52px; }
.pin.anchor::after {
  content: ''; position: absolute; inset: -7px; border-radius: 50%;
  border: 3.5px solid var(--certain);
}

/* target: the group being placed — ring in the confidence colour */
.pin.target {
  width: 76px; height: 76px; z-index: 5;
  border-color: var(--likely);
  box-shadow: 0 0 0 3px rgba(255, 176, 32, .35), 0 5px 14px rgba(0, 0, 0, .4);
}
.pin.target.confirmed {
  border-color: var(--certain);
  box-shadow: 0 0 0 3px rgba(47, 209, 90, .35), 0 5px 14px rgba(0, 0, 0, .4);
}

.pin .cnt {
  position: absolute; top: -6px; right: -6px;
  background: var(--pill); color: #fff;
  border-radius: 11px; min-width: 22px; height: 22px; padding: 0 4px;
  font-size: 11px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid #fff;
}

/* confirmed residue: small green marker that stays on the map */
.pin.placed { width: 36px; height: 36px; z-index: 3; }
.pin.placed::after {
  content: ''; position: absolute; inset: -6px; border-radius: 50%;
  border: 3px solid var(--certain);
}

/* the flying photo, before it becomes a pin */
.flier {
  position: absolute; z-index: 6;
  width: 84px; height: 84px; border-radius: 14px;
  border: 4px solid #fff;
  box-shadow: 0 10px 28px rgba(0, 0, 0, .45);
  background-size: cover;
  transform: translate(-50%, -50%);
  pointer-events: none;
}
.flier .tag {
  position: absolute; left: -8px; bottom: -9px;
  background: #c62c22; color: #fff;
  font-size: 9px; font-weight: 800; letter-spacing: .6px;
  padding: 3px 7px; border-radius: 8px;
  border: 2px solid #fff;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .35);
}

/* uncertain region — dashed violet, never a pin */
.region {
  position: absolute; z-index: 3;
  border-radius: 50%;
  background: rgba(191, 90, 240, .14);
  border: 3px dashed rgba(191, 90, 240, .85);
  transform: translate(-50%, -50%);
}

/* floating review card, straight from the app */
.review-card {
  position: absolute; z-index: 8;
  width: 262px;
  border-radius: 17px; overflow: hidden;
  box-shadow: 0 10px 32px rgba(0, 0, 0, .44);
  transform: translate(-50%, 12px);
  color: #fff;
}
.review-card .cover { position: absolute; inset: 0; }
.review-card .scrim {
  position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(8, 10, 14, .94) 0%, rgba(8, 10, 14, .7) 34%, rgba(8, 10, 14, .05) 68%);
}
.review-card .body { position: relative; padding: 52px 58px 13px 13px; }
.review-card .exif {
  display: flex; align-items: center; gap: 7px;
  font-size: 10px; font-weight: 600;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  opacity: .95; margin-bottom: 7px; white-space: nowrap;
}
.review-card .exif b {
  background: rgba(198, 44, 34, .92); color: #fff;
  font-weight: 800; letter-spacing: .4px;
  padding: 2px 7px; border-radius: 7px; font-size: 9px;
}
.review-card .tlb {
  display: flex; height: 18px; border-radius: 6px; overflow: hidden;
  margin-bottom: 8px; font-size: 0;
}
.review-card .tlb .s { background: rgba(47, 209, 90, .75); }
.review-card .tlb .gap {
  background: repeating-linear-gradient(45deg, rgba(255, 176, 32, .85) 0 5px, rgba(255, 176, 32, .42) 5px 10px);
}
.review-card .tlb .gap.violet {
  background: repeating-linear-gradient(45deg, rgba(191, 90, 240, .85) 0 5px, rgba(191, 90, 240, .42) 5px 10px);
}
.review-card .title { font-size: 16px; font-weight: 700; letter-spacing: -.2px; line-height: 1.2; }
.review-card .sub { font-size: 11.5px; opacity: .9; margin-top: 3px; }
.review-card .fab {
  position: absolute; right: 12px; bottom: 12px;
  width: 42px; height: 42px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--certain); color: #fff;
  box-shadow: 0 3px 10px rgba(0, 0, 0, .4);
}
.review-card .fab.ghost {
  background: rgba(255, 255, 255, .18);
  border: 1.5px solid rgba(255, 255, 255, .45);
}
.review-card .fab svg { width: 20px; height: 20px; }

/* app pill furniture */
.pill {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--pill); color: #fff;
  border-radius: 22px; padding: 11px 16px;
  font-size: 13px; font-weight: 600; white-space: nowrap;
  box-shadow: 0 3px 10px rgba(0, 0, 0, .28);
}
.pill .cd { width: 9px; height: 9px; border-radius: 50%; flex: none; }

.scan-pill { position: absolute; top: 74px; left: 26px; z-index: 9; }

/* hero copy panel — left third; the animation plays on the right of the map */
.hero-copy {
  position: relative; z-index: 10;
  margin: 84px 0 0 5vw;
  max-width: 560px;
  padding: 34px 36px 30px;
  text-align: left;
  /* Frosted glass over the map. The blur was always here; at .8 alpha it had
     nothing to show through, so the panel read as a plain card. Lower alpha
     plus a heavier blur lets the streets and the harbour show as soft colour
     while the text stays on a bright, even ground.
     The gradient is what stops it looking like flat tinted plastic: brighter
     at the top-left where light would catch, settling toward the bottom. */
  background: linear-gradient(157deg,
    rgba(255, 255, 255, .66) 0%,
    rgba(247, 247, 249, .52) 46%,
    rgba(238, 240, 245, .56) 100%);
  /* Less blur, much more saturation: the map stays legible through the glass
     and its colour comes through vividly, rather than being smeared to a
     neutral wash. */
  -webkit-backdrop-filter: blur(12px) saturate(3); backdrop-filter: blur(12px) saturate(3);
  border-radius: 26px;
  border: 1px solid rgba(255, 255, 255, .75);
  box-shadow:
    0 18px 50px rgba(15, 20, 30, .20),
    /* the lit top edge that reads as thickness */
    inset 0 1px 0 rgba(255, 255, 255, .9);
}

/* Without backdrop-filter there is no blur to hide behind, and the map would
   show through at full detail straight under the text. Go nearly opaque. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .hero-copy { background: rgba(247, 247, 249, .95); }
}
.hero-copy h1 {
  margin: 0 0 14px;
  font-size: clamp(26px, 2.6vw, 34px);
  font-weight: 800; letter-spacing: -1.2px; line-height: 1.16;
}
.hero-copy h1 em { font-style: normal; color: var(--manual); }
.hero-copy .lede {
  margin: 0; max-width: 58ch;
  font-size: clamp(15px, 1.6vw, 17px); color: #333a42;
}
.hero-ctas {
  display: flex; gap: 12px; flex-wrap: wrap;
  margin-top: 22px;
}
.hero-foot { margin: 16px 0 0; font-size: 13px; color: var(--sub); font-weight: 600; }

/* ------------------------------ bands ------------------------------ */

.band { padding: 88px 26px; max-width: 1280px; margin: 0 auto; }
.band h2 {
  margin: 0 0 10px;
  font-size: clamp(26px, 3.4vw, 38px);
  font-weight: 800; letter-spacing: -1px; line-height: 1.15;
}
.band-lede { margin: 0 0 34px; font-size: 17px; color: var(--sub); max-width: 68ch; }
.band-note { margin: 30px 0 0; font-size: 14.5px; color: var(--sub); font-style: italic; }

.band.alt {
  max-width: none;
  background: #edeef2;
}
.band.alt > * { max-width: 1280px; margin-left: auto; margin-right: auto; }
.band.alt h2 { margin-bottom: 26px; }

.band.dark {
  max-width: none;
  background: var(--ink); color: #e9eaec;
  position: relative; overflow: hidden;
}
.band.dark > * { max-width: 1280px; margin-left: auto; margin-right: auto; position: relative; z-index: 2; }
.band.dark h2 { margin-bottom: 26px; }
.band.dark p { color: #b9bec6; }
.band.dark em, .band.dark strong { color: #fff; }

.trio { display: grid; grid-template-columns: repeat(3, 1fr); gap: 30px; }
.trio h3 { margin: 0 0 8px; font-size: 18px; letter-spacing: -.3px; }
.trio p { margin: 0; font-size: 15px; color: var(--sub); }
.step-glyph { width: 46px; height: 46px; margin-bottom: 14px; }
.step-glyph svg { width: 100%; height: 100%; }

.split { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; }
.split h3 { margin: 0 0 8px; font-size: 18px; letter-spacing: -.3px; }
.split p { margin: 0; font-size: 15.5px; color: var(--sub); }
.band.dark .split p { color: #b9bec6; }
.big-p { font-size: 19px !important; line-height: 1.5; color: var(--ink) !important; font-weight: 550; }
.band.alt .big-p { color: var(--ink) !important; }

/* confidence grid */
.conf-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 22px; }
.conf {
  background: linear-gradient(180deg, color-mix(in srgb, var(--c) 16%, #fff) 0%, #fff 58%);
  border-radius: var(--card-radius);
  padding: 22px 20px 20px;
  border-top: 5px solid var(--c);
  box-shadow: 0 4px 18px rgba(0, 0, 0, .07);
}
.conf-dot {
  display: block; width: 14px; height: 14px; border-radius: 50%;
  background: var(--c); margin-bottom: 12px;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--c) 25%, transparent);
}

/* mini map-vignette in each confidence card, built from the hero's photo
   pins — the ring colour inherits the card's --c, so each scene speaks its
   own confidence colour */
.conf-art {
  position: relative; width: 200px; height: 80px;
  margin: 2px 0 14px;
}
.conf-art .art-line { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.conf-art .mp {
  position: absolute; width: 46px; height: 46px;
  border-radius: 50%; border: 3px solid #fff; background-size: cover;
  box-shadow: 0 0 0 3px var(--c), 0 3px 8px rgba(0, 0, 0, .28);
}
.conf-art .mp.anc {
  width: 30px; height: 30px;
  box-shadow: 0 0 0 2.5px var(--certain), 0 2px 6px rgba(0, 0, 0, .25);
}
.conf-art .mp.sq {
  width: 36px; height: 36px;
  border-radius: 9px; transform: rotate(-6deg);
  box-shadow: 0 3px 8px rgba(0, 0, 0, .28);
}
.conf-art .cnt {
  position: absolute; top: -7px; right: -9px;
  background: var(--pill); color: #fff;
  border-radius: 9px; min-width: 18px; height: 18px; padding: 0 4px;
  font-size: 10px; font-weight: 700; font-style: normal;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid #fff;
}
.conf-art .ok {
  position: absolute; right: -7px; bottom: -5px;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--certain); border: 2px solid #fff;
  display: flex; align-items: center; justify-content: center;
}
.conf-art .ok svg { width: 11px; height: 11px; }
.conf-art .rgn {
  position: absolute; border-radius: 50%;
  border: 2.5px dashed var(--c);
  background: color-mix(in srgb, var(--c) 12%, transparent);
}
.conf-art .ghost {
  position: absolute; border-radius: 50%;
  border: 2.5px dashed color-mix(in srgb, var(--c) 60%, transparent);
}
.conf h3 { margin: 0 0 7px; font-size: 17px; }
.conf p { margin: 0; font-size: 14px; color: var(--sub); }

.honesty-quote {
  margin: 44px auto 0; max-width: 62ch;
  padding: 4px 0 4px 22px;
  border-left: 4px solid var(--uncertain);
}
.honesty-quote p { margin: 0 0 8px; font-size: 18px; line-height: 1.5; font-weight: 550; }
.honesty-quote cite { font-size: 13.5px; color: var(--sub); font-style: normal; }

/* faq */
.faq { max-width: 760px; }
.faq details {
  border-bottom: 1px solid rgba(0, 0, 0, .1);
  padding: 4px 0;
}
.faq summary {
  cursor: pointer; list-style: none;
  padding: 14px 30px 14px 0;
  font-size: 16.5px; font-weight: 650; letter-spacing: -.2px;
  position: relative;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: '+'; position: absolute; right: 4px; top: 50%;
  transform: translateY(-50%);
  font-size: 22px; font-weight: 400; color: var(--sub);
  transition: transform .2s ease;
}
.faq details[open] summary::after { transform: translateY(-50%) rotate(45deg); }
.faq details p { margin: 0 0 16px; font-size: 15px; color: var(--sub); max-width: 68ch; }

/* closer */
.band.closer {
  /* Full-bleed, like .band.alt and .band.dark: the map should run to the
     viewport edges rather than stopping at the 1280px column, so the page ends
     on a place instead of on a card. The text is re-constrained below. */
  max-width: none;
  position: relative; overflow: hidden;
  text-align: center;
  /* Room above and below so the map is a place, not a band of texture. */
  padding-top: 96px; padding-bottom: 150px;
}
.band.closer .band-lede { margin-left: auto; margin-right: auto; }
/* Content above the backdrop, and back inside the column — same shape as
   `.band.alt > *`. The :not() is load-bearing: `.band.closer > *` (0,2,0)
   out-specifies `.cta-map` (0,1,0), so without it this rule forces the map back
   to position:relative, which collapses it to zero height and stacks every pin
   at the top of the band; the max-width would crop it to the column too. */
.band.closer > *:not(.cta-map) {
  position: relative; z-index: 2;
  max-width: 1280px; margin-left: auto; margin-right: auto;
}

/* ---------- CTA map ---------- */

.cta-map { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.cta-map-svg,
.cta-track { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

/* The heading and the badge run down the middle, so the map is washed out hard
   there and allowed to come through at the edges where the pins are. Without
   this the CTA would be competing with street lines for attention, and the CTA
   has to win. */
.cta-map::after {
  content: ''; position: absolute; inset: 0; z-index: 1;
  background:
    /* Opaque only directly behind the column of text, falling away quickly so
       the map is genuinely legible at the edges. */
    radial-gradient(46% 66% at 50% 44%, rgba(247, 247, 249, .96) 28%, rgba(247, 247, 249, .58) 62%, rgba(247, 247, 249, 0) 100%),
    /* Softened only at the TOP, where the band meets the page. The bottom stop
       used to fade back to the page colour, which left a pale gap between the
       map and the dark footer; the map now runs at full strength straight into
       it, so the two read as one block. */
    linear-gradient(180deg, rgba(247, 247, 249, .88) 0%, rgba(247, 247, 249, .06) 26%, rgba(247, 247, 249, .06) 100%);
}

/* Pins speak the hero's language — green ring = the photo already knows where
   it is, amber ring = the group being placed — on their own class rather than
   the hero's .pin, so the hero's much larger dimensions do not follow them
   here. (These began as the footer scene's; that scene is gone and this is the
   only place they are used, hence the neutral names.) */
.map-pin {
  position: absolute; z-index: 2;
  width: 40px; height: 40px; border-radius: 50%;
  border: 3px solid #fff;
  background-size: cover;
  /* Sized for a light backdrop: a heavier drop shadow is what you need to lift
     a pin off near-black, and reads as grime on the page background. */
  box-shadow: 0 2px 10px rgba(22, 24, 28, .22);
  transform: translate(-50%, -50%);
}
.map-pin.anchor::after {
  content: ''; position: absolute; inset: -6px; border-radius: 50%;
  border: 3px solid var(--certain);
}

/* The one being solved: amber, slightly larger, resolving to green on a loop. */
.map-pin.target {
  width: 52px; height: 52px; z-index: 3;
  border-color: var(--likely);
  box-shadow: 0 0 0 3px rgba(255, 176, 32, .35), 0 4px 14px rgba(22, 24, 28, .3);
  animation: map-solve 9s ease-in-out infinite;
}
.map-pin-count {
  position: absolute; top: -6px; right: -6px;
  background: var(--pill); color: #fff;
  border-radius: 10px; min-width: 20px; height: 20px; padding: 0 4px;
  font-size: 10.5px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid #fff;
}

/* The dashed track crawls toward the pin, then goes green with it. */
.map-track-line { animation: map-track 9s ease-in-out infinite; }

@keyframes map-solve {
  0%, 8%    { border-color: var(--likely); box-shadow: 0 0 0 3px rgba(255, 176, 32, .35), 0 4px 14px rgba(22, 24, 28, .3); }
  38%       { border-color: var(--likely); box-shadow: 0 0 0 7px rgba(255, 176, 32, .16), 0 4px 14px rgba(22, 24, 28, .3); }
  52%, 100% { border-color: var(--certain); box-shadow: 0 0 0 3px rgba(47, 209, 90, .38), 0 4px 14px rgba(22, 24, 28, .3); }
}
@keyframes map-track {
  0%        { stroke: #ffb020; stroke-dashoffset: 120; opacity: .25; }
  20%, 44%  { stroke: #ffb020; stroke-dashoffset: 0;   opacity: .95; }
  52%, 100% { stroke: #2fd15a; stroke-dashoffset: 0;   opacity: .8; }
}

/* Wide layout: a chain down the left of the centred column, one anchor
   balancing it on the right. */
.cta-pin-a { left: 9%;  top: 26%; }
.cta-pin-b { left: 17%; top: 56%; }
.cta-pin-c { left: 26%; top: 82%; }
.cta-pin-d { left: 83%; top: 30%; }
.cta-track-narrow { display: none; }

@media (max-width: 700px) {
  /* The heading wraps to nearly the full width here, so the flanking positions
     above would put pins on the words. The chain moves to the bottom strip,
     below the badge, and the balancing anchor goes — there is no room for it
     that is not either on the text or off the edge. */
  .cta-pin-a { left: 14%; top: 72%; }
  .cta-pin-b { left: 38%; top: 86%; }
  .cta-pin-c { left: 64%; top: 74%; }
  .cta-pin-d { display: none; }
  .cta-track-wide { display: none; }
  .cta-track-narrow { display: block; }
}

/* ---------------------------------------------------------------------------
   Cross-network app bar (.app-network) — "More photography apps for you"
   Rendered by template-parts/app-network.php from the a1-app-network mu-plugin,
   directly above the closing CTA (which stays the last element before the
   dark <footer>).

   Ported from filters-venn/style.css, which builds the block from its own
   --bg-soft/--surface/--border/--ink/--muted/--accent/--radius tokens. This
   theme does not define those, so the block is re-grounded in the tokens it
   DOES have (--ink/--sub/--manual/--card-radius) plus #fff for the card
   surface and #edeef2 — the same "alt band" tint the rest of this theme uses
   to set a section off from the plain page background (see .band.alt) — for
   the bar itself, since the CTA right below it shares the page's own --bg and
   would otherwise blend straight into an un-tinted bar with no seam.
--------------------------------------------------------------------------- */
.app-network {
  background: #edeef2;
  padding: 56px 0 60px;
}
.app-network .container {
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 26px;
}
.app-network-title {
  margin: 0 0 6px;
  font-size: 1.4rem;
  font-weight: 800;
  letter-spacing: -.02em;
  color: var(--ink);
}
.app-network-intro {
  margin: 0 0 26px;
  font-size: .95rem;
  color: var(--sub);
}
.app-network-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 18px;
  /* auto-fit keeps two cards side by side on desktop and stacks them on a
     phone without a media query; it also absorbs another app being added to
     the registry later without touching this file. */
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
.app-network-card {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  padding: 20px;
  background: #fff;
  border: 1px solid rgba(22, 24, 28, .08);
  border-radius: var(--card-radius);
  box-shadow: 0 4px 18px rgba(0, 0, 0, .07);
  text-decoration: none;
  transition: transform .18s ease, box-shadow .18s ease;
}
.app-network-card:hover,
.app-network-card:focus-visible {
  transform: translateY(-3px);
  box-shadow: 0 8px 22px rgba(0, 0, 0, .12);
  text-decoration: none;
}
.app-network-icon {
  width: 48px;
  height: 48px;
  border-radius: 12px;
  flex: 0 0 auto;
}
.app-network-body { min-width: 0; }
.app-network-name {
  display: block;
  margin-bottom: 5px;
  font-weight: 700;
  font-size: 1.02rem;
  color: var(--ink);
}
.app-network-pitch {
  display: block;
  margin-bottom: 10px;
  font-size: .9rem;
  line-height: 1.5;
  color: var(--sub);
}
.app-network-cta {
  display: block;
  font-size: .86rem;
  font-weight: 600;
  color: var(--manual);
}
@media (prefers-reduced-motion: reduce) {
  .app-network-card { transition: none; }
  .app-network-card:hover,
  .app-network-card:focus-visible { transform: none; }
}

/* --- Compact variant (.app-network--compact) -------------------------------
   Used on every page EXCEPT the front page. Same tokens, same behaviour, about
   a third the height: the heading stays, the intro and the per-app pitch are
   not rendered at all (see template-parts/app-network.php), and each app
   becomes an icon + name chip. It needs no extra i18n strings, so it works in
   every locale the full variant does. */
.app-network--compact {
  padding: 34px 0 36px;
}
.app-network--compact .app-network-title {
  margin-bottom: 14px;
  font-size: 1.1rem;
}
.app-network--compact .app-network-grid {
  /* Chips size to their content and wrap, rather than stretching to fill a
     grid column the way the full cards do. */
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
.app-network-chip {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 9px 16px 9px 9px;
  background: #fff;
  border: 1px solid rgba(22, 24, 28, .08);
  border-radius: 999px;
  text-decoration: none;
  transition: transform .18s ease, box-shadow .18s ease;
}
.app-network-chip:hover,
.app-network-chip:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .1);
  text-decoration: none;
}
.app-network-chip-icon {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  flex: 0 0 auto;
}
.app-network-chip-name {
  font-weight: 600;
  font-size: .95rem;
  color: var(--ink);
}
.app-network-chip-arrow {
  font-weight: 600;
  font-size: .95rem;
  color: var(--manual);
}
@media (prefers-reduced-motion: reduce) {
  .app-network-chip { transition: none; }
  .app-network-chip:hover,
  .app-network-chip:focus-visible { transform: none; }
}

/* footer */
footer {
  position: relative; overflow: hidden;
  /* No top margin: the closing CTA sits directly above on every page and ends
     in its own map, so a gap here would put a strip of page colour between the
     two — which is exactly the seam we removed the bottom fade to close. */
  margin: 0;
  padding: 44px 0 52px;
  background: #101216;
  font-size: 13.5px; color: #8b93a0;
}
/* Same column as .band / .nav-inner / .lang-banner-row (Task 19); footer
   itself stays full-bleed (background above). Replaces the old `footer > *`
   rule — the span and nav are now both inside this one wrapper instead of
   being direct children of <footer>. */
.footer-inner {
  position: relative; z-index: 2;
  display: flex; align-items: flex-start; justify-content: space-between; gap: 18px;
  flex-wrap: wrap;
  max-width: 1280px; margin: 0 auto; padding: 0 26px;
}
footer nav { display: flex; gap: 18px; flex-wrap: wrap; }
footer a { color: #aab3c0; text-decoration: none; font-weight: 600; }
footer a:hover { color: #fff; }

/* ------------------------------ content pages ------------------------------ */

.page-head { padding: 132px 26px 10px; max-width: 860px; margin: 0 auto; }
.page-head h1 {
  margin: 0 0 12px;
  font-size: clamp(30px, 4vw, 44px);
  font-weight: 800; letter-spacing: -1.2px; line-height: 1.1;
}
.page-head .lede { margin: 0; font-size: 18px; color: var(--sub); max-width: 68ch; }

.band.narrow { max-width: 860px; padding: 46px 26px; }
/*
 * Sub-page and blog-post h2 rhythm: each heading after the first gets real
 * breathing room from the section above it (owner: "all items are too close
 * to each other and we need space"). :first-of-type is scoped per .band.narrow
 * container, so it keeps the opening heading tight regardless of what precedes
 * it in a given template — nothing (how-it-works, cameras, privacy), a figure
 * (download), or nothing again in each of support's three separate sections —
 * while every heading after it gets the larger margin. Blog posts inherit this
 * for free: single.php's content section carries class="band narrow post-body".
 */
.band.narrow h2 { font-size: clamp(22px, 2.6vw, 30px); margin-top: 76px; }
.band.narrow h2:first-of-type { margin-top: 8px; }

.prose h2 { margin: 42px 0 10px; font-size: 24px; font-weight: 750; letter-spacing: -.6px; }
.prose h3 { margin: 28px 0 8px; font-size: 18px; font-weight: 700; letter-spacing: -.3px; }
.prose p, .prose li { font-size: 15.5px; color: #3a4048; }
.prose ul { padding-left: 22px; }
.prose strong { color: var(--ink); }
.prose table {
  border-collapse: collapse; width: 100%; margin: 18px 0; font-size: 14.5px;
}
.prose th, .prose td {
  text-align: left; padding: 9px 12px;
  border-bottom: 1px solid rgba(0, 0, 0, .1);
}
.prose th { font-size: 13px; text-transform: uppercase; letter-spacing: .4px; color: var(--sub); }
.prose code {
  background: rgba(0, 0, 0, .05); padding: 1px 6px; border-radius: 5px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 13.5px;
}
.callout {
  border-left: 4px solid var(--manual);
  background: rgba(10, 132, 255, .06);
  border-radius: 0 12px 12px 0;
  padding: 14px 18px; margin: 22px 0;
}
.callout.violet { border-color: var(--uncertain); background: rgba(191, 90, 240, .07); }
.callout.green { border-color: var(--certain); background: rgba(47, 209, 90, .08); }
.callout p { margin: 0; }

/* ------------------------------ phone demo ------------------------------ */
/* landscape iPhone playing the review flow: cards resolve, pins flip green */

.phone-demo { margin: 34px 0 10px; }

.phone-frame {
  position: relative;
  width: 100%; max-width: 720px;
  aspect-ratio: 2.1 / 1;
  margin: 0 auto;
  background: #14161a;
  border-radius: 45px;
  padding: 12px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, .35);
}
/* the bezel repaints ABOVE the screen contents, so nothing inside can ever
   appear to sit on top of the frame; its border overlaps the screen edge by
   1px so no sliver of map can peek through at the corners */
.phone-frame::before {
  content: ''; position: absolute; inset: 0;
  border-radius: 45px;
  border: 13px solid #14161a;
  z-index: 8; pointer-events: none;
}
/* dynamic island: a capsule just inside the screen, camera lens at its foot */
.phone-frame::after {
  content: ''; position: absolute; left: 26px; top: 50%;
  transform: translateY(-50%);
  width: 24px; height: 88px; border-radius: 13px;
  background:
    radial-gradient(circle at 50% 76%, rgba(70, 92, 122, .95) 0 4.5px, rgba(30, 42, 58, .6) 5.5px, transparent 6.5px),
    #000;
  z-index: 9;
  box-shadow: 0 0 0 2.5px rgba(0, 0, 0, .35);
}

.phone-screen {
  position: relative; width: 100%; height: 100%;
  border-radius: 32px; overflow: hidden;
  background: #f6f3ec;
}
.phone-screen .demo-map { position: absolute; inset: 0; width: 100%; height: 100%; }

.demo-status {
  position: absolute; top: 7px; left: 62px; right: 20px; z-index: 6;
  display: flex; justify-content: space-between;
  font-size: 11px; font-weight: 650; color: #16181c;
}

.demo-pill {
  position: absolute; top: 26px; left: 62px; z-index: 6;
  font-size: 11.5px; padding: 8px 13px; border-radius: 18px;
}

/* pins inside the phone */
.demo-pin {
  position: absolute; z-index: 4; border-radius: 50%;
  border: 3px solid #fff; background-size: cover;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .35);
  transform: translate(-50%, -50%);
  transition: opacity .4s ease, border-color .3s ease, box-shadow .3s ease;
}
.demo-pin.tgt {
  width: 52px; height: 52px;
  border-color: var(--likely);
  box-shadow: 0 0 0 2.5px rgba(255, 176, 32, .35), 0 3px 10px rgba(0, 0, 0, .35);
}
.demo-pin.tgt.done {
  border-color: var(--certain);
  box-shadow: 0 0 0 2.5px rgba(47, 209, 90, .35), 0 3px 10px rgba(0, 0, 0, .35);
}
.demo-pin.anc { width: 30px; height: 30px; }
.demo-pin.anc::after {
  content: ''; position: absolute; inset: -5px; border-radius: 50%;
  border: 2.5px solid var(--certain);
}
.demo-pin.left { width: 22px; height: 22px; z-index: 3; }
.demo-pin.left::after {
  content: ''; position: absolute; inset: -4px; border-radius: 50%;
  border: 2px solid var(--certain);
}
.demo-region {
  position: absolute; z-index: 3; border-radius: 50%;
  width: 92px; height: 92px;
  background: rgba(191, 90, 240, .14);
  border: 2.5px dashed rgba(191, 90, 240, .85);
  transform: translate(-50%, -50%);
  transition: opacity .4s ease;
}

/* the card rail along the bottom */
.demo-cards { position: absolute; left: 0; right: 0; bottom: 0; top: 0; z-index: 7; }

.demo-card {
  position: absolute; bottom: 12px;
  width: 208px; height: 148px;
  border-radius: 14px; overflow: hidden;
  box-shadow: 0 7px 20px rgba(0, 0, 0, .38);
  color: #fff;
  transition: transform .45s cubic-bezier(.3,.7,.3,1), opacity .45s ease;
}
.demo-card .cover { position: absolute; inset: 0; background-size: cover; }
.demo-card .scrim {
  position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(8, 10, 14, .94) 0%, rgba(8, 10, 14, .7) 38%, rgba(8, 10, 14, .05) 72%);
}
.demo-card .body { position: absolute; left: 0; right: 0; bottom: 0; padding: 0 44px 9px 10px; }
.demo-card .exif {
  display: flex; align-items: center; gap: 5px;
  font-size: 8px; font-weight: 600;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  margin-bottom: 5px; white-space: nowrap;
}
.demo-card .exif b {
  background: rgba(198, 44, 34, .92); color: #fff;
  font-weight: 800; padding: 1.5px 5px; border-radius: 5px; font-size: 7.5px;
}
.demo-card .tlb { display: flex; height: 12px; border-radius: 4px; overflow: hidden; margin-bottom: 5px; }
.demo-card .tlb .s { background: rgba(47, 209, 90, .75); }
.demo-card .tlb .gap {
  background: repeating-linear-gradient(45deg, rgba(255, 176, 32, .85) 0 4px, rgba(255, 176, 32, .42) 4px 8px);
}
.demo-card .tlb .gap.violet {
  background: repeating-linear-gradient(45deg, rgba(191, 90, 240, .85) 0 4px, rgba(191, 90, 240, .42) 4px 8px);
}
.demo-card .title { font-size: 12.5px; font-weight: 700; letter-spacing: -.2px; line-height: 1.15; }
.demo-card .sub { font-size: 9px; opacity: .9; margin-top: 2px; }
.demo-card .fab {
  position: absolute; right: 9px; bottom: 9px;
  width: 32px; height: 32px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--certain);
  box-shadow: 0 2px 8px rgba(0, 0, 0, .4);
  transition: transform .25s ease;
}
.demo-card .fab.ghost {
  background: rgba(255, 255, 255, .18);
  border: 1.5px solid rgba(255, 255, 255, .45);
}
.demo-card .fab svg { width: 15px; height: 15px; }

/* resolve states — exits clear the rail's right-shifted start position */
.demo-card.confirmed { transform: translateX(-170%) rotate(-4deg) !important; opacity: 0; }
.demo-card.skipped { transform: translateX(-60%) translateY(130%) rotate(-9deg) !important; opacity: 0; }

.demo-caption {
  text-align: center; font-size: 13.5px; color: var(--sub);
  margin: 16px auto 0; max-width: 60ch;
}

@media (max-width: 560px) {
  .demo-card { width: 172px; height: 128px; }
  .demo-pill { font-size: 10px; padding: 6px 10px; }
}

/* ------------------------------ responsive ------------------------------ */

@media (max-width: 900px) {
  .nav nav { display: none; }
  .trio, .conf-grid { grid-template-columns: 1fr 1fr; }
  .split { grid-template-columns: 1fr; gap: 24px; }
}

@media (max-width: 560px) {
  .trio, .conf-grid { grid-template-columns: 1fr; }
  .band { padding: 60px 20px; }
  .hero { align-items: flex-end; }
  .hero-copy { margin: 110px 14px 4vh; padding: 26px 20px 24px; text-align: center; }
  .hero-ctas { justify-content: center; }
  .scan-pill { left: 14px; top: 66px; font-size: 12px; }
  .review-card { width: 230px; }
}

/* reduced motion: hero.js checks this too and renders a static scene */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .cta-btn, .cta-ghost { transition: none; }
  /* Settle the CTA scene in its SOLVED state rather than freezing it
     mid-guess: the story still reads, nothing moves. */
  .map-pin.target { animation: none; border-color: var(--certain); box-shadow: 0 0 0 3px rgba(47, 209, 90, .38), 0 4px 14px rgba(22, 24, 28, .3); }
  .map-track-line { animation: none; stroke: #2fd15a; stroke-dashoffset: 0; opacity: .8; }
}
