:root {
  --ink: #1c1a17;
  --muted: #6b645c;
  --rule: #e2ddd6;
  --paper: #fdfcfa;
  --panel: #f6f1e9;
  --accent: #7a5c3e;
  --available: #2f6b45;
  --reserved: #9a5b2c;
  --unavailable: #8a2f2f;
  --measure: 46rem;
}

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

/* The hidden attribute is only display:none in the UA sheet, so any author
   rule setting display beats it. This keeps it authoritative. */
[hidden] {
  display: none !important;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 clamp(1rem, 0.95rem + 0.25vw, 1.0625rem) / 1.65 ui-serif, Georgia, "Times New Roman", serif;
}

img {
  max-width: 100%;
}

a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
}

.skip {
  position: absolute;
  left: -100vw;
}

.skip:focus {
  left: 0.5rem;
  top: 0.5rem;
  z-index: 10;
  background: var(--ink);
  color: #fff;
  padding: 0.6rem 1rem;
}

/* ---------- masthead ---------- */

.masthead {
  border-bottom: 1px solid var(--rule);
}

/* The brand is the only thing left in this row, so it is a plain block. It was a
   flex container while the language switch sat beside the name, which is what
   made the name wrap: the switch and the gap took 86px of a 390px screen and the
   name needs 236px to stay on one line. */
.masthead__inner {
  max-width: 72rem;
  margin: 0 auto;
  padding: 0.9rem 1.25rem 0.7rem;
}

/* Only as wide as the drawing and the name, so the tagline centres under those
   rather than under the whole width of the row. */
.brand__lockup {
  width: fit-content;
  max-width: 100%;
}

.brand__link {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  text-decoration: none;
}

.brand__mark {
  display: block;
  width: clamp(3.6rem, 10vw, 7rem);
  height: auto;
  flex: none;
}

/*
 * The name was cropped out of the logo drawing and set beside it, so it does the
 * job the lettering used to do inside the mark, and it was too quiet for it:
 * smaller than the heading of every page it sat above. It now clears h1 at every
 * width, and the drawing grew with it so the two still read as one lockup.
 *
 * Both clamps rise faster than they start. A masthead has the whole width of a
 * desktop to be generous in and much less on a phone. With the row to itself the
 * name sets on one line from 360px up; at the 320px floor it needs 236px and has
 * 210px, so there it still takes two. Lowering the floor far enough to fix that
 * would shrink the name on every phone to suit the smallest one.
 */
.brand__word {
  font-size: clamp(1.9rem, 1.35rem + 2.2vw, 3rem);
  line-height: 1.1;
  letter-spacing: 0.01em;
}

/*
 * The five resorts read as one line or they read as a broken list, so nowrap and
 * then a size chosen to make that safe. Two things had to give for it to fit.
 *
 * The width is the logo's, not the row's: at width 0 the tagline contributes
 * nothing to the lockup's fit-content width, so the drawing and the name decide
 * it alone, and min-width brings the tagline straight back up to whatever they
 * came to. Without that it was the widest thing in the lockup and the logo sat
 * in the middle of a line of small caps wider than itself.
 *
 * The size is fluid because that width is. The string is 27.5 times its own font
 * size before any letter-spacing, so at the 320px floor — 280px of room, the one
 * width where the logo is squeezed too — it cannot be the old 12px however the
 * tracking is set. Hence a floor near 9px and 0.05em rather than 0.1em: the
 * spacing was a sixth of the length, and the airier setting would have cost
 * another px of size to pay for. Both are back to full by tablet width.
 */
.brand__tagline {
  width: 0;
  min-width: 100%;
  margin: 0.35rem 0 0;
  text-align: center;
  white-space: nowrap;
  font-size: clamp(0.57rem, 0.4rem + 0.8vw, 0.75rem);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
}

/* The tracking is only cramped where the width is. 52rem because that is where
   the logo has finally grown wider than the tagline at full size — restoring it
   any earlier puts the line back outside the lockup it just came inside. */
