/* ==========================================================================
   Midrand Wild Goose — warm editorial
   Hand-written vanilla CSS. No framework, no build step, no preprocessor.

   Order: faces, tokens, reset, type, layout primitives, chrome, components,
   controls, motion, breakpoints. Nothing below overrides a token.
   ========================================================================== */

/* ---------------------------------------------------------------- faces --
   Both faces are variable, clamped to the 400..500 the design uses, and
   subset to the Latin range listed below. tools/fonts.py is the source of
   this unicode-range and build.py asserts no page emits a character outside
   it, so the two cannot drift apart.                                      */

@font-face {
  font-family: "Newsreader";
  src: url("/assets/fonts/newsreader-latin-var.woff2") format("woff2-variations"),
       url("/assets/fonts/newsreader-latin-var.woff2") format("woff2");
  font-weight: 400 500;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC,
                 U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Geist";
  src: url("/assets/fonts/geist-latin-var.woff2") format("woff2-variations"),
       url("/assets/fonts/geist-latin-var.woff2") format("woff2");
  font-weight: 400 500;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC,
                 U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* --------------------------------------------------------------- tokens -- */

:root {
  /* colour. One accent for the whole site. No section inverts the theme. */
  --canvas:     #F7F6F3;
  --tint:       #F1EFEA;   /* alternate section ground, 1 step off canvas */
  --surface:    #FFFFFF;
  --ink:        #111111;   /* never #000 */
  --ink-muted:  #5F5B54;   /* 6.3:1 on canvas */
  /* Brand purple, sampled from the goose mark — the weighted mean of the
   * purple cluster in the 2017 artwork is rgb(88,47,139), and #572691 is the
   * saturated centre of it. 9.3:1 on canvas, so it clears AA for body text as
   * well as for large text, and white on it is 10.0:1 for the solid button.
   * The garden green this replaced measured 7.2:1 and was not the brand. */
  --accent:     #572691;
  --accent-ink: #431C73;   /* 11.8:1, the hover and active step */

  /* Two border colours, and the difference matters.
   *
   * --hairline is decoration: the edge of a static card, a divider, a tag.
   * At 1.2:1 it is deliberately almost invisible, which is the point, and
   * WCAG 1.4.11 does not apply to purely decorative boundaries.
   *
   * --control-line is the boundary of an actual control — a text input, a
   * select, a ghost button, the mobile menu button — where the border IS
   * what tells you the control is there. Those must clear 3:1. This value
   * is the lightest warm grey that does so against all three grounds the
   * site uses: 3.75 on white, 3.47 on canvas, 3.26 on tint.
   */
  --hairline:     #E3DFD8;
  --control-line: #8A8378;
  --placeholder:  #6E6A62;  /* 5.0:1 on canvas, still clearly not a value */

  /* type */
  --display: "Newsreader", ui-serif, Georgia, "Times New Roman", serif;
  --sans: "Geist", ui-sans-serif, system-ui, -apple-system, "Segoe UI",
          Helvetica, Arial, sans-serif;

  /* space */
  --s1: 4px;   --s2: 8px;   --s3: 12px;  --s4: 16px;  --s5: 24px;
  --s6: 32px;  --s7: 48px;  --s8: 64px;  --s9: 96px;  --s10: 128px;

  --sect-y: var(--s9);
  --gutter: var(--s5);
  --wrap: 1200px;
  --measure: 65ch;

  --r-card: 8px;
  --r-ctl: 6px;

  --head-h: 72px;

  /* one easing for entry, one for interaction */
  --ease-in-view: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-ui: cubic-bezier(0.32, 0.72, 0, 1);
  --lift: 0 2px 8px rgba(17, 17, 17, 0.04);
}

/* ---------------------------------------------------------------- reset -- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--head-h) + var(--s5));
}

body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, p, ul, ol, figure, blockquote, address { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img, picture, svg { display: block; max-width: 100%; }
img { height: auto; }
button { font: inherit; color: inherit; }
address { font-style: normal; }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
a:hover { color: var(--accent-ink); }

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

::selection { background: #D8E0D5; color: var(--ink); }

.skip {
  position: absolute;
  left: var(--s4);
  top: calc(-1 * var(--s10));
  z-index: 100;
  padding: var(--s3) var(--s4);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-ctl);
  color: var(--ink);
  text-decoration: none;
  transition: top 160ms var(--ease-ui);
}
.skip:focus { top: var(--s4); }

/* ----------------------------------------------------------------- type -- */

.hero__h {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2.5rem, 5vw, 3.75rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.sect__h, .split__h, .band__h, .phead__h {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2rem, 3.5vw, 2.75rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.pair__h, .card__h, .contact__value {
  font-family: var(--sans);
  font-weight: 500;
  font-size: 1.5rem;
  line-height: 1.25;
  letter-spacing: -0.01em;
}

.lead {
  font-size: clamp(1.1875rem, 1.6vw, 1.375rem);
  line-height: 1.5;
  color: var(--ink);
}

.eyebrow {
  font-size: 0.75rem;
  font-weight: 500;
  line-height: 1.5;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-muted);
}

small, .small { font-size: 0.875rem; line-height: 1.5; }

/* ----------------------------------------------------- layout primitives -- */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.sect { padding-block: var(--sect-y); }
.sect--tight { padding-block: var(--s7); }
.sect--tint { background: var(--tint); }

.sect__h + .sect__intro { margin-top: var(--s4); }
.sect__intro { max-width: var(--measure); color: var(--ink-muted); }
.sect__h + .grid,
.sect__h + .strip,
.sect__h + .cards,
.sect__h + .quotes,
.sect__h + .tags { margin-top: var(--s7); }

/* --------------------------------------------------------------- header -- */

.head {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--canvas);
  border-bottom: 1px solid var(--hairline);
}

.head__in {
  min-height: var(--head-h);
  display: flex;
  align-items: center;
  gap: var(--s5);
}

/* The mark is the bird plus the wordmark, and the two are sized off each
 * other: 2.5rem of goose is almost exactly the height of the two text lines,
 * so the lockup reads as one block with a flat baseline rather than as an
 * icon parked next to some type. */
.mark {
  display: flex;
  align-items: center;
  gap: var(--s3);
  color: var(--ink);
  text-decoration: none;
  margin-right: auto;
  padding-block: var(--s3);
}
.mark__words { display: block; }
.mark__name {
  display: block;
  font-family: var(--display);
  font-size: 1.25rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
}
.mark__sub {
  display: block;
  font-size: 0.6875rem;
  line-height: 1.4;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* The goose. Width is derived from the viewBox so the two never disagree,
 * and the whole thing is one colour: the wing is the same accent held back,
 * standing in for the silver gradient the original used. A logo is exempt
 * from WCAG 1.4.3 and 1.4.11, which is why the wing is allowed to sit at
 * 1.6:1 against the canvas — it is shading inside a mark, not a boundary
 * anyone has to see to use the site. */
.goose {
  display: block;
  height: 2.5rem;
  width: auto;
  flex: none;
  color: var(--accent);
}
.goose__wing { opacity: 0.34; }
.mark:hover .goose { color: var(--accent-ink); }

.nav { display: flex; align-items: center; gap: var(--s6); }
.nav__list { display: flex; align-items: center; gap: var(--s5); }

.nav__list a {
  display: block;
  padding-block: var(--s2);
  color: var(--ink);
  font-size: 0.9375rem;
  text-decoration: none;
  position: relative;
}
.nav__list a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 220ms var(--ease-ui);
}
.nav__list a:hover::after { transform: scaleX(1); }
.nav__list a[aria-current="page"] { color: var(--accent); }
.nav__list a[aria-current="page"]::after {
  background: var(--accent);
  transform: scaleX(1);
}

.nav__tel {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  padding: var(--s2) var(--s4);
  border: 1px solid var(--control-line);
  border-radius: 9999px;
  background: var(--surface);
  color: var(--ink);
  font-size: 0.875rem;
  text-decoration: none;
  white-space: nowrap;
  transition: border-color 200ms var(--ease-ui), box-shadow 200ms var(--ease-ui);
}
.nav__tel:hover { border-color: var(--accent); box-shadow: var(--lift); color: var(--ink); }
.nav__tel .i { color: var(--accent); }

.burger { display: none; }

/* ------------------------------------------------------------------ hero --
   A full-bleed 16:9 band, height-capped so the headline and both buttons sit
   above the fold on a laptop, with the text panel lifted over the bottom
   edge of the photograph.                                                 */

.hero { padding-bottom: var(--s9); }

.hero__media { background: var(--tint); }
.hero__media img {
  width: 100%;
  aspect-ratio: 16 / 9;
  max-height: 52vh;
  object-fit: cover;
}

.hero__in {
  position: relative;
  z-index: 1;
  max-width: 940px;
  margin-top: -56px;
  padding-top: var(--s7);
  padding-bottom: 0;
  background: var(--canvas);
  border-top-left-radius: var(--r-card);
  border-top-right-radius: var(--r-card);
}

.hero__sub {
  margin-top: var(--s5);
  max-width: 48ch;
  font-size: clamp(1.0625rem, 1.4vw, 1.1875rem);
  color: var(--ink-muted);
}

.hero__acts {
  margin-top: var(--s6);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
}

/* page head, for the one page with no photograph */

.phead {
  padding-top: var(--s8);
  padding-bottom: var(--s7);
  border-bottom: 1px solid var(--hairline);
}
.phead__in { max-width: 820px; }
.phead__sub {
  margin-top: var(--s4);
  max-width: 50ch;
  font-size: 1.1875rem;
  color: var(--ink-muted);
}

/* ----------------------------------------------------------------- prose -- */

.prose {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: var(--s9);
  align-items: start;
}
.prose--single { grid-template-columns: minmax(0, 1fr); }

.prose__body { max-width: var(--measure); }
.prose__body > * + * { margin-top: var(--s5); }
.prose__body p { color: var(--ink-muted); }
.prose__body .lead { color: var(--ink); }
.prose__body strong { font-weight: 500; color: var(--ink); }
.prose__body .eyebrow + .lead { margin-top: var(--s3); }
.prose__body .sect__h + p { margin-top: var(--s5); }

/* a single pull quote, so the landing page keeps its social proof without
   spending a whole section on it */
.pull {
  padding-left: var(--s5);
  border-left: 2px solid var(--accent);
}
.pull blockquote p {
  font-family: var(--display);
  font-size: 1.375rem;
  line-height: 1.4;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.pull figcaption {
  margin-top: var(--s4);
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--ink);
}
.pull__src {
  display: block;
  font-weight: 400;
  color: var(--ink-muted);
}

/* ------------------------------------------------------------- data-pair -- */

.pair {
  margin-top: var(--s7);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s7);
}
.pair__col { min-width: 0; }
.pair__note { margin-top: var(--s4); color: var(--ink-muted); }
.pair__h + .pair__note { margin-top: var(--s3); }

