/* ==========================================================================
   components.css — Church Boilerplate
   --------------------------------------------------------------------------
   Component layer for the flagship homepage. Adapts to index.html (the single
   source of truth) and builds on the helpers already declared in base.css
   (.grid, .container, .t-*, .squircle, .edge, .edge-mask-x, .sheen base,
   motion base states behind .js, reduced-motion path).

   RULES OBSERVED:
   - ZERO raw hex / rgba. Every color, radius, shadow, easing, duration, space
     and z-index comes from var(--token) in tokens.css. The only literal colors
     are the standard #000 mask idioms (alpha-only) required for masking — same
     convention base.css already uses for .edge / .edge-mask-x.
   - One dominant accent (maroon). Warm + light only — no dark panels; the
     deepest surface is --surface-3.
   - Squircle + hairline-gradient-edge treatment is reused via .squircle .edge
     (defined in base.css); this file only extends component-specific shape.
   - Touch (hover:none / pointer:coarse) disables tilt visuals; tap targets ≥44px.
   - Full responsive pass: desktop showcase → tablet (16→8) → mobile (8→4),
     leaning on the grid collapse base.css already provides and tuning the
     bespoke nested grids (hero, life, services, invitation) by hand.
   - Complements base.css's prefers-reduced-motion block with component polish.

   ORDER
     1.  Shared shape / media primitives (.media, .media__inner, fallback fill)
     2.  Header (#site-header) + brand + nav pills + buttons
     3.  Hero (#hero) + warm radial glow
     4.  Section rhythm (.section, .section-head)
     5.  Life (#life) asymmetric tile grid + tiles + captions
     6.  Ticker (#ticker-values) marquee
     7.  Hizmetler (#pillars) — weekly-gatherings list + image stage
     8.  Invitation (#invitation) warm CTA + zoom-only MapLibre map
     9.  Footer (#site-footer)
     13. Responsive — tablet
     14. Responsive — mobile
     15. Touch / coarse pointer
     16. Reduced-motion component polish
   ========================================================================== */


/* ==========================================================================
   1. SHARED SHAPE / MEDIA PRIMITIVES
      .media       canonical squircle media shell (pairs with .squircle .edge)
      .media__inner clips the image/video; JS translates it for [data-parallax]
      Warm gradient fallback fill so a missing/slow image never looks broken.
   ========================================================================== */

.media {
  position: relative;
  display: block;
  /* Cap to the containing cell. Without this, a tile whose min-height exceeds
     its aspect-ratio height (e.g. a tall media tile) derives its WIDTH from that
     height (min-height × ratio) and overflows its grid cell on narrow screens.
     max-width pins it to the cell instead. */
  max-width: 100%;
  overflow: hidden;                 /* belt-and-braces clip for the squircle  */
  /* Warm tonal fallback: a soft paper→surface gradient with a faint maroon
     wash, so an empty/late media frame reads as an intentional warm tile. */
  background-color: var(--surface-2);
  background-image:
    linear-gradient(
      135deg,
      var(--surface-1) 0%,
      var(--surface-2) 52%,
      var(--surface-3) 100%),
    radial-gradient(
      120% 90% at 18% 12%,
      var(--accent-soft) 0%,
      transparent 60%);
  background-blend-mode: normal;
  isolation: isolate;               /* keep .edge / .sheen stacking contained */
  aspect-ratio: 4 / 3;              /* sensible default; overridden per slot   */
}

/* The clipping wrapper that holds the actual <img>/<video>. JS drifts THIS
   element for parallax, so it overflows its parent and the parent clips it. */
.media__inner {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: inherit;
  z-index: 0;                        /* sits below .edge::after (1) + .sheen (2)*/
}

/* Parallax needs vertical headroom so the drift never reveals an empty edge.
   JS translates within ±amount; 112% height + centered top covers it. */
.js [data-parallax] .media__inner {
  height: 116%;
  top: -8%;
}

.media__inner img,
.media__inner video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Media never captures the pointer, so pointermove/enter/leave always reach
     the tile container (drives parallax + reflection) and the z5 .tile__link
     stays clickable — identical for <img> and <video>. */
  pointer-events: none;
  /* gentle warm settle on load; honored-away under reduced-motion below */
  transition: transform var(--dur-slower) var(--ease-out-expo),
              filter var(--dur-slow) var(--ease-out-quart);
}

/* Subtle scale-in on hover for tiltable cards (paired with the sheen sweep). */
.js [data-tilt]:hover .media__inner img,
.js [data-tilt]:hover .media__inner video {
  transform: scale(1.035);
}

/* Tilt cards lift with a warm soft shadow on hover (gray-free). */
.js [data-tilt] {
  box-shadow: var(--shadow-sm);
}
.js [data-tilt]:hover {
  box-shadow: var(--shadow-card-hover);
}


/* ==========================================================================
   2. HEADER  (#site-header)
      Sticky, translucent, backdrop-blurred bar. .container is the flex row
      (.site-header__inner is also applied to it). JS toggles .is-scrolled.
   ========================================================================== */

.site-header {
  position: fixed;          /* overlay the hero so its white reaches y=0 (no warm body strip) */
  top: 0;
  left: 0;
  right: 0;
  z-index: var(--z-sticky);
  background: transparent;  /* the bar itself NEVER adds a surface — no band */
  /* transition already declared in base.css for #site-header */
}

/* The bar adds nothing at any scroll state: transparent, no blur, no border,
   no shadow. Only the logo chip + the menu island carry surfaces. */
.site-header.is-scrolled,
.site-header.is-compact { background: transparent; }

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  padding-block: var(--space-3);
  min-height: clamp(3.5rem, 6vw, 4.5rem);
}

/* --- brand (badge + wordmark) --- */
.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  flex: 0 0 auto;
  color: var(--ink);
}

.brand__badge {
  display: inline-grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  background: transparent;           /* top state: just the maroon mark on white */
  color: var(--accent);              /* the monogram stroke is currentColor      */
  flex: 0 0 auto;
  position: relative;
  z-index: 2;                        /* above the wordmark so it occludes it      */
  border: 1px solid transparent;     /* animates to --line in the compact chip    */
  transition: background var(--dur-base) var(--ease-out-quart),
              border-color var(--dur-base) var(--ease-out-quart),
              box-shadow var(--dur-base) var(--ease-out-quart);
}
/* Compact: keep the white badge + maroon border (from the header rule below);
   just add a subtle lift so it reads when the header floats over content. */
.site-header.is-compact .brand__badge {
  box-shadow: var(--shadow-sm);
}
.brand__badge--lg {
  width: 3.75rem;
  height: 3.75rem;
}
/* The image mark (the Vakıf seal) inset inside the badge. The seal's artwork
   fills 98.8% of its own canvas — no bleed margin of its own — so the 60% inset
   here is what gives it breathing room inside the white chip, the same job the
   cross SVG's 0-100 viewBox padding used to do. 80% rather than the template's
   60%: that value was sized for a plain cross, and the seal carries a circular
   legend that needs the extra area to read. object-fit guards the ratio. */
.brand__mark { width: 80%; height: 80%; object-fit: contain; }

/* THE CHURCH'S OWN MARK in the header (Oct 2026). Replaced the Vakif seal, which
   now appears only in the footer membership badge.

   Height-sized, not box-fitted. The mark is 2.03:1 and its SVG viewBox is an A4
   artboard, so the artwork fills 95.8% of the width but only 66.9% of the
   height. Fitting it into the old 2.75rem SQUARE badge left 29x20 of visible ink
   at 390. Setting the HEIGHT to the same 2.75rem token and letting the width
   follow gives 60x29 of ink at every width, and keeps the header height exactly
   where it was, which a taller variant did not.

   flex: none so it never shrinks next to the wordmark. No chip, no border, no
   filter: the gradients are the brand asset. */
.brand__logo {
  display: block;
  height: 2.75rem;
  width: auto;
  flex: none;
}

/* Header logo — option 2: a white squircle badge with a thin maroon border and a
   flat maroon Latin cross. Scoped to .site-header; the FOOTER badge gets the same
   treatment via its own twin rule below. Same size/position/squircle radius as
   before, so the wordmark still slides behind it on .is-compact. Colours come
   from tokens (re-skinnable). */
.site-header .brand__badge {
  background: var(--surface-1);
  border: 1.5px solid var(--maroon);
}
/* Footer logo — IDENTICAL flat-cross mark: same white squircle badge + thin
   maroon border (the cross SVG is shared). Static — no self-draw, no slide. */
.site-footer .brand__badge {
  background: var(--surface-1);
  border: 1.5px solid var(--maroon);
}
/* The cross fills the badge; its 0–100 viewBox geometry carries the padding. */
.brand__cross { width: 100%; height: 100%; }

.brand__word {
  font-weight: var(--wght-semibold);
  font-variation-settings: "wght" var(--wght-semibold), "opsz" 22,
                           "ROND" var(--ROND-soft);
  letter-spacing: -0.01em;
  font-size: clamp(1rem, 0.95rem + 0.3vw, 1.1875rem);
  line-height: 1;
  white-space: nowrap;
  position: relative;
  z-index: 1;                /* below the badge so it tucks behind on collapse */
  transition: transform var(--dur-ui) var(--ease-hover), opacity var(--dur-ui) var(--ease-hover);
}
.brand__word-2 {
  color: var(--muted);
  font-weight: var(--wght-regular);
  font-variation-settings: "wght" var(--wght-regular), "opsz" 22,
                           "ROND" var(--ROND-soft);
}
/* Collapse: the wordmark slides left, tucks behind the badge, and fades out. */
.site-header.is-compact .brand__word {
  transform: translateX(-2.5rem);
  opacity: 0;
  pointer-events: none;
}

/* --- center meta (location · time) --- */
.site-header__meta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--muted);
  white-space: nowrap;
}
.site-header__sep { color: var(--accent); opacity: 0.7; }
.site-header__time { color: var(--ink); }

/* --- right nav: pills + filled CTA --- */
/* Right-side menus: the expanded nav (top state) + the compact icon button,
   grid-stacked in one cell on the right of the header. */
.site-header__menus { display: grid; }
.site-header__menus > * { grid-area: 1 / 1; justify-self: end; align-self: center; }

.site-header__nav {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex: 0 0 auto;
  /* Calm fade/slide out on collapse — synchronized with the toggle + wordmark. */
  transition: opacity var(--dur-ui) var(--ease-hover),
              transform var(--dur-ui) var(--ease-hover);
}
/* Collapse: the whole expanded menu (pills + CTA) fades/slides out. */
.site-header.is-compact .site-header__nav {
  opacity: 0;
  transform: translateY(-6px);
  pointer-events: none;
}

/* Compact control: a single squircle menu-icon button the nav collapses INTO.
   Positioned wrapper so the openable panel anchors to the button. */
.menu-compact { position: relative; }

.menu-toggle {
  width: 2.75rem;
  height: 2.75rem;
  display: inline-grid;
  place-items: center;
  /* At REST: no frame — just the clean grid icon. The box (fill + border + shadow)
     appears only on hover / keyboard focus (below). The transparent 1px border
     keeps the box model stable (border-box) so hover never reflows. */
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  box-shadow: none;
  color: var(--ink);
  cursor: pointer;
  /* Hidden in the top state; revealed only when compact. The 0.1s delay lets the
     pills fade out first, so the nav "settles into" the icon — calm, sequential. */
  opacity: 0;
  transform: scale(0.85);
  pointer-events: none;
  transition: opacity var(--dur-ui) var(--ease-hover) 0.1s,
              transform var(--dur-ui) var(--ease-hover) 0.1s,
              background var(--dur-hover) var(--ease-hover),
              border-color var(--dur-hover) var(--ease-hover),
              box-shadow var(--dur-hover) var(--ease-hover);
}
/* The box appears on hover AND keyboard focus (same look as the old resting box).
   The global :focus-visible maroon outline (base.css) also still shows. */
.menu-toggle:hover,
.menu-toggle:focus-visible {
  background: var(--surface-2);
  border-color: var(--line);
  box-shadow: var(--shadow-sm);
}
.menu-toggle__icon { width: 1.15rem; height: 1.15rem; }
.site-header.is-compact .menu-toggle {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

/* The openable 2×2 menu panel — the grid lives HERE, never in the bar. */
.menu-panel {
  position: absolute;
  top: calc(100% + 0.6rem);
  right: 0;
  z-index: 60;
  /* Single vertical column (NOT a 2×2 grid). */
  display: flex;
  flex-direction: column;
  min-width: 12rem;
  /* Same white squircle surface language as the logo chip + icon button
     (the corner-shape superellipse layer was removed project-wide, so a plain
     var(--r-md) radius matches the chip's rounding exactly). */
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-md, var(--shadow-sm));
  overflow: hidden;
  padding: 0.4rem;                   /* inset so rows don't touch the rounded corners */
  opacity: 0;
  transform: scale(0.96) translateY(-6px);
  transform-origin: top right;
  pointer-events: none;
  visibility: hidden;
  transition: opacity 0.3s var(--ease-out-quart),
              transform 0.4s var(--ease-out-expo),
              visibility 0s linear 0.4s;
}
.menu-panel.is-open {
  opacity: 1;
  transform: none;
  pointer-events: auto;
  visibility: visible;
  transition: opacity 0.3s var(--ease-out-quart),
              transform 0.4s var(--ease-out-expo),
              visibility 0s;
}
.menu-panel__item {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 44px;
  padding: 0.75rem 0.9rem;
  background: transparent;
  color: var(--ink);
  text-decoration: none;
  border-radius: var(--r-sm);        /* soft inner rounding on hover */
  font-weight: var(--wght-medium);
  font-variation-settings: "wght" var(--wght-medium), "opsz" 16,
                           "ROND" var(--ROND-soft);
  font-size: 0.9375rem;
  line-height: 1;
  white-space: nowrap;
  transition: background var(--dur-hover) var(--ease-hover), color var(--dur-hover) var(--ease-hover);
}
/* No divider lines between rows — the panel reads as clean spacing only; the
   item padding (above) gives the breathing room. Hover keeps its rounded fill. */
.menu-panel__item:hover { background: var(--surface-2); }
.menu-panel__item--cta { color: var(--accent); font-weight: var(--wght-semibold); }
.menu-panel__item--cta:hover { background: var(--accent-soft); } /* faint maroon tint, never dark */
/* "yakında" (not-built-yet) items: muted label + a small outlined tag. href="#"
   is preventDefault'd by the anchor handler, so they never navigate; the default
   cursor signals they're not yet active. Hover stays the subtle shared fill. */
.menu-panel__item.is-soon { color: var(--muted); cursor: default; }
.menu-soon {
  margin-left: auto;                 /* float the tag to the right of the row */
  padding: 0.15em 0.5em;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);     /* stays delineated even over the hover fill */
  background: var(--surface-1);
  color: var(--muted);
  font-size: 0.6875rem;
  font-weight: var(--wght-medium);
  font-variation-settings: "wght" var(--wght-medium);
  letter-spacing: 0.02em;
  line-height: 1.35;
}

.nav-pills {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.nav-pills__link {
  display: inline-flex;
  align-items: center;
  /* Labels must never break inside their own pill. Without this, "Neye
     İnanıyoruz?" and "İncil oku" wrapped to two lines at every width, which is
     what the client saw. .nav-pills__cta already had nowrap via .btn, which is
     why the 228px CTA was NOT the one wrapping. */
  white-space: nowrap;
  min-height: 2.5rem;
  padding: var(--space-2) var(--space-4);
  background: var(--surface-1);
  border: 1px solid var(--line);     /* visible hairline so the white pill reads on white */
  color: var(--ink);
  font-weight: var(--wght-medium);
  font-variation-settings: "wght" var(--wght-medium), "opsz" 16,
                           "ROND" var(--ROND-soft);
  /* 0.8125rem, NOT the template's 0.9375rem. This is what buys the breakpoint.
     At 0.9375rem the single-line row measures 1151px and needs a ~1490px
     viewport, which would show the pill row only to 1440-plus screens. At
     0.8125rem the row measures 1071px, which fits far lower and puts the row in
     front of ordinary desktop visitors, which is the point of having it.
     14.6px at the 1120px-and-up root (the root maxes at 18px there), so it does
     render smaller than the footer nav. That is an accepted trade, made
     deliberately: a navbar nobody sees is worth less than a slightly smaller
     one everybody sees. Do not "restore" 0.9375rem without re-measuring the
     breakpoint, or the row silently overflows. */
  font-size: 0.8125rem;
  line-height: 1;
  transition: color var(--dur-hover) var(--ease-hover),
              background var(--dur-hover) var(--ease-hover),
              border-color var(--dur-hover) var(--ease-hover),
              box-shadow var(--dur-hover) var(--ease-hover),
              transform var(--dur-hover) var(--ease-hover);
}
.nav-pills__link:hover {
  color: var(--accent);
  border-color: rgba(var(--ink-rgb), 0.25);
  box-shadow: var(--shadow-sm);
  transform: translateY(-1px);
}
.nav-pills__link:active { transform: translateY(0); }
/* "yakında" (not-built-yet) pills in the top bar: quietly muted text, no hover
   pop, default cursor — reads as not-yet-active while staying a clean pill. No
   visible tag (the title="yakında" tooltip carries the hint). href="#" is
   preventDefault'd by the anchor handler, so they never navigate. */
.nav-pills__link.is-soon { color: var(--muted); cursor: default; }
.nav-pills__link.is-soon:hover {
  color: var(--muted);
  border-color: var(--line);
  box-shadow: none;
  transform: none;
}


/* ==========================================================================
   BUTTONS  (.btn / .btn--filled) — the filled maroon pill CTA.
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 2.75rem;               /* ≥44px tap target                       */
  padding: var(--space-3) var(--space-5);
  font-weight: var(--wght-medium);
  font-variation-settings: "wght" var(--wght-medium), "opsz" 16,
                           "ROND" var(--ROND-soft);
  font-size: 0.9375rem;
  line-height: 1;
  letter-spacing: 0.005em;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--dur-hover) var(--ease-hover),
              color var(--dur-hover) var(--ease-hover),
              box-shadow var(--dur-hover) var(--ease-hover),
              transform var(--dur-hover) var(--ease-hover);
}

.btn--filled {
  background: var(--accent);
  color: var(--text-on-maroon);
  box-shadow: var(--shadow-sm);
}
.btn--filled:hover {
  background: var(--accent-strong);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}
.btn--filled:active { transform: translateY(0); }

/* OUTLINE variant — an accent hairline + accent text on the page surface, so it
   reads as a secondary action next to a .btn--filled. Same box model and tokens
   as --filled (identical min-height, so the 44px tap target is inherited); only
   fill and border differ. Used by the WhatsApp link in the İletişim contact
   column, where a second FILLED button would read as a second submit. */
.btn--outline {
  background: transparent;
  color: var(--accent);
  border: 1px solid var(--accent-line);
  box-shadow: none;
}
.btn--outline:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-strong);
}
.btn--outline:active { transform: translateY(0); }


/* ==========================================================================
   3. HERO  (#hero)
      Big breathing headline w/ maroon accent word, eyebrow, two arrow-links,
      LCP media. A VERY subtle warm radial light — restrained, not a blob.
   ========================================================================== */

.hero {
  position: relative;
  padding-top: clamp(5.5rem, 9vw, 7rem);     /* clears the fixed transparent header */
  padding-bottom: clamp(1.5rem, 3vw, 2.5rem); /* tight so the mosaic peeks in        */
  overflow: clip;
  background: var(--hero-bg);                /* flat pure white — no glow, no tint    */
}

.hero .container { position: relative; z-index: var(--z-content); }

.hero__grid { align-items: end; row-gap: clamp(2rem, 5vw, 4rem); }

.hero__copy { display: flex; flex-direction: column; }

.hero__eyebrow { margin-bottom: var(--space-5); }

.hero__title {
  margin-bottom: var(--space-5);
  /* base.css drives the breathing weight; keep tracking generous on display */
  max-width: 18ch;
}

/* The homepage slogan is a full sentence, not a one-word page title, so at
   .t-display's size it dominated the fold. Scaled to 70% of the shared clamp:
   every term multiplied by 0.7, so the reduction is a uniform 30% at every
   width rather than a different ratio per breakpoint.
     shared:   clamp(3rem,   1.6rem  + 7vw,   9rem)
     slogan:   clamp(2.1rem, 1.12rem + 4.9vw, 6.3rem)
   max-width stays in `ch`, which is font-relative, so it shrinks with the type
   and the line breaks land in the same places. Scoped to the homepage: the
   other eight heroes are single words and were not part of the complaint. */
.hero__title--slogan {
  font-size: clamp(2.1rem, 1.12rem + 4.9vw, 6.3rem);
}

.hero__sub {
  max-width: 38ch;
  margin-bottom: var(--space-7);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: clamp(2.5rem, 4vw, 4rem);
}
.hero__actions .arrow-link { font-size: 1.0625rem; }

.hero__media {
  aspect-ratio: 16 / 9;
  width: 100%;
}


/* ==========================================================================
   4. SECTION RHYTHM
      .section      vertical padding via --section-y (surface utilities set bg)
      .section-head heading block (eyebrow + h + lead) with editorial spacing
   ========================================================================== */

.section {
  padding-block: var(--section-y);
}

.section-head { row-gap: var(--space-4); margin-bottom: var(--block-y); }
.section-head > .t-eyebrow { margin-bottom: var(--space-1); }
.section-head > .t-lead { margin-top: var(--space-3); max-width: 52ch; }


/* ==========================================================================
   5. LIFE  (#life)  — asymmetric / editorial photo mosaic.
      Explicit 12-col placement with VARIED tile sizes + staggered start/end
      rows so the outer silhouette is irregular (broken top & bottom edges,
      non-flush sides), with deliberate EMPTY pockets (top-right + lower-right)
      so it breathes. Tile 1 (Pazar buluşması) is the large visual anchor.
      Entrance = data-reveal="stagger" on the grid (reuses initReveal) + the
      scale override below. Hover = tilt + the direction-aware reflection
      (.sheen, base.css). Tablet → 2-col varied; mobile → single column.
   ========================================================================== */

/* Shared tile span — the mosaic overrides it via explicit nth-child placement. */
.tile { --span: 6; grid-column: span var(--span); }

.life__grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-auto-rows: clamp(44px, 3.7vw, 60px);
  gap: var(--gutter);
}
.life__grid .tile { aspect-ratio: auto; height: 100%; min-height: 0; }
/* FOUR tiles (İçerik.docx item 8), re-cut from the original six. Two column
   blocks (1–7 and 8–12) with staggered start/end rows so the top and bottom
   edges stay broken; row 1 on the right and row 13 on the right are left empty
   to breathe, exactly as the six-tile version did. Verified at 1440/1280/1024:
   no overlaps and no interior gaps. */
