/* ==========================================================================
   Eddy's Resort — Lake Mille Lacs
   Concept B design system.

   Sourced from the client-approved style guide, not invented:
   docs/concept-b/MLCV-2610-003_eddysWebsiteRedesign_styleGuide_1.pdf
   (homepage comp alongside it: MLCV-2610-003_eddysWebsiteRedesign_1.pdf).

     #CD2031  brand red   (style guide: RGB 205/32/49)
     #EBEBEB  light gray  (style guide: RGB 235/235/235)
     #231F20  near-black. The style guide's third swatch has no label; in the
              PDF it is filled 100% K (`0 0 0 1 k`), and #231F20 is how 100% K
              displays under the standard press profile. The comp itself paints
              its dark band pure #000; one near-black is kept rather than two.

   Headlines are Playfair Display Black, subheads and body Roboto, secondary
   nav Roboto Condensed Medium, icons Google Material Symbols.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Brand red. The channels are the single definition; every red in this file
     derives from them, so a brand change is one line.
     Measured contrast: --red is 5.46:1 on white and 4.58:1 on --gray, so it
     passes AA as text on both light grounds. White on --red is 5.46:1.
     It is 2.99:1 on --black, so red TEXT never goes on a black ground. */
  --red-rgb:   205, 32, 49;
  --red:       rgb(var(--red-rgb));
  --charcoal:  #403d3d;   /* red text link hover (issue 95): 10.75:1 white, 9.02:1 gray */
  --red-wash:  rgba(var(--red-rgb), 0.10);

  /* Neutrals */
  --black-rgb:  35, 31, 32;
  --black:      rgb(var(--black-rgb));   /* 16.30:1 on white */
  --text-soft:  #4a4546;                  /* 9.41:1 white, 7.90:1 gray */
  --text-muted: #6b6566;                  /* 5.71:1 white, 4.79:1 gray */
  --gray:       #ebebeb;
  --gray-light: #f5f5f5;                  /* comp: feature strip band */
  --line:       #d6d6d6;                  /* hairline rules, decorative only */
  --line-strong: #bfbfbf;                 /* comp: room card border, decorative */
  --white:      #ffffff;
  --ok:         #2f7d4f;                  /* success alert edge; decorative */

  /* Type */
  --serif:     "Playfair Display", Georgia, "Times New Roman", serif;
  --sans:      "Roboto", "Helvetica Neue", Arial, sans-serif;
  --condensed: "Roboto Condensed", "Arial Narrow", sans-serif;

  /* Heading scale. Playfair Black is a high-contrast display serif, so it
     runs larger and looser than body copy but never uppercase. */
  --fs-h1:  clamp(2.5rem, 5vw, 4.5rem);
  --fs-h2:  clamp(2.25rem, 4.5vw, 4.0625rem);   /* comp: 65px at 1440 */
  --fs-h3:  clamp(1.125rem, 1.4vw, 1.375rem);
  --fs-eyebrow: clamp(1.125rem, 2vw, 1.8125rem); /* comp: 29px at 1440 */

  --leading-head:    1.1;
  --leading-numeral: 0.9;   /* single-line numerals: box hugs the glyph */

  /* Utility type: notice bar, utility nav, primary nav. */
  --text-utility-sm: 0.8125rem;
  --text-utility:    0.875rem;
  --text-utility-lg: 0.9375rem;

  /* Rhythm */
  --measure:    64ch;
  --gutter:     clamp(1.25rem, 4vw, 4rem);
  --section:    clamp(3.5rem, 7vw, 6.5rem);
  --max:        1280px;
  --max-narrow: 760px;

  /* Motion */
  --ease:  cubic-bezier(0.22, 0.61, 0.36, 1);
  --swift: cubic-bezier(0.16, 1, 0.3, 1);
}

/* --------------------------------------------------------------------------
   2. Reset + base
   -------------------------------------------------------------------------- */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
/* Keeps anchor targets (the /see attractions the homepage links to, #66) and
   keyboard focus clear of the pinned header, site-wide. With JS the header is
   pinned in its compact form: 79px at 1440, 71px at 390, measured on issue 80.
   Without JS inner pages keep the full sticky header, 239px at 1440. */
html { scroll-padding-top: 16rem; }
html.js { scroll-padding-top: 6rem; }

body {
  margin: 0;
  background: var(--white);
  color: var(--black);
  font-family: var(--sans);
  font-size: clamp(1.0625rem, 0.4vw + 0.97rem, 1.1875rem);
  line-height: 1.6;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

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

/* The hidden attribute is only a UA-stylesheet display:none, so any author
   display rule beats it: .tabs__list (grid) and .carousel__btn (grid) showed
   with JS off, as dead focusable controls (found on PR 88). Make it win. */
[hidden] { display: none !important; }

a { color: var(--red); text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
/* Red text links go charcoal on hover and keyboard focus, not a darker red
   (Ryan, issue 95). Links with their own colour (buttons, footer, nav) set
   their own hover. */
a:hover, a:focus-visible { color: var(--charcoal); }

:focus-visible { outline: 3px solid var(--red); outline-offset: 3px; }
/* A red ring vanishes on a red ground. */
.section--red :focus-visible { outline-color: var(--white); }

.skip-link {
  position: absolute; left: -9999px;
  background: var(--black); color: var(--white);
  padding: 0.75rem 1.25rem; z-index: 999;
  font-family: var(--condensed); text-transform: uppercase; letter-spacing: 0.08em;
}
.skip-link:focus { left: 1rem; top: 1rem; }
/* White on black in every state; the global link hover would put a dark
   colour on the black box. */
.skip-link:hover, .skip-link:focus-visible { color: var(--white); }

/* Google Material Symbols (style guide: "Icons"). Use as
     <span class="icon" aria-hidden="true">waves</span>
   next to a visible text label. An icon that stands alone as a control needs
   an aria-label on the control itself -- the ligature text is not a label. */
.icon {
  font-family: "Material Symbols Outlined";
  font-weight: normal; font-style: normal;
  font-size: 1.5em; line-height: 1;
  display: inline-block; vertical-align: middle;
  text-transform: none; letter-spacing: normal; white-space: nowrap;
  word-wrap: normal; direction: ltr;
  -webkit-font-feature-settings: "liga"; font-feature-settings: "liga";
  -webkit-font-smoothing: antialiased;
}

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

/* Motion is decoration here — every animation has a static resting state. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    /* Delays too, not just durations. Collapsing the duration alone leaves a
       delayed property waiting on a clock that nothing else is running to --
       .btn's label flip is delayed to meet the wipe, so with the wipe snapped
       to instant the label sat in the wrong colour for the whole delay. That
       measured worse under reduced motion than before the delay existed. */
    transition-delay: 0s !important;
  }
}

/* --------------------------------------------------------------------------
   3. Typography
   -------------------------------------------------------------------------- */

h1, h2, h3, h4 { margin: 0 0 0.4em; }

/* Headlines: Playfair Display Black, mixed case, as set in the comp. */
h1, h2 {
  font-family: var(--serif);
  font-weight: 900;
  line-height: var(--leading-head);
  letter-spacing: -0.005em;
  text-wrap: balance;
}
h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }


/* Subheads: Roboto. The comp's card titles (CABINS, KING SUITE) are bold caps. */
h3 { font-family: var(--sans); font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em; line-height: 1.2; font-size: var(--fs-h3); }
h4 { font-family: var(--condensed); font-weight: 500; text-transform: uppercase; letter-spacing: 0.08em; font-size: 0.875rem; }

p { margin: 0 0 1.2em; max-width: var(--measure); }
p:last-child { margin-bottom: 0; }

/* The small label above a section headline -- "Where You'll Stay", "Let's
   Eat", "Our Story". Plain Roboto in sentence case, sitting tight on the
   Playfair line below it; it inherits the section's text colour. */
.eyebrow {
  font-family: var(--sans);
  font-size: var(--fs-eyebrow);
  font-weight: 400;
  line-height: 1.3;
  color: inherit;
  margin: 0 0 0.35rem;
}
/* p carries the --measure max-width, so a centred eyebrow needs auto margins
   too, or its box sits left and its text centres in the wrong place (issue 96). */
.eyebrow--center { text-align: center; margin-inline: auto; }
/* An eyebrow that labels a block (a form, a contact list) rather than leading
   into a Playfair heading needs air below it (Dan, PR 87). */
.eyebrow--standalone { margin-bottom: 1.5rem; }
/* .eyebrow--plain and .eyebrow--light still appear in markup but no longer
   style anything: Concept A drew a rule before the label and tinted it on
   dark grounds. The inner-page restyle removes them (issue 80). */

/* The lede sits directly above .prose body copy, so its colour matches the ink
   of the copy it leads -- a softer colour read as a lighter weight, which is how
   it was reported on /stay, /eat and /gather (#19).

   Size, not colour, is what separates it. The old floor was 1.1875rem, exactly
   body's own ceiling, and the vw term did not clear that floor until ~1462px --
   so from 1024px to 1440px the lede was the same face, size, weight and colour
   as the paragraph under it. The floor is now above body's ceiling at every
   width, and the preferred term is tuned to hold roughly 1.15-1.26x of body
   across the range rather than collapsing onto it. */
.lede { font-size: clamp(1.3125rem, 0.5vw + 1.1rem, 1.5rem); line-height: 1.5; color: var(--black); }
.section--black .lede { color: rgba(255,255,255,0.78); }

.prose > * + * { margin-top: 1.2em; }
.prose h2, .prose h3 { margin-top: 1.6em; }
.prose ul, .prose ol { max-width: var(--measure); padding-left: 1.25rem; }
.prose li { margin-bottom: 0.4em; }

/* --------------------------------------------------------------------------
   4. Layout
   -------------------------------------------------------------------------- */

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