.ticks { margin-top: var(--s4); display: grid; gap: var(--s2); }
.ticks li {
  position: relative;
  padding-left: var(--s5);
  color: var(--ink);
}
/* Most tick items are statements — the distances on the home page — but on the
   404 page and in the handler's error list they are links, and a link has to
   be a target in its own right. Bare, they measured 22px, under the 24px WCAG
   2.5.8 asks for at AA; this takes them to 32px. Only the link variant is
   touched, so the statement lists keep their tighter rhythm. */
.ticks a {
  display: inline-block;
  padding-block: 5px;
}
/* The padding pushes the text down, so the bullet follows it. If a browser
   lacks :has() the dot sits 5px high on these two pages and nothing else
   changes, which is a fair trade for not restructuring a working component. */
.ticks li:has(a)::before { top: calc(0.68em + 5px); }

.ticks li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.68em;
  width: 7px;
  height: 7px;
  border-radius: 9999px;
  background: var(--accent);
}

/* ----------------------------------------------------------------- split -- */

.split {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s9);
  align-items: center;
}
.split--flip .split__media { order: 2; }

/* A deliberately narrow media column. The only portrait original is 477px
   wide, so a half-width column would upscale it; 320px keeps it near 1.5x.
   It is also a height decision — at 360px the 3:4 image stood 480px tall
   against three short paragraphs and the pair drifted apart, so the column is
   sized to the copy beside it rather than to the grid. Closer gap and a
   slightly longer measure for the same reason. */
