/* ==========================================================================
   MadHaul marketing site — shared stylesheet

   Tokens copied verbatim from DESIGN_TOKENS.md (extracted from the app's own
   css/style.css on 2026-08-15). Do not drift from these values: the site is
   meant to look like the product.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS  (DESIGN_TOKENS.md section 1)
   -------------------------------------------------------------------------- */

:root {
  /* Backgrounds / surfaces */
  --bg: #0e0d0d;
  --surface: #141414;
  --surface2: #1c1c1c;
  --surface3: #242424;
  --bundle-bg: #160122;

  /* Borders */
  --border: #2a2a2a;
  --border2: #333;

  /* Accent */
  --accent: #00c4a0;
  --accent-dim: #00a085;
  --accent-glow: rgba(0, 196, 160, 0.15);

  /* The logo orange — DESIGN_TOKENS.md calls it --brand-haul; same colour, and
     NOT --amber, which is the Needs Relisting status colour. Used by the
     wordmark and by the credit pack names, and nowhere else. */
  --brand: #D9720B;

  /* Text */
  --text: #ffffff;
  --text-muted: #c0c0c0;
  --text-soft: #a8a8a8;
  --label-warm: #f5e7c4;

  /* Status colours */
  --blue: #5b9cf6;    /* Listed / Relisted */
  --amber: #f5a623;   /* Needs Relisting */
  --purple: #a78bfa;  /* Needs Posting */
  --green: #4cd964;   /* Sold */
  --red: #ce4b4b;     /* Destructive / negative / error */
  --lime: #c8f135;

  /* Platform colours */
  --c-vinted: var(--accent);
  --c-ebay: #e53238;
  --c-fb: #1877F2;
  --c-depop: #971400;
  --c-gumtree: #72BF44;
  --c-shpock: #00A3DE;

  /* Category tints for features.html's five pills. Site-only, like --brand —
     not DESIGN_TOKENS values. Desaturated on purpose and kept clear of the
     status colours above, so a category tint never reads as an item's status.
     Each pairs with a glow for its active pill, the way --accent does. */
  --cat-add: #bf7e63;
  --cat-add-glow: rgba(191, 126, 99, 0.15);
  --cat-price: #7c9e82;
  --cat-price-glow: rgba(124, 158, 130, 0.15);
  --cat-sell: #6c8cae;
  --cat-sell-glow: rgba(108, 140, 174, 0.15);
  --cat-manage: #9482a8;
  --cat-manage-glow: rgba(148, 130, 168, 0.15);
  --cat-track: #b69a5c;
  --cat-track-glow: rgba(182, 154, 92, 0.15);

  /* Radius */
  --r: 12px;
  --radius: var(--r);

  /* Fonts */
  --head: 'Sora', sans-serif;
  --body: 'DM Sans', sans-serif;
  --font-head: var(--head);
  --font-body: var(--body);

  /* Site-only layout scale (not app tokens) */
  --wrap: 1080px;
  --wrap-narrow: 680px;
  --section-y: 72px;
  /* The header's 60px row plus its bottom border. Anything that sticks below
     the header offsets by this, so the two cannot drift apart. */
  --header-h: 61px;
  /* A pinned single-row .tile-bar: its 20px of padding plus the tallest pill
     either row holds. Set to the taller of the two rows, so a scroll target
     offsetting by it clears both rather than landing under one. */
  --tile-bar-h: 70px;
}

/* --------------------------------------------------------------------------
   2. RESET / BASE
   -------------------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 76px;
}

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.6;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  /* Swapping a panel changes the height of everything below it, and the swap is
     followed by a scroll to the top of whatever opened. Left on, scroll
     anchoring corrects for that height change and fights the scroll it was
     just given. */
  overflow-anchor: none;
}

img { max-width: 100%; height: auto; display: block; }

h1, h2, h3, h4 {
  font-family: var(--font-head);
  font-weight: 700;
  line-height: 1.18;
  margin: 0 0 16px;
  letter-spacing: -0.02em;
}

h1 { font-size: clamp(2rem, 7vw, 3.25rem); font-weight: 800; }
h2 { font-size: clamp(1.5rem, 4.6vw, 2.1rem); }
h3 { font-size: 1.125rem; font-weight: 600; }
h4 { font-size: 1rem; font-weight: 600; }

p { margin: 0 0 16px; color: var(--text-muted); }
p:last-child { margin-bottom: 0; }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

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

ul, ol { margin: 0 0 16px; padding-left: 22px; color: var(--text-muted); }
li { margin-bottom: 8px; }
li:last-child { margin-bottom: 0; }

hr { border: 0; border-top: 1px solid var(--border); margin: 40px 0; }

/* Visible focus on everything interactive. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--accent);
  color: var(--bg);
  padding: 10px 16px;
  font-family: var(--font-body);
  font-weight: 600;
  border-radius: 0 0 var(--r) 0;
}
.skip-link:focus { left: 0; text-decoration: none; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   3. LAYOUT
   -------------------------------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 20px;
}

/* Centres itself when used without .wrap, as inside a feature panel. */
.wrap-narrow { max-width: var(--wrap-narrow); margin-inline: auto; }

section { padding: var(--section-y) 0; }

.section-alt { background: var(--surface); border-block: 1px solid var(--border); }

