/* =========================================================================
   ClearHarbor — Download / CTA page (Pages/Download.cshtml, route "/download")
   Full-bleed pass, reverted back to the base it shares with ComingSoon after
   Andrew rejected two intermediate layouts:
     - a contained card that boxed the CTA cluster in a dark panel, and
     - a split layout that confined the watercolour to its own right-hand
       panel.
   Both cropped the art down to a fraction of the frame; the full-bleed hero
   is the brand, so this page goes back to reusing coming-soon.css's shell
   (.coming-soon-shell/.hero/.hero-media-stack/.hero-chrome/.hero-spacer/
   .hero-copy) verbatim, same as ComingSoon.cshtml does — nothing in this file
   duplicates or overrides those rules except the deliberate exceptions below
   (anti-zoom fix, the hero-media grade, the flat CTA cluster). Buttons/
   eyebrow/.disabled-link still come from site.css. Built against the live
   maritime palette in tokens.css
   (--bg/--panel/--ink/--text/--muted/--accent/--cta-bg/--cta-ink).

   Art direction, second pass (Andrew's call after reviewing the LIGHT-glass
   lockup): "getting closer — not sure about the container there. Make the
   text a bit bigger and LOSE THE CONTAINERS and keep everything else." Even
   the light, translucent glass card read as a distinct object sitting on
   the water, especially in dark mode. This is the Craft "no container,
   restraint carries it" treatment — the CTA cluster (button, spec lines,
   trust line, disclosure) now sits DIRECTLY on the graded painting, exactly
   the way the headline/subhead already did. .download-panel keeps its class
   NAME (download.js reads it to add .os-match-windows/.os-match-mac) but no
   longer paints a surface — it's a bare flex layout wrapper now, nothing
   else. The historical glass-lockup rationale (light-vs-dark alpha, pinned
   descendant tokens, the backdrop-filter fallback ladder) is gone with it;
   see git history if that reasoning is ever needed again.

   THE PROBLEM THIS FILE NOW SOLVES: without a panel behind it, the
   secondary CTA-cluster text loses the surface it depended on for contrast.
   Held with non-container means only, in priority order:
     a. Size — every secondary line is bumped one step up the type scale.
        Still well under the 24px/18.66px-bold "large text" threshold
        though, so this alone never earns the lighter 3:1 AA bar — sizes
        below are still held to 4.5:1.
     b. A whisper of text-shadow on the whole cluster (Shadeed's technique,
        already used by coming-soon.css's own .hero-eyebrow) — a lift, not
        a visible effect. Themed per hero for the same reason the grade and
        the scrim are.
     c. Secondary text recoloured from --muted to --text. Measured (Pillow,
        real pixels of hero-light.webp/hero-dark.webp, mean + darkest-5%
        patch over the CTA-cluster's footprint, x:2-34%/y:62-94%,
        composited against coming-soon.css's own scrim wash — which already
        reaches this deep into .hero-copy, see the scrim comment below):
        light theme --muted clears only 3.09:1 mean / 2.82:1 darkest —
        short of the 4.5:1 small text needs. --text on the same composite
        clears 5.19:1 / 4.73:1. Dark theme clears either way (--muted
        5.66:1 / 5.73:1, --text 10.79:1 / 10.93:1) but is set to --text too,
        for one rule instead of a per-theme split, and because it only
        widens the dark-theme margin further.
     d. Not needed. (c) alone closes every gap measured — no extra wash
        beyond coming-soon.css's existing scrim was required. If a future
        copy change reopens a gap, add a wash scoped to ".download-shell"
        before reaching for a visible box — see the file-level doctrine
        note on this repo about not quietly re-litigating a settled call.

   Art direction, third pass (Andrew's call after reviewing the no-container
   version above: "this is good," then two refinements): (1) the old
   .download-actions two-column row left the macOS line stranded off to the
   button's right with no visible relationship to it — collapsed into ONE
   left-aligned vertical stack (.download-cta-group/.download-primary/
   .download-secondary below), the macOS line shrunk one type-scale step
   so it reads as clearly subordinate to the Windows unit above it, not a
   competing column; (2) the whole block was bottom-anchored and read
   bottom-heavy — raised toward vertical centre via a second .hero-spacer
   (see the vertical-position rule near the end of this file).

   Both changes move and reshape the CTA cluster's footprint, which is
   exactly the footprint the AA math above (b/c) was measured against — so
   it was RE-verified rather than assumed to still hold (Playwright, real
   rendered boxes with text painted transparent so only the composited
   backdrop — image + grade filter + scrim, all real browser output, no
   manual approximation — gets sampled; mean + darkest-5% per line, both
   themes, 9 viewports from 375x667 to 1920x1080 incl. the 150%-DPI case
   Andrew reviews at). It holds: dark theme stays far clear (~10.7-11.2:1
   everywhere); light theme's worst case across the whole matrix is the
   disclosure summary at 1366x768, 4.61:1 darkest-5% — still over the
   4.5:1 small-text floor, just a tighter margin than before now that this
   line sits lower in a taller stack. No further wash was needed to close
   that; if a future pass tightens it further, that's the line to re-check
   first.

   THE BUTTON: same composited backdrop, no override needed. --cta-bg/
   --cta-ink are left to cascade from tokens.css exactly as everywhere else
   on the site — no light-literal pinning. That turns out to be the right
   pairing by construction: light theme's navy fill sits on light theme's
   (bright) painting, dark theme's cream fill sits on dark theme's (near-
   black) painting — each theme's button is already the high-contrast
   partner for that theme's own art. Measured (Pillow, same footprint/scrim
   composite as above): light navy-on-light-art 8.27:1 mean / 7.54:1
   darkest; dark cream-on-dark-art 13.66:1 mean / 13.83:1 darkest. Both
   clear the 3:1 non-text/UI-component floor with a wide margin — no ring,
   no extra shadow, no per-theme override required.

   UNDO: delete this file, its <link> in Download.cshtml, and
   Download.cshtml(.cs) + Options/DownloadOptions.cs — then remove the
   "/download" exemption and Configure<DownloadOptions> call in Program.cs.
   ========================================================================= */

