/*
Theme Name: Janet Gatehouse
Theme URI: https://janetgatehouse.au
Author: Lachlan Collins
Description: A minimal block theme for the Janet Gatehouse mayoral site. Built for a four-page brochure site with an election-compliance footer; deliberately carries no commercial or e-commerce surface.
Version: 1.0.0
Requires at least: 6.7
Tested up to: 7.0
Requires PHP: 8.2
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: janet
*/

/* Component CSS ported from mockup/styles.css — the agreed design. Colours
   and font stacks are aliased from the palette/fontFamilies theme.json
   defines, so a hex value or font stack has exactly one home; nothing here
   restates one. Everything mockup-only (the .mockbar top bar, the "Hide
   placeholder marks" toggle, .ph/.block-ph/.ph-outline marking, the
   --flag tokens) is deliberately left behind — see CLAUDE.md. */

/* The header, hero, pillar band and footer are full-bleed bands that must sit
   flush against each other, as they do in the mockup. WordPress ships
   `:where(.wp-site-blocks) > * { margin-block-start: 24px }`, which renders as
   a pale strip between every band — most visibly under the header and either
   side of the pillar band. `:where()` carries zero specificity, so a plain
   selector overrides it without !important. */
.wp-site-blocks > * {
  margin-block-start: 0;
}

/* Same reason, one level in: the full-bleed bands stack directly against each
   other, so the block gap between them shows as a pale seam — clearest where
   the gold wave meets the navy pillar band. Scoped to the band classes rather
   than to `main > *`, because a content page's title and post content are also
   direct children of main and do want their spacing. */
.hero,
.pillars,
.band,
.band-dark,
.section-surface,
.band-paper,
.photo-band,
.cta {
  margin-block-start: 0;
  margin-block-end: 0;
}

:root {
  color-scheme: light;

  --navy: var(--wp--preset--color--navy);
  --navy-deep: var(--wp--preset--color--navy-deep);
  --navy-mid: var(--wp--preset--color--navy-mid);
  --navy-line: var(--wp--preset--color--navy-line);

  --gold: var(--wp--preset--color--gold);
  --gold-bright: var(--wp--preset--color--gold-bright);
  --gold-tint: var(--wp--preset--color--gold-tint);

  --green: var(--wp--preset--color--green);
  --green-tint: var(--wp--preset--color--green-tint);
  --green-ring: var(--wp--preset--color--green-ring);

  --ink: var(--wp--preset--color--ink);
  --ink-soft: var(--wp--preset--color--ink-soft);
  --muted: var(--wp--preset--color--muted);

  --paper: var(--wp--preset--color--paper);
  --surface: var(--wp--preset--color--surface);
  --line: var(--wp--preset--color--line);

  --display: var(--wp--preset--font-family--display);
  --sans: var(--wp--preset--font-family--sans);
  --accent: var(--wp--preset--font-family--accent);
  --quote: var(--wp--preset--font-family--quote);

  --wrap: 70rem;
  --radius: 10px;
}

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

body {
  -webkit-font-smoothing: antialiased;
}

/* Display headings: heavy, tight, uppercase — the graphic's headline voice.
   Sizes are set directly here (not via theme.json elements) so this
   component CSS is the one place heading typography is decided. */
h1, h2, h3 {
  font-family: var(--display);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -0.01em;
  color: var(--navy);
  margin: 0 0 0.5em;
}

h1 { font-size: clamp(2.1rem, 5.5vw, 3.4rem); text-transform: uppercase; }
h2 { font-size: clamp(1.5rem, 3.2vw, 2.1rem); text-transform: uppercase; }
/* h3 is mixed case: a section has one capitalised headline, and the subheads
   under it read as text, not as more headline. */
h3 { font-size: 1.15rem; }

p { margin: 0 0 1.1em; }
a:hover { color: var(--navy); }

/* The rule above is written for links on the light page. The navy header and
   footer are the same document, so their links inherit it and hover to navy on
   navy — the brand disappears. The dark fields declare their own hover once,
   rather than each element patching it. */
.site-header a:hover,
.site-header a:focus-visible,
.site-footer a:hover,
.site-footer a:focus-visible { color: #fff; }

.wrap {
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: 1.25rem;
}

/* ---------- Header ----------
   Navy, continuous with the hero field below it. */

.site-header {
  background: var(--navy);
  color: #fff;
}

.site-header .wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 2rem;
  align-items: center;
  justify-content: space-between;
  padding-block: 1rem;
}

/* The name-over-tagline block, used by BOTH the header and the footer --
   which is why this is scoped to the class and not to either location. The
   first version of this rule was written as `.site-header .brand-block` and
   left the footer stretched, because the two are the same component and only
   one of them got fixed.

   gap:0 because the tagline carries its own margin-top, exactly as the
   mockup's .brand span does. A WordPress flex group otherwise inherits
   --wp--style--block-gap (1.5rem here), which pushes the tagline away from
   the name and makes the band half again as tall as the design. */
.brand-block {
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* The mockup's tagline is a <span> inside the brand link, so it inherits
   that link's line-height: 1.1. WordPress's is a <p>, which inherits the
   body's 1.65 -- about 7px taller at this font size, which is most of why
   the header and footer bands were taller than the design. Both are set
   here, on the shared block, rather than twice by location. */
.brand-block .wp-block-site-title,
.brand-block .wp-block-site-tagline {
  margin: 0;
  line-height: 1.1;
}

.brand-block .wp-block-site-tagline {
  margin-top: 0.25rem;
}

.site-header .wp-block-site-title,
.site-header .wp-block-site-title a {
  font-family: var(--display);
  font-size: 1.25rem;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: #fff;
  text-decoration: none;
  line-height: 1.1;
}

.site-header .wp-block-site-tagline {
  display: block;
  font-family: var(--sans);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold);
  margin: 0.25rem 0 0;
}

/* Nav is always visible — no hamburger, no hidden items. Four links fit. */
.site-header .wp-block-navigation {
  --wp--style--block-gap: 0.35rem 1.4rem;
}

.site-header .wp-block-navigation a {
  color: #cfdcea;
  text-decoration: none;
  font-size: 0.88rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding-block: 0.25rem;
  border-bottom: 2px solid transparent;
}

