/* Wickham Reach Inn.

   Coastal working landscape, not coastal luxury. Fog grey and weathered cedar
   with a spruce ground; the warm signal colour is reserved for availability and
   rates, which is where a guest's eye needs to go.

   Light rather than dark: a Maine inn in fog is pale, and a black site would be
   fashionable in the wrong direction. Editorial serif for display, quiet
   grotesque for body, mono for anything a guest has to compare. */

@font-face {
  font-family: 'Fraunces';
  src: url('/showcase/wickham-reach/fonts/fraunces-latin-variable.woff2') format('woff2');
  font-weight: 100 900;
  font-display: swap;
}
@font-face {
  font-family: 'Instrument Sans';
  src: url('/showcase/wickham-reach/fonts/instrument-sans-latin-variable.woff2') format('woff2');
  font-weight: 100 900;
  font-display: swap;
}

:root {
  --paper: #f8f7f4;
  --fog: #edebe6;
  --fog-2: #e2e0d9;
  --spruce: #1f3830;
  --spruce-2: #2c4a40;
  --ink: #141917;
  --ink-2: #4a534f;
  --ink-3: #616a65;
  --cedar: #8a6a4a;
  --signal: #9d5227;
  --rule: #dcd9d1;
  --rule-2: #c6c2b8;

  --display: 'Fraunces', Georgia, 'Times New Roman', serif;
  --body: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --gut: 36px;
  /* Header height at rest, used to slide the hero up underneath it. */
  --top-h: 90px;
}

* {
  box-sizing: border-box;
}
html {
  -webkit-text-size-adjust: 100%;
}
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
}
img {
  display: block;
  max-width: 100%;
}
a {
  color: inherit;
}
:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 3px;
}
.skip {
  position: absolute;
  left: -9999px;
}
.skip:focus {
  left: 14px;
  top: 14px;
  z-index: 60;
  background: var(--ink);
  color: var(--paper);
  padding: 12px 18px;
}

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

h1,
h2 {
  font-family: var(--display);
  font-optical-sizing: auto;
  font-weight: 600;
  letter-spacing: -0.022em;
  line-height: 1.02;
  margin: 0;
  text-wrap: balance;
}
h1 {
  font-size: clamp(38px, 5.6vw, 82px);
}
h2 {
  font-size: clamp(26px, 3.1vw, 42px);
}
h3 {
  font-family: var(--display);
  font-weight: 600;
  font-size: 22px;
  letter-spacing: -0.015em;
  margin: 0;
}
.h-sub {
  margin-top: 40px;
}
p {
  margin: 0 0 16px;
}
.eyebrow {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--signal);
  margin: 0 0 20px;
}
.eyebrow a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: inherit;
}
.answer,
.page-lede,
.hero-note {
  color: var(--ink-2);
  max-width: 64ch;
}
.page-lede,
.hero-note {
  font-size: 19px;
  line-height: 1.5;
}
.answer {
  font-size: 17.5px;
  margin-top: 18px;
}
.hint {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-3);
  margin: 10px 0 0;
}

/* --- actions -------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 50px;
  padding: 0 24px;
  border: 0;
  border-radius: 2px;
  background: var(--spruce);
  color: var(--paper);
  font-family: var(--body);
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.18s ease;
}
.btn:hover {
  background: var(--spruce-2);
}
.btn-block {
  display: flex;
  width: 100%;
}
.arrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 44px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--spruce);
  border-bottom: 1px solid var(--signal);
  padding-bottom: 4px;
}
.arrow:hover {
  color: var(--signal);
}

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

/*
 * The header follows the page. It sits translucent over whatever is beneath
 * it, including the hero photograph, and condenses once you leave the top.
 *
 * `backdrop-filter` is the whole effect, so the background alpha stays high
 * enough to carry the nav on its own where the filter is unsupported. The
 * border only appears in the scrolled state; at the top there is nothing to
 * divide it from.
 */
.top {
  position: sticky;
  top: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 30px;
  padding: 22px var(--gut);
  border-bottom: 1px solid transparent;
  background: rgba(248, 247, 244, 0.72);
  transition:
    padding 0.35s cubic-bezier(0.22, 1, 0.36, 1),
    background-color 0.35s ease,
    border-color 0.35s ease;
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .top {
    background: rgba(248, 247, 244, 0.6);
    -webkit-backdrop-filter: blur(18px) saturate(1.4);
    backdrop-filter: blur(18px) saturate(1.4);
  }
  .top[data-scrolled] {
    background: rgba(248, 247, 244, 0.82);
  }
}
.top[data-scrolled] {
  padding-top: 13px;
  padding-bottom: 13px;
  border-bottom-color: var(--rule);
}
/* The wordmark loses its subtitle on condense rather than shrinking, which
   would reflow the row every time you crossed the threshold. */
.top .mark small {
  max-height: 20px;
  opacity: 1;
  overflow: hidden;
  transition:
    max-height 0.35s cubic-bezier(0.22, 1, 0.36, 1),
    opacity 0.2s ease,
    margin-top 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}
.top[data-scrolled] .mark small {
  max-height: 0;
  opacity: 0;
  margin-top: 0;
}

/*
 * Paper grain.
 *
 * The ground here is a warm off-white, and large flat areas of it look like
 * unpainted CSS. Real printed matter has tooth.
 *
 * This was a WebGL pass first, which rendered as coloured static: turbulence
 * fills the channels independently, so noise is rainbow unless something
 * explicitly desaturates it. SVG `feTurbulence` plus `feColorMatrix
 * type="saturate" values="0"` guarantees grey, weighs nothing, needs no
 * bundle, and cannot drift the way a shader's uniforms can.
 *
 * Fixed, multiplied, and inert, so it never intercepts a click and never
 * lifts the blacks under the hero.
 */
.grain {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.22;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.95' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size: 180px 180px;
}
@media (prefers-reduced-transparency: reduce) {
  .grain {
    display: none;
  }
}
.mark {
  text-decoration: none;
  flex: none;
}
.mark strong {
  display: block;
  font-family: var(--display);
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1;
}
.mark small {
  display: block;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: 4px;
}
.top nav ul {
  display: flex;
  gap: 28px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.top nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 15.5px;
  text-decoration: none;
  color: var(--ink-2);
}
.top nav a:hover,
.top nav a[aria-current='page'] {
  color: var(--ink);
}
.top-book {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 18px;
  border: 1px solid var(--spruce);
  border-radius: 2px;
  font-size: 14.5px;
  font-weight: 600;
  text-decoration: none;
  color: var(--spruce);
}
.top-book:hover {
  background: var(--spruce);
  color: var(--paper);
}
.burger {
  display: none;
  margin-left: auto;
  min-height: 44px;
  padding: 0 14px;
  background: none;
  border: 1px solid var(--rule-2);
  border-radius: 2px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  color: var(--ink);
}
.mnav {
  display: none;
  flex-direction: column;
  border-bottom: 1px solid var(--rule);
  background: var(--fog);
}
.mnav[data-open] {
  display: flex;
}
.mnav a {
  display: flex;
  align-items: center;
  min-height: 54px;
  padding: 0 var(--gut);
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
  font-size: 16px;
}

