/* Easy Sweep — easysweep.app
   Dark-only by design: this is a developer tool, and a single committed look
   reads better than a compromised pair.

   The palette is lifted from the app icon — a folded paper bird running teal
   at the beak through cyan and blue into a deep indigo at the tail, on a white
   field. Accents carry an `-rgb` channel token beside the hex so an alpha
   never has to restate the colour. */

:root {
  /* Ink. Neutral black read cold under a blue icon, so the greys carry a
     slight blue cast that the accents can sit on without arguing. */
  --bg:          #05070c;
  --bg-2:        #090c14;
  --surface:     #0e1220;
  --surface-2:   #141a2a;
  --border:      #1c2333;
  --border-lit:  #2a3346;

  --text:        #f2f4f8;
  --text-dim:    #a6afc0;
  --text-faint:  #6a7383;

  /* The bird, sampled facet by facet: its beak, its body, its lit wing, and
     the fold under the tail. */
  --teal:        #3ad4b7;
  --cyan:        #22c6de;
  --blue:        #3a86ee;
  --blue-lit:    #73a9f2;
  --blue-deep:   #083fc3;

  --teal-rgb:    58, 212, 183;
  --cyan-rgb:    34, 198, 222;
  --blue-rgb:    58, 134, 238;
  --lit-rgb:     115, 169, 242;
  --deep-rgb:    8, 63, 195;

  /* The call-to-action blue, sampled between the tail facet's own two stops
     (#286BEA and #083FC3). Flat, not a gradient — and dark enough to hold white
     type at 6:1, which the lit wing and the beak are nowhere near. */
  --cta:    #1855d6;
  --cta-hv: #1e63ea;

  --amber:       #f5a623;
  --red:         #ff453a;
  --green:       #32d74b;

  --amber-rgb:   245, 166, 35;
  --green-rgb:   50, 215, 75;

  --r-sm: 8px;
  --r:    14px;
  --r-lg: 22px;
  --r-xl: 30px;

  --shadow:    0 1px 2px rgba(0,0,0,.4), 0 8px 24px rgba(0,0,0,.35);
  --shadow-lg: 0 2px 6px rgba(0,0,0,.5), 0 30px 70px -20px rgba(0,0,0,.8);

  /* Theme-dependent surfaces. `--link` and `--eyebrow` exist because the raw
     accents are tuned for a dark ground: --blue-lit is 2.3:1 on white and
     --teal barely 1.9:1, so light needs darker inks for the same roles while
     the decorative gradient keeps the original hues. */
  --link:        var(--blue-lit);
  --eyebrow:     var(--teal);
  --nav-bg:      rgba(5,7,12,.72);
  --nav-bg-lit:  rgba(5,7,12,.88);
  --ghost-bg:    rgba(var(--blue-rgb), .14);
  --ghost-bg-hv: rgba(var(--blue-rgb), .22);
  --ghost-bd:    rgba(var(--lit-rgb), .32);
  --ghost-bd-hv: rgba(var(--lit-rgb), .55);
  --window-bd:   rgba(255,255,255,.10);
  --glow-blue:   rgba(var(--blue-rgb), .30);
  --glow-teal:   rgba(var(--teal-rgb), .16);
  --glow-deep:   rgba(var(--deep-rgb), .26);
  --glow-cta:    rgba(var(--blue-rgb), .24);

  --page:  1160px;
  --gutter: 24px;

  color-scheme: dark;

  --font: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text",
          "Helvetica Neue", Inter, system-ui, sans-serif;
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, monospace;
}

/* ---------- Light theme ----------

   Follows the system setting; there is no toggle. Only tokens are redefined —
   if a light fix needs a component rule, the component is reaching past a token
   and that is what should be fixed instead.

   The accents are NOT re-hued: the bird's blue and teal stay exactly as they
   are in the gradient and the icon. What changes is the ink used where an
   accent has to carry text, and how hard the decorative glows are pushed —
   on white they read at roughly half strength before they turn milky. */