/* SEVEN tiles. The previous four used only TWO column starts (1, 8) and TWO
   spans (5, 7) of the twelve this grid offers, so the mosaic read as a
   two-column layout wearing a twelve-column grid. Aspect range was 1.74-2.92;
   it is now 1.04-2.92 across three starts and four spans. Occupancy checked
   cell by cell: no overlaps, no interior holes, 14 rows.
   SIX tiles since Sep 2026: the seventh was a full-width texture band closing
   the grid at rows 15-18. The client asked for it out. The grid uses
   grid-auto-rows, not an explicit template, so removing it simply ends the
   mosaic at row 14 and leaves no hole. */
.life__grid .tile:nth-child(1) { grid-column: 1 / span 7;   grid-row: 1 / span 8; }  /* anchor */
.life__grid .tile:nth-child(2) { grid-column: 8 / span 5;   grid-row: 1 / span 4; }
.life__grid .tile:nth-child(3) { grid-column: 8 / span 5;   grid-row: 5 / span 4; }
.life__grid .tile:nth-child(4) { grid-column: 1 / span 4;   grid-row: 9 / span 6; }
.life__grid .tile:nth-child(5) { grid-column: 5 / span 3;   grid-row: 9 / span 6; }  /* narrowest */
.life__grid .tile:nth-child(6) { grid-column: 8 / span 5;   grid-row: 9 / span 6; }
.life__grid .tile:nth-child(2) .media__inner img,
.life__grid .tile:nth-child(3) .media__inner img { object-position: 50% 40%; }

/* Entrance: the tiles now fade in via the opacity-only [data-reveal] clarify
   (initReveal, play-once for media so photos never strobe) — NO translateY/scale
   rise. tilt owns the tile transform; parallax owns the inner-media transform. */

/* Video tile: keep the b-roll backdrop WARM (never the near-black --ink) so any
   uncovered area before the first frame / on aspect mismatch stays light. The
   .media warm gradient also shows through behind the video element. */
.tile--video .media__inner video { background: var(--surface-3); }

/* --- Tile hover/focus reveal: a stretched link + bottom scrim with a label and
   a "Keşfet" CTA showing where the tile leads. Link (z5) sits above .sheen (z2)
   and .edge::after (z1) so the whole tile is clickable; the scrim has
   pointer-events:none so it never blocks the link, and tilt/sheen still run. --- */
.tile__link { position: absolute; inset: 0; z-index: 5; border-radius: inherit; }
.tile__reveal {
  position: absolute; inset: 0; z-index: 4; border-radius: inherit;
  display: flex; flex-direction: column; align-items: flex-start; justify-content: flex-end;
  gap: var(--space-3); padding: clamp(1rem, 2vw, 1.5rem);
  background: linear-gradient(to top, rgba(var(--ink-rgb), 0.62) 0%, rgba(var(--ink-rgb), 0.18) 38%, transparent 64%);
  opacity: 0; transition: opacity var(--dur-base) var(--ease-out-quart); pointer-events: none;
}
.tile:hover .tile__reveal, .tile:focus-within .tile__reveal { opacity: 1; }
.tile__reveal-label {
  color: var(--paper); font-weight: var(--wght-semibold);
  font-variation-settings: "wght" var(--wght-semibold), "opsz" 22, "ROND" var(--ROND-soft);
  font-size: clamp(1rem, 0.9rem + 0.5vw, 1.25rem); line-height: 1.1; letter-spacing: -0.01em;
  text-shadow: 0 1px 8px rgba(var(--ink-rgb), 0.45);
  transform: translateY(6px); transition: transform var(--dur-base) var(--ease-out-expo);
}
.tile__reveal-cta {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-4); border-radius: var(--r-pill);
  background: var(--surface-1); color: var(--ink);
  font-weight: var(--wght-medium);
  font-variation-settings: "wght" var(--wght-medium), "opsz" 16, "ROND" var(--ROND-soft);
  font-size: 0.875rem; line-height: 1; box-shadow: var(--shadow-sm);
  transform: translateY(6px); transition: transform var(--dur-base) var(--ease-out-expo) 0.04s;
}
.tile__reveal-cta-arrow { color: var(--accent); transition: transform var(--dur-base) var(--ease-out-expo); }
.tile:hover .tile__reveal-label, .tile:focus-within .tile__reveal-label,
.tile:hover .tile__reveal-cta, .tile:focus-within .tile__reveal-cta { transform: none; }
.tile:hover .tile__reveal-cta .tile__reveal-cta-arrow { transform: translateX(3px); }


/* ==========================================================================
   6. TICKER  (#ticker-values)  — quiet kinetic marquee, edge-masked.
      JS clones .marquee__track for a seamless loop; data-speed sets px/s.
      Both the original and cloned track share the .is-animating animation.
   ========================================================================== */

.ticker {
  --ticker-pad: clamp(2.5rem, 5vw, 4.5rem);
  padding-block: var(--ticker-pad);
  position: relative; /* anchor for the static Yuhanna 3:16 reference */
}

.marquee {
  position: relative;
  display: flex;
  width: 100%;
  overflow: hidden;
  /* .edge-mask-x (base.css) supplies the fade-at-ends mask */
}

.marquee__track {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  gap: clamp(1.5rem, 3vw, 3rem);
  /* Seam gap + vertical breathing live on .marquee__item, NOT here: this is a
     ul[role="list"], and base.css resets that to padding:0 (which out-specifies a
     .marquee__track padding rule). */
  white-space: nowrap;
  will-change: transform;
}

/* CSS keyframe fallback for the NO-JS path only. When JS is present, initMarquee
   drives a transform-based seamless loop and this animation must NOT run (a
   running CSS animation would override GSAP's per-frame inline transform). It is
   therefore scoped to .no-js so the two systems never animate transform at once.
   Reverse keys off the SAME data-reverse attribute hook the JS reads, so the
   fallback and the JS driver agree. */
.no-js .marquee__track { animation: marquee-drift 25.45s linear infinite; } /* +10% faster (was 28s) */
.no-js .marquee[data-reverse] .marquee__track { animation-direction: reverse; }
.no-js .marquee:hover .marquee__track { animation-play-state: paused; }

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

.marquee__item {
  font-family: var(--font-sans);
  /* ~13% smaller than before — the verse reads as elegant running text. */
  font-size: clamp(1.3rem, 0.85rem + 2.1vw, 2.6rem);
  font-weight: var(--wght-medium);
  font-variation-settings: "wght" var(--wght-medium), "opsz" 40,
                           "wdth" 96, "ROND" var(--ROND-soft);
  letter-spacing: -0.01em;
  color: var(--ink);
  line-height: 1.3;                 /* room for ascenders / descenders / diacritics */
  /* Vertical breathing so tall glyphs are never clipped; the item is the flex
     content, so this also drives the band height (initMarquee's minHeight). Extra
     bottom room keeps the verse clear of the corner reference. On the ITEM (not the
     ul[role=list], which base.css resets to padding:0) so every clone carries it. */
  padding-block: 1rem 2.1rem;
  padding-inline-end: 5rem;         /* trailing seam gap before the verse restarts */
}

/* Static John 3:16 reference, tucked in the band's bottom-right. Sits ABOVE the
   scrolling verse (z-index) but pointer-events:none, and OUTSIDE the masked
   .marquee so the edge fade never dims it. Anchored just inside the band's lower
   edge (band bottom ≈ the section's padding-bottom = --ticker-pad). */
.ticker__ref {
  position: absolute;
  right: 1.25rem;
  bottom: calc(var(--ticker-pad) + 0.4rem);
  z-index: 3;
  pointer-events: none;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  color: var(--muted);
}


/* ==========================================================================
   7. HİZMETLER  (#pillars)  — weekly-gatherings list + companion image stage.
      Self-contained module (everything namespaced .services__*). Hovering /
      focusing a row (or scrolling on touch) activates it; its image wipes over
      the stack and the giant ghost day-word roll-swaps. Wired in initServices().
   ========================================================================== */

/* Neutralize the section's --section-y; .services__inner owns the rhythm.
   Pure-white background (was the surface-2 utility, #F1F0EC) via the token. */
.pillars { padding-block: 0; background: var(--surface-1); }

/* All absolute lengths in this module are ×0.9 (10% smaller, proportions locked).
   Unitless line-heights, em letter-spacing, fr tracks, %s and FVS axes are left
   as-is — they scale with font-size / the layout automatically. */
.services__inner { padding-block: clamp(1.8rem, 3.6vw, 2.925rem); } /* .container = width + h-gutter */
.services__head { margin-bottom: clamp(1.35rem, 2.7vw, 2.025rem); }
.services__eyebrow {
  text-transform: uppercase; letter-spacing: 0.18em; font-size: 0.702rem;
  color: var(--maroon); font-weight: 600; font-variation-settings: "wght" 600; margin-bottom: 0.765rem;
}
.services__title {
  font-size: clamp(2.07rem, 5.13vw, 3.87rem); line-height: 0.98; letter-spacing: -0.025em;
  font-weight: 600;
  font-variation-settings: "opsz" 110, "wght" 600;
}

.services__layout {
  display: grid; grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(1.8rem, 4.5vw, 4.5rem); align-items: start;
}

.services__index { list-style: none; margin: 0; padding: 0; }
.services__row {
  position: relative; display: grid; grid-template-columns: 1fr auto;
  align-items: baseline; gap: 1.08rem; padding: clamp(1.215rem, 2.34vw, 1.98rem) 0;
  cursor: pointer; transition: transform var(--dur-hover-soft) var(--ease-hover);
}
.services__name {
  font-size: clamp(1.44rem, 2.925vw, 2.475rem); line-height: 1; letter-spacing: -0.02em;
  font-weight: 700; /* CHANGE 3: service NAME always bold — static fonts render their real 700 face; Google Sans Flex keeps its own wght axis via the fvs below */
  font-variation-settings: "opsz" 60, "wght" 460; color: var(--muted);
  transition: color var(--dur-hover-soft) var(--ease-hover),
              font-variation-settings var(--dur-hover-soft) var(--ease-hover),
              letter-spacing var(--dur-hover-soft) var(--ease-hover);
}
.services__meta {
  font-size: 0.9rem; color: var(--muted); white-space: nowrap; opacity: 0.7;
  transition: color var(--dur-hover-soft) var(--ease-hover), opacity var(--dur-hover-soft) var(--ease-hover);
}
.services__contact {
  grid-column: 1 / -1; margin-top: 0.585rem; justify-self: start; font-size: 0.855rem;
  color: var(--maroon); text-decoration: none; font-weight: 540; font-variation-settings: "wght" 540;
  opacity: 0; transform: translateY(-3.6px); pointer-events: none;
  transition: opacity var(--dur-hover-soft) var(--ease-hover), transform var(--dur-hover-soft) var(--ease-hover);
}
.services__arr { display: inline-block; transition: transform var(--dur-hover-soft) var(--ease-hover); }
.services__contact:hover .services__arr { transform: translateX(3.6px); }

.services__row.is-active { transform: translateX(7.2px); }
.services__row.is-active .services__name {
  color: var(--maroon); font-weight: 720; font-variation-settings: "opsz" 60, "wght" 720; letter-spacing: -0.025em;
}
.services__row.is-active .services__meta { color: var(--ink); opacity: 1; }
.services__row.is-active .services__contact { opacity: 1; transform: none; pointer-events: auto; }
.services__row:not(.is-active):hover .services__name {
  color: var(--ink); font-weight: 560; font-variation-settings: "opsz" 60, "wght" 560;
}

/* THEME STUDIO v2 — service-name REST weight for the ten added families.
   The rest-state axis value below (.services__name, "wght" 460) was authored for
   the variable Google Sans Flex; the four static families ignore
   font-variation-settings entirely and render their real font-weight: 700. The
   ten added families are ALSO variable, so without this rule they would inherit
   Google Sans Flex's 460 by accident and sit visibly lighter than the static
   four. Pin them to a flat 700 rest state instead, matching the static families.
   The axis list stays "opsz" + "wght" so the hover (560) / active (720)
   transitions still interpolate. googlesans is deliberately NOT listed: it keeps
   its 460 rest state byte-identical. */
html:is([data-font="bricolage"],[data-font="archivo"],[data-font="epilogue"],[data-font="schibsted"],[data-font="chivo"],[data-font="familjen"],[data-font="fraunces"],[data-font="literata"],[data-font="newsreader"],[data-font="bitter"]) .services__name {
  font-weight: 700;
  font-variation-settings: "opsz" 60, "wght" 700;
}

/* The docx's verbatim service description. The row is a 2-col grid
   (name | meta), so the paragraph spans both. Tokens only. */
.services__desc {
  grid-column: 1 / -1;
  margin: 0.55rem 0 0;
  max-width: 52ch;
  color: var(--muted);
  font-size: 0.95rem;
  line-height: 1.7;
}

.services__stage { position: relative; }
/* Sticky stage. All four descriptions are inline, which makes the index column
   taller than the image; sticky keeps the image beside the text the whole way
   down instead of stranding it at the top with dead space below.
   Verified: no ancestor of .services__stage carries transform / perspective /
   filter / contain at any scroll position, and Lenis drives NATIVE scroll here
   (html and body both compute transform:none), so nothing breaks sticky.
   Scoped to the two-column band — below 860px the module stacks and the stage
   moves to order:-1, where pinning would be wrong. */
@media (min-width: 861px) {
  .services__stage { position: sticky; top: 7rem; align-self: start; }
}
.services__ghost {
  position: absolute; top: -15%; left: 50%; transform: translateX(-50%);
  height: 1em; overflow: hidden; font-size: clamp(4.23rem, 13.5vw, 11.07rem);
  line-height: 1; pointer-events: none; z-index: var(--z-ghost);
}
.services__ghost-txt {
  display: block; font-weight: 760; font-variation-settings: "opsz" 144, "wght" 760;
  color: var(--maroon-ghost); letter-spacing: -0.03em; white-space: nowrap;
  transition: transform 0.5s var(--ease-out-expo), opacity 0.4s var(--ease-out-expo);
}

.services__frame {
  position: relative; z-index: var(--z-content); aspect-ratio: 4 / 5;
  /* The frame is fr-sized (no absolute width), so to make it 10% smaller — the
     "frame width/height × 0.9" — cap it to 90% of its cell. Centred, so the
     absolutely-positioned ghost (centred on the stage) stays centred on it.
     Mobile (single-column banner) restores full width below. */
  width: 90%; margin-inline: auto;
  border-radius: var(--r-card); overflow: hidden;
  box-shadow: var(--shadow-md); background: var(--surface-3);
}
.services__img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  clip-path: inset(0 0 0 100%); transform: scale(1.04);
  transition: clip-path 0.6s var(--ease-out-expo), transform 0.7s var(--ease-out-expo);
}
.services__img.is-show { clip-path: inset(0 0 0 0); transform: scale(1); }

