/* ─────────────────────────────────────────────────────────────
 * home.css — the YUPA homepage, rebuilt as a place to POST.
 *
 * ## What changed and why
 *
 * The old homepage was a startup landing page: a big headline, a phone
 * mockup, feature sections, a download push. That page's job was to explain
 * YUPA. This page's job is to get a local or a business to POST something —
 * a Task or a Job Opportunity — inside about fifteen seconds of landing.
 *
 * The reference is Craigslist's usefulness, not its looks: categories you can
 * see at a glance, obvious posting, visible live activity. Everything here is
 * built on YUPA's own tokens instead.
 *
 * ## `styles.css` MUST be loaded before this file
 *
 * Every colour, radius and font below is a variable defined in `styles.css`
 * `:root`. Loading this alone renders the page transparent on black — the same
 * trap `post.css` has. The <head> loads them in order.
 *
 * ## No dark-mode block. On purpose.
 *
 * `styles.css` has no dark theme, so a `prefers-color-scheme: dark` override
 * here would apply on a light page and paint light-on-light. That exact bug
 * shipped once on the opportunity review screen. Use the tokens.
 *
 * ## Mobile is the real design, not the fallback
 *
 * Most traffic arrives from TikTok, Instagram, Facebook groups and QR codes —
 * one thumb, one hand, a cold visitor. So the base styles here ARE the phone
 * layout and the media queries add desktop, not the other way round. Nothing
 * above the fold on a phone is decorative: location, two post buttons, and the
 * proof that students are nearby.
 *
 * Class prefix `hm-` throughout, so nothing here can collide with the shared
 * component classes in `styles.css` used by the rest of the site.
 * ───────────────────────────────────────────────────────────── */

.hm-wrap {
  width: 100%;
  max-width: 1060px;
  margin: 0 auto;
  padding: 0 18px;
}

/* ══ hero leftovers ══════════════════════════════════════════
 * Deliberately short. A cold visitor from a QR code gets one sentence, then
 * the two buttons. Everything explanatory lives further down for the minority
 * who scroll to find it. */
.hm-hero { padding: 16px 0 6px; }
.hm-here {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12.5px; font-weight: 700; color: var(--ink-2);
  background: var(--bg-tint);
  border: 1px solid rgba(124,111,240,.16);
  padding: 6px 12px; border-radius: var(--r-full);
  margin-bottom: 14px;
}
.hm-here b { color: var(--lav-deep); font-weight: 800; }
.hm-here.is-empty { display: none; }

