/* ============================================================================
   GOOD SHEPHERD BOARDING — Lumberton, TX
   Deliberately small and quiet: one typeface pairing, one accent, lots of air.
   The brief was "nice and clean and simple", and the business has no facility
   photography yet, so the design has to hold up on type, colour and space alone.

   PALETTE is sampled from their actual logo file, not guessed:
     #304020  the deep olive-green ink of the dog and the wordmark
     #f6f0ec  the warm cream the logo badge sits on
   plus the two sage tones already set on their Book'n Buddy branding record
   (#e0edd4 primary, #cce8b5 secondary).

   CONTRAST NOTE: both sage tones are far too light to carry text — #e0edd4 on
   white is about 1.2:1. They are washes and accents only. Readable text uses
   --ink (#304020, ~10:1 on cream) or --moss (#4a6033, ~6:1). Do not "brighten"
   body text to the sage; it fails WCAG AA and disappears outdoors on a phone.
   ========================================================================= */

@import url('https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,600;9..144,700&family=Karla:wght@400;500;600;700&family=Dancing+Script:wght@600;700&display=swap');

:root {
  --ink:    #304020;   /* logo green */
  --ink-90: #3b4f29;
  --moss:   #4a6033;   /* accessible mid-green for links/eyebrows */
  --sage:   #e0edd4;   /* their branding primaryColor */
  --sage-2: #cce8b5;   /* their branding secondaryColor */
  --sage-50:#f2f8ec;
  --cream:  #f6f0ec;   /* logo background */
  --cream-2:#fbf8f5;
  --paper:  #ffffff;
  --body:   #4f5a45;
  --muted:  #7b8473;
  --line:   #e4e0d8;
  /* The client's mockup sets "Feels at Home" in a bright gold script, but that
     was over a DARK photo. On this cream hero a bright gold would be ~2:1 and
     unreadable, so it is deepened to hold >=4.5:1 while reading as the same
     gold. Do not lighten it back to the mockup's value on a light background. */
  --gold:   #8a6d15;

  --display: 'Fraunces', Georgia, serif;
  --sans:    'Karla', system-ui, sans-serif;

  --r:    16px;
  --r-lg: 26px;
  --shadow-sm: 0 1px 2px rgba(48,64,32,.05), 0 2px 10px rgba(48,64,32,.04);
  --shadow:    0 6px 18px rgba(48,64,32,.08), 0 18px 42px rgba(48,64,32,.07);
  --ease: cubic-bezier(.22,.61,.36,1);
  --wrap: 1080px;
}

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* The closed mobile drawer is `position: fixed` and parked off-screen right.
   `overflow-x: hidden` on BODY cannot clip it — a fixed element's containing
   block is the viewport, not the body — so at 390px the page scrolled sideways
   to 702px. Measured, then fixed here.
   `clip` rather than `hidden` on the root deliberately: `hidden` would turn
   <html> into a scroll container and can break the sticky header, whereas
   `clip` clips without creating one. (`visibility: hidden` on the drawer was
   tested and does NOT remove the overflow.) */
html { overflow-x: clip; }
body {
  font-family: var(--sans); color: var(--body); background: var(--cream-2);
  line-height: 1.75; font-size: 17px; -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}
/* `height: auto` is NOT optional here. Every <img> carries width/height
   attributes (good — they reserve space and stop layout shift), but without
   this the attribute height is used literally: the yard photo rendered
   1080x980 instead of its declared 16:9, because `aspect-ratio` cannot win
   against a used height. Measured, not guessed. */
img, svg, iframe { display: block; max-width: 100%; }
img { height: auto; }
a { color: var(--moss); text-underline-offset: 3px; }
a:hover { color: var(--ink); }

h1, h2, h3 { font-family: var(--display); color: var(--ink); line-height: 1.12; font-weight: 600; letter-spacing: -.015em; }
h1 { font-size: clamp(2.3rem, 5.5vw, 3.9rem); font-weight: 700; }
h2 { font-size: clamp(1.75rem, 3.4vw, 2.6rem); }
h3 { font-size: clamp(1.1rem, 1.7vw, 1.3rem); font-weight: 600; }
p { text-wrap: pretty; }

