/* ==========================================================================
   Middleton on Sea Association
   One stylesheet, no build step, no external fonts or services.

   Design notes for whoever picks this up next:
   - Colours are drawn from the estate: shingle, sea, greensward, thatch.
   - Body text is 18px minimum with 1.7 line height. Many of our members are
     older, and the brief asks for dyslexia-friendly type. Never go smaller.
   - Backgrounds are warm off-white, never pure white. Pure white on a bright
     screen is harder to read for longer.
   - Measure is capped at about 66 characters. Long lines lose the reader.
   - Nothing is justified. Ragged right is easier to track.
   ========================================================================== */

:root {
  --sea-deep:   #1d4f5e;
  --sea:        #2b6c7e;
  --sea-light:  #e7f0f2;
  --green:      #4a7c59;
  --green-soft: #eaf1ea;
  --sand:       #e9dfcc;
  --sand-soft:  #f6f1e6;
  --thatch:     #b8813f;   /* decorative only: borders, rules. 3.25:1, fails as text */
  --thatch-ink: #8d6228;   /* the same hue, dark enough for text. 5.2:1 on paper */
  --ink:        #22303a;
  --ink-soft:   #4d5c66;
  --paper:      #fdfbf7;
  --paper-alt:  #f7f3ec;
  --rule:       #ddd5c6;
  --focus:      #8d6228;

  --measure: 66ch;
  --gap: 1.5rem;
  --radius: 6px;
  --shadow: 0 1px 2px rgba(34,48,58,.06), 0 6px 20px rgba(34,48,58,.05);
}

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

html {
  -webkit-text-size-adjust: 100%;
  /* No dark variant is offered, but declaring the scheme still tells the
     browser how to render scrollbars and form controls. */
  color-scheme: light;
  /* Keep anchor targets clear of the sticky masthead. scroll-padding-top acts
     on the scrolling container and so covers fragment navigation on first load
     as well as in-page jumps; scroll-margin-top on the target alone did not
     survive arriving at the page with the fragment already in the URL. */
  scroll-padding-top: 6rem;
}

body {
  margin: 0;
  /* Removes the 300ms double-tap delay on touch devices, and stops the grey
     flash on tap being left to whatever the browser fancies. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgba(29, 79, 94, .12);
  background: var(--paper);
  color: var(--ink);
  font-family: Georgia, "Iowan Old Style", "Palatino Linotype", Palatino, serif;
  font-size: 1.125rem;      /* 18px */
  line-height: 1.7;
  text-rendering: optimizeLegibility;
}

/* Headings and interface elements use a humanist sans for contrast with the
   serif body. System stack only, so nothing is fetched over the network. */
h1, h2, h3, h4, .brand, .primary, .menu-toggle, .brand-members, .crumbs, .subnav,
.card__date, .foot, .button, .quick__label, .tag {
  font-family: "Segoe UI", Roboto, -apple-system, BlinkMacSystemFont,
               "Helvetica Neue", Arial, sans-serif;
}

h1, h2, h3, h4 {
  line-height: 1.25; color: var(--sea-deep); margin: 0 0 .6em;
  /* Stops a heading dropping a single word onto its own line. */
  text-wrap: balance;
}
h1 { font-size: clamp(2rem, 5vw, 2.9rem); letter-spacing: -.015em; }
h2 { font-size: clamp(1.5rem, 3.2vw, 1.95rem); margin-top: 2.2em; }
h3 { font-size: 1.3rem; margin-top: 1.8em; color: var(--sea); }
h4 { font-size: 1.1rem; margin-top: 1.6em; color: var(--ink); }

p, ul, ol, blockquote, table { margin: 0 0 1.15em; }

a { color: var(--sea-deep); text-decoration-thickness: 1px; text-underline-offset: .18em; }
a:hover { color: var(--thatch-ink); }

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-radius: 2px;
}

img { max-width: 100%; height: auto; display: block; }

