/* ==========================================================================
   Leo Pilates Studio — Editorial Wellness Theme
   Structured as one continuous 3-act story rather than stacked sections:
   Act 1 (hero + breathe) hooks, Act 2 flows, Act 3 closes on a single CTA.
   ========================================================================== */

:root{
  --ink: #111110;
  --ink-soft: #1c1b19;
  --paper: #EEEAE2;
  --paper-2: #E5DFD5;
  --white: #ffffff;
  --muted: #6f6a61;
  --muted-light: rgba(238,234,226,0.72);
  --text-secondary: #433f38;
  --line-dark: rgba(255,255,255,0.14);
  --line-light: rgba(17,17,16,0.14);

  --font-display: "Manrope", "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
  --font-body: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;

  --container: 1280px;
  --gutter: clamp(20px, 5vw, 64px);

  --ease: cubic-bezier(.22,1,.36,1);
}

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

html{ scroll-behavior: smooth; }

body{
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img{ display:block; max-width:100%; }
a{ color: inherit; text-decoration: none; }

/* Visually hidden but still readable by screen readers / crawlers — used
   to give the h1 its full "Leo Pilates Studio — Düzce" accessible name
   without changing the large "LEO PILATES" visual wordmark underneath it. */
.sr-only{
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.container{
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.grain{
  position: fixed;
  inset: 0;
  z-index: 999;
  pointer-events: none;
  opacity: 0.035;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

@media (prefers-reduced-motion: reduce){
  *{ animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
  html{ scroll-behavior: auto; }
  .line-inner, .hero-kicker span, .hero-sub span{ transform: none !important; opacity: 1 !important; }
  .gallery-item{ clip-path: none !important; }
  /* breathe: resting values already match each animation's own 0%/100%
     keyframe state, and the global animation-duration/iteration-count
     rule above already collapses a triggered run to a near-instant,
     one-shot flash rather than a real 14s motion sequence — no extra
     overrides needed, and forcing one here would fight the start/repeat
     button's own show/hide logic (.breathe-hook.is-active). */
}

/* ---------- shared labels / headings ---------- */

.label, .kicker{
  font-size: 13.5px;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink);
  margin: 0 0 18px;
  display: inline-block;
}

.section-head{ margin-bottom: clamp(40px, 6vw, 72px); }

/* mask-reveal building blocks: any heading split into .line > .line-inner
   starts hidden and is revealed on load (hero) or on scroll (everything
   else) via JS. */
.line{ display:block; overflow:hidden; }
.line-inner{
  display:block;
  transform: translateY(112%);
  will-change: transform;
}

/* iPad/iOS Safari only (this @supports feature check is only ever true on
   WebKit-on-iOS/iPadOS — desktop Safari, Chrome, Firefox all fail it, so
   none of their sizing/alignment is touched). A late web-font swap there
   can nudge these lines' true rendered glyph height a hair past what was
   first measured, and the tight line-heights some of these headings use
   (e.g. .hero-title at 0.96) leave overflow:hidden no slack to absorb
   that — clipping a sliver off a descender/accent. A few px of extra
   clipping room fixes that without touching font-size, clamp() values, or
   any layout measurement anywhere else; no compensating negative margin,
   so this adds a few px of height here on iPad only (by design, not a
   side effect to cancel out). */
@supports (-webkit-touch-callout: none){
  .line, .hero-kicker, .hero-sub{ padding-bottom: 6px; }
}

/* ---------- buttons ---------- */

.btn{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 15px 30px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border-radius: 999px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background 0.4s var(--ease), color 0.4s var(--ease), border-color 0.4s var(--ease), transform 0.4s var(--ease);
}
.btn .arrow-icon{ transition: transform 0.45s var(--ease); }
.btn:hover .arrow-icon{ transform: translate(3px, -3px); }

.btn-outline-light{
  border-color: var(--line-dark);
  color: var(--paper);
  background: transparent;
}
.btn-outline-light:hover{ background: var(--paper); color: var(--ink); }

.btn-finale{
  background: var(--paper);
  color: var(--ink);
  padding: 20px 42px;
  font-size: 14px;
}
.btn-finale:hover{ background: var(--white); transform: translateY(-3px); }

/* header CTA inverts with the header's own state — always high contrast
   against whatever is behind it, dark image or light bar. */
.header-cta{
  background: var(--paper);
  color: var(--ink);
  padding: 12px 26px;
}
.header-cta:hover{ background: var(--white); transform: translateY(-1px); }
.site-header.is-scrolled .header-cta{ background: var(--ink); color: var(--paper); }
.site-header.is-scrolled .header-cta:hover{ background: var(--ink-soft); }

/* ---------- shared underline / letter-spacing micro-interactions ---------- */

.nav-desktop a,
.footer-social a,
.footer-meta a,
.footer-credit a,
.faq-cta a{
  position: relative;
  transition: letter-spacing 0.4s var(--ease);
}
.nav-desktop a::after,
.footer-social a::after,
.footer-meta a::after,
.footer-credit a::after,
.faq-cta a::after{
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -2px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.45s var(--ease);
}
.nav-desktop a:hover::after,
.footer-social a:hover::after,
.footer-meta a:hover::after,
.footer-credit a:hover::after,
.faq-cta a:hover::after{ transform: scaleX(1); transform-origin: left; }
.nav-desktop a:hover{ letter-spacing: 0.03em; }

/* ==========================================================================
   HEADER — a real premium bar, not a hairline.
   Over the hero it sits on its own dark scrim (independent of the hero's
   own overlay) so it reads clearly from the very first frame; once scrolled
   it switches to a solid warm bar with a soft shadow.
   ========================================================================== */

.site-header{
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 200;
  color: var(--paper);
  transition: background 0.4s var(--ease), border-color 0.4s var(--ease), color 0.4s var(--ease), box-shadow 0.4s var(--ease);
  border-bottom: 1px solid transparent;
}
.site-header::before{
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 170px;
  background: linear-gradient(180deg, rgba(17,17,16,0.62) 0%, rgba(17,17,16,0) 100%);
  z-index: -1;
  opacity: 1;
  transition: opacity 0.5s var(--ease);
  pointer-events: none;
}

.site-header.is-scrolled{
  color: var(--ink);
  background: rgba(238,234,226,0.92);
  backdrop-filter: blur(10px);
  border-color: var(--line-light);
  box-shadow: 0 10px 30px rgba(17,17,16,0.06);
}
.site-header.is-scrolled::before{ opacity: 0; }

.header-inner{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  /* exact height, not derived from padding + content guesswork — matches
     measured reference values (87px before scroll, 63px after).
     align-items:center keeps logo, nav links and the CTA all vertically
     centered within this fixed row in both states. */
  height: 87px;
  transition: height 0.4s var(--ease);
}
.site-header.is-scrolled .header-inner{ height: 63px; }

.logo{
  display: inline-flex;
  align-items: center;
  transition: opacity 0.3s ease;
}
.logo:hover{ opacity: 0.75; }

.logo-img{
  display: block;
  width: clamp(130px, 20vw, 165px);
  height: auto;
}
.logo-footer .logo-img{
  /* same visible size as before the logo file was trimmed of its
     transparent padding — width equivalents of the old 34-46px height
     range at the old 1.88:1 file aspect ratio, so the footer mark looks
     pixel-for-pixel unchanged. */
  width: clamp(64px, 9.4vw, 86px);
  height: auto;
}

.nav-desktop{ display: flex; gap: clamp(20px, 3vw, 40px); margin: 0 auto; }
.nav-desktop a{ font-size: 14px; font-weight: 500; letter-spacing: 0.03em; padding: 4px 0; }

.header-cta{ flex-shrink: 0; }

.nav-toggle{
  display: none;
  width: 32px; height: 20px;
  position: relative;
  background: none; border: none; cursor: pointer; padding: 0;
}
.nav-toggle span{
  position: absolute; left: 0; right: 0; height: 1px;
  background: currentColor;
  transition: transform 0.4s var(--ease), opacity 0.3s var(--ease), top 0.4s var(--ease);
}
.nav-toggle span:nth-child(1){ top: 2px; }
.nav-toggle span:nth-child(2){ top: 16px; }
.nav-toggle[aria-expanded="true"] span:nth-child(1){ top: 9px; transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2){ top: 9px; transform: rotate(-45deg); }

.nav-mobile{
  position: fixed; inset: 0; z-index: 190;
  background: var(--ink); color: var(--paper);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 48px;
  clip-path: circle(0% at 100% 0%);
  transition: clip-path 0.7s var(--ease);
  pointer-events: none;
}
.nav-mobile.is-open{ clip-path: circle(150% at 100% 0%); pointer-events: auto; }
.nav-mobile nav{ display: flex; flex-direction: column; align-items: center; gap: 24px; }
.nav-mobile nav a{ font-family: var(--font-display); font-weight: 600; font-size: 32px; }

@media (max-width: 860px){
  .nav-desktop, .header-cta{ display: none; }
  .nav-toggle{ display: block; }
}

/* Anchor-nav offset: the header is position:fixed and floats over the page,
   which is fine for the full-screen hero/breathe/finale sections (they're
   designed for it), but content sections whose own top padding is smaller
   than the header's height would otherwise land partly underneath it after
   a nav jump. 110px comfortably covers the header's compact height on both
   desktop and mobile — Gallery's 50px padding floor was the tightest case,
   but Hizmetler/Hakkımızda get the same safety net. */
#hizmetler, #hakkimizda, #galeri, #sss{
  scroll-margin-top: 110px;
}

/* ==========================================================================
   ACT 1a — HERO
   The photo carries the message; type stays legible, bold and never
   competes for space — it just refuses to look faint next to it.
   ========================================================================== */

.hero{
  position: relative;
  height: 100svh;
  min-height: 620px;
  display: flex;
  align-items: center;
  overflow: hidden;
  background: var(--ink);
}

.hero-bg{ position: absolute; inset: -10% 0 0 0; height: 120%; overflow: hidden; }
.hero-bg img{
  width: 100%; height: 100%;
  object-fit: cover;
  /* newer reformer shot: she sits closer to center with open floor/window
     on the left and more of the reformer row on the right, instead of the
     old photo's hard right-of-center subject — a near-center anchor keeps
     her in frame without needing the old photo's aggressive 58%/74% bias. */
  object-position: 48% 38%;
  /* no static scale — the 120%-height/-10%-inset oversize on .hero-bg
     already gives the yPercent scroll-parallax below all the overscan
     margin it needs; this scale was purely an extra cosmetic crop-in that,
     stacked with the new photo's already-tighter framing, read as too
     zoomed. */
  /* light touch — premium, already well-lit photo; don't flatten it. */
  filter: brightness(0.96) contrast(1.04) saturate(1.02);
  will-change: transform;
}

@media (max-width: 600px){
  /* On narrow phones this 1.78:1 image covers a tall, narrow container by
     matching height exactly and showing only a narrow vertical slice of it.
     In the new photo she's roughly centered (unlike the old one, which sat
     hard right at 75-85% and needed a much stronger shift) — a slightly
     wider anchor than the desktop 48% keeps her fully in that slice instead
     of favoring the empty window side. Vertical is unaffected by this (full
     image height already shows on mobile either way). */
  .hero-bg img{ object-position: 52% 38%; }
}

.hero-overlay{
  position: absolute; inset: 0;
  /* flat, uniform warm tint — no directional gradient, no panel behind
     the text. Legibility comes from text-shadow + positioning, not from
     darkening one part of the frame more than another. */
  background: rgba(20,15,10,0.2);
}

.hero-inner{
  position: relative;
  z-index: 2;
  color: var(--paper);
  width: 100%;
  max-width: min(600px, 92%);
  will-change: transform;
}

.hero-kicker{
  font-size: 14px;
  font-weight: 800;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--white);
  /* Removing the "LEO PILATES" title collapsed this gap down to a plain
     26px, shrinking the whole hero text block's footprint (was ~600x158,
     dropped to ~600x72) — scaled back up so the kicker+subtitle block
     reclaims roughly the vertical room the title used to occupy, instead
     of reading as two cramped lines sitting in the middle of the photo. */
  margin: 0 0 clamp(64px, 11vw, 112px);
  overflow: hidden;
  /* deliberately no text-shadow / background / box-shadow / filter — sits
     flat on the photo; readability comes from weight + tracking + color
     contrast only. */
}
.hero-kicker span, .hero-sub span{ display: inline-block; transform: translateY(112%); opacity: 0; }

.hero-sub{
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(18px, 2.2vw, 25px);
  color: var(--paper);
  margin: 0;
  overflow: hidden;
  text-shadow: 0 1px 10px rgba(0,0,0,0.45);
}

.hero-scroll-wrap{
  position: absolute; right: var(--gutter); bottom: 40px; z-index: 2;
  display: none; flex-direction: column; align-items: center; gap: 10px;
}
.hero-scroll-label{ font-size: 10px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted-light); }
.hero-scroll-line{ width: 1px; height: 56px; background: var(--line-dark); overflow: hidden; position: relative; display: block; }
.hero-scroll-line i{
  position: absolute; top: -100%; left: 0; right: 0; height: 100%;
  background: var(--paper);
  animation: scrollLine 2.6s ease-in-out infinite;
  font-style: normal;
}
@keyframes scrollLine{ 0%{ top: -100%; } 50%{ top: 0%; } 100%{ top: 100%; } }
@media (min-width: 720px){ .hero-scroll-wrap{ display: flex; } }

/* ==========================================================================
   ACT 1b — BREATHE HOOK
   A soft transparent halo + three thin organic rings, not a glowing ball.
   Rings breathe out of phase for an organic ripple; light and type pulse
   on the same rhythm as the ring. Backdrop is warmer and more visible.
   ========================================================================== */

.breathe-hook{
  position: relative;
  height: 100svh;
  min-height: 640px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--ink);
}

