/* International Executive Rentals — our own stylesheet.
 *
 * This replaces the 528 KB Squarespace stylesheet the clone used to serve. Every rule
 * here keys off a class this project's own templates emit; there is no `sqs-` selector,
 * no `data-*` selector, and no theme flag to fight. Colours and measures are the ones
 * the live site actually renders — its `proxima-nova` never loads, so what visitors see
 * is the Times New Roman fallback, and that is what this file reproduces without
 * downloading a font.
 */

/* ------------------------------------------------------------------ tokens */
:root {
  --ink: #1f2526;
  --ink-soft: rgba(31, 37, 38, 0.75);
  /* 0.55 measured 3.62:1 on white, which fails AA for body-size text. 0.65 is 4.91:1. */
  --ink-faint: rgba(31, 37, 38, 0.65);
  --teal: #2b6173;
  --teal-dark: #234f5e;
  --button: #272727;
  --paper: #ffffff;
  --rule: #d9d9d4;
  --wash: #f4f4f1;

  --measure: 1020px;   /* the live site's #page width */
  --prose-measure: 700px;
  --gap: 24px;

  --serif: "Times New Roman", Times, Georgia, serif;
  --ui: "Times New Roman", Times, serif;
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--serif);
  font-size: 18px;
  line-height: 1.6;
  color: var(--ink);
  background: var(--paper);
}

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

a { color: var(--ink-soft); text-decoration: none; }
a:hover { color: var(--ink); }

h1, h2, h3, h4 {
  font-weight: 400;
  line-height: 1.2;
  margin: 0 0 0.5em;
  /* These headings are set in capitals, so a long one breaks into two lines with one or two words
     stranded on the second. Balance gives the lines back. */
  text-wrap: balance;
}
h1 { font-size: 30px; text-transform: uppercase; }
h2 { font-size: 26px; text-transform: uppercase; }
h3 { font-size: 20px; text-transform: uppercase; }
h4 { font-size: 18px; }

p, ul, ol { margin: 0 0 1em; }