.site-header .wp-block-navigation .current-menu-item > a,
.site-header .wp-block-navigation a[aria-current="page"] {
  color: #fff;
  border-bottom-color: var(--gold);
}

/* ---------- Hero ---------- */

.hero {
  position: relative;
  /* The portrait is sunk past this box's bottom edge on purpose, so the hero
     clips her: nothing of her reaches the pillar band or the document, and the
     bleed can never produce a scrollbar. See .portrait-cutout. */
  overflow: hidden;
  /* Named because .portrait-cutout sinks itself by exactly this much — the two
     have to move together or she stops short of the curve. */
  --hero-pad-bottom: clamp(4rem, 9vw, 7rem);
  --hero-wash: 1;
  background: linear-gradient(160deg, var(--navy-mid) 0%, var(--navy) 52%, var(--navy-deep) 100%);
  color: #fff;
  padding-top: clamp(2rem, 5vw, 3.5rem);
  padding-bottom: var(--hero-pad-bottom);
}

.hero-grid {
  display: grid;
  gap: clamp(2rem, 5vw, 3.5rem);
  align-items: center;
}

@media (min-width: 62rem) {
  /* Even columns, not copy-weighted: the portrait can only rise by growing
     (see .portrait-cutout), so the figure column is what buys her height. */
  .hero-grid { grid-template-columns: 1fr 1fr; }
}

/* ---------- Hero backdrop ----------
   The graphic puts a photograph of the place behind the headline and the
   portrait. Its own version of that band is a composited causeway and is
   synthetic, so it cannot ship (docs/media.md); the photograph here is Marion
   Bay Lookout, cropped above the railing and the interpretive sign by
   tools/build-images.sh. It is a stand-in for a photograph Janet chooses, not
   a settled choice — docs/open-questions.md 14.

   Two layers, not one: the photograph, then a navy wash weighted to the left
   so the display type keeps its contrast whatever the crop does behind it.
   Both sit at z-index 0; the content and the curve raise themselves above. */
.hero::before,
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
}

.hero::before {
  /* The vertical focus is only ever felt on a short hero: the home hero is deep
     enough that the 1600x700 crop covers it with no vertical slack to move, so
     the whole frame shows there whatever this says. The About and Contact heroes
     are half that height, and at 32% their window sat in the empty top-of-frame
     sky — a navy-washed slab with nothing in it. 70% pulls the window down onto
     the band that carries the detail: the hills on the horizon and the water,
     with the beach at the curve. Lower still lands the text on bright sand. */
  background: url("assets/hero-backdrop.webp") center 70% / cover no-repeat;
}

/* One gradient, scaled by --hero-wash. The home hero sets the display type over
   the brightest part of the frame and needs the full wash; a short hero has less
   photograph to show and cannot afford to bury what little it has, so it dials
   the same ramp back rather than defining a second one. */
.hero::after {
  background: linear-gradient(
    100deg,
    color-mix(in srgb, var(--navy) calc(100% * var(--hero-wash)), transparent) 0%,
    color-mix(in srgb, var(--navy) calc(92% * var(--hero-wash)), transparent) 34%,
    color-mix(in srgb, var(--navy) calc(70% * var(--hero-wash)), transparent) 66%,
    color-mix(in srgb, var(--navy-deep) calc(82% * var(--hero-wash)), transparent) 100%
  );
}

/* The curve passes in *front* of the portrait, and that ordering is the whole
   trick: the photograph is cropped at Janet's chest, so wherever she ends she
   ends on a straight line. Behind the curve that line is never drawn — the
   green-and-gold band is simply what she stands behind, the way she disappears
   into the bottom band of the campaign graphic. In front of it she is cut in
   open navy instead, and reads as a pasted rectangle. She still crosses the
   photograph band above, which is where motif 3's depth actually comes from. */
.hero > .wrap { position: relative; z-index: 2; }
.hero .portrait-cutout { position: relative; z-index: 3; }
.hero .wave { z-index: 4; }

/* ---------- The cut-out portrait ----------
   Motif 3 of docs/design-language.md: Janet overlaps the band edges rather than
   sitting inside a frame, which is what stops the hero being stacked
   rectangles. Two properties stage her, and both are measured rather than
   eyeballed.

   aspect-ratio + object-fit crop the box to the top of the frame, so the
   element is shorter than the photograph and the layout never has to reserve
   room for a torso nobody sees. This is what keeps her large and central in
   her column instead of sunk out of sight by a huge negative margin.

   How much of the photograph may show is a hard limit, not taste, and both
   numbers are measured off the file rather than eyeballed: scanning the alpha
   row by row, her right sleeve first grazes the frame edge at row 785 of 1200
   (65%) and is solidly against it by row 840. Past there the silhouette stops
   being an outline and becomes the crop. The aspect-ratio pins the box's own
   bottom to row 860 at every rendered width — a ratio fixes the photo row, not
   a pixel count — and the last ~30px of the box is behind the curve's fill, so
   what a reader actually sees stops near row 810, inside the faint head of
   that ramp.

   She rises by growing, never by translating. Her base is pinned to the hero's
   bottom edge (below), so a wider box is the only thing that lifts her head up
   the field, which is what the even hero columns are for. Translating her up
   would carry the straight base out from behind the curve — the one thing this
   staging exists to prevent.

   The block-end margin then sinks the box's own straight base to the hero's
   bottom edge, where the curve's fill is drawn over her. It is derived from
   --hero-pad-bottom rather than restated, so the two cannot drift apart. */
.portrait-cutout {
  display: block;
  width: 100%;
  max-width: 22rem;
  /* height: auto is load-bearing, not tidiness: the markup carries width/height
     attributes for layout stability, and that height is a presentational hint
     with a real used value — aspect-ratio below is ignored until it is auto. */
  height: auto;
  aspect-ratio: 798 / 860;
  object-fit: cover;
  object-position: center top;
  margin-inline: auto;
  margin-block-end: calc(-1 * var(--hero-pad-bottom));
  filter: drop-shadow(0 18px 30px rgb(2 20 40 / 45%));
}

/* Bottom-aligned so the sink above is measured from a known edge — the hero's
   content box — instead of from wherever vertical centring happened to leave
   her. */
.hero-grid .hero-figure { align-self: end; }

@media (min-width: 62rem) {
  .portrait-cutout { max-width: 34rem; }
}