/* --- hero ----------------------------------------------------------------- */

/*
 * The hero runs up underneath the header rather than starting below it.
 * Without this the translucent header only has paper behind it on the one
 * page where the effect matters most, and the blur has nothing to do.
 *
 * Pulling up by the header's height means the hero must grow by the same
 * amount to keep its visible height, hence the calc on min-height.
 */
.hero {
  position: relative;
  z-index: 0;
  margin-top: calc(-1 * var(--top-h));
  min-height: calc(82svh + var(--top-h));
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  padding: var(--top-h) var(--gut) 0;
}
.hero-shot {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  transition: opacity 0.9s ease;
}
.hero-shot.on {
  opacity: 1;
}
.hero-shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hero-scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(
      100deg,
      rgba(14, 20, 18, 0.86) 0%,
      rgba(14, 20, 18, 0.58) 34%,
      rgba(14, 20, 18, 0.12) 62%,
      rgba(14, 20, 18, 0) 78%
    ),
    linear-gradient(
      5deg,
      rgba(14, 20, 18, 0.88) 0%,
      rgba(14, 20, 18, 0.42) 40%,
      rgba(14, 20, 18, 0.04) 74%
    );
}
.hero-body {
  position: relative;
  z-index: 2;
  color: var(--paper);
  max-width: 60ch;
  padding-bottom: 34px;
}
.hero-body .eyebrow {
  color: #e9c9a8;
}
.hero-note {
  color: #dfe2df;
  margin-top: 20px;
}

/* The date finder sits in the hero, which is the whole positioning: both
   reference properties defer this to an off-domain vendor page. */
.finder {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 1fr 1fr auto auto;
  gap: 14px;
  align-items: end;
  background: var(--paper);
  border: 1px solid var(--rule-2);
  border-bottom: 0;
  border-radius: 3px 3px 0 0;
  padding: 18px 20px;
}
.finder-f {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.finder-f label {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.finder-f input,
.finder-f select {
  min-height: 46px;
  padding: 0 12px;
  border: 1px solid var(--rule-2);
  border-radius: 2px;
  background: var(--paper);
  font-family: var(--body);
  font-size: 16px;
  color: var(--ink);
}
.finder-f input:focus,
.finder-f select:focus {
  border-color: var(--spruce);
  outline: none;
}

/* --- bands ---------------------------------------------------------------- */

.band {
  padding: 96px var(--gut);
  border-top: 1px solid var(--rule);
}
.band-alt {
  background: var(--fog);
}
.measure {
  max-width: 76ch;
  margin-bottom: 40px;
}
.page-top {
  padding: 70px var(--gut) 44px;
}
.page-top.narrow {
  max-width: 76ch;
}
.page-top h1 {
  max-width: 17ch;
}
.page-top .page-lede {
  margin-top: 22px;
}
.two {
  display: grid;
  grid-template-columns: 1.5fr 1fr;
  gap: 60px;
  align-items: start;
}

/* --- rooms ---------------------------------------------------------------- */

.rooms-strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--rule);
  border-top: 1px solid var(--rule);
}
.room-card {
  background: var(--paper);
  text-decoration: none;
  padding-bottom: 26px;
}
.room-card figure {
  margin: 0;
}
.room-card img {
  width: 100%;
  height: 42svh;
  object-fit: cover;
}
.room-meta {
  padding: 24px var(--gut) 0;
}
.room-view {
  color: var(--ink-2);
  font-size: 15.5px;
  margin-top: 10px;
}
.room-rate {
  margin: 14px 0 0;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}
.room-rate strong {
  font-size: 20px;
}
.room-rate span {
  color: var(--ink-3);
  font-size: 12px;
}
.room-card:hover h3 {
  color: var(--signal);
}

.room-list,
.guide-list {
  border-top: 1px solid var(--rule);
}
.room-row,
.guide-row.flip,
.guide-list .guide-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 52px;
  align-items: center;
  padding: 80px var(--gut);
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
}
.room-row.flip > figure,
.guide-list .guide-row.flip > figure {
  order: 2;
}
.room-row figure,
.guide-list .guide-row figure {
  margin: 0;
}
.room-row img,
.guide-list .guide-row img {
  width: 100%;
  height: 54svh;
  object-fit: cover;
}
.mini {
  display: flex;
  flex-wrap: wrap;
  gap: 28px;
  margin: 26px 0;
  border-top: 1px solid var(--rule);
  padding-top: 18px;
}
.mini dt {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.mini dd {
  margin: 5px 0 0;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 15px;
}

.bleed {
  margin: 0;
  height: 66svh;
}
.bleed img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* --- rate card ------------------------------------------------------------ */

.rate-card {
  border: 1px solid var(--rule-2);
  background: var(--fog);
  padding: 26px;
  border-radius: 3px;
}
.rate-card dl {
  margin: 0 0 22px;
  border-top: 1px solid var(--rule-2);
}
.rate-card dl > div {
  display: flex;
  justify-content: space-between;
  gap: 18px;
  padding: 12px 0;
  border-bottom: 1px solid var(--rule);
}
.rate-card dt {
  font-size: 14.5px;
}
.rate-card dt span {
  display: block;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-3);
  margin-top: 2px;
}
.rate-card dd {
  margin: 0;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 16px;
  white-space: nowrap;
}
.rate-note {
  margin: 14px 0 0;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.55;
  color: var(--ink-3);
}

/* --- splits, guides, quotes ----------------------------------------------- */