.hm-h1 {
  font-family: var(--font-display);
  font-size: clamp(26px, 7.6vw, 38px);
  line-height: 1.08;
  letter-spacing: -.028em;
  font-weight: 800;
  margin: 0 0 10px;
}
.hm-h1 .g {
  background: var(--grad);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
.hm-sub {
  font-size: 14.5px; line-height: 1.48; color: var(--ink-2);
  margin: 0 0 16px; max-width: 44ch;
}

/* ══ the two posting choices ════════════════════════════════
 * THE PAGE. Two cards, equal weight, both above the fold on a phone.
 *
 * The old hero pushed "Post a Job" as one button and hid opportunities in a
 * one-line link underneath, on the reasoning that hiring is the rarer intent.
 * That reasoning is now wrong: converting businesses into opportunity posters
 * is the product. They get the same size and the same prominence, and the
 * words tell you which one you are — "I need something done" versus "I'm
 * hiring" — rather than making you infer it from a product noun. */
.hm-pick { display: grid; gap: 10px; margin-bottom: 22px; }
.hm-card {
  position: relative;
  display: block; text-decoration: none; color: inherit;
  border: 1.5px solid var(--line);
  border-radius: var(--r-lg);
  padding: 15px 15px 14px;
  background: var(--bg);
  box-shadow: var(--sh-sm);
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
  overflow: hidden;
}
.hm-card:active { transform: scale(.985); }
@media (hover: hover) {
  .hm-card:hover { border-color: rgba(124,111,240,.42); box-shadow: var(--sh-md); transform: translateY(-2px); }
}
.hm-card::after {
  content: ""; position: absolute; inset: 0;
  background: var(--grad-soft); opacity: 0; transition: opacity .16s ease;
  pointer-events: none;
}
@media (hover: hover) { .hm-card:hover::after { opacity: .55; } }
.hm-card > * { position: relative; z-index: 1; }

.hm-card-top { display: flex; align-items: center; gap: 11px; margin-bottom: 9px; }
.hm-card-ico {
  width: 42px; height: 42px; flex: none;
  display: grid; place-items: center;
  border-radius: 13px; font-size: 21px;
  background: var(--grad-soft);
}
.hm-card-t {
  font-family: var(--font-display);
  font-size: 17.5px; font-weight: 800; letter-spacing: -.02em;
  line-height: 1.12;
}
.hm-card-d { font-size: 13.4px; line-height: 1.42; color: var(--ink-2); margin: 0 0 11px; }

/* ══ categories ═════════════════════════════════════════════
 * The Craigslist idea, and the one that does the converting: a visitor who
 * does not know what "post a task" means DOES know they need their lawn done.
 * Every tile carries its own service into the form, so the first question is
 * already answered when they arrive. */
.hm-sec { padding: 26px 0; border-top: 1px solid var(--line-2); }
/* Stacked on a phone, side by side once there is room. Side by side at
 * 390px squeezed the heading into two ragged lines against the note. */
.hm-sec-h {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: 3px; margin-bottom: 14px;
}
@media (min-width: 620px) {
  .hm-sec-h { flex-direction: row; align-items: baseline; justify-content: space-between; gap: 12px; }
}
.hm-h2 {
  font-family: var(--font-display);
  font-size: 19px; font-weight: 800; letter-spacing: -.02em; margin: 0;
}
.hm-sec-note { font-size: 12.5px; color: var(--ink-3); }

.hm-tabs {
  display: inline-flex; gap: 4px; padding: 4px;
  background: var(--bg-soft); border-radius: var(--r-full);
  margin-bottom: 14px;
}
.hm-tab {
  appearance: none; border: 0; cursor: pointer;
  font-family: var(--font); font-size: 13.5px; font-weight: 700;
  color: var(--ink-2); background: transparent;
  padding: 8px 15px; border-radius: var(--r-full);
  transition: background .14s ease, color .14s ease;
}
/* Selected state is aria-pressed, never a class — the same rule post.css
 * follows, after a build shipped a chip that changed the model and nothing on
 * screen because the stylesheet had never heard of the class being toggled. */
.hm-tab[aria-pressed="true"] {
  background: var(--bg); color: var(--ink);
  box-shadow: var(--sh-sm);
}

.hm-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 9px;
}
.hm-cat {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 7px; text-align: center;
  min-height: 88px; padding: 12px 7px;
  text-decoration: none; color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--bg);
  transition: border-color .14s ease, background .14s ease, transform .14s ease;
}
.hm-cat:active { transform: scale(.97); }
@media (hover: hover) {
  .hm-cat:hover { border-color: rgba(124,111,240,.4); background: var(--bg-tint); }
}
.hm-cat-e { font-size: 22px; line-height: 1; }
.hm-cat-n { font-size: 11.8px; font-weight: 700; line-height: 1.25; letter-spacing: -.01em; }
.hm-more {
  grid-column: 1 / -1;
  display: flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 46px; margin-top: 3px;
  font-size: 13.5px; font-weight: 800; color: var(--lav-deep);
  text-decoration: none;
  border: 1px dashed rgba(124,111,240,.4);
  border-radius: var(--r-md);
  background: rgba(124,111,240,.04);
}

/* ══ live activity ══════════════════════════════════════════
 * Proof, not decoration. Hidden entirely when the feed is empty or the
 * endpoint fails — an empty "Live on YUPA" heading is worse than no section,
 * because it says the marketplace is dead. */