@media (min-width: 52rem) {
  .brand__tagline {
    letter-spacing: 0.1em;
  }
}

/* Wide screen: the links on the left, the language on the right of the same row.
   The toggle is only in the flow below 52rem, which is where the script shows it
   and where the rule further down puts the list on a line of its own. */
.nav {
  max-width: 72rem;
  margin: 0 auto;
  padding: 0 1.25rem 0.9rem;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 1.4rem;
}

.nav__lang {
  font-size: 0.8125rem;
  color: var(--muted);
  font-variant: small-caps;
  letter-spacing: 0.06em;
  text-decoration: none;
  flex: none;
  margin-left: auto;
}

.nav__lang:hover,
.nav__lang:focus-visible {
  color: var(--ink);
}

.nav__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  /* The row gap is the larger of the two: when the list does wrap, the rows have
     to read as rows rather than as one field of words. */
  gap: 0.55rem 1.4rem;
}

.nav__toggle {
  display: block;
  margin-bottom: 0.6rem;
  padding: 0.45rem 0.9rem 0.45rem 0;
  background: none;
  border: 0;
  font: inherit;
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--muted);
  cursor: pointer;
}

.nav__toggle::before {
  content: "≡";
  margin-right: 0.5rem;
  font-size: 1.1em;
}

.nav__toggle[aria-expanded="true"]::before {
  content: "×";
}

.nav--collapsed .nav__list {
  display: none;
}

/* Below 52rem the script shows the Menu button and folds the list away, so the
   first row is the button and the language switch — the side of that row the
   button leaves empty is exactly what the switch needs. The list, when it is
   open, takes a line of its own underneath. `order` rather than DOM order, so
   the switch still follows the links for a screen reader. With no JavaScript the
   button stays hidden and the switch simply sits above the open list. */
@media (max-width: 52rem) {
  .nav__list {
    order: 1;
    flex-basis: 100%;
  }
}

.nav a {
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  text-decoration: none;
  color: var(--muted);
  padding: 0.2rem 0;
  border-bottom: 1px solid transparent;
}

.nav a:hover,
.nav a:focus-visible {
  color: var(--ink);
}

.nav a[aria-current="page"] {
  color: var(--ink);
  border-bottom-color: var(--accent);
}

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

.page {
  max-width: var(--measure);
  margin: 0 auto;
  padding: clamp(1.5rem, 4vw, 3rem) 1.25rem;
}

.wide {
  padding-bottom: 2rem;
}

.wide .page {
  padding-top: clamp(1.5rem, 4vw, 3rem);
  padding-bottom: 1.5rem;
}

h1 {
  font-size: clamp(1.75rem, 1.3rem + 1.8vw, 2.5rem);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin: 0 0 0.75rem;
}

h2 {
  font-weight: 400;
  font-size: 1.35rem;
  margin: 2.5rem 0 0.75rem;
}

h3 {
  font-weight: 400;
  font-size: 1.0625rem;
  font-variant: small-caps;
  letter-spacing: 0.06em;
  color: var(--accent);
  margin: 2rem 0 0.5rem;
}

.prose blockquote {
  margin: 1.5rem 0;
  padding: 0.75rem 1rem;
  border-left: 3px solid var(--reserved);
  background: var(--panel);
  font-size: 0.9375rem;
  color: var(--muted);
}

.prose blockquote p {
  margin: 0;
}

.lede {
  font-size: 1.15em;
  color: #3d3830;
  margin-top: 0;
}

.season {
  margin: 0 0 2rem;
  color: var(--muted);
  font-variant: small-caps;
  letter-spacing: 0.08em;
}

.hero,
.band {
  margin: 0;
}

.hero img,
.band img {
  display: block;
  width: 100%;
  object-fit: cover;
}

