/* ============================================================================
   NIMBUS MARKETING SITE
   Depends on tokens.css. Never hardcode a colour here that is not a token.
   Shape rule in force: buttons/chips = pill, cards = --r-lg, panels = --r-xl.
   ========================================================================== */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
/* The decorative clouds and the preview's edge chips deliberately overhang the
   viewport. body{overflow-x:hidden} stops a desktop scrollbar but not iOS Safari's
   sideways pan, so the root clips too (clip, not hidden: it makes no scroll
   container and so cannot break position:fixed or sticky). */
html { overflow-x: clip; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--canvas);
  color: var(--body);
  font: var(--t-body);
  letter-spacing: var(--tracking-tight);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

h1, h2, h3, h4 { color: var(--ink); margin: 0; letter-spacing: var(--tracking-display); }
p { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }
img, svg { max-width: 100%; }

/* A class rule that sets `display` beats the user-agent's
   `[hidden] { display: none }`, because a class outranks a bare attribute
   selector. An element toggled with `el.hidden = true` then stays on screen
   with the attribute silently set, which is exactly how the download list
   shipped expanded. One global rule costs nothing and closes the whole class
   of bug. */
[hidden] { display: none !important; }

/* Fail closed. A [data-when] block exists to say something only a particular
   deployment can truthfully say. entity.js decides which, and adds
   .entity-ready when it has. Without scripting nobody decides, and showing every
   variant at once published "Free for one person" and "Free, and finished" and a
   price next to "takes no payments" on the same page. So nothing flag-gated is
   shown until a script has chosen. */
html:not(.entity-ready) [data-when] { display: none !important; }


:focus-visible {
  outline: 3px solid var(--brand-text);
  outline-offset: 3px;
}

/* On the photograph and on the nav over it, the accent has no contrast, so the
   outline is white (the surface is the same brightness in both themes). */
.nav-wrap:not(.scrolled) :focus-visible { outline-color: #ffffff; }
/* ...except inside the open menu sheet, which is a light surface. */
.nav-wrap:not(.scrolled) .nav-sheet :focus-visible { outline-color: var(--brand-text); }

/* FOCUS IS AN OUTLINE, never a box-shadow. It was a 40% accent halo in a
   box-shadow, and two things broke it: a primary button's glow is also a
   box-shadow, declared on the same element, so it replaced the ring and the
   button showed NO focus at all; and a faint halo on a navy bar fails 3:1 anyway.
   An outline cannot be overridden by a shadow, and Windows High Contrast, which
   strips shadows, leaves it alone. forced-colors gets the system colour. */
@media (forced-colors: active) {
  :focus-visible { outline: 3px solid Highlight; outline-offset: 2px; }
}

/* The ring is brand-coloured, which all but disappears against the hero sky.
   Anything sitting on the photograph gets a white outline instead. */
.hero :focus-visible,
.download :focus-visible { outline: 2px solid #ffffff; outline-offset: 3px; }

.skip-link {
  position: absolute; left: var(--s-4); top: -100px;
  z-index: var(--z-toast);
  padding: var(--s-3) var(--s-5);
  background: var(--surface); color: var(--ink);
  border-radius: var(--r-pill); box-shadow: var(--e-3);
  font: var(--t-label);
  transition: top var(--d-fast) var(--ease-out);
}
.skip-link:focus { top: var(--s-4); }

.num { font-family: var(--font-sans); font-weight: 600; letter-spacing: -0.02em; font-variant-numeric: tabular-nums lining-nums; }

/* ---------------------------------------------------------------------------
   CLOUDSCAPE PRIMITIVES (phase 10.1b)
   The same objects the app is made of, so the page and the product read as one
   thing: a sky behind everything, cloud surfaces floating on it, one sunlit top
   edge, an icon tile, and numbers set in Outfit (never the mono, whose slashed
   zero reads as an error). Nothing here is a colour the tokens cannot derive.
   ------------------------------------------------------------------------ */
:root { --sunlit: inset 0 1px 0 var(--glass-inner); }

/* The page is the sky: a gentle vertical gradient from the pale top to a slightly
   deeper blue by the pricing section. The hero photograph dissolves into it.
   The depth is capped by text, not taste: --muted measures 4.8:1 on the palest
   end and loses AA on anything much bluer than this (it was 2.3:1 at 70%, 4.2:1 at 22%). */
body {
  background:
    linear-gradient(to bottom,
      var(--canvas) 0%,
      color-mix(in srgb, var(--sky-top) 8%, var(--canvas)) 62%,
      color-mix(in srgb, var(--sky-top) 14%, var(--canvas)) 100%);
}

.card {
  background: var(--cloud);
  border-radius: var(--r-lg);
  box-shadow: var(--sunlit), var(--e-2);
}
@media (hover: hover) {
  .card-lift { transition: transform var(--d-base) var(--ease-out), box-shadow var(--d-base) var(--ease-out); }
  .card-lift:hover { transform: translateY(-2px); box-shadow: var(--sunlit), var(--e-3); }
}

/* The icon tile: one glyph on a soft rounded square. */
.tile {
  display: inline-grid; place-items: center;
  width: 44px; height: 44px; flex: none;
  border-radius: 14px;
  background: var(--brand-50);
  color: var(--brand);
  font-size: 1.35rem;
  box-shadow: var(--sunlit);
}

/* Faint cloud shapes behind sections, the same silhouette as the logo. One
   decorative layer, no motion, and well under any text it sits beside. */
.cloud-deco::before {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  width: min(520px, 62vw); aspect-ratio: 32 / 24;
  top: var(--cd-top, 4%); left: var(--cd-left, auto); right: var(--cd-right, -6%);
  background: color-mix(in srgb, var(--brand) 4%, transparent);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 4 32 24'%3E%3Cpath d='M23.5 24H9A4.5 4.5 0 1 1 9.07 15A7 7 0 1 1 22.93 13.03A5.5 5.5 0 1 1 23.5 24Z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 4 32 24'%3E%3Cpath d='M23.5 24H9A4.5 4.5 0 1 1 9.07 15A7 7 0 1 1 22.93 13.03A5.5 5.5 0 1 1 23.5 24Z'/%3E%3C/svg%3E") center / contain no-repeat;
}


/* ---------------------------------------------------------------- glass --- */
.glass {
  background: var(--glass-bg);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(170%);
  backdrop-filter: blur(var(--glass-blur)) saturate(170%);
  border: 1px solid var(--glass-stroke);
  box-shadow: inset 0 1px 0 var(--glass-inner), var(--e-3);
}
.glass-strong {
  background: var(--glass-bg-2);
  -webkit-backdrop-filter: blur(calc(var(--glass-blur) * 1.4)) saturate(180%);
  backdrop-filter: blur(calc(var(--glass-blur) * 1.4)) saturate(180%);
  border: 1px solid var(--glass-stroke);
  box-shadow: inset 0 1px 0 var(--glass-inner), var(--e-4);
}

/* -------------------------------------------------------------- buttons --- */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--s-2);
  white-space: nowrap;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  font: var(--t-label);
  cursor: pointer;
  transition: transform var(--d-fast) var(--ease-out),
              background var(--d-fast) var(--ease-out),
              box-shadow var(--d-fast) var(--ease-out),
              border-color var(--d-fast) var(--ease-out);
}
.btn-sm { padding: 9px 18px; }
.btn-lg { padding: 15px 28px; font-size: 0.9375rem; }
.btn:not(.btn-sm):not(.btn-lg) { padding: 12px 22px; }
.btn-block { width: 100%; }
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0) scale(0.985); }