/* ------------------------------------------------------------------ access */
/* Hidden until focused, then pinned where a keyboard user can see it. */
.skip-link {
  position: absolute;
  left: 8px;
  top: -100px;
  z-index: 200;
  padding: 10px 16px;
  background: var(--ink);
  color: #fff;
  font-size: 16px;
  text-transform: uppercase;
}
.skip-link:focus { top: 8px; color: #fff; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

:focus-visible {
  outline: 3px solid var(--teal);
  outline-offset: 2px;
}
.site-header :focus-visible,
.site-footer :focus-visible { outline-color: #fff; }

/* ------------------------------------------------------------------ header */
.site-header {
  background: var(--teal);
  padding: 0 20px;
  /* The dropdown and the mobile menu are positioned against the header box, so it has to be a
     containing block, and it has to sit above the page so a panel can float over the banner. */
  position: relative;
  z-index: 100;
}
.header-inner {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 20px 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.site-logo img { max-width: 260px; }

/* The brand block is the wordmark alone. It used to carry a line of small capitals under the
   picture naming the family of bedroom listings in the bar — a caption, because at the time the
   four listings stood in the bar themselves and nothing in the menu named what they were. The
   bar names the family itself now: San Francisco Properties stands in the menu as the dropdown
   the listings open under, and a second city's family gets its own dropdown beside it. A caption
   repeating one city's name under the logo on every page would say the doubled thing and name
   the wrong one the day the second family arrives, so the picture stands alone. */
.site-brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

/* The nav is not a positioning context: the phone's menu panel anchors to the header, so
   opening it does not grow this box. The auto margin holds it at the right-hand end of
   whatever row it lands on, signed in or out. */
.site-nav { position: static; margin-left: auto; }

/* The way into the back office, printed only for a reader who is signed in — View.EditURL,
 * internal/site/render.go — and drawn as a button rather than as a link: the same box the Menu
 * toggle draws, filled white, so it reads as the one thing on the teal bar that does something
 * rather than names a page. Its letters are teal-dark on white, close to 9:1, and on hover it is
 * the fill that leaves, so the button keeps the shape it had.
 *
 * It sits in the bar's own flow, at the right-hand end of the wordmark's row: the menu shrink-wraps
 * to two rows beside the wordmark now, but wordmark, menu and button together are still wider than
 * the measure — 260 + 168 + 634, against the 1,020 the measure is — so the auto margin keeps the
 * button in the corner beside the wordmark's opposite end and the menu takes the row under them.
 * The signed-in bar is then the signed-out bar with one button added to a row it already had.
 * Below the desktop breakpoint the corner belongs to the Menu toggle, so the button sits beside the
 * toggle instead, and the toggle never moves. */
.header-edit {
  font-family: var(--ui);
  font-size: 14px;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--teal-dark);
  background: #fff;
  border: 1px solid rgba(255, 255, 255, 0.5);
  padding: 10px 18px;
  margin-left: auto;
}
.header-edit:hover { color: #fff; background: transparent; border-color: #fff; }

.nav-toggle {
  display: none;
  font-family: var(--ui);
  font-size: 14px;
  text-transform: uppercase;
  color: #fff;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.5);
  padding: 10px 18px;
  cursor: pointer;
}

/* The menu is two lists inside one box — the home link and the property families, each printed
   as a dropdown, on the first row, the site's pages and the two ways out on the second — because
   a wrapping flex list sizes itself to a single unbroken line. As one list the menu is too wide
   for the measure, so it always took a row of its own and the header became three lines tall; as
   two lists it shrink-wraps to its widest row and sits beside the wordmark in a header two lines
   tall. The box is what the Menu toggle opens and closes, which is why it is one focusable unit
   and one aria-controls target.

   The two kinds of page are divided by a hairline at both ends of the breakpoint — in the
   bar's first row, and inside the phone's panel, where the panel is no longer one flat list
   but a list with families printed open in it. The hairline sits close: 8 px of rule on each
   side, because what separates the rows is the rule, and 22 px of air around a 1 px line is
   padding pretending to be structure. */
.nav-rows { display: none; }

.nav-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 22px;
  width: max-content;
}

.nav-list a,
.nav-folder summary {
  font-family: var(--ui);
  font-size: 14px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.85);
  background: none;
  /* Every menu item reserves a 2px rule and leaves it clear. Reserving it here is what lets the
     current item be *drawn* rather than recoloured without the bar changing height. The folder's
     summary is a menu item too — it just opens one rather than naming one. */
  border-bottom: 2px solid transparent;
  padding: 6px 0;
  cursor: pointer;
}
/* Hover brightens the letters and draws a faint rule. The page you are on draws a solid one.
   Before this, "current" was 0.85 white against 1.0 white — the same difference hover makes, so
   the menu item for the page you were reading looked like whatever you were pointing at. */
.nav-list a:hover,
.nav-folder summary:hover {
  color: #fff;
  border-bottom-color: rgba(255, 255, 255, 0.45);
}
.nav-list a[aria-current="page"] {
  color: #fff;
  border-bottom-color: #fff;
}

/* A property family — San Francisco Properties, and whatever city comes next — sits in the bar
   as a dropdown: its title is the bar's item, and the listings it holds open under it. The
   family, not the listing, is the unit the bar names, so each city keeps its own door and its
   own list. The disclosure is native <details>, so the dropdown works with no JavaScript at
   all — with it, site.js opens it on mouse arrival and closes it on departure — and the
   open panel hangs 12 px below the title, which is the gap site.js's closing delay covers.
   The listing links inside it keep the nav-cat class — the same hook the bar's tests read — and
   the one that names the page being read takes the white rule like any other current link.

   Opening a family drops a panel *below* the bar instead of pushing the bar taller: the panel
   leaves the flex row (position: absolute), so the header keeps the exact height it had closed
   and the other menu items stay put. It is a shade darker than the bar so it reads as a menu
   attached to its title, and it floats over the page rather than displacing it. The family that
   holds the page being read is marked the way a current link is — the rule under its title is
   drawn, not the title recoloured. */
.nav-folder > details { position: relative; }
.nav-folder > details > summary { list-style: none; }
.nav-folder > details > summary::-webkit-details-marker { display: none; }
.nav-folder > details > summary::after { content: " \25BE"; }
.nav-folder > details[open] > summary::after { content: " \25B4"; }
.nav-folder.is-active > details > summary {
  color: #fff;
  border-bottom-color: #fff;
}
.nav-sublist {
  list-style: none;
  margin: 0;
  padding: 0;
}
.nav-sublist a { display: block; padding: 6px 0; }
.nav-folder > details[open] > .nav-sublist {
  position: absolute;
  top: calc(100% + 12px);
  left: 0;
  z-index: 120;
  min-width: 232px;
  margin: 0;
  padding: 10px 18px 12px;
  background: var(--teal-dark);
  box-shadow: 0 14px 30px rgba(18, 22, 23, 0.30);
}
.nav-folder > details[open] > .nav-sublist a { padding: 8px 0; }

@media (min-width: 960px) {
  /* The breakpoint is arithmetic, not taste: the measure is 1,020 inside a header padded 20, so a
     viewport of 1,060 gives the full measure, and the bar needs 260 px of wordmark, a 16 px gap and
     a 634 px menu — 910 px, so 960 leaves it room. Below it the menu folds behind the Menu toggle,
     exactly as it did at 900 before the menu shrank. */
  .nav-rows {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
  }
  .nav-list + .nav-list {
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid rgba(255, 255, 255, 0.18);
  }
}

@media (max-width: 959px) {
  .nav-toggle { display: block; }

  /* Beside the Menu toggle, not in the corner the toggle has always held. The button's own box
     shrinks before the bar's does, which is what keeps the pair on the wordmark's row down to a
     tablet's width; at a phone's width the pair takes the row below it instead. */
  .header-edit { padding: 8px 14px; }

  /* Inside the panel a row is no longer a row: both lists lay out as plain columns, each
     family printed open — its listings already hanging indented under its title, one tap
     from the toggle. A divider still divides the two lists here, because the panel is no
     longer one flat list to run your eye down: it has a shape, and the hairline is where
     the pages a visitor came for stop and the site's own pages begin. */
  .nav-list { display: block; width: auto; }

  /* The open menu is a panel that hangs *below* the bar, anchored to the header, so tapping
     Menu never stretches the bar down the page. It scrolls on its own if the list is taller
     than the screen, and it is tall enough, before scrolling, to hold the whole menu open:
     one row per page plus the family titles, at tap-target heights, come to a little over
     470 px. The family's dropdown inside it is a plain accordion rather than a second
     floating panel — there is nothing to float above. */
  .nav-rows.is-open {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    position: absolute;
    top: calc(100% + 12px);
    right: 20px;
    z-index: 120;
    width: min(340px, calc(100vw - 40px));
    max-height: min(80vh, 560px);
    overflow-y: auto;
    padding: 10px 20px 18px;
    background: var(--teal-dark);
    box-shadow: 0 16px 34px rgba(18, 22, 23, 0.34);
  }
  .nav-rows.is-open .nav-list + .nav-list {
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid rgba(255, 255, 255, 0.18);
  }

  /* Inside the panel, a link's padding is a finger's target, not a cursor's aim: 6 px under a
     14 px line reads as both a cramped list and a small mark to hit. The panel's links take
     11 px above and below — with the line box, a strip about 39 px tall, near the 44 px the
     guidelines reach for and comfortably above what a row of 6 px strips was — and they go
     block, because padding is only a target when it belongs to a box: an inline link's strip
     of paint is the text, and a thumb aiming beside the word hits the panel, not the link.
     The listings inside a family take 9 px rather than 11: they are the row under the title,
     and a step down in air is what says they belong to it. */
  .nav-rows.is-open .nav-list a,
  .nav-rows.is-open .nav-folder summary { display: block; padding: 11px 0; }
  .nav-rows.is-open .nav-folder details[open] .nav-sublist a { padding: 9px 0; }

  /* Inside the panel an opened family stops floating: the panel already floats, and a second
     one inside it would float over its own list. The listings hang under their title with an
     indent and a little air of their own, so it is visible which door each one belongs to —
     which is the whole point of a family once a second city's door stands above this one.
     The title still answers a tap, to fold its list away; site.js is what opens every family
     when the panel is the menu, so no listing ever waits behind a closed title. */
  .nav-folder > details[open] > .nav-sublist {
    position: static;
    min-width: 0;
    margin: 0;
    padding: 2px 0 8px 20px;
    background: none;
    box-shadow: none;
  }
}

/* ------------------------------------------------------------------ flash */
.flash {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 16px 32px;
  font-size: 16px;
}
.flash-ok { background: #eaf3ef; color: #1d4b34; }
.flash-error { background: #f8e9e7; color: #7a1f16; }

/* ------------------------------------------------------------------ gate */
/* The page in front of the one menu item that leaves the site (internal/site/gate.go). It is
 * deliberately short and plain: its whole job is to be read before the click, so nothing on it
 * competes with the address it names. The column is the prose measure, not the 1020px page
 * measure — a departure notice you have to scan across two columns is a notice you skip. */
.gate { max-width: var(--prose-measure); }
.gate h1 { margin-bottom: 20px; }
.gate-lead { font-size: 20px; line-height: 1.55; }
.gate-facts { margin: 26px 0 32px; padding-left: 1.25em; }
.gate-facts li { margin-bottom: 0.55em; }
.gate-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 22px; margin: 0 0 26px; }
.gate-back { color: var(--teal); border-bottom: 1px solid var(--rule); }
.gate-back:hover { color: var(--ink); border-bottom-color: var(--teal); }
/* The full destination, printed. This is the one page on the site where reading exactly where you
 * are going is the point of the page, so it is set as content rather than hidden in a title. */
.gate-url {
  font-size: 15px;
  color: var(--ink-faint);
  overflow-wrap: break-word;
}

/* ------------------------------------------------------------------ banner */
/* The banner spans the viewport, so it lives outside the content column. Its box is
 * reserved by aspect-ratio, which is what keeps the page from jumping when the file
 * arrives. */
.banner { margin: 0; overflow: hidden; }
.banner-img {
  width: 100%;
  aspect-ratio: 21 / 9;
  min-height: 240px;
  max-height: 560px;
  object-fit: cover;
}
.banner-caption {
  max-width: var(--prose-measure);
  margin: 0 auto;
  padding: 24px 32px 0;
}

/* The property page prints its name and headline over the hero photograph itself. Whatever the
   photograph is, the words go at the bottom left of the picture in white, and what makes them
   readable on a bright sky, a pale façade, or a dark interior is not luck: a gradient wash rises
   from the bottom edge and reaches full darkness exactly where the words stand, so the contrast
   under them never falls below about 5:1 no matter what the image shows. The shadow is a second
   layer of insurance against the brightest possible pixels. */
.property-banner { position: relative; }
.property-banner::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top,
    rgba(17, 20, 21, 0.82) 0%,
    rgba(17, 20, 21, 0.55) 30%,
    rgba(17, 20, 21, 0) 65%);
  pointer-events: none;
}
.banner-overlay {
  /* Above the wash: the pseudo-element is the figure's last child and would otherwise paint
     over the caption's own box. */
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  align-items: flex-end;
}
.banner-overlay-inner {
  width: 100%;
  /* The same column the header and the page body are pinned to, so the words begin exactly
     where the prose below begins. */
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 32px 40px;
}
.banner-eyebrow {
  margin: 0 0 10px;
  font-size: 15px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: rgba(255, 255, 255, 0.9);
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.55);
}
.property-banner .banner-headline {
  margin: 0;
  max-width: 24em;
  color: #fff;
  font-size: 40px;
  text-shadow: 0 2px 14px rgba(0, 0, 0, 0.5);
}
@media (max-width: 899px) {
  .property-banner .banner-headline { font-size: 32px; }
}

