/**
 * @file
 * Subscribe band.
 *
 * Same Campaign Monitor form and the same two list checkboxes (weekly /
 * monthly) as the outgoing theme — the field names cm-name, cm-okihruh-okihruh,
 * cm-ol-jkfdjy and cm-ol-jkfdjj are preserved verbatim in the Twig so existing
 * subscriber lists keep working. Only the presentation changed: it was an
 * unlabelled stack of inputs in the footer, and is now a titled band with
 * visible labels and a stated expectation of what arrives.
 *
 * The form is always open. A "Subscribe Now" disclosure was added here to match
 * the outgoing site and then removed at Council's request — the band exists to
 * collect an address, and a control whose only job is to reveal the field that
 * collects it is a step with nothing in it.
 */

/**
 * A CARD IN THE CONTAINER, NOT A BAND ACROSS THE SCREEN.
 *
 * It was 100vw with a hairline top and bottom — a full-width stripe that read
 * as part of the footer's furniture. The client asked for the section to sit
 * inside the page container with rounded corners and some depth, and to look
 * the same on every page it appears on, so this is the one rule that decides
 * that: the same width as the header and the content above it, wherever the
 * `subscribe` region is printed.
 *
 * THE DEPTH IS FOUR SHADOWS, NOT ONE
 *  - a 1px inset highlight along the top edge: the light that makes a raised
 *    surface look raised, and the only part of the effect that is doing real
 *    work at a glance;
 *  - a tight 1px drop, which is the card's contact shadow;
 *  - a wide, very soft drop that separates it from the page;
 *  - a magenta bloom underneath at low opacity, so the card sits in the site's
 *    own light rather than on a grey plane.
 *
 * One `box-shadow: 0 20px 40px black` would have given a drop shadow and no
 * dimension; it is the top highlight against the lower drops that reads as
 * three-dimensional.
 *
 * Removing 100vw also removes one of the four bands that made the document
 * wider than the window — see the note on `html { overflow-x: clip }`.
 */
.subscribe {
  position: relative;
  grid-column: content;

  /**
   * IT FILLS THE CONTAINER IT IS IN. IT DOES NOT MAKE ITS OWN.
   *
   * This was `min(var(--wrapper-max), 100% - var(--gutter) * 2)` — the site's
   * standard wrapper — and that is wrong for the same reason it was wrong on
   * the event page's grid: on the live site the block is placed in a region
   * inside a section inside `.band__inner`, every one of which has ALREADY
   * taken the gutter off. Applying it again inset the card 43px inside the
   * cards above it at desktop width and pushed the form's column past the
   * card's own padding, where `overflow: hidden` cut the email field off.
   *
   * `100%` of whatever contains it, capped at the wrapper: nested in the page
   * container it lines up with the content exactly, and printed straight into
   * the page shell it still cannot exceed 1320px. The one context that has no
   * container of its own — the `subscribe` region on interior pages — gets one
   * in the page template (`.subscribe-region`), so the card keeps its gutters
   * on a phone.
   */
  inline-size: 100%;
  max-inline-size: var(--wrapper-max);
  margin-inline: auto;
  margin-block: var(--space-xl);

  /**
   * NOT `overflow: hidden`.
   *
   * The rounded corners do not need it — nothing inside paints to the card's
   * edge — and it was doing real harm: when the form's column came out wider
   * than the card, the clip SLICED THE EMAIL FIELD IN HALF instead of letting
   * it show. A layout bug you can see is a layout bug someone fixes; a layout
   * bug that is neatly cut off at a rounded corner looks like a design.
   *
   * The layout below can no longer overflow (the fields wrap rather than
   * spill), so this is belt and braces on top of that — but it is the belt
   * that fails visibly.
   */

  /* Curvy, and proportional: 20px on a phone, 32px at full width. A fixed
     radius that suits a 1320px card looks like a mistake on a 320px one. */
  border-radius: clamp(1.25rem, 0.75rem + 2vw, 2rem);
  border: 1px solid var(--border-subtle);

  background:
    radial-gradient(
      85% 140% at 100% 0%,
      color-mix(in srgb, var(--me-magenta) 26%, transparent) 0%,
      transparent 62%
    ),
    linear-gradient(
      170deg,
      var(--surface-2) 0%,
      var(--surface-1) 58%
    );

  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--me-white) 14%, transparent),
    0 1px 2px color-mix(in srgb, var(--me-black) 45%, transparent),
    0 22px 44px -26px color-mix(in srgb, var(--me-black) 85%, transparent),
    0 44px 90px -64px color-mix(in srgb, var(--me-magenta) 60%, transparent);
}

