/* ===========================================================================
   SSTGC — components
   =========================================================================== */

/* ── Buttons ───────────────────────────────────────────────────────────────*/

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: .72em 1.5em;
  border: 1.5px solid transparent;
  border-radius: var(--r-sm);
  font-size: var(--t-sm);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  cursor: pointer;
  transition: background-color var(--fast) var(--ease),
              border-color var(--fast) var(--ease),
              color var(--fast) var(--ease),
              transform .08s var(--ease);
  /* 44px minimum — the congregation skews older and mobile. */
  min-height: 44px;
}
.btn:active { transform: translateY(1px); }

.btn--primary { background: var(--brand); border-color: var(--brand); color: var(--white); }
.btn--primary:hover { background: var(--brand-hover); border-color: var(--brand-hover); color: var(--white); }

.btn--outline { background: transparent; border-color: var(--brand); color: var(--brand); }
.btn--outline:hover { background: var(--brand); color: var(--white); }

.btn--ghost { background: transparent; border-color: var(--line-strong); color: var(--text); }
.btn--ghost:hover { border-color: var(--brand); color: var(--brand); }

.btn--invert { background: var(--white); border-color: var(--white); color: var(--brand); }
.btn--invert:hover { background: var(--saffron-50); color: var(--brand-hover); }

.btn--lg { padding: .9em 1.9em; font-size: var(--t-base); min-height: 52px; }
.btn--sm { padding: .55em 1.1em; font-size: var(--t-xs); min-height: 38px; }
.btn--block { display: flex; width: 100%; }

/* ── Card ──────────────────────────────────────────────────────────────────*/

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
  transition: box-shadow var(--med) var(--ease),
              border-color var(--med) var(--ease),
              transform var(--med) var(--ease);
  display: flex;
  flex-direction: column;
}
/* Generic card media. Contain by default, because this card is used for the
   event gallery — where the images are designed artwork with text on them —
   as well as for photographs. A letterboxed photo is tidy; a poster with its
   message cropped off is broken, so the safe default is the one that never
   cuts. Add .card__media--photo where the content is known to be photographic. */
.card__media { aspect-ratio: 3 / 2; overflow: hidden; background: var(--saffron-50); }
.card__media img { width: 100%; height: 100%; object-fit: contain; transition: transform var(--med) var(--ease); }
.card__media--photo img { object-fit: cover; }
.card__body { padding: var(--s-5); display: flex; flex-direction: column; flex: 1; }
.card__title { font-size: var(--t-lg); font-weight: 600; margin-bottom: var(--s-2); line-height: var(--lh-snug); }
.card__title a { color: var(--text-strong); }
.card__meta { font-size: var(--t-xs); color: var(--text-soft); margin-bottom: var(--s-2); }
.card__excerpt { font-size: var(--t-sm); color: var(--text-soft); margin-bottom: var(--s-4); }
.card__foot { margin-top: auto; padding-top: var(--s-2); }

a.card, .card--link { color: inherit; }
.card:hover { border-color: var(--line-strong); box-shadow: var(--shadow-lift); transform: translateY(-2px); }
.card:hover .card__media img { transform: scale(1.04); }
.card:hover .card__title a { color: var(--brand); }

/* ── Header ────────────────────────────────────────────────────────────────*/

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

/* Utility strip — Live Darshan, socials, portal login. Saffron so the
   masthead below it reads as white and calm. */
.utility-bar {
  background: var(--brand);
  color: var(--saffron-100);
  font-size: var(--t-xs);
}
.utility-bar .wrap {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--s-4);
  min-height: 38px;
  flex-wrap: wrap;
  min-width: 0;
}
@media (max-width: 560px) {
  /* Centred once it wraps to two lines — right-aligned wrapped text leaves a
     ragged left edge against the screen edge. */
  .utility-bar .wrap { justify-content: center; gap: var(--s-3); padding-block: var(--s-2); }
  .utility-bar { font-size: 11px; }
}
.utility-bar a { color: var(--saffron-100); }
.utility-bar a:hover { color: var(--white); }
.utility-bar ul { display: flex; gap: var(--s-4); list-style: none; padding: 0; margin: 0; align-items: center; }

/* Social links in the utility bar. Targeted by href rather than by a wrapper
   class, because the widget markup varies and the links are what matter. */
.utility-bar a[href*="facebook"],
.utility-bar a[href*="youtube"],
.utility-bar a[href*="instagram"],
.utility-bar a[href*="twitter"],
.utility-bar a[href*="x.com"],
.utility-bar a[href*="whatsapp"],
.utility-bar__socials a {
  display: inline-grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: var(--r-full);
  transition: background var(--fast) var(--ease);
  vertical-align: middle;
}
.utility-bar a[href*="facebook"]:hover,
.utility-bar a[href*="youtube"]:hover,
.utility-bar a[href*="instagram"]:hover,
.utility-bar a[href*="twitter"]:hover,
.utility-bar a[href*="x.com"]:hover,
.utility-bar a[href*="whatsapp"]:hover,
.utility-bar__socials a:hover { background: rgba(255, 255, 255, .18); }

.utility-bar svg { display: block; }

/* A widget wrapping the socials in a <ul> puts a bullet and a line break
   between each one. Flatten it. */
.utility-bar ul li { display: inline-flex; align-items: center; }
.utility-bar .utility-widget { display: inline-flex; align-items: center; gap: var(--s-2); }

/* Masthead */
.masthead {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  min-height: 78px;
  text-align: left;
  /* Without this a flex child refuses to shrink below its content width, and
     the logo is a wide horizontal lockup — which is what pushed the menu
     button off the right of a phone screen. */
  min-width: 0;
}

.masthead__brand {
  /* Shrinks, but only so far.
   *
   * It was flex-shrink: 0, which pushed the menu button off a 375px screen.
   * Then it was flex: 0 1 auto with min-width: 0 — and once the utility items
   * joined the same row, the brand was the only thing that could give, so it
   * collapsed to a few pixels and the logo disappeared.
   *
   * A floor of 180px: it can shrink to make room, and stops before it becomes
   * nothing. Below that width the row wraps instead, which is the right
   * failure. */
  /* With only the logo and the menu on this row there is room for both, so
     the logo keeps its size and the menu takes what is left. */
  flex: 0 0 auto;
  display: flex;
  align-items: center;
}
.masthead__brand a { display: block; min-width: 0; }
.masthead__brand img {
  max-height: 54px;
  max-width: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}

/* The nav sits next to the logo, not pushed to the right edge.
   `margin-left: auto` put it hard right, which is what "menu items are not
   left aligned" meant — the block, not the text inside it. */
/* The nav ends at the wrap's right edge, so it lines up with the utility row
   above it.
   `margin-right: auto` was left over from when the utility items shared this
   row and needed pushing to the far right — it centres the nav in the space
   after the logo instead, which left it about 80px short of the edge. */
.masthead__nav { margin-left: auto; }

@media (max-width: 1023px) {
  .masthead { min-height: 66px; gap: var(--s-3); }
  .masthead__brand img { max-height: 42px; }
}
@media (max-width: 420px) {
  .masthead { min-height: 60px; }
  .masthead__brand img { max-height: 36px; }
}

/* Primary navigation */
.nav-primary ul { display: flex; gap: var(--s-1); list-style: none; padding: 0; margin: 0; align-items: center; }
.nav-primary li { position: relative; }

/* Alignment is set on the container and inherited, rather than on the link
   alone. Something upstream — the utility-bar widget, or a plugin's stylesheet
   — was centring the header, and a rule on the <a> alone lost to it. Setting
   it on every level of the nav means nothing can cascade past. */
.site-header,
.masthead,
.masthead__nav,
.nav-primary,
.nav-primary ul,
.nav-primary li,
.nav-primary a,
.nav-primary .sub-menu,
.nav-primary .sub-menu li,
.nav-primary .sub-menu a { text-align: left; }

.nav-primary a {
  display: block;
  text-align: left;
  padding: var(--s-3) var(--s-4);
  font-size: var(--t-sm);
  font-weight: 500;
  color: var(--text);
  border-radius: var(--r-sm);
  white-space: nowrap;
}
.nav-primary a:hover { color: var(--brand); background: var(--brand-tint); }

.nav-primary .current-menu-item > a,
.nav-primary .current_page_item > a,
.nav-primary .current-menu-ancestor > a { color: var(--brand); font-weight: 600; }