.eyebrow {
  font-family: var(--font-head);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 12px;
}

.lede { font-size: 1.0625rem; color: var(--text-muted); max-width: 40em; }

.fine { font-size: 0.875rem; color: var(--text-soft); line-height: 1.55; }

/* --------------------------------------------------------------------------
   4. BUTTONS  (DESIGN_TOKENS.md section 3 for .btn-primary; .btn-secondary's
   border is a site-only teal-tinted outline, not verbatim — see CLAUDE.md's
   token rules. .btn-secondary is anchor-only on this site, never the app's
   own cancel button, so it can read as a link-button instead of matching the
   app's flat one.)
   -------------------------------------------------------------------------- */

.btn-primary {
  background: var(--accent);
  color: var(--bg);
  border: none;
  border-radius: var(--radius);
  padding: 10px 20px;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
  transition: background 0.2s;
}
.btn-primary:hover { background: var(--accent-dim); }
.btn-primary:disabled { opacity: 0.3; cursor: not-allowed; filter: grayscale(1); }

.btn-secondary {
  background: none;
  color: var(--text);
  border: 1px solid color-mix(in srgb, var(--accent) 50%, var(--border));
  border-radius: var(--radius);
  padding: 10px 20px;
  font-family: var(--font-body);
  font-size: 14px;
  cursor: pointer;
}
.btn-secondary:hover { border-color: var(--accent); background: var(--accent-glow); }

/* Anchors dressed as buttons need a little more room than the app's own. */
a.btn-primary, a.btn-secondary {
  display: inline-block;
  text-decoration: none;
  line-height: 1.4;
  padding: 13px 24px;
  font-size: 15px;
}
a.btn-primary:hover { text-decoration: none; }
a.btn-secondary:hover { text-decoration: none; border-color: var(--accent); background: var(--accent-glow); color: var(--text); }

.btn-row { display: flex; flex-wrap: wrap; gap: 12px; margin: 24px 0 0; }

/* Accent chip row — DESIGN_TOKENS.md section 3, .actions-btn */
.actions-btn {
  width: 100%;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 12px;
  padding: 13px 16px;
  border-radius: var(--r);
  border: 1px solid var(--border);
  background: var(--surface2);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 500;
  text-align: left;
}
.actions-btn.accent {
  background: var(--accent-glow);
  border-color: var(--accent);
  color: var(--accent);
}
.actions-btn-icon {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.04);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.actions-btn.accent .actions-btn-icon { background: rgba(0, 196, 160, 0.15); }

/* --------------------------------------------------------------------------
   5. HEADER
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(14, 13, 13, 0.94);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}

.site-header .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;  /* two pills and the toggle share the phone header; ≥880px gets 16px back */
  min-height: 60px;
}

/* Logo mark plus "Mad" white / "Haul" brand orange, matching the app header. */
.wordmark {
  display: inline-flex;
  align-items: center;
  /* No gap: "Mad" and <span>Haul</span> are separate flex items, so a gap
     would split the word. The mark carries its own margin instead. */
  font-family: var(--font-head);
  font-weight: 800;
  font-size: 1.25rem;
  letter-spacing: -0.03em;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
}
.wordmark:hover { text-decoration: none; }
.wordmark span { color: var(--brand); }
.wordmark img { width: 30px; height: 30px; flex-shrink: 0; margin-right: 9px; }

/* The pill pair sitting left of the toggle below 880px, where the nav's own
   links are hidden and the dropdown would otherwise be the only route out.
   Scoped to the header to outrank a.btn-primary/a.btn-secondary, which set
   their own padding and display. */
.site-header .header-cta {
  margin-left: auto;
  padding: 8px 14px;
  font-size: 13px;
  white-space: nowrap;
}
/* The pair travels together: only the first claims the free space. */
.site-header .header-cta + .header-cta { margin-left: 0; }

.nav-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--r);
  color: var(--text);
  cursor: pointer;
}

.site-nav {
  display: none;
  position: absolute;
  left: auto;
  right: 0;
  top: 100%;
  width: 38%;
  min-width: 180px;
  background: var(--surface2);
  border-bottom: 1px solid var(--border);
  border-left: 1px solid var(--border);
  padding: 8px 20px 16px;
}
.site-nav.open { display: block; }

.site-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.site-nav li { margin: 0; }

.site-nav a {
  display: block;
  padding: 11px 4px;
  color: var(--text);
  font-size: 15px;
  font-weight: 600;
  text-align: left;
  border-bottom: 1px solid var(--border);
}
.site-nav a:hover { color: var(--text); text-decoration: none; }
.site-nav a[aria-current="page"] { color: var(--accent); }

.site-nav .nav-cta { display: none; }

@media (min-width: 880px) {
  .nav-toggle { display: none; }
  .site-header .wrap { gap: 16px; }
  .site-header .header-cta { display: none; }  /* the nav row carries both links here */
  .site-nav {
    display: block;
    position: static;
    width: auto;
    min-width: 0;
    background: none;
    border: 0;
    padding: 0;
  }
  .site-nav ul { flex-direction: row; align-items: center; gap: 22px; }
  .site-nav a { padding: 6px 0; border-bottom: 0; font-size: 14px; }
  .site-nav .nav-cta { display: block; }
  .site-nav .nav-cta a {
    padding: 9px 18px;
    background: var(--accent-glow);
    border: 1px solid var(--accent);
    color: var(--accent);
    border-radius: var(--r);
    font-weight: 600;
  }
  .site-nav .nav-cta a:hover { color: var(--accent); }
}