/* The masthead is sticky, so following a link to #verge scrolls that heading to
   the very top of the viewport and straight underneath the header, hiding the
   term and the first line of its definition. Reported on Android; it affects
   every browser. Anchor targets are pushed down by the header height plus a
   little breathing room.

   6rem, not the measured ~4.5rem, because the header is content-sized and grows
   if the brand wraps on a very narrow screen. Erring high costs a little white
   space; erring low hides the thing the reader clicked to see. */
[id] { scroll-margin-top: 6rem; }

/* And mark where they landed. The glossary is eighteen entries long and
   arriving in the middle of it, the eye needs telling which one. Left as a
   quiet background rather than a flash, so it works with reduced motion and is
   still there if the reader looks away and back. */
main :target {
  background: var(--sand-soft);
  box-shadow: 0 0 0 .4rem var(--sand-soft);
  border-radius: 2px;
}

hr { border: 0; border-top: 1px solid var(--rule); margin: 2.5rem 0; }

code { background: var(--paper-alt); padding: .1em .35em; border-radius: 3px; font-size: .9em; }

/* ---------------------------------------------------------------- layout */
.wrap { width: 100%; max-width: 68rem; margin-inline: auto; padding-inline: 1.25rem; }

main { padding-bottom: 4rem; }

/* Everything in main sits at the reading measure by default, and the blocks
   that are deliberately wider opt out below.

   This is inverted from the obvious arrangement, which is to list the elements
   that should be constrained. That version is an allowlist, so anything not on
   it silently spans the full width of the window. It is exactly how the
   document links came to bleed across the whole page while the text around
   them stayed in its column. Constrained-by-default fails safe; a new kind of
   block can only go full width if somebody says so here. */
main > * {
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: 1.25rem;
}
main > h1 { margin-top: 2rem; }

/* The deliberate opt-outs. */
main > .hero { max-width: none; padding-inline: 0; }
main > .quick,
main > .cards,
main > .gallery { max-width: 68rem; }
main > figure.photo { max-width: 56rem; }
main > .index-group,
main > .index-jump,
main > .index-filter,
main > .index-count { max-width: 60rem; }
main > .slideshow { max-width: 62rem; }

/* Text for screen readers only. Used by the build to announce that a link
   opens in a new tab, which is otherwise a silent change of context. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

.skip {
  position: absolute; left: -9999px;
  background: var(--sea-deep); color: #fff; padding: .75rem 1.25rem;
  border-radius: 0 0 var(--radius) 0; z-index: 100;
}
.skip:focus { left: 0; top: 0; }

/* ---------------------------------------------------------------- masthead */
.masthead {
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
  position: sticky; top: 0; z-index: 50;
}
.masthead__inner {
  display: flex; align-items: center; gap: 1rem;
  flex-wrap: wrap; padding-block: .85rem;
}
.brand { display: flex; align-items: center; gap: .7rem; text-decoration: none; color: var(--sea-deep); }
/* The mark is a landscape lockup rather than a square badge, so it is sized by
   height and allowed its own width. flex: none stops it being squeezed when the
   brand text wraps on a narrow screen, which would distort the diamonds. */
.brand__mark { flex: none; display: flex; align-items: center; }
.brand__mark svg { display: block; height: 34px; width: auto; }
@media (max-width: 30rem) {
  .brand__mark svg { height: 28px; }
}
.brand__name { display: block; font-weight: 700; font-size: 1.15rem; letter-spacing: -.01em; }
.brand__sub { display: block; font-size: .78rem; color: var(--ink-soft); letter-spacing: .04em; text-transform: uppercase; }

/* Members link. Top right on every page, in the masthead rather than the menu,
   because somebody arriving to read the accounts should not have to hunt.

   Ordered rather than reordered in the markup, so that the reading order stays
   sensible for a screen reader and for a page with no CSS: it sits next to the
   brand in the HTML and is moved to the end of the row here.

   Outlined, not filled. The one filled button in the masthead is Menu, and two
   competing buttons next to each other on a phone is how people press the wrong
   one. */