.breathe-media{ position: absolute; inset: 0; }
.breathe-media img{
  width: 100%; height: 100%;
  object-fit: cover;
  /* subject (hands on chest/belly, eyes closed) sits right-of-center —
     keep that detail centered in frame rather than the window/plants
     on the left. Photo is already warm and premium, so no artificial
     sepia/grayscale tint is needed this time, just a light dimming. */
  object-position: 62% 38%;
  filter: contrast(1.03) brightness(0.9) saturate(1.02);
}
.breathe-overlay{
  position: absolute; inset: 0;
  /* light warm scrim — enough for the ring/text to read clearly without
     flattening the studio's natural light and detail. */
  background: radial-gradient(circle at 50% 42%, rgba(40,28,18,0.22) 0%, rgba(30,22,15,0.34) 55%, rgba(20,15,10,0.48) 100%);
}

.breathe-content{
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(4px, 1vw, 10px);
  color: var(--paper);
  text-align: center;
  padding: 0 24px;
}

.breathe-ring-wrap{
  position: relative;
  width: clamp(240px, 32vw, 420px);
  height: clamp(240px, 32vw, 420px);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: clamp(4px, 1.5vw, 14px);
  /* purely decorative (halo/rings/progress ring, nothing interactive
     inside it) — but being `position: relative` puts it in a higher paint
     layer than the non-positioned .breathe-start below it, and the halo's
     inset:-38% makes it physically overlap that area. Without this, the
     halo silently swallows clicks meant for the start/repeat button. */
  pointer-events: none;
}