.split--portrait {
  grid-template-columns: minmax(0, 320px) minmax(0, 1fr);
  gap: var(--s7);
}
/* The cap, not the column, is what holds below 901px: the split collapses to
   one column there, and an uncapped 3:4 image in a 700px column would stand
   930px tall and be upscaled nearly 1.5x to do it. */
.split--portrait .split__media { max-width: 320px; }
.split--portrait .split__media img { aspect-ratio: 3 / 4; }
.split--portrait .split__body p { max-width: 52ch; }

.split__media img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--r-card);
}
.split__body { min-width: 0; }
.split__body > * + * { margin-top: var(--s5); }
.split__body .eyebrow + .split__h,
.split__body .eyebrow + .lead { margin-top: var(--s3); }
.split__body p { color: var(--ink-muted); max-width: 46ch; }

/* --------------------------------------------------------- strip, grid --- */

.strip, .grid {
  display: grid;
  gap: var(--s5);
}
.strip { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid  { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.strip figure, .grid figure { min-width: 0; }

.strip img, .grid img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--r-card);
  background: var(--tint);
}

.grid figcaption {
  margin-top: var(--s3);
  font-size: 0.875rem;
  color: var(--ink-muted);
}

/* ----------------------------------------------------------- amenity cards -- */

.cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s5);
}