/* Single column on narrow widths (module owns its own breakpoint). */
@media (max-width: 860px) {
  .services__layout { grid-template-columns: 1fr; gap: 2.25rem; } /* was 2.5rem ×0.9 */
  .services__stage { order: -1; }
  .services__ghost { display: none; }
  /* Full-width banner on mobile (single column); the 10% reduction here is
     carried by the scaled type + spacing, not a narrowed image. */
  .services__frame { aspect-ratio: 16 / 10; width: auto; margin-inline: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .services__row, .services__name, .services__meta, .services__contact,
  .services__arr, .services__ghost-txt, .services__img,
  .services__desc { transition: none !important; }
}

/* ==========================================================================
   10. INVITATION  (#invitation)  — warm tonal CTA on surface-3 (never dark).
       Copy column + a real, zoom-only MapLibre map locked on the church.
   ========================================================================== */

/* Copy floats over the map stage — no card. Left-aligned, in the site gutter.
   (Desktop adds the floating-stage height + paper halo in the min-width block.) */
.visit-content {
  position: relative;
  z-index: 3;                              /* above the map stage */
  max-width: 46rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.visit-content > .t-eyebrow { margin-bottom: var(--space-3); }
.invitation__title { margin-bottom: var(--space-5); max-width: 16ch; }
.visit-content > .t-lead { max-width: 42ch; margin-bottom: var(--space-6); }

/* Definition list of when / where details. */
.invitation__details {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-7);
  margin-bottom: var(--space-7);
}
.invitation__detail { display: flex; flex-direction: column; gap: var(--space-2); }
.invitation__detail dt { letter-spacing: 0.04em; }
.invitation__detail dd { color: var(--ink); }

.invitation__cta { align-self: flex-start; }

/* --------------------------------------------------------------------------
   Visit map (.visitmap) — a zoom-only, church-locked MapLibre map (js/visitmap.js)
   that DISSOLVES into the paper page on all four edges: the land tone is matched
   to --paper in JS, and a paper-coloured feather overlay fogs the periphery.
   No hard rectangle, no seam. Mobile-first: a full-width band under the copy.
   -------------------------------------------------------------------------- */
.visitmap {
  position: relative;
  width: 100%;
  min-height: clamp(340px, 64vw, 420px);   /* stacked height (mobile) */
  margin-top: clamp(2rem, 6vw, 3rem);
  background: var(--paper);                 /* same tone as land + page */
  overflow: clip;
}

/* Two classes (0,2,0) so this beats MapLibre's own `.maplibregl-map { position:
   relative }` — maplibre-gl.css loads after components.css, and the map adds
   .maplibregl-map to this same element. Without this the box collapses to 0. */
.visitmap .visitmap__canvas { position: absolute; inset: 0; z-index: 0; }

/* THE FEATHER — a paper-coloured fog laid over the map that fades it into the
   page on every edge. The radial centre stays transparent so the streets + pin
   read; the periphery resolves to solid --paper, so there is no map rectangle.
   (Mobile values; desktop overrides below with the approved focal + 4 edges.) */
.visitmap__feather {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  /* MOBILE FEATHER - SYMMETRIC IS CORRECT HERE, and for a reason that does not
     apply above the breakpoint. Below 53.75rem (860px) `.visitmap` is still
     `position: relative` and sits in normal flow BELOW the copy. Measured at
     375, 768 and 856: vertical overlap between `.visit-content` and `.visitmap`
     is exactly 0px, with a 32-46px gap between them. At 864 the map flips to
     `position: absolute` and the overlap jumps to 624px. So there is no text
     over the map here, the halo has no work to do, and this rule's only job is
     the four-edge vignette. Do not copy the desktop block's asymmetry down.

     What was actually wrong: the radial was 140% wide, so its clear core
     overran both side edges, and there were no left/right linears at all - the
     map met the page on a hard vertical cut. Fixed on all four edges. */
  background:
    radial-gradient(50% 50% at 50% 46%,
      transparent 0 52%,
      rgba(var(--paper-rgb), 0.5) 80%,
      var(--paper) 100%),
    linear-gradient(to right,  var(--paper) 0, transparent 12%),
    linear-gradient(to left,   var(--paper) 0, transparent 12%),
    linear-gradient(to top,    var(--paper) 0, transparent 14%),
    linear-gradient(to bottom, var(--paper) 0, transparent 14%);
}

/* Keep the pin crisp ABOVE the feather fog. The MapLibre marker sits inside the
   canvas container (will-change makes it its own context); a z-index here lifts
   it past the feather (z-index 1). */
.visitmap .maplibregl-marker { z-index: 2; }

/* Zoom-only map → no grab/grabbing cursor. */
.visitmap .maplibregl-canvas-container,
.visitmap .maplibregl-canvas { cursor: default; }

/* Keep MapLibre's chrome discreet. */
.visitmap .maplibregl-ctrl-attrib { font-size: 0.6875rem; }
.visitmap .maplibregl-ctrl-attrib.maplibregl-compact { background: rgba(var(--paper-rgb), 0.82); }

/* Maroon teardrop pin (built in JS; colour comes from here). */
.visitmap__pin {
  color: var(--maroon);
  line-height: 0;
  cursor: default;
  filter: drop-shadow(0 4px 6px rgba(var(--ink-rgb), 0.28));
}
.visitmap__pin svg { display: block; }

/* Fallback (empty key / no WebGL / tile error). Single paper tone, no card.
   js/visitmap.js hides the feather + canvas when this shows. */
.visitmap__fallback {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: var(--space-6);
  text-align: center;
  color: var(--muted);
  background: var(--paper);
}
.visitmap__fallback[hidden] { display: none; }
.visitmap__dir { color: var(--maroon); font-weight: 600; }

/* ----- Desktop (≥ 53.75rem / 860px): one full-bleed stage; copy floats over it. */
@media (min-width: 53.75rem) {
  /* The section becomes the stage: the map fills it edge-to-edge behind
     everything; the copy (inside .container) floats on the left. No section
     padding — the stage height comes from .visit-content, so the map bleeds to
     the true section top/bottom and the viewport's left/right edges. */
  #invitation { position: relative; overflow: clip; padding-block: 0; }

  .visit-content {
    min-height: clamp(560px, 78vh, 820px);
    justify-content: center;
    padding-block: clamp(3rem, 7vw, 7rem);
  }

  /* PAPER HALO BEHIND THE COPY. It is not a panel and not a cloud: it is the
     mechanism by which paper BECOMES map. Three things make that work, and all
     three are load-bearing.

     1. THE BOX IS EXTENDED ONE FULL COLUMN WIDTH TO THE LEFT (inset ... -100%),
        so the gradient reaches full transparency BEFORE it meets its own left
        box edge, instead of being severed by it.

        `.visit-content` is a near-constant 828px column but it is CENTRED, so
        its left edge is at x=58 on a 1440 viewport and x=173 on a 1920 one.
        At 1440 the feather is ~0.92 opaque there and hid the cut; at 1920 the
        feather is only ~0.71, and the severed halo showed as a hard vertical
        step of 0.254 down the left of the copy. Measured, both widths. The
        extension puts the halo's own left edge 300px past the point where the
        gradient is already zero, at every viewport.

     2. THE STOPS ARE A RAISED COSINE, not a plateau plus a ramp. alpha(d) =
        P/2 * (1 + cos(pi*d/D)) sampled at eight points. Zero slope at both
        ends, so there is no distance at which the fog visibly starts or stops.
        A plateau is what made this read as a cloud with an edge.

     3. PEAK DENSITY IS 0.92, NOT 1.0, and it is held flat out to 44% of the
        radius before the fade starts, because the copy's TEXT reaches ~70% of
        the column width (d = 0.435) even though the fade must finish by the
        column's right edge (d = 0.683). An earlier attempt faded from d=0 and
        left the paragraph's last words at 0.24 coverage; at 864 that measured
        1.69:1 over a dark road label. The plateau is not decorative.

        0.92 IS A MEASURED CEILING, NOT A TASTE CHOICE. Required paper coverage
        to hold 4.5:1 over OpenFreeMap's darkest feature (a road label at
        rgb 102,102,102), by text colour:
          gold   rgb(138,101,25)  5.00:1 on bare paper  needs A >= 0.918
          muted  rgb(103,97,86)   5.78:1 on bare paper  needs A >= 0.812
          ink    rgb(21,18,13)   17.60:1 on bare paper  needs A >= 0.153
        The 14.6px gold eyebrow sets the floor for the whole copy. Lowering the
        peak below 0.92 to show more map fails that run first. See DEVIR.md.

     GEOMETRY IS VIEWPORT-INVARIANT BY CONSTRUCTION. With the box at 2x the
     column width, 59% puts the focal back exactly where 18% put it on the
     unextended box, and 60% reproduces the original 120% radius. The right
     edge therefore still lands at 0.82/1.20 = 68.33% of the radius, which is
     the same number at every viewport because focal and radius both scale with
     the column. Change one of these three and recompute the other two.

     Do NOT fix map-fog problems in `.visitmap__feather`. That rule handles the
     PAGE EDGES, is byte-identical to the seed, and is correct. */
  .visit-content::before {
    content: "";
    position: absolute;
    inset: 0 0 0 -100%;
    z-index: -1;
    pointer-events: none;
    background: radial-gradient(60% 250% at 59% 50%,
      rgba(var(--paper-rgb), 0.920) 0%,
      rgba(var(--paper-rgb), 0.920) 44%,
      rgba(var(--paper-rgb), 0.832) 48.87%,
      rgba(var(--paper-rgb), 0.602) 53.73%,
      rgba(var(--paper-rgb), 0.318) 58.6%,
      rgba(var(--paper-rgb), 0.088) 63.46%,
      transparent 68.33%);
  }


  /* Map fills the whole section, behind the copy. */
  .visitmap {
    position: absolute;
    inset: 0;
    width: auto;
    min-height: 0;
    margin-top: 0;
    z-index: 0;
    background: transparent;                /* land already matches the page */
  }

  /* On desktop the map fills the whole section, so the fallback would otherwise
     center under the floating copy. Push it into the right region (where the map
     visually sat) so it reads cleanly, clear of the text. */
  .visitmap__fallback {
    align-items: flex-end;
    text-align: right;
    padding-inline-end: clamp(2rem, 6vw, 6rem);
    padding-inline-start: min(50%, 46rem);
  }

  /* Desktop feather — APPROVED values. Paper expressed via --paper-rgb (the
     codebase keeps raw colour in tokens.css) — same rendered colour. Radial
     focal near the pin keeps the centre clear; all four edges + a stronger left
     fade (under the copy) dissolve the map into the page. */
  /* RESTORED to the original asymmetric mask, Sep 2026.
     The reference box is NOT the visible map. `.visitmap` is a FULL-BLEED
     1440x702 backdrop, and `.visit-content` (the copy column, 828px wide at
     x=58, z-index 3) sits ON TOP of its left 60%. So the map a visitor actually
     sees is only the strip to the RIGHT of x=886.
     The asymmetry was doing a job: fog the map beneath the copy so the text
     stays legible, and keep the clear window in that right-hand strip. A
     symmetric vignette moves the clear window behind the text, which is what
     the previous "fix" did. */
  /* DESKTOP FEATHER — ASYMMETRIC ON PURPOSE. Do not "balance" it.

     Two layers fog this map and they have DIFFERENT jobs. Read both before
     touching either:

       .visit-content::before  is a paper halo clipped to the copy column
                               (x 58..886 at 1440). It is what keeps the map
                               off the text. Composited, it holds the map at
                               >=0.87 opaque everywhere a glyph actually sits.
       .visitmap__feather      (this rule) fogs the PAGE EDGES so the map never
                               meets the paper on a hard cut.

     So this rule deliberately does almost nothing on the left: the left linear
     releases at 26% (x=374) because the halo has already taken over by then.
     Measured composite at mid-height: 1.00 fog out to x=620, 0.87 at x=780,
     0.53 at the copy box edge, fully clear only from x=960 where the map is
     meant to be read. The radial focal at 64% sits 35px right of that edge.

     Measuring this rule ON ITS OWN shows a 546px "hole" behind the copy. That
     hole is not real; it is the halo's territory. See CLAUDE.md rule 11.

     KNOWN, NOT FIXED HERE - the vertical line at x=886. The halo's radial fades
     out at 82% of its radius, but `.visit-content`'s box ends at 68% of it, so
     the halo is still ~53% opaque when it is cut off by its own box edge. That
     is a hard 0.53 -> 0 step at x=886 (61.5% across the map), and it is what
     reads as a line down the middle of the map. Verified Sep 2026 by rendering
     the live page's own fog layers over a flat dark backdrop: smooth to the
     left of 886, a clean vertical cut at it.

     It does NOT come from this rule. Both this rule and .visit-content::before
     are byte-identical to church-theme-studio@d63ed19, so the step has always
     been there; it only reads as a line when what sits behind it at that x has
     enough contrast. Left alone pending a decision, because the fix belongs to
     .visit-content::before and not to the map fog. */
  .visitmap__feather {
    background:
      radial-gradient(120% 110% at 64% 52%,
        transparent 0 40%,
        rgba(var(--paper-rgb), 0.55) 66%,
        var(--paper) 90%),
      linear-gradient(to right,  var(--paper) 0 2%, transparent 26%, transparent 100%),
      linear-gradient(to left,   var(--paper) 0 1%, transparent 18%),
      linear-gradient(to top,    var(--paper) 0 1%, transparent 20%),
      linear-gradient(to bottom, var(--paper) 0 1%, transparent 20%);
  }
}


/* ==========================================================================
   12. FOOTER  (#site-footer)  — light / warm, organized, calm. Static cross mark.
   ========================================================================== */

.site-footer {
  /* Tightened ~35% (was clamp(4rem, 8vw, 7rem)) — less airy, more intentional. */
  padding-block: clamp(2.6rem, 5.2vw, 4.55rem);
  border-top: 1px solid var(--line);
}

/* Row gap between the columns row and the copyright row, reduced ~40% via a
   local clamp (the global --block-y token is left untouched — it is used by
   .grid and section heads elsewhere). Was var(--block-y) = clamp(2.5rem,5vw,5rem). */
.site-footer__grid { row-gap: clamp(1.5rem, 3vw, 3rem); align-items: start; }

.site-footer__brand { display: flex; flex-direction: column; gap: 1rem; } /* was --space-5 (1.5rem) */
/* Footer brand is a WORDMARK, not a badge (the seal lives once in this footer,
   in the Vakıf membership badge). Reuses the header's .brand__word typography;
   only the size is lifted, so the brand still leads the column above the
   t-lead tagline instead of sitting smaller than it. */
.site-footer__wordmark { display: inline-block; color: var(--ink); text-decoration: none; }
.site-footer__wordmark .brand__word { font-size: clamp(1.25rem, 1.1rem + 0.5vw, 1.5rem); }
.site-footer__tagline { max-width: 26ch; color: var(--text-muted); }

.site-footer__col { display: flex; flex-direction: column; gap: 0.7rem; } /* was --space-4 (1rem) */
.site-footer__heading { letter-spacing: 0.08em; }

.site-footer__list { display: flex; flex-direction: column; gap: 0.5rem; } /* was --space-3 (0.75rem) */
.site-footer__list .arrow-link { font-size: 0.9375rem; }

.site-footer__address { font-style: normal; line-height: 1.7; color: var(--ink); }

/* Bottom meta row: divider, spaced, calm. The margin-top stacked on the grid
   row-gap was the main source of emptiness — both reduced ~40%. */
.site-footer__base {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-top: clamp(1.5rem, 3vw, 3rem); /* was var(--block-y) */
  padding-top: 1.3rem;                   /* was --space-6 (2rem), ~35% tighter */
  border-top: 1px solid var(--line);
}


/* ==========================================================================
   13. RESPONSIVE — TABLET  (≤ 64rem). Grid collapses 16 → 8 in base.css; here
       we re-balance the bespoke nested layouts and header density.
   ========================================================================== */
@media (max-width: 64rem) {

  /* Header: drop the center meta line to keep the bar uncluttered. */
  .site-header__meta { display: none; }
  .site-header__inner { gap: var(--space-4); }

  /* Hero: media goes full-width below the copy; tighten the title measure. */
  .hero__title { max-width: 22ch; }
  .hero__media { aspect-ratio: 16 / 10; }

  /* Life mosaic → 2-column varied (simplified from the desktop asymmetry;
     vertical offsets removed; anchor full-width + one tall accent for variety).
     :nth-child(n) reset beats the desktop placements inside this breakpoint. */
  .life__grid { grid-template-columns: repeat(2, 1fr); grid-auto-rows: clamp(150px, 23vw, 220px); grid-auto-flow: row dense; gap: var(--gutter); }
  .life__grid .tile:nth-child(n) { grid-column: auto; grid-row: auto; height: 100%; }
  /* Four tiles in a 2-column grid: tiles 1 and 4 run full width, 2 and 3 pair.
     The old `nth-child(4) { grid-row: span 2 }` tall accent is removed — with
     six tiles it filled; with four it left an empty cell beside tile 4. */
  /* Seven tiles in a 2-column grid: the anchor runs full width, then 2+3, 4+5
     and 6+7 pair off. 1 + 3 pairs = 7, no empty cell. The old nth-child(4)
     full-width rule is removed: with seven tiles it strands a cell. */
  .life__grid .tile:nth-child(1) { grid-column: 1 / -1; }   /* anchor full-width */

}


/* ==========================================================================
   14. RESPONSIVE — MOBILE  (≤ 40rem). base.css makes everything full-width;
       collapse the flex layouts and trim type for a deliberate small screen.
   ========================================================================== */
@media (max-width: 40rem) {

  /* Header: brand + CTA only; pills hide to protect the tap zone. The CTA and
     the in-page anchors keep navigation reachable; brand returns to top. */
  /* `.nav-pills { display: none }` REMOVED. It was the surviving half of the
     original defect (the other half, `.menu-compact { display: none }`, went
     earlier). It is now provably redundant -- below 1440px the whole
     .site-header__nav is display:none -- and leaving it would re-arm the fault
     the moment anyone touched the breakpoint. See docs/template-nav-bug.md. */
  .site-header__inner { min-height: 3.5rem; }
  .brand__badge { width: 2.5rem; height: 2.5rem; }

  /* Keep the mobile header as-is: no scroll-collapse. Neutralize the compact
     state so the brand stays put and nothing overlaps.
     NOTE: this block used to also carry `.menu-compact { display: none; }`.
     Together with `.nav-pills { display: none }` above, that left the mobile
     header with NO navigation at all once html.studio was removed — the
     "Dua iste" CTA is an <li> INSIDE .nav-pills, so it went with the pills.
     The rule is deleted. See "SINGLE-DESIGN HEADER" below, which shows the
     hamburger at every width. Full write-up: docs/template-nav-bug.md */
  .site-header.is-compact .site-header__nav { opacity: 1; transform: none; pointer-events: auto; }
  .site-header.is-compact .brand__word { transform: none; opacity: 1; pointer-events: auto; }
  .site-header.is-compact .brand__badge { box-shadow: none; } /* mobile stays flat; the white badge + maroon border + cross persist */

  /* Hero: actions stack with breathing room. padding-top clears the fixed header. */
  .hero { padding-top: 5.5rem; }
  .hero__actions { gap: var(--space-4); flex-direction: column; align-items: flex-start; }
  .hero__sub { margin-bottom: var(--space-6); }

  /* Life: clean single column, offsets removed (asymmetry is desktop-only).
     :nth-child(n) reset beats both the desktop AND tablet placements here. */
  .life__grid { grid-template-columns: 1fr; grid-template-rows: none; grid-auto-rows: auto; grid-auto-flow: row; gap: var(--space-4); }
  .life__grid .tile:nth-child(n) { grid-column: 1 / -1; grid-row: auto; height: auto; }
  /* Seven tiles, single column. Each carries its own ratio so the stack keeps
     the shape variety the desktop grid gets from its spans. */
  .life__grid .tile:nth-child(1) { aspect-ratio: 16 / 10; }
  .life__grid .tile:nth-child(2) { aspect-ratio: 16 / 9; }
  .life__grid .tile:nth-child(3) { aspect-ratio: 3 / 2; }
  .life__grid .tile:nth-child(4) { aspect-ratio: 4 / 3; }
  .life__grid .tile:nth-child(5) { aspect-ratio: 1 / 1; }
  .life__grid .tile:nth-child(6) { aspect-ratio: 3 / 2; }

  /* Invitation details wrap to a column; CTA full width for an easy tap. */
  .invitation__details { gap: var(--space-5); }
  .invitation__cta { align-self: stretch; }

  /* Footer base row stacks. */
  .site-footer__base { flex-direction: column; align-items: flex-start; gap: var(--space-2); }
}


/* ==========================================================================
   14b. SECTION BLOCK-NAME ANCHORS
        index.html (the single source of truth) carries section block classes
        whose layout/background currently come from co-classes (.section,
        surface-* utilities, .grid, child elements). These selectors are
        intentionally declared as empty anchor hooks so a future re-skin can
        target a whole section by name without editing index.html. Keep empty
        unless a re-skin needs section-scoped overrides.
   ========================================================================== */
.life {
  padding-top: clamp(0.5rem, 2vw, 1.5rem); /* top only; bottom keeps --section-y */
  background: var(--hero-bg);              /* continue the hero's white through the mosaic */
}
.invitation {
  background: var(--paper);  /* single tone so the map dissolves seamlessly */
}


/* ==========================================================================
   15a. NO FINE POINTER AT ALL — disable the hover-dependent tile visuals.
        Was half of one `@media (hover: none), (pointer: coarse)` block. Split,
        because the two halves answer different questions: whether a hover
        effect is USABLE, and whether a finger will be tapping. Only the first
        half belongs on the capability query, and getting it wrong is what left
        hybrid-device visitors with the labels always showing and no hover lift.
        (base.css neutralizes [data-tilt] transform + .sheen on the same query;
        here we also drop the hover lift / scale so nothing sticks on tap.)
   ========================================================================== */
@media not all and (any-pointer: fine) {
  /* Mosaic: labels visible by default, lighter scrim, no transform. */
  .tile__reveal { opacity: 1; background: linear-gradient(to top, rgba(var(--ink-rgb), 0.5) 0%, transparent 55%); }
  .tile__reveal-label, .tile__reveal-cta { transform: none; }

  .js [data-tilt] { box-shadow: var(--shadow-sm); }
  .js [data-tilt]:hover { box-shadow: var(--shadow-sm); transform: none; }
  .js [data-tilt]:hover .media__inner img,
  .js [data-tilt]:hover .media__inner video { transform: none; }
}

/* ==========================================================================
   15b. TOUCH ERGONOMICS — tap targets ≥44px. DELIBERATELY still keyed to the
        primary pointer: this is about a finger being used, not about whether a
        hover effect is available, so it is the one half of the old block that
        must NOT move to a capability query. Unchanged from before the split.
   ========================================================================== */
@media (hover: none), (pointer: coarse) {
  .nav-pills__link { min-height: 2.75rem; }     /* ≥44px                       */
  .arrow-link { padding-block: var(--space-1); } /* easier tap                  */
}


/* ==========================================================================
   16. REDUCED-MOTION COMPONENT POLISH
       base.css owns the global neutralizing path; here we make sure the
       component-level hover transforms / image settle don't animate either,
       and the ticker holds still & readable.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  /* Header collapse stays FUNCTIONAL but instant — no slide/scale, just a swap. */
  .brand__word, .site-header__nav, .menu-toggle, .menu-panel {
    transition: none !important; transition-delay: 0s !important;
  }

  .tile__reveal, .tile__reveal-label, .tile__reveal-cta, .tile__reveal-cta-arrow { transition: none; transform: none; }

  .media__inner img,
  .media__inner video { transition: none !important; transform: none !important; }

  .js [data-tilt]:hover .media__inner img,
  .js [data-tilt]:hover .media__inner video { transform: none !important; }

  /* No-JS fallback drift is killed under reduced motion; the JS ticker never
     starts in reduced motion (initMarquee returns early), so the track holds
     still & readable in both paths. */
  .no-js .marquee__track { animation: none !important; transform: none !important; }

  .btn,
  .nav-pills__link { transition: color var(--dur-fast) linear; }
  .btn--filled:hover,
  .nav-pills__link:hover { transform: none !important; }
}


/* ==========================================================================
   SOCIAL / BAĞLAN  (#connect)  — self-contained "follow us" module.
   Three equal brand orbs in an ARC (Instagram higher centre; Facebook + YouTube
   lower sides): a thin solid brand ring + white face + brand-colour glyph, with
   a gentle continuous float and a once-only slide-in entrance (initSocial adds
   .is-in; CSS does the motion). NO blur/glow layer (design rule). Background is
   white (--surface-1): the orb faces are also --surface-1, so on white the
   circles are defined purely by their thin brand ring + soft shadow (intentional
   — no borders). Neighbours: #invitation (--paper) above, #site-footer (surface-2)
   below. Fully removable: delete the #connect markup, initSocial(), and this banner.
   ========================================================================== */
/* HEIGHT, Sep 2026. The client found this section too tall and called it 100vh.
   It never was: the height came from this padding pair, the .social__head margin
   below, and .social__stage's own `min(72vh, 700px)`. Measured, it ran 95vh to
   124vh and exceeded a full screen at five of seven widths. Trimmed here; the
   real saving is on the stage. Nothing keys off a full-screen panel: the only
   100vh in the repo is body{min-height}, there is no scroll-snap anywhere, and
   the wave regenerates from the stage's own measured height. */
#connect.social { background: var(--surface-1); padding-block: clamp(3.25rem, 5.5vw, 5.5rem); }

.social__inner { max-width: var(--container); margin: 0 auto; padding-inline: var(--page-pad); isolation: isolate; }
/* ^ isolation:isolate = own stacking context (no visual change) so the "Topluluk"
   watermark's z-index:-1 sits BEHIND the heading/eyebrow but still ABOVE the
   section background. */

.social__head {
  max-width: 36rem;
  margin-bottom: clamp(1.75rem, 3.5vw, 2.75rem);   /* was clamp(2rem, 5vw, 4rem) */
  opacity: 0;
  transform: translateY(var(--entrance-shift));
  /* TEXT block → gentle --ease-text (not the punchy slide ease). */
  transition: opacity var(--dur-entrance-lg) var(--ease-text),
              transform var(--dur-entrance-lg) var(--ease-text);
}
.social__head.is-in { opacity: 1; transform: none; }
.social__eyebrow {
  text-transform: uppercase; letter-spacing: 0.2em; font-size: 0.78rem;
  color: var(--maroon); font-weight: 600; margin-bottom: 0.7rem;
}
.social__title {
  font-size: clamp(1.9rem, 3.6vw, 2.9rem); line-height: 1.05; letter-spacing: -0.02em;
  font-weight: 600;
  font-variation-settings: "opsz" 90, "wght" 600;
}

/* The stage is the canvas the ARC is laid out on, not padding: the orbs are
   placed by percentage of it. Its height used to be `min(72vh, 700px)`, which is
   unrelated to what the arc needs, so a dead band opened under the bottom orbs:
   measured 52.9px at 1440, 63.9px at 1024 and 182px at 768, where the 700px cap
   met an arc needing only 476px.
   The bottom orbs sit at top:44% and are orbW tall, so the arc exactly fills the
   stage when 0.44H + orbW = H, i.e. H = orbW / 0.56. Deriving the height from the
   ORB SIZE removes the dead band at every width and leaves the 6%/44% arc
   percentages, the orb sizes and the entrance untouched. Below 761px the stacked
   override still wins, so mobile is unaffected. */
.social__stage { position: relative; width: 100%; height: calc(clamp(210px, 24vw, 310px) / 0.56); }

.social__orb {
  position: absolute; display: block; text-decoration: none; cursor: pointer;
  width: clamp(210px, 24vw, 310px);
  opacity: 0;
  /* opacity + transform share ONE duration so the fade and the slide settle
     together (no opacity-finishes-early gap). Big translate kept as a feature. */
  transition: opacity var(--dur-entrance-lg) var(--ease-entrance),
              transform var(--dur-entrance-lg) var(--ease-entrance);
}
.social__orb::after { content: ""; display: block; padding-bottom: 100%; } /* square */
.social__from-left  { transform: translateX(-130px) scale(0.94); }
.social__from-right { transform: translateX(130px)  scale(0.94); }
.social__from-top   { transform: translateY(-120px) scale(0.94); }
.social__orb.is-in { opacity: 1; transform: none; }
.social__orb.is-in:hover { transform: translateY(-12px); transition: transform var(--dur-hover-soft) var(--ease-hover); }

/* DESKTOP ONLY: cap the disc at 220px instead of 310px (Eylül 2026).
   The client's note was that the section "draws too much attention", not only
   that it is tall, so the discs are part of the complaint rather than only its
   cost. At 220 the disc AREA is (220/310)^2 = 50.4% of before, and the section
   drops from 94.5vh to 76.6vh at 1440 and from 102.1vh to 82.6vh at 1280,
   where it had been TALLER THAN THE SCREEN.

   220 is a floor, not a preference. It is the last value where a desktop disc
   is still larger than the phone disc (218.4px at 390), and it keeps the wave's
   sag scaling at 19.7px against its own 16px floor (which engages at a 179.2px
   orb). 60vh was asked for and rejected: it needs 136px discs, 35% below this
   clamp's OWN mobile minimum. See docs/DEVIR.md 7.14.

   Scoped to min-width 761px so the stacked mobile layout below it is byte
   identical. In practice this binds at 917px and up, because below that 24vw is
   already under 220. The stage stays derived from orbW / 0.56 so the arc's 6% /
   44% percentages and the wave's own draw() are untouched: the wave redraws
   itself from the new stage height. */
@media (min-width: 761px) {
  .social__orb  { width: clamp(210px, 24vw, 220px); }
  .social__stage { height: calc(clamp(210px, 24vw, 220px) / 0.56); }
}

/* arc positions (symmetric: middle higher, sides lower) */
.social__orb--fb { left: 3%;  top: 44%; transition-delay: 0s; }
.social__orb--ig { left: 37%; top: 6%;  transition-delay: 0.28s; }
.social__orb--yt { left: 70%; top: 44%; transition-delay: 0.56s; }

/* gentle continuous float */
.social__float { position: absolute; inset: 0; }
.social__orb--fb .social__float { animation: social-floaty 6.5s ease-in-out infinite; }
.social__orb--ig .social__float { animation: social-floaty 7.6s ease-in-out infinite; animation-delay: -2.4s; }
.social__orb--yt .social__float { animation: social-floaty 8.2s ease-in-out infinite; animation-delay: -4.6s; }

/* clean thin solid brand ring (mask leaves only a 3px ring; #000 is the
   alpha-only mask idiom used elsewhere, not a palette colour) */