/* ------------------------------------------------------------------ layout */
main { display: block; }

.page-body {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 32px;
}

/* The home page is a stack of full-width photographs, each followed by its heading and copy.
   Every section used to carry its own 64px top and bottom padding, so a paragraph and the next
   photograph sat 92px apart while the heading touched the bottom edge of the picture above it.
   The rhythm is now a single value — one fixed gap between sections — the photograph gets a
   little air before the words begin, and the copy is a centred column under the photograph
   instead of a left-pinned block with a wide blank margin on its right. */
.home-section {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 32px;
}
.home-section:first-child { padding-top: 48px; }
.home-section:last-child { padding-bottom: 56px; }
.home-section + .home-section { margin-top: 56px; }
.home-section .banner { margin-bottom: 28px; }
.home-section .section-body { max-width: var(--prose-measure); margin: 0 auto; }

.folder-nav {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 32px 32px 0;
}
/* The title used to be 15 px at 400 weight in faint ink — fine print sitting above the very links
   it names, so the whole list read like a footnote. It is a signpost, not a whisper: 18 px, bold,
   in the same soft ink the links carry. */
.folder-nav-title {
  font-size: 18px;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0 0 14px;
}
.folder-nav ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 26px; }
/* At 14 px and 400 weight the links were smaller than the page's own body copy (18 px) — the one
   row a visitor uses to choose a bedroom count was the weakest type on the page. Bold 16 px puts
   them at the body's weight class without shouting past the 18 px title over them. */