.split-band,
.innkeeper {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 56px;
  align-items: center;
}
.split-media {
  margin: 0;
}
.split-media img {
  width: 100%;
  height: 56svh;
  object-fit: cover;
}
.guide-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
}
.guide {
  text-decoration: none;
}
.guide figure {
  margin: 0 0 20px;
}
.guide img {
  width: 100%;
  height: 34svh;
  object-fit: cover;
}
.guide p {
  color: var(--ink-2);
  margin-top: 10px;
  font-size: 15.5px;
}
.guide:hover h3 {
  color: var(--signal);
}
.guide-read {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.quote-band {
  background: var(--spruce);
  color: var(--fog);
}
.quote-band .rating {
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  color: #e9c9a8;
  margin-bottom: 34px;
}
.quote-band .stars {
  letter-spacing: 0.1em;
}
.quote-band blockquote {
  margin: 0 0 34px;
  max-width: 62ch;
}
.quote-band blockquote p {
  font-family: var(--display);
  font-size: clamp(20px, 2.3vw, 27px);
  line-height: 1.36;
  margin: 0 0 14px;
}
.quote-band cite {
  font-style: normal;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  color: #b9c4bf;
}
.quote-band cite span {
  display: block;
  opacity: 0.75;
  margin-top: 3px;
}

.prose {
  max-width: 70ch;
  margin: 0 auto;
  padding: 78px var(--gut);
}
.prose h2 {
  font-size: clamp(23px, 2.4vw, 30px);
  margin: 44px 0 14px;
}
.prose h2:first-child {
  margin-top: 0;
}
.prose p {
  color: var(--ink-2);
  font-size: 17.5px;
}

.tick,
.cross {
  list-style: none;
  margin: 0 0 18px;
  padding: 0;
}
.tick li,
.cross li {
  position: relative;
  padding-left: 26px;
  margin-bottom: 10px;
  font-size: 16px;
  color: var(--ink-2);
}
.tick li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 9px;
  width: 9px;
  height: 5px;
  border-left: 2px solid var(--spruce);
  border-bottom: 2px solid var(--spruce);
  transform: rotate(-45deg);
}
.cross li::before {
  content: '';
  position: absolute;
  left: 3px;
  top: 12px;
  width: 11px;
  border-top: 1px solid var(--rule-2);
}

/* --- booker --------------------------------------------------------------- */

.booker {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: 56px;
  align-items: start;
}
.booker-step {
  display: grid;
  grid-template-columns: 54px 1fr;
  gap: 22px;
  padding: 34px 0;
  border-top: 1px solid var(--rule);
}
.booker-step:first-child {
  border-top: 0;
  padding-top: 0;
}
.step-n {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--signal);
  margin: 6px 0 0;
}
.date-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
  margin-top: 18px;
}

.avail {
  list-style: none;
  margin: 20px 0 0;
  padding: 0;
  border-top: 1px solid var(--rule);
}
.avail li {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 18px;
  align-items: center;
  padding: 16px 0;
  border-bottom: 1px solid var(--rule);
}
.avail .a-name strong {
  display: block;
  font-family: var(--display);
  font-size: 19px;
}
.avail .a-name span {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-3);
}
.avail .a-rate {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}
.avail .a-rate small {
  display: block;
  color: var(--ink-3);
  font-size: 12px;
}
.avail button {
  min-height: 44px;
  padding: 0 16px;
  border: 1px solid var(--spruce);
  border-radius: 2px;
  background: none;
  color: var(--spruce);
  font-family: var(--body);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.avail button:hover,
.avail li[data-picked] button {
  background: var(--spruce);
  color: var(--paper);
}
/* Refusals say why. A room that silently vanishes teaches the guest nothing
   and reads as a broken calendar. */
.avail li[data-blocked] {
  color: var(--ink-3);
}
.avail .a-why {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-3);
  text-align: right;
  max-width: 24ch;
}

.summary {
  position: sticky;
  top: 24px;
  border: 1px solid var(--rule-2);
  background: var(--fog);
  padding: 26px;
  border-radius: 3px;
}
.sum {
  margin: 0 0 16px;
  border-top: 1px solid var(--rule-2);
}
.sum > div {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 11px 0;
  border-bottom: 1px solid var(--rule);
}
.sum dt {
  font-size: 14.5px;
  color: var(--ink-2);
}
.sum dd {
  margin: 0;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 15px;
}
.sum .sum-total dt,
.sum .sum-total dd {
  font-weight: 700;
  color: var(--ink);
  font-size: 17px;
}
.sum-note {
  margin: 0;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.55;
  color: var(--ink-3);
}

.hold-form {
  display: grid;
  grid-template-columns: 1fr 1fr auto;
  gap: 14px;
  align-items: end;
  margin-top: 18px;
}
.held {
  margin-top: 20px;
  border-left: 2px solid var(--signal);
  background: rgba(157, 82, 39, 0.08);
  padding: 18px 20px;
}
.held strong {
  display: block;
  margin-bottom: 5px;
}
.held span {
  font-size: 15px;
  color: var(--ink-2);
}

/* --- handoff -------------------------------------------------------------- */

/*
 * The handoff list.
 *
 * This was a bordered grid of filled cells with a 54px first column for a step
 * number. The numbers came out when the site dropped 01/02/03, and the column
 * stayed, so every card's content was squeezed into 54px and wrapped one word
 * per line. Rebuilt as the same hairline ledger the rooms index uses: name and
 * role hold the left, the explanation runs at a readable measure on the right,
 * and nothing is boxed.
 */
.handoff {
  list-style: none;
  margin: 48px 0 0;
  padding: 0;
}
.handoff li {
  display: grid;
  grid-template-columns: minmax(0, 26ch) minmax(0, 1fr);
  gap: 10px 64px;
  align-items: baseline;
  padding: 30px 0;
  border-top: 1px solid var(--rule);
  position: relative;
}
.handoff li:last-child {
  border-bottom: 1px solid var(--rule);
}
/* The engine is the one that owns the reservation, so it gets the accent rule
   rather than a filled background. */
.handoff li.on::before {
  content: '';
  position: absolute;
  left: -18px;
  top: 30px;
  bottom: 30px;
  width: 2px;
  background: var(--signal);
}
.handoff strong {
  display: block;
  font-family: var(--display);
  font-size: clamp(20px, 2vw, 25px);
  line-height: 1.15;
  letter-spacing: -0.01em;
}
.handoff em {
  display: block;
  font-style: normal;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 8px 0 0;
}
.handoff p {
  margin: 0;
  color: var(--ink-2);
  font-size: 16.5px;
  line-height: 1.6;
  max-width: 58ch;
}

@media (max-width: 820px) {
  .handoff li {
    grid-template-columns: 1fr;
    gap: 14px;
  }
  .handoff li.on::before {
    left: -14px;
  }
}

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

.foot {
  border-top: 1px solid var(--rule);
  background: var(--fog);
}
.foot-grid {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr;
  gap: 40px;
  padding: 62px var(--gut);
}
.foot-name {
  font-family: var(--display);
  font-size: 22px;
  font-weight: 600;
  margin: 0 0 8px;
}
.foot-addr,
.foot-season {
  font-size: 15px;
  color: var(--ink-2);
}
.foot-season {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-3);
}
.foot a {
  text-decoration: none;
}
.foot-grid > div:first-child a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
.foot a:hover {
  color: var(--signal);
}
.foot-col {
  display: flex;
  flex-direction: column;
}
.foot-col h2 {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 12px;
}
.foot-col a {
  display: flex;
  align-items: center;
  min-height: 44px;
  font-size: 15px;
  color: var(--ink-2);
}
.foot-base {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 26px;
  padding: 22px var(--gut) 30px;
  border-top: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--ink-3);
}