.social__ring {
  position: absolute; inset: 0; border-radius: 50%; z-index: 1;
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
          mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
}
.social__orb--ig .social__ring { background: var(--ig); }
.social__orb--fb .social__ring { background: var(--fb-blue); }
.social__orb--yt .social__ring { background: var(--yt-red); }

.social__face {
  position: absolute; inset: 3px; border-radius: 50%;
  background: var(--surface-1); z-index: 2; box-shadow: var(--shadow-md);
}

.social__logo {
  position: absolute; inset: 0; z-index: 3; display: grid; place-items: center;
  transition: transform var(--dur-hover-soft) var(--ease-hover);
}
.social__logo svg { width: 32%; height: auto; display: block; }
.social__logo--yt svg { width: 40%; }
.social__orb:hover .social__logo { transform: translateY(-12%); }
.social__orb--ig .social__logo { color: var(--ig); }
.social__orb--fb .social__logo { color: var(--fb-blue); }
.social__orb--yt .social__logo { color: var(--yt-red); }

.social__btn {
  position: absolute; z-index: 4; bottom: 15%; left: 50%; transform: translate(-50%, 12px);
  color: var(--surface-1); /* white text on the brand pill */
  font-size: 0.9rem; font-weight: 560; font-variation-settings: "wght" 560; padding: 0.5rem 1.1rem;
  border-radius: var(--r-pill); white-space: nowrap;
  opacity: 0; pointer-events: none;
  transition: opacity var(--dur-hover-soft) var(--ease-hover), transform var(--dur-hover-soft) var(--ease-hover);
}
.social__orb:hover .social__btn { opacity: 1; transform: translate(-50%, 0); }
.social__orb--ig .social__btn { background: var(--ig-mag); }
.social__orb--fb .social__btn { background: var(--fb-blue); }
.social__orb--yt .social__btn { background: var(--yt-red); }

@keyframes social-floaty { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-16px); } }

/* --- Decorative layers (behind the orbs), modular + removable. Both live inside
   .social__stage so their coordinates line up with the orbs, and both sit BELOW
   the orbs in the stacking order (orbs are opaque + later in DOM, so they cover
   the wave where they cross). pointer-events:none → orb hover/click untouched. --- */
#connect.social { overflow: hidden; } /* contain the oversized watermark bleed to the section */

/* Threaded wave: static; stroke = the brand gradient (colours from tokens, no
   hardcoded hex). The viewBox + path geometry are rebuilt from the orbs' real
   centres by initSocialWave() (1:1 px viewBox, preserveAspectRatio meet);
   non-scaling-stroke keeps the thin lines crisp. */
.social__wave {
  position: absolute; inset: 0; width: 100%; height: 100%;
  z-index: 0; pointer-events: none;
}
.social__wave path { fill: none; stroke: url(#social-wave-grad); stroke-linecap: round; vector-effect: non-scaling-stroke; }
.social__wave-main  { stroke-width: 1.9; stroke-opacity: 0.30; }
.social__wave-echo  { stroke-width: 1.4; stroke-opacity: 0.13; }
.social__wave-echo2 { stroke-width: 1.3; stroke-opacity: 0.10; }
.social__wave-fb { stop-color: var(--fb-blue); }
.social__wave-ig { stop-color: var(--ig-mag); }
.social__wave-yt { stop-color: var(--yt-red); }

/* Oversized faint "Topluluk" watermark. Resting opacity 0.07 (also the no-JS /
   reduced-motion state); initSocialWatermark ghosts it in on scroll. */
.social__watermark {
  /* z-index:-1 drops the word BEHIND the heading/eyebrow (which now overlaps it).
     .social__inner is isolated so this -1 lands behind the heading yet stays ABOVE
     the section background; without that isolate, -1 would hide it entirely. */
  position: absolute; inset: 0; z-index: -1;
  pointer-events: none;
}
.social__watermark span {
  /* User-picked spot: pulled UP so the word overlaps the heading, anchored RIGHT.
     VERTICAL: box top = (heading baseline) − 84px. The baseline sits a fixed ~83px
     above the stage top, so in stage coords that's −83 − 84 = −167px (fixed px, not
     a % that drifts). HORIZONTAL: the containing block (.social__watermark, inset:0
     of the stage) already equals the content box — its parent .social__inner has
     padding-inline:var(--page-pad) — so right:8px lands 8px inside the content's
     right edge (no extra page-pad math). left/top/right OFFSETS only — NO CSS
     transform here (the GSAP ghost-in animates translateX x:140→0; it bleeds off
     the right during the slide, clipped by #connect overflow:hidden). */
  position: absolute;
  /* WAS a fixed -167px. That is measured off the heading baseline and does not
     shrink when the section padding does, so with the trimmed padding above the
     word rose past the section's top edge and #connect{overflow:hidden} sliced
     it: measured 14.6px (10.1% of the word box) at 768 and 0.8px at 1024.
     -11.6vw resolves to -167.04px at 1440, so 1440 and wider are byte-for-byte
     the design that already worked; narrower viewports get a proportional lift,
     floored at -95px. Verified: clipping back to 0 at all seven widths. */
  top: clamp(-167px, -11.6vw, -95px);
  right: 8px;
  left: auto;
  font-family: var(--font-sans);
  font-weight: 600; font-variation-settings: "wght" 600;
  font-size: clamp(96px, 21vw, 250px);
  letter-spacing: -0.03em; line-height: 0.9;
  white-space: nowrap;
  color: var(--maroon);
  opacity: 0.07;
}

/* Stacked mobile layout has no arc — the threaded wave + centred watermark don't
   apply there, so hide both. */
@media (max-width: 760px) {
  .social__wave, .social__watermark { display: none; }
}

@media (max-width: 760px) {
  .social__stage { height: auto; display: flex; flex-direction: column; align-items: center; gap: 3rem; }
  /* Stack in normal flow, but keep `relative` (NOT static) so each orb stays the
     positioned containing block for its absolute .social__float/ring/face/logo —
     otherwise those escape the orb and overlap. */
  .social__orb { position: relative !important; left: auto; top: auto; width: clamp(200px, 56vw, 250px); }
}
@media (prefers-reduced-motion: reduce) {
  .social__orb, .social__head { transition: none; opacity: 1; transform: none; }
  .social__float { animation: none !important; }
}


/* ==========================================================================
   THEME STUDIO — WARM-ACCENT LAYER + WARMTH DOSES
   --------------------------------------------------------------------------
   Flat colours ONLY (no gradients, no overlays) and tokens ONLY (no raw hex).
   All values come from the per-palette --warm / --warm-strong / --warm-deep /
   --spark / --tint-* tokens (tokens.css §1/§1b), so this layer recolours with
   the active palette automatically. Nothing here animates → reduced-motion safe.

   DIAGNOSED TARGETS (verified against index.html):
     • Eyebrows/kickers use THREE classes: .t-eyebrow (hero + invitation),
       .services__eyebrow (#pillars), .social__eyebrow (#connect). All three here.
     • #ticker-values: the verse is .marquee__item (inside the masked .marquee);
       the reference label .ticker__ref ("Yuhanna 3:16") EXISTS, outside the mask.
     • #invitation emphasised word = .invitation__title .hl ("bekliyoruz");
       its primary CTA = .btn--filled.invitation__cta ("Yol tarifini al").
   ========================================================================== */

/* (a) ALL eyebrows/kickers → warm text only (plain text, no marker). The flat
   ::before spark-dot square + its 17px left-padding were removed per request, so
   eyebrows render as plain text again; the warm text colour is unchanged.
   Overrides the muted .t-eyebrow and the maroon .services__/.social__ eyebrow
   colours (same specificity, declared later). */
.t-eyebrow,
.services__eyebrow,
.social__eyebrow {
  color: var(--warm);
}

/* (b) Ticker band (always on, every warmth level): flat tint fill, verse in the
   palette accent, reference label in the warm hue at weight 600. */
#ticker-values { background: var(--tint-ticker); }
#ticker-values .marquee__item { color: var(--accent); }
.ticker__ref {
  color: var(--warm);
  font-weight: 600;
  font-variation-settings: "wght" 600;   /* drives the variable Google Sans Flex */
}

/* (c)+(d) WARMTH DOSES (html[data-warm]).
   warm 1 (Az): #invitation word + CTA stay --accent (base defaults — no rule),
     and there are NO section tints.
   warm 2 (Orta, default) AND warm 3: the #invitation emphasised word + ONLY this
     section's primary CTA go warm (CTA fill --warm-strong, hover --warm-deep).
     Every OTHER .hl / .btn--filled across the site stays --accent (untouched). */
html[data-warm="2"] .invitation__title .hl,
html[data-warm="3"] .invitation__title .hl { color: var(--warm-strong); }

html[data-warm="2"] .btn--filled.invitation__cta,
html[data-warm="3"] .btn--filled.invitation__cta { background: var(--warm-strong); }
html[data-warm="2"] .btn--filled.invitation__cta:hover,
html[data-warm="3"] .btn--filled.invitation__cta:hover { background: var(--warm-deep); }

/* warm 3 (Biraz fazla) adds ONE flat section tint — #connect ONLY. #pillars is
   intentionally NOT tinted: the ticker band (#ticker-values) right above it is
   always coloured, and two coloured bands back-to-back read poorly, so #pillars
   stays white (its .pillars var(--surface-1)) — the white gap between the ticker
   and the tinted #connect. #invitation also stays on --paper (map + feather). So
   the only two coloured bands (ticker, connect) always have white/paper between
   them. CHANGE 5: the #connect social orbs are opaque discs defined by their brand
   ring + shadow; when #connect is tinted, make the orb FACE match the panel so the
   discs blend in (still fully opaque — the wave never shows through them; it only
   threads the gaps behind). Selectors out-specify #connect.social / .social__face. */
html[data-warm="3"] #connect.social { background: var(--tint-3); }
html[data-warm="3"] #connect .social__face { background: var(--tint-3); }

/* (e) Line-wrap restoration: the studio loads five fonts live AND renders h2s at
   weight 800 (bolder headings), so several fonts are wider than Google Sans Flex
   and push the #connect heading "Bizi sosyal medyada takip et." onto a 2nd line at
   wide viewports. Relax this section head's width cap so it stays one line at the
   SAME type size for ALL five fonts. Verified 1 line at 1280–1920px for
   googlesans / poppins / montserrat / hanken / general (widest single-line is
   Montserrat @ ~42.9rem, so 44rem holds all with margin). No copy/markup/motion
   change; flat + tokens-agnostic length only. */
.social__head { max-width: 44rem; }


/* ==========================================================================
   SINGLE-DESIGN HEADER — hamburger navigation at every width
   --------------------------------------------------------------------------
   PKV Pendik Kilisesi ships the .menu-panel dropdown as its ONLY navigation,
   at all widths. Two reasons:

     1. Fidelity. İçerik.docx calls the navigation "açılır menü" in five
        separate items, and the church chose this palette/font inside the
        theme studio, where html.studio hid the pills at every width. The
        dropdown is the navigation they actually saw and signed off on.
     2. It cannot fit. The pill row is ~996px wide today and ~1075px after the
        docx's label renames ("Etkinlikler ve Duyurular" alone is a 228px
        pill), against a nowrap flex header. Measured: it needs ≈1244px now
        and ≈1440px after the renames. Below that it silently overflowed —
        body{overflow-x:clip} swallowed it with no scrollbar — taking the
        hamburger and the whole .menu-panel off-screen with it, because both
        sit after the nav in the same nowrap row.

   The pill markup and every .nav-pills rule stay in place, inert, as a
   template asset for the next church. Nothing here deletes them.
   Evidence, thresholds and the template-level write-up: docs/template-nav-bug.md
   ========================================================================== */

/* Hide the expanded pill nav at every width (the same selector html.studio
   used, minus the studio scope) … */
.site-header__nav { display: none; }

/* … and keep the EXISTING .menu-compact hamburger visible, reusing its
   open/close + outside-click + Esc + close-on-choose logic in main.js
   unchanged. The base .menu-toggle rule hides it until .is-compact; override
   that resting state so the toggle is reachable at the top of the page too.
   Transitions/tokens are untouched, so the base.css reduced-motion neutraliser
   still governs the panel's expand. */
.menu-compact { display: block; }
.menu-toggle {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

/* --------------------------------------------------------------------------
   PILL ROW ABOVE 1360px. The client asked for the boilerplate navbar; this is it.
   --------------------------------------------------------------------------
   Two things moved the breakpoint down from the ~1490px it once needed:

     1. `white-space: nowrap` on .nav-pills__link. Without it two labels broke
        inside their own pills at EVERY width, which is what made the row read as
        1075px when the true single-line row was wider. This is the actual fix
        and it stays.
     2. Makaleler was removed in Sep 2026, taking the row from eight pills to
        SEVEN. That alone is worth ~115px.

   MEASURED at 0.8125rem, seven pills, transitions neutralised and the row forced
   visible at every width. `slack` is the header's inner content box minus the
   sum of brand + nav + CTA:

       vw    1300  1310  1320  1330 | 1340  1345  1366  1380  1420  1440
       slack   -8     0    +9   +18 |  +27   +32   +51   +63   +99  +117
       clipped  1     1     1     1 |   0     0     0     0     0     0

   The row is a flat 956px from 1120px upward, because the root font maxes at
   18px there (clamp(100%, 0.95rem + 0.25vw, 112.5%) tops out at vw 1120), so
   both the 0.8125rem type and the rem-based pill padding stop growing.

   BREAKPOINT AT 1360px: 30px above 1330, the highest width that actually fails,
   with +45px of slack at the boundary itself. Chosen over a tighter value so
   1366x768 laptops, still one of the most common desktop widths, get the row.

   1200px WAS NOT REACHABLE and the arithmetic says why. At 1200 the header has
   about 1104px of inner width and brand + CTA take ~249px, so the row would have
   to fit in ~825px against its actual 956px. The pill PADDING is rem-based, not
   font-based, so shrinking the type does not shrink it: dropping 0.9375rem to
   0.8125rem bought only ~10px per pill, all of it text. Reaching 825px would
   need roughly 0.5625rem type, about 10px, which is not navigation any more.

   Stated in px, not rem: `rem` inside a media query resolves against the INITIAL
   16px rather than this site's fluid root, so 85rem would silently mean 1360
   regardless. An earlier 48rem landed exactly on 768 for that reason.

   BOTH CAN NEVER BE HIDDEN AT ONCE. Every declaration below is one half of a
   complementary pair, so there is no width and no scroll state with no
   navigation. That was the original template defect and it stays structurally
   impossible rather than merely avoided. Full write-up: docs/template-nav-bug.md
   -------------------------------------------------------------------------- */
@media (min-width: 1360px) {
  .site-header__nav { display: flex; }

  /* NO SCROLL SWAP UP HERE. The template collapses the pill row into the
     hamburger on .is-compact. Pendik does not: the client watched the icon
     appear and disappear while scrolling and read it as a bug, and their read
     wins. Above this breakpoint the pill row is the navigation at EVERY scroll
     position, and the hamburger never appears at any of them.

     This overrides the base `.site-header.is-compact .site-header__nav` rule,
     which fades and lifts the whole expanded menu out. Everything else
     .is-compact does is untouched and still fires on scroll: the transparent
     header background (shared with .is-scrolled), the brand badge's shadow lift,
     and the wordmark tucking behind the badge. Only the nav swap is cancelled. */
  .site-header.is-compact .site-header__nav {
    opacity: 1;
    transform: none;
    pointer-events: auto;
  }

  /* `display: none` on the WRAPPER, not `opacity: 0` on the button.
     An opacity-hidden <button> is still focusable: it would sit in the tab order
     as a dead control that does nothing when activated. .menu-compact also
     contains .menu-panel and its six links, so hiding the wrapper takes the
     whole dropdown out of the accessibility tree and the tab order together.
     Below 1360 this rule does not apply and the hamburger works as before. */
  .menu-compact { display: none; }
}

/* --------------------------------------------------------------------------
   NO PILL ROW AT ANY WIDTH. Decided Sep 2026, after three rounds.
   --------------------------------------------------------------------------
   The client asked for github.com/ac4rr/church-boilerplate's navbar, and it was
   built: a breakpoint above which the boilerplate's pill row appears. It has
   been REMOVED. The reasoning is worth keeping because the measurements are the
   useful part, and they are what killed it.

   That row is nowrap. With PKV Pendik's eight docx labels it measures 1151px at
   the original 0.9375rem, so it needs a viewport of ~1490px:

       row 1151px    1560 +62 · 1520 +30 · 1500 +11 · 1480 -8 · 1440 -47

   A 1520px breakpoint is above almost every real screen. The feature would have
   shipped invisible to nearly everyone, while the hamburger it replaced already
   worked at all six tested widths from the very first build. Shrinking the type
   to 0.8125rem brought the row to 1071px and let it fit at 1440, but rendered
   the PRIMARY navigation smaller than the footer's secondary nav.

   So Pendik ships hamburger-only, at every width. `.site-header__nav` stays
   `display: none` unconditionally, above. The pill markup and every .nav-pills
   rule remain in place, inert, as a template asset for the next church, whose
   labels may well be short enough to fit. Full write-up, including the two
   superseded measurements: docs/template-nav-bug.md

   `.nav-pills__link { white-space: nowrap }` is KEPT. It harms nothing while the
   row is hidden, and it is the fix the next church will need.
   -------------------------------------------------------------------------- */


/* ==========================================================================
   THEME STUDIO — HEADER (showcase dropdowns + always-on hamburger)
   --------------------------------------------------------------------------
   The production header markup is untouched and fully restorable: drop the
   `studio` class on <html> (+ the studio markup) and the original pill-nav +
   scroll-collapse header returns. In studio mode we:
     • show the three palette / font / warmth <select>s (hidden otherwise),
     • hide the expanded pill nav and keep the EXISTING .menu-compact hamburger
       always visible — reusing its open/close + outside-click + Esc + close-on-
       choose logic in main.js — so the six nav items live in the .menu-panel,
     • leave the scroll-driven .is-compact brand-word tuck intact (compact
       behaviour preserved). Every colour is a token → recolours per palette.
   ========================================================================== */

/* Controls hidden unless studio mode is on. */
.studio-controls { display: none; }
html.studio .studio-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 auto;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  min-width: 0;
}

.studio-field {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}
.studio-field__label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--muted);
  font-weight: 600;
  font-variation-settings: "wght" 600;
  white-space: nowrap;
}

/* Native <select> restyled with tokens (so the box recolours with the palette).
   appearance:none lets the token bg/border/text apply on every OS; the flat caret
   is the .studio-field::after triangle (also token-coloured). */
.studio-select {
  appearance: none;
  -webkit-appearance: none;
  font: inherit;
  font-size: 0.85rem;
  line-height: 1;
  color: var(--ink);
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 0.5rem 1.9rem 0.5rem 0.7rem;
  min-height: 2.5rem;                 /* ≥44px tap target */
  cursor: pointer;
  transition: border-color var(--dur-hover) var(--ease-hover),
              box-shadow var(--dur-hover) var(--ease-hover),
              color var(--dur-hover) var(--ease-hover);
}
.studio-select:hover { border-color: rgba(var(--ink-rgb), 0.28); box-shadow: var(--shadow-sm); }
/* keyboard focus uses the global :focus-visible accent ring (base.css). */
.studio-select option { color: var(--ink); background: var(--surface-1); }

/* Flat caret: a downward triangle at the select's right edge, palette-coloured. */
.studio-field::after {
  content: "";
  position: absolute;
  right: 0.7rem;
  top: 50%;
  margin-top: -2px;
  width: 0;
  height: 0;
  pointer-events: none;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid var(--muted);
}

/* In studio mode the expanded pill nav is replaced by the hamburger panel … */
html.studio .site-header__nav { display: none; }
/* … and the hamburger toggle stays ALWAYS visible (override the scroll-gated
   hidden top state); its open/close logic is the unchanged main.js handler. */