/* --------------------------------------------------------------------------
   6. HERO
   -------------------------------------------------------------------------- */

/* Bottom padding matches .btn-row's own top margin, so the hero's link row
   sits evenly between the paragraph above it and the rule below. */
.hero { padding: 48px 0 24px; border-bottom: 1px solid var(--border); }

.hero h1 { margin-bottom: 20px; }

.hero-sub { font-size: 1.0625rem; color: var(--text-muted); max-width: 34em; }

/* Three thumbnails between the subhead and the link row, matching .btn-row's own
   top margin so the three blocks sit evenly. */
.hero-shots {
  display: flex;
  justify-content: center;
  gap: 16px;
  margin-top: 24px;
}

/* Capped by HEIGHT, not width: the shots have slightly different aspects, so
   equal widths would leave their bottom edges out of line. `max-height` gives
   the full 220px wherever three of them fit — about 393px of viewport and up —
   and `max-width: 100%` lets them shrink with their flex items below that,
   `height: auto` holding the aspect. Flex shrinks all three by the same factor,
   so their heights stay equal to each other at every width.
   Written through .hero-shots because §7's `.shot img` sets width: 100% at the
   same specificity and comes later in the file — a lone `.hero-shot img` loses. */
.hero-shots .shot { flex: 0 1 auto; min-width: 0; cursor: zoom-in; }
.hero-shots .shot img { width: auto; height: auto; max-width: 100%; max-height: 220px; }

/* The hero's two links carry the page's onward routes, so they outsize the
   button they inherit from. §16 sizes them down again on a phone. */
.hero .btn-row .btn-secondary { padding: 15px 26px; font-size: 1rem; }

@media (min-width: 880px) {
  .hero { padding-top: 72px; }
}

/* --------------------------------------------------------------------------
   7. SCREENSHOTS
   The shots are dark, dense and detailed. Frame them quietly and give them
   room — nothing decorative should compete with them.
   -------------------------------------------------------------------------- */

/* The figure is layout only. The frame lives on the image, so the caption
   above it sits outside the frame rather than inside its top edge. */
.shot {
  margin: 0;
  max-width: 300px;
}

.shot img {
  width: 100%;
  height: auto;
  display: block;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 18px;
  padding: 8px;
}

.shot-center { margin-inline: auto; }

/* Labels the framed shot below it, and sits above the frame, not within it. */
.shot-caption {
  margin: 0 0 10px;
  font-size: 0.75rem;
  line-height: 1.45;
  font-weight: 600;
  text-align: center;
  color: var(--text);
}

/* A panel's screenshots in one swipeable row. Two sit side by side and never
   overflow; four or five scroll. The strip scrolls, not the page body. */
.shot-strip {
  display: flex;
  gap: 16px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* Room for the shots' own shadow and the scrollbar, so neither clips. */
  padding-bottom: 8px;
  -webkit-overflow-scrolling: touch;
}
.shot-strip .shot {
  flex: 0 0 auto;
  width: 260px;
  max-width: 78vw;
  scroll-snap-align: start;
}
/* Captions sit above the frame, so a one-line and a two-line caption would
   start their shots at different heights. Reserve two lines for both, and sit
   the text at the bottom of that box so the slack falls above it, not between
   the caption and the frame it labels. */
.shot-strip .shot-caption {
  min-height: calc(2 * 1.45em);
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

/* The viewer a hero thumbnail opens into. A native <dialog>, so showModal gives
   the focus trap and Escape for free — no <form>, and the thumbnail stays a
   plain link if this is unsupported. The chrome is transparent: the screenshot
   is the whole content. */
.shot-modal {
  padding: 0;
  border: 0;
  background: none;
  max-width: 92vw;
  max-height: 92vh;
  overflow: visible;
}
.shot-modal::backdrop { background: rgba(0, 0, 0, 0.82); }

.shot-modal img {
  display: block;
  width: auto;
  height: auto;
  max-width: 92vw;
  max-height: 92vh;
  border-radius: 14px;
}

.shot-modal-close {
  /* Inside the frame, not hung off its corner — at 92vh the corner is against
     the viewport edge and would be clipped or unreachable. */
  position: absolute;
  top: 10px;
  right: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid var(--border2);
  border-radius: 999px;
  background: var(--surface2);
  color: var(--text);
  cursor: pointer;
}
.shot-modal-close svg { width: 18px; height: 18px; }

/* --------------------------------------------------------------------------
   8. FEATURE SECTIONS
   -------------------------------------------------------------------------- */

.feature { border-bottom: 1px solid var(--border); }

/* Icon-tile menu on features.html — one shared panel below the grid shows
   whichever tile was last clicked, instead of every feature stacked in a
   long scroll. */
/* Half the usual section gap above the tiles: they belong to the rule they
   sit under, not to a section of their own. */
.feature-menu { border-bottom: 1px solid var(--border); padding-top: calc(var(--section-y) / 2); }

/* `.tile-bar` pins a single tile row under the header — how-it-works.html's
   step pills and features.html's category pills — so the row stays reachable
   for a reader deep in a panel. It is always a WRAPPER, never the tile row
   itself: a mask clips an element's background along with its content, so a
   masked row pinned directly would fade its own background out and let the
   page scroll through the gap. One row is one row at every width, so nothing
   here has to collapse. */
.tile-bar {
  position: sticky;
  top: var(--header-h);
  z-index: 40;
  padding: 10px 0;
  background: rgba(14, 13, 13, 0.94);
  backdrop-filter: blur(10px);
}

.feature-tiles {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}

.feature-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 20px 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  color: var(--text-muted);
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 0.875rem;
  text-align: center;
  cursor: pointer;
}
.feature-tile svg { width: 26px; height: 26px; flex-shrink: 0; }
.feature-tile:hover { border-color: var(--accent); color: var(--text); }
.feature-tile.is-active {
  background: var(--accent-glow);
  border-color: var(--accent);
  color: var(--text);
}


