/**
 * @file
 * Page-level layout.
 *
 * The outgoing theme nested .container > .row > .col-md-9 / .col-md-3 from
 * Bootstrap 4 and applied a fixed `padding: 0 80px` on the footer that broke
 * below 768px. Here the page is a single grid whose named columns every
 * component can opt into, so full-bleed bands and constrained content can be
 * interleaved without wrapper divs.
 */

.page {
  display: flex;
  flex-direction: column;
  min-block-size: 100svh;
}

.page__main {
  flex: 1 0 auto;
}

/**
 * Content grid.
 *
 * Direct children land in the `content` column by default. A child can claim
 * `full` (edge to edge), `wide` (breakout band) or `prose` (narrow measure).
 */
.grid-page {
  display: grid;
  /**
   * Rows sit at the top and keep their own height.
   *
   * A grid's default `align-content` is `stretch`, and `.page__main` is a flex
   * child with `flex: 1 0 auto` — so on any page shorter than the viewport the
   * leftover space was shared out between the auto rows. The skip-link anchor
   * is one of those rows: an empty element that was being inflated to a
   * hundred-odd pixels and pushing the first real row down. That is the gap
   * between the header and an event page's photograph, and it grew on the
   * shortest pages, which is the opposite of what padding does.
   */
  align-content: start;
  grid-template-columns:
    [full-start] minmax(var(--gutter), 1fr)
    [wide-start] minmax(0, calc((var(--wrapper-wide) - var(--wrapper-max)) / 2))
    [content-start] min(var(--wrapper-max), 100% - var(--gutter) * 2)
    [content-end] minmax(0, calc((var(--wrapper-wide) - var(--wrapper-max)) / 2))
    [wide-end] minmax(var(--gutter), 1fr)
    [full-end];
}

.grid-page > * {
  grid-column: content;
}

.grid-page > .breakout-wide { grid-column: wide; }
.grid-page > .breakout-full { grid-column: full; }

/* Simple centred wrapper for contexts outside the page grid. */
.wrapper {
  inline-size: min(var(--wrapper-max), 100% - var(--gutter) * 2);
  margin-inline: auto;
}

.wrapper--wide {
  inline-size: min(var(--wrapper-wide), 100% - var(--gutter) * 2);
}

.wrapper--prose {
  inline-size: min(var(--wrapper-prose), 100% - var(--gutter) * 2);
}

/* Vertical rhythm between page sections. */
.section {
  padding-block: var(--space-section);
}

.section--tight {
  padding-block: var(--space-l);
}

.section--flush-top {
  padding-block-start: 0;
}

.section--flush-bottom {
  padding-block-end: 0;
}

/**
 * A section that contains another section does not pad twice.
 *
 * `page.content` is wrapped in a `.section` by the page template, and several
 * view templates render their own `.section` inside it — so /hubs was getting
 * `--space-section` from the outer box and `--space-l` from the inner one, one
 * on top of the other, which is the band of empty canvas between the header and
 * the cards. The inner section owns the spacing; the outer one steps aside.
 */
.section:has(.section) {
  padding-block: 0;
}

/**
 * An event page opens with a full-bleed photograph, so any gap above it reads
 * as a mistake rather than as breathing room.
 *
 * `:has(.event-detail)` is a DESCENDANT test on purpose. The node is not a
 * direct child of the section — Drupal wraps it in a region and a block — so
 * the child combinator this started as never matched anything on the live site.
 */
.section:has(.event-detail) {
  padding-block-start: 0;
}

/**
 * A region wrapper with nothing to show in it takes no space.
 *
 * `.section--region` is on the wrappers the page template puts round a region
 * — boxes whose whole content is out of the theme's hands.
 *
 * Two ways one ends up empty. The search form is a block in `highlighted`, and
 * js/search.js moves it into the drawer under the header, leaving the region
 * behind: empty, but still inside a padded section. That was the band of blank
 * canvas between the header and the top of an event page's photograph. And a
 * region can hold a block that renders nothing on this particular route, which
 * Twig's `{% if page.region %}` does not catch — the variable is a non-empty
 * render array either way.
 *
 * js/search.js removes the wrappers it empties itself. This is the case it
 * cannot see, and the reason the test asks whether anything that would DRAW is
 * in there rather than whether an element exists: an empty region is still a
 * `<div>` inside a `<div>`, so `:empty` is false all the way down.
 */
.section--region:not(:has(form, p, a, button, img, svg, table, ul, ol, h1, h2, h3, h4, input, iframe)) {
  padding-block: 0;
  border: 0;
}

/* The same for a section left literally empty. */
.section:empty {
  padding-block: 0;
  border: 0;
}

/**
 * A full-bleed band that constrains its own content — and no longer paints.
 *
 * It carried `--surface-1` and a hairline top and bottom, which on the landing
 * page put a large lighter panel behind the council highlights, the newsletter
 * and the hubs strip. With the newsletter now a raised card of its own, that
 * panel was a second surface behind a surface: the card lost its separation
 * from the page and the hubs read as being inside something.
 *
 * The class stays for what it is actually for — claiming the full column and
 * centring a wrapper inside it. `.band--well` is still available where a
 * section genuinely wants a painted ground.
 */
.band {
  grid-column: full;
  background: transparent;
  border-block: 0;
}

.band--well {
  background: var(--surface-well);
}

.band__inner {
  inline-size: min(var(--wrapper-max), 100% - var(--gutter) * 2);
  margin-inline: auto;
  padding-block: var(--space-section);
}

/**
 * Two-column content + sidebar.
 * The old theme hard-coded col-md-9 / col-md-3. This collapses on container
 * width rather than viewport width, so it also behaves inside a narrow region.
 */
.layout-sidebar {
  display: grid;
  gap: var(--space-xl);
  grid-template-columns: 1fr;
  align-items: start;
}

@media (min-width: 62rem) {
  .layout-sidebar {
    grid-template-columns: minmax(0, 1fr) 20.5rem;
  }

  .layout-sidebar--left {
    grid-template-columns: 20.5rem minmax(0, 1fr);
  }

  .layout-sidebar--left > .layout-sidebar__main {
    order: 2;
  }
}

.layout-sidebar__aside {
  position: sticky;
  top: calc(var(--header-offset) + var(--space-m));
}

@media (max-width: 61.999rem) {
  .layout-sidebar__aside {
    position: static;
  }
}

/* Stack utility used inside cards and panels. */
.stack > * + * {
  margin-block-start: var(--stack-space, var(--space-s));
}

.stack--s { --stack-space: var(--space-2xs); }
.stack--m { --stack-space: var(--space-m); }
.stack--l { --stack-space: var(--space-l); }

.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--cluster-space, var(--space-2xs));
}