html.studio .menu-toggle {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

@media (max-width: 64rem) {
  /* Tablet: tighten the gap; labels drop (the selects self-describe) to keep the
     brand + selects + hamburger on one row. */
  html.studio .studio-controls { gap: var(--space-2) var(--space-3); }
  html.studio .studio-field__label { display: none; }
}
@media (max-width: 40rem) {
  /* Mobile: production hides .menu-compact + .nav-pills; studio needs the
     hamburger, so bring .menu-compact back. The controls wrap to their own row
     under the brand (the showcase header grows a little — acceptable). */
  html.studio .menu-compact { display: block; }
  html.studio .site-header__inner { flex-wrap: wrap; row-gap: var(--space-2); }
  html.studio .studio-controls { order: 3; flex-basis: 100%; justify-content: flex-start; }
  html.studio .studio-field__label { display: inline; }
  html.studio .studio-select { font-size: 0.8rem; }
}

/* THEME STUDIO v2 — CUSTOM-PALETTE NOTE.
   A full-width row at the BOTTOM of the switcher area. It is a flex item of
   .studio-controls (flex-basis 100%), so it is laid out in normal flow and can
   never overlap the nav or the hamburger — no positioning involved. Type is one
   step under .studio-field__label; every colour is a palette token, no new hex,
   so it recolours with the palette like the rest of the controls. */
.studio-note { display: none; }
html.studio .studio-note {
  display: block;
  flex: 0 0 100%;
  margin: 0;
  text-align: center;
  font-size: 0.68rem;
  line-height: 1.4;
  letter-spacing: 0.005em;
  color: var(--muted);
  text-wrap: pretty;
}
html.studio .studio-note a {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  transition: color var(--dur-hover) var(--ease-hover);
}
html.studio .studio-note a:hover { color: var(--accent-deep); }

@media (max-width: 40rem) {
  /* Mobile: the controls already own their own full-width row under the brand,
     so left-align the note with them instead of centring it under the selects. */
  html.studio .studio-note { text-align: left; }
}

/* THEME STUDIO v2 — clear the taller studio header.
   .site-header is position:fixed (adds no flow height) and .hero clears it with
   `padding-top: clamp(5.5rem, 9vw, 7rem)`, an allowance sized for the ~98px
   production header. The studio header carries three 15-option selects plus the
   custom-palette note and wraps to two rows at 768px and three at 390px, so it
   overlaid the hero (measured: 215px of header against an 89px allowance at
   390px, BEFORE the note was added). studio.js publishes the measured height as
   --studio-header-h; max() floors the padding at it while leaving every viewport
   where the original clamp is already large enough completely untouched. */
html.studio .hero {
  padding-top: max(clamp(5.5rem, 9vw, 7rem),
                   calc(var(--studio-header-h, 5.5rem) + var(--space-5)));
}

/* THEME STUDIO v2 — MOBILE THEME DISCLOSURE (<=40rem, studio only).
   Three 15-option selects plus the custom-palette note made the FIXED header
   253px tall at 390px, which is a poor first impression on the device a
   prospect is most likely to open this on. Below 40rem the header row collapses
   to brand + "Tema" toggle + hamburger, and the controls move into an
   absolutely-positioned OVERLAY panel.
   Because the panel is out of flow it cannot change the header's border-box
   height, so --studio-header-h (and therefore the hero's top padding) is
   IDENTICAL open and closed: expanding causes no layout jump.
   Above 40rem the toggle is display:none and nothing about the inline layout
   changes. Visibility is driven by opacity/transform/visibility, mirroring
   .menu-panel, so the base.css reduced-motion neutraliser collapses it to an
   instant swap. Tokens only, no new hex. */
.studio-toggle { display: none; }

@media (max-width: 40rem) {
  html.studio .studio-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 2.75rem;              /* >=44px tap target (CLAUDE.md rule 7) */
    padding: var(--space-2) var(--space-4);
    font: inherit;
    font-size: 0.72rem;
    font-weight: 600;
    font-variation-settings: "wght" 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink);
    background: var(--surface-1);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    cursor: pointer;
    transition: border-color var(--dur-hover) var(--ease-hover),
                box-shadow var(--dur-hover) var(--ease-hover);
  }
  html.studio .studio-toggle:hover {
    border-color: rgba(var(--ink-rgb), 0.28);
    box-shadow: var(--shadow-sm);
  }
  /* Flat caret, same language as .studio-field::after. */
  html.studio .studio-toggle::after {
    content: "";
    width: 0; height: 0;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 5px solid var(--muted);
    transition: transform var(--dur-hover) var(--ease-hover);
  }
  html.studio .studio-toggle[aria-expanded="true"]::after { transform: rotate(180deg); }

  /* All three items must share ONE row. Measured: at 390px the row overflowed
     its 350px budget by 0.2px (brand 198 + toggle 92 + hamburger 44 + 2 gaps),
     and at 360px by ~14px, so the hamburger wrapped to a second line. Tighten
     the row gap, run the toggle narrower, and tuck the brand's second word —
     the header already tucks the wordmark in its compact scroll state, so this
     is the same idea applied at mobile width. The brand still reads
     "Yaşayan Söz" and the toggle keeps its visible "Tema" label. */
  html.studio .site-header__inner { gap: var(--space-2) var(--space-3); }
  html.studio .brand__word-2 { display: none; }
  html.studio .studio-toggle { padding: var(--space-2) var(--space-3); font-size: 0.68rem; letter-spacing: 0.1em; }

  /* The controls become the overlay panel. position:absolute takes them OUT OF
     FLOW, which is what keeps --studio-header-h constant. */
  html.studio .site-header__inner { position: relative; }
  html.studio .studio-controls {
    position: absolute;
    top: calc(100% + 0.55rem);
    left: 0;
    right: 0;
    z-index: 60;
    flex-basis: auto;
    justify-content: flex-start;
    gap: var(--space-3) var(--space-4);
    padding: var(--space-4);
    background: var(--surface-1);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    box-shadow: var(--shadow-md);
    opacity: 0;
    transform: scale(0.97) translateY(-6px);
    transform-origin: top center;
    pointer-events: none;
    visibility: hidden;               /* also removes it from the tab order */
    transition: opacity var(--dur-ui) var(--ease-hover),
                transform var(--dur-ui) var(--ease-hover),
                visibility var(--dur-ui) linear;
  }
  html.studio .studio-controls.is-open {
    opacity: 1;
    transform: none;
    pointer-events: auto;
    visibility: visible;
  }
  /* Rule 7: lift the selects to a real 44px inside the panel. ADDITIVE override
     — the base .studio-select rule (min-height 2.5rem) is untouched. */
  html.studio .studio-select { min-height: 2.75rem; }
  html.studio .studio-field { flex: 1 1 100%; }
  html.studio .studio-field .studio-select { flex: 1 1 auto; }
}


/* ==========================================================================
   ABOUT PAGE  (hakkimizda.html)  — sections that exist ONLY on the About page.
   Reuses the shared primitives: .media/.squircle/.edge tiles, .t-* type, .hl,
   .container, the #invitation map, the maroon-fill CTA language, and the #connect
   "Topluluk" faint-watermark treatment. Flat colours + tokens ONLY (no raw hex, no
   background gradients/overlays — the .media warm fallback + the social-wave line
   are the only pre-existing gradients, untouched).
   ========================================================================== */

/* --- REVEAL (fade + rise) — the SAME treatment as the homepage #connect heading:
   opacity + translateY(--entrance-shift), --ease-text over --dur-entrance-lg,
   toggled BOTH directions (play on enter, reverse on leave) by initAboutReveal via
   the .is-in class. Hidden state is gated behind .js so no-JS shows everything; the
   watchdog (hakkimizda.html) + main.js reveal it on JS-fail. Reduced motion → final
   state, no transition. --- */
.js [data-reveal-up] {
  opacity: 0;
  transform: translateY(var(--entrance-shift));
  transition: opacity var(--dur-entrance-lg) var(--ease-text),
              transform var(--dur-entrance-lg) var(--ease-text);
  will-change: opacity, transform;
}
.js [data-reveal-up].is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal-up] { opacity: 1 !important; transform: none !important; transition: none !important; }
}

/* --- Background WATERMARK word — ONE standard treatment for every watermarked
   About section (HİKAYE / İMAN / DEĞERLER / EKİP). The faint word is absolutely
   positioned inside its own section container (inside the maroon panel for İMAN),
   top-right, bleeding off the RIGHT edge and NOT clipped at the top (the top offset
   is positive, so the full word height shows). The section's content wrapper sits
   ABOVE it (wrapper z-index:1, word layer z-index:0). Entrance = slide IN FROM THE
   RIGHT (initAboutReveal: gsap.from xPercent 24 → 0, sine.out, toggleActions play/
   reverse). Opacity is NOT animated — the faint CSS opacity is the resting state,
   so no-JS / reduced motion shows it faint. --- */
/* NO overflow HERE, deliberately: the watermark word is allowed to run past its
   section, even off screen. Do not reinstate overflow, and do not substitute
   clip, auto, or a mask. html{overflow-x:clip} stops the scrollbar. */
.about-wm { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.about-wm span {
  position: absolute;
  top: clamp(2rem, 4.5vw, 3.25rem);
  right: clamp(-2.5rem, -3.5vw, -1.25rem);
  font-family: var(--font-sans);
  font-size: clamp(4.5rem, 13vw, 11.5rem);
  font-weight: 800; font-variation-settings: "wght" 800;
  letter-spacing: -0.04em;
  line-height: 0.9;
  text-transform: uppercase;
  white-space: nowrap;
  pointer-events: none; user-select: none;
  color: var(--maroon); opacity: 0.06;     /* light sections */
}
/* Content wrapper sits ABOVE the watermark word. */
.about-story > .container,
.about-values > .container,
.about-team > .container { position: relative; z-index: 1; }
.about-belief__content { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; }

/* --- 2. FOTO ŞERİDİ — two rows of squircle tiles, scrubbed horizontally in
   OPPOSITE directions by initPhotoStrip (scroll-tied, not autoplay). --- */
.about-strip { overflow: clip; padding-block: clamp(3rem, 7vw, 6rem); background: var(--hero-bg); }
.about-strip__rows { display: flex; flex-direction: column; gap: var(--gutter); }

/* The park photograph's credit sits UNDER the strip, not inside a tile, because
   the rows counter-scroll and a caption on a moving tile slides away from what
   it credits. Only POSITION lives here; the look comes from the shared
   .media-credit. @pendikilcemiz gave permission IN EXCHANGE for the account
   name being visible, so this line is a condition of use. */
/* ===========================================================================
   SHARED CREDIT LINE — one treatment, every page.
   Replaces .iletisim-photo__cap and the look half of .about-strip__credit,
   which were two copies of the same declarations. A third copy was about to be
   written for the homepage; promoting it instead makes the "one credit
   language" rule structural rather than a convention retyped each time.

   Some of these lines are a LICENCE OR PERMISSION CONDITION, not decoration:
   CC BY obliges visible attribution, and @pendikilcemiz granted use in exchange
   for it. Never hide, shrink to nothing, or move into an alt.
   =========================================================================== */
.media-credit {
  margin-top: var(--space-3);
  max-width: 62ch;
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.6;
}
.media-credit a { color: var(--accent); text-underline-offset: 0.2em; }

/* The mosaic's credit. Tiles carry no caption of their own (their labels name
   the destination page and are aria-hidden), so Rıhtım's CC BY line sits under
   the section, aligned to the page gutter like the strip's. */
.life__credit {
  max-width: var(--container);
  margin: var(--space-4) auto 0;
  padding-inline: var(--page-pad);
}

/* The basemap credit. POSITION ONLY; the look comes from the shared
   .media-credit, same as the mosaic's and the strip's.

   This is a LICENCE CONDITION and it is also a SECURITY FIX. MapLibre's
   AttributionControl was removed in Oct 2026 because CVE-2026-85061 (CRITICAL)
   renders third-party attribution strings through a broken DOM.sanitize() and
   into innerHTML, zero-click. OpenFreeMap's TileJSON supplies exactly such a
   string. The attribution is therefore static HTML written by us, which
   satisfies OpenFreeMap, OpenMapTiles and OpenStreetMap and removes the sink.
   Do not reinstate maplibregl.AttributionControl. See docs/DEVIR.md. */
.visitmap__credit {
  /* Inside .container, so NO page-pad and NO auto centring: the container
     already supplies both. Only the top gap is ours. */
  margin-top: var(--space-4);
}

.about-strip__credit-pos {
  max-width: var(--container);
  /* --space-4, not the shared .media-credit's --space-3: this is what the strip
     credit already used and shipping the shared class must not move it. */
  margin: var(--space-4) auto 0;
  padding-inline: var(--page-pad);
}
.about-strip__row { display: flex; gap: var(--gutter); width: max-content; will-change: transform; }
.about-strip__tile {
  flex: 0 0 auto;
  height: clamp(150px, 20vw, 280px);
  width: var(--tw, 22rem);
  aspect-ratio: auto;            /* override .media's 4/3 — width + height are explicit here */
  max-width: none;
  /* --tw used to be set inline per tile, when the strip held ten differently
     sized stock images. All six church photographs use one width, so it lives
     here — which is also what lets the breakpoint below override it. 32rem is
     what keeps each row wider than its container at 1440, so initPhotoStrip's
     overflow stays > 0 and the counter-scroll survives. */
  --tw: 32rem;
}
/* On a phone a 512px tile crops these wide-angle room shots to ~76% of the
   frame and loses the context that makes them worth showing. 22rem still leaves
   ~666px of overflow at 390px, so the scrub keeps running. This must stay AFTER
   the rule above: same specificity, so source order decides. */
@media (max-width: 40rem) {
  .about-strip__tile { --tw: 22rem; }
}

/* PER-TILE WIDTHS. Every tile was 32rem, so all six were the identical rectangle
   at every viewport: 576x280 (2.06) at 1440, 568x205 (2.78) at 1024, 356x150
   (2.37) at 390. Height has to stay uniform -- that is what makes it a strip --
   but width is per-tile through --tw, so the shape variety is free.

   Widths are matched to each photograph's own aspect so the varied shapes also
   CROP LESS than the uniform 32rem did. Sources: 01 2.20, 02 1.77, 03 2.27,
   04 2.78, 05 2.02, noel 1.50, yol-basamaklar 2.20 (a deliberate 2.20 crop of a
   portrait original, see MEDIA-CREDITS.md). At 32rem/280 every one was forced to
   2.06, which over-cropped noel and 02 and wasted 04's width.

   SEVEN tiles now, rows of 4 and 3, so both rows keep the three-per-row minimum
   the counter-scroll needs. Row overflow stays positive at every width. */
/* Slot widths are chosen so NOTHING upscales at DPR2. Each tile's CSS width x2
   must stay under its source's real pixel width:
     park 720 -> 1440 (src 1920) · marina 648 -> 1296 (src 5081)
     ib-02 432 ->  864 (src 1024) · yol    720 -> 1440 (src 1536)
     ib-01 432 ->  864 (src 1024) · noel   432 ->  864 (src 1024)
   ib-01 used to sit in a 612px slot and upscaled 20%; it is fine at 432. The
   three former upscalers were a SLOT problem, not an image problem. */
.about-strip__row:nth-child(1) .about-strip__tile:nth-child(1) { --tw: 40rem; }  /* park   */
.about-strip__row:nth-child(1) .about-strip__tile:nth-child(2) { --tw: 36rem; }  /* marina */
.about-strip__row:nth-child(1) .about-strip__tile:nth-child(3) { --tw: 24rem; }  /* ib-02  */
.about-strip__row:nth-child(2) .about-strip__tile:nth-child(1) { --tw: 40rem; }  /* yol    */
.about-strip__row:nth-child(2) .about-strip__tile:nth-child(2) { --tw: 24rem; }  /* ib-01  */
.about-strip__row:nth-child(2) .about-strip__tile:nth-child(3) { --tw: 24rem; }  /* noel   */

/* Phones keep proportionally narrower tiles for the same reason the 22rem
   override exists, but still varied rather than identical frames. */
@media (max-width: 40rem) {
  /* park drops to 23rem (372px) so DPR2 needs 744 and it takes the 768 tier
     instead of 1024: 52.044 bytes saved on the heaviest image on the page. */
  .about-strip__row:nth-child(1) .about-strip__tile:nth-child(1) { --tw: 23rem; }
  .about-strip__row:nth-child(1) .about-strip__tile:nth-child(2) { --tw: 21rem; }
  .about-strip__row:nth-child(1) .about-strip__tile:nth-child(3) { --tw: 19rem; }
  .about-strip__row:nth-child(2) .about-strip__tile:nth-child(1) { --tw: 23rem; }
  .about-strip__row:nth-child(2) .about-strip__tile:nth-child(2) { --tw: 19rem; }
  .about-strip__row:nth-child(2) .about-strip__tile:nth-child(3) { --tw: 17rem; }
}

/* --- 3. HİKAYEMİZ — two columns on desktop (text left, community photo right),
   stacked on mobile with the image BELOW the text. Airy. --- */
/* overflow:hidden REMOVED so the .about-wm watermark can run past this box: the
   client's instruction is to let it overflow, even off screen. A border-radius
   clips this element's own background on its own, so the hidden overflow was
   only ever clipping CHILDREN. Containment now comes from html{overflow-x:clip}
   in base.css, which is what actually reaches the viewport. */
.about-story { position: relative; isolation: isolate; }
.about-story__inner {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}
.about-story__col { max-width: 44ch; }
.about-story__col > .t-eyebrow { margin-bottom: var(--space-4); }
.about-story__p { max-width: 44ch; }
.about-story__p + .about-story__p { margin-top: var(--space-5); }
.about-story__p .text-ink { color: var(--ink); } /* key phrases pop to ink over the muted lead */
.about-story__photo { width: 100%; aspect-ratio: 4 / 3; height: auto; max-width: none; } /* community photo, object-fit:cover via .media__inner img */
@media (max-width: 860px) {
  .about-story__inner { grid-template-columns: 1fr; gap: clamp(1.5rem, 5vw, 2.5rem); }
  .about-story__photo { order: 2; aspect-ratio: 16 / 10; }   /* image BELOW the text on mobile */
}

/* --- 4. NEYE İNANIYORUZ — a filled MAROON squircle PANEL (site maroon-panel
   language): var(--maroon) fill, var(--paper) text, site radius, generous padding.
   Centred, clean faith statement (comfortable weight — not heavy) + a paper-filled
   pill link. İMAN watermark rendered as very faint CREAM in the standard spot. --- */
.about-belief { background: var(--hero-bg); }
/* overflow:hidden REMOVED so the .about-wm watermark can run past this box: the
   client's instruction is to let it overflow, even off screen. A border-radius
   clips this element's own background on its own, so the hidden overflow was
   only ever clipping CHILDREN. Containment now comes from html{overflow-x:clip}
   in base.css, which is what actually reaches the viewport. */
.about-belief__panel {
  position: relative; isolation: isolate;
  background: var(--maroon);
  color: var(--paper);
  border-radius: var(--r-card);
  padding: clamp(3rem, 7vw, 6rem) clamp(1.5rem, 5vw, 5rem);
  text-align: center;
  display: flex; flex-direction: column; align-items: center;
}
.about-belief__panel .t-eyebrow { color: var(--paper); margin-bottom: var(--space-4); } /* kicker now sits inside .about-belief__content */
.about-belief__statement {
  max-width: 24ch; margin-inline: auto; color: var(--paper);
  font-size: clamp(1.6rem, 1.1rem + 2.2vw, 2.6rem);
  line-height: 1.28; letter-spacing: -0.02em;
  font-weight: 480; font-variation-settings: "opsz" 40, "wght" 480, "ROND" var(--ROND-soft); /* comfortable, not heavy */
}
.about-belief__statement .hl-cream { color: var(--paper); font-weight: 560; font-variation-settings: "opsz" 40, "wght" 560; } /* lighter cream emphasis; never italic */
.about-belief__cta {
  margin-top: clamp(1.75rem, 4vw, 2.75rem);
  background: var(--paper); color: var(--maroon);
  font-weight: 560; font-variation-settings: "wght" 560, "opsz" 16, "ROND" var(--ROND-soft);
}
.about-belief__cta:hover { background: var(--surface-2); box-shadow: var(--shadow-md); } /* no transform — avoids clashing with the reveal-up transform transition */
.about-belief .about-wm span { color: var(--paper); opacity: 0.08; } /* İMAN as faint cream on the maroon panel (standard) */

/* MİSYON on the page's plain surface, not the accent panel. Vizyon is a
   three-part list and Misyon is a single sentence: giving both the same accent
   block erased a distinction the source already makes, and the pair read as one
   component twice. This changes the SURFACE ONLY — alignment, watermark
   treatment, eyebrow treatment and type scale are all untouched. The colour
   flips below are forced by the surface (cream on paper is invisible) and every
   value is an existing token; the watermark keeps its 0.08 opacity, only its
   hue changes. --bg is the same surface #story and the values sections use. */
.about-belief--plain { background: var(--bg); }
.about-belief--plain .about-belief__panel { background: transparent; color: var(--ink); }
.about-belief--plain .about-belief__panel .t-eyebrow { color: var(--accent); }
.about-belief--plain .about-belief__statement { color: var(--ink); }
.about-belief--plain .about-wm span { color: var(--ink); }

/* KÖPRÜ — the vision's own three-part shape (Vizyon/Misyon docx). A list, not
   prose and not cards: the source is a colon followed by three parallel lines.
   Sized under .about-belief__statement so the statement still leads. Tokens
   only, no new hex. */
.kopru { list-style: none; margin: 1.1rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.55rem; }
.kopru__part {
  font-size: clamp(1.15rem, 1rem + 0.9vw, 1.75rem);
  line-height: 1.35;
  font-weight: var(--wght-medium);
  color: var(--paper);
  opacity: 0.88;
}

/* Name-only value rows. "6 Temel Değerimiz" and "Yolumuz" are given in the
   source as bare names with no descriptions, so these rows carry no
   .values__desc. Trim the padding the two-line rows needed. */
.values__row--name-only { padding-block: clamp(0.9rem, 1.6vw, 1.4rem); }

/* Kaynaklar cards. Outbound links to PKV Nilüfer Protestan Kilisesi, reusing
   the .values__row document rhythm rather than the video-thumbnail row this
   page used to carry (nothing is rehosted and no image is hotlinked, so there
   is no thumbnail to show). The source credit sits under the description; the
   arrow marks the link as leaving the site. Tokens only. */
.kaynak-row { display: block; text-decoration: none; color: inherit; }
.kaynak-row:hover .values__name { color: var(--accent); }
.kaynak-row__source {
  display: block;
  margin-top: 0.5rem;
  font-size: 0.8125rem;
  letter-spacing: 0.02em;
  color: var(--muted);
}
.kaynak-row__ext { color: var(--accent); }
.kaynak-intro { max-width: 58ch; margin-top: var(--space-3); color: var(--muted); }

/* Empty-state note for Etkinlikler ve Duyurular. That page ships deliberately
   empty (İçerik.docx item 17: the church adds entries itself), so this is a
   short line rather than a page of placeholder cards. Was shared with
   .makaleler-empty__note until Makaleler was removed in Sep 2026. */
.dua-empty__note { max-width: 46ch; color: var(--muted); margin: 0; }
.dua-empty__note a { color: var(--accent); text-underline-offset: 0.2em; }

/* ==========================================================================
   ÜÇTE ÜÇ  (#ucte-uc on incil-oku.html)
   --------------------------------------------------------------------------
   The church works off this chart in small groups, so which artifact is
   PRIMARY changes with the viewport rather than both being shown equally:

     >= 48rem  the image leads (18.1px chart text at the 60rem slot), the
               transcript follows as the machine-readable reference.
     <  48rem  the transcript leads at full body size, and the image is NOT
               rendered inline — at 350px its text would be 6.6px. It stays
               reachable through .ucteuc__full, which is present at every width.

   Tokens only, no new hex.
   ========================================================================== */
/* The eyebrow is a <p>, and base.css zeroes <p> margins, while .services__title
   carries no margin-top. Measured at 1440: eyebrow bottom 1507, heading top 1506
   -- a 0px gap, so the two were touching. Spacing belongs here rather than on
   .t-eyebrow, which is shared by every section that already handles its own. */
.ucteuc__head { max-width: 60rem; margin-inline: auto; }
.ucteuc__head .t-eyebrow { margin-bottom: var(--space-3); }
.ucteuc__lead { max-width: 46ch; color: var(--muted); margin-top: var(--space-3); }

/* Chart reduced 20% (60rem -> 48rem) and centred. It was 1080px wide inside a
   1325px container, flush left, leaving 245px empty to its right.
   Legibility re-checked: the source is 2392px wide with a median text ink height
   of 45px, so at 1080 it rendered at 20.3px and at 864 it renders at
   45 x (864/2392) = 16.3px -- still at body size, which is the floor we set. */
.ucteuc__figure { margin: var(--space-6) auto 0; max-width: 48rem; }
.ucteuc__img {
  display: block; width: 100%; height: auto;
  border-radius: var(--r-card);
  border: 1px solid var(--line);
  background: var(--surface-1);
}
.ucteuc__cap { margin-top: var(--space-3); }
.ucteuc__full {
  display: inline-flex; align-items: center; gap: 0.4rem;
  min-height: 44px;                       /* tap target, per CLAUDE.md §8 */
  color: var(--accent); font-weight: var(--wght-medium);
  text-underline-offset: 0.2em;
}

.ucteuc__cols {
  margin-top: var(--space-7);
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gutter);
  align-items: start;
}
.ucteuc__col { border-top: 1px solid var(--line); padding-top: var(--space-4); }
.ucteuc__coltitle {
  font-size: clamp(1.05rem, 0.95rem + 0.4vw, 1.25rem);
  font-weight: var(--wght-semibold); letter-spacing: 0.02em;
  margin: 0 0 var(--space-3);
}
.ucteuc__arrow { color: var(--accent); margin-right: 0.35rem; }
.ucteuc__list { margin: 0; padding-left: 1.4rem; display: flex; flex-direction: column; gap: 0.6rem; }
.ucteuc__list > li { font-size: 1rem; line-height: 1.6; }
.ucteuc__method { margin: 0.5rem 0 0.6rem; color: var(--accent-deep); font-weight: var(--wght-medium); }
.ucteuc__q { margin: 0; padding-left: 1.1rem; display: flex; flex-direction: column; gap: 0.45rem; }
.ucteuc__q > li { color: var(--muted); font-size: 0.95rem; line-height: 1.6; }