/* Real breathing pattern, one 14s cycle: inhale 4s (0-28.571%), hold 4s
   (28.571-57.143%), release 6s (57.143-100%). The halo, the three organic
   rings, the progress ring and the phase text all run on this same 14s
   timeline so everything the user sees is telling the same story. */

.breathe-halo{
  position: absolute;
  inset: -38%;
  border-radius: 50%;
  background: radial-gradient(circle, transparent 0%, rgba(238,234,226,0.3) 50%, transparent 78%);
  filter: blur(26px);
  /* calm, static resting look until the user presses "Egzersizi Başlat" —
     opacity matches the animation's own 0%/100% value so starting and
     finishing never causes a visible jump. */
  opacity: 0.5;
}
.breathe-hook.is-active .breathe-halo{ animation: haloBreath 14s ease-in-out 3; }
@keyframes haloBreath{
  0%      { transform: scale(0.85); opacity: 0.5; }
  28.571% { transform: scale(1.15); opacity: 1; }
  57.143% { transform: scale(1.15); opacity: 1; }
  100%    { transform: scale(0.85); opacity: 0.5; }
}

.breathe-ring{
  position: absolute;
  inset: 0;
  border: 1px solid rgba(238,234,226,0.42);
  border-radius: 50% 50% 49% 51% / 51% 49% 50% 50%;
  opacity: 0.35;
}
.breathe-hook.is-active .breathe-ring{ animation: ringBreath 14s ease-in-out 3; }
.breathe-ring-2{
  inset: -14%;
  border-color: rgba(238,234,226,0.26);
  border-radius: 52% 48% 50% 50% / 48% 52% 50% 50%;
  animation-delay: -1.1s;
}
.breathe-ring-3{
  inset: -28%;
  border-color: rgba(238,234,226,0.14);
  border-radius: 48% 52% 47% 53% / 53% 47% 52% 48%;
  animation-delay: -2.2s;
}
@keyframes ringBreath{
  0%      { transform: scale(0.9); opacity: 0.35; }
  28.571% { transform: scale(1.1); opacity: 0.9; }
  57.143% { transform: scale(1.1); opacity: 0.9; }
  100%    { transform: scale(0.9); opacity: 0.35; }
}