/* --- responsive ----------------------------------------------------------- */

@media (max-width: 1000px) {
  .two,
  .booker,
  .split-band,
  .innkeeper,
  .room-row,
  .guide-list .guide-row,
  .guide-row {
    grid-template-columns: 1fr;
    gap: 34px;
  }
  .room-row.flip > figure,
  .guide-list .guide-row.flip > figure {
    order: 0;
  }
  .rooms-strip {
    grid-template-columns: 1fr;
  }
  .summary {
    position: static;
  }
  .foot-grid {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 820px) {
  :root {
    --gut: 20px;
  }
  .top nav,
  .top-book {
    display: none;
  }
  .burger {
    display: block;
  }
  .band {
    padding-block: 64px;
  }
  .finder,
  .date-row,
  .hold-form {
    grid-template-columns: 1fr;
  }
  .finder .btn,
  .hold-form .btn {
    width: 100%;
  }
  .avail li {
    grid-template-columns: 1fr;
    gap: 10px;
  }
  .avail .a-rate,
  .avail .a-why {
    text-align: left;
    max-width: none;
  }
  .booker-step {
    grid-template-columns: 1fr;
    gap: 8px;
  }
  .room-card img,
  .room-row img,
  .guide-list .guide-row img,
  .split-media img {
    height: 38svh;
  }
  .bleed {
    height: 44svh;
  }
  .foot-grid {
    grid-template-columns: 1fr;
    gap: 28px;
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}

/* --- season control ------------------------------------------------------- */

/* Exposed deliberately as part of the demo frame rather than dressed up as
   something a real inn would ship. It exists to make the content model
   visible: one field moves the hero, the headline, the paragraph, the offer
   and the highlighted rate band at once. */
.seasons {
  position: relative;
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 14px;
}
.seasons-label {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(248, 247, 244, 0.72);
  margin-right: 4px;
}
.seasons button {
  min-height: 36px;
  padding: 0 14px;
  border: 1px solid rgba(248, 247, 244, 0.4);
  border-radius: 2px;
  background: rgba(20, 25, 23, 0.42);
  color: var(--paper);
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  transition:
    background-color 0.18s ease,
    color 0.18s ease;
}
.seasons button[aria-pressed='true'] {
  background: var(--paper);
  color: var(--ink);
  border-color: var(--paper);
}

/* --- fog ------------------------------------------------------------------ */

/* The one moving thing on the site, and it is the product: the inn sells the
   shoulder season and the shoulder season here is fog. Sits over the
   photograph, under the scrim, so the picture stays the subject. */
.fog {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.4s ease;
  mix-blend-mode: screen;
  /* Guarantees haze. Any residual high-frequency detail in the noise becomes
     atmosphere rather than speckle, and blurring a canvas is free. */
  filter: blur(14px);
  /*
   * A band, not a top-down wash.
   *
   * The first mask was opaque at the top and faded out by 88%, which put the
   * fog in the sky and cleared it off the water. That is backwards, and it is
   * most of why the effect read as a filter: coastal fog banks sit ON the
   * water and against the headland, thinning as they rise. Clear at the very
   * top, dense through the middle where the reach is, gone by the bottom where
   * the headline sits.
   */
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 24%, #000 60%, transparent 87%);
  mask-image: linear-gradient(180deg, transparent 0%, #000 24%, #000 60%, transparent 87%);
}

/*
 * The two layers drift independently.
 *
 * Each is scaled up so there is material to move into frame; the translate
 * never exceeds the overscan, so no edge is ever exposed. The keyframes are
 * deliberately uneven in both axes and in their spacing, because a constant
 * horizontal translate is precisely what makes fog read as a sheet on rails.
 * Real fog rises and settles as it passes, and different depths cross at
 * different rates, so the periods are long, unequal, and not multiples of each
 * other: the pair will not visibly repeat.
 */
.fog-l {
  position: absolute;
  inset: 0;
  transform-origin: 50% 60%;
}
.fog-l canvas {
  display: block;
  width: 100%;
  height: 100%;
}
@media (prefers-reduced-motion: no-preference) {
  .fog-far {
    animation: fog-far 227s ease-in-out infinite;
  }
  .fog-near {
    animation: fog-near 149s ease-in-out infinite;
  }
}
@keyframes fog-far {
  0% {
    transform: translate3d(-3.5%, 0.6%, 0) scale(1.16);
  }
  23% {
    transform: translate3d(-1.2%, -1.1%, 0) scale(1.2);
  }
  51% {
    transform: translate3d(2.4%, -0.3%, 0) scale(1.17);
  }
  74% {
    transform: translate3d(0.6%, 1.2%, 0) scale(1.21);
  }
  100% {
    transform: translate3d(-3.5%, 0.6%, 0) scale(1.16);
  }
}
@keyframes fog-near {
  0% {
    transform: translate3d(4.2%, 1.1%, 0) scale(1.26);
  }
  29% {
    transform: translate3d(1.4%, -0.9%, 0) scale(1.3);
  }
  58% {
    transform: translate3d(-3.1%, 0.4%, 0) scale(1.24);
  }
  81% {
    transform: translate3d(-0.8%, 1.4%, 0) scale(1.29);
  }
  100% {
    transform: translate3d(4.2%, 1.1%, 0) scale(1.26);
  }
}
.fog[data-fog-ready='true'] {
  opacity: 1;
}
.fog canvas {
  display: block;
  width: 100% !important;
  height: 100% !important;
}

/* --- the year ------------------------------------------------------------- */

/* A line, not a row of buttons. The same house reads differently every month,
   and the shoulder is the one worth selling, so the control is the story. */
.year {
  position: relative;
  z-index: 3;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border-top: 1px solid rgba(248, 247, 244, 0.28);
}
.year button {
  display: block;
  text-align: left;
  padding: 18px 0 26px;
  background: none;
  border: 0;
  border-top: 2px solid transparent;
  margin-top: -1px;
  color: rgba(248, 247, 244, 0.62);
  cursor: pointer;
  transition:
    color 0.3s ease,
    border-color 0.3s ease;
}
.year button span {
  display: block;
  font-family: var(--display);
  font-size: clamp(17px, 1.7vw, 23px);
  letter-spacing: -0.015em;
}
.year button em {
  display: block;
  font-style: normal;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-top: 5px;
  opacity: 0.72;
}
.year button:hover {
  color: var(--paper);
}
.year button[aria-pressed='true'] {
  color: var(--paper);
  border-top-color: #e9c9a8;
}

/* --- the date line -------------------------------------------------------- */

/* Asking for dates in the hero is the positioning: both reference properties
   defer this to a vendor page on another domain. Kept as a line of controls on
   the image rather than a white card, so it belongs to the photograph. */
.dateline {
  position: relative;
  z-index: 3;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 22px;
  padding: 0 0 26px;
}
.dateline .f {
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.dateline label {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(248, 247, 244, 0.72);
}
.dateline input,
.dateline select {
  min-height: 44px;
  padding: 0 10px;
  background: rgba(12, 18, 16, 0.42);
  border: 0;
  border-bottom: 1px solid rgba(248, 247, 244, 0.5);
  color: var(--paper);
  font-family: var(--mono);
  font-size: 15px;
  color-scheme: dark;
}
.dateline input:focus,
.dateline select:focus {
  outline: none;
  border-bottom-color: #e9c9a8;
}
.dateline button {
  min-height: 44px;
  padding: 0 20px;
  background: var(--paper);
  border: 0;
  border-radius: 2px;
  color: var(--ink);
  font-family: var(--body);
  font-size: 14.5px;
  font-weight: 600;
  cursor: pointer;
}
.dateline button:hover {
  background: #e9c9a8;
}

/* --- thesis --------------------------------------------------------------- */

/* One sentence, set large, where a rate table used to be. The argument that
   rates are published survives; the spreadsheet does not. */
/*
 * No max-width on the wrapper. `ch` resolves against the element's OWN font,
 * and this wrapper inherits 17px body type while the sentence inside it is set
 * at up to 50px display. `34ch` here measured 313px, so the headline ran nine
 * lines in a column a third of the page wide. The measure belongs on the
 * paragraph, in `em`, where it is relative to the type it is actually sizing.
 */
.thesis {
  padding: 120px var(--gut);
}
.thesis.thin {
  padding-block: 84px;
}
.thesis p {
  font-family: var(--display);
  font-size: clamp(28px, 3.6vw, 50px);
  max-width: 17em;
  line-height: 1.08;
  letter-spacing: -0.022em;
  margin: 0 0 22px;
  text-wrap: balance;
}
.thesis .thesis-2 {
  font-family: var(--body);
  font-size: 18px;
  line-height: 1.55;
  letter-spacing: 0;
  color: var(--ink-2);
  max-width: 46ch;
}
.thesis .thesis-2 strong {
  color: var(--ink);
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

/* --- plates: full bleed, text over image ---------------------------------- */

/* Rooms, offers and guides all arrive this way. A place needs the width of the
   page; a tile in a three-up grid is a thumbnail of a place. */
.plate {
  position: relative;
  min-height: 88svh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
}
.plate.tall {
  min-height: 96svh;
}
.plate.short {
  min-height: 72svh;
}
.plate-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.plate::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    92deg,
    rgba(12, 18, 16, 0.9) 0%,
    rgba(12, 18, 16, 0.6) 32%,
    rgba(12, 18, 16, 0.12) 62%,
    rgba(12, 18, 16, 0) 80%
  );
}
.plate.right {
  justify-content: flex-end;
}
.plate.right::after {
  background: linear-gradient(
    268deg,
    rgba(12, 18, 16, 0.9) 0%,
    rgba(12, 18, 16, 0.6) 32%,
    rgba(12, 18, 16, 0.12) 62%,
    rgba(12, 18, 16, 0) 80%
  );
}
.plate-copy {
  position: relative;
  z-index: 2;
  color: var(--paper);
  max-width: 46ch;
  padding: 0 var(--gut) 72px;
}
.plate-copy .eyebrow {
  color: #e9c9a8;
}
.plate-view {
  color: #e9edeb;
  font-size: 19px;
  line-height: 1.5;
  margin-top: 16px;
}
.plate-rate {
  margin: 20px 0 0;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 26px;
  color: var(--paper);
}
.plate-rate span {
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #b8c2be;
}
.arrow.light {
  color: var(--paper);
  border-bottom-color: #e9c9a8;
  margin-top: 22px;
}
.arrow.light:hover {
  color: #e9c9a8;
}

/* --- voices --------------------------------------------------------------- */

.voices {
  padding: 110px var(--gut);
  background: var(--spruce);
  color: var(--fog);
}
.voices .rating {
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  color: #e9c9a8;
  margin-bottom: 44px;
}
.voices blockquote {
  margin: 0 0 40px;
  max-width: 56ch;
}
.voices blockquote p {
  font-family: var(--display);
  font-size: clamp(21px, 2.5vw, 32px);
  line-height: 1.3;
  letter-spacing: -0.015em;
  margin: 0 0 16px;
}
.voices cite {
  font-style: normal;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  color: #b9c4bf;
}
.voices cite span {
  display: block;
  opacity: 0.78;
  margin-top: 3px;
}

/* --- booker step labels --------------------------------------------------- */

/* Was 01 / 02 / 03, which encoded nothing the words did not already say. */
.step-n {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--signal);
  margin: 8px 0 0;
}

@media (max-width: 820px) {
  .year {
    grid-template-columns: repeat(2, 1fr);
    gap: 0 18px;
  }
  .thesis {
    padding-block: 76px;
  }
  .plate,
  .plate.tall,
  .plate.short {
    min-height: 76svh;
  }
  .plate-copy {
    max-width: none;
    padding-bottom: 52px;
  }
  .voices {
    padding-block: 72px;
  }
}

/* --- the rooms walk ------------------------------------------------------ */

/*
 * The rooms index is a descent: second floor, ground floor, shore. Each
 * chapter opens with where you are standing, then the rooms you can see from
 * there. Hairlines only, so the page reads as one continuous walk rather than
 * as three stacked sections.
 */
.chapter-head {
  padding: 88px var(--gut) 40px;
  display: grid;
  grid-template-columns: minmax(0, 20ch) minmax(0, 54ch);
  gap: 8px 64px;
  align-items: baseline;
  border-top: 1px solid var(--rule);
}
.chapter-where {
  font-family: var(--mono);
  font-size: 0.8rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--signal);
  margin: 0;
}
.chapter-line {
  font-family: var(--display);
  font-size: clamp(1.25rem, 2vw, 1.7rem);
  line-height: 1.35;
  margin: 0;
  color: var(--ink);
}

/* Doors you pass without stopping. An index, never a filled table. */
.ledger {
  list-style: none;
  margin: 0;
  padding: 0 var(--gut) 24px;
}
.ledger li {
  display: grid;
  grid-template-columns: minmax(0, 20ch) minmax(0, 1fr) auto auto;
  gap: 4px 64px;
  align-items: baseline;
  padding: 26px 0;
  border-bottom: 1px solid var(--rule);
}
.ledger li:first-child {
  border-top: 1px solid var(--rule);
}
.ledger p {
  margin: 0;
}
.ledger-name {
  font-family: var(--display);
  font-size: 1.5rem;
  line-height: 1.1;
}
.ledger-bed,
.ledger-min {
  font-size: 0.95rem;
  color: var(--ink-2);
}
.ledger-rate {
  font-family: var(--mono);
  font-size: 1.05rem;
  white-space: nowrap;
}
.ledger-rate span {
  font-size: 0.86rem;
  color: var(--ink-2);
  margin-left: 8px;
}
.ledger-min {
  font-family: var(--mono);
  font-size: 0.86rem;
  white-space: nowrap;
}

/* A quiet exit line, not a call-to-action slab. */
.closer {
  padding: 80px var(--gut) 96px;
  border-top: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px 48px;
}
.closer-line {
  font-family: var(--display);
  font-size: clamp(1.5rem, 3vw, 2.4rem);
  margin: 0;
  max-width: 24ch;
}

/* --- the questions ------------------------------------------------------- */

.asked {
  padding: 96px var(--gut) 112px;
  border-top: 1px solid var(--rule);
  display: grid;
  /* Explicit px, not ch: the column's ch is the 17px body font while the
     heading inside it runs to 48px, which stacked it four lines deep. */
  grid-template-columns: minmax(0, 420px) minmax(0, 1fr);
  gap: 0 96px;
  align-items: start;
}
/* The heading holds the left column while the answers run past it, so the
   page uses its width instead of leaving half the screen empty. */
.asked h2 {
  font-size: clamp(1.7rem, 2.8vw, 2.4rem);
  margin: 0;
  position: sticky;
  top: 96px;
}
.asked dl {
  margin: 0;
  max-width: 66ch;
}
.asked div {
  padding: 30px 0;
  border-top: 1px solid var(--rule);
}
.asked dt {
  font-family: var(--display);
  font-size: clamp(1.2rem, 2.2vw, 1.6rem);
  line-height: 1.25;
  margin-bottom: 10px;
}
.asked dd {
  margin: 0;
  color: var(--ink-2);
  max-width: 60ch;
  line-height: 1.6;
}

@media (max-width: 900px) {
  .chapter-head {
    grid-template-columns: 1fr;
    padding-top: 64px;
    gap: 12px;
  }
  .ledger li {
    grid-template-columns: 1fr auto;
    gap: 2px 24px;
  }
  .ledger-bed {
    grid-column: 1;
  }
  .ledger-min {
    grid-column: 2;
    text-align: right;
  }
  .asked {
    padding-top: 64px;
    grid-template-columns: 1fr;
    gap: 40px;
  }
  .asked h2 {
    position: static;
  }
}

/*
 * Arrow links sitting on a photograph. Scoped to .plate-copy rather than left
 * to an opt-in `.light` class: the default ink arrow disappeared into the
 * Lupine photo, and axe cannot catch contrast over an image, so the safe
 * colour has to be the automatic one here.
 */
.plate-copy .arrow {
  color: var(--paper);
  border-bottom-color: #e9c9a8;
}
.plate-copy .arrow:hover {
  color: #e9c9a8;
}

.rate-card {
  border: 0;
  border-top: 1px solid var(--rule-2);
  background: none;
  padding: 26px 0 0;
  border-radius: 0;
}

/* --- motion -------------------------------------------------------------- */

/*
 * Rise on arrival.
 *
 * `data-rise` is applied by script, never in the markup, so a page with no JS
 * renders everything visible instead of hiding content behind an animation
 * that will not run. `data-shown` is the landed state.
 */
[data-rise] {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity 0.85s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.85s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}
[data-rise][data-shown] {
  opacity: 1;
  transform: none;
  will-change: auto;
}
/* Ledger rows and question blocks arrive as a run rather than together. */
.ledger li[data-rise]:nth-child(2) {
  transition-delay: 0.07s;
}
.ledger li[data-rise]:nth-child(3) {
  transition-delay: 0.14s;
}
.ledger li[data-rise]:nth-child(4) {
  transition-delay: 0.21s;
}

/*
 * Parallax on the full-bleed plates.
 *
 * Scroll-driven CSS animation, so the compositor owns it and no scroll handler
 * is involved. Where `animation-timeline` is unsupported the image simply sits
 * still, which is why the plate is overflow-hidden and the image is oversized
 * either way: nothing depends on the animation running.
 */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .plate-img {
      height: 118%;
      top: -9%;
      animation: plate-drift linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
    }
    @keyframes plate-drift {
      from {
        transform: translateY(-6%);
      }
      to {
        transform: translateY(6%);
      }
    }
  }
}