/* Dropdowns — hover on pointer devices, click-toggled on touch via JS */
.nav-primary .sub-menu {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  min-width: 232px;
  flex-direction: column;
  /* This is what was centring the dropdown, and it was not text-align.
     `.nav-primary ul` sets align-items: center for the horizontal top-level
     row — and that selector also matches the sub-menu, which is a ul. Combined
     with flex-direction: column here, align-items: center centres children
     HORIZONTALLY, so each <li> shrank to its text and sat in the middle of the
     column. text-align on the <a> could never fix that: the <a> was filling an
     <li> that was already centred. */
  align-items: stretch;
  gap: 0;
  padding: var(--s-2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-deep);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity var(--fast) var(--ease), transform var(--fast) var(--ease), visibility var(--fast);
  z-index: 20;
}
.nav-primary li:hover > .sub-menu,
.nav-primary li:focus-within > .sub-menu,
.nav-primary li.is-open > .sub-menu {
  opacity: 1; visibility: visible; transform: translateY(0);
}
.nav-primary .sub-menu li { width: 100%; }
.nav-primary .sub-menu a {
  display: block;
  width: 100%;
  padding: var(--s-2) var(--s-3);
  font-size: var(--t-sm);
  white-space: normal;
  text-align: left;
  line-height: var(--lh-snug);
}
.nav-primary .sub-menu .sub-menu { top: 0; left: calc(100% + 4px); }

.nav-primary .menu-item-has-children > a::after {
  content: '';
  display: inline-block;
  width: 5px; height: 5px;
  margin-left: 7px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translateY(-2px);
  opacity: .6;
}

/* Mobile toggle */
.nav-toggle {
  display: none;
  margin-left: auto;
  width: 44px; height: 44px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  cursor: pointer;
  padding: 0;
  place-items: center;
}
.nav-toggle span, .nav-toggle span::before, .nav-toggle span::after {
  display: block; width: 19px; height: 2px;
  background: var(--text-strong); border-radius: 2px;
  transition: transform var(--fast) var(--ease), opacity var(--fast) var(--ease);
}
.nav-toggle span::before, .nav-toggle span::after { content: ''; position: relative; }
.nav-toggle span::before { top: -6px; }
.nav-toggle span::after  { top: 4px; }
.nav-toggle[aria-expanded='true'] span { background: transparent; }
.nav-toggle[aria-expanded='true'] span::before { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded='true'] span::after  { transform: translateY(-4px) rotate(-45deg); }

@media (max-width: 1023px) {
  .nav-toggle { display: grid; }
  .masthead__nav {
    /* The desktop margins must not apply to a fixed drawer. */
    margin: 0;
    position: fixed;
    inset: 0 0 0 auto;
    width: min(88vw, 380px);
    background: var(--surface);
    box-shadow: var(--shadow-deep);
    padding: var(--s-6) var(--s-5) var(--s-10);
    overflow-y: auto;
    transform: translateX(100%);
    transition: transform var(--med) var(--ease);
    z-index: 200;
  }
  .masthead__nav.is-open { transform: translateX(0); }
  .nav-primary ul { flex-direction: column; align-items: stretch; gap: 0; }
  .nav-primary > ul > li { border-bottom: 1px solid var(--line); }
  .nav-primary a { padding: var(--s-4) var(--s-2); font-size: var(--t-base); }

  /* Submenus stack inline on mobile — a flyout at this width has nowhere to go */
  .nav-primary .sub-menu {
    position: static; opacity: 1; visibility: visible; transform: none;
    box-shadow: none; border: 0; padding: 0 0 var(--s-2) var(--s-4);
    min-width: 0; display: none;
  }
  .nav-primary li.is-open > .sub-menu { display: block; }
  .nav-primary .menu-item-has-children > a::after { float: right; margin-top: 8px; }

  .nav-scrim {
    position: fixed; inset: 0; z-index: 150;
    background: rgba(24, 24, 27, .45);
    opacity: 0; visibility: hidden;
    transition: opacity var(--med) var(--ease), visibility var(--med);
  }
  .nav-scrim.is-open { opacity: 1; visibility: visible; }
}

/* ── Hero ──────────────────────────────────────────────────────────────────
   Image and today's timings, side by side.

   The first version stacked four timing cards beside an uncropped image, so
   the band ran past 900px and pushed everything else off the first screen.
   Only darshan and aarti are here now — the times someone checks before
   setting out. Weekly and monthly programmes moved to their own band.

   The image is cropped to a fixed ratio so the hero's height is a design
   decision rather than whatever the office last uploaded.                   */

.hero { background: var(--saffron-100); }

.hero__inner {
  display: grid;
  grid-template-columns: minmax(0, 60fr) minmax(0, 40fr);
  gap: var(--s-5);
  /* The carousel sets the row height via its aspect ratio; the timings column
     stretches to match and groups its cards at the top. The 16:10 frame is
     chosen so the difference between the two is about 24px — small enough to
     read as padding rather than as a hole. */
  align-items: stretch;
  padding-block: var(--s-5);
}

/* ── Hero carousel ─────────────────────────────────────────────────────────
   The temple's notice posters — drives, brunches, parayans. The old site
   rotated these with Owl Carousel, 40KB plus jQuery, for a crossfade and some
   dots. This is the same behaviour in CSS and about seventy lines of script.

   The stage takes its height from the timings column beside it: slides are
   absolutely positioned, so they contribute nothing to the grid row, leaving
   the timings to measure it. Add an aarti and the poster grows with it — no
   ratio to keep in sync.                                                     */

.carousel {
  position: relative;
  min-width: 0;
  align-self: start;
  /* No overflow clip — the poster carries its own radius now. */
  /* 16:10.
   *
   * Matching the posters exactly at 4:3 made the frame 108px taller than the
   * timings beside it, and there is no good place to put 108px: below the last
   * card it reads as a missing card, distributed between the cards it reads as
   * broken spacing. Measured against the real content, 16:10 leaves 24px —
   * which reads as padding — at the cost of about 54px of tint down each side
   * of a 4:3 poster.
   *
   * A small even letterbox on a framed poster is unremarkable. A hole in the
   * layout is not. */
  aspect-ratio: 16 / 10;
  /* No visible frame.
   *
   * With `contain` and a top anchor, whatever a poster does not fill falls at
   * the bottom — and a frame with a background turns that into a white box
   * under the artwork. Transparent, the leftover is simply band, which is the
   * same thing sitting under the timings column beside it.
   *
   * The poster keeps its own rounded corner and shadow via .carousel__slide. */
  background: transparent;
  isolation: isolate;
}

/* Inset by the border so the poster's top edge sits exactly where the timings
   card's top edge does. */
.carousel__track { position: absolute; inset: 0; }

.carousel__slide {
  position: absolute;
  inset: 0;
  display: block;
  opacity: 0;
  visibility: hidden;
  transition: opacity .5s var(--ease), visibility .5s;
}
.carousel__slide.is-active { opacity: 1; visibility: visible; }
/* The shadow and radius belong to the poster, not to the frame around it. */
.carousel__slide img {
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lift);
}
.carousel__slide img {
  width: 100%; height: 100%;
  /* `contain`, not `cover`.
   *
   * These are posters: they carry a headline, a body, a donation amount and a
   * QR code. Cover cropped the Neem Leaf Drive so "Only 200 of 1001 leaves
   * remain" — the actual ask — fell off the bottom. Nothing on a poster is
   * safe to cut, because the temple designed all of it to be read.
   *
   * The cost is letterboxing on posters whose shape differs from the stage.
   * That is the right trade: a band of tint beside a poster is tidy, a poster
   * with its message cut off is broken. */
  object-fit: contain;
  /* Top, not centre.
   *
   * A contained poster whose shape differs from the frame is letterboxed. With
   * `center` that space splits above and below, so the artwork starts lower
   * than the timings card beside it — and because the letterbox is the same
   * saffron as the band behind it, the frame is invisible and the misalignment
   * reads as a mistake.
   *
   * Anchored to the top, the poster's top edge meets the card's top edge and
   * all the letterboxing falls below, where the band absorbs it. */
  object-position: center top;
}
.carousel__slide:focus-visible { outline: 3px solid var(--brand); outline-offset: -3px; }

/* ── Arrows ────────────────────────────────────────────────────────────────
   Held at 0 opacity until hover or keyboard focus, so the poster is not
   permanently covered by chrome. Always visible on touch, where there is no
   hover to reveal them.                                                      */

.carousel__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  display: grid;
  place-items: center;
  width: 42px; height: 42px;
  border: 0;
  border-radius: var(--r-full);
  background: rgba(255, 255, 255, .92);
  color: var(--ground);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(24, 24, 27, .18);
  opacity: 0;
  transition: opacity var(--fast) var(--ease), background var(--fast) var(--ease);
}
.carousel__arrow--prev { left: var(--s-3); }
.carousel__arrow--next { right: var(--s-3); }

.carousel:hover .carousel__arrow,
.carousel:focus-within .carousel__arrow { opacity: 1; }
.carousel__arrow:hover { background: #fff; }
.carousel__arrow:focus-visible { opacity: 1; outline: 2px solid var(--brand); outline-offset: 2px; }

@media (hover: none) {
  .carousel__arrow { opacity: .9; }
}

/* ── Dots ──────────────────────────────────────────────────────────────────
   On a scrim, because a poster's own artwork is behind them and a bare dot
   disappears against half of these designs.                                  */

/* Dots sit under the poster, not over it.
   Overlaid, they covered the last line of the Neem Leaf Drive — "Please visit
   front desks for any questions" — which is the poster's closing instruction.
   Chrome does not belong on top of content that has to be read. */
.carousel__dots {
  position: absolute;
  left: 50%;
  bottom: var(--s-3);
  transform: translateX(-50%);
  z-index: 2;
  display: flex;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-full);
  background: rgba(24, 24, 27, .45);
  backdrop-filter: blur(8px);
  /* Fades out unless someone is interacting, so a poster being read is never
     partly covered. */
  opacity: 0;
  transition: opacity var(--fast) var(--ease);
}
.carousel:hover .carousel__dots,
.carousel:focus-within .carousel__dots { opacity: 1; }