/**
 * The container for the one case that has none: the `subscribe` region.
 *
 * page.html.twig and page--front.html.twig print that region straight into the
 * page shell, where "100% of my container" is the whole viewport. This is the
 * page's own wrapper, so the card lands on the content column there too — and
 * keeps a gutter either side on a phone.
 */
.subscribe-region {
  inline-size: min(var(--wrapper-max), 100% - var(--gutter) * 2);
  margin-inline: auto;
}

/* The page grid is not always the parent — this only matters when it is. */
.grid-page > .subscribe {
  grid-column: content;
}

/**
 * TWO HALVES THAT SHRINK AND WRAP — NOT TWO GRID TRACKS.
 *
 * This was a grid: `minmax(0, 1fr) minmax(0, 1.05fr)`, with `min-inline-size: 0`
 * on the items so neither could overflow its track. That is the correct grid,
 * and it still put the form past the card's right edge on the live site.
 *
 * WHY. Grid track sizing needs a DEFINITE container width. Give the card an
 * ancestor that is sized by its content — a float, an inline-block, a flex or
 * grid item that shrink-wraps, a table cell, an editor's pasted layout — and
 * the width is indefinite while the tracks are sized, so the `fr` tracks are
 * resolved against the content's own max-content instead. The card is then
 * capped at 1320px by its own `max-inline-size`, while the grid inside it keeps
 * the wider track sizes it had already worked out. The card looks right and the
 * form hangs off the end of it: exactly the screenshot.
 *
 * A wrapping flex row cannot do that. Flex items shrink when the line is too
 * long (`min-inline-size: 0` is what allows shrinking past their content), and
 * when they cannot shrink far enough the line wraps. Whatever the ancestor
 * does, the two halves end up inside the card.
 *
 * The same lesson as the two text fields below it, learned twice. Anywhere the
 * width of the container is not ours to guarantee, flex over grid.
 */
.subscribe__inner {
  inline-size: 100%;
  margin-inline: auto;
  padding: clamp(var(--space-l), 1.5rem + 2vw, var(--space-2xl))
           clamp(var(--space-m), 1rem + 2vw, var(--space-2xl));
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-l);
  align-items: start;
}

.subscribe__inner > * {
  /* 20rem is the width below which the two halves are better stacked than
     squeezed; above it they share the row. */
  flex: 1 1 20rem;
  min-inline-size: 0;
}

@media (min-width: 56rem) {
  .subscribe__inner {
    gap: var(--space-2xl);
    /* Centred against the heading rather than pinned to the top of it: in a
       card the form is one of two things being weighed, not a footnote under a
       title. */
    align-items: center;
  }

  /* The form takes slightly more of the row than the words do — it has two
     fields side by side to fit and the heading has a measure it should not
     exceed anyway. */
  .subscribe__inner > .subscribe__form {
    flex-grow: 1.15;
  }
}

.subscribe__title {
  font-size: var(--step-3);
  max-inline-size: 18ch;
  margin-block-end: var(--space-2xs);
}

.subscribe__text {
  color: var(--text-secondary);
  max-inline-size: 34rem;
}

/**
 * THE FORM IS CAPPED IN ITS OWN UNITS, NOT ONLY BY ITS SHARE OF THE ROW.
 *
 * Everything above makes the two halves shrink and wrap, which is the right
 * layout — but every one of those mechanisms depends on the container's width
 * being known when the row is laid out, and the whole reason this bug has been
 * hard is that some ancestor on the live site does not give a definite one.
 *
 * `min(100%, 34rem)` needs no such knowledge. Whatever mode the browser is in,
 * whatever the parent does, this box is at most 544px wide and at most as wide
 * as what contains it, so its contribution to any intrinsic-size calculation is
 * bounded — and 544 + the intro's own 544 cap + the 64px gap is inside the
 * card at every width the card is used at. Proved: with this cap in place the
 * PRE-FIX grid, forced back on inside a shrink-to-fit parent, no longer
 * overflows either. The layout above is the fix; this is the floor under it.
 *
 * 34rem and not less: below about 32rem the two frequency checkboxes stop
 * fitting on one line, and a form that reads "Weekly / Monthly" stacked looks
 * like two questions rather than one.
 */