/* --- the rate sheet ------------------------------------------------------ */

/*
 * The rate table is the demo's argument, so it stays a table. What it needed
 * was to stop looking like a spreadsheet pasted onto a marketing page: the
 * room name set in the display face, prices large enough to scan, a row that
 * responds to the cursor, and the season you are shopping brought forward
 * instead of three columns competing at equal weight.
 */
.rate-sheet {
  padding: 96px var(--gut) 104px;
  border-top: 1px solid var(--rule);
}
.sheet-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px 48px;
  align-items: end;
  margin-bottom: 44px;
}
.sheet-now {
  grid-row: 2;
  grid-column: 1;
  margin: 0;
  font-family: var(--display);
  font-size: clamp(1.5rem, 3vw, 2.3rem);
  line-height: 1.1;
}
.sheet-now span {
  font-style: italic;
}
.sheet-head .eyebrow {
  grid-column: 1;
  margin: 0;
}
.sheet-year {
  grid-row: 1 / span 2;
  grid-column: 2;
  align-self: end;
  border: 0;
  padding: 0;
  gap: 0;
}

/* Included and not, as two runs of type rather than a list beside a card. */
.terms {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 34ch), 1fr));
  gap: 56px 96px;
  padding: 0 var(--gut) 96px;
}
.terms h2 {
  font-size: clamp(1.4rem, 2.4vw, 1.9rem);
  margin: 0 0 22px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--rule-2);
}