@media (prefers-color-scheme: light) {
  :root {
    color-scheme: light;

    --bg:          #ffffff;
    --bg-2:        #f5f7fb;
    --surface:     #ffffff;
    --surface-2:   #eef1f7;
    --border:      #e3e7ef;
    --border-lit:  #ccd3e0;

    --text:        #0b1120;
    --text-dim:    #4b5565;
    --text-faint:  #6d7684;

    /* Accent inks, darkened for type on white. */
    --link:        #1558c4;
    --eyebrow:     #07786a;

    /* Neutral-cool rather than pure black, so a card edge does not look bruised. */
    --shadow:    0 1px 2px rgba(16,24,40,.06), 0 8px 24px rgba(16,24,40,.08);
    --shadow-lg: 0 2px 6px rgba(16,24,40,.08), 0 30px 60px -25px rgba(16,24,40,.28);

    --nav-bg:      rgba(255,255,255,.72);
    --nav-bg-lit:  rgba(255,255,255,.90);
    --ghost-bg:    rgba(var(--blue-rgb), .09);
    --ghost-bg-hv: rgba(var(--blue-rgb), .15);
    --ghost-bd:    rgba(var(--blue-rgb), .30);
    --ghost-bd-hv: rgba(var(--blue-rgb), .48);
    --window-bd:   rgba(11,17,32,.12);

    --glow-blue:   rgba(var(--blue-rgb), .16);
    --glow-teal:   rgba(var(--teal-rgb), .15);
    --glow-deep:   rgba(var(--deep-rgb), .10);
    --glow-cta:    rgba(var(--blue-rgb), .12);
  }
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.6;
  letter-spacing: -0.011em;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, svg, video { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

/* ---------- Layout ---------- */

.wrap {
  max-width: var(--page);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.narrow { max-width: 780px; margin-inline: auto; }

section { position: relative; }

.band { padding: 76px 0; }
.band--tight { padding: 60px 0; }

.band--sunken {
  background: var(--bg-2);
  border-block: 1px solid var(--border);
}

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

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 660;
  letter-spacing: -0.028em;
  line-height: 1.08;
}

h1 { font-size: clamp(2.6rem, 6.2vw, 4.5rem); }
h2 { font-size: clamp(1.8rem, 3.4vw, 2.5rem); letter-spacing: -0.03em; }
h3 { font-size: 1.2rem; letter-spacing: -0.02em; line-height: 1.3; }

p { margin: 0; }

.lede {
  font-size: clamp(1.1rem, 2.1vw, 1.32rem);
  line-height: 1.55;
  color: var(--text-dim);
  letter-spacing: -0.015em;
}

.eyebrow {
  display: inline-block;
  font-size: .8rem;
  font-weight: 620;
  letter-spacing: .09em;
  text-transform: uppercase;
  /* Teal, not blue: it is the one note in the icon that nothing else on the
     page uses, so it marks a section start without competing with the CTA. */
  color: var(--eyebrow);
  margin-bottom: 18px;
}

.sect-head { max-width: 720px; margin-bottom: 40px; }
.sect-head--center { max-width: 780px; margin-inline: auto; text-align: center; }
.sect-head .lede { margin-top: 16px; font-size: 1.08rem; }

.dim { color: var(--text-dim); }
.faint { color: var(--text-faint); }
code, .mono { font-family: var(--mono); font-size: .88em; }

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 14px 26px;
  border: 1px solid transparent;
  border-radius: 980px;
  font-family: inherit;
  font-size: 1rem;
  font-weight: 590;
  letter-spacing: -0.012em;
  cursor: pointer;
  white-space: nowrap;
  transition: transform .18s ease, box-shadow .18s ease, background .18s ease,
              border-color .18s ease, opacity .18s ease;
}

.btn:active { transform: translateY(1px) scale(.99); }
.btn svg { flex: none; }

.btn--primary {
  background: var(--cta);
  color: #fff;
}
.btn--primary:hover {
  background: var(--cta-hv);
  transform: translateY(-2px);
}

.btn--ghost {
  background: var(--ghost-bg);
  border-color: var(--ghost-bd);
  color: var(--link);
}
.btn--ghost:hover {
  background: var(--ghost-bg-hv);
  border-color: var(--ghost-bd-hv);
  transform: translateY(-2px);
}

.btn--sm { padding: 9px 18px; font-size: .92rem; }
.btn--wide { width: 100%; }

/* Apple's App Store badge shape, rebuilt: the glyph beside a small line over a
   larger one. Kept on the dark neutral rather than the brand gradient so it
   reads as a second, quieter route next to the download. */
.btn--appstore {
  gap: 11px;
  padding: 9px 24px 9px 20px;
  background: #000;
  color: #fff;
}
.btn--appstore:hover {
  background: #1a1a1a;
  transform: translateY(-2px);
}
.btn__stack {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.05;
  text-align: left;
}
.btn__over {
  font-size: .62rem;
  font-weight: 520;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: rgba(255,255,255,.72);
}
.btn__main {
  font-size: 1.06rem;
  font-weight: 560;
  letter-spacing: -0.02em;
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: center;
}

/* ---------- Nav ---------- */

.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--nav-bg);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid transparent;
  transition: border-color .25s ease, background .25s ease;
}
.nav.is-stuck {
  border-bottom-color: var(--border);
  background: var(--nav-bg-lit);
}

