/* =====================================================================
   GOLD ERP — Tasarim Sistemi "Baskı Kontrol Şeridi"  v2.3.0
   =====================================================================
   Bu dosya alti katmandan uretilmistir. ELLE DUZENLEMEYIN;
   katmanlari duzenleyip yeniden birlestirin.

     10-tokens      belirtecler, reset, tipografi, odak, cikti
     20-primitives  buton, girdi, tablo, panel, rozet, dialog, toast
     30-shell       giris ekrani, uygulama kabugu, kenar cubugu, kontrol seridi
     40-screens-a   uretim akisi: is emri, olcu, renk, uretim, kalite, arsiv
     50-screens-b   yonetim: stok, muhasebe, personel, musteri, rapor, ayarlar
     60-responsive  3 breakpoint (1250/900/560), mobil cekmece, dokunma hedefleri

   Kurallar: tek :root, !important yok (.hidden/[hidden] haric),
   gradyan/blur/neon yok, sayisal veri mono+tabular-nums.
   ===================================================================== */



/* ==================== 10-tokens.css ==================== */

/* ============================================================
   GOLD ERP v1.21.6 — KATMAN 1/6: TEMEL
   Belirteçler · reset · gövde · tipografi · sayısal tipografi ·
   odak · gizleme · kaydırma çubuğu · çıktı (yalnızca çekişmeyen kısmı)
   Tek :root bu dosyada. Diğer katmanlar yalnızca var(--x) kullanır.
   BURADA OLMAYANLAR — bilinçli: bağlantı biçimi (20-primitives),
   hareket azaltma bloğu ve çekişen baskı bildirimleri (60-responsive).
   ============================================================ */

/* === BELİRTEÇLER — TEK :root === */
:root{
  /* Yüzey — arayüzün %95'i (lacivert/mavi tema, R7) */
  --k:#1B2333;            /* mürekkep siyahı */
  --k-2:#26314A;          /* yükseltilmiş koyu yüzey */
  --k-3:#36435E;          /* koyu kenarlık */
  --paper:#F8F9FB;        /* kuşe olmayan kâğıt — ana zemin */
  --paper-2:#EDF1F7;      /* ikincil zemin, tablo başlığı */
  --surface:#FFFFFF;      /* kart yüzeyi */
  --line:#D7DEE9;         /* saç teli kenarlık */
  --line-2:#E9EEF5;       /* daha silik kenarlık */
  --ink:#1F2937;          /* ana metin */
  --ink-2:#4B5563;        /* ikincil metin */
  --ink-3:#636C7B;        /* silik metin / etiket — WCAG AA 4.5:1 DOĞRULANDI:
                             --surface 5,35:1 · --paper 5,11:1 · --paper-2 4,68:1
                             (soft tonlarda da geçer: m 4,55 · c 4,74 · y 5,02 ·
                             plate 4,64 · ok 4,69 · no 4,57). Daha açık hiçbir
                             değer üç zeminin hepsini geçmiyor — yükseltme. */

  /* Proses renkleri — YALNIZCA anlam taşıyan yerlerde */
  --m:#1D4ED8;            /* magenta = TEK etkileşim rengi */
  --m-hover:#1740AF;
  --m-soft:#E7EEFD;
  --c:#0E7490;            /* cyan = aktif aşama / bilgi */
  --c-soft:#E3F1F5;
  --y:#B45309;            /* sarı = bekleyen / uyarı */
  --y-soft:#FBF3E2;
  --plate:#A66634;        /* ham klişe amberi = arşiv/klişe bağlamı */
  --plate-soft:#F5EBE0;
  --ok:#15803D;           /* tamamlandı */
  --ok-soft:#E6F3EA;
  --no:#B91C1C;           /* hata / iptal */
  --no-soft:#FBEAEA;

  /* Tipografi */
  --ui:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --mono:ui-monospace,"SF Mono","Cascadia Mono","Roboto Mono",Consolas,"Liberation Mono",monospace;

  /* Ölçek — 4px tabanlı */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px; --s7:48px;
  --r1:4px; --r2:8px; --r3:12px;   /* yarıçap — DÜŞÜK tutulur, alet gibi */
  --tap:44px;                       /* minimum dokunma hedefi */

  /* Gölge — çok az, kâğıt gibi. Kullanım amacı belirteçle birlikte kilitli. */
  --sh1:0 1px 2px rgba(18,18,22,.06);   /* panel / kart — yüzeyden 1 kademe */
  --sh2:0 4px 12px rgba(18,18,22,.08);  /* açılır liste, yüzen şerit — ORTA kademe.
                                           Şu an çağıran yok; ölçeğin ortasını
                                           belgelemek için DURUYOR (SPEC §2 listesi).
                                           Yeni yüzen öge gelirse sh1/sh3 arası
                                           uydurulmaz, bu kullanılır. */
  --sh3:0 16px 40px rgba(18,18,22,.16); /* dialog / çekmece — en üst kademe */

  /* YEDEĞE DÜŞEN BELİRTEÇLER — değerler BİLEREK bugünkü yedeklerin aynısı.
     CSS'te `var(--card,#fff)`, `var(--hover,#eef2ff)`, `var(--muted,#6b7280)`,
     `var(--warn,#b45309)` yazan kurallar vardı ama bu dört belirteç :root'ta
     HİÇ tanımlı değildi; hepsi sessizce yedeğe düşüyordu. Açık temada hiçbir
     şey değişmez (aynı renkler), ama koyu tema tanımsız belirteci DEVRALAMAZ:
     tanımlanmasaydı açılır liste (.secim-listesi) ve satır vurgusu koyu
     zeminde BEYAZ kalırdı. Koyu tema bunlar olmadan doğru olamazdı. */
  --card:#FFFFFF;
  --hover:#EEF2FF;
  --muted:#6B7280;
  --warn:#B45309;
}

/* ==================== TEMA ŞABLONLARI ====================
   `applyAppearanceSettings()` gövdeye data-theme / data-accent yazıyor
   (web/js/13-ayarlar-ve-si-stem-guvenli.js). BU KURALLAR YOKTU: öznitelik
   gövdeye yazılıyor, hiçbir kural onu okumuyordu. Ayar kaydediliyor,
   "AYARLAR KAYDEDİLDİ ✓" yazıyor, ekran hiç değişmiyordu.

   NEDEN EMİNİZ: aynı fonksiyondaki diğer iki seçenek ÇALIŞIYORDU
   (body.compact-mode, body.hide-slogan) — çünkü onların CSS karşılığı
   vardı. Fark tam olarak buydu.

   Yalnızca BELİRTEÇ değiştiriliyor; tek bir yerleşim/boyut kuralı bile
   değil. Arayüzün geri kalanı zaten var(--x) okuyor, bu yüzden koyu tema
   kendiliğinden yayılıyor.

   SIRA ÖNEMLİ: vurgu blokları temadan SONRA gelir. İkisi de gövde
   üzerinde ve özgüllükleri EŞİT (0,1,1); eşitlikte kaynak sırası kazanır.
   Vurgu önce yazılsaydı koyu tema onu ezer, vurgu rengi çalışmazdı. */

body[data-theme="dark"]{
  --k:#0B0F16;
  --k-2:#151B27;
  --k-3:#2A3346;
  --paper:#12161F;
  --paper-2:#1A2130;
  --surface:#171E2B;
  --line:#2C3648;
  --line-2:#232C3C;
  --ink:#E8ECF3;
  --ink-2:#B4BECD;
  --ink-3:#93A0B2;
  --card:#171E2B;
  --hover:#1E2940;
  --muted:#93A0B2;
  --warn:#E0952B;
  --m:#5B8DEF;
  --m-hover:#7FA9F7;
  --m-soft:#16243F;
  --c:#22A5C4;
  --c-soft:#0E2A33;
  --y:#E0952B;
  --y-soft:#332610;
  --plate:#C98B52;
  --plate-soft:#33241A;
  --ok:#42B072;
  --ok-soft:#123020;
  --no:#E5605C;
  --no-soft:#361719;
}

body[data-accent="gold"]{
  --m:#A67908;
  --m-hover:#8A6406;
  --m-soft:#F7EFD9;
}
body[data-accent="navy"]{
  --m:#1E3A6E;
  --m-hover:#16294F;
  --m-soft:#E4E9F2;
}

body[data-theme="dark"][data-accent="gold"]{
  --m:#D9A73C;
  --m-hover:#E8BC5E;
  --m-soft:#332916;
}
body[data-theme="dark"][data-accent="navy"]{
  --m:#7C9BD4;
  --m-hover:#9AB3E0;
  --m-soft:#1A2438;
}

/* === RESET === */
*,*::before,*::after{box-sizing:border-box}

body,h1,h2,h3,h4,h5,h6,p,figure,blockquote,dl,dd,fieldset,legend,pre{margin:0}

img,svg,video,canvas,iframe{display:block;max-width:100%}
img,video{height:auto}

button,input,select,textarea{font:inherit;color:inherit}
button{background:transparent;border:0;padding:0;text-align:inherit;cursor:pointer}
button[disabled],input[disabled],select[disabled],textarea[disabled]{cursor:not-allowed}

/* uygulama <em> ve <i> ögelerini vurgu için değil, kap olarak kullanıyor */
em,i,address{font-style:normal}

body{
  background:var(--paper);
  color:var(--ink);
  font-family:var(--ui);
  font-size:14px;
  line-height:1.5;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}

/* === TİPOGRAFİ TABANI === */
h1,h2,h3,h4,h5,h6{font-family:var(--ui);letter-spacing:-.01em;line-height:1.22}
h5,h6{font-size:14px;font-weight:650}

b,strong{font-weight:650}

/* Mikro etiket — kontrol şeridi künyesi. SPEC §3 kapsamı: ALAN ADI,
   alan grubu adı, tablo başlığı. Yalnızca gerçek etiket ögeleri:
   <label>, <legend>, .field-title. <small> BU AİLEDE DEĞİL — bkz. aşağı. */
label,legend,.field-title{
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-3);
  line-height:1.45;
}
legend,.field-title{display:block}

/* <small> = ikincil AÇIKLAMA metni, etiket değil.
   Uygulamada <small> hem etiket hem tam cümle taşıyor; cümleleri uppercase +
   .08em ile basmak okunabilirliği yıkıyordu ("KAMERA VE GALERİDEN EKLENEN
   GÖRSELLER BİRLİKTE KORUNUR..."). Etiket olarak kullanılan <small> içeriği
   HTML/JS'te zaten büyük harfle yazılı ("MÜŞTERİ KODU", "GOLD ERP WEB"),
   bu yüzden dönüşümü kaldırmak etiket görünümünü bozmuyor. */
small{
  display:block;
  font-size:11px;
  font-weight:400;
  letter-spacing:normal;
  text-transform:none;
  line-height:1.5;
  color:var(--ink-3);
}

/* Etiketin içindeki denetim mikro etiket tipografisini MİRAS ALMAZ */
label input,label select,label textarea,label button,label code{
  font-size:14px;
  font-weight:400;
  letter-spacing:normal;
  text-transform:none;
  color:var(--ink);
}

/* === SAYISAL TİPOGRAFİ ===
   Ölçü aleti karakteri: mm/cm² ölçüleri, iş no, müşteri kodu, adet,
   tutar, tarih, yüzde — hepsi mono + tabular figürler. */
code,kbd,samp,pre,
input[type="number"],input[type="date"],input[type="time"],
input[type="datetime-local"],input[type="month"],input[type="week"],
input[inputmode="decimal"],input[inputmode="numeric"],input[inputmode="tel"],
.phone-mask,
.cmyk-values,.pantone-definition b,
.measure-line,.production-measure-list,.measure-footer b,
.measure-entry input,.production-measure-entry input,.dimension-fields input,
.calc-row input,.calc-row b,.calc-summary-grid b,.grand-total b,.tl-total b,
.slider-row span,
.stock-quantity-cell,.stock-current-box b,
.tracking-due,.tracking-hero-count b,.tracking-summary b,
.archive-counter b,.archive-stage span,.archive-stage small,
.tracking-stage span,.tracking-stage small,
.job-summary b,.customer-head-code b,
.management-stat b,.workflow-metric b,.workflow-column-head b,
.top-graphic-copy span,.top-graphic-breakdown em,
.quality-stat b,.production-metric-grid b,
.stock-summary-card b,.personnel-summary-card b,
.accounting-stat b,.report-stat b,.reports-mini-stats b,
.bar-row b,.rank-row b,.rank-row em,
.system-status-card b,.smart-data-grid b,.test-reset-preview b{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1;
}

/* Kod/yol gibi teknik dizeler biraz küçülür */
code,kbd,samp{font-size:12px;color:var(--ink-2);word-break:break-all}

/* === SEÇİM · YER TUTUCU ===
   BAĞLANTI biçimi bilinçli olarak BURADA DEĞİL: tek sahibi 20-primitives
   (`a` renk/altçizgi + `a:focus-visible`). Aynı seçiciyi iki katmanda yazmak
   önceki bildirimi ölü koda çeviriyordu. */
::selection{background:var(--m-soft);color:var(--ink)}

/* === GÖRÜNÜR KLAVYE ODAĞI === */
:focus-visible{outline:2px solid var(--m);outline-offset:2px}

/* `a` bu listede YOK: bağlantı odağı 20-primitives'in tek sahipliğinde.
   Yukarıdaki genel :focus-visible bağlantıyı da kapsıyor, odak kaybı olmaz. */
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible{
  outline:2px solid var(--m);
  outline-offset:1px;
  box-shadow:0 0 0 3px var(--m-soft);
}

/* Fare tıklamasında halka çizilmez; klavye odağı yukarıda korunur */
:focus:not(:focus-visible){outline:none}

/* === HAREKET AZALTMA — BU KATMANDA DEĞİL ===
   `*,*::before,*::after` seçicisi özgüllük 0 taşır ve bu dosya İLK katmandır;
   sonraki her `transition:` bildirimi (button, input, tbody tr, nav button,
   .workflow-metric, .pantone-row, #toast ...) onu eziyordu — hareket azaltma
   fiilen çalışmıyordu. !important yasak olduğu için tek doğru yer SON katman.
   TAM BLOK 60-responsive.css dosya sonuna taşındı. (`scroll-behavior` bildirimi
   düşürüldü: hiçbir katman `smooth` yazmıyor, app.js:2136'daki
   `scrollIntoView({behavior:"smooth"})` ise CSS ile bastırılamaz — JS turunun işi.) */

/* === GİZLEME — !important yalnızca bu iki kuralda === */
.hidden{display:none!important}
[hidden]{display:none!important}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
html {
  -webkit-text-size-adjust: 100%;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}

::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{
  background:var(--line);
  border:3px solid transparent;
  background-clip:padding-box;
  border-radius:99px;
}
::-webkit-scrollbar-thumb:hover{background:var(--ink-3);background-clip:padding-box}
::-webkit-scrollbar-corner{background:transparent}

/* === ÇIKTI — matbaa ERP'si, föy ve liste basılır ===
   BURADA YALNIZCA sonraki katmanların ÇEKİŞMEDİĞİ bildirimler durur.
   Bu dosya ilk katman; sonraki bir katman aynı seçiciye aynı özelliği yazdığı
   anda buradaki baskı bildirimi ölür (!important yasak, özgüllük hilesi de
   @layer altında işe yaramaz). Bu yüzden çekişen bildirimler SON katmana
   taşındı — bkz. 60-responsive.css dosya sonu. */

/* ===================================================================
   KOK SEVIYE GERI YUKLEME — CSS birlestirme onarimi

   NE OLDU
     Yinelenen secicileri birlestiren arac, bir secicinin kok seviyedeki
     tanimi ile @media icindeki tanimini AYNI kural sayip tek kurala
     indirdi ve sonucu son gordugu yere - yani medya blogunun icine -
     yazdi. Kural masaustunde ARTIK HIC UYGULANMIYOR.

   NASIL GORUNDU
     Is emri karti basligi alt alta dizildi (musteri revizesi R5),
     PDF onizleme 300x150px'e dustu (R6). Musterinin bildirmedigi
     18 secici daha ayni durumdaydi.

   NEDEN FARK EDILMEDI
     Birlestirmenin dogrulugu "hangi deger kazaniyor" diye sinanmisti;
     o karsilastirma MEDYA BAGLAMINI hesaba katmiyordu. Medya blogunun
     icine tasinan kural, araca gore hala ayni degeri kazaniyordu.

   BURADAKI KURALLAR birlestirme oncesi dosyadan OZGUN METNIYLE alindi.
   Konum bilincli: ilk @media'dan once, boylece mobil kurallar ezmeye
   devam eder.
   =================================================================== */

body,h1,h2,h3,h4,h5,h6,p,figure,blockquote,dl,dd,fieldset,legend,pre{margin:0}
h1,h2,h3,h4,h5,h6{font-family:var(--ui);letter-spacing:-.01em;line-height:1.22}
h1{font-size:34px;font-weight:700}
h2{font-size:26px;font-weight:700}
h3{font-size:20px;font-weight:650}
h4{font-size:16px;font-weight:650}
code,kbd,samp,pre,
input[type="number"],input[type="date"],input[type="time"],
input[type="datetime-local"],input[type="month"],input[type="week"],
input[inputmode="decimal"],input[inputmode="numeric"],input[inputmode="tel"],
.phone-mask,
.cmyk-values,.pantone-definition b,
.measure-line,.production-measure-list,.measure-footer b,
.measure-entry input,.production-measure-entry input,.dimension-fields input,
.calc-row input,.calc-row b,.calc-summary-grid b,.grand-total b,.tl-total b,
.slider-row span,
.stock-quantity-cell,.stock-current-box b,
.tracking-due,.tracking-hero-count b,.tracking-summary b,
.archive-counter b,.archive-stage span,.archive-stage small,
.tracking-stage span,.tracking-stage small,
.job-summary b,.customer-head-code b,
.management-stat b,.workflow-metric b,.workflow-column-head b,
.top-graphic-copy span,.top-graphic-breakdown em,
.quality-stat b,.production-metric-grid b,
.stock-summary-card b,.personnel-summary-card b,
.accounting-stat b,.report-stat b,.reports-mini-stats b,
.bar-row b,.rank-row b,.rank-row em,
.system-status-card b,.smart-data-grid b,.test-reset-preview b{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1;
}
.table{overflow:auto;border-radius:var(--r1)}
.toolbar{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--s2);
  margin-bottom:var(--s3);
}
.toolbar button{flex:0 0 auto}
#toast{
  position:fixed;
  right:var(--s5);
  top:var(--s5);
  z-index:9999;
  max-width:min(420px,calc(100vw - var(--s6)));
  padding:var(--s3) var(--s4);
  border-radius:var(--r2);
  background-color:var(--k);
  color:#fff;
  font:600 13px/1.45 var(--ui);
  box-shadow:var(--sh3);
  opacity:0;
  pointer-events:none;
  transition:opacity .16s;
}
dialog{
  margin:auto;
  padding:0;
  border:0;
  border-radius:var(--r3);
  background:var(--surface);
  color:var(--ink);
  box-shadow:var(--sh3);
  max-width:min(96vw,1200px);
  max-height:92vh;
  overflow:auto;
}
.gold-modal-header{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--s3);
  padding:var(--s3) var(--s4);
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r2);
  box-shadow:var(--sh1);
}
.alert-ok{margin-top:var(--s4);min-width:150px}
.empty-state,
.workflow-empty,
.personnel-empty,
.quality-empty,
.archive-empty,
.stock-empty,
.accounting-empty,
.reports-empty,
.revision-empty,
.system-empty,
.settings-log-empty,
.forms-preview-empty,
.archive-delivery-no-image,
.production-all-done{
  padding:var(--s5) var(--s4);
  text-align:center;
  color:var(--ink-3);
  font:600 11px/1.6 var(--ui);
  text-transform:uppercase;
  letter-spacing:.08em;
}
.empty-state,
.revision-empty,
.settings-log-empty,
.forms-preview-empty,
.archive-delivery-no-image,
.production-all-done,
div.reports-empty{
  border:1px dashed var(--line);
  border-radius:var(--r2);
  background:var(--paper);
}
.login-shell{
  width:min(1080px,100%);
  display:grid;
  grid-template-columns:minmax(0,1.02fr) minmax(0,.98fr);
  background:var(--surface);
  border:1px solid var(--k-3);
  border-radius:var(--r3);
  overflow:hidden;
  box-shadow:var(--sh3);
}
.app>aside{
  min-height:0;
  overflow-y:auto;
  overscroll-behavior:contain;
  padding-bottom:var(--s5);
  background:var(--k);
  border-right:1px solid var(--k-3);
}
.app main{
  display:flex;
  flex-direction:column;
  min-width:0;
  min-height:0;
  overflow:auto;
  overscroll-behavior:contain;
}
.app nav button{
  display:grid;
  grid-template-columns:var(--s5) minmax(0,1fr);
  align-items:center;
  justify-items:start;
  gap:var(--s2);
  width:100%;
  min-height:38px;
  padding:var(--s2) var(--s3);
  background:transparent;
  border:0;
  border-left:3px solid transparent;
  border-radius:0;
  font:inherit;
  font-size:13px;
  font-weight:600;
  line-height:1.2;
  text-align:left;
  color:rgba(255,255,255,.72);
  cursor:pointer;
  transition:background-color 140ms,color 140ms,border-color 140ms;
}
main>header{
  position:sticky;
  top:0;
  z-index:30;
  flex:0 0 auto;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--s4);
  min-height:var(--header-h);
  padding:var(--s2) var(--s5);
  background:var(--surface);
  border-bottom:1px solid var(--line);
}
.user{
  display:flex;
  align-items:center;
  gap:var(--s3);
  flex:0 1 auto;
  min-width:0;
}
.user b,
.user span{min-width:0}
.user b{
  font-size:13px;
  font-weight:600;
  color:var(--ink);
}
.user button{
  min-height:32px;
  padding:0 var(--s3);
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r1);
  font:inherit;
  font-size:12px;
  font-weight:600;
  color:var(--ink-2);
  cursor:pointer;
  transition:background-color 140ms,border-color 140ms,color 140ms;
}
.page{
  padding:var(--s5);
  min-width:0;
}
.workflow-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: stretch;
  gap: var(--s3);
}
.workflow-arrow {
  align-self: center;
  font: 400 20px/1 var(--mono);
  color: var(--ink-3);
  user-select: none;
}
.production-record {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) auto;
  gap: var(--s3);
  align-items: start;
  padding: var(--s3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}
.production-image-buttons span {
  font: 600 11px/1.4 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}
.production-image-item {
  display: grid;
  gap: var(--s1);
  padding: var(--s2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r1);
  text-align: center;
}
.job-summary {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr)) auto;
  align-items: center;
  gap: var(--s4);
  padding: var(--s4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  box-shadow: var(--sh1);
}
.job-summary b {
  display: block;
  font: 700 20px/1.2 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
}
.date-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--s2);
}
.radio-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: var(--s2);
}
.file-preview {
  display: grid;
  place-items: center;
  min-height: 420px;
  padding: var(--s3);
  background: var(--paper-2);
  border: 1px dashed var(--line);
  border-radius: var(--r1);
  overflow: hidden;
  font: 600 11px/1.6 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}
.file-preview img {
  max-width: 100%;
  max-height: 420px;
  object-fit: contain;
  background: var(--surface);
}
.job-forms-list i {
  font-style: normal;
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--m);
}
.forms-preview-empty {
  display: grid;
  place-items: center;
  min-height: 400px;
}
.forms-preview-card iframe {
  width: 100%;
  height: 100%;
  min-height: min(70vh, 820px);
  border: 1px solid var(--line);
  border-radius: var(--r1);
  background: var(--surface);
}
.color-card {
  display: grid;
  grid-template-columns: 22px 40px minmax(0, 1fr) auto auto;
  gap: var(--s3);
  align-items: center;
  padding: var(--s2) var(--s3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}
.color-card i,
.pantone-row i,
.preview-row i {
  display: block;
  border: 1px solid var(--ink-3);
  border-radius: 1px;
  background: var(--surface);
  box-shadow: var(--sh1);
}
.color-card i { width: 40px; height: 40px; }
.color-name { min-width: 0; }
.color-system {
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
  white-space: nowrap;
}
.slider-row {
  display: grid;
  grid-template-columns: 150px minmax(0, 1fr) 52px;
  gap: var(--s3);
  align-items: center;
  padding: var(--s2) 0;
  border-bottom: 1px solid var(--line-2);
}
.preview-row {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr) auto;
  gap: var(--s4);
  align-items: center;
  margin-top: var(--s4);
  padding: var(--s4);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}
.management-live{
  margin-left:auto;
  display:inline-flex;
  align-items:center;
  gap:var(--s2);
  padding:var(--s1) var(--s2);
  background:var(--ok-soft);
  border:1px solid var(--line);
  border-radius:var(--r1);
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink);
}
.app main{min-width:0}
.page{min-width:0}
.table{
  max-width:100%;
  overflow-x:auto;
  overscroll-behavior-x:contain;
  scrollbar-width:thin;
  scrollbar-color:var(--ink-3) var(--line-2);
}
.app main{
  overflow-y:auto;
  overflow-x:hidden;
  -webkit-overflow-scrolling:touch;
}
.table{
  min-width:0;
  max-width:100%;
  overflow-x:auto;
  overflow-y:visible;
  -webkit-overflow-scrolling:touch;
}
.app main{
  overflow-y:auto;
  overflow-x:clip;
}
.app main{
  overscroll-behavior-x:none;
  overscroll-behavior-y:contain;
}
.app main{
  overflow:visible;
}
.app main{max-width:100%}
.app main{overflow-x:clip;}
.page{overflow-x:clip; max-width:100%;}

@media print{
  @page{margin:14mm}

  /* `html`/`body` başka katmanda hiç geçmiyor — bu kural geçerli */
  html,body{height:auto;overflow:visible;background:#fff;color:#000}

  /* Bu iki seçiciye sonraki katmanlar `display` yazmıyor — geçerli.
     Kenar çubuğu @900'de position:fixed olduğundan kaldırılmazsa
     her sayfaya yeniden basılırdı. */
  .app>aside,#toast{display:none}

  /* Sayfa kırılması — `break-inside` başka hiçbir yerde yazılmıyor */
  .panel,tr,td,th{break-inside:avoid}
  thead{display:table-header-group}
}


/* ==================== 20-primitives.css ==================== */

/* ============================================================
   GOLD ERP — KATMAN 2: İLKELLER
   Buton, form denetimi, panel, tablo, sekme, rozet, dialog.
   Belirteçler 10-tokens katmanındadır; burada yalnızca var() kullanılır.
   ============================================================ */

/* === BUTON — taban === */
button,
.button,
.button-link{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:var(--s2);
  min-height:38px;
  padding:0 var(--s3);
  border:1px solid var(--line);
  border-radius:var(--r1);
  background:var(--surface);
  color:var(--ink);
  font:600 13px/1.2 var(--ui);
  text-align:center;
  text-decoration:none;
  white-space:nowrap;
  cursor:pointer;
  transition:background-color .14s,border-color .14s,box-shadow .14s,color .14s;
}

button:hover,
.button:hover,
.button-link:hover{background:var(--paper-2);border-color:var(--ink-3)}

button:active,
.button:active,
.button-link:active{background:var(--line-2)}

button:focus-visible,
.button:focus-visible,
.button-link:focus-visible{outline:2px solid var(--m);outline-offset:2px}

/* Birincil — tek etkileşim rengi */
button.primary,
.button.primary,
.button-link.primary{background:var(--m);border-color:var(--m);color:#fff}
button.primary:hover,
.button.primary:hover,
.button-link.primary:hover{background:var(--m-hover);border-color:var(--m-hover)}

/* Yıkıcı işlem */
button.danger{background:var(--no);border-color:var(--no);color:#fff}

/* Koyu yüzey butonu (eski .dark) */
button.dark{background:var(--k);border-color:var(--k);color:#fff}

/* Dolgu yerine konturlu proses tonları: eski .purple/.cyan/.success
   parlak renkleri bırakıldı — proses paleti yalnızca kontur+metinde. */
button.purple{color:var(--plate);border-color:var(--plate);background:var(--surface)}
button.purple:hover{background:var(--plate-soft);border-color:var(--plate)}
button.cyan{color:var(--c);border-color:var(--c);background:var(--surface)}
button.cyan:hover{background:var(--c-soft);border-color:var(--c)}
button.success{color:var(--ok);border-color:var(--ok);background:var(--surface)}
button.success:hover{background:var(--ok-soft);border-color:var(--ok)}

/* Dolgulu varyantlarda hover = 1 kademe koyulaşma.
   `filter` KULLANILMAZ: geçiş listesinde olmadığı için ani zıplıyordu.
   .danger için koyulaştırma iç gölgeyle (box-shadow geçiş listesinde var),
   .dark için --k kademeleriyle yapılır — ikisi de belirteç tabanlı. */
button.danger:hover{
  background:var(--no);
  border-color:var(--no);
  box-shadow:inset 0 0 0 100px rgba(18,18,22,.14);
}
button.dark:hover{background:var(--k-2);border-color:var(--k-3)}

/* Devre dışı */
button:disabled,
button[disabled],
.button.disabled,
.button-link.disabled{
  opacity:.45;
  box-shadow:none;
  cursor:not-allowed;
  pointer-events:none;
}

/* Küçük varyant — tablo hücresi içindeki satır işlemleri.
   32px = --s6, ölçeğe oturur (eski 30px ölçekte yoktu). */
td button{min-height:32px;padding:0 var(--s2);font-size:12px}

/* === BAĞLANTI === */
a{color:var(--m);text-decoration:underline;text-underline-offset:2px}
a:hover{color:var(--m-hover)}
a:focus-visible{outline:2px solid var(--m);outline-offset:2px}

/* === FORM DENETİMLERİ === */
label,
.field-title{
  display:block;
  font:600 11px/1.5 var(--ui);
  text-transform:uppercase;
  letter-spacing:.08em;
  color:var(--ink-3);
}
.field-title{margin:var(--s3) 0 var(--s2)}

input,
select,
textarea{
  width:100%;
  min-height:38px;
  padding:0 var(--s3);
  border:1px solid var(--line);
  border-radius:var(--r1);
  background:var(--surface);
  color:var(--ink);
  /* etiketten miras kalan büyük harf / harf aralığı sıfırlanır */
  font:400 14px/1.4 var(--ui);
  text-transform:none;
  letter-spacing:normal;
  transition:background-color .14s,border-color .14s,box-shadow .14s;
}
/* DOKUNMATİKTE OTOMATİK YAKINLAŞTIRMAYI ÖNLE
   ------------------------------------------------------------------
   iOS Safari ve Android tarayıcıları, puntosu 16px'in ALTINDA olan bir
   metin alanına odaklanıldığında sayfayı kendiliğinden yakınlaştırır.
   Alan yukarıdaki kuralda 14px olduğu için giriş ekranında kullanıcı
   adı kutusuna dokunmak bu yakınlaştırmayı tetikliyordu; yakınlaşma
   giriş yapıldıktan SONRA da geri alınmıyor ve uygulama büyütülmüş,
   yana kaymış görünüyordu.

   NEDEN `maximum-scale=1` DEĞİL
       Yakınlaştırmayı viewport etiketiyle kapatmak sorunu görünüşte
       çözer ama parmakla büyütmeyi de tümden engeller — küçük yazıyı
       okuyamayan kullanıcı için gerçek bir kayıp. Üstelik iOS 10'dan
       beri bu kısıt zaten yok sayılıyor. Doğru çözüm eşiğin üstüne
       çıkmak; yakınlaştırma kullanıcıda kalıyor.

   NEDEN YALNIZCA `pointer: coarse`
       Masaüstünde 14px bilinçli bir yoğunluk tercihi ve orada böyle bir
       davranış yok. Kural yalnızca dokunmatik girdili cihazlarda geçerli
       — bu bir MEDYA ÖZEL DAVRANIŞI, temel kuralın yerine geçmiyor.

   ÖZGÜLLÜK NOTU
       `label input` kuralı (yukarıda, mikro etiket tipografisini sıfırlayan
       kural) 14px'i (0,0,2) özgüllükle yazıyor. Buradaki liste onunla AYNI
       biçimde yazılmalı; yalnızca `input` yazmak (0,0,1) yetmez ve alanların
       neredeyse tamamı `<label>` içinde olduğu için kural sessizce hiçbir
       şey yapmaz. İlk denemede tam bu oldu. */
/* EKRAN YETKİ MATRİSİ — hangi rol hangi ekranda çalışabilir (Ayarlar) */
.izin-matrisi { display: grid; gap: var(--s4); }
.izin-rol {
  padding: var(--s3);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  background: var(--paper);
}
.izin-rol h4 { margin: 0 0 var(--s3); font-size: 14px; }
.izin-rol h4 small { color: var(--ink-3); font-weight: 400; }
.izin-kutulari {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: var(--s2);
}
.izin-kutu {
  display: flex;
  align-items: center;
  gap: var(--s2);
  min-height: var(--tap);
  padding: 0 var(--s2);
  border-radius: var(--r1);
  cursor: pointer;
}
.izin-kutu:hover { background: var(--paper-2); }
.izin-kutu input { width: auto; min-height: 0; }
.izin-kutu input:disabled + span { color: var(--ink-3); }

/* AÇIKLAMA NOTU — müşteri isteği Y5 ("fark edilsin")
   Punto bir tık büyük, kalın ve kırmızı. Özgüllük (0,1,0) olduğu için
   `label textarea` (0,0,2) kuralını da, dokunmatikteki 16px ezmesini de
   geçer — sıra bağımlı değil. */
.job-notes {
  font-size: 16px;
  font-weight: 600;
  color: var(--no);
  border-color: var(--no);
  background: var(--no-soft);
}
.job-notes::placeholder { color: var(--ink-3); font-weight: 400; }
.notes-form-picks { margin-top: var(--s2); }

/* RENK SEPETİ — çoklu renk seçimi (Y6) */
.color-basket-bar {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s3);
  margin-top: var(--s3);
  padding-top: var(--s3);
  border-top: 1px solid var(--line);
}
.color-basket { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s1); }
.basket-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  padding: var(--s1) var(--s2);
  border: 1px solid var(--line);
  border-radius: var(--r3);
  background: var(--paper);
  font-size: 12px;
}
.basket-chip i {
  width: 14px; height: 14px;
  border: 1px solid var(--line);
  border-radius: 3px;
}
.basket-chip button {
  width: auto; min-height: 0; padding: 0 4px;
  border: 0; background: none; color: var(--ink-3);
  font-size: 15px; line-height: 1; cursor: pointer;
}
.basket-chip button:hover { color: var(--no); }

/* YÖNETİLEBİLİR LİSTE (iş türleri) — Y10 */
.liste-duzenle { display: grid; gap: var(--s3); }
.liste-satir { display: flex; gap: var(--s2); }
.liste-satir input { flex: 1 1 auto; }
.liste-satir button { flex: 0 0 auto; width: auto; padding: 0 var(--s4); }
.etiket-listesi { display: flex; flex-wrap: wrap; gap: var(--s2); }
.etiket {
  display: inline-flex; align-items: center; gap: var(--s2);
  padding: var(--s1) var(--s3);
  border: 1px solid var(--line);
  border-radius: var(--r3);
  background: var(--paper-2);
  font: 600 12px/1.4 var(--ui);
}
.etiket button {
  width: auto; min-height: 0; padding: 0 2px;
  border: 0; background: none; color: var(--ink-3);
  font-size: 15px; line-height: 1; cursor: pointer;
}
.etiket button:hover { color: var(--no); }

/* TOPLU TESLİM ÇUBUĞU — Y12 */
.toplu-teslim-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  margin-top: var(--s3);
  padding-top: var(--s3);
  border-top: 1px solid var(--line);
}
.toplu-teslim-bar button { width: auto; padding: 0 var(--s4); }

/* "TÜMÜNÜ SEÇ" etiketi yalnizca telefonda gorunur. Masaustunde sutun
   basligi dar; orada kutucuk tek basina anlasilir. */
.sec-tumu label { display: none; }
#shippingRouteTable input[type="checkbox"] { width: auto; min-height: 0; }

/* Satır ekle düğmesi listenin ALTINDA (Y9) — müşteri "üstte yeni satır
   olacağına yanında ekle seçeneği olsun" dedi: eklenen satır gözün gittiği
   yerde belirsin. */
.calc-add-row {
  width: 100%;
  margin-top: var(--s2);
  border: 1px dashed var(--line);
  background: var(--paper);
  color: var(--ink-2);
  font-weight: 600;
}
.calc-add-row:hover { border-color: var(--m); color: var(--m); }

/* ===================================================================
   SIKIŞIK PENCERE DÜZENİ — müşteri isteği
     "İş emrinde veya diğer sekmelerde bütün bilgiler göz önünde olsa,
      mouse ile aşağı yukarı inip çıkmasak. Standart bir pencere ölçüsü
      belirleyip kenar boşlukları belli, altı hafif gri sekmeler belli
      olacak şekilde yapsak hata payını azaltmış oluruz."

   ÖLÇÜLDÜ (1366x768, iş emri kartı):
     pencere 707px yer kaplıyor ama SEKME İÇERİĞİNE yalnızca 387px kalıyordu;
     başlık + künye + sekme çubuğu + alt butonlar 320px yiyordu.
     "İş Bilgileri" sekmesi 885px içerikle 498px taşıyordu.

   İKİ KOL BİRDEN ÇEKİLİYOR:
     1) Pencereye daha çok yükseklik verilir (92vh -> 96vh) ve kaydırma
        sorumluluğu SEKME İÇERİĞİNE bırakılır; pencerenin kendisi kaymaz.
        Böylece başlık ve alt buton şeridi HER ZAMAN görünür kalır —
        kullanıcı "kaydet" düğmesini aramak için aşağı inmez.
     2) Form ritmi sıkıştırılır: alan yüksekliği 38->32, etiket-alan
        boşluğu ve bölüm dolgusu kısılır.

   DOKUNMATİKTE UYGULANMAZ: parmakla kullanımda 32px'lik hedef küçük kalır
   (44px dokunma hedefi kuralı). Bu yüzden blok `pointer: fine` ile
   sınırlı — fare kullanan masaüstünde yoğunluk, tablette rahatlık.
   =================================================================== */
@media (pointer: fine) {
  .job-dialog,
  .centered-card-dialog {
    /* STANDART PENCERE ÖLÇÜSÜ — müşteri "kenar boşlukları belli olsun" dedi.
       Pencere ekranı tamamen kaplamıyor; çevresindeki boşluk onu bir
       "pencere" gibi okutuyor ve arkadaki listeyle karışmıyor. Üst sınır
       1320px: daha genişi 3 sütunu gereksiz yayar, göz satır takip
       ederken yorulur. */
    width: min(1320px, 95vw);
    max-width: min(1320px, 95vw);
    /* 92vh İDİ → 96vh (15.08 revizesi Y3). 1366×768'de bu 31 px demek ve
       İş Bilgileri sekmesinin kalan taşmasını kapatıyor. Diyalog zaten
       ortalanmış; 4vh kenar boşluğu arkadaki ekranı hâlâ gösteriyor,
       yani "pencere mi tam ekran mı" belirsizliği doğmuyor. */
    max-height: 96vh;
  }

  /* KIRPMA ARTIK YALNIZCA İŞ EMRİ KARTINDA (revize m17).

     ESKİ HÂLİ: kırpma yukarıdaki GRUPLU kuralın içindeydi, yani
     `.centered-card-dialog` taşıyan 24 pencerenin HEPSİNE uygulanıyordu.
     Oysa kırpılan içeriği kaydırarak açan bir iç kap YALNIZCA iş emri
     kartında var: aşağıdaki `.job-dialog .tab-page` kuralı. Diğer
     pencerelerde 96vh'yi aşan her şey hem görünmüyor hem de
     KAYDIRILARAK AÇILAMIYORDU — Müşteri Kartı'nda "Müşteriyi Kaydet"
     düğmesi, Personel/Stok kartında alt satırlar erişilemez kalıyordu.

     Müşterinin "bu alan sayfa aşağı kaymıyor, sayfa ölçeğini küçültünce
     geliyor" dediği şey budur: yakınlaştırma küçülünce içerik 96vh'ye
     sığıyor ve kusur kendiliğinden kayboluyor. Bu, teşhisin kanıtı.

     AYNI TAKAS TELEFONDA BİR KEZ YAPILDI VE GERİ ALINDI — aşağıdaki
     `dialog[open] > form` bloğunun açıklamasına bakınız. Oradaki ders
     burada da geçerli: kırpma İSTİSNA olur, kaydırma VARSAYILAN. Yeni
     bir pencere eklendiğinde onu listeye yazmayı unutmanın bedeli
     "kaydırma çubuğu çıkar" olur — "içerik erişilemez" değil.

     Kırpma kalkınca taban kural `dialog{overflow:auto}` devreye girer:
     sığmayan pencere kendi içinde kayar.
     Kapı: tests/test_pencere_dikey_kaydirma.py */
  .job-dialog { overflow: hidden; }

  .job-dialog form,
  .centered-card-dialog form {
    display: flex;
    flex-direction: column;
  }

  /* 96vh TAVANI DA YALNIZCA İŞ EMRİ KARTINA AİT (revize m17).

     Gerekçesi "form pencereyle AYNI boyda olsun ki pencerenin kazandığı
     yer kullanılsın" idi; bu yalnızca içinde KENDİ KAYAN SEKMESİ olan
     pencerede anlamlı. Kendi kayan kabı olmayan bir formda tavan iki
     zarar veriyordu:
       1) form kutusu 96vh'de duruyor, içerik kutunun DIŞINA taşıyordu;
          üstteki kırpma da onu kesiyordu (asıl kusur buydu);
       2) esnek sütun yığınında kendi kaydırması olan çocuklar
          (`min-height:0` taşıyan `.table`, `.cari-ekstre-tablo`)
          negatif alan dağıtımında eziliyordu.
     Tavan kalkınca form boyu içeriğine eşit olur; sığmayan pencerenin
     KENDİSİ kayar. */
  .job-dialog form { max-height: 96vh; }

  /* Künye bandı: 4 sütun zaten var, yalnızca dolgusu kısılıyor. */
  .job-dialog .job-summary { padding: var(--s2) var(--s3); }
  .job-dialog .gold-modal-header { padding: var(--s2) var(--s3); }
  .job-dialog .gold-modal-header h2 { font-size: 17px; }
  .job-dialog .gold-modal-header p { display: none; }

  /* FORM RİTMİ — her alan ~60px'ten ~48px'e iner.
     Yedi alanlı bir sütunda bu 84px kazanç demek. */
  .job-dialog input:not([type="checkbox"]):not([type="radio"]),
  .job-dialog select,
  .centered-card-dialog input:not([type="checkbox"]):not([type="radio"]),
  .centered-card-dialog select { min-height: 32px; }

  .job-dialog textarea,
  .centered-card-dialog textarea { min-height: 64px; }

  .job-dialog label,
  .centered-card-dialog label { font-size: 10.5px; }

  .job-dialog .subcard { padding: var(--s2) var(--s3); }
  .job-dialog .subcard h3 { margin-bottom: var(--s2); font-size: 12px; }
  .job-dialog .tab-page { padding: var(--s2) var(--s1) var(--s2); }

  /* KARTIN İÇİ ÇOK SÜTUNLU
       Ölçüldü: iş emri kartındaki kartlar 641px GENİŞLİĞİNDE ama alanlar
       tek sütun hâlinde alt alta diziliyordu. 641px'lik bir satırda tek bir
       "Tram" kutusu durması hem yer israfı hem de kaydırma sebebi.

       `auto-fit` + `minmax` bilinçli: sütun sayısı kartın genişliğine göre
       kendiliğinden belirleniyor. Dar bir kartta 1, geniş kartta 3 sütun
       olur; ayrı ayrı kırılma noktası tanımlamak gerekmez.

       VARSAYILAN TAM SATIR — BİLİNÇLİ TERS ÇEVİRME
       Önce bunun tersi yazılmıştı: sütuna girmeyecek sınıflar TEK TEK
       sayılıyordu. Listede unutulan her sınıf 185px'lik bir hücreye
       eziliyordu; müşteri bunu dört ayrı ekranda hata olarak bildirdi
       (ölçü giriş satırı, form listesi, onay resim kutusu, en/boy/yükseklik).

       Sayarak yetişmek mümkün değil: kart içine yeni bir blok eklenince
       liste yine eksik kalır. Bu yüzden varsayılan TAM SATIR; yalnızca
       "etiket + tek girdi" biçimindeki basit alanlar sütuna akar.
       Böylece unutmanın bedeli "bozuk düzen" değil, "biraz daha uzun
       kart" olur — yani zararsız tarafa düşer. */
  /* Alt sınır 185 -> 220: açılır listelerde isim kesiliyordu
     ("MUSTAFA BEY — GRAFİ"). Ölçüldü: 185'te 1 kesilme, 200'de 0.
     220 seçildi çünkü taşma 200 ile birebir aynı (18px) ama daha uzun
     isimlere pay bırakıyor; 240'ta taşma 29'a çıkıyor. */
  .job-dialog .subcard {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--s2) var(--s3);
    align-content: start;
  }
  .job-dialog .subcard > * { grid-column: 1 / -1; }

  /* Yan yana akmasına izin verilen TEK durum: içinde metin girdisi ya da
     açılır liste olan etiket. Onay kutusu/radyo içerenler ve textarea'lı
     olanlar dışarıda kalır — onların metni uzun, dar sütunda sarıyor. */
  .job-dialog .subcard > label:has(:is(
      input:not([type="checkbox"]):not([type="radio"]), select)) {
    grid-column: auto;
  }

  /* Dikey radyo grupları da yatay akar: "Sevk Yeri" dört seçenekle
     202px yer kaplıyordu. */
  .job-dialog .vertical-radio {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s2) var(--s3);
  }

  /* İŞ BİLGİLERİ SEKMESİ: ÜÇ SÜTUN
       Ölçüldü: sol kart 308px, sağ sütun 807px (iki kart ALT ALTA).
       Sekmenin yüksekliğini uzun sütun belirlediği için sol taraftaki
       500px boşuna duruyordu.

       `display: contents` sağ sarmalayıcıyı düzenden ÇIKARIR; iki kartı
       doğrudan üst gridin çocuğu yapar. Böylece HTML değiştirmeden
       iki sütun üç sütuna dönüşür ve yükseklik en uzun KARTA iner
       (807 -> ~403). */
  .job-dialog .job-info-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .job-dialog .job-info-right { display: contents; }

  /* FORMLAR SEKMESİ: önizleme SABİT değil, KALAN ALANI doldurur.
     R6'da önizleme `min(78vh,900px)` yapılmıştı ("çok küçük" şikâyeti).
     Sabit yükseklik bu kez sekmeyi taşırıyor. Doğrusu: kalan alanın
     tamamını kapla — hem büyük hem taşmıyor. */
  .job-dialog .forms-layout { height: 100%; min-height: 0; }
  .job-dialog .forms-preview-card {
    min-height: 0;
    height: 100%;
  }
  .job-dialog .forms-preview-card iframe { min-height: 0; }
  /* Form listesi iki sütun: altı form 556px yer kaplıyordu. */
  .job-dialog .job-forms-list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: var(--s2);
  }

  /* SEKME KENDİ YÜKSEKLİĞİNİ AŞMAZ — UZUN LİSTELER KENDİ İÇİNDE KAYAR
       Kullanıcının istediği "her şey göz önünde" şu demek: ekranın YAPISI
       (başlık, künye, sekmeler, kaydet düğmesi) hep görünsün, kaydırmak
       gerekiyorsa yalnızca uzun bir LİSTE kendi kutusunda kaysın.
       İkinci referans ekranındaki mantık da bu.

       `grid-template-rows: minmax(0,1fr)` sekmeyi tam olarak kalan alana
       sabitler; `min-height:0` olmadan grid/flex çocukları içeriklerinden
       küçülmeyi reddeder ve taşma geri gelir. */
  .job-dialog .tab-page {
    display: grid;
    grid-template-rows: minmax(0, 1fr);
    /* `hidden` İDİ — ÖLÇÜLDÜ VE İÇERİK ULAŞILAMAZ KALIYORDU.
       1366×768'de İş Bilgileri sekmesi 558 px içeriği 421 px kutuya
       sığdırmaya çalışıyor; `hidden` ile aradaki 137 px yalnızca
       görünmüyor değil, KAYDIRILARAK DA AÇILAMIYORDU. "Ölçü Biçimi"
       radyoları ve "bu not hangi formlara basılsın" kutuları tıklanamaz
       hâldeydi — müşteri bunu bildirdi (15.08 revizesi Y3).

       Niyet çift kaydırma çubuğundan kaçınmaktı; bedeli erişilemeyen
       form alanı oldu. Aşağıdaki sıkıştırma içeriği normal ekranlarda
       zaten sığdırıyor; `auto` yalnızca güvenlik ağı — sığmadığında
       kırpmak yerine kaydırılabilir kalıyor. */
    overflow-y: auto;
    overflow-x: hidden;
  }
  .job-dialog .tab-page > *,
  .job-dialog .two-col > *,
  .job-dialog .forms-layout > *,
  .job-dialog .plate-montage-grid > * { min-height: 0; }
  .job-dialog .two-col,
  .job-dialog .forms-layout,
  .job-dialog .plate-montage-grid { align-items: stretch; }

  /* Kaymasına izin verilen kutular: yalnızca LİSTELER. */
  .job-dialog .color-list,
  .job-dialog .measure-list,
  .job-dialog .job-forms-list,
  .job-dialog .revision-history-list,
  .job-dialog .production-measure-list { overflow: auto; }

  /* ÖLÇÜ SEKMESİ — SIRAYA BAĞLI ŞABLON DEĞİL, FLEX YIĞIN.

     Burada `grid-template-rows: auto minmax(0,1fr)` yazıyordu: "iki
     çocuk var, ikincisi kalan alanı doldurur" varsayımı. Sekmede DÖRT
     çocuk var (ölçü yönetimi bandı, iki sütunlu ölçü kartları,
     üretimde girilen ölçüler, ...). Fazladan çocuklar örtük `auto`
     satırlara düşüp yeri kapıyor, `1fr` satırındaki ÖLÇÜ KARTLARI
     0'a çöküyordu: ölçüldü, kartlar 18 px kalıyor ve alttaki kart
     üzerlerine biniyordu. Müşteri "girilen ölçüler yukarıda aşağıda
     kalıyor" derken bunu görüyordu.

     Aynı hata `.subcard`ta bir kez yaşanmış ve orada flex yığına
     geçilerek çözülmüştü (bkz. aşağıdaki açıklama). Sekme de öyle:
     çocuklar kendi boylarını alır, sığmayınca SEKME kayar. Kaç çocuk
     olduğu ya da hangi sırada durdukları artık önemsiz. */
  .job-dialog #tab-measure {
    display: flex;
    flex-direction: column;
    gap: var(--s3);
    overflow-y: auto;
  }
  .job-dialog #tab-measure > * { flex: 0 0 auto; }

  /* ÖLÇÜ KARTI DÜŞEY YIĞIN — SIRAYA BAĞLI ŞABLON DEĞİL
     Burada `grid-template-rows: auto auto minmax(0,1fr) auto` yazıyordu:
     "üçüncü çocuk listedir" varsayımı. Kartta sekiz çocuk var, dolayısıyla
     varsayım şimdiden yanlıştı ve listenin 180px'lik alt sınırı 1fr izini
     taşırıp alttaki toplam satırının ÜZERİNE biniyordu (ölçüldü: 56px).

     Flex yığında liste kalan alanı kendisi alır; kaç çocuk olduğu ya da
     hangi sırada durdukları önemsiz. Yeni bir alan eklendiğinde şablonu
     güncellemeyi unutmak diye bir risk kalmıyor. */
  .job-dialog .subcard:has(.measure-list) {
    display: flex;
    flex-direction: column;
    gap: var(--s2);
  }
  .job-dialog .subcard:has(.measure-list) .measure-list {
    /* ALT SINIR GERİ GELDİ — AMA BU KEZ ÇAKIŞMADAN.

       `min-height: 0` yazılmıştı; gerekçe, eski 180px'lik alt sınırın
       alttaki TOPLAM satırının üzerine binmesiydi. O taşma GRID
       şablonundan geliyordu (`grid-template-rows` ile listeye 1fr
       verilip üstüne 180px dayatılıyordu). Kart artık FLEX yığın:
       alt sınır kartı BÜYÜTÜR, komşusunun üstüne binmez.

       `min-height: 0` bırakmanın bedeli ölçüldü: her iki liste de
       18 px'e iniyordu, içerik 58 px iken. Yani girilen ölçü ekranda
       görünmüyor, kullanıcı kaydırmadan ne yazdığını bilemiyordu —
       müşteri şikâyeti tam buydu.

       Değer satır sayısına bağlı: 5 satır + kutu dolgusu. Piksel
       yerine `em` kullanılıyor ki yazı tipi büyürse kutu da büyüsün.
       Çakışma testi: `scripts/olcu_kutusu_kontrol.py`. */
    flex: 1 1 auto;
    min-height: 9.5em;
    max-height: none;
  }

  /* ALT ŞERİT: açık gri, üstten çizgili, HER ZAMAN görünür.
     Müşterinin "altı hafif gri" dediği bant budur; kaydet/iptal aramak
     için aşağı inmek gerekmiyor.

     `.customer-actions` de buraya DAHİL: müşteri kartı ayrı bir sınıf
     kullandığı için bu bandın dışında kalmıştı ve düğmeler pencerenin
     yuvarlatılmış köşesine sıfır boşlukla yapışıyordu ("kenarlarını
     düzeltsene", "iç içe duruy"). Sınıf adı farklı, işlevi aynı. */
  .job-dialog .dialog-actions,
  .centered-card-dialog .dialog-actions,
  .customer-dialog .customer-actions {
    flex: 0 0 auto;
    background: var(--paper-2);
    border-top: 1px solid var(--line);
  }
}

/* FİYAT ÖZETİ — iş emri kartı > Fiyat sekmesi */
.fiyat-ozet { display: grid; gap: var(--s1); }
.fiyat-satir {
  display: flex;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s2) 0;
  border-bottom: 1px solid var(--line-2);
  font-size: 13px;
}
.fiyat-satir b { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.fiyat-satir.toplam {
  margin-top: var(--s2);
  padding-top: var(--s3);
  border-top: 2px solid var(--ink);
  border-bottom: 0;
  font-size: 15px;
}
.fiyat-satir.toplam b { font-size: 18px; color: var(--m); }

@media (pointer: coarse) {
  input,
  select,
  textarea,
  label input,
  label select,
  label textarea { font-size: 16px; }
}

label>input:not([type="checkbox"]):not([type="radio"]),
label>select,
label>textarea{margin-top:var(--s1)}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
textarea {
  resize: vertical;
  min-height: 96px;
  padding: var(--s2) var(--s3);
  line-height: 1.5;
}
select{cursor:pointer}

/* Bütün sayısal girdiler mono + tabular */
input[type="number"],
input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[inputmode="decimal"],
input[inputmode="tel"]{font-family:var(--mono);font-variant-numeric:tabular-nums}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
::placeholder {
  color: var(--ink-3);
  opacity: 1;
}

/* Odak: 1px yerine 2px görünen magenta kenar + yumuşak halka.
   border-width değiştirmek yerine iç gölge kullanılır (yerleşim kaymaz). */
input:focus,
select:focus,
textarea:focus{
  outline:none;
  border-color:var(--m);
  box-shadow:0 0 0 1px var(--m),0 0 0 4px var(--m-soft);
}

/* Yüksek kontrast (Windows Yüksek Kontrast / forced-colors): box-shadow
   tamamen atılır, kenarlık rengini sistem ezer — yukarıdaki odak göstergesi
   yok olur. Sistem renkli gerçek bir outline geri konur. */
@media (forced-colors:active){
  input:focus,
  select:focus,
  textarea:focus{outline:2px solid Highlight;outline-offset:2px}
}

/* Hata durumu — kullanıcı etkileşiminden sonra */
input:user-invalid,
select:user-invalid,
textarea:user-invalid{border-color:var(--no);box-shadow:0 0 0 3px var(--no-soft)}

/* Devre dışı / salt okunur */
input:disabled,
select:disabled,
textarea:disabled,
input[readonly],
textarea[readonly]{
  background:var(--paper-2);
  color:var(--ink-3);
  box-shadow:none;
  cursor:not-allowed;
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
fieldset {
  border: 1px solid var(--line);
  padding: var(--s3);
  min-width: 0;
  border-radius: var(--r2);
  margin: 0;
}
legend{
  padding:0 var(--s2);
  font:600 11px/1 var(--ui);
  text-transform:uppercase;
  letter-spacing:.08em;
  color:var(--ink-3);
}

/* Dosya yolu / kod gösterimi */
code{
  display:block;
  padding:var(--s2) var(--s3);
  border:1px solid var(--line-2);
  border-radius:var(--r1);
  background:var(--paper-2);
  color:var(--ink-2);
  font:400 12px/1.5 var(--mono);
  word-break:break-all;
}

/* === ONAY KUTUSU / RADYO — 18px, magenta işaret === */
input[type="checkbox"],
input[type="radio"]{
  flex:0 0 auto;
  width:18px;
  height:18px;
  min-height:0;
  padding:0;
  margin:0;
  border:0;
  background:none;
  box-shadow:none;
  accent-color:var(--m);
  cursor:pointer;
}
input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible{outline:2px solid var(--m);outline-offset:2px}

/* CMYK kaydırıcıları — border ve halka yok, bu yüzden klavye odağı
   ayrıca kurulur. Fare tıklamasında halka çizilmez, KLAVYE odağı görünür. */
input[type="range"]{
  min-height:24px;
  padding:0;
  border:0;
  background:none;
  accent-color:var(--m);
}
input[type="range"]:focus:not(:focus-visible){box-shadow:none}
input[type="range"]:focus-visible{
  outline:2px solid var(--m);
  outline-offset:2px;
  box-shadow:none;
}

/* Onay/radyo etiketleri: cümle metni, geniş dokunma alanı */
.checkline,
.calc-check,
.settings-switch,
.system-switch,
.personnel-active-label,
.production-material-check,
.checks label,
.inline-radio label,
.vertical-radio label,
.radio-grid label,
.bar-grid label,
.dimension-mode label,
.measurement-source-row label,
.personnel-permissions label{
  display:flex;
  align-items:center;
  gap:var(--s2);
  min-height:34px;
  font:400 13px/1.4 var(--ui);
  text-transform:none;
  letter-spacing:normal;
  color:var(--ink);
  cursor:pointer;
}

/* === PANEL + REGISTER ÇARPISI === */
.panel{
  position:relative;
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r2);
  padding:var(--s4);
  box-shadow:var(--sh1);
}
/* İkincil imza: yalnızca sol-üst ve sağ-alt köşede saç teli çarpı.
   1px merkez + her yöne 4px kol → SPEC'in 8px kolu (simetri korunarak;
   1px merkez tek sayı olduğu için 4+1+4 en yakın simetrik gerçekleme).
   Gradyan kullanılmaz. */
.panel::before,
.panel::after{
  content:"";
  position:absolute;
  width:1px;
  height:1px;
  background:var(--line);
  pointer-events:none;
  box-shadow:
    0 -4px var(--line),0 -3px var(--line),0 -2px var(--line),0 -1px var(--line),
    0 1px var(--line),0 2px var(--line),0 3px var(--line),0 4px var(--line),
    -4px 0 var(--line),-3px 0 var(--line),-2px 0 var(--line),-1px 0 var(--line),
    4px 0 var(--line),3px 0 var(--line),2px 0 var(--line),1px 0 var(--line);
}
.panel::before{left:var(--s2);top:var(--s2)}
.panel::after{right:var(--s2);bottom:var(--s2)}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
table {
  border-collapse: collapse;
  border-spacing: 0;
  width: 100%;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

th{
  position:sticky;
  top:0;
  z-index:1;
  padding:var(--s2) var(--s3);
  background:var(--paper-2);
  color:var(--ink-3);
  text-align:left;
  white-space:nowrap;
  font:600 11px/1.4 var(--ui);
  text-transform:uppercase;
  letter-spacing:.08em;
  /* border-collapse ile sticky kenarlık kaybolur — iç gölge kullanılır */
  box-shadow:inset 0 1px 0 var(--line),inset 0 -1px 0 var(--line);
}

td{
  padding:var(--s2) var(--s3);
  border-bottom:1px solid var(--line-2);
  color:var(--ink);
  vertical-align:middle;
}

tbody tr{cursor:pointer;transition:background-color .14s,box-shadow .14s}
tbody tr:hover{background:var(--paper-2)}

/* Klavye odağı — satırlar tıklanabilir (app.js click/dblclick bağlıyor).
   HTML tarafında tabindex="0" eklendiği anda odak görünür olsun diye
   stil şimdiden hazır; aksi halde görünmez odak kalırdı. */
tbody tr:focus-visible{
  outline:2px solid var(--m);
  outline-offset:-2px;
  background:var(--m-soft);
}

/* Seçili satır: sol kenarda 3px magenta şerit */
tbody tr.selected{background:var(--m-soft);box-shadow:inset 3px 0 0 var(--m)}

/* Satır durumları (app.js üretir) */
tbody tr.exported,
tbody tr.passive-stock-row,
tbody tr.passive-personnel{color:var(--ink-3)}
tbody tr.critical-stock-row{box-shadow:inset 3px 0 0 var(--no)}

/* Sıralanabilir başlık */
th.sortable{cursor:pointer;user-select:none}
th.sortable:hover{color:var(--ink-2)}
th.active-sort{color:var(--m)}
th.sortable span{font-size:10px;opacity:.6}
th.active-sort span{opacity:1}

/* Sayısal hücreler: mono + sağa yaslı */
td.stock-quantity-cell,
td.positive,
td.negative,
td.total{
  font-family:var(--mono);
  font-weight:600;
  text-align:right;
  white-space:nowrap;
}
td.positive{color:var(--ok)}
td.negative{color:var(--no)}

/* Kompakt görünüm — veri yoğunluğu (body.compact-mode) */
body.compact-mode td{padding:var(--s1) var(--s2)}
body.compact-mode th{padding:var(--s1) var(--s2)}
.toolbar input{flex:1 1 240px;min-width:0}
.toolbar select{flex:0 1 200px;width:auto}

/* === SEKMELER — alt çizgi, dolgu zemin yok === */
.tabs,
.customer-tabs,
.reports-tabs,
.settings-tabs{
  display:flex;
  gap:var(--s4);
  margin:0 0 var(--s4);
  padding:0;
  border-bottom:1px solid var(--line);
  overflow-x:auto;
  overflow-y:hidden;
  scrollbar-width:thin;
}
.tabs button,
.customer-tabs button,
.reports-tabs button,
.settings-tabs button{
  flex:0 0 auto;
  min-height:38px;
  padding:0 var(--s1);
  border:0;
  border-bottom:2px solid transparent;
  border-radius:0;
  background:none;
  color:var(--ink-2);
  font:600 13px/1 var(--ui);
}
.tabs button:hover,
.customer-tabs button:hover,
.reports-tabs button:hover,
.settings-tabs button:hover{background:none;color:var(--ink)}
.tabs button.active,
.customer-tabs button.active,
.reports-tabs button.active,
.settings-tabs button.active{color:var(--m);border-bottom-color:var(--m)}

/* Sekme sayacı */
.tabs span,
.customer-tabs span{
  margin-left:var(--s1);
  padding:1px var(--s1);
  border-radius:var(--r1);
  background:var(--paper-2);
  color:var(--ink-3);
  font:600 11px/1.4 var(--mono);
}

/* === DURUM ROZETLERİ — -soft zemin + koyu metin, nokta yok === */
.status-pill,
.quality-status,
.accounting-status,
.stock-status,
.personnel-status,
.approval-status,
.movement-type,
.archive-file-badge,
.primary-tag,
.produced-job-badge,
.gold-produced-badge,
.test-reset-warning,
.tracking-due{
  display:inline-flex;
  align-items:center;
  min-height:20px;
  padding:2px var(--s2);
  border-radius:var(--r1);
  background:var(--paper-2);
  color:var(--ink-2);
  font:600 11px/1.4 var(--ui);
  text-transform:uppercase;
  letter-spacing:.08em;
  white-space:nowrap;
}

/* İş durumu — y:bekleyen  c:aktif  ok:tamam  plate:arşiv  no:hata */
.status-pill[data-status="MÜŞTERİ ONAYI BEKLİYOR"],
.status-pill[data-status="KALİTE KONTROL BEKLİYOR"],
.status-pill[data-status="SEVKİYATA HAZIR"]{background:var(--y-soft);color:var(--ink)}
.status-pill[data-status="ÜRETİME HAZIR"],
.status-pill[data-status="ÜRETİMDE"],
.status-pill[data-status="DAĞITIMDA"]{background:var(--c-soft);color:var(--ink)}
.status-pill[data-status="TESLİM EDİLDİ"],
.status-pill[data-status="TESLIM EDILDI"],
.status-pill[data-status="ÜRETİM TAMAMLANDI"],
.status-pill[data-status="TAMAMLANDI"]{background:var(--ok-soft);color:var(--ink)}
.status-pill[data-status="ARŞİVLENDİ"],
.status-pill[data-status="ARSIVLENDI"]{background:var(--plate-soft);color:var(--ink)}
.status-pill[data-status="İPTAL"]{background:var(--no-soft);color:var(--ink)}
.status-pill.good{background:var(--ok-soft);color:var(--ink)}
.status-pill.bad{background:var(--no-soft);color:var(--ink)}

/* Kalite / muhasebe / onay */
.quality-status.done,
.accounting-status.done,
.approval-status.done{background:var(--ok-soft);color:var(--ink)}
.quality-status.waiting,
.accounting-status.pending,
.approval-status.waiting{background:var(--y-soft);color:var(--ink)}

/* Stok ve personel kartı durumu */
.stock-status.critical{background:var(--no-soft);color:var(--ink)}
.stock-status.active,
.personnel-status.active{background:var(--ok-soft);color:var(--ink)}
.stock-status.passive,
.personnel-status.passive{background:var(--paper-2);color:var(--ink-3)}

/* Stok hareket türü */
.movement-type.in{background:var(--ok-soft);color:var(--ink)}
.movement-type.out{background:var(--no-soft);color:var(--ink)}
.movement-type.adjust{background:var(--c-soft);color:var(--ink)}

/* Arşiv dosya rozetleri */
.archive-file-badge.job-file{background:var(--c-soft);color:var(--ink)}
.archive-file-badge.delivery-file{background:var(--plate-soft);color:var(--ink)}
.archive-file-badge.empty{background:var(--paper-2);color:var(--ink-3)}

/* Diğer rozetler */
.primary-tag{background:var(--c-soft);color:var(--ink)}
.test-reset-warning{background:var(--no-soft);color:var(--ink)}

/* === ARŞİV SALT OKUNUR ŞERİDİ — m11 ======================================
   Şeridi web/js/13-ayarlar-ve-si-stem-guvenli.js:487 üretir. Orada
   `#jobDialog` içinde `.dialog-head` aranıyor; o pencere
   `.gold-modal-header` kullandığı için BULUNAMIYOR ve şerit dialog'un SON
   çocuğu olarak, formun KARDEŞİ olarak ekleniyor.

   MÜŞTERİ ŞİKÂYETİ (m11): "salt okunur şeriti butonları kapatıyor".

   ZİNCİR (yalnızca masaüstü): `.job-dialog{height:96vh}` ve
   `.job-dialog form{height:100%}` formu pencerenin TAMAMI yapıyor;
   pencere `display:block` ve @media(pointer:fine) ile `overflow:hidden`,
   yani KAYDIRILAMIYOR. Şeridin akıştaki yeri bu yüzden görünür alanın
   ALTINDA kalıyordu. Eski `position:sticky;bottom:0` onu kendi yüksekliği
   kadar yukarı çekip `z-index:2` ile `.job-actions` şeridinin (MÜŞTERİ
   LİNKİ / REFERANS AL / İptal) üzerine bindiriyordu. Kaydırma olmadığı
   için bu kalıcıydı: düğmeler hem örtülü hem tıklanamaz kalıyor, tıklama
   şeride düşüyordu.

   ÇÖZÜM ÖRTMEK DEĞİL, SIRA VERMEK: pencere sütun flex olunca şerit kendi
   SATIRINI alır, form şerit kadar kısalır ve hiçbir şeyin üstüne binmez.
   Aynı kurgu ≤900px'te (60-responsive) ZATEN vardı — hata bu yüzden
   yalnızca masaüstünde görülüyordu; eksik olan tek parça buydu.

   `sticky` GERİ KONMAMALI: taşma bir gün geri döndüğünde aynı kusuru
   birebir geri getirir. Şeridin görünür kalmasını sağlayan şey artık
   konumlandırma değil, flex satırının kendisi (`flex:0 0 auto`).

   `[open]` KAPISI ZORUNLU: `display` yazmak `dialog{display:none}`
   varsayılanını ezer, KAPALI pencere sayfa içeriği gibi akışa dökülürdü.
   Kural EN ÜST DÜZEYDE duruyor ve `!important` TAŞIMIYOR ki
   60-responsive'in ≤900px ve yatay telefon (tek akış) blokları onu hâlâ
   ezebilsin. */
.job-dialog[open]{display:flex;flex-direction:column}
.gold-produced-badge{
  display:flex;
  justify-content:center;
  flex:0 0 auto;
  padding:var(--s2) var(--s4);
  border-radius:0;
  background:var(--plate-soft);
  color:var(--ink);
  box-shadow:inset 0 1px 0 var(--line);
}
.tracking-due.overdue{background:var(--no-soft)}
.tracking-due.today{background:var(--y-soft)}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.danger-text {
  color: var(--no);
}
#toast.show{opacity:1}
/* RENK VARYANTI YOK — bilinçli. app.js:59 `e.className="show"` ile sınıf
   listesini komple EZİYOR, yani `.success`/`.error` öğeye hiç girmiyor;
   ayrıca `e.style.background` satır içi yazıldığı için bütün @layer
   kurallarını yeniyor. Bu yüzden toast TEK nötr stille çalışır.
   ESCALATE (CSS ile çözülemez) — app.js:59 şu iki satır değişirse
   renk varyantı anlam kazanır ve buraya geri eklenebilir:
     SİL : e.style.background=error?"#dc2626":"#172033";
     YAZ : e.className=error?"show error":"show";                         */

/* === MERKEZ BAŞARI KUTUSU — app.js:66-78 #centerSuccess üretir ===========
   Kutu body'nin sonuna ekleniyor ve `.show` ile 1.6s görünüyor.
   Ekranın ortasında durur; başarı duygusu geniş renk dolgusuyla değil
   sol kenardaki 3px --ok şeridiyle verilir (SPEC §2 renk disiplini).     */
.center-success{
  position:fixed;
  left:50%;
  top:50%;
  translate:-50% -50%;
  z-index:9999;
  max-width:min(420px,92vw);
  padding:var(--s4) var(--s5);
  border-radius:var(--r2);
  border-left:3px solid var(--ok);
  background-color:var(--k);
  color:#fff;
  font:600 16px/1.4 var(--ui);
  text-align:center;
  box-shadow:var(--sh3);
  opacity:0;
  pointer-events:none;
  transition:opacity .16s;
}
.center-success.show{opacity:1}
dialog::backdrop{background:rgba(18,18,22,.55)}

/* Uygulamanın modal işaretçisi (19 dialog). Yüzey / yarıçap / gölge
   yukarıdaki `dialog{}` tabanından gelir; burada yalnızca dar içerikte
   cılız kalmayan bir taban genişlik ve kaydırmanın arka sayfaya sızmaması
   eklenir. `display` BİLİNÇLİ OLARAK ELLENMEZ — `dialog{display:none}`
   varsayılanı ezilirse kapalı pencere sayfa içeriği gibi görünür.
   Bütün pencere düzeyi seçiciler ayrıca `[open]` kapılıdır: bu katmanda
   `display` yazılmadığı için zorunlu değil, ama kural sonradan
   genişletilirse kapalı pencere yine güvende kalır. */
.gold-modal[open]{min-width:min(360px,92vw);overscroll-behavior:contain}

/* === DIALOG KÜNYE BANDI ==================================================
   `.dialog-head` 12 dialogda, `.gold-modal-header` #jobDialog'da. Bir kısmı
   doğrudan `dialog` çocuğu (`dialog{padding:0}`), bir kısmı `form` çocuğu:
   bu yüzden bant kendi dolgusunu TAŞIMAK ZORUNDA, yoksa başlık ve ×
   dialog kenarına yapışır. Opak zemin ayrıca 60-responsive'in bu bandı
   `position:sticky` yaptığı kısa ekranlarda içerik sızmasını engeller.   */
.dialog-head{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--s3);
  padding:var(--s3) var(--s4);
  background:var(--paper-2);
  border-bottom:1px solid var(--line);
}

.dialog-head>div,
.gold-modal-header>div{flex:1 1 auto;min-width:0}

.dialog-head small,
.gold-modal-header small{
  display:block;
  font:600 11px/1.4 var(--ui);
  text-transform:uppercase;
  letter-spacing:.08em;
  color:var(--ink-3);
}
.dialog-head h2,
.gold-modal-header h2{
  margin:0;
  font-size:20px;
  font-weight:650;
  letter-spacing:-.01em;
}
.dialog-head p,
.gold-modal-header p{margin:var(--s1) 0 0;font-size:12px;color:var(--ink-2)}

/* Kapatma butonu — bandın sağ ucunda 32px kare. Odak halkası
   `button:focus-visible` tabanından gelir, tekrar yazılmaz.
   Mobilde 60-responsive --tap boyutuna büyütür. */
.dialog-head>button,
.dialog-close,
.gold-modal-close{
  flex:0 0 auto;
  margin-left:auto;
  width:32px;
  height:32px;
  min-height:0;
  padding:0;
  font:400 18px/1 var(--ui);
  color:var(--ink-2);
}
.dialog-head>button:hover,
.dialog-close:hover,
.gold-modal-close:hover{background:var(--no-soft);border-color:var(--no);color:var(--no)}

/* === UYARI PENCERESİ — #alertDialog (app.js showAlert) ve
   #unsavedChangesDialog. Uygulamada en sık açılan pencereler.
   Öğeler doğrudan `dialog` çocuğu, `dialog{padding:0}` olduğu için
   dolgu buradan gelir. `display` ezilmez: metin ortalaması ve
   `margin:0 auto` blok akışında yeterli, kapalı dialog güvende.        */
.alert-dialog[open]{
  width:min(440px,92vw);
  padding:var(--s5);
  text-align:center;
}
/* İkon "!" — her iki pencere de UYARI, hata değil: SPEC'te uyarı rengi --y.
   Yarıçap --r1 (SPEC: yarıçap düşük tutulur, daire kullanılmaz). */
.alert-icon{
  display:grid;
  place-items:center;
  width:40px;
  height:40px;
  margin:0 auto var(--s3);
  border:1px solid var(--y);
  border-radius:var(--r1);
  background:var(--y-soft);
  color:var(--ink);
  font:700 20px/1 var(--ui);
}
.alert-dialog h2{
  margin:0 0 var(--s2);
  font-size:20px;
  font-weight:650;
  letter-spacing:-.01em;
}
/* app.js:63 metni gerçek satır sonlarıyla yazıyor → pre-line şart */
.alert-message{
  margin:0;
  font:400 14px/1.5 var(--ui);
  color:var(--ink-2);
  white-space:pre-line;
}

/* === ALT (CHILD) PENCERE — #contactDialog, #addressDialog,
   #productionActionDialog. Genişlik sınırı olmadığı için 4 alanlık form
   `dialog{max-width:1200px}` ile sayfa kadar yayılıyordu.               */
.child-dialog[open]{width:min(720px,94vw)}
.child-dialog>form{display:grid;gap:var(--s3);padding:var(--s5)}
.child-dialog textarea{min-height:80px}

/* === AKSİYON BANDI ======================================================
   `.child-actions` (3 pencerede <footer>): bant — üst kenarlık + zemin.
   `.dialog-actions` (yalnızca app.js şifre penceresinde): tek birincil
   düğme taşıdığı için bant değil, gerilen sade satır.                    */
.child-actions{
  display:flex;
  flex-wrap:wrap;
  justify-content:flex-end;
  gap:var(--s2);
  margin:0;
  padding:var(--s3) var(--s4);
  background:var(--paper-2);
  border-top:1px solid var(--line);
}
.child-actions button{min-width:120px}

.dialog-actions{
  display:flex;
  flex-wrap:wrap;
  gap:var(--s2);
  margin-top:var(--s1);
}
.dialog-actions button{flex:1 1 auto;min-width:150px}

/* === TOPLU TESLİM PENCERESİ — #bulkDeliveryDialog (S10) ==================
   `dialog{padding:0}` olduğu için her pencere kendi dolgusunu verir. Bu
   pencereye hiç verilmemişti: alanlar kenara yapışıyor, aralarında boşluk
   olmadığı için etiketler üst üste biniyordu ("kenar boşlukları yok, üst
   üste duruyor").

   Dolgu <form>'a değil GÖVDEYE veriliyor; künye şeridi baştan sona
   uzanmaya devam etsin (diğer pencerelerdeki görünümle aynı kalsın) diye.  */
#bulkDeliveryDialog[open]{width:min(560px,94vw)}
#bulkDeliveryDialog>form{
  display:flex;
  flex-direction:column;
  gap:var(--s3);
}
#bulkDeliveryDialog .bulk-delivery-body{
  margin:var(--s4) var(--s4) 0;
  /* Liste kalan alanı alıp KENDİ İÇİNDE kaysın; pencere büyümesin. */
  min-height:0;
}
#bulkDeliveryDialog .bulk-delivery-body .measure-list{
  min-height:0;
  max-height:32vh;
}
#bulkDeliveryDialog .dialog-actions{
  margin:0;
  padding:0 var(--s4) var(--s4);
}

/* === ŞİFRE DEĞİŞTİRME PENCERESİ — app.js:210-231 üretir, `cancel`
   engellendiği için kapatılamaz; künyesi sınıfsız bir <header>.          */
.password-change-dialog[open]{width:min(460px,92vw)}
.password-change-dialog>form{display:grid;gap:var(--s3);padding:var(--s5)}
.password-change-dialog header small{
  display:block;
  font:600 11px/1.4 var(--ui);
  text-transform:uppercase;
  letter-spacing:.08em;
  color:var(--ink-3);
}
.password-change-dialog header h2{
  margin:0;
  font-size:20px;
  font-weight:650;
  letter-spacing:-.01em;
}
.password-change-dialog p{margin:0;font-size:12px}
/* Hata satırının kırmızısı `.danger-text`ten gelir; :not() olmadan bu
   seçici (0,1,1) onu (0,1,0) ezip griye çevirirdi. */
.password-change-dialog p:not(.danger-text){color:var(--ink-2)}
/* Hata satırı boşken izgarada boş bir sıra bırakmaz */
.password-change-dialog .danger-text:empty{display:none}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.muted {
  color: var(--ink-3);
  font-size: 12px;
  white-space: pre-line;
}

hr{border:0;border-top:1px solid var(--line);margin:var(--s4) 0}

/* Boş durum — ortalanmış, silik, mikro etiket */
.empty-state,
.workflow-empty,
.personnel-empty,
.quality-empty,
.archive-empty,
.stock-empty,
.accounting-empty,
.reports-empty,
.revision-empty,
.system-empty,
.settings-log-empty,
.forms-preview-empty,
.archive-delivery-no-image,
.production-all-done{
  padding:var(--s5) var(--s4);
  text-align:center;
  color:var(--ink-3);
  font:600 11px/1.6 var(--ui);
  text-transform:uppercase;
  letter-spacing:.08em;
}
/* Blok bağlamındakiler ince kesikli çerçeve alır (tablo hücreleri almaz) */
.empty-state,
.revision-empty,
.settings-log-empty,
.forms-preview-empty,
.archive-delivery-no-image,
.production-all-done,
div.reports-empty{
  border:1px dashed var(--line);
  border-radius:var(--r2);
  background:var(--paper);
}


/* ==================== 30-shell.css ==================== */

/* ===========================================================
   GOLD ERP — 30-shell
   Kabuk: giris ekrani, uygulama izgarasi, kenar cubugu, header,
   kontrol seridi (imza ogesi), sayfa kapsayicisi ve yerlesim izgaralari.
   Masaustu halleri. Mobil: 60-responsive.

   KAYDIRMA MODELI (baglayici karar — birlestirmede geri alinmaz):
   dikey kaydirma .app main ICINDE olur. Kenar cubugu ve header
   ekranda sabit kalir. Giris ekrani bu kurgudan MUAFTIR: belge
   akisinda kalir ve gerektiginde belge seviyesinde kaydirilir.
   =========================================================== */


/* === YUKSEKLIK VE KAYDIRMA MODELI — KARAR VE GEREKCE ===
   Dikey kaydirma .app main icindedir (asagida). Bu modeli kurmak icin
   html ve body'ye yukseklik/overflow YAZILMAZ. Uc sebep:

   1) 10-tokens'in @media print blogu html,body{height:auto;overflow:visible}
      yaziyor ve "html/body baska katmanda hic gecmiyor" varsayimina
      dayaniyor. Katman sirasi geregi (30 > 10) buraya yazilacak bir
      html/body yuksekligi o baski kuralini OLDURUR ve ciktida sayfa
      tek ekrana kirpilir. Kabuk yuksekligini html/body'ye baglamayarak
      o kural gecerli kalir.
   2) body'ye height/min-height:100% verilirse mobilde body 100vh
      (buyuk gorunur alan) olur, kabuk ise 100dvh — aradaki tarayici
      cubugu farki kadar IKINCI bir belge kaydirma cubugu dogar.
   3) Giris ekrani belge akisinda kalir: yatay telefonda giris karti
      ekrandan uzunsa belge seviyesinde kaydirilabilir. Bu yuzden
      html/body'ye overflow:hidden da yazilmaz (60-responsive'in
      "html/body kirpma YOK" sozu da korunur).

   Kabuk yuksekligini dogrudan gorunur alandan alir: .app{height:100dvh}.
   dvh -> tarayici adres cubugu acildiginda kabuk da kucululur;
   dvh desteklemeyen tarayici 100vh'ye duser. */


/* === GIRIS EKRANI: ZEMIN VE KABUK === */

.login-view{
  min-height:100vh;
  min-height:100dvh;
  padding:var(--s5);
  background:var(--k);
  display:grid;
  place-items:center;
}


/* === GIRIS EKRANI: SOL MARKA PANELI (--k) === */

.login-brand-panel{
  background:var(--k);
  padding:var(--s7) var(--s6);
  display:flex;
  flex-direction:column;
  justify-content:center;
  gap:var(--s6);
}

/* logo tasiyici: koyu zeminde okunurluk icin acik plaka */
.login-brand-frame{
  min-height:132px;
  padding:var(--s4);
  background:var(--surface);
  border-radius:var(--r2);
  display:grid;
  place-items:center;
}

.login-brand-frame img{
  display:block;
  width:100%;
  max-width:360px;
  max-height:104px;
  object-fit:contain;
}

/* marka kilidi: eski altin harf yerine ham klise amberi */
.login-brand-copy span{
  display:block;
  font-size:11px;
  font-weight:600;
  text-transform:uppercase;
  letter-spacing:.08em;
  color:var(--plate);
}

.login-brand-copy h1{
  margin:var(--s3) 0 var(--s2);
  font-size:34px;
  font-weight:700;
  line-height:1.15;
  letter-spacing:-.01em;
  color:var(--surface);
}

.login-brand-copy p{
  margin:0;
  font-size:16px;
  line-height:1.5;
  color:rgba(255,255,255,.72);
}


/* === GIRIS EKRANI: SAG KART === */

.login-form-panel{
  padding:var(--s7) var(--s6);
  background:var(--paper);
  display:grid;
  place-items:center;
}

.login-form-card{
  position:relative;
  width:min(400px,100%);
  padding:var(--s6) var(--s5) var(--s5);
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r2);
  box-shadow:var(--sh1);
}

/* imza: kart ust kenarinda 6 asamalik proses renk bandi */
.login-form-card::before{
  content:"";
  position:absolute;
  top:0;
  left:var(--s5);
  width:26px;
  height:4px;
  background:var(--c);
  box-shadow:26px 0 0 var(--m),52px 0 0 var(--y),78px 0 0 var(--plate),104px 0 0 var(--ok),130px 0 0 var(--k);
}

.login-form-card>small{
  display:block;
  font-size:11px;
  font-weight:600;
  text-transform:uppercase;
  letter-spacing:.08em;
  color:var(--ink-3);
}

.login-form-card h2{
  margin:var(--s2) 0 var(--s1);
  font-size:26px;
  font-weight:650;
  letter-spacing:-.01em;
  color:var(--ink);
}

.login-form-card>p{
  margin:0 0 var(--s5);
  font-size:14px;
  color:var(--ink-2);
}

.login-form-card form{
  display:grid;
  gap:var(--s4);
}

.login-form-card label{
  display:grid;
  gap:var(--s2);
  font-size:11px;
  font-weight:600;
  text-transform:uppercase;
  letter-spacing:.08em;
  color:var(--ink-3);
}

.login-form-card input,
.login-form-card button{
  min-height:var(--tap);
}

.login-security-note{
  margin-top:var(--s4);
  padding-top:var(--s3);
  border-top:1px solid var(--line-2);
  font-size:11px;
  text-align:center;
  color:var(--ink-3);
}


/* === ILK GIRIS BAGLAMI: ZORUNLU SIFRE DEGISTIRME ===
   app.js forcePasswordChange() (satir 210-225) bu dialogu enterApp()
   icinde, setSessionView(true) CAGRILMADAN ONCE acar ve `cancel`
   olayini engeller: arkada hala giris ekrani (.login-view, koyu --k
   zemin) durur, kapatilamaz, kurulumun ilk ekranidir.

   Isbolumu: dialog KUTUSU (genislik, form izgarasi/dolgusu, kunye
   tipografisi) 20-primitives'te tanimli. Burada yalnizca GIRIS EKRANI
   BAGLAMI var: dialog, arkasinda duran .login-form-card ile ayni 6
   asamalik proses renk bandini tasir, boylece kurulumun ilk iki adimi
   tek akisin parcasi gibi okunur. Bant, form dolgusuyla (var(--s5))
   ayni hizadan baslar.
   [open] kapisi: kapali dialog display:none kalir. */
.password-change-dialog[open]::before{
  content:"";
  position:absolute;
  top:0;
  left:var(--s5);
  width:26px;
  height:4px;
  background:var(--c);
  box-shadow:26px 0 0 var(--m),52px 0 0 var(--y),78px 0 0 var(--plate),104px 0 0 var(--ok),130px 0 0 var(--k);
}


/* === UYGULAMA IZGARASI ===
   .app gorunur alan kadar yuksektir; iki kolon (kenar cubugu + main).
   Tek ortulu satir olusur; satir tanimlanmadigi icin gorunur alan
   yuksekligine gerilir (align-content:normal), boylece her iki kolon
   da tam ekran yuksekligindedir. */

.app{
  /* Header yuksekligi TEK KAYNAK: kontrol seridi bu belirtece yapisir.
     Deger sihirli sayi degil, header'in kendi kurgusu:
     en uzun cocuk var(--tap)=44px (mobil hamburger / cikis butonu)
     + dikey dolgu 2 x var(--s2) = var(--s4)=16px
     + alt sac teli kenarlik 1px                  ->  61px.
     Boylece 900px alti dokunma hedefleri buyudugunde header BUYUMEZ,
     serit ile header arasinda kayma olusmaz.

     ALT KENARLIK NEDEN HESABA GIRIYOR (olculen kusur): kutu modeli
     border-box oldugu icin min-height alt kenarligi DE kapsar, ama
     icerik 44+16=60px'i doldurdugunda kenarlik dis tarafta buyur ve
     header'in gercek yuksekligi 61px olur. --header-h 60px iken
     60.0 -> seridin ust 1px'i (390px'te 0.67px) header'in ALTINDA
     kaliyordu; elementFromPoint(60, 60.5) header donuyordu. Kenarlik
     hesaba katilinca min-height = 44+16+1 = gercek yukseklik ve
     top:var(--header-h) ile cakisma 0px olur. */
  --header-h:calc(var(--tap) + var(--s4) + 1px);

  display:grid;
  grid-template-columns:250px minmax(0,1fr);
  height:100vh;
  height:100dvh;
  background:var(--paper);
}


/* === KENAR CUBUGU: MARKA BLOGU === */

.brand{
  padding:var(--s3);
  border-bottom:1px solid var(--k-3);
}

/* logo koyu zeminde kaybolmasin: acik plaka uzerinde durur */
.brand img{
  display:block;
  width:100%;
  max-height:52px;
  padding:var(--s2);
  background:var(--surface);
  border-radius:var(--r1);
  object-fit:contain;
}

.brand small{
  display:block;
  margin-top:var(--s2);
  font-size:11px;
  font-weight:600;
  text-transform:uppercase;
  letter-spacing:.08em;
  text-align:center;
  color:var(--ink-3);
}

/* Ayarlar > Gorunum > "Slogani goster" kapali:
   app.js applyAppearanceSettings() body'ye .hide-slogan ekler.
   Kenar cubugundaki slogan karsiligi .brand small ("ERP WEB
   PROFESSIONAL") — eski .sidebar-slogan / aside footer artik yok. */
body.hide-slogan .brand small{
  display:none;
}

.current-logo img{
  display:block;
  max-width:100%;
  object-fit:contain;
}


/* === KENAR CUBUGU: NAVIGASYON (15 oge) === */

.app nav{
  display:flex;
  flex-direction:column;
  padding:var(--s2) 0;
}

.app nav button span{
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}

.app nav button:hover{
  background:var(--k-2);
  color:#fff;
}

.app nav button.active{
  background:var(--k-2);
  border-left-color:var(--m);
  color:#fff;
}

.app nav button:focus-visible{
  outline:2px solid var(--m);
  outline-offset:-2px;
}

main>header>div{
  min-width:0;
  flex:1 1 auto;
}

main>header small{
  display:block;
  font-size:11px;
  font-weight:600;
  text-transform:uppercase;
  letter-spacing:.08em;
  color:var(--ink-3);
}

main>header h1{
  margin:0;
  font-size:20px;
  font-weight:650;
  letter-spacing:-.01em;
  color:var(--ink);
}

/* Kunye ve baslik TEK SATIRDA kalir. Bu, header'in gercek yuksekligini
   boyle tutulur. Bilgi GIZLENMEZ, kirpilir. */
main>header small,
main>header h1{
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}

.user b,
.user span{min-width:0}

.user span{
  font-size:11px;
  font-weight:600;
  text-transform:uppercase;
  letter-spacing:.08em;
  color:var(--ink-3);
}

.user button:hover{
  background:var(--paper-2);
  border-color:var(--ink-3);
  color:var(--ink);
}

.user button:focus-visible{
  outline:2px solid var(--m);
  outline-offset:2px;
}


/* === PANEL BASLIK ALANLARI === */

.panel-title-row{
  display:flex;
  align-items:flex-start;
  justify-content:space-between;
  gap:var(--s4);
  margin-bottom:var(--s4);
  min-width:0;
}

.panel-title-row h3{
  margin:0;
  font-size:16px;
  font-weight:650;
  letter-spacing:-.01em;
  color:var(--ink);
}

.panel-title-row small{
  display:block;
  margin-top:var(--s1);
  font-size:12px;
  font-weight:400;
  letter-spacing:0;
  text-transform:none;
  color:var(--ink-3);
}

.section-head{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--s3);
  margin-bottom:var(--s3);
  min-width:0;
}

.section-head h3{
  margin:0;
  font-size:14px;
  font-weight:650;
  letter-spacing:-.01em;
  color:var(--ink);
}

.section-head p{
  margin:var(--s1) 0 0;
  font-size:12px;
  color:var(--ink-3);
}


/* === PANEL YERLESIM IZGARALARI (masaustu) === */

.two-col{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:var(--s4);
  align-items:start;
}

.three-col{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:var(--s4);
  align-items:start;
}

.one-col{
  grid-template-columns:minmax(0,1fr);
}

.two-col>*,
.three-col>*{
  min-width:0;
}


/* === KABUGUN MOBIL HALLERI — OLCULEN KUSUR DUZELTMELERI ==================
   Kirilma noktalari SPEC bolum 7'nin izin verdigi iki genislik: 900 ve 560.
   Yeni kirilma noktasi ACILMADI.

   Bu blok neden 60-responsive'de degil de burada: duzeltilen dort kusurun
   hepsi KABUK sozlesmesinin parcasi (header'in yigin katmani, cekmecenin
   header ile iliskisi, serit patch'inin dolgusu, header tipografisi) ve
   bu sozlesmelerin sahibi bu dosya. 60-responsive'in ayni ozgullukte
   bildirim yazmadigi ozellikler secildi; boylece katman sirasi (30 < 60)
   bu kurallari EZMEZ:
     - main>header      -> 60-responsive yalnizca justify/gap/padding yazar
     - .app>aside       -> 60-responsive padding yazmaz
     - .user span/.user b -> 60-responsive yalnizca max-width/overflow yazar
   ======================================================================== */

@media (max-width:900px){

  /* KUSUR (kritik, 768x1024): cekmece acikken hamburger butonuna
     DOKUNULAMIYOR, yani cekmece kendi butonuyla kapatilamiyordu.
     Olcum: aside position:fixed 288x1024 z-index:50; header z-index:30.
     #mobileMenuBtn 44x44 @ (12,8) tamamen cekmecenin altinda kaliyor;
     elementFromPoint(34,30) -> aside icindeki <img>; gercek tiklama
     6000ms'de 'img from <aside> subtree intercepts pointer events' ile
     BASARISIZ, body.mobile-menu-open kalkmiyordu.
     Cozum burada olmak zorunda: buton app.js tarafindan header'in ICINE
     ekleniyor (ensureMobileMenu: header.prepend), header ise z-index:30
     ile KENDI yigin baglami; butona z-index vermek onu header'in
     baglamindan cikaramaz. Tek dogru mudahale header katmanini
     cekmecenin (50) ve kaplamanin (40) uzerine almaktir.
     Toast/center-success (9999) ve dialog top-layer bundan etkilenmez. */
  main>header{z-index:60}

  /* Header artik cekmecenin ustunde boyandigi icin cekmecenin ust
     --header-h'si opak header'in altinda kalirdi (marka logosu gizlenir).
     Icerik header'in altindan baslar; 61px'lik dolgu tam olarak header
     kadar, sihirli sayi yok. Kaydirma: 15 nav ogesi x 44px + marka blogu
     ~101px = ~761px; 800px'lik telefonda dolgu ile 822px'e cikiyor,
     yani liste ARTIK kaydirilmak zorunda -> asagidaki taban kural
     (.app>aside{overflow-y:auto}) ile son oge (SISTEM & YEDEK) 640px ve
     740px yuksekligindeki telefonlarda da erisilebilir kalir. */
  .app>aside{
    padding-top:var(--header-h);
    -webkit-overflow-scrolling:touch;
  }

  /* KUSUR (yuksek, 15 ekranin tamami): serit clientWidth 360-390 /
     scrollWidth 559-561 -> 169-201px (%30-36) gorunmez; KALITE ve
     SEVKIYAT hic gorunmuyordu (SEVKIYAT right=561, viewport'u 201px
     asiyor). SPEC bolum 4 mobilde SARMA ve ETIKET GIZLEME yasakliyor
     ("yatay kaydirilir, etiketler gizlenmez"), o yuzden cozum patch
     dolgusunu daraltmak: 6 patch x 2 x (16-12) = 48px kazanc,
     scrollWidth 561 -> 487 (olculdu). 768px tablette bu, seridin
     TAMAMEN sigmasi demek: cw 768 / sw 768, gizli 0px.
     Kaydirilabilirligin ikinci ipucu tutma noktalari: proximity secildi
     (mandatory serbest swipe'i kilitler). Gradyan maske SPEC bolum 2
     geregi YAZILMADI; gorunur ince cubuk 60-responsive'de zaten var. */


  /* KUSUR (yuksek/orta, 15 ekranin tamami): #userRole scrollWidth 55px,
     clientWidth system'de 12-18px -> 37-43px kirpik, ekranda 'Y..' —
     hicbir bilgi tasimadan yer yiyor ve #pageTitle'i kirptiriyor.
     Kirpma yerine gizleme burada DOGRU: 12px'lik bir kutuda kirpilmis
     metin bilgi degil, gurultudur. Cikis butonu ve kullanici adi kalir. */
  .user span{display:none}
}


@media (max-width:560px){

  /* KUSUR (yuksek, 13/15 ekran): h1#pageTitle 20px'te header'a sigmiyor.
     Olcum (360-414px): system 271>154..176 -> 95-117px kirpik
     ('Sistem ve Yedekleme M...'), settings 252>149..170 -> 82-103px,
     accounting 178>125..144, personnel 165>134..138, ... production
     113>107. Iki adimla kapatildi:
       1) kullanici adi/rolu header'dan cikti (asagida + yukarida)
          -> baslik blogu 360px'te ~225px'e genisliyor,
       2) baslik SPEC bolum 3 olceginde bir kademe iniyor (20 -> 16px)
          -> en uzun baslik 271px x .8 = ~217px, 225px'e SIGAR.
     Ara deger uydurulmadi; 16px olcekte var. Govdedeki h2 basligi
     zaten 20px kaldigi icin sayfa kimligi kaybolmaz. */
  main>header h1{font-size:16px}

  /* KUSUR (yuksek, 15/15 ekran): b#userName scrollWidth 121px sabit,
     clientWidth 27-46px -> 75-94px kirpik, ekranda 'GO...'/'GOL...'.
     360px telefonda 44px hamburger + baslik + kullanici blogu + Cikis
     ayni satira sigmiyor; kirpilmis iki karakter yerine baslik tam
     gorunur. 560-900 arasinda ad GIZLENMEZ (orada yer var, yalnizca
     rol gizlenir). Cikis butonu her olcude yerinde kalir. */
  .user b{display:none}

  /* Serit telefonda bir kademe daha daralir: dolgu 8px, cip-etiket
     araligi 4px -> scrollWidth 487'den 439'a iner (olculdu). Gizli
     kalan: 414px'te 236 -> 25px, 390px'te 169 -> 49px, 360px'te
     201 -> 79px; KALITE artik her ucunde de TAM gorunur, yalnizca
     SEVKIYAT kaydirma gerektirir. Etiketler ve 11px kunye
     tipografisi (SPEC bolum 3-4) AYNEN kalir. */
}


/* === OTURUM KAPISI — GUVENLIK, ezilmemeli ===
   app.js body uzerinde .session-authenticated sinifini yonetir.
   Bu iki kural kimlik dogrulama KAPISIDIR: oturum acilmadan uygulama
   ekrani, oturum acikken giris ekrani gorunmemeli. Herhangi bir sonraki
   kural veya satir ici stil tarafindan ezilirse giris yapilmadan arayuz
   sizabilir; bu yuzden !important kullanimi BILINCLI bir istisnadir
   (.hidden/[hidden] ile birlikte ucuncu ve son istisna).
   regression_checks.py check_security_regressions() bu iki secicinin
   varligini dogruluyor — silinmemeli. */
body.session-authenticated #loginView{display:none!important}
body:not(.session-authenticated) #appView{display:none!important}


/* ==================== 40-screens-a.css ==================== */

/* ==========================================================================
   40-screens-a.css — URETIM AKISI EKRANLARI
   Uretim, Kalite, Sevkiyat, Aktif Is Takibi, Klise Arsivi,
   Is Emri Dialogu (7 sekme), Olcu sistemi, Renk / Pantone sistemi.
   Belirtecler 10-tokens katmaninda tanimlidir; burada yalnizca var() ile
   kullanilir. Katman sarmalayici, belirtec blogu ve oncelik zorlamasi yok.
   ========================================================================== */

/* === ASAMA RENK DIZISI — kontrol seridiyle ayni dil ======================
   SPEC 4: asama renkleri sirayla --c, --m, --y, --plate, --ok, --k.
   Uygulamanin 6 asamasi (musteri onayi > kalite > uretime kabul >
   uretim bitisi > dagitim cikisi > teslim) bu diziyi paylasir.
   Her gosterge kendi --stage degerini nth-child ile alir.               */

.production-stage,
.archive-stage,
.tracking-stage { --stage: var(--ink-3); }

.production-stage:nth-child(1),
.archive-stage:nth-child(1),
.tracking-stage:nth-child(1) { --stage: var(--c); }

.production-stage:nth-child(2),
.archive-stage:nth-child(2),
.tracking-stage:nth-child(2) { --stage: var(--m); }

.production-stage:nth-child(3),
.archive-stage:nth-child(3),
.tracking-stage:nth-child(3) { --stage: var(--y); }

.production-stage:nth-child(4),
.archive-stage:nth-child(4),
.tracking-stage:nth-child(4) { --stage: var(--plate); }

.production-stage:nth-child(5),
.archive-stage:nth-child(5),
.tracking-stage:nth-child(5) { --stage: var(--ok); }

.production-stage:nth-child(6),
.archive-stage:nth-child(6),
.tracking-stage:nth-child(6) { --stage: var(--k); }


/* === SAYFA KABUKLARI ===================================================== */

.production-page,
.quality-page,
.shipping-page,
.archive-page,
.active-tracking-page {
  display: grid;
  gap: var(--s4);
  align-content: start;
}

/* === GIRIS BASLIKLARI (kunye seridi) ===================================== */

.production-intro,
.quality-intro,
.shipping-intro,
.archive-intro,
.tracking-hero {
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding: var(--s4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  box-shadow: var(--sh1);
}

.production-intro h2,
.quality-intro h2,
.shipping-intro h2,
.archive-intro h2,
.tracking-hero h2 {
  margin: 0;
  font: 700 20px/1.25 var(--ui);
  letter-spacing: -.01em;
  color: var(--ink);
}

.production-intro p,
.quality-intro p,
.shipping-intro p,
.archive-intro p,
.tracking-hero p {
  margin: var(--s1) 0 0;
  font-size: 12px;
  color: var(--ink-2);
  max-width: 78ch;
}

.tracking-hero small {
  display: block;
  margin-bottom: var(--s1);
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

/* Ikon karesi — alet gibi, yuvarlak degil */
.production-icon,
.quality-icon,
.shipping-icon,
.archive-icon {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: var(--r1);
  border: 1px solid var(--line);
  font-size: 20px;
  line-height: 1;
}

/* SPEC 6: proses rengi METIN/GLIF olarak 4.5:1'i gecmiyor (--c 2,7 / --plate 3,3 /
   --ok 3,8). Anlam -soft zeminde tasinir, glif --ink kalir (16:1).            */
.production-icon { background: var(--c-soft);     color: var(--ink); }
.quality-icon    { background: var(--ok-soft);    color: var(--ink); }
.shipping-icon   { background: var(--y-soft);     color: var(--ink); }
.archive-icon    { background: var(--plate-soft); color: var(--ink); }

/* Sayac blogu (arsiv / takip) */
.archive-counter,
.tracking-hero-count {
  margin-left: auto;
  flex: 0 0 auto;
  text-align: right;
  padding-left: var(--s4);
  border-left: 1px solid var(--line);
}

.archive-counter b,
.tracking-hero-count b {
  display: block;
  font: 700 26px/1.1 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.archive-counter span,
.tracking-hero-count span {
  display: block;
  margin-top: var(--s1);
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

/* === EKRAN ARAC CUBUKLARI ================================================ */

.production-split-toolbar,
.shipping-split-toolbar,
.tracking-toolbar,
.quality-toolbar,
.archive-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2);
}

.production-split-toolbar input,
.shipping-split-toolbar input,
.tracking-toolbar input,
.quality-toolbar input,
.archive-toolbar input {
  flex: 1 1 260px;
  min-width: 0;
}

.tracking-toolbar select,
.archive-toolbar select {
  flex: 0 1 220px;
}

/* Siralanabilir baslik oklari mono kalsin.
   OZGULLUK NOTU: 20-primitives'te `th.sortable span{font-size:10px}` var —
   ozgulluk (0,2,1). Onceki hali `.tracking-sort span` (0,2,0) oldugu icin
   font-size bildirimi OLU kalıyordu ve oklar 10px basiliyordu (tarayici
   olcumu: tracking 8 oge, stock 6 oge @10px). `th` eklenerek (0,2,1) esitlik
   kuruluyor; bu dosya 20-primitives'ten SONRA geldigi icin kazanir.        */
th.tracking-sort span,
th.quality-sort span,
th.archive-sort-header span {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-3);
}

.archive-sort-header,
.tracking-sort,
.quality-sort {
  white-space: nowrap;
}


/* === URETIM SAYFASI — gunluk metrikler =================================== */

.production-metric-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--s3);
}

.production-metric-grid article {
  padding: var(--s3) var(--s4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  box-shadow: var(--sh1);
}

.production-metric-grid article:nth-child(1) { box-shadow: inset 3px 0 0 var(--c),     var(--sh1); }
.production-metric-grid article:nth-child(2) { box-shadow: inset 3px 0 0 var(--plate), var(--sh1); }
.production-metric-grid article:nth-child(3) { box-shadow: inset 3px 0 0 var(--y),     var(--sh1); }
.production-metric-grid article:nth-child(4) { box-shadow: inset 3px 0 0 var(--no),    var(--sh1); }
.production-metric-grid article:nth-child(5) { box-shadow: inset 3px 0 0 var(--ok),    var(--sh1); }

.production-metric-grid span {
  display: block;
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

.production-metric-grid b {
  display: block;
  margin-top: var(--s2);
  font: 700 26px/1.1 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

/* Yalnızca GERİ KAZANILAN kutusunda var — sayı fire hesabına girmiyor,
   `title` tooltip'i dokunmatikte hiç açılmadığı için görünür metin şart
   (bkz. .management-stat/.stock-summary-card small ile AYNI dil). */
.production-metric-grid small {
  display: block;
  margin-top: var(--s1);
  font-size: 12px;
  color: var(--ink-3);
}

/* === URETIM SAYFASI — ham klise kaydi ==================================== */

.raw-plate-panel { display: grid; gap: var(--s4); }

.raw-plate-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s3);
}

.raw-plate-head h3 {
  margin: 0;
  font: 650 16px/1.3 var(--ui);
  letter-spacing: -.01em;
}

.raw-plate-head p {
  margin: var(--s1) 0 0;
  font-size: 12px;
  color: var(--ink-2);
}

.raw-plate-head input { flex: 0 0 170px; }

/* BULGU K1: okunamayan ham kalınlık kaydı uyarısı — Kalınlığa Göre Fire
   tablosunun altında. `.fiyat-tarih-ipucu` ile AYNI görsel dil (border-left
   + zemin rengi); yeni bir uyarı biçemi icat edilmedi. JS bu kutuyu
   `eslesmeyen[]` boşsa `.hidden` bırakır (bkz. kalinlikFiresiniCiz). */
.fire-eslesmeyen-uyari {
  padding: var(--s2);
  border-left: 3px solid var(--warn);
  background: var(--paper-2);
  border-radius: var(--r1);
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--ink-2);
}

/* GERİ KAZANIM ROZETİ — ham sütunundan AYRI okunmalı.
   Aynı hücrede ham'la yan yana durursa toplandığı sanılır; bu rozet
   "bu miktar fire hesabına girmedi" demek. */
.fire-geri-kazanim{
  display:inline-block;
  margin-inline-start:var(--s2);
  font-size:.85em;
  opacity:.85;
}

/* FİRE HESABI AÇIKLAMASI (Görev 3) — `.fiyat-tarih-ipucu` ile AYNI görsel
   dil (border-left + ikincil zemin), yeni bir kutu biçemi icat edilmedi;
   tek fark kapanır/açılır olması (`<details>`). Varsayılan kapalı olduğu
   için `summary` kapalıyken de rahat tıklanabilsin diye panel gibi
   davranıyor, ayrı bir "kart" biçemi eklenmedi. */
.fire-hesap-aciklama{
  /* IZGARA ÖĞESİ KÜÇÜLEBİLMELİ — `min-width:0` OLMADAN SAĞA TAŞIYOR.
     Kullanıcı bildirdi: "Fire nasıl hesaplanıyor yazısı sağa taşmış, bir
     kısmı okunmuyor."
     Sebep: `.reports-tab-page` bir grid (styles.css:5198) ve bu `<details>`
     onun ÖĞESİ. Izgara öğesinin varsayılanı `min-width:auto`, yani
     içeriğinin DOĞAL genişliğinin altına inmez. İçerideki `<pre>` örneğin
     satırları uzun olduğu için kutu şişiyor ve küçülmeyi reddediyor;
     `.fire-hesap-ornek`in kendi `overflow-x:auto`u HİÇ DEVREYE GİRMİYOR
     çünkü kaydırılacak bir daralma yaşanmıyor — ebeveyn büyüyor.
     Bu depo kalıbı biliyor: `min-width:0` 51 yerde geçiyor ve
     `.reports-tab-page`in kendisine de verilmiş (6928). Yeni öğeye
     verilmemişti. */
  min-width:0;
  padding:var(--s2) var(--s3);
  border-left:3px solid var(--y);
  background:var(--paper-2);
  border-radius:var(--r1);
  font-size:12.5px;
  line-height:1.55;
  color:var(--ink-2);
}
/* Gövde de küçülebilmeli: içindeki `ol` de bir grid (aşağıda), aynı
   `min-width:auto` varsayılanı zinciri burada da kırardı. */
.fire-hesap-aciklama-govde{min-width:0}
.fire-hesap-aciklama summary{
  cursor:pointer;
  font-weight:650;
  color:var(--ink);
}
.fire-hesap-aciklama[open] summary{margin-bottom:var(--s2)}
.fire-hesap-aciklama-govde ol{margin:0;padding-inline-start:1.2em;display:grid;gap:var(--s1);min-width:0}
.fire-hesap-aciklama-govde li{min-width:0;overflow-wrap:anywhere}
.fire-hesap-aciklama-govde p{margin:var(--s3) 0 var(--s1)}
/* Sayısal örnek — sabit genişlikli rakamlarla hizalanır. Telefon genişliği
   (bkz. 60-responsive.css @360x800) taşırsa SAYFA değil KENDİ kutusu
   yatay kaydırılır. */
.fire-hesap-ornek{
  margin:0;
  padding:var(--s2);
  overflow-x:auto;
  font-family:var(--mono);
  font-size:11.5px;
  line-height:1.5;
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--r1);
}

.raw-plate-form {
  display: grid;
  grid-template-columns: minmax(0, 2fr) repeat(3, minmax(0, 1fr)) minmax(0, 1.4fr) auto;
  gap: var(--s2);
  align-items: center;
  padding: var(--s3);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}

.raw-plate-form input {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.workflow-column {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  gap: var(--s3);
  padding: var(--s4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  box-shadow: inset 0 3px 0 var(--y), var(--sh1);
}
.production-finish-column,
.shipping-route-column { box-shadow: inset 0 3px 0 var(--c), var(--sh1); }

.workflow-column-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s3);
  padding-bottom: var(--s3);
  border-bottom: 1px solid var(--line);
}

.workflow-column-head h3 {
  margin: 0;
  font: 650 15px/1.3 var(--ui);
  letter-spacing: -.01em;
}

.workflow-column-head p {
  margin: var(--s1) 0 0;
  font-size: 12px;
  color: var(--ink-2);
}

.workflow-column-head b {
  flex: 0 0 auto;
  font: 700 26px/1 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.workflow-table {
  max-height: 420px;
  overflow: auto;
}

/* `min-width:560px` kaldirildi: bu tablolar 482-519px'lik yan panelde
   duruyor, yani taban her zaman kaptan genisti. */
.workflow-table table { width: 100%; min-width: 0; }
.workflow-table tbody tr { cursor: pointer; }

/* .quality-empty / .archive-empty 20-primitives bos durum ailesinde;
   .workflow-empty ayni aileye buradan katilir.                          */
.workflow-empty {
  padding: var(--s5) var(--s4);
  text-align: center;
  font: 600 11px/1.6 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

/* === PANO IS AKISI ROZETLERI (workflow-metric) =========================== */

.workflow-summary-panel { display: grid; gap: var(--s3); align-content: start; }

/* Pano is akisi izgarasi — 6 asama rozeti. Giristen sonraki ILK ekran;
   taban kural olmadan 6 rozet tek kolonda dizilip paneli 6 kat uzatiyordu.
   .management-grid'in 1.5fr izinde 3 kolon ~250px iz verir.                */
.dashboard-workflow {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s3);
}

.workflow-metric {
  position: relative;
  overflow: hidden;
  display: block;
  width: 100%;
  min-height: 84px;
  padding: var(--s3) var(--s3) var(--s4);
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  cursor: pointer;
  transition: background-color 140ms, border-color 140ms;
}

.workflow-metric:hover { background: var(--paper-2); }
.workflow-metric:focus-visible { border-color: var(--m); box-shadow: 0 0 0 3px var(--m-soft); }

.workflow-metric span {
  display: block;
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

.workflow-metric b {
  display: block;
  margin-top: var(--s2);
  font: 700 26px/1.1 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.workflow-metric small {
  display: block;
  margin-top: var(--s1);
  font-size: 11px;
  color: var(--m);
}

.workflow-metric i {
  position: absolute;
  inset: auto 0 0 0;
  height: 3px;
  background: var(--ink-3);
}

/* Durum seridi — asama renk dizisiyle ayni sira */
.workflow-metric i[data-status="MÜŞTERİ ONAYI BEKLİYOR"]   { background: var(--c); }
.workflow-metric i[data-status="KALİTE KONTROL BEKLİYOR"]  { background: var(--m); }
.workflow-metric i[data-status="ÜRETİME HAZIR"]            { background: var(--y); }
.workflow-metric i[data-status="ÜRETİMDE"]                 { background: var(--plate); }
.workflow-metric i[data-status="SEVKİYATA HAZIR"]          { background: var(--ok); }
.workflow-metric i[data-status="DAĞITIMDA"]                { background: var(--k); }
.workflow-metric i[data-status="TESLİM EDİLDİ"]            { background: var(--ok); }


/* === URETIM IS AKIS DIALOGU ============================================== */

.production-dialog {
  width: min(1080px, 96vw);
  max-height: 92vh;
  padding: 0;
}

.production-dialog-shell {
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr);
  max-height: 92vh;
}

.production-job-head {
  display: flex;
  align-items: flex-start;
  gap: var(--s4);
  padding: var(--s4) var(--s5);
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}

.production-job-head small {
  display: block;
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

.production-job-head h2 {
  margin: var(--s1) 0 0;
  font: 700 20px/1.25 var(--ui);
  letter-spacing: -.01em;
}

.production-job-head p {
  margin: var(--s1) 0 0;
  font-size: 12px;
  color: var(--ink-2);
}

.production-job-head .dialog-close { margin-left: auto; }

/* Asama seridi — baski kontrol seridinin dialog karsiligi */
.production-stage-strip {
  display: flex;
  overflow-x: auto;
  background: var(--paper-2);
  border-bottom: 1px solid var(--line);
}

.production-stage {
  display: flex;
  align-items: center;
  gap: var(--s2);
  flex: 1 0 auto;
  min-height: 34px;
  padding: var(--s2) var(--s3);
  border-right: 1px solid var(--line);
  font: 600 11px/1.3 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
  white-space: nowrap;
}

.production-stage:last-child { border-right: 0; }

/* Patch karesi: dolu = tamamlandi, konturlu = bekliyor */
.production-stage::before {
  content: "";
  flex: 0 0 auto;
  width: 10px;
  height: 10px;
  border: 1px solid var(--line);
  background: transparent;
}

.production-stage.done {
  background: var(--surface);
  color: var(--ink);
}

.production-stage.done::before {
  background: var(--stage);
  border-color: var(--stage);
}

.production-stage.active {
  background: var(--c-soft);
  color: var(--ink);
  box-shadow: inset 0 -2px 0 var(--c);
}

.production-stage.active::before { border-color: var(--c); }

/* Dialog govdesi: yapilacak islem + tamamlananlar */
.production-dialog-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: var(--s5);
  padding: var(--s5);
  overflow: auto;
  background: var(--paper);
}

.production-current-section,
.production-completed-section {
  display: grid;
  gap: var(--s3);
  align-content: start;
  min-width: 0;
}

.production-current-section h3,
.production-completed-section h3 {
  margin: 0;
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

.production-current-card {
  display: grid;
  gap: var(--s4);
  padding: var(--s4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  box-shadow: inset 3px 0 0 var(--c), var(--sh1);
}

.production-current-card h4 {
  margin: 0;
  font: 650 16px/1.3 var(--ui);
  letter-spacing: -.01em;
}

.production-current-card p {
  margin: var(--s2) 0 0;
  font-size: 13px;
  color: var(--ink-2);
}

/* Bos durum cercevesi 20-primitives'ten; burada yalnizca ic yerlesim */
.production-all-done {
  display: grid;
  gap: var(--s1);
  justify-items: center;
}

.production-all-done b { font: 700 14px/1.4 var(--ui); color: var(--ink); }
.production-all-done span { font-size: 12px; color: var(--ink-2); }

/* Tamamlanan asama kayitlari */
.production-completed-list {
  display: grid;
  gap: var(--s2);
  max-height: 52vh;
  overflow: auto;
}

.production-record-check {
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  border-radius: var(--r1);
  background: var(--ok-soft);
  color: var(--ink);
  font-size: 13px;
  font-weight: 700;
}

.production-record h4 {
  margin: 0;
  font: 650 14px/1.3 var(--ui);
}

.production-record p {
  margin: var(--s1) 0 0;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  color: var(--ink-2);
}

.production-record small {
  display: block;
  margin-top: var(--s1);
  font-size: 12px;
  color: var(--ink-3);
}

.delivery-received {
  display: inline-block;
  margin-top: var(--s2);
  padding: 2px var(--s2);
  border-radius: var(--r1);
  background: var(--ok-soft);
  color: var(--ink);
  font-size: 11px;
}

.production-record-image {
  margin-top: var(--s2);
  font-size: 12px;
}

/* === URETIM ASAMA KAYIT FORMU (child dialog) ============================= */

.production-action-dialog {
  width: min(760px, 96vw);
  max-height: 92vh;
  padding: 0;
}

/* Kunye bandi (.dialog-head) ve aksiyon bandi (.child-actions) kenara
   dayanir; yatay dolgu yalnizca govde ogelerine verilir. Bkz. .job-dialog. */
.production-action-dialog form {
  display: grid;
  gap: var(--s3);
  max-height: 92vh;
  padding: 0;
  overflow: auto;
}

.production-action-dialog form > :not(.dialog-head):not(.child-actions) {
  margin-inline: var(--s5);
}

/* Sevkiyat / teslim asamasi kaydediliyorsa ust kenarda asama rengi */
.shipping-action-mode { box-shadow: inset 0 3px 0 var(--ok); }
.delivery-action-mode { box-shadow: inset 0 3px 0 var(--k); }

/* Olcu bolumu — uretimde girilen gercek olculer */
.production-measure-slot {
  display: grid;
  gap: var(--s3);
  padding: var(--s4);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r2);
}

.measurement-source-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s4);
}

.measurement-source-note {
  padding: var(--s2) var(--s3);
  background: var(--c-soft);
  border-radius: var(--r1);
  font: 600 11px/1.5 var(--mono);
  letter-spacing: .02em;
  color: var(--ink-2);
}

.production-stock-choice { display: grid; gap: var(--s1); }

.production-stock-choice small {
  font-size: 11px;
  color: var(--ink-3);
}

.production-material-options { display: grid; gap: var(--s2); }

.production-material-check {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--s2);
  align-items: start;
  padding: var(--s2) var(--s3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r1);
  font-weight: 400;
  cursor: pointer;
}

.production-material-check b {
  display: block;
  font: 650 13px/1.4 var(--ui);
}

.production-material-check small {
  display: block;
  font-size: 11px;
  color: var(--ink-3);
}

.production-material-check:has(input:checked) {
  border-color: var(--m);
  background: var(--m-soft);
}

/* Asetat otomatik dusum — bilgilendirici, kullanici degistiremez */
/* `.acetate-auto` KALDIRILDI: dayandığı `checked disabled` onay kutusu
   bilgi satırına çevrildi (bkz. .production-material-note). Kural
   dursaydı hiçbir öğeyi eşleştirmeyen ölü CSS olurdu. */

.production-bar-stock { display: grid; gap: var(--s1); }

/* === URETIM OLCU GIRISI ================================================== */

.production-measure-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s3);
}

.production-measure-grid article {
  display: grid;
  gap: var(--s2);
  align-content: start;
  padding: var(--s3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}

.production-measure-grid h4 {
  margin: 0;
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

.production-measure-entry,
.measure-entry {
  display: grid;
  grid-template-columns: repeat(3, minmax(56px, 1fr)) minmax(0, 2fr) auto;
  gap: var(--s1);
  align-items: center;
}

/* DAR KARTTA SATIR İKİYE BÖLÜNÜR  (20.08)
   ====================================================================
   Kullanıcı bildirdi: "kutucuklar taşma yapıyor, alana sığmıyor".
   Ölçüldü — ölçü penceresi üç sütuna geçince kart 261px'e indi ve
   yukarıdaki ızgara şu hâle geldi:  56px 56px 56px  0px  62px
   Yani AÇIKLAMA alanı SIFIR piksele çöktü ve + Ekle düğmesiyle üst üste
   bindi. Kullanıcının ekran görüntüsünde Açıklama'nın hiç görünmemesinin
   sebebi buydu; alan duruyordu ama tıklanamıyordu.

   SEBEBİ BENİM DEĞİŞİKLİĞİMDİ: pencereyi üç sütuna bölerken ölçü
   kartlarının daralacağını hesaba katmadım. Sabit 56px'lik üç sütun +
   düğme, 219px'lik kullanılabilir alana sığmıyor.

   ÇÖZÜM: kartın KENDİ genişliğine göre satırı ikiye böl. Ekran
   genişliğine bakan bir medya sorgusu burada yanlış ölçüt olurdu —
   aynı kart iş emri kartında geniş, muhasebe penceresinde dar.
   ==================================================================== */
.production-measure-grid > article,
.measure-grid > article { container-type: inline-size; }

@container (max-width: 340px) {
  .production-measure-entry,
  .measure-entry { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* Açıklama iki sütun, düğme bir sütun: ikinci satır tam dolar. */
  .production-measure-entry > input:nth-child(4),
  .measure-entry > input:nth-child(4) { grid-column: 1 / 3; }
  .production-measure-entry > button,
  .measure-entry > button { grid-column: 3 / 4; }
}

.production-measure-entry input:nth-child(-n+3),
.measure-entry input:nth-child(-n+3) {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.production-measure-list {
  min-height: 120px;
  max-height: 220px;
  overflow: auto;
  padding: var(--s2);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}

.production-measure-list > div {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: var(--s2);
  align-items: center;
  padding: var(--s1) 0;
  border-bottom: 1px solid var(--line-2);
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 12px;
}

.production-measure-list b { font-weight: 700; color: var(--ink); }

.production-measure-list p {
  margin: 0;
  padding: var(--s3) 0;
  font-size: 12px;
  color: var(--ink-3);
}

/* Toplam satiri ustte ince cizgiyle ayrilir */
.production-measure-list > strong {
  display: block;
  margin-top: var(--s2);
  padding-top: var(--s2);
  border-top: 1px solid var(--line);
  text-align: right;
  font: 700 13px/1.4 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

/* === ASAMA GORSELLERI ==================================================== */

.production-image-section {
  display: grid;
  gap: var(--s2);
  padding: var(--s3);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}

.production-image-section > small {
  font-size: 11px;
  color: var(--ink-3);
}

.production-image-buttons {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2);
}

.production-image-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--s2);
}

.production-image-item.existing { box-shadow: inset 3px 0 0 var(--ok); }
.production-image-item.pending  { box-shadow: inset 3px 0 0 var(--y); }

.production-image-item img {
  width: 100%;
  height: 84px;
  object-fit: contain;
  background: var(--paper-2);
  border-radius: var(--r1);
}

.production-image-item > div {
  height: 84px;
  display: grid;
  place-items: center;
  background: var(--ok-soft);
  border-radius: var(--r1);
  color: var(--ink);
  font-size: 20px;
}

.production-image-item span {
  font-size: 12px;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.production-image-item small {
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}


/* === KALITE KONTROL ====================================================== */

.quality-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s3);
}

.quality-stat {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  box-shadow: var(--sh1);
}

.quality-stat.warning { box-shadow: inset 3px 0 0 var(--y),  var(--sh1); }
.quality-stat.success { box-shadow: inset 3px 0 0 var(--ok), var(--sh1); }
.quality-stat.total   { box-shadow: inset 3px 0 0 var(--c),  var(--sh1); }

.quality-stat-icon {
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: var(--r1);
  border: 1px solid var(--line);
  background: var(--paper-2);
  color: var(--ink-2);
  font-size: 16px;
}

/* Ikon glifi notr; durum bilgisi sol seritte ve -soft zeminde (SPEC 6) */
.quality-stat.warning .quality-stat-icon { background: var(--y-soft);  color: var(--ink); }
.quality-stat.success .quality-stat-icon { background: var(--ok-soft); color: var(--ink); }
.quality-stat.total   .quality-stat-icon { background: var(--c-soft);  color: var(--ink); }

.quality-stat span {
  display: block;
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

.quality-stat b {
  display: block;
  margin: var(--s1) 0;
  font: 700 26px/1.1 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.quality-stat small { font-size: 11px; color: var(--ink-3); }

/* .quality-status rozeti 20-primitives rozet sisteminden gelir. */

.quality-table-panel { display: grid; gap: var(--s3); }


/* === SEVKIYAT ============================================================ */

/* KAPALI DIALOG KURALI: yazar kaynakli `display` bildirimi, UA sayfasindaki
   dialog:not([open]){display:none} kuralini ozgullukten bagimsiz olarak ezer.
   Bu yuzden display DAIMA [open] kapisinin arkasinda kalir.                 */
.shipping-label-dialog {
  width: min(860px, 96vw);
  max-height: 94vh;
  padding: 0;
}

.shipping-label-dialog[open] {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
}

.shipping-label-dialog-head {
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding: var(--s4) var(--s5);
  border-bottom: 1px solid var(--line);
}

.shipping-label-dialog-head h2 {
  margin: 0;
  font: 700 20px/1.25 var(--ui);
  letter-spacing: -.01em;
}

.shipping-label-dialog-head span {
  display: block;
  margin-top: var(--s1);
  font: 700 13px/1.3 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
}

.shipping-label-dialog-head button { margin-left: auto; }

.shipping-label-dialog iframe {
  width: 100%;
  height: 100%;
  min-height: 420px;
  border: 0;
  background: var(--paper-2);
}

.shipping-label-dialog footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--s2);
  padding: var(--s3) var(--s5);
  border-top: 1px solid var(--line);
}


/* === AKTIF IS TAKIBI ===================================================== */

.tracking-summary {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s3);
}

.tracking-summary > div,
.tracking-summary > button {
  display: block;
  width: 100%;
  padding: var(--s3) var(--s4);
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  box-shadow: inset 3px 0 0 var(--ink-3), var(--sh1);
  transition: background-color 140ms, border-color 140ms, box-shadow 140ms;
}

.tracking-summary > button { cursor: pointer; }
.tracking-summary > button:hover { background: var(--paper-2); }

.tracking-summary > .active    { box-shadow: inset 3px 0 0 var(--c),     var(--sh1); }
.tracking-summary > .overdue   { box-shadow: inset 3px 0 0 var(--no),    var(--sh1); }
.tracking-summary > .today     { box-shadow: inset 3px 0 0 var(--y),     var(--sh1); }
.tracking-summary > .urgent    { box-shadow: inset 3px 0 0 var(--plate), var(--sh1); }
.tracking-summary > .approved  { box-shadow: inset 3px 0 0 var(--c),     var(--sh1); }
.tracking-summary > .completed { box-shadow: inset 3px 0 0 var(--ok),    var(--sh1); }

.tracking-summary > .selected {
  border-color: var(--m);
  background: var(--m-soft);
  box-shadow: inset 3px 0 0 var(--m), var(--sh1);
}

.tracking-summary span {
  display: block;
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

.tracking-summary b {
  display: block;
  margin-top: var(--s2);
  font: 700 26px/1.1 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.tracking-table-panel { display: grid; gap: var(--s3); }

/* Son hareket hucresi */
.tracking-movement {
  display: block;
  font: 600 12px/1.4 var(--ui);
  color: var(--ink);
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.tracking-due {
  background: none;
  color: var(--ink);
  font-family: var(--mono);
  letter-spacing: normal;
  font-variant-numeric: tabular-nums;
}

/* Salt okunur is akisi zaman cizgisi */
.tracking-stage-timeline,
.archive-stage-timeline {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--s2);
}

.tracking-stage,
.archive-stage {
  display: grid;
  gap: var(--s1);
  justify-items: start;
  padding: var(--s3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}

/* Patch karesi = asama numarasi / onay isareti */
.tracking-stage span,
.archive-stage span {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border: 1px solid var(--line);
  background: transparent;
  font: 700 11px/1 var(--mono);
  color: var(--ink-3);
}

.tracking-stage b,
.archive-stage b {
  font: 650 13px/1.3 var(--ui);
  color: var(--ink-2);
}

.tracking-stage small,
.archive-stage small {
  font: 600 11px/1.4 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}

.tracking-stage em {
  font-style: normal;
  font-size: 11px;
  color: var(--ink-2);
}

/* SPEC 6 IHLALI DUZELTMESI: patch icinde GERCEK METIN var (✓ veya asama
   numarasi). Duz dolgu + beyaz metin 6 asamanin 4'unde 4.5:1'in altinda
   kaliyordu (--y 1,67 / --c 3,04 / --plate 3,32 / --ok 4,37). Dolguyu koyu
   metne cevirmek de ise yaramaz: 6. asama --k, koyu uzerinde koyu = 1:1.
   Cozum: 2px asama renginde kontur + --ink metin. Tamamlandi/bekliyor
   ayrimi korunur (bekleyen 1px --line sac teli), kontrast her asamada 16:1. */
.tracking-stage.completed span,
.archive-stage.completed span {
  background: var(--surface);
  border: 2px solid var(--stage);
  color: var(--ink);
}

.tracking-stage.completed b,
.archive-stage.completed b { color: var(--ink); }

.tracking-stage.current {
  background: var(--c-soft);
  border-color: var(--c);
}

.tracking-stage.current span { border-color: var(--c); color: var(--ink); }
.tracking-stage.current b { color: var(--ink); }

.tracking-stage.pending,
.archive-stage.pending { background: var(--paper-2); }

/* Son hareket notu kutusu */
.tracking-last-note {
  display: grid;
  gap: var(--s1);
  padding: var(--s3);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}

.tracking-last-note span {
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

.tracking-last-note p {
  margin: 0;
  white-space: pre-line;
  font-size: 13px;
  color: var(--ink-2);
}


/* === KLISE ARSIVI ======================================================== */

.archive-table-panel { display: grid; gap: var(--s4); }

.archive-panel-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s3);
  padding-bottom: var(--s3);
  border-bottom: 1px solid var(--line);
}

.archive-panel-head h3 {
  margin: 0;
  font: 650 16px/1.3 var(--ui);
  letter-spacing: -.01em;
}

.archive-panel-head small {
  display: block;
  margin-top: var(--s1);
  font-size: 11px;
  color: var(--ink-3);
}

.archive-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
}

/* Dosya rozetleri — rozet gorunumu 20-primitives katmanindan gelir */
.archive-file-badges {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s1);
}

/* Salt okunur acilan is emri — ust kenarda klise amberi */
.archive-readonly-dialog { box-shadow: inset 0 3px 0 var(--plate), var(--sh3); }

/* --- Arsiv teslimat dialogu --- */
.archive-delivery-dialog,
.archive-workflow-dialog {
  width: min(880px, 96vw);
  max-height: 92vh;
  padding: 0;
}

/* display yalnizca [open] ile — bkz. .shipping-label-dialog notu */
.archive-delivery-dialog[open],
.archive-workflow-dialog[open] {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
}

.archive-delivery-body,
.archive-workflow-body {
  display: grid;
  gap: var(--s4);
  align-content: start;
  padding: var(--s5);
  overflow: auto;
  background: var(--paper);
}

.archive-delivery-meta,
.archive-workflow-detail {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--s2);
}

.archive-delivery-meta > div,
.archive-workflow-detail > div {
  padding: var(--s3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}

.archive-delivery-meta span,
.archive-workflow-detail span {
  display: block;
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

.archive-delivery-meta b,
.archive-workflow-detail b {
  display: block;
  margin-top: var(--s1);
  font: 650 13px/1.4 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.archive-delivery-note-card {
  display: grid;
  gap: var(--s1);
  padding: var(--s3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r1);
  box-shadow: inset 3px 0 0 var(--plate);
}

.archive-delivery-note-card span {
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

.archive-delivery-note-card p {
  margin: 0;
  font-size: 13px;
  color: var(--ink-2);
  white-space: pre-line;
}

.archive-delivery-image-section { display: grid; gap: var(--s2); }

.archive-delivery-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: var(--s2);
}

.archive-delivery-gallery button {
  display: grid;
  gap: var(--s1);
  padding: var(--s2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r1);
  cursor: pointer;
  transition: border-color 140ms, box-shadow 140ms;
}

.archive-delivery-gallery button:hover { border-color: var(--m); }

.archive-delivery-gallery img {
  width: 100%;
  height: 110px;
  object-fit: contain;
  background: var(--paper-2);
  border-radius: var(--r1);
}

.archive-delivery-gallery span {
  font-size: 12px;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.archive-delivery-gallery small {
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

/* .archive-delivery-no-image bos durum gorunumu 20-primitives'ten gelir. */


/* === ASAMA GORSEL GALERISI (app.js:1220-1226 uretir) =====================
   Uretim ve arsiv ekranlarindan acilan galeri. Dialog `display` ALMAZ:
   taban dialog{overflow:auto} + govdenin kendi kaydirmasi yeterli, boylece
   [open] kapisi gerekmez ve kapali dialog asla akisa dokulmez.           */

.stage-image-gallery-dialog {
  width: min(960px, 96vw);
  max-height: 92vh;
  padding: 0;
}

.stage-image-gallery-body {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: var(--s3);
  max-height: 72vh;
  padding: var(--s4);
  overflow: auto;
}

.stage-image-card {
  display: grid;
  gap: var(--s1);
  padding: var(--s2);
  text-align: left;
  white-space: normal;
  font: inherit;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  cursor: pointer;
  transition: background-color 140ms, border-color 140ms, box-shadow 140ms;
}

.stage-image-card:hover { background: var(--paper-2); border-color: var(--m); }
.stage-image-card:focus-visible { border-color: var(--m); box-shadow: 0 0 0 3px var(--m-soft); }

.stage-image-card img {
  width: 100%;
  height: 132px;
  object-fit: cover;
  background: var(--paper-2);
  border-radius: var(--r1);
}

.stage-image-card span {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink);
  overflow-wrap: anywhere;
}

.stage-image-card small {
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}


/* === IS EMRI DIALOGU — kabuk =============================================
   Neredeyse tam ekran bir form: yogun ama nefes alan yerlesim.
   Kagit zemin (--paper) uzerinde beyaz alt kartlar.                      */

.job-dialog {
  width: min(1560px, 98vw);
  height: 96vh;
  max-width: none;
  padding: 0;
}

/* DOLGU SAHIPLIGI: kunye bandi (.gold-modal-header) kendi dolgusunu
   20-primitives'ten alir ve dialog kenarina DAYANIR. Bu yuzden form yatay
   dolgu tasimaz; govde ogeleri margin-inline ile ice cekilir. Aksi halde
   bant 16px ice kacar ve kenarliklari dialog kenarina ulasmaz.           */
.job-dialog form {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  height: 100%;
  padding: 0 0 var(--s4);
  background: var(--paper);
}

.job-dialog form > :not(.gold-modal-header) { margin-inline: var(--s4); }

.job-summary > div { min-width: 0; }

.job-summary small {
  display: block;
  margin-bottom: var(--s1);
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.produced-job-badge {
  background: var(--ok-soft);
  color: var(--ink);
  align-self: flex-start;
}

/* Sekme govdesi — tek kaydirilan alan */
.tab-page {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: var(--s1) var(--s1) var(--s4);
}

/* === SALT OKUNUR IS EMRI (app.js:3994 `readonly-job-section`) ============
   Uretilmis is: app.js sinifi 5 sekme panelinin (.tab-page) uzerine koyup
   icindeki tum girdileri disabled yapiyor. Gorsel karsiligi olmadan form
   "bozuk" gorunuyordu — uretim/kalite akisinda dogrudan is hatasi riski. */

.readonly-job-section {
  background: var(--paper-2);
  box-shadow: inset 3px 0 0 var(--plate);
}

/* Kunye: sag ustte klise amberi rozet. ::before kullanilir (icerikten ONCE)
   ve `sticky` ile kaydirma boyunca gorunur kalir; `float` YOK — .tab-page
   icindeki grid kapsayicilar float'tan kacinip yerlesimi bozardi.        */
.readonly-job-section::before {
  content: "ÜRETİLMİŞ İŞ — SALT OKUNUR";
  position: sticky;
  top: 0;
  z-index: 3;
  display: block;
  width: max-content;
  max-width: 100%;
  margin: 0 0 var(--s3) auto;
  padding: 2px var(--s2);
  background: var(--plate-soft);
  border: 1px solid var(--plate);
  border-radius: var(--r1);
  font: 600 11px/1.6 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink);
}

/* Kapali alanlar OKUNUR kalir: 20-primitives `input:disabled` --ink-3 metni
   --paper-2 uzerinde 3,5:1 veriyor; veri kaybolmus gibi gorunuyordu.     */
.readonly-job-section input:disabled,
.readonly-job-section select:disabled,
.readonly-job-section textarea:disabled {
  opacity: 1;
  background: var(--surface);
  border-color: var(--line);
  color: var(--ink-2);
  -webkit-text-fill-color: var(--ink-2);
  cursor: not-allowed;
}

/* .two-col yerlesimi 30-shell katmanindadir; buradaki gridler ona esittir */
.job-info-grid,
.visual-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s4);
  align-items: start;
}

.job-info-right { display: grid; gap: var(--s4); align-content: start; }

/* Alt kart footer — yapisik islem seridi */
.job-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--s2);
  padding-top: var(--s3);
  border-top: 1px solid var(--line);
}

.job-actions button { min-width: 150px; }


/* === ALT KARTLAR (subcard) ===============================================
   Eski #ddd gri gitti: kagit yuzey + sac teli kenarlik + mikro etiket.  */

.subcard {
  display: grid;
  gap: var(--s3);
  align-content: start;
  padding: var(--s4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  box-shadow: var(--sh1);
}

.subcard > h3 {
  margin: 0;
  padding-bottom: var(--s2);
  border-bottom: 1px solid var(--line-2);
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

.subcard textarea { min-height: 96px; }

/* Kart icine gomulu ikincil kart */
.embedded-card {
  display: grid;
  gap: var(--s2);
  padding: var(--s3);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}

.embedded-card > h3 {
  margin: 0;
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

/* Kalinlik secenekleri gercek bir cip gibi: konturlu, secilince magenta */
.radio-grid label {
  padding: 0 var(--s2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r1);
  transition: background-color 140ms, border-color 140ms;
}

.radio-grid label:hover { background: var(--paper-2); }
.radio-grid label:has(input:checked) { border-color: var(--m); background: var(--m-soft); }

.inline-radio {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s5);
}

.vertical-radio { display: grid; gap: var(--s2); }

.bar-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s3);
}

.bar-grid > div { display: grid; gap: var(--s2); align-content: start; }

.bar-grid b {
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

.checks {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s5);
}

/* Uretimde esas alinacak olcu isareti — kritik secim, vurgulu */
.production-basis-check {
  padding: var(--s2) var(--s3);
  background: var(--plate-soft);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}

/* Olcu bicimi (2D / 3D) */
.dimension-block { display: grid; gap: var(--s2); }

.dimension-mode {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s4);
}

/* EN × BOY × YÜKSEKLİK — HER ZAMAN TEK SATIR (S5)
   Önce `auto-fit, minmax(88px, 1fr)` vardı: sütun sayısını kabın genişliği
   belirliyordu. Kap 185px'e düşünce üç alan ikiye bölünüp yükseklik alt
   satıra kaçıyordu. Ölçü zaten "en × boy × yükseklik" diye tek nefeste
   okunan bir şey; alt satıra düşmesi okumayı bozuyor.

   Flex + `flex: 1 1 0` alanları eşit paylaştırır ve dar kapta sarmak
   yerine BİRLİKTE küçültür — istenen davranış bu. Gizli yükseklik alanı
   `display:none` olduğu için 2B modda kendiliğinden ikiye döner. */
.dimension-fields {
  display: flex;
  gap: var(--s2);
}

.dimension-fields > label {
  flex: 1 1 0;
  min-width: 0;
}

.dimension-fields input {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
}


/* === KLISE VE MONTAJ SEKMESI ============================================= */

.plate-montage-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: var(--s4);
  align-items: start;
}

/* PARÇA SAYISI ALANI — müşteri revizesi R4
   Alan kartın tamamı kadar (~820px) genişti. Sağa hizalı olduğu için rakam
   en sağda duruyor, kullanıcı ise alanın solundaki boşluğa tıklıyordu:
   imleç rakamın SOLUNA düşüyor ve yazılan yeni sayı eskisinin yanına
   ekleniyordu ("5" yazınca 51). Alanı sayının boyuna indirmek, tıklanan yer
   ile rakamın arasındaki mesafeyi tamamen kaldırıyor. */
.plate-main-card input[name="piece_count"] {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
  max-width: 200px;
}

.plate-side-stack { display: grid; gap: var(--s4); align-content: start; }


/* === REVIZYON SEKMESI ==================================================== */

.revision-page-grid {
  display: grid;
  grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
  gap: var(--s4);
  align-items: start;
}

.revision-entry-card,
.revision-history-card { min-width: 0; }

.revision-entry-card textarea { min-height: 120px; }

.revision-history {
  display: grid;
  gap: var(--s2);
  max-height: 52vh;
  overflow: auto;
}

.revision-history article {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: var(--s3);
  padding: var(--s3);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}

.revision-history b {
  align-self: start;
  display: grid;
  place-items: center;
  height: 24px;
  border-radius: var(--r1);
  background: var(--surface);
  border: 1px solid var(--line);
  font: 700 12px/1 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.revision-history article > div {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s2);
}

.revision-history span { font: 650 13px/1.4 var(--ui); color: var(--ink); }

.revision-history time {
  font: 400 11px/1.4 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}

.revision-history p {
  grid-column: 2;
  margin: var(--s1) 0 0;
  font-size: 13px;
  color: var(--ink-2);
  white-space: pre-line;
}

.file-buttons { align-content: start; }
.file-buttons button { width: 100%; }

.file-buttons p {
  margin: 0;
  font-size: 12px;
  color: var(--ink-2);
}


/* === FORMLAR / YAZDIR SEKMESI ============================================ */

.forms-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: var(--s4);
  align-items: start;
}

.forms-list-card { min-width: 0; }

.job-forms-list { display: grid; gap: var(--s2); }

.job-forms-list button {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr) auto;
  gap: var(--s3);
  align-items: center;
  width: 100%;
  padding: var(--s3);
  text-align: left;
  white-space: normal;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r1);
  cursor: pointer;
  transition: background-color 140ms, border-color 140ms;
}

.job-forms-list button:hover { background: var(--paper-2); border-color: var(--ink-3); }

.job-forms-list button > span {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--r1);
  background: var(--paper-2);
  font-size: 16px;
  color: var(--ink-2);
}

.job-forms-list b { display: block; font: 650 13px/1.4 var(--ui); color: var(--ink); }
.job-forms-list small { display: block; font-size: 11px; color: var(--ink-3); }

.forms-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2);
  padding-top: var(--s3);
  border-top: 1px solid var(--line-2);
}

.forms-actions > span {
  flex: 1 1 180px;
  font-size: 12px;
  color: var(--ink-2);
}

/* PDF ÖNİZLEME BOYUTU — müşteri revizesi R6 ("önizleme çok küçük")
   Kart sabit 480px'ti ve içindeki iframe ona uymuyordu; A4 dikey bir form
   o yükseklikte okunamayacak kadar küçülüyordu. Artık kart görünür alana
   göre ölçekleniyor ve iframe kartı SONUNA KADAR dolduruyor.
   `minmax(0,1fr)` şart: 1fr tek başına içeriğin taban boyutunu taban kabul
   eder ve iframe taşarak kartı büyütürdü. */
.forms-preview-card {
  min-height: min(78vh, 900px);
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
}


/* === MUSTERI ONAYI SEKMESI =============================================== */

.approval-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  gap: var(--s4);
  align-items: start;
}

.approval-card textarea { min-height: 96px; }

.approval-image-box {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2);
  padding: var(--s3);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}

.approval-image-box span {
  font: 600 11px/1.4 var(--mono);
  color: var(--ink-3);
}

.approval-save-btn { width: 100%; }

/* Rozet gorunumu 20-primitives'ten; onay kartinda tam genislikte serit olur */
.approval-status {
  display: flex;
  justify-content: center;
  min-height: 32px;
}

.approval-status-card p {
  margin: 0 0 var(--s2);
  font-size: 13px;
  color: var(--ink-2);
}

.approval-status-card b { color: var(--ink); }


/* === URETIM OLCULERI SEKMESI (mikrometre ciktisi) ========================
   Tamamen mono + tabular-nums, sutunlar hizali, toplam ustte ince cizgi. */

.measurement-governance-card {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) repeat(2, minmax(0, 1fr)) auto;
  gap: var(--s3);
  align-items: end;
  margin-bottom: var(--s4);
  padding: var(--s4);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  box-shadow: inset 3px 0 0 var(--plate);
}

.measurement-governance-card span {
  display: block;
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

.measurement-governance-card b {
  display: block;
  margin: var(--s1) 0;
  font: 650 14px/1.3 var(--ui);
  color: var(--ink);
}

.measurement-governance-card small {
  display: block;
  font-size: 11px;
  color: var(--ink-3);
}

.measure-list {
  min-height: 180px;
  max-height: 300px;
  overflow: auto;
  padding: var(--s2) var(--s3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}

.measure-line {
  padding: var(--s1) 0;
  border-bottom: 1px solid var(--line-2);
  font: 400 12px/1.6 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.measure-line:last-child { border-bottom: 0; }

.measure-list p {
  margin: 0;
  padding: var(--s3) 0;
  font-size: 12px;
  color: var(--ink-3);
}

/* Toplam satiri — listenin ustunde ince cizgiyle ayrilir */
.measure-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2);
  padding-top: var(--s2);
  border-top: 1px solid var(--line);
}

.measure-footer b {
  font: 700 13px/1.4 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}


/* === RENK SISTEMI — gercek Pantone cipi ==================================
   1.341 kayitli katalog. Cip: kare, ince koyu kontur, hafif ic golge;
   yaninda mono teknik kod. Bu ekranin yildizi.                          */

.color-list {
  display: grid;
  gap: var(--s2);
  align-content: start;
  min-height: 280px;
  max-height: 420px;
  overflow: auto;
  padding: var(--s2);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}

.color-list p { margin: 0; padding: var(--s3); font-size: 12px; color: var(--ink-3); }

.color-card > b {
  font: 400 11px/1.4 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}

/* Pantone / CMYK cipi — kontur belirtece baglanir. Onceki hali uc uydurma
   rgba() ve 8px bulanik ic golge iceriyordu; bulanik ic golge bir yuzey
   parlaklik gecisi (gradyan) uretiyordu — SPEC 2 yasakliyor.             */
.color-card i,
.pantone-row i,
.preview-row i {
  display: block;
  border: 1px solid var(--ink-3);
  border-radius: 1px;
  background: var(--surface);
  box-shadow: var(--sh1);
}

/* Dogrulanmamis Pantone kodu — renk uydurulmaz. Gradyan yerine kesikli
   kontur: SPEC 2 "Gradyan YOK", ayni bilgi cizgi diliyle verilir.        */
.color-screen-preview.pantone-unverified,
.pantone-row i.pantone-unverified {
  background: var(--paper-2);
  border-style: dashed;
  border-color: var(--ink-3);
  box-shadow: none;
}

.color-name strong {
  display: block;
  font: 650 13px/1.4 var(--ui);
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
}

/* CMYK kanal degerleri — kanal renkleri yalnizca burada anlam tasir */
.cmyk-values {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s1);
  margin-top: var(--s1);
}

.cmyk-values span {
  padding: 1px var(--s1);
  border-radius: 2px;
  font: 600 11px/1.5 var(--mono);
  font-variant-numeric: tabular-nums;
}

/* Belirtec seti disinda hex YOK: kanal kimligi -soft zeminden okunur,
   metin murekkep siyahi kalir (SPEC 2 "renk uydurma", SPEC 5 rozet deseni). */
.c-channel { background: var(--c-soft);  color: var(--k); }
.m-channel { background: var(--m-soft);  color: var(--m-hover); }
.y-channel { background: var(--y-soft);  color: var(--k); }
.k-channel { background: var(--paper-2); color: var(--k); }

.pantone-definition { margin-top: var(--s1); }

.pantone-definition b {
  font: 700 12px/1.4 var(--mono);
  letter-spacing: .02em;
  color: var(--ink);
}

.pantone-definition small {
  display: block;
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
}

.color-technical-note {
  margin: var(--s3) 0 0;
  padding: var(--s3);
  background: var(--y-soft);
  border: 1px solid var(--line);
  border-radius: var(--r1);
  font-size: 12px;
  line-height: 1.6;
  color: var(--ink-2);
}

/* --- Renk secici dialogu --- */
/* Kunye bandi kenara dayanir; govde ogeleri margin-inline ile ice cekilir.
   `.tabs` bir yatay kaydirma kabi oldugu icin dolgu yerine margin verilir —
   kaydirma kabinda sag dolgu tarayicida yenmez.                          */
.color-dialog {
  width: min(880px, 96vw);
  max-height: 92vh;
  overflow: auto;
  padding: 0;
}

.color-dialog form {
  display: grid;
  gap: var(--s3);
  padding: 0 0 var(--s5);
}

.color-dialog form > :not(.dialog-head) { margin-inline: var(--s5); }

.slider-row b {
  font: 600 12px/1.4 var(--ui);
  color: var(--ink-2);
}

.slider-row span {
  font: 700 12px/1.4 var(--mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
  color: var(--ink);
}

/* Kanal sirasi: C, M, Y, K */
.slider-row:nth-of-type(1) input { accent-color: var(--c); }
.slider-row:nth-of-type(2) input { accent-color: var(--m); }
.slider-row:nth-of-type(3) input { accent-color: var(--y); }
.slider-row:nth-of-type(4) input { accent-color: var(--k); }

.preview-row i { width: 56px; height: 56px; }

.preview-row b {
  font: 700 13px/1.4 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.pantone-catalog-info {
  padding: var(--s2) var(--s3);
  background: var(--c-soft);
  border-radius: var(--r1);
  font: 600 11px/1.5 var(--mono);
  color: var(--ink-2);
}

.pantone-list {
  max-height: 380px;
  overflow: auto;
  margin-top: var(--s3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}

.pantone-list p { margin: 0; padding: var(--s4); font-size: 12px; color: var(--ink-3); }

/* Katalog satiri — cip + mono kod + eylem */
.pantone-row {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) auto;
  gap: var(--s3);
  align-items: center;
  width: 100%;
  padding: var(--s2) var(--s3);
  text-align: left;
  background: var(--surface);
  border: 0;
  border-bottom: 1px solid var(--line-2);
  border-radius: 0;
  cursor: pointer;
  transition: background-color 140ms;
}

.pantone-row:hover { background: var(--paper-2); }
.pantone-row:focus-visible { background: var(--m-soft); box-shadow: inset 3px 0 0 var(--m); }

.pantone-row i { width: 34px; height: 26px; }

.pantone-row b {
  font: 700 12px/1.4 var(--mono);
  letter-spacing: .02em;
  color: var(--ink);
}

.pantone-row span {
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--m);
}

/* 2010 katalogda bulunmayan kod — sistem renk uydurmaz */
.pantone-row.catalog-missing { background: var(--y-soft); }
.pantone-row.catalog-missing span { color: var(--ink); }


/* === GORSEL DIALOGU =====================================================
   NOT: .qr-box / .qr-box img / .qr-box span / .qr-dialog / .qr-dialog img /
   .qr-dialog b bloklari SILINDI. index.html ve app.js taramasinda bu
   siniflarin HIC bir karsiligi yok (yalnizca eski styles.css'te vardi) —
   olu kod. Ayni sebeple @900'deki .qr-box{display:none} de kaldirildi.  */

.image-dialog {
  width: min(1100px, 94vw);
  height: min(860px, 92vh);
  padding: var(--s7) var(--s4) var(--s4);
  background: var(--k);
}

.image-dialog img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: var(--surface);
  border-radius: var(--r1);
}

.image-dialog > button {
  position: absolute;
  right: var(--s3);
  top: var(--s3);
}


/* === ANA TABLOLARIN SAYISAL SUTUNLARI ====================================
   SPEC 3: "Tablo hucrelerinde sayi varsa o hucre mono olur." 20-primitives
   yalnizca `table{font-variant-numeric:tabular-nums}` veriyor (mono degil).
   Uretim akisinin ana tablolari burada kapsanir; sutun sirasi index.html'den
   birebir dogrulandi. Metin sutunlari (musteri, personel adi) KAPSAM DISI. */

/* #jobsTable: 1=ID · 2=Is No · 6=Klise kalinligi · 9=Termin */
#jobsTable td:nth-child(1),
#jobsTable td:nth-child(2),
#jobsTable td:nth-child(6),
#jobsTable td:nth-child(9),
/* #qualityTable: 1=ID · 2=Is No · 7=Termin */
#qualityTable td:nth-child(1),
#qualityTable td:nth-child(2),
#qualityTable td:nth-child(7),
/* #trackingTable: 1=Is No · 8=Termin */
#trackingTable td:nth-child(1),
#trackingTable td:nth-child(8),
/* #archiveTable: 1=Is No · 5=Teslim tarihi */
#archiveTable td:nth-child(1),
#archiveTable td:nth-child(5),
/* #personnelTable: 1=Personel no */
.personnel-table-wrap td:nth-child(1),
/* #rawPlateTable: 2=Kalinlik · 3=En×Boy · 4=Adet · 5=Toplam */
#rawPlateTable td:nth-child(2),
#rawPlateTable td:nth-child(3),
#rawPlateTable td:nth-child(4),
#rawPlateTable td:nth-child(5) {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

/* Adet / toplam = saga yasli (SPEC 5: sayisal hucreler mono + saga yasli) */
#rawPlateTable td:nth-child(4),
#rawPlateTable td:nth-child(5) { text-align: right; }

/* 4 is akisi tablosunun 1. sutunu Is No; 4. sutun YALNIZCA "bekleyen"
   tablolarda Termin — "islemde" tablolarinda personel adi, o yuzden
   .workflow-table degil tbody id'si hedeflenir.                          */
.workflow-table td:nth-child(1),
#productionReadyTable td:nth-child(4),
#shippingReadyTable td:nth-child(4) {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}


/* === DUYARLILIK — SPEC 7: yalnizca 3 kirilma noktasi =====================
   TEK SAHIP KURALI: mukerrer / olu merdiven bildirimleri silindi. Burada
   yalnizca 60-responsive'de KARSILIGI OLMAYAN kurallar kalir.            */

/* SILINENLER (60-responsive ile birebir mukerrer ya da 60 tarafindan
   ezildigi icin OLU): @1250 .production-metric-grid · .forms-layout;
   @900 .workflow-split · .tracking-summary · .quality-stats · .job-summary ·
   .job-info-grid · .visual-grid · .production-measure-grid · .job-dialog ·
   .production-dialog · .archive-delivery-dialog · .archive-workflow-dialog ·
   .job-actions button · dokunma hedefi etiket listesi (60:304-323) ·
   .workflow-arrow{transform:none} (60:248 rotate(90deg) ile celisiyordu) ·
   .qr-box{display:none} (olu sinif);
   @560 .production-metric-grid · .tracking-summary · .quality-stats ·
   .job-summary · .measurement-governance-card · .raw-plate-form ·
   .measure-entry · .production-measure-entry · .color-card (+ .color-system
   display:none — bilgi gizleme) · .slider-row · .preview-row ·
   .production-record · .file-preview.                                     */

@media (max-width: 1250px) {
  /* 60-responsive'de karsiligi yok: dialog govdesi ve olcu formlari */
  .production-dialog-body { grid-template-columns: minmax(0, 1fr); }
  .measurement-governance-card { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .raw-plate-form { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  /* 60-responsive bu ucunu yalnizca @900'de tek kolona indiriyor;
     1250–900 araligini burasi karsilar.                                   */
  .approval-grid,
  .revision-page-grid,
  .plate-montage-grid { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 900px) {
  /* Ok hizasi 40'ta, donusu 60-responsive'de (celisen transform kaldirildi) */
  .workflow-arrow { justify-self: center; }

  /* 60-responsive .bar-grid'i yalnizca @560'ta tek kolona indiriyor */
  .bar-grid { grid-template-columns: minmax(0, 1fr); }

  /* 60-responsive'in tam ekran dialog listesinde OLMAYAN ucu */
  .production-action-dialog,
  .shipping-label-dialog,
  .color-dialog {
    width: 100%;
    max-width: 100%;
    max-height: 100dvh;
    border-radius: 0;
  }

  /* 60-responsive'in dokunma hedefi listesinde olmayan tek etiket */
  .dimension-mode label { min-height: var(--tap); }

  /* --- CMYK KAYDIRACLARI: 24px -> 44px dokunma hedefi -------------------
     Olcum: #colorDialog icindeki 4 adet input[type=range] 148x24 (@360),
     178x24 (@390), 202x24 (@414), 24px (@768) — dikeyde esigin 20px altinda.
     Kok neden 60-responsive'in `input{min-height:var(--tap)}` kurali DEGIL:
     20-primitives'te `input[type="range"]{min-height:24px}` (0,1,1) o kurali
     (0,0,1) ozgullukle eziyor. Burada (0,2,1) ile ve daha sonraki kaynak
     sirasiyla kapatilir. Chrome kaydiraci kutu icinde dikey ORTALAR, yani
     ince ray gorunumu korunur; ::-webkit-slider-thumb'a dokunmak
     -webkit-appearance:none gerektirip tum yerlesik gorunumu bozacakti. */
  .slider-row input[type="range"] { min-height: var(--tap); }

  /* --- SIRALANABILIR BASLIK: 31,4px -> 44px ------------------------------
     Olcum @768: th.sortable.tracking-sort/quality-sort/archive-sort-header
     yuksekligi 31,4-32,0px. `min-height` tablo hucresinde islemez, bu yuzden
     `height` kullanilir (60-responsive `.table td{height:var(--tap)}` ile
     ayni desen). Ok glifi 10px'ten (20-primitives) 12px'e cikar.           */
  th.tracking-sort,
  th.quality-sort,
  th.archive-sort-header { height: var(--tap); }

  th.tracking-sort span,
  th.quality-sort span,
  th.archive-sort-header span { font-size: 12px; }

  /* --- SEVKIYAT ROTA TABLOSU: 14px tasma --------------------------------
     Olcum @390: div.table.workflow-table sw 347 / cw 333 -> 14px gizli.
     4 kolon (IS NO / MUSTERI / ISIN ADI / DAGITIMA CIKARAN) 20-primitives'in
     var(--s3)=12px yatay hucre dolgusuyla 347px istiyor. Dolgu var(--s2)=8px
     olunca 4 x 8 = 32px kazanilir -> 315px, kapsayiciya sigar ve bu tabloda
     yatay kaydirma tamamen kalkar.                                        */
  .workflow-table th,
  .workflow-table td { padding-inline: var(--s2); }

  /* --- YATAY KAYDIRILAN SERITLER: kaydirma gorunur olsun ----------------
     Olcum: #jobTabs cw 328 / sw 775 -> 447px (%57,7) gizli; dokunmatik
     cihazda kaplama (overlay) kaydirma cubugu yalnizca kaydirma sirasinda
     ciziliyor, bu yuzden "daha var" ipucu yok.
     SARMA (flex-wrap) OLCULEREK REDDEDILDI: 7 sekmenin etiket toplami
     623px; 358px'lik satira 3+3+1 diziliyor, yani 3 satir = 132px. Serit
     45px'ten 132px'e cikarak asagida job-summary'den kazanilan 106px'i
     yiyordu. Ayrica 20-primitives `.tabs{overflow-y:hidden}` ikinci satiri
     kirpar. Cozum: cubugu KALICI ve 6px yap (kaplama cubugu yerine klasik
     cubuga zorlar), kaydirmayi sekme sinirina oturt.
     `scrollbar-width`/`scrollbar-color` ZORUNLU olarak `auto`ya cekilir:
     Chromium'da bu iki standart ozellik baslangic degerinden farkli oldugu
     surece ::-webkit-scrollbar* kurallarini YOK SAYAR. 20-primitives
     `.tabs{scrollbar-width:thin}`, 60-responsive de @900'de her ikisini
     birden veriyor — bu yuzden hem oradaki 4px kurali hem de buradaki
     kural sifirlama olmadan OLU kalirdi. Tarayicida olculdu: sifirlama
     olmadan serit 54,7px (thin cubuk 9,7px), sifirlama ile 50,7px
     (6px cubuk) — yani kural artik gercekten uygulaniyor.                  */
  .job-dialog .tabs,
  .production-stage-strip {
    scroll-snap-type: x proximity;
    scroll-padding-inline: var(--s4);
    overscroll-behavior-x: contain;
    scrollbar-width: auto;
    scrollbar-color: auto;
  }

  .job-dialog .tabs::-webkit-scrollbar,
  .production-stage-strip::-webkit-scrollbar { height: 6px; }

  .job-dialog .tabs::-webkit-scrollbar-track,
  .production-stage-strip::-webkit-scrollbar-track { background: var(--line-2); }

  .job-dialog .tabs::-webkit-scrollbar-thumb,
  .production-stage-strip::-webkit-scrollbar-thumb {
    background: var(--ink-3);
    border-radius: var(--r1);
  }

  .job-dialog .tabs button,
  .production-stage { scroll-snap-align: start; }

  /* --- IS EMRI DIALOGU: dikey butce ------------------------------------
     Olcum @360x800: header 72,4 + ozet 247,6 + sekme 45 = 365px sabit bant,
     forma yalnizca 318px kaliyor (dialogun %39,8'i). Iki olu bosluk burada
     kapatilir: form satir araligi var(--s3)->var(--s2) (3 aralik, 12px) ve
     form alt dolgusu (16px). @900'de .job-actions zaten `position:sticky`
     ile en alta yapisiyor, altindaki 16px dolgu OLCULEN olu alandi
     (footer bottom 784, dialog 800).                                      */
  .job-dialog form {
    gap: var(--s2);
    padding-bottom: 0;
  }
}

@media (max-width: 560px) {
  .production-intro,
  .quality-intro,
  .shipping-intro,
  .archive-intro,
  .tracking-hero { flex-wrap: wrap; }

  .archive-counter,
  .tracking-hero-count {
    margin-left: 0;
    padding-left: 0;
    border-left: 0;
    text-align: left;
  }

  /* 24px izli kayit satiri tek kolona dustugunde buton veri kolonuna gecer */
  .production-record > button { grid-column: 2; justify-self: start; }

  .archive-actions button,
  .production-image-buttons button { flex: 1 1 auto; }

  /* --- IS EMRI KUNYESI: 4 yigin satir -> 4 kunye satiri -----------------
     Olcum @360x800: .job-summary 247,6px = ekranin %31'i; 60-responsive
     @560 blogu onu TEK KOLONA indiriyor (SPEC 7 gerektiriyor) ve her satir
     etiket(11px x 1,4 = 15,4) + 4px alt bosluk + deger(20px x 1,2 = 24) =
     43,4px yer kapliyor. Kolon sayisi SPEC'e uygun sekilde 1 KALIR; kazanc
     satiri DIKEY yigindan YATAY kunyeye cevirmekten gelir: etiket solda,
     deger sagda, ayni satirda. Yeni satir yuksekligi max(15,4; 16,8) =
     16,8px -> 4 x 16,8 + 3 x 8 aralik + 24 dolgu + 2 kenarlik = 117px.
     Kazanc ~106px, dogrudan #tab-info'ya gider (318px -> ~450px).
     `white-space:nowrap` ayni zamanda .job-summary b uzerindeki mevcut
     `text-overflow:ellipsis`i CALISIR hale getirir — nowrap olmadan uzun
     musteri adi satir kirip yuksekligi geri buyutuyordu.                  */
  .job-dialog .job-summary > div {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s3);
  }

  .job-dialog .job-summary small {
    margin-bottom: 0;
    flex: 0 0 auto;
  }

  .job-dialog .job-summary b {
    min-width: 0;
    font-size: 14px;
    text-align: right;
    white-space: nowrap;
  }
}


/* ==================== 50-screens-b.css ==================== */

/* ============================================================
   GOLD ERP — KATMAN 5/6: YONETIM VE VERI EKRANLARI
   Yonetim paneli, akilli hesaplama, musteri karti, personel,
   stok, muhasebe koprusu, rapor merkezi, ayarlar, sistem & yedek.
   Belirtecler 10-tokens katmaninda tanimlidir; burada yalnizca
   var(--x) ile kullanilirlar. Ikinci bir belirtec blogu yoktur.
   ============================================================ */


/* === 1. EKRAN KABUKLARI — dikey ritim ===
   Her ekran tek kolonlu bir izgara; bloklar arasi bosluk gap ile
   kurulur, alt bloklarda margin-bottom kullanilmaz. */
.management-dashboard,
.smart-page,
.stock-page,
.personnel-page,
.accounting-page,
.reports-page,
.settings-page,
.system-page{
  display:grid;
  align-content:start;
  gap:var(--s4);
}

.customer-tab-page,
.reports-tab-page,
.settings-tab-page{
  display:grid;
  align-content:start;
  gap:var(--s4);
}

/* Panel govdeleri — icerik ustten yigilir, min-width:0 cok kolonlu
   izgaralarda tablo/kod tasmasini keser. */
.accounting-filter-card,
.accounting-table-card,
.reports-filter-card,
.reports-job-table-card,
.report-chart-card,
.executive-summary-card,
.settings-card,
.calc-card,
.calc-summary-panel,
.smart-data-card,
.stock-items-panel,
.stock-movements-panel,
.system-backup-card,
.system-backup-list-card,
.system-path-card{
  display:grid;
  align-content:start;
  min-width:0;
}
.report-chart-card{min-height:320px}


/* === 2. EKRAN GIRISLERI — kunye seridi ===
   Ekranin en ustundeki tanitim blogu. Kare ikon alani + baslik +
   aciklama + sagda islem dugmesi. Renkli daire yok. */
.management-hero,
.smart-intro,
.stock-intro,
.personnel-intro,
.accounting-intro,
.reports-intro,
.settings-intro,
.system-intro{
  display:flex;
  align-items:center;
  flex-wrap:wrap;
  gap:var(--s4);
  padding:var(--s4);
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r2);
  box-shadow:var(--sh1);
}

.management-hero h2,
.smart-intro h2,
.stock-intro h2,
.personnel-intro h2,
.accounting-intro h2,
.reports-intro h2,
.settings-intro h2,
.system-intro h2{
  margin:0;
  font-size:20px;
  font-weight:650;
  letter-spacing:-.01em;
  color:var(--ink);
}

.management-hero p,
.smart-intro p,
.stock-intro p,
.personnel-intro p,
.accounting-intro p,
.reports-intro p,
.settings-intro p,
.system-intro p{
  margin:var(--s1) 0 0;
  max-width:76ch;
  font-size:13px;
  color:var(--ink-2);
}

/* Kare ikon alani — --paper-2 zemin, ince kenarlik */
.management-hero-icon,
.smart-icon,
.stock-intro-icon,
.personnel-intro-icon,
.accounting-intro-icon,
.reports-intro-icon,
.settings-intro-icon,
.system-intro-icon{
  flex:0 0 auto;
  width:40px;
  height:40px;
  display:grid;
  place-items:center;
  background:var(--paper-2);
  border:1px solid var(--line);
  border-radius:var(--r1);
  color:var(--ink-2);
  font-size:20px;
  line-height:1;
}

/* Giristeki tek islem dugmesi sagda durur */
.accounting-intro button,
.settings-intro button,
.system-intro button{
  margin-left:auto;
}

.reports-export-buttons{
  margin-left:auto;
  display:flex;
  flex-wrap:wrap;
  gap:var(--s2);
}
.management-live i{
  width:8px;
  height:8px;
  background:var(--ok);
}


/* === 3. ISTATISTIK KARTLARI ===
   Mikro etiket + mono deger + sol renk seridi. Katman 2'deki
   .stat ile ayni dil; deger 26px mono 700.
   TEK RECETE: bu ekranlardaki YEDI kart ailesi (hicbiri .stat
   sinifini tasimiyor) ayni kutuyu ve ayni tipografiyi buradan
   alir. Ikinci/ucuncu bir stat tanimi YAZILMAZ — eskiden
   .reports-mini-stats article ve .system-status-card ayni receteyi
   kendi bloklarinda tekrar yaziyordu. */
.management-stat,
.accounting-stat,
.report-stat,
.stock-summary-card,
.personnel-summary-card,
.reports-mini-stats article,
.system-status-card{
  padding:var(--s4);
  text-align:left;
  white-space:normal;          /* button{white-space:nowrap} mirasini kes */
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r2);
  box-shadow:inset 3px 0 0 var(--line);
}

/* Ikon tasiyan kartlar iki kolon; ikonsuz olanlar (rapor mini
   kartlari, sistem durumu) blok akisinda kalir. */
.management-stat,
.accounting-stat,
.report-stat,
.stock-summary-card,
.personnel-summary-card{
  display:flex;
  align-items:flex-start;
  gap:var(--s3);
}

/* TIKLANAMAYAN SAYAÇ KARTI.
   "Bugün Açılan" kartının ayrıntısı yöneticiye ait; yönetici olmayanda
   kart yalnızca sayı gösteriyor. `disabled` KULLANILMIYOR: bu depoda
   `disabled` bir kez görsel sanılıp form gönderimini kırdı. Burada
   yalnızca görünüm ve odak değişiyor, düğme DOM'da aynı kalıyor. */
.management-stat.stat-tiklanamaz{
  cursor:default;
  pointer-events:none;
}

.management-stat span,
.accounting-stat span,
.report-stat span,
.stock-summary-card span,
.personnel-summary-card span,
.reports-mini-stats span,
.system-status-card span{
  display:block;
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-3);
}

.management-stat b,
.accounting-stat b,
.report-stat b,
.stock-summary-card b,
.personnel-summary-card b,
.reports-mini-stats b,
.system-status-card b{
  display:block;
  margin-top:var(--s2);
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:26px;
  font-weight:700;
  line-height:1.1;
  color:var(--ink);
}

.management-stat small,
.accounting-stat small,
.report-stat small,
.stock-summary-card small,
.personnel-summary-card small,
.system-status-card small{
  display:block;
  margin-top:var(--s1);
  font-size:12px;
  color:var(--ink-3);
}

/* Kart ikonlari — kare, notr; renk yalnizca glife girer */
.management-stat-icon,
.accounting-stat-icon,
.report-stat-icon,
.stock-summary-icon,
.personnel-summary-icon{
  flex:0 0 auto;
  width:32px;
  height:32px;
  display:grid;
  place-items:center;
  background:var(--paper-2);
  border:1px solid var(--line);
  border-radius:var(--r1);
  color:var(--ink-2);
  font-size:15px;
  line-height:1;
}

/* Izgaralar */
.management-stats{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s3)}
/* SUTUN SAYISI SABIT DEGIL, YERE GORE (v2.78.1)
   =====================================================================
   ESKISI: `repeat(6,minmax(0,1fr))`. 1366px'te her karta 168px dusuyordu;
   "TOPLAM CIRO (KDV HARIC)" etiketi TEK BASINA 152px istiyor, ikon 32px,
   arada bosluk var. Kart kendi icerigini kirpiyordu: musteri sayinin
   sagini goremiyordu (olculdu: 1440'ta 34px, 1366'da 46px, 1280'de 60px).

   NIYE `minmax(0,1fr)` YETMEDI: o kural sutunun SIFIRA kadar
   daralabilecegini soyler — yani kirpilmayi serbest birakir. Cozum
   sutun sayisini azaltmak; `auto-fit` bunu genislige gore kendisi yapar
   ve yeni kart eklendiginde esik listesi guncellemeyi unutma riski
   dogmuyor.

   215px: en uzun etiket + ikon + dolgu. 200px denendi, 1366'da 10px
   tasti.

   `!important` KULLANILMADI — bilerek. Denedim ve 900px altindaki mevcut
   kural ezildigi icin ORADA yeni bir tasma actim. Taban kural
   degistirildi, medya sorgulari kendi esiklerinde hala kazaniyor. */
.accounting-stats,
.reports-stats,
.stock-summary-grid,
.personnel-summary-grid,
.system-status-grid{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(215px,1fr));
  gap:var(--s3);
}
/* Esnek kutu cocugu varsayilan olarak icerigin altina inmez; kart
   icindeki metin blogu bu izin olmadan daralamiyor. */
.report-stat>*,
.accounting-stat>*,
.management-stat>*,
.stock-summary-card>*,
.personnel-summary-card>*{min-width:0}

/* Serit renkleri — asama/anlam rengi */
.accounting-stat{box-shadow:inset 3px 0 0 var(--c)}
/* Fiyatı girilmemiş iş varsa CİRO KARTI uyarı rengine geçer.
   Sayının kendisi doğru görünür ama EKSİKTİR; rengin işi, rakamın
   sorgulanmadan kabul edilmesini engellemek. */
.accounting-stat.uyari{box-shadow:inset 3px 0 0 var(--y)}
.accounting-stat.uyari small{color:var(--y)}

/* === CARİ HESAP ========================================================
   Para sütunları sağa yaslı ve mono: rakamların basamakları alt alta
   gelmezse iki tutarı gözle karşılaştırmak mümkün olmuyor.              */
.accounting-amount{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  text-align:right;
  white-space:nowrap;
}
/* Borçlu bakiye vurgulanır — ekranı açan kişinin aradığı satır budur. */
.cari-borclu b,.cari-borclu{color:var(--no)}
.cari-toplam-satiri{background:var(--surface-2,var(--surface));font-weight:700}
.cari-tahsilat-satiri td{color:var(--ok)}

/* "FİYAT YOK" rozeti: 0,00 ₺ yazmak eksik fiyatı gerçek bir tutar gibi
   gösterirdi. */
.accounting-unpriced{
  display:inline-block;
  padding:1px var(--s1);
  border:1px solid var(--y);
  border-radius:var(--r1);
  font-size:10.5px;
  font-weight:700;
  color:var(--y);
  white-space:nowrap;
}
.cari-uyari{
  margin:0 0 var(--s2);
  padding:var(--s2) var(--s3);
  border:1px solid var(--y);
  border-left-width:3px;
  border-radius:var(--r1);
  background:var(--y-soft,transparent);
  font-size:12px;
  color:var(--ink);
}
.cari-arac{display:flex;align-items:end;gap:var(--s2)}
.cari-arac label{font-size:10.5px}

.cari-ekstre-dialog[open]{width:min(900px,95vw)}
.cari-ekstre-body{margin:var(--s4) var(--s4) 0;min-height:0}
.cari-ekstre-tablo{max-height:42vh;overflow:auto}
.cari-ozet-serit{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(120px,1fr));
  gap:var(--s2);
}
.cari-ozet-serit>div{
  padding:var(--s2);
  border:1px solid var(--line);
  border-radius:var(--r1);
  background:var(--surface);
}
.cari-ozet-serit span{display:block;font-size:10px;color:var(--ink-3)}
.cari-ozet-serit b{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:14px;
}
.tahsilat-body{margin:var(--s4) var(--s4) 0}
.customer-price-body{margin:var(--s4) var(--s4) 0}
.fiyat-tarih-ipucu{
  padding:var(--s2);
  border-left:3px solid var(--y);
  background:var(--paper-2);
  border-radius:var(--r1);
  font-size:11.5px;
  line-height:1.5;
  color:var(--ink-2);
}
#customerPriceDialog[open]{width:min(520px,94vw)}
#customerPriceDialog .dialog-actions{margin:0;padding:var(--s3) var(--s4) var(--s4)}
#tahsilatDialog[open]{width:min(460px,94vw)}
#tahsilatDialog .dialog-actions,
#cariEkstreDialog .dialog-actions{margin:0;padding:var(--s3) var(--s4) var(--s4)}
.report-stat{box-shadow:inset 3px 0 0 var(--k-3)}
.management-stat{box-shadow:inset 3px 0 0 var(--c)}
.today-stat{box-shadow:inset 3px 0 0 var(--y)}

.stock-summary-icon.blue{color:var(--c)}
.stock-summary-icon.red{color:var(--no)}
.stock-summary-icon.purple{color:var(--plate)}
.stock-summary-icon.green{color:var(--ok)}
.stock-summary-card:has(.blue){box-shadow:inset 3px 0 0 var(--c)}
.stock-summary-card:has(.red){box-shadow:inset 3px 0 0 var(--no)}
.stock-summary-card:has(.purple){box-shadow:inset 3px 0 0 var(--plate)}
.stock-summary-card:has(.green){box-shadow:inset 3px 0 0 var(--ok)}

.personnel-summary-icon.active{color:var(--ok)}
.personnel-summary-icon.passive{color:var(--ink-3)}
.personnel-summary-icon.department{color:var(--c)}
.personnel-summary-card:has(.active){box-shadow:inset 3px 0 0 var(--ok)}
.personnel-summary-card:has(.department){box-shadow:inset 3px 0 0 var(--c)}


/* === 3B. DEFTER TABLOLARI — SAYISAL HUCRE TIPOGRAFISI ===
   Muhasebe, rapor ve stok hareket tablolari birer defter: kolonlarin
   cogu kod, tarih, kalinlik, adet veya alan. Sayisal hucreler eskiden
   td:nth-child(2),(4),(7)… yamalariyla tek tek isaretleniyordu; bu
   kolon SIRASINA bagliydi ve app.js kolon ekledigi/yerini degistirdigi
   anda hucre sessizce UI fontunda kaliyordu (SPEC 3 ihlali).
   Mono kapsami konumdan cikarildi: defter hucrelerinin TAMAMI mono.
   Tutamak konum degil, ogenin kendisi:
     - veri hucresi           -> td (colspan'siz)
     - bos durum satiri       -> td[colspan] (haric tutulur, UI kalir)
     - rozet/dugme            -> kendi font bildirimi var, etkilenmez
   font-variant-numeric:tabular-nums 20-primitives'te table uzerinde
   global oldugu icin burada tekrar edilmez. */
.accounting-table-wrap td:not([colspan]),
.reports-table-wrap td:not([colspan]),
.stock-movement-wrap td:not([colspan]){font-family:var(--mono)}

/* Saga yaslama kolon konumunu GEREKTIRIYOR: bu olcu hucrelerinde
   app.js sinif yazmiyor (app.js bu turda salt okunur) ve CSS'in
   baska tutamagi yok. Bu yuzden konuma bagli tek bir kural kaldi ve
   karsiliklari thead etiketiyle yaziliyor. Sinifi olan sayisal
   hucrelerde (.stock-quantity-cell / .positive / .negative / .total)
   hizalama 20-primitives'ten gelir, burada tekrarlanmaz. */
.accounting-table-wrap td:nth-child(7),   /* Parça      */
.accounting-table-wrap td:nth-child(8),   /* Klişe cm²  */
.accounting-table-wrap td:nth-child(9),   /* Asetat cm² */
.reports-table-wrap td:nth-child(8),      /* Parça      */
.reports-table-wrap td:nth-child(9),      /* cm²        */
.reports-table-wrap td:nth-child(10),     /* Revizyon   */
.stock-movement-wrap td:nth-child(5){     /* Kalan      */
  text-align:right;
  white-space:nowrap;
}


/* === 4. YONETIM PANELI (management-) === */
.management-stat{
  width:100%;
  align-items:center;
  cursor:pointer;
  font:inherit;
  transition:background-color 140ms,border-color 140ms,box-shadow 140ms;
}
.management-stat:hover{background:var(--paper-2)}
.management-stat:focus-visible{outline:2px solid var(--m);outline-offset:2px}
.management-stat-copy{min-width:0;flex:1 1 auto}
.management-stat em{
  margin-left:auto;
  flex:0 0 auto;
  font-style:normal;
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--m);
}

/* Bugun karti — gun kirilimi yamalari */
.today-stat-breakdown{
  display:flex;
  flex-wrap:wrap;
  gap:var(--s1);
  margin-top:var(--s2);
}
.today-stat-breakdown span{
  display:inline-flex;
  align-items:center;
  gap:var(--s1);
  padding:2px var(--s2);
  background:var(--paper-2);
  border:1px solid var(--line-2);
  border-radius:var(--r1);
  font-size:11px;
  letter-spacing:0;
  text-transform:none;
  color:var(--ink-2);
}
.today-stat-breakdown b{
  display:inline;
  margin:0;
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:12px;
  color:var(--ink);
}

.management-grid{
  display:grid;
  grid-template-columns:minmax(0,1.5fr) minmax(280px,.5fr);
  gap:var(--s4);
}

/* Pano sag kolonu — EN COK IS ACAN GRAFIKER (app.js:302-313).
   Kart govdesi tek bir <button>: kimlik/olcu kunyesi onun icinde,
   bu yuzden izgara .top-graphic-card'a degil butona kurulur. */
.top-graphic-panel{display:grid;gap:var(--s3);align-content:start}
.top-graphic-card{display:grid}
.top-graphic-card>button{
  display:grid;
  grid-template-columns:44px minmax(0,1fr) auto;
  gap:var(--s3);
  align-items:center;
  min-height:0;
  padding:var(--s3);
  text-align:left;
  white-space:normal;
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r1);
  box-shadow:inset 3px 0 0 var(--m);
}
.top-graphic-avatar{
  display:grid;
  place-items:center;
  width:44px;
  height:44px;
  background:var(--paper-2);
  border:1px solid var(--line);
  border-radius:var(--r1);
  font-family:var(--mono);
  font-size:16px;
  font-weight:700;
  line-height:1;
  color:var(--ink-2);
}
.top-graphic-copy{min-width:0}
.top-graphic-copy b{
  display:block;
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
  font-size:16px;
  font-weight:650;
  letter-spacing:-.01em;
  color:var(--ink);
}
.top-graphic-copy span{
  display:block;
  margin-top:2px;
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  color:var(--ink-3);
}
.top-graphic-breakdown{display:flex;flex-wrap:wrap;gap:var(--s1);margin-top:var(--s2)}
.top-graphic-breakdown em{
  padding:1px var(--s2);
  background:var(--paper-2);
  border:1px solid var(--line-2);
  border-radius:var(--r1);
  font-size:11px;
  color:var(--ink-2);
}
/* Yildiz bir GLIF, etiket degil: buyuk harf/harf araligi anlamsiz.
   Renk notr — --plate arsiv/klise baglamina ayrilmistir (bkz. bulgu 8),
   ayrica --plate metin/glif olarak kontrasti gecmiyor. */
.top-graphic-crown{
  align-self:start;
  font-size:20px;
  line-height:1;
  color:var(--ink-2);
}

/* Pano sag kolonu — KALICI VERI NOTU (index.html:82) */
.persistent-data-note{
  display:grid;
  gap:var(--s1);
  padding:var(--s2) var(--s3);
  background:var(--paper-2);
  border:1px solid var(--line-2);
  border-radius:var(--r1);
  box-shadow:inset 3px 0 0 var(--ok);
}
.persistent-data-note b{
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.persistent-data-note span{
  font-family:var(--mono);
  font-size:12px;
  color:var(--ink-2);
  overflow-wrap:anywhere;
}


/* === 5. AKILLI HESAPLAMA (smart- / calc-) === */
.smart-settings{
  display:grid;
  grid-template-columns:repeat(8,minmax(110px,1fr));
  gap:var(--s3);
  align-items:end;
}
/* Onay kutusu satirlari: KUTU gorunumu buradan, ETIKET tipografisi
   ve dokunma yuksekligi 20-primitives:213-237'den (cumle metni,
   400/13px, min-height 34px), mobil dokunma hedefi
   60-responsive:304-323'ten gelir. Kutu olcusu TEK YERDE:
   20-primitives input[type=checkbox] = 18px. */
.calc-check{
  padding:0 var(--s3);
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--r1);
}

.smart-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s4)}
.smart-bottom{display:grid;grid-template-columns:minmax(0,1.7fr) minmax(260px,.7fr);gap:var(--s4)}

.calc-card-head{
  display:flex;
  align-items:flex-start;
  justify-content:space-between;
  gap:var(--s3);
  margin-bottom:var(--s3);
}
.calc-card-head h3{margin:0;font-size:16px;font-weight:650;letter-spacing:-.01em}
.calc-card-head p{margin:var(--s1) 0 0;font-size:12px;color:var(--ink-3)}

/* Satir izgarasi — baslik ve satir ayni kolon seridini paylasir */
.calc-table-head,
.calc-row{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr) minmax(0,.8fr) minmax(0,.9fr) 68px;
  gap:var(--s2);
  align-items:center;
}
.calc-table-head{
  padding:var(--s2) var(--s3);
  background:var(--paper-2);
  border:1px solid var(--line);
  border-radius:var(--r1);
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.calc-rows{display:grid;gap:var(--s2);margin-top:var(--s2)}
.calc-row{
  padding:var(--s2);
  background:var(--surface);
  border:1px solid var(--line-2);
  border-radius:var(--r1);
}
.calc-row input{min-width:0}
.calc-row b{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:13px;
  text-align:right;
  color:var(--ink);
}

.calc-summary-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--s2)}
.calc-summary-grid>div{
  padding:var(--s3);
  background:var(--paper);
  border:1px solid var(--line-2);
  border-radius:var(--r1);
}
.calc-summary-grid small{
  display:block;
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.calc-summary-grid b{
  display:block;
  margin-top:var(--s2);
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:16px;
  color:var(--ink);
}

/* Toplamlar — tutar daima mono ve saga yasli */
.grand-total,
.tl-total{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--s3);
  margin-top:var(--s2);
  padding:var(--s3) var(--s4);
  border-radius:var(--r1);
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
}
.grand-total{background:var(--k);color:#fff}
.grand-total b{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:26px;
  letter-spacing:0;
  color:#fff;
}
.tl-total{background:var(--paper-2);border:1px solid var(--line);color:var(--ink-2)}
.tl-total b{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:20px;
  letter-spacing:0;
  color:var(--ink);
}

.calc-actions-panel{display:flex;flex-direction:column;gap:var(--s2)}
.calc-actions-panel h3{margin:0 0 var(--s1);font-size:16px;font-weight:650}
.calc-actions-panel button{width:100%}
.calc-help{
  margin-top:var(--s2);
  padding:var(--s3);
  background:var(--paper-2);
  border:1px solid var(--line-2);
  border-radius:var(--r1);
  font-size:12px;
  color:var(--ink-2);
}
.calc-help b{
  display:block;
  margin-bottom:var(--s1);
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.calc-help p{margin:var(--s1) 0 0}


/* === 6. MUSTERI KARTI (customer-) === */
.customer-toolbar{
  display:grid;
  grid-template-columns:minmax(240px,1fr) auto auto;
  gap:var(--s2);
  align-items:center;
}
.customer-sort,
.customer-job-sort{cursor:pointer;white-space:nowrap;user-select:none}

.customer-dialog{width:min(96vw,1080px)}
.customer-head{
  display:grid;
  grid-template-columns:minmax(0,1fr) auto 40px;
  align-items:center;
  gap:var(--s4);
  padding:var(--s3) var(--s4);
  background:var(--paper-2);
  border-bottom:1px solid var(--line);
}
.customer-head small{
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.customer-head h2{margin:var(--s1) 0 0;font-size:20px;font-weight:650;letter-spacing:-.01em}
.customer-head-code{
  padding-left:var(--s4);
  border-left:1px solid var(--line);
  text-align:right;
}
.customer-head-code b{
  display:block;
  margin-top:var(--s1);
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:16px;
  color:var(--ink);
}

.customer-tabs{justify-content:center}
/* Sekme sayaci icin kural YOK — 20-primitives:420-428 tek sahip. */

/* KENAR BOŞLUĞU — ölçüldü: sekme içeriği ve alt şerit pencere kenarından
   0px uzaktaydı (künye 16px'teydi). Tablolar ve düğmeler kartın
   yuvarlatılmış köşesine yapışıp dışarı sarkıyormuş gibi görünüyordu.
   Dolgu <form>'a değil SEKMEYE veriliyor; künye ve sekme şeridi baştan
   sona uzanmaya devam etsin diye. */
.customer-dialog .customer-tab-page{padding:var(--s4)}

.customer-general-grid textarea{min-height:120px;resize:vertical}
.customer-mini-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s3)}

.customer-section-toolbar{
  display:flex;
  align-items:center;
  justify-content:space-between;
  flex-wrap:wrap;
  gap:var(--s3);
  padding:var(--s3) var(--s4);
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r2);
}
.customer-section-toolbar h3{margin:0;font-size:16px;font-weight:650;letter-spacing:-.01em}
.customer-section-toolbar p{margin:var(--s1) 0 0;font-size:12px;color:var(--ink-3)}

.customer-card-list{display:grid;gap:var(--s2)}
.customer-list-card{
  display:grid;
  grid-template-columns:40px minmax(160px,1fr) auto auto;
  align-items:center;
  gap:var(--s3);
  padding:var(--s3);
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r2);
  box-shadow:inset 3px 0 0 var(--c);
  transition:background-color 140ms,border-color 140ms;
}
.customer-list-card:hover{background:var(--paper-2)}
.customer-list-card h4{margin:0;font-size:14px;font-weight:650}
.customer-list-card p{margin:2px 0;font-size:13px;color:var(--ink-2)}
.customer-list-card small{font-size:12px;color:var(--ink-3);line-height:1.5}
/* Adres karti ikincil bir kayit: notr serit. --plate YALNIZCA
   arsiv/klise baglaminda kullanilir (musteri adresi degil). */
.address-card{box-shadow:inset 3px 0 0 var(--line)}
.customer-list-icon{
  width:32px;
  height:32px;
  display:grid;
  place-items:center;
  background:var(--paper-2);
  border:1px solid var(--line);
  border-radius:var(--r1);
  font-size:15px;
  line-height:1;
}
.customer-list-tags{min-width:96px}
/* .primary-tag icin kural YOK — 20-primitives:431-454 + :499 tek
   sahip (--c-soft = bilgi/birincil kayit). Buradaki eski ikinci
   tanim --ok-soft yazip 'tamamlandi' anlamiyla catisiyordu. */
.customer-list-actions{display:flex;gap:var(--s1)}

/* ALT ŞERİT — pencerenin kenarına yapışmaz.
   Önceden yalnızca `padding-top` vardı: yanlarda ve altta hiç boşluk
   yoktu, düğmeler yuvarlatılmış köşenin üzerine taşıyor ve karttan
   dışarı sarkıyormuş gibi görünüyordu. Müşteri bunu "kenarlarını
   düzeltsene / iç içe duruy" diye bildirdi.

   Ölçüldü: geometrik ÇAKIŞMA yoktu (0 kesilme, 0 çakışma). Sorun
   tamamen boşluktu — bu yüzden düzen değil, yalnızca dolgu değişti. */
.customer-actions{
  display:grid;
  grid-template-columns:auto 1fr auto auto;
  align-items:center;
  gap:var(--s2);
  padding:var(--s3) var(--s4);
  border-top:1px solid var(--line);
}
.customer-actions button{min-width:120px}


/* === 7. PERSONEL (personnel-) === */
.personnel-toolbar{
  display:grid;
  grid-template-columns:minmax(220px,1fr) repeat(4,auto);
  gap:var(--s2);
  align-items:center;
}
.personnel-sort{cursor:pointer;white-space:nowrap;user-select:none}
.personnel-table-wrap{overflow:auto;max-height:620px}
.personnel-table-panel tbody{cursor:pointer}
.passive-personnel{opacity:.6}

.permission-badges{display:flex;flex-wrap:wrap;gap:var(--s1)}
.permission-badges span{
  padding:1px var(--s1);
  background:var(--paper-2);
  border:1px solid var(--line);
  border-radius:var(--r1);
  font-size:11px;
  font-weight:600;
  letter-spacing:.04em;
  color:var(--ink-2);
}
.permission-badges em{font-style:normal;font-size:11px;color:var(--ink-3)}

/* Personel tanim penceresi */
.personnel-dialog{width:min(96vw,760px)}
.personnel-dialog-head,
.stock-dialog-head{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--s3);
  padding:var(--s3) var(--s4);
  background:var(--paper-2);
  border-bottom:1px solid var(--line);
}
.personnel-dialog-head h2,
.stock-dialog-head h2{margin:0;font-size:20px;font-weight:650;letter-spacing:-.01em}
.personnel-dialog-head span,
.stock-dialog-head span{
  display:block;
  margin-top:var(--s1);
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.personnel-dialog-head button,
.stock-dialog-head button{
  flex:0 0 auto;
  width:32px;
  height:32px;
  padding:0;
  background:transparent;
  border:1px solid var(--line);
  border-radius:var(--r1);
  color:var(--ink-2);
  font-size:18px;
  line-height:1;
  cursor:pointer;
}
.personnel-dialog-head button:hover,
.stock-dialog-head button:hover{background:var(--surface);color:var(--ink)}

.personnel-dialog form,
.stock-dialog form{display:grid;gap:var(--s4);padding:var(--s4)}
.personnel-dialog footer,
.stock-dialog footer{
  display:flex;
  justify-content:flex-end;
  gap:var(--s2);
  padding-top:var(--s3);
  border-top:1px solid var(--line);
}

.personnel-form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s3)}
.personnel-permissions{
  grid-column:1/-1;
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:var(--s2);
  margin:0;
  padding:var(--s3);
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--r1);
}
.personnel-permissions legend{
  padding:0 var(--s1);
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-3);
}
/* .personnel-permissions label ve kutu olcusu icin kural YOK:
   20-primitives:213-237 (etiket) + 20-primitives:186-200 (18px kutu)
   tek sahiptir. */

.personnel-note-label{grid-column:1/-1}
.personnel-note-label textarea{min-height:96px;resize:vertical}
.personnel-active-label{
  grid-column:1/-1;
  padding:0 var(--s3);
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--r1);
}


/* === 8. STOK (stock-) === */
.stock-toolbar{
  display:grid;
  grid-template-columns:minmax(220px,1fr) 150px 150px repeat(4,auto);
  gap:var(--s2);
  align-items:center;
}
.stock-content-grid{
  display:grid;
  grid-template-columns:minmax(0,1.3fr) minmax(360px,.7fr);
  gap:var(--s4);
  align-items:start;
}
.stock-panel-title{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--s3);
  margin-bottom:var(--s3);
}
.stock-panel-title h3{margin:0;font-size:16px;font-weight:650;letter-spacing:-.01em}
.stock-panel-title small{display:block;margin-top:2px;font-size:12px;color:var(--ink-3)}

.stock-sort{cursor:pointer;white-space:nowrap;user-select:none}
.stock-table-wrap,
.stock-movement-wrap{overflow:auto;max-height:520px}
.stock-items-panel tbody{cursor:pointer}
/* Kritik stok = --no. 20-primitives:310 ayni satira --no seridi
   veriyor; zemin de ayni dile getirildi (eskiden --y-soft idi ve
   sari zemin + kirmizi serit celisiyordu). */
.critical-stock-row{background:var(--no-soft)}
.passive-stock-row{opacity:.6}

/* Miktar hucreleri icin kural YOK: .stock-quantity-cell / .positive /
   .negative recetesi 20-primitives:319-330'da (mono + 600 + saga
   yasli + renk). Kalan/Tarih gibi sinifsiz sayisal hucreler icin
   bkz. bolum 3B (defter tablolari). */

.stock-dialog{width:min(96vw,640px)}
.stock-movement-dialog{width:min(96vw,560px)}
.stock-form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s3)}
.stock-note-label{grid-column:1/-1}
.stock-note-label textarea{min-height:88px;resize:vertical}
/* GERİ KAZANIM BAYRAĞI — `.checkline` ailesinin tipografisi ve
   `.settings-switch`'in kutu görünümü kullanılır, yeni bir dil kurulmaz.
   Farkı: burada checkbox+başlığın ALTINDA ek bir `<small>` açıklama
   satırı var; `<small>` tam genişlik alıp yeni satıra düşer, girinti
   checkbox genişliği + boşlukla hizalanır. */
.stock-flag-label{
  grid-column:1/-1;
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--s2);
  min-height:34px;
  padding:var(--s2) var(--s3);
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--r1);
  font:400 13px/1.4 var(--ui);
  text-transform:none;
  letter-spacing:normal;
  color:var(--ink);
  cursor:pointer;
}
.stock-flag-label small{
  flex-basis:100%;
  margin-left:calc(18px + var(--s2));
  color:var(--ink-2);
  font-size:12px;
  line-height:1.4;
}
.stock-current-box{
  padding:var(--s3) var(--s4);
  background:var(--paper-2);
  border:1px solid var(--line);
  border-radius:var(--r1);
  box-shadow:inset 3px 0 0 var(--c);
}
.stock-current-box span{
  display:block;
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.stock-current-box b{
  display:block;
  margin-top:var(--s1);
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:26px;
  font-weight:700;
  color:var(--ink);
}


/* === 9. MUHASEBE KOPRUSU (accounting-) === */
.accounting-filter-grid{
  display:grid;
  grid-template-columns:160px 160px 180px minmax(180px,1fr) auto;
  gap:var(--s3);
  align-items:end;
}
.accounting-note{
  margin:var(--s3) 0 0;
  padding-top:var(--s3);
  border-top:1px solid var(--line-2);
  font-size:12px;
  color:var(--ink-3);
}

.accounting-action-card{
  display:grid;
  grid-template-columns:minmax(0,1fr) auto auto;
  align-items:center;
  gap:var(--s3);
}
.accounting-action-card b{display:block;font-size:14px;font-weight:650;color:var(--ink)}
.accounting-action-card small{display:block;margin-top:var(--s1);font-size:12px;color:var(--ink-3)}

.accounting-table-wrap{overflow:auto;max-height:520px}
/* nowrap kaldirildi — genel kuralla ayni gerekce (bkz. `.table td`). */
.accounting-table-wrap th,
.accounting-table-wrap td{white-space:normal}
/* Sayisal hucre tipografisi: bolum 3B (kolon konumuna bagli
   nth-child mono yamalari kaldirildi). */
.accounting-table-wrap .exported{opacity:.6}
/* .accounting-row-check icin olcu kurali YOK — onay kutusu 18px,
   accent-color --m: 20-primitives:186-200 tek sahip. */

/* Aktarim gecmisi penceresi — dialog tabani (20-primitives:533)
   zemin/kenar/yaricap/golge/backdrop'u zaten veriyor; burada
   yalnizca genislik daraltilir. */
.accounting-history-dialog{
  width:min(96vw,1180px);
  max-height:88vh;
}
.accounting-history-dialog form{
  display:grid;
  grid-template-rows:auto minmax(0,1fr);
  max-height:88vh;
}
.accounting-history-body{overflow:auto;padding:var(--s4)}
.accounting-history-actions{white-space:nowrap}
.accounting-download,
.accounting-undo{min-height:32px;padding:0 var(--s2);font-size:12px}


/* === 10. RAPOR MERKEZI (reports- / report-) === */
.reports-filter-grid{
  display:grid;
  grid-template-columns:160px 160px minmax(320px,1fr) auto;
  gap:var(--s3);
  align-items:end;
}
.reports-presets{display:flex;flex-wrap:wrap;gap:var(--s1)}

.executive-summary-list{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:var(--s2);
  margin-top:var(--s3);
}
.executive-summary-list>div{
  display:flex;
  align-items:flex-start;
  gap:var(--s2);
  padding:var(--s2) var(--s3);
  background:var(--paper);
  border:1px solid var(--line-2);
  border-radius:var(--r1);
}
.executive-summary-list span{
  flex:0 0 20px;
  width:20px;
  height:20px;
  display:grid;
  place-items:center;
  background:var(--k);
  border-radius:var(--r1);
  color:#fff;
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:11px;
}
.executive-summary-list p{margin:0;font-size:13px;line-height:1.5;color:var(--ink-2)}

/* Sekmeler icin kural YOK. Tek sahip 20-primitives:382-428; o blok
   .tabs / .customer-tabs / .reports-tabs / .settings-tabs dortlusunu
   birlikte tanimliyor (gap --s4, buton 38px, aktif renk --m).
   Buradaki eski ikinci tanim SPEC 5'i iki yerden ihlal ediyordu:
   masaustu sekme yuksekligi 44px ve aktif sekme metni --ink.
   Mobil dokunma hedefi 60-responsive:379-382'de. */

.reports-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s4);align-items:start}
.report-chart-card h3{margin:0 0 var(--s4);font-size:16px;font-weight:650;letter-spacing:-.01em}

/* Grafikler — mürekkep cubuklari, mono degerler */
.bar-chart,
.rank-chart{display:grid;gap:var(--s2)}
.bar-row{
  display:grid;
  grid-template-columns:96px minmax(0,1fr) 88px;
  align-items:center;
  gap:var(--s2);
}
.rank-row{
  display:grid;
  grid-template-columns:24px 140px minmax(0,1fr) 108px;
  align-items:center;
  gap:var(--s2);
}
.bar-row span,
.rank-row span{
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
  font-size:12px;
  color:var(--ink-2);
}
.bar-row b,
.rank-row b{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:12px;
  text-align:right;
  color:var(--ink);
}
.rank-row em{
  width:20px;
  height:20px;
  display:grid;
  place-items:center;
  background:var(--paper-2);
  border:1px solid var(--line);
  border-radius:var(--r1);
  font-family:var(--mono);
  font-style:normal;
  font-size:11px;
  color:var(--ink-2);
}
.bar-track,
.rank-track{
  height:10px;
  background:var(--paper-2);
  border:1px solid var(--line-2);
  border-radius:var(--r1);
  overflow:hidden;
}
.bar-track i,
.rank-track i{display:block;height:100%;background:var(--k)}

/* Kart kutusu ve span/b tipografisi bolum 3'te (tek stat recetesi);
   burada yalnizca izgara kalir. */
.reports-mini-stats{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:var(--s3)}

.reports-table-wrap{overflow:auto;max-height:460px}
.reports-table-wrap th,
.reports-table-wrap td{white-space:nowrap}

/* GÜN SONU SEKMESİ — TEK GÜN SÜZGECİ.
   `.reports-filter-grid` KULLANILMADI: o ızgara dört sütuna sabit
   (160px 160px minmax(320px,1fr) auto) ve üç öğeli bu satırda PDF
   düğmesini 320px'e şişirirdi. Kalıp `.raw-plate-head` ile aynı: saran
   flex + mevcut boşluk belirteçleri. Yeni renk tanımlanmadı. */
.gun-sonu-filtre{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--s3)}
.gun-sonu-filtre label{flex:0 0 180px}

/* TOPLAM SATIRI — kalıp `.cari-toplam-satiri` (bölüm 9).

   Zemin `tr`de, `td`de DEĞİL: telefonda `.serit-tablo` satırı flex şeride
   çeviriyor ve hücre zemini üç ayrı gri kutu gibi görünürdü.

   SEÇİCİ `.table tbody tr.gun-sonu-toplam` — sınıfın TEK BAŞINA yazılması
   YETMİYOR ve bu ölçülerek bulundu:
     `tbody tr:hover`          (0,1,2) satır 1595
     `.table tbody tr`         (0,1,2) satır ~8390, @media(max-width:900px),
                               `background:var(--surface)` veriyor
   Yalnızca `tbody tr.gun-sonu-toplam` yazılsaydı (0,1,2) ikisiyle de
   BERABERE kalır, kaynak sırası gereği telefonda `.table tbody tr`
   kazanır ve toplam satırı zeminini SESSİZCE kaybederdi — üstelik kayıp
   yalnızca ≤900px'te görünür. `.table` öne alınınca (0,2,2) her ölçüde
   ve fare üzerindeyken de kazanıyor (toplam satırı tıklanabilir değil,
   hover vurgusu zaten istenmiyor). */
.table tbody tr.gun-sonu-toplam{background:var(--paper-2);font-weight:700}

/* BOŞ DURUM / HATA SATIRI ŞERİTTE KIRPILMAZ.
   `.serit-tablo tbody td` her hücreye `nowrap + overflow:hidden +
   ellipsis` veriyor (uzun firma adı satırı yatayda taşırmasın diye).
   Tek hücrelik BOŞ DURUM satırında bu ters tepiyor: 390px'te ölçüldü,
   "Bu tarihte teslim edilen iş yok." cümlesi "…EDİLEN İŞ Y…" diye
   kırpılıyordu — yani tablonun NEDEN boş olduğunu söyleyen tek cümle
   telefonda okunamıyordu. Aynı satır hata metnini de taşıyor; orada
   kırpılma doğrudan "sebebi göstermemek" demek.
   Kalıp `.workflow-empty` (aynı sorun, aynı çözüm): tam satır, ortalı,
   saran metin.

   SEÇİCİDEKİ FAZLADAN `tr` ÖLÇÜMLE GELDİ, SÜS DEĞİL. İlk hâli
   `.serit-tablo tbody td.gun-sonu-bos` (0,2,2) idi; `white-space` ve
   `overflow` kazanıyordu ama `flex` KAZANMIYORDU:
       `.serit-tablo tbody td:first-child{flex:0 0 auto}`  (0,2,2), satır ~8955
   ile berabere kalıp kaynak sırası gereği kaybediyordu — tek hücrelik
   satırda o hücre AYNI ZAMANDA `:first-child`. Sonuç `flex:0 0 auto`:
   hücre satırı doldurmuyor ve büzülemediği için uzun bir HATA metni
   şeridi yatayda taşırabiliyordu. `tr` eklenince (0,2,3) her iki kuralı
   da geçiyor. Masaüstünde bir şey değişmiyor (orada `flex` zaten
   kullanılmıyor, `white-space:normal` de kazanıyor). */
.serit-tablo tbody tr td.gun-sonu-bos,
.serit-tablo tbody tr td.olcu-kapsami-hucre{
  flex:1 1 100%;
  white-space:normal;
  overflow:visible;
  text-overflow:clip;
  text-align:center;
}

/* ÖLÇÜ KAPSAMI NOTU — cm² toplamının yanındaki "kaç işi kapsıyor" cümlesi
   (app/olcu_kapsami.py). Toplam satırının hemen ALTINDA duruyor; ayrı bir
   panele konsaydı toplamla arasındaki bağ okunmazdı.

   YENİ HEX RENK YOK: `--ink-2` (ikincil metin) ve `--paper-2` (ikincil
   zemin) zaten tanımlı ve ikisinin de koyu tema karşılığı var. Doğrudan
   bir renk yazsaydım koyu temada okunmaz hâle gelirdi.

   UYARI RENGİ DEĞİL: bu bir hata değil, bir kapsam bilgisi. Kapsamı tam
   olan raporlarda da basılıyor; kırmızı yazılsaydı her rapor hatalı
   görünür ve bir süre sonra hiç okunmazdı. */
.olcu-kapsami{
  color:var(--ink-2);
  font-size:.78rem;
  line-height:1.45;
}
.table tbody tr td.olcu-kapsami-hucre{
  background:var(--paper-2);
  color:var(--ink-2);
  font-size:.78rem;
  line-height:1.45;
  white-space:normal;
  text-align:left;
}
/* Sayisal hucre tipografisi: bolum 3B. */


/* === 11. AYARLAR (settings-) === */
/* Form yogun ekran: alan gruplari izgarayla, gruplar arasi ayrim
   panel basliginin altindaki saç teli cizgiyle kurulur. */
.settings-form-grid{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:var(--s4);
  padding-top:var(--s4);
  border-top:1px solid var(--line-2);
}
.settings-form-grid.one-col{grid-template-columns:minmax(0,1fr)}
.settings-form-grid .wide{grid-column:1/-1}
.settings-form-grid textarea{min-height:104px;resize:vertical}
.settings-form-grid code{
  display:block;
  margin-top:var(--s1);
  padding:var(--s2);
  background:var(--paper-2);
  border:1px solid var(--line-2);
  border-radius:var(--r1);
  font-family:var(--mono);
  font-size:12px;
  color:var(--ink-2);
  overflow-wrap:anywhere;
}
.settings-two-col{display:grid;grid-template-columns:1fr 1fr;gap:var(--s4);align-items:start}

/* Anahtarlar — yalnizca kutu gorunumu; etiket tipografisi, dokunma
   yuksekligi ve 18px onay kutusu 20-primitives'te. */
.settings-switch,
.system-switch{
  padding:0 var(--s3);
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--r1);
}

.settings-shortcut-card{
  display:flex;
  align-items:center;
  justify-content:space-between;
  flex-wrap:wrap;
  gap:var(--s4);
}
.settings-shortcut-card h3{margin:0 0 var(--s1);font-size:16px;font-weight:650;letter-spacing:-.01em}
.settings-shortcut-card p{margin:0;max-width:70ch;font-size:13px;color:var(--ink-2)}

.settings-log-actions{display:flex;flex-wrap:wrap;gap:var(--s2)}
.settings-log-list{display:grid;gap:var(--s1);max-height:560px;overflow:auto;margin-top:var(--s3)}
.settings-log-list>div{
  display:grid;
  grid-template-columns:180px minmax(0,1fr);
  gap:var(--s3);
  padding:var(--s2);
  background:var(--paper);
  border:1px solid var(--line-2);
  border-radius:var(--r1);
}
.settings-log-list span{
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.settings-log-list code{
  font-family:var(--mono);
  font-size:12px;
  color:var(--ink-2);
  white-space:pre-wrap;
  overflow-wrap:anywhere;
}

/* Lisans künyesi — mürekkep zeminli tek blok */
.settings-license-card{
  display:grid;
  align-content:center;
  gap:var(--s2);
  background:var(--k);
  border-color:var(--k-3);
  color:#fff;
  text-align:center;
}
.settings-license-card span{
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:rgba(255,255,255,.72);
}
.settings-license-card b{
  font-family:var(--mono);
  font-size:34px;
  font-weight:700;
  color:#fff;
}
.settings-license-card small{
  font-size:12px;
  font-weight:600;
  letter-spacing:.08em;
  color:rgba(255,255,255,.72);
}


/* === 12. SISTEM & YEDEK (system- / smart-data-) === */
/* Kart kutusu + span/small tipografisi bolum 3'te (tek stat
   recetesi). Burada yalnizca deger farki: bu kartin degeri sayi
   degil yol/surum dizesi — 26px yerine 16px ve kirilabilir. */
.system-status-card b{
  margin:var(--s2) 0 var(--s1);
  font-size:16px;
  overflow-wrap:anywhere;
}
.system-status-card.good{box-shadow:inset 3px 0 0 var(--ok)}
.system-status-card.bad{box-shadow:inset 3px 0 0 var(--no)}

.system-center-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s4);align-items:start}
.system-settings-form{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:var(--s3);
  padding-top:var(--s4);
  border-top:1px solid var(--line-2);
}
.system-settings-form button{grid-column:1/-1}
.system-manual-actions{margin-top:var(--s3);display:flex;flex-wrap:wrap;gap:var(--s2)}

.system-path-list{display:grid;gap:var(--s2);padding-top:var(--s4);border-top:1px solid var(--line-2)}
.system-path-list>div{
  padding:var(--s2) var(--s3);
  background:var(--paper);
  border:1px solid var(--line-2);
  border-radius:var(--r1);
}
.system-path-list b{
  display:block;
  margin-bottom:var(--s1);
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.system-path-list code{
  font-family:var(--mono);
  font-size:12px;
  color:var(--ink);
  overflow-wrap:anywhere;
}

.system-download-link{min-height:32px;padding:0 var(--s2);font-size:12px}

/* Bilgilendirici blok — guvenli guncelleme.
   Anlam GENIS ALAN DOLGUSUNDA degil 3px seritte: zemin notr kalir
   (SPEC 2 renk disiplini). */
.system-warning{
  margin-top:var(--s3);
  padding:var(--s3);
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r1);
  box-shadow:inset 3px 0 0 var(--ok);
}
.system-warning b{
  display:block;
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.system-warning p{margin:var(--s1) 0 0;font-size:13px;color:var(--ink-2)}

/* Smart Data Manager */
.smart-data-grid{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:var(--s2);
  padding-top:var(--s4);
  border-top:1px solid var(--line-2);
}
.smart-data-grid>div{
  padding:var(--s2) var(--s3);
  background:var(--paper);
  border:1px solid var(--line-2);
  border-radius:var(--r1);
}
.smart-data-grid span{
  display:block;
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.smart-data-grid b,
.smart-data-grid code{
  display:block;
  margin-top:var(--s1);
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:13px;
  color:var(--ink);
  overflow-wrap:anywhere;
}
.smart-data-actions{display:flex;gap:var(--s2);margin-top:var(--s3)}
.smart-data-actions button{flex:1 1 auto}
.smart-data-note{
  margin-top:var(--s3);
  padding:var(--s3);
  background:var(--paper-2);
  border:1px solid var(--line-2);
  border-radius:var(--r1);
  font-size:12px;
  line-height:1.5;
  color:var(--ink-2);
}


/* === 13. YIKICI ISLEMLER — geri yukleme ve test sifirlama ===
   Bu ERP'de geri yukleme ve sifirlama veri kaybi uretir. Uyari
   GENIS ALAN DOLGUSUYLA degil 3px --no seridiyle verilir: iki blok
   da .panel oldugu icin zemin/kenarlik/golge oradan gelir, burada
   yalnizca serit eklenir (--sh1 korunmali, yoksa .panel golgesi
   silinir). */
.test-reset-card,
.system-restore-card{
  box-shadow:inset 3px 0 0 var(--no),var(--sh1);
}
.system-restore-card{
  display:flex;
  align-items:center;
  justify-content:space-between;
  flex-wrap:wrap;
  gap:var(--s4);
}
.system-restore-card h3{margin:0 0 var(--s1);font-size:16px;font-weight:650;letter-spacing:-.01em}
.system-restore-card p{margin:0;max-width:72ch;font-size:13px;color:var(--ink-2)}

/* Rozet recetesi 20-primitives:431-454 + :501 (--no-soft zemin).
   Burada yalnizca yerlesim: .panel-title-row bir flex satiri
   (sarmiyor), rozet daralmamali. */
.test-reset-warning{flex:0 0 auto}
.test-reset-preview{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:var(--s2);
  margin-top:var(--s3);
}
.test-reset-preview>div{
  padding:var(--s3);
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r1);
}
.test-reset-preview span{
  display:block;
  font-size:11px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.test-reset-preview b{
  display:block;
  margin-top:var(--s2);
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:20px;
  font-weight:700;
  color:var(--ink);
}
.test-reset-info{
  margin-top:var(--s3);
  padding:var(--s3);
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r1);
  font-size:13px;
  line-height:1.5;
  color:var(--ink-2);
}
.test-reset-controls{
  display:grid;
  grid-template-columns:minmax(240px,1fr) auto;
  gap:var(--s3);
  align-items:end;
  margin-top:var(--s3);
}
.test-reset-controls strong{font-family:var(--mono);color:var(--ink)}


/* === 14. DURUM ROZETLERI — BU KATMANDA KURAL YOK ===
   Rozet sistemi TEK SAHIPLI: 20-primitives:430-506.
   O blok .stock-status / .movement-type / .personnel-status /
   .accounting-status tabanini (inline-flex, min-height 20px,
   padding 2px --s2, --paper-2 zemin, --ink-2 metin, nowrap) ve
   BUTUN durum varyantlarini (-soft zeminler) veriyor.
   Buradaki eski ikinci tanim inline-block + 1px kenarlik + --ink
   metin yaziyor, katman sirasi geregi kazaniyor ve melez bir rozet
   uretiyordu; ayrica kenarlik ekleyerek ayni tabloda duran
   .status-pill / .quality-status ailesinden ayrisiyordu.
   SPEC 5 rozeti "-soft zemin + koyu metin" olarak tanimlar,
   kenarliktan soz etmez -> ikinci tanim tumuyle kaldirildi.

   === 15. BOS DURUMLAR — BU KATMANDA KURAL YOK ===
   Tek sahip 20-primitives:552-585; on dort bos durum sinifini
   birlikte tanimliyor. Buradaki ikinci tanim yalnizca dikey
   boslugu (--s5 -> --s7) iki katina cikariyordu, yani 14 bos
   durumun 6'si sessizce farkli goruniyordu. Daha ferah bir bos
   durum isteniyorsa deger 20-primitives'te TEK YERDE degisir. */


/* === 16. DUYARLILIK — SADECE 3 kirilim === */

/* --- 900–1250px: dar masaustu / tablet yatay --- */
@media (max-width:1250px){
  .management-grid,
  .stock-content-grid,
  .reports-grid{grid-template-columns:minmax(0,1fr)}

  .accounting-stats,
  .reports-stats,
  .system-status-grid,
  .reports-mini-stats{grid-template-columns:repeat(3,minmax(0,1fr))}

  .stock-summary-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .reports-presets{grid-column:1/-1}

  .stock-toolbar{grid-template-columns:repeat(3,minmax(0,1fr))}
  .personnel-toolbar{grid-template-columns:repeat(2,minmax(0,1fr))}

  /* SABIT GENISLIK DAYATMASI KALDIRILDI (16.08).
     Burada bes tabloya elle genislik veriliyordu; 1250px'in ALTINDA
     devreye girdigi icin dizustunde yatay kaydirmayi garanti ediyordu
     — ornegin `.reports-table-wrap table{min-width:1020px}` 1034px'lik
     bir kaba 1020px'lik taban koyuyor, kalan her sutun tasiyordu.
     Sutun sayisini kap genisligine gore dusuren blok (dosyanin
     sonunda, "KAP SORGUSU" basligi) bunun yerini aliyor. */
}

/* --- 560–900px: tablet dikey / buyuk telefon --- */
@media (max-width:900px){
  .management-stats,
  .accounting-stats,
  .reports-stats,
  .system-status-grid,
  .reports-mini-stats,
  .stock-summary-grid,
  .personnel-summary-grid{grid-template-columns:repeat(2,minmax(0,1fr))}

  .smart-grid,
  .smart-bottom,
  .system-center-grid,
  .settings-two-col,
  .settings-form-grid,
  .system-settings-form,
  .executive-summary-list{grid-template-columns:minmax(0,1fr)}

  .settings-form-grid .wide{grid-column:auto}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.accounting-filter-grid,
  .reports-filter-grid {
  grid-template-columns: repeat(2,minmax(0,1fr));
}

  .stock-toolbar,
  .personnel-toolbar,
  .customer-toolbar{grid-template-columns:minmax(0,1fr)}

  .accounting-action-card,
  .test-reset-preview{grid-template-columns:repeat(2,minmax(0,1fr))}

  .personnel-permissions{grid-template-columns:repeat(2,minmax(0,1fr))}
  .settings-log-list>div{grid-template-columns:minmax(0,1fr)}

  .bar-row{grid-template-columns:80px minmax(0,1fr) 72px}
  .rank-row{grid-template-columns:20px 104px minmax(0,1fr) 88px}

  .customer-tabs{justify-content:flex-start}

  /* --- DOKUNMA HEDEFLERI: bu katmanin KENDI actigi acikliklar ---
     Asagidaki kural olmadan 60-responsive'in genel
     `button{min-height:var(--tap)}` tabani ISLEMIYOR: oradaki secici
     eleman (0,0,1), buradaki min-height:32px bildirimleri ise sinif
     (0,1,0) — kaynak sirasi degil OZGULLUK karar veriyor, yani 32px
     kazaniyor. Olculen sonuc: .system-download-link 49,6x32 (esigin
     12px altinda) ve ayni recete .accounting-download/.accounting-undo
     ikilisinde. Cozum ayni ozgullukte min-height vermek. */
  .system-download-link,
  .accounting-download,
  .accounting-undo{min-height:var(--tap)}

  /* Siralanabilir baslik hucreleri: th.sortable dokunma yuksekligi
     olculdugunde 31,4-32,0px (esigin 12-13px altinda). 60-responsive
     yalnizca `td`ye yukseklik veriyor (`.table td{height:var(--tap)}`),
     thead bosta kalmis. Bu katmanin sahip oldugu dort siralama sinifi
     ayni yuksekligi alir; tablo/arsiv/kalite basliklari 40-screens-a'nin
     isi. `height` tablo hucresinde asgari yukseklik gibi davranir. */
  .customer-sort,
  .customer-job-sort,
  .stock-sort,
  .personnel-sort{height:var(--tap)}

  /* Sekme dugmeleri: yukseklik 44px (60-responsive) ama GENISLIK kisa
     etiketlerde esigin altinda kaliyordu — olculen: 'Sirket' 41,5px,
     'Lisans' 43,3px. Yatay dolgu yerine min-width, cunku dolgu ayni
     zamanda seridin toplam genisligini (611px) daha da buyutur. */
  .customer-tabs button,
  .reports-tabs button,
  .settings-tabs button{min-width:var(--tap)}

  /* Aktarim gecmisi penceresi mobilde tam ekran (60-responsive dialogu
     100dvh yapiyor ve max-height:none ile kendi 88vh sinirimi eziyor),
     ama FORM'daki 88vh sinirini ezen bir kural yok: 800px'lik telefonda
     704px'lik form + 96px olu bant kaliyor ve govde bosa kirpiliyor.
     Sinir burada kalkar; yuksekligi artik dialogun flex kolonu kurar. */
  .accounting-history-dialog[open] form{max-height:none}
}

/* --- <560px: telefon --- */
@media (max-width:560px){
  .management-stats,
  .accounting-stats,
  .reports-stats,
  .system-status-grid,
  .reports-mini-stats,
  .stock-summary-grid,
  .personnel-summary-grid{grid-template-columns:minmax(0,1fr)}

  .smart-settings,
  .accounting-filter-grid,
  .reports-filter-grid,
  .calc-summary-grid,
  .smart-data-grid,
  .stock-form-grid,
  .personnel-form-grid,
  .customer-mini-grid,
  .test-reset-preview,
  .test-reset-controls,
  .personnel-permissions{grid-template-columns:minmax(0,1fr)}

  .accounting-action-card{grid-template-columns:minmax(0,1fr)}
  .accounting-action-card button{width:100%}

  .customer-actions{grid-template-columns:minmax(0,1fr)}
  .customer-list-card{grid-template-columns:32px minmax(0,1fr)}

  .smart-data-actions{flex-direction:column}

  .grand-total b{font-size:20px}
  .management-stat em{display:none}

  /* --- SEKME SERITLERI TELEFONDA SARILIR -------------------------------
     Olculen: .settings-tabs cw 336 / sw 611 -> 275px (%45) gorunmez,
     'Lisans' sag kenari 622,5px (viewport'u 262px asiyor); .reports-tabs
     cw 336 / sw 488 -> 152px (%31); .customer-tabs cw 360 / sw 468 ->
     108px, 'Musteri Isleri' sekmesi tumuyle disarida (left 357,5).
     Seritler overflow-x:auto oldugu icin ERISILEBILIR ama gorsel ipucu
     yok; SPEC gradyan maskeyi yasakladigi (bolum 2: "Gradyan YOK") ve
     etiketleri kisaltmak veriyi yok ettigi icin cozum SARMA: yatay
     tasma 0'a duser, on sekmenin hepsi ayni anda gorunur.
     Satir araligi --s2, kolon araligi --s3 (tabandaki --s4 tek satir
     icindi; sarilinca 16px iki eksende fazla yer yiyordu).
     .tabs GENEL sinifina DOKUNULMAZ — #jobTabs onun ustunde durur ve
     is emri karti bu katmanin kapsaminda degil. */
  .customer-tabs,
  .reports-tabs,
  .settings-tabs{
    flex-wrap:wrap;
    gap:var(--s2) var(--s3);
  }

  /* --- IC ICE DIKEY KAYDIRMA TELEFONDA KALKAR --------------------------
     Sarmalayicilarin dikey siniri masaustu icindi: .personnel-table-wrap
     620px, .stock-table-wrap / .stock-movement-wrap / .accounting-table-wrap
     520px, .reports-table-wrap 460px. 360x800 telefonda kaydirma kabinin
     gorunur yuksekligi 800 - header 61 - kontrol seridi 34 = 705px; yani
     620px'lik kutu ekranin %88'ini kaplayan bir kaydirma tuzagi kuruyor
     ve tablonun tamami taranmadan sayfa asagi inmiyor. Sinir kalkinca
     dikey kaydirma TEK yerde (`.app main`) toplanir; sarmalayicinin
     overflow:auto'su yatay eksende gorevine devam eder (SPEC bolum 7:
     "Genis tablolar: overflow-x:auto KAPSAYICI icinde").
     .settings-log-list BILINCLI olarak listede DEGIL: o bir gunluk
     penceresi (ikincil widget), sinirsiz buyumesi sayfayi kilitler. */
  .stock-table-wrap,
  .stock-movement-wrap,
  .personnel-table-wrap,
  .accounting-table-wrap,
  .reports-table-wrap{max-height:none}
}


/* ==================== 60-responsive.css ==================== */

/* =========================================================================
   GOLD ERP v1.21.6 — KATMAN 6/6 · DUYARLILIK VE MOBIL
   Belirtim bolum 7. SADECE 3 GENISLIK kirilmasi: 1250px · 900px · 560px.

   Genislik olmayan uc ek sorgu — her birinin gerekcesi yaninda:
     (max-width:900px) and (max-height:560px)
         Yatay telefon. Genislik kapisi ZORUNLU: kapisiz hali 1400x500 gibi
         genis-kisa masaustu pencerelerinde de dorduncu bir duzen modu
         uretiyordu. SPEC 7 genislik kirilmasi saymiyor.
     (prefers-reduced-motion:reduce)
         SPEC bolum 6 tabani. Bu dosya SON katman oldugu icin burada.
     print
         Onceki katmanlarin ozgullukle EZEMEDIGI cikti sifirlamalari.
         10-tokens ve 30-shell'in print notlari bu blogu buraya yonlendiriyor.
   ========================================================================= */


/* === 1. TASMA GUVENLIGI — her olcude gecerli =============================
   Govde ASLA yatay kaymaz. Cozum: kapsayicilarda min-width:0,
   genis tablolarda sarmalayici kaydirma. html/body kirpma YOK. */

.app main{min-width:0}
.page{min-width:0}
.panel{min-width:0}
.subcard{min-width:0}
.tab-page{min-width:0}
.customer-tab-page{min-width:0}
.settings-tab-page{min-width:0}
.reports-tab-page{min-width:0}

/* Genis tablo sarmalayicisi: yatay kaydirma burada olur, sayfada degil */
.table{
  max-width:100%;
  overflow-x:auto;
  overscroll-behavior-x:contain;
  scrollbar-width:thin;
  scrollbar-color:var(--ink-3) var(--line-2);
}

/* Uzun dosya yolu / kod parcasi satiri kirar, kapsayiciyi genisletmez */
code{overflow-wrap:anywhere}

/* Mobil menu ogeleri masaustunde yok — app.js bunlari her zaman uretir
   (#mobileMenuBtn ve #mobileMenuBackdrop) */
.mobile-menu-button{display:none}
.mobile-menu-backdrop{display:none}


/* === 2. <=1250px — DAR MASAUSTU / TABLET YATAY =========================== */
@media (max-width:1250px){

  /* Kenar cubugu bir kademe daralir, icerik alani buyur */
  .app{grid-template-columns:216px minmax(0,1fr)}

  /* 5–6 kolonlu olcum kartlari -> 3 */
  .system-status-grid,
  .smart-data-grid,
  .reports-stats,
  .reports-mini-stats,
  .accounting-stats{grid-template-columns:repeat(3,minmax(0,1fr))}/* 3 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.smart-settings {
  grid-template-columns: repeat(4,minmax(0,1fr));
}

  /* 6 asamali seritler -> 3 */
  .archive-stage-timeline,
  .tracking-stage-timeline{grid-template-columns:repeat(3,minmax(0,1fr))}

  /* 4 kolonlu kart/olcu izgaralari -> 2 */
  .management-stats,
  .dashboard-workflow,
  .production-metric-grid,
  .stock-summary-grid,
  .calc-summary-grid,
  .tracking-summary,
  .test-reset-preview,
  .today-stat-breakdown,
  .personnel-permissions,
  .accounting-filter-grid,
  .reports-filter-grid{grid-template-columns:repeat(2,minmax(0,1fr))}

  /* Yan yana iki buyuk panel -> tek kolon */
  .management-grid,
  .forms-layout,
  .stock-content-grid,
  .system-center-grid,
  .three-col{grid-template-columns:minmax(0,1fr)}
}


/* === 3. <=900px — TABLET DIKEY / BUYUK TELEFON ===========================
   Kenar cubugu cekmeceye doner, tum dokunma hedefleri --tap olur. */
@media (max-width:900px){

  /* --- 3a. KENAR CUBUGU = CEKMECE -------------------------------------
     display:none KULLANILMAZ: erisilebilirligi bozar ve gecisi imkansiz
     kilar. Cekmece yerinde durur, gorunurlugu kapanir.
     KAYMA (transform) YOK: SPEC bolum 6 gecisleri background-color /
     border-color / box-shadow / opacity ile sinirliyor, layout ve
     transform animasyonunu yasakliyor. visibility:hidden ogeyi hem
     boyamadan hem de isabet testinden cikarir; opacity gecisi izinli
     tek yumusatma. */
  .app{grid-template-columns:minmax(0,1fr)}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.app>aside {
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-bottom: var(--s5);
  background: var(--k);
  border-right: 1px solid var(--k-3);
  position: fixed;
  inset: 0 auto 0 0;
  width: min(288px,86vw);
  height: 100dvh;
  z-index: 50;
  box-shadow: var(--sh3);
  opacity: 0;
  visibility: hidden;
  transition: opacity 160ms,visibility 160ms;
}
  body.mobile-menu-open .app>aside{
    opacity:1;
    visibility:visible;
  }/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.app nav button {
  display: grid;
  grid-template-columns: var(--s5) minmax(0,1fr);
  align-items: center;
  justify-items: start;
  gap: var(--s2);
  width: 100%;
  min-height: var(--tap);
  padding: var(--s2) var(--s3);
  background: transparent;
  border: 0;
  border-left: 3px solid transparent;
  border-radius: 0;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.2;
  text-align: left;
  color: rgba(255,255,255,.72);
  cursor: pointer;
  transition: background-color 140ms,color 140ms,border-color 140ms;
}

  /* Kaplama: dialog backdrop ile ayni koyulukta, cekmecenin altinda */
  .mobile-menu-backdrop{
    display:block;
    position:fixed;
    inset:0;
    z-index:40;
    padding:0;
    border:0;
    border-radius:0;
    background:rgba(18,18,22,.55);
    opacity:0;
    visibility:hidden;
    transition:opacity 160ms,visibility 160ms;
  }
  body.mobile-menu-open .mobile-menu-backdrop{
    opacity:1;
    visibility:visible;
  }

  /* Cekmece acikken arka plan kaymaz. Kaydirma kabi BODY DEGIL, `.app main`
     (30-shell tek kaynak) — kilit oraya konur; `body{overflow:hidden}`
     bu modelde hicbir sey yapmiyordu. */
  body.mobile-menu-open main{overflow:hidden}

  /* Hamburger butonu (app.js: #mobileMenuBtn) — 44px dokunma hedefi.
     Header yuksekligi bundan tureyen --header-h belirtecinden gelir
     (30-shell: calc(var(--tap) + var(--s4)) = 60px), sihirli sayi yok.
     Bu esitligin GERCEKTEN tutmasi icin header ICERIGI de 44px'i
     asmamali; asagidaki satir yuksekligi kilidi (3b) onu sagliyor.
     ofsetidir — ucu birlikte kayar ya da birlikte durur. */
  .mobile-menu-button{
    display:flex;
    flex:0 0 auto;
    flex-direction:column;
    align-items:stretch;
    justify-content:center;
    gap:var(--s1);
    width:var(--tap);
    height:var(--tap);
    min-height:var(--tap);
    padding:0 var(--s3);
    border:1px solid var(--line);
    border-radius:var(--r1);
    background:var(--surface);
  }
  .mobile-menu-button span{
    display:block;
    width:100%;
    height:2px;
    background:var(--ink);
  }
  body.mobile-menu-open .mobile-menu-button{
    border-color:var(--m);
    background:var(--m-soft);
  }/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.user button {
  min-height: var(--tap);
  padding: 0 var(--s3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r1);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-2);
  cursor: pointer;
  transition: background-color 140ms,border-color 140ms,color 140ms;
}

  /* --- 3c. YERLESIM: KADEMELI TEK KOLON ------------------------------- */
  .two-col,
  .three-col,
  .visual-grid,
  .job-info-grid,
  .plate-montage-grid,
  .revision-page-grid,
  .approval-grid,
  .customer-general-grid,
  .customer-mini-grid,
  .child-form-grid,
  .reports-grid,
  .smart-grid,
  .smart-bottom,
  .settings-two-col,
  .settings-form-grid,
  .system-settings-form,
  .stock-form-grid,
  .personnel-form-grid,
  .production-measure-grid,
  .production-material-options,
  .measurement-governance-card,
  .executive-summary-list,
  .workflow-split,
  .raw-plate-form,
  .archive-workflow-detail,
  .archive-delivery-meta,
  .stage-image-gallery-body,
  .archive-delivery-gallery{grid-template-columns:minmax(0,1fr)}

  /* Iki kolonda kalanlar: dar ama okunur oldugu icin */
  .management-stats,
  .quality-stats,
  .accounting-stats,
  .reports-stats,
  .reports-mini-stats,
  .system-status-grid,
  .smart-data-grid,
  .stock-summary-grid,
  .personnel-summary-grid,
  .production-metric-grid,
  .archive-stage-timeline,
  .tracking-stage-timeline,
  .dashboard-workflow,
  .tracking-summary,
  .calc-summary-grid,
  .test-reset-preview,
  .smart-settings,
  .job-summary,
  .personnel-permissions,
  .accounting-filter-grid,
  .reports-filter-grid,
  .production-image-gallery{grid-template-columns:repeat(2,minmax(0,1fr))}

  /* Bu kapsayicilar grid DEGIL (40-screens-a: display:flex + flex-wrap:wrap
     zaten temelde var), grid-template-columns olu kalirdi. Sarma yeniden
     BILDIRILMEZ; burada yalnizca aciklama metinleri tam satira alinir. */
  .forms-actions span{flex:1 1 100%;white-space:normal}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.production-image-buttons span {
  font: 600 11px/1.4 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
  flex: 1 1 100%;
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.workflow-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: stretch;
  gap: var(--s3);
  min-height: 0;
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.workflow-arrow {
  align-self: center;
  font: 400 20px/1 var(--mono);
  color: var(--ink-3);
  user-select: none;
  padding: var(--s2) 0;
  transform: rotate(90deg);
}

  /* --- 3c-2. OLCU VE HESAP SATIRLARI --------------------------------- */
  /* Bunlar TEK KOLONA INDIRILMEZ: her satir bir kayit: 10 satirlik bir
     olcu listesi tek kolonda 50 satira yayilir ve kayit sinirlari kaybolur.
     Uc sayisal alan yan yana kalir, serbest metin ve buton tam satir alir.
     Uc kolon 320px'te de sigar: (288 - 2x4 bosluk)/3 = 93px iz. */
  .measure-entry,
  .production-measure-entry{grid-template-columns:repeat(3,minmax(0,1fr))}
  .measure-entry input:nth-of-type(4),
  .production-measure-entry input:nth-of-type(4),
  .measure-entry button,
  .production-measure-entry button{grid-column:1/-1}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.calc-row {
  grid-template-columns: repeat(3,minmax(0,1fr));
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.calc-row b {
  grid-column: 1/3;
  text-align: left;
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.calc-row button {
  grid-column: 3;
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.calc-table-head {
  display: none;
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.color-card {
  display: grid;
  grid-template-columns: 22px 40px minmax(0,1fr);
  gap: var(--s3);
  align-items: center;
  padding: var(--s2) var(--s3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.color-card i {
  width: 40px;
  height: 40px;
  grid-column: 2;
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.color-name {
  min-width: 0;
  grid-column: 3;
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.color-system {
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
  white-space: nowrap;
  grid-column: 1/-1;
  overflow: hidden;
  text-overflow: ellipsis;
}
  .color-card button{grid-column:1/-1;justify-self:start}

  /* Musteri / adres kartlari: etiket ve aksiyonlar alt satira */
  .customer-list-card,
  .address-card{grid-template-columns:auto minmax(0,1fr)}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.customer-list-tags,
  .customer-list-actions {
  grid-column: 1/-1;
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.customer-head {
  grid-template-columns: minmax(0,1fr) var(--tap);
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.customer-head-code {
  grid-column: 1;
  padding-left: 0;
  border-left: 0;
  text-align: left;
}

  .accounting-action-card,
  .test-reset-controls,
  .settings-log-actions,
  .archive-actions,
  .reports-export-buttons,
  .measurement-source-row,
  .checks,
  .inline-radio{flex-wrap:wrap}

  /* --- 3d. DOKUNMA HEDEFLERI (>= --tap) ------------------------------- */
  button,
  select,
  textarea,
  input,
  .button,
  .button-link{min-height:var(--tap)}

  /* Kutu isaretleyiciler 24px, dokunma hedefi saran etiket satiri (44px) */
  input[type=checkbox],
  input[type=radio]{
    width:var(--s5);
    height:var(--s5);
    min-height:var(--s5);
    flex:0 0 auto;
  }
  .checkline,
  .calc-check,
  .settings-switch,
  .system-switch,
  .accounting-row-check,
  .production-material-check,
  .production-basis-check,
  .personnel-active-label,
  .inline-radio label,
  .vertical-radio label,
  .radio-grid label,
  .bar-grid label,
  .checks label,
  .measurement-source-row label,
  .personnel-permissions label{
    display:flex;
    align-items:center;
    gap:var(--s2);
    min-height:var(--tap);
  }/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2);
  margin-bottom: var(--s3);
}
  .toolbar input,
  .toolbar select{flex:1 1 100%;min-width:0}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.toolbar button {
  flex: 1 1 auto;
  min-height: var(--tap);
}

  /* Bu ucu 50-screens-b'de display:grid'e cevriliyor; `.toolbar`in flex
     bildirimleri onlarda ISLEMEZ, tek kolon acikca verilir.
     Kalan yedi serit FLEX kapsayici: onlara grid-template-columns yazmak
     olu bildirimdi, kaldirildi. */
  .customer-toolbar,
  .stock-toolbar,
  .personnel-toolbar{grid-template-columns:minmax(0,1fr)}
  /* Satir aksiyonlari icin satir yuksekligi dokunma hedefi kadar */
  .table td{height:var(--tap)}

  /* Siralanabilir baslik: dokunma yuksekligi + okunur glif — TABAN.
     Olculen @768: th.sortable yuksekligi 31,4-32,0px (esigin 12-13px
     altinda), siralama oku 10px (20-primitives). 40 ve 50 katmanlari
     yedi ADLI siralama sinifini duzeltti (tracking/quality/archive/
     customer/customer-job/stock/personnel); jobs, dashboard, reports ve
     system tablolarinin `th.sortable`lari SAHIPSIZ kaldi. Bu iki kural
     hepsini birden kapsayan taban: ayni degerler, cakisma degil.
     `min-height` tablo hucresinde islemez, `height` asgari gibi davranir.
     Glif 10 -> 11px: SPEC bolum 3 mikro etiket olcusu ve th metniyle
     AYNI boy (12px olsa oktan buyuk gorunurdu; 40-screens-a de 11px
     secti). Olculen "daha yuksek kontrast" istegi opacity .6 -> .8 ile
     karsilanir, renk bildirimi 40'ta kaldigi icin tekrar edilmez. */
  .table th.sortable{height:var(--tap)}
  .table th.sortable span{font-size:11px;opacity:.8}

  /* --- 3e-2. KIMLIK KOLONU DONAR ---------------------------------------
     Olculen: sarmalayici cw 341, tablo 682px (stock); scrollLeft 250'de
     Kod (98px) ve Malzeme (107px) kolonlarinin IKISI de ekran disinda
     (left -225 / -128), yani deger kolonu ile kayit kimligi ASLA ayni
     anda gorunmuyor. Gizli genislikler: tracking 457px, archive 419px,
     reports 390px, personnel 388px, accounting 384px, jobs 344px.
     Ilk kolon sabitlenince kimlik her kaydirma konumunda ekranda kalir.

     ZEMIN: satira tasinir, hucreye YAZILMAZ. Sabit hucrenin altindan
     icerik gecmemesi icin opak zemin sart; zemin `tr`de oldugu icin
     :hover (--paper-2) ve .selected (--m-soft) renkleri de sabit
     hucreye gecer (`background-color:inherit`). Ozgulluk bilincli:
     `.table tr` (0,1,1) < `tbody tr:hover` / `tbody tr.selected`
     (0,1,2) — durum renkleri kazanmaya devam eder.
     KENARLIK: border-collapse:collapse sabit hucrenin kenarligini
     dusurur (th'de ayni sorun ic golgeyle cozulmus), bu yuzden sag
     ayrac ic golge ile cizilir. */
  .table tr{background:var(--surface)}
  .table th:first-child,
  .table td:first-child{
    position:sticky;
    left:0;
  }
  .table td:first-child{
    z-index:1;
    background-color:inherit;
    box-shadow:inset -1px 0 0 var(--line);
  }
  /* KATMAN SIRASI (ucu birlikte okunmali): yatay kaydirmada sabit ilk
     kolon diger kolonlarin uzerinden gecer, dikey kaydirmada sabit
     baslik satiri ilk kolonun uzerinden gecer, kose hucresi ikisinin de
     ustunde kalir. Bu yuzden td:first-child 1, th 2, th:first-child 3.
     `th{z-index:1}` tabani (20-primitives, 0,0,1) burada (0,1,1) ile
     yukseltilir; aksi halde kaydirilan kimlik hucresi baslik satirini
     kapatirdi. */
  .table th{z-index:2}
  .table th:first-child{z-index:3}

  /* Secili satirin 3px magenta seridi (SPEC bolum 5) tr uzerindeki ic
     golgeyle cizilir; hucreler satirin UZERINE boyandigi icin opak
     zeminli sabit ilk hucre o seridi gizlerdi. Serit ayni deger ve ayni
     gorunumle sabit hucreye tasinir, sag ayracla birlesir. Kritik stok
     satirinin --no seridi ayni nedenle tekrarlanir. */
  .table tr.selected td:first-child{
    box-shadow:inset 3px 0 0 var(--m),inset -1px 0 0 var(--line);
  }
  .table tr.critical-stock-row td:first-child{
    box-shadow:inset 3px 0 0 var(--no),inset -1px 0 0 var(--line);
  }

  /* Tablo basligindaki "tumunu sec" kutusu (#accountingSelectAll) tek
     SARMALAYICI ETIKETI OLMAYAN isaretleyici: 24px kutuda 44px'lik
     dokunma alani CSS ile uretilemez — degistirilmis (replaced) ogede
     padding ve ::before/::after islemez, transform ise isabet alanini
     da kucultur. Bu yuzden kutunun KENDISI --tap olur. Dogru cozum
     HTML tarafinda sarmalayici <label>, o kapsam disinda. */
  .table th>input[type=checkbox]{
    width:var(--tap);
    height:var(--tap);
  }

  .tabs button,
  .customer-tabs button,
  .reports-tabs button,
  .settings-tabs button{min-height:var(--tap);white-space:nowrap}

  /* [open] zorunlu: display yazmak kapali dialogu gorunur yapardi */
  .job-dialog[open],
  .customer-dialog[open],
  .production-dialog[open],
  .archive-workflow-dialog[open],
  .archive-delivery-dialog[open],
  .accounting-history-dialog[open]{display:flex;flex-direction:column;overflow:hidden}

  /* Sabit bantlar sikismaz — aksi halde icerikleri ust uste biner */
  .gold-modal-header,
  .dialog-head,
  .customer-head,
  .production-job-head,
  .personnel-dialog-head,
  .stock-dialog-head,
  .shipping-label-dialog-head,
  .job-summary,
  .produced-job-badge,
  .production-stage-strip,
  .tabs,
  .customer-tabs{flex:0 0 auto}
  .job-actions button,
  .customer-actions button,
  .child-actions button{flex:1 1 auto;min-width:0;min-height:var(--tap)}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.alert-ok {
  margin-top: var(--s4);
  min-width: 150px;
  width: 100%;
  min-height: var(--tap);
}
  .dialog-head button,
  .stock-dialog-head button,
  .personnel-dialog-head button,
  .shipping-label-dialog-head button,
  .accounting-history-dialog button[type=submit]{min-width:var(--tap);min-height:var(--tap)}
  .color-list,
  .measure-list,
  .pantone-list,
  .revision-history,
  .production-measure-list,
  .revision-history-card,
  .colors-card{min-height:0}
  .color-list,
  .measure-list,
  .pantone-list{max-height:48dvh}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.forms-preview-card iframe {
  width: 100%;
  min-height: 180px;
  border: 1px solid var(--line);
  border-radius: var(--r1);
  background: var(--surface);
}
  .login-brand-panel,
  .login-form-panel{padding:var(--s5)}
}


/* === 4. <=560px — TELEFON ===============================================
   Ic bosluklar --s3'e iner, tipografi bir kademe duser (12px tabani asilmaz). */
@media (max-width:560px){

  /* Tipografik olcek: 26->20, 20->16, 16->14. Mikro etiket 11px kalir. */
  body{font-size:12px}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
h1 {
  font-size: 20px;
  font-weight: 700;
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
h2 {
  font-size: 20px;
  font-weight: 700;
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
h3 {
  font-size: 14px;
  font-weight: 650;
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
h4 {
  font-size: 14px;
  font-weight: 650;
}/* 3 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.page {
  padding: var(--s3);
  min-width: 0;
}
  .panel,
  .subcard,
  .settings-card,
  .calc-card,
  .approval-card{padding:var(--s3)}

  /* Kalan cok kolonlu izgaralar tek kolona iner.
     SAYISAL KART IZGARALARI DA BURADA: 26px/20px mono deger + 11px
     uppercase etiket 360px telefonda ~150px'lik iki kolona SIGMIYOR.
     Iki kolonda tutulan tek grup asagida. */
  .management-stats,
  .quality-stats,
  .accounting-stats,
  .reports-stats,
  .reports-mini-stats,
  .system-status-grid,
  .smart-data-grid,
  .stock-summary-grid,
  .personnel-summary-grid,
  .dashboard-workflow,
  .archive-stage-timeline,
  .tracking-stage-timeline,
  .smart-settings,
  .job-summary,
  .personnel-permissions,
  .accounting-filter-grid,
  .reports-filter-grid,
  .production-image-gallery,
  .production-metric-grid,
  .tracking-summary,
  .calc-summary-grid,
  .test-reset-preview,
  .bar-grid{grid-template-columns:minmax(0,1fr)}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.radio-grid {
  display: grid;
  grid-template-columns: repeat(2,minmax(0,1fr));
  gap: var(--s2);
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.slider-row {
  display: grid;
  grid-template-columns: 96px minmax(0,1fr) var(--tap);
  gap: var(--s3);
  align-items: center;
  padding: var(--s2) 0;
  border-bottom: 1px solid var(--line-2);
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.preview-row {
  display: grid;
  grid-template-columns: var(--s7) minmax(0,1fr);
  gap: var(--s4);
  align-items: center;
  margin-top: var(--s4);
  padding: var(--s4);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}
  .preview-row button{grid-column:1/-1}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.date-row {
  display: grid;
  grid-template-columns: minmax(0,1fr) auto;
  gap: var(--s2);
}
  .job-forms-list>button{grid-template-columns:auto minmax(0,1fr)}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.job-forms-list i {
  font-style: normal;
  font: 600 11px/1.4 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--m);
  text-align: left;
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.production-image-item {
  display: grid;
  gap: var(--s1);
  padding: var(--s2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r1);
  text-align: center;
  grid-template-columns: 40px minmax(0,1fr);
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.production-record {
  display: grid;
  grid-template-columns: var(--s5) minmax(0,1fr);
  gap: var(--s3);
  align-items: start;
  padding: var(--s3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r1);
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.app main>header {
  justify-content: flex-start;
  gap: var(--s2);
  padding: var(--s2) var(--s3);
  padding-inline: var(--s2);
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.gold-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s2) var(--s3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  box-shadow: var(--sh1);
}
  .gold-modal-header h2{line-height:1.2}
  .gold-modal-header p{line-height:1.4}/* 3 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.login-shell {
  width: min(1080px,100%);
  display: grid;
  grid-template-columns: minmax(0,1fr);
  background: var(--surface);
  border: 1px solid var(--k-3);
  border-radius: var(--r3);
  overflow: hidden;
  box-shadow: var(--sh3);
  min-height: 0;
  padding: var(--s3);
}
  .login-brand-panel,
  .login-form-panel,
  .login-form-card{padding:var(--s4)}/* 3 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
dialog {
  margin: auto;
  padding: 0;
  border: 0;
  border-radius: var(--r3);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--sh3);
  max-width: calc(100vw - var(--s4));
  max-height: calc(100dvh - var(--s4));
  overflow: auto;
  width: calc(100vw - var(--s4));
}
}


/* === 5. YATAY TELEFON — dialog yukseklik kontrolu ========================
   Genislik kirilmasi DEGIL, yukseklik sorgusu; bu yuzden GENISLIK KAPISI
   ile sinirlandi. Kapisiz hali 1400x500 gibi genis-kisa masaustu
   pencerelerinde de gecerli olup @900'un dialog kurgusunu tersine
   ceviriyordu — yani dorduncu bir duzen modu. Simdi yalnizca gercekten
   yatay telefon/kucuk tablet olan olcuye uygulanir.
   420px yuksekliginde sabit bantlar (kunye + sekme + aksiyon) tum alani
   yedigi icin dialog TEK AKISTA kaydirilir, baslik sticky kalir. */
@media (max-width:900px) and (max-height:560px){
  dialog{max-height:calc(100dvh - var(--s3))}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.job-dialog,
  .customer-dialog,
  .production-dialog,
  .archive-workflow-dialog,
  .archive-delivery-dialog,
  .accounting-history-dialog,
  .image-dialog {
  width: 100%;
  height: 100dvh;
  max-width: none;
  max-height: 100dvh;
  margin: 0;
  border-radius: 0;
}

  /* Tek akis: kaydirma dialogun kendisinde, sutun flex kalkar.
     [open] kapisi ZORUNLU — display yazmak kapali dialogu sayfa icerigi
     gibi gorunur yapardi. */
  .job-dialog[open],
  .customer-dialog[open],
  .production-dialog[open],
  .accounting-history-dialog[open]{display:block;overflow:auto}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.job-dialog form,
  .customer-dialog form,
  .accounting-history-dialog form,
  .production-dialog-shell {
  flex: 1;
  min-height: 0;
  display: block;
  flex-direction: column;
  height: auto;
  gap: 0;
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.tab-page,
  .customer-tab-page,
  .production-dialog-body,
  .archive-workflow-body,
  .archive-delivery-body,
  .accounting-history-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow: visible;
}

  /* Baslik yukarida kalir ki kapatma butonu her zaman erisilebilir olsun */
  .gold-modal-header,
  .dialog-head,
  .production-job-head,
  .personnel-dialog-head,
  .stock-dialog-head{
    position:sticky;
    top:0;
    z-index:3;
    padding-block:var(--s2);
    background:var(--surface);
  }/* 3 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.job-actions,
  .customer-actions,
  .child-actions,
  .dialog-actions {
  position: static;
  bottom: 0;
  z-index: 2;
  flex: 0 0 auto;
  flex-wrap: wrap;
  gap: var(--s2);
  padding: var(--s2);
  margin: 0;
  background: var(--surface);
  border-top: 1px solid var(--line);
  padding-block: var(--s2);
}/* 4 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.job-summary {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr)) auto;
  align-items: center;
  gap: var(--s2);
  padding: var(--s2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r2);
  box-shadow: var(--sh1);
  height: auto;
  min-height: 0;
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.job-summary b {
  display: block;
  font: 700 20px/1.2 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 14px;
}/* 4 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.file-preview {
  display: grid;
  place-items: center;
  min-height: 0;
  padding: var(--s3);
  background: var(--paper-2);
  border: 1px dashed var(--line);
  border-radius: var(--r1);
  overflow: hidden;
  font: 600 11px/1.6 var(--ui);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-3);
  max-height: 40dvh;
}/* 4 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.file-preview img {
  max-width: 100%;
  max-height: calc(40dvh - var(--s5));
  object-fit: contain;
  background: var(--surface);
}
  .color-list,
  .measure-list,
  .pantone-list,
  .revision-history,
  .production-measure-list{min-height:0;max-height:34dvh}/* 3 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.forms-preview-empty {
  display: grid;
  place-items: center;
  min-height: 0;
}
}


/* === 6. HAREKET AZALTMA — SPEC bolum 6 zorunlu tabani ====================
   `!important` YASAK oldugu icin bu blok OZGULLUKLE kazanir.
   NEDEN duz `*` yetmiyor: dosyalar `@layer` icinde DEGIL, dolayisiyla
   kaskadda once ozgulluk karsilastirilir, sonra kaynak sirasi. `*`
   ozgullugu (0,0,0) — `button{transition:...}` (0,0,1) bile onu eziyordu;
   10-tokens'taki eski blok tam bu yuzden olu koddu ve bu dosyaya tasindi.
   `:root` tekrari ozgullugu (0,3,0)'a cikarir. Bu, SPEC bolum 8.4'un
   izin verdigi en derin secicinin (iki sinif seviyesi -> en fazla
   (0,2,n)) UZERINDE kalir; yani gelecekte yazilacak her kural-uyumlu
   `transition` bildirimini de kapsar, listelemeye gerek yok.
   Tek istisna kimlik secicileri: (1,0,0) hicbir sinif zinciriyle
   yenilemez, o yuzden ayrica yazilir (dosyalarda tek ornek: #toast). */
@media (prefers-reduced-motion:reduce){
  :root:root:root *,
  :root:root:root *::before,
  :root:root:root *::after{
    transition:none;
    animation:none;
  }/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
#toast {
  position: fixed;
  right: var(--s5);
  top: var(--s5);
  z-index: 9999;
  max-width: min(420px,calc(100vw - var(--s6)));
  padding: var(--s3) var(--s4);
  border-radius: var(--r2);
  background-color: var(--k);
  color: #fff;
  font: 600 13px/1.45 var(--ui);
  box-shadow: var(--sh3);
  opacity: 0;
  pointer-events: none;
  transition: none;
}
}


/* === 7. CIKTI (print) — onceki katmanlarin EZEMEDIGI sifirlamalar ========
   10-tokens ve 30-shell bu bildirimleri bilincli olarak son katmana
   devretti: 10-tokens ilk katman oldugu icin `.app`/`main` uzerine
   yazdigi cikti kurallari 30-shell'in ayni ozgullukteki duzen
   kurallarina kaybediyordu. Burada kaynak sirasi lehimize.
   Kaydirma kabi ekranda `.app main`; kagitta kap OLMAZ, yoksa
   yalnizca ilk ekran basilir. */
@media print{
  .app{display:block;height:auto}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.app main {
  display: block;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  overflow: visible;
  overscroll-behavior: contain;
  height: auto;
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.table {
  overflow: visible;
  border-radius: var(--r1);
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.table table {
  width: 100%;
  min-width: 0;
}/* 3 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.table th,
  .table td {
  white-space: normal;
  padding-inline: var(--s2);
}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.dialog-close,
  .gold-modal-close {
  display: none;
  align-items: center;
  justify-content: center;
  width: var(--tap);
  height: var(--tap);
  min-height: var(--tap);
}

  /* app.js oturum acildiginda bunlari her zaman uretir; kagitta yeri yok */
  .mobile-menu-button,
  .mobile-menu-backdrop{display:none}
}


/* ==================== 70-mobile-hotfix.css ==================== */

/* =====================================================================
   70 — MOBIL TASMA DUZELTMESI
   =====================================================================
   Gercek telefonda (iPhone, 390px) alinan ekran goruntusuyle tespit edilen
   yatay tasma kusurlari. Kok neden: "baslik solda + aksiyon sagda" desenini
   kuran flex satirlarinda flex-wrap YOK; sagdaki oge kuculmedigi icin satir
   kapsayicidan genis kaliyor ve sayfa yatay kayiyor.

   Bu katman EN SON birlestirilir, dolayisiyla kaynak sirasiyla kazanir;
   ozgulluk hilesine veya !important'a gerek yok.
   ===================================================================== */


/* === TABAN: BASLIK + AKSIYON SATIRI DESENI =============================
   .management-hero'nun hicbir katmanda taban kurali yoktu; .management-live
   ise margin-left:auto ile sagda konumlanmayi bekliyor. Kapsayiciyi burada
   acikca flex yapiyoruz ki hem masaustunde beklenen yerlesim olussun hem de
   asagidaki sarma kurallari tutunacak bir zemin bulsun. */
.management-hero{
  display:flex;
  align-items:flex-start;
  gap:var(--s4);
  min-width:0;
}
.management-hero>*{min-width:0}


/* === <=900px — SATIRLAR SARILIR ======================================== */
@media (max-width:900px){

  /* --- Baslik + aksiyon satirlari ---
     Sagdaki oge artik alt satira gecebiliyor; satir kapsayiciyi zorlamiyor. */
  .management-hero,
  .panel-title-row,
  .section-head,
  .dialog-head{flex-wrap:wrap}

  .panel-title-row>*,
  .section-head>*,
  .dialog-head>*{min-width:0}

  /* Aksiyon butonu alt satira gecince tam genislige yayilir — parmakla
     basilabilir bir hedef olur, kirpilmis metin kalmaz. */
  .panel-title-row button,
  .section-head button{flex:1 1 100%}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
main>header {
  position: sticky;
  top: 0;
  z-index: 30;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2);
  min-height: var(--header-h);
  padding: var(--s2) var(--s5);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
  #userRole{display:none}
}


/* === <=560px — TELEFON ================================================= */
@media (max-width:560px){

  /* Baslik ve aksiyon dikey yigilir; aksiyon tam genislik. */
  .management-hero{gap:var(--s3)}/* 3 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.management-live {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  padding: var(--s1) var(--s2);
  background: var(--ok-soft);
  border: 1px solid var(--line);
  border-radius: var(--r1);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink);
  flex: 0 0 auto;
  width: 100%;
  justify-content: center;
}

  /* Rozet/etiket satirlari sarilir — "0 Onay bekleyen / 0 Onayli /
     0 Tamamlanan" ucusu tek satirda sigmiyordu. */
  .today-stat-breakdown,
  .management-stat-tags,
  .stat-tags{flex-wrap:wrap}/* 3 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.user b {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  max-width: 7ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
}


/* === SON EMNIYET KEMERI ===============================================
   Yatay tasmanin kok nedenlerini yukarida cozduk. Bu blok, GOZDEN KACMIS
   bir ogenin tum sayfayi yatay kaydirmasini engeller: tasma, ogenin KENDI
   kapsayicisinda kalir. body{overflow-x:hidden} KULLANILMIYOR — o, sorunu
   gizler ve position:sticky'yi bozar. Burada yalnizca kaydirma kabi olan
   `.app main` sinirlandiriliyor. */
@media (max-width:900px){
  /* .app main max-width:100vw KALDIRILDI — iOS'ta 100vw dikey kaydirma
     alanini icerir ve yatay tasma yaratir; main zaten grid track (1fr)
     icinde kapsayiciya sigar, ayrica 80-scroll-fix max-width:100% verir. */
  .page{min-width:0}
}


/* =====================================================================
   UYGULAMA KABUGU KAYDIRMA KURGUSU — asil kok neden
   =====================================================================
   Eski styles.css'te `html,body{height:100%;overflow:hidden}` vardi ve
   yeniden yazimda DUSTU. Sonucu iki belirti:

   1. "Ust kisim asagi cekince gorunuyor": .app{height:100dvh} olmasina
      ragmen body'nin yukseklik siniri olmadigi icin kaydirma BODY'de
      olusuyordu. main>header{position:sticky} ise `main` icinde sabitlenir;
      body kaydiginda header'la birlikte tum kabuk yukari cikiyordu.
   2. "Ekran yana kayiyor": body kaydirilabilir oldugu icin herhangi bir
      tasma YATAY DOKUMAN kaydirmasina donusuyordu; `.app main{max-width}`
      emniyeti bunu engelleyemez, cunku tasma body seviyesinde kaciyor.

   Cozum: kaydirma kabini tekrar `.app main` yap, body'yi sabitle.
   Yukseklik icin 100vh/100dvh yerine `height:100%` kullaniliyor —
   html/body zincirine yapistigi icin mobil tarayici arayuzu (adres cubugu)
   buyuyup kuculdugunde kayma olusmaz.
   ===================================================================== */
html,body{
  height:100%;
  overflow:hidden;
}

/* Giris ekrani da kendi icinde kaydirilir: kart uzun ekranlarda tasarsa
   body kilitli oldugu icin erisilemez kalmasin. */
#loginView{
  height:100%;
  overflow-y:auto;
  -webkit-overflow-scrolling:touch;
}

/* Kabuk tam gorunur alani doldurur (vh/dvh yerine yuzde). */
.app{height:100%}

/* TEK kaydirma kabi. overflow-x:hidden, gozden kacmis bir tasmanin
   .table kendi ic yatay kaydirmalarini korur (onlarin overflow-x:auto'su
   bu kuraldan etkilenmez). */
.app main{
  overflow-y:auto;
  overflow-x:hidden;
  -webkit-overflow-scrolling:touch;
}


/* =====================================================================
   TABLO KAYDIRMA — yatay tasmanin gercek kaynagi
   =====================================================================
   Playwright ile 390px'te olculdu: doc 390/390, main 390/390 (kabuk
   dogru), FAKAT <table> ogeleri 526-824px genisliginde. .table
   sarmalayicisinda `overflow:auto` VAR ama sarmalayici DARALMIYOR:
   flex/grid cocuklarinin varsayilan `min-width:auto` degeri, icerigin
   min-content genisliginin altina inmelerini engeller. Sarmalayici
   tabloyla birlikte buyuyunce ic kaydirma hic devreye girmez.

   Cozum: kaydirma kabina ve atalarina min-width:0 vermek. Boylece
   sarmalayici kapsayiciya sigar ve tablo KENDI icinde yatay kayar —
   sagdaki kolonlara parmakla erisilir.
   ===================================================================== */
.table{
  min-width:0;
  max-width:100%;
  overflow-x:auto;
  overflow-y:visible;
  -webkit-overflow-scrolling:touch;
}

/* Kaydirma kabinin atalari da daralabilmeli; aksi halde min-width:0
   asagiya gecmez ve tablo yine kapsayicisini zorlar. */
.panel,
.panel>*,
.page>*{min-width:0}

/* TAKAS TERSINE CEVRILDI — "kaydirma asagi kabul edilebilir ama yana
   kaydirma kabul edilemez" (musteri, 16.08).

   ESKI KURAL SUYDU:
       .table table{min-width:max-content}
       .table th,.table td{white-space:nowrap}
   Gerekcesi "kolonlar okunabilir bir alt sinirin altina sikismasin,
   hucreler satir kirmasin" idi. Bedeli yatay kaydirmaydi ve o bedel o
   gun kabul edilmisti. Olculdu: 1366px'te DOKUZ tablonun hepsi yana
   kayiyordu (Rapor Merkezi kabindan 944px genis).

   `min-width:max-content` tabloya "en genis halinde dur" diyor;
   `nowrap` ise bir sutunun en-az genisligini TUM metin yapiyor —
   "Isin Adi" sutunu tek basina 478-702px yiyordu. Ikisi birlikte
   kaldirilinca sutunun en-az genisligi EN UZUN KELIME'ye iner.

   Satirlar uzar, sayfa asagi kayar: musterinin acikca kabul ettigi
   taraf burasi. */
.table table{width:100%;min-width:0}
.table th,
.table td{white-space:normal}


/* =====================================================================
   `overflow-x:hidden` -> `clip`
   =====================================================================
   `.app main` hem overflow-y:auto hem overflow-x:hidden oldugunda iOS
   Safari'de YATAY OLARAK PANLANABILIR bir kaydirma kabi olusuyor:
   kullanici parmakla saga kaydirinca icerik kayiyor ve sol taraf
   ekran disinda kaliyor ("nlı Yönetim Paneli" gibi soldan kirpilmis
   metin). `clip` ise kaydirma kabi OLUSTURMAZ — kirpar ve panlamayi
   tamamen imkansiz kilar. Tablolar yukarida kendi kaplarinda kaydigi
   icin bu kirpma artik bir seyi erisilemez BIRAKMIYOR.
   ===================================================================== */
.app main{
  overflow-y:auto;
  overflow-x:clip;
}


/* === iOS SAFARI EMNIYETI ==============================================
   Safari'de `overflow-x:clip` ile `overflow-y:auto` birlikte kullanildiginda
   bazi surumler clip'i hidden gibi hesaplayip yatay panlanabilir bir kap
   birakiyor. Olcum main'in yatay kaydirma payi olmadigini gosteriyor
   (390/390), yani panlanacak alan yok; yine de zincirlenen dokunma
   hareketlerinin kabi kaydirmasini kesin olarak engelliyoruz. */
.app main{
  overscroll-behavior-x:none;
  overscroll-behavior-y:contain;
}


/* ==================== 80-scroll-fix.css ==================== */

/* =====================================================================
   80 — iOS SAFARI KAYDIRMA MODELI: KESIN COZUM
   =====================================================================
   ONCEKI HATA: 70-mobile-hotfix "app-shell" modeli kurdu —
   html,body{overflow:hidden;height:100%} + .app main{overflow:auto}.
   Bu modelde kaydirma BODY'de degil `.app main` icinde olur ve
   main>header{position:sticky} yalnizca main'e yapisir.

   iOS Safari'de bu model COKUYOR: nested overflow kabinda sticky ve
   momentum-scroll guvenilmez calisir; kullanici parmakla kaydirinca
   header ve kontrol seridi yukari kayip GERI GELMIYOR (gercek cihazda
   dogrulandi — Playwright mobil emulasyonu bu davranisi taklit etmez,
   o yuzden statik olcumde gorunmedi).

   COZUM: tek kaydirma kabi = DOKUMAN. Natural document scroll'da
   position:sticky iOS dahil her yerde kusursuz calisir. Bu katman en
   son birlestigi icin onceki overflow kurallarini kaynak sirasiyla
   ezer; !important gerekmez.
   ===================================================================== */

/* Doküman dogal akista kayar. overflow:hidden ve sabit yukseklik KALKAR.
   KRITIK KURAL: overflow-x ve overflow-y'den biri `hidden`, digeri
   `visible` olursa CSS spec `visible` olani `auto`'ya cevirir ve o eleman
   ISTEMEDEN kaydirma kabi olur. Bu yuzden:
   - html: yatay tasmayi KESER (overflow-x:hidden), dikey scrollport'tur
     (overflow-y:auto) — tek gercek kaydirma kabi budur.
   - body: HICBIR overflow kisiti ALMAZ (visible/visible). Aksi halde body
     scroll-container olur ve icindeki sticky header BOZULUR — header
     dokumanla birlikte yukari kayar. Yatay koruma zaten html'de. */
html{
  height:auto;
  overflow-x:hidden;
  overflow-y:auto;
  /* iOS rubber-band: parmakla dikey kaydirirken yatay ESNEME (yana kayma
     hissi) olusur. Scroll kabi artik HTML oldugu icin bu kural burada
     olmali (onceden main'deydi ama main scroll kabi degil). */
  overscroll-behavior-x:none;
}
body{
  height:auto;
  min-height:100%;
  overflow:visible;
}

/* Giris ekrani da dogal akista; kilitli body yoktu artik. */
#loginView{
  height:auto;
  min-height:100vh;
  overflow:visible;
}

/* Uygulama kabugu: sabit yukseklik yerine en az viewport kadar. */
.app{
  height:auto;
  min-height:100vh;
  overflow:visible;
}

/* main artik KENDI kaydirma kabi DEGIL — icerik dogal akar, sayfa kayar.
   dokuman scroll'una yapisir ve iOS'ta ekranin ustunde SABIT kalir.

   KRITIK: main'de overflow, `visible` DISINDA bir deger (clip/hidden/auto)
   olursa main, icindeki sticky header icin kaydirma kabi olur ve sticky
   BOZULUR — header dokumanla birlikte yukari kayar. Bu yuzden main
   overflow:visible OLMAK ZORUNDA. Yatay tasma korumasi html/body
   uzerindeki overflow-x:hidden ile saglanir (asagida), tablolar da kendi
   .table sarmalayicilarinda kayar. */
.app main{
  overflow:visible;
}

/* Masaustunde kenar cubugu dokuman kayarken sabit kalir (grid kolonu
   icinde sticky). Mobilde zaten position:fixed cekmece, bu kural
   900px ustunde gecerli. */
@media (min-width:901px){
  .app>aside{
    position:sticky;
    top:0;
    height:100vh;
    align-self:start;
    overflow-y:auto;
  }
}


/* === iOS YATAY KAYMA EMNIYETI ========================================
   Chromium'da yatay kayma olcumu 0 (scrollX=0), ancak iOS Safari root
   element overflow-x:hidden'i her zaman guvenilir uygulamaz. Ekstra
   emniyet: main genisligi ATA'ya sigar (100vw DEGIL — 100vw iOS'ta
   dikey kaydirma alanini icerir). Geniş tablolar zaten .table icinde
   kayar; buradaki kural sayfanin KENDISININ yatay panlanmasini keser. */
.app main{max-width:100%}


/* ==================== 90-mobile-usability.css ==================== */

/* =====================================================================
   90 — MOBIL KULLANILABILIRLIK
   =====================================================================
   Playwright ile 360/390px'te olculen GERCEK kusurlar (yatay tasma degil,
   GIZLENEN KONTROLLER). Kaynak: mobil olcum turu raporu.

   Hepsi 900px altinda gecerli; masaustu yerlesimi degismez.
   ===================================================================== */

@media (max-width:900px){

  /* === 1. HEADER: kullanici adi/rol basligi kirpiyordu ===============
     Olcum: 15 ekranin tamaminda #pageTitle + #userName + #userRole ayni
     anda kirpik (system: baslik 117px, ad 94px, rol 43px kayip). Sebep:
     4 oge 360px'e sigmiyor. Cozum: kullanici adi ve rol mobilde
     header'dan GIZLENIR (bu bilgi zaten cekmecenin ustunde ve Ayarlar'da
     var); sadece Cikis butonu kalir. Boylece #pageTitle tam gorunur. */
  /* HEADER: TASMASI IMKANSIZ GRID.
     Chromium her genislikte (320/390/430) header'i sigdiriyor ama gercek
     iOS cihazda Cikis butonu sagdan tasip erisilemez oluyor (kullanici
     "cikis butonu sayfanin disinda" dedi). Flex + margin-left:auto yerine
     3 kolonlu grid: [hamburger auto] [baslik 1fr, kuculur] [Cikis auto].
     Orta kolon min-width:0 ile daralir/ellipsis olur; Cikis (auto kolon)
     HER ZAMAN son kolonda, viewport icinde kalir. Matematiksel garanti. */
  .app main>header{
    display:grid;
    grid-template-columns:auto minmax(0,1fr) auto;
    align-items:center;
    gap:var(--s2);
  }
  .app main>header>div:not(.user){min-width:0}

  #userName,
  #userRole{display:none}/* 3 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.user {
  display: flex;
  align-items: center;
  gap: var(--s3);
  flex: 0 0 auto;
  min-width: 0;
  margin-left: auto;
}
  #logout{min-height:var(--tap)}

  /* Kullanici adi ve rol cekmecenin ustune tasinir: marka blogunun altina
     app.js zaten #userName/#userRole'u header'a koyuyor; burada cekmece
     icin AYRI bir gosterim yok — bilgi kaybi degil, mobilde oncelik
     sayfa basligi. (Cekmece kimlik satiri ileride app.js ile eklenebilir.) */


  /* === 2. #jobTabs: 7 sekmenin 4'u ekran disindaydi ==================
     Olcum: cw 328 / sw 775, %57.7 gizli. Cozum: DETERMINISTIK GRID.
     flex-wrap denendi ama uzun sekme metinleri (flex:1 1 auto + nowrap)
     her butonu kendi satirina itti (7 satir). Grid 2 kolon kesin sonuc
     verir: 7 sekme 4 satir, hicbiri gizli degil. Uzun metin buton
     icinde sarar (white-space:normal), kaydirma gerekmez. */
  #jobTabs{
    display:grid;
    grid-template-columns:repeat(2,minmax(0,1fr));
    gap:var(--s1);
    overflow:visible;
  }
  #jobTabs button{
    min-height:var(--tap);
    white-space:normal;
    text-align:center;
    padding:var(--s2);
    line-height:1.25;
  }

  /* Ayni desen diger sayfa-ici sekme cubuklari icin (musteri, ayarlar,
     rapor). .tabs genel sinifi + varyantlari. */
  .tabs{
    display:grid;
    grid-template-columns:repeat(2,minmax(0,1fr));
    gap:var(--s1);
    overflow:visible;
  }
  .tabs button{
    min-height:var(--tap);
    white-space:normal;
    text-align:center;
  }

  /* Sekmeler zaten grid 2 kolon (yukarida); 560 altinda ek kural gerekmez. */
}


/* ==================== 95-ios-clip.css ==================== */

/* =====================================================================
   95 — iOS YATAY TASMA: KABA KUVVET EMNIYETI
   =====================================================================
   Chromium 320/390/430'da docScrollWidth==viewport (tasma YOK) ama gercek
   iOS Safari'de sayfa yana kayiyor. iOS'un root-scroller'i html'deki
   overflow-x:hidden'i her zaman uygulamaz. `overflow-x:clip` FARKLIDIR:
   scroll kabi OLUSTURMAZ (yani sticky header'i BOZMAZ) ama tasmayi kesin
   kirpar. iOS 16+ destekler. Zincirin her seviyesine koyariz ki hangi
   seviyede tasarsa tassin, viewport disina cikamasin. */
html{overflow-x:clip;}
body{overflow-x:clip; max-width:100%;}
.app{overflow-x:clip; max-width:100%;}
.app main{overflow-x:clip;}
.page{overflow-x:clip; max-width:100%;}

/* Her sayfanin dogrudan cocuklari viewport'u asamaz; tasan icerik kendi
   icinde sarar. Tablolar zaten .table icinde kayar (o overflow:auto
   korunur — clip onu ezmez cunku .table'a ayri kural yok). */
.page>*{max-width:100%;}


/* ==================== 99-header-rebuild.css ==================== */

/* Bu katman 99c-header-yeni.css ile DEGISTIRILDI. Bilerek bos birakildi
   ki eski (calismayan) header kurallari yeniyle catismasin. */


/* ==================== 99b-tables-as-cards.css ==================== */

/* =====================================================================
   99b — MOBILDE TABLOLAR KART OLUR (yatay tasmanin kokten sonu)
   =====================================================================
   TESPIT: Kullanicinin cihazinda sayfa viewport'tan ~%14 genisti. 390px
   ekranda ~55px fazla = #recentJobs tablosunun genisligi (445px). Yani
   `.table{overflow-x:auto}` sarmalayicisi gercek iOS'ta tabloyu
   SINIRLAMIYOR; tablo sayfayi geniyor, header de sayfa genisliginde
   oldugu icin Cikis butonu ekran disinda kaliyor.

   COZUM: mobilde tabloyu tablo olarak render ETME. Tum tablo ogeleri
   blok'a cevrilir; her satir bir KART olur. Boylece hicbir oge
   viewport'tan genis OLAMAZ — yatay kaydirma ihtimali yapisal olarak
   ortadan kalkar. Masaustunde (>900px) tablolar aynen kalir.
   ===================================================================== */

@media (max-width:900px){

  .table{
    overflow:hidden;      /* yatay kaydirma YOK */
    max-width:100%;
    min-width:0;
  }

  .table table,
  .table thead,
  .table tbody,
  .table tr,
  .table th,
  .table td{
    display:block;
    width:100%;
    max-width:100%;
    min-width:0;
    white-space:normal;      /* nowrap kaldirilir, metin sarar */
    overflow-wrap:anywhere;  /* uzun kod/ad tasmaz */
  }

  /* Baslik satiri gizlenir: kart duzeninde kolon basligi anlamsiz.
     (Siralama masaustunde yapilir; mobilde arama/filtre kullanilir.) */
  .table thead{display:none}

  /* Her satir bir kart */
  .table tbody tr{
    border:1px solid var(--line);
    border-radius:var(--r2);
    background:var(--surface);
    padding:var(--s3);
    margin-bottom:var(--s3);
    box-shadow:var(--sh1);
  }
  .table tbody tr:last-child{margin-bottom:0}

  /* Hucreler alt alta; ilk hucre kartin basligi gibi one cikar */
  .table tbody td{
    border:0;
    padding:var(--s1) 0;
  }
  .table tbody td:first-child{
    font-weight:650;
    font-size:15px;
    padding-top:0;
  }

  /* Secili satir vurgusu kart kenarinda */
  .table tbody tr.selected,
  .table tbody tr[class*="selected"]{
    border-color:var(--m);
    box-shadow:inset 3px 0 0 var(--m);
  }
}


/* ==================== 99c-header-yeni.css ==================== */

/* =====================================================================
   99c — UST BAR: SIFIRDAN, MOBIL ONCELIKLI
   =====================================================================
   Onceki tum header denemeleri (flex, grid) gercek iOS cihazda tasti.
   Sebep her seferinde ayniydi: cocuk ogelerin "intrinsic" genisligi
   ebeveyni buyutuyordu.

   YENI TASARIM ILKESI: hicbir cocuk header'in genisligine KATKI YAPMAZ.
     - hamburger  -> position:absolute (sol capa)
     - cikis      -> position:absolute (sag capa)
     - baslik     -> position:absolute, left/right ile SINIRLANMIS kutu
   Mutlak konumlu ogeler ebeveynin icerik genisligine katilmaz; header
   her zaman kapsayicisi kadardir. Ustune overflow:hidden ile son kilit.
   Markup: <header><div class="hdr-title">…</div><div class="user">…</div></header>
   (app.js hamburger'i header'a prepend eder; o da mutlak konumlanir.)
   ===================================================================== */

/* --- MOBIL TABAN (once mobil) ---------------------------------------- */
.app main>header{
  position:sticky;
  top:0;
  z-index:30;
  display:block;               /* flex/grid YOK */
  height:56px;
  padding:0;
  background:var(--surface);
  border-bottom:1px solid var(--line);
  overflow:hidden;             /* son kilit */
  max-width:100%;
}

/* Hamburger — sol capa (app.js uretir) */
.app main>header .mobile-menu-button{
  position:absolute;
  left:6px;
  top:6px;
  width:44px;
  height:44px;
  margin:0;
  display:flex;
  align-items:center;
  justify-content:center;
  z-index:2;
}

/* Cikis — sag capa */
.app main>header .user{
  position:absolute;
  right:6px;
  top:6px;
  height:44px;
  margin:0;
  display:flex;
  align-items:center;
  gap:var(--s2);
  z-index:2;
}
.app main>header .user #logout{
  height:44px;
  min-width:44px;
  padding:0 var(--s3);
  white-space:nowrap;
}
/* Mobilde kullanici adi/rol gizli: dar ekranda basliga oncelik. */
.app main>header #userName,
.app main>header #userRole{display:none}

/* Baslik — iki capa arasinda SINIRLANMIS kutu. left/right verildigi icin
   genisligi kapsayiciya kilitlidir; icerik ne olursa olsun buyuyemez. */
.app main>header .hdr-title{
  position:absolute;
  left:56px;
  right:56px;
  top:0;
  bottom:0;
  display:flex;
  flex-direction:column;
  justify-content:center;
  min-width:0;
  overflow:hidden;
}
.app main>header .hdr-title small{
  display:block;
  font-size:10px;
  line-height:1.1;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-3);
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}
.app main>header .hdr-title #pageTitle{
  display:block;
  margin:0;
  font-size:16px;
  line-height:1.2;
  font-weight:700;
  letter-spacing:-.01em;
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}


/* --- MASAUSTU (>900px): capalar cozulur, klasik duzen ---------------- */
@media (min-width:901px){
  .app main>header{
    height:auto;
    min-height:64px;
    padding:var(--s3) var(--s5);
    overflow:visible;
  }
  .app main>header .mobile-menu-button{display:none}
  .app main>header .hdr-title{
    position:static;
    left:auto;right:auto;
    justify-content:center;
  }
  .app main>header .hdr-title #pageTitle{font-size:20px;white-space:normal}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.app main>header .user {
  margin: 0;
  /* margin-left: auto artik gereksiz, grid konumluyor */
    justify-self:end;
  position: absolute;
  right: var(--s5);
  top: 50%;
  transform: translateY(-50%);
  height: auto;
}
  .app main>header #userName{display:inline;font-weight:650}
  .app main>header #userRole{display:inline;color:var(--ink-3);font-size:12px}

  /* Kabuk zinciri: hicbir seviye viewport'u asamaz. */
  .app,
  .app main,
  .page{max-width:100%;min-width:0}/* 2 ayri tanim tek kurala indirildi (sonuncusu kazanacak sekilde birlestirildi) */
.page>* {
  max-width: 100%;
}
}


/* "Oturumu acik tut" satiri — giris kartinda, buton ustunde */
.remember-row{
  display:flex;
  align-items:center;
  gap:var(--s2);
  margin:var(--s3) 0;
  font-size:14px;
  font-weight:500;
  letter-spacing:normal;
  text-transform:none;
  color:var(--ink-2);
  cursor:pointer;
  min-height:var(--tap);
}
.remember-row input[type="checkbox"]{
  width:20px;
  height:20px;
  flex:0 0 auto;
  accent-color:var(--m);
  margin:0;
}

/* MALİYET / MARJ KUTUSU — iş emri kartı > Fiyat sekmesi (E maddesi).
   Satış özetinden ayrı bir kutu: ikisi farklı soruya cevap veriyor
   ("ne kadara sattık" ve "ne kazandık"). Aynı listeye karıştırmak
   maliyeti satış kalemi gibi okuturdu. */
.maliyet-ozet{
  margin-top:var(--s3);
  padding-top:var(--s3);
  border-top:1px dashed var(--line);
}
/* Zarar KIRMIZI: eksi marj gözden kaçmamalı. */
.fiyat-satir.toplam.zarar b{color:var(--no)}

/* YAPIM AŞAMASINDA KARTI — kullanıma kapatılmış ekranlar.
   Sayfa gizlenmiyor, içeriği bu kartla değiştiriliyor: boş ekran
   "bozuldu" gibi okunurdu. */
.bakim-karti{
  display:grid;
  place-items:center;
  gap:var(--s2);
  max-width:520px;
  margin:var(--s6) auto;
  padding:var(--s6) var(--s5);
  border:1px solid var(--y);
  border-radius:var(--r2);
  background:var(--surface);
  text-align:center;
}
.bakim-ikon{font-size:40px;line-height:1}
.bakim-karti h2{margin:0;font-size:18px;letter-spacing:.06em;color:var(--y)}
.bakim-karti p{margin:0;color:var(--ink-2)}
.bakim-karti small{color:var(--ink-3)}

/* GENEL FİYAT SATIRI — müşteri kartındaki Fiyatlar sekmesi.
   Bu satır tüm müşteriler için geçerli; buradan silinmesi/düzeltilmesi
   diğer müşterilerin fiyatını sessizce yok ederdi. Görsel olarak da
   ayrılıyor ki karıştırılmasın. */
.fiyat-genel-satir{background:var(--paper-2)}
.fiyat-genel-rozet{
  display:inline-block;
  margin-left:var(--s1);
  padding:1px var(--s1);
  border:1px solid var(--line);
  border-radius:var(--r1);
  font-size:10px;
  font-weight:700;
  color:var(--ink-3);
}

/* MÜŞTERİ TAKİP LİNKİ PENCERESİ */
.track-link-body{margin:var(--s4) var(--s4) 0}
#trackLinkDialog[open]{width:min(560px,94vw)}
#trackLinkDialog .dialog-actions{margin:0;padding:var(--s3) var(--s4) var(--s4)}
/* Bağlantı tek satırda ve seçilebilir dursun; kırpılırsa kullanıcı
   yanlış parçayı kopyalar. */
#trackLinkUrl{font-family:var(--mono);font-size:12.5px}

/* SEÇENEK TEKSE AÇILIR LİSTE DEĞİL, DÜZ METİN.
   "İşlemi yapan" kutusu kural gereği tek ad gösteriyor ama açılır liste
   gibi durduğu için kullanıcı seçim yapabileceğini sanıyordu ("neden
   Karakoç çıkıyor"). Kutu devre dışı ama SİLİK GÖSTERİLMİYOR: bilgi
   okunabilir kalmalı, yalnızca tıklanabilir görünmemeli. */
.salt-okunur-secim{
  appearance:none;
  background:var(--paper);
  border-color:var(--line-2);
  color:var(--ink);
  opacity:1;
  cursor:default;
  /* TIKLANAMAZLIK BURADAN GELİYOR, `disabled` ÖZNİTELİĞİNDEN DEĞİL.
     Öznitelik kullanılmıştı ve kaydetmeyi kırdı: form gövdesi
     `new FormData(form)` ile kuruluyor, devre dışı alanlar oraya
     girmiyor ve personel adı sunucuya hiç gitmiyordu. Kutu artık form
     açısından canlı, yalnızca etkileşime kapalı. */
  pointer-events:none;
}

/* EKİP EKRANI — solda kişi listesi, sağda seçilenin tamamı.
   Tek sütuna düşme sınırı 1100px: sağ panelde iki sütunluk alan grubu var
   ve daha dar bir yerde yan yana durunca alanlar okunmaz hâle geliyordu
   (aynı hatayı ölçü ekranında bir kez yaptım, açıklama alanı 0px'e
   düşmüştü). */
.ekip-bolme{display:grid; gap:14px; grid-template-columns:1fr;}
@media (min-width:1100px){
  .ekip-bolme{grid-template-columns:minmax(0,1.05fr) minmax(0,1fr);
              align-items:start;}
}
.ekip-detay{padding:16px; display:flex; flex-direction:column; gap:14px;}
.ekip-bos{margin:0; padding:24px 8px; text-align:center;}

.ekip-alt{display:block; font-size:11.5px; color:var(--ink-3);
          font-variant-numeric:tabular-nums;}
.ekip-sayi{font-variant-numeric:tabular-nums; font-weight:650;}
.ekip-sayi small{font-weight:400; color:var(--ink-3);}
#personnelTable tr{cursor:pointer;}
#personnelTable tr.secili{background:var(--m-soft);}
#personnelTable tr.secili td:first-child{box-shadow:inset 3px 0 0 var(--m);}

.ekip-rozet{display:inline-block; padding:2px 8px; border-radius:999px;
            font-size:10.5px; font-weight:700; letter-spacing:.04em;
            border:1px solid transparent; white-space:nowrap;}
.ekip-rozet.yonetici{background:var(--plate-soft); color:var(--plate);
                     border-color:color-mix(in srgb,var(--plate) 35%,transparent);}
.ekip-rozet.aktif{background:var(--ok-soft,#E4F2E9); color:var(--ok);
                  border-color:color-mix(in srgb,var(--ok) 30%,transparent);}
.ekip-rozet.yok{background:var(--paper-2); color:var(--ink-3);
                border-color:var(--line);}

.ekip-detay-bas{display:flex; gap:12px; align-items:flex-start; flex-wrap:wrap;}
.ekip-avatar{width:42px; height:42px; border-radius:50%; flex:none;
             background:var(--k-2); color:#fff; display:grid;
             place-items:center; font-weight:700; font-size:15px;}
.ekip-detay-bas h3{margin:0; font-size:17px; line-height:1.25;}
.ekip-ustbilgi{font-size:12.5px; color:var(--ink-3);
               font-variant-numeric:tabular-nums;}

.ekip-blok{border:1px solid var(--line); border-radius:8px;
           padding:12px 14px 14px; margin:0; background:var(--surface);}
.ekip-blok legend{font-size:11px; letter-spacing:.1em; text-transform:uppercase;
                  color:var(--ink-3); font-weight:700; padding:0 6px;}
.ekip-satirlar{display:grid; gap:9px; grid-template-columns:1fr;}
@media (min-width:520px){.ekip-satirlar{grid-template-columns:1fr 1fr;}}
.ekip-alan{display:flex; flex-direction:column; gap:3px; min-width:0;}
.ekip-alan span{font-size:11px; color:var(--ink-3); letter-spacing:.04em;
                text-transform:uppercase; font-weight:600;}
.ekip-kutucuk{border:1px solid var(--line); border-radius:5px;
              background:var(--paper); padding:6px 9px; font-size:13px;
              color:var(--ink-2); min-height:19px; overflow-wrap:break-word;}

.ekip-uyari{margin:8px 0 0; padding:9px 11px; border-radius:6px;
            background:var(--y-soft); border:1px solid
            color-mix(in srgb,var(--y) 32%,transparent);
            border-left:3px solid var(--y); font-size:13px;}

.ekip-yonetici{display:flex; align-items:center; gap:10px; font-size:13px;
               background:var(--plate-soft); border-radius:6px;
               padding:9px 11px; margin-bottom:11px;
               border:1px solid color-mix(in srgb,var(--plate) 30%,transparent);}
.ekip-kutular{display:grid; gap:6px;
              grid-template-columns:repeat(auto-fill,minmax(150px,1fr));}
.ekip-ek{display:flex; align-items:center; gap:7px; font-size:12.5px;
         padding:5px 8px; border:1px solid var(--line-2); border-radius:5px;
         background:var(--paper); min-width:0;}
.ekip-ek span{overflow-wrap:anywhere;}
.ekip-dugmeler{display:flex; gap:8px; flex-wrap:wrap; margin-top:11px;}

/* GİRİŞ KİLİTLERİ PANELİ (EKİP ekranı, yalnızca yönetici).
   Yeni sınıf adları kullanıldı, var olan `.ekip-*` kuralları DEĞİŞTİRİLMEDİ:
   bu depoda ortak bir kuralı "birleştirmek" başka ekranları bozdu. Panel
   kendi adlarıyla yaşıyor, kimsenin görünümünü değiştirmiyor. */
.ekip-kilit-panel{margin-bottom:14px;}
.ekip-kilit-basi{display:flex; align-items:flex-start; gap:12px;
                 justify-content:space-between; flex-wrap:wrap;}
.ekip-kilit-basi h3{margin:0; font-size:14px;}
.ekip-kilit-basi p{margin:3px 0 0; font-size:12px; color:var(--ink-3);}
.ekip-kilit-tablo{margin-top:10px;}
/* Kilitli satır GÖRÜNÜR olmalı: yönetici tabloya bakınca acil olanı
   ayırt edemezse liste "gizlemek değil işaretlemek" işini yapmaz. */
.ekip-kilit-tablo tbody tr.kilitli{background:var(--danger-soft,#FBE9E7);}

/* AÇIK SEKME ESKİ SÜRÜMDE — yenileme şeridi.
   `position:fixed` ve yüksek `z-index`: şerit sayfanın en üstünde
   kalmalı, çünkü kullanıcı onu görmeden çalışmaya devam ederse eski kodun
   ürettiği hatayı bize "sistem bozuk" diye bildiriyor. `dialog` katmanının
   üstüne ÇIKMIYOR (dialog kendi katmanında) — bilerek: açık bir pencerenin
   üstüne binip düğmesini kapatmasın. */
.surum-uyarisi {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 60;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  justify-content: center;
  padding: 10px 16px;
  background: var(--warn, #b45309);
  color: #fff;
  font-size: .9rem;
  font-weight: 600;
  box-shadow: 0 2px 10px rgb(0 0 0 / .25);
}
.surum-uyarisi button {
  padding: 6px 14px;
  border: 0;
  border-radius: 6px;
  background: #fff;
  color: var(--warn, #b45309);
  font-weight: 800;
  font-size: .82rem;
  cursor: pointer;
}

/* ÖLÇÜ PENCERESİ — ARŞİV KİLİDİ ŞERİDİ.
   Kırmızı DEĞİL: bir şey bozulmadı, iş sadece kapanmış. Kırmızı şerit
   kullanıcıya "hata yaptım" dedirtir ve destek çağrısı üretir. */
/* ÖLÇÜ KİLİDİ — SEBEP KUTUSU.
   Şeridin hemen altında duruyor: onayı veren kişi, neyi onayladığını
   GÖRDÜĞÜ yerde sebebi yazsın. Ayrı bir pencere, bağlamı koparırdı.

   `flex-wrap` ŞART: dar ekranda üç öge (alan + iki düğme) tek satıra
   sığmıyor ve düğme kırpılıyordu — bu depoda "TOPLU ETİKE…" diye yarım
   kalan düğme olarak bir kez yaşandı. */
.olcu-kilit-sebep {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2, 8px);
  align-items: center;
  padding: 10px var(--s4, 16px);
  background: color-mix(in srgb, var(--warn, #b45309) 6%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--warn, #b45309) 35%, transparent);
}
.olcu-kilit-sebep label { font-size: .82rem; font-weight: 600; }
/* Alan kalan genişliği alır ama 12rem'in altına inmez: daralınca
   düğmelerin altına iner, kırpılmaz. */
.olcu-kilit-sebep input { flex: 1 1 12rem; min-width: 12rem; }

/* Şerit içindeki KİLİDİ AÇ düğmesi metnin akışında kalsın. */
.olcu-kilit-serit button { margin-left: var(--s2, 8px); }

.olcu-kilit-serit {
  margin: 0;
  padding: 10px var(--s4, 16px);
  background: color-mix(in srgb, var(--warn, #b45309) 12%, transparent);
  border-bottom: 2px solid var(--warn, #b45309);
  color: var(--warn, #b45309);
  font-size: .88rem;
  font-weight: 600;
  line-height: 1.45;
}

/* Fire tablosunda "hesaplanamadı" durumları.
   Sayı yerine metin yazılıyor: ham kayıt yokken "%0,00" yazmak
   "fire yok" diye okunur, oysa hesaplanamamıştır. */
.uyari-metin {
  color: var(--warn, #b45309);
  font-weight: 700;
  font-size: .82em;
  letter-spacing: .02em;
}

/* PENCERE GÖVDESİ — kenara yapışmasın.
   `gold-modal` kalıbında başlık ve alt şerit KENARDAN KENARA uzanır
   (kendi iç boşlukları var, alt çizgileri tam genişlik olmalı). Gövde ise
   kendi yatay boşluğunu vermek zorunda.
   Bu unutulunca alanlar pencere kenarına yapıştı: önce toplu teslimde
   (S10), sonra kullanıcı/parola/ölçü pencerelerinde ve son olarak benim
   eklediğim toplu dağıtım penceresinde. Dördüncü tekrar — artık tek sınıf.
   Kapısı: scripts/regression_checks.py `pencere_govdesi`. */
.modal-body {
  padding-left: var(--s4);
  padding-right: var(--s4);
}

/* ============================================================
   TELEFONDA AKIŞ EKRANLARI — ŞERİT DÜZENİ
   Kullanıcı isteği: "Bunları şerit şeklinde yapıp aşağı yukarı
   sağa sola giderse ilk etapta yeter."

   ÖLÇÜLEN SORUN (412 px telefon, Sevkiyat Merkezi):
     - Sütun genişliği 176 px  (iki sütun yan yana sıkışıyor)
     - Bir iş satırı 246 px YÜKSEK — tek iş ekranın dörtte biri
     - Sağdaki sütunun içeriği kesiliyor

   NEDEN ZATEN DÜZELMEMİŞTİ
     `@media (max-width:900px)` içinde `.workflow-split` için
     `grid-template-columns:minmax(0,1fr)` kuralı ZATEN VARDI (satır ~6763)
     ama ETKİSİZDİ: düz `.workflow-split` kuralı dosyada DAHA SONRA
     geliyor (~6804) ve medya sorgusu özgüllük eklemediği için sonraki
     kural kazanıyordu. Kod okununca "mobil desteği var" görünüyor,
     tarayıcıda yok. Bu yüzden bu blok dosyanın EN SONUNDA.
   ============================================================ */
@media (max-width: 900px) {

  /* Sütunlar ALT ALTA: her biri tam genişlik alır, 176 px'e sıkışmaz.
     Asıl gezinme yukarı-aşağı olur. */
  .workflow-split { grid-template-columns: minmax(0, 1fr); }

  /* Aradaki "→" oku dikey akışta yanıltıcı; aşağıyı gösteriyor. */
  .workflow-arrow { transform: rotate(90deg); justify-self: center; }

  /* Tablo artık 560 px'e zorlanmıyor; şerit kendi genişliğine sığar.
     Yine de sığmayan içerik için yatay kaydırma açık kalıyor
     ("sağa sola giderse yeter"). */
  /* TABLO DÜZEN MODELİNDEN ÇIKARILIYOR.
     Yalnızca satırları `flex` yapmak yetmedi: `table` ve `tbody` hâlâ
     tablo modelindeyken satırlar hücre saymıyor ve tablo GENİŞLİĞİ 0
     ölçüldü (satır yine 246 px kaldı). Üç seviyenin birlikte blok olması
     şart. */
  .workflow-table table, .serit-tablo table,
  .workflow-table thead, .serit-tablo thead,
  .workflow-table tbody, .serit-tablo tbody { display: block; width: 100%; min-width: 0; }

  /* YÜKSEKLİK KİLİDİ KALDIRILIYOR — "aşağı kaymıyor" şikâyetinin sebebi.
     Masaüstünde `.workflow-table` 420 px'e sınırlı ve kendi içinde
     kayıyor; iki sütun yan yana dururken doğru. Telefonda ise sütunlar
     alt alta ve sayfa zaten kayıyor: 420 px'lik kutu 59 işten yalnızca
     4'ünü gösteriyor, `overflow:hidden` ile birleşince kalanına
     ULAŞILAMIYORDU. Ölçüm: sayfa 1052 px, kaydırma 137 px'te bitiyor.
     Telefonda liste tam boyunca uzuyor, gezinme sayfanın kendisinde. */
  .workflow-table { max-height: none; overflow: visible; }

  /* HER İŞ TEK ŞERİT.
     Hücreler alt alta yığılıp 246 px'e çıkıyordu; flex ile yan yana
     dizilip 2 satıra iniyor. */
  .workflow-table tbody tr,
  .serit-tablo tbody tr {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px var(--s2);
    padding: var(--s2) var(--s3);
    /* KART SÜSÜ SIFIRLANIYOR. Genel `.table tbody tr` her satırı
       çerçeve + köşe yuvarlama + gölge + alt boşluk ile karta çeviriyor;
       şeritte bunların hepsi üst üste binince liste "kaba" görünüyordu.
       Yalnızca `padding` yazmak yetmiyordu: diğer dört özellik genel
       kuraldan miras kalmaya devam ediyordu. Ayırıcı tek çizgi. */
    margin-bottom: 0;
    border: 0;
    border-bottom: 1px solid var(--line);
    border-radius: 0;
    box-shadow: none;
    /* DOKUNMA HEDEFİ HÜCREDE DEĞİL SATIRDA.
       `.table td{height:var(--tap)}` her hücreye 44 px veriyor; kart
       düzeninde doğru, çünkü orada tıklanan hücre. Şeritte tıklanan
       şey satırın kendisi (row.onclick müşteriyi açıyor), 7 hücrenin
       her biri 44 px olunca satır 107 px'e şişiyordu. Hedef satıra
       taşındı: parmak için 44 px korunuyor, boy yarıya iniyor. */
    min-height: var(--tap);
  }
  .workflow-table tbody td,
  .serit-tablo tbody td { height: auto; }
  .workflow-table tbody td,
  .serit-tablo tbody td {
    padding: 0;
    border: 0;
    /* Uzun firma adi satiri yatayda tasirmasin: hucre daralabilsin,
       sigmayan kisim ucnokta olsun. Sutun sirasina gore kural yazmak
       yerine her hucreye ayni izin veriliyor — yeni sutun eklenince
       listeye eklemeyi unutma riski dogmuyor. */
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    /* `width: auto` ŞART.
       Genel `.table` mobil kart düzeni (bu dosyada yukarıda) her hücreye
       `width:100%` veriyor ve hücreler alt alta diziliyordu — ölçümde beş
       hücrenin beşi de 328 px genişlikte, satır 246 px yüksekti. Yalnızca
       `max-width` vermek yetmedi: `width` hiç ezilmediği için genel kural
       kazanmaya devam etti. */
    width: auto;
    max-width: 100%;
    overflow-wrap: normal;
  }
  /* Satır kartı değil ŞERİT: genel kuralın kart görünümü geri alınıyor. */
  .workflow-table tbody tr {
    margin-bottom: 0;
    border-radius: 0;
    box-shadow: none;
  }
  /* HÜCRELER AKAR, SÜTUN SIRASINA BAĞLI DEĞİL.
     Önce `nth-child(n+3)` ile belirli sütunları ayrı satıra zorlamıştım;
     ama sevkiyat tablolarında ilk sütun onay kutusu, üretim ve kalite
     tablolarında değil — aynı numara farklı alanlara denk geliyordu.
     Sütun numarası saymak yerine hücreler soldan sağa akıyor ve sığmayan
     yeni satıra geçiyor: kaç sütun olursa olsun çalışır. */
  .workflow-table tbody td { flex: 0 1 auto; min-height: 0; line-height: 1.4; }
  .workflow-table tbody td:first-child,
  .serit-tablo tbody td:first-child {
    flex: 0 0 auto;
    /* Yatay kaydirmali tabloda ilk sutun sabitlenir ve sagina ic golgeyle
       ayrac cizilir. Seritte sutun diye bir sey yok; o golge satirin
       ortasinda asili dikey bir cizgi olarak goruluyordu. */
    position: static;
    box-shadow: none;
  }
  /* İlk metin hücresi (iş no) öne çıksın, kalanlar soluk. */
  .workflow-table tbody td:not(:first-child) ~ td { color: var(--ink-2); }

  /* Boş durum satırı şerit değil, ortalanmış tek metin. */
  .workflow-table tbody td.workflow-empty { flex: 1 1 100%; text-align: center; }

  /* Başlık satırı: şeritte sütun adı anlamsız, ama "tümünü seç" kutusu
     mobilde ASIL işe yarayan şey (57 işi toplu çıkarmak). O kalıyor. */
  .workflow-table thead tr,
  .serit-tablo thead tr { display: flex; align-items: center; }
  .workflow-table thead th,
  .serit-tablo thead th { border: 0; padding: var(--s1) var(--s3); }
  .workflow-table thead th:not(:first-child),
  .serit-tablo thead th:not(:first-child) { display: none; }
}

/* ŞERİT DÜZENİNDE ETİKETLİ HÜCRE.
   Müşteri listesinde "2 / 1 / 1" gibi çıplak sayılar alt alta duruyordu:
   başlık satırı mobilde gizlendiği için hangisinin yetkili, hangisinin
   adres ya da iş sayısı olduğu anlaşılmıyordu. Etiket hücrenin kendisinde
   duruyor; ayrı bir liste tutmak gerekmiyor. */
@media (max-width: 900px) {
  .serit-tablo tbody td[data-etiket]::before {
    content: attr(data-etiket) " ";
    color: var(--ink-3);
    font-size: .85em;
  }
}

/* SEVKİYAT ŞERİDİ — TELEFON DÜZELTMELERİ.

   TAŞMANIN KÖKÜ: `.toplu-teslim-bar` dört düğmeyi tek satıra diziyordu
   (43+170+133+138 = 484 px). 412 px'lik ekranda sütun 519 px'e
   zorlanıyor, taşan kısım kırpılıyordu: müşteri "TOPLU ETİKE…" diye
   yarım kalan düğmeyi ve kaydıramadığı bir alanı görüyordu. Düğme
   genişliğini elle kısmak yerine çubuğun sarılmasına izin veriliyor —
   yarın beşinci düğme eklenirse de kendiliğinden alt satıra iner. */
@media (max-width: 900px) {
  .workflow-column { min-width: 0; }
  .workflow-table table { max-width: 100%; }

  .toplu-teslim-bar { flex-wrap: wrap; }
  .toplu-teslim-bar > span { flex: 1 1 100%; }
  .toplu-teslim-bar button { flex: 1 1 auto; min-width: 0; }

  /* Başlık satırındaki kutucuk etiketsizdi: ekranda ne olduğu
     anlaşılmayan boş gri bir kutu duruyordu. Kutucuk toplu sevkiyat
     için gerekli, o yüzden kaldırılmadı — adı yazıldı. */
  .sec-tumu label {
    display: inline;
    margin-left: var(--s2);
    font-size: 12px;
    letter-spacing: .04em;
    color: var(--ink-2);
    cursor: pointer;
  }
  .workflow-table thead th:first-child {
    display: flex;
    align-items: center;
  }
}

/* PENCERE İÇERİĞİ KAYMALI — YOKSA KAYDET DÜĞMESİNE ULAŞILAMIYOR.

   ÖLÇÜM: Telefonda Müşteri Kartı penceresi 899 px, içindeki form
   1338 px. Pencerede `overflow:hidden` var (başlık bandı sabit kalsın
   diye, doğru); ama kayacak bir iç bölüm tanımlı olmadığı için taşan
   439 px kırpılıyordu. Kırpılan bölgede Açıklama alanı, İPTAL ve
   KAYDET düğmesi vardı: telefondan müşteri kaydedilemiyordu.

   NEDEN `dialog[open] > form`, PENCERE ADI LİSTESİ DEĞİL: Var olan
   kuralda tam bu kusur için yazılmış bir istisna zaten vardı, ama
   yalnızca `(max-height: 560px)` için — yani yatay tutulan telefon
   için. Dikey tutulan telefon listeye girmemişti. Pencere adı saymak
   yerine kural yazılıyor: hangi pencere olursa olsun, içeriği
   sığmıyorsa kayar. Yeni pencere eklendiğinde listeye yazmayı unutma
   riski kalmıyor.

   `min-height: 0` ŞART: Esnek öğelerin varsayılanı `min-height:auto`;
   bu, öğenin içeriğinden kısalmasını engeller ve `overflow-y:auto`
   hiçbir işe yaramaz. Kaydırma bu satır olmadan çalışmaz.

   Yapışkan başlık bozulmaz: kaydırma kabı artık form olduğu için
   `position:sticky` başlıklar formun tepesine yapışmaya devam eder. */
@media (max-width: 900px) {
  dialog[open] > form {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
  }
}

/* Rol kartında ekran izinlerinden sonra gelen ek işlem yetkileri başlığı. */
.izin-islem-baslik {
  margin: var(--s3) 0 var(--s2);
  font-size: 12px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-2);
}

/* YÖNETİCİ ÖZEL DENETİMLER — GİZLEME KURALI CSS'TE.

   NEDEN JS DEĞİL: `uygulaIslemIzinleri()` yalnızca çağrıldığı anda
   çalışır. Yönetici özel düğmelerin çoğu satır içinde SONRADAN üretiliyor
   (tablo satırları, pencere içerikleri). Her render'ın sonuna çağrı
   eklemek gerekirdi ve unutulan tek çağrı, düğmeyi sessizce herkese
   açardı — "listeye eklemeyi unutma" tuzağının aynısı.

   CSS kuralı öğe ne zaman doğarsa doğsun geçerlidir: gövdede
   `rol-yonetici` sınıfı yoksa `data-izin="yonetici"` taşıyan her öğe
   gizlidir. Tek koşul, tek yer.

   BU GİZLEME GÜVENLİK DEĞİLDİR: asıl kapı sunucuda (app/yetki.py).
   Buradaki iş, basınca 403 verecek düğmeyi hiç göstermemek. */
body:not(.rol-yonetici) [data-izin="yonetici"] { display: none !important; }

/* Ölçü kaydı şeridi: iki ölçü kartının ALTINDA, tam genişlikte.
   Yatayda yayılır ki dört blok alt alta uzayıp yer kaplamasın. */
.olcu-kaydi-serit {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2) var(--s4);
}
.olcu-kaydi-serit > label:first-child { flex: 1 1 240px; }
.olcu-kaydi-serit > #measurementAudit,
.olcu-kaydi-serit > #barLength { flex: 1 1 240px; margin: 0; }

/* AYARLARDA HENÜZ UYGULANMAYAN ANAHTARLAR
   Bu anahtarlar kaydediliyor ve geri okunuyordu ama hiçbir davranışı
   değiştirmiyordu; yönetici var olmayan bir korumayı açık görüyordu.
   Sessizce kaldırmak yerine NE OLDUĞU yazılıyor: değer korunuyor, ama
   anahtarın şu an bir etkisi olmadığı ekranda görünüyor. */
.settings-switch.settings-pasif { opacity: .72; cursor: default; }
.settings-not {
  font-size: .78em; font-weight: 600; letter-spacing: .02em;
  color: var(--muted, #6b7280);
  border: 1px solid var(--line, #d8dbe0);
  border-radius: 999px; padding: .1em .6em; margin-left: .35em;
  white-space: nowrap;
}

/* MÜŞTERİ ARAMA KUTUSU (iş emri)
   Açılır listenin ÜSTÜNDE duran süzgeç. Etiketin içinde iki öğe var
   (input + select); ikisi de tam genişlik alsın ve arada boşluk kalsın. */
.secim-arama {
  margin-bottom: var(--s2, .4rem);
  font-size: .92em;
}

/* OTURUM DÜŞTÜ UYARISI (giriş ekranı)
   Sessizce boş kalan ekran yerine sebebi yazan şerit. */
.login-error {
  margin: var(--s2, .5rem) 0 0;
  padding: .6em .9em;
  border-radius: .6em;
  background: #fdecea;
  color: #8a1c12;
  border: 1px solid #f3b8b1;
  font-size: .9em;
  line-height: 1.35;
}
@media (prefers-color-scheme: dark) {
  .login-error { background: #3a1512; color: #ffd7d1; border-color: #7d2e26; }
}

/* İŞ KARTI ÖZET ŞERİDİNDE AŞAMA + İLERLETME DÜĞMESİ
   Grafik aşaması eklenmişti ama tamamlama düğmesi yoktu; kullanıcı
   "nasıl geçeceğiz?" diye sordu. Aşama artık kartın üstünde yazıyor ve
   ilerletme düğmesi tam yanında. */
.job-summary-stage {
  display: flex;
  flex-direction: column;
  gap: .25rem;
  align-items: flex-start;
}
.job-summary-stage button {
  margin-top: .15rem;
  padding: .35em .8em;
  font-size: .82em;
  white-space: nowrap;
}
@media (max-width: 720px) {
  .job-summary-stage { width: 100%; }
  .job-summary-stage button { width: 100%; }
}

/* ŞERİTTE GİZLENECEK HÜCRE.
   İş emri listesinde ilk sütun veritabanı KİMLİĞİ ("258"). Masaüstünde
   sıralama için işe yarıyor ama telefonda satırın başında durup asıl
   kimliği (iş numarasını) gölgeliyor — kullanıcının örnek gösterdiği
   müşteri listesi de doğrudan kod + firma ile başlıyor.

   Sütun SIRASINA göre değil SINIFA göre gizleniyor: `td:first-child`
   yazsaydım sütun sırası değişince yanlış hücre kaybolurdu ve kimse
   fark etmezdi. */
@media (max-width: 900px) {
  .serit-tablo td.serit-gizli,
  .serit-tablo th.serit-gizli { display: none; }
}

/* ÖLÇÜ BEKLEYEN İŞLER — arama kutusu + yenile düğmesi.
   Panel başlığının sağında yan yana dururlar; dar ekranda alt alta
   geçip tam genişlik alırlar (düğme parmakla basılabilir kalsın). */
.olcu-arac-cubugu {
  display: flex;
  gap: var(--s2, .5rem);
  align-items: center;
  flex-wrap: wrap;
}
/* ÖLÇÜ SÜZGECİ — etiket ve kutu TEK PARÇA: "Ölçü" yazısı dar ekranda
   seçim kutusundan kopup alt satıra düşmesin. Kural medya sorgusunun
   DIŞINDA, yani her genişlikte geçerli. */
.olcu-suzgec-etiketi {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-size: .92em;
  white-space: nowrap;
}
.olcu-arac-cubugu input {
  min-width: 15rem;
  font-size: .92em;
}
@media (max-width: 720px) {
  .olcu-arac-cubugu { width: 100%; }
  .olcu-arac-cubugu input,
  .olcu-arac-cubugu .olcu-suzgec-etiketi,
  .olcu-arac-cubugu button { flex: 1 1 100%; }
}

/* AKILLI HESAPLAMA — hesap yapılamadı uyarısı.
   Boşken hiç yer kaplamaz; yalnızca sebep yazılınca görünür. */
.hesap-uyari:empty { display: none; }
.hesap-uyari {
  margin-top: var(--s2, .5rem);
  padding: .5em .75em;
  border-radius: .5em;
  background: #fdecea;
  color: #8a1c12;
  border: 1px solid #f3b8b1;
  font-size: .88em;
  line-height: 1.35;
}
@media (prefers-color-scheme: dark) {
  .hesap-uyari { background: #3a1512; color: #ffd7d1; border-color: #7d2e26; }
}

/* MÜŞTERİ SEÇİCİ — tek kutu (yaz, altta çıkan listeden seç).
   `select` gizleniyor ama DOM'da duruyor: formu okuyan kodun tamamı
   onun üzerinden çalışıyor, kaldırmak zincirin her halkasını
   değiştirmek demekti. */
.gizli-alan { display: none !important; }
/* `.aramali-secim` bu kuralı PAYLAŞIYOR, ikinci bir kopyası yazılmadı:
   25-aramali-secim.js'in kurduğu sarmal da açılır listeyi konumlandıran
   `position: relative` bağlamına ihtiyaç duyuyor. Sınıfın ayrı adı var
   çünkü fabrika artık yalnızca müşteri değil, sekiz cari kutusunu ve
   stok/personel listelerini de kuracak — "musteri-secici" adı orada
   yanıltıcı olurdu. */
.musteri-secici,
.aramali-secim { position: relative; }
.secim-listesi {
  position: absolute;
  z-index: 40;
  left: 0; right: 0;
  top: 100%;
  max-height: 15rem;
  overflow-y: auto;
  background: var(--card, #fff);
  border: 1px solid var(--line, #d8dbe0);
  border-radius: .5em;
  box-shadow: 0 8px 24px rgba(0,0,0,.12);
}
.secim-listesi button {
  display: block;
  width: 100%;
  text-align: left;
  padding: .55em .8em;
  border: 0;
  border-radius: 0;
  background: transparent;
  font-size: .95em;
  cursor: pointer;
}
.secim-listesi button:hover,
.secim-listesi button.secili { background: var(--hover, #eef2ff); }
.secim-listesi .secim-kod { color: var(--ink-3, #6b7280); margin-right: .5em; }
/* `.secim-not` (kırpma bildirimi) `.secim-bos` ile AYNI görünümü alıyor —
   ikisi de listenin içindeki "satır değil, açıklama" satırı. Ayrı bir
   kural yazmak, biri değişince ötekinin geride kalması demekti. */
.secim-listesi .secim-bos,
.secim-listesi .secim-not { padding: .6em .8em; color: var(--ink-3, #6b7280); }

/* === ARAMALI SEÇİM KUTUSU — BAŞLANGIÇ (25-aramali-secim.js) ===
   Kullanıcı isteği: "dropdown menülerde tek tek satır satır aramak zorunda
   kalıyoruz ... ilk 3 harfini felan yazsak".
   Bu blok YENİ HEX RENK GETİRMEZ; yalnızca mevcut belirteçleri kullanır.
   Görünümün tamamı zaten yukarıdaki `.secim-listesi` ailesinden geliyor;
   burada yalnızca fabrikanın eklediği kutu ve KLAVYE/DOKUNMA farkları var. */

/* Arama kutusu, gizlenen <select>'in yerini alıyor: aynı genişlikte
   durmazsa form ızgarasında sütun daralır ve yanındaki alan kayar. */
.aramali-secim .secim-arama-kutusu { width: 100%; }

/* KLAVYE VURGUSU FAREYLE AYNI GÖRÜNMESİN.
   `.secili` ile `:hover` aynı arka planı paylaşıyor (yukarıda). Fare
   listenin üstünden geçerken ok tuşuyla seçilmiş satır KAYBOLUYOR gibi
   görünüyordu — kullanıcı hangi satırda olduğunu bilemeden Enter'a
   basardı. Sol kenardaki şerit yalnızca klavye vurgusunda çıkıyor.
   Yeni renk yok: mevcut etkileşim rengi (--m). */
.secim-listesi button.secili { box-shadow: inset 3px 0 0 var(--m); }

/* MOBİL (5. kural).
   Liste satırı masaüstünde ~34px; parmakla basılabilir en küçük hedef bu
   depoda `--tap` (44px) olarak sabit ve diğer ekranlarda da bu kullanılıyor.
   Ayrıca listenin yüksekliği `vh` ile sınırlanıyor: telefonda ekranın
   yarısını klavye kaplıyor, 15rem'lik sabit yükseklik klavyenin ALTINA
   taşıyor ve seçilecek satırlar görünmez oluyordu. */
@media (max-width: 900px) {
  .secim-listesi { max-height: 45vh; }
  .secim-listesi button { min-height: var(--tap); }
}
/* === ARAMALI SEÇİM KUTUSU — BİTİŞ === */

/* === CANLI SAAT VE DÖVİZ KURU (REVİZE md.6) ===
   Hero satırının sağ öbeği: CANLI rozeti + saat. Kur şeridi hero'nun
   ALTINDA, istatistik kartlarının üstünde. İkisi de yeni renk
   getirmiyor; mevcut belirteçlerle kuruldu. */
.dash-live-strip{
  margin-left:auto;
  display:flex;
  align-items:center;
  gap:var(--s3);
  flex-wrap:wrap;
}
.dash-live-strip .management-live{margin-left:0}

.dash-clock{
  display:flex;
  flex-direction:column;
  align-items:flex-end;
  line-height:1.15;
}
.dash-clock b{
  font-family:var(--mono);
  /* SABİT GENİŞLİKLİ RAKAM: saniye ilerlerken sayı genişliği değişirse
     saat her tikte sağa sola oynar — "hareketli saat" istendi, titreyen
     saat değil. */
  font-variant-numeric:tabular-nums;
  font-size:22px;
  font-weight:600;
  letter-spacing:.02em;
  color:var(--ink);
}
.dash-clock span{
  font-size:11px;
  color:var(--ink-3);
  letter-spacing:.02em;
}

.dash-rates{
  display:flex;
  align-items:center;
  flex-wrap:wrap;
  gap:var(--s2);
  margin-bottom:var(--s4);
}
.dash-rate{
  display:inline-flex;
  align-items:baseline;
  gap:var(--s2);
  padding:var(--s2) var(--s3);
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--r1);
}
.dash-rate-para{
  font-size:11px;
  font-weight:650;
  letter-spacing:.06em;
  color:var(--ink-3);
}
.dash-rate b{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:15px;
  font-weight:600;
  color:var(--ink);
}
.dash-rate-kaynak{
  font-size:11px;
  color:var(--ink-3);
  letter-spacing:.02em;
}

/* Akıllı Hesaplama'daki kur ipucu. Kutunun ALTINDA duruyor: yanına
   koymak dar ekranda etiketi ikinci satıra itiyordu. */
/* Kur ipucu artık ızgaranın kendi satırı (tam genişlik). Kutunun
   içindeyken `align-items:end` yüzünden o kutuyu yukarı itiyor ve
   hizayı bozuyordu — müşteri bunu işaretledi (15.08 Y5). */
.calc-rate-hint{
  grid-column:1 / -1;
  display:block;
  font-size:11px;
  color:var(--ink-3);
  min-height:14px;   /* metin gelince düzen zıplamasın */
}

@media (max-width:640px){
  .dash-live-strip{margin-left:0;width:100%;justify-content:space-between}
  .dash-clock{align-items:flex-start}
  .dash-clock b{font-size:19px}
}

/* === BEKLEME GÖSTERGESİ (REVİZE md.7) ===
   Halka döner, logo sabit durur. Katman TIKLAMAYI ENGELLEMEZ
   (`pointer-events:none`): istek asılı kalırsa kullanıcı ekrana
   kilitlenmemeli. z-index dialog katmanının (9999) üstünde. */
.gold-bekleme{
  position:fixed;
  inset:0;
  z-index:10000;
  display:flex;
  align-items:center;
  justify-content:center;
  pointer-events:none;
  background:rgba(18,18,22,.14);
}
.gold-bekleme[hidden]{display:none}

.gold-bekleme-kart{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:var(--s3);
  padding:var(--s5) var(--s6);
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r3);
  box-shadow:var(--sh3);
}
.gold-bekleme-kart span{
  font-size:11px;
  font-weight:650;
  letter-spacing:.12em;
  color:var(--ink-3);
}

.gold-bekleme-halka{
  position:relative;
  width:96px;
  height:96px;
  border-radius:50%;
  /* Halkanın kendisi: üç kenarı silik, biri marka rengi. Dönerken
     tek renkli bir yay görünür — klasik ve okunur. */
  border:3px solid var(--line-2);
  border-top-color:var(--m);
  animation:gold-bekleme-don .9s linear infinite;
}
.gold-bekleme-halka img{
  position:absolute;
  /* Logo halkanın İÇİNDE ve dönmüyor: `animation` yalnızca halkada.
     Ortalama `inset+margin:auto` ile yapılıyor, `transform` ile
     değil — transform kullansaydım halkanın dönüşünü devralırdı. */
  inset:16px;
  width:auto;
  height:auto;
  /* Amblem DİKEY (303x500): yüksekliği sınırlamak yeterli, genişlik
     kendiliğinden dairenin içinde kalıyor. */
  max-width:calc(100% - 32px);
  max-height:calc(100% - 32px);
  margin:auto;
  object-fit:contain;
}

@keyframes gold-bekleme-don{ to{ transform:rotate(360deg) } }

/* Hareket duyarlılığı: dönme yerine yumuşak nefes. Göstergenin
   "çalışıyor" mesajı korunuyor, baş döndürücü kısmı kalkıyor. */
@media (prefers-reduced-motion:reduce){
  .gold-bekleme-halka{
    animation:gold-bekleme-nabiz 1.6s ease-in-out infinite;
    border-top-color:var(--line-2);
  }
  @keyframes gold-bekleme-nabiz{
    0%,100%{ opacity:1 }
    50%{ opacity:.45 }
  }
}

/* === İŞ AKIŞI PENCERESİNDE İŞ GÖRSELİ (REVİZE md.8) ===
   Başlık şeridinin sağında, kapatma düğmesinin solunda küçük bir
   önizleme; tıklanınca büyük hâli açılıyor. */
.tracking-workflow-image{
  flex:0 0 auto;
  width:56px;
  height:56px;
  padding:0;
  border:1px solid var(--line);
  border-radius:var(--r1);
  overflow:hidden;
  background:var(--surface);
  cursor:zoom-in;
}
.tracking-workflow-image.hidden{display:none}
.tracking-workflow-image img{
  width:100%;
  height:100%;
  /* `cover`: küçük karede işin ne olduğu anlaşılsın diye kadraj dolu
     tutuluyor; tam hâli zaten tıklayınca açılıyor. */
  object-fit:cover;
}
.tracking-workflow-image:hover{border-color:var(--m)}
.tracking-workflow-image:focus-visible{
  outline:2px solid var(--m);
  outline-offset:2px;
}

/* Sevkiyat tablosundaki sevk yeri seçici (REVİZE md.9). Tablo içinde
   durduğu için normal form kutusundan daha alçak; satır yüksekliğini
   büyütmemesi gerekiyor. */
.sevk-yeri-kutusu{
  width:100%;
  min-width:96px;
  padding:2px var(--s2);
  font-size:12px;
  border:1px solid var(--line);
  border-radius:var(--r1);
  background:var(--surface);
}
.sevk-yeri-kutusu:disabled{opacity:.55}

/* Sevkiyat araç şeridindeki gün seçici (REVİZE md.10/md.11). Etiket ve
   liste düğmelerinin ikisi de bu tarihi kullanıyor. */
.sevk-gun-alani{
  display:inline-flex;
  align-items:center;
  gap:var(--s2);
  font-size:11px;
  font-weight:650;
  letter-spacing:.06em;
  color:var(--ink-3);
}
/* `select` DE BURADA: satış fişi firma seçicisi aynı şeritte, aynı
   etikete sarılı duruyor. Ayrı bir kural yazsaydım iki kutu yan yana
   farklı yükseklikte görünürdü. `input` genişliği araç çubuğunun
   `flex:1 1 260px` kuralından geliyor; `select` o kuralın kapsamında
   olmadığı için içeriği kadar dar kalır — istenen de bu. */
.sevk-gun-alani input,
.sevk-gun-alani select{
  padding:var(--s1) var(--s2);
  border:1px solid var(--line);
  border-radius:var(--r1);
  background:var(--surface);
  font-size:12px;
  color:var(--ink);
}
.sevk-gun-alani select{max-width:220px}

/* === SATIŞ FİŞİ ==========================================================
   Şerit (teslimden sonra) ve pencere. Özet ızgarası ile uyarı kutusu
   CARİ EKSTRE'den ödünç alınıyor (`.cari-ozet-serit`, `.cari-uyari`):
   ikisi de aynı işi yapıyor ve ikinci bir kopya, biri güncellenip diğeri
   kalınca aynı bilgiyi iki farklı biçimde gösterirdi.                    */
.satis-fisi-serit{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--s2);
  margin-top:var(--s3);
  padding:var(--s2) var(--s3);
  border:1px solid var(--line);
  border-left:3px solid var(--ok);
  border-radius:var(--r1);
  background:var(--ok-soft);
  font-size:12px;
  color:var(--ink);
}
/* Düğmeleri sağa iten esnek boşluk; `margin-left:auto` sarma olunca
   düğmeyi tek başına bir satıra atıyordu. */
.satis-fisi-serit-bosluk{flex:1 1 auto}

.satis-fisi-dialog[open]{width:min(920px,95vw)}
.satis-fisi-body{margin:var(--s4) var(--s4) 0;min-height:0}
.satis-fisi-tablo{max-height:42vh;overflow:auto}

/* === MUHASEBE SEKMELERİ (REVİZE s.2-s.5) ===
   İş emri kartındaki sekme şeridiyle aynı dili konuşuyor: alt çizgi
   seçili sekmeyi işaretliyor, kutu/çerçeve yok. */
.muhasebe-sekmeler{
  display:flex;
  gap:var(--s1);
  flex-wrap:wrap;
  margin-bottom:var(--s4);
  border-bottom:1px solid var(--line);
}
.muhasebe-sekmeler button{
  /* Zemin ve yuvarlaklık temel düğme stilinden geliyor (ölçüldü:
     rgb(255,255,255) / 4px). Burada AÇIKÇA yazılıyor ki görünüm miras
     kalan bir yan etki değil, seçilmiş olsun. */
  background:var(--surface);
  border-radius:var(--r1) var(--r1) 0 0;
  padding:var(--s3) var(--s4);
  /* Dokunma hedefi: sevkiyat/muhasebe ekranları tablette de kullanılıyor. */
  min-height:var(--tap);
  font-size:12px;
  font-weight:650;
  letter-spacing:.06em;
  color:var(--ink-3);
  border-bottom:2px solid transparent;
  margin-bottom:-1px;
  white-space:nowrap;
}
.muhasebe-sekmeler button:hover{color:var(--ink)}
.muhasebe-sekmeler button.active{
  color:var(--m);
  border-bottom-color:var(--m);
}
.muhasebe-sekmeler button:focus-visible{
  outline:2px solid var(--m);
  outline-offset:-2px;
}
.muhasebe-sekme-icerik.hidden{display:none}

/* Ölçü penceresindeki "asetat otomatik düşer" bilgisi. Onay kutusu
   kılığından çıkarıldı (bkz. index.html'deki gerekçe); komşu tiklerle
   aynı hizada dursun diye aynı kutu ölçüleri kullanılıyor. */
.production-material-note{
  display:flex;
  flex-direction:column;
  gap:2px;
  padding:var(--s2) var(--s3);
  background:var(--paper);
  border:1px dashed var(--line);
  border-radius:var(--r1);
}
.production-material-note b{font-size:12px;color:var(--ink)}
.production-material-note small{font-size:11px;color:var(--ink-3)}

/* İş emri kartındaki muhasebe bayrakları (REVİZE s.6) ve muhasebe
   ekranındaki BEDELSİZ rozeti. */
.job-flag{
  display:flex;
  align-items:flex-start;
  gap:var(--s2);
  padding:var(--s2) 0;
  cursor:pointer;
}
.job-flag input{margin-top:3px;flex:0 0 auto}
.job-flag b{display:block;font-size:13px;font-weight:600;color:var(--ink)}
.job-flag small{display:block;font-size:11px;color:var(--ink-3);line-height:1.35}

/* BEDELSİZ, "FİYAT YOK"tan AYRI renkte: ikisi de sıfır tutarı anlatıyor
   ama biri düzeltilmesi gereken bir eksik, diğeri alınmış bir karar.
   Aynı renkte olsalardı ayrım yalnızca metinde kalır, göz taramasında
   kaybolurdu. */
.accounting-free{
  display:inline-block;
  padding:1px var(--s2);
  border:1px solid var(--c);
  border-radius:var(--r1);
  background:var(--c-soft);
  color:var(--c);
  font-size:11px;
  font-weight:650;
  letter-spacing:.04em;
  white-space:nowrap;
}

/* === ÖLÇÜ PENCERESİ: ÖLÇÜ + FİYAT TEK EKRANDA (REVİZE s.6) ===
   Solda ölçüler (klişe / asetat yan yana), sağda birim fiyat ve tutar.
   Müşterinin taslağı bu düzen. */
.accounting-measure-wide[open]{width:min(1180px,96vw)}

.olcu-duzen{
  display:grid;
  /* ÜÇ SÜTUN (20.08 toparlama):  Ölçüler | Birim Fiyat | Tutar
     ESKİSİ: `minmax(0,1fr) 340px` — iki sütun. Sağ sütun 340px'e
     sıkıştığı için 1170px yüksekliğe uzuyor, sol sütun 534px kalıyor
     ve arada 636px BOŞLUK oluşuyordu. Kullanıcı "ortada devasa boşluk
     var" diye bildirdi; ekran görüntüsünde ölçüldü.

     Pencere 1098px geniş, yani yer VARDI — içerik iki sütuna
     sıkıştırıldığı için dikeye taşıyordu. Üçüncü sütun açılınca
     (canlı ölçüm): en uzun sütun 1170 -> 688px, sütunlar arası fark
     636 -> 154px, dikey kaydırma 662 -> 181px.

     Ölçü sütunu 2fr: Klişe ve Asetat kartları YAN YANA kalsın diye.
     1.35fr denendi, alt alta düştüler ve sol sütun 831px'e uzadı. */
  grid-template-columns:minmax(0,2fr) minmax(0,1fr) minmax(0,1fr);
  gap:var(--s4);
  align-items:start;
}
.olcu-olculer{min-width:0}
/* Tutar kendi sütununda; fiyat sütunuyla aynı iç düzeni paylaşıyor. */
.olcu-tutar{min-width:0;display:grid;gap:var(--s3);align-content:start}

.olcu-fiyat{
  display:grid;
  gap:var(--s3);
  min-width:0;
}
.olcu-fiyat .subcard{padding:var(--s3)}
.olcu-fiyat h4{
  margin:0 0 var(--s2);
  font-size:11px;
  font-weight:650;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.olcu-fiyat-grid{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:var(--s2);
}
.olcu-fiyat-grid label{
  display:flex;
  flex-direction:column;
  gap:2px;
  font-size:11px;
  color:var(--ink-3);
}
.olcu-fiyat-grid input,
.olcu-fiyat-grid select{
  padding:var(--s1) var(--s2);
  font-size:12px;
  border:1px solid var(--line);
  border-radius:var(--r1);
  background:var(--surface);
  color:var(--ink);
}
.olcu-fiyat-grid input[readonly]{background:var(--paper);color:var(--ink-2)}

/* DAR EKRAN: iki sütun alt alta. Fiyat bloğu ÖLÇÜLERİN ALTINA iniyor —
   üstte kalsaydı, asıl iş olan ölçü girişi ekranın dibine düşerdi. */
@media (max-width:1000px){
  .olcu-duzen{grid-template-columns:minmax(0,1fr)}
  .olcu-fiyat{order:2}
  .olcu-fiyat-grid{grid-template-columns:1fr 1fr}
}

/* "SON ÖLÇÜYÜ SİL" satırı — listenin altında, sağa yaslı. Satır başındaki
   "×" düğmeleri KALIYOR: onsuz yalnızca sondan geriye silinebilir, ortadaki
   bir satır düzeltilemezdi. */
.olcu-sil-satiri{
  display:flex;
  justify-content:flex-end;
  margin-top:var(--s2);
}
.olcu-sil-satiri button{
  padding:var(--s1) var(--s3);
  font-size:11px;
  font-weight:600;
  letter-spacing:.04em;
}

/* Rapor Merkezi'nde grafiker satırı tıklanabilir (15.08 revizesi Y1).
   İmleç ve vurgu olmadan tıklanabilirlik görünmezdi. */
.tiklanabilir-satir{cursor:pointer}
.tiklanabilir-satir:hover{background:var(--hover,#eef2ff)}

/* Arşivdeki işte Fiyat sekmesi hiç görünmez (15.08 revizesi Y7).
   `hidden` yerine ayrı sınıf: `data-izin` kuralı da aynı öğeye
   `display:none` uygulayabiliyor; ikisi tek sınıfa yığılsaydı biri
   diğerini geri açardı. */
#jobTabs button.arsivde-gizli{display:none !important}

/* === İŞ EMRİ KARTI SIKIŞTIRMA (15.08 revizesi Y3) ===
   "EKRAN HİÇ ALT ÜST SAĞ SOL OLMASIN, EKRANIN İÇİNDE BÜTÜN BİLGİLER OLSUN"

   Ölçüldü (1366×768): İş Bilgileri sekmesi 558 px içerik / 421 px alan.
   Aradaki 137 px dikey ritimden geliyor — alan sayısı değil, alanlar
   arası boşluk. Kurallar YALNIZCA `.job-dialog` içinde geçerli; diğer
   ekranların ferahlığı korunuyor. */
.job-dialog .subcard{padding:var(--s3)}
.job-dialog .subcard h3{margin-bottom:var(--s2);font-size:12px}
.job-dialog label{gap:2px}
.job-dialog .field-title{margin-top:var(--s2);margin-bottom:2px;font-size:11px}
.job-dialog input,
.job-dialog select,
.job-dialog textarea{padding:var(--s1) var(--s2);font-size:12px}
.job-dialog .inline-radio,
.job-dialog .vertical-radio{gap:var(--s1)}
.job-dialog .vertical-radio label,
.job-dialog .inline-radio label,
.job-dialog .checkline{min-height:26px;font-size:12px}
.job-dialog .embedded-card{padding:var(--s2);margin-top:var(--s2)}
.job-dialog .embedded-card h3{margin-bottom:var(--s1)}

/* Not alanı kartın kalanını doldursun: sabit yükseklikle hem yer
   harcıyor hem de uzun notta kaydırma gerektiriyordu. */
.job-dialog #jobNotes{min-height:88px;resize:vertical}

/* === İŞ AKIŞI PENCERESİ: GÖRSELE YER (15.08 revizesi Y6) ===
   "BU BURADA ÇOK KÜÇÜK OLMUŞ LA — ŞU KUTUCUĞUN BİRİNİ AŞAĞIYA ALSAK
    SAĞ TARAFA BİR YER YAPSAK DAHA İYİ OLMAZ MI"

   ÖZGÜLLÜK NOTU: görsel düğmesi `.dialog-head>button` kuralına
   yakalanıyordu (32×32 kapatma düğmesi ölçüsü) — 56 px yazdığım kural
   uygulanmıyordu, canlıda ölçüldü. Görsel artık başlıkta değil,
   gövdenin sağ sütununda; oradaki kural onu bağlamıyor. */
.archive-workflow-dialog[open]{width:min(1080px,96vw)}

.tracking-akis-duzen{
  display:grid;
  grid-template-columns:minmax(0,1fr) 260px;
  gap:var(--s4);
  align-items:start;
}
.tracking-akis-gorsel{
  display:block;
  width:100%;
  padding:0;
  border:1px solid var(--line);
  border-radius:var(--r2);
  overflow:hidden;
  background:var(--surface);
  cursor:zoom-in;
}
.tracking-akis-gorsel img{
  display:block;
  width:100%;
  height:auto;
  max-height:320px;
  object-fit:contain;
  background:var(--paper);
}
.tracking-akis-gorsel figcaption{
  padding:var(--s2);
  font-size:11px;
  color:var(--ink-3);
  text-align:center;
}
.tracking-akis-gorsel:hover{border-color:var(--m)}
.tracking-akis-gorsel:focus-visible{outline:2px solid var(--m);outline-offset:2px}
.tracking-akis-gorsel.hidden{display:none}

@media (max-width:900px){
  .tracking-akis-duzen{grid-template-columns:minmax(0,1fr)}
  .tracking-akis-gorsel img{max-height:220px}
}

/* İş Bilgileri sekmesi İKİ SÜTUN: solda tek kart, sağda iki kart (m04).
   Üst ızgara da ikiye iniyor; üç sütunluk kural kalsaydı üçüncü sütun
   boş kalır ve kartlar gereksiz daralırdı. */
.job-dialog #tab-info .job-info-grid{grid-template-columns:1fr 1fr}
/* SAĞ YIĞIN GERÇEK BİR IZGARA — `display:contents` DEĞİL (m04).

   `contents` sarmalayıcıyı düzenden ÇIKARIR: "Öncelik ve Açıklama" ile

   "Baskı Renkleri" üst ızgaranın doğrudan çocuğu olur ve İKİ sütunlu

   ızgarada renk kartı üçüncü hücreye, yani SOL sütuna — "Temel İş

   Bilgileri"nin altına — düşer. Müşterinin istediği yer notun ALTI.

   Sarmalayıcı kendi ızgarası kalınca iki kart sağda alt alta diziliyor.

   (pointer:fine) bloğundaki `.job-dialog .job-info-right{display:contents}`

   duruyor; bu satır kimlik seçicisi taşıdığı için onu yener. */

.job-dialog #tab-info .job-info-right{display:grid}

/* İŞ BİLGİLERİ KARTLARI İKİ SÜTUN (15.08 revizesi Y3).
   Ölçüldü: "Temel İş Bilgileri" kartında 6 alan ALT ALTA, her biri
   52 px = 312 px. Kart 422 px geniş; yatay yer boşa gidiyordu. İki
   sütunda aynı alanlar 3 satıra iniyor.

   Müşterinin gösterdiği örnek (AKINSOFT cari kartı) da bu düzen:
   "küçük açılacak bir ekranda bütün bilgiler olsa süper olacak".

   TAM GENİŞLİK İSTEYENLER ayrıca sayılıyor — başlık, alan başlıkları,
   radyo grupları, ölçü bloğu ve not alanı ikiye bölünürse okunmaz. */
.job-dialog #tab-info .subcard{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:var(--s2) var(--s3);
  align-content:start;
}
.job-dialog #tab-info .subcard > h3,
.job-dialog #tab-info .subcard > .field-title,
.job-dialog #tab-info .subcard > .dimension-block,
.job-dialog #tab-info .subcard > .embedded-card,
.job-dialog #tab-info .subcard > .inline-radio,
.job-dialog #tab-info .subcard > .vertical-radio,
.job-dialog #tab-info .subcard > .radio-grid,
.job-dialog #tab-info .subcard > .musteri-secici,
.job-dialog #tab-info .subcard > textarea,
.job-dialog #tab-info .subcard > p,
.job-dialog #tab-info .subcard > .checkline,
.job-dialog #tab-info .subcard > div{grid-column:1 / -1}

/* Not alanı iki sütunlu ızgarada da tam genişlik ve esnek kalsın. */
.job-dialog #tab-info .subcard > label:has(textarea){grid-column:1 / -1}

@media (max-width:900px){
  .job-dialog #tab-info .subcard{grid-template-columns:1fr}
}

/* KLİŞE VE MONTAJ SEKMESİ DE İKİ SÜTUN (15.08 revizesi Y3).
   Renk kartını buraya taşıyınca taşma bu sekmeye geçti — ölçüldü:
   1366×768'de 136 px. Sorunu taşımak çözmek değil; aynı sıkıştırma
   burada da uygulanıyor.

   Ölçüm: "Klişe / Baskı Bilgileri" kartı 738 px GENİŞ ama alanları alt
   alta, iç yüksekliği 579 px. Yatay yer boşa gidiyordu. */
.job-dialog #tab-plate .subcard{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:var(--s2) var(--s3);
  align-content:start;
}
.job-dialog #tab-plate .subcard > h3,
.job-dialog #tab-plate .subcard > .section-head,
.job-dialog #tab-plate .subcard > .radio-grid,
.job-dialog #tab-plate .subcard > .color-list,
.job-dialog #tab-plate .subcard > .embedded-card,
.job-dialog #tab-plate .subcard > p,
.job-dialog #tab-plate .subcard > textarea{grid-column:1 / -1}

/* SEVK YERİ YAN YANA. Dört seçenek alt alta 4×26 px yer kaplıyordu;
   yan yana tek satıra iniyor. Etiketler kısa (İşletme/Kargo/Otobüs/
   Elden), sarmalama riski yok. */
.job-dialog #tab-plate .vertical-radio{
  display:flex;
  flex-wrap:wrap;
  gap:var(--s1) var(--s3);
}

/* Renk kartı listesi kartın kalanını doldursun; sabit yükseklik hem yer
   harcıyor hem uzun renk listesinde ikinci bir kaydırma doğuruyordu. */
.job-dialog #tab-info .colors-card{align-content:start}
/* ÖLÜ KURAL SİLİNDİ (v2.78.1):
       .job-dialog #tab-plate .color-list{max-height:150px;overflow:auto}
   Bu benim işe yaramayan ilk denememdi. `.color-list` tabanında
   `min-height:280px` var ve CSS'te min, max'ı YENER — kural dosyada
   duruyordu, canlıda hiçbir şey değişmiyordu. Sonradan min ile birlikte
   doğrusu yazıldı (aşağıda), ama bu satır silinmeden kaldı ve "burada
   bir sınır var" izlenimi veriyordu. Kaydırma izni aşağıdaki kuralda. */

/* KARTLAR İÇERİĞİNE GÖRE BOYUTLANSIN (15.08 revizesi Y3).
   ÖLÇÜLDÜ: dış ızgara 4 kartı 2×2 satıra bölüp her satıra eşit yer
   veriyordu — "Klişe / Baskı Bilgileri" kartına 210 px düşüyor ama
   içeriği 564 px. Kart KENDİ İÇİNDE kırpılıyordu; sekme kaydırılsa
   bile o içerik açılmıyordu, çünkü taşma kartın içindeydi.

   `align-items:start` + `min-height:auto`: kart içeriği kadar uzuyor,
   taşma varsa SEKME kayıyor (o artık `overflow-y:auto`). Kırpılan
   hiçbir alan kalmıyor. */
.job-dialog #tab-plate .plate-montage-grid,
.job-dialog #tab-info .job-info-grid{align-items:start}
.job-dialog #tab-plate .plate-montage-grid > *,
.job-dialog #tab-info .job-info-grid > *{min-height:auto}
.job-dialog #tab-plate .subcard,
.job-dialog #tab-info .subcard{overflow:visible}

/* RENK LİSTESİ BOŞKEN 280 PX YER KAPLIYORDU (15.08 Y3; kart m04'te

   İş Bilgileri sekmesine dönünce bu kural da onunla taşındı).
   Temel kuralda `min-height:280px` var ve CSS'te `min`, `max`ı YENER —
   bu yüzden yukarıda yazdığım `max-height:150px` hiçbir işe yaramamıştı
   (canlıda ölçüldü: boş liste 280 px). `min-height` de burada
   düşürülüyor; liste dolduğunda kendi kaydırması var. */
.job-dialog #tab-info .color-list{
  min-height:96px;
  max-height:190px;
}

/* Muhasebe bayrakları kartı iki onay kutusu için 155 px kaplıyordu.
   Açıklama satırları iş emri kartında kısaltılıyor — kutunun ne
   yaptığı başlıkta zaten yazılı. */
.job-dialog .job-flag{padding:var(--s1) 0}
.job-dialog .job-flag small{font-size:10px;line-height:1.25}
.job-dialog .embedded-card .job-flag b{font-size:12px}


/* =====================================================================
   KAP SORGUSU — SUTUN OYNCELIGI  (16.08)
   =====================================================================
   MUSTERI: "kaydirma asagi kabul edilebilir ama yana kaydirma kabul
   edilemez".

   NIYE @container, NIYE @media DEGIL
       Once ekran genisligine gore kademe yazdim; dort tablo tasmaya
       devam etti. Hepsi dar panelin icindeydi: Stok Hareketleri'nin
       kabi 1366px ekranda bile 334px, Sevkiyat'inki 482px. Ekrana
       bakan bir sorgu bu tablolara asla "dar" demiyor. Kap sorgusunda
       olcut tablonun KENDI genisligi; ayni kural hem tam genislikteki
       Is Emirleri'ne hem yan paneldeki Stok Hareketleri'ne dogru
       davraniyor.

   NIYE display:none, NIYE DOM'DAN SILME
       styles.css'te 20'den fazla `td:nth-child(n)` kurali var (mono
       yazi tipi, saga yaslama, sticky sutun) ve JS'te `colspan`
       sayilari. `display:none` ogeyi DOM'da BIRAKIR, bu yuzden
       nth-child ve colspan dogru kalir. Sutunu DOM'dan silseydim
       hepsi bir sutun kayardi ve kimse fark etmezdi.

   GIZLENMEYENLER — bilerek
       Arsiv "Dosyalar" (dugmeler), Sevkiyat "Sevk Yeri" (secici) ve
       toplu secim kutusu gizlenmiyor. Onlari gizlemek yatay kaydirmayi
       bitirir ama ozelligi ULASILAMAZ yapar: sorunu cozmek degil, yer
       degistirmek olurdu.

   901px ALTINDA DEVREDE DEGIL
       O esikte `.serit-tablo`/`.workflow-table` zaten satirlari alt
       alta seren kart duzenine geciyor; orada yatayda kazanilacak
       butce yok, buna karsilik telefonda okunsun diye `data-etiket`
       verilmis hucreleri silmis olurdum.

   @media screen — KAGIDA TUM SUTUNLAR BASILIR.
   ===================================================================== */
.table,
.stock-table-wrap,
.stock-movement-wrap,
.personnel-table-wrap,
.accounting-table-wrap,
.reports-table-wrap,
.workflow-table{
  container-type:inline-size;
  container-name:tbl;
}

@media screen and (min-width:901px){

  /* --- 1. kademe: kap 1000px alti — kimlik/denetim sutunlari --- */
  @container tbl (max-width:1000px){
    #tblJobs th:nth-child(1),      #tblJobs td:nth-child(1),        /* ID (Is No zaten var) */
    #tblTracking th:nth-child(6),  #tblTracking td:nth-child(6),    /* Son Hareket */
    #tblTracking th:nth-child(7),  #tblTracking td:nth-child(7),    /* Son Islem Yapan */
    #tblQuality th:nth-child(1),   #tblQuality td:nth-child(1),     /* ID */
    #tblQuality th:nth-child(6),   #tblQuality td:nth-child(6),     /* Son Islem */
    #tblArchive th:nth-child(6),   #tblArchive td:nth-child(6),     /* Teslim Eden */
    #tblArchive th:nth-child(7),   #tblArchive td:nth-child(7),     /* Teslim Alan */
    #tblPersonnel th:nth-child(6), #tblPersonnel td:nth-child(6),   /* Telefon */
    #tblPersonnel th:nth-child(7), #tblPersonnel td:nth-child(7),   /* E-posta */
    #tblReports th:nth-child(4),   #tblReports td:nth-child(4),     /* Tarih */
    #tblReports th:nth-child(11),  #tblReports td:nth-child(11),    /* Revizyon */
    #tblReports th:nth-child(12),  #tblReports td:nth-child(12),    /* Teslim */
    #tblProdActive th:nth-child(4),#tblProdActive td:nth-child(4),  /* Kabul Eden */
    #tblProdReady th:nth-child(4), #tblProdReady td:nth-child(4),   /* Termin */
    #tblShipReady th:nth-child(6), #tblShipReady td:nth-child(6),   /* Termin */
    #tblShipRoute th:nth-child(6), #tblShipRoute td:nth-child(6),   /* Dagitima Cikaran */
    #tblStockMove th:nth-child(5), #tblStockMove td:nth-child(5){   /* Kalan */
      display:none;
    }
  }

  /* --- 2. kademe: kap 780px alti --- */
  @container tbl (max-width:780px){
    #tblJobs th:nth-child(5),      #tblJobs td:nth-child(5),        /* Grafiker */
    #tblJobs th:nth-child(6),      #tblJobs td:nth-child(6),        /* Klise */
    #tblTracking th:nth-child(4),  #tblTracking td:nth-child(4),    /* Grafiker */
    #tblQuality th:nth-child(8),   #tblQuality td:nth-child(8),     /* Oncelik */
    #tblArchive th:nth-child(4),   #tblArchive td:nth-child(4),     /* Grafiker */
    #tblPersonnel th:nth-child(5), #tblPersonnel td:nth-child(5),   /* Gorev */
    #tblReports th:nth-child(5),   #tblReports td:nth-child(5),     /* Grafiker */
    #tblReports th:nth-child(7),   #tblReports td:nth-child(7),     /* Tur */
    #tblStockMove th:nth-child(2), #tblStockMove td:nth-child(2){   /* Islem */
      display:none;
    }
  }

  /* --- Uretim ekraninin iki tablosu (v2.78.1) ---
     Ilk listede kimlikleri YOKTU: veri gelince tasabilirlerdi ve
     kural yazacak tutamak da bulunmuyordu. Bugun sigiyorlar (sahte
     satirla olculdu) ama sutun eklenirse sessizce tasarlardi. */
  @container tbl (max-width:520px){
    #tblFire th:nth-child(2), #tblFire td:nth-child(2),        /* Ham */
    #tblRawPlate th:nth-child(6), #tblRawPlate td:nth-child(6){ /* Personel */
      display:none;
    }
  }

  /* --- 3. kademe: kap 560px alti (yan paneller) --- */
  @container tbl (max-width:560px){
    #tblJobs th:nth-child(7),      #tblJobs td:nth-child(7),        /* Oncelik */
    #tblArchive th:nth-child(5),   #tblArchive td:nth-child(5),     /* Teslim Tarihi */
    #tblPersonnel th:nth-child(3), #tblPersonnel td:nth-child(3),   /* Ana Departman */
    #tblPersonnel th:nth-child(4), #tblPersonnel td:nth-child(4),   /* Yetkiler */
    #tblReports th:nth-child(6),   #tblReports td:nth-child(6),     /* Kalinlik */
    #tblReports th:nth-child(8),   #tblReports td:nth-child(8),     /* Parca */
    #tblReports th:nth-child(10),  #tblReports td:nth-child(10),    /* Asetat cm2 */
    #tblStockMove th:nth-child(6), #tblStockMove td:nth-child(6){   /* Is No */
      display:none;
    }
  }
}


/* =====================================================================
   YATAY KAYDIRMA — SON UC KAYNAK  (16.08, v2.77.1)
   =====================================================================
   v2.77.0 dagitildiktan SONRA canlida olculen artiklar. Ucu de
   "sutunlar sarabilsin" kuralinin ISTISNASI oldugu icin kaldi.
   ===================================================================== */

/* 1) ROZETLER
   `.status-pill` ve kardeslerinde `white-space:nowrap` var. "MUSTERI
   ONAYI BEKLIYOR" rozeti tek basina Durum sutununu 175px'e cikariyordu
   (Anasayfa, 950px). Rozet SATIR ICINDE sarabilir; tablo disinda
   (baslik, kart) nowrap kalir -- kural bilerek `.table td` ile
   sinirli. */
.table td .status-pill,
.table td .quality-status,
.table td .accounting-status,
.table td .stock-status,
.table td .personnel-status,
.table td .approval-status,
.table td .movement-type,
.table td .archive-file-badge,
.table td .primary-tag{white-space:normal}

/* 2) SIRALAMA BASLIKLARI
   `.stock-sort` / `.personnel-sort` / `.customer-job-sort` nowrap
   veriyordu; "Seri / Tip ↕" gibi basliklar sutunu geniste tutuyordu.
   Ok isareti `<span>` icinde ve kendi basina sarmiyor. */
.table th.sortable,
.table th.customer-job-sort,
.table th.personnel-sort,
.table th.stock-sort{white-space:normal}

/* 3) IS AKISI BOLMESI ERKEN TEK SUTUNA INIYOR
   `.workflow-split` iki sutunlulugunu 900px'e kadar koruyordu; 1024px
   ekranda "Sevkiyata Hazir" tablosunun kabi 328px'e dusuyor ve alti
   sutun oraya sigmiyordu (72px tasma).

   NIYE DOSYANIN SONUNDA: `.workflow-split` duz kurali styles.css:6866'da
   YENIDEN tanimlaniyor ve 6825'teki medya sorgusunu eziyor -- ayni tuzak
   styles.css:8343'te zaten kayitli. Sonda olan kazanir. */
@media screen and (max-width:1150px){
  .workflow-split{grid-template-columns:minmax(0,1fr)}
  .workflow-arrow{transform:rotate(90deg);justify-self:center}
}

/* 4) STOK TABLOSU
   `tblStock` ilk listede unutulmustu: kimligi yoktu, dolayisiyla hicbir
   kap sorgusu ona degmiyordu (1280px'te 8px tasma). Kimlik verildi ve
   kendi kademesi yazildi. */
@media screen and (min-width:901px){
  @container tbl (max-width:640px){
    #tblStock th:nth-child(4), #tblStock td:nth-child(4),   /* Marka */
    #tblStock th:nth-child(5), #tblStock td:nth-child(5){   /* Seri / Tip */
      display:none;
    }
  }
}


/* =====================================================================
   KOD / TARIH SUTUNLARI TIRE'DEN BOLUNMESIN  (v2.77.2)
   =====================================================================
   Sarma acildiktan sonra canlida gorulen kusur: "2026-0001" is numarasi
   hucrede "2026-" / "0001" diye ikiye ayriliyordu; tarihler de
   "2026-" / "08-02" oluyordu. CSS tireyi dogal bir satir sonu firsati
   sayiyor.

   ONCE KOSULSUZ YAZDIM VE OLCUM CURUTTU: `nowrap`i her genislikte
   verince yatay tasma GERI GELDI (Sevkiyat 192px, Rapor 45px, 1366px).
   Yorumda "bu sutunlar dar, tasmaya yol acmiyor -- olculdu" yazmistim;
   olcmeden once yazmisim. Sayi yalanladi.

   DOGRUSU: kod butunlugu ancak YER VARKEN korunabilir. Kap 700px'in
   ustundeyse tire kirilmaz; altindaysa kirilmaya izin verilir, cunku
   oradaki secenek "kod ikiye bolunur" ile "tablo yana kayar"
   arasindadir ve musteri ikincisini reddetti.

   Hedef listesi mono blogundan birebir alindi (ayri liste tutulmuyor).
   ===================================================================== */
@container tbl (min-width:700px){
#jobsTable td:nth-child(1),
#jobsTable td:nth-child(2),
#jobsTable td:nth-child(9),
#qualityTable td:nth-child(1),
#qualityTable td:nth-child(2),
#qualityTable td:nth-child(7),
#trackingTable td:nth-child(1),
#trackingTable td:nth-child(8),
#archiveTable td:nth-child(1),
#archiveTable td:nth-child(5),
.personnel-table-wrap td:nth-child(1),
.workflow-table td:nth-child(1),
#productionReadyTable td:nth-child(4),
#shippingReadyTable td:nth-child(4),
/* RAPOR MERKEZI BILEREK DISARIDA.
   12 sutunla en yogun tablo o. Kod sutunlarina nowrap verince 1366px'te
   45px tasti (olculdu, v2.77.2 canli dogrulama). Secenek "is numarasi
   tireden bolunur" ile "tablo yana kayar" arasindaydi; musteri
   ikincisini reddetti. Burada tarih ve is no iki satira inebilir. */
/* Stok hareketleri: 1=Tarih · 6=Is No */
.stock-movement-wrap td:nth-child(1),
.stock-movement-wrap td:nth-child(6),
/* Muhasebe aktarim listesi: 1=Is No · 2=Tarih */
.accounting-table-wrap td:nth-child(1),
.accounting-table-wrap td:nth-child(2){
  white-space:nowrap;
}
}


/* ==================== MUHASEBE MODÜLÜ — TAM EKRAN KABUK (Aşama 0) ====================
   Kullanıcı sözü: "MUHASEBE düğmesi tam ekran ayrı modüle götürsün,
   yalnızca muhasebe alanları görünsün, basit kullanışlı olmalı."

   `body.muhasebe-modu` sınıfı YALNIZCA muhasebe ekranı açıkken var olur
   (bkz. web/js/01-cekirdek.js `showPage`, web/js/muhasebe/00-kabuk.js).

   DOSYANIN EN SONUNA EKLENDİ, hiçbir @media/@container bloğunun İÇİNE
   değil — kaynak sırası en yüksek ve yanlışlıkla bir medya bağlamına
   girme riski yok (bkz. proje notu: "0 kazanan değer değişti" kanıtı
   bir medya bağlamı karışıklığı yüzünden 20 seçiciyi masaüstünde
   bozmuştu; bu blok o riski taşımasın diye en sona, açık bir üst
   seviye kural olarak kondu). ===================================== */

/* Kenar çubuğu (logo + kenar menüsü) tam ekran modda TAMAMEN gizlenir;
   ".app nav"ı tek başına gizlemek 250px'lik boş bir şerit bırakırdı —
   "tam ekran" bunu karşılamaz. Grid tek koloma inince `main` tüm
   genişliği alır. */
body.muhasebe-modu .app{
  grid-template-columns:minmax(0,1fr);
}
body.muhasebe-modu .app>aside{
  display:none;
}
/* ERP başlığı (küçük "GOLD ERP WEB" etiketi + h1 #pageTitle) gizlenir;
   çıkış (.user / #logout) KALIR — tam ekran modda da oturumu kapatabilmek
   gerekir. hdr-title mutlak konumlu olduğu için gizlenmesi header'ın
   yüksekliğini BOZMAZ (bkz. .app main>header .hdr-title kuralı). */
body.muhasebe-modu .app main>header .hdr-title,
body.muhasebe-modu .app main>header .mobile-menu-button{
  display:none;
}

.muhasebe-kabuk{
  display:flex;
  align-items:center;
  flex-wrap:wrap;
  gap:var(--s3);
  padding:var(--s3) var(--s4);
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r2);
  box-shadow:var(--sh1);
}
.muhasebe-kabuk-baslik{
  display:flex;
  align-items:center;
  gap:var(--s2);
  font-size:15px;
  font-weight:700;
  letter-spacing:-.01em;
  color:var(--ink);
  white-space:nowrap;
}
.muhasebe-kabuk-baslik span{font-size:18px;line-height:1}
.muhasebe-kabuk-menu{
  display:flex;
  gap:var(--s1);
  flex-wrap:wrap;
}
.muhasebe-kabuk-menu button{
  min-height:var(--tap);
  padding:var(--s2) var(--s3);
  font-size:12px;
  font-weight:650;
  letter-spacing:.04em;
  color:var(--ink-3);
  background:var(--paper-2);
  border:1px solid var(--line);
  border-radius:var(--r1);
}
.muhasebe-kabuk-menu button:hover{color:var(--ink)}
.muhasebe-kabuk-menu button.active{
  color:var(--m);
  border-color:var(--m);
  background:var(--paper);
}
.muhasebe-kabuk-menu button:focus-visible{
  outline:2px solid var(--m);
  outline-offset:-2px;
}
.muhasebe-kabuk-ozet{
  font-size:12px;
  color:var(--ink-3);
}
.muhasebe-kabuk-don{
  margin-left:auto;
}

/* KASA + BANKA TANITIM KARTLARI — Aşama 1.
   Grid`in kolon sayısı sabit değil: dar ekranda (telefon/tablet) tek
   sütuna düşer, aksi hâlde iki kart bloğu yan yana taşardı. */
.kartlar-grid{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(360px,1fr));
  gap:var(--s4);
}
.kartlar-table-wrap{max-height:min(60vh,520px)}
.kartlar-row-actions{
  display:flex;
  gap:var(--s1);
  flex-wrap:wrap;
  justify-content:flex-end;
}
.kartlar-row-actions button{
  padding:4px 10px;
  font-size:11px;
}
.kartlar-empty{text-align:center;color:var(--ink-3);padding:var(--s4)}

/* DİYALOG ÇATISI — `.stock-dialog*` ile AYNI YAPI, kasıtlı olarak
   AYRI bir ad taşıyor: her modül kendi CSS ad alanında kalıyor
   (bkz. `.settings-form-grid`, `.stock-form-grid` — aynı kalıp),
   böylece stok ekranındaki bir değişiklik bu modülü etkilemiyor. */
.kartlar-dialog{width:min(96vw,560px)}
.kartlar-dialog-head{
  display:flex;
  align-items:flex-start;
  justify-content:space-between;
  gap:var(--s3);
  padding:var(--s4);
  border-bottom:1px solid var(--line);
}
.kartlar-dialog-head h2{margin:0;font-size:20px;font-weight:650;letter-spacing:-.01em}
.kartlar-dialog-head span{font-size:12px;color:var(--ink-3)}
.kartlar-dialog-head button{
  min-height:var(--tap);
  min-width:var(--tap);
  font-size:18px;
  border-radius:var(--r1);
}
.kartlar-dialog-head button:hover{background:var(--surface);color:var(--ink)}
.kartlar-dialog form{display:grid;gap:var(--s4);padding:var(--s4)}
.kartlar-form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s3)}
.kartlar-dialog footer{
  display:flex;
  justify-content:flex-end;
  gap:var(--s2);
  padding:var(--s4);
  border-top:1px solid var(--line);
}

/* CARİ HAREKET FÖYÜ — Aşama 3. Diyalog çatısı `.kartlar-dialog*`den
   (yukarıdaki) AYNEN devralınıyor; yalnızca bu panele özgü olanlar burada. */
.foy-arac-cubugu{
  display:flex;
  align-items:end;
  flex-wrap:wrap;
  gap:var(--s3);
  margin-bottom:var(--s3);
}
.foy-arac-cubugu label{font-size:10.5px}
/* Başlıkta iki eylem: TAHSİLAT ve YENİ DEKONT. */
.foy-baslik-eylemleri{display:flex;gap:var(--s2);flex-wrap:wrap}
/* KESİM NOTU — bilgi şeridi, uyarı değil.
   Kırmızı/sarı bir uyarı rengi kullanılmadı: bu bir hata değil, defterin
   nereden bölündüğünü söyleyen bir açıklama. Renkler mevcut belirteçlerden
   alınıyor (uydurulmuş hex bu depoda bir kez kapıya takıldı). */
.foy-kesim-notu{
  margin:0 0 var(--s3);
  padding:var(--s2) var(--s3);
  border-left:3px solid var(--m);
  background:var(--m-soft);
  border-radius:var(--r1);
  font-size:11px;
  line-height:1.5;
}
.foy-table-wrap{max-height:min(60vh,560px)}
.foy-devir-satiri td{
  background:var(--paper-2);
  font-style:italic;
  color:var(--ink-3);
}
.muhasebe-kaynak-etiket{
  font-size:10px;
  font-weight:650;
  letter-spacing:.04em;
  color:var(--ink-3);
  padding:2px 8px;
  border:1px solid var(--line);
  border-radius:999px;
}
/* Açıklama alanı `.kartlar-form-grid`in iki sütununu birden kaplasın —
   tek satırlık bir metin girişini yarım genişliğe sıkıştırmak okumayı
   zorlaştırırdı. */
.foy-dekont-aciklama{grid-column:1 / -1}

/* ================================================================
   ORTAK KALIPLAR — Aşama 9 (Ortak Kalıplar + Cari Hesap Kartı)
   Kaynak: onaylanan maket (muhasebe-maket.html) + web/js/muhasebe/
   kalip.js. Sınıf adları MAKETTEN — İCAT EDİLMEDİ (bkz. kalip.js dosya
   başı yorumu, tests/test_muhasebe_ortak_kalip.py). Bu blok BİLEREK
   dosyanın EN SONUNA eklendi, hiçbir @media bloğunun İÇİNE GİRMİYOR —
   "0 kazanan değer" bir medya bağlamının içine sızıp masaüstünü
   bozmasın diye (bu depoda yaşanmış bir ders).
   ================================================================ */

/* ---- kart çerçevesi — ORTAK KALIPLAR md. "Tüm KART ekranlarında" ---- */
.ekran{
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r2);
  overflow:hidden;
  box-shadow:var(--sh1);
}
.ekran-bas{
  background:var(--k);
  color:#fff;
  padding:var(--s3) var(--s4);
  display:flex;
  align-items:center;
  gap:var(--s3);
  flex-wrap:wrap;
}
.ekran-bas .ad{font-weight:600;letter-spacing:.02em}
.ekran-bas .kod{font:12px var(--mono);opacity:.6}
.ekran-govde{padding:var(--s4)}

/* ---- kart içi sekmeler ---- */
.ekran .sekmeler{
  display:flex;
  gap:2px;
  border-bottom:1px solid var(--line);
  margin-bottom:var(--s3);
  overflow-x:auto;
}
.ekran .sekmeler button{
  border:0;
  background:transparent;
  padding:var(--s2) var(--s3);
  font:600 13px var(--ui);
  color:var(--ink-3);
  cursor:pointer;
  white-space:nowrap;
  border-bottom:2px solid transparent;
}
.ekran .sekmeler button.aktif{color:var(--m);border-bottom-color:var(--m)}

/* ---- alan ızgarası: kod alanı + "?" arama düğmesi (kalip.js aramaAlani) ---- */
.alanlar{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(230px,1fr));
  gap:var(--s3) var(--s4);
}
.cari-karti-ikinci-blok{margin-top:var(--s4)}
.alan{min-width:0}
.alan label{
  display:block;
  font-size:11px;
  text-transform:uppercase;
  letter-spacing:.05em;
  color:var(--ink-3);
  margin-bottom:3px;
}
.kutu{
  display:flex;
  border:1px solid var(--line);
  border-radius:var(--r1);
  background:var(--paper);
  overflow:hidden;
}
.kutu input{
  flex:1;
  min-width:0;
  border:0;
  background:transparent;
  padding:7px var(--s2);
  font:14px var(--ui);
  color:var(--ink);
}
.kutu input.kod{font-family:var(--mono)}
.kutu .ara{
  border:0;
  border-left:1px solid var(--line);
  background:var(--m-soft);
  color:var(--m);
  width:30px;
  cursor:pointer;
  font-weight:700;
  font-size:13px;
}
.kutu.zorunlu{border-color:var(--m)}
.rozet{
  display:inline-block;
  font-size:11px;
  padding:2px 7px;
  border-radius:99px;
  background:var(--c-soft);
  color:var(--c);
  font-weight:600;
}

/* ---- işlem şeridi (kalip.js islemSeridi) ---- */
.serit{
  display:flex;
  gap:var(--s1);
  flex-wrap:wrap;
  align-items:center;
  padding:var(--s3) var(--s4);
  background:var(--paper-2);
  border-top:1px solid var(--line);
}
.serit .bosluk{flex:1;min-width:var(--s2)}
.serit button{
  border:1px solid var(--line);
  background:var(--surface);
  color:var(--ink-2);
  padding:6px 11px;
  border-radius:var(--r1);
  font:600 12.5px var(--ui);
  cursor:pointer;
  display:inline-flex;
  align-items:center;
  gap:5px;
  white-space:nowrap;
}
.serit button:hover{border-color:var(--m);color:var(--m)}
.serit button.birincil{background:var(--m);border-color:var(--m);color:#fff}
.serit button.birincil:hover{background:var(--m-hover);border-color:var(--m-hover);color:#fff}
.serit button.yikici:hover{border-color:var(--no);color:var(--no)}
.serit button.gez{font-family:var(--mono);padding:6px 9px}

/* ---- durum satırı (kalip.js durumSatiri) ----
   `#fff` İCAT DEĞİL: `var(--k-2)` bu depoda hep koyu kalan (temaya göre
   TERSİNMEYEN) bir yüzey; üstünde metin rengi olarak `#fff` zaten
   onlarca yerde kullanılıyor (bkz. `.grand-total`, `button.dark`). */
.durum{
  display:flex;
  justify-content:space-between;
  gap:var(--s3);
  flex-wrap:wrap;
  padding:var(--s2) var(--s4);
  background:var(--k-2);
  color:#fff;
  font:12px var(--mono);
}

/* ---- arama penceresi: TEK, PAYLAŞILAN diyalog (kalip.js aramaAlani) ---- */
.kalip-arama-dialog{
  border:0;
  border-radius:var(--r2);
  box-shadow:var(--sh3);
  padding:0;
  width:min(480px,92vw);
  max-height:min(70vh,560px);
}
/* DISPLAY YALNIZCA [open] İLE — KOŞULSUZ VERİLİRSE PENCERE KAPANMAZ.
   Tarayıcının kendi kuralı `dialog:not([open]){display:none}` ama o UA
   kuralı; buradaki sınıf seçicisi (0,1,0) onu EZİYOR. Koşulsuz
   `display:flex` yazıldığında `close()` çalışıyor, `open` niteliği
   kalkıyor, ARKA PERDE kayboluyor — ama kutu ekranda kalıyor.
   Kullanıcının tarifi tam buydu: "kapanmış gibi olmaya çalışıyor ama
   kapanmıyor." Belirti yanıltıcı: kusur JS'te değil, CSS'te. */
.kalip-arama-dialog[open]{
  display:flex;
  flex-direction:column;
}
.kalip-arama-dialog::backdrop{background:rgba(18,18,22,.4)}
.kalip-arama-bas{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--s3);
  padding:var(--s3) var(--s4);
  border-bottom:1px solid var(--line);
  background:var(--paper-2);
}
.kalip-arama-bas button{
  border:0;
  background:transparent;
  color:var(--ink-3);
  cursor:pointer;
  font-size:14px;
  line-height:1;
}
.kalip-arama-bas button:hover{color:var(--no)}
.kalip-arama-dialog input[type="search"]{
  margin:var(--s3) var(--s4) 0;
  border:1px solid var(--line);
  border-radius:var(--r1);
  padding:7px var(--s3);
  font:14px var(--ui);
  color:var(--ink);
  background:var(--paper);
}
.kalip-arama-liste-sar{
  margin:var(--s3) var(--s4) var(--s4);
  overflow:auto;
  border:1px solid var(--line);
  border-radius:var(--r1);
}
.kalip-arama-liste-sar table{width:100%;border-collapse:collapse;font-size:13px}
.kalip-arama-liste-sar td{padding:7px var(--s3);border-bottom:1px solid var(--line-2);cursor:pointer}
.kalip-arama-liste-sar tr:last-child td{border-bottom:0}
.kalip-arama-liste-sar tr:hover td{background:var(--m-soft)}
.kalip-arama-liste-sar td.kalip-arama-bos{color:var(--ink-3);font-style:italic;cursor:default}

/* ---- ekran içi kısa not (Adresler/Yetkililer stub sekmeleri) ---- */
.muhasebe-not{color:var(--ink-3);font-size:13px;margin:0 0 var(--s3)}

/* ---- CARİ EŞLEŞTİRME (Aşama 11) ----
   Elle arama alanı + "Mikro'da yok" / "Şimdilik atla" düğmeleri tek satırda,
   dar ekranda alt alta — `.foy-arac-cubugu` ile AYNI esneklik ilkesi. */
.cari-eslesme-elle{
  display:flex;
  align-items:end;
  flex-wrap:wrap;
  gap:var(--s3);
  margin-top:var(--s3);
}
.cari-eslesme-elle-dugmeler{display:flex;gap:var(--s2);flex-wrap:wrap}

/* ============================ MUHASEBE — ÇOK SATIRLI IZGARA + 4 KUTU ÖZET
   Kaynak: docs/muhasebe/mikro_ekran_envanteri.md "ORTAK KALIPLAR".
   Çizim `web/js/muhasebe/kalip.js` içindeki izgara() / ozetKutulari()
   fonksiyonlarında; burada YALNIZCA görünüm var.                        */

/* KENDİ KABINDA KAYAR. Bu depoda 8 tabloda yatay taşma yaşandı ve 14
   ekran boyutunda düzeltildi; geniş bir fiş ızgarası SAYFAYI değil
   kendini kaydırmalı. */
.izgara-sarmal{ overflow-x:auto; border:1px solid var(--line); border-radius:6px; }

.muhasebe-izgara{ width:100%; border-collapse:collapse; font-size:13px; }
.muhasebe-izgara th,
.muhasebe-izgara td{ padding:6px 9px; border-bottom:1px solid var(--line);
                     text-align:left; white-space:nowrap; }
.muhasebe-izgara thead th{ position:sticky; top:0; background:var(--card);
                           color:var(--muted); font-weight:600;
                           letter-spacing:.02em; text-transform:uppercase;
                           font-size:11px; }
.muhasebe-izgara tbody tr:hover{ background:var(--hover); }
.muhasebe-izgara tbody tr:last-child td{ border-bottom:0; }

/* RAKAMLAR ALT ALTA HİZALANSIN: tutar sütununda tabular-nums olmadan
   basamaklar kayar ve göz toplamı denetleyemez. */
.muhasebe-izgara .sayi{ text-align:right; font-variant-numeric:tabular-nums;
                        font-family:var(--mono); }
.muhasebe-izgara .izgara-bos td{ text-align:center; color:var(--muted);
                                 padding:18px 9px; white-space:normal; }

/* Dört kutu: dar ekranda ikişerli, geniş ekranda yan yana dört. */
.ozet-kutular{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr));
               gap:8px; }
@media (min-width:720px){
  .ozet-kutular{ grid-template-columns:repeat(4,minmax(0,1fr)); }
}
.ozet-kutu{ display:flex; flex-direction:column; gap:2px; padding:10px 12px;
            border:1px solid var(--line); border-radius:6px;
            background:var(--card); }
.ozet-etiket{ font-size:11px; letter-spacing:.04em; text-transform:uppercase;
              color:var(--muted); }
.ozet-deger{ font-size:17px; font-variant-numeric:tabular-nums;
             font-family:var(--mono); }
.ozet-kutu.vurgu{ border-color:var(--m); }
.ozet-kutu.vurgu .ozet-deger{ font-weight:700; color:var(--m); }

/* ÖLÇÜ ONAYLARI — IZGARA + İNCELEME.
   Kullanıcı kararı (26.08): "popup gibi değil gridli incelenebilir
   birşey olmalı... işin geçmişi felanda görmeli".

   İki sütun: solda kuyruk, sağda seçili talebin dökümü. Dar ekranda
   alt alta iner — `minmax(0,...)` ŞART, yoksa uzun içerik sütunu
   şişirip yatay kaydırma üretir. */
.olcu-onay-duzen {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
  gap: var(--s3, 12px);
  align-items: start;
}
@media (max-width: 900px) {
  .olcu-onay-duzen { grid-template-columns: minmax(0, 1fr); }
}
.olcu-onay-liste { max-height: min(60vh, 520px); }
.olcu-onay-liste tbody tr { cursor: pointer; }

.olcu-onay-detay {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: var(--s3, 12px);
  max-height: min(70vh, 620px);
  overflow: auto;
}
.olcu-onay-detay h5 {
  margin: var(--s3, 12px) 0 var(--s1, 4px);
  font-size: .82rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.olcu-onay-bos { color: var(--ink-3); }
.olcu-onay-talep {
  padding: var(--s2, 8px);
  border-left: 3px solid var(--warn);
  background: color-mix(in srgb, var(--warn) 8%, transparent);
}
/* Mini tablolar kendi kabında kayar: uzun açıklama sayfayı yatayda
   taşırmasın. */
.olcu-onay-mini { width: 100%; border-collapse: collapse; font-size: .86rem; }
.olcu-onay-mini td, .olcu-onay-mini th {
  padding: 4px 6px;
  border-bottom: 1px solid var(--line);
  text-align: left;
}
.olcu-onay-eylem {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2, 8px);
  margin-top: var(--s3, 12px);
}

/* IZGARA DIŞA AKTARMA ÇUBUĞU.
   Sarmalın DIŞINDA duruyor: içine konsaydı yatay kaydırma kabının
   içinde kalır ve geniş tablolarda düğmeler ekrandan kayardı. */
.izgara-aktar-cubugu {
  display: flex;
  justify-content: flex-end;
  gap: var(--s2);
  margin-bottom: var(--s1);
}
.izgara-aktar-cubugu button {
  font-size: .78rem;
  padding: .25em .7em;
}
/* Yazdırırken çubuk KAĞIDA GİRMESİN — düğme resmi bir belgede anlamsız. */
@media print { .izgara-aktar-cubugu { display: none; } }

/* MİKRO GEÇMİŞİ SATIRI — Klişe Arşivi içinde, tıklanamaz.
   Kullanıcı isteği (27.08.2026): Mikro geçmişi ile yeni işler TEK
   ekranda. Eskiler görselsiz geldiği için satırın farkı görünür
   olmalı; yoksa kullanıcı "bunun görseli niye yok" diye arar. */
#archiveTable tr.arsiv-mikro-satiri {
  cursor: default;
  opacity: .82;
}
#archiveTable tr.arsiv-mikro-satiri:hover { background: transparent; }
/* YENİ RENK UYDURULMUYOR — kapı bunu sınıyor.
   `--m-soft` / `--m` bu depoda zaten "bilgi/vurgu" rolünde kullanılıyor.
   Ham hex yazsaydım tema değişince rozet okunmaz hâle gelirdi. */
.archive-file-badge.mikro {
  background: var(--m-soft);
  color: var(--m);
}

/* ==================== E-FATURA İÇE AKTARIM (muhasebe paneli) ====================

   YENİ RENK UYDURULMADI — hepsi mevcut belirteçler:
     --ok/--ok-soft (kaydedilebilir), --no/--no-soft (engel/hata),
     --y/--y-soft (uyarı), --m/--m-soft (adım numarası), --line/--surface.
   Ham hex yazsaydım koyu ve yüksek karşıtlık temalarında rozet okunmaz
   hâle gelirdi (bkz. `.archive-file-badge.mikro` yanındaki aynı not). */

.efatura-adim { align-items: flex-end; }
/* Adım numarası: "1) DOSYA SEÇ" akışının görsel çıpası. `.rozet`
   kopyalanmadı — o sınıf `--c`/`--c-soft` bekleyen bir bağlamda yaşıyor. */
.efatura-adim-no {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 99px;
  background: var(--m-soft);
  color: var(--m);
  font-weight: 700;
  font-size: 12px;
  margin-bottom: var(--s2);
}
.efatura-durum { margin: var(--s2) 0; color: var(--ink-2); min-height: 1.2em; }
.efatura-durum-hata { color: var(--no); font-weight: 600; }

/* Rozet — üç durum, üç mevcut renk çifti. */
.efatura-rozet {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 99px;
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}
.efatura-rozet-ok { background: var(--ok-soft); color: var(--ok); }
.efatura-rozet-engel { background: var(--no-soft); color: var(--no); }
.efatura-rozet-uyari { background: var(--y-soft); color: var(--y); }

/* SEBEP METNİ KIRPILMAZ.
   `.serit-tablo tbody td` her hücreye `nowrap + ellipsis` veriyor (uzun
   ünvan satırı taşırmasın diye). Durum hücresinde bu ters teper: sunucunun
   "kartı açıp VKN'sini yazın, sonra arşivi yeniden yükleyin" gibi YÖNERGE
   içeren engel metni telefonda "…kartı aç…" diye kesilir ve kullanıcı ne
   yapacağını göremezdi — `gun-sonu-bos` ile AYNI sorun, aynı çözüm.
   Seçicideki fazladan `tr` de aynı ölçümden geliyor: `.serit-tablo tbody
   td:first-child{flex:0 0 auto}` (0,2,2) ile berabere kalmamak için. */
.serit-tablo tbody tr td.efatura-durum-hucre {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
}
.efatura-sebep,
.efatura-uyari-satir {
  display: block;
  font-size: 11.5px;
  line-height: 1.35;
  margin-top: 2px;
}
.efatura-sebep { color: var(--no); }
.efatura-uyari-satir { color: var(--y); }

/* Atlanan dosyalar — tablo DEĞİL, ayrı blok (fatura satırı değiller). */
.efatura-atlanan {
  border: 1px solid var(--line);
  border-left: 3px solid var(--y);
  border-radius: var(--r1);
  background: var(--surface);
  padding: var(--s2) var(--s3);
  margin: var(--s3) 0;
  font-size: 12px;
}
.efatura-atlanan ul { margin: var(--s1) 0 0; padding-left: var(--s4); }

.efatura-tablo { margin-top: var(--s3); }

/* İŞ BAĞLAMA BLOĞU — yalnızca SATIŞ satırının altında.
   `colspan`lı hücre olduğu için şerit etiketleyicisi bu satırı zaten
   atlıyor (22-serit-etiket.js: "sütun hizası yoktur"). Hücrenin kırpılma
   izni de geri alınıyor: içinde giriş alanları var, ezilirlerse
   kullanılamaz hâle gelirler. */
.serit-tablo tbody tr td.efatura-is-hucre {
  flex: 1 1 100%;
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  background: var(--paper-2);
  padding: var(--s3);
}
.efatura-isler-bas { margin: 0 0 var(--s2); font-size: 12px; color: var(--ink-2); }
.efatura-isler-bos { margin: 0; font-size: 12px; color: var(--no); }
.efatura-is-satir {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--s2);
  padding: var(--s2) 0;
  border-top: 1px solid var(--line);
}
.efatura-is-ad { display: flex; align-items: center; gap: var(--s2); flex: 1 1 220px; }
.efatura-is-tutar-alan { flex: 0 0 130px; font-size: 10.5px; }
.efatura-is-toplam {
  margin: var(--s2) 0 0;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  color: var(--ink-2);
}
.efatura-ac {
  font-size: 11px;
  padding: 1px 6px;
  border: 1px solid var(--line);
  border-radius: var(--r1);
  background: var(--surface);
  color: var(--m);
  cursor: pointer;
}

/* Kaydet şeridi — uyarı solda, düğme sağda; dar ekranda alt alta
   (`.foy-arac-cubugu` ile AYNI esneklik ilkesi). */
.efatura-kaydet-serit {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--s3);
  margin-top: var(--s3);
}
.efatura-kaydet-serit .uyari-metin { flex: 1 1 260px; margin: 0; }
.efatura-sonuc-baslik { margin: var(--s5) 0 var(--s2); }

/* GELEN e-İRSALİYE BÖLÜMÜ — önizlemenin İKİNCİ tablosu.
   YENİ RENK YOK, YENİ KURAL DA NEREDEYSE YOK: irsaliye satırı fatura
   satırıyla aynı sınıfları kullanıyor (`.efatura-rozet*`, `.efatura-sebep`,
   `.efatura-durum-hucre`). Ayrı bir görünüm yazsaydım aynı bilgi iki farklı
   biçimde çizilir ve biri güncellendiğinde öteki geride kalırdı.
   Buradaki tek şey bölümü fatura tablosundan ayıran başlık aralığı —
   `.efatura-sonuc-baslik` KOPYALANMADI, o "Kayıt Sonucu" başlığının adı. */
.efatura-irsaliye-baslik { margin: var(--s5) 0 var(--s2); }

/* ==================== İRSALİYE LİSTESİ (muhasebe paneli) ====================
   BAŞLANGIÇ İŞARETİ — `tests/test_irsaliye_ekrani.py` bu satırla blok
   keserek "uydurulmuş hex renk yok" kapısını ÖLÇÜYOR. İşaret silinirse
   kapı boş özne üstünde ölçüm yapardı ve o yüzden orada assert'li.

   YENİ RENK YOK: bu blokta tek bir ham hex bile yok — irsaliye satırı
   kardeş listelerle aynı sınıfları kullanıyor (`.serit-tablo`,
   `.kartlar-empty`, `tbody tr.selected`). Ayrı bir görünüm yazsaydım aynı
   bilgi iki farklı biçimde çizilir ve biri güncellendiğinde öteki geride
   kalırdı. Buradaki üç kural da DÜZENDİR, renk değil. */

/* SATIR TIKLANABİLİR: ayrıntı (satırlar) satıra tıklayınca açılıyor ve
   bunun tek görünür işareti imleç. Seçili satırın vurgusu GENEL kuraldan
   geliyor (`tbody tr.selected`, styles.css) — bu ekran için yeni bir
   seçim sınıfı İCAT EDİLMEDİ. */
.irsaliye-satir { cursor: pointer; }

/* ETTN KIRPILMAZ.
   `.serit-tablo tbody td` her hücreye `nowrap + ellipsis` veriyor (uzun
   ünvan satırı taşırmasın diye). ETTN'de bu ters teper: 36 haneli tekil
   belge kimliği telefonda "f47ac10b-58cc-4372…" diye kesilir ve
   kullanıcının portalda aratacağı değeri okumasına imkân kalmazdı —
   `efatura-durum-hucre` ile AYNI sorun, aynı çözüm.
   Seçicideki fazladan `tr` de aynı ölçümden geliyor: `.serit-tablo tbody
   td:first-child{flex:0 0 auto}` (0,2,2) ile berabere kalmamak için.
   `break-all` şart: ETTN boşluksuz tek sözcüktür, `normal` tek başına
   onu sarmaz, hücreden taşırırdı. */
.serit-tablo tbody tr td.irsaliye-ettn,
.serit-tablo tbody tr td.alis-ettn {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  word-break: break-all;
}

/* ALIŞ FATURASI LİSTESİNDE ETTN — MASAÜSTÜ GENİŞLİĞİ
   36 hane, tablonun EN GENİŞ sütunu olurdu ve tutar sütunlarını sağa
   itip yatay kaydırma doğururdu (bu depoda 8 tabloda düzeltilen sorun).
   Sarmalayıp iki satıra bölmek, sütunu ~18 karakter genişliğinde tutuyor;
   tam değer `title` niteliğinde ve seçilip kopyalanabiliyor. GİZLEMİYOR,
   yalnızca sarıyor. */
.alis-ettn {
  max-width: 20ch;
  word-break: break-all;
  font-size: 0.85em;
  color: var(--muted);
}

/* Ayrıntı başlığının tablodan ayrılması — `.efatura-sonuc-baslik` ile
   AYNI aralık. O sınıf KOPYALANMADI: adı "Kayıt Sonucu" başlığının adı ve
   iki ekran bir gün ayrı yönlere gidebilir. */
.irsaliye-satir-baslik { margin: var(--s5) 0 var(--s2); }
/* ==================== İRSALİYE LİSTESİ — BİTİŞ ==================== */