@media (max-width: 900px) {
  .sheet-head {
    grid-template-columns: 1fr;
    gap: 8px;
  }
  .sheet-year {
    grid-row: auto;
    grid-column: 1;
    margin-top: 18px;
  }
  .rate-sheet {
    padding-top: 64px;
  }
}

/*
 * The year control was written for the hero, where it sits on a photograph and
 * therefore uses paper-coloured text. On the rates page it sits on paper, so
 * every one of those colours has to invert or the control is invisible. Three
 * seasons here rather than four: "closed" has no rates to highlight.
 */
.sheet-year {
  grid-template-columns: repeat(3, minmax(0, auto));
  gap: 0 40px;
  border-top-color: var(--rule-2);
}
.sheet-year button {
  color: var(--ink-2);
  padding: 14px 0 0;
}
.sheet-year button:hover {
  color: var(--ink);
}
/* .year sets opacity 0.72 on em for the dark hero. On paper that multiplies
   --ink-3 down to 3:1, so the opacity has to be cancelled, not just recoloured. */
.sheet-year button em {
  color: var(--ink-3);
  opacity: 1;
}
.sheet-year button[aria-pressed='true'] {
  color: var(--ink);
  border-top-color: var(--signal);
}
.sheet-year button[aria-pressed='true'] em {
  color: var(--signal);
  opacity: 1;
}