.hm-feed { display: grid; gap: 8px; }
.hm-row {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--bg);
}
.hm-row-e {
  width: 36px; height: 36px; flex: none;
  display: grid; place-items: center;
  border-radius: 11px; font-size: 17px;
  background: var(--bg-soft);
}
.hm-row-b { min-width: 0; flex: 1; }
.hm-row-t {
  font-size: 14.2px; font-weight: 700; line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hm-row-m {
  font-size: 12.2px; color: var(--ink-3); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hm-row-p { font-size: 14px; font-weight: 800; color: var(--ink); flex: none; }
.hm-kind {
  display: inline-block; font-size: 10.5px; font-weight: 800;
  text-transform: uppercase; letter-spacing: .03em;
  padding: 2px 7px; border-radius: var(--r-full); margin-right: 6px;
  color: var(--lav-deep); background: rgba(124,111,240,.11);
}
.hm-kind.task { color: var(--teal-deep); background: rgba(24,179,161,.12); }
.hm-live {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 700; color: var(--ink-3);
}
.hm-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: #22c55e; box-shadow: 0 0 0 3px rgba(34,197,94,.16);
}
/* Honour reduced motion — the pulse is decoration and nothing depends on it. */
@media (prefers-reduced-motion: no-preference) {
  .hm-dot { animation: hm-pulse 2.2s ease-in-out infinite; }
  @keyframes hm-pulse { 0%,100% { opacity: 1 } 50% { opacity: .45 } }
}
.hm-skel {
  height: 62px; border-radius: var(--r-md);
  background: linear-gradient(90deg, var(--bg-soft) 25%, var(--line-2) 37%, var(--bg-soft) 63%);
  background-size: 400% 100%;
}
@media (prefers-reduced-motion: no-preference) {
  .hm-skel { animation: hm-shimmer 1.3s linear infinite; }
  @keyframes hm-shimmer { to { background-position: -135% 0 } }
}

/* ══ why people use YUPA ═══════════════════════════════════
 * Real cards. As bare rows these read as three stray paragraphs floating
 * between two bordered sections, with nothing holding them together. Equal
 * height, one accent disc each, and the same border and radius as every other
 * surface on the page so they read as peers of the posting cards. */
.hm-trust { display: grid; gap: 10px; }
.hm-tr {
  display: block;
  padding: 18px 18px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--bg);
  transition: border-color .16s ease, box-shadow .16s ease;
}
@media (hover: hover) {
  .hm-tr:hover { border-color: rgba(124,111,240,.32); box-shadow: var(--sh-sm); }
}
.hm-tr-e {
  display: grid; place-items: center;
  width: 40px; height: 40px; margin-bottom: 12px;
  border-radius: 13px; font-size: 19px; line-height: 1;
  background: var(--grad-soft);
}
.hm-tr-t {
  font-family: var(--font-display);
  font-size: 15.5px; font-weight: 800; letter-spacing: -.015em;
  margin: 0 0 5px; color: var(--ink);
}
.hm-tr-d { font-size: 13.5px; line-height: 1.5; color: var(--ink-2); margin: 0; }

/* ══ footer ═════════════════════════════════════════════════ */
.hm-foot {
  border-top: 1px solid var(--line);
  padding: 24px 0 34px; margin-top: 12px;
  background: var(--bg-soft);
}
.hm-store { display: flex; flex-wrap: wrap; gap: 9px; margin-bottom: 16px; }
.hm-store a {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13px; font-weight: 700; text-decoration: none;
  color: var(--ink); background: var(--bg);
  border: 1px solid var(--line); border-radius: var(--r-full);
  padding: 9px 14px;
}
.hm-store svg { width: 15px; height: 15px; }
.hm-links { display: flex; flex-wrap: wrap; gap: 8px 18px; margin-bottom: 12px; }
.hm-links a { font-size: 13px; color: var(--ink-2); text-decoration: none; }
.hm-links a:hover { color: var(--ink); }
.hm-fine { font-size: 12px; color: var(--ink-3); line-height: 1.5; }

/* ══ sticky mobile action bar ═══════════════════════════════
 * Appears only after the hero buttons scroll away, so the primary action is
 * never more than a thumb-reach away on a long page. Phone only — on desktop
 * the page is short enough that it would just be clutter. */