/* Step-pill variant, on how-it-works.html: three pills strung along a progress
   track, the first flush left and the last flush right. Flex rather than the
   grid it modifies, because a connector has to stretch across whatever space
   the labels leave and a grid cell cannot span between two pills. Written
   against .feature-tiles as well, or the min-width:880px grid below this
   reclaims the four columns. It only restyles .feature-tile inside itself, so
   the tile's own colours and weights still edit in one place for every
   layout. */
.feature-tiles.step-tabs { display: flex; align-items: center; }

.step-tabs .feature-tile {
  flex: 0 0 auto;
  flex-direction: row;
  gap: 0;
  padding: 10px 22px;
  border-radius: 999px;
  background: none;
  border-color: var(--border);
}
.step-tabs .feature-tile.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg);
}

/* The track between two pills. It lights when an active pill sits somewhere
   after it — which is every line behind the current step, so the row fills in
   as a progress bar. Purely decorative, and `aria-hidden` in the markup. */
.step-line {
  flex: 1 1 auto;
  min-width: 8px;
  height: 2px;
  border-radius: 2px;
  background: var(--border2);
}
.step-line:has(~ .feature-tile.is-active) { background: var(--accent); }

/* Category-pill variant, on features.html: five pills over five panels. Flex
   rather than the grid it modifies, and written against .feature-tiles for the
   same reason .step-tabs is — or the min-width:880px grid below reclaims the
   four columns. These are categories, not a sequence, so nothing connects
   them: no .step-line, no progress to read along the row. */
.feature-tiles.cat-tabs {
  display: flex;
  align-items: center;
  gap: 10px;
  /* Five pills exceed a narrow phone even icon-only (§16), and the page body
     must never scroll sideways — so the row scrolls in its own right. */
  overflow-x: auto;
}

.cat-tabs .feature-tile {
  flex: 0 0 auto;
  flex-direction: row;
  gap: 8px;
  padding: 10px 16px;
  border-radius: 999px;
  background: none;
  border-color: var(--border);
}
/* The tint rides the icon at rest, so the categories are told apart without a
   pill having to shout — and it is the whole signal once §16 clips the labels. */
.cat-tabs .feature-tile svg { width: 20px; height: 20px; color: var(--tile-color, currentColor); }
.cat-tabs .feature-tile:hover { border-color: var(--tile-color, var(--accent)); }
.cat-tabs .feature-tile.is-active {
  background: var(--tile-glow, var(--accent-glow));
  border-color: var(--tile-color, var(--accent));
  color: var(--text);
}

/* One tint per category, set on the pill and on the panel it opens, so the
   colour is named once here rather than repeated through the markup. */
.cat-tabs [data-category="add"],
.cat-panel[data-category="add"] { --tile-color: var(--cat-add); --tile-glow: var(--cat-add-glow); }
.cat-tabs [data-category="price"],
.cat-panel[data-category="price"] { --tile-color: var(--cat-price); --tile-glow: var(--cat-price-glow); }
.cat-tabs [data-category="sell"],
.cat-panel[data-category="sell"] { --tile-color: var(--cat-sell); --tile-glow: var(--cat-sell-glow); }
.cat-tabs [data-category="manage"],
.cat-panel[data-category="manage"] { --tile-color: var(--cat-manage); --tile-glow: var(--cat-manage-glow); }
.cat-tabs [data-category="track"],
.cat-panel[data-category="track"] { --tile-color: var(--cat-track); --tile-glow: var(--cat-track-glow); }

/* One category's cards and the dots that page through them. The pills above
   name the category; the dots carry position inside it. Card chrome is shared
   with .spotlight below. */
.cat-panel { margin-top: 28px; }
.cat-panel .feature-panel { margin-top: 0; }
/* The category's own tint, so the dots say which set is being paged. */
.cat-panel .spot-dot.is-active::before { background: var(--tile-color, var(--accent)); }

.feature-panel { margin-top: 28px; }

/* A swapped-in panel is scrolled to by the swipe and by the panel links, and
   both pinned bands are above it — the header and the tile bar. The second
   selector is features.html, where the panel sits one level in, inside the
   category that holds it. */
.tile-bar ~ .feature-panel .feature-content,
.tile-bar ~ .cat-panel .feature-content {
  scroll-margin-top: calc(var(--header-h) + var(--tile-bar-h) + 8px);
}