@media (hover: none) { .carousel__dots { opacity: 1; } }

.carousel__dot {
  width: 8px; height: 8px;
  padding: 0;
  border: 0;
  border-radius: var(--r-full);
  background: rgba(255, 255, 255, .5);
  cursor: pointer;
  transition: background var(--fast) var(--ease), width var(--fast) var(--ease);
}
.carousel__dot:hover { background: rgba(255, 255, 255, .8); }
.carousel__dot.is-active { background: var(--saffron-400); width: 22px; }
.carousel__dot:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* ── Pause ─────────────────────────────────────────────────────────────────
   An autoplaying carousel must be stoppable. Someone reading a notice about a
   date should not have it taken away, and a moving element with no control is
   a WCAG failure, not a preference.                                          */

.carousel__pause {
  position: absolute;
  right: var(--s-3);
  bottom: var(--s-4);
  z-index: 2;
  display: grid;
  place-items: center;
  width: 30px; height: 30px;
  border: 0;
  border-radius: var(--r-full);
  background: rgba(24, 24, 27, .38);
  backdrop-filter: blur(6px);
  color: #fff;
  font-size: 10px;
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--fast) var(--ease);
}
.carousel:hover .carousel__pause,
.carousel:focus-within .carousel__pause { opacity: 1; }
.carousel__pause:focus-visible { opacity: 1; outline: 2px solid #fff; outline-offset: 2px; }
.carousel__pause[data-paused='true'] { opacity: 1; }

/* Without JavaScript, show the first slide and hide the controls. */
.no-js .carousel__slide { opacity: 1; visibility: visible; }
.no-js .carousel__slide:not(.is-active) { display: none; }
.no-js .carousel__arrow,
.no-js .carousel__dots,
.no-js .carousel__pause { display: none; }

/* ── Timings column ────────────────────────────────────────────────────────
   Darshan above, Aarti below.

   This rule went missing when the gallery block was replaced by the carousel —
   the container had no styles at all, so it was a plain block and the two
   cards simply stacked from the top, leaving the difference in height as a gap
   under the second one.

   The cards group at the top. `space-between` was tried and was worse: with
   100px+ to distribute it pushed the two cards apart into what looked like a
   fault. The carousel's 16:10 frame closes most of the mismatch instead, so
   what remains is small enough to read as padding.                          */

.timings {
  display: grid;
  grid-template-columns: 1fr;
  grid-auto-rows: max-content;
  gap: var(--s-4);
  align-content: start;
  min-width: 0;
}

@media (max-width: 900px) {
  /* Stack. This rule was lost when the gallery block was replaced, so the two
     columns stayed side by side down to phone width. */
  .hero__inner { grid-template-columns: 1fr; gap: var(--s-4); }
  /* Poster on top at a shallower ratio so it does not fill the screen, then
     the two timings cards side by side beneath it. */
  .carousel { aspect-ratio: 16 / 10; }
  .timings { grid-template-columns: 1fr 1fr; align-content: start; }
}
@media (max-width: 560px) {
  .carousel { aspect-ratio: 4 / 3; }
  .carousel__arrow { width: 36px; height: 36px; font-size: 20px; }
  /* Cards stack, so each is the full width again — the time can sit beside its
     label rather than above it, which halves the card's height. */
  .timings { grid-template-columns: 1fr; }
  .timings__row {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: var(--s-4);
    align-items: baseline;
    padding-block: var(--s-3);
  }
  .timings__time { font-size: 1.15rem; order: 2; }
  .timings__label { margin-top: 0; order: 1; }
  .timings__card--wide .timings__time { font-size: 1rem; }
}

/* ── Timings card ──────────────────────────────────────────────────────────
   The most-read content on the site, so the time is the display type and the
   name sits under it. The previous version set the time at body size and
   right-aligned it as metadata — but the number is what someone came for.

   Same ACF fields, same "Label: time" lines. sstgc_render_timings() already
   splits label from time; only the presentation changed.                    */

.timings__card {
  background: var(--surface);
  border: 1px solid var(--brand-line);
  border-radius: var(--r);
  box-shadow: var(--shadow);
  align-self: start;
  /* No `overflow: hidden`. It was there to clip the saffron bar to the card's
     radius, and it cut the last row's numerals when a row grew — the border
     was drawn straight through "6:00 PM". The bar rounds its own corners
     instead. */
}

/* Saffron edge, matching the one where the page meets the footer — the same
   motif twice, so the page has a signature rather than a decoration. */
.timings__card::before {
  content: '';
  display: block;
  height: 3px;
  background: linear-gradient(90deg, var(--saffron-600), var(--saffron-400) 50%, var(--saffron-600));
  border-radius: var(--r) var(--r) 0 0;
  /* Cover the card's own 1px border at the top so the bar meets the corners. */
  margin: -1px -1px 0;
}

/* Masthead: label, hairline, and whatever free text the field opened with —
   "Monday to Sunday" becomes the right-hand note instead of a first row. */
.timings__card h3 {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--brand);
  margin: 0;
  padding: var(--s-4) var(--s-5) var(--s-3);
}
.timings__card h3::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--brand-line);
}

/* The rows form a two-column grid. Four aartis in two rows is a shape the eye
   takes in at once; four stacked rows is something it has to read. */
.timings__rows {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.timings__row {
  padding: var(--s-3) var(--s-5) var(--s-4);
  border-top: 1px solid var(--line);
  min-width: 0;
}
.timings__row:nth-child(odd)  { border-right: 1px solid var(--line); }
/* The first row of each column has the masthead rule above it already. */
.timings__row:nth-child(1),
.timings__row:nth-child(2) { border-top: 0; }

.timings__time {
  display: block;
  font-size: 1.4rem;
  font-weight: 600;
  /* Tabular figures align clock times down a column. They do the same for the
     day numbers in a date, so this holds for the festivals column too. */
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.015em;
  color: var(--text-strong);
  line-height: 1.12;
}
/* AM/PM drops back so the eye reads the number and stops. */
.timings__time .meridiem {
  font-size: var(--t-sm);
  font-weight: 500;
  color: var(--text-soft);
  margin-left: 3px;
  letter-spacing: 0;
}
/* An en dash in a range — "8:30 AM to 1:00 PM" — is a separator, not a digit. */
.timings__time .sep { color: var(--line-strong); font-weight: 400; margin-inline: 2px; }

.timings__label {
  display: block;
  font-size: var(--t-sm);
  color: var(--text-secondary);
  margin-top: var(--s-1);
  line-height: var(--lh-snug);
}

/* A line with no time — "Monday to Sunday" on its own — is a note, not a row.
   It sits full width under the masthead. */
.timings__note {
  grid-column: 1 / -1;
  padding: 0 var(--s-5) var(--s-3);
  font-size: var(--t-sm);
  color: var(--text-soft);
}

/* A range is wider than a single time. At a 40% column each half is about
   200px, and "8:30 AM – 1:00 PM" at the full size wrapped onto two lines —
   which grew the card and pushed the layout out of alignment. */
.timings__card--wide .timings__time {
  font-size: 1.05rem;
  white-space: nowrap;
}
.timings__card--wide .timings__time .meridiem { font-size: var(--t-xs); }

/* Rows go single-column at 760px, not 460px.
   Between 560 and 900 the two cards sit side by side, so each card is about
   320px and each of its two row-columns about 160px — not enough for
   "Madhyana Aarti" above "12:00 PM" without wrapping. Below 760 the cards are
   narrow enough that one row per line reads better than two cramped ones. */
@media (max-width: 760px) {
  .timings__rows { grid-template-columns: 1fr; }
  .timings__row:nth-child(odd) { border-right: 0; }
  .timings__row:nth-child(2) { border-top: 1px solid var(--line); }
}

.band--sunk .timings__card { box-shadow: none; }

/* ── Event / list cards ────────────────────────────────────────────────────*/

.event-card .card__media { aspect-ratio: 300 / 215; }

.aarti-list { list-style: none; padding: 0; display: grid; gap: 0; }
.aarti-list li {
  display: flex; align-items: center; gap: var(--s-4);
  padding: var(--s-4) var(--s-2);
  border-bottom: 1px solid var(--line);
}
.aarti-list li:first-child { border-top: 1px solid var(--line); }
.aarti-list__name { flex: 1; font-weight: 500; color: var(--text-strong); }
.aarti-list__actions { display: flex; gap: var(--s-2); flex-shrink: 0; }

/* ── Person card — priests, trustees ───────────────────────────────────────*/

.person { text-align: center; }
.person__photo {
  width: 132px; height: 132px;
  border-radius: var(--r-full);
  object-fit: cover;
  margin: 0 auto var(--s-4);
  border: 3px solid var(--brand-line);
}
.person__name { font-size: var(--t-lg); font-weight: 600; color: var(--text-strong); margin-bottom: var(--s-1); }
.person__role { font-size: var(--t-sm); color: var(--brand); font-weight: 500; margin-bottom: var(--s-2); }
.person__meta { font-size: var(--t-sm); color: var(--text-soft); }

/* ── Forms ─────────────────────────────────────────────────────────────────*/

.field { margin-bottom: var(--s-4); }
.field label { display: block; font-size: var(--t-sm); font-weight: 500; margin-bottom: var(--s-2); color: var(--text); }

input[type='text'], input[type='email'], input[type='url'], input[type='tel'],
input[type='number'], input[type='password'], input[type='search'],
input[type='date'], input[type='time'], select, textarea {
  width: 100%;
  padding: var(--s-3) var(--s-4);
  font-size: var(--t-sm);
  color: var(--text-strong);
  background: var(--surface);
  border: 1.5px solid var(--line);
  border-radius: var(--r-sm);
  min-height: 46px;
  transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
textarea { min-height: 132px; resize: vertical; line-height: var(--lh-body); }

input:hover, select:hover, textarea:hover { border-color: var(--line-strong); }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 13%, transparent);
}
::placeholder { color: var(--text-soft); opacity: 1; }

