/* ============================================================
   Hesed — design tokens
   Display: Newsreader (warm literary serif, carries the Name
   and scripture). Body: Public Sans (calm grotesque, utility).
   ============================================================ */

:root {
  --espresso: #2B211A;
  --parchment: #FFFFFF;
  --oat: #E4D8C3;
  --olive: #6E7A54;
  --gold: #B8863B;
  --stone: #8C8172;

  --font-display: "Newsreader", "Iowan Old Style", "Palatino Linotype", Georgia, serif;
  --font-body: "Public Sans", -apple-system, "Segoe UI", sans-serif;

  --space-1: 0.5rem;
  --space-2: 1rem;
  --space-3: 1.5rem;
  --space-4: 2.5rem;
  --space-5: 4rem;
  --space-6: 6rem;
  --space-7: 9rem;
  --space-8: 8rem;

  /* Sized to the wordmark: the logo is 11rem, plus 1rem padding top and
     bottom, so 14rem leaves ~1rem of breathing room and no more. The old
     13rem/8.5rem pairing left 2.5rem of dead space under the logo. */
  --nav-height-top: 14rem;
  --nav-height-scrolled: 4.5rem;
  --nav-gap-top: 1.5rem;
  --nav-gap-scrolled: 0rem;

  --radius: 3px;
  --motion-fast: 200ms;
  --motion-ease: cubic-bezier(0.4, 0, 0.2, 1);

  --focus-ring: 0 0 0 3px rgba(184, 134, 59, 0.45);
}

/* ---------- reset ---------- */

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

html {
  -webkit-text-size-adjust: 100%;
  color-scheme: light;
}

a,
button {
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgba(184, 134, 59, 0.18);
}

body {
  margin: 0;
  background: var(--parchment);
  color: var(--espresso);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* height:auto is load-bearing. Every img carries width/height attributes to
   reserve space and prevent layout shift; without this, max-width clamps the
   width while the height attribute holds, squashing the image. */
img {
  max-width: 100%;
  height: auto;
  display: block;
}

h1, h2, h3, p, figure {
  margin: 0;
}

a {
  color: var(--gold);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
}

a:hover {
  color: var(--olive);
}

a:focus-visible,
button:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius);
}

.skip-link {
  position: absolute;
  left: var(--space-2);
  top: 0;
  transform: translateY(calc(-100% - 4px));
  background: var(--espresso);
  color: var(--parchment);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius);
  z-index: 200;
  transition: transform var(--motion-fast) var(--motion-ease);
}

.skip-link:focus {
  transform: translateY(var(--space-2));
}

/* ============================================================
   Nav — "shutter up" behaviour
   ============================================================ */

/* Fixed, with a constant-height spacer (body::before) holding its slot in
   the layout — shrinking the bar must never change the document height,
   or the content jumps every time the shutter fires. */
.site-nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: var(--nav-height-top);
  padding: var(--space-2)
           max(var(--space-4), env(safe-area-inset-right))
           var(--space-2)
           max(var(--space-4), env(safe-area-inset-left));
  background: var(--parchment);
  border-bottom: 1px solid transparent;
  transition: min-height var(--motion-fast) var(--motion-ease),
              padding var(--motion-fast) var(--motion-ease),
              background var(--motion-fast) var(--motion-ease),
              border-color var(--motion-fast) var(--motion-ease);
}

body::before {
  content: "";
  display: block;
  height: var(--nav-height-top);
}

.site-nav.is-scrolled {
  min-height: var(--nav-height-scrolled);
  padding-top: var(--space-1);
  padding-bottom: var(--space-1);
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(6px);
  border-bottom-color: var(--oat);
}