@media (max-width: 64rem) {
  .ucteuc__cols { grid-template-columns: 1fr 1fr; }
}

/* Below 768px the transcript is the primary artifact. 47.9375rem = 767px, so
   768 itself stays on the image side — measured, the chart's text renders at
   13.3px there, which is small but legible. The image comes OUT of the flow
   rather than being shown at an illegible size; the "tam boyutta aç" link
   stays, so the chart is still reachable on a phone. */
@media (max-width: 47.9375rem) {
  .ucteuc__cols { grid-template-columns: 1fr; margin-top: var(--space-5); order: 1; }
  .ucteuc__figure { display: contents; }        /* keeps the caption/link in flow */
  .ucteuc__img, .ucteuc__figure picture { display: none; }
  .ucteuc__cap { order: 2; margin-top: var(--space-5); }
  .ucteuc__list > li { font-size: 1.0625rem; }  /* full body size on a phone */
  .ucteuc__q > li { font-size: 1rem; }
}

/* ==========================================================================
   PROJEMİZ (projemiz.html) — a reading page: one measured column of prose with
   the three project photographs breaking it. Not in the primary nav; reached
   from Hakkımızda. Reuses .media/.squircle and the type scale; tokens only.
   ========================================================================== */
.projemiz__wrap { max-width: 46rem; margin-inline: auto; }
.projemiz__head { margin-bottom: var(--space-4); }
.projemiz__lead { margin: 0 0 var(--space-6); }
.projemiz__h2 {
  margin: var(--space-7) 0 var(--space-4);
  font-size: clamp(1.35rem, 1.1rem + 1vw, 1.9rem);
  font-weight: var(--wght-semibold); letter-spacing: -0.01em;
}
.projemiz__p { margin: 0 0 var(--space-4); line-height: 1.75; color: var(--muted); }
.projemiz__p:last-of-type { margin-bottom: 0; }
.projemiz__photo { width: 100%; margin: var(--space-6) 0; aspect-ratio: auto; max-width: none; }
.projemiz__photo .media__inner img { width: 100%; height: auto; display: block; }
.projemiz__close { margin: var(--space-6) 0 0; color: var(--ink); }

/* --- 5. DEĞERLERİMİZ — #pillars-style list + squircle accent-soft hover
   (~0.3s, no layout shift; the base padding reserves the room, the divider fades to
   transparent) + DEĞERLER watermark. --- */
/* overflow:hidden REMOVED so the .about-wm watermark can run past this box: the
   client's instruction is to let it overflow, even off screen. A border-radius
   clips this element's own background on its own, so the hidden overflow was
   only ever clipping CHILDREN. Containment now comes from html{overflow-x:clip}
   in base.css, which is what actually reaches the viewport. */
.about-values { position: relative; isolation: isolate; background: var(--surface-1); }
.about-values__head { margin-bottom: clamp(1.5rem, 3vw, 2.5rem); }
.about-values__head > .t-eyebrow { margin-bottom: 0.6rem; }
.values__list { list-style: none; margin: 0; padding: 0; }
.values__row {
  display: block;
  padding: clamp(1.2rem, 2.4vw, 2rem) clamp(0.85rem, 1.6vw, 1.3rem);
  border-top: 1px solid var(--line);
  border-radius: var(--r-md);
  transition: background var(--dur-hover-soft) var(--ease-hover),
              border-color var(--dur-hover-soft) var(--ease-hover);
}
.values__row:last-child { border-bottom: 1px solid var(--line); }
.values__row:hover { background: var(--accent-soft); border-color: transparent; } /* faint accent tint, never dark; no size change */
.values__name {
  display: block;
  font-size: clamp(1.35rem, 2.8vw, 2.3rem); line-height: 1.05; letter-spacing: -0.02em;
  color: var(--ink); font-weight: 640; font-variation-settings: "opsz" 60, "wght" 640;
  transition: color var(--dur-hover-soft) var(--ease-hover);
}
.values__row:hover .values__name { color: var(--accent); }
.values__desc {
  display: block; margin-top: 0.5rem; max-width: 54ch;
  color: var(--muted); font-size: clamp(1rem, 1.3vw, 1.15rem); line-height: 1.5;
}

/* --- 6. EKİBİMİZ — exactly 2 clean cards, CENTERED, with SMALLER (~190px) square
   squircle photos: role (uppercase maroon) · name · short bio. + EKİP watermark. --- */
.about-team { position: relative; isolation: isolate; overflow: hidden; background: var(--hero-bg); }
.about-team__head { margin-bottom: clamp(1.5rem, 3vw, 2.5rem); text-align: center; }
.about-team__head > .t-eyebrow { margin-bottom: 0.6rem; }
.about-team__grid { display: flex; flex-wrap: wrap; justify-content: center; gap: clamp(2rem, 6vw, 5rem); }
.about-team__card { display: flex; flex-direction: column; align-items: center; text-align: center; max-width: 22rem; }
.about-team__photo {
  width: clamp(200px, 22vw, 248px); aspect-ratio: 4 / 5; height: auto; max-width: none; /* portrait, object-fit:cover via .media__inner img */
  margin-bottom: var(--space-4);
}
.about-team__role { margin-bottom: var(--space-2); }
.about-team__name { margin-bottom: var(--space-3); }
.about-team__bio { color: var(--muted); max-width: 34ch; line-height: 1.6; }

/* About responsive */
@media (max-width: 40rem) {
  .about-team__grid { gap: var(--space-7); }
  .about-belief__statement { max-width: 20ch; }
}


/* ==========================================================================
   İNANÇ BİLDİRGESİ PAGE  (inanc-bildirgesi.html)
   --------------------------------------------------------------------------
   Reuses: .hero, .t-*, .hl, .container, the maroon-panel language, the standard
   .about-wm watermark (hero only), the [data-reveal-up] fade+rise reveal, and the
   shared Lenis anchor smooth-scroll. Adds only this page's reading layout, sticky
   index rail (scroll-spy), scripture chips + verse popover, and the maroon contact
   panel. Flat colours + tokens ONLY (no raw hex; the rgba tints use the --maroon-rgb
   / --paper-rgb channels from tokens.css, same idiom as --accent-soft).
   ========================================================================== */

/* --- 2. İÇİNDEKİLER — clickable 8-item overview, 2 columns desktop / 1 mobile,
   pillars-style hover (soft maroon tint + maroon title). Links (href="#id") are
   smooth-scrolled by the shared Lenis anchor handler. --- */
.inanc-toc__list {
  list-style: none; margin: clamp(1.25rem, 2.5vw, 2rem) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-2) clamp(1.5rem, 4vw, 3rem);
}
.inanc-toc__item {
  display: flex; align-items: baseline; gap: var(--space-3);
  padding: clamp(0.7rem, 1.4vw, 1rem) clamp(0.75rem, 1.4vw, 1.1rem);
  border-radius: var(--r-md); color: var(--ink);
  transition: background var(--dur-hover-soft) var(--ease-hover);
}
.inanc-toc__item:hover { background: var(--accent-soft); } /* faint maroon tint, never dark */
.inanc-toc__num { color: var(--maroon); font-variant-numeric: tabular-nums; font-weight: 640; font-variation-settings: "wght" 640; font-size: 0.95rem; min-width: 1.9em; }
.inanc-toc__title { font-size: clamp(1.05rem, 1.4vw, 1.25rem); font-weight: 560; font-variation-settings: "wght" 560; transition: color var(--dur-hover-soft) var(--ease-hover); }
.inanc-toc__item:hover .inanc-toc__title { color: var(--maroon); }
@media (max-width: 40rem) { .inanc-toc__list { grid-template-columns: 1fr; } }

/* --- 3. DOC AREA — [ sticky rail | reading ] desktop; single column < 1100px. --- */
.inanc-doc { padding-top: clamp(1.5rem, 3vw, 3rem); } /* tighter: İçindekiler sits right above */
.inanc-doc__grid { display: grid; grid-template-columns: 220px 1fr; gap: clamp(2.5rem, 5vw, 4.5rem); align-items: start; }

/* Sticky index rail + live scroll-spy (NOT faded — no reveal on the rail).
   ORDER MATTERS. This block MUST stay ABOVE the max-width:1100px query below.
   Both this rule and the one in the query are a single class, so they have
   equal specificity, and a media query adds NONE. Whichever comes last wins.
   This sat BELOW the query until Oct 2026, so `display: flex` beat
   `display: none` at every width and the rail was never hidden: on a 360px
   phone it pinned at top:110px and the nine articles scrolled underneath it,
   327px of collision from scroll 1400 to the end of the page. The sibling
   .inanc-doc__grid rule was always correct because its unconditional
   declaration sits above the query, which is the pattern this now follows. */
.inanc-rail { position: sticky; top: 110px; display: flex; flex-direction: column; gap: 0.1rem; }

@media (max-width: 1100px) {
  .inanc-doc__grid { grid-template-columns: 1fr; }
  .inanc-rail { display: none; } /* the top İçindekiler is the navigation on narrow screens */
}
.inanc-rail__item {
  position: relative; display: flex; align-items: baseline; gap: var(--space-2);
  padding: 0.5rem 0.4rem 0.5rem 0.9rem; border-radius: var(--r-sm);
  color: var(--muted); font-size: 0.9rem; font-weight: 500; font-variation-settings: "wght" 500; line-height: 1.3;
  transition: color var(--dur-hover) var(--ease-hover);
}
.inanc-rail__num { font-variant-numeric: tabular-nums; opacity: 0.7; font-size: 0.78rem; }
.inanc-rail__item::before { /* left-bar marker for the active article */
  content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 2px; height: 0; background: var(--maroon); border-radius: 2px;
  transition: height var(--dur-hover) var(--ease-hover);
}
.inanc-rail__item:hover { color: var(--ink); }
.inanc-rail__item.is-current { color: var(--maroon); font-weight: 640; font-variation-settings: "wght" 640; }
.inanc-rail__item.is-current::before { height: 1.1em; }

/* Reading column (~68ch). */
.inanc-reading { max-width: 68ch; }
.inanc-article { padding-block: clamp(2rem, 4vw, 3.25rem); scroll-margin-top: 110px; }
.inanc-article:first-child { padding-top: 0; }
.inanc-article + .inanc-article { border-top: 1px solid var(--line); } /* hairline between articles */
.inanc-article__head { display: flex; align-items: baseline; gap: var(--space-3); margin-bottom: var(--space-4); }
.inanc-article__num { color: var(--maroon); font-variant-numeric: tabular-nums; font-size: clamp(1rem, 1.4vw, 1.2rem); font-weight: 720; font-variation-settings: "wght" 720; }
.inanc-article__title { font-size: clamp(1.6rem, 1.1rem + 2vw, 2.4rem); line-height: 1.05; letter-spacing: -0.02em; font-weight: 800; font-variation-settings: "opsz" 40, "wght" 800, "ROND" var(--ROND-soft); }
.inanc-article__body { color: var(--ink); font-size: clamp(1.05rem, 1rem + 0.35vw, 1.2rem); line-height: 1.7; }
.inanc-article__body + .inanc-article__body { margin-top: var(--space-4); }

/* --- 4. SCRIPTURE CHIPS + VERSE POPOVER. --- */
.inanc-refs { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-5); }
.ref {
  display: inline-flex; align-items: center; min-height: 2rem; padding: 0.35rem 0.85rem;
  border: 0; border-radius: var(--r-pill);
  background: rgba(var(--maroon-rgb), 0.07); color: var(--maroon);
  font-family: var(--font-sans); font-size: 0.8rem; font-weight: 700; font-variation-settings: "wght" 700; line-height: 1;
  cursor: pointer; transition: background var(--dur-hover) var(--ease-hover);
}
.ref:hover { background: rgba(var(--maroon-rgb), 0.13); }

/* One reusable light popover card (JS positions it fixed, above or below the chip). */
.verse-pop {
  position: fixed; top: 0; left: 0; z-index: var(--z-overlay);
  max-width: min(30rem, calc(100vw - 2rem));
  background: var(--surface-1); border: 1px solid var(--line); border-radius: var(--r-md);
  box-shadow: var(--shadow-lg); padding: var(--space-4) var(--space-5);
  pointer-events: none; /* non-interactive text card */
}
.verse-pop[hidden] { display: none; }
.verse-pop__label { display: block; color: var(--maroon); text-transform: uppercase; font-size: 0.72rem; letter-spacing: 0.08em; font-weight: 600; font-variation-settings: "wght" 600; margin-bottom: var(--space-2); }
.verse-pop__text { display: block; color: var(--ink); font-size: 0.92rem; line-height: 1.6; }

/* --- 5. KAPANIŞ — maroon contact panel (reuses the About maroon-panel language). --- */
.inanc-contact { background: var(--hero-bg); }
.inanc-contact__panel {
  position: relative; overflow: hidden;
  background: var(--maroon); color: var(--paper); border-radius: var(--r-card);
  padding: clamp(2.5rem, 6vw, 5rem) clamp(1.5rem, 5vw, 4.5rem);
}
.inanc-contact__title { color: var(--paper); max-width: 18ch; margin-bottom: clamp(1.5rem, 3vw, 2.5rem); font-size: clamp(1.9rem, 1.3rem + 2.4vw, 3rem); line-height: 1.1; letter-spacing: -0.02em; font-weight: 760; font-variation-settings: "opsz" 72, "wght" 760, "ROND" var(--ROND-soft); }
.inanc-contact__row { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-end; gap: clamp(1.5rem, 4vw, 3rem); }
.inanc-contact__sub { color: rgba(var(--paper-rgb), 0.82); max-width: 42ch; line-height: 1.6; font-size: clamp(1rem, 1.3vw, 1.15rem); }
.inanc-contact__mailwrap { display: flex; align-items: center; gap: var(--space-4); }
.inanc-contact__mail { color: var(--paper); font-weight: 680; font-variation-settings: "wght" 680; font-size: clamp(1.05rem, 1.5vw, 1.3rem); letter-spacing: -0.01em; }
.inanc-contact__mail:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.inanc-contact__copy {
  display: inline-grid; place-items: center; flex: 0 0 auto; width: 2.75rem; height: 2.75rem;
  border-radius: var(--r-pill); background: rgba(var(--paper-rgb), 0.14); color: var(--paper); cursor: pointer;
  transition: background var(--dur-hover) var(--ease-hover);
}
.inanc-contact__copy:hover { background: rgba(var(--paper-rgb), 0.26); }
.inanc-contact__ico { display: block; }
.inanc-contact__ico--check { display: none; }
.inanc-contact__copy.is-copied .inanc-contact__ico--copy { display: none; }
.inanc-contact__copy.is-copied .inanc-contact__ico--check { display: block; }

/* Right-side action stack: the email row on top, the CTA link directly under it. */
.inanc-contact__actions { display: flex; flex-direction: column; align-items: flex-end; gap: var(--space-4); }

/* CTA is the shared homepage-hero arrow-link (text + right arrow — NO background,
   border or pill/padding), recoloured cream to read on the maroon panel. The
   inline-flex layout, the arrow's hover nudge (translateX 0.4em) and the label
   underline all come from the base .arrow-link; here we only flip the colour. */
.inanc-contact__cta { color: var(--paper); }
.inanc-contact__cta .arrow-link__label { background-image: linear-gradient(var(--paper), var(--paper)); }

@media (max-width: 640px) {
  .inanc-contact__row { flex-direction: column; align-items: flex-start; }
  .inanc-contact__actions { align-items: flex-start; }
}
@media (prefers-reduced-motion: reduce) {
  .inanc-rail__item::before { transition: none; }
  .ref, .inanc-toc__item, .inanc-toc__title, .inanc-contact__copy { transition: none; }
}


/* ==========================================================================
   DISCLOSURE ROWS  ([data-disclosure] — Yolumuz on hakkimizda.html)
   --------------------------------------------------------------------------
   Turns a .values__row from a bare name into "click the name, read the detail",
   WITHOUT changing a row that has no detail yet. A row with no
   [data-disclosure-toggle] keeps the existing .values__row--name-only styling
   exactly, so the section can be filled in one item at a time.

   Visual language is the Değerler row it already sits in: same hairline, same
   hover tint, same radius. The only new furniture is a +/- rule pair, drawn
   with currentColor so it recolours per palette. Tokens only, no hex.
   ========================================================================== */

.values__row--disclosure { padding: 0; }          /* the button owns the padding */

.values__heading { margin: 0; font: inherit; }    /* h3 for outline order, not for looks */

.values__toggle {
  /* reset the button back to the row */
  appearance: none; -webkit-appearance: none;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  width: 100%; margin: 0; text-align: start; cursor: pointer;
  background: none; border: 0; border-radius: var(--r-md);
  padding: clamp(1.2rem, 2.4vw, 2rem) clamp(0.85rem, 1.6vw, 1.3rem);
  color: inherit; font: inherit;
  transition: color var(--dur-hover-soft) var(--ease-hover);
}
.values__toggle:hover .values__name { color: var(--accent); }
.values__toggle:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

/* +/- drawn from two rules; the vertical one collapses when open. */
.values__toggle-icon {
  position: relative; flex: 0 0 auto;
  width: 0.85rem; height: 0.85rem;
  color: var(--accent);
}
.values__toggle-icon::before,
.values__toggle-icon::after {
  content: ""; position: absolute; inset-inline-start: 0; inset-block-start: 50%;
  width: 100%; height: 2px; border-radius: 2px; background: currentColor;
  transform: translateY(-50%);
  transition: transform var(--dur-hover) var(--ease-hover), opacity var(--dur-hover) var(--ease-hover);
}
.values__toggle-icon::after { transform: translateY(-50%) rotate(90deg); }
.is-open .values__toggle-icon::after { transform: translateY(-50%) rotate(0deg); opacity: 0; }

/* NO-JS SAFETY, copied from .iletisim-faq__panel: the collapsed state is gated
   on `.js`, so without JavaScript every panel renders OPEN and the detail is
   still readable. Same reason that page's SSS works with JS off.

   CLOSED PANELS ARE ALSO HIDDEN FROM THE A11Y TREE AND TAB ORDER, not merely at
   height 0: visibility:hidden takes anything focusable inside out of the tab
   order. The 0s delay holds it hidden until the collapse finishes. */
.values__panel { overflow: hidden; transition: height var(--dur-base) var(--ease-hover); }
.js .values__panel {
  height: 0; visibility: hidden;
  transition: height var(--dur-base) var(--ease-hover),
              visibility 0s linear var(--dur-base);
}
.js .values__row.is-open .values__panel {
  visibility: visible;
  transition: height var(--dur-base) var(--ease-hover),
              visibility 0s linear 0s;
}
.values__desc {
  margin: 0;
  padding: 0 clamp(0.85rem, 1.6vw, 1.3rem) clamp(1.2rem, 2.4vw, 2rem);
  max-width: 62ch; color: var(--muted); line-height: 1.6;
}

/* Scripture inside a disclosure panel (6 Temel Değerimiz). Same visual language
   as .yazi__quote in the article pages: flat accent rule, tinted surface, the
   reference on its own line, no italic and no quotation-mark glyph. Inset with
   the same horizontal clamp as .values__desc, because .values__panel itself
   carries no padding. Additive: .values__desc is untouched. */
.values__quote {
  margin: 0 clamp(0.85rem, 1.6vw, 1.3rem) clamp(0.9rem, 1.8vw, 1.25rem);
  padding: clamp(0.8rem, 1.5vw, 1.1rem) clamp(0.9rem, 1.7vw, 1.2rem);
  border-left: 3px solid var(--accent);
  background: var(--tint-2);
  border-radius: var(--r-sm);
}
.values__quote p {
  margin: 0; max-width: 62ch;
  font-size: 1rem; line-height: 1.65; color: var(--ink);
}
.values__quote cite {
  display: block; margin-top: var(--space-2);
  font-style: normal;                    /* the site has no italic anywhere */
  font-size: 0.8125rem; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--accent-deep); font-weight: var(--wght-semibold);
}

@media (prefers-reduced-motion: reduce) {
  .values__panel, .values__row.is-open .values__panel,
  .values__toggle, .values__toggle-icon::before, .values__toggle-icon::after { transition: none; }
}


/* İletişim hero photograph, as a BAND BENEATH the copy rather than behind it.
   Behind it was measured and failed: over the sky the display title cleared
   7.11 at its darkest point against a 3.0 bar, but the lead measured 1.62
   against a 4.5 bar where the dark hill ridge rises into its box. The only crop
   that clears the ridge pushes the skyline to 99.2% of the frame, which throws
   away the photograph to save the text. A scrim would fix it and is exactly
   what the house rule forbids (flat colours, no overlays). So the type stays on
   paper and the photograph keeps its composition: skyline at 70%, sea below.
   Full bleed to match the .visitmap band further down the same page. */
.hero--photo { position: relative; }
.hero__band { display: block; width: 100%; margin-top: clamp(2rem, 4.5vw, 3.5rem); }
.hero__band-img {
  display: block; width: 100%;
  height: clamp(150px, 23vw, 330px);
  object-fit: cover;
  object-position: 50% 50%;
}

/* Kaynaklar index credit line. Sits under the intro, above the list. Smaller
   and quieter than .kaynak-intro: it is a statement of origin, not a pitch. */
.kaynak-notice {
  margin-top: var(--space-3);
  max-width: 62ch;
  color: var(--muted);
  font-size: 0.9375rem;
  line-height: 1.6;
}

/* The source's OWN attribution line, where an article carries one. Italic
   because the source sets it italic, which is a deliberate exception to the
   project's no-italics rule: this is a quotation of their byline, not our type.
   Separate from .yazi__source, which is the credit WE add. Both stay. */
.yazi__byline { margin-top: var(--space-5); color: var(--muted); font-size: 0.9375rem; }

/* Boxed panels inside an article (.yazi__panel). The Nilüfer source puts three
   multi-line panels inside single-cell <table>s. They are not data tables, so
   they are rebuilt as an <aside> box: same visual separation, correct semantics,
   and they reflow on a phone where a table would not. */