.nav__inner {
  max-width: var(--page);
  margin: 0 auto;
  padding: 0 var(--gutter);
  height: 62px;
  display: flex;
  align-items: center;
  gap: 32px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 11px;
  font-weight: 640;
  font-size: 1.03rem;
  letter-spacing: -0.02em;
  margin-right: auto;
}
/* The bare bird, not the app icon: the icon's white field read as a bright chip
   punched into a dark bar. Width-driven, since the mark is wider than it is tall. */
.brand img { width: 32px; height: auto; }

.nav__links {
  display: flex;
  gap: 30px;
  font-size: .95rem;
  color: var(--text-dim);
  font-weight: 520;
}
.nav__links a { transition: color .16s ease; }
.nav__links a:hover { color: var(--text); }

/* ---------- Hero ---------- */

.hero {
  position: relative;
  padding: 60px 0 0;
  text-align: center;
  overflow: hidden;
}

/* The icon's own run of colour, thrown behind the mark: teal at the top right
   where the beak points, deep indigo at the left where the tail folds under. */
.hero__glow {
  position: absolute;
  /* A percentage `top` here resolves against the hero's own (very tall) height,
     which put the gradient's centre hundreds of pixels above the viewport and
     made the whole glow invisible. Pin it in px instead. */
  inset: -280px -15% auto -15%;
  height: 1000px;
  pointer-events: none;
  background:
    radial-gradient(44% 40% at 50% 40%, var(--glow-blue), transparent 68%),
    radial-gradient(28% 30% at 74% 26%, var(--glow-teal), transparent 70%),
    radial-gradient(30% 32% at 22% 32%, var(--glow-deep), transparent 72%);
  filter: blur(6px);
}

.hero__inner { position: relative; }

.hero__icon {
  width: 128px;
  height: auto;
  margin: 0 auto 24px;
  filter: drop-shadow(0 22px 44px rgba(var(--blue-rgb), .42));
}

/* Sized so the download button clears the fold on a 13" laptop with the copy
   above it — the screenshot then breaks the bottom edge rather than leading. */
.hero h1 {
  max-width: 19ch;
  margin-inline: auto;
  font-size: clamp(2.2rem, 5vw, 3.5rem);
}
.hero .lede { max-width: 58ch; margin: 20px auto 0; font-size: 1.1rem; }
.hero .cta-row { justify-content: center; margin-top: 30px; }

.hero__meta {
  margin-top: 18px;
  font-size: .88rem;
  color: var(--text-faint);
}

/* System requirements. Deliberately not chips: a rounded outlined pill sat a
   few pixels under two rounded pill buttons and read as a third and fourth
   button. Borderless, so the glyph carries the fact and nothing invites a
   click. */
.specs {
  list-style: none;
  padding: 0;
  margin: 22px 0 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px 26px;
}
.spec {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--text-faint);
  font-size: .88rem;
  white-space: nowrap;
}
/* Sized against the label's x-height, not its line box: any larger and the
   glyph read as an icon with a caption rather than a mark beside a word. The
   colour is inherited — everything below the buttons is one tone, so the specs
   and the trust line under them read as a single block of small print. */