/* --- the booker, modernised ---------------------------------------------- */

/*
 * The booking page read as a form in a grey box beside a grey card. Everything
 * here is the same move made elsewhere on the site: drop the container, keep a
 * hairline, and let type carry the hierarchy.
 */
.booker {
  gap: 72px;
}
.booker-step {
  /* "Dates" and "Rooms" are words now, not 01/02, and 54px cropped them. */
  grid-template-columns: minmax(0, 90px) minmax(0, 1fr);
  gap: 28px;
  padding: 44px 0;
}
.booker-step h2 {
  font-size: clamp(1.6rem, 3vw, 2.3rem);
  margin: 0 0 14px;
  letter-spacing: -0.015em;
}

/*
 * The running total. It was a bordered, filled card; now it is a column with
 * one heavy rule at the top, and the total itself is set in the display face
 * at a size that answers the question the page exists to answer.
 */
.summary {
  top: calc(var(--top-h) + 28px);
  border: 0;
  border-top: 2px solid var(--ink);
  background: none;
  border-radius: 0;
  padding: 24px 0 0;
}
.sum {
  border-top: 0;
}
.sum > div {
  padding: 15px 0;
}
.sum-total {
  border-top: 1px solid var(--rule-2);
  padding-top: 22px !important;
  align-items: baseline;
}
.sum-total dt {
  font-family: var(--display);
  font-size: 20px;
}
.sum-total dd {
  font-family: var(--display);
  font-size: clamp(28px, 4vw, 38px);
  line-height: 1;
  letter-spacing: -0.02em;
}

/* Availability rows get the ledger's breathing room. */
.avail li {
  padding: 22px 0;
}
.avail .a-name strong {
  font-size: 21px;
}
.avail button {
  border-radius: 2px;
  transition:
    background-color 0.25s ease,
    color 0.25s ease;
}

@media (max-width: 900px) {
  .booker-step {
    grid-template-columns: 1fr;
    gap: 10px;
    padding: 34px 0;
  }
  .summary {
    position: static;
  }
}

/* --- the rate sheet, second pass ------------------------------------------ */

/*
 * The sheet still read as a spreadsheet: six columns at one weight, every
 * number in mono, and the active season painted as a static rectangle that
 * began mid-header and stopped at the caption. Three changes, in order of how
 * much they matter.
 *
 * 1. The season highlight is now ONE object rather than seven tinted cells, so
 *    switching seasons slides a marker across the sheet the way you would move
 *    a ruler down a printed page. It is a single transformed element, so the
 *    compositor owns the move and not one table cell repaints. The old
 *    per-cell tint stays as the no-script fallback: the table is marked
 *    `data-marked` only once script has placed the marker.
 * 2. The active price is set in the display face and the off-season prices go
 *    quiet in mono, so the answer and the reference numbers are two different
 *    kinds of type rather than the same type at two sizes. That is the change
 *    that stops the block reading as a spreadsheet.
 * 3. Every active price carries what it saves against July. A shoulder-season
 *    inn's whole argument is that number, and the table had never said it.
 */

.sheet-sub {
  grid-row: 3;
  grid-column: 1;
  margin: 16px 0 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.sheet-sub > span {
  position: relative;
}
.sheet-sub > span + span {
  margin-left: 18px;
  padding-left: 18px;
}
.sheet-sub > span + span::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.1em;
  bottom: 0.1em;
  width: 1px;
  background: var(--rule-2);
}
.sheet-claim {
  color: var(--signal);
}
/* The control now spans three rows of the head rather than two. */
.sheet-year {
  grid-row: 1 / span 3;
}

@media (max-width: 900px) {
  .sheet-year {
    grid-row: auto;
  }
}

/* --- the booker: the room, behind the row --------------------------------- */

/*
 * The availability list was a grid of names, prices and buttons: correct, and
 * completely mute about what you would actually be sleeping in. The room
 * photographs already exist on the room pages, so the fix was to put one
 * behind each row rather than to send people away to look.
 *
 * Three rules make it work rather than make it noisy.
 *
 * The photograph is masked out before it reaches the price, so the mono
 * figures on the right never sit on top of an image. The colour is taken out,
 * so seven photographs from seven rooms read as one set on this paper instead
 * of seven competing casts. And hovering one row drops the others back, which
 * is what turns a list into a thing you look through: the row you are on is
 * the only one at full strength.
 */

.avail li {
  position: relative;
  padding: 26px 0;
  /* Contains the negative z-index of the photograph, so it sits behind this
     row's own text and not behind the page. */
  isolation: isolate;
  transition:
    opacity 0.45s ease,
    filter 0.45s ease;
}

.avail .a-shot {
  position: absolute;
  /* Bleeds into the gutter, so the photograph is a band across the row rather
     than a rectangle that stops where the text happens to stop. */
  inset: 1px -18px;
  z-index: -1;
  overflow: hidden;
  opacity: 0;
  transition: opacity 0.55s ease;
  -webkit-mask-image: linear-gradient(to right, #000 0%, rgba(0, 0, 0, 0.55) 46%, transparent 82%);
  mask-image: linear-gradient(to right, #000 0%, rgba(0, 0, 0, 0.55) 46%, transparent 82%);
}
.avail .a-shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) contrast(1.06) brightness(1.02);
  /* Settles rather than appears. The scale is slower than the fade, so the
     photograph is still moving after it has finished arriving. */
  transform: scale(1.08);
  transition: transform 1.1s cubic-bezier(0.22, 1, 0.36, 1);
}
.avail li:hover .a-shot,
.avail li:focus-within .a-shot {
  opacity: 0.2;
}
.avail li:hover .a-shot img,
.avail li:focus-within .a-shot img {
  transform: scale(1);
}
/* A room you cannot have still shows itself, but not as brightly as one you can. */
.avail li[data-blocked]:hover .a-shot,
.avail li[data-blocked]:focus-within .a-shot {
  opacity: 0.1;
}

/* The others, dropped back. */
.avail:hover li:not(:hover),
.avail:focus-within li:not(:focus-within) {
  opacity: 0.32;
}
/* Except the one already chosen, which should never vanish while you compare. */
.avail:hover li[data-picked]:not(:hover),
.avail:focus-within li[data-picked]:not(:focus-within) {
  opacity: 1;
}

/* Same gesture as the rate sheet: a rule in the gutter and a small shift of
   the name, so the two lists behave like one house. */