.yazi__panel {
  margin: clamp(1.4rem, 3vw, 2.2rem) 0;
  padding: clamp(1.1rem, 2.4vw, 1.6rem) clamp(1rem, 2.2vw, 1.5rem);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-1);
  max-width: 62ch;
}
.yazi__panel p { margin: 0 0 0.5rem; color: var(--muted); line-height: 1.55; }
.yazi__panel p:last-child { margin-bottom: 0; }
.yazi__panel-t { color: var(--ink); font-weight: var(--wght-semibold); }

/* ==========================================================================
   ARTICLE EMPTY STATE + SOURCE CREDIT  (.yazi__empty, .yazi__source)
   --------------------------------------------------------------------------
   The eight Kaynaklar articles ship as SHELLS: real title, real credit, no body.
   .yazi__empty is what stands in for the body until the text is cleared for
   hosting, and it is not an apology: it hands the reader a working link to the
   full text on the church that wrote it, so nothing on the page dead-ends.

   .yazi__source is permanent. It stays after the body arrives, because the
   credit is owed whether or not the text lives here.
   ========================================================================== */

.yazi__empty {
  margin: 0;
  padding: clamp(1.1rem, 2.4vw, 1.6rem) clamp(1rem, 2.2vw, 1.5rem);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-1);
  color: var(--muted);
  line-height: 1.6;
  max-width: 62ch;
}
.yazi__empty-link { color: var(--accent); text-underline-offset: 0.2em; }

.yazi__source {
  margin-top: clamp(2rem, 4vw, 3rem);
  padding-top: clamp(1rem, 2vw, 1.4rem);
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.9375rem;
  line-height: 1.6;
  max-width: 62ch;
}
.yazi__source strong { color: var(--ink); font-weight: var(--wght-semibold); }
.yazi__source-link {
  color: var(--accent);
  text-underline-offset: 0.2em;
  white-space: nowrap;
}


/* ==========================================================================
   KAYNAKLAR PAGE  (kaynaklar.html) — outbound resource links
   --------------------------------------------------------------------------
   STATUS: mostly inert. The page ships eight outbound links built from
   .values__row + .kaynak-row (see the KAYNAK ROW block), not video entries.
   Of the .videolar-* rules below only .videolar-accent is still used, on the
   hero kicker. The rest are kept as a template asset for a church that ships
   video; see the dead-code table in CLAUDE.md. Original rationale follows.

   Was the structural sibling of the MAKALELER block, which was deleted with its
   page in Sep 2026. Reuses the same shared pieces:
   the shared .hero + .t-lead .hero__sub .clarify treatment, the .t-eyebrow
   accent kicker, the .arrow-link, the About "Değerler" .values__row hover, and
   the shared visit closer. The one shape difference is deliberate: a video entry
   needs a poster, so each row leads with a thumbnail + play affordance +
   duration, where a Makaleler row is text-only. Every entry is a <button> (a
   click-to-play facade), so the button's own chrome is reset back to the row
   treatment. Flat colours + tokens ONLY. NO italic.
   ========================================================================== */

/* Hero subtitle accent word. (Mirrored the deleted .makaleler-accent; this is
   now the only copy of that treatment.) */
.videolar-accent {
  color: var(--accent);
  font-weight: var(--wght-semibold); font-variation-settings: "opsz" 22, "wght" var(--wght-semibold),
                           "ROND" var(--ROND-soft), "GRAD" var(--GRAD-base);
}

/* Shared facade furniture: the play disc and the duration chip sit on the
   thumbnail. Both are token-only; the chip uses the --ink-rgb channel. */
.videolar-play {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  display: grid; place-items: center;
  width: 3.25rem; height: 3.25rem;
  border-radius: var(--r-pill);
  background: var(--surface-1);
  color: var(--accent);
  box-shadow: var(--shadow-md);
  transition: transform var(--dur-hover-soft) var(--ease-hover);
}
.videolar-dur {
  position: absolute; right: var(--space-2); bottom: var(--space-2);
  padding: 0.15rem 0.45rem;
  border-radius: var(--r-sm);
  background: rgba(var(--ink-rgb), 0.72);
  color: var(--paper);
  font-size: 0.7rem; line-height: 1.4;
  font-variant-numeric: tabular-nums; letter-spacing: 0.02em;
  font-weight: 600; font-variation-settings: "wght" 600;
}
/* The injected embed replaces the thumbnail inside the same box. */
.videolar-frame { display: block; width: 100%; height: 100%; border: 0; }

/* --- ÖNE ÇIKAN — featured facade (2-col desktop, stacked mobile) --- */
.videolar-kicker { margin-bottom: clamp(1.25rem, 2.5vw, 2rem); }
.videolar-featured__card {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(1.5rem, 4vw, 3.5rem); align-items: center;
  width: 100%; padding: 0; text-align: left;
  background: transparent; border: 0; font: inherit; color: inherit; cursor: pointer;
}
.videolar-featured__media { position: relative; overflow: hidden; aspect-ratio: 4 / 3; }
.videolar-featured__img { display: block; width: 100%; height: 100%; object-fit: cover; }
.videolar-featured__tint {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(155deg,
    rgba(var(--paper-rgb), 0.10),
    rgba(var(--maroon-rgb), 0.16) 58%,
    color-mix(in srgb, var(--maroon-deep) 24%, transparent));
}
.videolar-featured__body { display: flex; flex-direction: column; align-items: flex-start; }
.videolar-featured__date { color: var(--muted); font-size: 0.82rem; font-variant-numeric: tabular-nums; letter-spacing: 0.01em; font-weight: var(--wght-semibold); font-variation-settings: "wght" var(--wght-semibold); }
.videolar-featured__title {
  display: block; margin-top: var(--space-3);
  font-size: clamp(1.8rem, 4vw, 2.9rem); line-height: 1.05; letter-spacing: -0.025em;
  color: var(--ink); font-weight: 800;
  font-variation-settings: "opsz" 60, "wght" 800, "ROND" var(--ROND-soft);
  transition: color var(--dur-hover-soft) var(--ease-hover);
}
.videolar-featured__excerpt { display: block; margin-top: var(--space-4); color: var(--muted); font-size: clamp(1.05rem, 1.4vw, 1.2rem); line-height: 1.5; max-width: 44ch; }
.videolar-featured__more { margin-top: clamp(1.25rem, 2.5vw, 1.75rem); color: var(--accent); }
.videolar-featured__card:hover .videolar-featured__title { color: var(--accent); }
.videolar-featured__card:hover .arrow-link__icon { transform: translateX(0.4em); }
.videolar-featured__card:hover .arrow-link__label { background-size: 100% 1.5px; }
.videolar-featured__card:hover .videolar-play { transform: translate(-50%, -50%) scale(1.06); }
@media (max-width: 820px) { .videolar-featured__card { grid-template-columns: 1fr; } }

/* --- SON VİDEOLAR — header row + six rows reusing .values__row --- */
.videolar-list__head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-4); margin-bottom: clamp(0.5rem, 1.5vw, 1rem); }
.videolar-list__title { color: var(--ink); }
.videolar-list__count { color: var(--muted); font-variant-numeric: tabular-nums; font-size: clamp(1.1rem, 2vw, 1.5rem); font-weight: var(--wght-medium); font-variation-settings: "wght" var(--wght-medium); }
.videolar-list { display: block; }
/* Each row is a <button>: reset its chrome, then take the .values__row
   treatment. border-top only, so hairlines sit BETWEEN consecutive rows. */
.videolar-row {
  display: grid;
  grid-template-columns: clamp(6.5rem, 17vw, 11rem) 1fr;
  gap: clamp(0.9rem, 2.2vw, 1.75rem);
  align-items: center;
  width: 100%; text-align: left;
  background: transparent;
  border: 0;
  border-top: 1px solid var(--line);
  font: inherit; color: inherit; cursor: pointer;
}
.videolar-list .videolar-row:first-child { border-top: 0; }
.videolar-row__media { position: relative; overflow: hidden; aspect-ratio: 16 / 10; border-radius: var(--r-sm); }
.videolar-row__img { display: block; width: 100%; height: 100%; object-fit: cover; }
.videolar-row__tint { position: absolute; inset: 0; pointer-events: none; background: rgba(var(--maroon-rgb), 0.08); }
.videolar-row .videolar-play { width: 2.25rem; height: 2.25rem; box-shadow: var(--shadow-sm); }
.videolar-row .videolar-play svg { width: 15px; height: 15px; }
.videolar-row__body { display: block; min-width: 0; }
.videolar-row__date { display: block; color: var(--muted); font-size: 0.82rem; font-variant-numeric: tabular-nums; letter-spacing: 0.01em; font-weight: var(--wght-semibold); font-variation-settings: "wght" var(--wght-semibold); }
.videolar-row__title {
  display: block; margin-top: 0.4rem;
  font-size: clamp(1.3rem, 2.6vw, 1.75rem); line-height: 1.12; letter-spacing: -0.02em;
  color: var(--ink); font-weight: 700;
  font-variation-settings: "opsz" 40, "wght" 700, "ROND" var(--ROND-soft);
  transition: color var(--dur-hover-soft) var(--ease-hover);
}
.videolar-row__desc { display: block; margin-top: 0.4rem; color: var(--muted); font-size: 1rem; line-height: 1.5; max-width: 60ch; }
.videolar-row:hover .videolar-row__title { color: var(--accent); }
.videolar-row:hover .videolar-play { transform: translate(-50%, -50%) scale(1.08); }

@media (prefers-reduced-motion: reduce) {
  .videolar-featured__title, .videolar-row__title, .videolar-play { transition: none; }
  .videolar-featured__card:hover .arrow-link__icon { transform: none; }
  .videolar-featured__card:hover .videolar-play,
  .videolar-row:hover .videolar-play { transform: translate(-50%, -50%); }
}


/* ==========================================================================
   SHARED NAV + FOOTER additions — the site-wide page nav (Anasayfa · Hakkımızda ·
   Neye İnanıyoruz? · Makaleler · İletişim + the "Etkinlikler ve Duyurular" CTA) and the footer link
   row. The nav active state ([aria-current="page"]) is defined above. Tokens only.
   ========================================================================== */

/* "Dua iste" CTA pill in the nav-pills row — reuses .btn--filled (maroon fill);
   match the text-pill height so the row stays aligned. */
.nav-pills__cta { min-height: 2.5rem; padding: var(--space-2) var(--space-4); }

/* Footer page-nav — a horizontal link row above the copyright base. */
.site-footer__nav {
  display: flex; flex-wrap: wrap; gap: 0.5rem clamp(1.25rem, 3vw, 2.25rem);
  padding-top: clamp(1.25rem, 2.5vw, 2rem); border-top: 1px solid var(--line);
}
.site-footer__navlink { color: var(--muted); font-size: 0.9375rem; transition: color var(--dur-hover) var(--ease-hover); }
.site-footer__navlink:hover { color: var(--accent); }
.site-footer__navlink[aria-current="page"] { color: var(--accent); font-weight: var(--wght-semibold); font-variation-settings: "wght" var(--wght-semibold); }
@media (prefers-reduced-motion: reduce) { .site-footer__navlink { transition: none; } }

/* ==========================================================================
   İLETİŞİM PAGE  (iletisim.html) — contact form + SSS accordion
   --------------------------------------------------------------------------
   Reuses: .hero + .t-lead .hero__sub .clarify, .t-eyebrow maroon kicker, the
   primary .btn pill, the .arrow-link icon nudge, the Değerler hover feel
   (accent-soft + maroon), [data-reveal-up], and the shared visit closer.
   Flat colours + tokens ONLY (focus ring uses the --maroon-rgb channel). NO italic.
   ========================================================================== */

/* Hero subtitle accent word — maroon + semibold within the normal-weight muted line. */
.iletisim-hero__accent {
  color: var(--accent); font-weight: var(--wght-semibold);
  font-variation-settings: "opsz" 22, "wght" var(--wght-semibold), "ROND" var(--ROND-soft), "GRAD" var(--GRAD-base);
}

/* --- 2. Contact: intro (left) · form card (right) --- */
.iletisim-contact__grid { display: grid; grid-template-columns: 0.85fr 1.15fr; gap: clamp(2rem, 5vw, 4.5rem); align-items: start; }
@media (max-width: 60rem) { .iletisim-contact__grid { grid-template-columns: 1fr; } }
.iletisim-contact__lead { color: var(--muted); max-width: 42ch; }
.iletisim-contact__block { margin-top: clamp(1.75rem, 3.5vw, 2.75rem); }
.iletisim-contact__block > .t-eyebrow { margin-bottom: 0.6rem; }
.iletisim-contact__mail { font-size: clamp(1.1rem, 1.5vw, 1.35rem); color: var(--ink); letter-spacing: -0.01em; font-weight: var(--wght-medium); font-variation-settings: "wght" var(--wght-medium); transition: color var(--dur-hover) var(--ease-hover); }
.iletisim-contact__mail:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 0.2em; }

/* WhatsApp — outline button under the e-posta address. Deliberately NOT filled:
   the form's "Gönder" submit is the only filled button in this section, so the
   secondary treatment stops this reading as a second submit. Sizing, min-height
   (>=44px) and focus ring all come from .btn / .btn--outline. */
/* The e-posta address is an inline <a> and .btn is inline-flex, so the WhatsApp
   button flowed onto the same line and read as cramped beside it. `display: flex`
   makes it block-level so it starts its own line; `width: fit-content` keeps the
   pill hugging its label instead of stretching the column. */
.iletisim-contact__wa { margin-top: var(--space-4); display: flex; width: fit-content; }
.iletisim-contact__wa-icon { flex: 0 0 auto; }

/* Social icon buttons — reuse the site's exact FB/IG/YT SVG logos (from #connect). */
.iletisim-social { display: flex; gap: var(--space-3); }
.iletisim-social__btn {
  display: inline-grid; place-items: center; width: 2.9rem; height: 2.9rem;
  background: var(--surface-1); border: 1px solid var(--line); color: var(--accent);
  transition: background var(--dur-hover) var(--ease-hover), color var(--dur-hover) var(--ease-hover),
              border-color var(--dur-hover) var(--ease-hover), transform var(--dur-hover) var(--ease-hover),
              box-shadow var(--dur-hover) var(--ease-hover);
}
.iletisim-social__btn:hover { background: var(--accent); color: var(--paper); border-color: transparent; transform: translateY(-2px); box-shadow: var(--shadow-md); }

/* Form card + inputs. */
.iletisim-form { display: flex; flex-direction: column; gap: var(--space-4); background: var(--surface-1); border: 1px solid var(--line); border-radius: var(--r-card); padding: clamp(1.5rem, 3vw, 2.5rem); }
.iletisim-form__field { display: flex; flex-direction: column; gap: 0.4rem; }
.iletisim-form__label { font-size: 0.8rem; color: var(--muted); letter-spacing: 0.01em; font-variation-settings: "wght" var(--wght-semibold); font-weight: var(--wght-semibold); }
.iletisim-form__input {
  font: inherit; color: var(--ink); background: var(--paper);
  border: 1px solid var(--line); border-radius: 14px; padding: 0.7rem 0.85rem;
  transition: border-color var(--dur-hover) var(--ease-hover), box-shadow var(--dur-hover) var(--ease-hover);
}
.iletisim-form__input::placeholder { color: var(--muted); }
.iletisim-form__input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(var(--maroon-rgb), 0.12); }
.iletisim-form__textarea { resize: vertical; min-height: 7rem; line-height: 1.5; }
.iletisim-form__submit { align-self: flex-start; }
.iletisim-form__submit:hover .iletisim-form__arrow { transform: translateX(0.4em); }

/* --- 3. SSS accordion — rows reuse the Değerler hover (accent-soft + maroon question) --- */
.iletisim-faq__kicker { margin-bottom: clamp(1.25rem, 2.5vw, 2rem); }
/* Full content width (no max-width): rows stretch edge to edge, +/- icon at far right. */
.iletisim-faq__list { width: 100%; }
.iletisim-faq__item { border-bottom: 1px solid var(--line); border-radius: var(--r-md); transition: background var(--dur-hover-soft) var(--ease-hover); }
.iletisim-faq__item:hover { background: var(--accent-soft); }
.iletisim-faq__q { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); width: 100%; text-align: left; cursor: pointer; color: var(--ink); padding: clamp(1.1rem, 2vw, 1.5rem) clamp(0.85rem, 1.6vw, 1.2rem); }
.iletisim-faq__q-text { font-size: clamp(1.05rem, 1.4vw, 1.2rem); line-height: 1.3; font-weight: var(--wght-semibold); font-variation-settings: "wght" var(--wght-semibold); transition: color var(--dur-hover-soft) var(--ease-hover); }
.iletisim-faq__item:hover .iletisim-faq__q-text,
.iletisim-faq__item.is-open .iletisim-faq__q-text { color: var(--accent); }

/* +/− morph icon (two maroon bars; the vertical collapses to a minus when open). */
.iletisim-faq__icon { position: relative; flex: 0 0 auto; width: 1.1rem; height: 1.1rem; }
.iletisim-faq__icon::before, .iletisim-faq__icon::after { content: ""; position: absolute; left: 50%; top: 50%; background: var(--accent); border-radius: 2px; transition: transform var(--dur-base) var(--ease-hover); }
.iletisim-faq__icon::before { width: 1.1rem; height: 2px; transform: translate(-50%, -50%); }
.iletisim-faq__icon::after { width: 2px; height: 1.1rem; transform: translate(-50%, -50%); }
.iletisim-faq__item.is-open .iletisim-faq__icon::after { transform: translate(-50%, -50%) scaleY(0); }

/* Panel height tween. Collapsed only under .js so no-JS shows every answer. */
.iletisim-faq__panel { overflow: hidden; transition: height var(--dur-base) var(--ease-hover); }
.js .iletisim-faq__panel { height: 0; }
.iletisim-faq__a { color: var(--muted); line-height: 1.6; max-width: 68ch; padding: 0 clamp(0.85rem, 1.6vw, 1.2rem) clamp(1.1rem, 2vw, 1.5rem); }

@media (prefers-reduced-motion: reduce) {
  .iletisim-social__btn, .iletisim-contact__mail, .iletisim-form__input, .iletisim-form__arrow,
  .iletisim-faq__item, .iletisim-faq__q-text, .iletisim-faq__panel,
  .iletisim-faq__icon::before, .iletisim-faq__icon::after { transition: none; }
  .iletisim-social__btn:hover { transform: none; }
}


/* ==========================================================================
   ETKINLIKLER PAGE  (etkinlikler.html) — prayer-request form (intimate, centered)
   --------------------------------------------------------------------------
   STATUS: fully inert. Etkinlikler ve Duyurular ships as a deliberate empty
   state with no form (Icerik.docx item 17), so none of the .dua-* rules below
   match anything on the page. Kept, with js/dua.js, for a church that wants
   the form back; see the dead-code table in CLAUDE.md. Original rationale
   follows.

   Reuses the .iletisim-form* card + input styling and the shared hero / reveal
   systems. Adds only the centered column, optional-label suffix, checkbox row,
   and the soft maroon assurance box. Flat colours + tokens only (assurance tint
   uses the --maroon-rgb channel). NO italic, NO em-dashes.
   ========================================================================== */
.dua-hero__accent {
  color: var(--accent); font-weight: var(--wght-semibold);
  font-variation-settings: "opsz" 22, "wght" var(--wght-semibold), "ROND" var(--ROND-soft), "GRAD" var(--GRAD-base);
}
/* Intimate centered column, narrower than the other pages. */
.dua-prayer__col { max-width: 660px; margin-inline: auto; }
.dua-prayer__lead { color: var(--muted); margin-bottom: clamp(1.75rem, 3.5vw, 2.5rem); }
.dua-prayer__strong { color: var(--ink); font-weight: var(--wght-semibold); font-variation-settings: "wght" var(--wght-semibold); }

/* Optional-field label suffix (lighter than the bold field label). */
.dua-form__opt { color: var(--muted); font-weight: var(--wght-regular); font-variation-settings: "wght" var(--wght-regular); }

/* Native checkbox row (accent-color tints the native control maroon). */
.dua-form__check { display: flex; align-items: flex-start; gap: var(--space-3); cursor: pointer; color: var(--muted); font-size: 0.95rem; line-height: 1.5; }
.dua-form__check input[type="checkbox"] { flex: 0 0 auto; width: 1.1rem; height: 1.1rem; margin-top: 0.15rem; accent-color: var(--maroon); cursor: pointer; }

/* Assurance box: soft maroon tint + maroon shield icon. */
.dua-assure { display: flex; align-items: flex-start; gap: var(--space-3); margin-top: clamp(1.5rem, 3vw, 2rem); padding: clamp(1rem, 2vw, 1.25rem) clamp(1rem, 2vw, 1.35rem); background: rgba(var(--maroon-rgb), 0.06); border-radius: 14px; }
.dua-assure__icon { flex: 0 0 auto; color: var(--accent); margin-top: 0.1rem; }
.dua-assure__text { color: var(--muted); font-size: 0.9rem; line-height: 1.55; }


/* ==========================================================================
   İNCİL OKU PAGE  (incil-oku.html) — YouVersion reader inside OUR design system
   --------------------------------------------------------------------------
   UI stays on the site's single UI font (Google Sans Flex). The reader PASSAGE
   text uses a self-hosted serif (Source Serif 4, upright only) scoped ONLY to
   .incil__passage. Flat colours + tokens only (focus ring + verse numbers via
   the --maroon-rgb channel / var(--accent)). NO italic.
   ========================================================================== */

/* Self-hosted serif for the reading text (latin + latin-ext for Turkish). */
@font-face { font-family: "Source Serif 4"; src: url("../assets/fonts/source-serif-4-latin-400.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family: "Source Serif 4"; src: url("../assets/fonts/source-serif-4-latin-ext-400.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }

/* Hero accent phrase (maroon + semibold within the muted subtitle). */
.incil-hero__accent { color: var(--accent); font-weight: var(--wght-semibold); font-variation-settings: "opsz" 22, "wght" var(--wght-semibold), "ROND" var(--ROND-soft), "GRAD" var(--GRAD-base); }

/* Reader column, narrower/centered. */
.incil__col { max-width: 820px; margin-inline: auto; }

/* Toolbar: our styled squircle selects + the "YouVersion'da aç" link. */
.incil__toolbar { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--space-4); margin-bottom: clamp(1.5rem, 3vw, 2.5rem); }
.incil__selects { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.incil__field { position: relative; display: flex; flex-direction: column; gap: 0.35rem; }
.incil__field-label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.12em; color: var(--muted); font-weight: var(--wght-semibold); font-variation-settings: "wght" var(--wght-semibold); }
.incil__select { appearance: none; -webkit-appearance: none; font: inherit; font-size: 0.9375rem; color: var(--ink); background: var(--surface-1); border: 1px solid var(--line); border-radius: 14px; padding: 0.6rem 2.2rem 0.6rem 0.85rem; min-height: 2.75rem; cursor: pointer; transition: border-color var(--dur-hover) var(--ease-hover), box-shadow var(--dur-hover) var(--ease-hover); }
.incil__field--chapter .incil__select { min-width: 5rem; }
.incil__select:hover { border-color: rgba(var(--ink-rgb), 0.28); }
.incil__select:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(var(--maroon-rgb), 0.12); }
.incil__select:disabled { opacity: 0.7; cursor: default; }
/* Custom chevron (token-coloured triangle over the select). */
.incil__field::after { content: ""; position: absolute; right: 0.95rem; bottom: 1.2rem; width: 0; height: 0; pointer-events: none; border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 5px solid var(--accent); }
/* The YouVersion hand-off. It was an inline .arrow-link in --accent; Oct 2026
   it became a .btn--filled, so the colour override had to go or it would have
   painted maroon text on the maroon fill (.incil__yv sits ~2700 lines after
   .btn--filled, so at equal specificity it wins on order). .btn already sets
   white-space: nowrap. Only the no-shrink hook is left. */