.section { padding-block: var(--section); position: relative; }
.section--tight { padding-block: calc(var(--section) * 0.6); }
/* The comp's three section grounds. Measured: white on --red 5.46:1, white
   at 0.8 alpha on --black 10.80:1, --black on --gray 13.67:1. */
.section--gray { background: var(--gray); }
.section--black { background: var(--black); color: rgba(255,255,255,0.8); }
.section--black h1, .section--black h2, .section--black h3 { color: var(--white); }
.section--red { background: var(--red); color: var(--white); }
.section--red h1, .section--red h2, .section--red h3,
.section--red a:not(.btn) { color: var(--white); }

.rule { border: 0; height: 1px; background: var(--line); margin: 0; }

/* --------------------------------------------------------------------------
   6. Buttons
   -------------------------------------------------------------------------- */

/* Concept B: square red rectangles with bold Roboto caps ("BOOK", "ALL ROOMS
   & CABINS"). Padding and font-size are unchanged from Concept A on purpose --
   the label-flip delays below are measured against that geometry. */
.btn {
  position: relative;
  display: inline-flex; align-items: center; gap: 0.6rem;
  font-family: var(--sans);
  font-size: 0.8125rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.06em;
  padding: 1.1rem 2.2rem;
  border: 2px solid transparent;
  border-radius: 0;                 /* pill buttons read as SaaS, not resort */
  cursor: pointer; text-decoration: none;
  overflow: hidden;

  /* Wipe fill rather than a colour fade — reads as signage, not a web control.
     The fill is a BACKGROUND LAYER, not a positioned ::before. A positioned
     pseudo-element paints above non-positioned inline content, so on every
     button whose label is a bare text node rather than a <span> the fill
     covered the label outright — the whole button went blank on hover (#17,
     comment #7). Backgrounds always paint below text, whatever the markup, so
     this cannot regress when someone writes a button without the span. */
  background-image: linear-gradient(to top, var(--btn-fill, transparent) 0 100%);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 0;
  /* border-box, not the padding-box default. The border is 2px of transparent,
     so the button's own background-color shows through it; sizing the fill to
     the padding box left that colour as a ring around the arrived fill — the
     "thin line along the bottom" in comment #26. */
  background-origin: border-box;

  /* The label flips in ONE STEP rather than crossfading. A 350ms crossfade
     leaves it a mid-grey sitting on the arrived fill — measured at 3.26:1 on
     --outline and 4.48:1 on --light, both under AA — for most of the
     transition.

     TWO DELAYS, because the crossing is not symmetric. The fill wipes up from
     the bottom, so entering it reaches the label almost immediately, while
     leaving it must retreat most of the button's height before uncovering it.
     Both measured on this curve, for a 60px button whose label sits 20–40px
     above its lower edge:

       entering  fill covers the label   10ms → 27ms   (midpoint 18ms)
       leaving   fill uncovers it        50ms → 86ms   (midpoint 68ms)

     The delay below on .btn governs the EXIT, because the exit transitions to
     this rule's values. The delay on .btn:hover governs the ENTRY. A single
     18ms delay flipped the label 50ms before the fill had uncovered it, which
     put --outline's ink label on its own ink fill at contrast 1.0 for 42ms
     (#50). --primary and --light are unaffected either way: their labels are
     white in both states, so there is no flip to mistime.

     These are tuned to the button's geometry; a future change to .btn padding
     or font-size should re-measure rather than assume. */
  transition: background-size 0.4s var(--swift),
              border-color 0.35s var(--ease),
              color 0s linear 68ms;              /* EXIT: fill uncovers label */
}
.btn:hover, .btn:focus-visible {
  background-size: 100% 100%;
  transition: background-size 0.4s var(--swift),
              border-color 0.35s var(--ease),
              color 0s linear 18ms;              /* ENTRY: fill covers label */
}

.btn--primary { background-color: var(--red); color: var(--white); --btn-fill: var(--black); }
.btn--primary:hover, .btn--primary:focus-visible { color: var(--white); }

.btn--outline { border-color: currentColor; color: var(--black); background-color: transparent; --btn-fill: var(--black); }
.btn--outline:hover, .btn--outline:focus-visible { color: var(--white); border-color: var(--black); }

/* Red on hover, per comment #7 — the value confirmed on #29. Filling white
   behind a white label was the original complaint; red keeps the label
   white throughout, so this variant needs no colour flip at all. For a light
   outline that sits ON a red ground, use --on-red instead. */
.btn--light { border-color: rgba(255,255,255,0.55); color: var(--white); background-color: transparent; --btn-fill: var(--red); }
.btn--light:hover, .btn--light:focus-visible { color: var(--white); border-color: var(--red); }

/* The comp's outlined white-on-red button ("SEE FULL MENU", "CALL THE
   KITCHEN"). Fills white on hover, so the label flips to red: 5.46:1. Same
   geometry as .btn, so the same flip delays hold. */
.btn--on-red { border-color: var(--white); color: var(--white); background-color: transparent; --btn-fill: var(--white); }
.btn--on-red:hover, .btn--on-red:focus-visible { color: var(--red); }


/* The comp's red uppercase text action under each room card ("BOOK CABIN",
   "LEARN MORE"). Red on white is 5.46:1; hover goes charcoal, per a:hover. */
.text-link {
  font-family: var(--sans);
  font-size: 0.8125rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--red); text-decoration: none;
}
.text-link:hover, .text-link:focus-visible { color: var(--charcoal); text-decoration: underline; }

.link-arrow {
  font-family: var(--sans);
  font-size: 0.9375rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.06em;
  color: inherit; text-decoration: none;
  display: inline-flex; align-items: center; gap: 0.6rem;
  padding-bottom: 0.3rem;
  background-image: linear-gradient(var(--red), var(--red));
  background-size: 100% 1px; background-position: 0 100%; background-repeat: no-repeat;
  transition: background-size 0.4s var(--swift), color 0.3s var(--ease);
}
.link-arrow::after { content: "\2192"; transition: transform 0.35s var(--swift); }
.link-arrow:hover { color: var(--red); }
.link-arrow:hover::after { transform: translateX(6px); }

/* --------------------------------------------------------------------------
   7. Header — seasonal notice, utility row, primary row
   -------------------------------------------------------------------------- */

/* The comp's red closure bar: wide-tracked caps. White on --red, 5.46:1.
   Sizes in this section are measured from the comp rendered at 1440 wide
   (docs/concept-b, issue 75); §22 steps them down for small screens. */
.notice {
  background: var(--red);
  color: var(--white);
  font-family: var(--condensed);
  font-size: 1.0625rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.3em;
  text-align: center; padding: 1rem var(--gutter);
}
.notice a { color: var(--white); }

/* Two bands, as in the comp: a solid --gray utility band, then the nav band.
   Homepage: the nav band is translucent white over the hero photo, then the
   whole header goes solid white once the notice bar scrolls away (.is-stuck,
   set by app.js). --stack-top is the notice bar's height, measured in JS, so
   at page load the fixed header sits below it. Inner pages (.masthead--solid)
   are solid from the start and stick in flow. */
.masthead {
  position: fixed; top: var(--stack-top, 0px); left: 0; right: 0; z-index: 60;
  color: var(--black);
  /* White at 40% over the photo, sampled from the comp (the band reads
     ~rgb(206,222,233) where the sky under it is ~rgb(172,207,230)). Black
     nav text on it measured 9+:1 against the real hero photo. */
  background: rgba(255, 255, 255, 0.4);
  border-bottom: 1px solid transparent;
  transition: background-color 0.4s var(--ease), border-color 0.4s var(--ease),
              top 0.3s var(--ease);
}
.masthead.is-stuck,
.masthead--solid {
  background: var(--white);
  border-bottom-color: var(--line);
}
.masthead.is-stuck { top: 0; }
.masthead--solid { position: sticky; top: 0; background: var(--white); }
/* Homepage without JS: --stack-top is never measured, so a fixed header sat at
   0 over the whole notice bar. Absolute with top:auto keeps it at its place in
   the flow, just under the notice, still over the hero photo (issue 128). */
:root:not(.js) .masthead:not(.masthead--solid) { position: absolute; top: auto; }
/* With JS, inner pages get the same fixed header as the homepage, and an
   in-flow .masthead-spacer holds its full height (--masthead-h, measured in
   app.js). Compacting a sticky header in flow would pull the content up under
   the reader mid-scroll; a fixed one over a fixed-height spacer cannot.
   Without JS: the sticky full-size header above, no spacer. */
.js .masthead--solid { position: fixed; top: var(--stack-top, 0px); }
.js .masthead--solid.is-stuck { top: 0; }
.masthead-spacer { display: none; }
.js .masthead-spacer { display: block; height: var(--masthead-h, 0px); }
/* app.js measures the full height with this on: a read mid-transition would
   return an in-between height. */
.masthead.is-measuring, .masthead.is-measuring * { transition: none !important; }

/* Utility band: "Est. 1960 // Lake Mille Lacs" left, About · Contact ·
   Directions · reservations phone right, red on --gray (4.58:1). Style guide:
   secondary nav is Roboto Condensed Medium. */
.utility {
  background: var(--gray);
  color: var(--red);
  font-family: var(--condensed);
  font-size: 1.1875rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.01em;
}
.utility__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem; min-height: 3.75rem; padding-block: 0.4rem;
}
.utility__links { display: flex; gap: 3rem; list-style: none; margin: 0; padding: 0; flex-wrap: wrap; }
.utility__link { color: inherit; text-decoration: none; }
.utility__link:hover, .utility__link:focus-visible, .utility__link[aria-current="page"] { text-decoration: underline; text-underline-offset: 0.3em; }
/* The scrolled bar drops the utility band to stay compact; the phone is still
   in the footer, the menu and the sticky booking bar. */