.card {
  padding: var(--s6);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  transition: box-shadow 240ms var(--ease-ui);
}
/* Shadow only. An earlier version darkened the border here too, but these
   cards are not interactive — a border that changes colour on hover without
   being a control is a 3:1 non-text contrast obligation bought for nothing. */
.card:hover { box-shadow: var(--lift); }

.card__icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 6px;           /* concentric with the 8px card */
  background: var(--tint);
  color: var(--accent);
}
.card__h { margin-top: var(--s5); }
.card p { margin-top: var(--s3); color: var(--ink-muted); font-size: 1rem; }

/* ------------------------------------------------------------------ tags -- */

.tags { display: flex; flex-wrap: wrap; gap: var(--s3); }
.tags li {
  padding: var(--s3) var(--s5);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 9999px;
  font-size: 0.9375rem;
  color: var(--ink);
}

/* ---------------------------------------------------------------- quotes -- */

.quotes {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s5);
}

.quote {
  display: flex;
  flex-direction: column;
  padding: var(--s6);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
}
.quote__title {
  font-family: var(--sans);
  font-size: 0.875rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--accent);
}
.quote blockquote { margin-top: var(--s4); }
.quote blockquote p {
  font-family: var(--display);
  font-size: 1.125rem;
  line-height: 1.5;
  color: var(--ink);
}
.quote figcaption {
  margin-top: var(--s5);
  padding-top: var(--s4);
  border-top: 1px solid var(--hairline);
  font-size: 0.875rem;
  font-weight: 500;
}
.quote__src { display: block; font-weight: 400; color: var(--ink-muted); }

.quotes__more { margin-top: var(--s6); }

/* -------------------------------------------------------------- contacts -- */