/* ---- Anti-zoom: pin the art to the viewport, not to .hero's box -----------
   ComingSoon never needs this: its .hero-copy content is fixed, so .hero's
   min-height floor (coming-soon.css fix-9) never actually grows past one
   screen. This page has a <details> disclosure that can — and
   .hero-media-stack is position:absolute; inset:0 (coming-soon.css), so its
   box tracks whatever height .hero resolves to. If .hero grew when the
   disclosure opened, the art's box would grow with it and
   background-size:cover would re-fit ("zoom") to the new, taller box — the
   exact defect that sank the split layout in the first place, just
   reintroduced a different way.

   Scoped to ".download-shell" (added only in Download.cshtml) instead of
   touching coming-soon.css's own ".hero-media-stack" rule, so ComingSoon's
   behaviour is untouched. position:fixed removes the layer from the
   .hero/.coming-soon-shell flow entirely — inset:0 now means "the viewport",
   full stop, independent of how tall the content column above it gets. If
   the disclosure's content pushes the page taller than one screen, the PAGE
   scrolls over this pinned background; the background itself never resizes. */
.download-shell .hero-media-stack {
  position: fixed;
}

/* ---- Grade ------------------------------------------------------------------
   "Calibrated art, not raw stock" (research direction: Superhuman/Craft grade
   their photography rather than run it flat). A gentle warm/desaturated
   push, CSS-only and fully reversible — the .webp source files are untouched,
   delete this rule and the raw paintings come back exactly as shipped.

   Scoped to ".download-shell .hero-media" (not coming-soon.css's own
   ".hero-media") so ComingSoon's teaser is completely unaffected.

   Kept deliberately small — checked against both extremes of both source
   paintings (Pillow, actual pixels) so it nudges tone without crushing or
   muddying either:
     - sepia(0.06): at this amount the near-black water in hero-dark.webp
       (rgb ~20,30,37) only drifts to ~21,30,36 — a whisper of warmth, not
       the brown-black "muddy" shift a heavier sepia() would cause (full
       sepia pulls that same navy toward rgb ~38,34,26, a hue flip, which is
       exactly the "muddy" failure mode the brief warned about).
     - saturate(0.92) + contrast(1.04) + brightness(1.01): trims a touch of
       raw-stock vibrancy and lifts a hair of density without crushing the
       dark hero's blacks (checked: 20 -> ~16, imperceptible) or blowing out
       the light hero's sky (240 -> ~239, imperceptible).
   Same filter for both themes on purpose — the math above holds for both
   paintings' extremes, so one grade serves both rather than needing a
   per-theme split (unlike the CTA-cluster text-shadow below, which does
   need one). */
.download-shell .hero-media {
  filter: sepia(0.06) saturate(0.92) contrast(1.04) brightness(1.01);
}