.incil__yv { flex: none; }

/* Chapter title (UI font) + passage (self-hosted serif). */
.incil__chapter-title { font-size: clamp(1.5rem, 1.1rem + 1.8vw, 2.1rem); line-height: 1.1; letter-spacing: -0.02em; font-weight: 800; font-variation-settings: "opsz" 40, "wght" 800, "ROND" var(--ROND-soft); margin-bottom: clamp(1rem, 2vw, 1.5rem); }
.incil__passage { font-family: "Source Serif 4", Georgia, "Times New Roman", serif; color: var(--ink); font-size: clamp(1.08rem, 1rem + 0.5vw, 1.28rem); line-height: 1.9; transition: opacity var(--dur-base) var(--ease-text); }
.incil__passage.is-loading { opacity: 0; }
.incil__para { margin: 0 0 1.15em; text-wrap: pretty; }
.incil__para:last-child { margin-bottom: 0; }
/* Poetry. The API marks poetic lines div.q1 / div.q2, and across the canon they
   outnumber prose paragraphs about 4:1, so this is the common case rather than
   an edge case. Hanging indent so a wrapped line reads as a continuation. */
.incil__line { margin: 0 0 0.15em; padding-left: 1.3em; text-indent: -1.3em; text-wrap: pretty; }
.incil__line--in { padding-left: 2.7em; }
.incil__line:last-child { margin-bottom: 0; }
/* Restore the paragraph gap where poetry meets prose. */
.incil__line + .incil__para, .incil__para + .incil__line { margin-top: 1.15em; }
/* Descriptive title ("David'in mezmuru"). Muted, not italic: no italics here. */
.incil__d { margin: 0 0 0.75em; color: var(--muted); font-size: 0.9em; }
/* Verse numbers: small maroon superscripts in the UI font. */
.incil__verse { font-family: var(--font-sans); font-size: 0.62em; font-weight: 600; font-variation-settings: "wght" 600; color: var(--accent); vertical-align: super; line-height: 0; margin-right: 0.3em; }
.incil__note { font-family: var(--font-sans); color: var(--muted); font-size: 1.05rem; line-height: 1.6; }

/* Chapter nav (reuse .arrow-link; reset the <button> chrome). */
.incil__nav { display: flex; justify-content: space-between; gap: var(--space-4); margin-top: clamp(1.5rem, 3vw, 2.5rem); }
.incil__navbtn { background: none; border: 0; padding: 0; color: var(--accent); cursor: pointer; }
.incil__navbtn:disabled { opacity: 0.35; cursor: default; pointer-events: none; }


/* ==========================================================================
   TAP TARGETS on a touch device — five links measured under the 44px minimum
   at 390px: .yazi__source-link 91x18, the article's WhatsApp CTA 145x20,
   .services__contact 96x21, .iletisim-contact__mail 195x21 and the two
   .incil__navbtn at 74x25 and 80x25.

   Each gets a 44px hit area from an absolutely positioned ::after rather than
   from padding. Padding would have been simpler but it grows the line box or
   the grid row and moves everything below it; an overlay costs NOTHING in
   layout, which is what let this be verified as a zero-shift change.

   Gated on `any-pointer: coarse` (a coarse pointer is AVAILABLE, the same
   capability reasoning as section 14 in base.css), so a mouse-only desktop is
   untouched by construction and a hybrid device still gets the bigger target.

   `.yazi__source-link` was the most important of these while Nilüfer's
   permission required the link. That credit was removed in Oct 2026 (the
   author granted publication without attribution, DEVIR 4.0.-1f), so this
   selector is now INERT. Kept, not deleted, per the dead-code convention.
   the original to be reachable, and 18px on a phone is not reachable.
   ========================================================================== */
@media (any-pointer: coarse) {
  .yazi__source-link,
  .yazi__wa,
  .services__contact,
  .iletisim-contact__mail,
  .incil__navbtn { position: relative; }

  .yazi__source-link::after,
  .yazi__wa::after,
  .services__contact::after,
  .iletisim-contact__mail::after,
  .incil__navbtn::after {
    content: "";
    position: absolute;
    left: 0; right: 0; top: 50%;
    transform: translateY(-50%);
    height: 44px;
    /* invisible, and never on top of its own text */
    z-index: 0;
  }
}
.incil__navbtn--prev:hover:not(:disabled) .arrow-link__icon { transform: translateX(-0.4em); }
.incil__navbtn--next:hover:not(:disabled) .arrow-link__icon { transform: translateX(0.4em); }

/* Version attribution / copyright. */
.incil__attribution { margin-top: clamp(1.5rem, 3vw, 2rem); color: var(--muted); font-size: 0.82rem; line-height: 1.5; }

@media (prefers-reduced-motion: reduce) {
  .incil__passage, .incil__select { transition: none; }
  .incil__navbtn--prev:hover:not(:disabled) .arrow-link__icon,
  .incil__navbtn--next:hover:not(:disabled) .arrow-link__icon { transform: none; }
}


/* ==========================================================================
   17. VAKIF + WHATSAPP  (added 20 Aug 2026, PKV revision list)
       Three additions, all built from existing tokens and the hairline device
       the footer and the Inanc articles already use, so a re-skin still only
       touches tokens.css. The one exception is WhatsApp green, which is a
       fixed third-party hue and lives with the other brand colours in §1.
   ========================================================================== */

/* ---- WhatsApp button (Iletisim contact column) ---------------------------
   Geometry comes from .btn; this only recolours it. Sits under the e-mail
   block because a phone number is how these churches are actually reached. */
.wa-btn { background: var(--wa); color: #fff; border-color: transparent; }
.wa-btn:hover { background: var(--wa-deep); color: #fff; }
.wa-btn__icon { flex: none; }
.wa-btn__note { margin-top: 0.6rem; font-size: 0.875rem; color: var(--muted); }

/* ---- Vakif membership row (shared footer) --------------------------------
   Required on every member church's site. Sits directly above .site-footer__nav
   so it reads under the church's own details and borrows the nav's hairline
   rather than introducing a third rule into the footer stack. */
.site-footer__vakif { margin-top: clamp(1.25rem, 2.5vw, 2rem); }
.vakif-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-4);
  color: inherit;
  text-decoration: none;
}
.vakif-badge__mark { flex: none; width: 56px; height: 56px; object-fit: contain; }
.vakif-badge__text { display: flex; flex-direction: column; gap: 0.2rem; }
.vakif-badge__name {
  color: var(--ink);
  font-size: 0.9375rem;
  font-weight: var(--wght-medium);
  font-variation-settings: "wght" var(--wght-medium);
  transition: color var(--dur-hover) var(--ease-hover);
}
.vakif-badge__note { color: var(--muted); font-size: 0.875rem; max-width: 46ch; line-height: 1.5; }
.vakif-badge:hover .vakif-badge__name { color: var(--accent); }

/* ---- Inanc bildirgesi: source note + church commentary -------------------
   The eight articles are the Vakif's wording and are identical on every member
   site, so the page says so before the contents list. The commentary block is
   the single editable slot, and it takes the same hairline + padding rhythm as
   .inanc-article so it reads as the last entry rather than a pasted-on callout. */
/* Closing colophon, centred under the document. It used to sit above the
   contents list, left aligned, where it read as a warning label on the page.
   At the end, centred, it reads as what it is: the source of the text you have
   just finished. It takes the hairline ABOVE it now, so the rhythm down the
   reading column stays unbroken. */
.vakif-source {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-3);
  max-width: 52ch;
  margin-inline: auto;
  padding-block: clamp(2rem, 4vw, 3.25rem);
  border-top: 1px solid var(--line);
}
.vakif-source__mark { flex: none; width: 52px; height: 52px; object-fit: contain; }
.vakif-source__text { color: var(--muted); font-size: 0.9375rem; line-height: 1.6; text-wrap: pretty; }

.inanc-note {
  display: block;
  padding-block: clamp(2rem, 4vw, 3.25rem);
  border-top: 1px solid var(--line);
}
.inanc-note__body { margin-top: var(--space-3); color: var(--ink); }

@media (max-width: 40rem) {
  .vakif-badge { align-items: flex-start; gap: var(--space-3); }
  .vakif-badge__mark { width: 44px; height: 44px; }
  .vakif-source__mark { width: 44px; height: 44px; }
}

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


/* ==========================================================================
   18. STUDIO DROPDOWNS + AUTO-HIDE BAR  (added 21 Aug 2026)
   ========================================================================== */

/* ---- Downward-opening studio dropdowns -----------------------------------
   A native <select> on macOS opens its popup wherever the current option
   happens to sit, so with fifteen palettes it opened UPWARD over the page and
   a first-time visitor could not tell there was a list at all.
   js/studio-select.js builds a button and a listbox over each select; this
   opens it downward, always. The native control stays as the model, visually
   hidden, so studio.js is unchanged apart from one call. */
.studio-combo { position: relative; display: inline-flex; }

.studio-combo__btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  font: inherit;
  font-size: 0.85rem;
  line-height: 1;
  color: var(--ink);
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 0.5rem 0.7rem;
  min-height: 2.5rem;                 /* >=44px tap target */
  cursor: pointer;
  text-align: left;
  transition: border-color var(--dur-hover) var(--ease-hover),
              box-shadow var(--dur-hover) var(--ease-hover);
}
.studio-combo__btn:hover { border-color: rgba(var(--ink-rgb), 0.28); box-shadow: var(--shadow-sm); }
.studio-combo__value { white-space: nowrap; }

/* The same flat triangle the native control had, now inside the button so it
   can turn over when the list is open. */
.studio-combo__caret {
  width: 0; height: 0; margin-left: auto;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid var(--muted);
  transition: transform var(--dur-hover) var(--ease-hover);
}
.studio-combo.is-open .studio-combo__caret { transform: rotate(180deg); }

/* top:100% is the whole point: the list can only ever grow downward. */
.studio-combo__pop {
  position: absolute;
  top: calc(100% + 0.4rem);
  left: 0;
  min-width: 100%;
  max-height: min(60vh, 20rem);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0.35rem;
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-md);
  z-index: var(--z-overlay);
}
.studio-combo__group {
  margin: 0.45rem 0 0.2rem;
  padding-inline: 0.55rem;
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-weight: 600;
  font-variation-settings: "wght" 600;
  color: var(--muted);
}
.studio-combo__group:first-child { margin-top: 0.1rem; }
.studio-combo__opt {
  display: flex;
  align-items: center;
  min-height: 2.25rem;
  padding: 0.5rem 0.55rem;
  font-size: 0.875rem;
  color: var(--ink);
  border-radius: var(--r-sm);
  cursor: pointer;
}
.studio-combo__opt.is-active { background: var(--accent-soft); }
.studio-combo__opt[aria-selected="true"] {
  color: var(--accent);
  font-weight: var(--wght-medium);
  font-variation-settings: "wght" var(--wght-medium);
}

/* The old caret belonged to the field; the button carries its own now. */
.studio-field.has-combo::after { display: none; }

/* The popup has to be able to leave the bar. Nothing clipped it before, but the
   bar is fixed and short, so say it rather than rely on it. */
.site-header,
.site-header__inner,
.studio-controls,
.studio-field { overflow: visible; }

/* ---- Auto-hide bar --------------------------------------------------------
   js/header-autohide.js adds .is-hidden while you scroll down and drops it the
   moment you scroll up or come back to the top. The bar paints no surface, so
   until now it sat permanently on top of whatever scrolled underneath it.
   Transform only: the measured height feeding --studio-header-h does not
   change, so the hero offset never moves. */
#site-header {
  transition: background var(--dur-base) var(--ease-out-quart),
              box-shadow var(--dur-base) var(--ease-out-quart),
              transform var(--dur-ui) var(--ease-out-quart);
  will-change: transform;
}
#site-header.is-hidden { transform: translateY(-100%); }

@media (prefers-reduced-motion: reduce) {
  /* The module opts out entirely under this setting, so the bar just stays put.
     Kill the transform transition too, in case the class is ever applied. */
  #site-header { transition: none; }
  #site-header.is-hidden { transform: none; }
  .studio-combo__btn, .studio-combo__caret { transition: none; }
}

/* ==========================================================================
   YAZI — the article page (_yazi-sablonu.html and every copy of it)
   --------------------------------------------------------------------------
   Long-form prose in Kum + Bitter. Everything here is type and measure only:
   no new colours (tokens throughout), no italic, no gradients, flat rules.
   The five apologetics pieces from the church's old Wix site are long-form and
   inconsistently structured, so the template gives them a fixed shape: lead,
   H2 sections, optional H3 subheads, and a scripture blockquote.
   ========================================================================== */
.yazi { padding-block: clamp(2rem, 5vw, 4rem); }
.yazi__inner { max-width: 40rem; margin-inline: auto; }   /* measured 79.0 chars/line */

/* Reading measure, measured on this page at 1440 by counting real line boxes
   and excluding each paragraph's ragged last line:
     36rem = 648px = 69.0    38rem = 684px = 72.5 (was)
     40rem = 720px = 79.0    42rem = 756px = 82.3    44rem = 792px = 85.7
   40rem is the last step inside the 70-80 band. It holds at that measure
   because the body leading is 1.75, which is what makes a long line trackable;
   42rem was measured and rejected. */

/* The article opens with a plain .section, so unlike every other page it never
   got the hero's header-clearing top padding. Measured fresh, the .yazi__meta
   eyebrow sat BEHIND the fixed header by 4.3px at 1024, 14.4px at 768 and
   16.4px at 390. This is the hero's own allowance verbatim (see .hero above),
   so an article now opens where every other page opens, and the title drops
   with it. */
.yazi { padding-top: clamp(5.5rem, 9vw, 7rem); }

/* Meta line above the title: date, then reading time if it is known. */
.yazi__meta {
  display: flex; flex-wrap: wrap; gap: 0.5rem 1rem;
  color: var(--muted); font-size: 0.875rem; letter-spacing: 0.04em;
  text-transform: uppercase; margin-bottom: var(--space-3);
}

.yazi__title { margin: 0 0 var(--space-4); }

/* Lead paragraph: larger and muted, so the eye enters the piece before the
   body measure starts. Not italic -- the site has no italic anywhere. */
.yazi__lead {
  font-size: clamp(1.15rem, 1.02rem + 0.55vw, 1.4rem);
  line-height: 1.55; color: var(--muted);
  padding-bottom: var(--space-5);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--space-6);
}

.yazi__body > * + * { margin-top: var(--space-4); }
.yazi__body p { line-height: 1.75; }
.yazi__body h2 {
  font-size: clamp(1.5rem, 1.3rem + 0.85vw, 2rem);
  line-height: 1.2; letter-spacing: -0.01em;
  margin-top: var(--space-7); margin-bottom: var(--space-3);
}
.yazi__body h3 {
  font-size: clamp(1.15rem, 1.05rem + 0.4vw, 1.35rem);
  line-height: 1.3; color: var(--accent-deep);
  margin-top: var(--space-6); margin-bottom: var(--space-2);
}
.yazi__body ul, .yazi__body ol { padding-left: 1.4rem; display: flex; flex-direction: column; gap: 0.5rem; }
.yazi__body li { line-height: 1.7; }
.yazi__body a { color: var(--accent); text-decoration: underline; text-underline-offset: 0.2em; }

/* Diagrams inside an article: Nilufer's own figures, rehosted on our domain.
   They are small at source (230px to 1234px wide), so the rule is never to
   upscale. width/height carry each file's true pixels and `max-width: 100%`
   can only shrink them, so a small diagram sits centred at its own size
   rather than stretched across the measure.

   The card is not decoration. Every one of these files has an opaque white
   matte baked in, and white is `--surface-1` while .surface-paper resolves to
   `--bg`, measured rgb(251, 248, 240) in Kum: a 15/255 step in blue across a
   hard straight edge, so the matte lands as a visible rectangle. Giving it
   the same border, radius and background as the .yazi__panel directly above it
   makes that rectangle deliberate and consistent instead of accidental.
   (mix-blend-mode: multiply was tried first and cannot work here: .yazi__body
   carries `will-change: opacity` for the GSAP reveal, which isolates the group
   and leaves the blend nothing to multiply against.) */
.yazi__gorsel {
  margin: var(--space-6) 0;
  padding: clamp(0.75rem, 1.5vw, 1.1rem);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-1);
  text-align: center;
}
.yazi__gorsel img { display: inline-block; max-width: 100%; height: auto; }

/* Re-typeset schema: the circle as an image, its two lists as REAL TEXT.
   kesif-5 and kesif-6 baked those lists into the bitmap. Measured from the
   image's own pixels, their 22px cap height rendered at 6.2px and 5.8px at
   390, which is not readable, and baked text can never respond to a viewport.
   The circle is cropped out untouched (356x356) and the lists are set in the
   site's own type, so they are legible at every width, selectable, and read by
   a screen reader. Same card as .yazi__panel: these two belong to one family.

   `max-width: 100%` with no width, so the circle renders at its natural 356px
   capped by its column and is never upscaled, at any viewport. */
.yazi__sema {
  margin: var(--space-6) 0;
  padding: clamp(1.1rem, 2.4vw, 1.6rem) clamp(1rem, 2.2vw, 1.5rem);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-1);
  display: grid;
  grid-template-columns: minmax(0, 240px) minmax(0, 1fr);
  gap: clamp(1rem, 2.5vw, 1.75rem);
  align-items: center;      /* the lists run taller than the circle; centring it
                               stops a void opening under the drawing */
}
.yazi__sema img { display: block; max-width: 100%; height: auto; margin-inline: auto; }
.yazi__sema-listeler { display: flex; flex-direction: column; gap: var(--space-4); }
.yazi__sema ul {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 0.35rem;
}
/* The source separated the two lists by putting one either side of the circle.
   Stacked, a hairline carries that split without inventing a heading for it. */
.yazi__sema ul + ul { padding-top: var(--space-4); border-top: 1px solid var(--line); }
.yazi__sema li {
  position: relative; padding-left: 1rem;
  font-size: 0.9375rem; line-height: 1.45; color: var(--ink);
}
.yazi__sema li::before {
  content: ""; position: absolute; left: 0; top: 0.5em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--accent);
}

@media (max-width: 40rem) {
  /* Lists below the circle rather than beside it. */
  .yazi__sema { grid-template-columns: 1fr; }
}

/* Scripture blockquote. Flat left rule in the accent, tinted surface, and the
   reference on its own line. No italic, no quotation-mark glyph, no gradient. */
.yazi__quote {
  margin: var(--space-6) 0;
  padding: var(--space-4) var(--space-5);
  border-left: 3px solid var(--accent);
  background: var(--tint-2);
  border-radius: var(--r-sm);
}
.yazi__quote p { margin: 0; font-size: 1.0625rem; line-height: 1.7; color: var(--ink); }
.yazi__quote cite {
  display: block; margin-top: var(--space-3);
  font-style: normal;                    /* the site has no italic anywhere */
  font-size: 0.875rem; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--accent-deep); font-weight: var(--wght-semibold);
}

/* Back link to the index. */
.yazi__back { margin-top: var(--space-7); padding-top: var(--space-5); border-top: 1px solid var(--line); }

@media (max-width: 40rem) {
  .yazi__inner { max-width: none; }
  .yazi__quote { padding: var(--space-3) var(--space-4); }
}

/* --- Etkinlikler: the generated upcoming list (js/etkinlikler.js) ---------
   Reuses the .values__row rhythm rather than inventing a card. Manual entries
   carry an accent rule so a special event reads differently from the standing
   Sunday service without a second colour. Flat, tokens only. */
.etkinlik-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.etkinlik-row {
  display: grid; grid-template-columns: auto 1fr; gap: 0.25rem 1.25rem;
  align-items: baseline;
  padding: clamp(1rem, 2.2vw, 1.6rem) 0;
  border-top: 1px solid var(--line);
}
.etkinlik-row:last-child { border-bottom: 1px solid var(--line); }
.etkinlik-row__date {
  grid-column: 1; font-weight: var(--wght-semibold); color: var(--ink);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.etkinlik-row__day {
  grid-column: 2; color: var(--muted); font-size: 0.875rem;
  letter-spacing: 0.04em; text-transform: uppercase;
}
.etkinlik-row__title { grid-column: 1 / -1; font-size: clamp(1.05rem, 1rem + 0.3vw, 1.25rem); color: var(--ink); }
.etkinlik-row__note  { grid-column: 1 / -1; color: var(--muted); }

/* Event location. Rendered ONLY for an event that carries an address, which
   means only for an event that is not at the church: an event at the church
   leaves the field blank, and the church address goes on being stated once, in
   the visit block below, rather than repeated on every row.

   A link, never an embedded map. A map per event needs a WebGL context per
   event, and browsers cap live contexts, so a long list would work for the
   first few and then blank depending on the visitor's device. A directions
   link also answers the question the visitor actually has, starting from
   wherever they are standing.

   align-items is center rather than the row's baseline because the link
   carries vertical padding to reach a real tap target, and padding moves a
   flex item's first baseline, which would drop the link below the address. */
.etkinlik-row__yer {
  grid-column: 1 / -1;
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.1rem 0.85rem;
}
.etkinlik-row__adres { color: var(--muted); }
.etkinlik-row__yol {
  color: var(--accent);
  text-underline-offset: 0.2em;
  display: inline-block;
  padding-block: 0.3rem;
  min-height: 24px;
}

.etkinlik-row--ozel { border-left: 3px solid var(--accent); padding-left: var(--space-4); }

@media (max-width: 40rem) {
  .etkinlik-row { grid-template-columns: 1fr; gap: 0.2rem; }
  .etkinlik-row__day { grid-column: 1; }
}