.site-nav__side {
  flex: 1 1 0;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

.site-nav__side--right {
  justify-content: flex-end;
}

.site-nav__link {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.01em;
  color: var(--espresso);
  text-decoration: none;
  padding: var(--space-1) 0.25rem;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  border-bottom: 1px solid transparent;
  transition: color var(--motion-fast) var(--motion-ease),
              border-color var(--motion-fast) var(--motion-ease);
}

.site-nav__link:hover,
.site-nav__link:focus-visible {
  color: var(--gold);
  border-bottom-color: var(--gold);
}

.site-nav__logo {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  min-height: 44px;
}

.site-nav__logo img {
  height: 11rem;
  width: auto;
  mix-blend-mode: multiply;
  transition: height var(--motion-fast) var(--motion-ease);
}

.site-nav.is-scrolled .site-nav__logo img {
  height: 2.75rem;
}

.site-nav__slogan {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: 0.85rem;
  color: var(--stone);
  opacity: 0.7;
  white-space: nowrap;
  margin-left: var(--space-2);
  pointer-events: none;
  user-select: none;
}

/* Between 721px and 900px the bar is still fixed and cannot wrap, so the
   wordmark has to come down or it collides with the Menu link. */
@media (max-width: 900px) and (min-width: 721px) {
  :root {
    --nav-height-top: 11.5rem;
  }
  .site-nav__logo img {
    height: 8rem;
  }
}

@media (max-width: 720px) {
  :root {
    --nav-height-top: 11.5rem;
  }
  /* A fixed bar paired with a constant-height spacer cannot survive wrapping:
     once the links wrap to a second row the bar outgrows the spacer and covers
     the top of the page. In normal flow it simply takes the room it needs. */
  .site-nav {
    position: static;
    flex-wrap: wrap;
    padding-left: max(var(--space-2), env(safe-area-inset-left));
    padding-right: max(var(--space-2), env(safe-area-inset-right));
  }
  body::before {
    display: none;
  }
  .site-nav__logo img {
    height: 7.5rem;
  }
  .site-nav.is-scrolled .site-nav__logo img {
    height: 2.75rem;
  }
  .site-nav__slogan {
    display: none;
  }
  .site-nav__side {
    flex: 0 0 auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .site-nav,
  .site-nav__logo img {
    transition: none;
  }
}

/* ============================================================
   Shared layout
   ============================================================ */

.container {
  max-width: 72rem;
  margin: 0 auto;
  padding: 0 var(--space-4);
}

@media (max-width: 640px) {
  .container {
    padding: 0 var(--space-2);
  }
}

main {
  min-height: 60vh;
  scroll-margin-top: var(--nav-height-scrolled);
}

.site-footer {
  padding: var(--space-4) var(--space-4) var(--space-5);
  text-align: center;
  color: var(--stone);
  font-size: 0.875rem;
  border-top: 1px solid var(--oat);
  margin-top: var(--space-6);
}

/* ============================================================
   Landing page
   ============================================================ */

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

.hesed-meaning {
  padding: 0 var(--space-4) var(--space-5);
  text-align: center;
  font-family: var(--font-display);
  font-style: italic;
  color: var(--stone);
  font-size: 1.1rem;
}

.page-head {
  padding: var(--space-5) 0 0;
  text-align: center;
}

.page-head .eyebrow {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--olive);
}

/* h2 as well as h1: the landing page carries a copy of this block, and there
   the heading has to be an h2 — that page's h1 is "Hesed". */
.page-head h1,
.page-head h2 {
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 5vw, 3rem);
  margin-top: var(--space-1);
  text-wrap: balance;
}

.page-head__address {
  margin-top: var(--space-2);
  font-family: var(--font-display);
  font-size: 1.2rem;
  text-wrap: balance;
}

/* The copy on the landing page sits between two full sections rather than at
   the top of a page, so it needs its own space underneath and a rule above to
   separate it from the block before, matching how .ticker-section is divided
   off from what precedes it. */
.page-head--inline {
  padding: var(--space-5) 0;
  border-top: 1px solid var(--oat);
}

/* Heading and address sitting beside the map. The base .page-head is centred
   text; here the intro becomes the left column and reads left-aligned, so the
   address lines up under the heading rather than floating mid-column. */
.page-head--map {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-5);
  align-items: center;
  text-align: left;
}