.subscribe__form {
  display: grid;
  gap: var(--space-s);
  min-inline-size: 0;
  max-inline-size: min(100%, 34rem);
  /* Capped and therefore narrower than its share of the row: keep it against
     the card's trailing edge rather than floating in the middle of the gap. */
  margin-inline-start: auto;
}

/**
 * THE TWO TEXT FIELDS: A FLEX ROW THAT WRAPS, NOT A GRID THAT DOES NOT.
 *
 * Three goes at this, and the reason the first two failed is worth stating.
 *
 * `auto-fit, minmax(13rem, 1fr)` sized the fields from their content, and a
 * 200-character `maxlength` on the email input gives it an enormous intrinsic
 * width, so the name field was pushed underneath it. Stated tracks —
 * `repeat(2, minmax(0, 1fr))` — fixed that, and each field became exactly half
 * of whatever the form column was. But "exactly half of the column" is only
 * right while the column is wide enough for two fields, and a GRID TRACK
 * CANNOT WRAP: when the column came out narrower than the row needed, the row
 * kept its two halves and ran past the card's padding, where the card's
 * `overflow: hidden` cut the email field off at the corner. That is the
 * screenshot the client sent.
 *
 * A wrapping flex row has no such failure mode. `flex: 1 1 12rem` asks for
 * 12rem, takes an equal share of anything spare, and gives way when there is
 * not enough — the second field drops to its own line instead of hanging off
 * the edge. `min-inline-size: 0` is what lets a flex item shrink below its
 * content's intrinsic width at all; without it the input's own idea of how wide
 * it should be wins, which is where this started.
 */
.subscribe__fields {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-s);
  max-inline-size: 100%;
}

.subscribe__fields .form-item {
  flex: 1 1 12rem;
  min-inline-size: 0;
  margin: 0;
}

/* Belt and braces against a widget or a `size` attribute setting its own
   width — the inputs must fill their track and never exceed it. */
.subscribe__fields input,
.subscribe__form input[type="text"],
.subscribe__form input[type="email"] {
  inline-size: 100%;
  max-inline-size: 100%;
  box-sizing: border-box;
}

.subscribe__form fieldset {
  min-inline-size: 0;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
}

.subscribe__form legend {
  padding: 0;
  margin-block-end: var(--space-3xs);
}

.subscribe__options {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs) var(--space-l);
}

.subscribe__form .form-actions {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  position: static;
}

/**
 * The "choose a list" message.
 *
 * Not colour alone: the message is a sentence that says what to do, next to
 * checkboxes that carry `aria-invalid`, so it does not depend on being seen as
 * red. (js/subscribe.js writes it; there was no message at all before, and the
 * form's answer to "no list ticked" was Campaign Monitor's error page.)
 */