.hm-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  display: grid; grid-template-columns: 1fr 1fr; gap: 9px;
  padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
  background: rgba(255,255,255,.94);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
  border-top: 1px solid var(--line);
  transform: translateY(105%);
  transition: transform .22s ease;
}
.hm-bar.is-on { transform: translateY(0); }
.hm-bar a {
  display: flex; align-items: center; justify-content: center;
  min-height: 46px; border-radius: var(--r-full);
  font-size: 14.5px; font-weight: 800; text-decoration: none;
}
.hm-bar .t { color: #fff; background: var(--grad); }
.hm-bar .o { color: var(--ink); background: var(--bg); border: 1.5px solid var(--line); }
@media (min-width: 861px) { .hm-bar { display: none; } }

/* ══ desktop ════════════════════════════════════════════════
 * Added on top of the phone layout, never replacing it. */
@media (min-width: 620px) {
  .hm-grid { grid-template-columns: repeat(4, 1fr); }
  .hm-cat-n { font-size: 12.5px; }
  .hm-pick { grid-template-columns: 1fr 1fr; gap: 14px; }
}
@media (min-width: 861px) {
  .hm-wrap { padding: 0 28px; }
  .hm-hero { padding: 44px 0 12px; }
  .hm-h1 { font-size: 46px; }
  .hm-sub { font-size: 16.5px; }
  .hm-grid { grid-template-columns: repeat(6, 1fr); }
  .hm-sec { padding: 34px 0; }
  .hm-h2 { font-size: 22px; }
  .hm-card { padding: 22px 22px 20px; }
  .hm-trust { grid-template-columns: repeat(3, 1fr); gap: 20px; }
}


/* ══ "better in the app" ════════════════════════════════════
 * Said as a claim with evidence rather than a download banner. The website is
 * where you post; the app is where you run what you posted. */
.hm-app {
  border: 1.5px solid var(--line);
  border-radius: var(--r-lg);
  padding: 20px 18px;
  background: linear-gradient(180deg, var(--bg-tint) 0%, var(--bg) 100%);
}
.hm-eyebrow {
  display: inline-block; font-size: 11.5px; font-weight: 800;
  text-transform: uppercase; letter-spacing: .06em;
  color: var(--lav-deep); margin-bottom: 8px;
}
.hm-app .hm-h2 { margin-bottom: 12px; }
.hm-app-list { list-style: none; margin: 0 0 16px; padding: 0; display: grid; gap: 9px; }
.hm-app-list li {
  position: relative; padding-left: 24px;
  font-size: 13.8px; line-height: 1.45; color: var(--ink-2);
}
.hm-app-list li b { color: var(--ink); font-weight: 700; }
.hm-app-list li::before {
  content: ""; position: absolute; left: 4px; top: 7px;
  width: 7px; height: 7px; border-radius: 50%; background: var(--grad);
}
.hm-store { display: flex; flex-wrap: wrap; gap: 9px; }
.hm-store a {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 13.5px; font-weight: 700; text-decoration: none;
  color: var(--ink); background: var(--bg);
  border: 1px solid var(--line); border-radius: var(--r-full);
  padding: 10px 15px;
}
.hm-store svg { width: 15px; height: 15px; }
@media (min-width: 861px) {
  .hm-app { padding: 30px 28px; }
  .hm-app-list { grid-template-columns: 1fr 1fr; gap: 12px 26px; }
}

/* The sticky bar sits above the page's own bottom padding on a phone, so the
 * footer is never trapped underneath it. */
@media (max-width: 860px) {
  .hm-foot { padding-bottom: calc(80px + env(safe-area-inset-bottom)); }
}

/* ══ footer link columns ════════════════════════════════════
 * These replaced the horizontally scrollable service row that used to sit
 * under the header. Plain text, three columns, no affordance to learn. */
.hm-foot-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 20px 16px; margin-bottom: 20px; }
.hm-foot-h {
  font-size: 11.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .05em; color: var(--ink-3); margin: 0 0 9px;
}
.hm-foot-col a {
  display: block; font-size: 13.5px; color: var(--ink-2);
  text-decoration: none; padding: 4px 0;
}
.hm-foot-col a:hover { color: var(--ink); }
@media (min-width: 620px) { .hm-foot-cols { grid-template-columns: repeat(3, 1fr); gap: 26px; } }

/* ══ Community Fund / Founding Member meter ═════════════════
 * Modelled on the Pollos Live points meter: a bar that fills, a bubble that
 * pops, and milestone tiles that go from grey to unlocked. There it sells
 * free food for watching; here it sells a say in your neighbourhood.
 *
 * It LOOPS, and the caption says it is an example. An animated counter that
 * looked like a live figure would be inventing a number about the person
 * reading it. */
.hm-fund-lead {
  font-size: 14.5px; line-height: 1.55; color: var(--ink-2);
  margin: 0 0 16px; max-width: 62ch;
}
.hm-fund-lead b { color: var(--ink); font-weight: 800; }

.fm-box {
  background: var(--bg);
  border: 1.5px solid var(--line);
  border-radius: var(--r-lg);
  padding: 20px 18px;
  box-shadow: var(--sh-md);
}
.fm-top { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 12px; }
.fm-count { font-family: var(--font-display); font-size: 24px; font-weight: 800; letter-spacing: -.02em; }
.fm-sub { display: block; font-size: 12.5px; color: var(--ink-3); font-weight: 600; margin-top: 1px; }
.fm-bubble {
  flex: none;
  background: #1B8A44; color: #fff; font-size: 12px; font-weight: 800;
  border-radius: var(--r-full); padding: 6px 12px;
  opacity: 0; transform: translateY(6px) scale(.9);
  transition: opacity .3s cubic-bezier(.21,1.02,.73,1), transform .3s cubic-bezier(.21,1.02,.73,1);
}
.fm-bubble.pop { opacity: 1; transform: translateY(0) scale(1); }