.page-head--map .map-embed {
  margin: 0;
  max-width: none;
}

@media (max-width: 860px) {
  .page-head--map {
    grid-template-columns: 1fr;
    gap: var(--space-3);
    text-align: center;
  }
}

.story-split {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: var(--space-5);
  align-items: center;
  padding: var(--space-5) 0;
}

/* The landing page opens straight into a photo sitting under a nav that is
   already 14rem tall, so the standard 4rem section padding reads as a hole.
   Scoped to a leading .story-split, which only the landing page has — the
   other pages open with .page-head / .menu-page / .believe-layout and keep
   their normal spacing. */
.container > .story-split:first-child {
  padding-top: var(--space-2);
}

.story-split--flip {
  grid-template-columns: 0.9fr 1.1fr;
}

.story-split--flip .placeholder-photo--wide,
.story-split--flip .story-photo {
  order: 2;
}

/* Narrow-screen rules for the split live further down the file, after the
   pieces they override — see "Story split on narrow screens". */

.story-photo {
  margin: 0;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--oat);
  box-shadow: 0 14px 40px rgba(43, 33, 26, 0.14);
}

.story-photo img {
  display: block;
  width: 100%;
  height: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  object-position: center;
}

/* Landscape slot, matching .placeholder-photo--wide. Must follow
   .story-photo img — equal specificity, so source order decides. */
.story-photo--wide img {
  aspect-ratio: 16 / 10;
  object-position: center;
}

.placeholder-photo {
  aspect-ratio: 4 / 5;
  border-radius: var(--radius);
  background:
    repeating-linear-gradient(135deg, var(--oat), var(--oat) 10px, #ded1b8 10px, #ded1b8 20px);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--stone);
  font-size: 0.85rem;
  text-align: center;
  padding: var(--space-2);
}

.placeholder-photo span {
  background: rgba(255, 255, 255, 0.85);
  padding: 0.35em 0.7em;
  border-radius: var(--radius);
}

/* Must follow .placeholder-photo — equal specificity, so source order
   decides which aspect-ratio wins. */
.placeholder-photo--wide {
  aspect-ratio: 16 / 10;
}

.story-split__blurb {
  background: var(--oat);
  border-radius: var(--radius);
  padding: var(--space-4);
}

.story-split__blurb .eyebrow {
  display: inline-block;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--olive);
  margin-bottom: var(--space-2);
}

.story-split__blurb h2 {
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 600;
  margin-bottom: var(--space-2);
  text-wrap: balance;
}

.story-split__blurb p {
  color: var(--espresso);
  margin-bottom: var(--space-2);
}

.story-split__blurb p:last-child {
  margin-bottom: 0;
}

/* This week's special. Same panel as the rest of the page, with a gold edge
   so it reads as the one thing on the page that changes week to week. */
.story-split__blurb--special {
  border-left: 3px solid var(--gold);
}

/* The landing page dropped its "Come and see" placeholder, but where-we-are
   still uses this for the real address block. */
.location {
  padding: var(--space-5) 0 var(--space-6);
  text-align: center;
}

.location h2 {
  font-family: var(--font-display);
  font-size: 1.75rem;
  margin-bottom: var(--space-1);
  text-wrap: balance;
}

.location p {
  color: var(--stone);
}

/* ---------- scripture callout (welcome block) ---------- */

/* The scripture carries this block on its own — no heading above it — so it
   is set at display size and centred in the panel rather than run as body
   copy with an eyebrow stuck on top. */
.story-split__blurb--scripture {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  justify-content: center;
}

.scripture-callout {
  margin: var(--space-2) 0 0;
}

.scripture-callout p {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 2.6vw, 1.9rem);
  line-height: 1.35;
  font-weight: 500;
  font-style: italic;
  text-wrap: pretty;
  margin-bottom: 0;
}

.scripture-callout__ref {
  display: inline-block;
  margin-top: var(--space-2);
  font-family: var(--font-body);
  font-style: normal;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--olive);
}

/* ---------- Bible study times ---------- */