.avail li::before {
  content: '';
  position: absolute;
  left: -18px;
  top: 24px;
  bottom: 24px;
  width: 2px;
  background: var(--signal);
  transform: scaleY(0);
  transform-origin: 50% 0;
  transition: transform 0.42s cubic-bezier(0.22, 1, 0.36, 1);
}
.avail li:hover::before,
.avail li:focus-within::before {
  transform: scaleY(1);
}
.avail .a-name {
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}
.avail li:hover .a-name,
.avail li:focus-within .a-name {
  transform: translateX(6px);
}

/* Without a pointer there is no hover to reveal anything, so the preview is
   simply on, and nothing dims. */
@media (hover: none) {
  .avail .a-shot {
    opacity: 0.16;
  }
  .avail .a-shot img {
    transform: scale(1);
  }
  .avail:hover li:not(:hover) {
    opacity: 1;
  }
}

@media (max-width: 900px) {
  /* --gut is 20px here, so an 18px bleed would put the row past the page. */
  .avail .a-shot {
    inset: 1px -8px;
  }
  .avail li::before {
    left: -8px;
  }
}

@media (prefers-reduced-transparency: reduce) {
  .avail .a-shot {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .avail li,
  .avail .a-shot,
  .avail .a-shot img,
  .avail li::before,
  .avail .a-name {
    transition: none;
  }
  .avail .a-shot img {
    transform: none;
  }
}

/* --- the rate sheet, as rooms --------------------------------------------- */

/*
 * The sheet was a room-by-season table: seven rows, six columns, the room name
 * at the far left and its price most of the page away at the right. It was
 * accurate and it read as a spreadsheet, because that is what a rate matrix
 * reads as no matter how well the type inside it is set.
 *
 * The audit settled it. Nothing in this category uses a matrix. The reference
 * properties publish no rates at all; the design-led places run full-width
 * bands of prose with two hard facts; the one rate-publishing inn found puts a
 * single range on each room band and draws no grid anywhere.
 *
 * So the sheet is bands now, one per room, sharing the booker's behaviour: the
 * room's own photograph behind it on hover, the others dropping back. The
 * season control decides which of the three prices is the large one. All three
 * are still on the page in text, which is the argument the demo exists to make.
 */

.sheet {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--rule-2);
}
.sheet-room {
  position: relative;
  isolation: isolate;
  display: grid;
  /* The number, the room, the price. The price column is fixed so seven
     prices line up down the page without a table to do it. */
  grid-template-columns: 56px minmax(0, 1fr) 210px;
  gap: 0 40px;
  align-items: start;
  padding: 40px 0 44px;
  border-bottom: 1px solid var(--rule);
  transition:
    opacity 0.45s ease,
    filter 0.45s ease;
}

/* The room, behind the room. Same treatment as the booker's rows, at the
   larger size this band can carry. */
.sheet-shot {
  position: absolute;
  inset: 1px -18px;
  z-index: -1;
  overflow: hidden;
  opacity: 0;
  transition: opacity 0.6s ease;
  -webkit-mask-image: linear-gradient(to right, #000 0%, rgba(0, 0, 0, 0.42) 52%, transparent 86%);
  mask-image: linear-gradient(to right, #000 0%, rgba(0, 0, 0, 0.42) 52%, transparent 86%);
}
.sheet-shot-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) contrast(1.06) brightness(1.02);
  transform: scale(1.08);
  transition: transform 1.2s cubic-bezier(0.22, 1, 0.36, 1);
}
.sheet-room:hover .sheet-shot,
.sheet-room:focus-within .sheet-shot {
  opacity: 0.18;
}
.sheet-room:hover .sheet-shot-img,
.sheet-room:focus-within .sheet-shot-img {
  transform: scale(1);
}
.sheet:hover .sheet-room:not(:hover),
.sheet:focus-within .sheet-room:not(:focus-within) {
  opacity: 0.34;
}

/* Numbered, the way an index of rooms is numbered. Not decoration: it is the
   walk down to the water, which is also the price ladder. */
.sheet-n {
  margin: 6px 0 0;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.14em;
  color: var(--ink-3);
  transition: color 0.4s ease;
}
.sheet-room:hover .sheet-n,
.sheet-room:focus-within .sheet-n {
  color: var(--signal);
}

.sheet-of {
  min-width: 0;
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}
.sheet-room:hover .sheet-of,
.sheet-room:focus-within .sheet-of {
  transform: translateX(6px);
}
.sheet-of h3 {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(1.5rem, 2.6vw, 2.05rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.05;
}
.sheet-where {
  margin: 6px 0 0;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.sheet-view {
  margin: 16px 0 0;
  max-width: 46ch;
  color: var(--ink-2);
}
/* The hard facts, run together on one line with hairlines between. Three
   facts is what the category shows, and three is enough. */
.sheet-facts {
  display: flex;
  flex-wrap: wrap;
  margin: 16px 0 0;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.sheet-facts span + span {
  margin-left: 16px;
  padding-left: 16px;
  border-left: 1px solid var(--rule-2);
}
.sheet-of .arrow {
  margin-top: 20px;
}

/* The price, which is the thing this page exists for. */
.sheet-price {
  text-align: right;
}
.sheet-band {
  margin: 6px 0 0;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--signal);
}
.sheet-now-rate {
  margin: 8px 0 0;
  font-family: var(--display);
  font-size: clamp(2.4rem, 4.6vw, 3.4rem);
  line-height: 0.95;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.sheet-now-rate small {
  display: block;
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.sheet-save {
  margin: 14px 0 0;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--signal);
}
/* The rest of the year, as reference rather than as competition. */
.sheet-else {
  margin: 18px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}
.sheet-else span {
  display: block;
  margin-top: 5px;
}
.sheet-else em {
  font-style: normal;
  font-size: 10.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  margin-right: 10px;
}

.sheet-foot {
  margin: 20px 0 0;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-3);
}

@media (max-width: 900px) {
  .sheet-room {
    /* The number moves onto the room's line and the price sits under the
       prose, because a 210px price column beside 46ch of copy is two
       columns of four words each. */
    grid-template-columns: 40px minmax(0, 1fr);
    gap: 0 20px;
    padding: 32px 0 36px;
  }
  .sheet-price {
    grid-column: 2;
    text-align: left;
    margin-top: 22px;
  }
  .sheet-else span {
    display: inline-block;
    margin: 5px 22px 0 0;
  }
  .sheet-shot {
    inset: 1px -8px;
  }
}

/* Without a pointer the preview is simply on, and nothing dims. */
@media (hover: none) {
  .sheet-shot {
    opacity: 0.14;
  }
  .sheet-shot-img {
    transform: scale(1);
  }
  .sheet:hover .sheet-room:not(:hover) {
    opacity: 1;
  }
}

@media (prefers-reduced-transparency: reduce) {
  .sheet-shot {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sheet-room,
  .sheet-shot,
  .sheet-shot-img,
  .sheet-of,
  .sheet-n {
    transition: none;
  }
  .sheet-shot-img {
    transform: none;
  }
}