.contacts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s5);
}

.contact {
  display: block;
  padding: var(--s6);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  color: var(--ink);
  text-decoration: none;
  transition: box-shadow 240ms var(--ease-ui), border-color 240ms var(--ease-ui),
              transform 240ms var(--ease-ui);
}
.contact:hover {
  box-shadow: var(--lift);
  border-color: var(--accent);
  transform: translateY(-2px);
  color: var(--ink);
}
.contact__icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 6px;
  background: var(--tint);
  color: var(--accent);
}
.contact__label {
  display: block;
  margin-top: var(--s5);
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-muted);
}
.contact__value { display: block; margin-top: var(--s2); overflow-wrap: anywhere; }

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

.band { background: var(--tint); border-top: 1px solid var(--hairline); }
.band__in { max-width: 760px; }
.band__body { margin-top: var(--s4); color: var(--ink-muted); }
.band .eyebrow + .band__h { margin-top: var(--s3); }
.band__acts {
  margin-top: var(--s6);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
}

/* --------------------------------------------------------------- controls -- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  min-height: 48px;
  padding: 0 var(--s6);
  border: 1px solid transparent;
  border-radius: var(--r-ctl);
  font-size: 0.9375rem;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 200ms var(--ease-ui), border-color 200ms var(--ease-ui),
              box-shadow 200ms var(--ease-ui), color 200ms var(--ease-ui);
}

.btn--solid { background: var(--accent); color: #FFFFFF; }
.btn--solid:hover { background: var(--accent-ink); color: #FFFFFF; box-shadow: var(--lift); }

.btn--ghost { background: transparent; border-color: var(--control-line); color: var(--ink); }
.btn--ghost:hover { border-color: var(--accent); color: var(--ink); box-shadow: var(--lift); }

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  font-weight: 500;
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding-bottom: 2px;
}
.link-arrow .i { transition: transform 240ms var(--ease-ui); }
.link-arrow:hover .i { transform: translateX(3px); }

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

.form-wrap {
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
  gap: var(--s9);
  align-items: start;
}
.form-intro > * + * { margin-top: var(--s4); }
.form-intro .eyebrow + .sect__h { margin-top: var(--s3); }
.form-intro p { color: var(--ink-muted); max-width: 42ch; }
.form-alt { font-size: 0.9375rem; }

.form {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: var(--s5);
  padding: var(--s7);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
}

.f { display: block; min-width: 0; }
.f--full  { grid-column: span 6; }
.f--half  { grid-column: span 3; }
.f--third { grid-column: span 2; }

.f__label {
  display: block;
  margin-bottom: var(--s2);
  font-size: 0.875rem;
  font-weight: 500;
}
.f__opt { font-weight: 400; color: var(--ink-muted); }

.f input, .f select, .f textarea {
  width: 100%;
  min-height: 48px;
  padding: var(--s3) var(--s4);
  background: var(--canvas);
  border: 1px solid var(--control-line);
  border-radius: var(--r-ctl);
  font: inherit;
  font-size: 1rem;
  color: var(--ink);
  transition: border-color 180ms var(--ease-ui), background-color 180ms var(--ease-ui);
}
.f textarea { min-height: 132px; padding-top: var(--s3); resize: vertical; }
.f input:hover, .f select:hover, .f textarea:hover { border-color: var(--ink-muted); }
.f input:focus, .f select:focus, .f textarea:focus {
  background: var(--surface);
  border-color: var(--accent);
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
/* No field currently ships a placeholder — every field is labelled instead.
   The rule is here so that if one is ever added it starts out legible. */
.f input::placeholder, .f textarea::placeholder { color: var(--placeholder); }

.f select {
  appearance: none;
  padding-right: var(--s8);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235F5B54' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--s4) center;
}

.form__foot { grid-column: span 6; display: grid; gap: var(--s4); }
.form__note { font-size: 0.875rem; color: var(--ink-muted); }
.form__foot .btn { justify-self: start; }