/* soft circular progress ring: fills while inhaling, holds full through the
   hold, drains while releasing — a warm off-white glow, not a stark white
   line, so it reads as organic rather than a UI widget. */
.breathe-progress{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
  filter: drop-shadow(0 0 10px rgba(238,234,226,0.45));
}
.breathe-progress-track{
  fill: none;
  stroke: rgba(238,234,226,0.16);
  stroke-width: 1.5;
}
.breathe-progress-fill{
  fill: none;
  stroke: var(--paper);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 339.3;
  stroke-dashoffset: 339.3;
}
.breathe-hook.is-active .breathe-progress-fill{ animation: ringProgress 14s linear 3; }
@keyframes ringProgress{
  0%      { stroke-dashoffset: 339.3; }
  28.571% { stroke-dashoffset: 0; }
  57.143% { stroke-dashoffset: 0; }
  100%    { stroke-dashoffset: 339.3; }
}

.breathe-words{
  position: relative;
  height: clamp(52px, 8.5vw, 92px);
  display: none;
  align-items: center;
  justify-content: center;
}
.breathe-hook.is-active .breathe-words{ display: flex; }
.breathe-words span{
  position: absolute;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(30px, 6vw, 72px);
  letter-spacing: -0.01em;
  color: var(--paper);
  text-shadow: 0 2px 24px rgba(0,0,0,0.4);
  white-space: nowrap;
}
/* Each phase gets its own keyframes (not phase-shifted copies of one shared
   animation) so at most one is ever visible: the other two are always
   opacity:0 + visibility:hidden. Every switch happens in a sub-1% window so
   it reads as a clean cut, never a crossfade/overlap. */
/* resting state: all three phases stay hidden — the start screen (below)
   is what shows before the user presses "Egzersizi Başlat". Each phase
   animation runs exactly once (not infinite): the exercise is one full
   NEFES AL → NEFESİNİ TUT → YAVAŞÇA BIRAK pass, then main.js swaps the
   start screen's button to "Tekrarla" for the next round. */
.word-in, .word-hold, .word-out{ opacity: 0; visibility: hidden; }

.breathe-hook.is-active .word-in{ animation: phaseIn 14s ease-in-out 3; }
.breathe-hook.is-active .word-hold{ animation: phaseHold 14s ease-in-out 3; }
.breathe-hook.is-active .word-out{ animation: phaseOut 14s ease-in-out 3; }
@keyframes phaseIn{
  0%       { opacity: 1; visibility: visible; transform: scale(0.97); }
  28.2%    { opacity: 1; visibility: visible; transform: scale(1.03); }
  28.571%  { opacity: 0; visibility: hidden; transform: scale(1.03); }
  100%     { opacity: 0; visibility: hidden; transform: scale(1.03); }
}
@keyframes phaseHold{
  0%       { opacity: 0; visibility: hidden; transform: scale(1); }
  28.571%  { opacity: 0; visibility: hidden; transform: scale(1); }
  29%      { opacity: 1; visibility: visible; transform: scale(1); }
  56.7%    { opacity: 1; visibility: visible; transform: scale(1); }
  57.143%  { opacity: 0; visibility: hidden; transform: scale(1); }
  100%     { opacity: 0; visibility: hidden; transform: scale(1); }
}
@keyframes phaseOut{
  0%       { opacity: 0; visibility: hidden; transform: scale(1.03); }
  57.143%  { opacity: 0; visibility: hidden; transform: scale(1.03); }
  57.6%    { opacity: 1; visibility: visible; transform: scale(1.03); }
  99.6%    { opacity: 1; visibility: visible; transform: scale(0.97); }
  100%     { opacity: 0; visibility: hidden; transform: scale(0.97); }
}