.hero h1, .hero h2 { color: #fff; }

/* "Keeping" — the graphic's lead-in, underscored in gold. Kaushan Script is
   the brush face; it runs lighter and narrower per em than the Georgia italic
   it replaced, so the size is set larger here than the visual weight suggests
   to hold its own against the display caps below it. Colour and shadow are
   the sign-off's (.sign-off below), for the same reason: both lines sit
   over the photographic backdrop, and flat gold reads dull where the sky
   behind it is light. The rule under it stays flat gold on purpose — it is a
   drawn stroke, not lettering, and matches the hero's other rules. */
.script-lead {
  font-family: var(--accent);
  font-size: clamp(2.6rem, 6.4vw, 3.9rem);
  font-weight: 400;
  line-height: 1;
  color: var(--gold-bright);
  text-shadow: 0 2px 10px rgb(2 20 40 / 55%);
  margin: 0 0 0.1em;
}

.script-lead::after {
  content: "";
  display: block;
  width: 7.5rem;
  height: 3px;
  background: var(--gold);
  border-radius: 2px;
  margin-top: 0.1em;
}

.hero h1 {
  font-size: clamp(2.6rem, 8vw, 4.6rem);
  margin-bottom: 0.35em;
}

.hero h1 span {
  display: block;
  font-size: 0.58em;
  letter-spacing: 0.005em;
}

/* Gold rule under the hero wordmark. */
.rule {
  max-width: 30rem;
  height: 2px;
  background: var(--gold);
  opacity: 0.85;
  margin-bottom: 1.4rem;
}


/* Mixed case, and a size step below the headline: the graphic sets the name
   in the same caps as SORELL, but on the page that made two headlines and a
   hero of seven capitalised lines that read as one shouting block. The one
   line of capitals is the headline; the name is who is saying it. */
.hero .name {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(1.6rem, 3.8vw, 2.4rem);
  line-height: 1.05;
  letter-spacing: -0.015em;
  margin: 0 0 0.5rem;
}

/* The graphic's boxed "MAYOR for SORELL 2026" plate. On the site it is the
   letterhead's (.letter-head below), not the hero's: the header tagline
   already says it on every page, and the hero lost it with the values list
   and the lede when the column was thinned (decisions.md, 2026-09-09). */
.office {
  display: inline-block;
  background: rgba(255, 255, 255, 0.09);
  border: 1px solid var(--navy-line);
  border-radius: 4px;
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(0.95rem, 2vw, 1.15rem);
  letter-spacing: 0.02em;
  padding: 0.4rem 1rem;
  margin: 0 0 1.2rem;
}

.office em {
  font-family: var(--accent);
  font-weight: 400;
  font-size: 1.2em;
  letter-spacing: 0;
  color: var(--gold);
  padding-inline: 0.15em;
}

/* The ballot instruction: "Vote", the 1 in its ballot square, "Mayor and
   Councillor" (decisions.md, 2026-09-09). The square is drawn as the ballot
   paper, the how-to-vote cards and other candidates' corflutes draw it
   (design-language.md, "The ballot square"): a ruled square, not a filled
   tile, in the reverse of its ground -- white on navy, nothing filled in -- a
   heavy rule, and a bold numeral in the rule's colour filling most of the box.
   A rounded, shadowed white tile read as a keycap; a white tile with a dark
   rule showed its rule on one side only. Drawn in
   ems so one font-size sizes the whole lockup, and allowed to wrap so the
   office drops to its own line in a narrow phone column rather than
   shrinking. The same lockup is on every poster artboard (poster/poster.css
   .vote), sized for each. */
.vote {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25em 0.3em;
  margin: 0 0 1.6rem;
  font-family: var(--display);
  font-weight: 800;
  /* A step below the name and a step above the plaque size the poster
     keeps: the name is who, this is the ask, and on a phone it has to be
     the line the thumb stops on. */
  font-size: clamp(1.5rem, 3.6vw, 2.1rem);
  line-height: 1;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  color: #fff;
}

.vote-verb {
  color: var(--gold-bright);
  text-shadow: 0 2px 10px rgb(2 20 40 / 55%);
}

/* Sized in the numeral's own em: the glyph is a step larger than the words
   so its cap height fills about two-thirds of the box, as a written 1 does
   on the paper, and the box and its rule scale with it. */
.vote-box {
  /* A block container, not a grid: text-box only applies to one. A grid's
     place-items: center centres the numeral's line box, and the line box
     carries the face's descent space under a glyph that has no descender,
     so the 1 lands about a fifteenth of the box low in every face tried.
     text-box trims the line box to the cap height and align-content centres
     what is left, which puts the ink within a pixel of centre in Helvetica
     Neue, Arial Black, Roboto and the rest of the stack. The 0.6 line-height
     is for a browser without text-box: it keeps the untrimmed line box
     shorter than the box, because an overflowing one is not centred at all. */
  display: block;
  flex: none;
  font-size: 1.16em;
  width: 1.1em;
  height: 1.1em;
  line-height: 0.6;
  text-align: center;
  align-content: center;
  text-box: trim-both cap alphabetic;
  color: #fff;
  border: 0.095em solid #fff;
  border-radius: 0;
}

.hero .lede {
  font-size: clamp(1.02rem, 2vw, 1.18rem);
  line-height: 1.6;
  color: #dbe6f2;
  max-width: 34rem;
}

.hero-figure { display: grid; gap: 1.25rem; }

/* The About page portrait: the cleared studio frame, shown whole. Capped so a
   short copy column does not leave a tall empty navy field beside it; the
   frame is 2:3, so the cap crops it to roughly 4:5 from the top.

   The class is .portrait, which is what mockup/about.html and
   tools/content.sh actually emit. This rule was once written against
   .photo-portrait, a name from the placeholder era that no surface has ever
   used -- so the About page shipped to production with an unstyled img,
   rendering the portrait at its intrinsic 800x1200 beside a headline with no
   column to constrain it. Nothing caught it: `just check` reads pages for
   compliance, not for layout. */
.hero-grid .portrait {
  display: block;
  width: 100%;
  max-width: 21rem;
  max-height: 26rem;
  height: auto;
  margin-inline: auto;
  object-fit: cover;
  object-position: top;
  border-radius: var(--radius);
}

/* The graphic's sign-off line. Not a script: it is the one place a whole
   sentence has to be read, and a brush face at sentence length turned into
   texture (decisions.md, 2026-09-05). Inter Italic at 600 was chosen over
   the lighter weights because on this photographic backdrop the line has to
   read as a statement, not a caption, and over 700 because that competes
   with the display caps and breaks the line to three at desktop width. The
   size cap is the largest at which the line still breaks once in the hero's
   512px column at a 1280px viewport -- Inter at 600 runs about 6% wider than
   the system sans it was previewed against, and at 2.2rem "place." is already
   on a line of its own. The
   colour is gold-bright with a shadow, not plain gold, because the backdrop's
   local contrast varies. */
.sign-off {
  font-family: var(--quote);
  font-style: italic;
  font-size: clamp(1.3rem, 3.2vw, 2.1rem);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--gold-bright);
  text-shadow: 0 2px 10px rgb(2 20 40 / 55%);
  text-align: center;
  margin: 0 0 1rem;
}