.spec svg {
  width: 13px;
  height: 13px;
  flex: none;
}

/* The trust line stays plain text below — its three claims are prose, not specs. */
.specs + .hero__meta { margin-top: 16px; }

/* Held well under the content width: at full width the shot is 640px tall and
   pushes everything above it off the first screen. */
.hero__shot {
  margin-top: 46px;
  position: relative;
}
.hero__shot .window { max-width: 860px; margin-inline: auto; }
.hero__shot::after {
  content: "";
  position: absolute;
  inset: auto 0 -1px 0;
  height: 150px;
  background: linear-gradient(to bottom, transparent, var(--bg) 92%);
  pointer-events: none;
}

/* ---------- macOS window frame ---------- */

.window {
  border: 1px solid var(--window-bd);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--shadow-lg);
}
.window img { width: 100%; height: auto; display: block; }

/* ---------- Section tiles ---------- */

.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 16px;
}

.tile {
  position: relative;
  padding: 26px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: linear-gradient(180deg, var(--surface), var(--bg-2));
  transition: transform .22s ease, border-color .22s ease;
}
.tile:hover { transform: translateY(-3px); border-color: var(--border-lit); }

/* Folded planes, not pictograms: each mark is two facets of the same sheet, so
   the set reads as cut from the logo rather than picked from an icon library.
   The tiles step through the bird's own run of colour, beak to tail. */
.tile__mark { margin-bottom: 15px; color: var(--mark, var(--blue)); }
.tile__mark svg { width: 36px; height: 36px; }

.tiles .tile:nth-child(1) { --mark: var(--teal); }
.tiles .tile:nth-child(2) { --mark: var(--cyan); }
.tiles .tile:nth-child(3) { --mark: var(--blue-lit); }
.tiles .tile:nth-child(4) { --mark: var(--blue); }
.tiles .tile:nth-child(5) { --mark: #2b6fe0; }
.tiles .tile:nth-child(6) { --mark: var(--blue-deep); }

.tile h3 { margin-bottom: 9px; }
.tile p { color: var(--text-dim); font-size: .95rem; }

/* ---------- Section screenshot ---------- */

/* One shot per section, at the width of the copy above it. Three side by side
   scaled a 2820px-wide window down to a third of the column, which left the
   table rows — the whole point of the picture — as unreadable grey stripes. */
.shot {
  margin: 52px auto 0;
  max-width: 900px;
}
.shot figcaption {
  margin-top: 16px;
  text-align: center;
  font-size: .95rem;
  color: var(--text-faint);
  max-width: 62ch;
  margin-inline: auto;
}

/* ---------- Safety ---------- */

.guards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 16px;
}
.guard {
  padding: 24px 26px;
  border: 1px solid var(--border);
  border-left: 2px solid var(--blue);
  border-radius: 4px var(--r) var(--r) 4px;
  background: var(--bg-2);
}
.guard h3 { font-size: 1.04rem; margin-bottom: 9px; }
.guard p { color: var(--text-dim); font-size: .94rem; }

.note {
  max-width: 720px;
  margin: 28px auto 0;
  text-align: center;
  color: var(--text-faint);
  font-size: .94rem;
}

/* The global reset strips link colour and underline, which is right for nav and
   cards but leaves a link in body copy indistinguishable from the text. */
.guard p a, .tile p a, .note a, .hero__meta a {
  color: var(--link);
  text-decoration: underline;
  text-decoration-color: rgba(var(--lit-rgb), .4);
  text-underline-offset: 2px;
  transition: text-decoration-color .16s ease;
}
.guard p a:hover, .tile p a:hover, .note a:hover,
.hero__meta a:hover { text-decoration-color: var(--link); }

/* ---------- Pricing ---------- */

