/* Animate in-page anchor jumps (e.g. the hero's "Start Here" button and
   down-arrow) instead of snapping straight there. Site-wide, not
   hero-specific — this is what makes any #anchor link scroll smoothly. */
html {
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

/* Hero — homepage only (see overrides/home.html)

   A full-viewport-height section with three image layers (background,
   foreground grass, and the bird standing in it), a scrim for text
   legibility, and a scroll-down link. The layers' scroll-linked
   parallax transform is applied by JS in overrides/home.html; this file
   just sizes/positions them and leaves room (via the oversized
   `height`/`inset` below) for that transform to move them without
   exposing an edge. */

.hero-page .md-content__inner {
  margin: 0;
  padding: 0;
}

.hero-page .md-content__inner::before {
  display: none;
}

.hero {
  position: relative;
  /* mkdocs-material's sticky header is also z-index: 4, same as
     .hero__inner/.hero__more below — and .hero itself had no z-index of
     its own to contain them, so those children were being compared
     directly against the header in the SAME stacking context. Tied
     z-index falls back to DOM order, and .hero comes after the header,
     so its text/button won the tie and scrolled on top of the header
     bar instead of underneath it. Giving .hero its own (lower) z-index
     makes it a self-contained stacking context: everything inside it
     stacks internally as before, but the whole thing now competes
     against the header as one unit — at a value below the header's, so
     it can never paint over it again regardless of DOM order. */
  z-index: 0;
  left: 50%;
  width: 100vw;
  /* Pull up behind the sticky header so the hero fills the whole first
     screen, not just the space below the header. This default matches
     the header+tabs height on wide screens; overrides/home.html measures
     the real height on load/resize and corrects it precisely, since it
     varies (the tabs row only shows on wide screens; the previous
     hardcoded value drifted out of sync and left the hero short at the
     bottom). */
  margin: -96px 0 1.5rem -50vw;
  /* 100vh is sized to the LARGEST possible viewport (address bar
     collapsed) on mobile browsers, but on initial load the address bar
     is usually still showing, so the real visible area is shorter than
     100vh — the hero falls short of the screen and the next section's
     background shows through before any scrolling happens. 100dvh
     tracks the actual visible viewport as the address bar shows/hides,
     so it stays full-screen either way. Falls back to 100vh on browsers
     that don't support dvh. */
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  color: #fff;
  background: #0b3d3f;
}

/* Specificity note: mkdocs-material's `.md-typeset img { height: auto;
   max-width: 100% }` outranks a plain `.hero__image`/`.hero__grass`/
   `.hero__bird` (class+type beats a single class), so these need the
   extra `.hero` ancestor to win. */
.hero .hero__image {
  position: absolute;
  /* Sized a bit taller than the box itself (and shifted up to stay
     centred at rest) so the parallax scroll in overrides/home.html has
     room to shift it without ever exposing an edge. */
  inset: -8% 0 auto;
  z-index: 0;
  width: 100%;
  height: 116%;
  max-width: none;
  object-fit: cover;
  object-position: center 30%;
  will-change: transform;
}

/* The grass source image is portrait (taller than wide) with the actual
   grass confined to roughly its bottom third — the rest is transparent.
   Sized to the full hero box like the background, object-fit: cover
   would scale it up until its WIDTH clears the (much wider) box, which
   for a portrait image leaves it far taller than the box and shows most
   of its height once cropped — swallowing the scene instead of reading
   as a foreground strip. Confining the box itself to a shorter band
   along the bottom keeps the crop to roughly the grassy portion. */
.hero .hero__grass {
  position: absolute;
  inset: auto 0 -8%;
  z-index: 1;
  width: 100%;
  height: 26%;
  max-width: none;
  object-fit: cover;
  object-position: center 100%;
  will-change: transform;
  /* Soften the crop's top edge into the scene behind it instead of a
     hard horizontal seam. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 30%);
  mask-image: linear-gradient(to bottom, transparent 0%, black 30%);
}

/* A single small subject standing in the grass, not a full-bleed layer —
   sized to its own natural shape (object-fit: contain) and anchored to
   a fixed spot rather than stretched to cover the box. Moves with the
   grass (same scroll speed) since it's standing on that same ground. */
.hero .hero__bird {
  position: absolute;
  inset: auto 5% 10% auto;
  z-index: 2;
  width: auto;
  height: 34%;
  max-width: none;
  object-fit: contain;
  object-position: bottom right;
  will-change: transform;
}

/* Explicit z-index on every layer from here up: without it, the scrim
   (and the text/button content after it) would default to z-index:auto,
   which paints at the SAME level as the z-index:0 background — behind
   any layer above that has its own explicit z-index (grass, bird) —
   leaving them undarkened and the scrim doing nothing for them. */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 3;
  background:
    linear-gradient(0deg, rgba(6, 26, 27, 0.55) 0%, rgba(6, 26, 27, 0) 55%),
    linear-gradient(90deg, rgba(6, 26, 27, 0.45) 0%, rgba(6, 26, 27, 0) 60%);
  pointer-events: none;
}

.hero__inner {
  position: relative;
  z-index: 4;
  height: 100%;
  display: flex;
  align-items: flex-end;
  padding-bottom: 4rem;
}

.hero__teaser {
  max-width: 28rem;
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.45);
}