.wrap { width: min(100% - 2.5rem, var(--wrap)); margin-inline: auto; }
.narrow { width: min(100% - 2.5rem, 760px); margin-inline: auto; }
section { padding: clamp(3.25rem, 7vw, 6rem) 0; }
.bg-cream { background: var(--cream); }
.bg-sage  { background: linear-gradient(168deg, var(--sage), var(--sage-50)); }
.bg-ink   { background: var(--ink); color: #dfe6d6; }
.bg-ink h2, .bg-ink h3 { color: #fff; }

.eyebrow {
  font-family: var(--sans); font-weight: 700; font-size: .76rem; letter-spacing: .18em;
  text-transform: uppercase; color: var(--moss); display: inline-flex; align-items: center;
  gap: .55rem; margin-bottom: .85rem;
}
.eyebrow::before { content: ''; width: 24px; height: 2px; background: var(--sage-2); border-radius: 2px; }
.bg-ink .eyebrow { color: var(--sage-2); }
.sec-head { max-width: 640px; margin-bottom: clamp(2rem, 4vw, 3rem); }
.sec-head p { color: var(--muted); margin-top: .85rem; font-size: 1.04rem; }
.bg-ink .sec-head p { color: #a9b49c; }
.center { text-align: center; margin-inline: auto; }

/* ── buttons ─────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  font-family: var(--sans); font-weight: 700; font-size: .98rem;
  padding: .9rem 1.75rem; border-radius: 999px; border: 2px solid transparent;
  text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: transform .22s var(--ease), box-shadow .22s var(--ease), background .18s, color .18s, border-color .18s;
}
.btn:hover { transform: translateY(-2px); }
.btn:focus-visible { outline: 3px solid var(--moss); outline-offset: 3px; }
.btn-primary { background: var(--ink); color: #fff; box-shadow: var(--shadow-sm); }
.btn-primary:hover { background: #26331a; color: #fff; box-shadow: var(--shadow); }
.btn-ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn-ghost:hover { border-color: var(--ink); color: var(--ink); }
.bg-ink .btn-ghost { color: #fff; border-color: rgba(255,255,255,.28); }
.bg-ink .btn-ghost:hover { border-color: #fff; background: rgba(255,255,255,.08); }
.btn-lg { padding: 1.05rem 2.1rem; font-size: 1.03rem; }
.btn-row { display: flex; flex-wrap: wrap; gap: .75rem; }

/* ── header ──────────────────────────────────────────────────────────────── */
.topbar { background: var(--ink); color: #cfd8c3; font-size: .82rem; padding: .5rem 0; }
.topbar .wrap { display: flex; gap: 1.5rem; justify-content: center; align-items: center; flex-wrap: wrap; }
.topbar a { color: #e6ecdd; text-decoration: none; display: inline-flex; align-items: center; gap: .4rem; }
.topbar a:hover { color: var(--sage-2); }
.topbar svg { width: 14px; height: 14px; flex: none; }

/* The frosted background lives on a ::before layer, NOT on .site-header itself.
   `backdrop-filter` (like `filter` and `transform`) makes an element a
   CONTAINING BLOCK for its `position: fixed` descendants. The mobile drawer is
   a fixed child of this header, so with the filter on the header the drawer was
   positioned against the header's box instead of the viewport — it came out
   header-height tall with the links cut off. Moving the filter to a pseudo
   element keeps the effect and gives the drawer the viewport back.
   Do not move `backdrop-filter` back onto .site-header. */
.site-header {
  position: sticky; top: 0; z-index: 90; background: transparent;
  border-bottom: 1px solid transparent; transition: border-color .25s, box-shadow .25s;
}
.site-header::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: rgba(251,248,245,.92);
  backdrop-filter: blur(12px) saturate(1.3);
}
.site-header.scrolled { border-bottom-color: var(--line); box-shadow: 0 2px 18px rgba(48,64,32,.05); }
.nav { display: flex; align-items: center; gap: 1.25rem; padding: .35rem 0; }
/* The header carries the owner's actual logo — the full circular lockup, not a
   crop. It already contains "Good Shepherd BOARDING" and the tagline, so there
   is deliberately NO text wordmark beside it; that would set the same words
   twice. It needs real height to stay legible (the script and the tagline are
   fine detail), hence 76px and tighter nav padding to keep the bar sensible. */
.brand { display: flex; align-items: center; text-decoration: none; flex: none; }
.brand img { height: 76px; width: auto; transition: height .28s var(--ease); }
/* The header is sticky, so a 76px logo would occupy ~115px of every screen for
   the whole visit. Full size on arrival for brand presence, then it shrinks once
   the reader starts scrolling and the bar gets out of the way. */
.site-header.scrolled .brand img { height: 52px; }
.nav-links { display: flex; align-items: center; gap: .3rem; margin-left: auto; }
.nav-cta { margin-left: .5rem; flex: none; }
.nav-links a {
  font-weight: 600; font-size: .95rem; color: var(--ink-90); text-decoration: none;
  padding: .5rem .8rem; border-radius: 999px; transition: background .18s, color .18s;
}
.nav-links a:hover { background: var(--sage); color: var(--ink); }
/* `.nav-links a` (0,1,1) beats `.btn-primary` (0,1,0) — without this the header
   CTA renders dark-on-dark. Same trap caught on the Urban Dogs build. */
.nav-links a.btn-primary, .nav-links a.btn-primary:hover { color: #fff; }

/* ── mobile: a scrolling TAB STRIP, not an off-canvas drawer ──────────────
   The drawer was replaced deliberately. Being `position: fixed` and parked
   off-screen it caused two separate bugs — 702px of horizontal scroll on a
   375px phone, and a broken panel whenever an ancestor gained a containing
   block. A tab strip sits in normal flow and can do neither.
   The Book Now CTA is a SIBLING of .nav-links, not inside it, so it stays put
   on the top row while the tabs scroll underneath. */
@media (max-width: 860px) {
  .nav { flex-wrap: wrap; gap: .4rem .8rem; padding: .3rem 0 0; }
  .brand { margin-right: auto; }
  .nav-cta { order: 2; margin: 0; padding: .7rem 1.3rem; font-size: .92rem; }
  .nav-links {
    order: 3; width: 100%; margin: 0; gap: 0;
    overflow-x: auto; overscroll-behavior-x: contain;
    scrollbar-width: none; -ms-overflow-style: none;
    border-top: 1px solid var(--line);
    /* hints that there is more to the right without adding chrome */
    -webkit-mask-image: linear-gradient(to right, #000 86%, transparent);
            mask-image: linear-gradient(to right, #000 86%, transparent);
  }
  .nav-links::-webkit-scrollbar { display: none; }
  .nav-links a {
    white-space: nowrap; padding: .7rem .7rem; font-size: .88rem;
    border-radius: 0; border-bottom: 2px solid transparent;
  }
  .nav-links a:hover, .nav-links a:focus-visible { background: transparent; border-bottom-color: var(--sage-2); }
  .brand img { height: 56px; }
  .site-header.scrolled .brand img { height: 44px; }
}

/* ── hero ────────────────────────────────────────────────────────────────── */
/* padding:0 is load-bearing — .hero is a <section>, so without it the generic
   section padding stacks on top of .hero-inner's own and leaves a dead band. */
.hero { background: var(--cream); position: relative; overflow: hidden; padding: 0; }
.hero::after {
  content: ''; position: absolute; inset: auto -15% -45% 50%; height: 75%;
  background: radial-gradient(closest-side, var(--sage), transparent 72%);
  opacity: .7; pointer-events: none;
}
/* Two-column hero. The lobby photograph already carries the wordmark and the
   tagline on the greenery wall, so the hero deliberately does NOT repeat the
   logo lockup — that would set the same words twice, six inches apart. */
.hero-inner {
  padding: clamp(2.5rem, 5.5vw, 4.5rem) 0 clamp(2.75rem, 6vw, 5rem);
  position: relative; z-index: 1;
  display: grid; grid-template-columns: 1.02fr .98fr;
  gap: clamp(2rem, 5vw, 4rem); align-items: center;
}
/* Client's own hero copy: a two-line headline where the second line is a gold
   script, then a bold promise line, then the paragraph. */
.hero h1 .script {
  display: block; font-family: 'Dancing Script', cursive; font-weight: 700;
  color: var(--gold); font-size: 1.18em; line-height: 1; letter-spacing: 0;
  margin-top: .06em;
}
.hero-sub {
  font-family: var(--display); font-weight: 600; color: var(--ink);
  font-size: clamp(1.12rem, 1.9vw, 1.45rem); line-height: 1.32; margin-top: 1.25rem;
}
.hero p.lede { font-size: clamp(1.02rem, 1.5vw, 1.14rem); color: var(--body); max-width: 50ch; margin: 1rem 0 2rem; }
.hero-photo { position: relative; }
.hero-photo img {
  touch-action: manipulation;
  width: 100%; border-radius: var(--r-lg); box-shadow: var(--shadow);
  /* the source is a 672px-wide phone photo — never scale it past its own
     resolution or the greenery goes soft */
  max-width: 520px; margin-inline: auto;
}
@media (max-width: 900px) {
  .hero-inner { grid-template-columns: 1fr; text-align: center; }
  .hero p.lede { margin-inline: auto; }
  .hero .btn-row { justify-content: center; }
  .hero-photo { order: -1; }
  .hero-photo img {
  touch-action: manipulation; max-width: 420px; }
}

/* ── owner's note ────────────────────────────────────────────────────────── */
.note-grid { display: grid; grid-template-columns: .82fr 1.18fr; gap: clamp(2rem, 4.5vw, 3.5rem); align-items: center; }
@media (max-width: 880px) { .note-grid { grid-template-columns: 1fr; } }
/* Height is capped rather than set by aspect-ratio: at this column width a 3/4
   box ran ~690px tall, far past the quote beside it, and the crop bottomed out
   on the subject's jeans. A fixed height keeps the crop on her and the dog. */
.note-photo img {
  width: 100%; height: clamp(340px, 44vw, 540px); object-fit: cover;
  object-position: center 44%; border-radius: var(--r-lg); box-shadow: var(--shadow);
}
/* Single-column phone layout: the fixed height above becomes a short LANDSCAPE
   band across the full width, which crops a portrait photo down to a strip and
   cuts the subject's head off. Drive it by ratio instead so it stays a portrait
   frame with her and the dog intact. */
@media (max-width: 880px) {
  .note-photo img { height: auto; aspect-ratio: 4/5; max-width: 420px; margin-inline: auto; }
}
blockquote.owner {
  margin: 0; font-family: var(--display); font-size: clamp(1.12rem, 1.75vw, 1.42rem);
  line-height: 1.6; color: var(--ink); font-weight: 400; position: relative; padding-top: 1.75rem;
}
blockquote.owner::before {
  content: '\201C'; position: absolute; top: -.65rem; left: -.1rem;
  font-family: var(--display); font-size: 4.5rem; line-height: 1; color: var(--sage-2);
}
blockquote.owner p + p { margin-top: .9rem; }
.owner-sign { margin-top: 1.5rem; font-family: var(--sans); font-weight: 700; color: var(--ink); font-size: .95rem; }
.owner-sign small { display: block; font-weight: 500; color: var(--muted); font-size: .84rem; letter-spacing: .04em; margin-top: .15rem; }

/* ── scripture ───────────────────────────────────────────────────────────── */
.verse {
  border-left: 3px solid var(--sage-2); padding: .3rem 0 .3rem 1.4rem; margin-top: 2rem;
}
.verse p { font-family: var(--display); font-size: 1.05rem; line-height: 1.6; color: var(--ink); }
.bg-ink .verse p { color: #eef3e8; }
.verse cite { display: block; margin-top: .6rem; font-family: var(--sans); font-style: normal; font-weight: 700; font-size: .78rem; letter-spacing: .14em; text-transform: uppercase; color: var(--moss); }
.bg-ink .verse cite { color: var(--sage-2); }

/* ── wide feature photo ──────────────────────────────────────────────────── */
.feature-photo { border-radius: var(--r-lg); overflow: hidden; box-shadow: var(--shadow); }
.feature-photo img { width: 100%; height: auto; aspect-ratio: 16/9; object-fit: cover; }
/* 16:9 across a phone is a ~200px letterbox strip — the dog ends up a smudge.
   Squarer ratios give the yard room to read on a small screen. */
@media (max-width: 720px) { .feature-photo img { aspect-ratio: 4/3; } }
@media (max-width: 480px) { .feature-photo img { aspect-ratio: 1/1; } }

/* ── trust strip ─────────────────────────────────────────────────────────── */
.trust { background: var(--paper); border-block: 1px solid var(--line); padding: 1.4rem 0; }
.trust .wrap { display: flex; flex-wrap: wrap; gap: .9rem 2.4rem; justify-content: center; align-items: center; }
.trust-item { display: flex; align-items: center; gap: .55rem; font-size: .92rem; font-weight: 600; color: var(--ink-90); }
.trust-item svg { width: 18px; height: 18px; color: var(--moss); flex: none; }

/* ── grids / cards ───────────────────────────────────────────────────────── */
.grid { display: grid; gap: 1.35rem; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(265px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); }

.card {
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 1.7rem 1.75rem; display: flex; flex-direction: column;
  transition: transform .3s var(--ease), box-shadow .3s var(--ease), border-color .3s;
}
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow); border-color: var(--sage-2); }
.card .ico {
  width: 48px; height: 48px; border-radius: 14px; background: var(--sage);
  color: var(--ink); display: grid; place-items: center; margin-bottom: 1.1rem; flex: none;
}
.card .ico svg { width: 24px; height: 24px; }
.card p { color: var(--muted); font-size: .96rem; margin: .5rem 0 0; }
.card .price {
  font-family: var(--display); font-weight: 700; font-size: 1.85rem; color: var(--ink);
  margin-top: 1rem; letter-spacing: -.02em; line-height: 1;
}
.card .price small { font-family: var(--sans); font-size: .8rem; font-weight: 600; color: var(--muted); letter-spacing: 0; }

/* ── price rows ──────────────────────────────────────────────────────────── */
.rows { background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg); padding: .5rem 1.6rem; }
.row {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
  padding: 1rem .1rem; border-bottom: 1px dashed var(--line);
}
.row:last-child { border-bottom: 0; }
.row .n { font-weight: 600; color: var(--ink); }
.row .n small { display: block; font-weight: 400; font-size: .85rem; color: var(--muted); }
.row .v { font-family: var(--display); font-weight: 700; color: var(--ink); white-space: nowrap; font-size: 1.1rem; }

/* ── ticks ───────────────────────────────────────────────────────────────── */
.ticks { list-style: none; padding: 0; display: grid; gap: .75rem; }
.ticks li { display: flex; gap: .7rem; align-items: flex-start; }
.ticks svg { width: 20px; height: 20px; flex: none; color: var(--moss); margin-top: .25rem; }
.bg-ink .ticks svg { color: var(--sage-2); }

/* ── note ────────────────────────────────────────────────────────────────── */
.note {
  background: var(--sage-50); border: 1px solid var(--sage); border-radius: var(--r);
  padding: 1.15rem 1.4rem; display: flex; gap: .85rem; align-items: flex-start;
}
.note svg { width: 20px; height: 20px; color: var(--moss); flex: none; margin-top: .25rem; }
.note p { font-size: .95rem; color: var(--ink-90); }
.note strong { color: var(--ink); }

/* ── booking embed ───────────────────────────────────────────────────────── */
.booking-shell { background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden; box-shadow: var(--shadow); }
.booking-shell iframe { width: 100%; border: 0; min-height: 820px; }
.booking-fallback { display: none; text-align: center; padding: 2.4rem 1.5rem; }
@media (max-width: 768px) {
  .booking-shell iframe { display: none; }
  .booking-fallback { display: block; }
}

/* ── contact ─────────────────────────────────────────────────────────────── */
.contact-grid { display: grid; grid-template-columns: 1fr 1.1fr; gap: 2.25rem; align-items: start; }
@media (max-width: 860px) { .contact-grid { grid-template-columns: 1fr; } }
.contact-item { display: flex; gap: .9rem; align-items: flex-start; padding: 1rem 0; border-bottom: 1px solid var(--line); }
.contact-item:last-of-type { border-bottom: 0; }
.contact-item .ico { width: 42px; height: 42px; border-radius: 12px; background: var(--sage); color: var(--ink); display: grid; place-items: center; flex: none; }
.contact-item .ico svg { width: 20px; height: 20px; }
.contact-item h3 { font-size: 1rem; margin-bottom: .05rem; }
.contact-item a, .contact-item span { color: var(--muted); font-size: .96rem; text-decoration: none; }
.contact-item a:hover { color: var(--moss); }
.map-frame { border-radius: var(--r-lg); overflow: hidden; border: 1px solid var(--line); box-shadow: var(--shadow-sm); }
.map-frame iframe { width: 100%; height: 400px; border: 0; }

/* ── footer ──────────────────────────────────────────────────────────────── */
.site-footer { background: var(--ink); color: #a9b49c; padding: clamp(2.75rem,5vw,4rem) 0 0; font-size: .93rem; }
.footer-grid { display: grid; grid-template-columns: 1.5fr 1fr 1fr; gap: 2.25rem; padding-bottom: 2.5rem; }
@media (max-width: 760px) { .footer-grid { grid-template-columns: 1fr; gap: 1.75rem; } }
.site-footer h4 { color: #fff; font-family: var(--sans); font-size: .78rem; letter-spacing: .16em; text-transform: uppercase; margin-bottom: .9rem; }
.site-footer a { color: #c6cfba; text-decoration: none; }
.site-footer a:hover { color: var(--sage-2); }
.footer-links { list-style: none; padding: 0; display: grid; gap: .5rem; }
/* The footer uses logo-badge.png, NOT logo-full.png. The transparency
   knock-out on logo-full removed the badge's cream disc as well as the outer
   background, so its dark-green artwork was invisible against the dark green
   footer. logo-badge keeps an OPAQUE cream disc for exactly this case. */
.footer-mark { margin-bottom: 1rem; }
.footer-mark img { width: 108px; height: auto; }
.colophon {
  border-top: 1px solid rgba(255,255,255,.1); padding: 1.3rem 0; font-size: .84rem;
  display: flex; flex-wrap: wrap; gap: .7rem 1.4rem; align-items: center; justify-content: space-between;
}
.powered { display: inline-flex; align-items: center; gap: .5rem; }
.powered img { height: 26px; width: auto; }

/* ── page head (book page) ───────────────────────────────────────────────── */
.page-head { background: linear-gradient(168deg, var(--sage), var(--sage-50)); padding: clamp(2.5rem,5vw,4rem) 0 clamp(2.25rem,4vw,3.25rem); text-align: center; }
.page-head p { color: var(--ink-90); max-width: 58ch; margin: .9rem auto 0; font-size: 1.05rem; }

/* ── reveal ──────────────────────────────────────────────────────────────── */
.reveal { opacity: 0; transform: translateY(20px); transition: opacity .65s var(--ease), transform .65s var(--ease); }
.reveal.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .reveal { opacity: 1; transform: none; } }

.skip {
  position: absolute; left: 50%; transform: translate(-50%,-120%); top: .5rem; z-index: 200;
  background: var(--ink); color: #fff; padding: .65rem 1.15rem; border-radius: 999px;
  text-decoration: none; font-weight: 700; transition: transform .2s;
}
.skip:focus { transform: translate(-50%,0); color: #fff; }

/* ── gallery ─────────────────────────────────────────────────────────────── */
.gallery-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: .9rem; }
@media (max-width: 520px) { .gallery-grid { grid-template-columns: 1fr 1fr; gap: .6rem; } }
.gallery-grid button {
  padding: 0; border: 0; background: var(--sage-50); cursor: zoom-in; overflow: hidden;
  border-radius: var(--r); aspect-ratio: 1; box-shadow: var(--shadow-sm);
}
.gallery-grid img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s var(--ease); }
.gallery-grid button:hover img { transform: scale(1.05); }
.gallery-grid button:focus-visible { outline: 3px solid var(--moss); outline-offset: 3px; }
.gallery-empty { color: var(--muted); font-size: .95rem; }

/* lightbox */
.lb { position: fixed; inset: 0; z-index: 200; background: rgba(24,32,18,.92);
      display: grid; place-items: center; padding: 4vmin; opacity: 0; pointer-events: none;
      transition: opacity .25s var(--ease); }
.lb.open { opacity: 1; pointer-events: auto; }
.lb img { max-width: 100%; max-height: 88vh; border-radius: var(--r); box-shadow: var(--shadow-lg); }
.lb-close, .lb-prev, .lb-next {
  position: absolute; background: rgba(255,255,255,.14); color: #fff; border: 0; cursor: pointer;
  width: 46px; height: 46px; border-radius: 50%; display: grid; place-items: center; font-size: 1.3rem;
}
.lb-close { top: 3vmin; right: 3vmin; }
.lb-prev { left: 3vmin; top: 50%; transform: translateY(-50%); }
.lb-next { right: 3vmin; top: 50%; transform: translateY(-50%); }
.lb-close:hover, .lb-prev:hover, .lb-next:hover { background: rgba(255,255,255,.28); }

/* ── hidden photo editor (5 taps on the hero photo) ──────────────────────── */
.ed {
  position: fixed; inset: auto 0 0 0; z-index: 210; background: var(--paper);
  border-top: 3px solid var(--ink); box-shadow: 0 -10px 40px rgba(16,22,27,.22);
  max-height: 82vh; max-height: 82dvh; overflow-y: auto;
  transform: translateY(102%); transition: transform .34s var(--ease);
  /* The last row of buttons sits at the very bottom of a bottom-sheet, which on
     a phone lands under the home indicator / browser chrome. Pad by the safe
     area so "Download gallery.js" is always reachable. Same trap this repo hit
     with modal close buttons under the status bar. */
  padding: 1.1rem 1.2rem calc(1.4rem + env(safe-area-inset-bottom, 0px));
  -webkit-overflow-scrolling: touch;
}
.ed.open { transform: none; }
.ed h3 { font-size: 1.05rem; margin-bottom: .2rem; }
.ed .hint { font-size: .85rem; color: var(--muted); line-height: 1.6; }
.ed-head { display: flex; align-items: flex-start; gap: 1rem; margin-bottom: .9rem; }
.ed-head div { flex: 1; }
.ed-x { background: none; border: 0; font-size: 1.5rem; line-height: 1; cursor: pointer; color: var(--muted); padding: .2rem .4rem; }
.ed-drop {
  display: block; border: 2px dashed var(--sage-2); border-radius: var(--r);
  padding: 1.4rem 1.2rem; text-align: center; background: var(--sage-50);
  cursor: pointer; transition: border-color .2s, background .2s;
  -webkit-tap-highlight-color: rgba(48,64,32,.12); touch-action: manipulation;
}
.ed-drop:active { background: #e9f4de; }
/* visually hidden but STILL LAID OUT — a display:none file input will not open
   the picker on iOS. */
.vh { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden;
      clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
.ed-drop.over { border-color: var(--moss); background: #e9f4de; }
.ed-drop strong { color: var(--ink); display: block; font-size: .95rem; }
.ed-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: .6rem; margin: 1rem 0; }
.ed-item { position: relative; border-radius: 10px; overflow: hidden; aspect-ratio: 1; background: var(--sage-50); }
.ed-item img { width: 100%; height: 100%; object-fit: cover; }
.ed-item button {
  position: absolute; top: 4px; right: 4px; width: 26px; height: 26px; border-radius: 50%;
  border: 0; background: rgba(16,22,27,.7); color: #fff; cursor: pointer; font-size: .9rem; line-height: 1;
}
.ed-item .mv { position: absolute; bottom: 4px; left: 4px; display: flex; gap: 3px; }
.ed-item .mv button { position: static; width: 24px; height: 24px; font-size: .8rem; }
.ed-bar { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; padding-top: .2rem; }
.ed-bar .btn { flex: 1 1 auto; min-width: 150px; }
.ed-size { font-size: .84rem; font-weight: 700; }
.ed-size.warn { color: #a8541c; }
.ed-size.bad { color: #a33; }