.masthead.is-stuck .utility { display: none; }

/* Nav band: nav split around a centred logo. Three columns with equal outer
   tracks keep the logo on the true centre whatever the two sides hold. */
.masthead__inner { position: relative; padding-block: 2.25rem; transition: padding 0.4s var(--ease); }
.masthead.is-stuck .masthead__inner { padding-block: 0.75rem; }
.nav {
  display: grid; grid-template-columns: 1fr auto 1fr;
  align-items: center; gap: clamp(1rem, 2.5vw, 2.5rem);
}
.nav__list { display: flex; gap: clamp(1.25rem, 4.3vw, 3.9rem); list-style: none; margin: 0; padding: 0; }
.nav__right { display: flex; align-items: center; justify-content: flex-end; gap: clamp(1.25rem, 4.3vw, 3.9rem); }
.nav__link {
  font-family: var(--sans);
  font-size: clamp(1.0625rem, 1.55vw, 1.375rem); font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.01em;
  color: inherit; text-decoration: none;
  padding-block: 0.35rem;
  position: relative;
}
.nav__link::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0;
  height: 2px; background: var(--red);
  transform: scaleX(0); transform-origin: left;
  transition: transform 0.35s var(--swift);
}
/* Black nav links go red on hover (issue 95); red on white is 5.46:1. */
.nav__link:hover, .nav__link:focus-visible { color: var(--red); }
.nav__link:hover::after, .nav__link:focus-visible::after, .nav__link[aria-current="page"]::after { transform: scaleX(1); }

.masthead__logo { display: block; }
.masthead__logo img { width: clamp(140px, 15.6vw, 225px); transition: width 0.4s var(--ease); }
.masthead.is-stuck .masthead__logo img { width: clamp(96px, 8vw, 120px); }
/* Compact bar: one slim row. BOOK and the current-section underline stay; the
   reservations phone joins the row because the utility band is gone. */
.masthead.is-stuck .nav__link { font-size: 1rem; }
.masthead.is-stuck .masthead__book { font-size: 0.9375rem; padding: 0.6rem 1.1rem; }
.masthead__phone {
  display: none; white-space: nowrap;
  font-family: var(--condensed); font-weight: 500; font-size: 1rem;
  color: var(--red); text-decoration: none;
}
.masthead__phone:hover { text-decoration: underline; text-underline-offset: 0.3em; }
.masthead.is-stuck .masthead__phone { display: inline-block; }

/* The comp's BOOK: a compact red box, larger type than the nav. The label is
   white in both states, so the .btn flip timing does not apply here. */
.masthead__book { padding: 0.9rem 1.6rem; font-size: 1.125rem; letter-spacing: 0.02em; }

/* Focus rings follow the header's text colour (black), and red on BOOK. */
.masthead :focus-visible { outline-color: currentColor; }
.masthead .utility :focus-visible { outline-color: var(--red); }
.masthead .btn:focus-visible { outline-color: var(--red); }

/* Mobile menu (disclosure). Hidden on desktop; see §22 for the small-screen
   layout. Without JS there is no toggle and the menu renders open in flow. */
.menu-toggle, .menu { display: none; }
.menu-toggle {
  align-items: center; gap: 0.4rem;
  background: none; border: 0; padding: 0.5rem 0; cursor: pointer;
  color: inherit; font-family: var(--condensed); font-weight: 500;
  font-size: var(--text-utility); text-transform: uppercase; letter-spacing: 0.1em;
}
.menu__list { list-style: none; margin: 0; padding: 0; }
.menu__list--util { margin-top: 0.75rem; }
.menu__link {
  display: block; padding: 0.85rem 0;
  border-top: 1px solid var(--line);
  font-family: var(--sans); font-weight: 500; font-size: 1rem;
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--black); text-decoration: none;
}
.menu__list--util .menu__link { font-family: var(--condensed); font-size: var(--text-utility); color: var(--text-soft); }
.menu__link[aria-current="page"] { color: var(--red); }

/* --------------------------------------------------------------------------
   8. Hero + check-availability bar
   -------------------------------------------------------------------------- */

/* Photo only, as in the comp: no headline, no scrim, no motion. The fixed
   header sits over its top edge in the comp's dark treatment (§7). Height from
   the comp: 870px of photo at 1440 wide, i.e. 60.4vw, floored so a phone still
   gets a real picture under the header. */
.hero { position: relative; height: clamp(30rem, 60.4vw, 60rem); background: var(--gray); overflow: hidden; }
.hero__media { position: absolute; inset: 0; }
/* <picture> is display:inline by default, which leaves the img inside with no
   percentage height to resolve against and collapses the hero media to nothing.
   The wrapper has to be a block that fills .hero__media itself. */
.hero__media picture { display: block; width: 100%; height: 100%; }
/* Every photo fills the hero box at every width; object-position comes from
   the file's focus point (set inline in home.php), so the wide cover-crop keeps
   the same subject the portrait crop does. Until issue 144 a >=1080px rule
   grew the media box to 132% of the hero, anchored at the top, to reproduce
   the comp's crop of its shoreline photo. That photo is gone, and on the new
   ones the rule only cut off the bottom quarter, so the focus point alone
   steers the framing now. */
.hero__media img { width: 100%; height: 100%; object-fit: cover; }

/* Hero slideshow (issue 101): the shared .carousel, filling the hero box.
   Photo slides use the media above; event slides add copy on a scrim. */
.carousel--hero .carousel__track { position: absolute; inset: 0; }
.hero__slide { position: relative; height: 100%; overflow: hidden; }
.hero__slide--event .hero__media::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(var(--black-rgb), 0.35) 0%, rgba(var(--black-rgb), 0.3) 30%, rgba(var(--black-rgb), 0.72) 55%, rgba(var(--black-rgb), 0.88) 100%);
}
.hero__event {
  position: absolute; inset: auto 0 clamp(4rem, 7vw, 6rem);
  color: var(--white);
}
.hero__event-date { font-size: clamp(1.0625rem, 1.6vw, 1.375rem); font-weight: 500; margin: 0 0 0.35rem; text-shadow: 0 1px 2px rgba(var(--black-rgb), 0.6); }
.hero__event-title { font-family: var(--serif); font-weight: 900; font-size: var(--fs-h1); line-height: var(--leading-head); margin: 0; text-wrap: balance; text-shadow: 0 1px 3px rgba(var(--black-rgb), 0.5); }
.hero__event-more { margin: clamp(1rem, 2vw, 1.5rem) 0 0; }
.carousel--hero .carousel__btn { z-index: 2; }
/* Position dots: 24px targets (WCAG 2.5.8) around a 12px dot. */
.carousel__dots {
  position: absolute; z-index: 2; left: 50%; bottom: clamp(1rem, 2vw, 1.5rem); transform: translateX(-50%);
  display: flex; gap: 0.25rem;
}
.carousel__dot {
  width: 1.5rem; height: 1.5rem; padding: 0; border: 0; background: none; cursor: pointer;
  display: grid; place-items: center;
}
.carousel__dot::before {
  content: ""; width: 0.75rem; height: 0.75rem; border-radius: 50%;
  border: 2px solid var(--white); box-shadow: 0 0 0 1px rgba(var(--black-rgb), 0.45);
}
.carousel__dot[aria-current="true"]::before { background: var(--white); }
.carousel__dot:focus-visible { outline: 3px solid var(--white); outline-offset: 0; border-radius: 50%; }

/* Check-availability bar: three red cells and a gray action cell, full bleed,
   straight under the hero. White on --red is 5.46:1; --red on --gray 4.58:1. */
.availability {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  background: var(--red); color: var(--white);
}
.availability__field {
  position: relative;
  display: flex; flex-direction: column; justify-content: center; gap: 0.3rem;
  padding: 2.25rem clamp(1.25rem, 4.8vw, 4.5rem);
  /* 1px of half-white, sampled from the comp. Decorative only. */
  border-right: 1px solid rgba(255,255,255,0.5);
}
.availability label {
  font-family: var(--sans); font-size: clamp(1rem, 1.7vw, 1.5rem); font-weight: 400;
  text-transform: uppercase; letter-spacing: 0.01em; line-height: 1.2;
}
.availability input,
.availability select {
  width: 100%; min-height: 2.75rem;
  font-family: var(--sans); font-size: clamp(1.125rem, 2vw, 1.75rem); font-weight: 700;
  color: var(--white); background: transparent;
  border: 0; border-radius: 0;
  padding: 0.2rem 0;
  /* White native calendar glyph and picker chrome on the red ground. */
  color-scheme: dark;
}
.availability select { appearance: none; -webkit-appearance: none; padding-right: 2rem; cursor: pointer; }
/* The option list is drawn by the OS on its own light surface. */
.availability option { color: var(--black); background: var(--white); }
/* Each icon is centred on its 2.75rem control: field padding plus half the
   space the icon leaves, so it lines up with the native date indicator. */
.availability { --av-icon: clamp(1.5rem, 2.4vw, 2.25rem); }
.availability__field .icon {
  position: absolute; right: clamp(1.25rem, 4.8vw, 4.5rem);
  bottom: calc(2.25rem + (2.75rem - var(--av-icon)) / 2);
  font-size: var(--av-icon); pointer-events: none;
}
/* The comp's outlined calendar replaces the browser's small glyph (issue 96).
   The native indicator stays where it is, transparent and enlarged to the
   icon's size, so a click on the icon still lands on it and opens the picker;
   the icon itself ignores the pointer. */