/*
 * Wide screens size these against the viewport's height, which is what makes a
 * hero a hero. svh rather than vh: where a browser resizes `vh` as its chrome
 * retracts, the photo changed height under the reader's thumb mid-scroll. svh is
 * the viewport with the chrome showing, a fixed number for the life of the page.
 * The `vh` line above each is the fallback for anything too old to know `svh`,
 * and behaves as before rather than collapsing to the floor.
 *
 * The hero photo is 4:3 and this band is roughly 2.2:1, so a good half of the
 * frame is always cropped away. Taller than a typical banner, and positioned a
 * little above centre, keeps the whole chalet in view rather than slicing the
 * entrance off the bottom.
 */
.hero img {
  height: clamp(18rem, 68vh, 40rem);
  height: clamp(18rem, 68svh, 40rem);
  object-position: center 45%;
}

.band img {
  height: clamp(14rem, 40vh, 24rem);
  height: clamp(14rem, 40svh, 24rem);
}

/*
 * The homepage's mid-page band only, and the modifier is the whole point: .band
 * is also the banner across the top of every content page, so raising its height
 * here made the Accommodation, Location and Skiing banners enormous at the same
 * time. They keep the size above.
 *
 * This one asks for the photograph's own 4:3 rather than a height. It carries
 * the chalet at night, which is a building shot, and every attempt to fix its
 * crop by adding height only moved which end was losing: a 4:3 picture in a
 * letterbox has to give up the roof or the doorstep.
 *
 * 88svh is a ceiling rather than the usual case, and it does bite on a normal
 * desktop window — 4:3 of 1280 is 960px and the cap holds it to 792. That still
 * has the whole chalet in frame, apex to lit entrance, and it guarantees the
 * band can never be taller than the screen it is on. Narrower than about 1050px
 * the ratio wins and nothing is cropped.
 */
.band--home img {
  height: auto;
  aspect-ratio: 4 / 3;
  max-height: 88vh;
  max-height: 88svh;
}

/*
 * On a phone the height comes off the width instead, and nothing else. Every
 * viewport-height unit — vh, svh, dvh alike — is at the mercy of what a given
 * browser does with its own toolbars, and iPhones and Android phones disagree
 * about that; the hero was still changing size mid-scroll on an iPhone 14 Pro
 * while its plain 14 sat still. A ratio against the width cannot: the width does
 * not change while you scroll, on any phone.
 *
 * 5:6 is about what 68svh came to on a 390px screen, so the crop is the one that
 * was there before. The cap stops it running away on the widest phones, where
 * the same ratio would be 100px taller than the tallest thing it ever was.
 * height: auto is what lets aspect-ratio apply at all — without it the heights
 * above simply win and none of this does anything.
 */
@media (max-width: 34rem) {
  .hero img {
    height: auto;
    aspect-ratio: 5 / 6;
    max-height: 30rem;
  }

  .band img {
    height: auto;
    aspect-ratio: 4 / 3;
    max-height: 22rem;
  }
}

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

.prose > :first-child {
  margin-top: 0;
}

.prose p {
  margin: 0 0 1.1em;
}

.prose ul {
  padding-left: 1.2rem;
}

.prose li {
  margin-bottom: 0.4em;
}

/* The 404 page's two lists of ways back into the site, one per language. */
.miss {
  list-style: none;
  margin: 0 0 2rem;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.5rem;
  font-size: 0.9375rem;
}

/* ---------- availability ---------- */

.notice {
  margin: 0 0 2.5rem;
  padding: 0.85rem 1rem;
  border-left: 3px solid var(--accent);
  background: var(--panel);
  font-size: 0.9375rem;
  letter-spacing: 0.02em;
}

.month {
  margin-bottom: 2.5rem;
}

.month h2 {
  font-size: 1.0625rem;
  font-variant: small-caps;
  letter-spacing: 0.1em;
  color: var(--accent);
  margin: 0 0 0.5rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--rule);
}

.weeks {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9375rem;
  /* Each month is its own table, so without fixed widths the price and status
     columns land in a different place in every one. */
  table-layout: fixed;
}

.weeks th:first-child,
.weeks td:first-child {
  width: 52%;
}

.weeks th:nth-child(2),
.weeks td:nth-child(2) {
  width: 21%;
}