/* Spotlight variant, on index.html: no tile row above it, so each section is a
   card in its own right and the panel turns over on its own. */
.spotlight { margin-top: 0; }

/* Card chrome, shared: a section is a card wherever it is swiped between rather
   than read down a page — index.html's spotlight, features.html's categories
   and how-it-works.html's steps alike. */
.spotlight .feature-content,
.cat-panel .feature-content,
.step-cards .feature-content {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 28px 24px;
}

/* Nothing is pinned above the spotlight but the header. */
.spotlight .feature-content { scroll-margin-top: calc(var(--header-h) + 8px); }

/* A swapped-in card rises into place instead of appearing outright. Without it
   the swap is one frame — the card changes height and everything below it moves
   at the same instant, which reads as the page glitching rather than as a card
   turning. Going from `hidden` to shown restarts the animation on its own, so
   nothing in js/site.js drives this. Entrance only: fading the outgoing card
   would mean keeping it in the layout while it went, and `hidden` takes it
   straight out. §2's reduced-motion block cancels the whole thing. */
@keyframes card-in {
  from { opacity: 0; transform: translateY(8px); }
}

.spotlight .feature-content:not([hidden]),
.cat-panel .feature-content:not([hidden]),
.step-cards .feature-content:not([hidden]) {
  animation: card-in 260ms ease-out;
}

/* Position and count, and the keyboard route into the sections now the pills
   are gone. Built in js/site.js: a dot is labelled by its section's own
   eyebrow, which would otherwise be written out a second time. */
.spot-dots { display: flex; justify-content: center; margin-top: 22px; }

.spot-dot {
  display: grid;
  place-items: center;
  width: 34px;
  height: 30px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
/* The mark is drawn inside the button, so a 9px dot still has a 34px target. */
.spot-dot::before {
  content: '';
  width: 9px;
  height: 9px;
  border-radius: 999px;
  background: var(--border2);
}
.spot-dot:hover::before { background: var(--text-soft); }
.spot-dot.is-active::before { width: 22px; background: var(--accent); }

/* A card gives its section more presence than the same section has read down a
   plain page, so both ends of it are set a step up. */
.spotlight .eyebrow,
.cat-panel .eyebrow { font-size: 0.875rem; }
.spotlight .more-link a,
.cat-panel .more-link a { font-size: 1.1875rem; }

.feature-grid { display: grid; gap: 36px; align-items: center; }

/* Grid items default to min-width:auto, so a .shot-strip inside one would
   size the column to its full scroll width and push the page sideways. */
.feature-media { min-width: 0; }

@media (min-width: 880px) {
  /* Four across, matching the phone: twelve tiles land as three full rows at
     both widths. Taller here so the rows read as a band, not a thin strip of
     icons. */
  .feature-tiles { grid-template-columns: repeat(4, 1fr); gap: 14px; }
  .feature-tile { padding: 28px 14px; gap: 12px; font-size: 0.9375rem; }
  .feature-tile svg { width: 30px; height: 30px; }

  .feature-grid { grid-template-columns: 1fr minmax(260px, 310px); gap: 64px; }
  .feature-grid.wide-media { grid-template-columns: 1fr minmax(300px, 420px); }

  /* Reversed rows put the media first. `order` alone is not enough: the media
     would then land in the 1fr column and squeeze the text into the narrow
     one. The column template has to be mirrored as well. */
  .feature-grid.reverse .feature-body { order: 2; }
  .feature-grid.reverse .feature-media { order: 1; }
  .feature-grid.reverse { grid-template-columns: minmax(260px, 310px) 1fr; }
  .feature-grid.reverse.wide-media { grid-template-columns: minmax(300px, 420px) 1fr; }

  /* Sections carrying a PAIR of screenshots stack instead of sitting in a
     side column: two shots squeezed into a 310px column are ~145px each,
     which is unreadable for shots this dense. Stacked, they get ~310px each —
     the same size as the single shots elsewhere. */
  .feature-grid.feature-stack { grid-template-columns: 1fr; gap: 44px; }
  .feature-grid.feature-stack .feature-body { order: 0; max-width: 64ch; }
  .feature-grid.feature-stack .feature-media { order: 0; }
}

/* An inline honesty note — used wherever a claim needs its limit stated in
   the same breath. MARKETING_FACTS.md section 9. */
.note {
  margin-top: 20px;
  padding: 14px 16px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-left: 3px solid var(--amber);
  border-radius: var(--r);
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--text-muted);
}
.note strong { color: var(--text); }
.note p { font-size: 0.875rem; color: var(--text-muted); }
.note p:last-child { margin-bottom: 0; }

.note-accent { border-left-color: var(--accent); }
.note-red { border-left-color: var(--red); }

/* A note belonging to a whole row sits under the screenshot, full width.
   `order` is load-bearing: .reverse orders its body and media, so an
   unordered third child would jump ahead of both. */
.feature-grid > .note {
  order: 3;
  grid-column: 1 / -1;
  margin-top: 0;
  max-width: 64ch;
}

/* --------------------------------------------------------------------------
   9. CARDS / GRIDS / LISTS
   -------------------------------------------------------------------------- */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 22px;
}
.card h3 { margin-bottom: 8px; }
.card p { font-size: 0.9375rem; margin-bottom: 0; }