.study-times__title {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 600;
  margin-top: var(--space-3);
}

/* Rows are dt/dd pairs wrapped in a div so each day keeps its time on one
   line; a bare dl would let them wrap apart from one another. */
.study-times {
  margin: var(--space-2) 0 0;
  border-top: 1px solid rgba(43, 33, 26, 0.18);
}

.study-times__row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 0.4rem;
  padding: 0.4rem 0;
  border-bottom: 1px solid rgba(43, 33, 26, 0.18);
}

.study-times__row dt {
  font-weight: 600;
}

.study-times__row dd {
  margin: 0;
  margin-left: auto;
  font-variant-numeric: tabular-nums;
}

.study-times__note {
  margin-top: var(--space-2);
  font-family: var(--font-display);
  font-style: italic;
  color: rgba(43, 33, 26, 0.72);
  text-wrap: pretty;
}

/* ============================================================
   Story split on narrow screens

   The photo/text split stays side by side all the way down to the narrowest
   phone rather than stacking — the alternating left/right rhythm is the shape
   of the page, and collapsing it turned the whole thing into one long column.
   The `order` swap on --flip is deliberately left alone, so the photo keeps
   changing sides down the page.

   These blocks must stay AFTER the component rules above. They override
   .story-split__blurb h2, .scripture-callout p and .story-photo img at equal
   specificity, so source order is the only thing deciding the winner — put
   them back up with the .story-split layout and the desktop sizes silently win.
   ============================================================ */

@media (max-width: 860px) {
  /* minmax(0, 1fr), not 1fr: a bare 1fr floors at the column's min-content
     width, and on a 320px screen the text panel's longest word is wider than
     half the row — which crushed the photo column to 85px while the text kept
     172px. minmax(0, …) lets both columns actually reach an even split. */
  .story-split,
  .story-split--flip {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--space-3);
    padding: var(--space-4) 0;
    /* stretch, not centre: in a narrow column the text panel runs up to three
       times the photo's natural height, which left a small picture floating in
       the middle of a tall empty column. Stretching the frame to the row and
       letting object-fit crop keeps the two columns level. */
    align-items: stretch;
  }
  /* The frame is now as tall as the row, so the image fills it. Both width and
     height are definite here, which is what makes the aspect-ratio below give
     way rather than fight it.

     Anchored to the top, not the centre: beside a long text panel the crop gets
     tall and narrow, and a centred crop of a standing person takes the torso
     and loses the head. Top-anchoring keeps faces in every one of these shots. */
  .story-photo img {
    height: 100%;
    object-position: center top;
  }
  .story-split__blurb {
    padding: var(--space-3);
  }
  .story-split__blurb h2 {
    font-size: 1.45rem;
  }
}

/* Phone widths: each column is only ~8-9rem, so the panel type has to come
   down with it or the text is a two-word-per-line ribbon. */
@media (max-width: 560px) {
  .story-split,
  .story-split--flip {
    gap: var(--space-2);
    padding: var(--space-3) 0;
  }
  .story-split__blurb {
    padding: var(--space-2);
  }
  .story-split__blurb .eyebrow {
    font-size: 0.6rem;
    letter-spacing: 0.06em;
    margin-bottom: var(--space-1);
  }
  .story-split__blurb h2 {
    font-size: 1.05rem;
    margin-bottom: var(--space-1);
  }
  .story-split__blurb p {
    font-size: 0.8rem;
    line-height: 1.45;
  }
  .story-split__blurb p + p {
    margin-top: var(--space-1);
  }
  /* The tall 4:5 crop costs too much height once the column is this narrow;
     a squarer frame keeps the photo beside its text rather than towering over
     it. --wide keeps its own 16/10 — higher specificity, so it is unaffected. */
  .story-photo img {
    aspect-ratio: 1 / 1;
  }

  /* The verse is set at display size on desktop; at this width that is three
     words a line, so it drops to body size and keeps only its italic. */
  .scripture-callout p {
    font-size: 1rem;
    line-height: 1.4;
  }
  .scripture-callout__ref {
    font-size: 0.65rem;
    margin-top: var(--space-1);
  }

  .study-times__title {
    font-size: 1rem;
    margin-top: var(--space-2);
  }
  /* Day and time no longer fit on one line together, so the time drops
     underneath its day rather than being pushed to a right edge that is only
     a couple of centimetres away. */
  .study-times__row {
    display: block;
    padding: 0.3rem 0;
  }
  .study-times__row dt,
  .study-times__row dd {
    font-size: 0.78rem;
  }
  .study-times__row dd {
    margin-left: 0;
    color: var(--stone);
  }
  .study-times__note {
    font-size: 0.78rem;
  }
}