.btn-primary {
  background: var(--brand); color: var(--on-brand);
  box-shadow: 0 8px 24px -10px color-mix(in srgb, var(--brand) 60%, transparent);
}
.btn-primary:hover { background: var(--brand-600); box-shadow: 0 12px 28px -10px color-mix(in srgb, var(--brand) 70%, transparent); }

.btn-ghost {
  background: var(--cloud);
  color: var(--ink);
  box-shadow: var(--sunlit), var(--e-1);
}
.btn-ghost:hover { background: var(--cloud-2); box-shadow: var(--sunlit), var(--e-2); }

/* Dark frosted: the secondary action on a photographic surface, where a white
   or pale button would vanish into the cloud. Uses the allowed navy literal. */
.btn-dark-glass {
  background: color-mix(in srgb, #0c1830 42%, transparent);
  color: #ffffff;
  border-color: rgba(255, 255, 255, 0.40);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}
.btn-dark-glass:hover { background: color-mix(in srgb, #0c1830 58%, transparent); border-color: #ffffff; }

/* On the photographic sky these need their own opaque scrim for AA contrast. */
.btn-light { background: #ffffff; color: #0c1830; box-shadow: var(--e-3); }
.btn-light:hover { background: var(--brand-50); }
.btn-outline-light {
  background: color-mix(in srgb, #0c1830 42%, transparent);
  color: #ffffff;
  border-color: rgba(255, 255, 255, 0.40);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}
.btn-outline-light:hover { background: color-mix(in srgb, #0c1830 58%, transparent); border-color: #ffffff; }

.btn em { font-style: normal; opacity: 0.7; font-weight: 450; }

/* ------------------------------------------------------------------ nav --- */
.nav-wrap {
  position: fixed; inset: var(--s-4) 0 auto;
  z-index: var(--z-sticky);
  display: flex; justify-content: center;
  padding: 0 var(--gutter);
  pointer-events: none;
}
.nav {
  pointer-events: auto;
  width: 100%;
  max-width: var(--page-max);
  height: 64px;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--s-5);
  padding: 0 10px 0 20px;
  border-radius: var(--r-pill);
  transition: background var(--d-base) var(--ease-out),
              box-shadow var(--d-base) var(--ease-out);
}
/* Over the sky the nav is translucent white; once scrolled past the hero it
   picks up the page surface so text keeps contrast. */
.nav-wrap:not(.scrolled) .nav {
  background: rgba(12, 30, 68, 0.22);
  border-color: rgba(255, 255, 255, 0.30);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 10px 40px -18px rgba(8, 24, 60, 0.5);
}
.nav-wrap:not(.scrolled) .nav,
.nav-wrap:not(.scrolled) .nav a,
.nav-wrap:not(.scrolled) .brand-word { color: #ffffff; }
.nav-wrap:not(.scrolled) .nav-links a:hover { color: #ffffff; background: rgba(255,255,255,0.18); }
/* The nav's white-over-sky link colour must not reach the button: in dark mode the
   accent fill is a LIGHT blue and white on it measured 2.2:1. */
.nav-wrap:not(.scrolled) .nav .btn-primary { color: var(--on-brand); }
.nav-wrap:not(.scrolled) .theme-toggle { color: #ffffff; border-color: rgba(255,255,255,0.34); }

.brand { display: inline-flex; align-items: center; gap: 10px; }
.brand-mark { display: grid; place-items: center; color: var(--brand); }
/* Over the photographic sky the mark is white, like the wordmark beside it: that
   surface is the same brightness in both themes. */
.nav-wrap:not(.scrolled) .brand-mark { color: #ffffff; }
.brand-word { font: var(--t-title-md); letter-spacing: -0.02em; text-transform: lowercase; color: var(--ink); }

.nav-links { display: flex; justify-content: center; gap: var(--s-1); }
.nav-links a {
  display: block;
  padding: 8px 14px;
  border-radius: var(--r-pill);
  font: var(--t-label);
  color: var(--body);
  transition: background var(--d-fast) var(--ease-out), color var(--d-fast) var(--ease-out);
}
.nav-links a:hover { background: var(--surface-2); color: var(--ink); }

.nav-actions { display: flex; align-items: center; gap: var(--s-2); }
.theme-toggle {
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: var(--r-pill);
  border: 1px solid var(--hairline);
  background: transparent;
  color: var(--body);
  font-size: 1.05rem;
  cursor: pointer;
  transition: background var(--d-fast) var(--ease-out), color var(--d-fast) var(--ease-out);
}
.theme-toggle:hover { background: var(--surface-2); color: var(--ink); }

/* ----------------------------------------------------------------- hero --- */
.hero {
  position: relative;
  min-height: 100dvh;
  display: grid;
  grid-template-rows: 1fr auto;
  padding: 148px var(--gutter) 0;
  isolation: isolate;
}

.sky { position: absolute; inset: 0; z-index: -1; overflow: hidden; }

/* ---------------------------------------------------------------------------
   THE SKY
   The hero sits on a real photograph, not a gradient and not procedural noise.
   Four stacked layers, bottom to top:
     .sky-photo  the photograph, cover-fit, slowly drifting
     .sky-tint   a brand-blue wash that ties the photo to the palette
     .sky-scrim  a top gradient that guarantees nav and headline contrast
     .sky-fade   the dissolve into the page canvas at the bottom
   Day and night are separate files chosen by theme, so a viewer only ever
   downloads the one they see. `image-set` serves WebP where supported; the
   plain url() above it is the fallback older browsers keep.
   ------------------------------------------------------------------------ */
.sky-photo {
  position: absolute; inset: 0;
  background-repeat: no-repeat;
  background-position: center 38%;
  background-size: cover;
  background-color: var(--sky-mid);
  will-change: transform;
}

.sky-photo {
  background-image: url("../assets/sky-day.jpg");
  background-image: image-set(
    url("../assets/sky-day.webp") type("image/webp"),
    url("../assets/sky-day.jpg")  type("image/jpeg"));
}

/* Phones get the half-size file. At 390px wide the 2400px image is three
   times more pixels than the screen can show. */
@media (max-width: 760px) {
  .sky-photo {
    background-image: url("../assets/sky-day-sm.jpg");
    background-image: image-set(
      url("../assets/sky-day-sm.webp") type("image/webp"),
      url("../assets/sky-day-sm.jpg")  type("image/jpeg"));
  }
}

.sky-tint {
  position: absolute; inset: 0;
  background:
    radial-gradient(120% 86% at 50% 120%, color-mix(in oklab, var(--sky-haze) 62%, transparent), transparent 62%),
    linear-gradient(176deg,
      color-mix(in oklab, var(--brand-800) 30%, transparent) 0%,
      transparent 46%,
      color-mix(in oklab, var(--sky-low) 22%, transparent) 100%);
  /* soft-light, not multiply: it warms and unifies the photograph with the
     brand palette without crushing the clouds into a flat blue slab. */
  mix-blend-mode: soft-light;
  opacity: 0.8;
}

.sky-scrim {
  position: absolute; left: 0; right: 0; top: 0; height: 78%;
  background: linear-gradient(to bottom,
    color-mix(in srgb, #0c1830 60%, transparent),
    color-mix(in srgb, #0c1830 50%, transparent) 55%,
    transparent);
}

.sky-fade {
  position: absolute; left: 0; right: 0; bottom: 0; height: 44%;
  background: linear-gradient(to bottom, transparent, var(--canvas) 95%);
}

/* A very slow drift. The scale headroom keeps the edges off screen, and only
   `transform` animates, on a promoted layer, so this composites on the GPU. */
@media (prefers-reduced-motion: no-preference) {
  .sky-photo { animation: sky-drift 150s ease-in-out infinite; }
}
@keyframes sky-drift {
  from { transform: scale(1.06) translate3d(-1.2%, 0, 0); }
  50%  { transform: scale(1.11) translate3d(1.4%, -1%, 0); }
  to   { transform: scale(1.06) translate3d(-1.2%, 0, 0); }
}

/* --- night ------------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .sky-photo {
    background-image: url("../assets/sky-night.jpg");
    background-image: image-set(
      url("../assets/sky-night.webp") type("image/webp"),
      url("../assets/sky-night.jpg")  type("image/jpeg"));
  }
  :root:not([data-theme="light"]) .sky-tint { mix-blend-mode: normal; opacity: 0.5; }
}
:root[data-theme="dark"] .sky-photo {
  background-image: url("../assets/sky-night.jpg");
  background-image: image-set(
    url("../assets/sky-night.webp") type("image/webp"),
    url("../assets/sky-night.jpg")  type("image/jpeg"));
}
:root[data-theme="dark"] .sky-tint { mix-blend-mode: normal; opacity: 0.5; }

.hero-copy { position: relative; isolation: isolate; max-width: 1040px; margin: 0 auto; text-align: center; }
/* A soft navy pool behind the words, wider than the text, so the subtitle (the
   smallest white text on the photograph) clears 4.5:1 over the brightest cloud
   without the whole sky going dark. Measured, not eyeballed: see the hero test. */
.hero-copy::before {
  content: ""; position: absolute; z-index: -1;
  inset: -8% -14% -12%;
  background: radial-gradient(closest-side, color-mix(in srgb, #0c1830 62%, transparent) 55%, transparent);
  pointer-events: none;
}

/* The sky is one photograph in both themes, so the text on it is white in both
   (the two literals the design contract allows). The veil below is what makes
   that legible over the brightest cloud: it is navy at the top and middle,
   where the headline and subtitle sit, and clears toward the preview. */
.hero-chip {
  display: inline-flex; align-items: center; gap: 8px;
  margin-bottom: var(--s-6);
  padding: 7px 16px;
  border-radius: var(--r-pill);
  font: var(--t-label);
  color: #ffffff;
  background: color-mix(in srgb, #0c1830 38%, transparent);
  border: 1px solid rgba(255, 255, 255, 0.34);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}
.hero-chip:hover { background: color-mix(in srgb, #0c1830 52%, transparent); }
.hero-title {
  font: 600 clamp(2.75rem, 7.4vw, 5.75rem)/1.02 var(--font-sans);
  letter-spacing: -0.035em;
  color: #ffffff;
  text-shadow: 0 2px 10px rgba(8, 26, 62, 0.30), 0 4px 40px rgba(8, 26, 62, 0.45);
  margin-bottom: var(--s-6);
}
.hero-sub {
  max-width: 54ch; margin: 0 auto var(--s-7);
  font-size: 1.1875rem; line-height: 1.6;
  color: #ffffff;
  /* Two shadows: a tight one for edge definition against bright cloud, and a
     wide soft one that acts as a local scrim. */
  text-shadow: 0 1px 3px rgba(8, 26, 62, 0.45), 0 2px 26px rgba(8, 26, 62, 0.65);
}
.hero-cta { display: flex; flex-wrap: wrap; gap: var(--s-3); justify-content: center; }
/* The secondary hero button is .btn-dark-glass (see buttons). */

/* ------------------------------------------------------- live preview ----- */
/* A miniature of the app's Today screen, on the same surfaces: cloud panels,
   the sunlit top edge, tinted shadow, Outfit numerals. */
.preview-wrap { max-width: min(var(--page-max), 1120px); margin: var(--s-10) auto 0; width: 100%; padding-bottom: var(--s-9, 64px); }
.preview {
  position: relative;
  display: grid; grid-template-columns: 196px 1fr; gap: 14px;
  padding: 14px;
  border-radius: var(--r-xl);
  background: var(--glass-bg-2);
  -webkit-backdrop-filter: blur(24px) saturate(150%);
  backdrop-filter: blur(24px) saturate(150%);
  border: 1px solid var(--glass-stroke);
  box-shadow: inset 0 1px 0 var(--glass-inner), var(--e-4);
}
.pv-rail, .pv-panel {
  background: var(--cloud);
  border-radius: var(--r-lg);
  box-shadow: inset 0 1px 0 var(--glass-inner), var(--e-2);
}
.pv-rail { display: flex; flex-direction: column; gap: 4px; padding: 18px 12px; min-height: 100%; }
.pv-brand {
  display: flex; align-items: center; gap: 8px;
  padding: 0 8px 16px;
  font: var(--t-title-md); letter-spacing: -0.02em; color: var(--ink);
}
.pv-brand svg { color: var(--brand); }
.pv-rail-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px; border-radius: var(--r-pill);
  font: var(--t-label); color: var(--body);
}
.pv-rail-item i { font-size: 1.05rem; color: var(--muted); }
.pv-rail-item.is-active { background: var(--cloud-2); color: var(--ink); box-shadow: inset 0 1px 0 var(--glass-inner), var(--e-1); }
.pv-rail-item.is-active i { color: var(--brand); }

.pv-main { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.pv-top { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.pv-panel { padding: 22px 24px; display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.pv-label {
  display: flex; align-items: center; gap: 10px;
  font: var(--t-caption); text-transform: uppercase; letter-spacing: 0.09em; color: var(--muted);
}
.pv-label i { display: grid; place-items: center; width: 30px; height: 30px; border-radius: 10px; background: var(--brand-50); color: var(--brand); font-size: 1rem; }

.pv-big { display: flex; align-items: baseline; gap: 12px; }
.pv-big-n { font: 600 clamp(3rem, 5vw, 4.25rem)/0.95 var(--font-sans); letter-spacing: -0.03em; font-variant-numeric: tabular-nums lining-nums; color: var(--ink); }
.pv-big-l { font: var(--t-title-md); color: var(--body); }
.pv-cta { display: flex; flex-wrap: wrap; gap: 10px; margin-top: auto; }
.pv-pill {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 18px; border-radius: var(--r-pill);
  font: var(--t-label); color: var(--ink); background: var(--cloud-2);
}
.pv-pill.is-solid { background: var(--brand); color: var(--on-brand); box-shadow: 0 8px 24px -10px color-mix(in srgb, var(--brand) 60%, transparent); }

.pv-card-stage { perspective: 1400px; }
.pv-card {
  position: relative;
  width: 100%; min-height: 104px;
  border: 0; padding: 0;
  background: transparent;
  cursor: pointer;
  transform-style: preserve-3d;
  transition: transform var(--d-slow) var(--ease-in-out);
  font: inherit; text-align: left;
  perspective: 1400px;
}
.pv-card.flipped { transform: rotateX(180deg); }
.pv-card-face {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; gap: 6px; justify-content: center;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}
.pv-back { transform: rotateX(180deg); }
.pv-q, .pv-a { font: 500 1.125rem/1.35 var(--font-sans); color: var(--ink); }
.pv-hint { font: var(--t-caption); color: var(--muted); }
@media (prefers-reduced-motion: reduce) {
  .pv-card { transition: none; transform: none !important; }
  .pv-card .pv-back { transform: none; display: none; }
  .pv-card.flipped .pv-front { display: none; }
  .pv-card.flipped .pv-back { display: flex; }
}

.pv-grades { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.pv-grade {
  display: flex; flex-direction: column; gap: 1px; align-items: center;
  padding: 9px 4px;
  border-radius: var(--r-pill);
  border: 0;
  background: var(--cloud-3);
  color: var(--ink);
  font: var(--t-label);
  cursor: pointer;
  transition: transform var(--d-fast) var(--ease-out), box-shadow var(--d-fast) var(--ease-out);
}
.pv-grade em { font-style: normal; font-size: 0.6875rem; font-variant-numeric: tabular-nums; color: var(--muted); }
/* Again is the one failing state, so it keeps the status colour. Hard, Good and
   Easy are one accent stepped by magnitude, as in the app. */
.pv-grade.g-again { background: color-mix(in srgb, var(--err) 14%, var(--cloud)); color: color-mix(in srgb, var(--err) 62%, var(--ink)); }
.pv-grade.g-again em { color: inherit; }
.pv-grade.g-hard { background: var(--brand-100); }
.pv-grade.g-good { background: var(--brand); color: var(--on-brand); }
.pv-grade.g-good em { color: inherit; }
/* brand-700 is the darker step in light and the lighter step in dark, so with
   --on-brand it clears AA in both (8.7 and 12.3). */
.pv-grade.g-easy { background: var(--brand-700); color: var(--on-brand); }
.pv-grade.g-easy em { color: inherit; }
.pv-grade:hover:not(:disabled) { transform: translateY(-1px); box-shadow: var(--e-2); }
.pv-grade:disabled { opacity: 0.55; cursor: default; }

.pv-heat { display: grid; grid-template-columns: repeat(7, 1fr); gap: 10px; }
.pv-day {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 10px 4px 12px;
  border-radius: var(--r-md);
  background: var(--cloud-2);
}
.pv-day.is-today { background: var(--brand-50); }
.pv-day-n { font: var(--t-caption); color: var(--muted); }
.pv-day i { font-size: 1.7rem; line-height: 1; color: var(--brand); }
.pv-day .pv-dot { width: 6px; height: 6px; margin: 11px 0; border-radius: 50%; background: var(--cloud-3); }
.pv-day-c { font: 600 1.25rem/1 var(--font-sans); font-variant-numeric: tabular-nums lining-nums; color: var(--ink); }

/* Two floating chips, both driven by the preview state. They sit on the frame's
   edge where the rail and the grid are empty, never over a nav label. */
.pv-chip {
  position: absolute; z-index: 2;
  display: flex; align-items: center; gap: 12px;
  padding: 12px 18px 12px 12px;
  border-radius: var(--r-lg);
  background: var(--cloud);
  box-shadow: inset 0 1px 0 var(--glass-inner), var(--e-3);
  font: var(--t-label); color: var(--ink);
}
.pv-chip i { display: grid; place-items: center; width: 38px; height: 38px; border-radius: 12px; background: var(--brand-50); color: var(--brand); font-size: 1.15rem; }
.pv-chip strong { display: block; font-weight: 600; }
.pv-chip em { display: block; font-style: normal; font: var(--t-caption); color: var(--muted); }
.pv-chip-a { left: -28px; bottom: 34px; }
.pv-chip-b { right: -22px; top: -22px; }

@media (max-width: 900px) {
  .preview { grid-template-columns: 1fr; }
  .pv-rail { display: none; }
  .pv-top { grid-template-columns: 1fr; }
  .pv-heat { gap: 6px; }
  .pv-chip { position: static; margin: 0; }
  .pv-chip-a, .pv-chip-b { inset: auto; }
}

/* ---------------------------------------------------------------- band ---- */
.band {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--s-10) var(--gutter) var(--s-9);
}
.band-lede {
  max-width: 34ch; margin: 0 auto var(--s-8);
  text-align: center;
  font: 500 clamp(1.3rem, 2.2vw, 1.75rem)/1.35 var(--font-sans);
  letter-spacing: -0.02em;
  color: var(--ink);
}
.band-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--s-5); }
.band-list li { display: flex; flex-direction: column; gap: 6px; padding: var(--s-6) var(--s-7) var(--s-7); }
.band-year {
  font-size: clamp(2.6rem, 4.4vw, 3.6rem); line-height: 1; color: var(--brand);
  margin-bottom: var(--s-3);
}
.band-list strong { font: var(--t-title-md); color: var(--ink); }
.band-list span:not(.band-year) { font: var(--t-body-sm); color: var(--muted); }

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

/* ------------------------------------------------------------- section ---- */
/* Anchor links must not drop the heading under the fixed nav. */
.section, .band, .download { scroll-margin-top: 104px; }
.section { position: relative; isolation: isolate; max-width: var(--page-max); margin: 0 auto; padding: clamp(72px, 9vw, 120px) var(--gutter); }
.h-display { font: 600 clamp(2.1rem, 4.4vw, 3.4rem)/1.06 var(--font-sans); letter-spacing: -0.03em; text-wrap: balance; }
.center-head { text-align: center; max-width: 24ch; margin: 0 auto var(--s-9); text-wrap: balance; }
.lede { max-width: 62ch; font-size: 1.0625rem; line-height: 1.62; color: var(--muted); }
.eyebrow {
  font: var(--t-caption);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--brand-text);
  margin-bottom: var(--s-3);
}

/* ---------------------------------------------------------- method/curve -- */
.method-grid {
  display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
  gap: var(--s-9); align-items: center;
}
.method-head .h-display { margin-bottom: var(--s-5); }
.method-head .eyebrow { display: flex; align-items: center; gap: 12px; }
.method-head .eyebrow .tile { width: 34px; height: 34px; border-radius: 12px; font-size: 1.05rem; }

.curve-card {
  padding: var(--s-6);
  border-radius: var(--r-xl);
  background: var(--cloud);
  box-shadow: var(--sunlit), var(--e-3);
}
.curve-fig { margin: 0; }
.curve { width: 100%; height: auto; display: block; }
.cg-top { stop-color: var(--brand); stop-opacity: 0.22; }
.cg-bottom { stop-color: var(--brand); stop-opacity: 0; }
.c-massed { stroke: var(--muted); stroke-width: 2; stroke-dasharray: 5 6; }
.c-spaced { stroke: var(--brand); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.c-fill { fill: url(#curveGrad); }
.curve-grid-line { stroke: var(--hairline-soft); stroke-width: 1; }
.curve-label { fill: var(--muted); font: 500 15px var(--font-sans); font-variant-numeric: tabular-nums lining-nums; }
.curve-mark { fill: var(--cloud); stroke: var(--brand); stroke-width: 2.5; }

.curve-legend { display: flex; flex-wrap: wrap; gap: var(--s-5); margin-top: var(--s-3); }
.lg { display: inline-flex; align-items: center; gap: 8px; font: var(--t-body-sm); color: var(--muted); }
.lg::before { content: ""; width: 22px; height: 3px; border-radius: var(--r-pill); }
.lg-massed::before { background: var(--muted); }
.lg-spaced::before { background: var(--brand); }

.curve-ctl { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-5) var(--s-7); margin-top: var(--s-6); }
.ctl { display: grid; gap: 14px; font: var(--t-label); color: var(--ink); }
.ctl-row { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }
.ctl output {
  padding: 4px 12px; border-radius: var(--r-pill);
  background: var(--brand-50); color: var(--brand-text);
  font-size: 0.8125rem; box-shadow: var(--sunlit);
}

/* The slider is the app's: a pill track filled up to the value, a round thumb
   with the sunlit edge. --p is set from the value in site.js. */
input[type="range"] {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 8px;
  border-radius: var(--r-pill);
  background: linear-gradient(to right, var(--brand) var(--p, 50%), var(--cloud-3) var(--p, 50%));
  cursor: pointer;
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 24px; height: 24px; border-radius: var(--r-pill);
  background: var(--cloud); border: 0;
  box-shadow: var(--sunlit), var(--e-2), 0 0 0 2px var(--brand);
}
input[type="range"]::-moz-range-track { background: transparent; }
input[type="range"]::-moz-range-thumb {
  width: 24px; height: 24px; border-radius: var(--r-pill);
  background: var(--cloud); border: 0;
  box-shadow: var(--sunlit), var(--e-2), 0 0 0 2px var(--brand);
}

.curve-read { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-3); margin-top: var(--s-6); }
.read-tile {
  display: flex; flex-direction: column; gap: 6px;
  padding: 14px 18px; border-radius: var(--r-md);
  background: var(--cloud-2);
}
.read-tile.is-accent { background: var(--brand-50); }
.read-l { font: var(--t-caption); text-transform: uppercase; letter-spacing: 0.09em; color: var(--muted); }
.is-accent .read-l { color: var(--brand-text); }
.read-n { font-size: 1.9rem; line-height: 1; color: var(--ink); }
.is-accent .read-n { color: var(--brand-text); }

/* ---------------------------------------------------------------- bento --- */
.bento { display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--s-4); }
.cell {
  display: flex; flex-direction: column; gap: 10px;
  padding: var(--s-6);
  border-radius: var(--r-xl);
  background: var(--cloud);
  box-shadow: var(--sunlit), var(--e-2);
  transition: transform var(--d-base) var(--ease-out), box-shadow var(--d-base) var(--ease-out);
}
.cell:hover { transform: translateY(-2px); box-shadow: var(--sunlit), var(--e-3); }
.cell h3 { font: var(--t-title-md); }
.cell p { font: var(--t-body-sm); color: var(--muted); }

.cell-a { grid-column: span 3; }
.cell-b { grid-column: span 3; }
.cell-c { grid-column: span 2; }
.cell-d { grid-column: span 2; }
.cell-e { grid-column: span 2; }

.cell-visual { border-radius: var(--r-lg); margin-bottom: var(--s-2); overflow: hidden; position: relative; }

/* The Match miniature sits on a sky-tinted panel, tiles as small clouds. */
.cell-visual-grad {
  background: var(--brand-100);
  display: grid; place-items: center;
  padding: var(--s-4);
}
.mini-match { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; width: 100%; }
.mini-match span {
  display: grid; place-items: center;
  min-height: 44px; padding: 6px 4px;
  border-radius: var(--r-md);
  background: var(--cloud);
  color: var(--ink);
  box-shadow: var(--sunlit), var(--e-1);
  font: 500 0.8125rem/1.1 var(--font-sans);
  transition: background var(--d-fast) var(--ease-out), color var(--d-fast) var(--ease-out), transform var(--d-fast) var(--ease-out), opacity var(--d-base) var(--ease-out);
}
.mini-match span.lit { background: var(--brand); color: var(--on-brand); transform: translateY(-2px); }
.mini-match span.gone { opacity: 0.35; transform: translateY(-6px); }

.cell-code {
  margin: var(--s-2) 0 0;
  padding: var(--s-4);
  border-radius: var(--r-md);
  background: var(--cloud-2);
  font: 400 0.8125rem/1.75 var(--font-mono);
  color: var(--body);
  overflow-x: auto;
}
.cell-status { display: flex; align-items: center; gap: 8px; margin-top: auto; color: var(--body) !important; }
.cell-status i { color: var(--ok); font-size: 1.05rem; flex: none; }

.streak-top { display: flex; align-items: center; gap: 10px; }
.streak-flame { color: var(--sun); font-size: 2.1rem; }
.cell-stat { font-size: 3.6rem; color: var(--ink); line-height: 1; }
.streak-week { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; margin: var(--s-2) 0 auto; }
.streak-week span { height: 26px; border-radius: 9px; background: var(--brand); opacity: 0.85; display: grid; place-items: center; }
.streak-week .is-freeze { background: var(--brand-50); color: var(--brand); opacity: 1; font-size: 0.95rem; }

.cell-visual-ring { aspect-ratio: 1 / 1; max-width: 132px; margin: 0 auto var(--s-2); display: grid; place-items: center; background: transparent; overflow: visible; }
.focus-ring { grid-area: 1 / 1; width: 132px; height: 132px; transform: rotate(-90deg); overflow: visible; }
.fr-track { fill: none; stroke: var(--cloud-3); stroke-width: 10; }
.fr-fill {
  fill: none; stroke: var(--brand); stroke-width: 10; stroke-linecap: round;
  stroke-dasharray: 327; stroke-dashoffset: 82;
  transition: stroke-dashoffset 1s linear;
}
.fr-head { fill: var(--cloud); stroke: var(--brand); stroke-width: 3; filter: drop-shadow(0 0 6px color-mix(in srgb, var(--brand) 70%, transparent)); }
.focus-time { grid-area: 1 / 1; font-size: 1.5rem; color: var(--ink); }

.sync-visual { display: flex; align-items: center; gap: 8px; }
.sync-visual .tile { width: 42px; height: 42px; border-radius: 13px; font-size: 1.2rem; }
.sync-line { flex: 1; min-width: 12px; border-top: 2px dashed var(--brand-200); }
.sync-status { display: flex; align-items: center; gap: 8px; font: var(--t-caption) !important; color: var(--muted); }
.sync-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); }

/* ---------------------------------------------------------------- modes --- */
.modes-head {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr);
  gap: var(--s-8); align-items: end;
  margin-bottom: var(--s-8);
}
.eyebrow:has(.tile) { display: flex; align-items: center; gap: 12px; }
.eyebrow .tile { width: 34px; height: 34px; border-radius: 12px; font-size: 1.05rem; }
.modes-head .eyebrow { margin-bottom: var(--s-4); }
.modes-head .lede { margin-bottom: 6px; }

/* A 3 x 2 grid, not a rail: all six are visible at once, so Cram (the one that
   argues with the rest of the page) is never off screen. #modeRail keeps its id
   and role; it simply no longer scrolls. */
.rail { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-4); }
.mode {
  display: flex; flex-direction: column; gap: 10px;
  padding: var(--s-7);
  border-radius: var(--r-xl);
  background: var(--cloud);
  box-shadow: var(--sunlit), var(--e-2);
  transition: box-shadow var(--d-base) var(--ease-out), transform var(--d-base) var(--ease-out);
}
.mode:hover { box-shadow: var(--sunlit), var(--e-3); transform: translateY(-2px); }
.mode i {
  display: inline-grid; place-items: center; align-self: flex-start;
  width: 48px; height: 48px; border-radius: 15px;
  background: var(--brand-50); color: var(--brand);
  font-size: 1.45rem; box-shadow: var(--sunlit);
  margin-bottom: var(--s-3);
}
.mode h3 { font: var(--t-title-lg); }
.mode p { font: var(--t-body-sm); color: var(--muted); flex: 1; }
/* Cram gets an accent ring and a soft glow, not a different colour. */
.mode-cram {
  box-shadow: var(--sunlit), var(--e-3), 0 0 0 1.5px color-mix(in srgb, var(--brand) 45%, transparent),
              0 18px 48px -22px color-mix(in srgb, var(--brand) 55%, transparent);
  background:
    radial-gradient(110% 80% at 90% -10%, color-mix(in srgb, var(--brand) 12%, transparent), transparent 60%),
    var(--cloud);
}

.mode-tag {
  align-self: flex-start;
  padding: 6px 14px;
  border-radius: var(--r-pill);
  background: var(--brand-50);
  color: var(--brand-text);
  font: var(--t-caption);
  font-weight: 550;
}

/* ---------------------------------------------------------------- split --- */
.split {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: var(--s-10);
  align-items: center;
}
.split-copy .h-display { margin-bottom: var(--s-4); }
.split-copy .eyebrow { margin-bottom: var(--s-4); }
.ticks { display: grid; gap: 12px; margin-top: var(--s-6); }
.ticks li { display: flex; align-items: center; gap: 12px; font: var(--t-body); color: var(--body); }
.ticks i { color: var(--brand); font-size: 1.2rem; flex: none; }

.panel {
  border-radius: var(--r-xl); padding: var(--s-6);
  display: grid; gap: var(--s-4);
  background: var(--cloud);
  box-shadow: var(--sunlit), var(--e-3);
}
.panel-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }
.panel-head-sub { margin-top: var(--s-3); }
.panel-title { display: flex; align-items: center; gap: 12px; font: var(--t-caption); text-transform: uppercase; letter-spacing: 0.09em; color: var(--muted); }
.panel-title .tile { width: 34px; height: 34px; border-radius: 12px; font-size: 1.05rem; }
.chip {
  padding: 5px 14px; border-radius: var(--r-pill);
  background: var(--brand-50); color: var(--brand-text);
  font-size: 0.8125rem; font-variant-numeric: tabular-nums lining-nums;
  box-shadow: var(--sunlit);
}
.forecast { width: 100%; height: auto; }
.fc-bar { fill: var(--brand); transition: fill var(--d-fast) var(--ease-out); }
.fc-bar:hover { fill: var(--brand-700); }
.fc-axis { fill: var(--muted); font: 500 7px var(--font-sans); font-variant-numeric: tabular-nums lining-nums; }

/* Cloud cover: rounded cells, one hue stepped from the empty-sky tile to the
   full accent. The legend is the ramp itself, so it needs no key. */
.heat-year { display: grid; grid-auto-flow: column; grid-template-rows: repeat(7, 1fr); gap: 4px; }
.heat-year span { aspect-ratio: 1; border-radius: 4px; background: var(--cloud-3); }

/* -------------------------------------------------------------- pricing --- */
/* Flex rather than a fixed column count, because the number of cards is decided
   at runtime: entity.js removes whichever plans this deployment does not offer,
   so the row has to read correctly with two cards or three. The raised card is
   the one that costs money; the others sit centred beside it. */
.plans { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: var(--s-5); }
.plan {
  flex: 1 1 290px; max-width: 390px;
  display: flex; flex-direction: column; gap: var(--s-3);
  padding: var(--s-7);
  border-radius: var(--r-xl);
  background: var(--cloud);
  box-shadow: var(--sunlit), var(--e-2);
}
.plan-feature {
  padding-block: calc(var(--s-7) + 10px);
  box-shadow: var(--sunlit), var(--e-4), 0 0 0 2px var(--brand);
  background:
    radial-gradient(120% 70% at 85% -10%, color-mix(in srgb, var(--brand) 14%, transparent), transparent 60%),
    var(--cloud);
}
.plan-name { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); font: var(--t-title-md); }
.plan-price { display: flex; align-items: baseline; gap: 6px; color: var(--ink); }
.plan-price span { font: 600 clamp(2.6rem, 4.4vw, 3.4rem)/1 var(--font-sans); letter-spacing: -0.03em; font-variant-numeric: tabular-nums lining-nums; }
.plan-price em { font-style: normal; font: var(--t-body-sm); color: var(--muted); }
.plan-note { font: var(--t-body-sm); color: var(--muted); min-height: 2.6em; }
.plan-list { display: grid; gap: 11px; padding: var(--s-4) 0; margin-top: auto; }
.plan-list li { font: var(--t-body-sm); color: var(--body); padding-left: 26px; position: relative; }
.plan-list li::before {
  content: ""; position: absolute; left: 2px; top: 0.46em;
  width: 11px; height: 6px;
  border-left: 2px solid var(--brand-text); border-bottom: 2px solid var(--brand-text);
  transform: rotate(-45deg);
}

/* Class: slim, full width, and visibly not for sale. */
.plan-class {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--s-5);
  max-width: 1180px; margin: var(--s-5) auto 0;
  padding: var(--s-5) var(--s-6);
  border-radius: var(--r-xl);
  background: var(--cloud);
  box-shadow: var(--sunlit), var(--e-1);
}
.plan-class .plan-name { justify-content: flex-start; }
.plan-class .plan-note { min-height: 0; margin-top: 2px; }
.pc-list { display: flex; flex-wrap: wrap; gap: 6px 8px; margin-top: var(--s-3); }
.pc-list li { padding: 4px 12px; border-radius: var(--r-pill); background: var(--cloud-2); font: var(--t-caption); color: var(--body); }
.pc-buy { display: flex; align-items: center; gap: var(--s-5); }
.pc-buy .plan-price span { font-size: 1.9rem; }

/* ------------------------------------------------------ pricing honesty --- */
.plan-tag {
  display: inline-block;
  padding: 3px 11px;
  border-radius: var(--r-pill);
  background: var(--brand-50);
  color: var(--brand-text);
  font: var(--t-caption);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.plan-class .plan-tag { margin-left: 10px; }
.plan .is-unbuilt, .plan-class .is-unbuilt { opacity: 0.6; cursor: not-allowed; box-shadow: none; border: 1px dashed var(--hairline); }
.plans-note {
  max-width: 68ch;
  margin: var(--s-7) auto 0;
  text-align: center;
  font: var(--t-body-sm);
  color: var(--muted);
  line-height: 1.6;
}
.plans-note a { color: var(--brand-text); text-decoration: underline; text-underline-offset: 2px; }

/* The fine print, one disclosure. Frosted, full width of the plan row. */
.fineprint {
  max-width: 1180px; margin: var(--s-5) auto 0;
  border-radius: var(--r-lg);
  background: var(--cloud);
  box-shadow: var(--sunlit), var(--e-1);
}
.fineprint summary {
  display: flex; align-items: center; gap: 12px;
  padding: var(--s-4) var(--s-6);
  font: var(--t-label); color: var(--ink);
  cursor: pointer; list-style: none;
}
.fineprint summary::-webkit-details-marker { display: none; }
.fineprint summary::before {
  content: ""; width: 8px; height: 8px; flex: none;
  border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted);
  transform: rotate(-45deg);
  transition: transform var(--d-fast) var(--ease-out);
}
.fineprint[open] summary::before { transform: rotate(45deg); }
.fineprint-body { padding: 0 var(--s-6) var(--s-5); }
.fineprint-body .plans-note { max-width: none; margin: var(--s-3) 0 0; text-align: left; }

/* ------------------------------------------------------------- download --- */
/* An inset rounded band over the NIGHT photograph in both themes: it is a
   photographic surface, so, like the hero, it is the same brightness whichever
   theme the page is in and its text uses the two permitted literals. */
.download {
  position: relative;
  margin: var(--s-9) var(--gutter) 0;
  border-radius: 40px;
  overflow: hidden;
  isolation: isolate;
  background: #0c1830;
}
/* A navy veil, the same in both themes (the old one stepped through --brand-600,
   which is a LIGHT blue in dark mode and so thinned the scrim exactly when the
   photograph was darkest). */
.download::after {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(70% 60% at 50% 45%, color-mix(in srgb, #0c1830 58%, transparent), transparent 80%),
    color-mix(in srgb, #0c1830 40%, transparent);
}
.dl-sky {
  position: absolute; inset: 0; z-index: -2;
  background: #0c1830 url("../assets/sky-night-sm.jpg") center / cover no-repeat;
  background-image: image-set(url("../assets/sky-night-sm.webp") type("image/webp"), url("../assets/sky-night-sm.jpg") type("image/jpeg"));
}
.dl-inner { padding: clamp(56px, 8vw, 104px) var(--gutter); text-align: center; }
.dl-icon {
  display: block; margin: 0 auto var(--s-6);
  width: 116px; height: 116px; border-radius: 27px;
  box-shadow: 0 24px 50px -16px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.18);
}
.dl-title { font: 600 clamp(2.2rem, 5.2vw, 3.75rem)/1.04 var(--font-sans); letter-spacing: -0.035em; color: #ffffff; margin-bottom: var(--s-4); }
.dl-sub { max-width: 52ch; margin: 0 auto var(--s-7); color: #ffffff; font-size: 1.125rem; }
.dl-buttons { display: flex; flex-wrap: wrap; gap: var(--s-3); justify-content: center; }
.dl-buttons .btn { flex-direction: row; }
.dl-buttons span { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.2; }
.dl-buttons em { font-size: 0.6875rem; }
.dl-meta { margin-top: var(--s-6); font: var(--t-body-sm); color: #ffffff; }

/* --------------------------------------------------------------- footer --- */
.footer { max-width: var(--page-max); margin: 0 auto; padding: var(--s-11) var(--gutter) var(--s-7); }
/* One row: a brand column and four link columns. (This was a two-column grid
   holding a three-column grid holding four columns, so Legal wrapped under
   Product on a desktop.) */
.footer-inner { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 4fr); gap: var(--s-8); }
.footer-logo { display: inline-flex; align-items: center; gap: 10px; color: var(--brand); }
.footer-brand p { font: var(--t-body-sm); color: var(--muted); max-width: 30ch; margin-top: 12px; }
.footer-cols { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-6); }
.footer-cols h4 { font: var(--t-caption); text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); margin-bottom: var(--s-3); }
.footer-cols a { display: block; padding: 5px 0; font: var(--t-body-sm); color: var(--body); }
.footer-cols a:hover { color: var(--brand-text); }
.footer-base {
  display: flex; justify-content: space-between; gap: var(--s-4); flex-wrap: wrap;
  margin-top: var(--s-9); padding-top: var(--s-5);
  border-top: 1px solid var(--hairline);
  font: var(--t-caption); color: var(--muted);
}

/* ------------------------------------------------------- scroll reveals --- */
@media (prefers-reduced-motion: no-preference) {
  [data-reveal] {
    opacity: 0;
    transform: translateY(22px);
    transition: opacity var(--d-slow) var(--ease-out), transform var(--d-slow) var(--ease-out);
  }
  [data-reveal].in { opacity: 1; transform: none; }
}

/* ----------------------------------------------------------- responsive --- */
@media (max-width: 1080px) {
  /* Four cards at 230px each stop being readable before they stop fitting,
     so pair them off rather than letting auto-fit squeeze them. */
  .method-grid { grid-template-columns: 1fr; gap: var(--s-7); }
  .modes-head { grid-template-columns: 1fr; gap: var(--s-4); }
  .rail { grid-template-columns: repeat(2, 1fr); }
  .split { grid-template-columns: 1fr; gap: var(--s-8); }
}

@media (max-width: 880px) {
  .nav-links { display: none; }
  .nav-account { display: none; }
  .nav { grid-template-columns: auto 1fr; }
  .nav-actions { justify-self: end; }
  .hero { padding-top: 128px; }
  .bento { grid-template-columns: repeat(2, 1fr); }
  .cell-a, .cell-b, .cell-c, .cell-d, .cell-e { grid-column: span 2; }
  .plan-class { grid-template-columns: 1fr; }
  .pc-buy { justify-content: space-between; }
  .plan-feature { order: -1; }
  .curve-ctl { grid-template-columns: 1fr; }
  .footer-inner { grid-template-columns: 1fr; gap: var(--s-7); }
  .footer-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 620px) {
  .pv-grades { grid-template-columns: repeat(2, 1fr); }
  .curve-read { grid-template-columns: 1fr; }
  .rail { grid-template-columns: 1fr; }
  .mode { padding: var(--s-6); }
  .read-tile { flex-direction: row; align-items: baseline; justify-content: space-between; }
  .curve-card { padding: var(--s-5); }
  .curve-label { font-size: 26px; }
  .hero-cta .btn { width: 100%; }
  .dl-buttons .btn { width: 100%; }
  .footer-cols { grid-template-columns: 1fr 1fr; }
}

/* ------------------------------------------------- download: real builds --- */
.dl-buttons .is-unbuilt {
  opacity: 0.45;
  cursor: not-allowed;
  border-style: dashed;
}

/* ----------------------------------------------- download: the detection --- */
/* These sit on the photographic sky, where both themes are the same
   brightness, so they use the documented literal colours rather than tokens
   that would flip one of them to unreadable (AGENTS.md section 4, rule 4). */
.dl-detected {
  margin-top: var(--s-4);
  font: var(--t-body-sm);
  color: rgba(255, 255, 255, 0.82);
}

.dl-mobile {
  max-width: 50ch;
  margin: var(--s-5) auto 0;
  padding: var(--s-4) var(--s-5);
  border: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: var(--r-lg);
  background: rgba(10, 24, 52, 0.42);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  color: rgba(255, 255, 255, 0.92);
  font: var(--t-body-sm);
  text-align: left;
}
.dl-mobile .dl-copy { margin-top: var(--s-3); }
.dl-copy-url {
  display: block;
  margin-top: var(--s-3);
  padding: 8px 10px;
  border-radius: var(--r-md);
  background: rgba(10, 24, 52, 0.4);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: #ffffff;
  word-break: break-all;
  user-select: all;
}

.dl-others { margin-top: var(--s-5); }
.dl-others-toggle {
  padding: 7px 14px;
  border: 1px solid rgba(255, 255, 255, 0.34);
  border-radius: var(--r-pill);
  background: transparent;
  color: rgba(255, 255, 255, 0.92);
  font: var(--t-label);
  cursor: pointer;
  transition: background var(--d-fast) var(--ease-out), border-color var(--d-fast) var(--ease-out);
}
.dl-others-toggle:hover { background: rgba(255, 255, 255, 0.14); border-color: rgba(255, 255, 255, 0.6); }
.dl-others-toggle:focus-visible { outline: 2px solid #ffffff; outline-offset: 3px; }

.dl-others-list {
  display: flex; flex-wrap: wrap; gap: var(--s-3); justify-content: center;
  margin-top: var(--s-4);
}
.dl-others-list .btn { flex-direction: row; padding: 9px 18px; font-size: 0.875rem; }
.dl-others-list span { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.2; }
.dl-others-list em { font-size: 0.6875rem; }
.dl-others-list .is-unbuilt { opacity: 0.45; cursor: not-allowed; border-style: dashed; }

@media (max-width: 620px) {
  .dl-others-list .btn { width: 100%; }
}

.dl-note {
  max-width: 62ch;
  margin: var(--s-6) auto 0;
  text-align: left;
  padding: var(--s-4) var(--s-5);
  border: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: var(--r-lg);
  background: rgba(10, 24, 52, 0.42);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  color: rgba(255, 255, 255, 0.92);
}
.dl-note summary {
  cursor: pointer;
  font: var(--t-label);
  color: #ffffff;
  list-style: none;
}
.dl-note summary::-webkit-details-marker { display: none; }
.dl-note summary::before { content: "+  "; }
.dl-note[open] summary::before { content: "-  "; }
.dl-note p {
  font: var(--t-body-sm);
  line-height: 1.65;
  margin-top: var(--s-3);
  color: rgba(255, 255, 255, 0.86);
}
.dl-note code {
  font: 0.8125rem var(--font-mono);
  padding: 2px 6px;
  border-radius: var(--r-xs);
  background: rgba(255, 255, 255, 0.16);
}

.dl-checksums { max-width: 72ch; margin: var(--s-5) auto 0; text-align: left; }
.dl-sums-head {
  font: var(--t-caption);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: rgba(255, 255, 255, 0.6);
  margin-bottom: 6px;
}
.dl-sum {
  display: flex; flex-wrap: wrap; gap: 4px var(--s-4);
  padding: 7px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
}
.dl-sum-file { font: var(--t-caption); color: rgba(255, 255, 255, 0.86); flex: none; }
.dl-sum-hash {
  font: 0.6875rem/1.5 var(--font-mono);
  color: rgba(255, 255, 255, 0.55);
  word-break: break-all;
  flex: 1; min-width: 0;
}


/* ------------------------------------------------------------ account nav --- */
.nav-account {
  padding: 7px 12px;
  border-radius: var(--r-pill);
  color: var(--body);
  font: var(--t-label);
}
.nav-account:hover { color: var(--brand-text); background: var(--surface-2); }

@media (max-width: 520px) {
  .nav-account { display: none; }
}

#method.cloud-deco  { --cd-top: -2%; --cd-right: -8%; }
#modes.cloud-deco   { --cd-top: 6%;  --cd-left: -9%; --cd-right: auto; }
#pricing.cloud-deco { --cd-top: -4%; --cd-right: -6%; }

/* ------------------------------------------------------------ phone menu --- */
.nav-menu { display: none; position: static; }
/* Declared AFTER the base rule above, or the base wins on a phone and the menu
   never appears (same specificity, later wins). */
@media (max-width: 880px) {
  .nav-menu { display: block; }
  /* A thumb needs more than 38px. */
  .theme-toggle { width: 44px; height: 44px; }
  .nav .btn-sm { min-height: 44px; }
}
/* At 400% zoom the window is 320px wide and the nav's buttons no longer fit
   beside the wordmark. The mark stays (and the link keeps its aria-label), the
   word goes. */
@media (max-width: 380px) {
  .brand-word { display: none; }
  .nav { padding-left: 14px; }
}
.nav-menu summary { list-style: none; cursor: pointer; }
.nav-menu summary::-webkit-details-marker { display: none; }
.nav { position: relative; }
/* A frosted sheet under the nav, the same links as the inline row. */
.nav-sheet {
  position: absolute; left: 0; right: 0; top: calc(100% + var(--s-2));
  display: grid; gap: 2px;
  padding: var(--s-3);
  border-radius: var(--r-xl);
  background: color-mix(in srgb, var(--cloud) 98%, transparent);
  -webkit-backdrop-filter: blur(24px) saturate(160%);
  backdrop-filter: blur(24px) saturate(160%);
  box-shadow: var(--sunlit), var(--e-4);
}
.nav-sheet a { display: block; padding: 14px 18px; border-radius: var(--r-md); font: var(--t-body); color: var(--ink); }
.nav-sheet a:hover, .nav-sheet a:focus-visible { background: var(--cloud-2); }
/* The nav's white-over-sky colours must not leak into the sheet. */
.nav-wrap:not(.scrolled) .nav-sheet a { color: var(--ink); }

/* ---------------------------------------------------- reduced transparency --- */
/* Glass becomes a solid surface. tokens.css already turns --glass-bg and
   --glass-blur solid, which covers .glass; these are the rules that blur with a
   literal value, and the translucent navy ones that sit on the photograph (their
   text is white, so solid means the same navy at full strength). */
@media (prefers-reduced-transparency: reduce) {
  .btn-dark-glass, .btn-outline-light, .hero-chip, .preview, .dl-mobile, .dl-note, .nav-sheet {
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  .btn-dark-glass, .btn-outline-light, .hero-chip, .dl-mobile, .dl-note,
  .nav-wrap:not(.scrolled) .nav { background: #0c1830; }
  .preview { background: var(--cloud); }
  .nav-sheet { background: var(--cloud); }
}

/* ------------------------------------------------------------ forced colours --- */
/* Windows High Contrast removes box-shadow and replaces every colour, so a card
   that was a white shape with a soft shadow becomes text floating on nothing.
   Give every surface a real border in a system colour, and take the photographs
   out: white text over a photograph the browser cannot recolour is exactly the
   case this mode exists to prevent. */
@media (forced-colors: active) {
  .sky-photo, .dl-sky, .sky-tint, .sky-scrim, .sky-fade, .cloud-deco::before { display: none; }
  .card, .cell, .mode, .plan, .plan-class, .fineprint, .curve-card, .panel, .preview,
  .pv-panel, .pv-rail, .pv-chip, .read-tile, .pv-day, .band-list li, .dl-mobile, .dl-note,
  .nav, .nav-sheet { border: 1px solid CanvasText; }
  .btn, .pv-grade, .pv-pill, .chip, .mode-tag, .plan-tag, .hero-chip, .theme-toggle,
  .ctl output, .tile { border: 1px solid ButtonText; }
  .btn-primary, .pv-grade.g-good { border-width: 2px; }
  .c-spaced, .fr-fill { stroke: Highlight; }
  .c-massed, .fr-track, .curve-grid-line { stroke: GrayText; }
  .fc-bar { fill: Highlight; }
  .curve-mark, .fr-head { stroke: Highlight; fill: Canvas; filter: none; }
  input[type="range"] { forced-color-adjust: auto; }
}
