/* ==========================================================================
   PUTTİKA — white editorial. Black type, wide margins, minimal motion.
   Measurements follow the brief: 1640px container, 3 x ~545px columns,
   card width/inset variation instead of column gaps.
   ========================================================================== */

:root{
  --bg:#ffffff;
  --fg:#000000;
  --muted:#999999;
  --line:#e5e5e5;
  --contour:#e5e5e5;

  /* §4.1: the 1640px is the column area and the ~120px margin sits outside
     it, so the outer box is 1640 + 2*120. That lands each of the three
     columns at ~546px, matching the measured reference. */
  --hero-box-h:clamp(150px,14vw,230px);
  --container:1880px;
  --page-pad:120px;

  --col-count:3;
  --row-gap:220px;
}

*{ box-sizing:border-box; }

html{ background:var(--bg); }

body{
  margin:0;
  background:var(--bg);
  color:var(--fg);
  font-family:'Inter',-apple-system,Segoe UI,Roboto,Arial,sans-serif;
  font-size:15px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}

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

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

.shell{
  width:100%;
  max-width:var(--container);
  margin:0 auto;
  padding:0 var(--page-pad);
}

body.intro-lock{ overflow:hidden; height:100vh; }
body.menu-open,
body.lightbox-open{ overflow:hidden; }

/* ==========================================================================
   1. Loading — outline wordmark fills top-to-bottom, then lifts away
   ========================================================================== */
.intro-overlay{
  position:fixed;
  inset:0;
  z-index:900;
  background:var(--bg);
  display:flex;
  align-items:center;
  justify-content:center;
  padding:0 var(--page-pad);
}
.intro-mark{
  width:100%;
  max-width:var(--container);
  height:auto;
  overflow:visible;
}
.intro-mark text{
  font-family:'Space Grotesk',sans-serif;
  font-weight:700;
  font-size:150px;
  letter-spacing:-0.02em;
}
.intro-outline{
  fill:none;
  stroke:var(--fg);
  stroke-width:1;
  vector-effect:non-scaling-stroke;
}
.intro-solid{ fill:var(--fg); stroke:none; }

/* ==========================================================================
   2. Header — fixed, layered in front of the hero contour
   ========================================================================== */
.site-header{
  position:fixed;
  top:0; left:0; right:0;
  z-index:400;
  display:flex;
  align-items:center;
  gap:2rem;
  padding:34px var(--page-pad);
  overflow:hidden;            /* clips the half-cropped brand trace */
  pointer-events:none;        /* re-enabled per interactive child */
}
.site-header > *{ pointer-events:auto; }

.site-header .logo{
  font-family:'Space Grotesk',sans-serif;
  font-weight:700;
  font-size:17px;
  letter-spacing:0.02em;
  z-index:2;
}

/* Uploaded logo. --logo-height is written inline by the server from the admin
   panel's setting; the value here is only the fallback for a page rendered
   before one was chosen. `display:flex` kills the inline-image baseline gap,
   which would otherwise push the mark a few pixels above the nav it lines up
   with. Width is intentionally unconstrained — the admin sets the height and
   the mark keeps its own proportions, whatever aspect it happens to be. */
.site-header .logo--image{
  display:flex;
  align-items:center;
  line-height:0;
}
.site-header .logo-mark{
  height:var(--logo-height,24px);
  width:auto;
  max-width:min(340px,42vw);   /* a wide mark can never crowd out the nav */
  object-fit:contain;
  display:block;
}

.header-nav{ margin-left:auto; z-index:2; }
.header-nav ul{
  list-style:none;
  display:flex;
  gap:38px;
  margin:0; padding:0;
}
.header-nav a{
  position:relative;
  text-transform:uppercase;
  font-weight:700;
  font-size:14px;
  letter-spacing:0.06em;
}
.header-nav a::after{
  content:'';
  position:absolute; left:0; bottom:-6px;
  width:0; height:1px;
  background:currentColor;
  transition:width .35s ease;
}
.header-nav a:hover::after,
.header-nav a.current::after{ width:100%; }

/* 3x3 dot grid → full-screen menu */
.grid-toggle{
  z-index:2;
  display:grid;
  grid-template-columns:repeat(3,4px);
  gap:4px;
  padding:6px;
  margin:-6px;
  border:0;
  background:none;
  cursor:pointer;
}
.grid-toggle span{
  width:4px; height:4px;
  background:currentColor;
  transition:opacity .3s ease;
}
.grid-toggle:hover span{ opacity:.55; }
.grid-toggle:focus-visible{ outline:2px solid var(--fg); outline-offset:6px; }

/* Full-screen menu */
.full-menu{
  position:fixed;
  inset:0;
  z-index:600;
  background:var(--bg);
  display:flex;
  align-items:center;
  justify-content:center;
  opacity:0;
}
.full-menu[hidden]{ display:none; }
.full-menu ul{
  list-style:none;
  margin:0; padding:0;
  text-align:center;
}
.full-menu li + li{ margin-top:26px; }
.full-menu a{
  font-family:'Space Grotesk',sans-serif;
  font-weight:700;
  font-size:clamp(2.2rem,6vw,4.4rem);
  letter-spacing:-0.02em;
  transition:opacity .3s ease;
}
.full-menu a:hover{ opacity:.4; }
.full-menu-close{
  position:absolute;
  top:30px; right:var(--page-pad);
  font-size:22px;
  background:none;
  border:0;
  cursor:pointer;
  line-height:1;
}