/* Contact Form 7, which the theme uses */
.wpcf7-form p { margin-bottom: var(--s-4); }
.wpcf7 .wpcf7-submit { /* inherits .btn via functions.php filter */ }
.wpcf7-not-valid-tip { color: var(--danger); font-size: var(--t-xs); margin-top: var(--s-1); }
.wpcf7-response-output {
  border-radius: var(--r-sm) !important;
  border-width: 1px !important;
  padding: var(--s-3) var(--s-4) !important;
  font-size: var(--t-sm);
  margin: var(--s-4) 0 0 !important;
}

/* ── Tables ────────────────────────────────────────────────────────────────*/

.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; border-radius: var(--r); border: 1px solid var(--line); }

table { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }
thead th {
  background: var(--surface-sunk);
  font-size: var(--t-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--track-wide);
  color: var(--text-soft);
  text-align: left;
  padding: var(--s-3) var(--s-4);
  white-space: nowrap;
}
tbody td { padding: var(--s-3) var(--s-4); border-top: 1px solid var(--line); }
tbody tr:hover { background: var(--brand-tint); }
tbody td:first-child { font-weight: 500; color: var(--text-strong); }

/* ── Page hero (interior pages) ────────────────────────────────────────────*/

.page-hero {
  background: var(--ground);
  color: var(--white);
  padding-block: clamp(2.5rem, 2rem + 3vw, 4.5rem);
  position: relative;
  overflow: hidden;
}
.page-hero::after {
  /* One warm sweep from the top right, so the band has a light source rather
     than being a flat rectangle. */
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(88% 140% at 86% 0%, rgba(240, 153, 29, .28), transparent 60%);
  pointer-events: none;
}
.page-hero > * { position: relative; z-index: 1; }
.page-hero h1 { color: var(--white); margin-bottom: var(--s-2); }
.page-hero p { color: var(--on-ground-soft); max-width: var(--measure); }

.breadcrumb { font-size: var(--t-xs); color: var(--on-ground-soft); margin-bottom: var(--s-3); }
.breadcrumb a { color: var(--on-ground-soft); }
.breadcrumb a:hover { color: var(--saffron-400); }
.breadcrumb span + span::before { content: '/'; margin: 0 var(--s-2); opacity: .5; }

/* ── Subscribe band ────────────────────────────────────────────────────────*/

/* ── Subscribe cards ───────────────────────────────────────────────────────
   Icon, text, then the button on its own line. The first version put icon and
   text in a row with the button under the text, so a long URL-labelled button
   ran out of the card and over the text beside it.                          */

.subscribe__item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  height: 100%;
}
.subscribe__icon {
  width: 40px; height: 40px;
  flex-shrink: 0;
  object-fit: contain;
}
.subscribe__text {
  font-size: var(--t-sm);
  color: var(--text-soft);
  line-height: var(--lh-snug);
  margin: 0;
  max-width: none;
}
/* The button sits at the bottom, so two cards with different text lengths
   still line their buttons up. */
.subscribe__cta {
  margin-top: auto;
  max-width: 100%;
  /* A label that is still somehow long must wrap inside the button rather
     than push past the card edge. */
  white-space: normal;
  overflow-wrap: anywhere;
  text-align: center;
}

/* ── Footer ────────────────────────────────────────────────────────────────*/

.site-footer {
  background: var(--ground);
  color: var(--on-ground-soft);
  position: relative;
}

/* A saffron edge where the page meets the footer. Without it the band reads as
   the page falling away rather than closing. */
.site-footer::before {
  content: '';
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  background: linear-gradient(90deg, var(--saffron-700), var(--saffron-400) 50%, var(--saffron-700));
}

.footer-inner {
  display: grid;
  /* auto-fit rather than fixed columns: the site has two populated columns
     today and may have four later. Fixed columns crammed both into the left
     third and left two-thirds of the band empty. */
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: var(--s-10) var(--s-8);
  padding-block: var(--s-16) var(--s-12);
  align-items: start;
}

/* The identity column carries the logo and full address, so it needs more
   room than a three-item link list. */
.footer-brand { grid-column: span 1; max-width: 34ch; }

@media (min-width: 900px) {
  .footer-inner { grid-template-columns: 1.5fr repeat(auto-fit, minmax(180px, 1fr)); }
}

.site-footer a {
  color: var(--on-ground-soft);
  transition: color var(--fast) var(--ease);
}
.site-footer a:hover { color: var(--saffron-400); }

/* ── Footer headings ───────────────────────────────────────────────────────
   Sentence case at reading size, not a shrunken uppercase label. "QUICK LINKS"
   at 12px with wide tracking reads as a form label; the links under it are
   larger than their own heading, which inverts the hierarchy.               */

.site-footer h3 {
  font-size: var(--t-base);
  font-weight: 600;
  letter-spacing: -0.006em;
  text-transform: none;
  color: var(--on-ground);
  margin: 0 0 var(--s-4);
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--ground-line);
}

.site-footer ul { list-style: none; padding: 0; margin: 0; }
.site-footer li + li { margin-top: var(--s-1); }

/* Links get their own padded row, so the tap target is a full line rather
   than the width of the words. */
.site-footer nav a {
  display: block;
  padding: var(--s-2) 0;
  font-size: var(--t-sm);
  line-height: var(--lh-snug);
}

.site-footer img.footer-logo {
  max-height: 74px;
  width: auto;
  margin-bottom: var(--s-5);
}

/* ── Contact block ─────────────────────────────────────────────────────────*/

.footer-contact { display: grid; gap: var(--s-3); }
.footer-contact li {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: var(--s-3);
  align-items: start;
  font-size: var(--t-sm);
  line-height: var(--lh-snug);
  margin: 0;
}
.footer-contact li > span:first-child {
  opacity: .55;
  font-size: 13px;
  line-height: 1.5;
  text-align: center;
}
/* The address is the one item that wraps; balance it so "United States." does
   not sit alone on a second line. */
.footer-contact li:first-child > span:last-child { text-wrap: balance; }