/* ---- Type: whispered, not shouty --------------------------------------------
   "Type stays restrained so the image carries the emotion" (Superhuman).
   coming-soon.css's shared .hero-heading is already medium (500), not bold —
   eased one step further to regular (400) on this page only. Spectral reads
   the moment at any weight (it's the serif shift, not the boldness, doing
   the "considered" work) so dropping to 400 doesn't cost legibility, only
   loudness. Scoped to ".download-shell" so ComingSoon's own heading is
   untouched — revert by deleting this one rule if Andrew wants 500 back. */
.download-shell .hero-heading {
  font-weight: 400;
}

/* Subhead — nudged one small step up from coming-soon.css's shared --fs-lg
   now that the CTA cluster below it reads noticeably larger (see the
   cluster type-scale bumps further down); keeps the column's proportions
   reading like one considered whole instead of a big subhead sitting above
   suddenly-bigger secondary text. Deliberately small — the headline is
   still the one loud element on the page. Scoped to ".download-shell" only,
   same pattern as the heading-weight override above; ComingSoon's own
   subhead is untouched. */
.download-shell .hero-subhead {
  font-size: 1.12rem;
}

/* ---- CTA cluster: flat text on the painting, no lockup -----------------------
   .download-panel is now a bare layout wrapper — display/gap/max-width only.
   No background, no backdrop-filter, no border, no radius, no shadow, no
   padding, no pinned descendant tokens. The class name stays because
   download.js still selects it to toggle .os-match-windows/.os-match-mac;
   there is nothing left for those rules to style *on* this element itself
   any more (see .os-match-windows below, which now only touches the button). */
.download-panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  max-width: 36rem;
  /* .hero-subhead's own bottom margin is deliberately small (coming-soon.css
     ramps it down at short viewports); make up the difference here instead
     of touching that shared rule, so the cluster doesn't crowd the subhead
     above it now that there's no card edge to imply the gap on its own. */
  margin-top: var(--space-6);
}

/* Whisper lift — Shadeed's technique, same move coming-soon.css's own
   .hero-eyebrow already uses: low-alpha, short-blur text-shadow that reads
   as the type sitting a hair off the paper, not as a drawn effect. Applied
   to the whole cluster (inherits to every descendant that doesn't set its
   own text-shadow) rather than repeated per element. Alpha/colour flip per
   theme, same reasoning as the grade/scrim above — light art needs a dark
   whisper, dark art needs a light one, one static value can't serve both. */
.download-panel {
  text-shadow: 0 1px 2px rgb(14 26 31 / 0.22), 0 1px 5px rgb(14 26 31 / 0.12);
}
:root[data-theme="dark"] .download-panel {
  text-shadow: 0 1px 2px rgb(0 0 0 / 0.32), 0 1px 6px rgb(0 0 0 / 0.22);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .download-panel {
    text-shadow: 0 1px 2px rgb(0 0 0 / 0.32), 0 1px 6px rgb(0 0 0 / 0.22);
  }
}

/* Responsive — the cluster stays full flow width and tightens its own gap
   as the viewport narrows; the art stays full-bleed and pinned behind it the
   whole time (.download-shell .hero-media-stack above), so there's never a
   moment where the cluster and the art disagree about how much room either
   gets. Boats stay in frame at portrait widths via coming-soon.css's own
   fix-10 (background-position-x), inherited unchanged. */
@media (max-width: 768px) {
  .download-panel {
    max-width: none;
  }
}
@media (max-width: 480px) {
  .download-panel {
    gap: var(--space-4);
  }
}

/* CTA stack — ONE left-aligned vertical column (Andrew's regroup call: the
   old .download-actions row laid the Windows button and the macOS line out
   as two side-by-side flex columns, so the macOS note read as orphaned —
   stranded off to the right of the button with a gap and no visible
   relationship to it). .download-cta-group holds the two units — Windows
   primary, macOS secondary — at a TIGHTER gap than .download-panel's own
   outer gap (the space between this whole group / the trust line / the
   disclosure below, still var(--space-5)), so the pairing itself reads as
   one grouped cluster: "here's the main download, and here's the other
   platform coming" — not three evenly-spaced strangers down the page. */
.download-cta-group {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3);
}

.download-primary,
.download-secondary {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
}

/* .primary-button defaults to width:100% (site.css; designed for a
   single-column form context elsewhere) — reset to auto so it doesn't claim
   the full column width now that it's stacked above the (flat-text) macOS
   line instead of sitting in a row beside it. Full-width again under 480px
   — see the responsive block below — for a bigger mobile tap target. */
.download-primary .primary-button {
  width: auto;
  min-width: 15rem;
}
.download-primary .primary-button svg {
  width: 1.15em;
  height: 1.15em;
  flex-shrink: 0;
}