.fm-bar {
  height: 14px; border-radius: var(--r-full);
  background: var(--bg-soft); border: 1px solid var(--line); overflow: hidden;
}
.fm-fill {
  height: 100%; width: 0%; border-radius: var(--r-full);
  background: var(--grad);
  box-shadow: 0 0 14px rgba(124,111,240,.5);
  transition: width .5s cubic-bezier(.3,.9,.4,1);
}

.fm-miles { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 16px; }
.fm-mile {
  text-align: center; border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 12px 5px; transition: all .35s;
  filter: grayscale(1); opacity: .55;
}
.fm-mile .fm-emoji { display: block; font-size: 23px; margin-bottom: 4px; transition: transform .35s; }
.fm-mile b { display: block; font-size: 13.5px; }
.fm-mile span:not(.fm-emoji) { display: block; font-size: 10.5px; color: var(--ink-3); font-weight: 600; line-height: 1.25; }
.fm-mile.unlocked {
  filter: none; opacity: 1;
  border-color: rgba(124,111,240,.5); background: rgba(124,111,240,.07);
}
.fm-mile.unlocked .fm-emoji { transform: scale(1.22) rotate(-6deg); }

.fm-note { text-align: center; font-size: 12px; color: var(--ink-3); font-weight: 600; margin: 14px 0 0; }
.fm-note a { color: var(--lav-deep); font-weight: 800; }

/* The meter animates. Somebody who asked for less motion gets the finished
 * state instead of nothing — the milestones still read. */
@media (prefers-reduced-motion: reduce) {
  .fm-fill, .fm-mile, .fm-mile .fm-emoji, .fm-bubble { transition: none; }
}
@media (min-width: 861px) {
  .fm-box { padding: 28px 26px; }
  .fm-miles { gap: 12px; }
  .fm-mile span:not(.fm-emoji) { font-size: 11.5px; }
}

/* ══ the header must not read as a header ═══════════════════
 * User's instruction, and it is the right call for this page: the homepage now
 * opens on two decisions, and a slab of chrome above them is one more band of
 * the first screen spent on furniture.
 *
 * So on the homepage the nav has NO background, NO blur and NO border at any
 * scroll position — it is the page, with a wordmark and a menu button sitting
 * on it. `styles.css` adds a translucent white and a hairline on `.scrolled`;
 * both are overridden here rather than there, because every OTHER page still
 * wants a real header. Scoped to `.hm-home` on <body> so it cannot leak.
 *
 * `position: sticky` is kept: the menu button still has to be reachable
 * without scrolling back to the top. */
.hm-home .nav,
.hm-home .nav.scrolled {
  background: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  border-bottom-color: transparent;
  box-shadow: none;
}

/* Air between the sentence and the first decision.
 * At 16px the two ran together and the cards read as part of the paragraph. */
.hm-home .hero .lead { margin-bottom: 30px; }
@media (min-width: 861px) { .hm-home .hero .lead { margin-bottom: 36px; } }

/* ══ the posting cards inside the hero column ═══════════════
 * Two-up is right when the cards own the full width (phone, and tablet before
 * the hero splits). Once `.hero-grid` puts them in the left column beside the
 * phones, that column is ~40% of the viewport and two-up squeezes each card to
 * about 240px — the description breaks to five ragged lines and the pair reads
 * as cramped. Stack them there instead: the column is tall, and stacked cards
 * line up with the phones beside them.
 *
 * 980px is `.hero-grid`'s own breakpoint in styles.css, so this flips at
 * exactly the moment the layout becomes two columns. */
/* Side by side on desktop, not stacked.
 *
 * Two rows of card cost a whole card's height for nothing once the cards
 * became short. They only fit side by side because the copy column was widened
 * below — at `styles.css`'s own 1fr / 1.22fr split each card fell to ~240px,
 * which is what forced the stack in the first place. */
@media (min-width: 980px) {
  .hero-copy .hm-pick { grid-template-columns: 1fr 1fr; gap: 12px; }
  .hero-copy .hm-card { padding: 16px 16px 14px; }
}