.footer-socials,
.site-footer .utility-widget { display: flex; gap: var(--s-3); margin-top: var(--s-6); }
.footer-socials a,
.site-footer a[href*="facebook"],
.site-footer a[href*="youtube"],
.site-footer a[href*="instagram"],
.site-footer a[href*="twitter"],
.site-footer a[href*="x.com"] {
  display: grid; place-items: center;
  width: 38px; height: 38px;
  border-radius: var(--r-full);
  background: var(--ground-soft);
  transition: background var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.footer-socials a:hover { background: var(--brand); color: var(--white); transform: translateY(-2px); }

/* ── Footer bottom ─────────────────────────────────────────────────────────*/

.footer-bottom {
  padding-block: var(--s-5);
  border-top: 1px solid var(--ground-line);
  font-size: var(--t-xs);
  color: var(--on-ground-muted);
}
.footer-bottom .wrap {
  display: flex;
  justify-content: space-between;
  gap: var(--s-4);
  flex-wrap: wrap;
  align-items: center;
}

@media (max-width: 640px) {
  .footer-inner { padding-block: var(--s-12) var(--s-8); gap: var(--s-8); }
  .footer-bottom .wrap { flex-direction: column; align-items: flex-start; gap: var(--s-2); }
}

/* ── Pagination ────────────────────────────────────────────────────────────*/

.pagination { display: flex; gap: var(--s-2); justify-content: center; margin-top: var(--s-10); flex-wrap: wrap; }
.pagination .page-numbers {
  display: grid; place-items: center;
  min-width: 40px; height: 40px; padding: 0 var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-size: var(--t-sm); font-weight: 500;
  color: var(--text);
}
.pagination .page-numbers:hover { border-color: var(--brand); color: var(--brand); }
.pagination .page-numbers.current { background: var(--brand); border-color: var(--brand); color: var(--white); }

/* ── Back to top ───────────────────────────────────────────────────────────*/

.to-top {
  position: fixed;
  right: var(--s-5); bottom: var(--s-5);
  width: 44px; height: 44px;
  display: grid; place-items: center;
  background: var(--brand); color: var(--white);
  border: 0; border-radius: var(--r-full);
  box-shadow: var(--shadow-lift);
  cursor: pointer;
  opacity: 0; visibility: hidden;
  transform: translateY(10px);
  transition: opacity var(--med) var(--ease), transform var(--med) var(--ease), visibility var(--med);
  z-index: 90;
}
.to-top.is-visible { opacity: 1; visibility: visible; transform: translateY(0); }
.to-top:hover { background: var(--brand-hover); color: var(--white); }

/* ── Empty state ───────────────────────────────────────────────────────────*/

.empty { text-align: center; padding: var(--s-16) var(--s-5); }
.empty h2 { font-size: var(--t-xl); color: var(--text); margin-bottom: var(--s-2); }
.empty p { color: var(--text-soft); max-width: 42ch; margin: 0 auto var(--s-6); }

/* ── Person card ───────────────────────────────────────────────────────────
   Trustees, executive committee, priests. A portrait crop rather than the
   3:2 landscape used for event cards — a headshot cropped to landscape loses
   the head.                                                                */

.person-card__photo { aspect-ratio: 4 / 5; overflow: hidden; background: var(--surface-sunk); }
.person-card__photo img { width: 100%; height: 100%; object-fit: cover; object-position: center top; }

.person-card__role {
  font-size: var(--t-sm);
  color: var(--text-soft);
  line-height: var(--lh-snug);
}
.person-card__role p { margin: 0; }
.person-card__role p + p { margin-top: var(--s-2); }
/* The role is often the first line in bold; let it carry the accent. */
.person-card__role strong { color: var(--brand); font-weight: 600; }

/* A card with no photograph should not look like one that failed to load. */
.person-card:not(:has(.person-card__photo)) .card__body { padding-top: var(--s-6); }
.person-card:not(:has(.person-card__photo)) {
  border-top: 3px solid var(--brand-line);
}

/* ── Definition list inside a card ─────────────────────────────────────────
   Priest details. Two columns so the labels form a spine and the values
   align, rather than a run of "Label: value" sentences.                    */

.detail-list {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s-2) var(--s-4);
  font-size: var(--t-sm);
  margin: var(--s-3) 0 0;
}
.detail-list dt {
  font-size: var(--t-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--track-wide);
  color: var(--text-soft);
  padding-top: 2px;
}
.detail-list dd { margin: 0; color: var(--text-strong); overflow-wrap: anywhere; }

@media (max-width: 420px) {
  .detail-list { grid-template-columns: 1fr; gap: 0; }
  .detail-list dd { margin-bottom: var(--s-3); }
}

/* ── Aarti ─────────────────────────────────────────────────────────────────*/

.aarti-group {
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
}
.aarti-item { padding: var(--s-4) var(--s-5); }
.aarti-item + .aarti-item { border-top: 1px solid var(--line); }
.aarti-item:nth-child(odd) { background: var(--surface-sunk); }

.aarti-item__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
}
.aarti-item__title {
  font-size: var(--t-base);
  font-weight: 600;
  color: var(--text-strong);
  margin: 0;
}

/* Native audio controls, sized to sit under the title rather than beside it —
   the control bar has no useful small form. */
.aarti-item__audio {
  width: 100%;
  height: 38px;
  margin-top: var(--s-3);
}

/* ── Chapter list ──────────────────────────────────────────────────────────
   Satcharitra. Numbered, because the chapters are read in order and the
   number is how people find their place.                                   */

.chapter-list {
  list-style: none;
  padding: 0;
  counter-reset: chapter;
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
}
.chapter-list__item {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-3) var(--s-5);
  counter-increment: chapter;
}
.chapter-list__item + .chapter-list__item { border-top: 1px solid var(--line); }
.chapter-list__item:hover { background: var(--brand-tint); }

.chapter-list__item::before {
  content: counter(chapter);
  flex-shrink: 0;
  min-width: 1.9rem;
  font-size: var(--t-sm);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-soft);
}
.chapter-list__title {
  flex: 1;
  font-weight: 500;
  color: var(--text-strong);
  line-height: var(--lh-snug);
}
.chapter-list__item:hover .chapter-list__title { color: var(--brand); }

/* ── Empty page ────────────────────────────────────────────────────────────
   A page template that renders nothing leaves a white void between the hero
   and the footer, which reads as broken rather than empty. A minimum height
   keeps the page proportionate while the content is sorted out.            */

.band:not(:has(*:not(:empty))) { min-height: 0; }
main > .band:only-of-type { min-height: 40vh; }

/* The logo is a colour lockup drawn for a white page. On maroon it needs a
   little lift or the darker parts of the mark disappear into the band. */
.site-footer img.footer-logo { filter: brightness(1.08) saturate(1.05); }


/* ── About layout ──────────────────────────────────────────────────────────
   Text and a portrait image. The image column is fixed rather than an equal
   half: at 50/50 the prose runs to ~90 characters, well past comfortable.
   The image also sticks while the text scrolls, since it is context rather
   than a step in the reading.                                               */

.about-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 340px);
  gap: var(--s-10);
  align-items: start;
}
.about-figure {
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lift);
  margin: 0;
  position: sticky;
  top: calc(var(--s-6) + 78px);
}
.about-figure img { width: 100%; height: auto; }

@media (max-width: 900px) {
  .about-split { grid-template-columns: 1fr; gap: var(--s-8); }
  .about-figure { position: static; max-width: 420px; }
}

/* ── Deities ───────────────────────────────────────────────────────────────
   The principal deity leads at full width; the rest follow as an even grid.
   The previous build hid all descriptive text with display:none and showed a
   photo grid of names, which delivered every word to the browser and then
   concealed it.                                                             */

.deity-feature {
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1fr);
  gap: var(--s-10);
  align-items: start;
}

.deity-feature__media {
  margin: 0;
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lift);
  /* Murti photography is vertical. A landscape crop takes the head off. */
  aspect-ratio: 4 / 5;
  background: var(--surface-sunk);
}
.deity-feature__media img { width: 100%; height: 100%; object-fit: cover; object-position: center top; }

.deity-feature__name {
  font-size: var(--t-3xl);
  margin: 0 0 var(--s-5);
}

/* The description was written as continuous prose, so it wants the reading
   measure rather than the full column. */
.deity-feature__body .prose { max-width: var(--measure); }
.deity-feature__body .prose > *:first-child { margin-top: 0; }

@media (max-width: 900px) {
  .deity-feature { grid-template-columns: 1fr; gap: var(--s-6); }
  .deity-feature__media { max-width: 420px; aspect-ratio: 1; }
}

/* ── Deity cards ───────────────────────────────────────────────────────────*/

.deity-card__media {
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--surface-sunk);
}
.deity-card__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center top;
  transition: transform var(--med) var(--ease);
}
.deity-card:hover .deity-card__media img { transform: scale(1.03); }

.deity-card__text {
  font-size: var(--t-sm);
  color: var(--text-soft);
  line-height: var(--lh-snug);
}
.deity-card__text p { margin: 0; max-width: none; }
.deity-card__text p + p { margin-top: var(--s-2); }

/* Cards in a row hold different amounts of text. Clamping keeps the grid even
   without hiding the text outright — the full description is one tap away on
   the shrine itself, and a card is a summary, not the page. */
.deity-card__text {
  display: -webkit-box;
  -webkit-line-clamp: 5;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

@supports not (-webkit-line-clamp: 5) {
  .deity-card__text { max-height: 7.5em; overflow: hidden; }
}

/* Programme cards carry long labels ("Vishnu Sahasranama Parayan · Wednesday")
   which do not fit two-up. One column, time on the left as the anchor. */
.band--sunk .timings__rows { grid-template-columns: 1fr; }
.band--sunk .timings__row {
  display: grid;
  grid-template-columns: 6.2rem 1fr;
  gap: var(--s-4);
  align-items: baseline;
  border-right: 0 !important;
  padding-block: var(--s-3);
}
.band--sunk .timings__row:nth-child(2) { border-top: 1px solid var(--line); }
.band--sunk .timings__time { font-size: var(--t-base); font-weight: 600; }
.band--sunk .timings__label { margin-top: 0; color: var(--text-strong); }

@media (max-width: 520px) {
  .band--sunk .timings__row { grid-template-columns: 1fr; gap: 0; }
}

/* ── Edition list ──────────────────────────────────────────────────────────
   Satcharitra languages. The whole row is the link — a language name is two
   words and the previous build put a separate "Know More" button beside it,
   which is a smaller target than the row it sits in.                        */

.edition-list {
  list-style: none;
  padding: 0;
  margin: 0;
  counter-reset: edition;
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
}
.edition-list__item { counter-increment: edition; }
.edition-list__item + .edition-list__item { border-top: 1px solid var(--line); }

.edition-list__link {
  display: grid;
  grid-template-columns: 2.2rem 1fr auto auto;
  gap: var(--s-4);
  align-items: center;
  padding: var(--s-4) var(--s-5);
  color: inherit;
  transition: background var(--fast) var(--ease);
}
.edition-list__link::before {
  content: counter(edition);
  font-size: var(--t-sm);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-soft);
}
.edition-list__link:hover { background: var(--brand-tint); color: inherit; }