.subscribe__error {
  margin: 0;
  color: var(--me-danger, #ff6b6b);
  font-size: var(--step--1);
  font-weight: var(--weight-medium);
}

/* `.subscribe__privacy` was the "We use your email only…" line under the
   button. The class is kept for a moment so a cached render of the old template
   does not paint an unstyled paragraph; the markup no longer emits it. */
.subscribe__privacy {
  color: var(--text-muted);
  font-size: var(--step--2);
}

/**
 * Editor HTML is not a layout you control.
 *
 * The intro is a rich-text field: it can contain divs pasted from the old
 * theme, with `float`, `position: absolute`, negative margins and `.desktop` /
 * `.mobile` display switches still on them. None of that belongs in this band,
 * and any of it can push content out of the wrapper — it once pushed the
 * "Subscribe Now" control clean off the left edge of the viewport. Reset the
 * properties that move a box; leave everything that only paints one.
 */
.subscribe__intro {
  position: relative;
  min-inline-size: 0;
}

.subscribe__intro :is(div, p, span, a, ul, li, section) {
  float: none;
  position: static;
  inset: auto;
  transform: none;
  margin-inline-start: 0;
  max-inline-size: 100%;
}

/* ---------------------------------------------------------------------------
 * Editor-managed intro from the subscribe view
 * ------------------------------------------------------------------------ */
/* `:is()` rather than `:where()`: :where() contributes no specificity, so the
   `.subscribe__intro p` rule below out-ranked it and painted the heading in the
   muted body colour. :is() takes the specificity of its most specific argument
   (p:first-child), which is what this rule needs to win. */
.subscribe__intro > :is(h1, h2, h3, p:first-child) {
  font-size: var(--step-3);
  font-weight: var(--weight-bold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  max-inline-size: 18ch;
  margin-block-end: var(--space-2xs);
  /* The heading arrives as a <p> from the editor, so without this it inherits
     the muted body colour set below and reads as caption text. */
  color: var(--text-primary);
}

.subscribe__intro p {
  color: var(--text-secondary);
  max-inline-size: 34rem;
}

.subscribe__intro a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3xs);
  color: var(--text-accent);
  font-weight: var(--weight-bold);
  text-decoration: none;
}

.subscribe__intro a:hover {
  text-decoration: underline;
}

.subscribe__intro img {
  display: inline;
  inline-size: 1em;
  block-size: 1em;
}

/**
 * INSIDE A BAND, THE BAND PROVIDES THE AIR.
 *
 * The card carries its own vertical margin for the one context that has none —
 * the `subscribe` region on an interior page, where it sits directly on the
 * page shell. In the home page's band that margin is a third helping: the
 * section above it ends with its own bottom padding, `.band__inner` adds
 * `--space-section` on top of that, and then the card added 48px more. Three
 * spacings for one gap, and they were adding up to a screenful of nothing
 * between the last event card and the newsletter.
 *
 * The band's padding is the one that belongs to the band, so the card's own
 * margin comes off — and the band closes up against the section above it,
 * whose padding has already said "this is the end of that".
 */
.band .subscribe,
.band__inner .subscribe {
  /* The TOP margin only. Whatever follows the card inside the band — the hubs
     section on the front page — still wants the space underneath it. */
  margin-block-start: 0;
}

.band__inner:has(> .region .subscribe) {
  padding-block-start: var(--space-l);
}

/* The section above a band has already spaced itself; a band that follows one
   does not need to start with a full section's padding of its own. The two
   halves are split evenly so the gap comes to the same 64px as the shape
   below, whichever way the block happens to be placed. */
.section + .band > .band__inner {
  padding-block-start: var(--space-l);
}

.section:has(+ .band) {
  padding-block-end: var(--space-l);
}

/**
 * AND THE SAME COUNT, IN THE SHAPE THE FRONT PAGE ACTUALLY USES.
 *
 * The newsletter is not always in a band. Placed in `featured_bottom_second`
 * it lands in a `.section.section--flush-top`, and the gap above it was three
 * spacings deep again: the listing section's bottom padding (80px), then the
 * card's own 48px margin, with the flush-top modifier contributing nothing in
 * between. Nothing was IN that space — it read as a screenful of black canvas
 * between the last event card and the newsletter.
 *
 * The modifier already says "the box above has spaced us"; the card's own
 * margin is the third helping, so it comes off, and the listing's bottom
 * padding drops to a single step. One gap, stated once.
 */
.section--flush-top .subscribe {
  margin-block-start: 0;
}

.section:has(+ .section--flush-top) {
  /* One step, not two. 64px between the last card and the newsletter reads as
     "a new thing starts here"; 208px read as the end of the page. */
  padding-block-end: var(--space-2xl);
}

/**
 * An empty leftover takes no space.
 *
 * A view whose pager has been emptied — js/reveal.js removes stray pagers, and
 * a "see all" control it cannot act on — leaves the container behind, and a
 * container with margins is a gap with nothing in it. This is the difference
 * between a measured space and an accident.
 */
.view__footer:empty,
.view__header:empty,
.view .pager:empty,
.view nav.pager:not(:has(a, button, .pager__item)) {
  display: none;
}