.prices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 20px;
  max-width: 820px;
  margin-inline: auto;
}
.price {
  display: flex;
  flex-direction: column;
  padding: 34px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: linear-gradient(180deg, var(--surface), var(--bg-2));
}
.price--pro {
  border-color: rgba(var(--lit-rgb), .45);
}
.price h3 { font-size: 1.25rem; }
.price__amt {
  margin: 16px 0 4px;
  font-size: 3rem;
  font-weight: 680;
  letter-spacing: -0.045em;
  line-height: 1;
}
.price__per { font-size: .92rem; color: var(--text-faint); }

/* "from" rides the headline number rather than sitting on its own line: at 3rem
   the price is the loudest thing in the card, and a qualifier under it reads as
   a second fact instead of a modifier on the first. */
.price__from {
  font-size: .95rem;
  font-weight: 520;
  letter-spacing: -0.01em;
  color: var(--text-faint);
  margin-right: 8px;
  vertical-align: 0.9rem;
}

/* The seat ladder. Ruled rows rather than a bordered table — the card already
   has an edge, and a second one inside it boxes the price in.
   Every selector here is scoped with `.price` to outrank the `.price ul` feature
   list below, which would otherwise win on specificity and impose its 11px gap,
   its 26px indent, and — visibly — its ✓ bullet on each row. */
.price .seats {
  list-style: none;
  margin: 20px 0 0;
  padding: 0;
  display: grid;
  /* `flex: none` because `.price ul` below sets `flex: 1` so the feature list
     eats the card's leftover height and pins the button to the foot — and this
     is also a `ul` inside `.price`, so without this it shares that stretch. The
     rows don't stretch with it (`align-content` stays `start`), so the extra
     height would show as a slab of the `--border` ground below the last row
     the moment the free card became the taller of the pair. */
  flex: none;
  gap: 1px;
  background: var(--border);
  border-radius: var(--r-sm);
  overflow: hidden;
}
/* A grid rather than a flex row: only two of the three rows carry a saving, and
   under flex the single-Mac price would sit hard against the edge while the other
   two stopped short of it.

   The third column is a fixed width, not `minmax`, and that is the point. Each
   row is its own grid — CSS grid columns are not shared between siblings — so a
   saving label wider than its column would widen that row's third track and push
   its price left of the other two. Fixed plus `nowrap` means a label that
   outgrows the space overflows into the row's padding instead, which keeps the
   prices on one vertical line. Sized with headroom over "save 33%" so that only
   happens at a font size far above any default. */
.price .seats li {
  display: grid;
  grid-template-columns: 1fr auto 66px;
  align-items: baseline;
  gap: 10px;
  padding: 10px 13px;
  background: var(--surface);
  font-size: .94rem;
  color: var(--text-dim);
}
.price .seats li::before { content: none; }
.seats__p { color: var(--text); font-weight: 620; }
/* The saving explains the price rather than competing with it: small, accent
   ink, right-aligned under itself. */
.seats__save {
  text-align: right;
  font-size: .8rem;
  color: var(--eyebrow);
  white-space: nowrap;
}

.price ul {
  list-style: none;
  margin: 24px 0 28px;
  padding: 0;
  display: grid;
  gap: 11px;
  align-content: start;
  flex: 1;
}
.price ul li {
  position: relative;
  padding-left: 26px;
  font-size: .96rem;
  color: var(--text-dim);
}
.price ul li::before {
  content: "✓";
  position: absolute;
  left: 0;
  color: var(--link);
  font-family: var(--mono);
}
.price ul li strong { color: var(--text); font-weight: 600; }

/* The line under the buy button. Its job is to answer "so do I download it or
   buy it?" at the moment the question occurs, which is with the button under the
   cursor — not in a note at the foot of the section. */
.price__after {
  margin-top: 13px;
  font-size: .86rem;
  line-height: 1.5;
  text-align: center;
  color: var(--text-faint);
}
.price__after strong { color: var(--text-dim); font-weight: 600; }

/* ---------- Closing CTA ---------- */