.brand-members {
  order: 1; margin-left: auto;
  display: inline-flex; align-items: center;
  padding: .5rem .85rem; border-radius: var(--radius);
  border: 1px solid var(--sea-deep); color: var(--sea-deep);
  background: transparent; text-decoration: none;
  font-weight: 600; font-size: .92rem; white-space: nowrap;
}
.brand-members:hover, .brand-members:focus-visible {
  background: var(--sea-deep); color: #fff;
}
@media (max-width: 24rem) {
  /* Both buttons and a two-line brand will not fit. The link keeps its label,
     because an icon here would be a guess. */
  .brand-members { padding: .45rem .6rem; font-size: .85rem; }
}

.menu-toggle {
  order: 2; margin-left: .5rem;
  display: inline-flex; align-items: center; gap: .5rem;
  background: var(--sea-deep); color: #fff; border: 0; cursor: pointer;
  font-size: 1rem; padding: .6rem 1rem; border-radius: var(--radius);
}
.menu-toggle__bars, .menu-toggle__bars::before, .menu-toggle__bars::after {
  display: block; width: 18px; height: 2px; background: #fff; content: ""; position: relative;
}
.menu-toggle__bars::before { position: absolute; top: -6px; }
.menu-toggle__bars::after { position: absolute; top: 6px; }

.primary { order: 3; flex-basis: 100%; display: none; }
.primary.is-open { display: block; }
.primary ul { list-style: none; margin: .5rem 0 0; padding: 0; }
.primary li + li { border-top: 1px solid var(--rule); }
.primary a {
  display: block; padding: .8rem .25rem; text-decoration: none;
  color: var(--ink); font-weight: 600;
}
.primary a:hover, .primary a.is-active { color: var(--sea-deep); }

@media (min-width: 56rem) {
  .menu-toggle { display: none; }
  /* Members stays on the first row at the right, beside the brand, at every
     width. The nav is order 3 so it wraps to its own row underneath, which is
     what it already did at this width before Members existed.

     The first attempt put Members after the nav on wide screens. Because the
     masthead wraps, that produced a third row with the button sitting on its
     own at the bottom left, which is the opposite corner from the one asked
     for. Worth remembering that order and wrapping interact: ordering an item
     last does not move it right, it moves it onto the next line. */
  .primary { display: block; flex-basis: auto; margin-left: auto; }
  .primary ul { display: flex; gap: .35rem; margin: 0; }
  .primary li + li { border-top: 0; }
  .primary a { padding: .5rem .7rem; border-radius: var(--radius); font-size: .98rem; }
  .primary a.is-active { background: var(--sea-light); }
}

/* ---------------------------------------------------------------- crumbs, subnav */
.crumbs {
  max-width: var(--measure); margin: 1.25rem auto .25rem; padding-inline: 1.25rem;
  font-size: .85rem; color: var(--ink-soft);
}
.crumbs a { color: var(--ink-soft); }
.crumbs span[aria-hidden] { margin-inline: .45rem; opacity: .5; }

.subnav {
  max-width: var(--measure); margin: 1.5rem auto; padding: 1rem 1.25rem;
  background: var(--sand-soft); border-radius: var(--radius);
}
.subnav__title {
  margin: 0 0 .5rem; font-size: .78rem; text-transform: uppercase;
  letter-spacing: .07em; color: var(--ink-soft); font-weight: 700;
}
.subnav ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: .4rem .9rem; }
.subnav a { font-size: .95rem; }
.subnav a.is-active { font-weight: 700; color: var(--thatch-ink); }

/* ---------------------------------------------------------------- hero */
.hero {
  background: linear-gradient(180deg, var(--sea-light), var(--paper));
  border-bottom: 1px solid var(--rule);
  padding: clamp(2.5rem, 7vw, 4.5rem) 0 clamp(2rem, 5vw, 3rem);
  text-align: center;
}
.hero h1 { max-width: 20ch; margin-inline: auto; }
.hero__lede {
  max-width: 44ch; margin: 0 auto 1.5rem; font-size: clamp(1.15rem, 2.4vw, 1.4rem);
  color: var(--ink-soft); line-height: 1.55;
}