.folder-nav a {
  display: inline-block;
  /* The rule is drawn on the word, not on the row, so it stops where the label stops — and it is
     reserved here, clear, so marking the current page does not nudge the labels around it. */
  padding-bottom: 6px;
  border-bottom: 2px solid transparent;
  font-size: 16px;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--ink-soft);
}
/* This is the list that answers "which of these am I looking at?", and until now the answer was
   a 25% ink difference — 0.75 against 1.0 — which is exactly what :hover does to every other
   link in the list. So the current page is drawn, not darkened: the site's teal under it, a
   hairline under whatever you are pointing at. Two different marks for two different things. */
.folder-nav a:hover { color: var(--ink); border-bottom-color: var(--rule); }
.folder-nav .is-active a { color: var(--ink); border-bottom-color: var(--teal); }
/* The heading used to start a full 64 px of page-body below the list — more air than the heading
   itself keeps over the cards under it, so the list floated over an empty band and looked like it
   belonged to no one. 32 px ties the list to the page it is on: the nav names the collection, the
   heading opens it. */
.folder-nav + .page-body { padding-top: 32px; }

/* A property page no longer carries the sibling list — the listing it belongs to is one link
   away, and the link says so with an arrow pointing back up the page. It borrows the folder
   nav's measure, label size, and reserved underline, so it sits exactly where that list used
   to sit and reads as the same kind of thing: navigation, not prose. */
.property-back {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 24px 32px 0;
}
.property-back-link {
  display: inline-block;
  padding-bottom: 6px;
  border-bottom: 2px solid transparent;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.property-back-link:hover { color: var(--ink); border-bottom-color: var(--rule); }
.property-back-arrow { padding-right: 6px; }

/* When the page has a hero, the way back rides the photograph — centered across its top edge,
   the side of the picture opposite the headline, and drawn as a button rather than a line of
   nav text: over a picture there is no paper margin to hold a link, so the control carries
   its own surface. A translucent dark pill with a backdrop blur and a hairline light border
   stays legible over a bright sky or a dark interior — the same argument the headline's wash
   makes at the bottom of the picture, made per control instead of per page. */
.property-back-hero {
  position: absolute;
  top: 24px;
  /* An absolutely positioned box shrinks to its contents, so pulling the box back half its own
     width from the picture's midpoint centers the pill itself, not just its left edge. */
  left: 50%;
  transform: translateX(-50%);
  max-width: none;
  margin: 0;
  padding: 0;
  /* Above the gradient wash (the figure's ::after) *and* above the headline's figcaption:
     that caption layer is absolutely positioned over the whole picture, and being later in
     the tree it would otherwise sit on the button and eat its clicks. One and the other
     never overlap — the button rides the top edge, the caption stands at the foot — so
     both can keep their z-indexes. */
  z-index: 2;
}
.property-back-hero .property-back-link {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 10px 16px;
  border: 1px solid rgba(255, 255, 255, 0.45);
  border-radius: 999px;
  background: rgba(17, 20, 21, 0.45);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  box-shadow: 0 1px 8px rgba(0, 0, 0, 0.35);
  font-size: 13px;
  /* The plain link went bold with the folder nav it borrows; over a photograph the pill keeps its
     regular weight — the fill and the hairline already carry its presence. */
  font-weight: 400;
  letter-spacing: 0.06em;
  color: rgba(255, 255, 255, 0.95);
  transition: background-color 0.15s ease, border-color 0.15s ease;
}
.property-back-hero .property-back-link:hover {
  color: #fff;
  background: rgba(17, 20, 21, 0.7);
  border-color: rgba(255, 255, 255, 0.75);
}
.property-back-hero .property-back-arrow { font-size: 15px; }
/* The teal focus ring would vanish against a dark photograph, so over the hero it goes white,
   as it does in the header and footer. */
.property-back-hero :focus-visible { outline-color: #fff; }
/* The two halves of a phone's hero: a taller picture, and a smaller control on it.

   The wide band cannot survive at a phone's width. At 390 px the 21:9 ratio asks for 167 px of
   height, and the 240 px floor is what the page actually paints — a strip of a photograph, with
   the caption competing for what little of it is left. Below this breakpoint the hero takes a
   ratio a phone can hold, 4:3 with 280 px under it, and the object-fit: cover that has been on
   the image all along fills the taller box by cropping the sides instead of by letterboxing or
   stretching. The crop is the cost: a 16:9 photograph centred into a 4:3 box gives up about a
   third of its own width, which is what showing a phone a photograph rather than a strip of one
   buys. Only the property hero changes; the home and page banners keep the wide band.

   The way back rides that taller picture, and shrinks to match it. Sized for the desktop band, the
   pill took a third of the strip's height and half its width: more of the photograph spent saying
   where to go than showing what is there. At caption scale — 12px against the 25px headline at the
   picture's foot — and on a taller picture, it reads as a label on the photograph rather than a
   banner across it. The letter size was never what made the button wide, though: twenty-one
   uppercase letters are. Here the word that names what kind of list it is drops out, and the button
   says "Back to List" — no smaller a thing to tap, and a third fewer letters across the picture.
   Nothing is lost to anyone listening: the <nav> around it is already labelled "Property list", and
   that label is what an announcement reads first. The rule is not scoped to the hero, so the plain
   line of nav printed when a property has no hero picture loses the word at the same width, and the
   two spellings of the same link stay in step. */
@media (max-width: 559px) {
  .property-banner .banner-img { aspect-ratio: 4 / 3; min-height: 280px; }
  /* Centered, so only the inset from the top edge changes: the button sits closer to the edge of a
     phone's picture than of a desktop's, because the picture itself is that much shorter. */
  .property-back-hero { top: 8px; }
  .property-back-hero .property-back-link { padding: 8px 12px; font-size: 12px; letter-spacing: 0.05em; }
  .property-back-hero .property-back-arrow { font-size: 14px; }
  .property-back-scope { display: none; }
}

/* ------------------------------------------------------------------ grid */
.grid { display: block; }
.grid-row {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--gap);
  margin-bottom: var(--gap);
}
.grid-col { min-width: 0; }
.span-1 { grid-column: span 1; }
.span-2 { grid-column: span 2; }
.span-3 { grid-column: span 3; }
.span-4 { grid-column: span 4; }
.span-5 { grid-column: span 5; }
.span-6 { grid-column: span 6; }
.span-7 { grid-column: span 7; }
.span-8 { grid-column: span 8; }
.span-9 { grid-column: span 9; }
.span-10 { grid-column: span 10; }
.span-11 { grid-column: span 11; }
.span-12 { grid-column: span 12; }

@media (max-width: 899px) {
  .grid-col { grid-column: 1 / -1; }
}

/* ------------------------------------------------------------------ blocks */
.block { margin-bottom: var(--gap); }
.block > h2 { margin-top: 0; }
/* A block following prose had no gap at all before it: the block carries only a bottom margin,
   and the prose's last paragraph has its own margin-bottom zeroed, so the section's heading
   landed flush against the last line of description — Photos sitting hard under the enquiry
   paragraph on the property page. A block after prose takes the same gap the blocks give each
   other; between two blocks the margins collapse, so nothing there grows. */
.prose + .block { margin-top: var(--gap); }
/* A section already has its own padding under the last thing in it. The block margin and the
   row margin stacked on top of that padding, so the end of a section carried a second gap
   before the next one began. */
.grid-row:last-child, .block:last-child { margin-bottom: 0; }

.prose { max-width: var(--prose-measure); }
/* The measure is a reading distance, not a position. It sits flush left in its column, and at the
   site's own 1,020px measure a twelve-column block is 956px wide, so the 700px measure leaves 256px
   of the column over — all of it on the right. That stays invisible until a block asks to be
   centred, because then the centring happens on the measure's axis, 128px left of the column's.
   The one block on this site asks: the licence number /real-estate-sales prints under its
   call-to-action. Its 130px of ink landed at x 447–577 on a 1,280px screen — under the gutter
   between the second photograph and the third — while the banner, the header and the column itself
   all centre on x 640. The drift is (column − measure) / 2: nil up to 764px wide, 68px at 900, and
   the full 128px from 1,020 up, since a narrower column narrows the measure along with it. A block
   marked Wide — see Block.Wide — gets its column back, so the centring lands where it was written. */
.block-wide .prose { max-width: none; }
.prose > :last-child { margin-bottom: 0; }
.prose ul, .prose ol { padding-left: 1.3em; }
.prose li { margin-bottom: 0.4em; }
.prose blockquote {
  margin: 0 0 1em;
  padding: 0 0 0 18px;
  border-left: 3px solid var(--rule);
  color: var(--ink-soft);
}
.prose hr { border: 0; border-top: 1px solid var(--rule); margin: 2em 0; }
/* A property's prose is Markdown now, and Markdown has two shapes this page had no reason to draw
   before: a heading somebody wrote inside the text, and a piece of code. The heading sits under the
   page's own — internal/markdown will not print an h1 in prose at all — one step below the section
   title it lives inside. Code gets the monospace face and the same wash the rest of the site uses
   for something set apart. */
.prose h2, .prose h3, .prose h4 { margin: 1.6em 0 0.5em; }
.prose h2 { font-size: 20px; }
.prose h3 { font-size: 17px; }
.prose code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.92em;
  background: var(--wash);
  padding: 2px 5px;
}
.prose pre {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 16px;
  background: var(--wash);
  padding: 12px 14px;
  margin: 0 0 1em;
  overflow-x: auto;
}
.prose pre code { background: none; padding: 0; }

