:root {
  color-scheme: dark;
  --signal-orange: #f0591f;
  --orange-deep: #d14613;
  /* The accent set as text on paper. --signal-orange is a surface colour: as
     ink it measures 3.19:1 on --paper-bright and 2.97:1 on --paper, and
     --orange-deep only reaches 4.27:1 and 3.98:1, so both fail AA for normal
     text. Every orange word on a light ground uses this token instead:
     4.96:1 on --paper-bright, 4.62:1 on --paper. It is not a fourth brand
     colour - it is the one value at which the brand orange can be read.
     On graphite the accent is already legible, so that side keeps
     --signal-orange-invert at 6.43:1. */
  --orange-ink: #c03f0e;
  --orange-line: #fbd7c5;
  --orange-soft: #fff1ea;
  --ink: #27140e;
  --header-height: 52px;

  /* Sahne jetonları: kağıt tarafı ve grafit tarafı. Küre paleti earth.js
     içindeki tek PALETTE nesnesinden gelir; burada yalnız DOM katmanı var.

     --graphite, earth.js içindeki PALETTE.graphite.globe ile aynı değerdir.
     Sahne kararınca ekranı kaplayan yüzey kürenin kendisidir; onu izleyen
     grafit bant da aynı zeminden devam etmeli. İkisi ayrışırsa sahnenin
     bittiği yerde görünür bir yüzey kesiği oluşur. Biri değişirse diğeri de
     değişir. --graphite-deep, bandın içine gömülü hücreler içindir.

     Kağıt tarafı saf beyaz değil: sarıya çalan, gri kırıklı bir kağıt.
     Grafit tarafı da saf siyah değil: kahverengiye çalan koyu bir zemin.
     İkisi de aynı sıcak eksende durur, böylece geçiş renk atlamadan olur. */
  --paper: #f2efe7;
  --paper-bright: #faf7f0;
  --graphite: #251e17;
  --graphite-deep: #1a1510;
  /* Küre kadrajı doldurduğunda sahnenin alt kenarında kalan ton. Ölçülen
     değer; grafit bandın tepesi buradan başlar. */
  --graphite-rise: #231c16;
  --graphite-line: rgba(255, 255, 255, 0.16);
  /* Grafit zemin üzerindeki turuncu. earth.js içindeki
     PALETTE.graphite.focusLine ile aynı değerdir: atlas görünümünde tuvale
     çizilen omurga ile DOM katmanındaki rakam aynı turuncuyu taşımalı. */
  --signal-orange-invert: #ff7c42;
  /* The card stack is a ramp, not three dark panels: it opens on the same
     paper as the section heading above it and darkens one card at a time into
     the graphite the field band carries. Each card names its own ink next to
     its surface, so the paper card is authored as a paper card rather than as
     a dark card with light values patched over it. */
  --service-voice: var(--paper-bright);
  --service-messaging: #68554d;
  --service-connectivity: #251e17;
  /* The display family has a single axis (wght). It carries no "opsz" or
     "wdth" axis, so narrowing and optical correction are done with
     letter-spacing instead of variation settings. */
  --font-display: "Inter Tight", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-ui: "Space Grotesk", sans-serif;
  --font-body: "Helvetica Neue", Helvetica, Arial, sans-serif;
  /* Device material scale, verbatim from docs/prompts/illustration-style-card.md.
     A drawing that reads as hardware needs a tonal ladder, not one ink: a
     housing face one step lighter than its side, a recess one step darker
     than the panel around it. */
  --device-recess: #221d19;
  --device-body: #4a443e;
  --device-face: #7d746a;
  --device-plate: #d8d2c6;
  /* Measured against --paper, not against white. At #77716b the pair reached
     4.19:1, which reads as grey but fails AA for normal text; the page carries
     it on every supporting line, so one token was under the bar in a dozen
     places at once. #706a64 is the same grey one step down and clears both
     paper tones: 4.64:1 on --paper, 4.99:1 on --paper-bright. */
  --muted: #706a64;
  --muted-invert: #a79d92;
  --line: #d8d3cc;
  --line-strong: #bbb4ac;
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

@font-face {
  font-family: "Nunito";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/Nunito-Bold.ttf") format("truetype");
}

@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("../fonts/InterTight-latin-ext.woff2") format("woff2");
  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;
}

@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("../fonts/InterTight-latin.woff2") format("woff2");
  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+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 500 600;
  font-display: swap;
  src: url("../fonts/SpaceGrotesk-latin-ext.woff2") format("woff2");
  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;
}

@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 500 600;
  font-display: swap;
  src: url("../fonts/SpaceGrotesk-latin.woff2") format("woff2");
  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+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

* {
  box-sizing: border-box;
}

html,
body {
  min-height: 100%;
  margin: 0;
}

html {
  scroll-behavior: smooth;
}

body {
  overflow-x: hidden;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
}

canvas {
  display: block;
}

a {
  color: inherit;
}

h1,
h2,
h3 {
  font-family: var(--font-display);
  /* A display line breaks where the box ends, not where the sentence does, so
     a heading regularly left one or two words alone on its last line. Balance
     evens the lines instead. Turkish words are long, which makes an unbalanced
     rag worse here than it would be in English. Chrome applies this only to
     short blocks, so long headings keep the normal algorithm. */
  text-wrap: balance;
}

p {
  /* Widow and orphan control for reading text. Costs nothing where it is not
     supported, so it needs no fallback. */
  text-wrap: pretty;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  /* Turkish glyphs can exceed tight display line boxes. This inner safe area
     keeps accents and descenders intact inside reveal masks and clipped scenes. */
  padding-block: 0.12em;
}

.stage__evidence h2,
.clients__statement h2,
.service-stack__intro h2,
.service-card__heading h3 {
  font-weight: 560;
  letter-spacing: -0.018em;
}

/* What the opening act holds back until it is ready to show it.

   The last three are not animated by the entrance; they are held because the
   scroll scene is the only thing that takes them out of the first view, so a
   cold paint would show them under the title for a moment and then lose them.
   The stage curtain covered that with a window-wide backdrop blur until
   2026-08-03. This is the same cover for no compositing cost, and the head
   script's failsafe takes it off whatever happens. */
html.is-opening .site-header,
html.is-opening [data-earth-canvas],
html.is-opening [data-stage-title-rise],
html.is-opening .stage__claims,
html.is-opening [data-stage-evidence],
html.is-opening [data-stage-uptime],
html.is-opening .stage__focus {
  visibility: hidden;
}

/* The route back to the top. Fixed chrome, so it is authored hidden and
   non-focusable: the scene below reveals it once the reader is a screen down,
   and a page with no script keeps a header instead. The arrow is the page's
   own, turned a quarter turn - the independent rotate property, so the
   reveal tween can travel the button without undoing it. */
.to-top {
  position: fixed;
  z-index: 45;
  right: clamp(14px, 1.6vw, 26px);
  bottom: clamp(14px, 1.6vw, 26px);
  display: flex;
  width: 46px;
  height: 46px;
  align-items: center;
  justify-content: center;
  padding: 0;
  color: var(--paper-bright);
  background: var(--graphite);
  border: 1px solid rgba(250, 247, 240, 0.34);
  opacity: 0;
  visibility: hidden;
  cursor: pointer;
  transition:
    color 240ms ease,
    background-color 240ms ease,
    border-color 240ms ease;
}

.to-top:hover,
.to-top:focus-visible {
  color: var(--ink);
  background: var(--signal-orange);
  border-color: var(--signal-orange);
}

.to-top svg {
  width: 18px;
  height: auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  rotate: -90deg;
}

/* The repeated-drawing definitions. Hidden on the root element only: the
   <defs> children keep their own display, so every <use> instance still
   renders. */
.sprite {
  display: none;
}

.skip-link {
  position: fixed;
  z-index: 100;
  top: 0;
  left: 0;
  padding: 12px 16px;
  color: var(--ink);
  background: var(--paper-bright);
  transform: translateY(-110%);
  transition: transform 180ms ease;
}

.skip-link:focus {
  transform: translateY(0);
}

.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;
}

.site-header {
  --nav-color: var(--paper-bright);
  --nav-divider: rgba(255, 255, 255, 0.22);
  --nav-hover: rgba(255, 255, 255, 0.1);
  --cta-bg: var(--paper-bright);
  --cta-color: var(--graphite);
  position: fixed;
  z-index: 50;
  top: 0;
  left: 0;
  width: 100%;
  color: var(--nav-color);
  font-family: var(--font-ui);
  font-feature-settings: "ss01" 1, "ss02" 1;
  transition: color 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* A section whose surface is split down the middle asks for the header to
   carry its own ground (data-nav-surface). The bar is painted behind the
   header content, so nothing above it changes. */
.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--graphite);
  opacity: 0;
  transition: opacity 420ms cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}

.site-header[data-surface="graphite"]::before {
  opacity: 1;
}

.site-header[data-theme="light"],
.site-header.is-menu-open {
  --nav-color: var(--ink);
  --nav-divider: rgba(39, 20, 14, 0.18);
  --nav-hover: rgba(39, 20, 14, 0.07);
  --cta-bg: var(--graphite);
  --cta-color: var(--paper-bright);
}

/* Sinyal yüzeyi (turuncu zemin). Bağlantılar ve çağrı bloğu koyu mürekkebe
   döner, marka işareti beyaz kalır: turuncunun üzerinde gri/turuncu logo
   varyantı okunmuyor. Bu yüzden "light" temanın marka kuralları burada
   çalışmaz; yalnızca gezinme jetonları devralınır. */
.site-header[data-theme="signal"] {
  --nav-color: var(--ink);
  --nav-divider: rgba(39, 20, 14, 0.24);
  --nav-hover: rgba(39, 20, 14, 0.09);
  --cta-bg: var(--graphite);
  --cta-color: var(--paper-bright);
}

.site-header__inner {
  position: relative;
  display: grid;
  grid-template-columns: 240px auto 1fr;
  align-items: center;
  width: 100%;
  height: var(--header-height);
  padding: 0;
}

.site-header__inner::after {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: 1px;
  content: "";
  background: var(--nav-divider);
  opacity: 1;
  transform: scaleX(1);
  transform-origin: center;
  transition:
    transform 420ms cubic-bezier(0.22, 1, 0.36, 1),
    opacity 420ms ease;
}