/* A wider copy column, so two cards fit beside each other without cramping.
 * `styles.css` gives the phones the larger share (1fr / 1.22fr); on this page
 * the decisions matter more than the artwork, so the ratio flips. */
@media (min-width: 980px) {
  .hm-home .hero-grid { grid-template-columns: 1.25fr 1fr; }
}

/* The phones are a desktop flourish. On a phone the two posting cards are what
 * has to be above the fold, and a picture of a phone shown on a phone pushes
 * them under it. */
@media (max-width: 979px) {
  .hm-home .hero-visual { display: none; }
  .hm-home .hero-grid { grid-template-columns: 1fr; }
}

/* ══ THE HEADER'S "OUTLINE" WAS NEVER A BORDER ══════════════
 *
 * Reported three times, and each time the nav was already fully transparent —
 * background `rgba(0,0,0,0)`, border-bottom-width `0px`, no shadow, verified by
 * computed style with `.scrolled` forced on. The line was real; it just was not
 * the nav.
 *
 * It was a COLOUR CHANGE. `.hero` begins immediately below the sticky nav, and
 * its lavender blob wash (`.hero-bg`) is clipped to it — so the page was plain
 * white for the header's 68px and then tinted from y=68 down. That edge reads
 * as a hairline under the header, and no amount of removing borders from the
 * nav could touch it.
 *
 * The fix is the structure Pollos uses: the header sits ON the hero rather than
 * above it. Pull the hero up by the nav's height and give the padding back, so
 * the wash paints behind the header and the content lands exactly where it did.
 * One continuous background from the top of the page — nothing to see at the
 * seam because there is no seam.
 *
 * `--nav-h` is styles.css's own token, so this stays correct if the header
 * height ever changes. */
.hm-home .hero {
  margin-top: calc(-1 * var(--nav-h));
  padding-top: calc(76px + var(--nav-h));
}
@media (max-width: 980px) {
  /* styles.css shortens the hero's padding on small screens; match it so the
     copy does not gain a gap the desktop layout never had. */
  .hm-home .hero { padding-top: calc(22px + var(--nav-h)); }
}


/* ══ desktop: the phones must be whole on first paint ═══════
 * `.hero-grid` centres its columns, so against a tall copy column the phones
 * drifted down far enough that the bottom of them sat under the fold on an
 * 800px-tall laptop. Pin the visual to the top of the grid and lift it, so the
 * whole device shot is above the fold on load — which is the only moment it
 * has to do its job. */
@media (min-width: 980px) {
  .hm-home .hero-grid { align-items: start; }
  .hm-home .hero-visual { margin-top: -18px; }
  .hm-home .hero-phones { max-width: 620px; }
  /* Less top padding than styles.css's 76px: the header is transparent now, so
     the copy no longer needs to clear a solid bar. */
  .hm-home .hero { padding-top: calc(30px + var(--nav-h)); }
}

/* ══ section rhythm ═════════════════════════════════════════
 * One spacing scale for every band, so the page has a beat instead of
 * whatever each section happened to be given. */
.hm-sec { padding: 30px 0; }
@media (min-width: 861px) {
  .hm-sec { padding: 44px 0; }
  .hm-trust { grid-template-columns: repeat(3, 1fr); gap: 16px; }
  .hm-tr { padding: 22px 22px 20px; }
}
@media (min-width: 620px) and (max-width: 860px) {
  .hm-trust { grid-template-columns: repeat(3, 1fr); gap: 12px; }
}

/* The headline is sized for the COLUMN it lives in, not the viewport.
 *
 * `styles.css` clamps `.h1` up to 68px, which was tuned for a hero whose copy
 * had the page to itself. Here it shares the row with the phones, so it wraps
 * to three lines at ~72px each and pushed the second posting card 16px under
 * the fold on a 1280x800 laptop — the exact laptop most people open this on.
 * Smaller here, and everything above the fold stays above it. */
@media (min-width: 980px) {
  .hm-home .hero h1 { font-size: clamp(34px, 3.6vw, 52px); line-height: 1.06; }
  .hm-home .hero .lead { font-size: 16px; margin-bottom: 26px; }
  .hm-home .trust-pill { margin-bottom: 14px; }
}