/* the honeypot. Off-screen rather than display:none, because some bots skip
   fields that are not rendered at all. Hidden from assistive tech and from
   the tab order, so a real visitor can never reach it. */
.trap {
  position: absolute !important;
  left: -9999px !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* --------------------------------------------------------------- footer -- */

.foot {
  background: var(--canvas);
  border-top: 1px solid var(--hairline);
  padding-top: var(--s9);
}

.foot__in {
  display: grid;
  grid-template-columns: 1.4fr repeat(3, 1fr);
  gap: var(--s7);
  padding-bottom: var(--s8);
}

/* Larger here than in the header, and on its own line: the footer column is
 * wide and otherwise has no focal point. */
.foot__mark { margin-bottom: var(--s4); }
.foot__mark .goose { height: 3.25rem; }

.foot__name {
  font-family: var(--display);
  font-size: 1.375rem;
  letter-spacing: -0.01em;
}
.foot__blurb {
  margin-top: var(--s3);
  max-width: 34ch;
  font-size: 0.9375rem;
  color: var(--ink-muted);
}

.foot__h {
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-muted);
}

.foot__addr { margin-top: var(--s4); font-size: 0.9375rem; color: var(--ink-muted); }

.foot__link {
  display: block;
  margin-top: var(--s3);
  font-size: 0.9375rem;
  color: var(--ink);
  text-decoration: none;
  width: fit-content;
  border-bottom: 1px solid transparent;
  overflow-wrap: anywhere;
  transition: border-color 200ms var(--ease-ui);
}
.foot__link:hover { color: var(--ink); border-bottom-color: var(--ink); }
.foot__link--strong { font-weight: 500; }
.foot__h + .foot__link { margin-top: var(--s4); }

.foot__base {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--s4);
  padding-block: var(--s5);
  border-top: 1px solid var(--hairline);
  font-size: 0.875rem;
  color: var(--ink-muted);
}
/* The gap is reduced from --s5 to --s4 because the links now carry their own
   vertical padding, which supplies the separation the gap used to. */
.foot__nav { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4); }
.foot__nav a {
  display: inline-block;
  /* Bare text links here measured 18px tall, under the 24px minimum target
     size WCAG 2.5.8 requires at AA. The padding takes them to 40px without
     changing how they look. */
  padding: 11px var(--s2);
  margin-inline-start: calc(var(--s2) * -1);   /* keep the row optically flush */
  color: var(--ink-muted);
  text-decoration: none;
}
.foot__nav a:hover { color: var(--ink); }

/* ----------------------------------------------------------------- 404 --- */

.oops { padding-block: var(--s10); }
.oops__in { max-width: 560px; }
.oops p { margin-top: var(--s4); color: var(--ink-muted); }
.oops__acts { margin-top: var(--s6); display: flex; flex-wrap: wrap; gap: var(--s3); }

/* --------------------------------------------------------------- motion --
   Entry animation is additive: the hidden state only applies once the inline
   head script has set .js, so if the stylesheet loads and the script does
   not, every section is simply visible. IntersectionObserver drives it —
   there is no scroll listener anywhere in site.js.                        */