.availability input[type="date"]::-webkit-calendar-picker-indicator {
  opacity: 0; cursor: pointer;
  width: var(--av-icon); height: var(--av-icon);
  margin: 0; padding: 0;
}
/* Firefox has no such indicator and draws its own calendar button inside the
   input, so ours would make two icons. A browser that does not support the
   pseudo-element keeps its native button and drops ours. (Every browser
   accepts ::-webkit-* names as valid selectors; selector() still reports
   false for one it doesn't implement. Chrome: true for this, false for a
   made-up ::-webkit- name.) */
@supports not selector(::-webkit-calendar-picker-indicator) {
  .availability__cal { display: none; }
}
.availability :focus-visible { outline: 2px solid var(--white); outline-offset: 4px; }
.availability__submit {
  border: 0; border-radius: 0; cursor: pointer;
  background: var(--gray); color: var(--red);
  font-family: var(--sans); font-size: clamp(1.125rem, 2vw, 1.75rem); font-weight: 700;
  line-height: 1.25; text-transform: uppercase; letter-spacing: 0.01em;
  text-align: left;
  padding: 1.5rem clamp(1.25rem, 5.7vw, 5.125rem);
  transition: background-color 0.3s var(--ease);
}
.availability__submit:hover { background: var(--white); }
.availability__submit:focus-visible { outline: 3px solid var(--red); outline-offset: -6px; }
/* With Cabins & Rooms and the feature strip hidden (issue 100), the red bar
   sits on the red Launch section; the bar's own half-white rule keeps them apart. */
.availability + .launch { border-top: 1px solid rgba(255,255,255,0.5); }

/* Interior page header */
.pagehead { position: relative; background: var(--black); overflow: hidden; }
.pagehead__media { position: absolute; inset: 0; }
.pagehead__media img { width: 100%; height: 100%; object-fit: cover; filter: saturate(1) contrast(1.04); }
.pagehead__media::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(var(--black-rgb), 0.6) 0%, rgba(var(--black-rgb), 0.82) 100%);
}
.pagehead__body {
  position: relative;
  min-height: clamp(19rem, 42vh, 30rem);
  display: flex; flex-direction: column; justify-content: flex-end;
  padding-block: clamp(6rem, 10vw, 8rem) clamp(2.5rem, 5vw, 4rem);
  color: var(--white);
}
.pagehead__title { color: var(--white); margin: 0; }
/* Two even lines, not one long line and a stranded word or two (issue 98). */
.pagehead__sub { color: rgba(255,255,255,0.86); margin: 1rem 0 0; max-width: 52ch; text-wrap: balance; }

/* --------------------------------------------------------------------------
   10. Homepage: Plan Your Visit (tabs) + Our Story
   Measured from the comp rendered at 1440 (issue 78).
   -------------------------------------------------------------------------- */

/* Same 1227px content width as the other homepage sections; the photo
   columns bleed to the viewport edge. */
.plan, .story { --side: max(var(--gutter), calc((100% - 1227px) / 2)); }
.plan .wrap.plan__wrap, .story .wrap.story__head { max-width: calc(1227px + 2 * var(--gutter)); }

/* Tabs: three equal columns over a hairline, the selected one underlined red.
   Text on --gray: --black 13.67:1. */
.tabs__list {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
  border-bottom: 1px solid var(--text-muted);
  margin: clamp(1.5rem, 3vw, 2.75rem) 0 clamp(2rem, 5vw, 4.5rem);
}
.tabs__tab {
  background: none; border: 0; cursor: pointer;
  padding: 0.6em 0.5em 0.7em; margin-bottom: -1px;
  font-family: var(--sans); font-size: clamp(1.0625rem, 1.95vw, 1.75rem); font-weight: 400;
  text-transform: uppercase; color: var(--black);
  border-bottom: 4px solid transparent;
}
/* The selected label is red too, so the tabs read as interactive (issue 95).
   --red on --gray is 4.58:1. */
.tabs__tab[aria-selected="true"] { border-bottom-color: var(--red); color: var(--red); }
.tabs__tab:hover { color: var(--red); }
.tabs__tab:focus-visible { outline-offset: -4px; }
.tabs__panel:focus-visible { outline-offset: 6px; }
/* With JS the tab names the panel; without JS each panel needs its own. */
.tabs.is-enhanced .tabs__nojs-title { display: none; }

/* /eat menus (issue 25): the shared tabs, then one menu at a time. Sections
   head a two-column list of items on wide screens. Prices are small figures:
   Roboto 700, as printed (issue 94). */
/* A line that applies to the whole menu, e.g. the kids' single price: body
   text above the items, not a footnote (PR 119 review). */
.foodmenu__intro { font-size: clamp(1.0625rem, 1.5vw, 1.25rem); font-weight: 700; margin: 0 0 clamp(1.5rem, 3vw, 2.25rem); max-width: none; }
.foodmenu__group + .foodmenu__group { margin-top: clamp(1.75rem, 3.5vw, 3rem); }
.foodmenu__section {
  font-family: var(--sans); font-weight: 700; font-size: clamp(1.125rem, 1.9vw, 1.5rem);
  letter-spacing: 0; padding-bottom: 0.6em; border-bottom: 1px solid var(--black); margin: 0 0 1rem;
}
.foodmenu__items { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.25rem 3rem; }
@media (min-width: 900px) { .foodmenu__items { grid-template-columns: 1fr 1fr; } }
.foodmenu__item { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 1rem; align-content: start; }
.foodmenu__name { font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em; }
.foodmenu__price { grid-column: 2; grid-row: 1; font-family: var(--sans); font-weight: 700; text-align: right; white-space: nowrap; }
.foodmenu__desc, .foodmenu__extras { grid-column: 1 / -1; color: var(--text-soft); max-width: 40em; }
.foodmenu__extras { font-size: 0.9375rem; margin-top: 0.2rem; }
.foodmenu__line { grid-column: 1 / -1; font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em; }
.foodmenu__note { margin: clamp(1.75rem, 3vw, 2.5rem) 0 0; font-size: 0.875rem; color: var(--text-soft); max-width: none; }
.foodmenu__pdf { margin: 1rem 0 0; display: flex; gap: 0.75rem; align-items: baseline; }
.foodmenu__pdf-size { font-size: 0.875rem; color: var(--text-muted); }
.tabs__nojs-title {
  font-size: clamp(1.25rem, 2.2vw, 2rem); margin: 2.5rem 0 1rem;
  padding-bottom: 0.5rem; border-bottom: 4px solid var(--red);
}

.plan__panel {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: clamp(2rem, 9.5vw, 8.5rem);
  margin-right: calc(-1 * var(--side));   /* photo bleeds to the right edge */
}
.plan__heading {
  font-family: var(--sans); font-weight: 700; text-transform: uppercase; letter-spacing: 0;
  font-size: clamp(1.125rem, 1.95vw, 1.75rem); line-height: 1.2;
  margin: 0 0 1rem; padding-bottom: 0.6em; border-bottom: 1px solid var(--black);
}
.plan__heading ~ .plan__heading { margin-top: clamp(2rem, 4.5vw, 4rem); }
.plan__rows, .plan__grid { list-style: none; margin: 0; padding: 0; }
.plan__rows li, .plan__grid li, .plan__specs div {
  font-weight: 500; font-size: clamp(1rem, 1.9vw, 1.6875rem); line-height: 1.35;
  padding-block: 0.3em;
}
/* Column-major, as in the comp: Walleye / Smallmouth Bass / Northern Pike down
   the first column, in the order they are entered. */
.plan__grid { columns: 2; column-gap: 1.5rem; }
.plan__grid li { break-inside: avoid; }
.plan__intro { font-size: clamp(1rem, 1.65vw, 1.4375rem); line-height: 1.4; margin-bottom: clamp(1.5rem, 3vw, 2.5rem); }
.plan__specs { margin: 0; }
.plan__specs div { display: flex; justify-content: space-between; gap: 1rem; }
.plan__specs dd { margin: 0; font-family: var(--sans); font-weight: 700; }
/* LEARN MORE, plus MN Fishing Regulations on the FISH tab (issue 99): wraps
   to two rows on a narrow screen. */
.plan__more { margin: clamp(2rem, 4.5vw, 4rem) 0 0; display: flex; flex-wrap: wrap; gap: 1rem; }
.plan__more .btn { font-size: clamp(1rem, 1.55vw, 1.375rem); letter-spacing: 0; padding: 0.55em 1.1em; }

/* Photo strip: scroll-snap, so it works by swipe/scroll with no JS. */
.carousel { position: relative; }
.carousel__track {
  display: flex; overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.carousel__track::-webkit-scrollbar { display: none; }
.carousel__slide { flex: 0 0 100%; margin: 0; scroll-snap-align: start; }
.carousel__slide img { width: 100%; aspect-ratio: 575 / 567; object-fit: cover; }
/* White chevrons over the photo, as in the comp, on a dark disc so they hold
   3:1 against any photo (a control's graphic, WCAG 1.4.11). */
.carousel__btn {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 3rem; height: 3rem; border: 0; border-radius: 50%; cursor: pointer;
  display: grid; place-items: center;
  background: rgba(var(--black-rgb), 0.55); color: var(--white);
}
.carousel__btn .icon { font-size: 1.6rem; }
.carousel__btn--prev { left: 1rem; }
.carousel__btn--prev .icon { transform: translateX(0.2rem); }   /* optical centre of the chevron */
.carousel__btn--next { right: 1rem; }
.carousel__btn:hover { background: rgba(var(--black-rgb), 0.8); }
.carousel__btn:focus-visible { outline: 3px solid var(--white); outline-offset: 2px; }

/* Testimonials (issue 79): two quotes side by side on the black band.
   White on --black 16.30:1. */
.testimonials .wrap.testimonials__wrap { max-width: calc(1227px + 2 * var(--gutter)); }
.testimonials__grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  gap: clamp(2.5rem, 5vw, 4.5rem) clamp(2rem, 9vw, 8.1rem);
  margin-top: clamp(2rem, 5.5vw, 5rem);
}
.testimonial { margin: 0; color: var(--white); }
.testimonial__quote { margin: 0; }
.testimonial__quote::before {
  content: "\201C"; display: block;
  font-family: var(--serif); font-weight: 900; line-height: 0.6;
  font-size: clamp(3rem, 5vw, 4.5rem); height: 0.5em; margin-bottom: 0.45em;
}
.testimonial__quote p { font-size: clamp(1.0625rem, 1.65vw, 1.4375rem); line-height: 1.4; max-width: 36em; margin: 0; }
.testimonial__name { font-weight: 700; font-size: clamp(1.0625rem, 1.65vw, 1.4375rem); margin-top: 1.4em; }
.testimonial__source { font-weight: 400; }