.edition-list__name {
  font-size: var(--t-lg);
  font-weight: 500;
  color: var(--text-strong);
  /* Tamil, Telugu, Kannada and Devanagari all sit lower than Latin at the same
     size; a little extra line height stops the descenders clipping. */
  line-height: 1.5;
}
.edition-list__link:hover .edition-list__name { color: var(--brand); }

.edition-list__meta { font-size: var(--t-sm); color: var(--text-soft); white-space: nowrap; }

.edition-list__chev {
  color: var(--line-strong);
  transition: transform var(--fast) var(--ease), color var(--fast) var(--ease);
}
.edition-list__link:hover .edition-list__chev { color: var(--brand); transform: translateX(3px); }

@media (max-width: 520px) {
  .edition-list__link { grid-template-columns: 1.8rem 1fr auto; gap: var(--s-3); padding: var(--s-4); }
  .edition-list__chev { display: none; }
}

/* Chapter rows inside an edition need the download button to keep its place. */
.chapter-list__item { gap: var(--s-4); }
.chapter-list__item .btn { flex-shrink: 0; }

/* ── Notice grid ───────────────────────────────────────────────────────────
   The temple's event posters. These are designed artwork, not photographs —
   they carry their own type, border and background, so the card adds nothing
   but a shadow and a hover. Cropping them would cut off the text they were
   made to carry, so they keep their own aspect ratio.                       */

.notice-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr));
  gap: var(--s-5);
  align-items: start;
}

.notice-card {
  display: block;
  border-radius: var(--r);
  overflow: hidden;
  background: var(--surface-sunk);
  box-shadow: var(--shadow);
  transition: box-shadow var(--med) var(--ease), transform var(--med) var(--ease);
}
.notice-card img { width: 100%; height: auto; display: block; }

a.notice-card:hover {
  box-shadow: var(--shadow-lift);
  transform: translateY(-3px);
}
a.notice-card:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }

/* ── Teaching band ─────────────────────────────────────────────────────────
   The one pause in a page that is otherwise grid after grid, and the only
   place the maroon ground appears above the footer.                        */

.teaching {
  background: var(--ground);
  color: var(--on-ground);
  padding-block: clamp(3rem, 2.2rem + 3.5vw, 5rem);
  position: relative;
  overflow: hidden;
  text-align: center;
}
.teaching::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(70% 120% at 50% 0%, rgba(240, 153, 29, .16), transparent 62%);
  pointer-events: none;
}
.teaching > * { position: relative; z-index: 1; }

.teaching__quote { margin: 0; border: 0; padding: 0; }

.teaching__quote p {
  font-size: clamp(1.24rem, 1rem + 1.3vw, 1.8rem);
  font-weight: 300;
  line-height: 1.5;
  letter-spacing: -0.012em;
  color: var(--on-ground);
  margin: 0 auto;
  max-width: 34ch;
  text-wrap: balance;
}

/* No quotation-mark ornament. It rendered as the literal text "C" because
   the escape was written double-backslashed, and the band reads cleaner without
   it. A short saffron rule marks the band instead. */
.teaching__quote::before {
  content: '';
  display: block;
  width: 40px;
  height: 2px;
  background: var(--saffron-400);
  border-radius: 2px;
  margin: 0 auto var(--s-6);
  opacity: .7;
}

.teaching__cite {
  display: block;
  margin-top: var(--s-6);
  font-size: var(--t-sm);
  font-style: normal;
  font-weight: 600;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--saffron-400);
}

/* ── Ways to serve ─────────────────────────────────────────────────────────*/

.serve-grid {
  display: grid;
  /* auto-FILL, not auto-fit.
     With auto-fit, two cards stretched to half the page each — a card holding
     three lines of text was 550px wide with the text floating in it. auto-fill
     keeps the track at its natural size and the row is centred instead. */
  grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr));
  gap: var(--s-5);
  max-width: 1000px;
  margin-inline: auto;
  justify-content: center;
}
/* Two or three cards centre rather than spanning the full width. */
.serve-grid:has(> :nth-child(2):last-child) { max-width: 660px; }
.serve-grid:has(> :nth-child(3):last-child) { max-width: 900px; }

.serve-card {
  display: flex;
  flex-direction: column;
  padding: var(--s-6) var(--s-5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.serve-card:hover { border-color: var(--brand-line); box-shadow: var(--shadow-lift); }

.serve-card__icon {
  font-size: 26px;
  line-height: 1;
  display: grid;
  place-items: center;
  width: 52px; height: 52px;
  border-radius: var(--r-full);
  background: var(--brand-tint);
  margin-bottom: var(--s-4);
}
.serve-card__title { font-size: var(--t-lg); margin: 0 0 var(--s-2); }
.serve-card__text {
  font-size: var(--t-sm);
  color: var(--text-soft);
  line-height: var(--lh-snug);
  margin: 0 0 var(--s-5);
  max-width: none;
}
/* Buttons line up across the row whatever the text length. */
.serve-card__cta { margin-top: auto; align-self: flex-start; }

/* On a tinted ground a shadow reads as dirt rather than lift. */
.band--tint .subscribe__item { box-shadow: none; border-color: var(--brand-line); }

/* ── Rail ──────────────────────────────────────────────────────────────────
   A scroll-snap carousel with no library.

   The old site used Owl Carousel — 40KB plus jQuery — to rotate through eight
   event posters, of which seven were only seen by someone who waited. Native
   scroll snap does the same job in CSS, is draggable, keyboard-scrollable, and
   works before any JavaScript loads.

   Three cards visible with the fourth cut off: that cut edge is what tells
   someone there is more, which a rotator never does.                         */

.rail {
  /* The scroller is the width of the wrap; without this the last card bled
     past the right edge of the page instead of being clipped by it. */
  max-width: 100%;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(260px, calc((100% - var(--s-5) * 3) / 4));
  gap: var(--s-5);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  /* Cards stretch to the tallest, so the row has one baseline. */
  align-items: stretch;
  /* Room for the hover lift, which the scroller would otherwise clip. */
  padding-block: var(--s-1) var(--s-2);

  /* The scrollbar is hidden. It was a grey bar sitting under the row saying
     nothing the cut-off fourth card does not already say, and it moved the
     card bottoms up and down as the browser showed and hid it. The arrows and
     the cut edge are the affordance. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.rail::-webkit-scrollbar { display: none; }
.rail:focus-visible { outline: 2px solid var(--brand); outline-offset: 4px; border-radius: var(--r); }

.rail__item { scroll-snap-align: start; min-width: 0; }

.rail__btn {
  display: grid;
  place-items: center;
  width: 36px; height: 36px;
  border: 1px solid var(--line);
  border-radius: var(--r-full);
  background: var(--surface);
  color: var(--text-secondary);
  font-size: 15px;
  cursor: pointer;
  transition: border-color var(--fast) var(--ease), color var(--fast) var(--ease);
}
.rail__btn:hover { border-color: var(--brand); color: var(--brand); }
.rail__btn:disabled { opacity: .35; cursor: default; }
.rail__btn:disabled:hover { border-color: var(--line); color: var(--text-secondary); }

@media (max-width: 1100px) {
  .rail { grid-auto-columns: minmax(240px, calc((100% - var(--s-5) * 2) / 3)); }
}
@media (max-width: 860px) {
  .rail { grid-auto-columns: minmax(230px, calc((100% - var(--s-4)) / 2)); gap: var(--s-4); }
}
@media (max-width: 560px) {
  /* One and a bit on a phone — the bit is the affordance. */
  .rail { grid-auto-columns: 78%; }
  .rail__btn { display: none; }
}

/* ── Event card ────────────────────────────────────────────────────────────
   Event artwork is a poster with its own type and border. It keeps its aspect
   ratio rather than being cropped to a card shape — a crop cuts off the words
   the poster was made to carry.                                             */

.event-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
  color: inherit;
  transition: box-shadow var(--med) var(--ease), border-color var(--med) var(--ease), transform var(--med) var(--ease);
}
.event-card:hover {
  border-color: var(--brand-line);
  box-shadow: var(--shadow-lift);
  transform: translateY(-3px);
  color: inherit;
}

/* The poster is cropped to a fixed ratio here.
 *
 * My first pass kept the natural ratio so the artwork was never cut — but the
 * temple's posters range from square to tall, so a row of them had no shared
 * baseline and read as broken. At 260px wide none of the poster's text is
 * legible anyway; the full artwork is on the event page, uncropped.
 *
 * The crop is anchored high because these posters put their title at the top. */
.event-card__media {
  aspect-ratio: 4 / 3;
  background: var(--saffron-50);
  overflow: hidden;
  line-height: 0;
}
/* Contained, for the same reason as the hero: an event poster is read, not
   looked at. The card still keeps a fixed ratio so the row shares a baseline —
   the poster letterboxes inside it rather than being cut to fit. */
.event-card__media img {
  width: 100%; height: 100%;
  object-fit: contain;
  display: block;
  transition: transform var(--med) var(--ease);
}
.event-card:hover .event-card__media img { transform: scale(1.02); }

.event-card__body {
  padding: var(--s-4) var(--s-5) var(--s-5);
  display: flex;
  flex-direction: column;
  flex: 1;
}
.event-card__title {
  font-size: var(--t-base);
  font-weight: 600;
  line-height: var(--lh-snug);
  color: var(--text-strong);
  margin: 0 0 var(--s-3);
  /* Two lines, always. One-line titles left a gap that pushed "Read more" up
     on some cards and not others, so no two sat at the same height. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: calc(2 * var(--lh-snug) * 1em);
}
.event-card:hover .event-card__title { color: var(--brand); }

.event-card__more {
  margin-top: auto;
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--brand);
}

/* ── Widget areas ──────────────────────────────────────────────────────────
   functions.php registers these wrappers; nothing styled them, so a widget
   dropped into a footer column or the sidebar rendered unstyled. Found by
   sweeping every class used in a template against every class defined in CSS
   — the same sweep that found .timings had lost its rule entirely.          */

.footer-widget + .footer-widget { margin-top: var(--s-8); }
.footer-widget ul { list-style: none; padding: 0; margin: 0; }
.footer-widget li + li { margin-top: var(--s-2); }
.footer-widget a { display: block; padding: var(--s-1) 0; font-size: var(--t-sm); }

.widget { margin-bottom: var(--s-8); }
.widget:last-child { margin-bottom: 0; }
.widget ul { list-style: none; padding: 0; margin: 0; }
.widget li { padding-block: var(--s-2); border-bottom: 1px solid var(--line); }
.widget li:last-child { border-bottom: 0; }

.widget-title {
  font-size: var(--t-sm);
  font-weight: 700;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--brand);
  margin: 0 0 var(--s-3);
  padding-bottom: var(--s-2);
  border-bottom: 1px solid var(--brand-line);
}

/* The old theme's section-heading class, still present in migrated content. */
.heading { font-weight: 700; letter-spacing: -0.012em; }

/* ── Programme grid ────────────────────────────────────────────────────────
   Weekly, monthly and festivals. Three columns where all three are filled,
   two where the festivals field is empty — auto-fit rather than a fixed three,
   so the office leaving one blank does not leave a hole.                    */

.programme-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: var(--s-5);
  align-items: start;
}

