/* /hub - the RIPPLES Hub download page.
   Page-scoped, so nocturne.css does not need a cache-buster bump across
   50-odd pages for a single new page. */

.hub-head { padding-bottom: clamp(18px, 3vw, 34px); border-bottom: none; }

.hub-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(24px, 4vw, 56px);
  align-items: center;
}
.hub-hero-text .kicker { margin-bottom: 10px; }
.hub-hero-text h1 { margin: 0 0 14px; }
.hub-hero-text .lede { max-width: 34rem; margin: 0 0 clamp(20px, 3vw, 28px); }

/* ---- download buttons ----
   Mac and Windows are equal twins (Aviv, 2026-08-12) - same face, same
   weight, the visitor's platform merely ordered first by js/hub.js. Both
   flex to the same width so neither reads as the afterthought. */

.hub-dl { display: flex; flex-wrap: wrap; gap: 12px; max-width: 620px; }

.hub-btn {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  flex: 1 1 240px;
  padding: 14px 22px 13px;
  line-height: 1.3;
}
.hub-btn-main {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
  font-size: 15px;
}
.hub-btn-main svg { width: 16px; height: 16px; flex: none; }
/* The Apple mark is the real logo, inlined - lucide's `apple` is a FRUIT
   (stem and two lobes), which at 16px just reads as a broken circle. It is a
   solid glyph sitting next to stroked lucide icons, so it needs to be a shade
   smaller and lifted a hair: a filled mark carries more optical weight than an
   outline at the same box, and the logo's bitten top sits high in its viewBox.

   The colour is ALSO set as a fill attribute on the svg itself, not only
   here. An svg with no fill defaults to BLACK, so if this sheet is ever
   missing or stale - a poisoned edge cache did exactly that on 2026-08-13 -
   the mark renders black on the brick button. The attribute makes the icon
   correct with no CSS at all; this rule still owns size and position. */
.hub-btn-main .icon-apple {
  width: 15px; height: 15px;
  fill: currentColor; stroke: none;
  position: relative; top: -1px;
}
/* Facts in the body face, not mono - a sentence set in monospace reads as a
   terminal, and this is a shop front. */
.hub-btn-sub {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.82);
}

/* Waiting state: the build is not published yet, so the button must not look
   like it will do something. Kept as an <a> so the layout never shifts when a
   real href arrives. */
.hub-btn.is-waiting {
  opacity: 0.5;
  pointer-events: none;
  cursor: default;
}

/* The three objections a first-time downloader actually has. Stacked one per
   row, NOT a wrapping flex row: three items of uneven width put two on the
   first line and orphaned the third on the second, which read as a mistake.
   The fixed icon column is what makes it scan as a list - it lines up all
   three text edges no matter how wide the icon glyph is. */
.hub-trust {
  list-style: none;
  margin: 20px 0 0;
  padding: 0;
  display: grid;
  gap: 10px;
}
.hub-trust li {
  display: grid;
  grid-template-columns: 16px 1fr;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--cream-dim);
}
/* Lucide REPLACES the <i data-lucide> with an <svg>, so an `i` selector never
   matches once the script has run - the icons were falling back to lucide's
   own 24px and overflowing the column. Target the svg. */
.hub-trust i,
.hub-trust svg { width: 16px; height: 16px; color: var(--accent-bright); opacity: .9; }

.hub-hero-shot {
  border: 1px solid var(--line);
  border-radius: 12px;
  overflow: hidden;
  background: var(--surface);
  box-shadow: 0 24px 60px -24px rgba(0, 0, 0, 0.8);
}
.hub-hero-shot img { width: 100%; height: auto; display: block; }

/* ---- steps ---- */

.hub-steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(18px, 3vw, 34px);
  margin-top: clamp(18px, 3vw, 30px);
}
.hub-step h3 { margin: 12px 0 7px; }
.hub-step p { margin: 0; color: var(--cream-dim); }
.hub-step-num {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--surface);
  font-family: "Bebas Neue", sans-serif;
  font-size: 1.3rem;
  color: var(--accent-bright);
}

/* ---- product shots ----
   Alternating copy/shot rows, the same rhythm as the Noodle page: the eye
   crosses the page instead of scrolling past four identical stacks. */

.hub-shots .wrap { display: flex; flex-direction: column; gap: clamp(44px, 5vw, 74px); }

.hub-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(24px, 4vw, 60px);
  align-items: center;
}
.hub-split.flip .hub-split-copy { order: 2; }

.hub-split-copy .kicker { margin-bottom: 10px; }
/* These are section headlines, so they take the site's h2 scale rather than
   the smaller h3 default - they sit next to a full-height screenshot and were
   reading as captions. Body matches .lede for the same reason. */