/* We're Hiring (issue 128): a compact band above the footer. Text left,
   button right on desktop; the button drops under the text on a phone. */
.hiring { padding-block: clamp(2.5rem, 5vw, 4rem); }
.hiring__wrap { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1.5rem clamp(2rem, 5vw, 4rem); }
.hiring__body { flex: 1 1 32rem; }
.hiring__title { margin: 0 0 0.4em; }
.hiring__text { margin: 0; max-width: 60ch; }
.hiring__btn { flex: none; }

/* Our Story: photo bleeding left with the red badge over its corner. */
.story__head { margin-bottom: clamp(1.5rem, 3.5vw, 3.25rem); }
.story__head h2 { margin: 0; }
.story__grid {
  display: grid; grid-template-columns: minmax(0, 44.8vw) minmax(0, 1fr);
  column-gap: clamp(2rem, 8.2vw, 7.4rem);
  padding-right: var(--side);
}
.story__media { position: relative; margin-bottom: clamp(2rem, 3.4vw, 3rem); }
.story__img { width: 100%; aspect-ratio: 645 / 638; object-fit: cover; }
/* White on --red 5.46:1. */
.story__badge {
  position: absolute; right: clamp(-3.5rem, -3.8vw, -1rem); bottom: clamp(-3rem, -3.4vw, -1rem);
  width: clamp(7rem, 13.4vw, 12rem); aspect-ratio: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: var(--red); color: var(--white); margin: 0; text-align: center;
}
.story__badge-year { font-family: var(--serif); font-weight: 900; font-size: clamp(2.5rem, 5.4vw, 4.875rem); line-height: 1; }
.story__badge-label { font-weight: 700; text-transform: uppercase; font-size: clamp(0.875rem, 1.3vw, 1.1875rem); margin-top: 0.3em; }
/* The comp's copy grey (#7f7f7f) is 3.95:1; --text-muted passes, 5.71:1. */
.story__text { color: var(--text-muted); font-size: clamp(1rem, 1.65vw, 1.4375rem); line-height: 1.45; max-width: none; }
.story__more { color: var(--red); font-weight: 700; text-decoration: none; }
.story__more:hover, .story__more:focus-visible { color: var(--charcoal); text-decoration: underline; }
.story__stats {
  list-style: none; margin: clamp(1.5rem, 3vw, 2.5rem) 0 0; padding: clamp(1.5rem, 3vw, 2.5rem) 0 0;
  border-top: 1px solid var(--black);
  display: grid; grid-template-columns: repeat(3, auto); justify-content: start; column-gap: clamp(1.5rem, 4.5vw, 4rem);
}
.story__stat { color: var(--red); }
.story__num, .story__suffix { font-family: var(--serif); font-weight: 900; font-size: clamp(2.5rem, 5.5vw, 5rem); line-height: 1; }
.story__suffix { font-weight: 400; }
.story__label {
  display: block; width: min-content; margin-top: 0.4em;
  font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  font-size: clamp(0.8125rem, 1.35vw, 1.1875rem); line-height: 1.2;
}

/* --------------------------------------------------------------------------
   11. Homepage: The Launch (red band)
   Measured from the comp rendered at 1440 (issue 77). White on --red is
   5.46:1 for every text size here, including the menu descriptions.
   -------------------------------------------------------------------------- */

/* Same content width as the room cards: 1227px at 1440. --launch-side is the
   resulting side margin, which the full-bleed photo column ignores. */
.launch { --launch-side: max(var(--gutter), calc((100% - 1227px) / 2)); }
.launch .wrap.launch__head { max-width: calc(1227px + 2 * var(--gutter)); }
.launch__head {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 2rem;
  margin-bottom: clamp(2rem, 4.3vw, 4rem);
}
.launch__head h2 { margin: 0; }
.launch__logo { width: clamp(150px, 23.6vw, 340px); height: auto; flex: none; margin-top: -2.5rem; }

/* Photo column bleeds to the left edge (0-645px at 1440); the text column
   stops at the content edge on the right. */
.launch__grid {
  /* 44.8vw: the comp's 645px photo column is measured against the full
     1440 width, not the grid (which stops short of the right margin). */
  display: grid; grid-template-columns: minmax(0, 44.8vw) minmax(0, 1fr);
  column-gap: clamp(2rem, 8.2vw, 7.4rem);
  padding-right: var(--launch-side);
}
.launch__img { width: 100%; aspect-ratio: 645 / 604; object-fit: cover; }

/* Hours card (snippets/hourscard.php): white, black left edge, black row rules.
   Shared by the homepage Launch section and /eat. */
.hourscard {
  background: var(--white); color: var(--black);
  border-left: 6px solid var(--black);
  padding: clamp(1.25rem, 2.3vw, 2.1rem) clamp(1.25rem, 2.1vw, 1.9rem) clamp(1rem, 1.6vw, 1.5rem);
}
.launch .hourscard { margin: clamp(2rem, 3.6vw, 3.25rem) 0 0 var(--launch-side); }
.hourscard .hourscard__title {   /* beats .section--red h3 (white) */
  color: var(--red); font-size: clamp(1rem, 1.45vw, 1.3125rem); font-weight: 700;
  letter-spacing: 0.04em; margin: 0 0 clamp(0.75rem, 1.5vw, 1.4rem);
}
.hourscard .hours { max-width: none; }
.hourscard .hours th, .hourscard .hours td {
  font-size: clamp(1.125rem, 2vw, 1.8125rem); line-height: 1.25;
  padding: 0.35em 0; border-bottom: 1px solid var(--black);
}
.hourscard .hours th { font-weight: 400; text-transform: none; letter-spacing: 0; width: auto; color: var(--black); }
/* The comp's times are #7f7f7f, 3.95:1 on white; --text-muted passes, 5.71:1. */
.hourscard .hours td { text-align: right; color: var(--text-muted); white-space: nowrap; }
.hourscard .hours .is-closed { font-style: normal; }
.hourscard .hours tr:last-child th, .hourscard .hours tr:last-child td { border-bottom: 0; }

.launch__intro { font-size: clamp(1.0625rem, 1.65vw, 1.4375rem); line-height: 1.4; }
.launch__intro p { max-width: none; margin: 0; }
.launch__intro p + p { margin-top: 0.75em; }

.samplemenu { margin-top: clamp(2rem, 3.5vw, 3.25rem); }
.samplemenu__title, .samplemenu__section {
  font-family: var(--sans); font-weight: 700; text-transform: uppercase;
  letter-spacing: 0; font-size: clamp(1.25rem, 2.2vw, 2rem); line-height: 1.2;
  color: var(--white);
}
.samplemenu__title { margin: 0 0 clamp(1.25rem, 2.3vw, 2rem); }
.samplemenu__section {
  margin: clamp(1.75rem, 3.5vw, 3.25rem) 0 0; padding-bottom: clamp(0.75rem, 1.2vw, 1.1rem);
  border-bottom: 1px solid var(--white);
}
.samplemenu__title + .samplemenu__section { margin-top: 0; }
.samplemenu__list { list-style: none; margin: 0; padding: 0; }
.samplemenu__dish {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 1.5rem;
  margin-top: clamp(1rem, 2vw, 1.75rem);
}
.samplemenu__item { font-weight: 700; font-size: clamp(1.125rem, 1.9vw, 1.75rem); line-height: 1.25; }
.samplemenu__price {
  grid-column: 2; grid-row: 1 / span 2;
  font-family: var(--sans); font-weight: 700; line-height: 1.1;
  font-size: clamp(1.375rem, 2.2vw, 2rem);
}
.samplemenu__desc { font-size: clamp(1rem, 1.65vw, 1.4375rem); line-height: 1.3; max-width: 23em; }

.launch__actions {
  display: flex; flex-wrap: wrap; gap: 1rem clamp(1rem, 2.4vw, 2.1rem);
  margin: clamp(2rem, 4.1vw, 3.75rem) 0 0; max-width: none;
}
.launch__actions .btn { font-size: clamp(1rem, 1.7vw, 1.5625rem); letter-spacing: 0; padding: 0.55em 1em; }

/* --------------------------------------------------------------------------
   12. Split layout (inner pages)
   -------------------------------------------------------------------------- */

/* The interior templates (dining, gather, room, contact) lay out on .split. */
.split { display: grid; grid-template-columns: repeat(12, 1fr); gap: clamp(1.5rem, 3vw, 3.5rem); align-items: center; }
.split--top { align-items: start; }
.split__media { grid-column: 1 / span 7; }
.split__body  { grid-column: 8 / span 5; }
.split__media img { width: 100%; }

/* --------------------------------------------------------------------------
   13. Homepage room cards + feature strip
   Measured from the comp rendered at 1440 (issue 76).
   -------------------------------------------------------------------------- */

/* The comp sets this section wider than the header: 1227px of content at 1440
   (111px margins) against the standard wrap's 1152. */
.homerooms .wrap { max-width: calc(1227px + 2 * var(--gutter)); }
.homerooms h2 { margin-bottom: clamp(2rem, 4.2vw, 4rem); }