.breathe-caption{
  font-size: 13px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted-light);
  margin: 18px 0 0;
}

/* start / repeat screen — shown until the user presses the button, hidden
   for the duration of the run, shown again (button relabelled "Tekrarla")
   once the cycle completes. */
.breathe-start{
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 22px;
}
.breathe-hook.is-counting .breathe-start,
.breathe-hook.is-active .breathe-start{ display: none; }

/* short 3-2-1 countdown shown after pressing "Egzersizi Başlat", before
   the actual 14s×3 breathing sequence begins. */
.breathe-countdown{
  display: none;
  align-items: center;
  justify-content: center;
  height: clamp(52px, 8.5vw, 92px);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(48px, 9vw, 96px);
  color: var(--paper);
}
.breathe-hook.is-counting .breathe-countdown{ display: flex; }

.breathe-start-title{
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(24px, 4vw, 36px);
  color: var(--paper);
  margin: 0;
  text-shadow: 0 2px 16px rgba(0,0,0,0.4);
}

.btn-breathe{
  background: var(--paper);
  color: var(--ink);
  padding: 16px 36px;
}
.btn-breathe:hover{ background: var(--white); transform: translateY(-2px); }

/* ==========================================================================
   ACT 2 — SERVICES (sticky scrollytelling, no cards)
   Visual is intentionally more compact here — the big scenes are the
   hero, breathe and finale; the middle of the page stays editorial.
   ========================================================================== */

.services-scroll{ padding: clamp(90px, 12vw, 150px) 0 clamp(110px, 12vw, 170px); }

.services-layout{ display: grid; grid-template-columns: 1fr; gap: 20px; }
@media (min-width: 960px){
  .services-layout{ grid-template-columns: 0.85fr 1.15fr; gap: 90px; align-items: start; }
}

.services-visual{ position: sticky; top: 100px; height: 40vh; min-height: 280px; }
@media (min-width: 960px){ .services-visual{ height: 56vh; max-height: 480px; } }

.services-visual-track{ position: relative; width: 100%; height: 100%; overflow: hidden; background: var(--ink-soft); }

.visual-frame{ position: absolute; inset: 0; opacity: 0; transition: opacity 1s var(--ease); }
.visual-frame img{
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(1.08);
  filter: grayscale(0.15) contrast(1.06) brightness(0.96);
  transition: transform 1.4s var(--ease);
}
.visual-frame.is-active{ opacity: 1; }
.visual-frame.is-active img{ transform: scale(1); }

/* The visual column renders roughly as wide as it is tall (~1:1), while
   these studio photos are portrait (4:5) — object-fit:cover scales them
   to fill the column's width, so the crop that gets lost is off the top
   and bottom, never the sides. Each pose fills its frame differently, so
   the vertical anchor is tuned per photo to keep the key action (raised
   arm, flight line, stretch) in frame rather than splitting the loss
   evenly top/bottom. */
.visual-frame[data-visual="1"] img{ object-position: center 38%; } /* reformer: keep the reaching raised arm */
.visual-frame[data-visual="2"] img{ object-position: center 42%; }
.visual-frame[data-visual="3"] img{ object-position: center 46%; }
.visual-frame[data-visual="4"] img{ object-position: center 35%; } /* bungee fly: keep head/arms, she trails lower-left */
.visual-frame[data-visual="5"] img{ object-position: center 42%; }

.services-progress{ display: flex; align-items: center; gap: 16px; margin-top: 22px; }
.progress-track{ position: relative; flex: 1; height: 1px; background: var(--line-light); }
.progress-fill{ position: absolute; left: 0; top: 0; height: 100%; width: 0%; background: var(--ink); transition: width 0.5s var(--ease); }
.progress-ticks{ display: flex; gap: 14px; list-style: none; margin: 0; padding: 0; font-size: 11px; font-weight: 600; letter-spacing: 0.08em; color: var(--muted); }
.progress-ticks li{ transition: color 0.4s ease; }
.progress-ticks li.is-active{ color: var(--ink); }

.services-panels{ display: flex; flex-direction: column; }
.service-panel{
  padding: clamp(48px, 9vh, 120px) 0;
  border-bottom: 1px solid var(--line-light);
  opacity: 0.32;
  transform: translateY(10px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}
.service-panel:last-child{ border-bottom: none; }
.service-panel.is-active{ opacity: 1; transform: none; }

.service-num{
  display: inline-block;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--muted);
  margin-bottom: 14px;
  transition: color 0.5s ease, transform 0.5s var(--ease);
}
.service-panel.is-active .service-num{ color: var(--ink); transform: translateX(4px); }

.service-panel h3{
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(30px, 4vw, 48px);
  margin: 0 0 16px;
  letter-spacing: -0.01em;
  transition: letter-spacing 0.5s var(--ease);
}
/* Real mouse only — without this gate, a tap on a touch device (e.g. an
   iPad in landscape, wide enough to get this desktop layout) can leave the
   letter-spacing "stuck" in its hover state until the user taps elsewhere,
   a known iOS Safari :hover-after-tap quirk. */