.block-image .card { margin: 0; }
.card-caption {
  margin-top: 10px;
  font-size: 16px;
  color: var(--ink-soft);
}

/* ------------------------------------------------------------------ button */
.button {
  display: inline-block;
  padding: 14px 34px;
  font-family: var(--ui);
  font-size: 14px;
  text-transform: uppercase;
  color: #fff;
  background: var(--button);
  border: 0;
  cursor: pointer;
}
.button:hover { color: #fff; background: #000; }
.block-button { margin: 0 0 var(--gap); }

/* ------------------------------------------------------------------ gallery */
/* A grid row is as tall as the tallest thing in it, and these pictures arrive at whatever
   ratio the photographer shot them in. On /property-141 that is 29 tiles in three ratios —
   1.50, 0.85, 0.67 — so a row holding one portrait stood 258px tall while the two landscape
   pictures beside it rendered 115px, and 1,207px of the 2,118px section — 57% of it — was
   blank space beside a short picture. The grid was not broken; it was doing exactly what it
   was told, which was to size each row to its tallest item.

   So the tile is fixed, not the row: every picture is drawn into the same 3 / 2 rectangle,
   which is the ratio 21 of those 29 already have and the ratio the listing cards already use,
   so the crop only ever touches the minority. The crop is the thumbnail's problem alone — the
   anchor's href is the full picture, and the viewer shows all of it. */
.gallery {
  list-style: none;
  margin: 0 0 var(--gap);
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}
.gallery-item { margin: 0; }
.gallery-link { display: block; }
.gallery-img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

/* Two tiles to a row below the stacking point, and square tiles once the row is phone
   width. A half-width 3 / 2 tile on a phone is 161 px across and 107 px tall: the crop
   takes off the top and bottom of a picture that was already cut to the same 3 / 2
   ratio, so the shorter tile is simply less of the photograph. Square keeps the full
   161 px of it, and at that width a square band is still a band.

   The row count is worked out rather than fixed, because the width at which two tiles
   become absurd varies: 50% - 7px is exactly half the row less its share of the 12 px
   gap, so two columns always fit while the row is wide enough, and a third is
   arithmetically impossible below 899 px, where the desktop's own three stand. Under
   that the 150 px floor is what ends two-a-row — a 340 px phone has 300 px of body
   left after the page padding, which cannot hold two 150 px tiles and the gap, so it
   draws one tile across the whole width instead. A 360 px phone has 320 px, and two fit.

   The square is held back to the 699 px the footer already uses as its own boundary.
   Two tiles across a tablet are 324 px apiece, and a square that wide stands 324 px
   tall: taller than the picture reads well at, and enough to push the enquiry form off
   the screen. There the 3 / 2 band carries on; at 375 px the same pair is 161 px each. */
@media (max-width: 899px) {
  .gallery {
    /* The plain two first: a browser that cannot parse max() inside a track size drops
       the second line and keeps this one, which is two tiles to a row at every width the
       150 px floor would have granted them anyway — it only fails to narrow to one tile
       on the smallest phones, where two small tiles still read as a grid of photographs. */
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-columns: repeat(auto-fill, minmax(max(150px, 50% - 7px), 1fr));
  }
}
@media (max-width: 699px) {
  .gallery-img { aspect-ratio: 1 / 1; }
}

/* ------------------------------------------------------------------- tour */
/* The 3D tour frame. Matterport hands out its embed at 853×480, which is a 16:9-ish
   rectangle; the frame takes the full column and keeps that ratio, so the box it will
   fill is on the page before the tour is — the same rule the map frame follows, and
   the reason a lazy frame does not shove the form down when it lands. */
.tour { border: 1px solid var(--rule); }
.tour-frame { display: block; width: 100%; aspect-ratio: 853 / 480; border: 0; }

/* ------------------------------------------------------------------ cards */
.cards {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: var(--gap);
}
.card { margin: 0; }
.card-link { display: block; color: inherit; }
.card-img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; }
.card-title {
  display: block;
  margin-top: 10px;
  font-size: 16px;
  text-transform: uppercase;
  color: var(--ink);
}
.card-link:hover .card-title { text-decoration: underline; }
.card-blurb { margin: 6px 0 0; font-size: 17px; color: var(--ink-soft); }