/* ---------------------------------------------------------------- quick routes */
.quick {
  display: grid; gap: 1rem; list-style: none; padding: 0;
  margin: 0 auto 3rem; max-width: 68rem; padding-inline: 1.25rem;
  grid-template-columns: 1fr;
}
@media (min-width: 40rem) { .quick { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 62rem) { .quick { grid-template-columns: repeat(4, 1fr); } }
.quick li { margin: 0; }
.quick a {
  display: block; height: 100%; padding: 1.25rem;
  background: #fff; border: 1px solid var(--rule); border-radius: var(--radius);
  text-decoration: none; color: var(--ink); box-shadow: var(--shadow);
  transition: transform .12s ease, border-color .12s ease;
}
.quick a:hover { transform: translateY(-2px); border-color: var(--sea); }
.quick__label { display: block; font-weight: 700; color: var(--sea-deep); margin-bottom: .2rem; }
.quick__note { display: block; font-size: .95rem; color: var(--ink-soft); line-height: 1.5; }

/* Glossary links are a definition, not a destination, and they are styled to
   say so. A normal link three times in one sentence, which happens on the home
   page with verges, twittens and Greensward, reads as a minefield and makes the
   sentence harder to follow. These keep the body colour and take a dotted
   underline instead.

   Still a genuine link: the dotted underline is a non-colour cue, so it does
   not rely on colour alone, and it firms up on hover and focus. */
.gloss {
  color: inherit;
  text-decoration: underline dotted;
  text-decoration-color: var(--sea);
  text-decoration-thickness: 1px;
  text-underline-offset: .22em;
}
.gloss:hover,
.gloss:focus-visible {
  color: var(--sea-deep);
  text-decoration: underline solid;
  text-decoration-color: var(--sea-deep);
}

/* ---------------------------------------------------------------- callouts */
.callout {
  border-left: 4px solid var(--sea); background: var(--sea-light);
  padding: 1.1rem 1.25rem; border-radius: 0 var(--radius) var(--radius) 0;
  margin-block: 1.75rem;
}
.callout > :last-child { margin-bottom: 0; }
.callout--warm   { border-color: var(--green);  background: var(--green-soft); }
.callout--action { border-color: var(--thatch); background: #fbf3e6; }
.callout--legal  { border-color: var(--ink-soft); background: var(--paper-alt); font-size: .98rem; }
.callout--review {
  border-color: var(--thatch); background: #fbf3e6;
  max-width: var(--measure); margin: 1.5rem auto; padding: 1rem 1.25rem;
}

/* ---------------------------------------------------------------- cards */
.cards {
  list-style: none; padding: 0 1.25rem; margin: 0 auto 2rem;
  max-width: 68rem; display: grid; gap: 1.25rem; grid-template-columns: 1fr;
}
@media (min-width: 44rem) { .cards { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 66rem) { .cards { grid-template-columns: repeat(3, 1fr); } }
.card {
  background: #fff; border: 1px solid var(--rule); border-radius: var(--radius);
  padding: 1.35rem; box-shadow: var(--shadow);
}
.card__date { margin: 0 0 .35rem; font-size: .8rem; letter-spacing: .05em;
              text-transform: uppercase; color: var(--thatch-ink); font-weight: 700; }
.card__title { margin: 0 0 .5rem; font-size: 1.2rem; }
.card__title a { text-decoration: none; }
.card__title a:hover { text-decoration: underline; }
.card__desc { margin: 0; font-size: 1rem; color: var(--ink-soft); }

/* ---------------------------------------------------------------- tables */
.table-scroll { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; font-size: 1rem; }
th, td { text-align: left; padding: .7rem .8rem; border-bottom: 1px solid var(--rule); vertical-align: top; }
/* The charge tables put £500 above £10,000. Proportional digits make those
   columns ragged and harder to compare; tabular figures line them up. */
td { font-variant-numeric: tabular-nums; }
th { background: var(--paper-alt); font-weight: 700; color: var(--sea-deep); }

/* ---------------------------------------------------------------- misc */
blockquote {
  border-left: 3px solid var(--sand); padding-left: 1.1rem;
  color: var(--ink-soft); font-style: italic;
}
.button {
  display: inline-block; background: var(--sea-deep); color: #fff;
  padding: .75rem 1.35rem; border-radius: var(--radius);
  text-decoration: none; font-weight: 600;
}
.button:hover { background: var(--sea); color: #fff; }

.doc-link {
  display: block; padding: .9rem 1.1rem; margin-bottom: .6rem;
  background: #fff; border: 1px solid var(--rule); border-radius: var(--radius);
  text-decoration: none;
}
.doc-link:hover { border-color: var(--sea); }
.doc-link strong { display: block; color: var(--sea-deep); }
.doc-link span { font-size: .9rem; color: var(--ink-soft); }

/* ---------------------------------------------------------------- footer */
.foot {
  background: var(--sea-deep); color: #e8eff1; margin-top: 4rem;
  padding: 3rem 0 1.5rem; font-size: 1rem;
}
.foot__inner { display: grid; gap: 2rem; grid-template-columns: 1fr; }
@media (min-width: 48rem) { .foot__inner { grid-template-columns: 2fr 1fr 1fr; } }
.foot a { color: #fff; }
.foot a:hover { color: var(--sand); }
.foot ul { list-style: none; padding: 0; margin: 0; }
.foot li { margin-bottom: .4rem; }
.foot__name { font-weight: 700; font-size: 1.1rem; margin-bottom: .4rem; }
.foot__head { font-weight: 700; margin-bottom: .6rem; font-size: .82rem;
              text-transform: uppercase; letter-spacing: .07em; color: var(--sand); }
.foot__legal {
  margin-top: 2.5rem; padding-top: 1.25rem; border-top: 1px solid rgba(255,255,255,.18);
  font-size: .9rem; color: #c9d9de;
}


/* ---------------------------------------------------------------- photography
   Photographs are of the estate and, where people appear, of residents at
   Association events. No stock photography. The old site used stock portraits
   of models in place of the Road Representatives, which is exactly the sort of
   thing that makes a community site feel like a brochure. */

.hero--image {
  position: relative;
  background: var(--sea-deep);
  border-bottom: 0;
  padding: 0;
  text-align: left;
}
.hero--image .hero__photo {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block;
}
.hero--image::after {
  content: ""; position: absolute; inset: 0;
  /* The top of this photograph is bright overcast sky. At the original .30 the
     heading measured 2.46:1 against it, a clear fail, so it went to .60.
     On 22 August 2026 the photograph was measured properly rather than
     estimated: the brightest region is (246,247,249), not the (207,224,238)
     the audit had assumed, which put the lede at 4.20:1 and back under AA.
     Hence .70. Darker than is pretty, but the sky is the least interesting
     part of the frame and legibility is not negotiable here.
     Swapping this photograph means re-measuring HERO_BRIGHTEST_PHOTO in
     tools/audit.py. The recipe is in the comment there. */
  background: linear-gradient(180deg, rgba(12,38,46,.70) 0%, rgba(12,38,46,.86) 100%);
}
.hero--image .wrap {
  position: relative; z-index: 2;
  padding-block: clamp(4rem, 14vw, 8.5rem);
}
.hero--image h1 {
  color: #fff; max-width: 18ch; margin-inline: 0;
  text-shadow: 0 1px 20px rgba(0,0,0,.35);
}
.hero__place { white-space: nowrap; }
/* The Association's name, above the headline. A committee member pointed out
   that somebody landing on the home page got the character of the place before
   they got who we are. Small, spaced and quiet: it identifies rather than
   competes with the headline underneath. Pure white, because it is small text
   over a photograph and this is the one place contrast is hardest won. */
.hero__eyebrow {
  margin: 0 0 .6rem;
  font-family: "Segoe UI", Roboto, -apple-system, BlinkMacSystemFont,
               "Helvetica Neue", Arial, sans-serif;
  font-size: clamp(.85rem, 1.9vw, 1rem);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 1px 12px rgba(0,0,0,.45);
}
.hero--image .hero__lede {
  color: #f4f8f9; margin-inline: 0; max-width: 40ch;
  text-shadow: 0 1px 12px rgba(0,0,0,.35);
}

figure.photo {
  margin: 2.5rem auto; max-width: 56rem; padding-inline: 1.25rem;
}
figure.photo img {
  width: 100%; border-radius: var(--radius); box-shadow: var(--shadow);
}
/* A portrait photograph, constrained by height rather than width. A phone
   panorama held upright is about 1 to 2.33, and at the 56rem measure above it
   would render over two thousand pixels tall. Height-capped and centred, it
   comes out as a tall narrow strip, which happens to suit a twitten. */
figure.photo--tall img {
  width: auto; max-width: 100%; max-height: 40rem;
  margin-inline: auto; display: block;
}

figure.photo figcaption {
  margin-top: .7rem; font-size: .92rem; color: var(--ink-soft);
  font-family: "Segoe UI", Roboto, -apple-system, sans-serif; line-height: 1.5;
}

/* A photograph that sits alongside text on wider screens. */
figure.photo--side { max-width: var(--measure); }
@media (min-width: 52rem) {
  figure.photo--side { max-width: 56rem; }
}

.gallery {
  list-style: none; padding: 0 1.25rem; margin: 2rem auto 3rem;
  max-width: 68rem; display: grid; gap: .9rem;
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 44rem) { .gallery { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 66rem) { .gallery { grid-template-columns: repeat(4, 1fr); } }
.gallery li { margin: 0; }
.gallery img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--radius); box-shadow: var(--shadow);
}

/* ---------------------------------------------------------------- motion */
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
}

/* ---------------------------------------------------------------- print
   The brief requires a printable equivalent of everything member-facing.
   Every page prints as a clean document with links spelled out in full. */
/* ------------------------------------------------------------------ the index
   The A-Z page. Two columns where there is room, one on a phone. The filter box
   is hidden in the HTML and revealed by script, so nobody sees a search box
   that cannot search. */
.index-filter { margin: 1.5rem auto; }
.index-filter[hidden] { display: none; }
.index-filter label {
  display: block; font-weight: 600; margin-bottom: .4rem;
}
.index-filter input {
  width: 100%; font: inherit; font-size: 1.05rem;
  padding: .7rem .9rem; color: var(--ink);
  background: var(--paper);
  border: 2px solid var(--rule); border-radius: var(--radius);
}
.index-filter input:focus-visible {
  outline: 3px solid var(--focus); outline-offset: 2px; border-color: var(--sea);
}
.index-filter__status {
  margin: .5rem 0 0; min-height: 1.5em;
  font-size: .95rem; color: var(--ink-soft);
}
.index-count { color: var(--ink-soft); font-size: .95rem; margin-top: 0; }

.index-jump ul {
  list-style: none; margin: 0 0 2rem; padding: 0;
  display: flex; flex-wrap: wrap; gap: .35rem;
}
.index-jump li { margin: 0; }
.index-jump a {
  display: block; min-width: 2.5rem; min-height: 2.5rem;
  line-height: 2.5rem; text-align: center;
  border: 1px solid var(--rule); border-radius: var(--radius);
  background: var(--paper-alt); font-weight: 600; text-decoration: none;
}
.index-jump a:hover { background: var(--sand-soft); text-decoration: underline; }

.index-group { margin-bottom: 2rem; }
.index-group[hidden] { display: none; }
.index-group h2 {
  margin: 0 0 .6rem; padding-bottom: .3rem;
  border-bottom: 2px solid var(--thatch);
  font-size: 1.35rem;
}
.index-list { list-style: none; margin: 0; padding: 0; }
.index-list li[hidden] { display: none; }
.index-list li {
  margin: 0; padding: .45rem 0;
  border-bottom: 1px solid var(--rule);
}
.index-list a { font-weight: 600; }
.index-list__ctx {
  display: block; font-size: .9rem; color: var(--ink-soft);
}

@media (min-width: 45rem) {
  .index-list { columns: 2; column-gap: 2.5rem; }
  .index-list li { break-inside: avoid; }
}

/* ---------------------------------------------------------------- form

   The first form on this site. It exists because 25 pages tell a resident to
   ask their Road Representative and, until now, none of them said how.

   Field styling follows .index-filter, which was the only input on the site
   before this. The submit button reuses .button so that its contrast is the
   combination audit.py already measures rather than a new one.

   Labels sit above their field rather than beside it: at 320px a label beside
   a field wraps into a column of single words, and the association between the
   two stops being obvious to anybody, sighted or not. */
.form { max-width: var(--measure); margin: 1.5rem 0 0; }
.form > p { margin: 0 0 1.4rem; }
.form label { display: block; font-weight: 600; margin-bottom: .4rem; }
.form .hint {
  display: block; font-weight: 400; color: var(--ink-soft);
  font-size: .95rem; margin: -.15rem 0 .45rem;
}
.form input[type="text"], .form input[type="email"],
.form select, .form textarea {
  width: 100%; font: inherit; font-size: 1.05rem;
  padding: .7rem .9rem; color: var(--ink); background: var(--paper);
  border: 2px solid var(--rule); border-radius: var(--radius);
}
.form textarea { min-height: 10rem; resize: vertical; line-height: 1.6; }
.form input[type="text"]:focus-visible,
.form input[type="email"]:focus-visible, .form select:focus-visible,
.form textarea:focus-visible, .form button:focus-visible {
  outline: 3px solid var(--focus); outline-offset: 2px; border-color: var(--sea);
}
.form button {
  border: 0; cursor: pointer; font: inherit; font-size: 1.05rem;
  font-weight: 600;
  /* 44px minimum, which is the smallest target most guidance will accept for a
     finger. The first version of the Road Rep button was 21 pixels tall. */
  min-height: 44px;
}

/* The honeypot: a field no person can see, reach or hear. Positioned off
   screen rather than display:none, because a bot that reads the stylesheet
   skips what is hidden and fills in everything else. aria-hidden keeps it from
   screen readers, tabindex=-1 from the keyboard, so no real person can reach
   it by accident and be silently ignored for it. */
.form .hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

@media print {
  .index-filter, .index-jump { display: none !important; }
  .index-list { columns: 2; }
}

/* -------------------------------------------------------------- slideshow
   A scrolling strip of photographs that happens to have buttons, rather than a
   carousel that happens to be scrollable. With no JavaScript the track still
   scrolls and snaps, on a phone you swipe it, and the buttons simply never
   appear. Nothing moves on its own: see the note in tools/build.py. */
.slideshow { margin: 2.5rem auto; }
.slideshow__track {
  display: flex; gap: 1rem;
  list-style: none; margin: 0; padding: 0 0 .75rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
}
.slideshow__track:focus-visible { outline: 3px solid var(--focus); outline-offset: 4px; }
.slideshow__slide {
  flex: 0 0 100%;
  scroll-snap-align: center;
  margin: 0;
}
.slideshow__slide figure { margin: 0; }
.slideshow__slide img {
  width: 100%; height: auto;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  background: var(--paper-alt);
}
.slideshow__slide figcaption {
  margin-top: .6rem; font-size: .95rem; color: var(--ink-soft); line-height: 1.5;
}
.slideshow__hint, .slideshow__status {
  margin: .5rem 0 0; font-size: .9rem; color: var(--ink-soft);
}
.slideshow__controls {
  display: flex; align-items: center; gap: .75rem; margin-top: .75rem;
}
.slideshow__btn {
  min-width: 44px; min-height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  font: inherit; font-size: 1.25rem; line-height: 1;
  color: #fff; background: var(--sea-deep);
  border: 0; border-radius: var(--radius); cursor: pointer;
}
.slideshow__btn:hover { background: var(--sea); }
.slideshow__btn[disabled] { opacity: .35; cursor: default; }
.slideshow__btn:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
/* The pause control sits apart from the arrows: it does something different
   and a reader hunting for the stop button should not have to read three
   identical squares to find it. */
.slideshow__btn--play { margin-left: .5rem; background: var(--thatch-ink); }
/* Darker on hover, not lighter. Lightening this to #a2732f dropped the glyph to
   4.18:1 and failed AA, which is easy to miss because a hover state is not
   where anyone looks for a contrast bug. 6.67:1. */
.slideshow__btn--play:hover { background: #7a5522; }

/* Two at a time once there is room, so the strip reads as a strip. */
@media (min-width: 48rem) {
  .slideshow__slide { flex-basis: calc(50% - .5rem); }
}

@media (prefers-reduced-motion: reduce) {
  .slideshow__track { scroll-behavior: auto; }
}

@media print {
  /* A scrolling strip prints as one picture and a lot of white paper. On paper
     it becomes an ordinary stack of photographs instead. */
  .slideshow__controls, .slideshow__hint, .slideshow__status { display: none !important; }
  .slideshow__track { display: block; overflow: visible; }
  .slideshow__slide { break-inside: avoid; margin-bottom: 1rem; max-width: 12cm; }
}

@media print {
  .masthead, .foot, .skip, .subnav, .crumbs, .menu-toggle, .quick,
  .gallery, .hero--image .hero__photo, .form { display: none !important; }
  /* A printed form cannot be submitted, so it is replaced by the route that
     works on paper. Nobody is excluded for not being online. */
  .form-print::after {
    content: "To reach your Road Representative by post or telephone, use the "
             "Association's details above.";
    display: block; font-style: italic;
  }
  body { background: #fff; color: #000; font-size: 11.5pt; line-height: 1.45; }
  main > * { max-width: none !important; padding-inline: 0 !important; }
  h1, h2, h3 { color: #000; page-break-after: avoid; }
  h2, h3 { margin-top: 1.2em; }
  a { color: #000; text-decoration: underline; }
  /* Spell out link destinations, because a printed page cannot be clicked.
     Anchor links are excluded: the glossary is cross-linked from most pages and
     printing "(/our-estate/words-we-use/#twitten)" after every term would bury
     the sentence it is meant to help. */
  main a[href^="http"]::after,
  main a[href^="/"]:not([href*="#"])::after { content: " (" attr(href) ")"; font-size: 9pt; word-break: break-all; }
  .callout { border: 1px solid #999; background: none; page-break-inside: avoid; }
  .hero--image::after { display: none; }
  .hero--image h1, .hero--image .hero__lede { color: #000; text-shadow: none; }
  figure.photo { max-width: 12cm; page-break-inside: avoid; }
  figure.photo img { box-shadow: none; border: 1px solid #ccc; }
  table, blockquote, .card { page-break-inside: avoid; }
  main::after {
    content: "Middleton on Sea Association  ·  mosassociation.org";
    display: block; margin-top: 2em; padding-top: .5em;
    border-top: 1px solid #999; font-size: 9pt;
  }
}

/* ------------------------------------------------- members' area (served by
   tools/members-service.py, not built into the site, so the layout rules in
   `main > *` never reach it). Its own measure, matching every other page. */
.members-page {
  max-width: var(--measure); margin-inline: auto;
  padding: 2rem 1.25rem 4rem;
}
.members__out {
  display: flex; flex-wrap: wrap; align-items: center; gap: .75rem;
  justify-content: flex-end; font-size: .9rem; color: var(--ink-soft);
  margin-bottom: 1rem;
}
.button--quiet {
  background: transparent; color: var(--sea-deep);
  border: 1px solid var(--sea-deep); padding: .4rem .8rem;
  border-radius: var(--radius); cursor: pointer; font-size: .9rem;
}
.button--quiet:hover { background: var(--sea-deep); color: #fff; }