/* Inner pages: same navy field and swoosh, single column, smaller accent lead. */
/* Overrides the variable, not the property, so anything anchored to the
   hero's bottom padding stays anchored on an inner page too. */
.hero-inner {
  --hero-pad-bottom: clamp(3.5rem, 8vw, 6rem);
  --hero-wash: 0.8;
}
.hero-inner .lede { max-width: 44rem; }

.script-lead.sm { font-size: clamp(1.6rem, 4vw, 2.4rem); }
.script-lead.sm::after { width: 4.5rem; }

/* Green-and-gold swoosh dividing one band from the next. Each use's fill
   matches the colour of the section it curves into. */
.wave {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  width: 100%;
  height: clamp(40px, 6vw, 78px);
  display: block;
  /* The green ribbon rises up to seventeen and a half units above a curve that already
     touches y=6 at its flattest, so it crosses the top of the viewBox. An SVG clips to its
     viewport by default, which would cut the ribbon off exactly where the band
     is shallowest; letting it draw outside puts those few pixels over the navy
     field above, which is where they belong. */
  overflow: visible;
}

.wave-top {
  bottom: auto;
  top: -1px;
  transform: rotate(180deg);
}

/* The curve is drawn three times: the fill of the section it curves into, then
   the graphic's two ribbons. In the source neither ribbon is a uniform stroke:
   the gold is fullest on the left and dies to nothing on the right, the green
   does the opposite, and the two take turns — one brushed band with a colour
   change running through it, not two parallel rules. Each ribbon is therefore a
   filled shape whose two edges are the base curve with a varying vertical
   offset. The offsets are exact rather than sampled: a vertical offset that is
   itself a cubic in t adds straight onto a cubic Bezier's control points, so
   every edge is the base curve's control points with a per-point y shift, and
   the seam between the ribbons stays C1-smooth across the join at x=760. The
   band's lower edge sits 3.5 units below the base curve everywhere — where the
   old stroke reached, and where the section fill begins — so no seam shows.
   Green sits against the navy field and gold against the content below it; the
   180deg rotation of .wave-top swaps them, which is correct — it keeps green on
   whichever side the navy is, and puts the gold's full end on the right. Both
   colours come from the palette rather than the markup, so the SVGs carry no
   hex of their own except each use's fill. */
.wave-green,
.wave-gold { stroke: none; }

.wave-green { fill: var(--green); }
.wave-gold { fill: var(--gold); }


/* ---------- Bands ---------- */

.band { position: relative; }

.band-dark {
  background: var(--navy-deep);
  color: #fff;
}