.roomcards {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.5rem, 4.2vw, 4rem);
}
.roomcard {
  display: flex; flex-direction: column;
  border: 1px solid var(--line-strong);
  background: var(--white);
}
.roomcard__img { width: 100%; aspect-ratio: 369 / 260; object-fit: cover; }
.roomcard__body {
  flex: 1; display: flex; flex-direction: column;
  padding: clamp(1.5rem, 2.9vw, 2.75rem) clamp(1.25rem, 2.4vw, 2.25rem);
}
.roomcard__head { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; }
/* min-content breaks the name at every space, which is how the comp sets it:
   KING / SUITE, DOUBLE / QUEEN, CABINS on one line. */
.roomcard__name {
  width: min-content; margin: 0.3rem 0 0;
  font-family: var(--sans); font-weight: 400;
  font-size: clamp(1.25rem, 2vw, 1.8125rem); line-height: 1.2;
  text-transform: uppercase; letter-spacing: 0;
}
.roomcard__name a { color: var(--black); text-decoration: none; }
.roomcard__name a:hover { color: var(--red); }
/* Figures this size and smaller are Roboto 700, the weight of "Check
   availability"; only the large display figures (Our Story) stay Playfair
   (issue 94). The same rule sets .plan__specs dd, .samplemenu__price and
   .room__index. */
.roomcard__price { margin: 0; text-align: right; line-height: 1; }
.roomcard__amount {
  display: block;
  font-family: var(--sans); font-weight: 700; color: var(--red);
  font-size: clamp(1.75rem, 2.9vw, 2.625rem);
}
/* The comp's "/ night" is #7f7f7f, 3.95:1 on white; --text-muted is the
   nearest token that passes, 5.71:1. A block of its own, spaced, so it clears
   the amount instead of touching it (issue 94). */
.roomcard__per { display: block; margin-top: 0.4em; font-size: clamp(0.9375rem, 1.3vw, 1.1875rem); color: var(--text-muted); }

/* /stay only: the room's one-line summary. --text-soft on white 9.41:1. */
.roomcard__summary { color: var(--text-soft); margin: 1rem 0 0; font-size: 1rem; }
.roomcard__tags {
  list-style: none; margin: clamp(1.5rem, 3vw, 2.75rem) 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 0.95rem 1.25rem;
}
/* --text-soft on --gray: 7.90:1. */
.roomcard__tags li {
  background: var(--gray); color: var(--text-soft);
  font-size: clamp(0.875rem, 1.45vw, 1.3125rem); text-transform: uppercase;
  line-height: 1.2; padding: 0.55em 0.7em;
}
.roomcard__book {
  margin-top: auto; padding-top: clamp(1.5rem, 3vw, 2.7rem);
  font-size: clamp(1rem, 1.65vw, 1.5rem); letter-spacing: 0;
  align-self: flex-start;
}
.homerooms__all { text-align: center; margin: clamp(2.5rem, 6.2vw, 5.75rem) auto 0; max-width: none; }
.homerooms__all .btn { font-size: clamp(1rem, 1.65vw, 1.5rem); letter-spacing: 0; padding: 0.85rem 1.75rem; }

/* Four red icons over two-line labels on the light gray band.
   --red on --gray-light: 5.01:1. */
.featurestrip { background: var(--gray-light); padding-block: clamp(2.5rem, 4.5vw, 4rem); }
.featurestrip__list {
  list-style: none; margin-block: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 2rem 1rem;
}
.featurestrip__item {
  display: flex; flex-direction: column; align-items: center; gap: 0.75rem;
  text-align: center; color: var(--red);
}
.featurestrip__icon { font-size: clamp(3.5rem, 5.8vw, 5.25rem); font-variation-settings: "wght" 400; }
.featurestrip__label {
  font-weight: 700; line-height: 1.25;
  font-size: clamp(1.125rem, 1.95vw, 1.75rem);
}

/* --------------------------------------------------------------------------
   14. Section headers
   -------------------------------------------------------------------------- */

/* The homepage pattern: an eyebrow over a Playfair heading, no rule and no
   letterspaced caps. The optional meta ("3 photos") sits quietly at the right.
   --text-muted: 5.71:1 on white, 4.79:1 on --gray. */
.sechead {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: end; gap: 2rem;
  margin-bottom: clamp(2rem, 4.2vw, 4rem);
}
.sechead__title { margin: 0; }
.sechead__meta {
  font-size: 1rem; color: var(--text-muted);
  white-space: nowrap; padding-bottom: 0.6rem;
}
.section--black .sechead__meta { color: rgba(255,255,255,0.8); }

/* --------------------------------------------------------------------------
   15. Rooms
   -------------------------------------------------------------------------- */

.rooms { display: flex; flex-direction: column; }
.room {
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: clamp(1.75rem, 4vw, 4rem); align-items: center;
  padding-block: clamp(2.25rem, 4vw, 3.5rem);
  border-top: 1px solid var(--line);
}
.room:last-child { border-bottom: 1px solid var(--line); }
.room:nth-child(even) .room__media { order: 2; }
/* A row with no photo (see.php): the text takes the full width, at a
   readable measure, instead of sitting beside an empty column. */
.room--text { grid-template-columns: minmax(0, 1fr); }
.room--text .room__body { max-width: 46rem; }
.room__media { overflow: hidden; }
.room__media img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; transition: transform 0.9s var(--swift); }
.room:hover .room__media img { transform: scale(1.05); }
.room__index {
  font-family: var(--sans); font-weight: 700; font-size: 1.5rem;
  color: var(--red); display: block; margin-bottom: 0.5rem;
}
.room__title { margin-bottom: 0.6rem; }
.room__desc { color: var(--text-soft); margin-bottom: 1.25rem; }
/* A short fact under a row title: a price, a distance. Was an .eyebrow in
   Concept A; the Concept B eyebrow is a 29px section label, far too large. */
.subline { font-weight: 500; color: var(--text-soft); margin: 0 0 0.75rem; }
.section--black .subline { color: rgba(255,255,255,0.8); }

.amenities { list-style: none; padding: 0; margin: 0 0 1.5rem; display: flex; flex-wrap: wrap; gap: 0.5rem; }
/* The homepage room card's gray pill. --text-soft on --gray: 7.90:1. */
.amenities { gap: 0.6rem 0.75rem; }
.amenities li {
  font-size: 0.9375rem; text-transform: uppercase; line-height: 1.2;
  color: var(--text-soft); background: var(--gray);
  padding: 0.5em 0.7em;
}
.section--black .amenities li { color: var(--white); background: rgba(255,255,255,0.14); }

/* /stay amenities (issue 127): three lists side by side, one column on a
   phone. A sub-list (the casino pool hours) sits tight under its item. */
.amenitylists {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: 2rem clamp(2rem, 4vw, 3.5rem);
}
.amenitylists h3 { margin-bottom: 0.75rem; }
.amenitylists li ul { margin-top: 0.25rem; }
/* Optional wide photo above the lists (issue 130); 5:2, taller on a phone. */
.amenitylists__photo { display: block; width: 100%; height: auto; aspect-ratio: 5 / 2; object-fit: cover; margin-bottom: clamp(2rem, 4vw, 3rem); }
@media (max-width: 600px) { .amenitylists__photo { aspect-ratio: 3 / 2; } }

/* --------------------------------------------------------------------------
   16. Hours, spec lists, downloads
   -------------------------------------------------------------------------- */

.hours { width: 100%; border-collapse: collapse; max-width: 34rem; }
.hours th, .hours td { text-align: left; padding: 0.75rem 0; border-bottom: 1px solid var(--line); vertical-align: top; }
.hours th { font-weight: 700; font-size: 0.875rem; text-transform: uppercase; letter-spacing: 0.02em; width: 11rem; }
.hours td { color: var(--text-soft); }
.hours tr:last-child th, .hours tr:last-child td { border-bottom: 0; }
.hours .is-closed { color: var(--text-muted); font-style: italic; }
.section--black .hours th, .section--black .hours td { border-bottom-color: rgba(255,255,255,0.16); }
.section--black .hours th { color: var(--white); }
.section--black .hours td { color: rgba(255,255,255,0.8); }

/* One column track for the whole list (subgrid), so every value shares a left
   edge. Per-row grids sized the key column per row, and a long unbreakable
   value (an email) pushed its own value column left (issue 96). */
.speclist {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: minmax(8rem, 13rem) 1fr; column-gap: 1.5rem;
}
.speclist li {
  grid-column: 1 / -1;
  display: grid; grid-template-columns: subgrid;
  padding: 0.85rem 0; border-bottom: 1px solid var(--line);
}
.speclist__key { font-weight: 700; font-size: 0.875rem; text-transform: uppercase; letter-spacing: 0.02em; }
.speclist__val { color: var(--text-soft); }

/* Ice house rentals on /fish (issue 126): rates and package in a .split
   column, then the detail lists side by side, one column on a phone. */
.icehouse__head { margin: 2rem 0 0.75rem; }
.icehouse__lists {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: 2rem clamp(2rem, 4vw, 3.5rem); margin-top: clamp(2.5rem, 5vw, 4rem);
}
.icehouse__lists .icehouse__head { margin-top: 0; }
/* Bait shops are a two-column speclist: under ~26rem the directions wrap
   word by word, so this row stacks sooner. */
.icehouse__lists--wide { grid-template-columns: repeat(auto-fit, minmax(min(100%, 26rem), 1fr)); }