/* Disabled buttons render as non-interactive <span> elements, not <a>/<button>
   — .disabled-link already zeroes pointer-events/opacity (site.css); this
   only adds the cursor affordance so it doesn't look draggable/selectable. */
.download-primary .disabled-link {
  cursor: not-allowed;
}

@media (max-width: 480px) {
  .download-primary .primary-button {
    width: 100%;
    min-width: 0;
  }
}

/* Spec microlines (version/size/platform, "Apple Silicon & Intel") — bumped
   one step off --fs-xs now that they sit directly on the art instead of on
   the glass card. Colour is --text, not --muted — see the file-header
   contrast note (c): --muted measured short of 4.5:1 against this
   footprint in light theme, --text clears it in both. */
.download-meta {
  font-size: var(--fs-sm);
  color: var(--text);
  padding-left: var(--space-1);
  font-variant-numeric: tabular-nums;
}

/* Trust line — the ONE trust sentence the hero budget allows (research
   direction: a sentence near the button, not a badge wall). Bumped to
   --fs-base — one step above the spec microlines, same relative hierarchy
   the glass-panel version had (still the one secondary line meant to
   actually be read), just resized now that nothing but the art sits under
   either of them. */
.download-trust {
  font-size: var(--fs-base);
  color: var(--text);
  padding-left: 0;
}

/* macOS — honest "not ready" as a flat text line instead of a disabled
   button shape (the button-shaped-but-inert control was itself one of the
   "little containers" Andrew flagged — it doesn't need to look clickable
   to say "not yet"). No fill, no pill, no border: just a label.
   Deliberately ONE step down from the --fs-base it used to hold — now that
   this line sits beneath the Windows unit instead of beside it in its own
   column, it no longer needs to "hold its own" at button-adjacent size; it
   reads as a quieter, subordinate line, same type-scale as its own
   .download-meta caption below it. Still --text, not --muted, and still
   600-weight to keep it reading as a label rather than body copy — size is
   doing the de-emphasis here, not colour (colour is pinned by the AA floor,
   see file-header note c). Non-interactive underneath — a <p>, not a
   <span role>-adjacent element — which is also the more honest a11y shape:
   the old markup gave a non-focusable span aria-disabled="true", implying a
   control that isn't actually one; flat text has no such implication to
   walk back. */
.download-secondary-status {
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  margin: 0;
}
.download-secondary-status .status-dot {
  /* --text, not --muted — measured 2.82-3.09:1 on --muted against the light
     hero's composited footprint (Pillow, real pixels), short of AA. It's one
     glyph, but it's still text in the accessibility tree, not a background
     decoration, so it gets the same treatment as the rest of the cluster. */
  color: var(--text);
  margin: 0 0.35em;
}
.download-secondary-status .status-pending {
  font-variant-caps: all-small-caps;
  letter-spacing: 0.02em;
  color: var(--text);
}

/* SmartScreen disclosure — closed by default, same summary/+−/details-content
   language as .advanced-disclosure (site.css) so the interaction is already
   familiar. Now a flat text toggle: no border-top divider, no box — the
   +/− glyph is the only affordance carrying "this expands," same as it
   always was; the divider was doing separation the section-gap (.download-panel's
   own `gap`) already does on its own — no replacement rule needed, the
   details element has no resting padding of its own to strip. */
.download-disclosure > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: var(--space-2);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
}
.download-disclosure > summary::-webkit-details-marker { display: none; }
.download-disclosure > summary::after {
  content: "+";
  flex: 0 0 auto;
  font-size: 1rem;
  line-height: 1;
  color: var(--text);
}
.download-disclosure[open] > summary::after { content: "\2212"; }
.download-disclosure > summary:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
  border-radius: var(--r-sm);
}
.download-disclosure .download-disclosure-body {
  margin-top: var(--space-2);
}
/* Plain-paragraph disclosure body — the itemisation collapsible (Section 10)
   reuses .download-disclosure-body as a wrapper around several <p>, unlike the
   single icon+text .download-note row the SmartScreen note uses above. Same
   type scale/colour as .download-note (--fs-sm / --text) so the two disclosure
   bodies read as one voice; own rule because a bare <p> here would otherwise
   fall back to the browser default rather than this page's own scale. */
.download-disclosure-body p {
  max-width: 52ch;
  font-size: var(--fs-sm);
  line-height: 1.55;
  color: var(--text);
  margin: 0 0 var(--space-2);
}
.download-disclosure-body p:last-child { margin-bottom: 0; }