.weeks thead th {
  text-align: left;
  font-weight: 400;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--muted);
  padding: 0.5rem 0.5rem 0.5rem 0;
}

.weeks tbody th,
.weeks td {
  text-align: left;
  font-weight: 400;
  padding: 0.6rem 0.5rem 0.6rem 0;
  border-bottom: 1px solid var(--rule);
  vertical-align: baseline;
}

.weeks .price {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Booked weeks stay legible but visibly recede, so the eye lands on what's free. */
.weeks tr[data-status="reserved"] th,
.weeks tr[data-status="reserved"] .price,
.weeks tr[data-status="unavailable"] th,
.weeks tr[data-status="unavailable"] .price {
  color: var(--muted);
}

.nights {
  display: block;
  font-size: 0.75rem;
  color: var(--muted);
  font-style: italic;
}

.status {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  white-space: nowrap;
}

/* Three columns of letter-spaced uppercase do not fit a 320px phone. "NOT
   AVAILABLE" wanted 106px of a 76px cell and the French "DISPONIBILITÉ" and
   "NON DISPONIBLE" are longer again, so the status column was clipped mid-word,
   the price ran into it, and the whole page scrolled sideways. This is the page
   people book from, so it gets a tighter type scale, a wider status column and
   permission to wrap. */
@media (max-width: 30rem) {
  .weeks {
    font-size: 0.875rem;
  }

  .weeks th:first-child,
  .weeks td:first-child {
    width: 44%;
  }

  .weeks th:nth-child(2),
  .weeks td:nth-child(2) {
    width: 21%;
  }

  .weeks thead th {
    font-size: 0.6875rem;
    letter-spacing: 0.03em;
  }

  /* Two lines of "NON DISPONIBLE" beat one clipped line. */
  .status {
    font-size: 0.6875rem;
    letter-spacing: 0.03em;
    white-space: normal;
  }
}

.status--available { color: var(--available); }
.status--reserved { color: var(--reserved); }
.status--unavailable { color: var(--unavailable); }

.updated {
  color: var(--muted);
  font-size: 0.875rem;
  font-style: italic;
}

.terms {
  margin-top: 2rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
  color: var(--muted);
  font-size: 0.9375rem;
}

/* ---------- homepage season teaser ---------- */

.teaser {
  margin-top: 2rem;
  padding: 1.5rem 0 0;
  border-top: 1px solid var(--rule);
}

.teaser__season {
  margin: 0;
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
}

.teaser__links {
  margin: 0.75rem 0 0;
}

.teaser__more {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.5rem;
  margin: 1.25rem 0 0;
  font-size: 0.9375rem;
}

/* ---------- gallery ---------- */

.grid {
  list-style: none;
  margin: 0 auto;
  padding: 0 1.25rem;
  max-width: 72rem;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
  gap: 0.6rem;
}

.grid a {
  display: block;
}

.grid img {
  display: block;
  width: 100%;
  height: 14rem;
  object-fit: cover;
}

.grid a:focus-visible img {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

/* ---------- testimonials ---------- */

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

.quotes li {
  margin-bottom: 2rem;
  padding-left: 1rem;
  border-left: 2px solid var(--rule);
}

.quotes blockquote {
  margin: 0;
}

.quotes p {
  margin: 0 0 0.4rem;
  font-style: italic;
}

.quotes cite {
  font-style: normal;
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ---------- forms ---------- */

.contact-grid {
  display: grid;
  gap: 2.5rem;
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 52rem) {
  .contact-grid {
    grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  }
}

.field {
  margin: 0 0 1.1rem;
}

.field label {
  display: block;
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
  margin-bottom: 0.3rem;
}

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 0.6rem 0.7rem;
  font: inherit;
  font-size: 0.9375rem;
  color: inherit;
  background: #fff;
  border: 1px solid var(--rule);
  border-radius: 0;
}

.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.field--check label {
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.875rem;
  line-height: 1.45;
}

.field--check input {
  width: auto;
  margin-top: 0.2rem;
  flex: none;
}

.field__required {
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  color: var(--reserved);
}

.field--check .field__required {
  text-transform: uppercase;
}

.enquiry__fallback {
  margin-top: 1.5rem;
  font-size: 0.875rem;
  color: var(--muted);
}

/* Honeypot: present for bots, unreachable for people and screen readers. */
.hp {
  position: absolute;
  left: -100vw;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.cta {
  display: inline-block;
  margin-top: 0.5rem;
  padding: 0.75rem 1.7rem;
  background: var(--accent);
  color: #fff;
  border: 0;
  font: inherit;
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.11em;
  text-decoration: none;
  cursor: pointer;
}

.cta:hover,
.cta:focus-visible {
  background: var(--ink);
}

.contact-details address,
.footer address {
  font-style: normal;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  font-size: 0.9375rem;
  color: var(--muted);
}

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

.footer {
  margin-top: 3rem;
  border-top: 1px solid var(--rule);
  background: var(--panel);
}

.footer__inner {
  max-width: 72rem;
  margin: 0 auto;
  padding: 2.5rem 1.25rem 1.75rem;
  display: grid;
  gap: 2rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
}

.footer__heading {
  margin: 0 0 0.5rem;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--ink);
}

/* A strip under the three columns, spanning the full width: the credit covers
   every photograph on the site, and the legal pages belong to all of it too. */
.footer__bottom {
  max-width: 72rem;
  margin: 0 auto;
  padding: 0 1.25rem 2.5rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.5rem 2rem;
  font-size: 0.8125rem;
  color: var(--muted);
}

.footer__legal {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 1.25rem;
}

.footer__credit {
  margin: 0;
}

/* Two columns, because nine links in one are a taller footer than the two
   columns of address beside them, and the block stops reading as a set. */
.footer__links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.15rem 1rem;
  font-size: 0.9375rem;
  color: var(--muted);
}

/* ---------- print ---------- */

/* Guests print the prices and the terms. On paper the navigation, the video
   placeholders and the enquiry form are all noise, and a link is only useful if
   you can see where it goes. */
@media print {
  body {
    background: #fff;
    color: #000;
    font-size: 11pt;
  }

  .nav,
  .skip,
  .footer__links,
  .videos,
  .videos__hint,
  .enquiry,
  .cta,
  .teaser__links,
  .teaser__more,
  .grid {
    display: none;
  }

  .page,
  .wide .page {
    max-width: none;
    padding: 0;
  }

  a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 0.85em;
    word-break: break-all;
  }

  .month,
  .quotes li,
  figure {
    break-inside: avoid;
  }

  .hero img,
  .band img {
    max-height: 8cm;
  }
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.videos {
  list-style: none;
  margin: 0 0 2rem;
  padding: 0;
  display: grid;
  gap: 1rem;
  /* auto-fit rather than auto-fill: a page with one clip should give it the
     full width instead of leaving an empty column beside it. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
}

.videos iframe {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 0;
  background: var(--ink);
}

/* Stands in for the player until someone asks for it, so the page makes no
   request to YouTube on load. Same box as the iframe that replaces it, so
   nothing moves when it does. */
.video {
  display: grid;
  /* One cell: the poster and the play button stack in it rather than needing a
     position: absolute each, so the box is sized by the frame itself. */
  place-items: center;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--ink);
  color: #fff;
  text-decoration: none;
  cursor: pointer;
  overflow: hidden;
}

.video > * {
  grid-area: 1 / 1;
}

.video__poster {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Held back a little so the white play button reads against a bright frame,
     and lifted on hover so the tile answers the pointer. */
  filter: brightness(0.82);
  transition: filter 0.2s ease, transform 0.4s ease;
}

.video:hover .video__poster,
.video:focus-visible .video__poster {
  filter: brightness(1);
  transform: scale(1.02);
}

/* The brightness still changes, because that is what says "this is the one you
   are pointing at". Only the movement goes. */
@media (prefers-reduced-motion: reduce) {
  .video__poster {
    transition: filter 0.2s ease;
  }

  .video:hover .video__poster,
  .video:focus-visible .video__poster {
    transform: none;
  }
}

.video__play {
  width: 3.5rem;
  height: 3.5rem;
  border: 1px solid rgba(255, 255, 255, 0.7);
  border-radius: 50%;
  position: relative;
}

.video__play::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 54%;
  transform: translate(-50%, -50%);
  border-style: solid;
  border-width: 0.55rem 0 0.55rem 0.9rem;
  border-color: transparent transparent transparent #fff;
}