.downloads { display: grid; gap: 0.75rem; margin: 2rem 0 0; padding: 0; list-style: none; }
.download {
  display: flex; align-items: center; justify-content: space-between; gap: 1.5rem;
  padding: 1.25rem 1.5rem; background: var(--white);
  border: 1px solid var(--line);
  text-decoration: none; color: var(--black);
  transition: background 0.3s var(--ease), color 0.3s var(--ease), transform 0.3s var(--swift);
}
.download:hover { background: var(--red); border-color: var(--red); color: var(--white); transform: translateX(6px); }
.download__name { font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em; font-size: 0.9375rem; }
/* Full-strength colour, not opacity: 0.7 alpha dropped it under AA. */
.download__meta { font-size: 0.875rem; color: var(--text-muted); }
.download:hover .download__meta { color: var(--white); }

/* --------------------------------------------------------------------------
   17. Gallery
   -------------------------------------------------------------------------- */

.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 0.75rem; }
.gallery__item { overflow: hidden; margin: 0; position: relative; }
.gallery__item img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; transition: transform 0.9s var(--swift); }
.gallery__item:hover img,
.gallery__link:focus-visible img { transform: scale(1.06); }
.gallery__item--wide { grid-column: span 2; }
.gallery__item--wide img { aspect-ratio: 3 / 1.32; }

/* --gallery--uniform: opt-in, one block of identical cells.
   The default .gallery above is auto-fill/minmax with hardcoded double-width
   cells, so its column count moves with the viewport while the wide cells stay
   put and the block ends ragged -- at 1440px the last row was a single cell
   filling 19% of the width, at a different height from its neighbours (#26).

   Every cell here is the same size and a short final row is CENTRED rather than
   stretched. Stretching fills the row but makes those cells wider than the
   rest, which is the size difference reported on /see in #27. Flex rather than
   grid, because flex centres a short final row for free at any item count.

   NOTE ON CROPPING: the row height is fixed while the columns are fluid, so the
   cell's own ratio moves between roughly 1.86 and 2.15 across the range. No
   single crop ratio can match that, so object-fit performs a second, centred
   trim on top of the focus-aware crop() in snippets/gallery.php. Do not "fix"
   the crop rungs to match the cell -- there is no ratio that does. */
.gallery--uniform {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 0.75rem;
}
.gallery--uniform .gallery__item {
  flex: 0 0 calc((100% - 1.5rem) / 3);   /* three per row, two gaps */
  height: clamp(9rem, 14vw, 13rem);
}
.gallery--uniform .gallery__item img {
  width: 100%; height: 100%; aspect-ratio: auto; object-fit: cover; display: block;
}
@media (max-width: 900px) {
  .gallery--uniform .gallery__item { flex-basis: calc((100% - 0.75rem) / 2); }
}

/* Lightbox (issue 138). Each gallery cell's <img> sits in a link to the large
   photo. The link is a block at the cell's full height so the uniform cells'
   height:100% images still resolve against the cell: the grids are unchanged.
   The cell clips overflow (for the hover zoom), which would clip an outside
   focus ring, so the ring is drawn inside the cell instead: red with a white
   inner line, so it holds against light and dark photos alike. */
.gallery__link { display: block; height: 100%; position: relative; cursor: zoom-in; }
.gallery__link:focus-visible { outline: none; }
.gallery__link:focus-visible::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  border: 3px solid var(--red); box-shadow: inset 0 0 0 2px var(--white);
}

/* The dialog itself fills the viewport (a click on its empty area is a click
   on the backdrop, see app.js) and centres the photo. The photo keeps its own
   ratio, fitted inside 90vw by 85vh less room for the caption. The dark layer
   is the dialog's own background, not ::backdrop: text on it then has a real
   background behind it, so its contrast is what a checker measures too (axe
   can't see ::backdrop and measured the counter against the page beneath). */
html.has-lightbox { overflow: hidden; scrollbar-gutter: stable; }
.lightbox {
  width: 100%; height: 100%; max-width: none; max-height: none;
  margin: 0; padding: 4.5rem 0 1.5rem; border: 0;
  background: rgba(var(--black-rgb), 0.94); color: var(--white); overflow: hidden;
}
.lightbox[open] { display: grid; place-items: center; animation: lightbox-in 0.2s ease-out; }
.lightbox::backdrop { background: transparent; }
@keyframes lightbox-in { from { opacity: 0; } to { opacity: 1; } }

.lightbox__figure { margin: 0; display: grid; justify-items: center; gap: 0.75rem; }
.lightbox__stage { position: relative; display: grid; place-items: center; min-width: 6rem; min-height: 6rem; }
.lightbox__img {
  max-width: 90vw; max-height: min(85vh, calc(100vh - 10rem));
  width: auto; height: auto; object-fit: contain;
  transition: opacity 0.2s ease-out;
}
.lightbox__caption {
  max-width: min(60ch, 90vw); text-align: center;
  font-size: var(--text-utility-lg); line-height: 1.5;
}
.lightbox__count {
  position: absolute; top: 1.25rem; left: 1.25rem; margin: 0;
  font-family: var(--condensed); font-size: var(--text-utility); letter-spacing: 0.08em;
}

/* Loading: the old photo fades out and a ring spins until the new one has
   arrived. Reduced motion stills the ring through the global rule above. */
.lightbox.is-loading .lightbox__img { opacity: 0; }
.lightbox.is-loading .lightbox__stage::after {
  content: ""; position: absolute; width: 2.5rem; height: 2.5rem;
  border: 3px solid rgba(255, 255, 255, 0.3); border-top-color: var(--white); border-radius: 50%;
  animation: lightbox-spin 0.8s linear infinite;
}
@keyframes lightbox-spin { to { transform: rotate(360deg); } }

/* Same discs as the carousel: 3rem (48px) targets, white glyph on a dark disc. */
.lightbox__btn {
  position: absolute; width: 3rem; height: 3rem; border: 0; border-radius: 50%; cursor: pointer;
  display: grid; place-items: center;
  background: rgba(255, 255, 255, 0.12); color: var(--white);
}
.lightbox__btn[hidden] { display: none; }
.lightbox__btn .icon { font-size: 1.6rem; }
.lightbox__btn:hover { background: rgba(255, 255, 255, 0.24); }
.lightbox__btn:focus-visible { outline: 3px solid var(--white); outline-offset: 2px; }
.lightbox__btn--close { top: 0.75rem; right: 0.75rem; }
.lightbox__btn--prev { left: 1rem; top: 50%; transform: translateY(-50%); }
.lightbox__btn--prev .icon { transform: translateX(0.2rem); }   /* optical centre of the chevron */
.lightbox__btn--next { right: 1rem; top: 50%; transform: translateY(-50%); }
@media (max-width: 600px) {
  /* On a phone the arrows sit under the photo rather than on it. */
  .lightbox__btn--prev, .lightbox__btn--next { top: auto; bottom: 1rem; transform: none; }
  .lightbox { padding-bottom: 5rem; }
}

/* Where we are: a still image of the location plus a handoff to the guest's
   own maps app. Deliberately not an embed -- see the note in directions.php. */
.locator { margin-top: 2.5rem; }
/* The embedded Google map (issue 32): 16:9 across the column, taller on a
   phone so the pin has room around it. */
.locator__map { margin: 0 0 1.5rem; overflow: hidden; border: 1px solid var(--line); aspect-ratio: 16 / 9; }
.locator__map iframe { display: block; width: 100%; height: 100%; border: 0; }
@media (max-width: 600px) { .locator__map { aspect-ratio: 4 / 5; } }
.locator__go { margin: 0; }

/* --------------------------------------------------------------------------
   18. Journal
   -------------------------------------------------------------------------- */

.posts { display: grid; gap: 0; }
.post-row {
  display: grid; grid-template-columns: 9rem minmax(0, 1fr) 16rem;
  gap: clamp(1.5rem, 3vw, 3rem); align-items: start;
  padding-block: 2rem; border-top: 1px solid var(--line);
  text-decoration: none; color: inherit;
  transition: background 0.35s var(--ease), padding 0.35s var(--ease);
}
.post-row:last-child { border-bottom: 1px solid var(--line); }
.post-row:hover .post-row__title { color: var(--red); }
.post-row__date { font-size: 0.9375rem; font-weight: 500; color: var(--text-muted); padding-top: 0.2rem; }
.post-row__title { margin: 0 0 0.5rem; transition: color 0.25s var(--ease); }
.post-row__excerpt { color: var(--text-soft); font-size: 1rem; margin: 0; }
.post-row__media { overflow: hidden; }
.post-row__media img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; transition: transform 0.9s var(--swift); }
.post-row:hover .post-row__media img { transform: scale(1.06); }
.section--gray .post-row:hover { background: var(--white); }

/* --------------------------------------------------------------------------
   19. Sticky booking bar
   -------------------------------------------------------------------------- */

.bookbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 55;
  background: var(--black); color: var(--white);
  border-top: 3px solid var(--red);
  transform: translateY(110%);
  transition: transform 0.45s var(--swift);
}
.bookbar.is-up { transform: none; }
.bookbar__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem; padding-block: 0.9rem;
}
.bookbar__text { font-size: 1rem; }
.bookbar__text strong { color: var(--white); font-weight: 700; }
.bookbar__actions { display: flex; gap: 0.75rem; align-items: center; }
.bookbar .btn { padding: 0.85rem 1.75rem; }

/* --------------------------------------------------------------------------
   20. Forms
   -------------------------------------------------------------------------- */

.field { margin-bottom: 1.5rem; }
.field label { display: block; font-weight: 700; font-size: 0.875rem; text-transform: uppercase; letter-spacing: 0.02em; margin-bottom: 0.45rem; }
.field .req { color: var(--red); }
.field input, .field textarea, .field select {
  width: 100%; font-family: var(--sans); font-size: 1rem;
  /* A control's boundary needs 3:1 (WCAG 1.4.11). --line was 1.4:1 and the
     fields all but vanished; --text-muted is 5.71:1. */
  padding: 0.95rem 1.1rem; border: 1px solid var(--text-muted);
  background: var(--white); color: var(--black); border-radius: 0;
}
/* A solid 3px ring rather than a 10%-alpha wash, which was the whole focus
   indicator before. --red on white: 5.46:1. */