/* ============================================================
   Food ticker
   ============================================================ */

.ticker-section {
  padding: var(--space-5) 0;
  border-top: 1px solid var(--oat);
  text-align: center;
}

.ticker-section__eyebrow {
  display: inline-block;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--olive);
}

.ticker-section__title {
  font-family: var(--font-display);
  font-size: 2rem;
  margin-top: var(--space-1);
  text-wrap: balance;
}

/* The strip runs to the container's edges — wider than the text, so it reads
   as a band rather than a boxed image row. It cancels .container's padding
   rather than using the 100vw bleed trick: 100vw counts the scrollbar the
   viewport doesn't have, which spilled ~7px each side and gave the whole
   page a horizontal scrollbar. The two margins below must track .container's
   padding, including at the 640px breakpoint. */
.ticker {
  position: relative;
  margin: var(--space-4) calc(-1 * var(--space-4)) 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

/* width:max-content stops the flex row wrapping, so the track is exactly two
   copies wide and -50% lands on the start of the second copy.

   The spacing is margin-right on each item, deliberately NOT `gap`. With gap,
   N items have only N-1 gaps, so half the track is one gap short of a whole
   cycle and the loop jumps by that much every time it restarts. A trailing
   margin on every item — including the last — makes the two halves identical. */
.ticker__track {
  display: flex;
  width: max-content;
  align-items: stretch;
  animation: ticker-scroll 42s linear infinite;
}

/* Pause on hover, and on keyboard focus too — a keyboard user tabbing through
   the strip could not otherwise stop it. */
.ticker:hover .ticker__track,
.ticker:focus-within .ticker__track {
  animation-play-state: paused;
}

.ticker__item {
  flex: 0 0 auto;
  margin: 0 var(--space-3) 0 0;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--oat);
  box-shadow: 0 10px 30px rgba(43, 33, 26, 0.12);
}

/* Fixed box + object-fit: the photos are all portrait but not identically
   sized, and a ragged strip reads as a mistake rather than a marquee. */
.ticker__photo {
  width: 15rem;
  height: 20rem;
  object-fit: cover;
  object-position: center;
}

@keyframes ticker-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.ticker-dishes {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-1) var(--space-3);
  list-style: none;
  margin: var(--space-3) 0 0;
  padding: 0;
  font-family: var(--font-display);
  font-size: 1.05rem;
}

/* Separator dots between names, never trailing after the last one. */
.ticker-dishes li + li::before {
  content: "·";
  color: var(--gold);
  margin-right: var(--space-3);
}

@media (max-width: 640px) {
  /* .container drops to --space-2 padding here; the bleed has to follow it
     or the strip stops short of the edge. */
  .ticker {
    margin-left: calc(-1 * var(--space-2));
    margin-right: calc(-1 * var(--space-2));
  }
  .ticker__photo {
    width: 11rem;
    height: 14.5rem;
  }
  .ticker-dishes {
    font-size: 0.95rem;
  }
}

/* The food strip is slow, gentle and purely decorative. The owner asked for it
   to keep moving even when the OS "reduce motion" setting is on — same call as
   the Compass Deliver ticker — so it is slowed here rather than frozen. */
@media (prefers-reduced-motion: reduce) {
  .ticker__track {
    animation: ticker-scroll 70s linear infinite;
  }
}