@media (hover: hover) and (pointer: fine){
  .service-panel:hover h3{ letter-spacing: 0.01em; }
}

.service-panel p{ max-width: 460px; color: var(--text-secondary); font-size: 16px; line-height: 1.65; margin: 0; }

/* Per-panel image shown only below 960px (see media query) — the shared
   sticky visual column is a desktop-only pairing effect; hidden here and
   replaced by each service carrying its own image inline, in normal flow. */
.service-mobile-media{ display: none; }

@media (max-width: 959px){
  /* The sticky visual + its progress/tick indicator only make sense next to
     a side-by-side scrolling text column (the desktop layout). In the
     mobile single-column flow they don't pair with anything — this is also
     what was driving the reported "text overlapping" bug: the shared
     sticky image doesn't move, so as it "stuck" near the top mobile users
     scrolled the panel list underneath it while the inactive-panel
     opacity/translateY dimming below kept multiple partially-faded panels
     readable on screen at once, reading as overlapping text. */
  .services-visual{ display: none; }
  .services-progress{ display: none; }

  /* Every panel renders fully, no dimmed "inactive" ghost state — the
     active-tracking JS itself also stops running below this breakpoint
     (see main.js), so this isn't fighting a class that's still toggling. */
  .service-panel{ opacity: 1; transform: none; }

  .service-mobile-media{
    display: block;
    width: 100%;
    aspect-ratio: 4 / 5;
    overflow: hidden;
    margin-bottom: 24px;
  }
  .service-mobile-media img{
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
  }

  /* Same per-pose vertical anchors as the desktop sticky visual
     (.visual-frame[data-visual="N"] img) — without these, the mobile card
     image defaulted to a plain center crop and lost whichever detail
     (raised arm, head/arms on the bungee fly) the desktop version was
     specifically tuned to keep in frame. */
  .service-panel[data-panel="1"] .service-mobile-media img{ object-position: center 38%; }
  .service-panel[data-panel="2"] .service-mobile-media img{ object-position: center 42%; }
  .service-panel[data-panel="3"] .service-mobile-media img{ object-position: center 46%; }
  .service-panel[data-panel="4"] .service-mobile-media img{ object-position: center 35%; }
  .service-panel[data-panel="5"] .service-mobile-media img{ object-position: center 42%; }
}

/* "Devamını oku" / "Daha az göster" — small, text-only toggle, no button
   chrome, so it reads as part of the editorial copy rather than UI. */
.service-toggle{
  display: inline-block;
  margin-top: 16px;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--ink);
  position: relative;
}
.service-toggle::after{
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -2px;
  height: 1px;
  background: currentColor;
  opacity: 0.35;
  transition: opacity 0.3s ease;
}
.service-toggle:hover::after{ opacity: 0.85; }

/* detail: height + opacity are GSAP-driven in main.js (each answer's open
   height depends on its own content), independent per panel — more than
   one can be open at once, unlike the FAQ accordion. */
.service-detail{
  height: 0;
  overflow: hidden;
  opacity: 0;
}
.service-detail-inner{ padding-top: 18px; }
.service-detail-inner p{
  max-width: 460px;
  margin: 0 0 14px;
  font-size: 15px;
  line-height: 1.75;
  color: var(--muted);
}
.service-detail-inner p:last-child{ margin-bottom: 0; }

/* ==========================================================================
   STATEMENT — big typographic pauses between Act 2 movements
   ========================================================================== */

.statement{
  padding: clamp(90px, 14vw, 200px) 0;
  display: flex; align-items: center; justify-content: center;
  text-align: center;
}
.statement.is-dark{ background: var(--ink); color: var(--paper); }
.statement.is-light{ background: var(--paper-2); color: var(--ink); }

.statement-title{
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(30px, 7vw, 80px);
  line-height: 1.25;
  max-width: 920px;
  margin: 0 auto;
  letter-spacing: -0.015em;
}

/* ==========================================================================
   MEDIA / IMAGE REVEAL (panel-wipe technique — about)
   ========================================================================== */

.media-reveal{ position: relative; overflow: hidden; background: var(--ink-soft); }
.media-reveal img{
  /* absolute + inset:0 ties the image directly to this box's exact
     border-box, instead of matching it via width/height:100% in normal
     flow — the latter depends on the parent's aspect-ratio-computed
     height being resolved identically on both the box and the image,
     which some engines round by a sub-pixel differently, leaving the
     dark .media-reveal background peeking through as a thin line along
     one edge. Anchoring by inset makes that class of gap impossible. */
  display: block;
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(1.18);
  filter: grayscale(0.15) contrast(1.06) brightness(0.96);
  transition: filter 0.6s ease;
}
.about-media img{
  /* this photo is 3:2 (1536x1024), matching the box's own ratio exactly
     — object-fit:cover shows it edge-to-edge with no cropping, so a
     plain center anchor is all that's needed. */
  object-position: center;
  /* override .media-reveal img's shared grayscale/contrast/brightness —
     this photo's natural sunlit color is the whole point of the shot,
     so leave it untouched. */
  filter: none;
}
.reveal-panel{ position: absolute; inset: 0; background: var(--paper); transform-origin: left; z-index: 2; }