.field input:focus-visible, .field textarea:focus-visible, .field select:focus-visible {
  border-color: var(--red); outline: 3px solid var(--red); outline-offset: 2px;
}
.field [aria-invalid="true"] { border: 2px solid var(--red); }
/* Tied to its field by aria-describedby in contact.php. --red on white 5.46:1. */
.field__error { color: var(--red); font-size: 0.9375rem; font-weight: 500; margin: 0.4rem 0 0; }
.field textarea { min-height: 11rem; resize: vertical; }
.formnote { font-size: 0.9375rem; color: var(--text-muted); }

.alert { padding: 1rem 1.25rem; border-left: 4px solid; margin-bottom: 2rem; }
.alert--ok    { border-color: var(--ok); background: var(--gray-light); }
.alert--error { border-color: var(--red); background: var(--red-wash); }
.alert ul { margin: 0.5rem 0 0; padding-left: 1.1rem; }
.alert p { margin: 0; }
.hp { position: absolute; left: -9999px; }

/* --------------------------------------------------------------------------
   21. Footer
   -------------------------------------------------------------------------- */

/* The comp's red footer. All text is full white: 5.46:1 on --red. A reduced
   alpha white would drop under AA on this ground, so hierarchy comes from size
   and weight instead. */
.footer { background: var(--red); color: var(--white); padding-block: clamp(3.5rem, 7vw, 5rem) 1.5rem; }
.footer a { color: var(--white); text-decoration: none; }
.footer a:hover { text-decoration: underline; text-underline-offset: 0.25em; }
.footer :focus-visible { outline-color: var(--white); }
.footer__grid {
  display: grid; grid-template-columns: 1.4fr 1.6fr 1fr;
  gap: clamp(2rem, 4vw, 3.5rem);
  padding-bottom: 2.5rem;
}
.footer__logo { width: clamp(160px, 16.7vw, 240px); margin-bottom: clamp(1.25rem, 3.5vw, 3.25rem); }
.footer address { font-style: normal; font-size: clamp(1rem, 1.65vw, 1.5rem); line-height: 1.6; }
.footer__nav { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; }
.footer__nav ul { list-style: none; margin: 0; padding: 0; }
.footer__nav li { margin-bottom: 0.55em; font-size: clamp(1rem, 1.65vw, 1.5rem); line-height: 1.6; }
.footer__nav a {
  font-family: var(--sans); font-weight: 400;
  text-transform: uppercase; letter-spacing: 0;
}
.footer__contact { display: flex; flex-direction: column; gap: 0.2em; font-size: clamp(1rem, 1.65vw, 1.5rem); font-weight: 400; }
.footer__contact a { text-decoration: underline; text-underline-offset: 0.18em; }
.footer__social { display: flex; gap: 0.25rem; margin-top: 1rem; margin-left: -0.6rem; }
/* 44px targets around 22px glyphs. */
.footer__social a { width: 44px; height: 44px; display: grid; place-items: center; }
.footer__social a:hover { opacity: 0.8; }
.footer__social svg { width: clamp(22px, 2.2vw, 32px); height: clamp(22px, 2.2vw, 32px); fill: currentColor; }
.footer__base {
  display: flex; flex-wrap: wrap; gap: 0.75rem 2rem; justify-content: space-between;
  padding-top: 1.5rem; border-top: 1px solid rgba(255,255,255,0.35);
  font-family: var(--condensed); font-size: var(--text-utility-sm);
  text-transform: uppercase; letter-spacing: 0.1em;
}

/* --------------------------------------------------------------------------
   22. Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 1180px) {
  .footer__grid { grid-template-columns: 1fr 1fr; }
  .footer__brand { grid-column: 1 / -1; }
  .post-row { grid-template-columns: 7rem minmax(0, 1fr); }
  .post-row__media { display: none; }
}

/* Small-screen header. The split nav needs ~1080px, so below that the row
   becomes [Menu] [logo] [BOOK] and the page links move into the disclosure.
   The reservations phone stays visible in the utility row. */
@media (max-width: 1079px) {
  .nav__list, .utility__est, .utility__page { display: none; }
  .notice { font-size: var(--text-utility-sm); letter-spacing: 0.2em; padding-block: 0.55rem; }
  .utility { font-size: var(--text-utility-sm); letter-spacing: 0.1em; }
  .masthead__inner, .masthead.is-stuck .masthead__inner { padding-block: 0.6rem 0.8rem; }
  .masthead__book { font-size: 0.875rem; padding: 0.75rem 1.2rem; }
  /* No room in the phone row; the number is in the menu instead. */
  .masthead.is-stuck .masthead__phone { display: none; }
  .utility__inner { justify-content: flex-end; min-height: 2rem; }
  /* The phone is the one tap target left in this row; give it a 32px hit area. */
  .utility__phone { display: inline-block; padding-block: 0.5rem; }
  .utility__inner { padding-block: 0; }
  .masthead__inner { display: flex; flex-wrap: wrap; align-items: center; gap: 0 1rem; }
  .nav { flex: 1; grid-template-columns: 1fr auto; }
  .masthead__logo { justify-self: start; }
  .masthead__logo img { width: 112px; }
  .masthead.is-stuck .masthead__logo img { width: 96px; }

  /* No JS: no toggle, and the menu sits open under the row in normal flow. */
  .menu { display: block; order: 3; flex-basis: 100%; }
  .menu__link, .menu__list--util .menu__link { color: inherit; }

  /* With JS: a toggle, and the menu drops down as a white panel. */
  .js .masthead__inner { flex-wrap: nowrap; }
  .js .menu-toggle { display: inline-flex; }
  .js .menu {
    display: none; position: absolute; inset: 100% 0 auto 0;
    background: var(--white); border-bottom: 1px solid var(--line);
    padding: 0 var(--gutter) 1.25rem;
    max-height: calc(100svh - 6rem); overflow-y: auto;
  }
  .js .menu.is-open { display: block; }
  .js .menu__link { color: var(--black); }
  .js .menu__list--util .menu__link { color: var(--text-soft); }
  /* Menu links go red on hover, as the desktop nav does (issue 95). Last and
     three classes deep so it beats the two colour rules above. */
  .js .menu__list .menu__link:hover, .js .menu__list .menu__link:focus-visible { color: var(--red); }
  /* The current page in red, as on desktop (issue 106). Three classes deep and
     after the colour rules above, so it wins with JS on and off, in both lists. */
  .menu__list .menu__link[aria-current="page"] { color: var(--red); }
  .js .menu__list:first-child li:first-child .menu__link { border-top: 0; }
  /* Opening the menu over the hero turns the bar solid, so the white panel
     does not hang off a transparent strip. */
  .masthead.is-menu-open { background: var(--white); border-bottom-color: var(--line); }

  /* Availability bar: dates side by side, then guests, then the action. */
  .availability { grid-template-columns: 1fr 1fr; }
  .availability__field--select { grid-column: 1 / -1; border-right: 0; border-top: 1px solid rgba(255,255,255,0.5); }
  .availability__field:nth-child(2) { border-right: 0; }
  .availability__submit { grid-column: 1 / -1; padding-block: 1.25rem; text-align: center; }
}

@media (max-width: 900px) {
  /* The Launch stacks: photo full width, then the hours card, then the copy. */
  .launch__grid { grid-template-columns: 1fr; padding-right: 0; row-gap: 2.5rem; }
  .launch .hourscard { margin-right: var(--launch-side); }
  .launch__body { padding-inline: var(--launch-side); }
  .launch__logo { margin-top: 0; }
  /* Plan Your Visit and Our Story stack; their photos go full width. */
  .plan__panel { grid-template-columns: 1fr; row-gap: 2.5rem; margin-inline: calc(-1 * var(--side)); }
  .plan__info { padding-inline: var(--side); }
  .story__grid { grid-template-columns: 1fr; padding-right: 0; row-gap: 3.5rem; }
  .story__body { padding-inline: var(--side); }
  .story__badge { right: var(--side); }
  .roomcards { grid-template-columns: 1fr; }
  .featurestrip__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .split__media, .split__body { grid-column: 1 / -1 !important; grid-row: auto; }

  .room { grid-template-columns: 1fr; }
  .room:nth-child(even) .room__media { order: 0; }

  .gallery__item--wide { grid-column: span 1; }
  .gallery__item--wide img { aspect-ratio: 3 / 2; }

  .bookbar__text { display: none; }
  .bookbar__inner { justify-content: center; }
}

@media (max-width: 680px) {
  .sechead { grid-template-columns: 1fr; align-items: start; gap: 0.75rem; }
  .sechead__meta { padding-bottom: 0; }
  .footer__grid { grid-template-columns: 1fr; }
  /* The lockup would squeeze the heading to one word per line. */
  .launch__head { flex-direction: column; gap: 1.25rem; }
  .launch__logo { order: -1; width: 180px; }
  .masthead__book { padding: 0.6rem 1rem; }
  /* The comp tracking wraps the closure notice to four lines on a phone. */
  .notice { letter-spacing: 0.08em; padding-block: 0.45rem; }
  .post-row { grid-template-columns: 1fr; gap: 0.5rem; }
  .speclist { grid-template-columns: 1fr; }
  .speclist li { grid-template-columns: 1fr; gap: 0.25rem; }
}

/* --------------------------------------------------------------------------
   23. Print
   -------------------------------------------------------------------------- */

@media print {
  .masthead, .footer, .availability, .notice, .bookbar { display: none; }
  body { background: #fff; color: #000; }
}