.hub-split-copy h3 {
  font-size: clamp(2rem, 3.8vw, 3.2rem);
  line-height: 1.1;
  margin: 0 0 18px;
  max-width: 22ch;
  text-wrap: balance;
}
.hub-split-copy p {
  margin: 0;
  color: var(--cream-dim);
  max-width: 40ch;
  font-size: clamp(1.05rem, 1.5vw, 1.3rem);
  line-height: 1.62;
}

/* The shots are zoomed crops of the interface, not whole windows - a whole
   window shrunk into half a column makes its own text unreadable, which is
   what these sections are trying to show. Each one bleeds past the wrap on its
   outer edge so it reads as a window onto something larger. */
.hub-split-shot { margin: 0; }

/* The splits show REGIONS of the interface at near-full scale, so they get a
   plain frame with a faint top-light - the mac titlebar (traffic lights) is
   reserved for the hero, which is the one true whole window. A titlebar on a
   crop of the middle of a window would be claiming to be something it is not. */
.shot-frame {
  border: 1px solid var(--line);
  border-radius: 10px;
  overflow: hidden;
  background: var(--surface);
  box-shadow: 0 30px 64px -28px rgba(0, 0, 0, .9), inset 0 1px 0 rgba(241, 235, 222, .06);
}

/* The demos shot is the detail panel - a tall column, not a wide region. Let
   it stand at readable width instead of stretching to fill the half-column. */
.hub-split-shot.tall { display: flex; justify-content: center; }
.hub-split-shot.tall .shot-frame { max-width: min(400px, 100%); }
.shot-frame img,
.hub-split-shot img {
  width: 100%; height: auto; display: block;
  border: 0; border-radius: 0; box-shadow: none;
}
.shot-bar {
  display: flex; align-items: center; gap: 6px;
  padding: 9px 13px;
  background: linear-gradient(180deg, #1b1613, #14100f);
  border-bottom: 1px solid var(--line);
}
.shot-bar span {
  width: 9px; height: 9px; border-radius: 50%;
  background: #2f2723;
}

@media (min-width: 901px) {
  .hub-split { align-items: center; }
  /* copy left, shot right: bleed right. flip: shot left, bleed left. */
  .hub-split:not(.flip) .hub-split-shot { margin-right: calc(var(--pad) * -1); }
  .hub-split.flip .hub-split-shot { margin-left: calc(var(--pad) * -1); }
  .hub-split:not(.flip) .hub-split-copy { padding-right: clamp(8px, 1.5vw, 28px); }
  .hub-split.flip .hub-split-copy { padding-left: clamp(8px, 1.5vw, 28px); }
}

/* ---- at a glance ----
   The pre-download hesitation answered as facts, before the FAQ answers it as
   prose. Native Access does this as an "At a Glance" table and it reads as
   confidence. Values stay in the body face - mono is for keys, orders, prices
   and version strings, and "macOS 11 or newer" is none of those. */

.hub-specs {
  margin-top: clamp(14px, 2.5vw, 22px);
  max-width: 46rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  padding: 6px 20px;
}
.hub-spec {
  display: flex;
  gap: 18px;
  align-items: baseline;
  padding: 11px 0;
  font-size: 13.5px;
}
.hub-spec + .hub-spec { border-top: 1px solid var(--line); }
.hub-spec-k { flex: 0 0 9.5em; color: var(--cream-faint); }
.hub-spec-v { color: var(--cream-dim); }

/* ---- faq ---- */

.hub-faq { margin-top: clamp(18px, 3vw, 28px); max-width: 46rem; }
.hub-faq .win-setup { margin: 0 0 10px; }

/* ---- closing download ----
   Whoever read all the way through Keys and the FAQ is convinced or gone -
   convinced deserves the button here, not a newsletter form. Same manifest
   contract as the hero: js/hub.js arms every .js-dl-primary identically. */

.hub-close-inner { text-align: center; }
.hub-close-inner .kicker.center { display: inline-block; }
.hub-close-inner h2 { margin: 0 0 clamp(20px, 3vw, 28px); }
.hub-dl-center { justify-content: center; margin-left: auto; margin-right: auto; }
.hub-close-note {
  margin: 16px 0 0;
  font-size: 12.5px;
  color: var(--cream-faint);
}

/* ---- phone ----
   Two-column grids collapse explicitly. The .pillars.cols2 bug on /sync-music
   came from assuming a grid would wrap on its own; it does not. */

@media (max-width: 900px) {
  .hub-split { grid-template-columns: 1fr; gap: 20px; }
  .hub-split.flip .hub-split-copy { order: 0; }
  .hub-hero { grid-template-columns: 1fr; }
  .hub-hero-shot { order: -1; }
  .hub-steps { grid-template-columns: 1fr; gap: 22px; }
}

@media (max-width: 560px) {
  .hub-dl { flex-direction: column; align-items: stretch; }
  .shot-bar { padding: 7px 10px; }
  .shot-bar span { width: 7px; height: 7px; }
  .hub-btn { width: 100%; align-items: center; }
  .shot-frame { border-radius: 8px; }
}