.site-header.is-menu-open .site-header__inner::after {
  opacity: 0.12;
  transform: scaleX(1);
}

/* The lockup hugs the left edge of the bar with only an 8px gap. The mark box
   keeps the ratio of the horizontal logo: mark height is about 1.55x the
   wordmark cap height. */
.brand {
  position: relative;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  justify-self: start;
  width: 240px;
  height: 100%;
  padding-left: 8px;
  text-decoration: none;
  border-right: 1px solid var(--nav-divider);
  transition: width 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

.brand__art {
  position: relative;
  flex: 0 0 auto;
  width: 49px;
  height: 30px;
}

.brand__logo {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: left center;
}

.brand__logo {
  transition:
    opacity 420ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

.brand__word {
  display: inline-flex;
  align-items: baseline;
  padding-left: 3px;
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 650;
  letter-spacing: -0.045em;
  line-height: 1;
  white-space: nowrap;
  transition:
    color 420ms cubic-bezier(0.22, 1, 0.36, 1),
    opacity 280ms ease,
    transform 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

.brand__word-cloud,
.brand__word-cell {
  transition: color 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

.brand__word-cloud {
  color: var(--paper-bright);
}

.brand__word-cell {
  color: var(--signal-orange-invert);
}

.brand__logo--light {
  filter: brightness(0) invert(1);
}

.brand__logo--color {
  opacity: 0;
}

.site-header[data-theme="light"] .brand__logo--light,
.site-header.is-menu-open .brand__logo--light {
  opacity: 0;
  transform: translateY(-3px);
}

.site-header[data-theme="light"] .brand__logo--color,
.site-header.is-menu-open .brand__logo--color {
  opacity: 1;
}

.site-header[data-theme="light"] .brand__word-cloud,
.site-header.is-menu-open .brand__word-cloud {
  color: var(--ink);
}

.site-header[data-theme="light"] .brand__word-cell,
.site-header.is-menu-open .brand__word-cell {
  color: var(--orange-deep);
}

.site-header[data-theme="signal"] .brand__word-cloud {
  color: var(--ink);
}

.site-header[data-theme="signal"] .brand__word-cell {
  color: var(--paper-bright);
}

.desktop-nav,
.site-header__actions {
  display: flex;
  align-items: center;
  height: 100%;
}

.desktop-nav {
  justify-content: flex-start;
}

.desktop-nav a,
.header-link {
  position: relative;
  display: flex;
  align-items: center;
  height: 100%;
  padding: 0 16px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.025em;
  text-decoration: none;
  border-right: 1px solid var(--nav-divider);
  transition:
    color 220ms ease,
    background-color 220ms ease;
}

/* Bulunulan sayfa. Gezinme tek satır olduğu için işaret altta ince bir
   çizgi; hücre zemini hover için ayrılmıştır.

   İletişim bağlantısı gezinme listesinde değil, eylem grubunda durur. İşaret
   yine de ona da uygulanır: aksi hâlde iletişim sayfası, gezinmede bulunulan
   sayfayı göstermeyen tek sayfa olurdu. */
.desktop-nav a[aria-current="page"]::after,
.header-link[aria-current="page"]::after {
  position: absolute;
  right: 16px;
  bottom: 0;
  left: 16px;
  height: 2px;
  content: "";
  background: currentColor;
}

.desktop-nav a:hover,
.desktop-nav a:focus-visible,
.header-link:hover,
.header-link:focus-visible {
  background: var(--nav-hover);
}

.site-header__actions {
  grid-column: 3;
  justify-self: end;
}

.header-link {
  border-left: 1px solid var(--nav-divider);
  border-right: 0;
}

.desktop-nav,
.site-header__actions,
.menu-toggle {
  transition:
    opacity 240ms ease,
    transform 420ms cubic-bezier(0.22, 1, 0.36, 1),
    visibility 0s linear 0s;
}

/* The bar carries one action, and its label is a phrase rather than a word, so
   the arrow needs a gap of its own: `space-between` alone puts the two against
   each other the moment the label is wider than the minimum. */
.header-cta {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  min-width: 148px;
  height: 100%;
  padding: 0 20px;
  color: var(--cta-color);
  font-size: 15px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
  text-decoration: none;
  background: var(--cta-bg);
  border: 0;
  border-left: 1px solid var(--nav-divider);
  transition:
    color 280ms ease,
    background-color 280ms ease,
    border-color 280ms ease;
}

.header-cta:hover,
.header-cta:focus-visible {
  color: var(--nav-color);
  background: transparent;
}

.header-cta svg {
  width: 16px;
  margin: 0;
  fill: none;
  stroke: currentColor;
  stroke-linecap: square;
  stroke-width: 1.5;
}

.menu-toggle,
.mobile-menu {
  display: none;
}

/* ---------------------------------------------------------------------------
   Sahne: üç perdelik, kaydırmaya bağlı açılış.
   Yükseklik kaydırma bütçesidir; içerideki yapışkan katman sahnenin kendisi.
   --------------------------------------------------------------------------- */

.stage {
  position: relative;
  height: 512svh;
  background: var(--paper);
}

.stage__inner {
  /* Tek özellik: GSAP bunu 0'dan 1'e sürer, kağıttan grafite geçiş budur. */
  --stage-dark: 0;
  isolation: isolate;
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  color: var(--ink);
  background: var(--paper);
  font-family: var(--font-ui);
}

.stage__inner::before {
  position: absolute;
  z-index: 0;
  inset: 0;
  content: "";
  background: var(--graphite);
  opacity: var(--stage-dark);
}

/* Film grenini taklit eden ince gürültü katmanı. SVG feTurbulence ile
   üretiliyor: ek bir görsel dosyası gerekmiyor, her çözünürlükte keskin.
   Aynı doku sahneyi izleyen grafit bantta da sürer: zemin rengi eşit olsa
   bile grensiz bir blok, grenli sahnenin yanında düz bir yama gibi durur. */
.stage__inner::after,
.clients::after {
  position: absolute;
  z-index: 6;
  inset: 0;
  content: "";
  pointer-events: none;
  opacity: 0.38;
  mix-blend-mode: overlay;
  background-image: var(--grain);
  background-size: 220px 220px;
}

.stage__globe {
  position: absolute;
  z-index: 1;
  inset: var(--header-height) 0 0;
  will-change: transform;
}

.stage__canvas {
  position: absolute;
  inset: 0;
  overflow: hidden;
  cursor: grab;
  outline: 0;
  /* Yatay sürükleme küreyi döndürür, dikey hareket sayfayı kaydırır. */
  touch-action: pan-y;
}

.stage__canvas:active {
  cursor: grabbing;
}

.stage__canvas:focus-visible::after {
  position: absolute;
  inset: 34px;
  content: "";
  pointer-events: none;
  border: 1px solid var(--signal-orange);
}

.stage__canvas canvas {
  position: relative;
  z-index: 0;
  display: block;
  width: 100% !important;
  height: 100% !important;
}

.stage__canvas.is-static-fallback::before {
  position: absolute;
  z-index: 0;
  top: 50%;
  left: 50%;
  width: min(62vmin, 560px);
  aspect-ratio: 1;
  content: "";
  background:
    radial-gradient(circle at 38% 30%, rgba(255, 255, 255, 0.72), transparent 38%),
    radial-gradient(circle, var(--paper) 0 67%, var(--line-strong) 68% 68.5%, transparent 69%);
  border-radius: 50%;
  transform: translate(-50%, -50%);
}

.stage__loading.is-failed {
  color: var(--ink);
}

/* İstasyon ve sinyal katmanı. Küre gövdesi tuvalde kalır; istasyon işaretleri
   ve gezen sinyal burada vektör olarak durur, böylece Türkiye yakınlaşmasında
   ne bulanıklaşır ne de kalınlaşır. Öğeler bir kez kurulur, kare başına
   yalnızca öznitelikleri değişir. */
.earth-signal-layer {
  position: absolute;
  z-index: 1;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  overflow: hidden;
  pointer-events: none;
}

.earth-signal-route,
.earth-signal-static,
.earth-corridor-plume,
.earth-corridor-core {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

/* Çizgi kalınlıkları ekran uzayında sabit: sayfa yakınlaştırması da küre
   yakınlaştırması da görünen kalınlığı değiştirmez. */
.earth-station circle {
  vector-effect: non-scaling-stroke;
}

/* Atlas görünümünün şehir ağı. Rengi ve genel opaklığı grup üzerinden
   earth.js veriyor; buradaki iki kural yalnızca ipliği düğümlerden daha
   soluk tutuyor, böylece tek bir yazma işlemi katmanın tamamını sürüyor. */
.earth-web__link {
  fill: none;
  stroke: currentColor;
  stroke-dasharray: 1.4 3.6;
  stroke-linecap: round;
  stroke-width: 1;
  opacity: 0.42;
  vector-effect: non-scaling-stroke;
}

.earth-web__node {
  fill: currentColor;
  stroke: none;
  opacity: 0.85;
}

.stage__loading {
  position: absolute;
  z-index: 3;
  top: 50%;
  left: 50%;
  display: flex;
  align-items: center;
  margin: 0;
  color: var(--muted);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transform: translate(-50%, -50%);
  transition: opacity 400ms ease;
}

.stage__loading span {
  width: 8px;
  height: 8px;
  margin-right: 10px;
  background: var(--signal-orange);
  animation: stage-pulse 1.1s ease-in-out infinite;
}

.stage__loading.is-hidden {
  pointer-events: none;
  opacity: 0;
}

.stage__loading.is-hidden span {
  animation: none;
}

/* Opening title band ---------------------------------------------------- */

.stage__title {
  position: absolute;
  z-index: 3;
  top: calc(var(--header-height) + clamp(28px, 7vh, 82px));
  right: clamp(26px, 5vw, 76px);
  left: clamp(26px, 5vw, 76px);
  pointer-events: none;
}

/* Açılışın taşıyıcı katmanı: bütün başlık küçük başlar ve kendi merkezinde
   büyür. Kelimelerin yanlardan gelişi bunun içinde, kendi katmanlarında
   olur - iki hareket ayrı eksende durur, birbirini geri almaz. */
.stage__title-rise {
  transform-origin: 50% 50%;
  will-change: opacity, transform;
}

/* Navbar'dan destek metnine kadarki açılış bandı kendi zeminini taşır:
   sayfanın kağıdından bir ton açık, ayrı bir düzlem gibi. Altında sert bir
   kenar yerine yumuşak bir geçişle biter, çünkü küre perde ilerledikçe
   yukarı doğru bu alana giriyor. Bant .stage__title'ın kendi katmanında
   durur, böylece başlıkla aynı anda çıkar. */
.stage__title::before {
  position: absolute;
  z-index: -1;
  top: calc(-1 * (var(--header-height) + clamp(28px, 7vh, 82px)));
  right: calc(-1 * clamp(26px, 5vw, 76px));
  bottom: -34px;
  left: calc(-1 * clamp(26px, 5vw, 76px));
  content: "";
  background: linear-gradient(
    180deg,
    var(--paper-bright) 0,
    var(--paper-bright) calc(100% - 72px),
    rgba(250, 247, 240, 0) 100%
  );
}

.stage__title h1 {
  margin: 0;
  font-size: clamp(55px, 8.15vw, 131px);
  font-weight: 650;
  letter-spacing: -0.035em;
  line-height: 0.82;
  white-space: nowrap;
}

.stage__headline-line {
  display: inline-block;
  will-change: transform;
}

.stage__headline-line + .stage__headline-line {
  margin-left: 0.08em;
}

.stage__title-support {
  max-width: 38ch;
  margin: clamp(34px, 4.4vh, 48px) auto 0;
  color: var(--muted);
  font-size: clamp(15px, 1.5vw, 19px);
  letter-spacing: 0;
  line-height: 1.4;
  text-align: center;
}

/* Claim beats ----------------------------------------------------------- */

/* The paper cut. A graphite plate holds the right side of the stage with one
   hard edge; the globe keeps the paper side. The layer sits above the globe
   and below the grain, and never takes pointer events, so the globe
   underneath stays draggable. */
.stage__claims {
  --claim-plate-width: min(52vw, 680px);

  position: absolute;
  z-index: 4;
  inset: 0;
  pointer-events: none;
  will-change: transform;
}

/* The plate runs the full height of the stage, so the cut reads as one edge
   from the header to the base rather than as a panel floating in the scene.
   Its colour is the graphite the whole stage arrives at later: when the scene
   catches up, the plate stops being a plate because it is the same surface. */
.stage__claim-plate {
  position: absolute;
  /* Below the header, not behind it. The header is transparent over the paper
     act, so a plate running under it puts dark navigation on a dark ground. */
  inset: var(--header-height) 0 0 auto;
  width: var(--claim-plate-width);
  background: var(--graphite);
}

/* The tie. It runs on the paper side, from the globe to the plate edge, and
   the timeline moves it to whichever claim is live. It is the one thing that
   survives from the delivery the operator approved: the claim still arrives
   from the globe rather than appearing on its own. */
.stage__claim-tie {
  position: absolute;
  top: 0;
  right: var(--claim-plate-width);
  width: clamp(64px, 11vw, 190px);
  height: 1px;
  background: var(--orange-ink);
}

.stage__claim-tie-dot {
  position: absolute;
  top: 50%;
  right: 0;
  width: 9px;
  height: 9px;
  margin-top: -5px;
  margin-right: -5px;
  border-radius: 50%;
  background: var(--orange-ink);
}

/* All three claims are laid out once and stay. Nothing is lifted and nothing
   is stacked up as the scene runs, because every claim is on the plate from
   the first beat: only its state changes. */
.stage__claim-list {
  position: absolute;
  top: 50%;
  right: 0;
  width: var(--claim-plate-width);
  margin: 0;
  padding: 0 clamp(28px, 4vw, 68px);
  list-style: none;
  transform: translateY(-50%);
}

.stage__claim + .stage__claim {
  margin-top: clamp(26px, 4vh, 64px);
}

/* One layer, one property. The claim that is being read is at full strength
   and the other two stand back; the timeline moves nothing but their opacity.
   This was two layers of the same word - a filled one over an outlined one -
   until 2026-08-03. At this weight and size a hairline stroke broke up at
   every joint and read as damage rather than as a state. */
.stage__claim-word {
  position: relative;
  margin: 0;
  color: var(--paper);
  font-size: clamp(28px, 3.7vw, 58px);
  font-weight: 620;
  letter-spacing: -0.03em;
  line-height: 0.96;
  text-transform: uppercase;
  will-change: opacity, transform;
}

/* A fixed slot. Only the live claim shows its sentence, so a slot sized to its
   own text would give the three claims three different gaps and the column
   would lose its rhythm as the beats ran. */
.stage__claim-support {
  min-height: 3em;
  margin: clamp(10px, 1.4vh, 20px) 0 0;
  max-width: 44ch;
  color: var(--muted-invert);
  font-size: clamp(13px, 1.05vw, 16px);
  line-height: 1.5;
}

/* The credential line belongs to the plate now. Set across the whole stage it
   would straddle the cut and need two inks. */
.stage__claim-rail {
  position: absolute;
  right: 0;
  bottom: clamp(24px, 4.2vh, 52px);
  width: var(--claim-plate-width);
  margin: 0;
  padding: 0 clamp(28px, 4vw, 68px);
  color: var(--muted-invert);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

@media (max-width: 760px) {
  /* No room for a side cut: the plate becomes a band across the lower half
     and the globe sits above it. The claims used to be set straight over the
     dotted continents with nothing behind them, which is what the band
     repairs. */
  .stage__claim-plate {
    inset: auto 0 0 0;
    width: auto;
    height: 62%;
  }

  .stage__claim-tie {
    display: none;
  }

  .stage__claim-list {
    top: auto;
    bottom: clamp(58px, 11vh, 96px);
    width: auto;
    padding: 0 clamp(18px, 5vw, 30px);
    transform: none;
  }

  .stage__claim + .stage__claim {
    margin-top: clamp(18px, 3vh, 30px);
  }

  .stage__claim-word {
    font-size: clamp(26px, 8vw, 40px);
  }

  .stage__claim-support {
    font-size: 14px;
  }

  .stage__claim-rail {
    width: auto;
    padding: 0 clamp(18px, 5vw, 30px);
    bottom: clamp(16px, 3vh, 26px);
    letter-spacing: 0.1em;
    line-height: 1.6;
  }
}

/* The stage is not pinned without motion and no claim timeline exists, so the
   claims join the same static flow the rest of the stage uses. The cut is a
   scroll effect, so there is no plate here: the claims run on paper with paper
   ink, all three filled, every sentence shown, and the tie dropped because no
   signal travels. */
@media (prefers-reduced-motion: reduce) {
  .stage__claims {
    position: static;
    padding: 56px clamp(22px, 5vw, 76px) 0;
  }

  .stage__claim-plate,
  .stage__claim-tie {
    display: none;
  }

  .stage__claim-list {
    position: static;
    display: grid;
    gap: clamp(22px, 3.4vh, 44px);
    width: auto;
    padding: 0;
    transform: none;
  }

  .stage__claim {
    margin-top: 0;
  }

  .stage__claim-word {
    color: var(--ink);
    font-size: clamp(26px, 3.6vw, 42px);
    line-height: 1.05;
  }

  .stage__claim-support {
    max-width: 62ch;
    margin-top: 10px;
    color: var(--muted);
  }

  .stage__claim-rail {
    position: static;
    width: auto;
    margin-top: clamp(20px, 3vh, 32px);
    padding: 0;
    color: var(--muted);
    text-align: left;
  }
}
/* Perde 3 -------------------------------------------------------------- */

.stage__evidence {
  position: absolute;
  z-index: 4;
  bottom: clamp(36px, 6vh, 72px);
  left: clamp(26px, 5vw, 76px);
  width: min(46vw, 520px);
  color: var(--paper);
}

/* Airbrushed, not a panel. Two things kept it from reading that way: the box
   ended just past the block, so the ellipse was clipped into a hard vertical
   edge on the left, and a two-stop radial falls off linearly, which the eye
   reads as a rim. The box now reaches far enough out that the gradient dies
   before the edge, and three offset layers with staged stops approximate a
   sprayed falloff. */
.stage__evidence::before {
  position: absolute;
  z-index: -1;
  inset: -150px -230px -190px -340px;
  content: "";
  background:
    radial-gradient(
      ellipse 44% 40% at 46% 55%,
      rgba(23, 20, 15, 0.92) 0%,
      rgba(23, 20, 15, 0.74) 32%,
      rgba(23, 20, 15, 0.4) 55%,
      rgba(23, 20, 15, 0.15) 73%,
      rgba(23, 20, 15, 0) 90%
    ),
    radial-gradient(
      ellipse 62% 56% at 40% 60%,
      rgba(23, 20, 15, 0.48) 0%,
      rgba(23, 20, 15, 0.22) 44%,
      rgba(23, 20, 15, 0.06) 68%,
      rgba(23, 20, 15, 0) 86%
    ),
    radial-gradient(
      ellipse 34% 66% at 34% 48%,
      rgba(23, 20, 15, 0.4) 0%,
      rgba(23, 20, 15, 0.12) 52%,
      rgba(23, 20, 15, 0) 82%
    );
}

.stage__evidence h2 {
  margin: 0 0 26px;
  font-size: clamp(28px, 3.2vw, 46px);
  letter-spacing: -0.05em;
  line-height: 1;
}

.stage__evidence ul {
  display: grid;
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.stage__evidence li {
  padding-top: 12px;
  color: var(--muted-invert);
  border-top: 1px solid var(--graphite-line);
  font-size: 14px;
  line-height: 1.45;
}

.stage__evidence strong {
  display: block;
  margin-bottom: 3px;
  color: var(--paper);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

/* Erişilebilirlik göstergesi. Atlas görünümünün sağ alt köşesinde durur;
   altında cetvel yok, rakam ve etiket tek başına taşır. */
.stage__uptime {
  position: absolute;
  z-index: 4;
  right: clamp(26px, 5vw, 76px);
  bottom: clamp(36px, 6vh, 72px);
  display: flex;
  align-items: center;
  gap: clamp(14px, 1.4vw, 20px);
  pointer-events: none;
}

.stage__uptime-mark {
  display: block;
  flex: none;
  width: clamp(38px, 3.2vw, 48px);
  height: clamp(38px, 3.2vw, 48px);
}

.stage__uptime-mark svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.stage__uptime-dial {
  fill: none;
  stroke: var(--muted-invert);
  stroke-dasharray: 1 4.4;
  stroke-linecap: round;
  stroke-width: 1.4;
}

.stage__uptime-trace {
  fill: none;
  stroke: var(--signal-orange-invert);
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 2;
}

.stage__uptime-figure {
  display: flex;
  flex-direction: column;
  margin: 0;
}

.stage__uptime-figure strong {
  color: var(--signal-orange-invert);
  font-family: var(--font-display);
  font-size: clamp(34px, 3.6vw, 54px);
  font-weight: 600;
  letter-spacing: -0.045em;
  line-height: 0.9;
}

.stage__uptime-figure span {
  margin-top: 6px;
  color: var(--muted-invert);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

/* Küre sarmalayıcısının içinde durur: piksel koordinatları canvas ile
   birebir aynı olsun diye. */
.stage__focus {
  position: absolute;
  z-index: 5;
  inset: 0;
  pointer-events: none;
}

.stage__city {
  position: absolute;
  display: flex;
  align-items: center;
  color: var(--muted-invert);
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 8px;
  letter-spacing: 0.08em;
  line-height: 1.35;
  text-transform: uppercase;
}

.stage__city span {
  display: flex;
  flex-direction: column;
}

.stage__city strong {
  color: var(--paper);
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.02em;
  line-height: 1.2;
}

@keyframes stage-pulse {
  0%,
  100% {
    opacity: 0.35;
    transform: scale(0.75);
  }

  50% {
    opacity: 1;
    transform: scale(1);
  }
}

/* Perde 3'ün grafiti referans bandına taşınır, sayfa aşağıda kağıda döner. */
/* Bandın tepesi sahnenin bittiği tonu devralır ve aşağı doğru grafit zemine
   oturur. Küre yüzeyi kendi içinde gölge ve sıcak ışıkla değiştiği için birebir
   eşleşme mümkün değil; amaç kesik bir kenar yerine sürekli bir yüzey. */
.clients {
  isolation: isolate;
  position: relative;
  color: var(--paper);
  background-color: var(--graphite);
  background-image: linear-gradient(
    180deg,
    var(--graphite-rise) 0,
    var(--graphite) 58svh
  );
  background-repeat: no-repeat;
}

.clients__statement {
  position: relative;
  display: grid;
  align-content: center;
  justify-items: center;
  min-height: 76svh;
  padding: calc(var(--header-height) + 48px) 32px 64px;
  overflow: hidden;
  text-align: center;
}

.clients__statement::before {
  position: absolute;
  top: 0;
  right: 32px;
  left: 32px;
  height: 1px;
  content: "";
  background: var(--graphite-line);
}

.clients__statement h2 {
  max-width: 1080px;
  margin: 0;
  font-size: clamp(48px, 6.4vw, 94px);
  letter-spacing: -0.06em;
  line-height: 0.94;
}

.clients__marquee {
  position: relative;
  width: 100%;
  overflow: hidden;
  border-top: 1px solid var(--graphite-line);
  border-bottom: 1px solid var(--graphite-line);
}

.clients__track {
  display: flex;
  width: max-content;
  will-change: transform;
}

.client-cell {
  display: flex;
  flex: 0 0 clamp(224px, 18.75vw, 300px);
  align-items: center;
  justify-content: center;
  height: 270px;
  margin: 0;
  padding: 48px;
  background: var(--graphite-deep);
  border-right: 1px solid var(--graphite-line);
}

/* Logolar açık zeminli dosyalar; grafit bant üzerinde ters kontrastla
   okunur hale gelir. */
.client-cell img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 76px;
  filter: grayscale(1) invert(1);
  mix-blend-mode: screen;
  opacity: 0.82;
  transition:
    opacity 280ms ease,
    transform 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

.client-cell picture {
  display: flex;
  width: 100%;
  height: 100%;
  align-items: center;
  justify-content: center;
}

.plate__frame > picture {
  display: block;
  width: 100%;
  height: 100%;
}

.client-cell:hover img {
  opacity: 1;
  transform: scale(1.04);
}

/* Product service stack ------------------------------------------------- */

.service-stack {
  --service-card-expanded: clamp(32rem, 38vw, 36rem);
  --service-card-collapsed: 10rem;
  --service-visual: calc(var(--service-card-expanded) - 15rem);
  /* The sticky list used to be pulled up as the cards collapsed. With the
     3:1 card the collapsed title bar is only 10rem tall, so any lift drags
     the first title up behind the fixed header and it reads as cut off. */
  --service-list-lift: 0rem;
  position: relative;
  color: var(--paper-bright);
  background: var(--graphite);
}

.service-stack__intro {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  min-height: clamp(620px, 58vw, 820px);
  overflow: hidden;
  color: var(--ink);
  background: var(--paper);
  border-top: 1px solid var(--line);
}

.service-stack__intro-copy {
  z-index: 1;
  display: flex;
  grid-column: 1 / 6;
  flex-direction: column;
  justify-content: center;
  padding: clamp(88px, 9vw, 144px) clamp(32px, 4vw, 64px)
    clamp(72px, 8vw, 120px) clamp(26px, 5vw, 76px);
}

.service-stack__intro h2 {
  max-width: 8.6ch;
  margin: 0;
  font-size: clamp(58px, 6.4vw, 104px);
  letter-spacing: -0.065em;
  line-height: 0.9;
}

.service-stack__intro-copy > p {
  max-width: 32ch;
  margin: clamp(30px, 3.2vw, 48px) 0 0;
  color: var(--muted);
  font-size: clamp(16px, 1.4vw, 21px);
  line-height: 1.5;
}

/* The drawing is absolutely positioned inside this figure, so nothing in it
   contributes height. The figure takes the full height of the row instead of
   stating a proportion of its own: the copy beside it is centred in that row,
   and a figure sized to its own aspect sat at the top of it, above the
   heading, with the dividing rule stopping halfway down. The drawing centres
   itself inside the taller box through `xMidYMid meet`. */
.service-backbone {
  position: relative;
  grid-column: 6 / 13;
  align-self: stretch;
  min-width: 0;
  min-height: clamp(320px, 34vw, 470px);
  margin: 0;
  overflow: hidden;
  border-left: 1px solid var(--line);
  background: var(--paper);
}

.service-backbone::after {
  position: absolute;
  inset: 0;
  content: "";
  opacity: 0.13;
  mix-blend-mode: multiply;
  background-image: var(--grain);
  background-size: 220px 220px;
  pointer-events: none;
}

/* The convergence drawing.

   Geometry is authored in Penpot and exported carrying no colour at all: the
   whole palette arrives here, so the drawing recolours with the section the
   same way the service plates do. `xMidYMid meet` keeps the registered cloud
   mark undistorted; where the box is taller than the drawing the letterbox is
   invisible, because both are the same paper. */
.service-backbone__drawing {
  position: absolute;
  z-index: 2;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  /* No blend mode. Multiply plus an animated opacity on a nested group makes
     the browser promote that group to its own compositing layer, and the layer
     boundary then shows as a hard vertical edge across the cloud. The figure's
     grain comes from the .service-backbone::after overlay, which keeps its own
     multiply, so nothing is lost. */
  pointer-events: none;
}

.service-backbone__drawing path,
.service-backbone__drawing circle,
.service-backbone__drawing use {
  vector-effect: non-scaling-stroke;
}

/* The cloud convergence figure.

   Three flows enter from the left, meet at the exact centre of the registered
   cloud mark, and the mark's own two wave arcs radiate from that meeting
   point. Nothing leaves to the right: the emanation is the output. */
.service-backbone__drawing {
  position: absolute;
  z-index: 2;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  /* No blend mode. Multiply plus an animated opacity on a nested group makes
     the browser promote that group to its own compositing layer, and the layer
     boundary then shows as a hard vertical edge across the cloud. The figure's
     grain comes from the .service-backbone::after overlay, which keeps its own
     multiply, so nothing is lost. */
  pointer-events: none;
}

.service-backbone__drawing path,
.service-backbone__drawing circle,
.service-backbone__drawing rect,
.service-backbone__drawing use {
  vector-effect: non-scaling-stroke;
}

.backbone__cloud {
  /* Filled, because the mark's own contour crosses itself at the upper left
     lobe and an unfilled outline shows the crossing. Under multiply on paper
     this fill is all but invisible; it only hides the overlap. */
  fill: var(--paper-bright);
  stroke: var(--ink);
  stroke-width: 1.4;
  stroke-linejoin: round;
  opacity: 0.7;
}

.backbone__lane {
  fill: none;
}

/* Voice: a trace of a real signal. One continuous stroke, so the silences
   between talk spurts are silence rather than a gap in a pattern. */
.backbone__trace {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.3;
  stroke-linejoin: round;
  stroke-linecap: round;
  opacity: 0.8;
}

.backbone__axis {
  fill: none;
  stroke: var(--ink);
  stroke-width: 0.6;
  opacity: 0.28;
}

/* Messaging: discrete envelopes. Unlabelled - the page names the services in
   real text beside the figure, and three words at three taxonomic levels read
   as placeholder. */
.backbone__msg-line {
  fill: none;
  stroke: var(--ink);
  stroke-width: 0.8;
  stroke-dasharray: 1.5 4;
  opacity: 0.4;
}

.backbone__envelope rect {
  fill: var(--paper);
  stroke: var(--ink);
  stroke-width: 1;
  opacity: 0.92;
}

.backbone__envelope-flap {
  fill: none;
  stroke: var(--ink);
  stroke-width: 0.9;
  stroke-linejoin: round;
  opacity: 0.92;
}

/* Internet: a fibre bundle with light inside it. The strand is the cable and
   the pulse is the light, which is why the pulse is the one saturated thing on
   the access side - a lit fibre is a live state. */
.backbone__strand {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.6;
  opacity: 0.42;
}

.backbone__pulse {
  fill: var(--signal-orange);
  stroke: none;
}

/* What spills out of an opened envelope: the payload, as characters. Without a
   fill of its own this inherits `fill: none` from the lane and never appears.
   Anchored and centred on its own point, so the script can place and scale it
   with one transform. */
.backbone__char {
  fill: var(--ink);
  stroke: none;
  opacity: 0.85;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-anchor: middle;
  dominant-baseline: central;
}

.backbone__route {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.3;
  stroke-linecap: round;
  /* Matched to the trace. They used to differ, which put a visible seam exactly
     where a flow hands over to the line that carries it on. */
  opacity: 0.8;
}

/* What arrives at the meeting point is round, because what meets there is a
   signal and not a packet of a fixed size. */
.backbone__packet {
  fill: var(--ink);
  opacity: 0.85;
}

/* The mark's own two wave arcs, radiating from the point where the three
   meet. This is the figure's output and the only place it is stated. */
.backbone__wave {
  fill: var(--signal-orange);
}

/* The far band is lighter than the near one, so the pair reads as one emanation
   spreading rather than as two bands. This is the authored state, and it is what
   reduced motion shows - the earlier rule dimmed whichever arc happened to be
   first in the file, which left the near band half faded with no motion. */
.backbone__wave[data-backbone-wave="1"] {
  opacity: 0.62;
}

.backbone__beacon {
  fill: var(--signal-orange);
}

.backbone__mark {
  fill: none;
  stroke: var(--ink);
  stroke-width: 0.8;
  opacity: 0.3;
}

/* The traffic layer is created by the script, never authored in the markup: a
   packet riding a route that has not been drawn is a lie, and a dead script
   has to leave the drawing whole rather than half-lit. */
.backbone__packet {
  fill: var(--ink);
}

.backbone__lit {
  fill: none;
  stroke: var(--signal-orange);
  stroke-width: 2;
  stroke-linecap: round;
}

.service-backbone__routes circle {
  fill: var(--paper);
  stroke: var(--signal-orange);
  stroke-width: 3;
  vector-effect: non-scaling-stroke;
}

.service-stack__track {
  position: relative;
  background: var(--service-connectivity);
}

.service-stack__list {
  position: sticky;
  /* The stack begins below fixed chrome. The heading and plate offsets below
     preserve their former screen positions without letting card surfaces sit
     behind the navigation. */
  top: var(--header-height);
  will-change: transform;
}

/* Six values carry a card: the ground, the ink on it, the softened ink for
   running text, the hairline weight, the rule weight, and the one orange that
   means the line is live. Every rule below reads them, so a card changes side
   of the ramp by redeclaring this block and nothing else - including the plate
   drawings, which inherit them straight through <use>. */
.service-card {
  --service-surface: var(--service-voice);
  --service-ink: var(--ink);
  --service-ink-soft: rgba(39, 20, 14, 0.72);
  --service-hair: rgba(39, 20, 14, 0.44);
  --service-rule: rgba(39, 20, 14, 0.16);
  --service-grid: rgba(39, 20, 14, 0.1);
  --service-live: var(--signal-orange);
  position: relative;
  height: var(--service-card-expanded);
  overflow: hidden;
  color: var(--service-ink);
  background: var(--service-surface);
  border-top: 1px solid var(--service-rule);
  will-change: height;
}

/* The dark half of the ramp. Orange changes with it: the deep signal orange
   holds against paper and goes muddy on graphite, where the lifted invert
   reads instead. */
.service-card--messaging,
.service-card--connectivity {
  --service-ink: var(--paper-bright);
  /* The mauve card is the lightest of the three dark surfaces, so the ramp's
     one soft-ink value was tuned on graphite and arrived at 4.31:1 here. */
  --service-ink-soft: rgba(250, 247, 240, 0.82);
  --service-hair: rgba(250, 247, 240, 0.44);
  --service-rule: rgba(250, 247, 240, 0.18);
  --service-grid: rgba(250, 247, 240, 0.08);
  --service-live: var(--signal-orange-invert);
}

.service-card--messaging {
  --service-surface: var(--service-messaging);
}

.service-card--connectivity {
  --service-surface: var(--service-connectivity);
}

/* ---------------------------------------------------------------------------
   Card interior.

   Reference layout: title top left, a square technical plate to one side, a
   short statement under the title, then one rule across the card with the
   description on the left and the call to action on the right.

   The plate alternates sides down the stack - voice right, messaging left,
   connectivity right - while the title stays left on every card, because the
   collapsed cards are read as one column of titles and moving that anchor
   would break the stack.
   --------------------------------------------------------------------------- */

.service-card__heading {
  display: flex;
  align-items: center;
  height: var(--service-card-collapsed);
  padding: 18px clamp(26px, 5vw, 76px) 22px;
}

/* The title sits on the same side as the copy. On a flipped card the plate
   takes the left edge, and a title left there would be painted over by it. */
.service-card--flip .service-card__heading {
  justify-content: flex-end;
}

.service-card__heading h3 {
  margin: 0;
  font-size: clamp(58px, 6vw, 86px);
  letter-spacing: -0.055em;
  line-height: 0.78;
}

/* The second column is the space the plate occupies. The plate itself is
   positioned against the card, so this column only reserves the room. */
.service-card__content {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--service-visual);
  grid-template-rows: minmax(0, 1fr) auto;
  column-gap: clamp(36px, 5vw, 84px);
  height: calc(var(--service-card-expanded) - var(--service-card-collapsed));
  padding: 0 clamp(26px, 5vw, 76px) clamp(26px, 3vw, 38px);
  will-change: opacity, transform;
}

.service-card--flip .service-card__content {
  grid-template-columns: var(--service-visual) minmax(0, 1fr);
}

.service-card__lead {
  display: flex;
  min-width: 0;
  flex-direction: column;
  align-self: end;
  grid-area: 1 / 1;
  padding-bottom: clamp(18px, 2.4vw, 34px);
}

.service-card--flip .service-card__lead {
  grid-area: 1 / 2;
}

.service-card__services {
  width: 100%;
  border-bottom: 1px solid var(--service-rule);
}

.service-card__services article {
  display: grid;
  grid-template-columns: minmax(180px, 0.44fr) minmax(0, 1fr);
  gap: clamp(24px, 3vw, 46px);
  padding: clamp(15px, 1.5vw, 22px) 0;
  border-top: 1px solid var(--service-rule);
}

.service-card__services h4 {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(19px, 1.6vw, 24px);
  font-weight: 560;
  letter-spacing: -0.03em;
  line-height: 1.05;
}

.service-card__services p {
  max-width: 48ch;
  margin: 0;
  color: var(--service-ink-soft);
  font-size: clamp(14px, 1.06vw, 16px);
  line-height: 1.48;
}

/* The plate is anchored to the card, not to the content, so its top can sit
   level with the title the way the reference does. It is deliberately not a
   child of the content block: the collapse tween puts a transform on that
   block, which would make it the containing block and drop the plate by the
   height of the title bar mid-tween.

   Square by construction rather than by aspect-ratio off the card height:
   that height is animated, and a derived ratio would resize the plate on
   every frame of the collapse. */
.service-card__visual {
  position: absolute;
  z-index: 1;
  top: 6px;
  right: clamp(26px, 5vw, 76px);
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--service-visual);
  height: var(--service-visual);
  overflow: hidden;
  /* The plate ground is the card surface exactly, with no lightening layer
     over it: the drawings fill their bodies with the same token so a part
     drawn over another occludes it, and any tint here would show as a halo
     around every filled shape. The border alone separates plate from card. */
  background: var(--service-surface);
  border: 1px solid var(--service-rule);
  will-change: opacity;
}

.service-card--flip .service-card__visual {
  right: auto;
  left: clamp(26px, 5vw, 76px);
}

.service-card__visual svg {
  width: 100%;
  height: 100%;
}

.service-card__foot {
  display: flex;
  grid-area: 2 / 1 / 3 / 3;
  align-items: center;
  justify-content: flex-end;
  min-height: 62px;
  padding-top: 16px;
  border-top: 1px solid var(--service-rule);
}

.service-card__foot a {
  display: inline-flex;
  gap: 14px;
  align-items: center;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
}

.service-card__foot a span {
  border-bottom: 1px solid var(--service-hair);
}

.service-card__foot a svg {
  width: 18px;
  height: 18px;
  flex: none;
  margin-top: 1px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
}

.service-proposal {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(280px, 0.6fr) auto;
  gap: clamp(32px, 5vw, 76px);
  align-items: center;
  padding: clamp(58px, 6vw, 92px) clamp(26px, 5vw, 76px);
  color: var(--ink);
  background: var(--signal-orange);
  border-top: 1px solid rgba(39, 20, 14, 0.24);
}

.service-proposal > p {
  max-width: 15ch;
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(42px, 4.8vw, 74px);
  font-weight: 560;
  letter-spacing: -0.055em;
  line-height: 0.92;
}

.service-proposal > span {
  max-width: 36ch;
  /* 0.74 measured 3.55:1 against the orange. Orange is a bright ground, so a
     softened ink loses contrast on it much faster than it does on paper. */
  color: rgba(39, 20, 14, 0.9);
  font-size: clamp(15px, 1.2vw, 18px);
  line-height: 1.5;
}

.service-proposal > a {
  display: inline-flex;
  gap: 12px;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 15px 22px;
  color: var(--paper-bright);
  background: var(--graphite);
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-decoration: none;
  text-transform: uppercase;
}

.service-proposal svg {
  width: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
}

/* The plate contents. One square drawing per service on a ruled ground.
   Strokes do not scale with the plate, so the drawing keeps the same weight
   at every card size.

   Every plate draws the one object the service actually runs on and animates
   the single moment that service happens: the handset comes off the cradle,
   the code lands, the patch cord seats. Orange marks the path the traffic
   takes and nothing else. */

.service-plate__grid path {
  fill: none;
  stroke: var(--service-grid);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

/* A body carries a fill AND a hairline edge: the fill is the plate ground, so
   a part drawn over another part occludes it and the overlap reads as
   assembly rather than as two overlapping outlines. */
.service-plate__body {
  fill: var(--service-surface);
  stroke: var(--service-ink);
  stroke-width: 1.6;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.service-plate__seam {
  fill: none;
  stroke: var(--service-hair);
  stroke-width: 1;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

/* The line that carries the traffic: the handset cord and the patch cord. */
.service-plate__live {
  fill: none;
  stroke: var(--service-live);
  stroke-width: 2;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

/* A status lamp, drawn as a socket that always shows and a light that comes on
   inside it. Same orange as the lines: on this system orange always means the
   line is live, and a link lamp is that statement in one dot. */
.service-plate__socket {
  fill: var(--service-surface);
  stroke: var(--service-hair);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

.service-plate__lamp {
  fill: var(--service-live);
}

.service-plate__code {
  fill: var(--service-live);
  font-family: var(--font-ui);
  font-size: 27px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-anchor: middle;
}

.service-plate__sender,
.service-plate__otp-copy {
  fill: var(--service-ink);
  font-family: var(--font-ui);
}

.service-plate__sender {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-anchor: middle;
}

.service-plate__otp-copy {
  font-size: 10px;
  font-weight: 500;
}

@media (max-width: 820px) {
  .service-stack__intro {
    display: flex;
    min-height: 0;
    flex-direction: column;
  }

  .service-stack__intro-copy {
    padding: 86px 22px 58px;
  }

  .service-stack__intro h2 {
    max-width: 9ch;
    font-size: clamp(48px, 14vw, 64px);
  }

  .service-stack__intro-copy > p {
    margin-top: 30px;
  }

  .service-backbone {
    width: 100%;
    min-height: 0;
    aspect-ratio: 4 / 3;
    border-top: 1px solid var(--line);
    border-left: 0;
  }

  .service-stack__track {
    height: auto !important;
    margin-bottom: 0 !important;
  }

  .service-stack__list {
    position: static;
    transform: none !important;
  }

  .service-card {
    height: auto !important;
    overflow: visible !important;
  }

  .service-card__heading {
    height: auto;
    padding: 34px 22px 24px;
  }

  .service-card__heading h3 {
    font-size: clamp(54px, 17vw, 72px);
  }

  /* One column in source order: services, plate, link. The
     plate keeps its square, capped so it never fills the whole screen. */
  .service-card__content {
    display: flex;
    height: auto;
    padding: 0 22px 44px;
    flex-direction: column;
    gap: 30px;
    opacity: 1 !important;
    transform: none !important;
  }

  /* The content is a column flex here, so the desktop align-self that pins
     the statement to the bottom of its grid row would push it to the right
     edge instead: on a column flex the cross axis is horizontal. */
  .service-card__lead,
  .service-card--flip .service-card__lead,
  .service-card__foot {
    grid-area: auto;
    align-self: stretch;
    padding-bottom: 0;
  }

  .service-card__visual,
  .service-card--flip .service-card__visual {
    position: static;
    width: min(100%, 320px);
    height: min(78vw, 320px);
    margin: 0 22px 30px;
  }

  .service-card__foot {
    display: flex;
    min-height: 52px;
    align-items: flex-start;
    justify-content: flex-start;
  }

  .service-card__foot a {
    height: auto;
  }

  .service-card__services article {
    grid-template-columns: 1fr;
    gap: 10px;
    padding: 18px 0;
  }

  .service-card__services h4 {
    font-size: 22px;
  }

  .service-card__services p {
    font-size: 15px;
  }

  .service-proposal {
    grid-template-columns: 1fr;
    gap: 28px;
    padding: 58px 22px 62px;
  }

  .service-proposal > p {
    max-width: 11ch;
    font-size: clamp(42px, 13vw, 58px);
  }

  .service-proposal > a {
    justify-self: start;
  }
}

@media (max-width: 1100px) {
  .site-header__inner {
    grid-template-columns: 220px auto 1fr;
    padding: 0;
  }

  .site-header__inner::after {
    right: 0;
    left: 0;
  }

  .brand {
    width: 220px;
    padding-left: 8px;
  }

  .brand__word {
    padding-left: 2px;
    font-size: 26px;
  }

  .desktop-nav a,
  .header-link {
    padding-right: 12px;
    padding-left: 12px;
    font-size: 14px;
  }

  .header-cta {
    min-width: 128px;
    padding-right: 14px;
    padding-left: 14px;
  }
}

@media (max-width: 820px) {
  :root {
    --header-height: 56px;
  }

  .site-header__inner {
    display: flex;
    justify-content: space-between;
    padding: 0;
  }

  .site-header__inner::after {
    right: 0;
    left: 0;
  }

  .brand {
    width: 210px;
    height: 100%;
    padding-left: 8px;
  }

  .brand__word {
    padding-left: 2px;
    font-size: 26px;
  }

  .desktop-nav,
  .site-header__actions {
    display: none;
  }

  .menu-toggle {
    position: relative;
    display: block;
    width: 56px;
    height: 56px;
    padding: 0;
    color: currentColor;
    cursor: pointer;
    background: transparent;
    border: 0;
    border-left: 1px solid var(--nav-divider);
  }

  .menu-toggle span {
    position: absolute;
    right: 4px;
    left: 4px;
    height: 1px;
    background: currentColor;
    transition:
      top 240ms ease,
      transform 240ms ease;
  }

  .menu-toggle span:first-child {
    top: 23px;
  }

  .menu-toggle span:last-child {
    top: 33px;
  }

  .site-header.is-menu-open .menu-toggle span:first-child {
    top: 28px;
    transform: rotate(45deg);
  }

  .site-header.is-menu-open .menu-toggle span:last-child {
    top: 28px;
    transform: rotate(-45deg);
  }

  .site-header.is-menu-open {
    min-height: 100dvh;
    color: var(--ink);
    background: var(--orange-soft);
  }

  .mobile-menu {
    height: calc(100dvh - var(--header-height));
    padding: 24px 18px 28px;
    background: var(--orange-soft);
  }

  .mobile-menu:not([hidden]) {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
  }

  .mobile-menu nav {
    display: flex;
    flex-direction: column;
  }

  .mobile-menu nav a {
    display: flex;
    align-items: baseline;
    padding: 15px 0;
    font-size: clamp(32px, 10vw, 52px);
    letter-spacing: -0.045em;
    line-height: 1;
    text-decoration: none;
    border-bottom: 1px solid var(--orange-line);
  }

  .mobile-menu nav span {
    width: 36px;
    color: var(--orange-deep);
    font-size: 10px;
    letter-spacing: 0.08em;
  }

  /* One action, one column. A two-column grid left the single call to action
     sitting in the left half with the right half empty. */
  .mobile-menu__actions {
    display: grid;
    grid-template-columns: 1fr;
  }

  .mobile-menu__actions a {
    padding: 16px;
    text-align: center;
    text-decoration: none;
    border: 1px solid var(--orange-line);
  }

  .mobile-menu__actions .mobile-menu__cta {
    color: var(--paper-bright);
    background: var(--signal-orange);
    border-color: var(--signal-orange);
  }

  .clients__statement {
    min-height: 68svh;
    padding-top: calc(var(--header-height) + 42px);
    padding-bottom: 56px;
    padding-right: 18px;
    padding-left: 18px;
  }

  .clients__statement::before {
    right: 18px;
    left: 18px;
  }

  .clients__statement h2 {
    font-size: clamp(42px, 12vw, 64px);
  }

  .client-cell {
    flex-basis: 64vw;
    height: 210px;
    padding: 38px;
  }
}

/* Dar ekranda küre sol kenardan kırpılmaz: üst yarıda küçülerek ortada
   kalır, kartlar alt yarıdan tam genişlikte geçer. */
@media (max-width: 760px) {
  .stage {
    height: 390svh;
  }

  .stage__title {
    top: calc(var(--header-height) + 28px);
    right: 22px;
    left: 22px;
  }

  .stage__title::before {
    top: calc(-1 * (var(--header-height) + 28px));
    right: -22px;
    bottom: -26px;
    left: -22px;
  }

  .stage__title h1 {
    font-size: clamp(48px, 13.5vw, 58px);
    line-height: 0.84;
    white-space: normal;
  }

  .stage__headline-line {
    display: block;
    white-space: nowrap;
  }

  .stage__headline-line + .stage__headline-line {
    margin-left: 0;
  }

  .stage__title-support {
    max-width: 31ch;
    margin-top: 22px;
    font-size: 15px;
  }

  .stage__evidence {
    right: 22px;
    bottom: 26px;
    left: 22px;
    width: auto;
  }

.stage__evidence h2 {
    margin-bottom: 18px;
    font-size: clamp(26px, 8vw, 34px);
  }

  .stage__evidence li {
    font-size: 13px;
  }

  /* Dar ekranda kanıt bloğu alt kenarı tamamen kaplıyor; gösterge oraya
     sığmaz. Haritanın boş kalan üst kesimine, künyenin altına taşınır. */
  .stage__uptime {
    top: 98px;
    right: 22px;
    bottom: auto;
    gap: 12px;
  }

  .stage__uptime-mark {
    width: 32px;
    height: 32px;
  }

  .stage__uptime-figure strong {
    font-size: 30px;
  }

  .stage__uptime-figure span {
    font-size: 8px;
    letter-spacing: 0.18em;
  }

  /* Dar ekranda üçüncü perde tam ekran Türkiye + kanıt bloğu taşıyor;
     şehir etiketleri metnin üstüne düşüyordu, bu boyutta çıkarıldı. */
  .stage__city {
    display: none;
  }

  .stage__canvas:focus-visible::after {
    inset: 16px;
  }
}

/* ---------------------------------------------------------------------------
   Human infrastructure band.

   Direction: docs/research/website-directions/04-human-infrastructure.png

   One continuous mosaic, not a row of cards: plates are full bleed, meet on
   1px rules, and carry no radius and no shadow. The image plates are empty
   by design. Their ground is drawn here so an empty plate still reads as a
   held frame rather than as a missing asset, and .plate__image is already
   styled so a photograph can be dropped in without touching this sheet.
   --------------------------------------------------------------------------- */

.field {
  --field-row-lead: clamp(360px, 34vw, 520px);
  --field-row-sheet: clamp(196px, 17vw, 244px);
  --field-row-closing: clamp(260px, 25vw, 372px);
  --field-gutter: clamp(24px, 3.4vw, 52px);
  --plate-line: rgba(255, 255, 255, 0.14);
  position: relative;
  /* The connectivity card ends flush against the first plate without this.
     The two surfaces are the same graphite, so the separation is space and
     the section rule, not a device. */
  padding-top: clamp(64px, 7vw, 112px);
  color: var(--paper-bright);
  background: var(--graphite);
  border-top: 1px solid var(--graphite-line);
}

.field__mosaic {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-template-rows:
    var(--field-row-lead) var(--field-row-sheet)
    var(--field-row-closing);
}

.field__lead {
  grid-area: 1 / 1 / 2 / 8;
}

.field__panel {
  grid-area: 1 / 8 / 2 / 13;
}

.field__sheet {
  grid-area: 2 / 1 / 3 / 13;
}

.field__closing {
  grid-area: 3 / 1 / 4 / 7;
}

.field__detail {
  grid-area: 3 / 7 / 4 / 10;
}

.field__link {
  grid-area: 3 / 10 / 4 / 13;
}

/* Plates ------------------------------------------------------------------ */

.plate {
  position: relative;
  min-width: 0;
  margin: 0;
  overflow: hidden;
  background: var(--graphite-deep);
}

.plate__frame {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: var(--graphite-deep);
}

/* The empty state. A held frame: warm graphite, a fine diagonal ruling, and
   the same grain the stage uses. It must not read as a broken image, and it
   must not pretend to be a photograph either. */
.plate__frame[data-plate-empty] {
  background:
    repeating-linear-gradient(
      -45deg,
      rgba(255, 255, 255, 0.05) 0 1px,
      transparent 1px 10px
    ),
    radial-gradient(
      120% 90% at 22% 12%,
      rgba(255, 255, 255, 0.07),
      transparent 62%
    ),
    linear-gradient(158deg, #2c251d, #15110d);
}

.plate__frame[data-plate-empty]::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: 0.32;
  mix-blend-mode: overlay;
  background-image: var(--grain);
  background-size: 220px 220px;
  pointer-events: none;
}

/* Styled ahead of the photography. Adding one <img class="plate__image"> to a
   frame and removing data-plate-empty is the whole integration step. */
.plate__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) contrast(1.06) brightness(0.92);
}

.plate__caption {
  position: absolute;
  z-index: 2;
  right: 18px;
  bottom: 16px;
  left: 18px;
  display: flex;
  align-items: baseline;
  color: rgba(255, 255, 255, 0.68);
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.13em;
  line-height: 1.3;
  text-transform: uppercase;
}

/* Routes ------------------------------------------------------------------ */

.route {
  position: absolute;
  z-index: 1;
  inset: 0;
  width: 100%;
  height: 100%;
}

.route__line {
  fill: none;
  stroke: var(--signal-orange-invert);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 0.5 11;
}

/* The pin is one <use> instance per placement, so its two parts carry their
   own classes: a selector that reached in from .route__pin would stop at the
   instance boundary. */
.route__pin-body {
  fill: var(--signal-orange-invert);
}

.route__pin-eye {
  fill: var(--graphite-deep);
}

/* Statement panel --------------------------------------------------------- */

.field__panel {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: clamp(30px, 3.2vw, 54px) var(--field-gutter)
    clamp(30px, 3.2vw, 48px);
  color: var(--ink);
  background: var(--paper);
  border-left: 1px solid var(--line);
}

.field__panel h2 {
  max-width: 14ch;
  margin: 0;
  font-size: clamp(40px, 4.6vw, 86px);
  letter-spacing: -0.055em;
  line-height: 0.92;
}

.field__line {
  display: block;
}

/* Contact sheet ----------------------------------------------------------- */

.field__sheet {
  position: relative;
  overflow: hidden;
  background: var(--graphite-deep);
  border-top: 1px solid var(--plate-line);
}

/* The film edge. Two sprocket rails printed on the strip itself, so the
   frames read as one length of film rather than as six tiles. */
.field__sheet::before,
.field__sheet::after {
  content: "";
  position: absolute;
  z-index: 3;
  right: 0;
  left: 0;
  height: 14px;
  background:
    repeating-linear-gradient(
      90deg,
      rgba(255, 255, 255, 0.16) 0 9px,
      transparent 9px 24px
    ),
    var(--graphite);
  pointer-events: none;
}

.field__sheet::before {
  top: 0;
}

.field__sheet::after {
  bottom: 0;
}

.field__sheet-track {
  display: flex;
  height: 100%;
  padding: 14px 0;
  will-change: transform;
}

.plate--frame {
  flex: none;
  width: clamp(190px, 17vw, 250px);
  border-right: 1px solid var(--plate-line);
}

.plate--frame .plate__caption {
  right: 12px;
  bottom: 10px;
  left: 12px;
  font-size: 10px;
  letter-spacing: 0.1em;
}

/* Closing row ------------------------------------------------------------- */

.field__closing,
.field__detail {
  border-top: 1px solid var(--plate-line);
}

.field__detail {
  border-left: 1px solid var(--plate-line);
}

.field__link {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 0 var(--field-gutter);
  background: var(--paper);
  border-top: 1px solid var(--line);
  border-left: 1px solid var(--line);
}

.field__link a {
  display: flex;
  gap: 14px;
  align-items: center;
  white-space: nowrap;
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-decoration: none;
  text-transform: uppercase;
}

.field__rule {
  width: clamp(28px, 3.4vw, 56px);
  height: 1px;
  background: var(--line-strong);
  transform-origin: left;
}

.field__link svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
}

@media (max-width: 820px) {
  /* One column in source order. The closing plate and its detail keep sitting
     side by side: a single tall stack of plates loses the mosaic entirely. */
  .field__mosaic {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: auto;
  }

  .field__lead {
    grid-area: auto / 1 / auto / 3;
    height: clamp(280px, 68vw, 460px);
  }

  .field__panel {
    grid-area: auto / 1 / auto / 3;
    padding: 34px clamp(22px, 6vw, 40px) 40px;
    border-top: 1px solid var(--line);
    border-left: 0;
  }

  .field__panel h2 {
    max-width: none;
    font-size: clamp(38px, 10.5vw, 62px);
  }

  .field__sheet {
    grid-area: auto / 1 / auto / 3;
    height: clamp(190px, 46vw, 240px);
  }

  .field__closing {
    grid-area: auto / 1 / auto / 2;
    height: clamp(220px, 54vw, 320px);
  }

  .field__detail {
    grid-area: auto / 2 / auto / 3;
    height: clamp(220px, 54vw, 320px);
  }

  .field__link {
    grid-area: auto / 1 / auto / 3;
    justify-content: space-between;
    height: 92px;
    border-left: 0;
  }

  /* The rule stretches to fill the row, so the anchor has to own the full
     width first: a content-sized flex container leaves nothing to grow into
     and the rule collapses to zero. */
  .field__link a {
    width: 100%;
  }

  .field__rule {
    flex: 1;
    width: auto;
    margin: 0 4px;
  }
}

/* ---------------------------------------------------------------------------
   Footer

   The page's final surface carries one route and one record. The route is the
   proposal; every other destination is already in the header, so repeating it
   here only made the surface longer. The record is the part no other surface
   can carry: the legal entity, its BTK authorisation, and the line that
   answers. The generated graphite texture is intentionally quiet enough to
   sit behind body-size text without competing with it.
   --------------------------------------------------------------------------- */

.site-footer {
  position: relative;
  overflow: hidden;
  color: var(--paper-bright);
  background-color: var(--graphite-deep);
  background-image: linear-gradient(
    rgba(26, 21, 16, 0.82),
    rgba(26, 21, 16, 0.93)
  );
  background-position: center, center;
  background-size: auto, 520px 520px;
  border-top: 1px solid var(--graphite-line);
}

.site-footer.is-texture-ready {
  background-image:
    linear-gradient(rgba(26, 21, 16, 0.82), rgba(26, 21, 16, 0.93)),
    url("../img/footer-graphite-grid-texture-v1.png");
  background-image:
    linear-gradient(rgba(26, 21, 16, 0.82), rgba(26, 21, 16, 0.93)),
    image-set(
      url("../img/footer-graphite-grid-texture-v1.webp") type("image/webp"),
      url("../img/footer-graphite-grid-texture-v1.png") type("image/png")
    );
}

.site-footer__cta {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: end;
  padding: clamp(52px, 7vw, 106px) clamp(24px, 5vw, 76px)
    clamp(44px, 5.5vw, 78px);
  color: var(--ink);
  background: var(--signal-orange);
}

.site-footer__cta p {
  margin: 0 0 clamp(18px, 2vw, 30px);
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.site-footer__cta h2 {
  margin: 0;
  font-size: clamp(68px, 11vw, 170px);
  font-weight: 530;
  letter-spacing: -0.075em;
  line-height: 0.76;
}

.site-footer__actions a {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding: 17px 22px;
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-decoration: none;
  text-transform: uppercase;
}

.site-footer__actions svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-linecap: square;
  stroke-width: 1.5px;
  transition: transform 0.2s ease;
}

/* One route across the full width. The label stands at the left gutter and
   the arrow at the right one, so the strip reads as a door rather than as a
   button that lost its two neighbours. */
.site-footer__actions {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  padding: 1px 0 0;
  background: var(--graphite-deep);
  border-bottom: 1px solid var(--graphite-line);
}

.site-footer__actions a {
  position: relative;
  overflow: hidden;
  min-height: clamp(84px, 8vw, 122px);
  padding-inline: clamp(24px, 5vw, 76px);
  font-size: 12px;
  color: var(--ink);
  background: var(--signal-orange);
}

.site-footer__action-fill {
  position: absolute;
  z-index: 0;
  inset: 0;
  pointer-events: none;
  background: var(--graphite);
  transform: scaleX(0);
  transform-origin: left center;
}

.site-footer__actions strong,
.site-footer__actions svg {
  position: relative;
  z-index: 1;
}

.site-footer__actions strong {
  font: inherit;
}

.site-footer__actions svg {
  transition: none;
}

/* The mark and the record are bottom-aligned rather than centred. Centring
   two blocks of unequal height in a 640px band leaves the shorter one adrift
   with empty space above and below it; a shared baseline gives the record a
   place to stand. The hairline between the columns is the second half of the
   same job. */
.site-footer__body {
  /* Declared on the body, not on the mark, because the record reads it too:
     the lockup inside the cloud is a fixed fraction of the mark in the
     registered logo, not a fixed number of pixels. */
  --mark-width: clamp(540px, 52vw, 760px);
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(400px, 40%);
  align-items: end;
  min-height: clamp(500px, 43vw, 640px);
  padding-bottom: clamp(40px, 4vw, 64px);
}

.site-footer__mark {
  display: block;
  width: var(--mark-width);
  color: inherit;
  text-decoration: none;
  transform: translateX(-20%);
  will-change: opacity;
}

.site-footer__mark img {
  display: block;
  width: 100%;
  height: auto;
  will-change: transform;
}

/* The lockup inside the cloud. Vertically it sits where the registered logo
   puts it - low on the body, clear of the upper lobe and of the two signal
   arcs. Horizontally it hugs the left edge of the page: 20% is exactly the
   bleed the mark carries, so this cancels it and the word starts where the
   viewport does.

   A column flex box is what puts the descriptor under the word's first letter
   rather than under its centre. */
.site-footer__lockup {
  position: absolute;
  top: 77.5%;
  left: 20%;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* The independent translate property, not a transform: the entrance tween
     travels this element on x, and a transform here would be the thing GSAP
     overwrites - taking the placement with it. */
  translate: 0 -50%;
}

/* Written the way the header writes it: the display family at the header's
   own weight and tracking, split into the two words that carry the brand's
   two tones. The pairing is the one the header already uses on a signal
   ground - ink on the orange, paper for the second word. */
.site-footer__wordmark {
  font-family: var(--font-display);
  font-size: calc(var(--mark-width) * 0.15);
  font-weight: 650;
  letter-spacing: -0.045em;
  line-height: 1;
}

.site-footer__wordmark .brand__word-cloud {
  color: var(--ink);
}

.site-footer__wordmark .brand__word-cell {
  color: var(--paper-bright);
}

.site-footer__tagline {
  padding-left: 0.06em;
  color: rgba(39, 20, 14, 0.78);
  font-family: var(--font-display);
  font-size: calc(var(--mark-width) * 0.038);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.1;
}

/* The record panel. It runs the full height of the body and carries the
   hairline itself, so the column stays a panel even where its text does not
   reach: the reader sees a bounded field, not a paragraph adrift on a dark
   plate. */
.site-footer__record {
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  align-self: stretch;
  justify-content: flex-end;
  padding: clamp(48px, 5vw, 76px) clamp(24px, 5vw, 76px)
    clamp(8px, 1vw, 16px) clamp(28px, 3.4vw, 56px);
  border-left: 1px solid var(--graphite-line);
}

.site-footer__record-name {
  margin: 0 0 14px;
  color: var(--paper-bright);
  font-family: var(--font-display);
  font-size: clamp(20px, 1.6vw, 26px);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

/* The authorisation reads as what it is: three stamped tokens, not a
   sentence. This is the one fact on the page that separates an operator from
   a reseller, so it is given a form the eye stops on. */
.site-footer__record-licence {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 0 16px;
}

.site-footer__record-licence span {
  padding: 5px 9px;
  color: var(--signal-orange-invert);
  font-family: var(--font-ui);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border: 1px solid rgba(240, 92, 34, 0.55);
}

.site-footer__record-note {
  max-width: 46ch;
  margin: 0 0 clamp(24px, 2.4vw, 34px);
  color: var(--muted-invert);
  font-size: 13px;
  line-height: 1.6;
}

/* Label left, value right, one hairline per row: the layout a registry entry
   already has on the legal page, brought down to footer size. */
.site-footer__record-rows {
  display: grid;
  width: 100%;
  margin: 0;
  border-top: 1px solid var(--graphite-line);
}

.site-footer__record-rows > div {
  display: grid;
  grid-template-columns: 118px minmax(0, 1fr);
  gap: 16px;
  align-items: baseline;
  padding: 13px 0;
  border-bottom: 1px solid var(--graphite-line);
}

.site-footer__record-rows dt {
  color: var(--muted-invert);
  font-family: var(--font-ui);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.site-footer__record-rows dd {
  margin: 0;
  color: var(--paper-bright);
  font-size: 13px;
  line-height: 1.55;
}

.site-footer__record-rows a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid rgba(240, 92, 34, 0.55);
}

.site-footer__record-more {
  display: inline-flex;
  gap: 12px;
  align-items: center;
  margin-top: clamp(20px, 2vw, 30px);
  color: var(--paper-bright);
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-decoration: none;
  text-transform: uppercase;
}

.site-footer__record-more svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-linecap: square;
  stroke-width: 1.5px;
  transition: transform 0.2s ease;
}

.site-footer__record a:hover,
.site-footer__record a:focus-visible {
  color: var(--signal-orange-invert);
}

.site-footer__record-more:hover svg,
.site-footer__record-more:focus-visible svg {
  transform: translateX(6px);
}

.site-footer__legal {
  display: flex;
  flex-wrap: wrap;
  gap: 14px clamp(18px, 2.5vw, 40px);
  align-items: center;
  min-height: 68px;
  padding: 18px clamp(24px, 5vw, 76px);
  color: var(--muted-invert);
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border-top: 1px solid var(--graphite-line);
}

.site-footer__legal a {
  color: inherit;
  text-decoration: none;
}

.site-footer__legal a:hover,
.site-footer__legal a:focus-visible {
  color: var(--paper-bright);
}

/* The two legal links are pushed to the far side, so the bar splits into what
   the company is on the left and where to read its terms on the right. */
.site-footer__legal a:first-of-type {
  margin-left: auto;
}

@media (max-width: 820px) {
  .site-footer__cta {
    grid-template-columns: minmax(0, 1fr);
    padding: 52px 24px 44px;
  }

  .site-footer__cta h2 {
    max-width: 8ch;
    font-size: clamp(64px, 18vw, 100px);
    line-height: 0.85;
  }

  .site-footer__actions a {
    min-height: 76px;
    font-size: 11px;
  }

  /* One column, and the two blocks stop fighting for the same width. The mark
     gets the full measure of the screen instead of 56vw, which is what makes
     the descriptor readable again rather than eight pixels tall. */
  .site-footer__body {
    --mark-width: 104vw;
    grid-template-columns: minmax(0, 1fr);
    gap: 30px;
    align-items: start;
    min-height: 0;
    padding-top: 26px;
    padding-bottom: 0;
  }

  .site-footer__record {
    justify-content: flex-start;
    padding: 30px 24px 34px;
    border-top: 1px solid var(--graphite-line);
    border-left: 0;
  }

  .site-footer__record-name {
    font-size: 19px;
  }

  .site-footer__record-note {
    font-size: 12px;
  }

  .site-footer__record-rows > div {
    grid-template-columns: minmax(0, 1fr);
    gap: 5px;
    padding: 12px 0;
  }

  .site-footer__record-rows dd {
    font-size: 12.5px;
  }

  .site-footer__legal {
    padding: 20px 24px;
    line-height: 1.4;
  }

  .site-footer__legal a:first-of-type {
    width: 100%;
    margin-left: 0;
  }
}

/* Hareket azaltıldığında sahne sabitlenmez: küre tek ekranlık bir blok,
   üç kart ve omurga kanıtı onun altında normal akışta okunur. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
  }

  .stage,
  .stage__inner {
    height: auto;
  }

  .stage__inner {
    position: static;
    padding-bottom: 72px;
  }

  /* Sahne sabitlenmediğinde bant normal akışta durur; anıştırdığı düzlem
     aynı, yalnızca konumlandırması değişir. */
  /* The pinned layout positions this band with insets. Once it is static the
     same insets survive as relative offsets and push the band past the right
     edge of the viewport, so the headline loses its outer margin. Clearing
     them lets the padding below own the spacing. */
  .stage__title {
    position: relative;
    inset: auto;
    max-width: none;
    padding: calc(var(--header-height) + 56px) clamp(22px, 5vw, 76px) 0;
  }

  .stage__title::before {
    inset: 0 0 -30px;
  }

  .stage__globe {
    position: relative;
    inset: auto;
    height: 78svh;
    margin-top: 24px;
  }

  .stage__focus {
    display: none;
  }

  /* Sahne sabitlenmediğinde atlas kadrajı da yok; gösterge taşıdığı oranı
     zaten kanıt bloğunun ilk maddesi yazıyor, bu yüzden içerik kaybı olmadan
     kaldırılabilir. */
  .stage__uptime {
    display: none;
  }

  .stage__evidence {
    position: static;
    width: auto;
    padding: 56px clamp(22px, 5vw, 76px) 0;
    color: var(--ink);
  }

  /* Kanıt bloğu artık kürenin üstünde durmuyor; okunurluk perdesi gereksiz
     ve statik akışta yatay taşma yaratıyordu. */
  .stage__evidence::before {
    display: none;
  }

  .stage__evidence li {
    color: var(--muted);
    border-top-color: var(--line);
  }

  .stage__evidence strong {
    color: var(--ink);
  }

  .stage__eyebrow--invert {
    color: var(--orange-deep);
  }

  .clients__marquee {
    overflow-x: auto;
    scroll-snap-type: x mandatory;
  }

  .client-cell {
    scroll-snap-align: start;
  }

  .service-stack__track {
    height: auto !important;
    margin-bottom: 0 !important;
  }

  .service-stack__list {
    position: static;
    transform: none !important;
  }

  .service-card {
    height: auto !important;
    overflow: visible !important;
  }

  .service-card__content {
    height: auto;
    min-height: calc(
      var(--service-card-expanded) - var(--service-card-collapsed)
    );
    opacity: 1 !important;
    transform: none !important;
  }

  /* Nothing in the band is created by script under reduced motion: the plates
     are already uncovered, both routes are already drawn at full length, and
     every pin is already in place. Only the contact sheet needs a hand - it
     stops advancing on scroll, so it becomes a strip the visitor can pan. */
  .field__sheet {
    overflow-x: auto;
    scroll-snap-type: x mandatory;
  }

  .plate--frame {
    scroll-snap-align: start;
  }
}