/* ══ one continuous surface from the status bar down ════════
 * The hero's tint is blurred blobs painted over the body, and the body was
 * white — so on a phone the strip behind the status bar took white while the
 * page beneath it read lavender, and the two met in a hard line above the
 * header. `theme-color` in the <head> fixes the strip itself; this fixes the
 * page, so the wash starts at the very first pixel and fades to white by the
 * time the content sections begin.
 *
 * `background-color` under the gradient stays white: the gradient is sized in
 * viewport units and everything past it — categories, feed, footer — must be
 * white, not the tail of a wash. */
.hm-home {
  background-color: var(--bg);
  background-image: linear-gradient(
    180deg,
    #EDEAFB 0,
    #F3F1FD 34vh,
    var(--bg) 74vh
  );
  background-repeat: no-repeat;
}

/* ══ card titles are ONE line ═══════════════════════════════
 * They were hard-wrapped with a <br>, which cost a whole line of height on the
 * screen where vertical space is scarcest, and made two short titles look like
 * two-line paragraphs. The <br> is gone; this keeps them on one line at any
 * width by letting the type shrink a little rather than wrap. */
.hm-card-t {
  display: block;
  white-space: nowrap;
  font-size: clamp(15px, 4.4vw, 18px);
}
@media (min-width: 420px) { .hm-card-t { font-size: 18px; } }
@media (min-width: 620px) and (max-width: 979px) {
  /* Two cards share the row here, so each title has half the width. */
  .hm-card-t { font-size: clamp(13.5px, 2.5vw, 17px); }
}

/* ══ the route line's start pin ═════════════════════════════
 * `#scroll-path` already sits at `z-index: -1`, so the pin is genuinely BEHIND
 * the trust pill — it was never an ordering problem. It simply starts higher
 * than the pill's top edge, so the top of the marker showed in the gap above
 * it and read as a stray dot.
 *
 * Hidden on the homepage rather than nudged: the line emerging from behind the
 * pill looks deliberate, and moving the start point would need re-deriving it
 * from the hero's height on every resize for a marker nobody needs. The END
 * pin — the "Arrived" one that pays the journey off — is untouched. */
/* MOBILE ONLY. On desktop the pin is wanted and looks right — the hero is
 * wide there, so the trust pill sits well clear of it. It is only on a phone
 * that the pill lands on the pin and clips its top into a stray dot, and the
 * fix should not cost the desktop a piece of the journey artwork. */
@media (max-width: 979px) {
  .hm-home .sp-start { display: none; }
}

/* Both posting cards are the same height — via the GRID, not by clipping.
 *
 * First attempt forced the chips onto one row with `nowrap` + `overflow:
 * hidden`. That equalised the cards and silently cut "Yard work" and "Tutor"
 * in half at 320px, which is worse than the problem it solved: a truncated
 * example is a worse example than none.
 *
 * `grid-auto-rows: 1fr` makes every row the height of the tallest, so the two
 * cards match at any width while the chips wrap freely and nothing is ever
 * cut. It also holds if the lists change length later. */
.hm-pick { grid-auto-rows: 1fr; }


/* ══ the card's text block ══════════════════════════════════
 * Icon on the left, title and its one-line example list stacked beside it.
 * `min-width: 0` on the text column is what lets the subtext ellipsis instead
 * of forcing the card wider than its grid track — without it a flex child
 * refuses to shrink below its content. */