/* A "read on" link closing a card or a section. */
.more-link { margin-top: 14px; margin-bottom: 0; }
.more-link a { font-size: 1.0625rem; font-weight: 700; }

.grid-2, .grid-3 { display: grid; gap: 16px; }

@media (min-width: 720px) {
  .grid-2 { grid-template-columns: repeat(2, 1fr); }
  .grid-3 { grid-template-columns: repeat(3, 1fr); }
}

/* Problem list — the spine of the page. */
.problems { list-style: none; padding: 0; margin: 32px 0 0; display: grid; gap: 14px; }
.problems li { margin: 0; }

.problems a {
  display: block;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 20px 22px;
  color: var(--text-muted);
  text-decoration: none;
}
.problems a:hover { border-color: var(--border2); text-decoration: none; }

.problems .quote {
  display: block;
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 1.0625rem;
  color: var(--text);
  margin-bottom: 6px;
  line-height: 1.35;
}
.problems .answer { display: block; font-size: 0.9375rem; }

/* The jump gets its own line and outweighs the answer above it — it is the
   row's action, not the tail of its sentence. */
.problems .jump {
  display: block;
  margin-top: 10px;
  color: var(--accent);
  font-size: 1rem;
  font-weight: 700;
}

/* Numbered steps */
.steps {
  list-style: none;
  padding: 0;
  margin: 36px 0 0;
  counter-reset: step;
  display: grid;
  gap: 16px;
}
.steps li {
  counter-increment: step;
  margin: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 22px;
}
.steps li::before {
  content: counter(step);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin-bottom: 14px;
  border-radius: 8px;
  background: var(--accent-glow);
  color: var(--accent);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 14px;
}
.steps h3 { margin-bottom: 6px; }
.steps p { font-size: 0.9375rem; margin: 0; }

@media (min-width: 720px) { .steps { grid-template-columns: repeat(3, 1fr); } }

/* Free vs credits */
.split { display: grid; gap: 16px; margin-top: 32px; }
@media (min-width: 720px) { .split { grid-template-columns: 1fr 1fr; } }

.split-col {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 22px;
}
.split-col.is-free { border-color: rgba(0, 196, 160, 0.35); }

.split-col h3 { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; }
.split-col.is-free h3 { color: var(--accent); }
.split-col.is-paid h3 { color: var(--amber); }

.tick-list { list-style: none; padding: 0; margin: 0; }
.tick-list li {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  font-size: 0.9375rem;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
  color: var(--text-muted);
  margin: 0;
}
.tick-list li:last-child { border-bottom: 0; }
.tick-list svg { flex: 0 0 auto; margin-top: 5px; }
/* Same divided-row look as .tick-list, but plain flow rather than flex — for
   rows that are a sentence with emphasis inside, not an icon plus a label. */
.value-list { list-style: none; padding: 0; margin: 0; }
.value-list li {
  font-size: 0.9375rem;
  padding: 9px 0;
  margin: 0;
  border-bottom: 1px solid var(--border);
  color: var(--text-muted);
}
.value-list li:last-child { border-bottom: 0; }

/* In a feature panel the rows are long-form detail, not a divided table: eight
   ruled rows read as a wall, and the bold label already starts each one. */
.feature-text .value-list li { padding: 5px 0; border-bottom: 0; }

/* A sequence, not a set: .value-list's sentence-with-emphasis row, numbered and
   joined, where the rows are read in order rather than scanned. */
.flow { list-style: none; padding: 0; margin: 0; counter-reset: flow; }
.flow li {
  counter-increment: flow;
  position: relative;
  margin: 0;
  padding: 0 0 18px 36px;
  font-size: 0.9375rem;
  color: var(--text-muted);
}
.flow li::before {
  content: counter(flow);
  position: absolute;
  left: 0;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 8px;
  background: var(--accent-glow);
  color: var(--accent);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 12px;
}
/* The connector stops at the last marker — a line running past it would read as
   a step that isn't there. */
.flow li::after {
  content: '';
  position: absolute;
  left: 11px;
  top: 28px;
  bottom: 4px;
  width: 1px;
  background: var(--border);
}
.flow li:last-child { padding-bottom: 0; }
.flow li:last-child::after { content: none; }
.flow strong { color: var(--text); }