/* Google Maps embed. line-height:0 stops the inline iframe sitting on a text
   baseline and leaving a sliver of background under it inside the frame. */
.map-embed {
  margin: var(--space-4) auto 0;
  max-width: 56rem;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--oat);
  box-shadow: 0 14px 40px rgba(43, 33, 26, 0.14);
  line-height: 0;
}

.map-embed iframe {
  display: block;
  width: 100%;
  height: 26rem;
  border: 0;
}

@media (max-width: 640px) {
  .map-embed iframe {
    height: 19rem;
  }
}

/* ============================================================
   Who we believe in
   ============================================================ */

.believe-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 22rem;
  gap: var(--space-5);
  padding: var(--space-5) 0 var(--space-6);
  align-items: start;
}

/* Base state: static stacked list — the no-JS / reduced-motion /
   narrow-screen fallback. believe.js opts in to the crossfade. */
.scripture-scroll__viewport {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
}

/* Enhanced state: tall scroll track, sticky viewport, quotes stacked
   in one grid cell so the active one crossfades over the outgoing one. */
.scripture-scroll.is-enhanced {
  height: 260vh;
}

.scripture-scroll.is-enhanced .scripture-scroll__viewport {
  position: sticky;
  top: var(--nav-height-scrolled);
  /* min-height, not height: a quote taller than the box must push the box
     open rather than spill out of it and slide under the nav. */
  min-height: calc(100vh - var(--nav-height-scrolled));
  padding: var(--space-3) 0;
  display: grid;
  align-items: center;
}

.scripture-scroll.is-enhanced .scripture-block {
  grid-area: 1 / 1;
  opacity: 0;
  visibility: hidden;
  transform: translateY(14px);
  pointer-events: none;
}

.scripture-scroll.is-enhanced .scripture-block.is-active {
  opacity: 1;
  visibility: visible;
  transform: none;
  pointer-events: auto;
}

/* Transitions are gated behind .is-ready, which believe.js adds one frame
   after .is-enhanced. Without the gate, applying .is-enhanced animates every
   quote from visible to hidden — and because they all share grid cell 1/1,
   that half-second reads as the three scriptures printed over each other. */
.scripture-scroll.is-enhanced.is-ready .scripture-block {
  transition: opacity 500ms var(--motion-ease),
              transform 500ms var(--motion-ease),
              visibility 0s 500ms;
}

.scripture-scroll.is-enhanced.is-ready .scripture-block.is-active {
  transition: opacity 500ms var(--motion-ease),
              transform 500ms var(--motion-ease),
              visibility 0s;
}

.scripture-block {
  display: block;
  text-decoration: none;
  color: var(--espresso);
  border-left: 3px solid var(--oat);
  padding-left: var(--space-3);
  transition: border-color var(--motion-fast) var(--motion-ease);
}

.scripture-block:hover,
.scripture-block:focus-visible {
  border-left-color: var(--gold);
}

.scripture-block:hover .scripture-block__quote,
.scripture-block:focus-visible .scripture-block__quote {
  color: var(--gold);
}

.scripture-block__quote {
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 3.8vw, 2.85rem);
  line-height: 1.3;
  font-weight: 500;
  color: var(--espresso);
  text-wrap: pretty;
  transition: color var(--motion-fast) var(--motion-ease);
}

.scripture-block__ref {
  display: inline-block;
  margin-top: var(--space-2);
  font-family: var(--font-body);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--olive);
}

.believe-lamb {
  position: fixed;
  top: 50%;
  right: max(var(--space-4), calc((100vw - 72rem) / 2 + var(--space-4)));
  transform: translateY(-50%);
  width: 22rem;
}

.believe-lamb__frame {
  margin: 0;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--oat);
  box-shadow: 0 14px 40px rgba(43, 33, 26, 0.14);
}

.believe-lamb__frame img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 65vh;
  object-fit: cover;
}

.believe-lamb__caption {
  margin-top: var(--space-2);
  text-align: center;
  font-family: var(--font-display);
  font-style: italic;
  color: var(--stone);
  font-size: 0.95rem;
}