.close-cta {
  position: relative;
  text-align: center;
  padding: 84px 0;
  overflow: hidden;
  border-top: 1px solid var(--border);
}
.close-cta::before {
  content: "";
  position: absolute;
  inset: -60% -10% auto -10%;
  height: 700px;
  background: radial-gradient(46% 46% at 50% 50%, var(--glow-cta), transparent 70%);
  pointer-events: none;
}
.close-cta__in { position: relative; }
/* The page closes on the mark it opened with, smaller. */
.close-cta__icon {
  width: 80px;
  height: auto;
  margin: 0 auto 20px;
  filter: drop-shadow(0 14px 30px rgba(var(--blue-rgb), .38));
}
.close-cta .lede { margin-top: 20px; }
.close-cta .cta-row { justify-content: center; margin-top: 32px; }

/* The 404 page leads with this section, so it needs no rule above it. */
.close-cta--bare { border-top: 0; }

/* ---------- Footer ---------- */

.footer {
  border-top: 1px solid var(--border);
  background: var(--bg-2);
  padding: 56px 0 36px;
  font-size: .93rem;
}
.footer__cols {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr;
  gap: 40px;
}
.footer__brand p { color: var(--text-faint); margin-top: 14px; max-width: 30ch; }
.footer h4 {
  font-size: .78rem;
  font-weight: 640;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 16px;
}
.footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 11px; }
.footer ul a { color: var(--text-dim); transition: color .16s ease; }
.footer ul a:hover { color: var(--text); }
.footer__base {
  margin-top: 46px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: space-between;
  color: var(--text-faint);
  font-size: .86rem;
}

/* ---------- Legal / doc pages ---------- */

.doc { padding: 72px 0 100px; }
.doc h1 { font-size: clamp(2.1rem, 4.6vw, 3rem); }
.doc__meta { margin-top: 14px; color: var(--text-faint); font-size: .92rem; }
.doc h2 { font-size: 1.5rem; margin-top: 52px; }
.doc h3 { font-size: 1.1rem; margin-top: 32px; }
.doc p, .doc li { color: var(--text-dim); }
.doc p { margin-top: 16px; }
.doc ul, .doc ol { margin-top: 16px; padding-left: 24px; display: grid; gap: 10px; }
.doc a { color: var(--link); }
.doc a:hover { text-decoration: underline; }
.doc strong { color: var(--text); font-weight: 600; }
.doc hr { margin: 52px 0; border: 0; border-top: 1px solid var(--border); }
.doc table { width: 100%; border-collapse: collapse; margin-top: 20px; font-size: .95rem; }
.doc table th, .doc table td {
  padding: 12px 16px; text-align: left;
  border: 1px solid var(--border); color: var(--text-dim);
}
.doc table th { background: var(--surface); color: var(--text); font-weight: 600; }

/* ---------- Reveal on scroll ---------- */

/* Hidden only where a script can actually reveal it again. A CSP that forbids
   inline script means we cannot set a `.js` class before first paint, so the
   `scripting` query does that job — with JS off or blocked, the page is simply
   visible rather than three-quarters blank. */
.reveal {
  transition: opacity .7s cubic-bezier(.16,1,.3,1), transform .7s cubic-bezier(.16,1,.3,1);
}

@media (scripting: enabled) {
  .reveal { opacity: 0; transform: translateY(20px); }
}

.reveal.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

/* ---------- Responsive ---------- */

@media (max-width: 940px) {
  .shot { margin-top: 44px; }
  .footer__cols { grid-template-columns: 1fr 1fr; gap: 34px; }
  .band { padding: 64px 0; }
}

@media (max-width: 720px) {
  body { font-size: 16px; }
  .nav__links { display: none; }
  .hero { padding-top: 40px; }
  .hero__icon { width: 104px; }
  .hero__shot { margin-top: 38px; }
  .hero .cta-row { flex-direction: column; }
  .hero .cta-row .btn { width: 100%; }
  .shot { margin-top: 36px; }
  .shot .window { border-radius: var(--r); }
  .band { padding: 56px 0; }
  .close-cta { padding: 72px 0; }
  .close-cta .cta-row { flex-direction: column; }
  .close-cta .cta-row .btn { width: 100%; }
  .footer__cols { grid-template-columns: 1fr; }
}

::selection { background: rgba(var(--blue-rgb), .34); }

:focus-visible {
  outline: 2px solid var(--link);
  outline-offset: 3px;
  border-radius: 4px;
}