/* ==========================================================================
   3. Hero — giant 1px contour, top of the letters cropped away
   ========================================================================== */
.hero{
  width:100%;
  max-width:var(--container);
  margin:0 auto;
  padding:0 var(--page-pad);
}
.hero-clip{
  overflow:hidden;          /* the crop that eats the top of the letters */
  /* Değişken olarak duruyor çünkü açılış ekranındaki logo da aynı yüksekliği
     kullanmak zorunda: iki yerdeki logo hep aynı boyutta görünmeli. */
  height:var(--hero-box-h);
  display:flex;
  align-items:flex-start;
}
.hero-mark{
  width:100%;
  height:auto;
  transform:translateY(-28%); /* percentage now follows the SVG itself, not container width */
  overflow:visible;
}
/* Yüklenmiş bir hero görseli için -28% geçerli değil: o değer PUTTİKAA
   yazısının harf tepelerini kırpmak için seçilmişti ve her logonun kendi
   dikey dengesi farklı. Bunun yerine panelden ayarlanan --hero-offset-y
   kullanılıyor; ayarlanmamışsa 0, yani logo kutusunda olduğu gibi durur. */
/* Açılış ekranı logo sürümü. Gömülen şekillerin kendi boyası sadeleştirmede
   atıldığı için renk buradaki iki <g>'den miras alınıyor; GSAP de tek bir
   fill/stroke özelliğini animasyonlayarak bütün şekilleri birlikte sürüyor.
   Metin sürümünde aynı işi .intro-outline / .intro-solid kuralları yapıyor. */