@media (prefers-reduced-motion: no-preference) {
  .js [data-reveal] {
    opacity: 0;
    transform: translateY(12px);
    transition: opacity 600ms var(--ease-in-view), transform 600ms var(--ease-in-view);
    will-change: opacity, transform;
  }
  .js [data-reveal].is-in {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ------------------------------------------------------------ breakpoints -- */

@media (max-width: 1080px) {
  .prose { grid-template-columns: minmax(0, 1fr); gap: var(--s7); }
  .pull { max-width: var(--measure); }
  .split, .form-wrap { gap: var(--s7); }
  .foot__in { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s6); }
}

@media (max-width: 900px) {
  :root { --sect-y: var(--s8); }

  /* nav collapses to a disclosure panel */
  .burger {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    margin-left: auto;
    padding: 0;
    background: transparent;
    border: 1px solid var(--control-line);
    border-radius: var(--r-ctl);
    cursor: pointer;
  }
  .burger__bars, .burger__bars::before, .burger__bars::after {
    display: block;
    width: 18px;
    height: 1.5px;
    background: var(--ink);
    transition: transform 240ms var(--ease-ui), opacity 160ms var(--ease-ui);
  }
  .burger__bars::before, .burger__bars::after { content: ""; position: absolute; }
  .burger__bars::before { transform: translateY(-6px); }
  .burger__bars::after  { transform: translateY(6px); }
  .burger[aria-expanded="true"] .burger__bars { transform: rotate(45deg); }
  .burger[aria-expanded="true"] .burger__bars::before { opacity: 0; }
  .burger[aria-expanded="true"] .burger__bars::after  { transform: rotate(-90deg); }

  .mark { margin-right: 0; }

  .nav {
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    display: none;
    flex-direction: column;
    align-items: stretch;
    gap: var(--s4);
    padding: var(--s5) var(--gutter) var(--s6);
    background: var(--canvas);
    border-bottom: 1px solid var(--hairline);
  }
  .head__in { position: relative; flex-wrap: wrap; }
  .nav.is-open { display: flex; }
  .nav__list { flex-direction: column; align-items: stretch; gap: 0; }
  .nav__list a {
    padding-block: var(--s4);
    font-size: 1.0625rem;
    border-bottom: 1px solid var(--hairline);
  }
  .nav__list a::after { display: none; }
  .nav__tel { align-self: start; }

  .strip, .grid, .cards, .quotes, .contacts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .split, .pair, .form-wrap { grid-template-columns: minmax(0, 1fr); }
  .split--flip .split__media { order: 0; }
  .split__body p { max-width: var(--measure); }

  .hero__media img { max-height: 44vh; }
  .hero__in { margin-top: -40px; padding-top: var(--s6); }
}

@media (max-width: 680px) {
  :root { --sect-y: 56px; --gutter: var(--s4); }

  .sect--tight { padding-block: var(--s7); }
  .sect__h + .grid, .sect__h + .strip, .sect__h + .cards,
  .sect__h + .quotes, .sect__h + .tags { margin-top: var(--s6); }

  .grid, .cards, .quotes, .contacts { grid-template-columns: minmax(0, 1fr); }
  .strip { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }

  .form { padding: var(--s5); gap: var(--s4); }
  .f--half, .f--third { grid-column: span 6; }

  .hero { padding-bottom: var(--s8); }
  .hero__media img { aspect-ratio: 4 / 3; max-height: 48vh; }
  .hero__in { margin-top: -28px; }
  .hero__acts .btn { flex: 1 1 100%; }

  .phead { padding-top: var(--s7); }

  .foot__in { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .foot__base { justify-content: flex-start; }
}

/* ------------------------------------------------------- very small phones --
   320px is still in use, and at that width the wordmark's subtitle and the
   menu button cannot share a line: the header wrapped to 132px, nearly a
   quarter of the viewport, on every page. Tightening the subtitle rather than
   hiding it keeps "Guest House & Conference Centre" visible, which is the one
   line that says what the place actually is.

   Adding the goose cost that line about 36px and the header wrapped again, to
   121px. It is bought back here rather than by dropping the mark, because a
   phone is where the logo earns its keep. The subtitle loses 1px and some
   tracking, and the bird comes down to 1.75rem, which still clears the two
   text lines. Measured at 320: 73px, one line, no overflow. */
@media (max-width: 380px) {
  .head__in { gap: var(--s3); }
  .mark { gap: var(--s2); }
  .goose { height: 1.75rem; }
  .mark__name { font-size: 1.125rem; }
  .mark__sub { font-size: 0.625rem; letter-spacing: 0.035em; }
}