.band-dark h2, .band-dark h3 { color: #fff; }
.band-dark p { color: #c5d4e4; }
.band-dark .section-head p { color: #c5d4e4; }

.cta { padding-top: clamp(4.5rem, 9vw, 7rem); padding-bottom: clamp(3rem, 6vw, 4.5rem); }
.cta-quote { text-align: left; margin: 1.6rem 0 0; }

/* The About page's closing band sits between two navy blocks — the council record above
   and the footer below — so it takes the paper ground and the page keeps alternating. It
   carries no curve of its own: the curve is the council band's foot (fill paper, green
   against the navy), so this band needs only a section's ordinary headroom. The sign-off
   goes navy here because its lit gold is tuned for a dark field and fails on paper. */
.cta-paper { padding-top: clamp(2.5rem, 5vw, 4rem); }
.cta-paper .sign-off { color: var(--navy); text-shadow: none; }

/* ---------- Pillar band ---------- */

/* The band ends flat, on a thin gold rule: an echo of the hero's ribbons
   without their shape. A second curve, a plain curve and a diagonal cut were
   each tried under the hero's wave and each read as competing with it. */
.pillars {
  position: relative;
  background: var(--navy-deep);
  color: #fff;
  padding-block: clamp(2.5rem, 5vw, 3.5rem);
  /* A little deeper at the foot than the head: the copy needs air before the
     rule, where the head has the curve's fill above it already. */
  padding-bottom: clamp(3.5rem, 7vw, 5rem);
  border-bottom: 3px solid var(--gold);
}

.pillars h2 { color: #fff; }

/* Explicit column counts, not auto-fit: the larger type pushed the tracks past what
   auto-fit could keep four-across inside --wrap, and it silently settled on three —
   stranding the fourth pillar alone on a second row. Four across is the campaign
   graphic's signature and has to survive the type scale. */
.pillar-grid {
  display: grid;
  gap: 1.75rem 1.5rem;
  grid-template-columns: 1fr;
}

@media (min-width: 40rem) {
  .pillar-grid { grid-template-columns: repeat(2, 1fr); }
}

/* Four across, weighted by how much each pillar says — Growth carries twice the
   copy of Environment or Stability, and at equal widths it ran a third deeper
   than its neighbours while they sat half empty. The weights bring the four
   columns to near the same depth; the headings still fit two lines at the
   narrow end. Renumber if the copy changes. */
@media (min-width: 68rem) {
  .pillar-grid { grid-template-columns: 1fr 1.15fr 0.9fr 0.95fr; }
  /* The band steps out past the page column where there is room: four
     columns of copy want more width than the prose does, and a band that
     runs edge to edge in navy can afford to. Capped so it never outgrows the
     hero's grid by more than a column's worth. */
  .pillars > .wrap { max-width: calc(var(--wrap) + 14rem); }
}

/* One row of disc and value word, then the heading, then the sentences, all
   at the column's full width. The value word is one line at every width, so
   the four discs sit on one line too — a heading beside the disc wrapped to
   two or four lines and stepped the discs up and down the band.
   align-content: start matters — the grid stretches each .pillar to the tallest
   column's height, and auto rows would absorb that slack unevenly. */
.pillar { display: grid; gap: 0.6rem; align-content: start; }

.pillar-head {
  display: flex;
  align-items: center;
  gap: 0.9rem;
}

/* A flat green disc with the graphic's thin pale rim. The graphic also lights
   the ball top-left and halos it into the navy; at 4rem those two read as
   noise and the rim is the one detail that survives, so only it is kept
   (decisions.md, 2026-09-05). The glyphs are solid white shapes — at 2rem a
   1.7px stroke is a scratch, a fill is a mark. */
.pillar-icon {
  width: 4rem;
  height: 4rem;
  border-radius: 50%;
  background: var(--green);
  border: 2px solid var(--green-ring);
  display: grid;
  place-content: center;
}

/* The glyph's viewBox is the disc itself (assets/icons/), so filling the disc
   puts it exactly where the graphic puts it. */
.pillar-icon { flex: none; }
.pillar-icon svg { display: block; width: 100%; height: 100%; fill: #fff; }

.pillar h3 {
  color: #fff;
  font-size: clamp(1.2rem, 2.1vw, 1.35rem);
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin: 0;
}

/* Full white, both sentences: the band is read, not scanned, and a second
   sentence in a fainter grey was the part people gave up on. */
.pillar p {
  font-size: 1.05rem;
  line-height: 1.55;
  color: #fff;
  margin: 0;
}

/* The value word the pillar answers to, tying it back to the hero list. */
/* The four values beside their discs, in the sign-off's voice: Inter Italic
   600, gold, mixed case. Heavy display caps shouted beside the disc and the
   brush script made four more scripts on a page that uses it once. */
.pillar .pillar-value {
  font-family: var(--quote);
  font-style: italic;
  font-size: clamp(1.35rem, 2.5vw, 1.55rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0;
  /* The lit gold of "Keeping" and the sign-off: bright, with the soft navy
     shadow that lifts it off the field. Flat gold read dull beside the disc. */
  color: var(--gold-bright);
  text-shadow: 0 2px 10px rgb(2 20 40 / 55%);
  margin: 0;
}

/* Janet's supporting sentence — its own paragraph, the same weight as the first. */
.pillar .pillar-detail { margin-top: 0.35rem; }

/* The graphic rules the four apart with a hairline. Two-up the rule sits
   between the columns of each row; four-up between every neighbour. It is
   drawn in the middle of the column gap rather than as a border with padding,
   so no column is indented past its neighbour: text sits flush at both ends
   of the grid and the block reads as centred, which a left-flush first column
   beside three indented ones did not. */
.pillar { position: relative; }
.pillar::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(-0.5 * var(--pillar-gap));
  width: 1px;
  background: rgb(255 255 255 / 16%);
  display: none;
}
@media (min-width: 40rem) {
  .pillar-grid { --pillar-gap: 3rem; column-gap: var(--pillar-gap); }
  .pillar:nth-child(even)::before { display: block; }
}
@media (min-width: 68rem) {
  .pillar + .pillar::before { display: block; }
}

/* Track record — a titled item and its sentence. Used on the About page for the
   service history, where each entry is a thing done rather than a claim made. */
.record {
  list-style: none;
  margin: 1.25rem 0 0;
  padding: 0;
}
.record > li {
  padding: 0 0 1.1rem 1.25rem;
  margin-bottom: 1.1rem;
  border-bottom: 1px solid var(--line);
  border-left: 3px solid var(--gold);
}
.record > li:last-child { margin-bottom: 0; border-bottom: 0; padding-bottom: 0; }
.record > li > b {
  display: block;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--navy);
  margin-bottom: 0.35rem;
}
.record > li > p { margin: 0; }

/* The pages Janet asked the About page to carry — each organisation's own page, with her
   one-line gloss on what she does there. Plain links, deliberately: they are council and
   community bodies' pages, not ours, and the list must read as pointers rather than claims. */
.links {
  list-style: none;
  margin: 0.75rem 0 1.5rem;
  padding: 0;
}
.links > li {
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--line);
}
.links > li:last-child { border-bottom: 0; }
.links a { font-weight: 700; }

/* A long verbatim quotation from Janet — her leaflet, her statement. Quieter than
   .quote, which is a one-line pull; this one has to carry several paragraphs. */
.statement {
  background: var(--paper);
  border: 1px solid var(--line);
  border-left: 4px solid var(--gold);
  border-radius: var(--radius);
  padding: 1.25rem 1.5rem;
  margin: 1.5rem 0;
}
.statement p { margin: 0 0 0.9rem; }
.statement p:last-of-type { margin-bottom: 0; }
.statement cite {
  display: block;
  margin-top: 0.9rem;
  font-size: 0.85rem;
  font-style: normal;
  color: var(--muted);
}

/* ---------- Buttons ---------- */

.btn {
  display: inline-block;
  background: var(--gold);
  color: var(--navy-deep);
  text-decoration: none;
  font-family: var(--display);
  font-weight: 800;
  font-size: 0.92rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  padding: 0.8rem 1.7rem;
  border-radius: 6px;
}

.btn:hover { background: var(--gold-bright); color: var(--navy-deep); }

.btn-ghost {
  background: transparent;
  color: var(--navy);
  border: 2px solid var(--navy);
}

.btn-ghost:hover { background: var(--navy); color: #fff; }

.hero .btn-ghost, .pillars .btn-ghost, .band-dark .btn-ghost {
  color: #fff;
  border-color: rgba(255, 255, 255, 0.55);
}

.hero .btn-ghost:hover,
.pillars .btn-ghost:hover,
.band-dark .btn-ghost:hover { background: #fff; color: var(--navy); }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 1.6rem;
}

/* ---------- Photo placeholders ----------
   Placeholders, never stock or generated imagery — see CLAUDE.md. */

.photo {
  display: grid;
  place-content: center;
  text-align: center;
  gap: 0.4rem;
  background: repeating-linear-gradient(
    -45deg, #eef1f4, #eef1f4 10px, #e5e9ee 10px, #e5e9ee 20px
  );
  border: 2px dashed #b3bec9;
  border-radius: var(--radius);
  color: #6a7b90;
  padding: 1.5rem;
  min-height: 18rem;
}

.photo b {
  font-size: 0.88rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.photo small {
  font-size: 0.78rem;
  max-width: 24ch;
  line-height: 1.45;
}

/* ---------- Sections ---------- */

section, .section { padding-block: clamp(2.5rem, 5vw, 4rem); }

.section-tint { background: #e9eef5; }
.section-surface { background: var(--surface); border-block: 1px solid var(--line); }
/* Directly under a hero the section's top edge is the foot of the wave, whose
   fill is already this section's colour; a rule there draws a grey hairline
   across the curve's base. The wave is the join, so the border is dropped. */
.hero + .section-surface { border-top: 0; }

.section-head { max-width: 46rem; margin-bottom: 2rem; }
.section-head p { color: var(--ink-soft); margin-bottom: 0; }

.prose { max-width: 42rem; }
.prose h2 { margin-top: 2.2rem; }

/* Section headings carry a short gold rule, echoing the hero. */
.section-head h2::after,
.prose h2::after {
  content: "";
  display: block;
  width: 3.5rem;
  height: 3px;
  background: var(--gold);
  border-radius: 2px;
  margin-top: 0.6rem;
}

/* ---------- Pull quote ---------- */

.quote {
  border-left: 4px solid var(--gold);
  padding: 0.2rem 0 0.2rem 1.25rem;
  margin: 1.75rem 0;
  font-size: clamp(1.15rem, 2.4vw, 1.4rem);
  line-height: 1.5;
  color: var(--navy);
}

.quote cite {
  display: block;
  margin-top: 0.7rem;
  font-size: 0.85rem;
  font-style: normal;
  color: var(--muted);
}


/* ---------- The letter ----------
   The home page's letter is set as a letter, not as prose (decisions.md,
   2026-09-05): a sheet the width of a page, centred, with the graphic's name
   plaque as its letterhead on a navy strip, the text filling the sheet inside
   even margins, one pull quote, and a script signature on the tapered stroke.
   The heading shares the sheet's column so the two align at the left; a sheet
   wider than its text is a box with a hole in it, not a margin. */

.letter-band { background: var(--paper); border-block: 0; }

.letter-band .wrap > * {
  max-width: 48rem;
  margin-inline: auto;
}

.letter {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 3px;
  overflow: hidden;
  box-shadow: 0 1px 3px rgba(6, 45, 83, 0.07), 0 18px 40px -24px rgba(6, 45, 83, 0.35);
}

/* Letterhead: the name and the office plate, as the hero sets the name, on
   the navy field with the gold edge under it. `.office` is styled above with
   the hero classes; the letterhead is now its only use. */
.letter-head {
  background: linear-gradient(160deg, var(--navy-mid) 0%, var(--navy) 55%, var(--navy-deep) 100%);
  border-bottom: 4px solid var(--gold);
  color: #fff;
  padding: clamp(1.4rem, 3vw, 2rem) clamp(1.25rem, 5vw, 3rem);
}

.letter-name {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(1.35rem, 3vw, 1.8rem);
  line-height: 1.05;
  letter-spacing: -0.015em;
  margin: 0 0 0.6rem;
}

.letter-head .office { margin: 0; }

.letter-body {
  margin: clamp(1.75rem, 4vw, 2.75rem) clamp(1.25rem, 5vw, 3rem) clamp(2rem, 4vw, 3rem);
  font-size: 1.06rem;
  line-height: 1.7;
}

.letter-body p { margin-bottom: 1.25em; }

/* The opening paragraph is the lede: who she is, before the argument. */
.letter-lede {
  font-size: clamp(1.15rem, 2vw, 1.3rem);
  line-height: 1.55;
  font-weight: 500;
  color: var(--navy);
}

.letter-quote {
  margin: 2rem 0;
  font-family: var(--quote);
  font-style: italic;
  font-weight: 600;
}

.letter-ask {
  font-family: var(--display);
  font-size: 1.15rem;
  font-weight: 800;
  color: var(--navy);
}

/* The signature is the letter's one brush-script line: two words, where a
   signature belongs. It does the script's job — reading as a person — at the
   only other place on the site a hand is expected (decisions.md, 2026-09-05),
   and it sits on the graphic's tapered stroke in the reverse colour of its
   ground, as the sign-off does on the poster. */
.letter-sign { margin-top: 2.25rem; }

.letter-signature {
  font-family: var(--accent);
  font-size: 2.8rem;
  line-height: 1;
  color: var(--navy);
  margin: 0 0 0.2rem;
  /* The face slants right; a small negative offset seats the J on the margin. */
  margin-left: -0.05em;
}

/* The graphic's brush stroke, fading to nothing at both ends — the same
   gradient as poster.css's .tapered-rule, so the two surfaces draw one stroke. */
.tapered-rule {
  display: block;
  height: 6px;
  border: 0;
  --rule-edge: var(--gold);
  --rule-crown: var(--gold-bright);
  background: linear-gradient(90deg,
    transparent 0%,
    var(--rule-edge) 18%,
    var(--rule-crown) 50%,
    var(--rule-edge) 82%,
    transparent 100%);
  border-radius: 3px;
}

.tapered-rule--navy {
  --rule-edge: var(--navy-deep);
  --rule-crown: var(--navy);
}

.letter-stroke {
  width: 11rem;
  height: 5px;
  margin: 0 0 0.9rem -1rem;
}

.letter-signed {
  font-size: 0.95rem;
  line-height: 1.4;
  color: var(--ink);
  margin: 0;
}

.letter-signed small {
  display: block;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 0.15rem;
}

/* ---------- Cards ---------- */

.card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 5px solid var(--gold);
  border-radius: var(--radius);
  padding: 1.6rem 1.5rem 1.5rem;
  box-shadow: 0 1px 3px rgba(6, 45, 83, 0.07);
}

.section-surface .card { background: var(--paper); }

.card h3 { margin-bottom: 0.5em; color: var(--navy); }
.card p { font-size: 0.95rem; color: var(--ink-soft); margin-bottom: 0; }

/* Oversized gold numeral, echoing the graphic's heavy display type. */

.band-dark .card {
  background: rgba(255, 255, 255, 0.05);
  border-color: var(--navy-line);
  border-top-color: var(--gold);
  box-shadow: none;
}

.band-dark .card h3 { color: #fff; }
.band-dark .card p { color: #bacbdd; }

/* ---------- Poster ----------
   The campaign poster as a section of the site: one landscape frame on the
   paper ground, after the pillar band and before the closing band. The frame's
   proportions are the web artboard's (poster/artboards/sizes.conf), which is
   the file it holds. A tap opens it full screen (poster.js, below). */

.poster-band { padding-block: clamp(2.5rem, 5vw, 3.5rem); }

.poster { margin: 0; }

/* The frame is a link: a tap opens the poster full screen (poster.js), and
   with no script it opens the file itself. The caption says so in words, in
   place, so the larger view is never a hidden gesture. */
.poster-link {
  display: block;
  border-radius: var(--radius);
}
.poster-link:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 4px;
}

.poster img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
  border: 1px solid var(--line);
}

.poster-caption {
  margin: 0.75rem 0 0;
  font-size: 0.9rem;
  color: var(--ink-soft);
  text-align: center;
}

/* The full-screen view: a modal <dialog> the size of the viewport, the
   poster centred in it at the largest size that fits, on the navy the
   closing band uses. `display: flex` only while open, or the dialog's own
   `display: none` at rest is overridden and it renders inline. */
.poster-dialog {
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: clamp(0.75rem, 3vw, 2rem);
  border: 0;
  background: transparent;
  align-items: center;
  justify-content: center;
}
.poster-dialog[open] { display: flex; }
.poster-dialog::backdrop { background: rgba(3, 20, 40, 0.94); }

.poster-dialog img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  border-radius: var(--radius);
}

/* A landscape poster on a portrait phone is no larger full screen than in
   the page, so in portrait it is turned to run down the phone's long edge:
   the box is sized to the viewport's height by its width, then rotated
   about its centre, which the flex centring above already holds. The
   reader turns the phone; the browser's pinch-zoom takes it from there. */
@media (orientation: portrait) {
  .poster-dialog {
    --poster-pad: calc(2 * clamp(0.75rem, 3vw, 2rem));
    --poster-vh: 100vh;
    --poster-vh: 100dvh;
  }
  /* Height set outright rather than left to max-width/max-height: a flex
     item keeps the width its intrinsic size gives it and overflows. 1.5 is
     the artboard's aspect (poster/artboards/sizes.conf, 1536/1024). */
  .poster-dialog img {
    height: min(
      calc(100vw - var(--poster-pad)),
      calc((var(--poster-vh) - var(--poster-pad)) / 1.5)
    );
    width: auto;
    max-width: none;
    max-height: none;
    transform: rotate(90deg);
  }
}

.poster-close {
  position: fixed;
  top: clamp(0.5rem, 2vw, 1rem);
  right: clamp(0.5rem, 2vw, 1rem);
  width: 2.75rem;
  height: 2.75rem;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  font: 1.75rem/1 var(--sans);
  cursor: pointer;
}
.poster-close:hover,
.poster-close:focus-visible { background: rgba(255, 255, 255, 0.24); outline: 2px solid var(--gold); }

body:has(.poster-dialog[open]) { overflow: hidden; }

/* ---------- About page ----------
   The page used to be one white slab under the hero: a single 42rem prose
   column carrying six identical headings and two long lists, with no
   photograph and no change of ground from the hero's wave to the closing
   band. It now alternates the way the home page does — white, paper, a
   photograph, navy — and changes shape at each band, so a reader scrolling
   on a phone meets something other than the next heading. The copy is
   unchanged; only its setting is. */

/* Why I stood: her statement centred at the letter's width, so her own words
   get one treatment on both pages (decisions.md, 2026-09-05). */
.about-why .wrap > * {
  max-width: 48rem;
  margin-inline: auto;
}

/* The values line closes the band as a centred pull under a gold rule rather
   than a second left-ruled box under the first. */
.quote-centred {
  border-left: 0;
  border-top: 3px solid var(--gold);
  padding: 1.5rem 0 0;
  margin: 2.5rem auto 0;
  text-align: center;
  font-family: var(--quote);
  font-style: italic;
  font-weight: 600;
}

/* Service to Sorell: the paper ground, and the record as a grid of white
   cards at the page's full width — the About page's widest moment, as the
   pillar band is the home page's. Seven entries; the last spans the row so
   the grid closes on a strip rather than an orphan. */
.band-paper { background: var(--paper); }

.record-grid {
  display: grid;
  gap: 1.25rem;
  margin-top: 0;
}

.record-grid > li,
.record-grid > li:last-child {
  margin: 0;
  padding: 1.4rem 1.5rem 1.5rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 5px solid var(--gold);
  border-radius: var(--radius);
  box-shadow: 0 1px 3px rgba(6, 45, 83, 0.07);
  overflow: hidden;
}

/* A photograph on a card bleeds to the card's edges above the title. Fixed
   height and cover, so a portrait and a landscape source sit level. */
.record-grid > li > img {
  display: block;
  width: calc(100% + 3rem);
  max-width: none;
  height: 14rem;
  margin: -1.4rem -1.5rem 1.1rem;
  object-fit: cover;
}

.record-grid > li:last-child > p { max-width: 60ch; }

@media (min-width: 48rem) {
  .record-grid { grid-template-columns: 1fr 1fr; gap: 1.5rem; }
  .record-grid > li:last-child { grid-column: 1 / -1; }
}

/* One full-width photograph between her service record and her council
   record: the page's single quiet beat. The caption names the place only. */
.photo-band {
  position: relative;
  margin: 0;
  background: var(--navy-deep);
}

.photo-band img {
  display: block;
  width: 100%;
  height: clamp(16rem, 42vw, 32rem);
  object-fit: cover;
  object-position: center 60%;
}

.photo-band figcaption {
  position: absolute;
  right: 1rem;
  bottom: 0.75rem;
  padding: 0.3rem 0.6rem;
  border-radius: 3px;
  background: rgba(6, 45, 83, 0.72);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* On council: the hero's navy, a shade lighter than the closing band's so the
   two read as separate bands across the curve. Offices and the links she
   asked to have displayed sit side by side; the advocacy record is three
   cards, as the pillars are. */
.about-council {
  background: var(--navy);
  /* Room for the curve at its foot, which is drawn over this padding. */
  padding-bottom: clamp(4.5rem, 9vw, 7rem);
}

.about-council h3 {
  color: #fff;
  font-size: 1.05rem;
  margin-bottom: 0.6rem;
}

.council-grid { display: grid; gap: 2rem; }

@media (min-width: 60rem) {
  .council-grid { grid-template-columns: 1fr 1fr; gap: 3rem; }
}

.offices {
  list-style: none;
  margin: 0;
  padding: 0;
}

.offices li {
  position: relative;
  padding: 0.55rem 0 0.55rem 1.1rem;
  border-top: 1px solid var(--navy-line);
  color: #c5d4e4;
}

.offices li:last-child { border-bottom: 1px solid var(--navy-line); }

.offices li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 1.05rem;
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: var(--gold);
}

.about-council .links { margin-bottom: 0; }
.about-council .links > li { border-color: var(--navy-line); color: #c5d4e4; }
.about-council .links a { color: var(--gold-bright); }
.about-council .links a:hover,
.about-council .links a:focus-visible { color: #fff; }

.advocacy-head {
  max-width: 46rem;
  margin: 2.75rem 0 1.25rem;
  font-size: clamp(1.1rem, 2vw, 1.3rem);
  font-weight: 600;
  line-height: 1.45;
}

.card-grid { display: grid; gap: 1.25rem; }

@media (min-width: 48rem) {
  .card-grid { grid-template-columns: repeat(3, 1fr); }
}

/* ---------- Contact ----------
   No published email or phone: the form is the channel. Janet's council address and
   mobile are public on the Council site and must not be repeated here (CLAUDE.md),
   and a personal mobile on a campaign page is a permanent decision. */

.contact-layout {
  display: grid;
  gap: 2rem;
  align-items: start;
}

@media (min-width: 52rem) {
  .contact-layout { grid-template-columns: 1.35fr 1fr; gap: 2.5rem; }
}

.contact-form {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: clamp(1.25rem, 3vw, 1.75rem);
}

.field { margin-bottom: 1.1rem; }

.field label {
  display: block;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--navy);
  margin-bottom: 0.4rem;
}

.field .hint {
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--muted);
}

.field input,
.field textarea {
  display: block;
  width: 100%;
  font: inherit;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0.6rem 0.75rem;
}

.field textarea { resize: vertical; }

.field input:focus-visible,
.field textarea:focus-visible {
  outline: 2px solid var(--navy-mid);
  outline-offset: 1px;
  background: var(--surface);
}

.form-note { font-size: 0.9rem; margin-bottom: 1.25rem; }
.form-privacy { font-size: 0.85rem; color: var(--muted); margin-bottom: 1.25rem; }

/* The honeypot. Off-screen rather than display:none or visibility:hidden --
   a bot that reads the stylesheet skips a field hidden those two ways, and
   filling it in is the whole point. */
.field--trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* The line the form shows after a submission redirects back to the page.
   Both states are readable without colour alone carrying the meaning --
   the wording says which it is, and the left rule gives it weight. */
.form-status {
  margin: 0 0 1.25rem;
  padding: 0.85rem 1rem;
  border-left: 4px solid;
  border-radius: 0 4px 4px 0;
  font-size: 0.95rem;
}

.form-status--ok {
  border-left-color: var(--green);
  background: color-mix(in srgb, var(--green) 8%, transparent);
}

.form-status--error {
  border-left-color: #b3261e;
  background: color-mix(in srgb, #b3261e 7%, transparent);
}

.contact-aside { display: grid; gap: 1.25rem; }
.contact-aside .card p { font-size: 1rem; }
.contact-aside a { font-weight: 600; }
.contact-aside .card p + p { margin-top: 1rem; }

/* Each aside card's link carries the mark of where it goes -- the Facebook
   "f", the Council's logo -- so the eye reads the destination before the
   text does. Neither mark is ours (docs/media.md); each alt is empty because
   the link text already names the destination. The width attribute on the
   <img> sets each mark's size, since the two are different shapes. */
.channel-link {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
}

.channel-link img { flex: none; }

/* ---------- Footer ---------- */

.site-footer {
  background: var(--navy-deep);
  color: #b9c9da;
  padding-block: 2.5rem;
  font-size: 0.9rem;
}

/* A gold rule along the footer's top edge on the inner pages, where the footer follows a
   light section — the pillar band's rule, at the foot of the page. The home page is the
   exception: there the footer continues the navy closing band, and a rule would cut one
   block in two. `home` is WordPress's own body class for the front page; the mockup's
   index.html sets it by hand to match. */
body:not(.home) .site-footer { border-top: 3px solid var(--gold); }

.site-footer a { color: #fff; }

.footer-top {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2.5rem;
  justify-content: space-between;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid var(--navy-line);
}

.site-footer .wp-block-site-title,
.site-footer .wp-block-site-title a {
  font-family: var(--display);
  font-size: 1.25rem;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: #fff;
  text-decoration: none;
  line-height: 1.1;
}

.site-footer .wp-block-site-tagline {
  display: block;
  font-family: var(--sans);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold);
  margin: 0.25rem 0 0;
}

.footer-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.5rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.footer-nav a { text-decoration: none; }
.footer-nav a:hover { text-decoration: underline; }

/* The s.311 responsible-person statement. Required on every page from
   5 September 2026. See ../CLAUDE.md and docs/compliance.md — do not touch
   its structure or text, only how it looks. */
.jg-authorisation,
.authorisation {
  margin-top: 1.5rem;
  font-size: 0.82rem;
  line-height: 1.6;
  color: #93a8bd;
}

.jg-authorisation strong,
.authorisation strong { color: #fff; }

/* ---------- Utilities ---------- */

.muted { color: var(--muted); font-size: 0.9rem; }
.mt-0 { margin-top: 0; }
.center { text-align: center; }

.skip {
  position: absolute;
  left: -9999px;
}

.skip:focus {
  left: 1rem;
  top: 1rem;
  z-index: 200;
  background: #fff;
  padding: 0.6rem 1rem;
  border-radius: 6px;
}