@media (max-width: 900px) {
  .believe-layout {
    grid-template-columns: 1fr;
  }
  .believe-lamb {
    position: static;
    top: auto;
    right: auto;
    transform: none;
    width: 100%;
    max-width: 26rem;
    margin: 0 auto var(--space-4);
  }
}

/* ============================================================
   Menu
   ============================================================ */

.menu-page {
  padding: var(--space-5) 0 0;
  text-align: center;
  max-width: 44rem;
  margin: 0 auto;
}

.menu-page .eyebrow {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--olive);
}

.menu-page h1 {
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 5vw, 3rem);
  margin-top: var(--space-1);
  text-wrap: balance;
}

.menu-page__lede {
  margin-top: var(--space-2);
  font-family: var(--font-display);
  font-style: italic;
  color: var(--stone);
  font-size: 1.05rem;
}

/* Columns, not grid: menu groups are wildly uneven in height and a grid
   leaves ragged gaps under the short ones. break-inside keeps a group
   whole across the column boundary. */
.menu-board {
  max-width: 62rem;
  margin: var(--space-5) auto 0;
  columns: 2;
  column-gap: var(--space-5);
}

.menu-group {
  break-inside: avoid;
  /* Trailing margin belongs to the group, not the column: inline-block
     keeps the box from collapsing its margins into the column flow. */
  display: inline-block;
  width: 100%;
  margin-bottom: var(--space-4);
}

@media (max-width: 760px) {
  .menu-board {
    columns: 1;
    max-width: 34rem;
  }
}

.menu-group__title {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 600;
  text-align: center;
  padding-bottom: var(--space-1);
  border-bottom: 1px solid var(--oat);
  text-wrap: balance;
}

.menu-list {
  list-style: none;
  margin: var(--space-2) 0 0;
  padding: 0;
}

/* Leader dots: the name and price sit at the ends of a flex row and the
   ::after rule fills the gap between them, so the eye can track across. */
.menu-item {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 0.4rem;
  padding: 0.3rem 0;
}

.menu-item__name {
  font-size: 1rem;
}

.menu-item::after {
  content: "";
  flex: 1 1 1.5rem;
  order: 1;
  align-self: end;
  margin-bottom: 0.28em;
  border-bottom: 1px dotted var(--oat);
  min-width: 1.5rem;
}

.menu-item__price {
  order: 2;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  white-space: nowrap;
}

/* Full-width row of its own, under the leader line. */
.menu-item__desc {
  order: 3;
  flex: 0 0 100%;
  font-size: 0.875rem;
  color: var(--stone);
  line-height: 1.45;
  margin-top: 0.1rem;
}

.menu-note {
  margin-top: var(--space-2);
  font-family: var(--font-display);
  font-style: italic;
  color: var(--stone);
  font-size: 0.925rem;
  text-wrap: pretty;
}

.menu-extras {
  list-style: none;
  margin: var(--space-2) 0 0;
  padding: 0;
  font-size: 0.875rem;
  color: var(--stone);
}

.menu-extras li + li {
  margin-top: 0.2rem;
}

.menu-extras strong {
  color: var(--espresso);
  font-variant-numeric: tabular-nums;
}

/* The two showpieces — Latin special and afternoon tea. */
.menu-group--feature {
  background: var(--oat);
  border-radius: var(--radius);
  padding: var(--space-3);
  text-align: center;
}

.menu-group--feature .menu-group__title {
  border-bottom-color: rgba(43, 33, 26, 0.18);
}

.menu-group__standfirst {
  margin-top: var(--space-2);
  font-family: var(--font-display);
  font-size: 1.05rem;
  text-wrap: pretty;
}

.menu-group__dishes {
  margin-top: var(--space-2);
  font-family: var(--font-display);
  font-style: italic;
  color: var(--espresso);
  text-wrap: balance;
}

.menu-group__from {
  margin-top: var(--space-2);
  font-family: var(--font-display);
  font-size: 1.15rem;
}