/* ==========================================================================
   ABOUT — a real brand statement: bold headline, one confident paragraph,
   three named values. Image stays deliberately more contained here so the
   content carries the section (contrast with gallery's larger scale).
   ========================================================================== */

.about{ padding: clamp(90px, 12vw, 160px) 0; }

.about-grid{ display: grid; grid-template-columns: 1fr; gap: 40px; align-items: center; }
/* ~52% image / ~48% text — image stays inside its own column (never
   full-width, never above the section) with the text beside it; the
   photo's source order already puts it first, so mobile falls back to a
   natural image-on-top, text-below stack with no extra markup. */
@media (min-width: 900px){ .about-grid{ grid-template-columns: 58fr 42fr; gap: 64px; } }

/* Outer frame = the full media column — no background, no padding, the
   inner frame fills it edge to edge. */
.about-media{
  width: 100%;
  display: flex;
  padding: 0;
}

/* Inner box: this is the actual 3:2 crop (matches the photo's real pixel
   ratio exactly, so object-fit:cover shows it edge-to-edge with zero
   cropping) — sized to fill the frame's padded content area, not the
   whole column. */
.about-media-frame{ width: 100%; aspect-ratio: 3 / 2; }

.about-heading{
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(30px, 5vw, 58px);
  line-height: 1.12;
  margin: 0 0 26px;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.about-body{
  font-size: 16.5px;
  line-height: 1.75;
  color: var(--text-secondary);
  max-width: 560px;
  margin: 0;
}

.about-values{
  list-style: none;
  margin: 32px 0 0;
  padding: 26px 0 0;
  border-top: 1px solid var(--line-light);
  display: flex;
  flex-wrap: wrap;
  gap: 12px 32px;
}
.value-item{
  position: relative;
  padding-left: 18px;
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--ink);
}
.value-item::before{
  content: "";
  position: absolute;
  left: 0; top: 50%;
  transform: translateY(-50%);
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--ink);
}

/* ==========================================================================
   GALLERY — asymmetric editorial grid, one studio story
   ========================================================================== */

.gallery{ padding: clamp(50px, 7vw, 90px) 0 clamp(100px, 12vw, 160px); }

.gallery-intro{
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(20px, 3vw, 30px);
  margin: 0 0 clamp(36px, 5vw, 60px);
  color: var(--ink);
}

.gallery-grid{
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: minmax(190px, auto);
  gap: clamp(14px, 2vw, 28px);
}

.gallery-item{
  position: relative;
  overflow: hidden;
  margin: 0;
  background: var(--ink-soft);
  clip-path: inset(0 0 100% 0);
  will-change: clip-path;
}
.gallery-item img{
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(1.22);
  filter: grayscale(0.15) contrast(1.06) brightness(0.97);
  transition: filter 0.5s ease;
}
/* Soft legibility gradient — a separate layer from the caption text itself,
   spanning part of the image's own height (not a fixed-height bar glued to
   the bottom) so it reads as a gentle vignette on the photo rather than a
   solid strip. Low peak opacity, fades to fully transparent well before the
   image's midpoint. Hidden until hover/touch-open, same as the caption. */
.gallery-item::after{
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 55%;
  background: linear-gradient(0deg, rgba(17,17,16,0.4) 0%, rgba(17,17,16,0) 100%);
  opacity: 0;
  transition: opacity 0.45s var(--ease);
  pointer-events: none;
}

.gallery-item figcaption{
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; gap: 10px; align-items: baseline;
  padding: 18px 20px;
  color: var(--paper);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.45s var(--ease), transform 0.45s var(--ease);
}
.gallery-item figcaption span:first-child{ font-size: 11px; letter-spacing: 0.1em; opacity: 0.7; }
.gallery-item figcaption span:last-child{ font-size: 13px; font-weight: 600; letter-spacing: 0.04em; }

/* Real mouse: unchanged hover reveal. */
@media (hover: hover) and (pointer: fine){
  .gallery-item:hover img{ filter: grayscale(0) contrast(1.05) brightness(1.02); }
  .gallery-item:hover::after{ opacity: 1; }
  .gallery-item:hover figcaption{ opacity: 1; transform: translateY(0); }
}

/* Touch / coarse pointer: no :hover involved at all — main.js toggles
   .is-touched on click (one item open at a time), so the same gradient +
   caption reveal appears on tap instead of mouseover. The image's own
   scale-up (lighter than desktop's hover zoom) is GSAP-driven there too,
   since transform is already owned by the entrance/scroll tweens. */
@media (hover: none), (pointer: coarse){
  .gallery-item.is-touched img{ filter: grayscale(0) contrast(1.05) brightness(1.02); }
  .gallery-item.is-touched::after{ opacity: 1; }
  .gallery-item.is-touched figcaption{ opacity: 1; transform: translateY(0); }
}