.tick-list .cost {
  margin-left: auto;
  padding-left: 12px;
  color: var(--amber);
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 0.8125rem;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   10. PRICING
   -------------------------------------------------------------------------- */

.pack-grid { display: grid; gap: 16px; margin-top: 32px; }
@media (min-width: 720px) { .pack-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .pack-grid { grid-template-columns: repeat(4, 1fr); } }

.pack {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 24px 22px 22px;
  display: flex;
  flex-direction: column;
}
.pack.is-flagged { border-color: var(--accent); }

/* A pack name is brand orange, not the site's teal — it names a product, and
   the teal below it is the price. Scoped so every other .eyebrow stays teal. */
.pack .eyebrow { color: var(--brand); }

.pack-badge {
  position: absolute;
  top: -10px;
  left: 22px;
  background: var(--bg);
  border: 1px solid var(--accent);
  color: var(--accent);
  font-family: var(--font-head);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 3px 10px;
  border-radius: 999px;
}

.pack-buys {
  font-family: var(--font-head);
  font-size: 1.3125rem;
  font-weight: 700;
  color: var(--text);
  line-height: 1.25;
  margin: 0 0 4px;
}

.pack-price {
  font-family: var(--font-head);
  font-size: 1.75rem;
  font-weight: 800;
  color: var(--accent);
  margin: 14px 0 2px;
}

.pack-credits { font-size: 0.8125rem; color: var(--text-soft); margin: 0 0 16px; }

/* Price and credits left, the detail list beside them. */
.pack-row {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 18px;
  padding-top: 14px;
  margin-top: auto; /* bottom-pins the block in an equal-height card */
}
.pack-row .pack-price { grid-column: 1; grid-row: 1; margin-top: 0; }
.pack-row .pack-credits { grid-column: 1; grid-row: 2; margin-bottom: 0; }
.pack-row .pack-detail { grid-column: 2; grid-row: 1 / span 2; }

/* The divider is the list's own left border, so it is as tall as the list, not the card. */
.pack-detail {
  list-style: none;
  padding: 0 0 0 18px;
  margin: 0;
  border-left: 1px solid var(--border);
  font-size: 0.8125rem;
  color: var(--text-soft);
}
.pack-detail li { margin-bottom: 5px; }

/* Four packs across leaves ~200px inside a card — too narrow to split, so the row flattens. */
@media (min-width: 1000px) {
  .pack-row { display: contents; }
  .pack-row .pack-price { margin-top: 14px; }
  .pack-row .pack-credits { margin-bottom: 16px; }
  .pack-detail {
    padding: 14px 0 0;
    margin: auto 0 0;
    border-left: 0;
    border-top: 1px solid var(--border);
  }
}

.free-tier {
  background: var(--surface);
  border: 1px solid rgba(0, 196, 160, 0.35);
  border-radius: var(--r);
  padding: 26px;
  margin-top: 32px;
}
.free-tier .pack-price { font-size: 2.25rem; margin-top: 0; }

/* --------------------------------------------------------------------------
   11. FAQ  (native details/summary — no JS)
   -------------------------------------------------------------------------- */

.faq { margin-top: 32px; }

.faq details {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  margin-bottom: 10px;
}

.faq summary {
  cursor: pointer;
  list-style: none;
  padding: 18px 46px 18px 20px;
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 1rem;
  color: var(--text);
  position: relative;
}
.faq summary::-webkit-details-marker { display: none; }

.faq summary::after {
  content: "";
  position: absolute;
  right: 22px;
  top: 24px;
  width: 9px;
  height: 9px;
  border-right: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(45deg);
  transition: transform 0.2s;
}
.faq details[open] summary::after { transform: rotate(-135deg); top: 28px; }

.faq .faq-body { padding: 0 20px 20px; }
.faq .faq-body p { font-size: 0.9375rem; }

/* --------------------------------------------------------------------------
   12. LEGAL / PROSE PAGES
   -------------------------------------------------------------------------- */

.page-head { padding: 48px 0 40px; border-bottom: 1px solid var(--border); }
.page-head p { max-width: 40em; }

.updated { font-size: 0.8125rem; color: var(--text-soft); margin: 0 0 10px; }

.prose { padding: 44px 0 var(--section-y); }
.prose h2 { margin-top: 48px; font-size: 1.375rem; }
.prose h2:first-child { margin-top: 0; }
.prose h3 { margin-top: 30px; }
.prose p, .prose li { font-size: 0.9375rem; }

.table-wrap { overflow-x: auto; margin: 0 0 22px; }

table { width: 100%; min-width: 540px; border-collapse: collapse; font-size: 0.875rem; }
th, td {
  text-align: left;
  vertical-align: top;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  color: var(--text-muted);
}
th {
  font-family: var(--font-head);
  font-weight: 600;
  color: var(--text);
  background: var(--surface2);
}
tbody tr:last-child td { border-bottom: 0; }

/* An unresolved fact (CLAUDE.md §8): a faint dot, its note in title; §15 reveals them all. */
.ph {
  display: inline-block;
  width: 5px;
  height: 5px;
  margin-left: 4px;
  border-radius: 50%;
  background: var(--border);
  vertical-align: middle;
}

/* --------------------------------------------------------------------------
   13. FOOTER
   -------------------------------------------------------------------------- */

.footer-cta { padding: var(--section-y) 0; border-top: 1px solid var(--border); text-align: center; }
.footer-cta h2 { margin-bottom: 12px; }
.footer-cta p { max-width: 34em; margin-inline: auto; }
.footer-cta .btn-row { justify-content: center; }

.site-footer {
  background: var(--surface);
  border-top: 1px solid var(--border);
  padding: 44px 0 36px;
}

.footer-top {
  display: grid;
  gap: 28px;
  grid-template-columns: 1fr 1fr;
  grid-template-areas: "brand brand" "site legal";
  padding-bottom: 28px;
  border-bottom: 1px solid var(--border);
}
.footer-top .footer-col:nth-child(1) { grid-area: brand; }
.footer-top .footer-col:nth-child(2) { grid-area: site; }
.footer-top .footer-col:nth-child(3) { grid-area: legal; }

@media (min-width: 720px) {
  .footer-top { grid-template-columns: 1.5fr 1fr 1fr; grid-template-areas: "brand site legal"; }
}

.footer-col h2 {
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-soft);
  margin-bottom: 14px;
}