.hm-card-txt { min-width: 0; display: block; }
.hm-card-sub {
  display: block;
  margin-top: 2px;
  font-size: 12.5px;
  line-height: 1.35;
  font-weight: 500;
  color: var(--ink-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}


@media (min-width: 980px) {
  /* Half a column each, so the examples get the least room here. */
  .hero-copy .hm-card-t { font-size: 15.5px; }
  .hero-copy .hm-card-sub { font-size: 11.5px; }
  .hero-copy .hm-card-ico { width: 36px; height: 36px; font-size: 18px; }
}

/* ══ the posting cards read left on mobile ══════════════════
 * `styles.css` centres the whole hero below 920px (`.hero-grid { text-align:
 * center }`), which is right for the headline and the lead — but the cards
 * inherit it, and a centred title sitting beside a left-aligned icon reads as
 * misaligned rather than as centred. The icon anchors the row on the left, so
 * the words have to start there too.
 *
 * Only the cards are changed. The headline and the lead stay centred, which is
 * the deliberate choice in styles.css and looks right on a phone. */
@media (max-width: 979px) {
  .hm-home .hm-card { text-align: left; }
  .hm-home .hm-card-top { justify-content: flex-start; }
}


/* ══ one row per card ═══════════════════════════════════════
 * Icon, then the title with its examples underneath, then the arrow pushed to
 * the far right. The arrow used to sit on its own "Start →" row below, which
 * cost a whole line of height per card for a word the card already implies —
 * the entire card is the link.
 *
 * The arrow is `aria-hidden`: it is decoration, and the link already reads as
 * its title and subtext to a screen reader. */
.hm-card-top {
  display: flex;
  align-items: center;
  gap: 13px;
  margin-bottom: 0;
}
.hm-card-go {
  flex: none;
  margin-left: auto;
  display: grid;
  place-items: center;
  width: 30px; height: 30px;
  border-radius: 50%;
  color: var(--lav-deep);
  background: rgba(124,111,240,.09);
  transition: background .16s ease, transform .16s ease;
}
.hm-card-go svg { width: 15px; height: 15px; }
@media (hover: hover) {
  .hm-card:hover .hm-card-go { background: rgba(124,111,240,.18); transform: translateX(2px); }
}

/* The card is now a single row, so its padding is what gives it presence. */
.hm-card { padding: 15px 16px; }
@media (min-width: 980px) {
  .hero-copy .hm-card { padding: 14px 14px; }
  .hero-copy .hm-card-go { width: 26px; height: 26px; }
  .hero-copy .hm-card-go svg { width: 13px; height: 13px; }
}

/* ══ the safe area blends, the way Pollos does ══════════════
 * The status-bar strip takes `theme-color` (#EDEAFB) as a FLAT colour, but the
 * page under it was that colour PLUS the hero blobs — `blur(70px)` circles
 * sitting at `top: -180px`, bleeding down over the first hundred pixels. So the
 * strip read lighter than the page and the two met in a visible line.
 *
 * Pushing the blob layer below the header band makes the top of the page
 * exactly `#EDEAFB` — the same value the strip is painted with — so there is
 * nothing to see at the join. The blobs are blurred by 70px and start 150px
 * down, far enough that none of it reaches the top.
 *
 * Phone only: there is no status bar on desktop, and the blob placement there
 * is already right. */
@media (max-width: 979px) {
  /* MASK, not an offset.
   *
   * Pushing `.hero-bg` down did not work: `.hero-blob.b1` carries its own
   * `top: -180px`, so it climbed straight back over the top of the page. And
   * clipping the layer would just move the seam to wherever the clip is.
   *
   * Fading the whole blob layer in gives a flat top band with no edge
   * anywhere: nothing paints above 120px, so those pixels are exactly the
   * gradient's `#EDEAFB` — the same value `theme-color` puts behind the status
   * bar — and the blobs ramp up over the next 140px. */
  .hm-home .hero-bg {
    -webkit-mask-image: linear-gradient(180deg, transparent 0, transparent 120px, #000 260px);
    mask-image: linear-gradient(180deg, transparent 0, transparent 120px, #000 260px);
  }
  .hm-home {
    background-image: linear-gradient(
      180deg,
      #EDEAFB 0,
      #EDEAFB 120px,
      #F1EFFC 40vh,
      var(--bg) 76vh
    );
  }
}

/* Give the examples the room the arrow took.
 *
 * Moving the arrow onto the row cost the subtext about 40px and both lines
 * started ellipsising — "Moving, cleaning, tutoring, yard w…", which is worse
 * than no examples at all. Tightening the icon, the gap and the arrow buys the
 * text back without adding height. */
.hm-card-ico { width: 40px; height: 40px; font-size: 19px; }
.hm-card-top { gap: 11px; }
.hm-card-go { width: 28px; height: 28px; }
.hm-card-sub { font-size: 12px; }
.hm-card { padding: 14px 14px; }

/* The narrowest phones shrink rather than truncate.
 *
 * At 320px the card's text column is ~163px, and the example lists want ~214px
 * — so they ellipsised into "Moving, cleaning, tutoring, yard w…", which reads
 * as broken rather than as abbreviated. Shrinking the furniture buys the words
 * back. Ellipsis stays as the last resort below this, which is a graceful
 * degradation rather than a layout failure. */
@media (max-width: 360px) {
  .hm-card { padding: 12px 12px; }
  .hm-card-ico { width: 34px; height: 34px; font-size: 16px; }
  .hm-card-top { gap: 9px; }
  .hm-card-go { width: 24px; height: 24px; }
  .hm-card-go svg { width: 12px; height: 12px; }
  .hm-card-t { font-size: clamp(14px, 4.2vw, 16px); }
  .hm-card-sub { font-size: 10.8px; }
}