/* Three narrower columns means the rows go one-per-line sooner. */
.programme-grid .timings__rows { grid-template-columns: 1fr; }
.programme-grid .timings__row { border-right: 0 !important; }
.programme-grid .timings__row:nth-child(2) { border-top: 1px solid var(--line); }
.programme-grid .timings__row {
  display: grid;
  grid-template-columns: 5.4rem 1fr;
  gap: var(--s-4);
  align-items: baseline;
  padding-block: var(--s-3);
}
.programme-grid .timings__time {
  font-size: var(--t-base);
  font-weight: 600;
  line-height: var(--lh-snug);
}
/* A date range wraps rather than forcing the column wider than the card. */
.programme-grid .timings__time .sep { white-space: normal; }
.programme-grid .timings__label { margin-top: 0; color: var(--text-strong); }

@media (max-width: 480px) {
  .programme-grid .timings__row { grid-template-columns: 1fr; gap: 0; }
}

/* ── Community grid ────────────────────────────────────────────────────────
   Four ways in: WhatsApp, newsletter, temple volunteering, Sai Kitchen. The
   whole card is the link — these go to external sign-up forms and a small
   button is a smaller target than the card it sits in.                     */

.community-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
  gap: var(--s-5);
  align-items: stretch;
}

.community-card {
  display: flex;
  flex-direction: column;
  padding: var(--s-6) var(--s-5);
  background: var(--surface);
  border: 1px solid var(--brand-line);
  border-radius: var(--r);
  color: inherit;
  transition: border-color var(--fast) var(--ease),
              box-shadow var(--fast) var(--ease),
              transform var(--fast) var(--ease);
}
.community-card:hover {
  border-color: var(--brand);
  box-shadow: var(--shadow-lift);
  transform: translateY(-3px);
  color: inherit;
}
.community-card:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }

/* Reserve the icon's space whether or not there is an icon.
   Two of these four have images and two do not, and without this the cards
   without one started 72px higher than the cards with one — the row read as
   four different components rather than one set. */
.community-card::before {
  content: '';
  display: block;
  height: 0;
}
.community-card:not(:has(.community-card__icon))::before {
  height: calc(56px + var(--s-4));
}

.community-card__icon {
  width: 56px; height: 56px;
  object-fit: contain;
  border-radius: var(--r-sm);
  margin-bottom: var(--s-4);
}
.community-card__title {
  font-size: var(--t-lg);
  margin: 0 0 var(--s-2);
  line-height: var(--lh-snug);
}
.community-card:hover .community-card__title { color: var(--brand); }
.community-card__text {
  font-size: var(--t-sm);
  color: var(--text-soft);
  line-height: var(--lh-snug);
  margin: 0 0 var(--s-5);
  max-width: none;
}
.community-card__cta {
  margin-top: auto;
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--brand);
}

/* ── Temple Events, three columns ──────────────────────────────────────────
   Weekly, monthly, and whatever is coming up. The third is a field rather
   than a rule, because festival dates move every year.                      */

.programme-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: var(--s-5);
  align-items: start;
}

/* Three narrow columns cannot hold a two-up row inside each card. */
.programme-grid .timings__rows { grid-template-columns: 1fr; }
.programme-grid .timings__row {
  display: grid;
  /* max-content, not a fixed width: the times column needs 5.4rem but the
     festivals column carries dates — "13 August – 10 September" is three times
     that. Each card sizes its own value column to its longest entry, so the
     rows inside one card still line up. */
  grid-template-columns: minmax(4.6rem, max-content) 1fr;
  gap: var(--s-3);
  align-items: baseline;
  border-right: 0 !important;
  padding-block: var(--s-3);
}
.programme-grid .timings__row:nth-child(2) { border-top: 1px solid var(--line); }
.programme-grid .timings__time {
  font-size: var(--t-base);
  font-weight: 600;
  line-height: var(--lh-snug);
}
/* A date range wraps rather than forcing the column wider than the card. */
.programme-grid .timings__time .sep { white-space: normal; }
.programme-grid .timings__label { margin-top: 0; color: var(--text-strong); }

@media (max-width: 520px) {
  .programme-grid .timings__row { grid-template-columns: 1fr; gap: 0; }
}

/* ── Join our Temple Community ─────────────────────────────────────────────
   Four ways in, each a card that is entirely a link — the whole card is the
   target rather than a small button inside it.                              */

.community-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
  gap: var(--s-5);
  align-items: stretch;
}

.community-card {
  display: flex;
  flex-direction: column;
  padding: var(--s-6) var(--s-5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  color: inherit;
  transition: border-color var(--fast) var(--ease),
              box-shadow var(--fast) var(--ease),
              transform var(--fast) var(--ease);
}
.community-card:hover {
  border-color: var(--brand-line);
  box-shadow: var(--shadow-lift);
  transform: translateY(-2px);
  color: inherit;
}
.community-card:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }

/* Reserve the icon's space whether or not there is an icon.
   Two of these four have images and two do not, and without this the cards
   without one started 72px higher than the cards with one — the row read as
   four different components rather than one set. */
.community-card::before {
  content: '';
  display: block;
  height: 0;
}
.community-card:not(:has(.community-card__icon))::before {
  height: calc(56px + var(--s-4));
}

.community-card__icon {
  width: 56px; height: 56px;
  object-fit: contain;
  border-radius: var(--r-sm);
  margin-bottom: var(--s-4);
}
.community-card__title {
  font-size: var(--t-lg);
  font-weight: 600;
  color: var(--text-strong);
  margin: 0 0 var(--s-2);
  line-height: var(--lh-snug);
}
.community-card:hover .community-card__title { color: var(--brand); }
.community-card__text {
  font-size: var(--t-sm);
  color: var(--text-soft);
  line-height: var(--lh-snug);
  margin: 0 0 var(--s-5);
  max-width: none;
}
.community-card__cta {
  margin-top: auto;
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--brand);
}