/* Reassurance note — a quiet trust signal, not a warning. Icon + text reads
   as calm secondary information (same pattern as .warning-callout in
   site.css) instead of a lone paragraph of fine print. Used as the
   disclosure body above. Bumped to --fs-sm and recoloured to --text for the
   same reason as the rest of the cluster (file-header note c) — this line
   only appears when the disclosure is opened, but it needs to hold AA the
   moment it does. */
.download-note {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  max-width: 48ch;
  font-size: var(--fs-sm);
  color: var(--text);
  margin: 0;
}
.download-note svg {
  flex: 0 0 auto;
  width: 1em;
  height: 1em;
  margin-top: 0.15em;
}
.download-note strong { color: var(--ink); font-weight: 600; }

/* OS-detection nicety (wwwroot/js/download.js) — visually nudges the button
   matching the visitor's platform. Never changes which buttons render or
   whether they're clickable; a blocked/failed script just leaves both
   buttons in their default, fully-usable state. Only Windows has a live
   button today — the macOS slot is flat text now, not a button, so no
   os-match-mac rule exists (nothing there to ring); add one alongside the
   real Mac link/button when that build lands. */
.os-match-windows .download-primary .primary-button:not(.disabled-link) {
  box-shadow: 0 0 0 2px var(--accent-soft);
}

/* ---- Vertical position: raised, weighted center-left --------------------
   coming-soon.css's .hero is a flex column (.hero-chrome, then ONE
   .hero-spacer with flex:1 1 auto, then .hero-copy) — that single spacer
   eats 100% of whatever room .hero has left over, which is what pins
   .hero-copy to the floor of the frame. Fine for ComingSoon's short teaser
   line; bottom-heavy once this page's copy got bigger (Andrew's call).

   Fixed with a SECOND .hero-spacer, download-page-only, added as a sibling
   AFTER .hero-copy in Download.cshtml (untouched in ComingSoon.cshtml —
   that page still has exactly one spacer and stays bottom-anchored).
   coming-soon.css's own .hero-spacer rule already gives both spacers
   flex:1 1 auto — unmodified, not touched here — so with two of them the
   free space now splits between "above the copy" and "below the copy"
   instead of dumping 100% of it above. This modifier only changes the
   SPLIT: flex-grow:1.35 on the bottom spacer against the top spacer's
   inherited flex-grow:1 gives the bottom spacer ~57% of whatever free
   space is left over, vs. ~43% for the top one — nudging .hero-copy up
   from the floor toward centre, not shoving it to the top.

   How far that actually MOVES the block depends on how much free space
   there is to redistribute, which shrinks as the CTA stack got taller
   (Windows unit + macOS line now stacked, not side by side) — measured
   (Playwright, real rendered .hero-copy rect, .hero-copy's own vertical
   centre as % of viewport height, both themes — theme doesn't move the
   box, only paints it, so one set of numbers covers both):
     - 1440x900 / 1920x1080 / 1366x768 desktop-ish: 54.5% / 52.5% / 61.1%
       — i.e. essentially dead-centre, not upper-third; on the 768-tall
       laptop case the free-space pool is small enough (content already
       fills most of the frame) that the split barely has room to act,
       and the very last line (the disclosure) sits close enough to the
       bottom edge that a few px of page-scroll can appear depending on
       exact font metrics — same no-clipping trade the rest of .hero
       already makes (coming-soon.css fix-9), not a defect.
     - 820x1180 tablet: 51.5%. 390x844 / 480x800 mobile: 55.2% both.
     - 375x667 (short phone) / 844x390 (short landscape): content is
       taller than the viewport at these sizes regardless of the split —
       the page scrolls to reach the disclosure line, which is the
       correct outcome per the same no-clipping rule, not a bug in this
       ratio.
   Before this pass (single top-only spacer, shorter side-by-side CTA
   row) the block sat bottom-anchored around ~68% — this raises it into
   genuine center territory across the whole matrix, left-aligned by the
   column's own padding, exactly the "vertical center-left, well-weighted"
   position Andrew asked for, without needing a more aggressive ratio.

   Both spacers still carry coming-soon.css's own min-height guard
   (min(2dvh, 10px) under @supports), so on a very short viewport neither
   one can collapse to zero and let the raised block collide with
   .hero-chrome above it — worst case the page scrolls, same no-clipping
   rule as above. Same ratio at every width on purpose: it's proportional
   to whatever room is actually free, so it degrades gracefully on both
   narrow and short viewports without a separate breakpoint. */
.download-shell .hero-spacer-bottom {
  flex-grow: 1.35;
}