@media (min-width: 760px){
  .g-1{ grid-column: 1 / 3; grid-row: 1 / 3; }
  .g-2{ grid-column: 3 / 5; grid-row: 1 / 2; }
  .g-3{ grid-column: 3 / 4; grid-row: 2 / 3; margin-top: clamp(16px, 3vw, 40px); }
  .g-4{ grid-column: 4 / 5; grid-row: 2 / 3; }
  .g-5{ grid-column: 1 / 3; grid-row: 3 / 4; }
  .g-6{ grid-column: 3 / 5; grid-row: 3 / 4; margin-top: clamp(16px, 3vw, 40px); }
}
@media (max-width: 759px){
  .gallery-grid{ grid-template-columns: 1fr 1fr; grid-auto-rows: minmax(160px, auto); }
  .g-1, .g-5{ grid-column: 1 / 3; aspect-ratio: 16 / 11; }
  .g-2, .g-3, .g-4, .g-6{ aspect-ratio: 3 / 4; }
}

/* ==========================================================================
   FAQ — dark, quiet accordion bridging the light gallery/statement into
   the final CTA. One question open at a time; height is GSAP-driven in
   main.js since the open/closed amount depends on each answer's own
   (variable) content height.
   ========================================================================== */

.faq{
  background: var(--ink);
  color: var(--paper);
  padding: clamp(100px, 13vw, 170px) 0;
}

.faq-inner{ max-width: 860px; }

.faq-head{ margin-bottom: clamp(48px, 7vw, 88px); }
.faq .label{ color: var(--muted-light); }

.faq-list{ display: flex; flex-direction: column; }

.faq-item{ border-bottom: 1px solid var(--line-dark); }
.faq-item:first-child{ border-top: 1px solid var(--line-dark); }

.faq-question{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  width: 100%;
  background: none;
  border: none;
  margin: 0;
  padding: clamp(22px, 3vw, 28px) 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(16.5px, 2vw, 19px);
  letter-spacing: -0.005em;
  color: var(--paper);
  text-align: left;
  cursor: pointer;
}
.faq-question span:first-child{ transition: transform 0.4s var(--ease); }
@media (hover: hover) and (pointer: fine){
  .faq-question:hover span:first-child{ transform: translateX(8px); }
}

.faq-icon{
  position: relative;
  flex-shrink: 0;
  width: 20px; height: 20px;
  transition: transform 0.4s var(--ease);
}
.faq-icon::before, .faq-icon::after{
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  background: var(--paper);
  transform: translate(-50%, -50%);
}
.faq-icon::before{ width: 14px; height: 1px; }
.faq-icon::after{ width: 1px; height: 14px; }
.faq-item.is-open .faq-icon{ transform: rotate(45deg); }

.faq-answer{
  height: 0;
  overflow: hidden;
}
.faq-answer-inner{ max-width: 640px; padding: 0 0 clamp(22px, 3vw, 28px); }
.faq-answer-inner p{
  margin: 0;
  font-size: 15.5px;
  line-height: 1.75;
  color: var(--muted-light);
}

.faq-cta{
  margin: clamp(40px, 6vw, 64px) 0 0;
  font-size: 15px;
  color: var(--muted-light);
}
.faq-cta a{
  color: var(--paper);
  font-weight: 600;
  padding-bottom: 1px;
}

/* ==========================================================================
   ACT 3 — FINALE (full-screen closing hook + CTA)
   ========================================================================== */

.finale{
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: var(--ink);
  padding: clamp(80px, 10vh, 140px) 0;
}

.finale-media{ position: absolute; inset: -8% 0 0 0; height: 116%; overflow: hidden; }
.finale-media img{
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(1.05);
  filter: grayscale(0.2) contrast(1.1) brightness(0.55);
  will-change: transform;
}
@media (max-width: 600px){
  /* source photo is landscape (1800x1300) with the woman positioned
     right-of-center (plank pose, head/shoulders around 80-90% across);
     on a narrow/tall mobile box, cover's horizontal crop is severe and the
     default center anchor (50%) was landing on her hip/midsection instead
     — shift right so her upper body and the movement itself stay in frame. */
  .finale-media img{ object-position: 80% center; }
}
.finale-overlay{
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(17,17,16,0.5) 0%, rgba(17,17,16,0.72) 100%);
}

.finale-inner{
  position: relative;
  z-index: 2;
  color: var(--paper);
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.finale-title{
  font-family: var(--font-display);
  font-weight: 800;
  text-transform: uppercase;
  font-size: clamp(34px, 8.5vw, 100px);
  line-height: 1.08;
  letter-spacing: -0.005em;
  margin: 0 0 26px;
}

.finale-sub{
  font-size: clamp(16px, 1.9vw, 20px);
  color: rgba(238,234,226,0.88);
  margin: 0 0 40px;
  max-width: 480px;
}

.finale-actions{
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 28px;
}

/* ==========================================================================
   FOOTER — minimal, after the finale
   ========================================================================== */

.site-footer-mini{ background: var(--ink); color: var(--paper); padding: 40px 0 28px; }

.footer-mini-inner{
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding-bottom: 24px;
  border-bottom: 1px solid var(--line-dark);
}

.footer-meta{ font-size: 12.5px; color: var(--muted-light); margin: 0; }

.footer-social{ display: flex; gap: 20px; font-size: 13px; font-weight: 500; }

.footer-copy{
  display: block;
  padding-top: 18px;
  font-size: 11.5px;
  color: var(--muted-light);
}

.footer-credit{
  display: block;
  padding-top: 12px;
  font-size: 11.5px;
  color: var(--muted-light);
}
