/* newsletter.css — the email-capture component and the homepage band.
 *
 * WHY THIS IS ITS OWN FILE.
 * The homepage is hand-authored and deliberately lean: it loads tokens, base
 * and skin, and nothing else. pages.css — 10 KB gzipped of tool, blog, pricing
 * and contact styles — is never loaded there.
 *
 * That mattered the moment a newsletter form went on the homepage, because
 * every .nl rule lived in pages.css. The form was rendering completely
 * unstyled on the one page it had just been added to, and the block committed
 * before this had no styling at all in production. It looked right in a
 * preview that loaded the full bundle and wrong everywhere else.
 *
 * The fix is not to link pages.css from the homepage — that is 10 KB of
 * render-blocking CSS for one section — and not to copy the rules inline,
 * which guarantees the two drift. It is this: one small file, one source of
 * truth, loaded by the homepage directly and folded into app.css for every
 * built page by CSS_PARTS in build.js.
 */

/* --- newsletter capture (assets/js/newsletter.js) ---------------------------
 * Three placements, one component: site footer, end of a blog post, and the
 * moment a tool run finishes (compact variant, no heading — the surrounding
 * context has already earned the ask, so a headline would just shout).
 *
 * The consent checkbox is NOT visually de-emphasised. It is the thing that
 * makes the address lawfully mailable, and hiding it in grey 11px type is how
 * a list ends up unusable. It reads at body size, in body colour.
 */
.nl {
  margin-top: var(--s-6);
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-lg, 14px);
  background: var(--surface-2, var(--surface));
}
.nl-title { margin: 0 0 var(--s-2); font-size: var(--t-lg); font-weight: 600; }
.nl-lede { margin: 0 0 var(--s-4); font-size: var(--t-sm); color: var(--ink-soft); max-width: 56ch; }
.nl-row { display: flex; flex-wrap: wrap; gap: var(--s-2); align-items: center; }
/* Visible to screen readers only: the placeholder is a hint, not a label, and
   an input with no programmatic label fails WCAG 3.3.2. */