.intro-mark--logo .intro-outline{
  fill:none;
  stroke:var(--contour,#c9c9c9);
  stroke-width:1;
  vector-effect:non-scaling-stroke;
}
.intro-mark--logo .intro-solid{
  fill:var(--intro-fill, #3c3c3b);
  stroke:none;
}

/* Açılış logosunun kutusu. Genişliği hero'nunkiyle AYNI tabandan hesaplanıyor
   (kapsayıcı eksi sayfa boşluğu): .intro-overlay zaten yanlardan --page-pad
   kadar boşluklu, burada da kapsayıcı sınırından o boşluk düşülüyor. Böylece
   aynı --hero-width yüzdesi her iki yerde aynı piksel genişliği veriyor. */
.intro-mark-box{
  width:100%;
  max-width:calc(var(--container) - var(--page-pad) * 2);
  display:flex;
  justify-content:center;
  /* Ölçek burada, iç SVG'de değil: GSAP açılış sonunda #introMark'ın kendi
     transform'unu yazıyor (yukarı kaldırıp küçültüyor) ve oraya konan bir
     scale o animasyonla çakışırdı. Sarmalayıcıya konunca ikisi birbirine
     karışmıyor. */
  transform:scale(var(--hero-scale, 1));
}
.intro-mark--logo{
  width:100%;
  max-width:none;
  height:var(--hero-box-h);
}

.hero-mark--image{
  /* Yazı sürümü genişliğe göre ölçekleniyor ve üstü bilerek kırpılıyor.
     Yüklenen logoda amaç farklı: logonun TAMAMI görünmeli ve kutuda ortalı
     durmalı. Bu yüzden SVG kutuyu birebir kaplıyor ve içeriği
     preserveAspectRatio="xMidYMid meet" sığdırıp iki eksende de ortalıyor —
     hangi ekran genişliği olursa olsun. --hero-offset-y artık "tepeden ne
     kadar" değil, "ortadan ne kadar" anlamına geliyor. */
  width:100%;
  height:100%;
  align-self:stretch;
  /* Genişlik neden ölçek olarak uygulanıyor:
     preserveAspectRatio="meet" içeriği BAĞLAYICI kenara göre sığdırıyor. Hero
     kutusu çok geniş ve alçak (ör. 1640x230), logo ise ~4:1 — yani logoyu
     sınırlayan yükseklik. SVG elemanının genişliğini kısmak, genişlik
     bağlayıcı hale gelene kadar (bu kutuda ~%58) logoyu hiç küçültmüyordu.
     Ölçek çarpanı ise her zaman ve doğrusal çalışıyor: %100 = kutuya sığan
     boyut, %50 = onun yarısı.
     Sıra önemli: scale önce uygulanır, translateY sonra — kaydırma miktarı
     ölçekten etkilenmez. */
  transform:translateY(var(--hero-offset-y, 0%)) scale(var(--hero-scale, 1));
}
.hero-mark text{
  font-family:'Space Grotesk',sans-serif;
  font-weight:700;
  font-size:150px;
  letter-spacing:-0.02em;
  fill:none;
  stroke:var(--contour);
  stroke-width:1;
  vector-effect:non-scaling-stroke;
}

/* ==========================================================================
   4. Portfolio — groups of three in normal flow

   Placement is the browser's: there is no layout engine and no absolute
   positioning. Card spacing is structural (group padding + grid gap) and card
   height comes from the database-stored display ratio, so the composition is
   the same on every render.
   ========================================================================== */
:root{
  --edgtf-transition:.45s cubic-bezier(.25,.46,.45,.94);
}

.portfolio{
  width:100%;
  max-width:var(--container);
  margin:0 auto;
  padding:clamp(60px,8vw,130px) var(--page-pad) 0;
}

.portfolio-list-holder{
  position:relative;
  width:100%;
}

/* ==========================================================================
   Portfolio grid — groups of three, normal document flow

   No absolute positioning and no layout engine: each group is its own
   three-track grid and the groups stack in flow. The browser owns placement,
   so two cards can never be laid out on top of each other and there is no
   JS pass that could disagree with the CSS.

   Spacing is structural rather than decorative, and it comes from two
   independent mechanisms that both survive any image height:
     --portfolio-group-gap    grid gap BETWEEN groups
     --group-padding-block    breathing room INSIDE each group, top and bottom
   The visible distance between the last row of one group and the first row of
   the next is therefore gap + two paddings. Neither can collapse.
   ========================================================================== */
.portfolio-grid{
  /* The grid container for the groups themselves — this is what makes the
     between-group `gap` below apply at all; in plain block flow it would be
     ignored. One column, so the groups still stack exactly as before. */
  display:grid;
  grid-template-columns:minmax(0,1fr);
  gap:var(--portfolio-group-gap);

  --portfolio-group-gap:clamp(90px,8vw,140px);
  --portfolio-column-gap:clamp(32px,2.5vw,48px);
  --group-padding-block:70px;
  --group-padding-inline:clamp(24px,3vw,56px);
  /* Shows wherever a zoomed-out image no longer covers its frame. */
  --media-backdrop:#D3D3D3;
  --info-offset:20px;
}

.portfolio-group{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:var(--portfolio-column-gap);
  padding:var(--group-padding-block) var(--group-padding-inline);
  box-sizing:border-box;
  /* Cards of different heights sit on a shared centre line rather than a
     shared top edge, so a short card no longer hangs off the top of its row.
     It also keeps a final group of one or two cards in its own columns
     instead of letting the tracks stretch. */
  align-items:center;
}

/* ---------- The card ----------
   Four nested elements, four transform owners, one each:
     .portfolio-item            reveal      (one-shot, ends at none)
     .portfolio-item__parallax  GSAP scroll settle
     .portfolio-item__motion    group mouse micro-motion
     .portfolio-item__image     crop: zoom + x/y
   Nothing writes to an element it does not own. */
.portfolio-item{
  position:relative;
  margin:0;
  min-width:0;                 /* lets the grid track actually shrink */
  align-self:center;           /* explicit, so it survives a group-level change */
  opacity:0;
  transform:translateY(36px);
  transition:opacity .6s ease,transform .6s ease;
}
.portfolio-item--shown{
  opacity:1;
  transform:none;
}
/* Animation switched off: cards are simply present from the start. */
[data-enable-article-animation="no"] .portfolio-item{
  opacity:1;
  transform:none;
}

.portfolio-item__parallax{ display:block; }

.portfolio-item__motion{
  display:block;
  transform:translate3d(var(--group-motion-x,0),var(--group-motion-y,0),0);
  transition:transform 220ms ease-out;
  will-change:transform;
}

.portfolio-item__trigger{
  display:block;
  width:100%;
  padding:0;
  border:0;
  background:none;
  cursor:pointer;
  font:inherit;
  color:inherit;
}
.portfolio-item__trigger:focus-visible{ outline:2px solid var(--fg); outline-offset:4px; }

/* The frame. aspect-ratio comes from the database, so the box is reserved
   before a single byte of the image arrives — no layout shift on load. */
.portfolio-item__media{
  position:relative;
  width:100%;
  aspect-ratio:var(--display-ratio,1 / 1);
  overflow:hidden;
  background-color:var(--media-backdrop);
}

/* Crop lives here and only here.

   object-fit:cover is the BASE fit, not the crop mechanism: at zoom 1 it
   makes the image fill its frame, which is what keeps every existing image
   looking right without per-image setup. The transform is what actually
   crops. Below zoom 1 the scaled image no longer covers the frame and
   --media-backdrop shows through — that is the intended zoom-out behaviour,
   which is exactly why cover is not relied on alone.

   --position-x/y are percentages of the media box, so a saved offset means
   the same thing at every viewport width. */
.portfolio-item__image{
  position:absolute;
  left:50%;
  top:50%;
  width:100%;
  height:100%;
  object-fit:cover;
  transform:
    translate(-50%,-50%)
    translate(var(--position-x,0%),var(--position-y,0%))
    scale(var(--zoom,1));
  transform-origin:center;
}

/* ---------- Info box ----------
   A sibling of the transform wrappers, never a child: it must not inherit the
   parallax or the mouse motion, or the text would drift under the cursor. */
.portfolio-item__info{
  position:absolute;
  left:var(--info-offset);
  bottom:var(--info-offset);
  z-index:3;
  display:flex;
  flex-direction:column;
  gap:4px;
  padding:12px 16px;
  background:rgba(255,255,255,.92);
  opacity:0;
  transform:translateY(12px);
  transition:
    opacity 280ms ease,
    transform 360ms cubic-bezier(.2,.8,.2,1);
  pointer-events:none;
}
/* :focus-within is not a nicety here — the trigger is a real button, and
   without this the company and category would be hover-only, which §14
   forbids. */
.portfolio-item:hover .portfolio-item__info,
.portfolio-item:focus-within .portfolio-item__info{
  opacity:1;
  transform:translateY(0);
}
.portfolio-item__company{
  text-transform:uppercase;
  font-weight:700;
  font-size:14px;
  letter-spacing:.5px;
  line-height:1.25;
  color:var(--fg);
}
.portfolio-item__category{
  text-transform:uppercase;
  letter-spacing:1.5px;
  font-size:11px;
  color:var(--muted);
}

.empty-note{
  padding:3rem 0;
  color:var(--muted);
}
.empty-note a{ text-decoration:underline; }

/* 4.9 — bouncing-dot loader, shown only while a page is in flight */
.edgtf-pl-loading{
  display:none;
  justify-content:center;
  gap:8px;
  margin:60px 0 0;
}
.edgtf-pl-loading.edgtf-pl-loading-active{ display:flex; }
.edgtf-pl-loading > div{
  width:8px; height:8px;
  border-radius:50%;
  background:var(--fg);
  animation:edgtf-bounce 1.2s infinite ease-in-out both;
}
/* Child selectors, not bare classes: the `animation` shorthand above resets
   animation-delay, and at (0,1,1) it would outrank a (0,1,0) class rule —
   the three dots would then bounce in unison instead of chasing. */
.edgtf-pl-loading > .edgtf-pl-loading-bounce1{ animation-delay:-.28s; }
.edgtf-pl-loading > .edgtf-pl-loading-bounce2{ animation-delay:-.14s; }
@keyframes edgtf-bounce{
  0%,80%,100%{ transform:scale(0); opacity:.35; }
  40%{ transform:scale(1); opacity:1; }
}

/* 4.9 — "Daha Fazla": 112px ring, 1px stroke, transparent fill */
.edgtf-pl-load-more-holder{
  display:flex;
  justify-content:center;
  margin-top:200px;
}
.edgtf-pl-load-more-holder[hidden]{ display:none; }
.edgtf-pl-load-more{
  position:relative;
  padding:0;
  border:0;
  background:none;
  border-radius:50%;
  cursor:pointer;
}
.edgtf-pl-load-more-outer{
  position:relative;
  display:grid;
  place-items:center;
  width:112px; height:112px;
}
.edgtf-theme-svg{
  position:absolute;
  inset:0;
  width:112px; height:112px;
  overflow:visible;
}
.edgtf-theme-svg circle{
  fill:none;
  stroke:var(--fg);
  stroke-width:1;
  vector-effect:non-scaling-stroke;
  transform:rotate(-90deg);          /* start drawing from the top */
  transform-origin:center;
}
/* Loading state: the ring keeps its drawn length but spins. */
.edgtf-pl-load-more.edgtf-pl-load-more-loading .edgtf-theme-svg circle{
  animation:edgtf-ring-spin 1s linear infinite;
}
@keyframes edgtf-ring-spin{
  from{ transform:rotate(-90deg); }
  to{ transform:rotate(270deg); }
}
.edgtf-pl-load-more-inner{
  position:relative;
  z-index:2;
  text-transform:uppercase;
  font-weight:700;
  font-size:13px;
  letter-spacing:1px;
  text-align:center;
}
.edgtf-pl-load-more:disabled{ cursor:default; }
.edgtf-pl-load-more.edgtf-pl-load-more-disabled{ opacity:.3; pointer-events:none; }
.edgtf-pl-load-more:focus-visible{ outline:2px solid var(--fg); outline-offset:6px; }

/* ==========================================================================
   5. Custom cursor
   ========================================================================== */
.cursor{
  position:fixed;
  top:0; left:0;
  /* Above every overlay on the site — the full menu (600), the lightbox (800)
     and the intro (900). The native cursor is hidden site-wide, so anything
     that paints over this dot leaves the visitor with no pointer at all; the
     lightbox did exactly that. It is pointer-events:none, so sitting on top
     costs nothing — it cannot intercept a click from what is underneath. */
  z-index:1000;
  width:14px; height:14px;
  margin:-7px 0 0 -7px;
  border-radius:50%;
  background:var(--fg);
  pointer-events:none;
  opacity:0;
  display:grid;
  place-items:center;
  transition:width .3s ease,height .3s ease,margin .3s ease;
}
.cursor.is-active{ opacity:1; }
.cursor.is-large{
  width:46px; height:46px;
  margin:-23px 0 0 -23px;
}
.cursor-icon{
  width:16px; height:16px;
  color:#fff;
  opacity:0;
  transition:opacity .25s ease;
}
.cursor.is-large .cursor-icon{ opacity:1; }

/* ---------- Lightbox ----------
   The ring is pinned open here rather than left to the card hover that set
   it. The card is covered the instant the lightbox appears, so its mouseout
   never fires and `is-large` would be whatever it happened to be on the way
   in — stating it here is what makes the ring reliable.
   The extra `.cursor` in the icon rule is load-bearing: `.cursor.is-large
   .cursor-icon` above is three classes, so this has to match it and add an
   element to win when `is-large` is absent. */
body.lightbox-open .cursor{
  width:46px; height:46px;
  margin:-23px 0 0 -23px;
}
body.lightbox-open .cursor .cursor-icon{ opacity:1; }

/* ==========================================================================
   6. Right-edge social rail — slight zigzag, not a straight column
   ========================================================================== */
.social-rail{
  position:fixed;
  right:44px;
  top:58%;
  z-index:350;
  list-style:none;
  margin:0; padding:0;
  display:flex;
  flex-direction:column;
  gap:30px;
  opacity:0;
  pointer-events:none;
  transition:opacity .5s ease;
}
.social-rail.is-visible{ opacity:1; pointer-events:auto; }
.social-rail li:nth-child(2){ margin-right:25px; }
.social-rail li:nth-child(3){ margin-right:25px; }
.social-rail a{
  display:block;
  color:var(--fg);
  opacity:.75;
  transition:opacity .3s ease;
}
.social-rail a:hover{ opacity:1; }
.social-rail svg{ width:16px; height:16px; }

/* ==========================================================================
   7. "Yukarı Çık" — rotated, fixed to the lower right
   ========================================================================== */
.to-top{
  position:fixed;
  right:40px;
  bottom:70px;
  z-index:350;
  writing-mode:vertical-rl;
  text-orientation:mixed;
  transform:rotate(180deg);
  background:none;
  border:0;
  cursor:pointer;
  text-transform:uppercase;
  font-weight:700;
  font-size:12px;
  letter-spacing:0.12em;
  padding:6px 2px;
  opacity:0;
  pointer-events:none;
  transition:opacity .5s ease;
}
.to-top.is-visible{ opacity:1; pointer-events:auto; }
.to-top:focus-visible{ outline:2px solid var(--fg); outline-offset:4px; }

/* ==========================================================================
   7. Footer — content sits inside a huge SVG arc whose bottom is cropped
   ========================================================================== */
.site-footer{
  position:relative;
  margin-top:180px;            /* arc apex clears the More button */
  padding-bottom:90px;
  overflow:hidden;             /* crops the lower half of the circle */
  color:var(--fg);
}
.footer-arc{
  position:absolute;
  top:0;
  left:50%;
  transform:translateX(-50%);
  width:780px;
  height:390px;
  color:var(--fg);
  pointer-events:none;
}
.footer-inner{
  position:relative;
  z-index:1;
  display:flex;
  flex-direction:column;
  align-items:center;
  text-align:center;
  padding-top:118px;           /* drops the content into the arc */
}
.footer-nav{
  display:flex;
  gap:40px;
}
.footer-nav a{
  text-transform:uppercase;
  font-weight:700;
  font-size:14px;
  letter-spacing:0.06em;
  transition:opacity .3s ease;
}
.footer-nav a:hover{ opacity:.5; }
.footer-rule{
  display:block;
  width:245px;
  height:1px;
  background:var(--line);
  margin:34px 0 28px;
}
.footer-line{
  margin:0;
  font-size:15px;
  font-weight:400;
  color:var(--muted);
}
.footer-line + .footer-line{ margin-top:6px; }

/* ==========================================================================
   4.10 Lightbox
   ========================================================================== */
.lightbox{
  position:fixed;
  inset:0;
  z-index:800;
  background:rgba(255,255,255,.97);
  display:flex;
  align-items:center;
  justify-content:center;
  /* The chrome around the picture, declared once. The strip height is PINNED
     to this value (see .lightbox__thumbnails) rather than merely describing
     it, so the horizontal scrollbar cannot silently make the real strip
     taller than the number the image sizes itself against.
     14px padding x2 + 64px thumbnail + ~10px scrollbar. */
  --thumbnail-strip-height:102px;
  --lightbox-pad-top:6vh;
  --lightbox-pad-bottom:36px;
  --lightbox-caption-space:44px;   /* caption line + the stage's 16px gap */
  padding:var(--lightbox-pad-top) 8vw calc(var(--thumbnail-strip-height) + var(--lightbox-pad-bottom));
  opacity:0;
}
.lightbox[hidden]{ display:none; }
.lightbox.is-open{ opacity:1; }
.lightbox__stage{
  margin:0;
  max-width:100%;
  min-height:0;                /* lets the flex child actually shrink */
  flex:1 1 auto;
  display:flex;
  flex-direction:column;       /* column so the caption sits under the image */
  align-items:center;
  justify-content:center;
  gap:16px;
  overflow:hidden;
}

/* The lightbox image is intentionally NOT the grid image.

   It sizes itself from its own intrinsic proportions — width/height auto,
   capped by max-width/max-height — rather than being stretched to a box and
   fitted. Nothing from the grid's presentation reaches here: no display
   ratio, no crop zoom, no crop x/y, no object-position, no transform. The
   `transform:none` is a hard guarantee rather than a default, so a crop value
   can never leak in through an inherited custom property.

   width/height:100% and object-fit:cover are deliberately absent: with them
   the element would take the shape of its container and the file's own
   proportions would stop being what decides the picture. */
.lightbox__image{
  display:block;
  width:auto;
  height:auto;
  max-width:100%;
  /* Everything the picture is NOT allowed to occupy: the top padding, the
     strip and its clearance, and the caption. Subtracting only the strip
     would let the image run underneath it. */
  max-height:calc(
    100vh
    - var(--lightbox-pad-top)
    - var(--thumbnail-strip-height)
    - var(--lightbox-pad-bottom)
    - var(--lightbox-caption-space)
  );
  object-fit:contain;
  object-position:center;
  transform:none !important;
}
.lightbox__stage figcaption{
  flex:0 0 auto;
  font-size:13px;
  color:var(--muted);
  text-align:center;
}

/* ---------- Thumbnail strip ----------
   Every published image, in grid order. Built once from the manifest, so
   navigating only moves .is-active — the strip keeps its scroll position and
   no thumbnail is ever re-fetched. */
.lightbox__thumbnails{
  position:absolute;
  left:0; right:0; bottom:0;
  /* Pinned, so --thumbnail-strip-height is the truth rather than an estimate
     the scrollbar can invalidate. */
  height:var(--thumbnail-strip-height);
  box-sizing:border-box;
  display:flex;
  align-items:center;
  gap:8px;
  padding:14px 3vw;
  overflow-x:auto;
  overscroll-behavior-x:contain;
  scrollbar-width:thin;
  background:rgba(255,255,255,.9);
}
.lightbox__thumb{
  flex:0 0 auto;
  width:64px;
  height:64px;
  padding:0;
  border:0;
  background:none;
  cursor:pointer;
  opacity:.45;
  transition:opacity .25s ease,outline-color .25s ease;
  outline:2px solid transparent;
  outline-offset:2px;
}
.lightbox__thumb img{
  width:100%; height:100%;
  object-fit:cover;
  display:block;
}
.lightbox__thumb:hover{ opacity:.8; }
.lightbox__thumb.is-active{
  opacity:1;
  outline-color:var(--fg);
}
.lightbox-nav,
.lightbox-close{
  position:absolute;
  background:none;
  border:0;
  cursor:pointer;
  font-size:24px;
  line-height:1;
  padding:12px;
}
.lightbox-nav.prev{ left:3vw; top:50%; transform:translateY(-50%); }
.lightbox-nav.next{ right:3vw; top:50%; transform:translateY(-50%); }
.lightbox-close{ top:26px; right:3vw; font-size:20px; }
.lightbox-nav:disabled{ opacity:.2; cursor:default; }
.lightbox button:focus-visible{ outline:2px solid var(--fg); outline-offset:4px; }

/* ==========================================================================
   Secondary pages (about / contact)
   ========================================================================== */
.page{
  width:100%;
  max-width:var(--container);
  margin:0 auto;
  padding:220px var(--page-pad) 0;
}
.page-eyebrow{
  text-transform:uppercase;
  font-weight:700;
  font-size:13px;
  letter-spacing:1px;
  color:var(--muted);
  margin:0 0 28px;
}
.page-lead{
  font-family:'Space Grotesk',sans-serif;
  font-weight:700;
  font-size:clamp(1.8rem,3.4vw,3.1rem);
  line-height:1.22;
  letter-spacing:-0.02em;
  max-width:20ch;
  margin:0 0 120px;
}
.page-section{ margin-bottom:120px; }
.page-section h2{
  font-family:'Space Grotesk',sans-serif;
  font-weight:700;
  font-size:22px;
  letter-spacing:-0.01em;
  margin:0 0 34px;
  padding-bottom:18px;
  border-bottom:1px solid var(--line);
}
.disciplines{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:80px;
}
.discipline h3{
  text-transform:uppercase;
  font-size:13px;
  font-weight:700;
  letter-spacing:1px;
  margin:0 0 14px;
}
.discipline p{ margin:0; color:#444; max-width:44ch; }

.team{ list-style:none; margin:0; padding:0; }
.team li{
  display:flex;
  flex-wrap:wrap;
  gap:12px 40px;
  align-items:baseline;
  padding:22px 0;
  border-bottom:1px solid var(--line);
}
.team-name{ font-weight:700; font-size:16px; min-width:16ch; }
.team-role{ color:var(--muted); font-size:14px; }

.contact-grid{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:100px;
}
.contact-item{ margin-bottom:44px; }
.contact-item span{
  display:block;
  text-transform:uppercase;
  font-size:12px;
  font-weight:700;
  letter-spacing:1px;
  color:var(--muted);
  margin-bottom:8px;
}
.contact-item a{
  font-family:'Space Grotesk',sans-serif;
  font-weight:700;
  font-size:clamp(1.1rem,1.9vw,1.5rem);
  letter-spacing:-0.01em;
}
.contact-item a:hover{ opacity:.55; }

.contact-form{ display:grid; gap:22px; }
.contact-form label{
  display:block;
  text-transform:uppercase;
  font-size:12px;
  font-weight:700;
  letter-spacing:1px;
  color:var(--muted);
  margin-bottom:8px;
}
.contact-form input,
.contact-form textarea{
  width:100%;
  font:inherit;
  color:var(--fg);
  background:none;
  border:0;
  border-bottom:1px solid var(--line);
  padding:10px 0;
  border-radius:0;
}
.contact-form input:focus,
.contact-form textarea:focus{
  outline:none;
  border-bottom-color:var(--fg);
}
.contact-form textarea{ resize:vertical; min-height:120px; }
.contact-form button{
  justify-self:start;
  text-transform:uppercase;
  font-weight:700;
  font-size:13px;
  letter-spacing:1px;
  padding:16px 40px;
  border:1px solid var(--fg);
  background:none;
  border-radius:999px;
  cursor:pointer;
  transition:background .3s ease,color .3s ease;
}
.contact-form button:hover{ background:var(--fg); color:#fff; }
.contact-form button:disabled{ opacity:.45; cursor:default; }
.form-msg{ font-size:14px; min-height:1.2em; }
.form-msg.error{ color:#c0392b; }
.form-msg.success{ color:#1b7a3d; }

/* Honeypot. Taken out of the flow rather than display:none — some bots skip
   fields that are explicitly hidden, and .contact-form is a grid, so an
   absolutely positioned child costs no row and no gap. */
.hp-field{
  position:absolute;
  left:-9999px;
  width:1px;
  height:1px;
  overflow:hidden;
}

/* ==========================================================================
   Hakkımızda — 2400x650 slider + five-column text block

   The header is fixed and transparent, so the page owns the offset that keeps
   the wordmark from sitting on top of the first slide.
   ========================================================================== */
:root{
  --header-height:92px;
}

.about-page{ padding-top:var(--header-height); }

/* ---------- 2. Slider ----------
   Full-bleed on purpose: it is NOT limited by --container, unlike every other
   block on the site. The ratio is held by aspect-ratio rather than a fixed
   height, so it shrinks with the viewport and keeps its shape everywhere. */
.about-slider{
  position:relative;
  width:100%;
  aspect-ratio:2400 / 650;
  overflow:hidden;
  /* Shows wherever a zoomed-out image no longer covers the frame — the same
     value the portfolio media box uses. */
  background-color:#D3D3D3;
}
.about-slider__track{
  position:absolute;
  inset:0;
}

/* Slides are stacked, not laid side by side: the transition is a crossfade, so
   only opacity moves and nothing can be scrolled half-way between two images. */
.about-slider__slide{
  position:absolute;
  inset:0;
  opacity:0;
  transition:opacity .9s ease;
  pointer-events:none;
}
.about-slider__slide.is-active{
  opacity:1;
  pointer-events:auto;
}

/* Same crop construction as the portfolio card: cover is the base fit and the
   transform is the crop, so the admin's kadraj preview and the live slider are
   the same geometry rather than two approximations of it. */
.about-slider__image{
  position:absolute;
  left:50%;
  top:50%;
  width:100%;
  height:100%;
  max-width:none;
  object-fit:cover;
  transform:
    translate(-50%,-50%)
    translate(var(--position-x,0%),var(--position-y,0%))
    scale(var(--zoom,1));
  transform-origin:center;
}

.about-slider__dots{
  position:absolute;
  left:50%;
  bottom:clamp(14px,2vw,28px);
  transform:translateX(-50%);
  z-index:2;
  display:flex;
  gap:10px;
}
.about-slider__dot{
  width:8px;
  height:8px;
  padding:0;
  border:1px solid #fff;
  border-radius:50%;
  background:none;
  cursor:pointer;
  opacity:.75;
  transition:background .3s ease,opacity .3s ease;
}
.about-slider__dot.is-active{ background:#fff; opacity:1; }
.about-slider__dot:focus-visible{ outline:2px solid #fff; outline-offset:3px; }

/* ---------- 3. Text ---------- */
.about-content{
  display:grid;
  grid-template-columns:repeat(5,minmax(0,1fr));
  width:100%;
  max-width:var(--container);
  margin:0 auto;
  padding:clamp(70px,7vw,140px) var(--page-pad) 0;
}

/* First and last column stay empty; the text spans the middle three. */
.about-content__inner{
  grid-column:2 / 5;
  text-align:left;
}

/* Blocks keep their own line breaks: the second paragraph of the default copy
   is three lines by intent, and collapsing them would lose the Brand/Health
   split the sentence is built around. */
.about-content__lead,
.about-content__body{
  margin:0;
  white-space:pre-line;
}

.about-content__lead{
  font-weight:700;
  font-size:clamp(1.05rem,1.5vw,1.35rem);
  line-height:1.5;
  letter-spacing:-0.01em;
}

.about-content__body{
  font-weight:400;
  font-size:clamp(0.95rem,1.05vw,1.05rem);
  line-height:1.8;
  color:#333;
}

.about-content__lead + .about-content__body{ margin-top:38px; }
.about-content__body + .about-content__body{ margin-top:28px; }

/* ==========================================================================
   4.12 Responsive
   ========================================================================== */
@media (max-width:1439px){
  :root{ --page-pad:72px; }
}

/* Tablet — 2 columns, insets pulled in */
@media (max-width:1199px){
  :root{
    --page-pad:56px;
    --col-count:2;
    --row-gap:150px;
  }
  /* Below desktop the spacing revision does not apply — these restore the
     values that were in place before it, so tablet and mobile are untouched. */
  .portfolio-grid{
    --portfolio-group-gap:0px;
    --portfolio-column-gap:18px;
    --group-padding-block:52px;
    --group-padding-inline:18px;
  }

  /* Two columns, and the groups stop being boxes to do it.
     The DOM is chunked into threes for the desktop row. Laid out as groups in
     two columns, each three-card group breaks 2 + 1 and leaves a hole beside
     every third card — the grouping showing through as a gap, which is exactly
     what §12 says not to do. `display:contents` drops the group's own box so
     all cards flow into one continuous two-column grid and the DOM's threes
     stop being visible at all.

     What the group box was carrying moves up to the grid:
       padding-inline  the cards' inset from the page edge
       row-gap         previously 52px of group padding at each end, so twice
                       that between rows — the same vertical rhythm as before,
                       now applied evenly rather than only between groups
     align-items:center is not carried over: .portfolio-item{align-self:start}
     below already sets the alignment these cards need. */
  .portfolio-grid{
    grid-template-columns:repeat(2,minmax(0,1fr));
    column-gap:var(--portfolio-column-gap);
    row-gap:calc(var(--group-padding-block) * 2);
    padding-inline:var(--group-padding-inline);
  }
  .portfolio-group{ display:contents; }
  /* align-self on the item beats align-items on the group, so top alignment
     has to be restored here rather than on .portfolio-group. */
  .portfolio-item{ align-self:start; }
  .edgtf-pl-load-more-holder{ margin-top:150px; }
  .site-footer{ margin-top:140px; }
  .disciplines,
  .contact-grid{ grid-template-columns:minmax(0,1fr); gap:56px; }

  /* §6 tablet: eight tracks, text across 2/8 — the outer margins narrow so the
     measure stays readable as the viewport loses width. The slider keeps its
     ratio and its full-bleed width. */
  .about-content{ grid-template-columns:repeat(8,minmax(0,1fr)); }
  .about-content__inner{ grid-column:2 / 8; }
}

/* Mobile — single column, no offsets, no inset, no parallax/cursor */
@media (max-width:767px){
  :root{
    --page-pad:20px;
    --col-count:1;
    --row-gap:64px;
  }
  body{ cursor:auto; }

  .site-header{ padding:20px var(--page-pad); }
  /* The admin sets one height for a 34px-padded desktop header; this caps it
     so a generous choice cannot inflate the mobile bar. Never scales UP — a
     logo smaller than the cap keeps the size that was chosen. */
  .site-header .logo-mark{ height:min(var(--logo-height,24px),34px); }
  .header-nav{ display:none; }
  .grid-toggle{ margin-left:auto; }

  :root{ --hero-box-h:82px; }
  .portfolio{ padding-top:44px; }

  /* One card per row. The groups are already boxless from the tablet rule
     above, so this only has to narrow the grid to a single track — dropping
     back to a per-group layout here would reintroduce exactly the uneven
     rhythm that rule removes. The row gap is the full --row-gap, which is what
     the two 32px group paddings used to add up to. */
  .portfolio-grid{
    --group-padding-inline:0px;
    grid-template-columns:minmax(0,1fr);
    row-gap:var(--row-gap);
  }

  /* Both mouse-driven effects are off here (§12): the group motion is never
     bound on a coarse pointer, and the parallax is skipped below 768px. The
     resets are belt-and-braces for a device that reports a fine pointer at a
     phone width. */
  .portfolio-item__motion,
  .portfolio-item__parallax{ transform:none !important; }

  /* There is no hover on touch, so the info box must not depend on one. It
     sits under the image, permanently readable — two-tap-to-open is exactly
     the pattern §8 tells us to avoid. */
  .portfolio-item__info{
    position:static;
    opacity:1;
    transform:none;
    padding:12px 0 0;
    background:none;
    pointer-events:auto;
  }

  .cursor,
  .social-rail,
  .to-top{ display:none; }

  .edgtf-pl-load-more-holder{ margin-top:80px; }
  .site-footer{ margin-top:90px; padding-bottom:60px; }
  .footer-arc{ width:520px; height:260px; }
  .footer-inner{ padding-top:74px; }
  .footer-nav{ gap:24px; }
  .footer-nav a{ font-size:12px; }
  .footer-rule{ width:180px; margin:26px 0 22px; }
  .footer-line{ font-size:14px; }

  /* §6 mobile: the grid is dropped entirely and the inner block carries its
     own 20px inset. The section's own --page-pad is zeroed so the two do not
     stack into a 40px gutter. */
  :root{ --header-height:64px; }
  .about-content{
    display:block;
    padding-inline:0;
  }
  .about-content__inner{ padding-inline:20px; }

  .page{ padding-top:130px; }
  .page-lead{ margin-bottom:70px; }
  .page-section{ margin-bottom:70px; }
  .team li{ gap:4px; flex-direction:column; }

  .lightbox{
    /* 10px x2 + 52px thumbnail + ~10px scrollbar */
    --thumbnail-strip-height:82px;
    --lightbox-pad-top:8vh;
    --lightbox-pad-bottom:32px;
    padding:var(--lightbox-pad-top) 5vw calc(var(--thumbnail-strip-height) + var(--lightbox-pad-bottom));
  }
  .lightbox-nav.prev{ left:4px; }
  .lightbox-nav.next{ right:4px; }
  .lightbox__thumbnails{ padding:10px 12px; gap:6px; }
  .lightbox__thumb{ width:52px; height:52px; }
}

/* Pointer-capable, non-touch only: hide the native cursor for the custom one */
@media (hover:hover) and (pointer:fine) and (min-width:768px){
  /* One policy, stated once: on this site the native cursor does not exist,
     because the dot replaces it. `!important` is the mechanism rather than a
     shortcut — every interactive element declares its own `cursor:pointer` on
     a CLASS (.portfolio-item__trigger, .grid-toggle, .full-menu-close,
     .edgtf-pl-load-more, the lightbox chrome…), and a class outranks any plain
     selector this rule could use. Without it, each of those quietly puts the
     Windows hand back on top of the dot, and every new one added later would
     do the same. */
  html,
  body,
  body *{ cursor:none !important; }

  /* The single exception. A text field's I-beam is not decoration: it shows
     where the caret will land and how far the field runs. The dot still draws
     over it, so the visitor gets both — which is right for typing. */
  body input,
  body textarea,
  body [contenteditable]{ cursor:auto !important; }
}

/* ==========================================================================
   4.13 Reduced motion — reveal, parallax and the ring draw are all skipped
   ========================================================================== */
@media (prefers-reduced-motion:reduce){
  *,
  *::before,
  *::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
    scroll-behavior:auto !important;
  }
  /* Reveal, parallax and group motion are all skipped — cards render in
     their end state. The crop transform on __image is deliberately NOT reset:
     it is framing, not motion, and clearing it would show the wrong part of
     every photograph. */
  .portfolio-item{ opacity:1 !important; transform:none !important; }
  .portfolio-item__parallax,
  .portfolio-item__motion{ transform:none !important; }
  .portfolio-item__info{ transform:none !important; }
  .cursor{ display:none; }
}