.videos__hint {
  margin: 0 0 1rem;
  font-size: 0.8125rem;
  color: var(--muted);
  font-style: italic;
}

.video:hover .video__play,
.video:focus-visible .video__play {
  border-color: #fff;
  background: rgba(255, 255, 255, 0.12);
}

.video:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

/* A photograph shown whole rather than cropped to a band. Everything else on the
   site fills a fixed-height box with object-fit: cover, which is right for a
   view and wrong for two faces. Here the width is capped and the height simply
   follows the picture. */
.portrait {
  margin: 0 0 1.75rem;
  max-width: 24rem;
}

.portrait img {
  display: block;
  width: 100%;
  height: auto;
}

/* Two of them sit side by side across the text column. They need a shared shape
   or the row ends ragged, so here — and only here — the pair is cropped to 4:3.
   Below 34rem there is not enough width for two, so they stack and go back to
   their own proportions. */
.portrait[data-count="2"] {
  max-width: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.6rem;
}

.portrait[data-count="2"] img {
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

@media (max-width: 34rem) {
  .portrait[data-count="2"] {
    grid-template-columns: 1fr;
  }

  .portrait[data-count="2"] img {
    aspect-ratio: auto;
  }
}

/* ---------- map ---------- */

/*
 * The illustrated map, immediately above the Google Maps facade. The gap under
 * it is deliberately smaller than the gap above, so the two maps read as one
 * pair — a picture and the map that backs it up — set apart from the prose that
 * ends above them.
 */
.resort-map {
  margin: 3rem 0 1.75rem;
}

.resort-map a {
  display: block;
}

.resort-map a:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

.resort-map img {
  display: block;
  width: 100%;
  height: auto;
}

.map {
  margin: 0 0 2rem;
}

.map__facade {
  display: grid;
  place-items: center;
  position: relative;
  cursor: pointer;
}

/*
 * 5:2 rather than the 2:1 the still is drawn at, which takes about 70px off its
 * height. It keeps the full column width, so it still lines up with the
 * illustration above it and with every paragraph on the page — narrowing it
 * instead would have left it floating out of the column, which is the thing
 * that looks wrong. The crop is off the top and bottom and the pin is centred,
 * so nothing that matters is lost.
 *
 * min-height is for phones, where 5:2 of a 350px column would be 140px: too
 * short to pan a map in once it is the real thing.
 *
 * height: auto is what makes any of it work, and its absence was a live bug.
 * Astro writes width and height attributes onto the img, and a height attribute
 * beats aspect-ratio unless the height is auto — so the still ignored the ratio
 * and stood at its full 600px while the iframe, which has no such attribute,
 * obeyed it. The two were 250px apart, and the page jumped on the click that
 * this rule's own comment promises it would not.
 */
.map__facade img,
.map__frame {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 5 / 2;
  min-height: 14rem;
  border: 0;
  /* Same box as the iframe that replaces it, so nothing moves on the click. */
  object-fit: cover;
  background: var(--panel);
}

.map__open {
  position: absolute;
  padding: 0.55rem 1.1rem;
  background: rgba(255, 255, 255, 0.94);
  border: 1px solid var(--rule);
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink);
}

.map__facade:hover .map__open,
.map__facade:focus-visible .map__open {
  background: #fff;
  border-color: var(--ink);
}

.map__facade:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

.map__caption {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  margin-top: 0.6rem;
  font-size: 0.8125rem;
  color: var(--muted);
}

.inline-figure {
  margin: 0 0 2rem;
}

.inline-figure img {
  display: block;
  width: 100%;
  height: auto;
}