.hero__teaser h1 {
  margin: 0 0 0.5rem;
  color: #fff;
  font-size: 2.4rem;
  font-weight: 700;
  line-height: 1.15;
}

.hero__teaser p {
  margin: 0 0 1.25rem;
  font-size: 1.05rem;
  opacity: 0.92;
}

.hero__teaser .md-button {
  margin: 0 0.5rem 0.5rem 0;
  border-color: #fff;
  color: #fff;
}

.hero__teaser .md-button--primary {
  background-color: #f4c76b;
  border-color: #f4c76b;
  color: #0b3d3f;
}

.hero__teaser .md-button--primary:hover {
  background-color: #eab649;
  border-color: #eab649;
}

.hero__teaser .md-button:not(.md-button--primary):hover {
  background-color: rgba(255, 255, 255, 0.12);
}

.hero__more {
  position: absolute;
  z-index: 4;
  bottom: 1.25rem;
  left: 50%;
  width: 2.5rem;
  height: 2.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  opacity: 0.8;
  transform: translateX(-50%);
  animation: hero-bounce 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}

.hero__more:hover {
  opacity: 1;
}

.hero__more svg {
  width: 1.6rem;
  height: 1.6rem;
  fill: currentcolor;
}

@keyframes hero-bounce {
  0%, 100% { transform: translate(-50%, 0); }
  50% { transform: translate(-50%, 6px); }
}

@media (prefers-reduced-motion: reduce) {
  .hero__more {
    animation: none;
  }
}

@media (max-width: 44.9375em) {
  .hero__teaser h1 {
    font-size: 1.8rem;
  }

  /* The teaser text runs full-width on narrow screens (rather than
     sharing the row with the bird, as it does on wider ones), so at
     its usual size and position the bird sits behind the wrapped text.
     Tuck it smaller into the corner, low enough to clear the button
     row and sit among the grass instead. */
  .hero .hero__bird {
    inset: auto 3% 1% auto;
    height: 15%;
  }
}

/* Photo grids — room pages and the Photo Gallery.

   Each photo is authored as a markdown image whose `src` is the full-size
   version (~1600px) — that's what glightbox reads for the lightbox `href`
   — with a `srcset`/`sizes` attribute pointing the grid tile at a small
   thumbnail (~480px) instead. That split is the whole point: the grid on
   the page stays light to load, and the full-size file is only fetched
   if a guest actually opens the lightbox. glightbox wraps each `<img>`
   in its own `<a class="glightbox">` at render time, so the selectors
   below reach through that wrapper rather than styling the `<img>`
   directly. */
.photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
  gap: 0.5rem;
  margin: 1rem 0 1.5rem;
}

/* The material theme's root font-size is larger than 16px, so 9.5rem
   eats the whole line on a phone-width screen and the grid collapses to
   a single column. Use a smaller basis below ~600px so phones still get
   at least two tiles per row. */
@media (max-width: 37.5em) {
  .photo-grid {
    grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr));
  }
}

/* Markdown wraps a standalone image in its own <p>; without this the
   default paragraph spacing would put a gap under every tile. */
.photo-grid p {
  margin: 0;
  line-height: 0;
}

.photo-grid a {
  display: block;
}

.photo-grid img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 0.375rem;
  cursor: zoom-in;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.photo-grid img:hover {
  transform: scale(1.03);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
}

/* Respect the "no motion" preference the same way the hero bounce does
   above — the zoom-on-hover is a nice-to-have, not load-bearing. */
@media (prefers-reduced-motion: reduce) {
  .photo-grid img {
    transition: none;
  }

  .photo-grid img:hover {
    transform: none;
  }
}

/* glightbox's own lightbox chrome (close/nav buttons, captions) is
   unthemed by default — this nudges it to sit on top of the site's
   dark teal rather than plain black, and keeps the caption readable in
   both palettes. */
.glightbox-clean .gslide-description {
  background: rgba(11, 61, 63, 0.92);
}

.glightbox-clean .gdesc-inner {
  color: #fff;
}