.footer-col ul { list-style: none; padding: 0; margin: 0; }
.footer-col li { margin-bottom: 9px; }

.footer-col a { color: var(--text-muted); font-size: 0.9375rem; }
.footer-col a:hover { color: var(--accent); }

.footer-blurb { font-size: 0.875rem; color: var(--text-soft); margin: 14px 0 0; max-width: 32em; }

.footer-bottom { padding-top: 24px; }
.footer-bottom p { font-size: 0.8125rem; color: var(--text-soft); line-height: 1.6; margin-bottom: 10px; }

/* --------------------------------------------------------------------------
   14. 404
   -------------------------------------------------------------------------- */

.notfound { padding: 96px 0; text-align: center; }
.notfound .btn-row { justify-content: center; }

/* --------------------------------------------------------------------------
   15. PLACEHOLDER REVIEW MODE

   Uncomment the block below to turn each faint .ph dot into an amber tag that
   reads out its note, and see at a glance which facts are still missing.
   -------------------------------------------------------------------------- */

/*
.ph { width: auto; height: auto; padding: 1px 6px; border: 1px dashed var(--amber); border-radius: 5px; background: rgba(245, 166, 35, 0.12); color: var(--amber); font-size: 0.9em; vertical-align: baseline; }
.ph::after { content: attr(title); }
*/

/* --------------------------------------------------------------------------
   16. MOBILE TUNING

   The rest of this file is mobile-first: base rules are the phone layout and
   min-width queries add the desktop one. This section is the exception, and
   the only one — a max-width block that desktop can never see, so mobile
   sizing can be tuned without touching what ships at 880px and up.

   Sections 1-15 hold structure and shared values. Only mobile-only *sizing*
   belongs here, or a value ends up set in two places and the two drift.
   -------------------------------------------------------------------------- */

@media (max-width: 879.98px) {
  :root {
    --section-y: 44px;
    /* The pills shrink here, so the bar they sit in does too. */
    --tile-bar-h: 64px;
  }

  /* Spacing */
  .wrap { padding: 0 16px; }
  .hero { padding-top: 36px; }
  .page-head { padding: 32px 0 28px; }
  .prose { padding-top: 32px; }

  /* The hero's two links stay one row: each shrinks and wraps its own
     label instead of the row wrapping a button onto a second line. */
  .hero .btn-row { flex-wrap: nowrap; gap: 8px; }
  .hero .btn-row .btn-secondary {
    flex: 1 1 0;
    min-width: 0;
    padding: 14px 10px;
    font-size: 0.9375rem;
    text-align: center;
  }

  /* The header carries two pills and the toggle here, so the wordmark and the
     pills both give up a few pixels to keep the row on one line. */
  .wordmark { font-size: 1.125rem; }
  .wordmark img { width: 26px; height: 26px; margin-right: 7px; }
  .site-header .header-cta { padding: 8px 12px; font-size: 12px; }

  /* Cards and boxes */
  .card { padding: 18px; }
  .note { margin-top: 16px; padding: 12px 14px; }
  .problems a { padding: 16px 18px; }
  .split-col { padding: 18px; }
  .pack { padding: 20px 18px 18px; }
  .faq summary { padding: 15px 42px 15px 16px; }

  /* Screenshots */
  .shot img { padding: 6px; }

  /* Four tiles across a phone: the icon and label shrink to fit rather than
     the labels wrapping to three lines. */
  .feature-tiles { gap: 8px; }
  .feature-tile { padding: 14px 6px; gap: 7px; font-size: 0.75rem; }
  .feature-tile svg { width: 22px; height: 22px; }

  .spotlight .feature-content,
  .cat-panel .feature-content,
  .step-cards .feature-content { padding: 20px 16px; }

  /* The shrink above is for fitting four across; a step pill is sized by its
     label, like the rail's. */
  .step-tabs .feature-tile { padding: 9px 14px; font-size: 0.8125rem; }

  /* Five labelled pills do not fit a phone, so only the open one is named and
     the rest are their icon. The label is CLIPPED, never display:none — the
     icon is the whole button, so hiding the text outright would leave four of
     the five pills with no accessible name at all. */
  .cat-tabs .feature-tile { padding: 9px 12px; font-size: 0.8125rem; }
  .cat-tabs .feature-tile:not(.is-active) span {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  /* Ordering, not sizing — the one exception in this section, because a
     max-width query is the only place a rule is invisible to desktop, and the
     alternative sets every one of these values twice.

     On a phone the screenshot leads and the copy reads under it, with the
     heading still on top. `order` cannot reach inside .feature-body, so the
     body flattens and its two halves become grid items either side of the
     media. Desktop keeps the markup's own order and never sees any of this. */
  .feature-body { display: contents; }
  .feature-head { order: 1; }
  .feature-media { order: 2; }
  .feature-text { order: 3; }
  /* Section 8 sets 3, which would now tie with .feature-text. */
  .feature-grid > .note { order: 4; }

  /* Cancels the row gap below the heading — matches .feature-grid's own gap in
     section 8. A grid item does not collapse margins with its children, so the
     h2's 16px sits inside .feature-head and the gap stacks on top of it. That
     16px is the whole spacing under a heading everywhere else on the site. */
  .feature-head { margin-bottom: -36px; }

}