/* ------------------------------------------------------------------ map */
/* The frame's height is stated here rather than left to the frame: an iframe that is
   given none arrives at 150 px and grows when its document lands, and that growth is the
   layout shift the rest of the stylesheet works to avoid. */
.map { border: 1px solid var(--rule); }
.map-frame { display: block; width: 100%; height: 340px; border: 0; }
.map-address { font-style: normal; margin-top: 10px; font-size: 16px; color: var(--ink-soft); }
.map-address strong { display: block; color: var(--ink); }

/* ------------------------------------------------------------------ form */
.form-fields { list-style: none; margin: 0; padding: 0; }
.form-field { margin-bottom: 18px; }
.form-label, .form-field label {
  display: block;
  margin-bottom: 6px;
  font-size: 14px;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.required { color: #7a1f16; }
.form-field input, .form-field textarea {
  display: block;
  width: 100%;
  min-height: 44px;
  padding: 10px 12px;
  font-family: inherit;
  font-size: 18px;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 0;
}
.form-field textarea { min-height: 120px; }
.form-field input:focus, .form-field textarea:focus { border-color: var(--teal); }
.form-field input:invalid:not(:placeholder-shown) { border-color: #a33; }
.field-help { margin: 6px 0 0; font-size: 15px; color: var(--ink-faint); }
.form-submit { margin: 0; }

/* The honeypot: an input no visitor is ever shown, which a script that fills in every field it finds
   will fill in. It is moved off the screen rather than hidden with display:none, because a script that
   looks at the HTML it was handed should still find a field called website sitting in the form — that
   is the whole test — while display:none would teach one which inputs to skip. It is not the
   .visually-hidden helper above: that class hides a thing from the eye and announces it to a screen
   reader, and this one is hidden from both. */
.form-hp {
  position: absolute;
  top: -9999px;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ------------------------------------------------------------------ property */
.property-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 40px;
}
/* The main content comes first in the document so a keyboard reader reaches it before
 * the sidebar, but the live site shows the sidebar on the left. Both are pinned to the
 * same row: grid's sparse packing only moves its cursor forward, so without an explicit
 * row the sidebar would drop below the content it is meant to sit beside. */
.property-main { grid-column: 6 / 13; grid-row: 1; min-width: 0; }
.property-side { grid-column: 1 / 5; grid-row: 1; min-width: 0; }

@media (max-width: 899px) {
  .property-main, .property-side { grid-column: 1 / -1; grid-row: auto; }

  /* Below the stacking point the map leads the page, sitting directly under the hero
     photograph rather than waiting behind the description, the gallery and the tour.
     Someone on a phone has the picture of the property behind them and the rest of the
     listing ahead of them; "where is it?" is the question they are asking next.
     The sidebar is unpacked with display:contents so its own sections become items of
     .property-grid and can be ordered among them — each still needs the full width the
     sidebar itself took, since the rule above no longer reaches them. The document is
     left alone: main is still first in the markup, so a keyboard reader reaches the
     description before the map frame even though the map is now painted above it. */
  .property-side { display: contents; }
  .property-side > * { grid-column: 1 / -1; grid-row: auto; min-width: 0; }
  .property-side > .block-map { order: -1; }
}

.property-title { margin-bottom: 24px; }
.property-subheadline { margin: 0 0 6px; font-size: 20px; color: var(--ink-soft); }
/* On a page whose headline rides the hero, the subheadline is the first thing in the body and
   leads the prose on its own — it needs the room the withdrawn header used to carry. */
.property-main > .property-subheadline:first-child { margin: 0 0 20px; }
.property-neighbourhood, .property-features { margin-bottom: var(--gap); }
.property-features ul { list-style: none; margin: 0; padding: 0; }
.property-features li {
  padding: 8px 0;
  font-size: 17px;
  border-bottom: 1px solid var(--rule);
}

/* The way to edit the page, when a reader is signed in, leaves the bar here and rides the lower
   right corner of the window instead: a property page is long — hero, gallery, form, sidebar — and
   a button parked in the bar is off the screen long before the enquiry form is. `.layout-property`
   is the body class layoutClass names for this kind of page (internal/site/render.go), so only this
   page moves the button, and the anchor itself is untouched: the bar simply loses the row the button
   used to take.

   Out of the bar the button can no longer borrow the bar's skin: white on white paper is barely a
   box, so the fill and the letters trade places — white on teal-dark, the pair the header and the
   menu panel are drawn with, 8.9:1 — and the panel's own shadow is borrowed to lift it off whatever
   photograph or paragraph sits under it.

   The header wraps the button in a stacking context of its own at z-index 100, so the 110 below is a
   position inside the header's stack, not the page's: it outranks the bar's own parts, stays under
   the open menu panel's 120 — a panel that has taken the corner should keep it — and the whole
   header stack, 100, sits under the lightbox's 300 and over the measure's 2. The 20 px is the
   gutter the bar and the page body already keep, and env() holds it clear of a phone's home bar. */
.layout-property .header-edit {
  position: fixed;
  right: 20px;
  bottom: calc(20px + env(safe-area-inset-bottom));
  z-index: 110;
  /* The bar's auto margin would hold the button at its static position instead of the right edge
     once the box is out of flow, so it is zeroed rather than left to answer the flex row. */
  margin-left: 0;
  color: #fff;
  background: var(--teal-dark);
  border-color: var(--teal-dark);
  box-shadow: 0 16px 34px rgba(18, 22, 23, 0.34);
}
/* The same answer to the pointer as in the bar, inverted: the letters keep their colour and the
   fill lightens to the bar's own teal, 6.9:1 on white — the button never loses the shape and
   contrast that make it read over whatever it happens to float on. */
.layout-property .header-edit:hover {
  color: #fff;
  background: var(--teal);
  border-color: var(--teal);
}

/* ------------------------------------------------------------------ testimonials */
.testimonials { max-width: var(--prose-measure); margin: 0 auto; }
/* The other two home sections take their heading from crawled markup that centres it; this one
   is ours, and left-aligned in the middle of three centred headings it read as a mistake. */
.home-section .testimonials > h2 { text-align: center; }
.testimonial {
  margin: 0 0 28px;
  padding: 0 0 0 18px;
  border-left: 3px solid var(--teal);
}
.testimonial p { margin: 0 0 8px; }
/* Links in crawled copy sat in a paragraph with nothing but colour to tell them apart. */
.prose a { text-decoration: underline; text-underline-offset: 2px; }

.testimonial cite { font-size: 15px; text-transform: uppercase; color: var(--ink-faint); }

/* ------------------------------------------------------------------ lightbox */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  align-items: center;
  justify-content: center;
  /* The side padding is the arrows' lane: the picture is never drawn underneath them. */
  padding: 64px 96px 56px;
  /* A horizontal drag inside the viewer belongs to the viewer, so the browser does not try
     to pan the page behind it; vertical travel is left alone, and a phone can still scroll
     a caption or a short landscape screen. */
  touch-action: pan-y;
  background: rgba(18, 22, 23, 0.94);
}
.lightbox[hidden] { display: none; }
.lightbox :focus-visible { outline-color: #fff; }

.lightbox-stage {
  margin: 0;
  min-width: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}
/* The picture's own box, and the only thing that ever slides inside it. A swipe drags the
   picture on show and a copy of the one coming in, edge to edge, so the next photograph
   arrives from the side it belongs on instead of materialising behind the old one. */
.lightbox-lane {
  position: relative;
  min-width: 0;
  width: 100%;
  display: flex;
  justify-content: center;
}
/* 180px is the viewer's own padding, the caption line, and the gap between them. */
.lightbox-image, .lightbox-ghost { max-width: 100%; max-height: calc(100vh - 180px); }
/* The second picture of the pair: absolutely placed so the lane never grows and nothing else
   on the screen moves, kept out of the accessibility tree because a swipe is one photograph
   at a time to anyone reading it, and hidden until site.js has somewhere to put it. */
.lightbox-ghost {
  position: absolute;
  left: 50%;
  top: 50%;
  visibility: hidden;
}
.lightbox-lane.has-ghost .lightbox-ghost { visibility: visible; }
/* This is a swipe let go: the snap back to where the picture was, or the slide that carries
   the pair the rest of the way across. During the drag itself site.js switches it off with
   .is-dragging — a picture that lags its finger is not being dragged. */
.lightbox-image, .lightbox-ghost { transition: transform 180ms ease-out; }
.lightbox-lane.is-dragging .lightbox-image,
.lightbox-lane.is-dragging .lightbox-ghost { transition: none; }
.lightbox-meta {
  max-width: 900px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px 16px;
  text-align: center;
}
.lightbox-caption { font-size: 16px; color: rgba(255, 255, 255, 0.8); }
.lightbox-count {
  font-size: 14px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.8);
}

/* The three controls share one skin, so the viewer reads as one instrument. The fill is
   translucent because the arrows sit on top of the picture, not beside it: without it the
   label is just white letters over whatever the photograph happens to show there. */
.lightbox-close, .lightbox-prev, .lightbox-next {
  position: absolute;
  /* A swipe brings the next photograph in under the thumb, and it slides through the arrows'
     lane on its way to the centre: the controls are what a reader aims at, so they stay on
     top of a picture passing underneath them. */
  z-index: 1;
  padding: 10px 18px;
  font-family: var(--ui);
  font-size: 14px;
  text-transform: uppercase;
  color: #fff;
  background: rgba(18, 22, 23, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.6);
  cursor: pointer;
}
.lightbox-close:hover, .lightbox-prev:hover, .lightbox-next:hover {
  background: rgba(18, 22, 23, 0.85);
  color: #fff;
}
.lightbox-close { top: 16px; right: 16px; }
.lightbox-prev, .lightbox-next {
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 8px;
}
.lightbox-prev { left: 16px; }
.lightbox-next { right: 16px; }
.lightbox-arrow { font-size: 18px; line-height: 1; }
/* Out of pictures: the arrow stays put and goes quiet, which is what says the gallery ends
   here. aria-disabled rather than disabled keeps it in the accessibility tree — announced as
   dimmed, not vanished — and keeps the browser from stealing focus mid-walk. */
.lightbox-prev[aria-disabled="true"], .lightbox-next[aria-disabled="true"] {
  opacity: 0.35;
  border-color: rgba(255, 255, 255, 0.3);
  background: rgba(18, 22, 23, 0.55);
  cursor: default;
}
/* One picture is not a walk, so the arrows have nothing to say. */
.lightbox.is-single .lightbox-prev,
.lightbox.is-single .lightbox-next { display: none; }

@media (max-width: 899px) {
  .lightbox { padding: 60px 64px 52px; }
  .lightbox-image, .lightbox-ghost { max-height: calc(100vh - 172px); }
  .lightbox-prev, .lightbox-next { padding: 10px 12px; }
  .lightbox-prev { left: 10px; }
  .lightbox-next { right: 10px; }
}
/* Below this the word is the arrow's job, so the arrow keeps the lane to itself. */
@media (max-width: 559px) {
  .lightbox { padding: 56px 14px 48px; }
  .lightbox-image, .lightbox-ghost { max-height: calc(100vh - 168px); }
  .lightbox-prev, .lightbox-next { padding: 8px 10px; gap: 0; }
  .lightbox-nav-label { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
}

/* ------------------------------------------------------------------ footer */
/* Redesigned for reading. What the crawl left behind was one row of five links at 12px with 3px
   of letter-spacing — capitals stretched wide enough to be the slowest text on the page — with
   the address beside it in a column so narrow that one address took four lines, and the email
   printed twice. Three columns now, each with its own measure: the contact block, the policy
   pages, and the footer's own control. Body text is 16px, the same size the page is written in;
   only the labels are capitals. */
.site-footer {
  background: var(--teal);
  color: rgba(255, 255, 255, 0.8);
  /* The header is the same teal and the page above it ends in white, so without an edge of its
     own the footer reads as more of the same block the address was buried in. */
  border-top: 1px solid rgba(255, 255, 255, 0.18);
}
.footer-inner {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 40px 32px 32px;
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) auto;
  gap: 32px 48px;
  align-items: start;
}
.footer-name {
  margin: 0 0 14px;
  font-size: 21px;
  text-transform: uppercase;
  color: #fff;
  /* The name is long enough to break, and one word stranded on the second line is what the
     footer used to end with. Balance gives the two lines back. */
  text-wrap: balance;
}
.footer-info { font-style: normal; font-size: 18px; line-height: 1.7; }
.footer-info > * { display: block; }
.footer-address { color: #fff; }
.footer-info a { color: rgba(255, 255, 255, 0.85); }
.footer-info a:hover { color: #fff; text-decoration: underline; }

.footer-heading {
  margin: 0 0 12px;
  font-size: 15px;
  text-transform: uppercase;
  /* 0.75 is 4.68:1 against the footer's #2b6173. 0.65 — the token the body uses for faint text
     on white — is 3.95:1 here, which fails AA at this size. */
  color: rgba(255, 255, 255, 0.75);
}
/* One link per line, at the size the page is written in, instead of five capitals in a row that
   wrapped as soon as the row ran out of room. */
.footer-links ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.footer-links a { font-size: 18px; color: rgba(255, 255, 255, 0.85); }
.footer-links a:hover { color: #fff; text-decoration: underline; }

/* The footer's own control, kept out of the policy list it used to share a row with. It sits at
   the foot of the columns rather than the head, where a reader reaches for it. */
.footer-top { align-self: end; }
.footer-top a {
  display: inline-block;
  padding: 10px 18px;
  border: 1px solid rgba(255, 255, 255, 0.5);
  font-size: 15px;
  text-transform: uppercase;
  color: #fff;
}
.footer-top a:hover { color: #fff; background: rgba(255, 255, 255, 0.12); border-color: #fff; }

/* The copyright is the last thing on the page and the least important, so it gets its own rule
   and its own line rather than sitting under the columns as a fourth paragraph. */
.footer-base {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 32px 26px;
}
.footer-copyright {
  margin: 0;
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.15);
  font-size: 16px;
  color: rgba(255, 255, 255, 0.75);
}

@media (max-width: 899px) {
  .footer-inner { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  /* Two columns now, and the control stays under the list it belongs with rather than dropping
     into the empty lane beside the contact block. */
  .footer-top { grid-column: 2; }
}
@media (max-width: 699px) {
  .footer-inner { grid-template-columns: 1fr; gap: 28px; padding: 36px 20px 32px; }
  /* One column now, so the control goes back to it: a second column asked for in a one-column
     grid is a column the grid has to invent, and the footer stacks in two again. */
  .footer-top { grid-column: 1; }
  .footer-base { padding: 0 20px 24px; }
}

/* ------------------------------------------------------------------ narrow */
@media (max-width: 559px) {
  .page-body { padding: 20px 20px; }
  .home-section { padding: 0 20px; }
  .home-section:first-child { padding-top: 32px; }
  .home-section:last-child { padding-bottom: 40px; }
  .home-section + .home-section { margin-top: 40px; }
  .home-section .banner { margin-bottom: 20px; }
  .folder-nav { padding: 20px 20px 0; }
  .folder-nav + .page-body { padding-top: 24px; }
  .property-back { padding: 20px 20px 0; }
  .banner-overlay-inner { padding: 0 20px 24px; }
  .property-banner .banner-headline { font-size: 25px; }
  .banner-eyebrow { font-size: 13px; }
  h1 { font-size: 25px; }
  h2 { font-size: 22px; }
  .site-logo img { max-width: 200px; }
  /* 14.67 em again: 147 px at 10 px, under the 200 px the wordmark narrows to, so the caption never
     makes the brand block wider than the picture over it here either, and the *Menu* button keeps
     its place on the same line down to a small phone. */
  .site-brand-label { font-size: 12px; }
}

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