.menu-group__from strong {
  font-variant-numeric: tabular-nums;
}

.menu-group--feature .menu-note {
  color: rgba(43, 33, 26, 0.7);
}

/* Deals and the children's menu — outlined rather than filled, so the
   two fills above stay the loudest thing on the board. */
.menu-group--boxed {
  border: 1px solid var(--oat);
  border-radius: var(--radius);
  padding: var(--space-3);
}

.menu-group--boxed .menu-group__title {
  border-bottom: none;
  padding-bottom: 0;
}

.menu-group__flag {
  margin-top: var(--space-3);
  padding-top: var(--space-2);
  border-top: 1px solid var(--oat);
  text-align: center;
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--gold);
}

.menu-page--foot {
  padding: var(--space-3) 0 var(--space-6);
}

.menu-page__sweet {
  font-family: var(--font-display);
  font-size: 1.05rem;
  text-wrap: pretty;
}

.menu-page__note {
  margin-top: var(--space-2);
  font-family: var(--font-display);
  font-style: italic;
  color: var(--stone);
  font-size: 0.95rem;
}

/* ============================================================
   Reviews
   ============================================================ */

.reviews {
  padding: var(--space-5) 0;
  border-top: 1px solid var(--oat);
  text-align: center;
}

.reviews__eyebrow {
  display: inline-block;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--olive);
}

.reviews__title {
  font-family: var(--font-display);
  font-size: 2rem;
  margin-top: var(--space-1);
  text-wrap: balance;
}

/* The clamp lives on this wrapper, never on the multicol element itself.
   A multicol box with a definite height does not clip its overflow — it
   spawns extra columns off to the side, which throws the whole grid out
   of the page. Clipping one element up keeps the columns intact. */
.reviews__clip {
  --reviews-clamp: 34rem;
  margin-top: var(--space-4);
}

.reviews__clip.is-collapsed {
  max-height: var(--reviews-clamp);
  overflow: hidden;
  /* Fades the clipped row out rather than guillotining it mid-sentence. */
  -webkit-mask-image: linear-gradient(to bottom, #000 70%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 70%, transparent 100%);
}

/* Same reason as the menu board: the quotes vary from one line to ten,
   and columns pack them without the gaps a grid would leave. */
.reviews__grid {
  columns: 3;
  column-gap: var(--space-3);
  text-align: left;
}

@media (max-width: 1000px) {
  .reviews__grid {
    columns: 2;
  }
}

@media (max-width: 640px) {
  .reviews__clip {
    --reviews-clamp: 30rem;
  }
  .reviews__grid {
    columns: 1;
  }
}

.review {
  break-inside: avoid;
  display: inline-block;
  width: 100%;
  margin: 0 0 var(--space-3);
  background: var(--oat);
  border-radius: var(--radius);
  padding: var(--space-3);
}

.review blockquote {
  margin: 0;
}

.review blockquote p {
  font-family: var(--font-display);
  font-size: 1.02rem;
  line-height: 1.5;
  text-wrap: pretty;
}

.review blockquote p + p {
  margin-top: var(--space-2);
}

.review__by {
  margin-top: var(--space-2);
  font-family: var(--font-body);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--olive);
}

.reviews__more {
  margin-top: var(--space-2);
}

.reviews__toggle {
  font-family: var(--font-body);
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--espresso);
  background: none;
  border: 1px solid var(--oat);
  border-radius: var(--radius);
  padding: 0.7rem var(--space-3);
  min-height: 44px;
  cursor: pointer;
  transition: color var(--motion-fast) var(--motion-ease),
              border-color var(--motion-fast) var(--motion-ease);
}

.reviews__toggle:hover,
.reviews__toggle:focus-visible {
  color: var(--gold);
  border-color: var(--gold);
}

/* ============================================================
   Section fade-in (progressive enhancement — see scripts/fade.js)
   ============================================================ */

.fade-init {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 500ms var(--motion-ease), transform 500ms var(--motion-ease);
}

.fade-init.is-visible {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .fade-init {
    transition: none;
  }
}