/* On a tinted band a shadow reads as dirt rather than lift. */
.band--tint .community-card { box-shadow: none; border-color: var(--brand-line); }
.band--tint .community-card:hover { box-shadow: var(--shadow-lift); }

/* ── Sign-up link in a timings row ─────────────────────────────────────────
   The festivals column carries registration links. On its own line under the
   entry rather than inline, so a long festival name and a link do not compete
   for the same row.                                                          */

.timings__link {
  grid-column: 1 / -1;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: var(--s-2);
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--brand);
}
.timings__link::after { content: '→'; transition: transform var(--fast) var(--ease); }
.timings__link:hover { color: var(--brand-hover); }
.timings__link:hover::after { transform: translateX(3px); }

/* A festival entry with no time still needs its label to span the row. */
.programme-grid .timings__row:not(:has(.timings__time)) .timings__label { grid-column: 1 / -1; }

/* ── Utility bar, brand-coloured ───────────────────────────────────────────
   The previous site gave each social link its own brand colour and set Live
   Darshan, Login and Sign Up as filled buttons. This theme flattened all of it
   to plain text on saffron, which reads as a row of links rather than as the
   set of actions it is — and the social icons in particular vanished into the
   background.

   Each network keeps its own colour. That is the one place on the site where
   brand colours other than the temple's belong, because a Facebook icon that
   is not Facebook blue takes a moment longer to recognise.                  */

.utility-bar {
  background: var(--white);
  color: var(--text);
  border-bottom: 1px solid var(--line);
}
.utility-bar a { color: var(--text-secondary); }
.utility-bar a:hover { color: var(--brand); }

/* Slimmer than the original bar — the icons are 28px rather than 34px and the
   padding is tighter, so the row costs about 40px instead of 52. */
.utility-bar .wrap {
  gap: var(--s-3);
  min-height: 42px;
  padding-block: var(--s-1);

}
.utility-bar .social-icons a { width: 28px; height: 28px; }
.utility-bar .social-icons svg { width: 15px; height: 15px; }
.utility-bar a[href*="devotee_auth"] { width: 28px; height: 28px; }

/* Social icons as brand tiles. */
.utility-bar .social-icons {
  display: flex;
  gap: var(--s-2);
  align-items: center;
}
.utility-bar .social-icons a {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--r-sm);
  color: #fff !important;
  transition: transform var(--fast) var(--ease), filter var(--fast) var(--ease);
}
.utility-bar .social-icons a:hover { transform: translateY(-1px); filter: brightness(1.1); }
.utility-bar .social-icons svg { width: 17px; height: 17px; fill: currentColor; }

/* Matched on the href, same as the icon replacement — so these survive the
   widget being rebuilt with different classes. */
.utility-bar .social-icons a[href*="facebook.com"]  { background: #1877F2; }
.utility-bar .social-icons a[href*="youtube.com"]   { background: #FF0000; }
.utility-bar .social-icons a[href*="instagram.com"] {
  background: linear-gradient(45deg, #F58529, #DD2A7B 50%, #8134AF 75%, #515BD4);
}
.utility-bar .social-icons a[href*="x.com"],
.utility-bar .social-icons a[href*="twitter.com"]   { background: #000; }
.utility-bar .social-icons a[href*="wa.me"],
.utility-bar .social-icons a[href*="whatsapp.com"]  { background: #25D366; }

/* Live Darshan, Login and Sign Up as buttons. Matched on the link's own
   destination and text so the widget markup does not have to change. */
.utility-bar .red-color a,
.utility-bar a[href*="live-dharshan"],
.utility-bar a[href*="/sign-up"]:not([href*="devotee_auth"]) {
  display: inline-block;
  padding: var(--s-2) var(--s-4);
  border-radius: var(--r-sm);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: .02em;
  text-transform: uppercase;
  white-space: nowrap;
  color: #fff !important;
  transition: filter var(--fast) var(--ease);
}
.utility-bar .red-color a,
.utility-bar a[href*="live-dharshan"] { background: var(--ground); }
.utility-bar a[href*="/login"],
.utility-bar a[href*="/signup"],
.utility-bar a[href*="/sign-up"] { background: var(--brand); }
.utility-bar .red-color a:hover,
.utility-bar a[href*="live-dharshan"]:hover,
.utility-bar a[href*="/login"]:hover,
.utility-bar a[href*="/signup"]:hover { filter: brightness(1.12); color: #fff !important; }

/* The widget renders as a <ul>; strip the list styling so it sits inline. */
.utility-bar ul { flex-wrap: wrap; justify-content: flex-end; }
.utility-bar li { display: flex; align-items: center; }

@media (max-width: 700px) {
  .utility-bar .wrap { justify-content: center; }
  .utility-bar .social-icons a { width: 30px; height: 30px; }
  .utility-bar .social-icons svg { width: 15px; height: 15px; }
  .utility-bar .red-color a,
  .utility-bar a[href*="live-dharshan"],
  .utility-bar a[href*="/login"],
  .utility-bar a[href*="/signup"] { padding: var(--s-1) var(--s-3); font-size: 11px; }
}

/* The utility items sit on their own row above the masthead — see header.php
   for why the single-row version was abandoned. The bar's own styling is
   further up this file. */

/* ── Account actions ───────────────────────────────────────────────────────
   Login and Sign Up as icons.

   As text they were the two widest items in a row that was already full, and
   "Sign Up" wrapped onto two lines at the end of it. As icons they take 30px
   each and the row fits.

   Outlined rather than filled: they are secondary to Live Darshan, which is
   what most visitors actually came for.                                     */

/* The temple's links carry the type in the query string —
   ?type=login and ?type=signup — so the attribute selectors have to match
   that as well as a path. */
.utility-bar a[href*="/login"],
.utility-bar a[href*="/signup"],
.utility-bar a[href*="/sign-up"],
.utility-bar a[href*="/register"],
.utility-bar a[href*="type=login"],
.utility-bar a[href*="type=signup"],
.utility-bar a[href*="devotee_auth"] {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1.5px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: none;
  color: var(--text-secondary) !important;
  text-transform: none;
  transition: border-color var(--fast) var(--ease), color var(--fast) var(--ease);
}
.utility-bar a[href*="/login"]:hover,
.utility-bar a[href*="/signup"]:hover,
.utility-bar a[href*="/sign-up"]:hover,
.utility-bar a[href*="/register"]:hover,
.utility-bar a[href*="type=login"]:hover,
.utility-bar a[href*="type=signup"]:hover,
.utility-bar a[href*="devotee_auth"]:hover {
  border-color: var(--brand);
  color: var(--brand) !important;
  background: var(--brand-tint);
}
.utility-bar a[href*="/login"] svg,
.utility-bar a[href*="/signup"] svg,
.utility-bar a[href*="/sign-up"] svg,
.utility-bar a[href*="/register"] svg,
.utility-bar a[href*="devotee_auth"] svg { width: 16px; height: 16px; fill: currentColor; }

/* Sign Up is filled, Login is outlined.
   Two identical outlined squares side by side gave no way to tell which was
   which without hovering. Filling one makes the pair read as a set with an
   obvious primary — and joining is the action the temple wants. */
.utility-bar a[href*="type=signup"],
.utility-bar a[href*="/signup"],
.utility-bar a[href*="/register"] {
  background: var(--brand-tint);
  border-color: var(--brand-line);
  color: var(--brand) !important;
}
.utility-bar a[href*="type=signup"]:hover,
.utility-bar a[href*="/signup"]:hover {
  background: var(--brand);
  color: #fff !important;
  border-color: var(--brand);
}

/* The word appears on hover, since the icon alone cannot carry it. */
.utility-bar a[href*="devotee_auth"],
.utility-bar a[href*="/login"],
.utility-bar a[href*="/signup"] { position: relative; }

.utility-bar a[href*="devotee_auth"]::after {
  content: attr(aria-label);
  position: absolute;
  top: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  padding: 3px 8px;
  border-radius: var(--r-sm);
  background: var(--ground);
  color: var(--on-ground);
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--fast) var(--ease);
  z-index: 10;
}
.utility-bar a[href*="devotee_auth"]:hover::after,
.utility-bar a[href*="devotee_auth"]:focus-visible::after { opacity: 1; }

/* ── Right edge ────────────────────────────────────────────────────────────
   Both header rows end on the same line.

   The menu's last link carries padding, so "About Us" stopped short of the
   wrap edge while the utility icons reached it — a visible step between the
   two rows. Adding an offset to the bar moved the icons the wrong way; the
   gap is after the menu, not before the icons.

   Taking the padding off the last link is the fix. It only affects the
   trailing edge, so the spacing between menu items is untouched — and the
   hover area lost is 16px of empty space beyond the last word.            */
.nav-primary > ul > li:last-child > a { padding-right: 0; }

@media (max-width: 1023px) {
  /* In the drawer the links are full-width rows, and the padding is what
     keeps the text off the edge. */
  .nav-primary > ul > li:last-child > a { padding-right: var(--s-4); }
}