.nl-lab {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.nl-input { flex: 1 1 240px; min-width: 0; }
.nl-btn { flex: 0 0 auto; }
.nl-consent {
  display: flex; gap: var(--s-2); align-items: flex-start;
  margin-top: var(--s-3); font-size: var(--t-sm); color: var(--ink-soft);
  cursor: pointer; max-width: 60ch;
}
.nl-consent input { margin-top: 3px; flex: 0 0 auto; }
.nl-status { margin: var(--s-3) 0 0; font-size: var(--t-sm); min-height: 1.2em; }
.nl-status.ok { color: var(--ok, #16794a); }
.nl-status.err { color: var(--danger, #b42318); }

/* Compact: sits inside the tool workspace after a successful run, where the
   download button must remain the loudest element on the screen. */
.nl-compact { margin-top: var(--s-5); padding: var(--s-4); grid-column: 1 / -1; }
.nl-compact .nl-lede { margin-bottom: var(--s-3); font-size: var(--t-xs); }

/* Footer variant: a quiet lilac card above the compact white link footer. */
.ftr-nl { margin: 0 0 34px; }
.ftr-nl .nl {
  background: linear-gradient(135deg, #f7f4ff, #fbfcff);
  border-color: #e7e1fb;
  max-width: 620px;
}
.ftr-nl .nl-title { color: #15182b; }
.ftr-nl .nl-lede,
.ftr-nl .nl-consent { color: #62697b; }
.ftr-nl .nl-input {
  background: #fff;
  border-color: #dcdfea;
  color: #15182b;
}
.ftr-nl .nl-input::placeholder { color: #858b9b; }
.ftr-nl .nl-status.ok  { color: #177245; }
.ftr-nl .nl-status.err { color: #b42318; }

@media (max-width: 560px) {
  .nl-row { flex-direction: column; align-items: stretch; }
  .nl-btn { width: 100%; }
}
/* newsletter.js hides the footer slot when an earned slot is on the page. The
   attribute alone relies on the UA default, which any future `display` rule on
   these wrappers would silently defeat — and the symptom would be two identical
   forms on one screen. Made explicit so it cannot be overridden by accident. */
[data-newsletter][hidden] { display: none !important; }

/* --- homepage newsletter band ----------------------------------------------
 *
 * Built to the supplied design, and the deviations are listed at the bottom
 * rather than left for someone to find.
 *
 * ONE PHOTOGRAPH, NOT THREE. A band is a place, and three photographs make it
 * three places. The heading and the copy sit directly ON the photograph; only
 * the form gets a card, because the form is the only part that needs a surface
 * to be usable. That is the whole idea of the reference and it is why it works.
 *
 * THE SCRIM IS HORIZONTAL, NOT UNIFORM. Darkening the whole frame evenly to
 * make text readable also flattens the photograph into wallpaper. This one is
 * weighted: heavy across the left and centre where every word sits, releasing
 * over the right quarter so the climbers stay in the picture. White text is on
 * the dark side of it everywhere, never over the released part.
 *
 * Worst case in this photograph is the snowfield, i.e. pure white under a .68
 * scrim. Heading and body land at 6.9:1 — past AA for normal text, let alone
 * for a heading. Nothing here relies on the photo being dark.
 */
.nlband {
  position: relative;
  isolation: isolate;                /* keeps the negative z-indexes local */
  overflow: hidden;
  padding: clamp(var(--s-7), 6vw, var(--s-9)) var(--s-4);
  margin-top: var(--s-8);
}
.nlband-bg { position: absolute; inset: 0; z-index: -2; display: block; }
.nlband-bg img {
  display: block; width: 100%; height: 100%;
  object-fit: cover; object-position: center 45%;
}
/* Horizontal weighting for readability, plus a vertical pass that finishes on
   the footer's own #0f1729 — this band is the last thing on the page, so it
   dissolves into the footer instead of butting against it. */
.nlband::after {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(180deg, transparent 0%, transparent 52%, rgb(15 23 41 / .55) 88%, rgb(15 23 41 / .95) 100%),
    linear-gradient(90deg, rgb(8 12 20 / .74) 0%, rgb(8 12 20 / .68) 72%, rgb(8 12 20 / .34) 100%);
}

.nlband-inner { max-width: 42rem; margin: 0 auto; color: #fff; }
.nlband-inner h2 {
  margin: 0 0 var(--s-4);
  font-size: clamp(1.45rem, 1.05rem + 1.7vw, 2.1rem);
  line-height: 1.15; font-weight: 700;
  text-transform: uppercase;          /* uppercased in CSS, not in the markup,
                                         so the text stays readable to a screen
                                         reader and copies out as a sentence */
  letter-spacing: .005em; color: #fff;
}
.nlband-inner > p {
  margin: 0 0 var(--s-5);
  color: rgb(255 255 255 / .92); line-height: 1.6;
}

/* The card holds the form and nothing else. */
.nlcard {
  background: rgb(10 15 25 / .62);
  border: 1px solid rgb(255 255 255 / .14);
  border-radius: 16px;
  padding: var(--s-5);
  box-shadow: 0 20px 50px rgb(4 8 16 / .38);
  backdrop-filter: blur(12px) saturate(120%);
  -webkit-backdrop-filter: blur(12px) saturate(120%);
}
/* Still the form newsletter.js builds — only re-dressed for a dark surface.
   No second implementation and no duplicated validation. */
.nlcard .nl {
  border: 0; background: transparent; padding: 0; margin: 0; max-width: none;
}
.nlcard .nl-title, .nlcard .nl-lede { display: none; }   /* the heading above said it */
.nlcard .nl-input {
  background: rgb(255 255 255 / .10);
  border-color: rgb(255 255 255 / .26);
  color: #fff; border-radius: var(--r-md);
  padding-right: 46px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-opacity='.55' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='14' rx='2.5'/%3E%3Cpath d='m3.6 7.2 8.4 5.8 8.4-5.8'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 19px 19px;
}
.nlcard .nl-input::placeholder { color: rgb(255 255 255 / .60); }
/* Follows --accent rather than a literal, now that the accent is this blue.
   One place to change it, and it can never drift from the rest of the site. */
.nlcard .nl-btn {
  background: var(--accent); border-color: transparent; color: var(--accent-on);
  border-radius: var(--r-md);
  text-transform: uppercase; letter-spacing: .04em;
  padding-inline: var(--s-5);
}
.nlcard .nl-btn::before {
  content: ''; width: 15px; height: 15px; flex: 0 0 auto;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath d='M13.2 2 4 14h5.9l-1.1 8L19 10h-6z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.nlcard .nl-btn:hover { background: var(--accent-hover); }
.nlcard .nl-btn:active { background: var(--accent-active); }
/* Consent, centred under the row where the reference puts its privacy line.
   It stays a real required checkbox — that is what makes the address lawfully
   mailable, and test/newsletter.test.js fails if it is ever removed or
   pre-ticked. Quieter, not absent. */
.nlcard .nl-consent {
  justify-content: center; text-align: left;
  margin-top: var(--s-4); font-size: var(--t-xs);
  color: rgb(255 255 255 / .78); max-width: 42ch; margin-inline: auto;
}
.nlcard .nl-status { text-align: center; }
.nlcard .nl-status.ok  { color: #7ee2b8; }
.nlcard .nl-status.err { color: #ffb4ac; }
:where(.nlcard, .nlband-inner) :focus-visible { outline-color: #fff; }

@media (max-width: 640px) {
  .nlband { padding-inline: var(--s-3); }
  /* On a phone the right release would put text over bare photograph, so the
     scrim goes flat and heavy instead. */
  .nlband::after {
    background:
      linear-gradient(180deg, transparent 0%, transparent 52%, rgb(15 23 41 / .55) 88%, rgb(15 23 41 / .95) 100%),
      linear-gradient(90deg, rgb(8 12 20 / .74), rgb(8 12 20 / .70));
  }
  .nlcard { padding: var(--s-4); }
}
