/* TM paketi — kaynak sirasi korunur. Uretici: scripts/build_assets.py */

/* ===== css/tm-satis-ipuclari.css ===== */
/* ═══════════════════════════════════════════════════════════════════════
   Trendmetrik — "Satış İpuçları" kılavuz modalı + tetikleyici buton
   Kaynak: bayi-satis-ipuclari-klavuzu-2026-10-07/prototip/klavuz.css
   (sahte uygulama kabuğu — .tm-shell/.tm-sidebar/.tm-header/.tm-page —
   bilerek PORT EDİLMEDİ; gerçek header zaten var. Yalnız .tm-tips-btn
   tetikleyicisi ve .k-* modal gövdesi taşındı.)
   Kaynak prototip damgası (sha256 ilk 8, dondurma onaylı — 2026-10-08):
   klavuz.html cf4bffed · klavuz.js 93b27137 · klavuz.css f3e788a5 ·
   mockuplar.js 6aeb0953 · mockuplar.css e81f9032 · adimlar.json 8b6e346b ·
   adimlar.js 8c7d98a3
   ═══════════════════════════════════════════════════════════════════════ */
:root {
  /* marka */
  --lacivert: #031538;
  --lacivert-2: #0a2250;
  --mavi: #0175e4;
  --mavi-koyu: #0163c2;
  --mavi-acik: #73b7fe;
  --mavi-sis: #e8f3ff;
  --turuncu: #f27a1a;
  --turuncu-sis: #fff1e3;

  /* yüzey — gerçek uygulamanın tokenlarıyla aynı */
  --sayfa: #f4f6fa;
  --yuzey: #ffffff;
  --cizgi: #e7ebf1;
  --cizgi-2: #eef1f6;
  --murekkep: #0f172a;
  --murekkep-2: #475569;
  --murekkep-3: #94a3b8;

  --golge-kart: 0 8px 24px rgba(15, 23, 42, .06);
  --golge-sert: 10px 10px 0 rgba(3, 21, 56, .07);

  --ff-display: "Unbounded", "Manrope", sans-serif;
  --ff-body: "Manrope", ui-sans-serif, system-ui, sans-serif;

  --hiz: cubic-bezier(.22, .9, .22, 1);
  --yay: cubic-bezier(.34, 1.4, .5, 1);
}

/* — ★ Satış İpuçları tetikleyici düğmesi — */
/* — ★ Satış İpuçları düğmesi: nefes + periyodik parıltı — */
.tm-tips-btn {
  position: relative; isolation: isolate; overflow: hidden;
  display: inline-flex; align-items: center; gap: 8px;
  height: 36px; padding: 0 15px 0 12px;
  border: 0; border-radius: 999px; cursor: pointer;
  background: linear-gradient(118deg, #f27a1a 0%, #fb9c3f 54%, #f27a1a 100%);
  color: #fff; font-family: var(--ff-body); font-size: 13px; font-weight: 800;
  letter-spacing: -.01em;
  box-shadow: 0 2px 10px rgba(242, 122, 26, .34);
  animation: tipsBreathe 3.4s ease-in-out infinite;
  transition: transform .22s var(--yay), box-shadow .22s var(--hiz);
}
.tm-tips-btn:hover { transform: translateY(-1.5px); box-shadow: 0 8px 22px rgba(242, 122, 26, .46); }
.tm-tips-btn:active { transform: translateY(0) scale(.985); }
.tm-tips-btn:focus-visible { outline: 3px solid rgba(1, 117, 228, .5); outline-offset: 2px; }

.tm-tips-btn__glow {
  position: absolute; inset: -2px; z-index: -1; border-radius: inherit;
  background: radial-gradient(circle at 18% 50%, rgba(255, 255, 255, .55), transparent 62%);
  opacity: .65;
}
.tm-tips-btn__sheen {
  position: absolute; top: 0; left: -60%; width: 45%; height: 100%; z-index: 0;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .55), transparent);
  transform: skewX(-18deg);
  animation: tipsSheen 5.2s cubic-bezier(.5, 0, .3, 1) infinite;
}
.tm-tips-btn__bulb { position: relative; z-index: 1; font-size: 14px; line-height: 1;
  animation: tipsBulb 3.4s ease-in-out infinite; }
.tm-tips-btn__label { position: relative; z-index: 1; }
.tm-tips-btn__count {
  position: relative; z-index: 1;
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px;
  background: rgba(3, 21, 56, .28);
  display: grid; place-items: center;
  font-family: var(--ff-display); font-size: 10px; font-weight: 700;
}

@keyframes tipsBreathe {
  0%, 100% { box-shadow: 0 2px 10px rgba(242, 122, 26, .34); }
  50%      { box-shadow: 0 2px 10px rgba(242, 122, 26, .34), 0 0 0 7px rgba(242, 122, 26, .10); }
}
@keyframes tipsBulb { 0%, 86%, 100% { transform: rotate(0) scale(1); } 92% { transform: rotate(-11deg) scale(1.14); } }
@keyframes tipsSheen { 0%, 62% { left: -60%; } 86%, 100% { left: 125%; } }


/* ══════════════════════════════════════════════════════════════════
   2 — MODAL KABUĞU
   ══════════════════════════════════════════════════════════════════ */

.k-scrim {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(3, 21, 56, .62);
  backdrop-filter: blur(5px) saturate(.8);
  opacity: 0; transition: opacity .3s var(--hiz);
}
.k-scrim.is-on { opacity: 1; }
.k-scrim[hidden] { display: none; }

.k-root {
  position: fixed; inset: 0; z-index: 100;
  display: grid; place-items: center;
  padding: 26px;
  pointer-events: none;
}
.k-root[hidden] { display: none; }

.k-dialog {
  pointer-events: auto;
  width: min(1264px, 100%);
  height: min(730px, calc(100vh - 52px));
  display: grid;
  grid-template-columns: 268px 1fr;
  background: var(--yuzey);
  border-radius: 22px;
  overflow: hidden;
  box-shadow: 0 44px 110px rgba(3, 21, 56, .44), 0 0 0 1px rgba(3, 21, 56, .08);
  opacity: 0; transform: translateY(16px) scale(.985);
  transition: opacity .34s var(--hiz), transform .42s var(--yay);
}
.k-root.is-on .k-dialog { opacity: 1; transform: none; }


/* ── 2a — SOL RAY ──────────────────────────────────────────────── */

.k-rail {
  position: relative; isolation: isolate;
  background: var(--lacivert);
  color: #c3d1e6;
  padding: 26px 20px 20px;
  display: flex; flex-direction: column; gap: 22px;
  overflow: hidden;
}
.k-rail::before {            /* atmosfer: köşe ışığı */
  content: ""; position: absolute; inset: -40% -60% auto -40%; height: 90%;
  background: radial-gradient(ellipse at 30% 0%, rgba(1, 117, 228, .42), transparent 64%);
  z-index: -2;
}
.k-rail::after {             /* grenli doku */
  content: ""; position: absolute; inset: 0; z-index: -1; opacity: .05;
  background-image: radial-gradient(#fff 1px, transparent 1px);
  background-size: 4px 4px;
}

.k-rail__kicker {
  display: block; font-size: 9.5px; font-weight: 800; letter-spacing: .2em;
  text-transform: uppercase; color: #5f7fab;
}
.k-rail__title {
  display: block; margin-top: 8px;
  font-family: var(--ff-display); font-weight: 700; font-size: 25px; line-height: 1.04;
  letter-spacing: -.055em; color: #fff;
}
.k-rail__sub { display: block; margin-top: 10px; font-size: 11.5px; line-height: 1.5; color: #7f99bd; }

/* omurga */
.k-spine { list-style: none; margin: 0; padding: 0; flex: 1; position: relative; }
.k-spine::before {
  content: ""; position: absolute; left: 13px; top: 14px; bottom: 14px; width: 2px;
  background: rgba(255, 255, 255, .10); border-radius: 2px;
}
.k-spine__fill {
  position: absolute; left: 13px; top: 14px; width: 2px; height: 0;
  background: linear-gradient(180deg, var(--mavi-acik), var(--mavi));
  border-radius: 2px;
  transition: height .55s var(--hiz);
  box-shadow: 0 0 10px rgba(115, 183, 254, .6);
}

.k-node {
  position: relative; display: flex; align-items: flex-start; gap: 13px;
  padding: 9px 8px 9px 0; margin-left: 0; cursor: pointer;
  border: 0; background: none; width: 100%; text-align: left;
  color: inherit; font: inherit; border-radius: 10px;
  transition: background .18s var(--hiz);
}
.k-node:hover { background: rgba(255, 255, 255, .05); }
.k-node:focus-visible { outline: 2px solid var(--mavi-acik); outline-offset: 1px; }

.k-node__dot {
  position: relative; z-index: 1; flex-shrink: 0;
  width: 28px; height: 28px; border-radius: 50%;
  display: grid; place-items: center;
  background: #0c2149; border: 2px solid rgba(255, 255, 255, .14);
  font-family: var(--ff-display); font-size: 10.5px; font-weight: 700; color: #7f99bd;
  transition: all .34s var(--yay);
}
.k-node__meta { flex: 1; min-width: 0; display: block; }
.k-node__name {
  display: block;
  font-size: 12.5px; font-weight: 600; line-height: 1.3; color: #93a9c8;
  padding-top: 5px; transition: color .2s var(--hiz);
}
.k-node__bar {
  display: block; height: 2px; margin-top: 7px; border-radius: 2px;
  background: rgba(255, 255, 255, .12); overflow: hidden;
}
.k-node__bar i { display: block; height: 100%; width: 0; background: var(--mavi-acik);
  transition: width .45s var(--hiz); }

.k-node.is-done .k-node__dot { background: var(--mavi); border-color: var(--mavi); color: #fff; }
.k-node.is-done .k-node__name { color: #bed3ee; }

.k-node.is-active .k-node__dot {
  background: var(--turuncu); border-color: var(--turuncu); color: #fff;
  transform: scale(1.14);
  box-shadow: 0 0 0 5px rgba(242, 122, 26, .20);
}
.k-node.is-active .k-node__name { color: #fff; font-weight: 800; }

.k-rail__foot { display: flex; flex-direction: column; gap: 9px; }
.k-gauge { height: 4px; border-radius: 4px; background: rgba(255, 255, 255, .11); overflow: hidden; }
.k-gauge__fill {
  display: block; height: 100%; width: 0;
  background: linear-gradient(90deg, var(--mavi), var(--turuncu));
  border-radius: 4px; transition: width .5s var(--hiz);
}
.k-rail__progress {
  font-family: var(--ff-display); font-size: 10px; font-weight: 600;
  letter-spacing: .04em; color: #6f8bb0;
}


/* ── 2b — SAĞ SAHNE ────────────────────────────────────────────── */

.k-stage {
  display: flex; flex-direction: column; min-width: 0;
  background:
    radial-gradient(1100px 420px at 88% -12%, rgba(1, 117, 228, .07), transparent 62%),
    var(--yuzey);
}

.k-stage__top {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 18px 24px 12px;
}
.k-crumb { display: flex; align-items: center; gap: 9px; min-width: 0; }
.k-crumb__topic {
  font-family: var(--ff-display); font-size: 11px; font-weight: 600; letter-spacing: -.02em;
  color: var(--lacivert);
  background: var(--mavi-sis); border-radius: 7px; padding: 5px 10px;
  white-space: nowrap;
}
.k-crumb__sep { color: var(--murekkep-3); font-size: 13px; }
.k-crumb__step {
  font-size: 12px; font-weight: 600; color: var(--murekkep-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.k-stage__tools { display: flex; align-items: center; gap: 9px; flex-shrink: 0; }
.k-panel-link {
  display: inline-flex; align-items: center; gap: 6px;
  height: 32px; padding: 0 13px; border-radius: 9px;
  background: var(--lacivert); color: #fff; text-decoration: none;
  font-size: 12px; font-weight: 700;
  transition: background .18s var(--hiz), transform .18s var(--yay);
}
.k-panel-link:hover { background: var(--lacivert-2); transform: translateY(-1px); }
.k-close {
  width: 32px; height: 32px; border-radius: 9px; border: 1px solid var(--cizgi);
  background: var(--yuzey); color: var(--murekkep-2); cursor: pointer;
  display: grid; place-items: center;
  transition: all .18s var(--hiz);
}
.k-close:hover { background: #fdecec; border-color: #f7c9c9; color: #dc2626; }

/* adım noktaları */
.k-dots { display: flex; gap: 5px; padding: 0 24px 16px; }
.k-dots__i {
  flex: 1; height: 3.5px; border-radius: 3px; border: 0; padding: 0; cursor: pointer;
  background: var(--cizgi); position: relative; overflow: hidden;
  transition: background .2s var(--hiz);
}
.k-dots__i::after {
  content: ""; position: absolute; inset: 0; width: 0;
  background: var(--mavi); border-radius: 3px;
  transition: width .4s var(--hiz);
}
.k-dots__i.is-done::after { width: 100%; }
.k-dots__i.is-active { background: var(--turuncu-sis); }
.k-dots__i.is-active::after { width: 100%; background: var(--turuncu); }
.k-dots__i:focus-visible { outline: 2px solid var(--mavi); outline-offset: 3px; }

/* gövde */
.k-body {
  position: relative; flex: 1; min-height: 0;
  display: grid; grid-template-columns: minmax(0, 37%) minmax(0, 63%);
  gap: 26px; padding: 4px 26px 8px;
  overflow: hidden;
}

.k-ghost {
  position: absolute; left: -16px; bottom: -58px; z-index: 0; pointer-events: none;
  font-family: var(--ff-display); font-weight: 900; font-size: 210px; line-height: .8;
  letter-spacing: -.07em; color: rgba(3, 21, 56, .042);
}

.k-col { position: relative; z-index: 1; min-width: 0; overflow-y: auto; padding-bottom: 8px; }
.k-col::-webkit-scrollbar { width: 6px; }
.k-col::-webkit-scrollbar-thumb { background: #dde4ee; border-radius: 6px; }

.k-eyebrow {
  margin: 0 0 7px;
  font-family: var(--ff-display); font-size: 9.5px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--turuncu);
}
.k-title {
  margin: 0 0 10px;
  font-family: var(--ff-display); font-weight: 600; font-size: 23px; line-height: 1.16;
  letter-spacing: -.055em; color: var(--lacivert);
}
.k-lead { margin: 0 0 15px; font-size: 13.5px; line-height: 1.62; color: var(--murekkep-2); }
.k-lead b { color: var(--lacivert); font-weight: 800; }

.k-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.k-list li {
  position: relative; padding-left: 21px;
  font-size: 12.8px; line-height: 1.6; color: var(--murekkep-2);
}
.k-list li b { color: var(--lacivert); font-weight: 800; }
.k-list li::before {
  content: ""; position: absolute; left: 1px; top: 7px;
  width: 7px; height: 7px; border-radius: 2px;
  background: var(--mavi); transform: rotate(45deg);
}

/* sayaç */
.k-num {
  display: inline-block;
  font-family: var(--ff-display); font-weight: 700; font-size: 1.04em;
  letter-spacing: -.03em; color: var(--turuncu);
  font-variant-numeric: tabular-nums;
}

.k-why {
  margin-top: 18px; padding: 13px 15px;
  background: linear-gradient(135deg, var(--mavi-sis), #f4f9ff);
  border: 1px solid #cfe5ff; border-radius: 13px;
}
.k-why__tag {
  display: inline-block; margin-bottom: 6px;
  font-family: var(--ff-display); font-size: 8.5px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--mavi-koyu);
}
.k-why__text { margin: 0; font-size: 12.2px; line-height: 1.58; color: #1c3d63; }
.k-why__text b { font-weight: 800; }

.k-why[hidden], .k-warn[hidden] { display: none; }
.k-warn {
  display: flex; gap: 10px; margin-top: 13px; padding: 11px 13px;
  background: #fffaf3; border: 1px solid #ffdcb4; border-radius: 12px;
}
.k-warn__icon {
  flex-shrink: 0; width: 17px; height: 17px; border-radius: 50%;
  background: var(--turuncu); color: #fff;
  display: grid; place-items: center;
  font-family: var(--ff-display); font-size: 10px; font-weight: 800;
}
.k-warn__text { margin: 0; font-size: 11.8px; line-height: 1.55; color: #7a4310; }
.k-warn__text b { font-weight: 800; color: #5c3108; }


/* ── 2c — EKRAN GÖRÜNTÜSÜ SAHNESİ ──────────────────────────────── */

.k-col--media {
  display: flex; flex-direction: column; justify-content: flex-start;
  padding-top: 26px; overflow: hidden;
}

/* --ar = görselin en/boy oranı; JS her adımda yazar.
   Çerçeve, 390px'lik görüntü yüksekliğini aşmayacak şekilde daraltılır →
   img her zaman kutuyu TAM doldurur, dolayısıyla yüzde-cinsinden vurgu
   koordinatları görselle birebir hizalanır (letterbox YOK). */
.k-shot { --ar: 1.6; margin: 0; display: flex; flex-direction: column; gap: 9px; align-items: center; }
.k-shot[hidden] { display: none; }

.k-shot__frame {
  width: 100%;
  max-width: calc(440px * var(--ar));
  border: 1px solid var(--cizgi);
  border-radius: 13px;
  background: var(--yuzey);
  box-shadow: var(--golge-sert);
  overflow: hidden;
}
.k-shot__chrome {
  display: flex; align-items: center; gap: 5px;
  height: 27px; padding: 0 11px;
  background: #f7f9fc; border-bottom: 1px solid var(--cizgi-2);
}
.k-shot__chrome span { width: 7px; height: 7px; border-radius: 50%; background: #d9e1ec; }
.k-shot__chrome em {
  font-style: normal; font-size: 9.5px; font-weight: 600;
  color: var(--murekkep-3); letter-spacing: .01em; margin-left: 9px;
}
/* Eski "Gerçek ekran" düğmesi KALDIRILDI — çıplak tarayıcı butonu gibi
   duruyordu ve tasarıma yabancıydı. Yerine, yalnız kaynaksız (temsilî)
   çizimlerde görünen küçük, şerite gömülü bir etiket var. */
.k-shot__tag {
  margin-left: auto; padding: 2.5px 8px; border-radius: 5px;
  background: #e9eef5; color: #8795a8;
  font-family: var(--ff-body); font-size: 8.5px; font-weight: 800;
  letter-spacing: .07em; text-transform: uppercase;
}
.k-shot__tag[hidden] { display: none; }

.k-shot__view {
  position: relative; overflow: hidden;
  background: #fbfcfe;
  aspect-ratio: var(--ar);
  display: grid; place-items: center;
}
/* mockup kabı: genişlik/yükseklik JS'ten (tasarım px), sol-üstten ölçeklenir */
.k-shot__zoom {
  position: absolute; top: 0; left: 0;
  transform-origin: 0 0;
  transform: scale(1);
  transition: transform 1.25s cubic-bezier(.3, .72, .18, 1);
  will-change: transform;
}

/* GERÇEK png — yalnız "Gerçek ekran" düğmesiyle. ASLA büyütülmez:
   width/height auto + max 100% → sadece küçültme olur, yani hep net. */
.k-shot__real {
  position: relative; z-index: 2;
  width: auto; height: auto; max-width: 100%; max-height: 100%;
  display: block; object-fit: contain;
}
.k-shot__real[hidden] { display: none; }

/* spotlight: koyu maske + delik.
   --inv = 1/(toplam ölçek) → kenarlık ve halka her yakınlaşmada ~2px görünür. */
@property --inv { syntax: "<number>"; inherits: true; initial-value: 1; }
.k-spot {
  --inv: 1;
  position: absolute; z-index: 1;
  border-radius: calc(8px * var(--inv));
  box-shadow: 0 0 0 9999px rgba(3, 21, 56, .58);
  opacity: 0;
  transition: opacity .45s var(--hiz), --inv 1.25s cubic-bezier(.3, .72, .18, 1);
  pointer-events: none;
}
.k-spot[hidden] { display: none; }
.k-spot.is-on { opacity: 1; }
.k-spot__ring {
  position: absolute; inset: 0; border-radius: inherit;
  border: calc(2px * var(--inv)) solid var(--turuncu);
  box-shadow: 0 0 0 calc(4px * var(--inv)) rgba(242, 122, 26, .25),
              inset 0 0 calc(22px * var(--inv)) rgba(242, 122, 26, .18);
}
.k-spot__ring::after {
  content: ""; position: absolute; inset: calc(-4px * var(--inv)); border-radius: inherit;
  border: calc(2px * var(--inv)) solid var(--turuncu);
  animation: spotPulse 2.1s var(--hiz) infinite;
}
@keyframes spotPulse {
  0%   { transform: scale(1);    opacity: .85; }
  70%  { transform: scale(1.085); opacity: 0; }
  100% { transform: scale(1.085); opacity: 0; }
}

.k-shot__cap { font-size: 10px; line-height: 1.45; color: var(--murekkep-3); }


/* ── 2d — ÇİZİMLER (ekran görüntüsü olmayan adımlar) ───────────── */

.k-draw {
  display: flex; flex-direction: column; gap: 12px;
  flex: 1; min-height: 0; overflow-y: auto; padding-right: 4px;
}
.k-draw[hidden] { display: none; }
.k-draw::-webkit-scrollbar { width: 6px; }
.k-draw::-webkit-scrollbar-thumb { background: #dde4ee; border-radius: 6px; }

/* rozetler */
.kd-badges { display: flex; flex-direction: column; gap: 11px; }
.kd-badge {
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: 13px;
  padding: 14px 16px; border-radius: 15px;
  background: var(--yuzey); border: 1px solid var(--cizgi);
  box-shadow: var(--golge-kart);
}
.kd-badge::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  background: var(--kd-renk);
}
.kd-badge__chip {
  flex-shrink: 0; position: relative;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px 7px 9px; border-radius: 999px;
  background: var(--kd-renk); color: #fff;
  font-family: var(--ff-display); font-size: 10.5px; font-weight: 700; letter-spacing: -.02em;
  box-shadow: 0 4px 14px color-mix(in srgb, var(--kd-renk) 38%, transparent);
}
.kd-badge__chip svg { flex-shrink: 0; }
.kd-badge__meta { min-width: 0; }
.kd-badge__tier {
  display: flex; gap: 3px; margin-bottom: 5px;
}
.kd-badge__tier i {
  width: 15px; height: 4px; border-radius: 3px; background: #e3e9f2;
}
.kd-badge__tier i.on { background: var(--kd-renk); }
.kd-badge__note { font-size: 11.5px; line-height: 1.45; color: var(--murekkep-2); }

/* fiyat ekranı kartları */
.kd-screens { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.kd-screen {
  display: flex; align-items: center; gap: 9px;
  padding: 11px 13px; border-radius: 12px;
  background: var(--yuzey); border: 1px solid var(--cizgi);
  font-size: 11.8px; font-weight: 700; color: var(--lacivert);
  box-shadow: var(--golge-kart);
}
.kd-screen__n {
  width: 20px; height: 20px; flex-shrink: 0; border-radius: 6px;
  background: var(--mavi-sis); color: var(--mavi-koyu);
  display: grid; place-items: center;
  font-family: var(--ff-display); font-size: 9.5px; font-weight: 700;
}
.kd-screens__all {
  grid-column: 1 / -1; text-align: center; padding: 9px;
  border-radius: 11px; background: var(--mavi-sis);
  font-size: 11.5px; font-weight: 700; color: var(--mavi-koyu);
}

/* aralık göstergesi */
.kd-range { padding: 18px 16px 14px; border-radius: 15px; background: var(--yuzey);
  border: 1px solid var(--cizgi); box-shadow: var(--golge-kart); }
.kd-range__track {
  position: relative; height: 10px; border-radius: 10px;
  background: linear-gradient(90deg, #fee2e2 0 22%, #dcfce7 22% 62%, #fee2e2 62% 100%);
}
.kd-range__ok {
  position: absolute; left: 22%; width: 40%; top: -3px; bottom: -3px;
  border: 2px solid #16a34a; border-radius: 9px;
  box-shadow: 0 0 0 3px rgba(22, 163, 74, .12);
}
.kd-range__pin {
  position: absolute; top: -9px; width: 16px; height: 28px; margin-left: -8px;
  border-radius: 5px; background: var(--lacivert);
  box-shadow: 0 3px 9px rgba(3, 21, 56, .3);
  left: 42%;
  animation: pinDrift 5.2s ease-in-out infinite;
}
.kd-range__pin::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: 2px; height: 11px;
  margin: -5.5px 0 0 -1px; border-radius: 2px; background: rgba(255, 255, 255, .55);
}
@keyframes pinDrift {
  0%, 40%  { left: 42%; }
  58%, 72% { left: 76%; }
  90%, 100% { left: 42%; }
}
.kd-range__legend { display: flex; justify-content: space-between; margin-top: 14px; font-size: 10.5px; font-weight: 700; }
.kd-range__legend span:nth-child(1), .kd-range__legend span:nth-child(3) { color: #b91c1c; }
.kd-range__legend span:nth-child(2) { color: #15803d; }
.kd-range__msg { margin: 11px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--murekkep-2); }

/* haftalık takvim */
.kd-week { padding: 16px; border-radius: 15px; background: var(--yuzey);
  border: 1px solid var(--cizgi); box-shadow: var(--golge-kart); }
.kd-week__head { display: flex; align-items: center; gap: 9px; margin-bottom: 13px; }
.kd-week__icon {
  width: 32px; height: 32px; border-radius: 10px; flex-shrink: 0;
  background: var(--mavi-sis); color: var(--mavi-koyu);
  display: grid; place-items: center;
  animation: calTick 4s var(--hiz) infinite;
}
@keyframes calTick { 0%, 78%, 100% { transform: rotate(0); } 86% { transform: rotate(-9deg) scale(1.08); } 93% { transform: rotate(6deg); } }
.kd-week__title { font-family: var(--ff-display); font-size: 12.5px; font-weight: 600;
  letter-spacing: -.03em; color: var(--lacivert); }
.kd-week__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px; }
.kd-week__d {
  aspect-ratio: 1; border-radius: 8px; background: #f3f6fb;
  display: grid; place-items: center;
  font-family: var(--ff-display); font-size: 9.5px; font-weight: 600; color: var(--murekkep-3);
}
.kd-week__d.on {
  background: var(--mavi); color: #fff;
  animation: dayPop 4.4s var(--yay) infinite;
}
@keyframes dayPop { 0%, 72%, 100% { transform: scale(1); } 80% { transform: scale(1.16); } }
.kd-week__foot { margin: 12px 0 0; font-size: 11.3px; line-height: 1.5; color: var(--murekkep-2); }

/* komisyon tablosu */
.kd-table { border: 1px solid var(--cizgi); border-radius: 14px; overflow: hidden;
  background: var(--yuzey); box-shadow: var(--golge-kart); }
.kd-table__head {
  display: grid; grid-template-columns: 1fr 86px;
  padding: 9px 13px; background: var(--lacivert); color: #adc1dc;
  font-family: var(--ff-display); font-size: 8.5px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
}
.kd-table__head span:last-child { text-align: right; }
.kd-row {
  display: grid; grid-template-columns: 1fr 76px; align-items: center;
  padding: 6px 13px 7px; border-top: 1px solid var(--cizgi-2);
  opacity: 0; transform: translateX(-9px);
  animation: rowIn .42s var(--hiz) forwards;
}
@keyframes rowIn { to { opacity: 1; transform: none; } }
.kd-row__cat { display: block; font-size: 11.4px; font-weight: 800; color: var(--lacivert); }
.kd-row__grp { display: block; font-size: 10.2px; line-height: 1.35; color: var(--murekkep-3); margin-top: 1px; }
.kd-row__pct {
  text-align: right;
  font-family: var(--ff-display); font-size: 13px; font-weight: 700;
  letter-spacing: -.04em; color: var(--mavi-koyu);
  font-variant-numeric: tabular-nums;
}
.kd-row__bar { grid-column: 1 / -1; height: 2.5px; border-radius: 3px; background: var(--cizgi-2); margin-top: 4px; overflow: hidden; }
.kd-row__bar i { display: block; height: 100%; width: 0; border-radius: 3px;
  background: linear-gradient(90deg, var(--mavi-acik), var(--mavi));
  animation: barGrow .85s var(--hiz) forwards; }
@keyframes barGrow { to { width: var(--w); } }
.kd-row.is-low { background: #f3fbf5; }
.kd-row.is-high { background: #fff7f1; }
.kd-row.is-high .kd-row__pct { color: var(--turuncu); }
.kd-row.is-pop { background: var(--mavi-sis); }
.kd-tag {
  display: inline-block; margin-left: 6px; padding: 1.5px 6px; border-radius: 5px;
  font-family: var(--ff-body); font-size: 8.5px; font-weight: 800;
  letter-spacing: .04em; text-transform: uppercase;
  background: var(--lacivert); color: #fff; vertical-align: middle;
}
.kd-note { font-size: 10.5px; line-height: 1.5; color: var(--murekkep-3); }

/* marka komisyonu */
.kd-brand { display: flex; flex-direction: column; gap: 9px; }
.kd-brand__base {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 12px 14px; border-radius: 13px;
  background: var(--lacivert); color: #fff;
}
.kd-brand__base small { font-size: 10.5px; color: #9db4d4; display: block; margin-bottom: 3px; }
.kd-brand__base b { font-family: var(--ff-display); font-size: 12px; font-weight: 600; letter-spacing: -.03em; }
.kd-brand__pct { font-family: var(--ff-display); font-size: 21px; font-weight: 700; letter-spacing: -.05em; }
.kd-brand__row {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 13px; border-radius: 12px;
  background: var(--yuzey); border: 1px solid var(--cizgi);
  opacity: 0; transform: translateY(7px);
  animation: rowIn .4s var(--hiz) forwards;
}
.kd-brand__p {
  flex-shrink: 0; min-width: 52px; text-align: center;
  padding: 5px 9px; border-radius: 8px;
  background: #ecfdf3; color: #15803d;
  font-family: var(--ff-display); font-size: 12.5px; font-weight: 700; letter-spacing: -.04em;
}
.kd-brand__ex { font-size: 11px; line-height: 1.45; color: var(--murekkep-2); }
.kd-brand__save { font-size: 10px; font-weight: 800; color: #15803d; white-space: nowrap; margin-left: auto; }

/* hesap */
.kd-calc { display: flex; flex-direction: column; gap: 10px; }
.kd-calc__card {
  padding: 15px 16px; border-radius: 15px; background: var(--yuzey);
  border: 1px solid var(--cizgi); box-shadow: var(--golge-kart);
}
.kd-calc__card.is-alt { background: linear-gradient(135deg, var(--turuncu-sis), #fffaf4); border-color: #ffdcb4; }
.kd-calc__tag {
  font-family: var(--ff-display); font-size: 8.5px; font-weight: 700;
  letter-spacing: .15em; text-transform: uppercase; color: var(--murekkep-3);
}
.kd-calc__line {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 9px;
  font-family: var(--ff-display); font-size: 16px; font-weight: 600; letter-spacing: -.04em;
  color: var(--lacivert);
}
.kd-calc__op { color: var(--murekkep-3); font-weight: 400; }
.kd-calc__res { color: var(--turuncu); }
.kd-calc__foot { margin: 9px 0 0; font-size: 11.2px; line-height: 1.5; color: var(--murekkep-2); }

/* fatura takvimi */
.kd-bill { padding: 16px; border-radius: 15px; background: var(--yuzey);
  border: 1px solid var(--cizgi); box-shadow: var(--golge-kart); }
.kd-bill__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.kd-bill__d {
  aspect-ratio: 1; border-radius: 7px; background: #f5f7fb;
  display: grid; place-items: center;
  font-size: 9.5px; font-weight: 600; color: var(--murekkep-3);
}
.kd-bill__d.cut {
  background: var(--mavi); color: #fff;
  font-family: var(--ff-display); font-weight: 700;
  animation: billPing 5s var(--hiz) infinite;
  animation-delay: var(--d);
}
@keyframes billPing {
  0%, 60%, 100% { box-shadow: 0 0 0 0 rgba(1, 117, 228, 0); }
  70%           { box-shadow: 0 0 0 5px rgba(1, 117, 228, .28); }
}
.kd-bill__legend { display: flex; gap: 14px; margin-top: 12px; font-size: 10.5px; color: var(--murekkep-2); }
.kd-bill__legend span { display: inline-flex; align-items: center; gap: 5px; font-weight: 600; }
.kd-bill__legend i { width: 9px; height: 9px; border-radius: 3px; background: var(--mavi); }

/* örnek kurulum senaryoları */
.kd-scn { padding: 16px; border-radius: 15px; background: var(--yuzey);
  border: 1px solid var(--cizgi); box-shadow: var(--golge-kart); }
.kd-scn__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.kd-scn__f {
  display: flex; flex-direction: column; gap: 5px; padding: 11px 13px;
  border-radius: 11px; background: var(--mavi-sis);
  opacity: 0; transform: translateY(8px); animation: upIn .45s var(--hiz) forwards;
}
.kd-scn__k { font-size: 9.5px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  color: var(--mavi-koyu); }
.kd-scn__v { font-family: var(--ff-display); font-size: 13.5px; font-weight: 600;
  letter-spacing: -.02em; color: var(--lacivert); }
.k-type {
  display: inline-block; max-width: 100%; overflow: hidden; white-space: nowrap;
  vertical-align: bottom; font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  width: 0; animation: kType .65s steps(var(--ch)) forwards; animation-delay: var(--d);
}
@keyframes kType { to { width: calc(var(--ch) * 1ch); } }

.kd-etki {
  margin-top: 10px; padding: 13px 15px; border-radius: 12px;
  background: var(--turuncu-sis); border: 1px solid #ffdcb4;
  opacity: 0; transform: translateY(8px); animation: upIn .45s var(--hiz) forwards;
}
.kd-etki b { display: block; font-size: 9.5px; font-weight: 800; letter-spacing: .05em;
  text-transform: uppercase; color: var(--turuncu); margin-bottom: 5px; }
.kd-etki p { margin: 0; font-size: 11.8px; line-height: 1.55; color: #5c3108; }

/* taktik kartları */
.kd-tactics { display: flex; flex-direction: column; gap: 10px; }
.kd-tactic {
  display: flex; gap: 11px; align-items: flex-start; padding: 13px 15px;
  border-radius: 13px; background: var(--yuzey); border: 1px solid var(--cizgi);
  box-shadow: var(--golge-kart);
  opacity: 0; transform: translateY(8px); animation: upIn .45s var(--hiz) forwards;
}
.kd-tactic__ico {
  flex-shrink: 0; width: 26px; height: 26px; border-radius: 8px; margin-top: 1px;
  background: var(--mavi-sis); color: var(--mavi-koyu); display: grid; place-items: center;
}
.kd-tactic__b { min-width: 0; }
.kd-tactic__b p { margin: 0 0 5px; font-size: 12px; line-height: 1.5; color: var(--lacivert); }
.kd-tactic__src { font-size: 9.5px; font-weight: 700; letter-spacing: .03em;
  text-transform: uppercase; color: var(--murekkep-3); }


/* ── 2e — ALT ÇUBUK ────────────────────────────────────────────── */

.k-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 13px 24px 16px;
  border-top: 1px solid var(--cizgi-2);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0), #fbfcfe);
}

.k-never { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; }
.k-never input { position: absolute; opacity: 0; width: 0; height: 0; }
.k-never__box {
  width: 17px; height: 17px; border-radius: 5px; border: 1.8px solid #cbd5e1;
  background: var(--yuzey); position: relative;
  transition: all .18s var(--hiz);
}
.k-never__box::after {
  content: ""; position: absolute; left: 5px; top: 1.5px; width: 4px; height: 8px;
  border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg) scale(0);
  transition: transform .18s var(--yay);
}
.k-never input:checked + .k-never__box { background: var(--mavi); border-color: var(--mavi); }
.k-never input:checked + .k-never__box::after { transform: rotate(45deg) scale(1); }
.k-never input:focus-visible + .k-never__box { outline: 2px solid var(--mavi); outline-offset: 2px; }
.k-never__label { font-size: 12px; font-weight: 600; color: var(--murekkep-2); }

.k-nav { display: flex; gap: 9px; }
.k-btn {
  display: inline-flex; align-items: center; gap: 7px;
  height: 38px; padding: 0 17px; border-radius: 11px; cursor: pointer;
  font-family: var(--ff-body); font-size: 13px; font-weight: 800; letter-spacing: -.01em;
  border: 1px solid transparent;
  transition: all .2s var(--hiz), transform .18s var(--yay);
}
.k-btn:focus-visible { outline: 3px solid rgba(1, 117, 228, .4); outline-offset: 2px; }
.k-btn--ghost { background: var(--yuzey); border-color: var(--cizgi); color: var(--murekkep-2); }
.k-btn--ghost:hover:not(:disabled) { border-color: #cbd8e8; color: var(--lacivert); transform: translateY(-1px); }
.k-btn--ghost:disabled { opacity: .36; cursor: not-allowed; }
.k-btn--solid {
  background: var(--lacivert); color: #fff;
  box-shadow: 0 4px 14px rgba(3, 21, 56, .22);
}
.k-btn--solid:hover { background: var(--lacivert-2); transform: translateY(-1px);
  box-shadow: 0 8px 20px rgba(3, 21, 56, .3); }
.k-btn--solid.is-final { background: var(--turuncu); box-shadow: 0 4px 14px rgba(242, 122, 26, .34); }
.k-btn--solid.is-final:hover { background: #e06d11; }


/* ── 2f — GİRİŞ ANİMASYONLARI ──────────────────────────────────── */

.k-anim-up { opacity: 0; transform: translateY(12px); animation: upIn .5s var(--hiz) forwards; }
@keyframes upIn { to { opacity: 1; transform: none; } }

.k-shot.k-anim-slide { opacity: 0; transform: translateX(26px) scale(.975);
  animation: slideIn .58s var(--hiz) forwards; }
@keyframes slideIn { to { opacity: 1; transform: none; } }


/* ── 2g — DUYARLILIK ───────────────────────────────────────────── */

@media (max-width: 1080px) {
  .k-dialog { grid-template-columns: 1fr; height: calc(100vh - 36px); }
  .k-rail { flex-direction: row; align-items: center; gap: 16px; padding: 14px 18px; overflow-x: auto; }
  .k-rail__head, .k-rail__foot { display: none; }
  .k-spine { display: flex; gap: 6px; }
  .k-spine::before, .k-spine__fill { display: none; }
  .k-node__bar { display: none; }
  .k-body { grid-template-columns: 1fr; overflow-y: auto; }
  .k-ghost { display: none; }
}
@media (max-width: 760px) {
  .tm-tips-btn__label { display: none; }
  .k-root { padding: 10px; }
}


/* ── 2h — prefers-reduced-motion: TÜM HAREKET KAPALI ───────────── */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .k-anim-up, .k-shot.k-anim-slide { opacity: 1 !important; transform: none !important; }
  .k-shot__zoom { transform: none !important; }
  .kd-row, .kd-brand__row { opacity: 1 !important; transform: none !important; }
  .kd-row__bar i { width: var(--w) !important; }
  .k-spot { opacity: 1 !important; }
  .k-spot__ring::after { display: none; }
  .kd-range__pin { left: 42% !important; }
  .kd-scn__f, .kd-etki, .kd-tactic { opacity: 1 !important; transform: none !important; }
  .k-type { width: calc(var(--ch) * 1ch) !important; animation: none !important; }
}


/* ══════════════════════════════════════════════════════════════════
   3 — TAKTİK KARTLARI (💡) ve ÖRNEK KURULUM (📋)
   ══════════════════════════════════════════════════════════════════ */

.k-side { margin-top: 16px; }
.k-side[hidden] { display: none; }

/* — taktikler (medya sütunu) — */
.kd-tak { display: flex; flex-direction: column; gap: 11px; }
.kd-tak__k {
  display: flex; gap: 13px; align-items: flex-start;
  padding: 14px 16px; border-radius: 14px;
  background: var(--yuzey); border: 1px solid var(--cizgi);
  box-shadow: var(--golge-kart);
}
.kd-tak__n {
  flex-shrink: 0; width: 23px; height: 23px; border-radius: 8px;
  background: var(--turuncu-sis); color: var(--turuncu);
  display: grid; place-items: center;
  font-family: var(--ff-display); font-size: 10.5px; font-weight: 700;
}
.kd-tak__b { min-width: 0; }
.kd-tak__b b { display: block; font-size: 12.8px; font-weight: 800; color: var(--lacivert); }
.kd-tak__b em {
  display: block; margin-top: 5px; font-style: normal;
  font-size: 12px; line-height: 1.55; color: var(--murekkep-2);
}
.kd-tak__b em b { display: inline; color: var(--turuncu); font-weight: 800; }
.kd-tak__s {
  display: inline-block; margin-top: 8px; padding: 2.5px 8px; border-radius: 6px;
  font-size: 9.5px; font-weight: 800; letter-spacing: .02em;
  background: #f1f4f9; color: var(--murekkep-3);
}
.kd-tak__s.is-kaynak { background: var(--mavi-sis); color: var(--mavi-koyu); }

/* — örnek kurulum (metin sütunu) — */
.kd-orn {
  padding: 15px 16px 14px; border-radius: 15px;
  background: linear-gradient(145deg, #fffaf4, #fff);
  border: 1px solid #ffdcb4;
}
.kd-orn__h { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin-bottom: 11px; }
.kd-orn__t {
  padding: 3px 9px; border-radius: 6px; background: var(--turuncu); color: #fff;
  font-family: var(--ff-display); font-size: 9.5px; font-weight: 700; letter-spacing: -.01em;
}
.kd-orn__h b { font-size: 13.5px; font-weight: 800; color: var(--lacivert); }
.kd-orn__d { margin: 0; display: flex; flex-direction: column; gap: 6px; }
.kd-orn__d > div {
  display: grid; grid-template-columns: 112px 1fr; gap: 10px; align-items: baseline;
  padding-bottom: 6px; border-bottom: 1px dashed #f0dcc4;
}
.kd-orn__d dt { font-size: 10.5px; font-weight: 700; color: #a06a2c; letter-spacing: .01em; }
.kd-orn__d dd { margin: 0; font-size: 12.2px; font-weight: 700; color: var(--lacivert); }
.kd-orn__e {
  display: flex; align-items: baseline; gap: 9px; margin-top: 11px;
  font-size: 11.8px; line-height: 1.5; color: #1c3d63;
  background: var(--mavi-sis); border-radius: 10px; padding: 9px 12px;
}
.kd-orn__el {
  flex-shrink: 0; font-family: var(--ff-display); font-size: 8.5px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--mavi-koyu);
}
.kd-orn__u {
  margin: 9px 0 0; font-size: 11px; line-height: 1.5; color: #8a4b12;
  padding-left: 16px; position: relative;
}
.kd-orn__u::before { content: "⚠"; position: absolute; left: 0; top: 0; }
.kd-orn .kd-note { margin-top: 9px; }

/* — komisyon net kazanç tablosu — */
.kd-net { border: 1px solid var(--cizgi); border-radius: 14px; overflow: hidden;
  background: var(--yuzey); box-shadow: var(--golge-kart); }
.kd-net__h, .kd-net__r {
  display: grid; grid-template-columns: minmax(0, 1.5fr) 80px 110px 118px;
  align-items: center; gap: 10px; padding: 9px 14px;
}
.kd-net__h { background: var(--lacivert); color: #adc1dc;
  font-family: var(--ff-display); font-size: 8.5px; font-weight: 700;
  letter-spacing: .11em; text-transform: uppercase; }
.kd-net__h span:not(:first-child), .kd-net__r span:not(:first-child) { text-align: right; }
.kd-net__r { border-top: 1px solid var(--cizgi-2); font-size: 12px; color: var(--murekkep-2);
  opacity: 0; transform: translateX(-8px); animation: rowIn .42s var(--hiz) forwards;
  font-variant-numeric: tabular-nums; }
.kd-net__r b { display: block; font-family: var(--ff-display); font-size: 13px;
  font-weight: 700; letter-spacing: -.04em; color: var(--lacivert); }
.kd-net__r em { display: block; font-style: normal; font-size: 10.2px;
  color: var(--murekkep-3); margin-top: 1px; }
.kd-net__n { font-family: var(--ff-display); font-size: 13.5px; font-weight: 700;
  letter-spacing: -.04em; color: var(--mavi-koyu); }
.kd-net__r.is-simdi { background: #f4f7fb; }
.kd-net__r.is-simdi .kd-net__n { color: var(--murekkep-2); }
.kd-net__r.is-en { background: #f1fbf4; }
.kd-net__r.is-en .kd-net__n { color: #15803d; }
.kd-net__b { display: block !important; font-family: var(--ff-body); font-size: 8.5px;
  font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  color: #15803d !important; margin-top: 2px; }
.kd-net__v, .kd-net__w { margin-top: 11px; padding: 11px 14px; border-radius: 12px;
  font-size: 11.8px; line-height: 1.55; }
.kd-net__v { background: #f1fbf4; border: 1px solid #bfe7cd; color: #14532d; }
.kd-net__w { background: #fffaf3; border: 1px solid #ffdcb4; color: #7a4310; }
.kd-net__v b, .kd-net__w b { font-weight: 800; }

/* — Plus komisyon teklifi özeti — */
.kd-plus__h { margin-bottom: 11px; }
.kd-plus__h b { display: block; font-family: var(--ff-display); font-size: 14px;
  font-weight: 600; letter-spacing: -.04em; color: var(--lacivert); }
.kd-plus__h em { display: block; margin-top: 3px; font-style: normal; font-size: 11px;
  color: var(--murekkep-3); }
.kd-plus__t { border: 1px solid var(--cizgi); border-radius: 13px; overflow: hidden;
  background: var(--yuzey); box-shadow: var(--golge-kart); }
.kd-plus__hd, .kd-plus__r { display: grid; grid-template-columns: minmax(0,1fr) 120px 86px;
  gap: 10px; padding: 9px 14px; align-items: center; }
.kd-plus__hd { background: var(--lacivert); color: #adc1dc;
  font-family: var(--ff-display); font-size: 8.5px; font-weight: 700;
  letter-spacing: .11em; text-transform: uppercase; }
.kd-plus__hd span:not(:first-child), .kd-plus__r b, .kd-plus__r u { text-align: right; }
.kd-plus__r { border-top: 1px solid var(--cizgi-2); font-size: 11.8px; color: var(--murekkep-2); }
.kd-plus__r b { font-family: var(--ff-display); font-size: 12.5px; font-weight: 700;
  letter-spacing: -.04em; color: var(--lacivert); }
.kd-plus__r u { text-decoration: none; font-family: var(--ff-display); font-size: 12.5px;
  font-weight: 700; color: var(--murekkep-2); }
.kd-plus__r.is-on { background: linear-gradient(90deg, #fff4ea, #fffaf5); }
.kd-plus__r.is-on b, .kd-plus__r.is-on u { color: var(--turuncu); }
.kd-plus__n { margin-top: 11px; padding: 11px 14px; border-radius: 12px;
  background: var(--mavi-sis); border: 1px solid #cfe5ff;
  font-size: 11.8px; line-height: 1.55; color: #1c3d63; }
.kd-plus__n b { font-weight: 800; }

/* ═══ Trendyol Satıcı Paneli vektör mockup stilleri (.ty-*) — kaynak: mockuplar.css ═══ */
/* ═══════════════════════════════════════════════════════════════════════
   Trendyol Satıcı Paneli mockup stilleri — `.ty-*`
   Tasarım genişliği sabit px; çerçeveye sığdırma `.k-shot__zoom` ölçeğiyle.
   Tüm renkler resmî panel ekran görüntülerinden örneklendi.
   ═══════════════════════════════════════════════════════════════════════ */

.ty {
  --ty-nav: #18212c;
  --ty-util: #0d1620;
  --ty-org: #f27a1a;
  --ty-org-d: #e06d11;
  --ty-org-sf: #fdf0e3;
  --ty-org-br: #f3b273;
  --ty-ink: #293847;
  --ty-ink2: #64748b;
  --ty-ink3: #9aa6b6;
  --ty-line: #dfe4ea;
  --ty-line2: #eef1f5;
  --ty-fill: #f3f5f8;
  --ty-dark: #1f2d3d;
  --ty-blue: #2563eb;
  --ty-blue-sf: #f1f7ff;
  --ty-blue-br: #bcd9ff;
  --ty-pink: #fdeef4;
  --ty-pink-ink: #e6218a;
  --ty-green: #15803d;

  position: relative;
  background: #fff;
  color: var(--ty-ink);
  font-family: "Manrope", system-ui, sans-serif;
  font-size: 13px;
  line-height: 1.45;
  padding: 18px 20px 20px;
  text-align: left;
}
.ty--flush { padding: 0; }
.ty * { box-sizing: border-box; }
.ty svg { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round;
  stroke-linejoin: round; }

/* ── ortak parçalar ──────────────────────────────────────────────── */

.ty-h { margin-bottom: 14px; }
.ty-h b { display: block; font-size: 14.5px; font-weight: 800; color: var(--ty-ink); }
.ty-h em { display: block; margin-top: 4px; font-style: normal; font-size: 12.5px; color: var(--ty-ink3); }

.ty-lbl { font-size: 12.5px; font-weight: 800; color: var(--ty-ink); margin: 14px 0 9px; }
.ty-lbl--b { font-size: 14px; }
.ty-lbl--mt { margin-top: 20px; }
.ty-sub { display: block; font-style: normal; font-size: 11.5px; color: var(--ty-ink3); margin-bottom: 10px; }
.ty-mini { font-style: normal; font-size: 10.5px; color: var(--ty-ink3); }

.ty-sep { height: 10px; background: var(--ty-fill); margin: 18px -20px; border-block: 1px solid var(--ty-line2); }
.ty-blk { }
.ty-row { display: flex; align-items: flex-end; gap: 14px; flex-wrap: wrap; margin-top: 12px; }
.ty-row--mid { align-items: center; }
.ty-sp { flex: 1; }

/* form alanı */
.ty-f { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.ty-f > em { font-style: normal; font-size: 10.5px; font-weight: 600; color: var(--ty-ink3); letter-spacing: .01em; }
.ty-in {
  position: relative; display: flex; align-items: center; gap: 8px;
  height: 38px; padding: 0 11px;
  border: 1px solid var(--ty-line); border-radius: 7px; background: #fff;
  font-size: 12.5px; color: var(--ty-ink3);
}
.ty-in--sel { justify-content: space-between; color: var(--ty-ink); font-weight: 600; }
.ty-in--sel svg { width: 15px; height: 15px; color: var(--ty-ink3); flex-shrink: 0; }
.ty-in--ghost { background: var(--ty-fill); }
.ty-in--val { color: var(--ty-ink); font-weight: 700; }
.ty-se { width: 15px; height: 15px; margin-left: auto; }
.ty-tagic { width: 16px; height: 16px; color: var(--ty-org); stroke-width: 1.6; }

/* radyo */
.ty-rds { display: flex; align-items: center; gap: 24px; flex-wrap: wrap; }
.ty-rd { display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--ty-ink); }
.ty-rd > i, .ty-dot {
  width: 15px; height: 15px; border-radius: 50%; flex-shrink: 0;
  border: 2px solid #c3cbd6; background: #fff;
}
.ty-rd.is-on > i, .ty-card.is-on .ty-dot, .ty-t.is-on .ty-dot {
  border-color: var(--ty-org);
  box-shadow: inset 0 0 0 3px #fff, inset 0 0 0 9px var(--ty-org);
}
.ty-rd b { font-weight: 700; }
.ty-rd.is-on b { color: var(--ty-org); }
.ty-rds--lg .ty-rd b { font-size: 13.5px; }
.ty-i { width: 14px; height: 14px; color: #aeb8c6; flex-shrink: 0; }

/* seçim kartı (pill) */
.ty-cards { display: flex; gap: 14px; flex-wrap: wrap; }
.ty-card {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 12px 15px; border-radius: 9px;
  border: 1px solid var(--ty-line); background: var(--ty-fill);
  font-size: 12.5px; font-weight: 700;
}
.ty-card.is-on { border: 1.6px solid var(--ty-org); background: var(--ty-org-sf); }

/* 4'lü seçenek kartı */
.ty-opts { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
.ty-opt {
  display: flex; flex-direction: column; gap: 10px;
  padding: 15px 16px 18px; border-radius: 11px;
  border: 1px solid var(--ty-line); background: var(--ty-fill);
}
.ty-opt__h { display: flex; align-items: center; gap: 9px; }
.ty-opt__h b { font-size: 14px; font-weight: 800; }
.ty-opt__d { font-style: normal; font-size: 12.3px; line-height: 1.5; color: var(--ty-ink2); }

/* rozet */
.ty-tag {
  font-style: normal; font-size: 10px; font-weight: 800;
  padding: 2px 7px; border-radius: 5px;
  background: var(--ty-org-sf); color: var(--ty-org);
}
.ty-tag--red { background: #fde8e8; color: #d12d2d; margin-left: 7px; }

/* öneri bandı */
.ty-sugg {
  display: flex; gap: 11px; align-items: flex-start;
  padding: 13px 15px; border-radius: 9px;
  border: 1px solid var(--ty-org-br); background: var(--ty-org-sf);
}
.ty-sugg__w { width: 17px; height: 17px; color: var(--ty-org); flex-shrink: 0; margin-top: 16px; }
.ty-sugg__b { flex: 1; min-width: 0; }
.ty-sugg__b b { display: block; font-size: 12.8px; font-weight: 800; color: var(--ty-org); margin-bottom: 5px; }
.ty-sugg__b em { font-style: normal; font-size: 11.4px; line-height: 1.5; color: #7a4f22; display: block; }
.ty-sugg__a {
  flex-shrink: 0; align-self: center;
  font-size: 12.5px; font-weight: 800; color: var(--ty-org);
  text-decoration: underline; text-underline-offset: 3px;
}

/* buton */
.ty-btn {
  display: inline-flex; align-items: center; justify-content: center;
  height: 38px; padding: 0 17px; border-radius: 7px;
  font-size: 12.5px; font-weight: 800; white-space: nowrap;
  border: 1px solid transparent;
}
.ty-btn--org { background: var(--ty-org); color: #fff; }
.ty-btn--dark { background: var(--ty-dark); color: #fff; }
.ty-btn--out { background: #fff; border-color: var(--ty-line); color: var(--ty-ink); }
.ty-btn--outorg { background: #fff; border-color: var(--ty-org); color: var(--ty-org); }
.ty-btn--outred { background: #fff; border-color: #f0b4b4; color: #c0392b; }
.ty-btn--lg { height: 42px; padding: 0 22px; }
.ty-btn--wide { grid-column: 1 / -1; justify-self: end; width: 320px; margin-top: 16px;
  letter-spacing: .04em; }

/* onay kutusu */
.ty-chk { display: inline-flex; align-items: center; gap: 9px; margin-top: 14px;
  font-size: 12.5px; font-weight: 700; color: var(--ty-org); }
.ty-chk i { width: 15px; height: 15px; border-radius: 4px; border: 1.6px solid #c3cbd6; background: #fff; }
.ty-chk.is-on i { background: var(--ty-org); border-color: var(--ty-org);
  box-shadow: inset 0 0 0 2px #fff, inset 0 0 0 9px var(--ty-org); }
.ty-cb { width: 14px; height: 14px; border-radius: 3.5px; border: 1.6px solid #c3cbd6;
  background: #fff; flex-shrink: 0; display: inline-block; }
.ty-cb.is-on { background: var(--ty-org); border-color: var(--ty-org);
  box-shadow: inset 0 0 0 2px #fff, inset 0 0 0 9px var(--ty-org); }

/* küçük resim */
.ty-thumb { width: 38px; height: 38px; border-radius: 6px; background: var(--t);
  display: inline-grid; place-items: center; flex-shrink: 0; color: #8d99a8; }
.ty-thumb svg { width: 20px; height: 20px; }

/* yıldız */
.ty-stars { display: inline-flex; gap: 1px; vertical-align: middle; }
.ty-star { width: 13px; height: 13px; color: #d7dde5; fill: #d7dde5; stroke-width: 0; }
.ty-star.on { color: #ffa500; fill: #ffa500; }

.ty-link { color: var(--ty-org); text-decoration: underline; text-underline-offset: 2px; font-style: normal; }
.ty-blue { color: var(--ty-blue); font-weight: 700; font-style: normal; }
.ty-ok { font-style: normal; font-size: 10.5px; font-weight: 700; color: var(--ty-green); }
.ty-globe { display: inline-block; width: 11px; height: 11px; border-radius: 50%;
  background: linear-gradient(135deg, #2dd4bf, #0ea5e9); vertical-align: -1px; }


/* ══ M1 — üst menü ═════════════════════════════════════════════════ */

.ty-util {
  display: flex; align-items: center; justify-content: space-between;
  height: 32px; padding: 0 20px; background: var(--ty-util); color: #c3cedd; font-size: 11.5px;
}
.ty-util__l, .ty-util__r { display: flex; align-items: center; gap: 20px; }
.ty-util__l b { color: #fff; font-weight: 800; }
.ty-util__av { width: 15px; height: 15px; border-radius: 50%; border: 1.6px solid #c3cedd; }

.ty-nav {
  display: flex; align-items: center; gap: 22px;
  height: 58px; padding: 0 20px; background: var(--ty-nav); color: #e8eef6;
}
.ty-nav__brand { font-family: "Unbounded", sans-serif; font-weight: 700; font-size: 20px;
  letter-spacing: -.06em; color: #fff; }
.ty-nav__list { display: flex; align-items: center; gap: 4px; flex: 1; }
.ty-nav__i {
  position: relative; display: inline-flex; align-items: center; gap: 5px;
  padding: 9px 11px; border-radius: 8px; font-size: 13px; font-weight: 700; white-space: nowrap;
}
.ty-nav__i svg { width: 13px; height: 13px; }
.ty-nav__i.is-on { background: #26323f; }
.ty-nav__pip { position: absolute; top: 5px; left: 6px; width: 5px; height: 5px;
  border-radius: 50%; background: #ef4444; }
.ty-nav__search { width: 38px; height: 38px; border-radius: 50%; background: #2b3844;
  display: grid; place-items: center; color: #e8eef6; }
.ty-nav__search svg { width: 17px; height: 17px; }

.ty-page { padding: 0 20px 20px; background: #eef1f5; }
.ty-page__bar { display: flex; align-items: center; gap: 11px; height: 50px; }
.ty-back { width: 16px; height: 16px; color: var(--ty-ink2); }
.ty-page__bar b { font-size: 16px; font-weight: 800; }
.ty-page__links { margin-left: auto; display: flex; align-items: center; gap: 11px;
  font-size: 12.5px; font-weight: 700; color: #7c3aed; }
.ty-page__links i { color: var(--ty-line); font-style: normal; }
.ty-hero {
  height: 112px; border-radius: 10px; padding: 0 26px;
  display: flex; align-items: center;
  background: linear-gradient(104deg, #2a1340 0%, #4b1a52 46%, #7a1f4a 100%);
}
.ty-hero__t { font-family: "Unbounded", sans-serif; font-size: 20px; font-weight: 500;
  letter-spacing: -.045em; color: #fff; }
.ty-hero__t b { background: linear-gradient(90deg, #ff6ec7, #ffa14a);
  -webkit-background-clip: text; background-clip: text; color: transparent; font-weight: 700; }
.ty-panel { margin-top: -14px; background: #fff; border-radius: 10px; padding: 16px 18px 18px;
  box-shadow: 0 6px 20px rgba(15, 23, 42, .07); }
.ty-panel__top { border-bottom: 2px solid var(--ty-org); display: inline-block;
  padding-bottom: 7px; margin-bottom: 14px; }
.ty-panel__top b { color: var(--ty-org); font-size: 13.5px; font-weight: 800; }
.ty-panel__top em { display: block; text-align: center; font-style: normal;
  font-size: 12px; color: var(--ty-ink2); margin-top: 3px; }

/* Açılır liste `position:absolute` olduğu için kökün YÜKSEKLİĞİNE SAYILMAZ.
   min-height olmadan mockup ~590px ölçülüyor, liste alttan kırpılıyordu. */
.ty--menu { min-height: 700px; }
.ty-dd {
  position: absolute; top: 90px; left: 352px; width: 356px;
  background: #fff; border-radius: 10px; padding: 12px 0 16px;
  box-shadow: 0 18px 46px rgba(15, 23, 42, .26);
}
.ty-dd .ty-sep { height: 1px; background: var(--ty-line2); margin: 10px 22px; border: 0; }
.ty-dd__g { display: block; padding: 8px 22px 6px; font-size: 12px; font-weight: 700; color: var(--ty-ink3); }
.ty-dd__i { display: block; padding: 11px 22px; font-size: 14px; font-weight: 700; color: var(--ty-ink); }
.ty-plus { font-family: "Unbounded", sans-serif; font-weight: 700;
  background: linear-gradient(90deg, #f97316, #ec4899); -webkit-background-clip: text;
  background-clip: text; color: transparent; }


/* ══ M5/M6/M7 — kampanya ═══════════════════════════════════════════ */

.ty-tabs, .ty-mtabs, .ty-ctabs { display: flex; align-items: center; gap: 18px;
  border-bottom: 1px solid var(--ty-line); padding-bottom: 0; margin-bottom: 16px; }
.ty-tab { position: relative; padding: 4px 2px 12px; font-size: 13.5px; font-weight: 700;
  color: var(--ty-ink); white-space: nowrap; }
.ty-tab em { display: block; font-style: normal; font-size: 11px; font-weight: 600;
  color: var(--ty-ink2); margin-top: 3px; }
.ty-tab.is-on { color: var(--ty-org); }
.ty-tab.is-on::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px;
  height: 2.5px; background: var(--ty-org); border-radius: 2px; }
.ty-tabgrp { display: flex; align-items: center; gap: 18px; }
.ty-tabs__sep { width: 1px; height: 18px; background: var(--ty-line); margin-bottom: 10px; }
.ty-x { width: 17px; height: 17px; margin-left: auto; margin-bottom: 10px; color: var(--ty-ink2); }

.ty-chips { display: flex; gap: 12px; margin-bottom: 16px; }
.ty-chip { display: inline-flex; align-items: center; gap: 8px; height: 36px; padding: 0 16px;
  border-radius: 999px; border: 1px solid var(--ty-line); background: #fff;
  font-size: 12.5px; font-weight: 700; }
.ty-chip svg { width: 15px; height: 15px; }
.ty-chip.is-on { background: var(--ty-dark); color: #fff; border-color: var(--ty-dark); }

.ty-cmps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.ty-cmp { display: flex; flex-direction: column; gap: 9px; padding: 14px;
  border: 1px solid var(--ty-line); border-radius: 9px; background: #fff; }
.ty-cmp__s { display: inline-flex; align-items: center; gap: 6px; align-self: flex-start;
  font-style: normal; font-size: 10.5px; font-weight: 700; color: var(--ty-org);
  background: var(--ty-org-sf); border-radius: 6px; padding: 4px 9px; }
.ty-cmp__s svg { width: 13px; height: 13px; }
.ty-cmp__t { font-size: 12.8px; font-weight: 800; line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ty-cmp__g { display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
  border-top: 1px solid var(--ty-line2); padding-top: 9px; }
.ty-cmp__g span { font-size: 11.3px; line-height: 1.4; }
.ty-cmp__g span + span { border-left: 1px solid var(--ty-line2); padding-left: 10px; }
.ty-cmp__g em { display: block; font-style: normal; color: var(--ty-ink3); font-size: 10.5px; }
.ty-cmp__f { display: flex; align-items: center; gap: 12px; }
.ty-cmp__f .ty-btn { flex: 1; height: 32px; }
.ty-cnt { font-size: 11px; font-weight: 600; color: var(--ty-ink2); white-space: nowrap; }
.ty-cnt b { font-family: "Unbounded", sans-serif; font-size: 12.5px; font-weight: 700;
  color: var(--ty-ink); letter-spacing: -.04em; }
.ty-cnt.is-hot, .ty-cnt.is-hot b { color: #dc2626; }
.ty-cnt--sm { display: block; text-align: center; margin-top: 2px; }
.ty-cnt--sm b { margin: 0 4px; }

.ty-strip { height: 10px; margin: 18px -20px; background:
  repeating-linear-gradient(90deg, #4f7df3 0 72px, #7aa1ff 72px 120px); }

.ty-filt { }
.ty-tbl { margin-top: 18px; border: 1px solid var(--ty-line); border-radius: 9px; overflow: hidden; }
.ty-th, .ty-tr { display: grid; align-items: center; gap: 14px; padding: 13px 15px; }
.ty-th { background: var(--ty-fill); font-size: 12.3px; font-weight: 800; color: var(--ty-ink); }
.ty-th > span { display: flex; align-items: center; gap: 9px; }
.ty-th em { display: block; font-style: normal; font-size: 9.5px; font-weight: 600;
  color: var(--ty-ink3); margin-top: 2px; }
.ty-tr { border-top: 1px solid var(--ty-line2); font-size: 11.8px; color: var(--ty-ink2); }
.ty-tr b { color: var(--ty-ink); font-weight: 800; }
.ty-tr em { display: block; font-style: normal; margin-top: 3px; }

.ty-tbl--cmp .ty-th, .ty-tbl--cmp .ty-tr {
  grid-template-columns: minmax(0, 1.5fr) 118px minmax(0, 1.5fr) 150px 190px; }
.ty-tbl--cmp .ty-tr > span:first-child b { display: block; line-height: 1.35; }
.ty-pill { display: inline-block; background: var(--ty-fill); border-radius: 5px;
  padding: 3px 8px; font-size: 10.3px; margin-top: 6px !important; }
.ty-tr__cd { text-align: center; font-size: 9.5px; color: var(--ty-ink3); margin-top: 7px !important; }

.ty-tbl--prd .ty-th, .ty-tbl--prd .ty-tr {
  grid-template-columns: minmax(0, 1fr) 110px 170px 150px 80px; }
.ty-tbl--prd .ty-tr > span:first-child { display: flex; align-items: center; gap: 11px; }
.ty-cv { width: 14px; height: 14px; flex-shrink: 0; color: var(--ty-ink2); }

.ty-tbl--prc { position: relative; }
.ty-tbl--prc .ty-th, .ty-tbl--prc .ty-tr {
  grid-template-columns: minmax(0, 1fr) 160px 170px 230px; }
.ty-tbl--prc .ty-tr > span:first-child { display: flex; align-items: center; gap: 11px; }
.ty-colmark { position: absolute; top: 0; bottom: 0; right: 0; width: 260px; pointer-events: none; }

.ty-info { margin-top: 14px; padding: 11px 14px; border-radius: 8px;
  background: var(--ty-blue-sf); border: 1px solid var(--ty-blue-br);
  font-size: 11.8px; line-height: 1.5; color: #1e3a5f; }
.ty-info b { font-weight: 800; }
.ty-grayrow { display: flex; align-items: center; gap: 14px; margin-top: 14px; padding: 11px 14px;
  border-radius: 8px; background: var(--ty-fill); }
.ty-grayrow em { flex: 1; font-style: normal; font-size: 11.8px; color: var(--ty-ink2); }
.ty-acts { display: flex; align-items: center; gap: 11px; margin-top: 16px; flex-wrap: wrap; }

.ty-mfoot { display: flex; align-items: center; gap: 13px; margin-top: 16px; }
.ty-mfoot > em { font-style: normal; font-size: 12px; font-weight: 700; }
.ty-pg { display: inline-flex; align-items: center; gap: 6px; }
.ty-pg b, .ty-pg i { width: 28px; height: 28px; border-radius: 6px; display: grid;
  place-items: center; font-style: normal; font-size: 12px; font-weight: 700; color: var(--ty-ink2); }
.ty-pg b.is-on { background: var(--ty-dark); color: #fff; }

.ty-head { display: flex; align-items: flex-start; gap: 18px; padding: 15px 17px;
  border: 1px solid var(--ty-line); border-radius: 9px; background: #fff; margin-bottom: 16px; }
.ty-head__l { flex: 1; min-width: 0; }
.ty-head__l > b { display: flex; align-items: center; gap: 9px; font-size: 14.5px; font-weight: 800; }
.ty-head__m { display: flex; align-items: center; gap: 9px; margin-top: 6px; }
.ty-head__m em { font-style: normal; font-size: 11.5px; color: var(--ty-ink2); }
.ty-head__m em b { font-weight: 800; color: var(--ty-ink); }
.ty-head__m i { color: var(--ty-line); font-style: normal; }
.ty-cd { display: inline-flex; align-items: center; gap: 7px; flex-shrink: 0;
  background: #fdecec; border-radius: 8px; padding: 9px 15px; }
.ty-cd > span { text-align: center; }
.ty-cd b { display: block; font-family: "Unbounded", sans-serif; font-size: 18px;
  font-weight: 700; letter-spacing: -.05em; color: #dc2626; }
.ty-cd em { display: block; font-style: normal; font-size: 8px; font-weight: 700;
  letter-spacing: .06em; color: #e07a7a; margin-top: 1px; }
.ty-cd i { font-style: normal; color: #f0b4b4; font-size: 14px; margin-bottom: 9px; }


/* ══ M8 — kupon oluşturma ══════════════════════════════════════════ */

.ty-two { display: grid; grid-template-columns: minmax(0, 1fr) 290px; gap: 26px; }
.ty-two__l { min-width: 0; }
.ty-two__r { display: flex; flex-direction: column; gap: 12px; align-items: center; }

.ty-tlist { display: flex; flex-direction: column; gap: 11px; }
.ty-t { display: flex; gap: 10px; align-items: flex-start; }
.ty-t .ty-dot { margin-top: 2px; }
.ty-t b { font-size: 12.8px; font-weight: 800; }
.ty-t.is-on b { color: var(--ty-org); }
.ty-t .ty-tag { margin-left: 7px; }
.ty-t__d { display: block; font-style: normal; font-size: 11.3px; line-height: 1.45;
  color: var(--ty-ink2); margin-top: 3px; }

.ty-phone { position: relative; width: 258px; border-radius: 26px; padding: 10px;
  background: #1b2430; box-shadow: 0 10px 30px rgba(15, 23, 42, .22); }
.ty-phone__s { display: block; background: #fff; border-radius: 18px; padding: 10px 11px 13px; }
.ty-phone__img { display: grid; place-items: center; height: 118px; border-radius: 10px;
  background: #e9edf2; margin-bottom: 9px; }
.ty-phone__img .ty-thumb { width: 54px; height: 54px; background: #d2d9e2; }
.ty-phone__img .ty-thumb svg { width: 28px; height: 28px; }
.ty-phone em { display: block; font-style: normal; }
.ty-phone__t { font-size: 10.5px; font-weight: 700; color: var(--ty-ink); line-height: 1.35; }
.ty-phone__p { font-size: 9.5px; color: var(--ty-org); font-weight: 700; margin-top: 4px; }
.ty-phone__r { font-size: 9.5px; color: var(--ty-ink3); margin-top: 5px;
  display: flex !important; align-items: center; gap: 5px; }
.ty-phone__k { font-size: 9.5px; font-weight: 700; color: var(--ty-ink2);
  border-top: 1px solid var(--ty-line2); margin-top: 8px; padding-top: 7px; }
.ty-phone__c { display: flex; gap: 5px; margin-top: 6px; }
.ty-phone__c b { flex: 1; text-align: center; padding: 5px 0; border-radius: 5px;
  background: var(--ty-org-sf); color: var(--ty-org); font-size: 9.5px; font-weight: 800; }
.ty-phone__c b.org { background: var(--ty-org); color: #fff; }
.ty-phone__f { font-size: 9.5px; color: var(--ty-ink3); margin-top: 8px;
  border-top: 1px solid var(--ty-line2); padding-top: 7px; }
.ty-phone__d { position: absolute; left: 50%; bottom: -14px; transform: translateX(-50%);
  width: 26px; height: 5px; border-radius: 3px; background: var(--ty-line); }


/* ══ M9 — müşteri değerlendirme ════════════════════════════════════ */

.ty-ctabs { gap: 34px; }
.ty-ctabs .ty-tab { font-size: 15px; }
.ty-ctabs .ty-tab:not(.is-on) { color: var(--ty-ink2); }
.ty-cchips { display: flex; gap: 11px; margin-bottom: 16px; }
.ty-cchip { height: 40px; padding: 0 20px; border-radius: 9px; border: 1px solid var(--ty-line);
  display: inline-flex; align-items: center; font-size: 14px; font-weight: 700; color: var(--ty-ink); }
.ty-cchip.is-on { border-color: var(--ty-org); color: var(--ty-org); }

.ty-rev { display: flex; gap: 14px; padding: 16px 0; border-top: 1px solid var(--ty-line2); }
.ty-rev > .ty-thumb { width: 92px; height: 112px; border-radius: 8px; }
.ty-rev > .ty-thumb svg { width: 34px; height: 34px; }
.ty-rev__b { flex: 1; min-width: 0; }
.ty-rev__b > b { display: block; font-size: 13.5px; font-weight: 800; }
.ty-rev__b em { display: block; font-style: normal; font-size: 12.5px; color: var(--ty-ink2); margin-top: 6px; }
.ty-rev__r { display: flex !important; align-items: center; gap: 7px; }
.ty-rev__r b { font-size: 13px; font-weight: 800; color: var(--ty-ink); }
.ty-cpn { display: inline-flex !important; align-items: center; gap: 6px;
  background: var(--ty-pink); color: var(--ty-pink-ink); border-radius: 5px;
  padding: 4px 9px; font-size: 12px; font-weight: 600; width: auto; }
.ty-cpn b { font-weight: 800; color: var(--ty-pink-ink); }
.ty-cpn svg { width: 14px; height: 14px; }
.ty-rev .ty-btn { margin-top: 10px; }


/* ══ M10 — müşteri kupon biletleri ═════════════════════════════════ */

.ty-tkts { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.ty-tkt { border: 1px solid var(--ty-org-br); border-radius: 10px; background: var(--ty-org-sf);
  padding: 14px 16px 11px; position: relative; }
.ty-tkt__t { display: flex; align-items: center; gap: 12px; }
.ty-tkt__t b { font-family: "Unbounded", sans-serif; font-size: 21px; font-weight: 600;
  letter-spacing: -.05em; color: var(--ty-org); }
.ty-tkt__t em { font-style: normal; font-size: 12.5px; color: var(--ty-ink2); }
.ty-tkt__t .ty-btn { margin-left: auto; height: 34px; padding: 0 26px; font-size: 14px; }
.ty-tkt__x { margin-left: auto; width: 54px; height: 34px; border-radius: 7px; background: var(--ty-org); }
.ty-tkt__d { display: block; height: 1px; margin: 12px -16px 10px;
  background: repeating-linear-gradient(90deg, var(--ty-org-br) 0 6px, transparent 6px 12px); }
.ty-tkt__f { display: flex; align-items: center; justify-content: space-between; }
.ty-tkt__f em { display: inline-flex; align-items: center; gap: 5px; font-style: normal;
  font-size: 11.5px; color: #b45309; }
.ty-tkt__f svg { width: 13px; height: 13px; }

.ty-band { display: flex; align-items: center; gap: 14px; margin-top: 16px;
  padding: 14px 18px; border-radius: 10px; background: var(--ty-pink); }
.ty-band em { display: inline-flex; align-items: center; gap: 10px; flex: 1;
  font-style: normal; font-size: 17px; font-weight: 800; color: var(--ty-pink-ink); }
.ty-band svg { width: 19px; height: 19px; }
.ty-band__b { height: 38px; padding: 0 28px; border-radius: 8px;
  border: 1.4px solid var(--ty-pink-ink); color: var(--ty-pink-ink);
  display: inline-flex; align-items: center; font-size: 14px; font-weight: 700; }


/* ══ M11/M12/M13/M14 — giriş/liste ekranları + komisyon teklifi ═══════ */

.ty-scr__h { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.ty-scr__h b { font-size: 16.5px; font-weight: 800; }
.ty-scr__note { font-style: normal; font-size: 11.5px; font-weight: 700; color: var(--ty-ink3); }

.ty-st { font-style: normal; font-size: 11px; font-weight: 800; padding: 3px 9px;
  border-radius: 6px; background: var(--ty-fill); color: var(--ty-ink2); }
.ty-st.on { background: #ecfdf3; color: var(--ty-green); }

.ty-tbl--ind .ty-th, .ty-tbl--ind .ty-tr {
  grid-template-columns: minmax(0, 1.4fr) 140px 160px 120px 110px 90px; }
.ty-tbl--kpn .ty-th, .ty-tbl--kpn .ty-tr {
  grid-template-columns: minmax(0, 1.3fr) 150px 170px 90px 110px 110px; }

.ty-tbl--avj .ty-th, .ty-tbl--avj .ty-tr {
  grid-template-columns: minmax(0, 1.3fr) 130px 190px 190px 150px; }
.ty-tbl--avj .ty-tr > span:first-child { display: flex; align-items: center; gap: 11px; }
.ty-avj { display: inline-flex; align-items: center; gap: 6px; font-style: normal;
  font-size: 11.3px; font-weight: 800; color: var(--c, var(--ty-blue)); }
.ty-avj svg { width: 14px; height: 14px; flex-shrink: 0; }

/* M14 — komisyon tarifeleri (haftalık teklif) */
.ty-scr--kt { padding-top: 16px; }
.ty-kt__win { display: flex; align-items: baseline; gap: 12px; padding-bottom: 12px;
  border-bottom: 2px solid var(--ty-org); margin-bottom: 14px; }
.ty-kt__win b { font-size: 15px; font-weight: 800; color: var(--ty-org); }
.ty-kt__win em { font-style: normal; font-size: 12px; font-weight: 700; color: var(--ty-ink2); }
.ty-kt__days { display: flex; gap: 10px; margin-bottom: 16px; }
.ty-kt__days .ty-chip { border-radius: 10px; height: auto; padding: 10px 16px;
  font-size: 11.8px; font-weight: 700; }
.ty-kt__sum { display: flex; flex-direction: column; align-items: flex-end;
  font-style: normal; font-size: 10.5px; color: var(--ty-ink3); }
.ty-kt__sum b { font-size: 12.5px; color: var(--ty-ink); }
.ty-chk2 { display: inline-flex; align-items: center; gap: 7px; font-size: 12px;
  font-weight: 700; color: var(--ty-ink2); }
.ty-chk2 i { width: 15px; height: 15px; border-radius: 4px; border: 1.6px solid #c3cbd6; }
.ty-spark { width: 14px; height: 14px; color: #7c3aed; }
.ty-btn--pasif { background: var(--ty-fill); color: var(--ty-ink3); cursor: not-allowed; }

.ty-tbl--kt { overflow: visible; }
.ty-tbl--kt .ty-th, .ty-tbl--kt .ty-tr {
  grid-template-columns: minmax(0, 1.3fr) repeat(4, 150px) 150px; align-items: stretch; gap: 10px; }
.ty-tbl--kt .ty-tr { padding: 14px 15px; }
.ty-kt__p { display: flex; flex-direction: column; gap: 8px; }
.ty-kt__rec { display: inline-flex; align-items: center; gap: 5px; align-self: flex-start;
  font-style: normal; font-size: 9.5px; font-weight: 800; color: #7c3aed;
  background: #f3e8ff; border-radius: 6px; padding: 3px 8px; }
.ty-kt__rec svg { width: 11px; height: 11px; }
.ty-kt__pr { display: flex; align-items: flex-start; gap: 10px; }
.ty-kt__pr > span { min-width: 0; }
.ty-kt__pr b { display: block; font-size: 12px; font-weight: 800; color: var(--ty-ink);
  line-height: 1.35; }
.ty-kt__pr em { display: block; font-style: normal; font-size: 10px; color: var(--ty-ink3); }
.ty-kt__box { display: flex; flex-direction: column; gap: 8px; padding-top: 2px; }
.ty-kt__box > span { display: flex; flex-direction: column; gap: 2px; }
.ty-kt__box i { font-style: normal; font-size: 9.5px; color: var(--ty-ink3); }
.ty-kt__box b { font-size: 13px; font-weight: 800; color: var(--ty-ink); }
.ty-kt__rank { font-size: 10px; font-weight: 700; color: var(--ty-org); }
.ty-kt__how { font-style: normal; font-size: 10px; font-weight: 700; color: var(--ty-blue); }
.ty-kt__c { display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 10px 8px; border-radius: 9px; background: var(--ty-fill);
  border: 1.4px solid transparent; text-align: center; }
.ty-kt__c b { font-size: 13.5px; font-weight: 800; color: var(--ty-ink); }
.ty-kt__c em { font-style: normal; font-size: 10px; color: var(--ty-ink3); }
.ty-kt__k { font-style: normal; font-size: 9px; color: var(--ty-ink3); margin-top: 3px; }
.ty-kt__c u { font-style: normal; text-decoration: none; font-size: 13px; font-weight: 800;
  color: var(--ty-ink2); }
.ty-kt__r { width: 15px; height: 15px; border-radius: 50%; border: 2px solid #c3cbd6; margin-top: 2px; }
.ty-kt__c.is-on { background: #ecfdf3; border-color: #86e3ae; }
.ty-kt__c.is-on b, .ty-kt__c.is-on u { color: var(--ty-green); }
.ty-kt__ok { display: inline-flex !important; align-items: center; gap: 4px; margin-top: 2px;
  font-style: normal; font-size: 10px; font-weight: 800; color: var(--ty-green); }
.ty-kt__ok svg { width: 12px; height: 12px; }
.ty-kt__upd { display: flex; flex-direction: column; gap: 8px; justify-content: center; }
.ty-kt__upd .ty-in { height: 34px; font-weight: 700; color: var(--ty-ink); }
.ty-pen { width: 14px; height: 14px; margin-left: auto; color: var(--ty-ink3); }


/* ═══════════════════════════════════════════════════════════════════════
   GİRİŞ EKRANLARI + ÜRÜN KOMİSYON TARİFELERİ + DOLDURMA ANİMASYONU
   ═══════════════════════════════════════════════════════════════════════ */

.ty-pg__h { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.ty-pg__h b { font-size: 19px; font-weight: 800; letter-spacing: -.02em; }
.ty-pg__note { font-size: 11.5px; color: var(--ty-ink3); font-weight: 600; }

.ty-st { display: inline-block; font-style: normal; font-size: 10.5px; font-weight: 800;
  padding: 3px 9px; border-radius: 999px; background: #eef1f5; color: var(--ty-ink2); }
.ty-st.on { background: #e8f8ee; color: var(--ty-green); }

.ty-tbl--ind .ty-th, .ty-tbl--ind .ty-tr {
  grid-template-columns: minmax(0, 1.5fr) 130px 160px 90px 110px 80px; }
.ty-tbl--kpn .ty-th, .ty-tbl--kpn .ty-tr {
  grid-template-columns: minmax(0, 1.4fr) 150px 180px 80px 100px 110px; }
.ty-tbl--avj .ty-th, .ty-tbl--avj .ty-tr {
  grid-template-columns: minmax(0, 1.5fr) 120px 180px 200px 150px; }
.ty-tbl--avj .ty-tr > span:first-child { display: flex; align-items: center; gap: 11px; }

.ty-avj { display: inline-flex !important; align-items: center; gap: 6px;
  font-style: normal; font-size: 11px; font-weight: 800; color: #fff;
  background: var(--c); border-radius: 999px; padding: 4px 11px 4px 8px; }
.ty-avj svg { width: 12px; height: 12px; stroke-width: 3; }

/* ── Ürün Komisyon Tarifeleri ── */
.ty-pg--kt { }
.ty-kt__win { display: inline-block; border-bottom: 2.5px solid var(--ty-org);
  padding: 0 26px 8px 4px; margin-bottom: 16px; }
.ty-kt__win b { display: block; font-size: 14.5px; font-weight: 800; color: var(--ty-org); }
.ty-kt__win em { display: block; text-align: center; font-style: normal; font-size: 12px;
  color: var(--ty-ink2); margin-top: 3px; }
.ty-kt__days { display: flex; gap: 12px; margin-bottom: 14px; }
.ty-kt__days .ty-chip { font-size: 12.5px; height: 38px; padding: 0 20px; }

.ty-chk2 { display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px;
  font-weight: 600; color: var(--ty-ink); }
.ty-chk2 > i { width: 15px; height: 15px; border-radius: 4px; border: 1.6px solid #c3cbd6;
  background: #fff; flex-shrink: 0; }
.ty-spark { width: 15px; height: 15px; color: #7c3aed; fill: #7c3aed; stroke-width: 1.2; }
.ty-kt__sum { text-align: right; }
.ty-kt__sum em { display: block; font-style: normal; font-size: 11px; color: var(--ty-ink2); }
.ty-kt__sum b { font-size: 12.5px; font-weight: 800; }
.ty-btn--pasif { background: #f1f3f7; color: #aab4c2; border-color: #e6eaf0; }

.ty-tbl--kt .ty-th, .ty-tbl--kt .ty-tr {
  grid-template-columns: minmax(0, 1.55fr) repeat(4, 118px) 180px;
  align-items: stretch; gap: 0; padding: 0;
}
.ty-tbl--kt .ty-th > span { padding: 14px 12px; font-size: 12px; }
.ty-tbl--kt .ty-th > span + span,
.ty-tbl--kt .ty-tr > span + span { border-left: 1px solid var(--ty-line2); }
.ty-tbl--kt .ty-tr > span { padding: 14px 12px; display: flex; flex-direction: column; }

.ty-kt__rec { display: inline-flex !important; align-items: center; gap: 5px; align-self: flex-start;
  font-style: normal; font-size: 10px; font-weight: 800; color: #fff;
  background: linear-gradient(100deg, #6d4aff, #8b5cf6); border-radius: 6px; padding: 4px 9px;
  margin-bottom: 9px !important; }
.ty-kt__rec svg { width: 11px; height: 11px; fill: #fff; stroke-width: 0; }
.ty-kt__pr { display: flex; gap: 10px; align-items: flex-start; }
.ty-kt__pr .ty-thumb { width: 44px; height: 50px; }
.ty-kt__pr b { display: block; font-size: 12.3px; font-weight: 700; line-height: 1.35;
  color: var(--ty-ink); }
.ty-kt__pr em { display: block; font-style: normal; font-size: 10.5px; color: var(--ty-ink2);
  margin-top: 2px !important; }
.ty-kt__box { display: grid !important; grid-template-columns: 1fr 1.25fr; gap: 10px;
  margin-top: 11px; padding: 9px 11px; border-radius: 7px; background: #f4f6f9; }
.ty-kt__box i { display: block; font-style: normal; font-size: 9.5px; color: var(--ty-ink2);
  line-height: 1.3; }
.ty-kt__box b { display: block; font-size: 12.5px; font-weight: 800; margin-top: 3px; }
.ty-kt__rank { font-size: 10px; color: #7c3aed; text-decoration: none; }
.ty-kt__how { display: inline-block !important; margin-top: 5px !important; font-size: 10px;
  color: var(--ty-blue); text-decoration: underline; text-underline-offset: 2px; }

.ty-kt__c { align-items: center !important; justify-content: center; text-align: center; gap: 0; }
.ty-kt__c b { font-size: 15px; font-weight: 800; letter-spacing: -.02em; color: var(--ty-ink); }
.ty-kt__c > em { font-style: normal; font-size: 12px; color: var(--ty-ink2); margin-top: 1px; }
.ty-kt__k { font-style: normal; font-size: 9.5px; color: var(--ty-ink2); margin-top: 11px; }
.ty-kt__c u { text-decoration: none; font-size: 13.5px; font-weight: 800; color: var(--ty-org);
  margin-top: 2px; }
.ty-kt__c.is-on u { color: var(--ty-green); }
.ty-kt__ok { display: inline-flex !important; align-items: center; gap: 5px; margin-top: 10px !important;
  font-style: normal; font-size: 11px; font-weight: 700; color: var(--ty-green); }
.ty-kt__ok svg { width: 14px; height: 14px; color: var(--ty-green); }
.ty-kt__r { width: 15px; height: 15px; border-radius: 50%; border: 1.8px solid #c7cfda;
  margin-top: 11px; }
.ty-kt__upd { justify-content: center !important; gap: 9px; }
.ty-kt__upd .ty-in { position: relative; }
.ty-pen { position: absolute; right: 10px; width: 14px; height: 14px; color: var(--ty-ink2); }

/* ── doldurma (örnek kurulum) animasyonu ── */
.ty-ph { color: inherit; }
.ty-in[data-doldur] .ty-ph { color: var(--ty-ink3); }
.ty-in.is-dolu { border-color: var(--ty-org); background: #fffaf4; }
.ty-in.is-dolu .ty-ph { color: var(--ty-ink); font-weight: 800; }
.ty-in.is-dolu {
  animation: tyDolsun .5s cubic-bezier(.22,.9,.22,1) both;
  animation-delay: calc(var(--i, 0) * 300ms + 500ms);
}
.ty-in.is-dolu .ty-ph {
  animation: tyYazil .45s cubic-bezier(.22,.9,.22,1) both;
  animation-delay: calc(var(--i, 0) * 300ms + 560ms);
}
@keyframes tyDolsun {
  0%   { border-color: var(--ty-line); background: #fff;
         box-shadow: 0 0 0 0 rgba(242,122,26,0); }
  45%  { border-color: var(--ty-org); background: #fff3e6;
         box-shadow: 0 0 0 5px rgba(242,122,26,.18); }
  100% { border-color: var(--ty-org); background: #fffaf4;
         box-shadow: 0 0 0 0 rgba(242,122,26,0); }
}
@keyframes tyYazil {
  0%   { opacity: 0; transform: translateY(5px); clip-path: inset(0 100% 0 0); }
  100% { opacity: 1; transform: none; clip-path: inset(0 0 0 0); }
}
@media (prefers-reduced-motion: reduce) {
  .ty-in.is-dolu, .ty-in.is-dolu .ty-ph { animation: none !important; }
}



/* ===== css/tm-satis-ipuclari-override.css ===== */
/* ═══════════════════════════════════════════════════════════════════════
   Satış İpuçları kılavuzu — ENTEGRASYON OVERRIDE'LARI (uygulamaya özel).
   Bu dosya prototipin BİR PARÇASI DEĞİL — kaynak dosyalar (klavuz.css/js,
   mockuplar.css/js, adimlar.js) tm-satis-ipuclari*.css/.js içine OLDUKLARI
   GİBİ taşındı (bkz. o dosyaların başındaki "kaynak prototip damgası").
   Uygulamaya entegre ederken gereken TÜM davranış farkları BİLEREK buraya,
   ayrı bir dosyaya toplandı — amaç: `tm-satis-ipuclari.css` diff'i prototiple
   birebir kalsın, "ne taşındı" ile "biz ne değiştirdik" ayrı görünsün.
   Yükleme sırası: base.html'de tm-satis-ipuclari.css'den HEMEN SONRA.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 1) Z-INDEX — gerçek app sidebar'ının ÜSTÜNDE kalmalı ─────────────────
   Bulundu (2026-10-08): prototipte `.k-scrim`/`.k-root` sabit z-index:90/100
   kullanıyordu; gerçek uygulamada sidebar'ın z-index'i (--tm-z-sidebar:1035,
   tm-shell-v2.css) bundan yüksekti → modalın sol navy rayı (5 konu listesi)
   sidebar metninin ALTINDA kalıyordu (ekran görüntüsü + getComputedStyle ile
   doğrulandı). Tek-kaynak ölçeğe bağlandı (static/css/tm-z-layers.css). */
.k-scrim {
  z-index: calc(var(--tm-z-satis-ipuclari, 12060) - 1) !important;
}
.k-root {
  z-index: var(--tm-z-satis-ipuclari, 12060) !important;
}

/* ── 2) .k-stage ARKA PLANI — prototipteki çok-katmanlı bildirim geçersiz ──
   `background: <gradient>, var(--yuzey);` — ikinci katmanda yalnız renk
   olması CSS'te geçerli değildir (renk yalnız SON katmanın PARÇASI olabilir,
   kendi başına bir <image> değeri OLAMAZ) → bildirim SESSİZCE DÜŞER. Açık
   temada fark edilmiyordu çünkü üst `.k-dialog`'un (basit background) beyazı
   arkadan görünüyordu. Kaynak dosyadaki geçersiz bildirim BİLEREK silinmedi
   (prototiple birebir kalsın); burada geçerli background-image/-color ile
   TAMAMLANIYOR — iki bildirim çakışmıyor, ilki zaten tarayıcı tarafından hiç
   uygulanmıyor. */
.k-stage {
  background-image: radial-gradient(1100px 420px at 88% -12%, rgba(1, 117, 228, .07), transparent 62%);
  background-color: var(--yuzey);
}

/* ── 3) KOYU TEMA (html.dark-mode) — gerçek uygulamanın token'larına bağlanır.
   Prototipte koyu tema yoktu; burada yalnız modalın KENDİ custom property'leri
   (--sayfa, --yuzey, --cizgi, --cizgi-2, --murekkep, --murekkep-2, --murekkep-3)
   uygulamanın tema değişkenlerine yönlendirilir. .k- ve .tm-tips-btn ile başlayan
   seçicilerin TAMAMI zaten bu property'leri kullandığı için tek blokla modalın her
   yeri okunur kalır. Trendyol panel mockup'ı (.ty / --ty-*) BİLEREK değiştirilmez.
   UYARI: bu yorum bloğunu düzenlerken "*" hemen ardından "/" yazma (CSS yorumunu
   erken kapatır, önceki entegrasyon turunda bu yüzden bir kural tamamen düştü). */
html.dark-mode {
  --sayfa: var(--tm-surface-2, #0f172a);
  --yuzey: var(--tm-surface, #1e293b);
  --cizgi: var(--tm-border-color, #334155);
  --cizgi-2: var(--tm-border-light, #334155);
  --murekkep: var(--tm-text-primary, #e2e8f0);
  --murekkep-2: var(--tm-text-muted, #94a3b8);
  --murekkep-3: #64748b;
  --golge-kart: 0 8px 24px rgba(0, 0, 0, .4);
}
html.dark-mode .k-shot__frame,
html.dark-mode .k-shot__chrome {
  background: var(--tm-surface-2, #0f172a);
  border-color: var(--cizgi);
}
html.dark-mode .k-scrim {
  background: rgba(0, 0, 0, .72);
}
/* Bulundu 2026-10-08: .k-stage bir section elemanı; dark-mode.css (:337-343) TÜM
   section'ları (.tm-ds kapsamı dışında) background: transparent !important ile
   sıfırlıyor (site-geneli güvenlik ağı). .k-stage'in kendi background-color'ı bu
   kurala kaybediyordu; yalnız GERÇEK localStorage-fallback+reload akışında ortaya
   çıkar (dark-mode.css lazy-load'ı yalnız o akışta tetiklenir). */
html.dark-mode .k-stage {
  background-color: var(--yuzey) !important;
}


/* ===== css/ds/ds-tokens.css ===== */
/* =================================================================
   TRENDMETRIK DESIGN SYSTEM — DS SEMANTIC TOKEN LAYER (Faz 1, 2026-09-12;
   values re-derived from the measured reference spec 2026-09-13 —
   docs/ui-reference-spec.md, Apex primary)

   Primitive source of truth stays static/css/v2/tokens.css (untouched; the
   ~200 legacy pages keep resolving every legacy token). This file is the
   NARROWED semantic set the design-system scope (.tm-ds) is allowed to use:

     spacing  7 : --tm-space-1/2/3/4/6/8/12   (4/8/12/16/24/32/48px)
                  card inset 24 · column gap 16 · row gap 24 (reference: 24/16/24)
     radius   3 : --tm-radius-control (6) · --tm-radius-card (14) · --tm-radius-overlay (14)
     shadow   3 : --tm-shadow-card (resting surface, one hairline-soft shadow)
                  · --tm-shadow-overlay · --tm-shadow-modal
     colour     : semantic names only (bg / border / text / accent / status -fg -bg)
     type     6 : display 24/32 (+ display-sm 20/28, KPI-only) · title 18/28 · heading 16/24 · body 14/20 · caption 12/16 · micro 11/14
                  (reference scale 11/12/14/16/18/24, ratio ≈1.14; no fractional sizes)
     weight   4 : 400 body · 500 label · 600 card title · 700 page title + KPI number

   Rules (enforced by tests/test_ui_design_system_guard.py):
   - nothing in static/css/ds/** references a token outside this set;
   - no colour literal outside this file;
   - no box-shadow other than the three tokens; only --tm-shadow-card on resting surfaces.
   Everything below .tm-ds is scoped → inert on pages that have not opted in.
   ================================================================= */

:root {
  /* Elevation. Additive names; nothing legacy references them.
     Cila V1 (2026-09-23, onaylı mockup): light-mode kart gölgesi iki katmanlı
     (hairline + geniş/yumuşak) → "katmanlı derinlik" hissi. Koyu tema DEĞİŞMEDİ
     (bkz. [data-theme="dark"] bloğu aşağıda, aynı kalır). */
  /* 2026-10-11: hairline 0.04 → 0.08 — koyulaşan zeminde kartın kenarı
     yumuşak gölgede kayboluyordu ("içerik pasif"). */
  --tm-shadow-card:    0 1px 2px rgba(15, 23, 42, 0.08), 0 10px 28px -14px rgba(15, 23, 42, 0.22);
  --tm-shadow-overlay: 0 4px 12px rgb(0 0 0 / 0.08);   /* dropdown, popover, tooltip */
  --tm-shadow-modal:   0 16px 48px rgb(0 0 0 / 0.16);  /* modal, drawer */

  /* Site-wide kart gölge/radius aliası (Cila V1) — .tm-ds dışındaki bileşenler
     (.kpi-card, account_pages_base_compatible.css, assistant_widget.css, admin
     panelleri…) ZATEN `var(--tm-card-shadow, <fallback>)` / `var(--tm-radius-card,
     12px)` zinciriyle yazılmış (35+ dosya) ama token hiçbir yerde bare :root'ta
     tanımlı değildi → hepsi kendi yerel fallback'ine düşüyordu. Burada tanımlamak
     base.html'i extend eden TÜM sayfalara (satıcı paneli + admin kabuğu) aynı
     kartı tek kaynaktan verir — kapsam kasıtlı geniş (bkz. görev notu "Kapsam").
     .tm-ds içindeki `--tm-radius-card` (aşağıda .tm-ds bloğu) aynı 16px'e
     hizalandı; kontrol(6)/overlay(14) DEĞİŞMEDİ. */
  --tm-card-shadow:       var(--tm-shadow-card);
  --tm-card-shadow-hover: var(--tm-shadow-overlay);
  --tm-radius-card: 16px;
}

/* ---------- Promo paleti (2026-09-15, kullanıcı kararı: katalog banner'ı
   "renkli, canlı, kayan" olacak) ----------------------------------------
   "Düz yüzey" kuralı PAZARLAMA yüzeyleri için bilerek esnetildi; ama renk
   JS'te inline YAZILMAZ — token'dan gelir. Sebep: (a) koyu modda tema-dışı
   renk = okunmaz metin (bugün üç kez yaşandı), (b) inline renk guard'a
   görünmez → kilitlenemez, (c) review edilemez. Kullanım: kart/şerit
   `data-promo="1..6"` alır, rengi CSS seçer. Metin daima --tm-promo-fg
   (her ton için kontrast ölçülür, ≥4.5:1). */
:root {
  --tm-promo-fg:   #ffffff;
  --tm-promo-1:      #b4232b;   /* base = gradient başlangıcı */
  --tm-promo-1-from: var(--tm-promo-1);
  --tm-promo-1-to:   #82191f;
  --tm-promo-2:      #b35309;   /* base = gradient başlangıcı */
  --tm-promo-2-from: var(--tm-promo-2);
  --tm-promo-2-to:   #813c06;
  --tm-promo-3:      #6d28d9;   /* base = gradient başlangıcı */
  --tm-promo-3-from: var(--tm-promo-3);
  --tm-promo-3-to:   #4e1d9c;
  --tm-promo-4:      #0369a1;   /* base = gradient başlangıcı */
  --tm-promo-4-from: var(--tm-promo-4);
  --tm-promo-4-to:   #024c74;
  --tm-promo-5:      #15803d;   /* base = gradient başlangıcı */
  --tm-promo-5-from: var(--tm-promo-5);
  --tm-promo-5-to:   #0f5c2c;
  --tm-promo-6:      #9d174d;   /* base = gradient başlangıcı */
  --tm-promo-6-from: var(--tm-promo-6);
  --tm-promo-6-to:   #711137;
  /* Ambiyans bandı: aktif kartın tonundan şeffafa. Kullanım:
     `background: linear-gradient(90deg, var(--tm-promo-grad-from), var(--tm-promo-grad-to));`
     `--tm-promo-grad-from` kart tonuna `data-promo` ile bağlanır.
     Kart gradienti: `linear-gradient(135deg, var(--tm-promo-N-from), var(--tm-promo-N-to))`.
     `-to` daima aynı hue'nun KOYU ucu → beyaz metin gradientin HER İKİ ucunda
     da >=4.5:1 kalır (ölçüldü; açık mod 5.02-11.43, koyu mod 7.37-13.70). */
  --tm-promo-grad-from: var(--tm-promo-1);
  --tm-promo-grad-to:   transparent;
}

[data-theme="dark"],
html.dark-mode {
  /* Koyu modda aynı hue, daha düşük parlaklık (yüzey ışığı bastırmasın);
     metin yine --tm-promo-fg (beyaz) — kontrastlar ölçüldü. */
  --tm-promo-1:      #8f1b22;
  --tm-promo-1-to:   #6a1419;
  --tm-promo-2:      #8a4007;
  --tm-promo-2-to:   #662f05;
  --tm-promo-3:      #55209f;
  --tm-promo-3-to:   #3f1876;
  --tm-promo-4:      #02537c;
  --tm-promo-4-to:   #013d5c;
  --tm-promo-5:      #10632f;
  --tm-promo-5-to:   #0c4923;
  --tm-promo-6:      #7a1240;
  --tm-promo-6-to:   #5a0d2f;
}

/* ---------- Motion grammar (PR-1, 2026-10-10; referans video kare kare ölçüldü) ----------
   İlkel süre/eğriler static/css/v2/tokens.css'te kalır (--tm-dur-fast 150 /
   --tm-dur-base 200 / --tm-dur-slow 300, --tm-ease*, reduced-motion'da 0'lanır).
   Burada yalnız koreografinin ROLLERİ eklenir; tüketici: ds-motion.css,
   tm-kpi.js (sayım), tm-charts.js (morf, PR-3). :root'ta — kabuk (sidebar/ticker)
   ve body'ye portallanan modal da aynı dili konuşsun. */
:root {
  --tm-dur-enter: var(--tm-dur-slow);   /* giriş: opaklık + 6px kayma, tek sefer      (referans ~300 ms) */
  --tm-dur-morph: 450ms;                /* veri değişimi: sayı/çizgi/çubuk mevcut→hedef (referans ~450 ms) */
  /* 🔴 İLK SAYIM KAPALI (2026-10-11, kullanıcı: *"sayfa yüklemeleri kopuk, kasıyor"*).
     Ölçüldü (filmstrip, Genel Bakış): KPI'lar 0,00'dan sayarken ~0,9 sn boyunca
     "Ciro 0,00 / Marj 0,00" gibi GERÇEK OLMAYAN değerler gösteriyordu; kart kademesi
     + grafik açılışıyla birlikte sayfa ~2,1 sn'de oturuyordu. 0 ms → nihai değer
     ilk çizimde (tm-kpi.js playCountUp `!(ms > 0)` dalı). Canlı yenilemedeki
     mevcut→yeni geçişi (--tm-dur-morph) DEĞİŞMEDİ. */
  --tm-dur-count: 0ms;                  /* ilk sayım 0→değer — kapalı (bk. üst not)    (referans ~900 ms) */
  --tm-stagger:   50ms;                 /* okuma sırasında öğe başına gecikme          (referans ~50 ms) */
  --tm-ease-std:  var(--tm-ease-standard);
  /* Sıralı açılış (ds-motion.css "SIRALI AÇILIŞ", static/js/ds/tm-sira.js) */
  --tm-sira-aralik: 50ms;               /* bir satırın kademesi bittikten sonra alttaki için ara */
  --tm-sira-kademe: 30ms;               /* satır içinde soldan sağa panel başına gecikme   */
  --tm-sira-bekle:  900ms;              /* hazır olmayan satırı en çok bu kadar bekle      */
  --tm-sira-tavan:  2200ms;             /* sayfa açılışından sonra hepsini aç              */
  --tm-sira-kurtar: 3000ms;             /* JS yoksa CSS kendi açar (emniyet)            */
}
@media (prefers-reduced-motion: reduce) {
  :root { --tm-dur-enter: 0ms; --tm-dur-morph: 0ms; --tm-dur-count: 0ms; --tm-stagger: 0ms; }
}

[data-theme="dark"],
html.dark-mode {
  --tm-shadow-card:    0 1px 2px rgb(0 0 0 / 0.40);
  --tm-shadow-overlay: 0 4px 12px rgb(0 0 0 / 0.45);
  --tm-shadow-modal:   0 16px 48px rgb(0 0 0 / 0.60);
}

.tm-ds {
  /* ---------- Radius (3) ---------- */
  --tm-radius-control: var(--tm-radius-md);   /* 6px  — input, badge, button */
  --tm-radius-card:    16px;                  /* Cila V1: eski var(--tm-radius-xl)=14px; yalnız kart token'ı büyüdü */
  --tm-radius-overlay: var(--tm-radius-xl);   /* 14px — modal, popover (DEĞİŞMEDİ) */

  /* ---------- Resting surfaces: one soft shadow, no hover lift ---------- */
  --tm-card-shadow:       var(--tm-shadow-card);
  --tm-card-shadow-hover: var(--tm-shadow-card);

  /* ---------- Surfaces ---------- */
  --tm-bg-canvas:  var(--tm-surface-sunken);  /* page background */
  --tm-bg-surface: var(--tm-surface);         /* card — the ONE card tone per mode */
  --tm-bg-subtle:  var(--tm-ink-100);         /* table head, hover row */
  /* --tm-border / --tm-border-strong / --tm-text-primary / -secondary / -muted:
     inherited from tokens.css as-is (already semantic, already dark-aware). */

  /* ---------- Meaning colours: one job each ---------- */
  --tm-accent:      var(--tm-accent-500);
  --tm-accent-fg:   var(--tm-accent-600);
  --tm-accent-bg:   var(--tm-accent-50);
  --tm-accent-solid: #0175e4;                 /* solid accent SURFACE (brand blue, both modes; dark-mode.css lightens --tm-accent-500 for text/borders, not for a filled card) */
  --tm-on-accent:   var(--tm-text-on-brand);  /* text on a solid accent surface */
  --tm-success-fg:  var(--tm-ok);
  --tm-success-bg:  var(--tm-ok-bg);
  --tm-warning-fg:  var(--tm-warn);
  --tm-warning-bg:  var(--tm-warn-bg);
  --tm-danger-fg:   var(--tm-bad);
  --tm-danger-bg:   var(--tm-bad-bg);
  --tm-info-fg:     var(--tm-info);
  /* --tm-info-bg: NOT re-declared here. tokens.css already owns that exact name for both
     modes (#e0f2fe light / rgba(2,132,199,.15) dark) and it inherits into .tm-ds, exactly
     like --tm-border / --tm-text-* above. Until 2026-09-16 this line read
     `--tm-info-bg: var(--tm-info-bg)` — a self-reference. Per CSS spec a cyclic custom
     property is invalid at computed-value time, so it did not fall back to the tokens.css
     value: it OVERRODE it with nothing and every .tm-badge--info/--picking rendered on a
     TRANSPARENT background (measured in a real browser: rgba(0,0,0,0)). The badge then read
     as plain blue text, which looks like a link — a broken token that passed for a design
     choice. Siblings are safe because they alias a DIFFERENT primitive name
     (--tm-success-bg: var(--tm-ok-bg)); only info shared its own name. */

  /* ---------- Chart palette (value-preserving: identical to the literals
     hard-coded in static/js/tm-charts.js:21 before Faz 3 binds it here) ---------- */
  --tm-chart-1: var(--tm-brand-500);   /* #0175e4 */
  --tm-chart-2: var(--tm-orange-500);  /* #fd751f */
  --tm-chart-3: var(--tm-ok);          /* #16a34a */
  --tm-chart-4: var(--tm-brand-300);   /* #73b7fe */
  --tm-chart-5: #8b5cf6;               /* violet — no primitive exists yet */
  --tm-chart-6: #f59e0b;               /* amber  — no primitive exists yet */
  --tm-chart-7: var(--tm-bad);         /* #dc2626 */
  --tm-chart-axis:  var(--tm-text-muted);
  --tm-chart-track: var(--tm-ink-100);
  --tm-chart-grid:  var(--tm-border);

  /* ---------- Type scale (6) — size / line-height ---------- */
  --tm-type-display:    24px; --tm-type-display-lh: 32px;   /* page title, KPI number (≥1440) */
  --tm-type-display-sm: 20px; --tm-type-display-sm-lh: 28px; /* KPI number in the 5-up row under 1440 (24 ÷ 1.14).
     Do not raise this to the reference's 24/700: that figure was measured on a 4-up deck with wider cards.
     In our 5-up deck (user decision, ui-reference-spec.md line 47) the longest real value clips — measured
     2026-09-24, "264.254,40 TL" needs 150px against 144px of value box at 1280 and 148px at 1024. */
  --tm-type-title:      18px; --tm-type-title-lh:   28px;   /* section title */
  --tm-type-heading:    16px; --tm-type-heading-lh: 24px;   /* card title */
  --tm-type-body:       14px; --tm-type-body-lh:    20px;   /* table cell, subtitle */
  --tm-type-caption:    12px; --tm-type-caption-lh: 16px;   /* label, legend, delta */
  --tm-type-micro:      11px; --tm-type-micro-lh:   14px;   /* axis, badge */
  --tm-weight-regular:  400;
  --tm-weight-medium:   500;
  --tm-weight-semibold: 600;
  --tm-weight-bold:     700;

  /* ---------- KPI card: one fixed height for skeleton AND loaded card (the 14px grow when
     real cards replaced 148px placeholders was the whole CLS 0.014 on Genel Bakış) ---------- */
  --tm-dash-kpi-h: 160px;   /* reference 150 + 24px icon-disc row − tighter body; legacy value 148 stays outside .tm-ds */

  /* ---------- Density (Faz 3 DataTable / Faz 4 orders toggle) ---------- */
  --tm-row-h:       var(--tm-dash-table-row-h);    /* 52px comfortable */
  --tm-row-h-dense: var(--tm-dash-table-dense-h);  /* 40px */
}

/* Numeric columns / live counters: digits keep a fixed advance so values do
   not jitter when they change (Canlı Performans stability rule). */
.tm-ds .tm-num,
.tm-ds .kpi-value,
.tm-ds .tm-table td.tm-num,
.tm-ds [data-tm-num] {
  font-variant-numeric: tabular-nums;
}

/* =================================================================
   SHELL (A2, 2026-09-13) — sidebar / topbar / demo-banner / promo-FAB live
   OUTSIDE <main class="tm-ds">, so the `.tm-ds { … }` block above is invisible
   to them (custom properties only resolve for the scoping element + its
   descendants). This mirror is scoped to `body.tm-ds-shell` instead (set in
   templates/layouts/base.html exactly when `.tm-ds` is active AND ?legacy=1
   is absent — same pages, different ancestor). Consumed by
   static/css/ds/ds-shell.css. Kept HERE (not in ds-shell.css) because this
   is the one DS file the guard allows colour literals in
   (tests/test_ui_design_system_guard.py: TOKEN_FILE excluded from the
   colour-literal check) — the shell's permanently-dark sidebar surface has
   no existing semantic alias to reuse (unlike control-radius / shadow-card,
   which are already global in static/css/v2/tokens.css and used as-is). */
body.tm-ds-shell {
  /* Sidebar: ONE dark neutral surface in both app-themes (reference target,
     docs/ui-design-log.md § Kabuk). Text tones checked for ≥ 4.5:1 on --tm-shell-sidebar-bg. */
  /* --tm-shell-sidebar-* tokenları KALDIRILDI (2026-10-08): sol ray artık
     kendi tokenlarını v2/components/sidebar.css §0'da tanımlıyor. Bu küme
     yalnız ds-shell.css tarafından okunuyordu ve ray'e İKİNCİ bir renk
     kaynağı veriyordu (ds sayfalarında #12161f, diğerlerinde başka). Ölü
     token bırakmak, birinin yeniden bağlamasını davet eder. */
  /* Ticker band token'lari :root'a tasindi — asagiya bak (2026-09-16). */
  --tm-shell-accent:              #0175e4;   /* == --tm-accent-solid (.tm-ds-scoped, invisible here) */

  /* Control radius mirror (identical value to `.tm-ds`'s var(--tm-radius-md);
     no `.tm-ds` alias reaches the shell, so it is restated here, not copied
     as a literal). --tm-radius-full is already global (static/css/v2/tokens.css
     :root), no mirror needed. */
  --tm-radius-control: var(--tm-radius-md);
  /* Card/overlay radius mirror — portalled modals (catalog picker appends to
     body) are outside `.tm-ds`; without this they fall back to 6px. */
  --tm-radius-card:    var(--tm-radius-xl);
  --tm-radius-overlay: var(--tm-radius-xl);
}


/* ---------- Top announcement band tokens (ticker) — :root, KAPSAMSIZ -------
   templates/includes/_shell_ticker.html her sayfada render edilebilsin diye bu 7 token
   `body.tm-ds-shell` blogundan `:root`a tasindi (2026-09-16, kullanici istegi: "bu banner
   cok guzel ama bazi sayfalarda var bazilarinda yok, tum sayfalarda gozuksun").

   🔴 NEDEN ZORUNLUYDU: ticker kurallari bu token'lari 18 yerde kullaniyor ve HICBIRINDE
   `var(--x, yedek)` fallback'i yok. Kapsam disinda kalirlarsa CSS kuralinca deger `unset`
   olur → band zemini SEFFAF, metin miras — yani "kaynakta var, ekranda yok". Olculdu:
   7 token yalniz `body.tm-ds-shell`'de tanimliydi, digerleri (`--tm-space-*`, `--tm-radius-*`)
   zaten `v2/tokens.css`'te `:root`ta.

   ⚠️ Bu token'larin dark-mode varyanti YOK (tek tanim) — band iki modda da ayni renkte,
   bilerek: duyuru seridi marka rengi tasiyor, tema ile degismiyor. */
:root {
  /* 🔴 KONTRAST DUZELTMESI (2026-09-16, olculdu). Eski ton renkleri beyaz metinle AA'yi
     GECMIYORDU — serit metni 14/15px (buyuk-metin esigi degil), yani esik 4.5:
         eski  promo #0175e4 = 4.50 (tam sinir)  ·  success #16a34a = 3.30 ❌
               warning #d97706 = 3.19 ❌          ·  danger #dc2626 = 4.83
     Tonlar bir kademe koyulastirildi; ayni renk ailesi, okunur:
         yeni  promo 5.89 · success 5.02 · warning 5.02 · danger 5.75
     Bu, kullanicinin "gorsel iyilestirme" istegiyle AYNI turda cikti: banda parilti eklemek
     icin once zeminin okunur olmasi gerekiyordu — ACIK parilti kontrasti DUSURUYOR
     (olculdu: alpha .08 -> en dusuk 2.90), o yuzden parilti KOYU uctan yapiliyor. */
  --tm-shell-band-bg:      #0163c2;
  --tm-shell-band-bg-2:    #0b5cab;   /* gradyanin koyu ucu — kontrast tabandan YUKSEK */
  --tm-shell-band-fg:      #ffffff;
  --tm-shell-band-fg-18:   rgba(255, 255, 255, 0.18);
  --tm-shell-band-fg-45:   rgba(255, 255, 255, 0.45);
  --tm-shell-band-ok:      #15803d;
  --tm-shell-band-ok-2:    #166534;
  --tm-shell-band-warn:    #b45309;
  --tm-shell-band-warn-2:  #92400e;
  --tm-shell-band-danger:  #c62222;
  --tm-shell-band-danger-2:#b91c1c;
}

/* ---------- Cila V1 (2026-09-23, onaylı mockup docs/ui-audit/mockups/polish-v1.css,
   entegrasyon: static/css/ds/ds-polish.css) — 4 yeni token, yalnız burada mevcut
   bir semantic ada indirgenemeyen 4 durum için (gerisi mevcut token'lardan
   kuruluyor: --tm-brand-*, --tm-decor-*-soft, --tmv2-surface-2/3,
   --tmv2-form-focus-shadow, --tm-account-hero-gradient). Sidebar gradyanı
   :root'ta KAPSAMSIZ (sidebar her temada koyu — bkz. v2/components/sidebar.css
   §20 yorumu); header glass/gölge ve demo-banner yalnız açık temada kullanılır
   (ds-polish.css'te `html:not(.dark-mode):not([data-theme="dark"])` önekiyle). */
:root {
  --tm-polish-sidebar-grad: linear-gradient(180deg, #0f1622 0%, #0b1119 100%);
  --tm-polish-sidebar-active-grad: linear-gradient(90deg, rgba(1, 117, 228, 0.28), rgba(1, 117, 228, 0.10));
  --tm-polish-header-glass: rgba(255, 255, 255, 0.82);
  --tm-polish-header-shadow: 0 8px 24px -20px rgba(15, 23, 42, 0.35);
  --tm-polish-demo-bg-from: #fff4dc;
  --tm-polish-demo-bg-to: #fff8e8;
  --tm-polish-demo-border: #f3dfae;
}


/* ===== css/ds/ds-primitives.css ===== */
/* =================================================================
   TRENDMETRIK DESIGN SYSTEM — LAYOUT PRIMITIVES (Faz 2, 2026-09-12)

   Scope: every rule lives under .tm-ds (set on <main> by pages that opted in
   via {% block tmv2_ds_scope %}) → inert on the other ~200 pages.
   Padding owners: .tm-page and .tm-card ONLY. Everything else aligns; nothing
   else adds space. Sibling spacing is always the parent's gap, never margin.
   Resting surfaces: 1px border + the single --tm-shadow-card (reference-derived).

   Primitives:
     .tm-page            single outer container (max-width + --tm-space-6 padding)
     .tm-page-header     title · subtitle · actions — one per page
     .tm-grid            12-column grid, gap --tm-space-4, rows stretch
       .tm-col-{1..12}   column span (collapses: ≥6→12 under 1024, all→12 under 768)
     .tm-card            one content surface; .tm-card__header inside it
   ⚠ SCOPE: every DS rule is a DESCENDANT selector (`.tm-ds .tm-card`). Putting `tm-ds` and
     `tm-card` on the SAME node does NOT match — the element ends up completely unstyled
     (background rgba(0,0,0,0), border 0px) while the source looks correct. Use a wrapper:
     `<div class="tm-ds"><div class="tm-card">`. (Measured 2026-09-16, buybox banner.)
     This is the opposite of the modal-portal fix, where the scope class DOES go on the node
     itself — because there the node is the ANCESTOR of the DS-styled children.
     .tm-stack / .tm-row vertical / horizontal flow, gap only
     .tm-divider         1px separator inside a card (instead of a nested card)
   ================================================================= */

/* 🔴 Kapsam KÖKÜ font-family'i (2026-09-17 — kullanıcı: "yazıların stilleri
   uyumlu olsun", ⑥ madde). ÖLÇÜLDÜ (rendered DOM, 4 ds-scope'lu sayfa):
   `.tm-page-header__title` + `.tm-tab` (v2/components/tabs.css, `--tm-font-
   sans` KULLANIYOR, ds-DIŞI ama AYNI token) `"Inter var", Inter, ...` alıyor;
   `.tm-text-title`/`.tm-num`/`.tm-text-caption`/`.tm-badge` gibi ds
   utility'lerinin HİÇBİRİ font-family YAZMIYOR → Tailwind preflight'ın
   `ui-sans-serif, system-ui, ...` varsayılanına DÜŞÜYOR. Yani aykırı olan
   `.tm-tab` DEĞİLDİ (önceki varsayım YANLIŞTI) — aykırı olan ds utility'
   lerinin KENDİ token'ını hiç UYGULAMAMASIYDI.
   A/B ÖLÇÜMÜ (gerçek Chromium, aynı metin, iki stack yan yana): genişlik
   farkı 0px — repo'da HİÇBİR `@font-face` YOK, "Inter var"/"Inter" hiçbir
   makinede YÜKLENMİYOR, ikisi de aynı sistem-fontuna (`-apple-system`/
   `Segoe UI`/`ui-sans-serif`) düşüyor. Yani bu kural pratikte HİÇBİR sayfayı
   BOZMUYOR — computed-style DİZGİSİNİ tek token'a topluyor, görünen glif
   AYNI kalıyor (ve "Inter" ileride gerçekten yüklenirse tutarlılık ekliyor).
   Karar (koordinatörün ①/②/③ kuralı): tutarlılık yönünde + hiçbir sayfa
   bozulmuyor → DS'E TEK KURAL (dar `.tm-tab` müdahalesi değil). */
.tm-ds { font-family: var(--tm-font-sans); }

/* ---------- Page ---------- */
.tm-ds .tm-page {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: var(--tm-space-6);
  width: 100%;
  max-width: var(--tm-container-max);
  min-width: 0;
  margin: 0 auto;
  padding: var(--tm-space-6) 0;   /* horizontal gutter comes from the shell (.tmv2-page-body, 32px) — identical on every page */
  background: transparent;
  overflow-x: clip;
}
.tm-ds .tm-page--constrained { max-width: var(--tm-content-max); }

/* The shell wrappers between <main> and .tm-page must not add space of their
   own inside DS scope (they fight over padding with !important elsewhere —
   audit §2). Faz 4 measures this per page; Faz 5 removes the legacy rules. */
.tm-ds .tmv2-page-inner,
.tm-ds .tmv2-page-shell,
.tm-ds .tmv2-page-body {
  padding: 0;
  max-width: none;
}

/* ---------- Page header ---------- */
.tm-ds .tm-page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--tm-space-4);
  min-height: 40px;
  padding: 0;
}
.tm-ds .tm-page-header__title-group {
  display: flex;
  flex-direction: column;
  gap: var(--tm-space-1);
  min-width: 0;
}
.tm-ds .tm-page-header__title {
  margin: 0;
  font-family: var(--tm-font-sans);
  font-size: var(--tm-type-display);
  line-height: var(--tm-type-display-lh);
  font-weight: var(--tm-weight-bold);
  color: var(--tm-text-primary);
  letter-spacing: var(--tm-tracking-tight);
}
.tm-ds .tm-page-header__subtitle,
.tm-ds .tm-page-header__eyebrow {
  margin: 0;
  font-size: var(--tm-type-body);
  line-height: var(--tm-type-body-lh);
  color: var(--tm-text-secondary);
}
.tm-ds .tm-page-header__actions {
  display: flex;
  align-items: center;
  gap: var(--tm-space-2);
  flex-shrink: 0;
}

/* ---------- Grid ---------- */
.tm-ds .tm-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--tm-space-6) var(--tm-space-4);   /* rows 24 · columns 16 (reference) */
  align-items: stretch;
  width: 100%;
  min-width: 0;
}
.tm-ds .tm-col-1  { grid-column: span 1; }
.tm-ds .tm-col-2  { grid-column: span 2; }
.tm-ds .tm-col-3  { grid-column: span 3; }
.tm-ds .tm-col-4  { grid-column: span 4; }
.tm-ds .tm-col-5  { grid-column: span 5; }
.tm-ds .tm-col-6  { grid-column: span 6; }
.tm-ds .tm-col-7  { grid-column: span 7; }
.tm-ds .tm-col-8  { grid-column: span 8; }
.tm-ds .tm-col-9  { grid-column: span 9; }
.tm-ds .tm-col-10 { grid-column: span 10; }
.tm-ds .tm-col-11 { grid-column: span 11; }
.tm-ds .tm-col-12 { grid-column: span 12; }
.tm-ds .tm-grid > * { min-width: 0; }

@media (max-width: 1023.98px) {
  .tm-ds .tm-col-6, .tm-ds .tm-col-7, .tm-ds .tm-col-8, .tm-ds .tm-col-9,
  .tm-ds .tm-col-10, .tm-ds .tm-col-11 { grid-column: span 12; }
  .tm-ds .tm-col-3, .tm-ds .tm-col-4, .tm-ds .tm-col-5 { grid-column: span 6; }
}
@media (max-width: 767.98px) {
  .tm-ds .tm-page { padding: var(--tm-space-4) 0; gap: var(--tm-space-4); }
  .tm-ds .tm-grid { gap: var(--tm-space-3); }
  .tm-ds .tm-grid > [class*="tm-col-"] { grid-column: span 12; }
  .tm-ds .tm-page-header { flex-direction: column; align-items: flex-start; }
}

/* ---------- Card (the only content surface) ---------- */
.tm-ds .tm-card {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: var(--tm-space-4);
  min-width: 0;
  padding: var(--tm-space-6);
  background: var(--tm-bg-surface);
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-card);
  box-shadow: var(--tm-shadow-card);
  color: var(--tm-text-primary);
  transition: none;
}
/* 🔴 GENEL `:hover` kuralı KALDIRILDI (2026-09-17 — ÖLÇÜLDÜ, gerçek mouse
   hover + 6 hesaplanmış özellik: box-shadow/transform/background/border/
   cursor/outline, `diffKeys: []`). Kök: `box-shadow` REST'teki AYNI değeri
   tekrar yazıyordu + `transform: none` lift'i açıkça kapatıyordu + base
   kuralda `transition: none` olduğu için ZATEN geçişsizdi — üçü birlikte
   sıfır görsel etki üretiyordu ("fire ediyor ama görünmüyor"). Bırakmak
   okuyanı "hover var" sanmaya iterdi; kaldırmanın blast-radius'u SIFIR
   (hiçbir yerde bir şeyi DEĞİŞTİRMİYORDU). Satır-bazlı gerçek hover
   `.tm-card--band[data-bb3-row]:hover` altında, aşağıda. */
.tm-ds .tm-card--flush { padding: 0; }           /* table fills the card edge to edge */
.tm-ds .tm-card--flush > .tm-card__header { padding: var(--tm-space-6) var(--tm-space-6) 0; }

/* --band: TEK SATIRLIK bildirim şeridi (metin + tek aksiyon). Dolgu 24px → 12/16, satır-arası
   boşluk 16 → 8. Gerekçe (buybox oturumu, 2026-09-16 ölçümü): `.tm-card` ile kurulan şerit 90px
   oluyor; Genel Bakış'ta mevcut promo şeridiyle üst üste gelince ~134px üst-fold demek. Kullanıcı
   bu panel için üç turdur "çok karmaşık, dağınık" diyor — dikey bütçe burada gerçek bir maliyet.
   ⚠ Kart DEĞİLDİR: içine `__header`/kolon yığını koyulmaz. Tek satır taşamıyorsa `.tm-card` kullan.
   Yükseklik sabitlenmedi (`height`/`min-height` YOK): 360px'te metin iki satıra düşer ve şerit
   kendiliğinden uzar — sabit yükseklik orada metni keserdi. */
.tm-ds .tm-card--band { padding: var(--tm-space-3) var(--tm-space-4); gap: var(--tm-space-2); }
.tm-ds .tm-card--band > .tm-card__body { display: flex; flex-direction: row; align-items: center; gap: var(--tm-space-3); flex-wrap: wrap; }

/* 🔴 SATIR HOVER — GERÇEK geri bildirim (kullanıcı: "görsel olarak çok
   düz... görsel canlılık eklenmeli", 2026-09-17). ÖLÇÜLDÜ: genel
   `.tm-card:hover` (yukarıda kaldırıldı) sıfır görsel etki üretiyordu.
   Desen YENİ İCAT EDİLMEDİ — `ds-table.css:71`teki AYNI kalıp
   (`.tm-table tbody tr:hover > td { background: var(--tm-bg-subtle); }`)
   satır bağlamına taşındı, tutarlılık için.
   🔴 `prefers-reduced-motion` ALTINA KONMADI (koordinatör kararı,
   2026-09-17): bu bir DURUM DEĞİŞİMİ (renk), HAREKET değil — o ayar
   açık olan kullanıcı için bile çalışmaya devam etmeli; azaltılmış
   hareket tercihi, azaltılmış GERİ BİLDİRİM anlamına gelmemeli.
   `[data-bb3-row]` ile SADECE buybox v3 fırsat satırlarına daraltıldı —
   `.tm-card--band` `_campaign_hero.html`/`_rules_manager.html`/v2
   `_opportunity_banner.html`de de kullanılıyor, blast-radius onları
   ETKİLEMESİN diye. Boyut/dikey uzunluk DEĞİŞMEDİ — yalnız renk. */
.tm-ds .tm-card--band[data-bb3-row]:hover { background: var(--tm-bg-subtle); }

/* 🔴 SOL ŞERİT — fırsat büyüklüğüne göre renk (kullanıcı: "listeyi daha
   okunabilir renkli vs yapmak lazım", 2026-09-17).
   Amaç süs değil TARANABİLİRLİK: 100 satırlık listede göz, sayıyı okumadan
   önce şeridi görür ve nereye bakacağını seçer.
   ⚠️ TABAN ŞEFFAF: her satır AYNI geometriyi alır, yalnız RENK değişir —
   yoksa kademesi olan satır 3px kayar ve liste tırtıklı görünür (bu sayfanın
   üç turdur kovaladığı "kayma" şikâyetinin ta kendisi).
   ⚠️ Kademe adı `bb3-render.js::gapTone`'dan gelir; eşik BURADA TEKRAR
   YAZILMAZ — renk ile sayı aynı kaynaktan beslenir.
   ⛔ `unknown` (fark hesaplanamadı) BOYANMAZ: "bilmiyorum"u en soluk tonla
   göstermek onu "küçük fırsat" diye okutur.
   `[data-bb3-row]` ile yalnız v3 fırsat satırlarına daraltıldı — `.tm-card--band`
   başka yerlerde de kullanılıyor, blast-radius onları etkilemesin. */
.tm-ds .tm-card--band[data-bb3-row] { border-inline-start: 3px solid transparent; }
.tm-ds .tm-card--band[data-bb3-row][data-bb3-tier="high"] { border-inline-start-color: var(--tm-success-fg); }
.tm-ds .tm-card--band[data-bb3-row][data-bb3-tier="mid"]  { border-inline-start-color: color-mix(in srgb, var(--tm-success-fg) 75%, var(--tm-text-secondary) 25%); }
.tm-ds .tm-card--band[data-bb3-row][data-bb3-tier="low"]  { border-inline-start-color: color-mix(in srgb, var(--tm-success-fg) 45%, var(--tm-text-muted) 55%); }
/* `flex-direction: row` AÇIKÇA yazılı: `.tm-ds .tm-card__body` `column` diyor ve bu kural onu
   EZMEZ — yalnız yazmadığın özellik miras kalır. İlk yazımda unuttum, şerit 86px kaldı (hedef
   ~54); ölçünce çıktı. Aynı hatanın kardeşi bugün `.cpk-weekly__tabs`'ta yaşandı. */

.tm-ds .tm-card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--tm-space-3);
  min-height: 24px;
}
.tm-ds .tm-card__title {
  margin: 0;
  font-size: var(--tm-type-heading);
  line-height: var(--tm-type-heading-lh);
  font-weight: var(--tm-weight-semibold);
  color: var(--tm-text-primary);
}
.tm-ds .tm-card__subtitle {
  margin: 0;
  font-size: var(--tm-type-caption);
  line-height: var(--tm-type-caption-lh);
  color: var(--tm-text-muted);
}
.tm-ds .tm-card__actions {
  display: flex;
  align-items: center;
  gap: var(--tm-space-2);
  flex-shrink: 0;
}
.tm-ds .tm-card__body { display: flex; flex-direction: column; gap: var(--tm-space-3); min-width: 0; flex: 1 1 auto; }

/* ---------- Flow ---------- */
.tm-ds .tm-stack { display: flex; flex-direction: column; gap: var(--tm-space-4); min-width: 0; }
.tm-ds .tm-row   { display: flex; flex-direction: row; align-items: center; gap: var(--tm-space-3); min-width: 0; flex-wrap: wrap; }
.tm-ds .tm-stack--tight, .tm-ds .tm-row--tight { gap: var(--tm-space-2); }
.tm-ds .tm-stack--loose, .tm-ds .tm-row--loose { gap: var(--tm-space-6); }
.tm-ds .tm-row--between { justify-content: space-between; }
.tm-ds .tm-row--end { justify-content: flex-end; }
/* 🔴 `flex-basis: 0%` (Tailwind'in `flex-1`iyle AYNI), `auto` DEĞİL — bilerek.
   `min-width:0` yalnız SHRINK aşamasını serbest bırakır; SATIR KIRMA kararı
   `flex-basis`e (auto→max-content) bakar, shrink potansiyeline BAKMAZ.
   Ölçüldü (2026-09-16, buybox 390px, çizilmiş DOM): checkbox+thumb'ın
   yanındaki ad+barkod grubu `flex:1 1 auto` iken UZUN ADIN max-content
   genişliği (~301px) satıra sığmıyordu → grup THUMB'IN ALTINA
   kırılıyordu (ad.top 428 >= thumb.bottom 420), oysa `.tm-truncate`
   içeriği zaten kırpabiliyordu — kırpma devreye girmeden satır kırılması
   karar veriliyordu. `flex-basis:0%` bu grubun satır-kırma hesabına max-
   content'i SOKMAZ; grup sıfır tabanla satıra girer, `flex-grow:1` kalan
   alanı doldurur, `.tm-truncate` içeride kırpar. Sonuç: 390'da ad artık
   THUMB'IN YANINDA (aynı satır), satır kırılmıyor.

   ⚠️ GLOBAL PRİMİTİF — DEĞİŞİKLİKTEN ÖNCE PATLAMA YARIÇAPI ÖLÇÜLDÜ (Tailwind
   `flex-1`/`flex-auto`u BİLEREK ayırır; burada `.tm-grow` TEK sınıf olduğu
   için `auto→0%` HER tüketiciyi etkiler). Repo-genelinde `.tm-grow` YALNIZ
   2 şablonda, 13 kullanım (`buybox/v3/_opportunity_list.html`,
   `_rule_wizard.html`) — hepsi tek-satır (`.tm-row`/`.tm-stack`) içinde TEK
   büyüyen öğe ya da `.tm-truncate` ile eşleşiyor, sabit-genişlik beklentisi
   YOK. 5× boş iskelet `<span>` (içerik yok → `auto` da `0%` de 0, fark yok).
   Ölçüldü (gerçek Chromium, 390px, sihirbaz adım 1/3): `_rule_wizard.html`
   strateji etiketleri AYNI kökten AYNI hatayı taşıyordu — "Rakiple eşleş" /
   "Kademeli in" metni radyo düğmesinin YANINA sığmıyor, ALTINA kırılıyordu
   (`auto`: satır 85px/69px, metin kutusu düğmeyle aynı-satırda DEĞİL); bu
   fix'le düzeldi (satır 64px, metin düğmenin yanında). Adım 3 önizleme
   `dl`sindeki 3 istatistik sütunu içerik-oranlı (98/98/88px) → eşit
   (95/95/95px) genişliğe geçti — taşma/kırpma YOK, görsel iyileşme.
   12/12 sihirbaz+önizleme testi yeşil. Karar: GLOBAL KABUL (tek tüketici
   grubu bile bulunmadı, geri alınacak bir davranış YOK). */
.tm-ds .tm-grow { flex: 1 1 0%; min-width: 0; }

/* Sabit-taban KARŞILAŞTIRMA sütunu — flex satırında (TABLO DEĞİL; `.tm-table
   .tm-col-*` `width` kullanır ve `td`ye bağımlıdır, burada karşılığı yok).
   `min-width` (`width` DEĞİL): taşan içerik KIRPILMAZ. Fiyat metninin
   KENDİSİNİ hizalar (`.tm-col-info` aşağıda gerçek kökü çözer); bu ikisi
   BİRLİKTE çalışıyor. Tek tüketici bugün: `_opportunity_list.html`
   `[data-bb3-prices]`. */
.tm-ds .tm-col-value { display: inline-block; min-width: 26ch; }

/* 🔴 ASIL "KAYMA" KÖKÜ (kullanıcı geri bildirimi + ÖLÇÜM, 2026-09-17):
   fiyat metninin KENDİSİ değil, `.tm-card__body`'nin İKİ üst-seviye
   çocuğunun paylaşım biçimiydi. Ad grubu (`.tm-grow`, flex-basis 0%) satırda
   KALAN her şeyi yutar; bilgi/aksiyon grubu `auto` bazlıydı — yani ONUN
   genişliği (rozet metni + fark tutarı uzunluğuna göre) değiştikçe ad grubu
   ne kadar yer bırakacağını yeniden hesaplıyor ve bilgi grubunun BAŞLANGIÇ
   x'i satırdan satıra kayıyordu (Chromium'da ÖLÇÜLDÜ: TY1/TY4 satırlarında
   824,7px vs 848,9px — 24px fark, salt rozet metni uzunluğundan).
   Çözüm: bu gruba SABİT bir `flex-basis` ver (`auto` DEĞİL) — artık ad
   grubu HER satırda AYNI genişliği bırakıyor, bilgi grubu HER SATIRDA AYNI
   x'te başlıyor. `flex-shrink:1` + `min-width:0` KALDI: 390'da bu grup gene
   kendi satırına düşüp gerektiği kadar küçülebiliyor (mevcut wrap deseni
   BOZULMADI). Değer bugünkü en geniş içeriğe (~437px) değil, PAY BIRAKARAK
   seçildi (~480px) — `bbx-design`'ın bu bloğa ekleyeceği sapma göstergesi/
   durum işareti/denetim izi bugün taşmasın diye (koordinatör talebi).
   ⚠️ `.tm-grow` (ad grubu) BURADA DEĞİŞMEDİ — o ayrı, ölçülmüş, "GLOBAL
   KABUL" edilmiş bir primitif (yukarıdaki not); bu sınıf onun KARDEŞİNE
   uygulanıyor, ikisi çakışmıyor. */
.tm-ds .tm-col-info { flex: 0 1 480px; min-width: 0; }

/* ---------- Card density modifier (liste satırı) ---------- */
/* 🔴 ÖLÇÜLDÜ (2026-09-18, kullanıcı: "SATIRLAR HALA DİKEY OLARAK ÇOK GENİŞ"):
   Buy Box fırsat satırı 1440px'te 130px. Parçalar: kart dolgusu 12+12=24 ·
   gövde dolgusu 20+20=40 · içerik 64 (görsel). Yani satırın %49'u SAF BOŞLUK.
   ⛔ GÖRSEL KÜÇÜLTÜLMEDİ: kullanıcı 2026-09-17'de tam tersini istedi
   ("görseller çok küçük") ve 64px o istekle geldi. Bir şikâyeti çözerken
   önceki şikâyeti geri getirmek kabul edilmez — sıkıştırma YALNIZ boşluktan.
   Ölçüm: 130 → 106px (-%18), görsel boyutu DEĞİŞMEDEN. */
/* ⚠️ YALNIZ ≥992px — ÖLÇÜMLE SINIRLANDI. İlk hâli kapsamsızdı ve 390px'te
   TERS etki yapıyordu: dar ekranda gövde dolgusu zaten daha küçük, kural onu
   8px'e ÇIKARIYOR ve satır 146 → 162px oluyordu (mevcut sıkılık testi
   kırmızı yandı, bisect ile bu dosyaya indirgendi). Yani "daraltma" diye
   yazılan kural mobilde GENİŞLETİYORDU. Kazanım masaüstünde ölçüldü, kural
   da orada kalıyor. */
@media (min-width: 992px) {
  .tm-ds .tm-card--dense > .tm-card__body {
    padding-top: var(--tm-space-2);
    padding-bottom: var(--tm-space-2);
  }
}

/* ---------- Divider (sectioning inside a card — never a nested card) ---------- */
.tm-ds .tm-divider {
  height: 1px;
  width: 100%;
  background: var(--tm-border);
  border: 0;
  margin: 0;
}

/* ---------- Focus ring: visible everywhere, same everywhere ---------- */
.tm-ds :focus-visible {
  outline: 2px solid var(--tm-accent);
  outline-offset: 2px;
  box-shadow: none;
}

/* ═══════════════════════════════════════════════════════════════════════════
   SİHİRBAZ BİLEŞENLERİ (2026-09-17, kullanıcı: "kural oluşturma modalinde
   görsel olarak daha iyi, checkbox yerine toggle, her adımı açıklayan
   animasyon veya ikonlar, daha okunaklı yazı renkleri ve büyüklükleri")

   ⚠️ Üçü de GLOBAL DS'te, sayfa CSS'i YOK (kullanıcının bağlayıcı kararı).
   ⚠️ Her kural `.tm-ds` altında — `test_every_primitive_rule_is_scoped_under_tm_ds`.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ---------- 1) ADIM GÖSTERGESİ (.tm-stepper) ----------
   Kullanıcı "her adımı açıklayan ikonlar" istedi. Metinsel "Adım 3 / 4" tek
   başına NEREDE olduğunu söyler ama NE KALDIĞINI göstermez.
   🔴 TAMAMEN CSS-SÜRÜCÜLÜ: geçerli adım ataya yazılan `data-current` ile
   seçilir (`bb3-wizard.js` tek satır yazar). Adım başına JS/sınıf yönetimi
   YOK — `bb3-wizard.js` 496/500 satırda ve bu bileşen ona 1 satır ekliyor. */
.tm-ds .tm-stepper { display: flex; align-items: center; gap: var(--tm-space-2); list-style: none; margin: 0; padding: 0; }
.tm-ds .tm-stepper__item { display: flex; align-items: center; gap: var(--tm-space-2); flex: 1 1 0; min-width: 0; }
.tm-ds .tm-stepper__dot {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; flex-shrink: 0;
  border-radius: var(--tm-radius-full);
  border: 1px solid var(--tm-border);
  background: var(--tm-bg-subtle);
  color: var(--tm-text-muted);
  /* Geçiş RENK/ZEMİN üzerinde — konum değişmiyor, yani "kayma" üretmiyor.
     `prefers-reduced-motion` bloğu (aşağıda) süreyi zaten sıfırlıyor. */
  transition: background-color var(--tm-dur-base) var(--tm-ease), color var(--tm-dur-base) var(--tm-ease), border-color var(--tm-dur-base) var(--tm-ease);
}
.tm-ds .tm-stepper__dot svg { width: 15px; height: 15px; }
.tm-ds .tm-stepper__label { font-size: var(--tm-font-caption); color: var(--tm-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tm-ds .tm-stepper__line { flex: 1 1 auto; height: 1px; background: var(--tm-border); min-width: var(--tm-space-2); }

/* GEÇERLİ adım: dolgulu + vurgulu. */
.tm-ds .tm-stepper[data-current="1"] > .tm-stepper__item:nth-of-type(1) > .tm-stepper__dot,
.tm-ds .tm-stepper[data-current="2"] > .tm-stepper__item:nth-of-type(2) > .tm-stepper__dot,
.tm-ds .tm-stepper[data-current="3"] > .tm-stepper__item:nth-of-type(3) > .tm-stepper__dot,
.tm-ds .tm-stepper[data-current="4"] > .tm-stepper__item:nth-of-type(4) > .tm-stepper__dot {
  background: var(--tm-accent-solid); border-color: var(--tm-accent-solid); color: #fff;
}
.tm-ds .tm-stepper[data-current="1"] > .tm-stepper__item:nth-of-type(1) > .tm-stepper__label,
.tm-ds .tm-stepper[data-current="2"] > .tm-stepper__item:nth-of-type(2) > .tm-stepper__label,
.tm-ds .tm-stepper[data-current="3"] > .tm-stepper__item:nth-of-type(3) > .tm-stepper__label,
.tm-ds .tm-stepper[data-current="4"] > .tm-stepper__item:nth-of-type(4) > .tm-stepper__label {
  color: var(--tm-text-primary); font-weight: 600;
}
/* TAMAMLANAN adımlar: yeşil kenar + yeşil ikon (ilerleme görünür olsun). */
.tm-ds .tm-stepper[data-current="2"] > .tm-stepper__item:nth-of-type(1) > .tm-stepper__dot,
.tm-ds .tm-stepper[data-current="3"] > .tm-stepper__item:nth-of-type(-n+2) > .tm-stepper__dot,
.tm-ds .tm-stepper[data-current="4"] > .tm-stepper__item:nth-of-type(-n+3) > .tm-stepper__dot {
  border-color: var(--tm-success-fg); color: var(--tm-success-fg); background: var(--tm-success-bg);
}

/* ---------- 2) TOGGLE (.tm-switch) ----------
   Kullanıcı: "checkbox yerine toggle". Onay kutusu *"form alanı"* gibi
   görünüyor; bu iki onay ise **yetki veriyor** (fiyat yazma izni). Anahtar
   metaforu o kararı daha doğru anlatıyor.
   🔴 GERÇEK `<input type="checkbox">` KORUNUR (görsel olarak gizlenir, ama
   DOM'da durur): klavye, `:checked`, form davranışı ve mevcut JS
   (`$('bb3Consent').checked`) aynen çalışır. Salt-CSS bir div ile taklit
   etmek erişilebilirliği ve mevcut kodu kırardı. */
.tm-ds .tm-switch { position: relative; display: inline-flex; align-items: center; flex-shrink: 0; width: 38px; height: 22px; }
.tm-ds .tm-switch > input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  margin: 0; opacity: 0; cursor: pointer;
}
.tm-ds .tm-switch > .tm-switch__track {
  pointer-events: none;
  width: 38px; height: 22px; border-radius: var(--tm-radius-full);
  background: var(--tm-bg-subtle); border: 1px solid var(--tm-border);
  transition: background-color var(--tm-dur-base) var(--tm-ease), border-color var(--tm-dur-base) var(--tm-ease);
}
.tm-ds .tm-switch > .tm-switch__track::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 16px; height: 16px; border-radius: var(--tm-radius-full);
  background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, .25);
  transition: transform var(--tm-dur-base) var(--tm-ease);
}
.tm-ds .tm-switch > input:checked + .tm-switch__track { background: var(--tm-accent-solid); border-color: var(--tm-accent-solid); }
.tm-ds .tm-switch > input:checked + .tm-switch__track::after { transform: translateX(16px); }
/* Odak HALKASI input'ta değil RAY'da görünür (input şeffaf) — klavye
   kullanıcısı anahtarın seçili olduğunu görmek zorunda. */
.tm-ds .tm-switch > input:focus-visible + .tm-switch__track { outline: 2px solid var(--tm-accent); outline-offset: 2px; }

/* ---------- 3) SEÇİM KARTI (.tm-card--choice) ----------
   ⚠️ KART VARYANTI olarak yazıldı, yeni bir bileşen olarak DEĞİL: DS'in
   "dolguyu yalnız sayfa ve kart sahiplenir" sözleşmesi
   (`test_padding_owners_are_page_and_card_only`) bunu şart koşuyor. İlk
   yazımımda `.tm-choice` idi ve kilit haklı olarak kırmızı yandı — kuralı
   gevşetmek yerine bileşen doğru yere taşındı.
   Adım 1'in radyo listesi düz metindi. Kart, tıklama alanını büyütür ve
   seçili olanı ZEMİNLE gösterir (yalnız küçük bir radyo noktasıyla değil). */
.tm-ds .tm-card--choice {
  /* 🔴 `flex-direction: row` AÇIKÇA YAZILI — `.tm-card` tabanı `column`
     diyor ve `display:flex` onu EZMEZ; yalnız YAZMADIĞIN özellik miras
     kalır. İlk yazımımda unuttum ve kullanıcı sonucu gördü: radyo, ikon,
     başlık ve açıklama ALT ALTA dizildi, kart 140px'e şişti.
     ⚠️ Bu dosyanın `--band` yorumu (yukarıda) AYNI tuzağı zaten yazıyor:
     *"İlk yazımda unuttum, şerit 86px kaldı; ölçünce çıktı."* İkinci kez. */
  display: flex; flex-direction: row; align-items: flex-start; gap: var(--tm-space-3);
  padding: var(--tm-space-3);
  border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control);
  cursor: pointer;
  transition: background-color var(--tm-dur-fast) var(--tm-ease), border-color var(--tm-dur-fast) var(--tm-ease);
}
.tm-ds .tm-card--choice:hover { background: var(--tm-bg-subtle); }
.tm-ds .tm-choice-ic {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; flex-shrink: 0;
  border-radius: var(--tm-radius-control);
  background: var(--tm-accent-bg); color: var(--tm-accent-fg);
}
.tm-ds .tm-choice-ic svg { width: 17px; height: 17px; }
/* `:has()` desteklenmiyorsa kart yine tıklanabilir ve radyo görünür kalır —
   yalnız seçili ZEMİN olmaz. Bilinçli düşüş (graceful degradation). */
.tm-ds .tm-card--choice:has(> input:checked) { border-color: var(--tm-accent-solid); background: var(--tm-accent-bg); }
.tm-ds .tm-card--choice:has(> input:focus-visible) { outline: 2px solid var(--tm-accent); outline-offset: 2px; }

/* ---------- KAYDIRMA KUTUSU (.tm-scrollbox) ----------
   Kullanici (2026-09-17): "buybox listesini scroll edilebilir yapalim, liste
   uzun ve sayfa dikey olarak cok uzuyor." 100 satir x ~130px = ~13.000px
   sayfa demek; ustteki sekmeler/ozet ekrandan cikiyor.
   UYARI `min(...vh, ...px)`: kucuk ekranda oransal, buyuk ekranda sabit tavan —
   4K'da 68vh 1.400px olurdu ve "uzun sayfa" sorunu geri gelirdi.
   UYARI `overscroll-behavior: contain`: liste sonuna gelince kaydirma SAYFAYA
   zincirlenmesin. */
.tm-ds .tm-scrollbox {
  max-height: min(68vh, 760px);
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* ---------- Firsat satirini SIKILASTIR ----------
   Kullanici: "satirlari biraz daha daralt, cok bosluklar var."
   YASAK: DOLGU DEGISTIRILMEDI — DS sozlesmesi dolguyu yalniz `.tm-page`/
   `.tm-card` (+ varyantlari) sahiplendiriyor ve `[data-bb3-row]` oznitelikli
   bir secici oraya giremez (`test_padding_owners_are_page_and_card_only`).
   Sikisma GAP'lerden alindi — kural gevsetilmedi.
   UYARI `[data-bb3-row]` ile yalniz v3 firsat satirlarina daraltildi. */
.tm-ds .tm-card--band[data-bb3-row] { gap: var(--tm-space-1); }
.tm-ds .tm-card--band[data-bb3-row] > .tm-card__body { gap: var(--tm-space-2); row-gap: var(--tm-space-1); }

/* ---------- ADIM İKONU ÇİZİLME ANİMASYONU ----------
   Kullanıcı (2026-09-17) iki kez istedi: *"ben svg animasyonu olsun istedim."*
   Lucide ikonları inline `<svg>` ve `stroke` ile çiziliyor → `stroke-dasharray`
   + `stroke-dashoffset` ile GERÇEK bir çizilme animasyonu kurulabiliyor.
   ⚠️ Süs değil BİLGİ: yalnız GEÇERLİ adımın ikonu çizilir, yani animasyon
   "neredesin"i anlatır. Her adımda çalışsa anlamı kalmazdı.
   ⚠️ `data-current` değişince seçici eşleşmesi değişir → animasyon her adımda
   yeniden başlar (JS gerekmiyor).
   🟢 `prefers-reduced-motion` bloğu (hemen aşağıda) süreyi zaten sıfırlıyor:
   hareket istemeyen kullanıcı ikonu ANINDA çizilmiş görür, kaybetmez. */
@keyframes tm-stepper-draw {
  from { stroke-dashoffset: 56; }
  to   { stroke-dashoffset: 0; }
}
.tm-ds .tm-stepper[data-current="1"] > .tm-stepper__item:nth-of-type(1) > .tm-stepper__dot svg,
.tm-ds .tm-stepper[data-current="2"] > .tm-stepper__item:nth-of-type(2) > .tm-stepper__dot svg,
.tm-ds .tm-stepper[data-current="3"] > .tm-stepper__item:nth-of-type(3) > .tm-stepper__dot svg,
.tm-ds .tm-stepper[data-current="4"] > .tm-stepper__item:nth-of-type(4) > .tm-stepper__dot svg {
  stroke-dasharray: 56;
  animation: tm-stepper-draw var(--tm-dur-morph) var(--tm-ease-out) forwards;
}

/* ---------- Motion only on user action ---------- */
@media (prefers-reduced-motion: reduce) {
  .tm-ds *, .tm-ds *::before, .tm-ds *::after {
    animation-duration: 0.001ms;
    animation-iteration-count: 1;
    transition-duration: 0.001ms;
    scroll-behavior: auto;
  }
}


/* ===== css/ds/ds-motion.css ===== */
/* =================================================================
   DS — MOTION GRAMMAR (PR-1, 2026-10-10 — docs/ui-design-log.md
   "Hareket dilbilgisi"; referans video kare kare ölçüldü)

   Referansta TEK hareket dili var ve her yerde aynı:
     giriş      opaklık 0→1 + 6px yukarı kayma · ~300 ms · ease-out · öğe başına ~50 ms kademe
     durum      renk/zemin/pil 200 ms
     veri       sayı/çizgi/çubuk MEVCUT değerden hedefe 450 ms (yok et + sıfırdan çiz YOK)
     ilk sayım  0 → değer 900 ms
   Bizde 1.337 `transition` (çoğu `all 0.2s ease`), 367 `@keyframes` adı ve
   8 ayrı süre yazımı vardı. Bu dosya DS kapsamı için TEK giriş animasyonu ve
   kademe mekanizmasını verir; süreler/eğriler YALNIZ token'dan okunur
   (ds-tokens.css `--tm-dur-*`, `--tm-stagger`; static/css/v2/tokens.css
   `--tm-ease*`). Guard: tests/test_ui_design_system_guard.py —
   DS dosyalarında literal süre/eğri RATCHET, `transition: all` YASAK.

   Kullanım (PR-2 koreografisi): kart SARMALAYICISINA `data-tm-stage="N"`
   (N = okuma sırası, 0..11). Attribute yalnız statik şablon öğelerine konur
   (TMKpi.render / TMCharts'ın yeniden yazdığı iç düğümlere DEĞİL — aksi hâlde
   her yeniden render girişi tekrar oynatır; 2026-07-17 KPI flicker vakası).

   Kurallar:
   - yalnız `opacity` + `transform` (layout özelliği animasyonu yasak);
   - `animation-fill-mode: backwards` → gecikme boyunca başlangıç karesi,
     bitişte NORMAL hesaplanmış stil: hiçbir öğe opaklık 0'da KALAMAZ
     (2026-09-10 "boş ızgara" kuralı);
   - prefers-reduced-motion: ds-primitives.css'teki `.tm-ds *` kuralı süreyi
     0.001 ms'e indirir ve ds-tokens.css süre token'larını 0'lar → bu dosyada
     AYRI bir reduced-motion bloğu YOK (26 dağınık blok sorununu büyütmemek için).
   ================================================================= */

@keyframes tm-enter {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* Tek giriş: kademe indeksi attribute'tan okunur (inline style yok — şablon
   `style=` ratchet'i tests/test_ui_design_system_guard.py). */
.tm-ds [data-tm-stage] {
  animation-name: tm-enter;
  animation-duration: var(--tm-dur-enter);
  animation-timing-function: var(--tm-ease-out);
  animation-fill-mode: backwards;
  animation-delay: calc(var(--tm-stage, 0) * var(--tm-stagger));
}
.tm-ds [data-tm-stage="0"]  { --tm-stage: 0; }
.tm-ds [data-tm-stage="1"]  { --tm-stage: 1; }
.tm-ds [data-tm-stage="2"]  { --tm-stage: 2; }
.tm-ds [data-tm-stage="3"]  { --tm-stage: 3; }
.tm-ds [data-tm-stage="4"]  { --tm-stage: 4; }
.tm-ds [data-tm-stage="5"]  { --tm-stage: 5; }
.tm-ds [data-tm-stage="6"]  { --tm-stage: 6; }
.tm-ds [data-tm-stage="7"]  { --tm-stage: 7; }
.tm-ds [data-tm-stage="8"]  { --tm-stage: 8; }
.tm-ds [data-tm-stage="9"]  { --tm-stage: 9; }
.tm-ds [data-tm-stage="10"] { --tm-stage: 10; }
.tm-ds [data-tm-stage="11"] { --tm-stage: 11; }

/* Grup kademesi: JS'in yeniden yazdığı çocuklar (TMKpi.render → .kpi-card) attribute
   taşıyamaz; ebeveyn `data-tm-stage-group="N"` taban indeksi verir, çocuk sırası
   (nth-child) eklenir → kart i, (N+i)×50 ms'de girer. SSR iskelet (.kpi-card--ph)
   animasyonsuz: yerini gerçek kart aldığında giriş bir kez oynar. Yeniden-render
   (2026-07-17 flicker vakası) grid.__tmRendered guard'ıyla nav başına 1×. */
.tm-ds [data-tm-stage-group="0"] { --tm-stage: 0; }
.tm-ds [data-tm-stage-group="1"] { --tm-stage: 1; }
.tm-ds [data-tm-stage-group="2"] { --tm-stage: 2; }
.tm-ds [data-tm-stage-group="3"] { --tm-stage: 3; }
.tm-ds [data-tm-stage-group="4"] { --tm-stage: 4; }
.tm-ds [data-tm-stage-group="5"] { --tm-stage: 5; }
.tm-ds [data-tm-stage-group="6"] { --tm-stage: 6; }
.tm-ds [data-tm-stage-group] > :not(.kpi-card--ph):not(.kpi-card):not(.tm-skeleton):not(.skeleton) {
  animation-name: tm-enter;
  animation-duration: var(--tm-dur-enter);
  animation-timing-function: var(--tm-ease-out);
  animation-fill-mode: backwards;
  animation-delay: calc((var(--tm-stage, 0) + var(--tm-i, 0)) * var(--tm-stagger));
}
/* 🔴 KPI KARTLARI GİRİŞ SOLMASI ALMAZ (2026-10-11, ölçüldü — Genel Bakış). Kartlar SSR
   iskeletinin (.kpi-card--ph) YERİNE geçiyor; `backwards` dolgu yeni kartı opaklık 0'da
   tutuyor ve animasyon ancak ana iş parçacığı boşalınca (render'dan ~250 ms sonra)
   başlıyordu → iskelet kayboluyor, satır ~200 ms BOŞ kalıyor, sonra kartlar beliriyordu
   (iskelet → boşluk → kart). İskelet → kart doğrudan geçiş; diğer kartların kademesi aynen
   → aşağıdaki grup kuralının `:not()` listesine `.kpi-card` eklendi. */
.tm-ds [data-tm-stage-group] > :nth-child(2) { --tm-i: 1; }
.tm-ds [data-tm-stage-group] > :nth-child(3) { --tm-i: 2; }
.tm-ds [data-tm-stage-group] > :nth-child(4) { --tm-i: 3; }
.tm-ds [data-tm-stage-group] > :nth-child(5) { --tm-i: 4; }
.tm-ds [data-tm-stage-group] > :nth-child(6) { --tm-i: 5; }
.tm-ds [data-tm-stage-group] > :nth-child(7) { --tm-i: 6; }
.tm-ds [data-tm-stage-group] > :nth-child(8) { --tm-i: 7; }

/* Kayan seçim göstergesi (segment kontrol / sekme pili): gösterge YER
   DEĞİŞTİRMEZ, kayar. Konteyner `data-tm-slide` alır; JS yalnız
   `--tm-slide-x` / `--tm-slide-w` (px) yazar, geri kalanı CSS. Referans:
   7/30/90 gün pili (1,7–2,5 s). Tüketici PR-3'te bağlanır; burada yalnız
   mekanizma. */
.tm-ds [data-tm-slide] { position: relative; isolation: isolate; }
.tm-ds [data-tm-slide]::before {
  content: "";
  position: absolute;
  top: var(--tm-space-1);
  bottom: var(--tm-space-1);
  left: 0;
  width: var(--tm-slide-w, 0px);
  transform: translateX(var(--tm-slide-x, 0px));
  border-radius: var(--tm-radius-control);
  background: var(--tm-bg-surface);
  box-shadow: var(--tm-shadow-card);
  /* yalnız transform geçer; `width` layout özelliğidir, animasyonu YASAK (docs/ui-reference-spec.md hareket bütçesi) — JS genişliği anında yazar */
  transition: transform var(--tm-dur-base) var(--tm-ease-out);
  opacity: 0;
  z-index: -1;
  pointer-events: none;
}
.tm-ds [data-tm-slide].is-slide-ready::before { opacity: 1; }

/* =================================================================
   SAYFA GEÇİŞİ — belge-arası View Transition (PR-7, 2026-10-11)
   Ölçüldü (nav-timeline.cjs): her sidebar tıklaması tam yeniden yükleme; ~1,1 s
   boyunca sidebar yok (boş sayfa) + 0,6–0,8 s "Yükleniyor" perdesi. Referans:
   kabuk sabit, içerik blur + solma ~200 ms. Tarayıcı destekliyorsa (Chromium 126+)
   eski sayfanın görüntüsü yeni sayfa çizilene kadar kalır, kök çapraz solar;
   sidebar/üst çubuk aynı adla eşleşir → yerinde durur. Desteklemeyen tarayıcıda
   kural yok sayılır (ilerici iyileştirme). Süre/eğri token'dan.
   NOT: aynı ad bir sayfada İKİ öğede olursa geçiş iptal olur — seçiciler tekil. */
@view-transition { navigation: auto; }
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: var(--tm-dur-base);
  animation-timing-function: var(--tm-ease-out);
}
::view-transition-old(root) { animation-name: tm-vt-out; }
::view-transition-new(root) { animation-name: tm-vt-in; }
@keyframes tm-vt-out { to { opacity: 0; } }
@keyframes tm-vt-in  { from { opacity: 0; } }
#tmv2SidebarRoot { view-transition-name: tm-sidebar; }
#tmv2Header { view-transition-name: tm-topbar; }
::view-transition-group(tm-sidebar),
::view-transition-group(tm-topbar) { animation-duration: 0s; }
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}

/* =================================================================
   SIRALI AÇILIŞ — yukarıdan aşağı (2026-10-11, kullanıcı: *"yükleme karmaşık,
   sıralı oluşmuyor; üsttekiler önce, alttakiler sonra oluşmalı"*)
   Ölçüldü (filmstrip, Genel Bakış): panellerin içeriği VERİNİN GELİŞ sırasıyla
   doluyordu — en alttaki "Son siparişler" görselleri KPI değerlerinden ÖNCE
   çiziliyordu. Kart kademesi (data-tm-stage) kabuğu sıralıyor ama içerik
   fetch'e bağlı olduğu için sırayı bozuyordu.
   Düzenek: kök `[data-tm-sira-kok]`, panel = `.kpi-card · .ch-panel · .tm-card ·
   [data-tm-sira]`. Sırası gelmemiş panel BÜTÜNÜYLE saklanır (yer kaplar → kayma yok);
   iskeletli panel de — ölçüldü, Canlı'da en alttaki sipariş tablosunun iskeleti
   ortadaki grafiklerden önce görünüyordu. Sırası gelen iskelet görünür, verisi
   gelince yerine geçen kart solmadan açılır.
   Solma panelin KENDİSİNDE, çocuklarında değil: ölçüldü, TMKpi/grafikler çocukları
   sonradan yeniden yazınca çocuk animasyonu baştan başlıyor ve alttaki satır
   üsttekinden önce beliriyordu. Sıra ve hazırlık static/js/ds/tm-sira.js.
   `tm-sira` sınıfını <head> koyar (reduced-motion'da konmaz); sıra bitince
   `tm-sira-bitti` kuralı kapatır (sonraki filtre/yenileme etkilenmez).
   Emniyet: JS hiç çalışmasa da `--tm-sira-kurtar` sonra içerik görünür
   (forwards dolgu → hiçbir öğe opaklık 0'da KALMAZ). */
/* Kök içindeki kart kademesi KALICI kapalı (yalnız sıra bitene kadar değil): `none` →
   `tm-enter` dönüşü animasyonu YENİDEN başlatır — ölçüldü, sıra bitince tüm paneller
   ikinci kez kaybolup solarak geliyordu. */
html.tm-sira [data-tm-sira-kok] [data-tm-stage],
html.tm-sira [data-tm-sira-kok] [data-tm-stage-group] > * {
  animation-name: none;
}
/* İçinde başka panel olan sarmalayıcıyı tm-sira.js ilk boyamadan önce `tm-sira-acik` ile
   işaretler (JS yalnız en içtekileri sıralar). `:has()` ile yapılmadı: ölçüldü, sipariş
   tablosu çizilirken her DOM değişikliği seçiciyi yeniden değerlendirtiyordu. */
html.tm-sira:not(.tm-sira-bitti) [data-tm-sira-kok] :is(.kpi-card, .ch-panel, .tm-card, [data-tm-sira]):not(.tm-sira-acik) {
  opacity: 0;
  animation-name: tm-enter;
  animation-duration: var(--tm-dur-enter);
  animation-timing-function: var(--tm-ease-out);
  animation-delay: var(--tm-sira-kurtar);
  animation-fill-mode: forwards;
}
html.tm-sira [data-tm-sira-kok] .tm-sira-gir {
  animation-name: tm-enter;
  animation-duration: var(--tm-dur-enter);
  animation-timing-function: var(--tm-ease-out);
  animation-delay: var(--tm-sira-d);
  animation-fill-mode: backwards;
}


/* ===== css/ds/ds-stat-card.css ===== */
/* =================================================================
   DS — STAT CARD (Faz 3; layout re-derived from the measured reference,
   docs/ui-reference-spec.md, 2026-09-13). Canonical StatCard = the DOM that
   static/js/tm-kpi.js buildCard() emits (also what macros/ds/tm_components.html
   tm_stat_card renders server-side). Class names are the JS contract
   (docs/ui-audit.md Ek B) and are NEVER renamed here; this file only re-skins
   them inside .tm-ds:

     .kpi-grid > .kpi-card[.accent][.kpi-card--nospark][.kpi-card--ph][.kpi-card--error]
       .kpi-glow (accent only — neutralised: no colour wash)
       .kpi-head  > .kpi-ic > i · .kpi-label · .kpi-head-tools > .kpi-livebadge > .live-dot · .kpi-info
       .kpi-body  > .kpi-value > .unit · .kpi-deltarow > .kpi-delta(.up|.down|.flat) > i · .kpi-delta-txt · .kpi-vs
       .kpi-chart > svg (.kpi-spark-area · .kpi-spark-line · .kpi-dot · .kpi-cross-*)
       .kpi-pop (info popover — floating layer → --tm-shadow-overlay)

   Reference proportions (Apex KPI card, 1280): height ≈150 · text inset 20–24 ·
   label 12/500 muted (sentence case) · number 24/700 · delta 12 coloured text +
   muted "vs" text · sparkline 40px bleeding to the card's bottom edge · a tinted
   icon disc at the top-right. Same inner layout for every card; skeleton
   (.kpi-card--ph) has the exact height of the loaded card (no jump).
   ================================================================= */

.tm-ds .kpi-grid {
  display: grid;
  grid-template-columns: repeat(var(--tm-dash-kpi-cols, 5), minmax(0, 1fr));
  gap: var(--tm-space-4);
  align-items: stretch;
  grid-auto-rows: auto;
  width: 100%;
  min-width: 0;
  margin: 0;              /* legacy tm-kpi.css margin-bottom made the KPI→chart gap 36 instead of the 24 page gap */
}
@media (max-width: 1023.98px) {
  .tm-ds .kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tm-ds .kpi-grid > .kpi-card:nth-child(5):last-child { grid-column: span 2; }   /* 2 + 2 + 1 full-width, never a lone half card */
}
@media (max-width: 599.98px) {
  .tm-ds .kpi-grid { grid-template-columns: minmax(0, 1fr); }
  .tm-ds .kpi-grid > .kpi-card:nth-child(5):last-child { grid-column: auto; }
}
.tm-ds .kpi-card.accent { grid-column: auto; }   /* the accent card is one cell like the others at every width */

.tm-ds .kpi-card,
.tm-ds .kpi-card.accent,
.tm-ds .kpi-card.accent.orange,
.tm-ds .kpi-card--ph {
  --kc-tone: var(--tm-accent);
  --kc-ic-bg: var(--tm-accent-bg);
  --kc-ic-fg: var(--tm-accent-fg);
  --kc-fg: var(--tm-text-primary);
  --kc-fg-2: var(--tm-text-secondary);
  --kc-fg-3: var(--tm-text-muted);
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0;
  box-sizing: border-box;
  height: var(--tm-dash-kpi-h);        /* fixed: skeleton and loaded card are the same box → no shift on data arrival */
  min-height: var(--tm-dash-kpi-h);
  min-width: 0;
  padding: var(--tm-space-4) var(--tm-space-4) 0;   /* KPI inset 16 (reference 20; nearest token) */
  background: var(--tm-bg-surface);
  background-image: none;
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-card);
  box-shadow: var(--tm-shadow-card);
  color: var(--kc-fg);
  overflow: hidden;
  transition: none;
  transform: none;
}
.tm-ds .kpi-card:hover { box-shadow: var(--tm-shadow-card); border-color: var(--tm-border); transform: none; }
.tm-ds .kpi-card::after,
.tm-ds .kpi-glow { display: none; }             /* no accent bar, no colour wash */

/* Legacy tm-kpi.css pins `#tmOverviewKpiGrid .kpi-card { min-height: 213px }` at ≥1101px (id
   specificity 1,1,0, not !important). Restated with matching id specificity so the DS height
   applies; the legacy rule is a Faz 5 deletion candidate. */
.tm-ds #tmOverviewKpiGrid .kpi-card { min-height: var(--tm-dash-kpi-h); }

/* head: label first, tools, then the icon disc at the far right (DOM order is
   icon · label · tools — reordered visually only) */
.tm-ds .kpi-head {
  display: flex;
  align-items: center;
  gap: var(--tm-space-2);
  min-height: 24px;                   /* = disc height: the value row starts below the disc */
  /* 48 = disc 24 + 4 + info 16 + 4: label neither runs under the "i" button nor the disc (2026-09-24) */
  padding-right: calc(var(--tm-space-6) + var(--tm-space-4) + 2 * var(--tm-space-1));
}
/* Containing block is .kpi-head (tm-kpi.css `.kpi-head { position: relative }`), NOT the card:
   the old `top/right: 16px` (written for the card) dropped the disc 16px into the value row and
   left it overlapping the "i" button (measured 2026-09-24: disc 413..437 × 324..348, info
   409..425 × 312..328 → 12×4 px overlap). Anchored to the head's own top-right. */
.tm-ds .kpi-ic {
  position: absolute;
  top: 0;
  right: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: var(--tm-radius-full);
  background: var(--kc-ic-bg);
  color: var(--kc-ic-fg);
  flex-shrink: 0;
}
.tm-ds .kpi-ic i, .tm-ds .kpi-ic svg { width: 13px; height: 13px; }
.tm-ds .kpi-label {
  order: 1;
  flex: 0 1 auto;
  min-width: 0;
  font-size: var(--tm-type-caption);
  line-height: var(--tm-type-caption-lh);
  font-weight: var(--tm-weight-medium);
  color: var(--kc-fg-2);
  letter-spacing: 0;
  text-transform: none;
  white-space: normal;               /* long labels ("Geçerli Sipariş") wrap to a second line instead of truncating */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* tools (info button, live badge) float left of the disc so the label keeps the whole head width
   (with them in flow, "Geçerli Sipariş" wrapped and the row grew from 154 to 170px) */
.tm-ds .kpi-head-tools { order: 2; position: absolute; top: 50%; transform: translateY(-50%); right: calc(var(--tm-space-6) + var(--tm-space-1)); margin-left: 0; display: flex; align-items: center; gap: var(--tm-space-1); flex-shrink: 0; }   /* vertically centred on the 24px head (= disc centre), 4px left of the disc */
.tm-ds .kpi-livebadge {
  display: inline-flex;
  align-items: center;
  gap: var(--tm-space-1);
  padding: 0 var(--tm-space-2);
  height: 18px;
  border-radius: var(--tm-radius-full);
  background: var(--tm-danger-bg);
  color: var(--tm-danger-fg);
  font-size: var(--tm-type-micro);
  line-height: var(--tm-type-micro-lh);
  font-weight: var(--tm-weight-semibold);
}
.tm-ds .kpi-livebadge .live-dot { width: 6px; height: 6px; border-radius: var(--tm-radius-full); background: currentColor; }
/* the per-card CANLI badge rendered as a lone red dot beside the label; the page header already says the data is live */
.tm-ds .kpi-livebadge { display: none; }
.tm-ds .kpi-info {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border: 0;
  border-radius: var(--tm-radius-full);
  background: transparent;
  color: var(--kc-fg-3);
  cursor: pointer;
  opacity: 0;                      /* shown on card hover / keyboard focus / open — the label keeps its width */
}
.tm-ds .kpi-card:hover .kpi-info, .tm-ds .kpi-info:focus-visible, .tm-ds .kpi-info.open { opacity: 1; }
.tm-ds .kpi-info:hover, .tm-ds .kpi-info.open { background: var(--tm-bg-subtle); color: var(--kc-fg); }
.tm-ds .kpi-info i, .tm-ds .kpi-info svg { width: 12px; height: 12px; }

/* body */
.tm-ds .kpi-body { position: relative; z-index: 1; margin: 0; padding: var(--tm-space-1) 0 0; }
.tm-ds .kpi-value {
  display: flex;
  align-items: baseline;
  gap: var(--tm-space-1);
  font-family: var(--tm-font-sans);
  font-size: var(--tm-type-display-sm);
  line-height: var(--tm-type-display-sm-lh);
  font-weight: var(--tm-weight-bold);
  letter-spacing: var(--tm-tracking-tight);
  font-variant-numeric: tabular-nums;
  color: var(--kc-fg);
  min-width: 0;
  white-space: nowrap;
}
/* polish (2026-09-13, item 4, dark-mode text tiers): `dashboard-dark-mode.css`
   ships `html.dark-mode .kpi-value { color: var(--color-surface-3, #f1f5f9) }`
   at the SAME specificity (0,2,0) as `.tm-ds .kpi-value` above — a tie the
   later-loaded file wins (measured: non-accent KPI numbers rendered #f1f5f9,
   a stray near-white tier distinct from the #f4f4f5 primary every other
   label/value uses). Restated id-scoped (same pattern as the min-height rule
   above) so it wins on specificity regardless of load order. */
.tm-ds #tmOverviewKpiGrid .kpi-value,
.tm-ds #tmLiveKpiGrid .kpi-value { color: var(--kc-fg); }
.tm-ds .kpi-value .unit {
  font-size: var(--tm-type-caption);
  line-height: var(--tm-type-caption-lh);
  font-weight: var(--tm-weight-medium);
  color: var(--kc-fg-3);
}
/* delta on its own line, period text under it (5-up cards are ~140px wide) */
.tm-ds .kpi-deltarow { display: flex; flex-direction: column; align-items: flex-start; gap: 0; flex-wrap: nowrap; margin: 0; padding: var(--tm-space-1) 0 0; min-height: var(--tm-type-caption-lh); font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); font-family: var(--tm-font-sans); }
/* delta = coloured text, no pill (reference: "↗ +12.5%  vs last month") */
.tm-ds .kpi-delta {
  display: inline-flex;
  align-items: center;
  gap: var(--tm-space-1);
  height: auto;
  padding: 0;
  border-radius: 0;
  font-family: var(--tm-font-sans);
  font-size: var(--tm-type-caption);
  line-height: var(--tm-type-caption-lh);
  font-weight: var(--tm-weight-semibold);
  font-variant-numeric: tabular-nums;
  background: transparent;
  color: var(--kc-fg-2);
}
.tm-ds .kpi-delta i, .tm-ds .kpi-delta svg { width: 12px; height: 12px; }
.tm-ds .kpi-delta.up   { background: transparent; color: var(--tm-success-fg); }
.tm-ds .kpi-delta.down { background: transparent; color: var(--tm-danger-fg); }
.tm-ds .kpi-delta.flat { background: transparent; color: var(--kc-fg-3); }
.tm-ds .kpi-vs { font-family: var(--tm-font-sans); font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); color: var(--kc-fg-3); font-weight: var(--tm-weight-regular); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
/* a "flat" delta with no text is an empty span → do not draw it */
.tm-ds .kpi-delta.flat:has(> .kpi-delta-txt:empty) { display: none; }

/* sparkline — fixed box inside the card padding (2026-09-24: the full-bleed version ran into the
   16px rounded corners and got clipped by the card's overflow:hidden); empty box keeps height */
.tm-ds .kpi-chart {
  position: relative;
  left: 0;
  width: 100%;
  height: var(--tm-dash-sparkline-h);
  margin: auto 0 0;                  /* legacy tm-kpi.css `margin: 0 -16px` bleed cancelled too */
  padding: 0;
  overflow: visible;                 /* hover tooltip sits ABOVE the box (translateY(-100%)); `hidden` clipped it entirely (2026-09-24) — the card itself still clips */
}
/* 2026-09-24: uç nokta kartın sağ kenarında yarısı kesik kalıyordu (kullanıcı
   raporu; 3× büyütmede doğrulandı). Kart `overflow:hidden` + 16px yarıçap
   taşıyor, kıvılcım ise kartın iç kutusunu tam dolduruyordu; son veri
   noktasının dairesi kenarın dışına taşınca kırpılıyordu. Yuvaya sağdan
   nokta-yarıçapı kadar pay veriliyor — alan/çizgi görünümü korunur, yalnız son
   nokta içeride kalır. Sol tarafta sorun yok: seri soldan başlıyor. */
.tm-ds .kpi-chart { padding-right: 5px; }
.tm-ds .kpi-chart svg { display: block; width: 100%; height: 100%; }
/* polish (2026-09-13, item 5): buildCard() (tm-kpi.js) appends an EMPTY
   `.kpi-chart` (no svg child, aria-hidden) when `data.points` is missing/[]
   (İade Oranı: server sends `points: []` — no daily series exists to draw,
   docs contract 2026-09-08 forbids inventing one). The box already reserves
   the same height as a real sparkline so the row stays aligned; it was just
   blank (≈93% of the card empty). Quiet caption placeholder explaining why,
   same box, zero CLS (no size change) — decorative only, the real "why" for
   assistive tech stays in .kpi-vs's deltaText, this element's parent already
   carries aria-hidden.
   Cascade trap (found via computed-style probe): legacy tm-kpi.css:541
   `.kpi-card--nospark .kpi-chart { visibility: hidden }` (0,2,0) — written
   for the old "just hide the pointless empty box" behaviour — made the new
   ::after invisible too (visibility inherits into generated content).
   Restated at higher specificity (0,3,0) below; no !important needed. */
.tm-ds .kpi-card--nospark .kpi-chart { visibility: visible; }
.tm-ds .kpi-card--nospark .kpi-chart::after {
  content: "günlük seri yok";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--tm-text-muted);
  font-family: var(--tm-font-sans);
  font-size: var(--tm-type-micro);
  line-height: var(--tm-type-micro-lh);
}
.tm-ds .kpi-spark-line { stroke: var(--kc-tone); }
.tm-ds .kpi-spark-area { fill: var(--kc-tone); opacity: .12; }
.tm-ds .kpi-dot, .tm-ds .kpi-cross-dot { fill: var(--kc-tone); background: var(--kc-tone); width: 8px; height: 8px; border: 2px solid var(--tm-bg-surface); box-shadow: none; }   /* legacy: 3px tinted halo read as a dark ring */
.tm-ds .kpi-cross-line { stroke: var(--tm-border-strong); border-left-color: var(--tm-border-strong); }
.tm-ds .kpi-tip {
  position: absolute;
  padding: var(--tm-space-1) var(--tm-space-2);
  border-radius: var(--tm-radius-control);
  background: var(--tm-text-primary);
  color: var(--tm-bg-surface);
  font-size: var(--tm-type-micro);
  line-height: var(--tm-type-micro-lh);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

/* ---------- per-metric sparkline tone (token-driven) ----------
   Payload order is fixed by the builder (routes/pages/dashboard_server.py
   kpi_cards_overview): 1 ciro · 2 kâr · 3 kâr marjı · 4 sipariş · 5 iade oranı
   (tests/test_ui_faz4a_overview.py pins it). buildCard() writes the payload
   colour as an SVG attribute; CSS wins over presentation attributes, so the
   tone is restated here from the chart palette (same hues as the payload). */
.tm-ds #tmOverviewKpiGrid > .kpi-card:nth-child(2) { --kc-tone: var(--tm-chart-3); }   /* kâr — green */
.tm-ds #tmOverviewKpiGrid > .kpi-card:nth-child(3) { --kc-tone: var(--tm-chart-1); }   /* marj — blue */
.tm-ds #tmOverviewKpiGrid > .kpi-card:nth-child(4) { --kc-tone: var(--tm-chart-2); }   /* sipariş — orange */
.tm-ds #tmOverviewKpiGrid > .kpi-card:nth-child(5) { --kc-tone: var(--tm-chart-7); }   /* iade — red */
.tm-ds #tmOverviewKpiGrid > .kpi-card:nth-child(2) { --kc-ic-bg: var(--tm-success-bg); --kc-ic-fg: var(--tm-success-fg); }
.tm-ds #tmOverviewKpiGrid > .kpi-card:nth-child(4) { --kc-ic-bg: var(--tm-warning-bg); --kc-ic-fg: var(--tm-warning-fg); }
.tm-ds #tmOverviewKpiGrid > .kpi-card:nth-child(5) { --kc-ic-bg: var(--tm-danger-bg);  --kc-ic-fg: var(--tm-danger-fg); }

/* ---------- accent card (Ciro): the ONE solid accent surface on the page.
   Legacy `.kpi-card.accent .kpi-*` colour rules (tm-kpi.css, gradient + glow)
   outrank `.tm-ds .kpi-*` by specificity → restated at (0,3,0)+ ---------- */
.tm-ds .kpi-card.accent {
  --kc-tone: var(--tm-on-accent);
  --kc-fg: var(--tm-on-accent);
  --kc-fg-2: color-mix(in srgb, var(--tm-on-accent) 82%, transparent);
  --kc-fg-3: color-mix(in srgb, var(--tm-on-accent) 70%, transparent);
  background: var(--tm-accent-solid);
  background-image: none;
  border-color: var(--tm-accent-solid);
  color: var(--kc-fg);
}
.tm-ds .kpi-card.accent:hover { border-color: var(--tm-accent-solid); }
.tm-ds .kpi-card.accent .kpi-ic { background: color-mix(in srgb, var(--tm-on-accent) 18%, transparent); color: var(--tm-on-accent); }
.tm-ds .kpi-card.accent .kpi-label { color: var(--kc-fg-2); }
.tm-ds .kpi-card.accent .kpi-value { color: var(--kc-fg); }
.tm-ds .kpi-card.accent .kpi-value .unit { color: var(--kc-fg-3); }
.tm-ds .kpi-card.accent .kpi-info { color: var(--kc-fg-3); background: transparent; }
.tm-ds .kpi-card.accent .kpi-info:hover, .tm-ds .kpi-card.accent .kpi-info.open { background: color-mix(in srgb, var(--tm-on-accent) 18%, transparent); color: var(--kc-fg); }
.tm-ds .kpi-card.accent .kpi-delta.up,
.tm-ds .kpi-card.accent .kpi-delta.down,
.tm-ds .kpi-card.accent .kpi-delta.flat { background: transparent; color: var(--kc-fg); }
.tm-ds .kpi-card.accent .kpi-vs { color: var(--kc-fg-3); }
.tm-ds .kpi-card.accent .kpi-livebadge { background: color-mix(in srgb, var(--tm-on-accent) 20%, transparent); color: var(--kc-fg); }
.tm-ds .kpi-card.accent .kpi-dot { border-color: var(--tm-accent-solid); box-shadow: none; }
.tm-ds .kpi-card.accent .kpi-cross-line { border-left-color: color-mix(in srgb, var(--tm-on-accent) 60%, transparent); }
.tm-ds .kpi-card.accent .kpi-spark-line { stroke: var(--tm-on-accent); }
.tm-ds .kpi-card.accent .kpi-spark-area { fill: var(--tm-on-accent); opacity: .18; }
.tm-ds .kpi-card.accent .kpi-tip { background: var(--tm-on-accent); color: var(--tm-accent-solid); }

/* info popover — floating layer */
.tm-ds .kpi-pop {
  position: fixed;   /* tm-kpi.js wireInfo() writes viewport coordinates → fixed, not absolute */
  z-index: 5;
  padding: var(--tm-space-3);
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-overlay);
  background: var(--tm-bg-surface);
  box-shadow: var(--tm-shadow-overlay);
  color: var(--tm-text-primary);
  font-size: var(--tm-type-caption);
  line-height: var(--tm-type-caption-lh);
}
.tm-ds .kpi-pop-title { font-weight: var(--tm-weight-semibold); }
.tm-ds .kpi-pop-text, .tm-ds .kpi-pop-formula { color: var(--tm-text-secondary); }
.tm-ds .kpi-pop-formula { font-family: var(--tm-font-mono); font-size: var(--tm-type-micro); }

/* live update: a ~600 ms fading highlight behind the value, nothing else moves */
@keyframes tmKpiFlash {
  from { background-color: var(--tm-accent-bg); }
  to   { background-color: transparent; }
}
.tm-ds .kpi-value.flash { animation: tmKpiFlash var(--tm-dur-morph) var(--tm-ease-out) 1; border-radius: var(--tm-radius-control); }
.tm-ds .kpi-card.accent .kpi-value.flash { animation: none; }
.tm-ds .kpi-delta.flash { animation: none; }
.tm-ds .kpi-card.enter { animation: none; opacity: 1; transform: none; }

/* error state — same height, message in the body */
.tm-ds .kpi-card--error { border-color: var(--tm-danger-fg); }
.tm-ds .kpi-card--error .kpi-ic { background: var(--tm-danger-bg); color: var(--tm-danger-fg); }
.tm-ds .kpi-card--error .kpi-error-msg { color: var(--tm-danger-fg); font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); padding: var(--tm-space-2) 0 0; }

/* skeleton — identical box; bars where text will be */
.tm-ds .kpi-card--ph { animation: none; }
.tm-ds .kpi-card--ph .kpi-label,
.tm-ds .kpi-card--ph .kpi-value,
.tm-ds .kpi-card--ph .kpi-delta,
.tm-ds .kpi-card--ph .kpi-vs { color: transparent; background: var(--tm-bg-subtle); border-radius: var(--tm-radius-control); }
.tm-ds .kpi-card--ph .kpi-value { width: 60%; height: var(--tm-type-display-lh); }
.tm-ds .kpi-card--ph .kpi-label { width: 40%; height: var(--tm-type-caption-lh); }
.tm-ds .kpi-card--ph .kpi-chart { background: linear-gradient(to top, var(--tm-bg-subtle), transparent); }

@media (min-width: 1440px) {
  .tm-ds .kpi-value { font-size: var(--tm-type-display); line-height: var(--tm-type-display-lh); }
}

/* live page: legacy `.tm-live-page .kpi-card.accent { grid-column: span 2 }` outranked the (0,3,0) rule above */
.tm-ds .kpi-grid > .kpi-card.accent { grid-column: auto; }

/* Artışın KÖTÜ olduğu göstergeler (iade oranı) — 2026-09-24, kullanıcı isteği.
   Ok yönü değişmez (artış = yukarı ok, dürüst), yalnız RENK ters çevrilir:
   artış kırmızı, düşüş yeşil. `.invert` sınıfını tm-kpi.js `deltaInvert`
   alanından basar. */
.tm-ds .kpi-delta.invert.up { color: var(--tm-danger-fg); }
.tm-ds .kpi-delta.invert.down { color: var(--tm-success-fg); }


/* 2026-09-28 (ölçüldü): vurgulu (mavi) KPI kartında `günlük seri yok` yazısı
   okunmuyordu — kart arka planı rgb(1,117,228), yazı `--tm-text-muted`
   rgb(85,97,115) → kontrast ~1,5:1 (WCAG AA için 4,5:1 gerekir).
   Vurgulu kartta beyaza çekiliyor (≈4,9:1). Ölçüm: scripts/qa probe,
   getComputedStyle(.kpi-chart, '::after').color. */
.tm-ds .kpi-card.accent .kpi-chart::after { color: rgba(255, 255, 255, .82); }


/* ===== css/ds/ds-badge.css ===== */
/* =================================================================
   DS — STATUS BADGE (Faz 3). One component, one fixed status→colour map.
   Soft background + strong-ish text; never a solid fill.

     <span class="tm-badge tm-badge--shipped">Kargoda</span>

   Status map (order lifecycle, docs/manuel-sync + orders tab):
     pending    bekleyen        → warning
     picking    hazırlanıyor    → info
     shipped    kargoda         → accent
     delivered  teslim edildi   → success
     cancelled  iptal           → danger
     returned   iade            → muted (neutral)
   Generic tones for non-order contexts: --neutral --success --warning --danger --info --accent
   Legacy modifiers from v2/components/badges.css (--ok --warn --bad --brand) are
   aliased so existing markup inside .tm-ds keeps rendering.
   ================================================================= */

.tm-ds .tm-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--tm-space-1);
  height: 22px;
  padding: 0 var(--tm-space-2);
  border: 1px solid transparent;
  border-radius: var(--tm-radius-control);
  background: var(--tm-bg-subtle);
  color: var(--tm-text-secondary);
  font-size: var(--tm-type-caption);
  line-height: var(--tm-type-caption-lh);
  font-weight: var(--tm-weight-medium);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  vertical-align: middle;
  box-shadow: none;
}
.tm-ds .tm-badge--sm { height: 18px; font-size: var(--tm-type-micro); line-height: var(--tm-type-micro-lh); }
.tm-ds .tm-badge__dot { width: 6px; height: 6px; border-radius: var(--tm-radius-full); background: currentColor; flex-shrink: 0; }
.tm-ds .tm-badge--outline { background: transparent; border-color: var(--tm-border); }

.tm-ds .tm-badge--neutral,
.tm-ds .tm-badge--returned  { background: var(--tm-bg-subtle);   color: var(--tm-text-secondary); }
.tm-ds .tm-badge--success,
.tm-ds .tm-badge--ok,
.tm-ds .tm-badge--delivered { background: var(--tm-success-bg); color: var(--tm-success-fg); }
.tm-ds .tm-badge--warning,
.tm-ds .tm-badge--warn,
.tm-ds .tm-badge--pending   { background: var(--tm-warning-bg); color: var(--tm-warning-fg); }
.tm-ds .tm-badge--danger,
.tm-ds .tm-badge--bad,
.tm-ds .tm-badge--cancelled { background: var(--tm-danger-bg);  color: var(--tm-danger-fg); }
.tm-ds .tm-badge--info,
.tm-ds .tm-badge--picking   { background: var(--tm-info-bg);    color: var(--tm-info-fg); }
.tm-ds .tm-badge--accent,
.tm-ds .tm-badge--brand,
.tm-ds .tm-badge--shipped   { background: var(--tm-accent-bg);  color: var(--tm-accent-fg); }

/* Count bubble on tab buttons (orders-tab-badge is a JS hook — restyle only) */
.tm-ds .orders-tab-badge,
.tm-ds .tm-badge--count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 var(--tm-space-1);
  border-radius: var(--tm-radius-full);
  background: var(--tm-bg-subtle);
  color: var(--tm-text-secondary);
  font-size: var(--tm-type-micro);
  line-height: var(--tm-type-micro-lh);
  font-weight: var(--tm-weight-semibold);
  font-variant-numeric: tabular-nums;
  box-shadow: none;
}


/* ===== css/ds/ds-table.css ===== */
/* =================================================================
   DS — DATA TABLE (Faz 3). Built on the existing shell class
   .tm-table-shell (tm-page-shell.css) + .tm-table (v2/components/tables.css);
   this file re-skins them inside .tm-ds.

     <div class="tm-table-shell tm-table-shell--sticky">
       <table class="tm-table tm-table--sticky-first [tm-table--dense]">
         <thead><tr><th>…</th><th class="tm-num">Tutar</th></tr></thead>
         <tbody><tr><td>…</td><td class="tm-num">1.234,00</td></tr></tbody>
       </table>
     </div>

   Rules: text left, numbers right (.tm-num, tabular), status/date fixed
   width (.tm-col-status / .tm-col-date), sticky header, sticky first column,
   1px row divider, hover = --tm-bg-subtle only, no zebra, no shadow.
   Density: comfortable --tm-row-h (52px) / .tm-table--dense --tm-row-h-dense (40px).
   ================================================================= */

.tm-ds .tm-table-shell {
  position: relative;
  width: 100%;
  max-width: 100%;
  overflow-x: auto;
  overflow-y: visible;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  -webkit-overflow-scrolling: touch;
}
.tm-ds .tm-table-shell--sticky { overflow-y: auto; max-height: var(--tm-table-max-h, 70vh); }

.tm-ds .tm-table {
  width: 100%;
  min-width: 0;
  border-collapse: separate;
  border-spacing: 0;
  background: transparent;
  color: var(--tm-text-primary);
  font-size: var(--tm-type-body);
  line-height: var(--tm-type-body-lh);
}
.tm-ds .tm-table th,
.tm-ds .tm-table td {
  height: var(--tm-row-h);
  padding: 0 var(--tm-space-3);
  text-align: left;
  vertical-align: middle;
  border: 0;
  border-bottom: 1px solid var(--tm-border);
  background: var(--tm-bg-surface);
  white-space: nowrap;
}
.tm-ds .tm-table--dense th,
.tm-ds .tm-table--dense td { height: var(--tm-row-h-dense); padding: 0 var(--tm-space-2); }
.tm-ds .tm-table--wrap td { white-space: normal; }

.tm-ds .tm-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--tm-bg-subtle);
  color: var(--tm-text-secondary);
  font-size: var(--tm-type-caption);
  line-height: var(--tm-type-caption-lh);
  font-weight: var(--tm-weight-medium);
  letter-spacing: var(--tm-tracking-wide);
  text-transform: uppercase;
  border-bottom: 1px solid var(--tm-border-strong);
}
.tm-ds .tm-table tbody tr:hover > td { background: var(--tm-bg-subtle); }
.tm-ds .tm-table tbody tr:last-child > td { border-bottom-color: transparent; }
.tm-ds .tm-table tbody tr.is-selected > td { background: var(--tm-accent-bg); }

/* sticky first column (order number) — reference never scrolls away */
.tm-ds .tm-table--sticky-first th:first-child,
.tm-ds .tm-table--sticky-first td:first-child {
  position: sticky;
  left: 0;
  z-index: 1;
  border-right: 1px solid var(--tm-border);
}
.tm-ds .tm-table--sticky-first thead th:first-child { z-index: 3; }

/* column roles */
.tm-ds .tm-table .tm-num,
.tm-ds .tm-table th.tm-num,
.tm-ds .tm-table td.tm-num { text-align: right; font-variant-numeric: tabular-nums; }
.tm-ds .tm-table .tm-col-status { width: 120px; min-width: 120px; }
.tm-ds .tm-table .tm-col-date   { width: 136px; min-width: 136px; font-variant-numeric: tabular-nums; }
.tm-ds .tm-table .tm-col-check  { width: 40px; min-width: 40px; text-align: center; padding: 0 var(--tm-space-2); }
.tm-ds .tm-table .tm-col-actions { width: 1%; white-space: nowrap; text-align: right; }
.tm-ds .tm-table td.tm-cell-muted { color: var(--tm-text-muted); }
.tm-ds .tm-table td.tm-cell-strong { font-weight: var(--tm-weight-medium); }

/* row skeleton: same row height as data rows → no jump */
.tm-ds .tm-table tr.tm-row-skeleton > td > span {
  display: block;
  height: var(--tm-type-body-lh);
  width: 70%;
  border-radius: var(--tm-radius-control);
  background: var(--tm-bg-subtle);
}
.tm-ds .tm-table tr.tm-row-skeleton > td.tm-num > span { margin-left: auto; width: 50%; }

/* empty / error rows live inside the table body at data-row height ×3 */
.tm-ds .tm-table td.tm-table__state {
  height: calc(var(--tm-row-h) * 3);
  text-align: center;
  white-space: normal;
  color: var(--tm-text-muted);
}

@media (max-width: 767.98px) {
  .tm-ds .tm-table th, .tm-ds .tm-table td { padding: 0 var(--tm-space-2); }
  .tm-ds .tm-table--sticky-first th:first-child,
  .tm-ds .tm-table--sticky-first td:first-child { position: static; border-right: 0; }
}


/* ===== css/ds/ds-toolbar.css ===== */
/* =================================================================
   DS — TOOLBAR · FILTER CHIPS · BULK ACTION BAR (Faz 3)

     <div class="tm-toolbar">
       <div class="tm-toolbar__search">   search input (left)
       <div class="tm-toolbar__filters">  filter controls + active chips (center)
       <div class="tm-toolbar__actions">  primary action (right)
     </div>
     <div class="tm-bulkbar" hidden> … </div>   ← swaps INTO the toolbar's place

   One row on desktop; wraps on narrow screens. No margins; gap only.
   ================================================================= */

.tm-ds .tm-toolbar {
  display: flex;
  align-items: center;
  gap: var(--tm-space-3);
  min-height: 40px;
  min-width: 0;
  flex-wrap: wrap;
}
.tm-ds .tm-toolbar__search  { flex: 0 1 280px; min-width: 200px; }
.tm-ds .tm-toolbar__filters { flex: 1 1 auto; display: flex; align-items: center; gap: var(--tm-space-2); flex-wrap: wrap; min-width: 0; }
.tm-ds .tm-toolbar__actions { flex: 0 0 auto; display: flex; align-items: center; gap: var(--tm-space-2); margin-left: auto; }

.tm-ds .tm-toolbar .tm-input,
.tm-ds .tm-toolbar input[type="search"],
.tm-ds .tm-toolbar input[type="text"],
.tm-ds .tm-toolbar select {
  height: 36px;
  padding: 0 var(--tm-space-3);
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-control);
  background: var(--tm-bg-surface);
  color: var(--tm-text-primary);
  font-size: var(--tm-type-body);
  line-height: var(--tm-type-body-lh);
  box-shadow: none;
  width: 100%;
}
.tm-ds .tm-toolbar input::placeholder { color: var(--tm-text-muted); }

/* segmented status filter buttons (data-status hooks stay on the buttons) */
.tm-ds .tm-seg { display: inline-flex; gap: 0; border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); overflow: hidden; }
.tm-ds .tm-seg > button,
.tm-ds .tm-seg > a {
  display: inline-flex;
  align-items: center;
  gap: var(--tm-space-1);
  height: 34px;
  padding: 0 var(--tm-space-3);
  border: 0;
  border-right: 1px solid var(--tm-border);
  background: var(--tm-bg-surface);
  color: var(--tm-text-secondary);
  font-size: var(--tm-type-body);
  line-height: var(--tm-type-body-lh);
  font-weight: var(--tm-weight-medium);
  cursor: pointer;
  white-space: nowrap;
}
.tm-ds .tm-seg > :last-child { border-right: 0; }
.tm-ds .tm-seg > .is-active,
.tm-ds .tm-seg > [aria-pressed="true"],
.tm-ds .tm-seg > .orders-tab-active { background: var(--tm-accent-bg); color: var(--tm-accent-fg); }

/* active filter chip — removable */
.tm-ds .tm-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--tm-space-1);
  height: 26px;
  padding: 0 var(--tm-space-1) 0 var(--tm-space-2);
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-full);
  background: var(--tm-bg-subtle);
  color: var(--tm-text-primary);
  font-size: var(--tm-type-caption);
  line-height: var(--tm-type-caption-lh);
  white-space: nowrap;
}
.tm-ds .tm-chip__remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border: 0;
  border-radius: var(--tm-radius-full);
  background: transparent;
  color: var(--tm-text-muted);
  cursor: pointer;
}
.tm-ds .tm-chip__remove:hover { background: var(--tm-border); color: var(--tm-text-primary); }

/* bulk action bar — replaces the toolbar in place when rows are selected */
.tm-ds .tm-bulkbar {
  display: flex;
  align-items: center;
  gap: var(--tm-space-3);
  min-height: 40px;
  padding: 0 var(--tm-space-3);
  border: 1px solid var(--tm-accent-fg);
  border-radius: var(--tm-radius-control);
  background: var(--tm-accent-bg);
  color: var(--tm-text-primary);
  font-size: var(--tm-type-body);
  line-height: var(--tm-type-body-lh);
  box-shadow: none;
}
.tm-ds .tm-bulkbar[hidden] { display: none; }
.tm-ds .tm-bulkbar__meta { font-weight: var(--tm-weight-medium); font-variant-numeric: tabular-nums; }
.tm-ds .tm-bulkbar__actions { display: flex; align-items: center; gap: var(--tm-space-2); margin-left: auto; }

/* density toggle (orders): two states, same tokens */
.tm-ds .tm-density { display: inline-flex; border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); overflow: hidden; }
.tm-ds .tm-density > button { height: 34px; padding: 0 var(--tm-space-2); border: 0; background: var(--tm-bg-surface); color: var(--tm-text-muted); cursor: pointer; }
.tm-ds .tm-density > button[aria-pressed="true"] { background: var(--tm-bg-subtle); color: var(--tm-text-primary); }

@media (max-width: 767.98px) {
  .tm-ds .tm-toolbar__search { flex-basis: 100%; }
  .tm-ds .tm-toolbar__actions { margin-left: 0; width: 100%; }
  .tm-ds .tm-toolbar__actions > * { flex: 1 1 auto; }
}


/* ===== css/ds/ds-states.css ===== */
/* =================================================================
   DS — STATES (Faz 3): skeleton · empty · error · pagination
   Every data component supports loading / empty / error / filled; the
   loading skeleton has the SAME height as the filled state.

   Empty / error reuse the v2 class family (.tm-empty, __icon/__title/__desc/
   __actions — v2/components/empty-state.css) so existing markup keeps
   working; .tm-error is the danger-toned variant. The empty state says WHY
   it is empty and WHAT to do (an action slot), not just "kayıt yok".
   ================================================================= */

/* ---------- skeleton ---------- */
@keyframes tmSkeletonShimmer {
  from { background-position: -200px 0; }
  to   { background-position: calc(200px + 100%) 0; }
}
.tm-ds .tm-skeleton,
.tm-ds .skeleton {
  display: block;
  border-radius: var(--tm-radius-control);
  background: var(--tm-bg-subtle);
  background-image: linear-gradient(90deg, var(--tm-bg-subtle) 0, var(--tm-border) 50%, var(--tm-bg-subtle) 100%);
  background-size: 200px 100%;
  background-repeat: no-repeat;
  animation: tmSkeletonShimmer 1.2s var(--tm-ease) infinite;
  color: transparent;
  box-shadow: none;
}
.tm-ds .tm-skeleton--text { height: var(--tm-type-body-lh); width: 60%; }
.tm-ds .tm-skeleton--title { height: var(--tm-type-title-lh); width: 40%; }
.tm-ds .tm-skeleton--block { height: 100%; min-height: 120px; width: 100%; }
.tm-ds .tm-skeleton--circle { border-radius: var(--tm-radius-full); }
.tm-ds .tm-skeleton-stack { display: flex; flex-direction: column; gap: var(--tm-space-2); }
/* reduced-motion: ds-primitives.css `.tm-ds *` kuralı süreyi 0.001ms'e indirir — ayrı blok yok (PR-1, 2026-10-10). */

/* ---------- empty / error ---------- */
/* 🔴 GİRİŞ ANİMASYONU (kullanıcı: "animasyon yok" — canlı kusur raporu,
   2026-09-17). GLOBAL — bu dosya zaten TÜM boş/hata durumlarını kapsıyor
   ("Every data component supports loading / empty / error / filled"),
   ikinci bir sayfa-özel kopya YAZILMADI. Yumuşak, tek-seferlik; sonsuz
   döngü YOK (boş durum bir bildirimdir, sürekli hareket eden bir şey değil
   — `tm-live-empty`in "no decorative motion" ilkesiyle aynı çizgide). */
@keyframes tmEmptyStateIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
.tm-ds .tm-empty,
.tm-ds .tm-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--tm-space-2);
  min-height: var(--tm-state-min-h, 160px);
  padding: var(--tm-space-4);
  text-align: center;
  color: var(--tm-text-secondary);
  background: transparent;
  border: 0;
  box-shadow: none;
  animation: tmEmptyStateIn var(--tm-dur-base) var(--tm-ease-out) backwards;
}
.tm-ds .tm-empty--compact, .tm-ds .tm-error--compact { min-height: 96px; padding: var(--tm-space-2); }
.tm-ds .tm-empty__icon,
.tm-ds .tm-error__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--tm-radius-full);
  background: var(--tm-bg-subtle);
  color: var(--tm-text-muted);
}
.tm-ds .tm-error__icon { background: var(--tm-danger-bg); color: var(--tm-danger-fg); }
.tm-ds .tm-empty__icon svg, .tm-ds .tm-error__icon svg, .tm-ds .tm-empty__icon i, .tm-ds .tm-error__icon i { width: 18px; height: 18px; }
.tm-ds .tm-empty__title,
.tm-ds .tm-error__title {
  margin: 0;
  font-size: var(--tm-type-body);
  line-height: var(--tm-type-body-lh);
  font-weight: var(--tm-weight-semibold);
  color: var(--tm-text-primary);
}
.tm-ds .tm-empty__desc,
.tm-ds .tm-error__desc {
  margin: 0;
  max-width: 44ch;
  font-size: var(--tm-type-body);
  line-height: var(--tm-type-body-lh);
  color: var(--tm-text-secondary);
}
.tm-ds .tm-empty__actions,
.tm-ds .tm-error__actions { display: flex; gap: var(--tm-space-2); flex-wrap: wrap; justify-content: center; }

/* ---------- pagination (fixed under the table) ---------- */
.tm-ds .tm-pagination {
  display: flex;
  align-items: center;
  gap: var(--tm-space-3);
  min-height: 40px;
  flex-wrap: wrap;
  font-size: var(--tm-type-body);
  line-height: var(--tm-type-body-lh);
  color: var(--tm-text-secondary);
}
.tm-ds .tm-pagination__total { font-variant-numeric: tabular-nums; }
.tm-ds .tm-pagination__size { display: inline-flex; align-items: center; gap: var(--tm-space-2); }
.tm-ds .tm-pagination__size select {
  height: 32px;
  padding: 0 var(--tm-space-2);
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-control);
  background: var(--tm-bg-surface);
  color: var(--tm-text-primary);
}
.tm-ds .tm-pagination__pages { display: inline-flex; align-items: center; gap: var(--tm-space-1); margin-left: auto; }
.tm-ds .tm-pagination__pages > button,
.tm-ds .tm-pagination__pages > a,
.tm-ds .tm-pagination .page-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  height: 32px;
  padding: 0 var(--tm-space-2);
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-control);
  background: var(--tm-bg-surface);
  color: var(--tm-text-primary);
  font-variant-numeric: tabular-nums;
  box-shadow: none;
  cursor: pointer;
}
.tm-ds .tm-pagination__pages > .is-active,
.tm-ds .tm-pagination__pages > [aria-current="page"],
.tm-ds .tm-pagination .page-item.active .page-link { background: var(--tm-accent-bg); color: var(--tm-accent-fg); border-color: var(--tm-accent-fg); }
.tm-ds .tm-pagination__pages > [disabled],
.tm-ds .tm-pagination .page-item.disabled .page-link { opacity: .5; cursor: default; }

/* chart empty state (renderer markup .tm-live-empty, styled by v2/components/empty-state.css with an entrance
   animation and an infinite float): no decorative motion in DS scope — the empty state is a static message. */
.tm-ds .tm-live-empty, .tm-ds .tm-live-empty svg { animation: none; }



/* ===== css/ds/ds-chart-card.css ===== */
/* =================================================================
   DS — CHART CARD (Faz 3). Canonical wrapper = macros/tm_chart_panel.html
   (.ch-panel > .ch-head > .ch-head-l > .ch-h3 / .ch-sub · .ch-actions ·
   .ch-body > .ch-mount · .ch-state--{loading|empty|error}). Those class
   names are the tm-charts.js / bridge contract; this file re-skins them
   inside .tm-ds to be exactly a .tm-card with a .tm-card__header.
   The chart library's own title/legend is not used for the header.
   ================================================================= */

.tm-ds .ch-grid,
.tm-ds .tm-dashboard-ch-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--tm-space-6) var(--tm-space-4);   /* reference: rows 24 · columns 16 */
  align-items: stretch;
  width: 100%;
  min-width: 0;
}
.tm-ds .ch-panel.span-3  { grid-column: span 3; }
.tm-ds .ch-panel.span-4  { grid-column: span 4; }
.tm-ds .ch-panel.span-6  { grid-column: span 6; }
.tm-ds .ch-panel.span-8  { grid-column: span 8; }
.tm-ds .ch-panel.span-12 { grid-column: span 12; }
@media (max-width: 1023.98px) {
  .tm-ds .ch-panel.span-6, .tm-ds .ch-panel.span-8 { grid-column: span 12; }
  .tm-ds .ch-panel.span-3, .tm-ds .ch-panel.span-4 { grid-column: span 6; }
}
@media (max-width: 767.98px) {
  .tm-ds .ch-grid > .ch-panel, .tm-ds .tm-dashboard-ch-grid > .ch-panel { grid-column: span 12; }
  .tm-ds .ch-grid, .tm-ds .tm-dashboard-ch-grid { gap: var(--tm-space-4); }   /* phones: one 16px rhythm, same as the page gap (strict lint: 16 vs 24 mixed) */
}

.tm-ds .ch-panel {
  display: flex;
  flex-direction: column;
  gap: var(--tm-space-3);
  box-sizing: border-box;
  min-width: 0;
  min-height: 0;
  padding: var(--tm-space-6);
  background: var(--tm-bg-surface);
  background-image: none;
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-card);
  box-shadow: var(--tm-shadow-card);
  color: var(--tm-text-primary);
  transition: none;
}
.tm-ds .ch-panel:hover { box-shadow: var(--tm-shadow-card); transform: none; }

.tm-ds .ch-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--tm-space-3);
  min-height: 24px;
  padding: 0 0 var(--tm-space-2);
  border: 0;
}
.tm-ds .ch-head-l { display: flex; flex-direction: column; gap: var(--tm-space-1); min-width: 0; }
.tm-ds .ch-h3 {
  display: flex;
  align-items: center;
  gap: var(--tm-space-2);
  margin: 0;
  font-size: var(--tm-type-heading);
  line-height: var(--tm-type-heading-lh);
  font-weight: var(--tm-weight-semibold);
  color: var(--tm-text-primary);
}
.tm-ds .ch-h3__icon { display: inline-flex; color: var(--tm-text-muted); }
.tm-ds .ch-h3__icon svg, .tm-ds .ch-h3__icon i { width: 14px; height: 14px; }
.tm-ds .ch-sub { margin: 0; font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); color: var(--tm-text-muted); }
/* Grafik anatomisi (PR-4, 2026-10-10 — referans): başlık · neyi ölçer · BÜYÜK SAYI + delta + referans dönemi · grafik.
   Sayı tabular; delta semantik renk; "önceki N gün: X" soluk. */
.tm-ds .ch-kpi { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--tm-space-2); min-width: 0; }
.tm-ds .ch-kpi[hidden] { display: none; }
.tm-ds .ch-kpi__v { font-size: var(--tm-type-display); line-height: var(--tm-type-display-lh); font-weight: var(--tm-weight-bold); font-variant-numeric: tabular-nums; color: var(--tm-text-primary); }
.tm-ds .ch-kpi__d { font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); font-weight: var(--tm-weight-semibold); font-variant-numeric: tabular-nums; }
.tm-ds .ch-kpi__d.up { color: var(--tm-success-fg); }
.tm-ds .ch-kpi__d.down { color: var(--tm-danger-fg); }
.tm-ds .ch-kpi__d.flat { color: var(--tm-text-muted); }
.tm-ds .ch-kpi__vs { font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); color: var(--tm-text-muted); }
/* eksen: gövde fontu, mikro boy, soluk; grid hairline (referans: 3–4 tik, neredeyse görünmez çizgi) */
.tm-ds .ch-axis-ylabel, .tm-ds .ch-bar-xlabel { font-family: var(--tm-font-sans); font-size: var(--tm-type-micro); fill: var(--tm-chart-axis); }
.tm-ds .ch-grid-line { stroke: var(--tm-chart-grid); }
/* çubuk hover: üstüne gelinen çubuk mürekkep rengine döner (referans), opaklık oyunu yok */
.tm-ds .ch-bar-col:hover .ch-bar { fill: var(--tm-text-primary); opacity: 1; }
.tm-ds .ch-actions, .tm-ds .ch-tools { display: flex; align-items: center; gap: var(--tm-space-2); flex-shrink: 0; }
.tm-ds .ch-live-badge {
  display: inline-flex; align-items: center; gap: var(--tm-space-1);
  height: 18px; padding: 0 var(--tm-space-2);
  border-radius: var(--tm-radius-full);
  background: var(--tm-danger-bg); color: var(--tm-danger-fg);
  font-size: var(--tm-type-micro); line-height: var(--tm-type-micro-lh); font-weight: var(--tm-weight-semibold);
}
.tm-ds .ch-live-badge__dot { width: 6px; height: 6px; border-radius: var(--tm-radius-full); background: currentColor; }

.tm-ds .ch-body { position: relative; flex: 1 1 auto; min-height: 0; min-width: 0; padding: 0; }
.tm-ds .ch-mount { position: relative; width: 100%; min-height: var(--tm-ch-mount-h, 240px); }
.tm-ds .ch-mount svg { display: block; width: 100%; }

/* chart chrome: axis text and legends use tokens, not library defaults */
.tm-ds .ch-panel text { fill: var(--tm-chart-axis); font-family: var(--tm-font-sans); font-size: var(--tm-type-micro); }
.tm-ds .ch-legend { display: flex; flex-wrap: wrap; gap: var(--tm-space-2) var(--tm-space-3); font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); color: var(--tm-text-secondary); }
.tm-ds .ch-legend .dot { width: 8px; height: 8px; border-radius: var(--tm-radius-full); }
.tm-ds .ch-rank-track { height: 6px; border-radius: var(--tm-radius-full); background: var(--tm-chart-track); overflow: hidden; }
.tm-ds .ch-rank-fill { height: 100%; border-radius: var(--tm-radius-full); }
.tm-ds .ch-zoom-chip { border: 1px solid var(--tm-border); border-radius: var(--tm-radius-full); background: var(--tm-bg-surface); color: var(--tm-text-secondary); font-size: var(--tm-type-micro); padding: 0 var(--tm-space-2); height: 20px; }
.tm-ds .ch-zoom-chip.is-active, .tm-ds .ch-zoom-chip[aria-pressed="true"] { background: var(--tm-accent-bg); color: var(--tm-accent-fg); border-color: var(--tm-accent-fg); }

/* states share the mount height → no jump between loading / empty / error / ready */
.tm-ds .ch-state {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--tm-space-2);
  min-height: var(--tm-ch-mount-h, 240px);
  text-align: center;
  color: var(--tm-text-secondary);
  font-size: var(--tm-type-body); line-height: var(--tm-type-body-lh);
}
.tm-ds .ch-state__icon { display: inline-flex; width: 36px; height: 36px; align-items: center; justify-content: center; border-radius: var(--tm-radius-full); background: var(--tm-bg-subtle); color: var(--tm-text-muted); }
.tm-ds .ch-state--error .ch-state__icon { background: var(--tm-danger-bg); color: var(--tm-danger-fg); }
.tm-ds .ch-state__title { margin: 0; font-weight: var(--tm-weight-semibold); color: var(--tm-text-primary); }
.tm-ds .ch-state__sub { margin: 0; color: var(--tm-text-muted); }
.tm-ds .ch-state--loading { background: var(--tm-bg-subtle); border-radius: var(--tm-radius-control); }

/* Chart.js external HTML tooltip (tm-chart-tooltip.css) — floating layer */
.tm-ds .tm-chart-tooltip {
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-control);
  background: var(--tm-bg-surface);
  color: var(--tm-text-primary);
  box-shadow: var(--tm-shadow-overlay);
  font-size: var(--tm-type-caption);
  line-height: var(--tm-type-caption-lh);
  padding: var(--tm-space-2) var(--tm-space-3);
}

/* Week chart SVG fills its mount (was `#overviewTab #tmOvWeek.ch-mount svg.ch-svg { height:100% !important }`
   in tm-vanilla-dashboard-charts.css, now excluded from DS scope). */
.tm-ds .ch-mount svg.ch-svg { display: block; width: 100%; height: 100%; overflow: hidden; }

/* donut = ring + legend; the legend wraps under the ring when the card is narrow
   (legacy tm-charts.css laid them out for a wider mount and let the legend overflow) */
/* donut row (Genel Bakış: two span-6 cards): ring left, legend beside it in one column */
.tm-ds .ch-donut-wrap { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-start; gap: var(--tm-space-4) var(--tm-space-8); min-width: 0; width: 100%; }
/* wide card (Genel Bakış span-6): ring + legend side by side; narrow card (Canlı span-4): legend wraps under the ring
   with its labels intact — nowrap squeezed it to dots only */
.tm-ds .ch-donut { flex: 0 0 auto; max-width: 100%; }
.tm-ds .ch-legend { flex: 1 1 160px; min-width: 0; max-width: 320px; display: flex; flex-direction: column; gap: var(--tm-space-2); margin: 0; padding: 0; list-style: none; }
.tm-ds .ch-legend.row { flex-direction: row; flex-wrap: wrap; gap: var(--tm-space-2) var(--tm-space-4); }
.tm-ds .ch-legend li { display: grid; grid-template-columns: 8px minmax(0, 1fr) auto auto; gap: var(--tm-space-3); align-items: center; min-width: 0; }
.tm-ds .ch-legend .nm { font-size: var(--tm-type-body); line-height: var(--tm-type-body-lh); color: var(--tm-text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-ds .ch-legend .vl, .tm-ds .ch-legend .sh { font-size: var(--tm-type-body); line-height: var(--tm-type-body-lh); font-variant-numeric: tabular-nums; }
.tm-ds .ch-legend .vl { color: var(--tm-text-primary); font-weight: var(--tm-weight-semibold); }
.tm-ds .ch-legend .sh { color: var(--tm-text-muted); }
.tm-ds .ch-panel text.ch-donut-center-v { fill: var(--tm-text-primary); font-family: var(--tm-font-sans); font-size: var(--tm-type-display); font-weight: var(--tm-weight-bold); }
.tm-ds .ch-panel text.ch-donut-center-l { fill: var(--tm-text-muted); font-family: var(--tm-font-sans); font-size: var(--tm-type-caption); }
/* the ring keeps the size the renderer gave it (the generic `.ch-mount svg { width:100% }` must not stretch it) */
.tm-ds .ch-mount svg.ch-donut { width: auto; height: auto; max-width: 100%; flex: 0 0 auto; }
.tm-ds .ch-donut-wrap .ch-legend { flex: 1 1 auto; width: auto; max-width: none; min-width: 0; }
/* donut mounts size to the ring (reference donut card ≈250px); the generic 240px mount floor is for time series */
.tm-ds #tmOvPlatform.ch-mount, .tm-ds #tmOvStatus.ch-mount, .tm-ds .ch-mount:has(> .ch-donut-wrap) { min-height: 0; }   /* any donut mount, any page (Canlı's donut card was 97px taller than its ring) */
/* zoom chip sits in the empty top-right corner of the plot, not on the x-axis labels */
.tm-ds .ch-zoom-chip { position: absolute; top: auto; right: 0; bottom: var(--tm-space-6); }
/* legend text in the body face (legacy set the value/share cells in mono, which ate the name column: "Trend…") */
.tm-ds .ch-legend .nm, .tm-ds .ch-legend .vl, .tm-ds .ch-legend .sh { font-family: var(--tm-font-sans); }
/* legacy section margin between the KPI grid and the chart grid (24 page gap + 12 = 36): the page gap is the only spacing */
.tm-ds .ch-grid, .tm-ds .tm-dashboard-ch-grid { margin: 0; }
/* rankings (En Çok Satanlar): one tone — the renderer reads --tm-chart-N from its mount, so the palette is collapsed there;
   the two donuts keep the full palette (legend colours carry meaning) */
.tm-ds #tmOvTop, .tm-ds #tmOvTopQty { --tm-chart-2: var(--tm-chart-1); --tm-chart-3: var(--tm-chart-1); --tm-chart-4: var(--tm-chart-1); --tm-chart-5: var(--tm-chart-1); --tm-chart-6: var(--tm-chart-1); --tm-chart-7: var(--tm-chart-1); }
/* segmented control (renderer markup .ch-seg > button) — token type, no 11.5px */
.tm-ds .ch-seg { display: inline-flex; gap: var(--tm-space-1); padding: var(--tm-space-1); border-radius: var(--tm-radius-control); background: var(--tm-bg-subtle); }
.tm-ds .ch-seg button { border: 0; background: transparent; padding: 0 var(--tm-space-2); height: 24px; border-radius: var(--tm-radius-control); font-family: var(--tm-font-sans); font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); font-weight: var(--tm-weight-medium); color: var(--tm-text-secondary); box-shadow: none; transition: color var(--tm-dur-base) var(--tm-ease); }
.tm-ds .ch-seg button.on { background: var(--tm-bg-surface); color: var(--tm-text-primary); box-shadow: none; }
/* Kayan gösterge (PR-3, ds-motion.css [data-tm-slide]): pil ::before ile kayar; hazır olunca .on'un kendi zemini kalkar */
.tm-ds .ch-seg[data-tm-slide] button { position: relative; z-index: 1; }
.tm-ds .ch-seg[data-tm-slide].is-slide-ready button.on { background: transparent; }

/* rankings: token type + colours (legacy tm-charts.css literals) */
.tm-ds .ch-rank-row { border-bottom: 1px solid var(--tm-border); }
.tm-ds .ch-rank-row:last-child { border-bottom: 0; }
.tm-ds .ch-rank-nm { color: var(--tm-text-primary); font-size: var(--tm-type-body); line-height: var(--tm-type-body-lh); }
.tm-ds .ch-rank-meta, .tm-ds .ch-rank-no { color: var(--tm-text-muted); font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); }
.tm-ds .ch-rank-vl { color: var(--tm-text-primary); font-size: var(--tm-type-body); font-variant-numeric: tabular-nums; font-family: var(--tm-font-sans); }
.tm-ds .ch-rank-thumb { border-radius: var(--tm-radius-control); border: 1px solid var(--tm-border); }
@media (max-width: 767.98px) {
  /* narrow cards: the product name wraps to two lines instead of "Suni Deri Kadın…" */
  .tm-ds .ch-rank-nm { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
}

@media (max-width: 767.98px) {
  /* chart header: title line first, segment controls on their own full-width row */
  .tm-ds .ch-head { flex-wrap: wrap; }
  .tm-ds .ch-actions, .tm-ds .ch-tools { width: 100%; flex-wrap: wrap; }
  .tm-ds .ch-head-l { flex: 1 1 100%; }
}

/* ---------- chart chrome, reference-derived (Apex area chart): dashed hairline grid, one 2px line, soft fill,
   no end-pulse ornament. tm-charts.js writes these as SVG attributes; CSS wins over presentation attributes. ---------- */
.tm-ds .ch-svg .ch-grid-line { stroke: var(--tm-chart-grid); stroke-width: 1; stroke-dasharray: 3 4; }
.tm-ds .ch-svg .ch-grid-line.zero { stroke-dasharray: none; }
.tm-ds .ch-svg .ch-area-line { stroke-width: 2; }
.tm-ds .ch-svg .ch-area-line.is-dashed { stroke-width: 1.5; }
.tm-ds .ch-svg .ch-area-fill { opacity: 0.55; }
.tm-ds .ch-svg .ch-live-end-pulse { display: none; }
.tm-ds .ch-svg .ch-live-end-dot { stroke: var(--tm-bg-surface); }

/* Aylık karşılaştırma kartı — 2026-09-24, kullanıcı isteği.
   Grafiğin altında aynı dönem toplamları: bu ay, geçen ay, yüzde fark. */
.tm-ds .ch-foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--tm-space-3);
  padding: var(--tm-space-3) var(--tm-space-4) 0;
  font-size: 12px; color: var(--tm-text-muted);
}
.tm-ds .ch-foot-item b { color: var(--tm-text); font-weight: 600; }
.tm-ds .ch-foot-item--prev b { color: var(--tm-text-muted); }
.tm-ds .ch-foot-fark { margin-left: auto; font-weight: 600; font-variant-numeric: tabular-nums; }
.tm-ds .ch-foot-fark.up { color: var(--tm-success-fg); }
.tm-ds .ch-foot-fark.down { color: var(--tm-danger-fg); }
.tm-ds .ch-foot-fark.flat { color: var(--tm-text-muted); }

/* Kesikli karşılaştırma çizgisi ve ipucundaki göstergesi. */
.tm-ds .ch-tip-dot--dash { border-radius: 1px; height: 3px; }
.tm-ds .ch-tip-row--fark { border-top: 1px solid var(--tm-border); margin-top: 4px; padding-top: 4px; }


/* ===== css/ds/ds-utilities.css ===== */
/* =================================================================
   DS — UTILITIES (Faz 3). Tiny, token-only. No margin utilities on purpose
   (sibling spacing is the parent's gap).
   ================================================================= */

.tm-ds .tm-num        { font-variant-numeric: tabular-nums; }
.tm-ds .tm-right      { text-align: right; }
.tm-ds .tm-center     { text-align: center; }
.tm-ds .tm-truncate   { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.tm-ds .tm-text-muted { color: var(--tm-text-muted); }
.tm-ds .tm-text-secondary { color: var(--tm-text-secondary); }
.tm-ds .tm-text-caption { font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); }
.tm-ds .tm-text-body-sm { font-size: var(--tm-type-body); line-height: var(--tm-type-body-lh); }
.tm-ds .tm-text-title { font-size: var(--tm-type-title); line-height: var(--tm-type-title-lh); font-weight: var(--tm-weight-semibold); }

/* Yeşilin ÜÇ TONU — büyüklük hâlâ boyut/ağırlıkla anlatılıyor (`gapTone`,
   `bb3-render.js`), renk onu KAYBETMEZ, TAŞIR (koordinatör kararı,
   2026-09-17: kullanıcı 990 TL/4,83 TL ayrımını beğendi, tek düz renge
   indirmek o hiyerarşiyi siler). `color-mix` zaten dark-mode-aware iki
   token'ı karıştırıyor (ds-stat-card.css'teki `color-mix` deseniyle AYNI) —
   yeni ham hex YOK, koyu modda ayrı bakım gerekmiyor. */
.tm-ds .tm-text-success      { color: var(--tm-success-fg); }
.tm-ds .tm-text-success-mid  { color: color-mix(in srgb, var(--tm-success-fg) 75%, var(--tm-text-secondary) 25%); }
.tm-ds .tm-text-success-soft { color: color-mix(in srgb, var(--tm-success-fg) 45%, var(--tm-text-muted) 55%); }
/* 🔴 2026-09-17 (kullanıcı: "daha okunaklı yazı renkleri"). Sihirbazın 3.
   adımındaki üç sayı aynı siyahtı; hangisinin HEDEF, hangisinin SINIR,
   hangisinin KAZANÇ olduğu yalnız etiketten okunuyordu.
   ⚠️ Bu ikisi DS'te YOKTU — şablonda `tm-text-accent` / `tm-text-warning`
   yazıp bırakmak İKİ ÖLÜ SINIF demek olurdu (sessiz no-op). Ölçülüp eklendi.
   ⛔ Renk etiketin YERİNE geçmez, ÜSTÜNE gelir: renk körü kullanıcı için
   "Hedef fiyat / Kâr tabanı / Tahmini kâr" metinleri yerinde duruyor. */
.tm-ds .tm-text-accent  { color: var(--tm-accent-fg); }
.tm-ds .tm-text-warning { color: var(--tm-warning-fg); }

/* Kanıt rozetine EK canlılık noktası — metni KISALTMAZ, rengi metnin YERİNE
   koymaz (koordinatör + bbx-design kararı, 2026-09-17: renk erişilebilir
   değil + `title` dokunmatikte yok, bilgi metinden renge devredilemez).
   `.tm-badge__dot` zaten `currentColor` kullanıyor (ds-badge.css) — uyarı
   tonunda badge'in KENDİ rengini (amber) miras alır, ek sınıfa gerek yok;
   nötr/kanıtlı tonda gri kalırdı, bu sınıf ona vurgu verir. Arka plan
   DEĞİŞMEDİ → `test_evidence_badges_share_one_format`in "ikisi de AYNI
   arka plan" kilidine dokunmuyor. */
.tm-ds .tm-badge__dot--accent { color: var(--tm-accent-fg); }
/* Doubled class = specificity (0,3,0), deliberately. A utility must beat the component it is
   put on; at (0,2,0) `.tm-ds .tm-hidden` TIED with `.tm-ds .tm-btn { display: inline-flex }`
   40 lines below and LOST on source order — `class="tm-btn tm-hidden"` stayed visible.
   Hard to spot because it works on anything that does not set `display` itself. Same trap
   for the native `[hidden]` attribute (0,1,1). Moving the rule to the end of this file would
   only fix same-file collisions; ds-live/-shell/-catalog load AFTER it. `!important` is the
   usual answer (Bootstrap does it) but the DS guard forbids it outside the dark-mode shim,
   and specificity gets us there without it. */
.tm-ds .tm-hidden.tm-hidden,
.tm-ds [hidden][hidden]     { display: none; }
.tm-ds .tm-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* status dot (the only other use of radius-full besides avatars) */
.tm-ds .tm-dot { display: inline-block; width: 8px; height: 8px; border-radius: var(--tm-radius-full); background: currentColor; }
.tm-ds .tm-dot--success { color: var(--tm-success-fg); }
.tm-ds .tm-dot--warning { color: var(--tm-warning-fg); }
.tm-ds .tm-dot--danger  { color: var(--tm-danger-fg); }
.tm-ds .tm-dot--muted   { color: var(--tm-text-muted); }

/* avatar / product thumb */
.tm-ds .tm-avatar { width: 32px; height: 32px; border-radius: var(--tm-radius-full); object-fit: cover; background: var(--tm-bg-subtle); flex-shrink: 0; }
.tm-ds .tm-thumb  { width: 36px; height: 36px; border-radius: var(--tm-radius-control); object-fit: cover; background: var(--tm-bg-subtle); border: 1px solid var(--tm-border); flex-shrink: 0; }
/* 🔴 --lg: LİSTE bağlamı için. Kullanıcı (2026-09-17): "listedeki ürünlerin
   görselleri çok küçük". 36px yoğun/ikincil yerler için doğru (kural
   yöneticisi satırı), ama ürünün TANINMASI gereken fırsat listesinde değil —
   36px'te bir ürün görselinden ne olduğu anlaşılmıyor.
   ⚠️ `.tm-thumb` DEĞİŞTİRİLMEDİ, modifier eklendi: ölçüldü, `tm-thumb` yalnız
   buybox v3'te (3 dosya) kullanılıyor, yani tabanı büyütmek bugün güvenli
   OLURDU — ama utility'nin anlamı ("küçük küçük resim") korunarak bağlama
   göre seçim yapmak, bir sonraki sayfanın 64px'i miras almasından iyi. */
.tm-ds .tm-thumb--lg { width: 64px; height: 64px; }

/* buttons inside DS scope: flat, bordered, no shadow (Bootstrap .btn stays functional) */
.tm-ds .tm-btn,
.tm-ds .btn {
  box-shadow: none;
  border-radius: var(--tm-radius-control);
  font-size: var(--tm-type-body);
  line-height: var(--tm-type-body-lh);
  font-weight: var(--tm-weight-medium);
}
.tm-ds .tm-btn { display: inline-flex; align-items: center; gap: var(--tm-space-1); height: 36px; padding: 0 var(--tm-space-3); border: 1px solid var(--tm-border); background: var(--tm-bg-surface); color: var(--tm-text-primary); cursor: pointer; }
.tm-ds .tm-btn:not(:disabled):not([aria-disabled="true"]):hover { background: var(--tm-bg-subtle); }
.tm-ds .tm-btn--primary { background: var(--tm-accent); border-color: var(--tm-accent); color: var(--tm-text-on-brand); }
.tm-ds .tm-btn--primary:not(:disabled):not([aria-disabled="true"]):hover { background: var(--tm-accent-fg); border-color: var(--tm-accent-fg); }
/* Disabled state — MISSING from the DS layer until 2026-09-16. Measured on a REAL page (full
   base.html chain, 59 stylesheets, #tmv2App + .tm-ds), not in isolation — the two differ and the
   difference is the whole point. Legacy tm-ui-system.css:132 (`.tm-btn:disabled{opacity:.55;
   cursor:not-allowed}`) loads on every base.html page via base_head_v2_links.html:19, so the
   DIMMING already reached the button. What did not reach it: `.tm-ds .tm-btn{cursor:pointer}`
   (0,2,0) outranked that rule's cursor, and nothing suppressed hover. Develop, buybox v4
   #bb3CampaignCta (`tm-btn tm-btn--primary`, disabled by bb3-state.js:220 when no row is
   pickable): bg rgb(1,117,228) · opacity .55 · cursor POINTER · hover still lit to rgb(1,99,194).
   The button was dimmed yet still INVITED the pointer and ANSWERED the hover — so the dimming read
   as styling, not as "dead". The only real explanation was the `title` tooltip: absent on touch,
   unreachable by a screen reader.
   ⚠ In the DS layer alone (tokens.css + ds.css, as tests/e2e/ds-button-disabled-2026-09-16.cjs
   loads it) the same button computes opacity 1. That is a fixture artifact — do not cite it as
   what a user saw.
   Hover is EXCLUDED (`:not(:disabled)`) rather than overridden per variant, so ghost/primary/sm
   stay correct without counter-rules. `pointer-events: none` is deliberately NOT used: it would
   suppress the very tooltip that explains WHY the button is dead, and hiding the reason is worse. */
.tm-ds .tm-btn:disabled,
.tm-ds .tm-btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
.tm-ds .tm-btn--sm { height: 30px; padding: 0 var(--tm-space-2); font-size: var(--tm-type-caption); }
.tm-ds .tm-btn--ghost { border-color: transparent; background: transparent; }

/* Canlı Performansım promo band (includes/dashboard/dashboard_tabbed_live_promo_banner.html, inline <style>):
   inside DS scope it is a plain surface row with token text — no tinted wash, readable in dark. Dismissible +
   remembered by its own script (localStorage). */
.tm-ds .tm-live-promo { background: var(--tm-bg-surface); border: 1px solid var(--tm-border); border-radius: var(--tm-radius-card); box-shadow: var(--tm-shadow-card); animation: none; }
.tm-ds .tm-live-promo__inner, .tm-ds .tm-live-promo__text { color: var(--tm-text-secondary); }   /* dark-mode.css forces `span { color: inherit }` → the parent must carry the token */
.tm-ds .tm-live-promo__text strong { color: var(--tm-text-primary); font-size: var(--tm-type-body); line-height: var(--tm-type-body-lh); }
.tm-ds .tm-live-promo__sub { color: var(--tm-text-secondary); font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); }
.tm-ds .tm-live-promo__pulse { animation: none; box-shadow: none; background: var(--tm-accent); }

/* Demo tour invitation band (templates/pages/dashboard_live.html #tmDemoTourCta): same surface language as the
   Canlı Performansım promo above — no gradient wash, hairline card, one accent button. `.is-hidden` stays display:none
   (JS contract). */
.tm-ds .tm-demo-tour-cta { display: flex; align-items: center; gap: var(--tm-space-3); padding: var(--tm-space-2) var(--tm-space-4); background: var(--tm-bg-surface); background-image: none; border: 1px solid var(--tm-border); border-radius: var(--tm-radius-card); box-shadow: var(--tm-shadow-card); animation: none; }
.tm-ds .tm-demo-tour-cta.is-hidden { display: none; }
.tm-ds .tm-demo-tour-cta__icon { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: var(--tm-radius-full); background: var(--tm-accent-bg); color: var(--tm-accent-fg); flex-shrink: 0; }
.tm-ds .tm-demo-tour-cta__icon i, .tm-ds .tm-demo-tour-cta__icon svg { width: 13px; height: 13px; }
.tm-ds .tm-demo-tour-cta__copy { flex: 1 1 auto; min-width: 0; display: flex; align-items: baseline; gap: var(--tm-space-2); flex-wrap: wrap; }
.tm-ds .tm-demo-tour-cta__title { margin: 0; font-size: var(--tm-type-body); line-height: var(--tm-type-body-lh); font-weight: var(--tm-weight-semibold); color: var(--tm-text-primary); }
.tm-ds .tm-demo-tour-cta__lead { margin: 0; font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); color: var(--tm-text-secondary); }
.tm-ds .tm-demo-tour-cta__btn { display: inline-flex; align-items: center; gap: var(--tm-space-1); height: 28px; padding: 0 var(--tm-space-3); border: 0; border-radius: var(--tm-radius-control); background: var(--tm-accent-solid); color: var(--tm-on-accent); font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); font-weight: var(--tm-weight-semibold); box-shadow: none; transition: none; }
.tm-ds .tm-demo-tour-cta__btn i, .tm-ds .tm-demo-tour-cta__btn svg { width: 12px; height: 12px; }
.tm-ds .tm-demo-tour-cta__close { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border: 0; border-radius: var(--tm-radius-full); background: transparent; color: var(--tm-text-muted); }
.tm-ds .tm-demo-tour-cta__close:hover { background: var(--tm-bg-subtle); color: var(--tm-text-primary); }


/* ===== css/ds/ds-live.css ===== */
/* =================================================================
   DS — CANLI PERFORMANS (Faz 4b, 2026-09-13). Page-specific re-skin for
   templates/pages/dashboard_live.html once it opts into .tm-ds (tmv2_ds_scope
   block). The three page-owned overlay files (v2/components/live-dashboard.css,
   live-actions-v2.css, dashboard/live-perf-polish-2026-06-08.css — docs/ui-audit.md
   Ek A "Canlı Performans: bırakılabilir", 3.366 satır / 430 !important) now load
   only behind ?legacy=1; this file restates what the page still needs from
   tokens/primitives. KPI cards are NOT here — they are .kpi-card (tm-kpi.js
   buildCard(), same DOM as Genel Bakış) and are already re-skinned by
   ds-stat-card.css; this file only fixes the live-grid-specific min-height
   collision with dashboard-vanilla.css (kept, shared, not gated).

   Everything below is scoped .tm-ds .tm-live-page (or narrower) on purpose —
   .tm-ds alone is shared with the Genel Bakış/Siparişler DS pages (other
   agents own those); no rule here may leak outside this page's DOM.

   Class names are the JS/template contract (docs/ui-audit.md Ek B) and are
   never renamed here — only re-skinned. Reduced motion is already global
   under .tm-ds (ds-primitives.css); nothing here needs its own query except
   the one 600ms value-changed flash, which must stay off under
   prefers-reduced-motion.
   ================================================================= */

/* ---------- Page rhythm: `.tm-live-page { display:flex; flex-direction:column;
   gap:8px }` lived in the now-gated v2/components/live-dashboard.css — it was
   the page's ONLY vertical-rhythm mechanism (header/KPI/banners/main-grid/
   table). Without it children fall back to ad-hoc margins → 34/42/44px
   uneven gaps (layout-lint R3, live-r1/r2). Restated at the reference's one
   row gap (24). ---------- */
.tm-ds .tm-live-page {
  display: flex;
  flex-direction: column;
  gap: var(--tm-space-6);
  padding: var(--tm-space-6) 0;   /* same page box as Genel Bakış / Siparişler: shell gutter only, 24 top/bottom */
}

/* ---------- KPI grid: legacy `.tm-live-page .tm-live-kpi-grid .kpi-card`
   (dashboard-vanilla.css, class specificity 0,3,0) ties with ds-stat-card's
   `.tm-ds .kpi-card` (0,2,0) by specificity in the OTHER direction (higher);
   restated here at matching specificity so ds.css (loaded last) wins. ---- */
.tm-ds .tm-live-page .tm-live-kpi-grid.kpi-grid { margin: 0; }
/* r4 (2026-09-13, coordinator): 24/34/44/42px uneven vertical rhythm
   (layout-lint R3) — the demo-tour CTA's own `margin: 6px 0 10px` (template-
   inline, unconditional) stacked on top of `.tm-live-page { gap:24px }`.
   Neighbouring banners in this same template already document the pattern
   ("margin:0 -> dikey aralık parent gap'inden gelir"); restated here so
   ?legacy=1 keeps its original spacing. .tm-kpi-row / .tm-live-main-grid /
   .tm-live-orders-card margins excluded at the source
   (ui-stability-round4-2026-06-05.css, same commit). */
.tm-ds .tm-live-page .tm-demo-tour-cta { margin: 0; }
/* dashboard-vanilla.css (shared with Genel Bakış, not edited here) also sets
   `.tm-live-page .tm-live-main-grid { margin-top: 16px }` at (0,2,0) — beats
   the template's own inline `margin-top: 0` (0,1,0). Restated at (0,3,0). */
.tm-ds .tm-live-page .tm-live-main-grid { margin-top: 0; column-gap: var(--tm-space-4); row-gap: var(--tm-space-6); align-items: start; grid-template-columns: minmax(0, 1fr); }
/* 2026-09-13 (kullanıcı kararı): "Öncelikli aksiyonlar" (aksiyon merkezi) sayfadan kaldırıldı — DS kapsamında gizli,
   DOM/JS sözleşmesi (tmActionInsights) yerinde; grafik satırı tam genişlik: donut 4 + saatlik akış 8 yan yana. */
.tm-ds .tm-live-page #tmActionInsights, .tm-ds .tm-live-page .tm-live-main-grid__sidebar, .tm-ds .tm-live-page #tmDemoTourCta { display: none; }   /* kullanıcı kararı 2026-09-13: aksiyon merkezi ve demo tur daveti Canlı sayfasından kaldırıldı (DOM/JS sözleşmesi yerinde) */   /* the aside wrapper kept a 96px slot */
.tm-ds .tm-live-page .tm-live-main-grid { display: block; }   /* the content column is the only visible child now; as a grid the empty aside slot kept adding a 24px row gap */
.tm-ds .tm-live-page .tm-live-main-grid__content { grid-area: auto; grid-column: 1 / -1; grid-row: 1; min-width: 0; }   /* strict lint 2026-09-13: gap was 20 (not a token); stretch made the donut card 97px taller than its content */
.tm-ds .tm-live-page .tm-live-main-grid__content > .ch-grid,
.tm-ds .tm-live-page .tm-live-main-grid__content > .tm-dashboard-ch-grid { align-content: start; }
.tm-ds .tm-live-page .tm-live-kpi-grid .kpi-card { min-height: var(--tm-dash-kpi-h); }
/* ds-stat-card.css absolute-positions .kpi-head-tools assuming .kpi-card is
   the containing block; tm-kpi.css's `.kpi-head { position: relative }`
   (kept, shared, not edited here) makes .kpi-head the real one, so the
   live badge lands ~17px too low (into the value row). Every card on this
   page is mode:'live' (docs/ui-audit.md Ek B tm-kpi.js), so the badge is
   always present here — re-anchored to .kpi-head's own box, this page only. */
/* 2026-09-24: aynı hizalama artık ds-stat-card.css'te (tüm sayfalar) — sayfa-özel kural kaldırıldı. */
/* Every card on this page carries the "CANLI" live badge (mode:'live' for
   the whole grid, not just one accent card) — at 5-up card width (≈150px)
   the text collided with the label. The reference has no such badge at all
   (docs/ui-reference-spec.md §1); kept as a plain dot (still communicates
   "live"), dropped the redundant text + pill chrome to reclaim label width
   and cut one more saturated-colour use per card (target ≤20/page). */
.tm-ds .tm-live-page .kpi-livebadge {
  gap: 0;
  padding: 0;
  height: auto;
  width: 6px;
  overflow: hidden;
  white-space: nowrap;
  background: transparent;
}
.tm-ds .tm-live-page .kpi-livebadge .live-dot { width: 6px; height: 6px; flex-shrink: 0; }

/* ---------- Chart row (donut + hourly): ds-chart-card.css moved
   .ch-grid/.tm-dashboard-ch-grid to a 12-col grid with span-{3,4,6,8,12}
   only (Genel Bakış's vocabulary — owned file, not edited here). This page's
   template still carries the older 6-col span-2/span-4 classes
   (tm-vanilla-dashboard-charts.css, also used in ?legacy=1 mode) for the
   1:2 donut/hourly split. Re-mapped onto the 12-col grid so the ratio is
   unchanged in both modes; the template classes are not renamed. */
/* 2026-09-13: aksiyon merkezi kaldırılınca ızgara tam sayfa genişliğinde (888+ px) → donut 4 + saatlik akış 8 yan yana
   (kullanıcı kararı). Tablette alt alta. (Önceki ~500 px'lik sütunda 1:2 bölünme donut kartını 159 px'e düşürüyordu.) */
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 { grid-column: span 4; }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-4 { grid-column: span 8; }
/* DÜŞÜK-VERİ BOŞLUĞU (2026-09-18): grid satırı (align-items:stretch varsayılan) iki paneli EN
   UZUNA gerip kısa donut kartını dev boşlukla dolduruyordu — az veride donut ortada asılı, altında
   boşluk. Satır gerdirmesini kapat → her panel İÇERİK yüksekliğinde. Dolu veride de düzgün kalır. */
/* 2026-09-24 (kullanıcı): iki kart AYNI boyda olmalı. Satır gerdirmesi açık; saatlik akış paneli
   kendi içerik boyunda kalır (align-self:start) → satır yüksekliği = ikisinin uzunu; donut kartı ona
   gerilir, boş/dolu içeriği dikeyde ortalanır (aşağıda). Böylece ne az-veride kısa kart ne de dolu
   veride saatlik akışın altında boşluk kalır. */
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live { align-items: stretch; }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.tm-live-hourly-panel { align-self: start; }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 { display: flex; flex-direction: column; }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 > .ch-mount { flex: 1 1 auto; display: flex; align-items: center; justify-content: center; min-height: 0; }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 > .ch-mount > .tm-live-empty { flex: 1 1 auto; align-self: stretch; }
/* Boş durum ikonu + yumuşak süzülme (kullanıcı isteği, 2026-09-24); hareket tercihine saygılı. */
@media (prefers-reduced-motion: no-preference) {
  .tm-ds .tm-live-page .tm-live-empty svg { animation: tmEmptyFloat 3.2s ease-in-out infinite; }
}
@media (max-width: 1099.98px) {   /* same breakpoint as the hourly chart's responsive height (tm-vanilla-dashboard-charts.css) */
  .tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2,
  .tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-4 { grid-column: span 12; }
}

/* ================= Top strip: pulse line row + controls row =================
   Measured 2026-09-13 (layout-shift sources): with `flex-wrap: wrap` the strip
   was ONE row while the pulse line held skeletons (380px) and wrapped to TWO
   rows once JS filled it (643px) → header 34→73px, everything below moved
   39px = CLS 0.22. Two explicit rows from the first paint: no shift. */
.tm-ds .tm-live-page .tm-live-header {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;           /* one row when it fits (≥~1500px), two rows below — deterministic because every stat value reserves its width (min-width in ch) */
  align-items: center;
  justify-content: space-between;
  gap: var(--tm-space-3) var(--tm-space-6);
  padding: 0;
  margin: 0;
}
.tm-ds .tm-live-page .tm-live-header > .tm-live-pulseline { width: auto; flex: 1 1 auto; min-height: var(--tm-type-caption-lh); }
.tm-ds .tm-live-page .tm-live-pulseline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--tm-space-4);
  min-width: 0;
}
.tm-ds .tm-live-page .tm-live-stat {
  display: flex;
  align-items: baseline;
  gap: var(--tm-space-1);
  font-size: var(--tm-type-caption);
  line-height: var(--tm-type-caption-lh);
  white-space: nowrap;
}
/* r4 (2026-09-13, coordinator): dashboard-vanilla.css (shared, not edited
   here) sets `.tm-live-page .tm-live-stat__label { font-size: var(--tm-type-micro) }` /
   `__value { font-size: var(--tm-type-caption) }` (0,2,0) — 2 of the page's off-scale type
   steps. My rules below are (0,3,0) but were silent on font-size, so the
   legacy value still won (same bug class as kpi-head-tools/.num mono).
   Restated at the nearest DS steps (micro 11 / caption 12). */
.tm-ds .tm-live-page .tm-live-stat__label {
  color: var(--tm-text-muted);
  font-size: var(--tm-type-micro);
  line-height: var(--tm-type-micro-lh);
  text-transform: none;
  letter-spacing: 0;
  font-weight: var(--tm-weight-medium);
}
.tm-ds .tm-live-page .tm-live-stat__value {
  color: var(--tm-text-primary);
  font-size: var(--tm-type-caption);
  line-height: var(--tm-type-caption-lh);
  font-weight: var(--tm-weight-semibold);
  font-variant-numeric: tabular-nums;
  min-width: 3ch;
}
/* r4 (2026-09-13, coordinator): remaining 0.0025 load-CLS came from these
   three values arriving async and widening past the blanket 3ch guess
   (measured: "şimdi · Trendyol · ₺900" 143px≈21ch, "10 sip/sa (tipik 0,9)"
   121px≈18ch, "7,4% (5/68)" 76px≈11ch) — sized per stat so the final value
   never grows past its reserved box. */
#tmLiveLastOrder.tm-live-stat__value { min-width: 21ch; }
#tmLivePace.tm-live-stat__value { min-width: 18ch; }
#tmLiveCancelRate.tm-live-stat__value { min-width: 11ch; }

/* r4 (2026-09-13, coordinator): the demo-tour CTA (only demo users) toggles
   `.is-hidden` (display:none -> flex) client-side, AFTER first paint, once a
   session/localStorage dismissal check resolves (template inline <script>,
   not edited here). display:none reserves zero space, so the reveal shifted
   .tm-live-main-grid down — the single largest CLS contributor measured
   (r9/r4-base). `visibility:hidden` reserves the box's final height from the
   very first paint; the class-remove then only changes visibility, zero
   layout shift. Trade-off (documented, not solved): a user who dismissed the
   CTA earlier in the session now sees a permanent empty-but-present slot for
   the rest of this page life — the underlying show/hide model is JS state
   this task does not touch. */
.tm-ds .tm-live-page .tm-demo-tour-cta.is-hidden {
  display: flex;
  visibility: hidden;
  pointer-events: none;
}
.tm-ds .tm-live-page .tm-live-header__row--controls-only { margin: 0; flex-shrink: 0; }
.tm-ds .tm-live-page .tm-live-controls {
  display: flex;
  align-items: center;
  gap: var(--tm-space-2);
  flex-wrap: wrap;
}
.tm-ds .tm-live-page .tm-live-status {
  display: inline-flex;
  align-items: center;
  gap: var(--tm-space-1);
  height: 28px;
  padding: 0 var(--tm-space-2);
  border-radius: var(--tm-radius-control);
  background: var(--tm-bg-subtle);
  color: var(--tm-text-secondary);
  font-size: var(--tm-type-caption);
  line-height: var(--tm-type-caption-lh);
  font-weight: var(--tm-weight-medium);
}
.tm-ds .tm-live-page .tm-live-status[data-state="ok"] { background: var(--tm-success-bg); color: var(--tm-success-fg); }
.tm-ds .tm-live-page .tm-live-status[data-state="error"] { background: var(--tm-danger-bg); color: var(--tm-danger-fg); }
.tm-ds .tm-live-page .tm-live-status__dot { width: 7px; height: 7px; border-radius: var(--tm-radius-full); background: currentColor; flex-shrink: 0; }
.tm-ds .tm-live-page .tm-live-select,
.tm-ds .tm-live-page .tm-live-platform-select {
  height: 28px;
  padding: 0 var(--tm-space-2);
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-control);
  background: var(--tm-bg-surface);
  color: var(--tm-text-primary);
  font-size: var(--tm-type-caption);
  line-height: var(--tm-type-caption-lh);
  box-shadow: none;
}
.tm-ds .tm-live-page .tm-live-header .btn {
  box-shadow: none;
  background: var(--tm-bg-surface);
  border: 1px solid var(--tm-border);
  color: var(--tm-text-primary);
  border-radius: var(--tm-radius-control);
  transform: none;
}
.tm-ds .tm-live-page .tm-live-header .btn:hover { box-shadow: none; transform: none; background: var(--tm-bg-subtle); }
.tm-ds .tm-live-page .tm-live-header .btn--primary {
  background: var(--tm-accent-solid);
  border-color: var(--tm-accent-solid);
  color: var(--tm-on-accent);
}
.tm-ds .tm-live-page .tm-live-header .btn--primary:hover { background: var(--tm-accent-solid); box-shadow: none; }
.tm-ds .tm-live-page .tm-actions-overflow summary {
  height: 28px;
  display: inline-flex;
  align-items: center;
  padding: 0 var(--tm-space-2);
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-control);
  color: var(--tm-text-secondary);
  font-size: var(--tm-type-caption);
  cursor: pointer;
}
/* a disclosure popout is a floating layer, but its class name carries no
   "overlay/dropdown/menu" keyword for the shadow-scope lint to key off —
   named explicitly here instead of relying on --tm-shadow-overlay */
.tm-ds .tm-live-page .tm-actions-overflow__body {
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-control);
  background: var(--tm-bg-surface);
  box-shadow: none;
}

/* ================================ Action centre ============================
   Card chrome (surface/border/radius/24-inset/shadow) already comes from
   ds-primitives .tm-card — .tm-action-insights carries that class. Only the
   list/row/status colour is page-specific. */
.tm-ds .tm-live-page .tm-insights-filters { display: flex; flex-wrap: wrap; gap: var(--tm-space-2); }
.tm-ds .tm-live-page .tm-action-insights__last-check {
  font-size: var(--tm-type-micro);
  line-height: var(--tm-type-micro-lh);
  color: var(--tm-text-muted);
}
.tm-ds .tm-live-page .tm-action-grid { display: flex; flex-direction: column; gap: var(--tm-space-2); }
.tm-ds .tm-live-page .tm-action-card {
  display: flex;
  flex-direction: column;
  gap: var(--tm-space-1);
  width: 100%;
  padding: var(--tm-space-3);
  border: 1px solid var(--tm-border);
  border-left: 3px solid var(--tm-border);
  border-radius: var(--tm-radius-control);
  background: var(--tm-bg-surface);
  color: var(--tm-text-primary);
  text-align: left;
  cursor: pointer;
  transition: none;
}
.tm-ds .tm-live-page .tm-action-card:hover { background: var(--tm-bg-subtle); }
/* colour only for status — the severity stripe, nothing else changes */
.tm-ds .tm-live-page .tm-action-card[data-severity="critical"] { border-left-color: var(--tm-danger-fg); }
.tm-ds .tm-live-page .tm-action-card[data-severity="warning"]  { border-left-color: var(--tm-warning-fg); }
.tm-ds .tm-live-page .tm-action-card[data-severity="info"]     { border-left-color: var(--tm-info-fg); }
.tm-ds .tm-live-page .tm-action-card[data-severity="success"]  { border-left-color: var(--tm-success-fg); }
.tm-ds .tm-live-page .tm-action-card__head { display: flex; align-items: center; gap: var(--tm-space-2); }
.tm-ds .tm-live-page .tm-action-card__icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: var(--tm-radius-full);
  background: var(--tm-bg-subtle); color: var(--tm-text-secondary); flex-shrink: 0;
}
.tm-ds .tm-live-page .tm-action-card__icon i,
.tm-ds .tm-live-page .tm-action-card__icon svg { width: 12px; height: 12px; }
.tm-ds .tm-live-page .tm-action-card__badge {
  font-size: var(--tm-type-micro);
  line-height: var(--tm-type-micro-lh);
  color: var(--tm-text-muted);
  text-transform: uppercase;
  letter-spacing: var(--tm-tracking-wide, 0.02em);
}
.tm-ds .tm-live-page .tm-action-card__chevron { margin-left: auto; color: var(--tm-text-muted); flex-shrink: 0; }
.tm-ds .tm-live-page .tm-action-card__chevron i,
.tm-ds .tm-live-page .tm-action-card__chevron svg { width: 14px; height: 14px; }
.tm-ds .tm-live-page .tm-action-card__title {
  margin: 0;
  font-size: var(--tm-type-body);
  line-height: var(--tm-type-body-lh);
  font-weight: var(--tm-weight-medium);
  color: var(--tm-text-primary);
}
.tm-ds .tm-live-page .tm-action-card__desc {
  margin: 0;
  font-size: var(--tm-type-caption);
  line-height: var(--tm-type-caption-lh);
  color: var(--tm-text-secondary);
}
.tm-ds .tm-live-page .tm-action-card__meta { display: flex; flex-wrap: wrap; gap: var(--tm-space-1); }
.tm-ds .tm-live-page .tm-action-card__pill,
.tm-ds .tm-live-page .tm-action-card__sub-metric {
  display: inline-flex; align-items: center;
  height: 18px; padding: 0 var(--tm-space-1);
  border-radius: var(--tm-radius-control);
  background: var(--tm-bg-subtle);
  color: var(--tm-text-muted);
  font-size: var(--tm-type-micro);
  line-height: var(--tm-type-micro-lh);
}
.tm-ds .tm-live-page .tm-action-card__pill--impact { background: var(--tm-warning-bg); color: var(--tm-warning-fg); }
.tm-ds .tm-live-page .tm-action-card__metric,
.tm-ds .tm-live-page .tm-action-card__footer {
  display: flex; align-items: center; gap: var(--tm-space-1);
  font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh);
}
.tm-ds .tm-live-page .tm-action-card__metric-label,
.tm-ds .tm-live-page .tm-action-card__cta { color: var(--tm-text-muted); }
.tm-ds .tm-live-page .tm-action-card__metric-value { font-weight: var(--tm-weight-semibold); font-variant-numeric: tabular-nums; }
.tm-ds .tm-live-page .tm-action-allclear {
  display: flex; align-items: center; gap: var(--tm-space-3);
  padding: var(--tm-space-3);
  color: var(--tm-text-secondary);
  font-size: var(--tm-type-caption);
  line-height: var(--tm-type-caption-lh);
}
.tm-ds .tm-live-page .tm-action-allclear__icon { color: var(--tm-text-muted); flex-shrink: 0; }
.tm-ds .tm-live-page .tm-action-allclear__title { margin: 0; font-weight: var(--tm-weight-semibold); color: var(--tm-text-primary); }
.tm-ds .tm-live-page .tm-action-allclear__desc { margin: 0; }

/* ============================== Orders table =============================
   `.tm-live-tbl` also carries `.tm-table` → row height 52/40, sticky head,
   hover and .tm-num already come from ds-table.css. Only the live-specific
   cell types (order-number mono, `.num` alias, pill, product, status) and
   the filter bar / pager are page-specific. */
.tm-ds .tm-live-page .tm-live-filterbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--tm-space-3); }
.tm-ds .tm-live-page .tm-live-search {
  display: flex; align-items: center; gap: var(--tm-space-2);
  height: 32px; padding: 0 var(--tm-space-3);
  border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control);
  background: var(--tm-bg-surface); color: var(--tm-text-muted); flex: 1 1 220px; min-width: 160px;
}
.tm-ds .tm-live-page .tm-live-search input {
  border: 0; background: transparent; color: var(--tm-text-primary);
  font-size: var(--tm-type-body); line-height: var(--tm-type-body-lh); width: 100%;
}
.tm-ds .tm-live-page .tm-live-filtergroup { display: flex; align-items: center; gap: var(--tm-space-2); }
.tm-ds .tm-live-page .tm-live-filtergroup__label { font-size: var(--tm-type-caption); color: var(--tm-text-muted); }
/* r4 (2026-09-13, coordinator): amounts/net-kâr/marj were rendering mono —
   attributed via computed-style probe: tm-v2.css:478 `.tm-table td.num {
   font-family: var(--ff-num); font-variant-numeric: tabular-nums; font-weight:600; color:var(--ink); }` (shared,
   not edited here) is silent-but-still-applies on any property MY higher-
   specificity rule below doesn't also set (the class of bug ds-live.css
   already hit twice — kpi-head-tools/donut-span). Spec: mono ONLY for the
   order number; amounts/net-kâr/marj are body-face + tabular-nums. */
.tm-ds .tm-live-page .tm-live-tbl td.num,
.tm-ds .tm-live-page .tm-live-tbl th.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-family: var(--tm-font-sans);
  font-weight: var(--tm-weight-regular);
  color: var(--tm-text-primary);
}
.tm-ds .tm-live-page .tm-live-tbl .tm-mono,
.tm-ds .tm-live-page .tm-live-tbl td[data-cell="order"] {
  font-family: var(--tm-font-mono);
  font-size: var(--tm-type-caption);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-variant-numeric: tabular-nums;
}

/* r4 (2026-09-13, coordinator): "Durum" clipped past the card's right edge at
   1280 (measured: card content 838px, table auto-width 900px). table-layout:
   fixed + explicit widths from the header row (thead defines all 8 columns
   in a fixed template order, not JS-reordered — nth-child is safe); product
   name gets the remainder and already ellipsizes internally
   (.tm-live-product__name max-width:22ch). Column budget sums to 838px. */
.tm-ds .tm-live-page .tm-live-tbl { table-layout: fixed; width: 100%; }
/* r4 (2026-09-13, coordinator): "19:16" (5-char mono, 12px) needs 60px —
   54px was clipping it to "19:_" via the shared `.tm-mono` ellipsis rule
   (td[data-cell="time"] also carries .tm-mono). Widened Saat 54->60,
   trimmed 6px total off Net Kâr/Marj (both plain percentages/amounts, no
   truncation risk at the new widths). Budget still sums to 838px. */
/* polish (2026-09-13, item 3): "Hepsiburada" (11 chars) clipped in the 84px
   Pazaryeri column — measured (Playwright): td clientWidth===scrollWidth===84
   at 1280, i.e. the word was cut, not ellipsized (the existing rule set
   `text-overflow:ellipsis` without `white-space:nowrap`, which is a no-op per
   spec — an unbreakable word just overflows and gets clipped by
   `overflow:hidden` instead of showing "…"). Widened Pazaryeri 84->108px +
   added the missing `white-space:nowrap` so any future longer platform name
   ellipsizes instead of clipping silently. Saat is NOT shortened to fund this
   — 54px was proven to clip "19:16" one round ago (comment above); the table
   is `width:100%` with one flexible column (Ürün, nth-child(4), `width:auto`),
   so the +24px comes out of Ürün's remainder automatically, not neighbours. */
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(1),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(1) { width: 60px; }
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(2),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(2) { width: 108px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(3),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(3) { width: 130px; }
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(4),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(4) { width: auto; overflow: hidden; }
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(5),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(5) { width: 86px; }
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(6),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(6) { width: 86px; }
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(7),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(7) { width: 58px; }
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(8),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(8) { width: 88px; }
.tm-ds .tm-live-page .tm-live-pill { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.tm-ds .tm-live-page .tm-live-tbl td.tm-cell-pos { color: var(--tm-success-fg); font-weight: var(--tm-weight-semibold); }
.tm-ds .tm-live-page .tm-live-tbl td.tm-cell-neg { color: var(--tm-danger-fg); font-weight: var(--tm-weight-semibold); }
.tm-ds .tm-live-page .tm-live-tbl td.tm-cell-unknown { color: var(--tm-text-muted); }
/* maliyet-eksik uyarısı (Canlı Performans, "Bugünün Siparişleri") — satır rozeti
   + kart başlığı sayaç satırı. Renk yalnız --tm-warning-*; boşluk 7-token setinden. */
.tm-ds .tm-live-page .tm-live-cost-badge {
  display: inline-flex; align-items: center; gap: var(--tm-space-1);
  height: 20px; padding: 0 var(--tm-space-2);
  border-radius: var(--tm-radius-control);
  background: var(--tm-warning-bg); color: var(--tm-warning-fg);
  font-size: var(--tm-type-micro); line-height: var(--tm-type-micro-lh); font-weight: var(--tm-weight-medium);
  white-space: nowrap; flex-shrink: 0;
}
.tm-ds .tm-live-page .tm-live-missing-cost-note {
  margin: 0;
  font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh);
  color: var(--tm-warning-fg); font-weight: var(--tm-weight-medium);
}
.tm-ds .tm-live-page .tm-live-missing-cost-note a { color: inherit; }
.tm-ds .tm-live-page .tm-live-pill {
  display: inline-flex; align-items: center; gap: var(--tm-space-1);
  color: var(--tm-text-secondary); font-size: var(--tm-type-caption); white-space: nowrap;
}
.tm-ds .tm-live-page .tm-live-pill__dot { width: 6px; height: 6px; border-radius: var(--tm-radius-full); background: var(--tm-accent); flex-shrink: 0; }
.tm-ds .tm-live-page .tm-live-product { display: flex; align-items: center; gap: var(--tm-space-2); min-width: 0; }
.tm-ds .tm-live-page .tm-live-product__img { width: 28px; height: 28px; border-radius: var(--tm-radius-control); flex-shrink: 0; background: var(--tm-bg-subtle); object-fit: cover; }
.tm-ds .tm-live-page .tm-live-product__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 22ch; }
/* status — the reference StatusBadge: soft bg + text, colour is the only signal */
.tm-ds .tm-live-page .tm-live-state-badge {
  display: inline-flex; align-items: center; gap: var(--tm-space-1);
  height: 22px; padding: 0 var(--tm-space-2);
  border-radius: var(--tm-radius-control);
  background: var(--tm-bg-subtle); color: var(--tm-text-secondary);
  font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); font-weight: var(--tm-weight-medium);
  white-space: nowrap;
}
.tm-ds .tm-live-page .tm-live-state-badge[data-status="completed"] { background: var(--tm-success-bg); color: var(--tm-success-fg); }
.tm-ds .tm-live-page .tm-live-state-badge[data-status="cancelled"] { background: var(--tm-danger-bg); color: var(--tm-danger-fg); }
.tm-ds .tm-live-page .tm-live-state-badge[data-status="returned"] { background: var(--tm-warning-bg); color: var(--tm-warning-fg); }
.tm-ds .tm-live-page .tm-live-tblfoot {
  display: flex; align-items: center; justify-content: space-between; gap: var(--tm-space-3);
  padding-top: var(--tm-space-3);
  font-size: var(--tm-type-caption); color: var(--tm-text-muted); font-variant-numeric: tabular-nums;
}
.tm-ds .tm-live-page .tm-live-pager { display: flex; align-items: center; gap: var(--tm-space-1); }
.tm-ds .tm-live-page .tm-live-pager__btn,
.tm-ds .tm-live-page .tm-live-pager__num {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 26px; height: 26px; padding: 0 var(--tm-space-1);
  border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control);
  background: var(--tm-bg-surface); color: var(--tm-text-secondary);
  font-size: var(--tm-type-caption); font-variant-numeric: tabular-nums; cursor: pointer;
}
.tm-ds .tm-live-page .tm-live-pager__num[aria-current="true"],
.tm-ds .tm-live-page .tm-live-pager__num.is-active { background: var(--tm-accent-bg); color: var(--tm-accent-fg); border-color: transparent; }

/* live update: a row that just arrived gets the same --tm-dur-morph fading highlight
   as a KPI value (ds-stat-card tmKpiFlash) — colour only, no motion, nothing
   else in the row shifts. Off entirely under prefers-reduced-motion (the
   .tm-ds * rule in ds-primitives.css already zeroes animation-duration). */
@keyframes tmLiveRowFlash {
  from { background-color: var(--tm-accent-bg); }
  to   { background-color: transparent; }
}
.tm-ds .tm-live-page .tm-live-tbl tbody tr.is-new { animation: tmLiveRowFlash var(--tm-dur-morph) var(--tm-ease-out) 1; }

/* 2026-09-13 (sert lint r7): tur şeridi → grafik satırı 48 px (24 sayfa + 24 legacy iç boşluk) → 24 */
.tm-ds .tm-live-page .tm-live-main-grid { padding: 0; }
.tm-ds .tm-live-page .tm-live-main-grid__content { margin: 0; padding: 0; }
/* donut kartı (4/12, ~300 px) saatlik akış kartıyla aynı boyda (satır hizası): halka üstte, legend altta tam genişlik,
   içerik kartın boyuna yayılır — yan yana sıkışan legend ("p 8", "%1") ve 291 px boş alt kalmaz */
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 .ch-body { display: flex; flex-direction: column; }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 .ch-mount { flex: 1 1 auto; display: flex; }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 .ch-donut-wrap { flex: 1 1 auto; flex-direction: column; flex-wrap: nowrap; align-items: center; justify-content: space-between; gap: var(--tm-space-4); }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 .ch-donut-wrap svg.ch-donut { width: 200px; height: 200px; max-width: 100%; }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 .ch-donut-wrap .ch-legend { width: 100%; max-width: none; flex: 0 0 auto; }

/* hourly chart meta (legend + totals): a plain caption row, not a tinted box (reference chart cards carry only a
   segmented control and the plot) */
.tm-ds .tm-live-page .tm-live-hourly-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--tm-space-2) var(--tm-space-6); padding: 0; margin: 0; background: transparent; border: 0; border-radius: 0; box-shadow: none; font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); color: var(--tm-text-secondary); }
.tm-ds .tm-live-page .tm-live-hourly-meta[hidden] { display: none; }
.tm-ds .tm-live-page .tm-live-hourly-legend { display: flex; gap: var(--tm-space-4); align-items: center; }
.tm-ds .tm-live-page .tm-live-hourly-legend__item { display: inline-flex; align-items: center; gap: var(--tm-space-2); color: var(--tm-text-secondary); font-weight: var(--tm-weight-medium); }
.tm-ds .tm-live-page .tm-live-hourly-legend__swatch { width: 14px; height: 2px; border-radius: var(--tm-radius-full); background: var(--tm-chart-1); display: inline-block; }
.tm-ds .tm-live-page .tm-live-hourly-legend__swatch.is-baseline { background: var(--tm-border-strong); }
.tm-ds .tm-live-page .tm-live-hourly-stats { display: flex; flex-wrap: wrap; gap: var(--tm-space-2) var(--tm-space-4); margin-left: auto; color: var(--tm-text-muted); font-family: var(--tm-font-sans); }
.tm-ds .tm-live-page .tm-live-hourly-stats strong, .tm-ds .tm-live-page .tm-live-hourly-stats b { color: var(--tm-text-primary); font-weight: var(--tm-weight-semibold); font-family: var(--tm-font-sans); }

/* 2026-09-13 (kullanıcı: "şeritteki elemanlar niye farklı boyutlarda, KPI üstünde niye bu kadar boşluk"):
   üst şeritteki her kontrol 32 px, aynı yarıçap, aynı hairline; nabız çipleri de aynı kutu; şerit → KPI 24 px. */
.tm-ds .tm-live-page .tm-live-header { gap: var(--tm-space-2) var(--tm-space-6); }
.tm-ds .tm-live-page .tm-live-stat,
.tm-ds .tm-live-page .tm-live-status,
.tm-ds .tm-live-page .tm-live-select,
.tm-ds .tm-live-page .tm-live-platform-select,
.tm-ds .tm-live-page .tm-live-header .btn,
.tm-ds .tm-live-page .tm-live-controls > * { box-sizing: border-box; height: 32px; min-height: 32px; padding-top: 0; padding-bottom: 0; border-radius: var(--tm-radius-control); font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); }
.tm-ds .tm-live-page .tm-live-stat { padding-left: var(--tm-space-3); padding-right: var(--tm-space-3); border: 1px solid var(--tm-border); background: var(--tm-bg-surface); align-items: center; }
.tm-ds .tm-live-page .tm-live-status { padding-left: var(--tm-space-3); padding-right: var(--tm-space-3); }
.tm-ds .tm-live-page .tm-live-header .btn { display: inline-flex; align-items: center; gap: var(--tm-space-1); padding-left: var(--tm-space-3); padding-right: var(--tm-space-3); }
.tm-ds .tm-live-page .tm-live-pulseline { gap: var(--tm-space-2); }

/* 2026-09-13 prod geri bildirimi (kullanıcı: "KPI kartlarının üstünde çok fazla boşluk"): üst şeritteki 2 px dikey ayraç
   (`div.tmdr`) 68 px boyundaydı ve satırı 32 → 68 px'e itiyordu (18 px üst + 18 px alt hava). Ayraç gizli; şerit içerik boyunda.
   Fiyat kuralı kapsam uyarısı (`.tm-cov-alert`) Canlı sayfasından kaldırıldı (kullanıcı kararı; Fiyatlandırma sayfasında duruyor). */
.tm-ds .tm-live-page .tm-live-header > .tmdr { display: none; }
.tm-ds .tm-live-page .tm-cov-alert { display: none; }

/* 2026-09-13 prod (gerçek veri): ürün hücresindeki "Mağazada aç" bağlantısı üç satıra kırılıyordu (ikon / metin / dış-bağlantı ikonu).
   Tek satır, ürün adının yanında, ikonlar 12 px. Demo verisinde mağaza bağlantısı olmadığı için yerelde görünmüyordu.
   🔴 2026-10-07 (kullanıcı kararı, ekran görüntüsüyle bildirildi — İKİ TUR):
   ① "Satın al" dolu-mavi, "Mağazada aç" çıplak linkti — özel renk/boyut kuralları
   (eski `.tm-live-product__go` / `--buy`) buradan KALDIRILDI.
   ② İlk düzeltme ikisine `tm-btn--primary`/`tm-btn--ghost` verdi (hâlâ renk ayrımı
   vardı) — kullanıcı "ikisi de AYNI stil" derken BİREBİR aynı sınıfı kastetti.
   İkisi artık TIPATIP AYNI `class` dizgesini taşıyor (`tm-btn tm-btn--ghost
   tm-btn--sm tm-live-product__go`, bkz. dashboard-canli-init.js) — dolu renk YOK,
   hangisinin "satın al" olduğu yalnız `data-tm-satin-al` özniteliğinden anlaşılır.
   Bu dosyada hiçbir renk/buton-stili tanımı YOK; yalnız grup hizalaması (ürün
   adından ayrı, hücrenin sağında) ve ikon/etiket boyutu kaldı. Grup:
   `tm-live-product__actions` (static/js/dashboard/dashboard-canli-init.js —
   buyBtn + goLink burada sarılır). */
.tm-ds .tm-live-page .tm-live-product__actions { display: inline-flex; align-items: center; gap: var(--tm-space-2); margin-left: auto; flex-shrink: 0; }
.tm-ds .tm-live-page .tm-live-product__go-icon,
.tm-ds .tm-live-page .tm-live-product__go-ext { width: 12px; height: 12px; flex-shrink: 0; }
.tm-ds .tm-live-page .tm-live-product__go-label { white-space: nowrap; }
.tm-ds .tm-live-page td[data-cell="product"] > *, .tm-ds .tm-live-page .tm-live-product { display: inline-flex; align-items: center; gap: var(--tm-space-2); min-width: 0; max-width: 100%; }


/* ═══ Pazaryeri kırılımı — donut altındaki boşluğun doldurulması (2026-09-17).
   Kullanıcı: "bu alan çok boş ve kötü duruyor." Donut YALNIZ sipariş ADEDİ payını
   gösteriyordu; "hangi pazaryeri para kazandırıyor" cevapsızdı.

   🔴 Bu blok donut'un KENDİ legend'ini GİZLER: satırlar onun yerine geçer.
   İlk denemede ikisi birden duruyordu → aynı kartta iki platform listesi, kart
   ~950px'e uzadı (boşluktan daha kötü). Satırlar legend'in verdiği her şeyi
   (ad · adet · pay) veriyor, üstüne ciro/kâr/çubuk ekliyor. ═══ */
.tm-ds .tm-live-page #tmLivePlatformVanilla .ch-legend { display: none; }

.tm-ds .tm-live-page .tm-live-plat {
  display: flex;
  flex-direction: column;
  gap: var(--tm-space-3);
  margin-top: var(--tm-space-3);
  padding-top: var(--tm-space-3);
  border-top: 1px solid var(--tm-border);
}
.tm-ds .tm-live-page .tm-live-plat[hidden] { display: none; }
.tm-ds .tm-live-page .tm-live-plat__row { display: flex; flex-direction: column; gap: 3px; }
.tm-ds .tm-live-page .tm-live-plat__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--tm-space-2); min-width: 0;
}
.tm-ds .tm-live-page .tm-live-plat__name {
  display: inline-flex; align-items: center; gap: var(--tm-space-2);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--tm-type-body); color: var(--tm-text-primary);
}
.tm-ds .tm-live-page .tm-live-plat__dot {
  width: 8px; height: 8px; flex: 0 0 auto; border-radius: var(--tm-radius-full);
  background: var(--tm-text-muted);
}
.tm-ds .tm-live-page .tm-live-plat__rev {
  font-variant-numeric: tabular-nums; font-weight: var(--tm-weight-semibold);
  font-size: var(--tm-type-body); color: var(--tm-text-primary); flex-shrink: 0;
}
/* Çubuk: ray + dolgu. Dolgu rengi donut diliminin rengiyle AYNI (JS'ten inline). */
.tm-ds .tm-live-page .tm-live-plat__bar {
  height: 5px; border-radius: var(--tm-radius-full);
  background: var(--tm-surface-sunken); overflow: hidden;
}
.tm-ds .tm-live-page .tm-live-plat__bar > span {
  display: block; height: 100%; border-radius: inherit; background: var(--tm-text-muted);
}
.tm-ds .tm-live-page .tm-live-plat__meta {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 2px var(--tm-space-2);
  font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh);
  color: var(--tm-text-secondary); font-variant-numeric: tabular-nums;
}
.tm-ds .tm-live-page .tm-live-plat__meta .tm-cell-pos { color: var(--tm-success-fg); font-weight: var(--tm-weight-semibold); }
.tm-ds .tm-live-page .tm-live-plat__meta .tm-cell-neg { color: var(--tm-danger-fg); font-weight: var(--tm-weight-semibold); }
.tm-ds .tm-live-page .tm-live-plat__share { color: var(--tm-text-primary); font-weight: var(--tm-weight-semibold); }
/* Adet payı ↔ ciro payı ayrışmasının tek kelimelik özeti. */
.tm-ds .tm-live-page .tm-live-plat__note {
  padding: 0 var(--tm-space-2); border-radius: var(--tm-radius-full);
  background: var(--tm-accent-bg); color: var(--tm-accent-fg);
  font-weight: var(--tm-weight-semibold);
}

/* ═══ SİPARİŞ TABLOSU — MOBİL YIĞILMIŞ KART (2026-09-18 görsel iyileştirme) ═══════
   ds-live.css AKTİF .tm-ds bundle'ı tabloyu table-layout:fixed + 8 sabit-genişlik kolonla
   çiziyor (~610px) → ≤560px'te yatay-scroll'da Tutar/Net Kâr/Marj/Durum ekran dışı kalıyordu.
   (Legacy live-dashboard.css'teki kart düzeni bu sayfada INERT — DS bundle kazanıyor.) Hücrelerdeki
   mevcut data-cell attribute'ları etiket olur; #id specificity nth-child sabit-genişlikleri ezer. */
@media (max-width: 560px){
  .tm-ds .tm-live-page .tm-live-orders-card .tm-table-scroll{ overflow: visible; padding: 0; }
  .tm-ds .tm-live-page #tmLiveTable{ table-layout: auto; }
  .tm-ds .tm-live-page #tmLiveTable thead{ display: none; }
  .tm-ds .tm-live-page #tmLiveTable,
  .tm-ds .tm-live-page #tmLiveTable tbody,
  .tm-ds .tm-live-page #tmLiveTable tr,
  .tm-ds .tm-live-page #tmLiveTable td{ display: block; width: auto; }
  .tm-ds .tm-live-page #tmLiveTable tr{
    border:1px solid var(--tm-border,#e5e7eb); border-radius:12px; padding:8px 12px;
    margin-bottom:10px; background:var(--tm-bg-surface,#fff);
  }
  .tm-ds .tm-live-page #tmLiveTable td{
    border:none; padding:5px 0; display:flex; align-items:center; justify-content:space-between;
    gap:12px; text-align:right; white-space:normal; overflow:visible;
  }
  .tm-ds .tm-live-page #tmLiveTable td::before{
    content: attr(data-cell); color:var(--tm-text-muted,#64748b); font-size:11px; font-weight:600;
    text-transform:uppercase; letter-spacing:.03em; text-align:left; flex:0 0 auto;
  }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="time"]::before{ content:"Saat"; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="pill"]::before{ content:"Pazaryeri"; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="order"]::before{ content:"Sipariş No"; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="product"]::before{ content:"Ürün"; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="price"]::before{ content:"Tutar"; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="profit"]::before{ content:"Net Kâr"; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="margin"]::before{ content:"Marj"; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="status"]::before{ content:"Durum"; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="product"]{ flex-direction:column; align-items:flex-start; text-align:left; gap:3px; }
  /* 2026-10-05: "Satın al" + "Mağazada aç" eklenince ürün adı sıfıra eziliyordu → kart içinde satıra kırılır. */
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="product"]{ height:auto; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="product"] .tm-live-product{ flex-wrap:wrap; row-gap:6px; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="product"] .tm-live-product__name{ flex:1 1 60%; max-width:none; }
  .tm-ds .tm-live-page #tmLiveTable td[colspan]{ display:block; text-align:center; }
  .tm-ds .tm-live-page #tmLiveTable td[colspan]::before{ content:""; }
  .tm-ds .tm-live-page #tmLiveTable tr.is-skel td::before{ content:""; }
}

/* ═══ 2026-10-03 KULLANILABİLİRLİK DÜZELTMELERİ (kullanıcı: "görsel olarak tutarlı ama kullanıcı için çok
   kullanışlı değil"). Ölçüm gerçek sayfada (gorsel_sunucu canli-performans, 1440 + 390):
   ① tablo: ürün adı 22ch'te kesiliyordu (1440'ta bile "Bambu Kesme Tahtası B…"), boş alan varken
   ② pazaryeri kartı ~700px, saatlik akış ~490px → sağda ~200px boşluk (grafik boyu: tm-vanilla-dashboard-charts.css)
   ③ mobil sipariş kartı 8 etiketli satır (~450px/sipariş) → 10 sipariş ≈ 4.500px kaydırma
   DS kuralları (token boşluk, !important yok, renk sabiti yok) bu blokta korunur; başka stili EZMESİ gereken
   üç kural (KPI ızgarası, seçici genişliği, kart arka planı) static/css/v2/components/live-dashboard.css'te. ═══ */

/* ① ürün adı kolonun kalanını kullanır */
.tm-ds .tm-live-page .tm-live-product { min-width: 0; }
.tm-ds .tm-live-page .tm-live-product__name { max-width: none; flex: 1 1 auto; min-width: 0; }

/* ② pazaryeri satırları sıkı */
.tm-ds .tm-live-page .tm-live-plat { gap: var(--tm-space-2); padding-top: var(--tm-space-2); }
.tm-ds .tm-live-page .tm-live-plat__row { gap: var(--tm-space-1); }
.tm-ds .tm-live-page .tm-live-plat__bar { height: 4px; }
.tm-ds .tm-live-page .tm-live-plat__meta { flex-wrap: nowrap; white-space: nowrap; overflow: hidden; }

/* ③ mobil */
@media (max-width: 560px){
  .tm-ds .tm-live-page .tm-live-controls { flex-wrap: nowrap; width: 100%; }
  .tm-ds .tm-live-page .tm-live-status { flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
  .tm-ds .tm-live-page .tm-live-pulseline { display: grid; grid-template-columns: 1fr 1fr; gap: var(--tm-space-2); width: 100%; }
  .tm-ds .tm-live-page .tm-live-pulseline .tm-live-stat:first-child { grid-column: 1 / -1; }
  .tm-ds .tm-live-page .tm-live-stat { min-width: 0; overflow: hidden; }

  /* Sipariş kartı: saat·pazaryeri·durum / ürün / sipariş no·tutar·kâr·marj */
  /* 2026-10-09: ADET ve AKSİYON hücreleri eklendi → iki yeni alan. `actions` kendi
     satırında ve TAM GENİŞLİK (kullanıcı isteği); `qty` de kendi satırında,
     etiket solda · sayı sağda. Alan adı yazılmayan bir
     hücre ızgaraya "auto-placement" ile girip kartı bozardı — ikisi de adlandırıldı. */
  .tm-ds .tm-live-page #tmLiveTable tr:not(.is-skel){
    display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto auto;
    grid-template-areas: "time pill pill pill status" "product product product product product"
                         "order order order order order"
                         "qty qty price profit margin"
                         "actions actions actions actions actions";
    column-gap: var(--tm-space-3); row-gap: var(--tm-space-1); padding: var(--tm-space-3);
  }
  .tm-ds .tm-live-page #tmLiveTable tr:not(.is-skel) td{ padding: 0; justify-content: flex-start; text-align: left; }
  .tm-ds .tm-live-page #tmLiveTable tr:not(.is-skel) td::before{ content: none; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="time"]{ grid-area: time; font-size: 12px; color: var(--tm-text-muted); }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="pill"]{ grid-area: pill; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="status"]{ grid-area: status; justify-content: flex-end; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="product"]{ grid-area: product; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="product"] .tm-live-product{ width: 100%; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="product"] .tm-live-product__name{ white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="order"]{ grid-area: order; font-size: 11px; color: var(--tm-text-muted); align-self: end; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; min-width: 0; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="price"],
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="profit"],
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="margin"]{ flex-direction: column; align-items: flex-end; text-align: right; font-variant-numeric: tabular-nums; font-size: var(--tm-type-caption); }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="price"]{ grid-area: price; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="profit"]{ grid-area: profit; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="margin"]{ grid-area: margin; }
  .tm-ds .tm-live-page #tmLiveTable tr:not(.is-skel) td[data-cell="price"]::before,
  .tm-ds .tm-live-page #tmLiveTable tr:not(.is-skel) td[data-cell="profit"]::before,
  .tm-ds .tm-live-page #tmLiveTable tr:not(.is-skel) td[data-cell="margin"]::before{
    display: block; font-size: var(--tm-type-micro); font-weight: 600; letter-spacing: .03em;
    text-transform: uppercase; color: var(--tm-text-muted);
  }
  .tm-ds .tm-live-page #tmLiveTable tr:not(.is-skel) td[data-cell="price"]::before{ content:"Tutar"; }
  .tm-ds .tm-live-page #tmLiveTable tr:not(.is-skel) td[data-cell="profit"]::before{ content:"Net Kâr"; }
  .tm-ds .tm-live-page #tmLiveTable tr:not(.is-skel) td[data-cell="margin"]::before{ content:"Marj"; }
  /* ADET: diğer üç sayıyla aynı kademe ve aynı etiket biçimi. */
  /* ADET, kartta diğer üç sayıyla AYNI satırda ve AYNI biçimde (etiket üstte, değer altta).
     Önce kendi tam-genişlik satırındaydı; o düzende SİPARİŞ NO iki sütuna sıkışıp kesiliyordu
     (ölçüldü 390px: `order` hücresi taşıyor). Sipariş no tam satıra geri alındı, ADET
     sayı satırına katıldı — ikisi de kesilmiyor. */
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="qty"]{ grid-area: qty; flex-direction: column; align-items: flex-end; text-align: right; font-variant-numeric: tabular-nums; font-size: var(--tm-type-caption); }
  .tm-ds .tm-live-page #tmLiveTable tr:not(.is-skel) td[data-cell="qty"]::before{
    display: block; font-size: var(--tm-type-micro); font-weight: 600; letter-spacing: .03em;
    text-transform: uppercase; color: var(--tm-text-muted); content: "Adet";
  }
  /* AKSİYON: kartın altında tam genişlik; iki düğme eşit pay alır (dokunma hedefi 36px).
     Masaüstündeki "ikon-only" kısaltması burada GEÇERSİZ — mobilde etiket şart,
     tek başına ikonun ne yaptığı hover ipucu olmadan anlaşılmaz. */
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="actions"]{ grid-area: actions; padding-top: var(--tm-space-2); }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="actions"] .tm-live-rowact{ display: flex; width: 100%; gap: var(--tm-space-2); }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="actions"] .tm-live-rowact__btn{ flex: 1 1 0; justify-content: center; min-height: 36px; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="actions"] .tm-live-rowact__lbl{ display: inline; }
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="actions"] .tm-live-rowact__bos{ display: none; }
  /* Ürün hücresi mobilde: ad 2 satır kutu, kod altında tek satır. */
  .tm-ds .tm-live-page #tmLiveTable td[data-cell="product"] .tm-live-product__txt{ width: 100%; }
}

/* ====================================================================
   2026-10-09 — Canlı Performans düzen + tipografi (kullanıcı isteği)
   ==================================================================== */

/* ① KPI SAYISI ÖLÇEĞE DÖNÜYOR. dashboard-vanilla.css:388 bu sayfaya özel bir
   `clamp(20px, 1.55vw, 26px)` yazıyor; seçici (0,3,0) olduğu için ds-stat-card.css’in
   `.tm-ds .kpi-value` (0,2,0) token kuralını — min-width:1440 medyası dahil — EZİYOR.
   ÖLÇÜLDÜ (1440px): Canlı 22,32px (1,55vw), Genel Bakış ise aynı kart ailesinde 24px.
   Seçici `.tm-live-page`-kapsamlı olduğu için Genel Bakış hiç eşleşmiyor → iki sayfa
   aynı rol için iki farklı boy. Burada (0,4,0) ile token'a geri dönülüyor: <1440 20/28,
   ≥1440 24/32 — yani clamp’in alt ucu zaten buydu, değişen yalnız akışkanlık ve üst uç.
   (ds-tokens.css’deki "5’li destede 24 taşırdı" notu display-sm’i savunur; o not
   <1440 içindir ve token zaten orada 20 diyor.) */
.tm-ds .tm-live-page .tm-live-kpi-grid .kpi-value {
  font-size: var(--tm-type-display-sm);
  line-height: var(--tm-type-display-sm-lh);
}
@media (min-width: 1440px) {
  .tm-ds .tm-live-page .tm-live-kpi-grid .kpi-value {
    font-size: var(--tm-type-display);
    line-height: var(--tm-type-display-lh);
  }
}

/* ② Platform kartı: halka kalan boşluğa büyür (sabit 200px kuralı
   tm-vanilla-dashboard-charts.css’in id’li 140px kuralı tarafından ezildiği için ÖLÜYDÜ
   — ölçüm 2026-10-09: gerçek halka 140×140). Artık iki pakette de aynı davranış.
   `justify-content: space-between` kaldırıldı: halkayı kartın tam ortasına çivileyip
   listeyi dibe iten kural oydu. */
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 .ch-donut-wrap {
  justify-content: center; height: 100%;
}
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 .ch-donut-wrap svg.ch-donut {
  width: auto; height: 100%; max-height: min(240px, 100%); min-height: 0; max-width: 100%;
}
/* Mount’un tabanı kartın doğal yüksekliğini belirler — 110 (bkz. tm-vanilla…css açıklaması). */
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 > .ch-mount {
  flex: 1 1 110px; min-height: 110px; overflow: hidden;
}

/* ③ Yeni parçaların token'lı sürümü (tm-vanilla’daki id’li kurallarla AYNI değer).
   Satır/başlık/yıldız renkleri DS metin kademelerinden gelir, düz hex değil. */
.tm-ds .tm-live-page .tm-live-plat__cols {
  border-bottom-color: var(--tm-border); color: var(--tm-text-muted);
  font-size: var(--tm-type-micro); line-height: var(--tm-type-micro-lh);
}

/* ④ Saatlik Akış özet satırı: ana rakam başlık kademesine çıkar (metin aynı). */
.tm-ds .tm-live-page .tm-live-hourly-stats .tm-live-hourly-stat { display: inline-flex; align-items: baseline; gap: var(--tm-space-1, 4px); }
.tm-ds .tm-live-page .tm-live-hourly-stats .tm-live-hourly-stat.is-ana > strong {
  font-size: var(--tm-type-title); line-height: var(--tm-type-title-lh);
}

/* ⑤ Koyu temada özet şeridinin ARKA PLANI: tm-vanilla-dashboard-charts.css’teki
   `html.dark-mode .tm-live-hourly-panel .tm-live-hourly-meta` (0,3,1) kuralları, DS’in
   `.tm-ds .tm-live-page .tm-live-hourly-meta` (0,3,0) düz-zemin kuralını eziyordu → açık temada
   çerçevesiz bir satır, koyu temada gradyanlı bir kutu görünüyordu (aynı bileşen, iki farklı
   kimlik — ekran görüntüsünde açıkça görülüyor). İkisi de düz zemine çekildi (2026-10-09). */
html.dark-mode .tm-ds .tm-live-page .tm-live-hourly-panel .tm-live-hourly-meta,
body.dark-mode .tm-ds .tm-live-page .tm-live-hourly-panel .tm-live-hourly-meta {
  background: transparent; border: 0; padding: 0; box-shadow: none;
}

/* ====================================================================
   2026-10-09 — "Bugünün Siparişleri" tablosu: ADET sütunu + AKSİYON sütunu +
   iki satırlı ürün hücresi (kullanıcı isteği)
   -------------------------------------------------------------------
   SÜTUN BÜTÇESİ YENİDEN KURULDU. Tablo `table-layout: fixed` + nth-child genişlikler
   ile çiziliyor; iki sütun eklenince ESKİ nth-child numaraları KAYAR (5=Tutar artık
   5=Adet olur) — bu yüzden aşağıdaki blok eski 1-8 kurallarını 1-10 olarak YENİDEN
   yazıyor; yukarıdaki r4/polish kuralları aynı özgüllükte ama DAHA ERKEN olduğu için
   burada eziliyor. Eski genişlik gerekçeleri (Saat 60 "19:16" kesiliyordu · Pazaryeri
   108 "Hepsiburada" kesiliyordu) KORUNDU.
     1 Saat 60 · 2 Pazaryeri 108 · 3 Sipariş No 124 · 4 Ürün auto · 5 Adet 54
     6 Tutar 86 · 7 Net Kâr 80 · 8 Marj 58 · 9 Durum 88 · 10 Aksiyon 168 (<1400: 76)
   ==================================================================== */
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(1),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(1) { width: 60px; }
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(2),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(2) { width: 108px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(3),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(3) { width: 124px; }
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(4),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(4) { width: auto; overflow: hidden; }
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(5),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(5) { width: 48px; }
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(6),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(6) { width: 86px; }
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(7),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(7) { width: 86px; }
/* MARJ 68: "-%%22,8" 65px istiyor (ölçüldü 1440) — 60’da son rakam kesiliyordu. */
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(8),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(8) { width: 68px; }
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(10),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(10) { width: 84px; }

/* Tutar · Net Kâr · Marj · Adet: sağa hizalı, tabular-nums (rakamlar alt alta tutsun). */
.tm-ds .tm-live-page .tm-live-tbl td[data-cell="qty"],
.tm-ds .tm-live-page .tm-live-tbl th.num { text-align: right; font-variant-numeric: tabular-nums; }
.tm-ds .tm-live-page .tm-live-tbl td[data-cell="qty"] { color: var(--tm-text-secondary); }

/* ÜRÜN hücresi iki satır: ad (1 satır, ellipsis) + barkod/kod (küçük, mono). */
.tm-ds .tm-live-page .tm-live-product__txt { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; gap: 1px; }
.tm-ds .tm-live-page .tm-live-product__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: none; }
.tm-ds .tm-live-page .tm-live-product__kod {
  font-family: var(--tm-font-mono); font-size: var(--tm-type-micro); line-height: var(--tm-type-micro-lh);
  color: var(--tm-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tm-ds .tm-live-page .tm-live-mp-badge {
  display: inline-flex; align-items: center; gap: var(--tm-space-1); flex-shrink: 0;
  height: 20px; padding: 0 var(--tm-space-2); border-radius: var(--tm-radius-control);
  background: var(--tm-bg-subtle); color: var(--tm-text-secondary);
  font-size: var(--tm-type-micro); line-height: var(--tm-type-micro-lh); font-weight: var(--tm-weight-medium);
  white-space: nowrap;
}
.tm-ds .tm-live-page .tm-live-mp-badge [data-lucide] { width: 11px; height: 11px; }

/* AKSİYON hücresi: iki düğme sağa hizalı. Satır tıklanınca detay çekmecesi açılıyor;
   düğmelerin kendi işleri var → hücrede imleç varsayılan, satır "pointer" değil. */
.tm-ds .tm-live-page .tm-live-tbl td[data-cell="actions"] { text-align: right; }
.tm-ds .tm-live-page .tm-live-rowact { display: inline-flex; align-items: center; gap: var(--tm-space-2); justify-content: flex-end; }
.tm-ds .tm-live-page .tm-live-rowact__bos { color: var(--tm-text-muted); }
.tm-ds .tm-live-page .tm-live-rowact__btn { flex-shrink: 0; }
.tm-ds .tm-live-page .tm-live-rowact__ic,
.tm-ds .tm-live-page .tm-live-rowact__ext { width: 12px; height: 12px; flex-shrink: 0; }
.tm-ds .tm-live-page .tm-live-rowact__lbl { white-space: nowrap; }

/* <1400px: etiketler düşer, ikon-only kalır — 168px’lik sütun 1280’de ÜrÜN’ü 100px’in
   altına düşürüyordu (ölçüm 2026-10-09). Erişilebilirlik korunur: her iki düğmede de
   `title` + `aria-label` zaten var (dashboard-canli-init.js), etiket yalnız GÖRSEL. */
/* DURUM 88’e geri: 80’e kırpınca "Geçerli" rozeti taşıyordu (ölçüldü, her genişlikte). */
.tm-ds .tm-live-page .tm-live-tbl th:nth-child(9),
.tm-ds .tm-live-page .tm-live-tbl td:nth-child(9) { width: 88px; }
/* ≥1600: iki etiketli düğme + dış-bağlantı ikonu 221px istiyor → 232. */
@media (min-width: 1600px) {
  .tm-ds .tm-live-page .tm-live-tbl th:nth-child(10),
  .tm-ds .tm-live-page .tm-live-tbl td:nth-child(10) { width: 232px; }
}
/* <1400: SİPARİŞ NO 184 → 120. 184, Amazon’un 19 karakterlik numarası içindi (2026-10-05);
   dar ekranda o 64px ÜRÜN ADINDAN çalınıyor (ölçüldü 1280: ad 40px). Numara kesilince
   `title` tam değeri taşır ve satır tıklanınca detay çekmecesi zaten tam numarayı yazıyor. */
@media (max-width: 1399.98px) {
  .tm-ds .tm-live-page .tm-live-tbl th:nth-child(3),
  .tm-ds .tm-live-page .tm-live-tbl td:nth-child(3) { width: 120px; }
}
/* <1180: 10 sütun artık SİĞMİYOR. ÖLÇÜLDÜ (1100, tablo 772px): sabitler 716 → ÜRÜN 56px,
   ad 0px — hücre boş görünüyordu. Burada ezmek yerine KAYDIRMAYA geçiyoruz: sarmalayıcı
   `.tm-table-scroll` zaten `overflow-x:auto` (ui-polish-2026-06-04.css:109), tabloya taban
   genişlik verilir. 2026-09-13’teki "fixed layout" kararı "Durum kesiliyordu" diye alınmıştı;
   taban-genişlikli kaydırmada HİÇBİR ŞEY kesilmiyor, o gerekçe karşılanıyor.
   ≤560px zaten kart düzenine geçiyor (ayrı blok), bu aralık yalnız tablet/dar masaüstü. */
@media (min-width: 560.02px) and (max-width: 1179.98px) {
  .tm-ds .tm-live-page .tm-live-tbl { min-width: 940px; }
}
@media (max-width: 1599.98px) {
  .tm-ds .tm-live-page .tm-live-rowact__lbl,
  .tm-ds .tm-live-page .tm-live-rowact__ext,
  .tm-ds .tm-live-page .tm-live-cost-badge__lbl { display: none; }
  .tm-ds .tm-live-page .tm-live-rowact__btn { padding-left: var(--tm-space-2); padding-right: var(--tm-space-2); }
  .tm-ds .tm-live-page .tm-live-cost-badge { padding: 0 var(--tm-space-1); }
}

/* ═══ 2026-10-10 — YOĞUNLUK + GRAFİK TASARIMI (kullanıcı: "konteynerler, grafikler çok büyük, kaba; KPI ile
   grafik arasında niye boşluk var; grafik ve pasta tasarımlarını iyileştir, daha yoğun ve kullanışlı").
   Ekran görüntüsü incelemesi (1650×935, QA senaryosu) — tespitler:
   ① KPI kartı 160 px, değer 24 px; kart gövdesinin yarısı boş kıvılcım kutusu.
   ② KPI ile grafik satırı arasında 58 px boşluk: dashboard-vanilla.css `.tm-kpi-row{min-height:150px}`
      (kartlar 108'e inince satır 150'de kaldı) + ana ızgara margin-top 16.
   ③ Saatlik Akış: başlık 26 px + alt yazı + 2. satırda legend/istatistik → grafik 130 px aşağıda başlıyor;
      "Bugün toplam" gibi asıl sayı 12 px küçük metin, kullanıcı aramak zorunda.
   ④ Platform kartı: tek dilimli 240 px halka ("4 Sipariş") kartın yarısı; bilgi (satırlar, yıldız) altına itilmiş.
   Çözüm (yalnız bu sayfa; DOM/JS aynı; duman testi canli-duzen-duman-2026-10-09.cjs sözleşmesi korunur):
   KPI 108 px + değer 20 px; boşluk 58 → 12; Saatlik Akış başlığı tek satır + istatistik şeridi "hero"
   (Bugün toplam 20 px, kıyaslar yanında, legend sağda), grafik 260; Platform kartı 2 sütun: halka 120 px
   SOLDA, pazaryeri satırları SAĞINDA, yıldız altta tam genişlik. ═══ */
/* 2026-10-11 (kullanıcı ekran görüntüsü): 16 px'lik kıvılcım kartın alt
   kenarına yapışık, uç noktası kenarda kesik duruyordu. Kart 112 → 120,
   kıvılcım 16 → 24 px; alt metin (`.kpi-vs`) artık çoğunlukla tek ortak
   notta (`#tmLiveKpiNote`) olduğu için kart içi satır sayısı artmadı. */
.tm-ds .tm-live-page { --tm-dash-sparkline-h: 24px; --tm-dash-kpi-h: 120px; }
/* Kıvılcım yüksekliği id-özgüllüklü kuralla sabitlenmiş (tm-vanilla-dashboard-charts.css ≤560 bloğu + DS);
   token tek başına ezilmiyordu → ölçülen 56 px, kart (overflow:hidden) altından kırpılıyordu (QA BLOK-3).
   Kart bütçesi: 12 pad + 24 baş + 58 gövde + 16 kıvılcım = 110 ≤ 112. */
html body .tm-ds .tm-live-page .tm-live-kpi-grid .kpi-chart { height: var(--tm-dash-sparkline-h) !important; }
/* İki grafik kartı AYNI boyda (kullanıcı 2026-09-24) — eski eşitlik saatlik yüksekliğin (450) platform kartının
   doğal boyuna denk gelmesine dayanıyordu; grafik 240'a inince iki kart da satıra GERİLİR (align-self: stretch),
   satır = uzun olanın boyu (zengin veride platform, az veride saatlik). Grafik üstte sabit 240; artan boşluk altta. */
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.tm-live-hourly-panel { align-self: stretch; }
html body .tm-ds .tm-live-page .tm-kpi-row { min-height: 0 !important; height: auto !important; margin-bottom: 0 !important; }   /* ölçüldü: satır 150 px'te kalıyordu (kartlar 108) → 42 px ölü boşluk */
html body .tm-ds .tm-live-page .tm-live-main-grid { margin-top: var(--tm-space-3) !important; row-gap: var(--tm-space-3); }
/* ① KPI kartı */
.tm-ds .tm-live-page .tm-live-kpi-grid .kpi-card { padding-top: var(--tm-space-3); }
.tm-ds .tm-live-page .tm-live-kpi-grid .kpi-value { font-size: var(--tm-type-display-sm); line-height: var(--tm-type-display-sm-lh); }
@media (min-width: 1440px) { .tm-ds .tm-live-page .tm-live-kpi-grid .kpi-value { font-size: var(--tm-type-display-sm); line-height: var(--tm-type-display-sm-lh); } }
.tm-ds .tm-live-page .tm-live-kpi-grid .kpi-body { padding-top: 0; }
.tm-ds .tm-live-page .tm-live-kpi-grid .kpi-deltarow { padding-top: 0; min-height: 0; }
.tm-ds .tm-live-page .tm-live-kpi-grid .kpi-deltarow .kpi-vs { font-size: var(--tm-type-micro); line-height: var(--tm-type-micro-lh, 14px); }
/* Grafik kartları ortak: iç pay 12/16, başlık 16 px tek satır, alt yazı küçük */
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel { padding: var(--tm-space-3) var(--tm-space-4) var(--tm-space-3); }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live .ch-head { margin-bottom: var(--tm-space-2); align-items: center; }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live .ch-h3 { font-size: var(--tm-type-heading); line-height: 1.25; font-weight: var(--tm-weight-semibold); }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live .ch-sub { font-size: var(--tm-type-micro); margin-top: 1px; }
/* ③ Saatlik Akış: istatistik şeridi = hero (asıl sayı büyük, kıyaslar yanında, legend sağda) */
.tm-ds .tm-live-page .tm-live-hourly-meta { flex-wrap: nowrap; align-items: baseline; gap: var(--tm-space-4); margin: 0 0 var(--tm-space-1); padding-bottom: var(--tm-space-1); border-bottom: 1px solid var(--tm-border); }
.tm-ds .tm-live-page .tm-live-hourly-stats { order: 1; margin-left: 0; flex: 1 1 auto; align-items: baseline; gap: var(--tm-space-1) var(--tm-space-4); }
.tm-ds .tm-live-page .tm-live-hourly-legend { order: 2; flex: 0 0 auto; }
.tm-ds .tm-live-page .tm-live-hourly-stat.is-ana { display: inline-flex; align-items: baseline; gap: var(--tm-space-2); }
.tm-ds .tm-live-page .tm-live-hourly-stat.is-ana strong { font-weight: var(--tm-weight-bold); letter-spacing: -0.01em; }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live .ch-head { margin-bottom: var(--tm-space-1); }
/* ④ Platform kartı (2026-10-10, kullanıcı: "pie chart'ı büyüt, boş yer kalmasın, yerleşimi düzgün yap"):
   halka ÜSTTE ve büyük (160), satır listesi ALTINDA TAM GENİŞLİK. İki sütun denendi (halka solda 150) →
   satır sütunu 156 px'e düşüp 5 adın 4'ü kırpılıyordu (ölçüldü); tek sütunda satırlar ~370 px alıyor,
   kırpma 0 ve halka daha büyük. Satırlar kalan yüksekliği eşit paylaşır → alt boşluk kalmaz. */
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 { display: flex; flex-direction: column; }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 > .ch-mount { flex: 0 0 auto; min-height: 160px; display: flex; align-items: center; justify-content: center; margin-bottom: var(--tm-space-2); }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 .ch-donut-wrap { height: auto; justify-content: center; }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 .ch-donut-wrap svg.ch-donut { width: 160px; height: 160px; max-height: 160px; }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 .ch-donut-wrap svg.ch-donut .ch-donut-center-v { font-size: var(--tm-type-display-sm); }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 > .tm-live-plat__cols { flex: 0 0 auto; margin: 0; padding: 0 0 var(--tm-space-1); }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 > .tm-live-plat { flex: 1 1 auto; margin-top: 0; padding-top: 0; border-top: 0; gap: 0; justify-content: space-evenly; }
.tm-ds .tm-live-page .tm-live-plat__row { gap: 2px; }
.tm-ds .tm-live-page .tm-live-plat__bar { height: 3px; }
/* ≤1099: GERÇEKTEN tek sütun — halka üstte, liste altında tam genişlik. (Önceki hâli aynı iki-sütun
   şablonunu tekrar yazıyordu → 390 px'te ad/kâr kırpılıyordu; QA ölçümü 2026-10-10.) */
@media (max-width: 1099px) {
  .tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 .ch-donut-wrap svg.ch-donut { width: 150px; height: 150px; max-height: 150px; }
}

/* ═══ 2026-10-10 — GRAFİK + PLATFORM KARTI GÖRSEL TASARIMI (kullanıcı, tur 3: "grafik kullanışlı değil,
   platform dağılımı kaba duruyor, göze daha güzel görünmeli"). Çizim kodu (tm-charts.js) aynı; yalnız bu
   sayfada SVG/satır stilleri: ince-yuvarlak çizgi, sakin ızgara, okunur eksen, koyu araç ipucu; halka ince
   şerit + sessiz ray; pazaryeri satırları tek düzen (logo · ad · ciro / pay çubuğu · yüzde / adet · kâr). ═══ */
/* Saatlik Akış — çizgi & alan */
.tm-ds .tm-live-page #tmLiveHourlyFlow .ch-area-line { stroke-width: 2.25; stroke-linejoin: round; stroke-linecap: round; }
.tm-ds .tm-live-page #tmLiveHourlyFlow .ch-area-line.is-dashed { stroke: var(--tm-text-muted); stroke-width: 1.5; stroke-dasharray: 3 4; opacity: .85; }
.tm-ds .tm-live-page #tmLiveHourlyFlow .ch-grid-line { stroke: var(--tm-border); stroke-dasharray: none; opacity: .7; }
.tm-ds .tm-live-page #tmLiveHourlyFlow .ch-grid-line.zero { stroke: var(--tm-border-strong); opacity: 1; }
.tm-ds .tm-live-page #tmLiveHourlyFlow .ch-axis-ylabel,
.tm-ds .tm-live-page #tmLiveHourlyFlow .ch-bar-xlabel { font-family: var(--tm-font-sans); font-size: 11px; fill: var(--tm-text-muted); font-variant-numeric: tabular-nums; }
.tm-ds .tm-live-page #tmLiveHourlyFlow .ch-cross { stroke: var(--tm-text-muted); stroke-dasharray: 2 3; opacity: .7; }
.tm-ds .tm-live-page #tmLiveHourlyFlow .ch-cross-dot { stroke: var(--tm-surface); stroke-width: 2; }
.tm-ds .tm-live-page #tmLiveHourlyFlow .ch-live-end-dot { stroke-width: 2.5; }
.tm-ds .tm-live-page #tmLiveHourlyFlow .ch-tip { border-radius: 10px; padding: 8px 10px; box-shadow: 0 8px 24px rgba(2, 12, 34, .28); }
.tm-ds .tm-live-page #tmLiveHourlyFlow .ch-tip-row { font-size: 12px; gap: 8px; }
.tm-ds .tm-live-page .tm-live-hourly-legend__swatch { width: 16px; height: 2.5px; }
.tm-ds .tm-live-page .tm-live-hourly-legend__swatch.is-baseline { height: 0; border-top: 1.5px dashed var(--tm-text-muted); background: transparent; }
/* Platform halkası — ince şerit, sessiz ray, belirgin merkez */
.tm-ds .tm-live-page #tmLivePlatformVanilla svg.ch-donut > circle:first-child { stroke: var(--tm-surface-sunken); stroke-width: 12; }
.tm-ds .tm-live-page #tmLivePlatformVanilla .ch-donut-seg { stroke-width: 12; transition: stroke-width var(--tm-dur-fast) var(--tm-ease), opacity var(--tm-dur-fast) var(--tm-ease); }
.tm-ds .tm-live-page #tmLivePlatformVanilla .ch-donut-seg.dim { opacity: .35; }
.tm-ds .tm-live-page #tmLivePlatformVanilla .ch-donut-center-v { font-family: var(--tm-font-sans); font-size: var(--tm-type-display-sm); font-weight: 700; fill: var(--tm-text-primary); letter-spacing: -0.01em; }
.tm-ds .tm-live-page #tmLivePlatformVanilla .ch-donut-center-l { font-family: var(--tm-font-sans); font-size: var(--tm-type-micro); font-weight: 600; fill: var(--tm-text-muted); letter-spacing: .08em; text-transform: uppercase; }
/* Pazaryeri satırları — tek düzen, hairline ayırıcı */
.tm-ds .tm-live-page .tm-live-plat__cols { display: flex; justify-content: space-between; font-size: var(--tm-type-micro); font-weight: var(--tm-weight-semibold); letter-spacing: .08em; text-transform: uppercase; color: var(--tm-text-muted); padding: 0 0 4px; border-bottom: 1px solid var(--tm-border); }
.tm-ds .tm-live-page .tm-dashboard-ch-grid--live > .ch-panel.span-2 > .tm-live-plat { border-top: 0; padding-top: 0; gap: 0; }
.tm-ds .tm-live-page .tm-live-plat__row { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "head rev" "bar bar" "meta meta"; column-gap: var(--tm-space-3); row-gap: 3px; align-items: center; padding: 6px 0; border-bottom: 1px solid var(--tm-border); }
.tm-ds .tm-live-page .tm-live-plat__row:last-child { border-bottom: 0; }
.tm-ds .tm-live-page .tm-live-plat__head { display: contents; }
.tm-ds .tm-live-page .tm-live-plat__name { grid-area: head; font-size: var(--tm-type-body); line-height: var(--tm-type-body-lh); font-weight: var(--tm-weight-semibold); gap: 7px; min-width: 0; }
.tm-ds .tm-live-page .tm-live-plat__name .tm-pz-logo, .tm-ds .tm-live-page .tm-live-plat__name img { width: 18px; height: 18px; border-radius: 4px; flex: 0 0 auto; }
.tm-ds .tm-live-page .tm-live-plat__rev { grid-area: rev; font-size: var(--tm-type-body); line-height: var(--tm-type-body-lh); }
.tm-ds .tm-live-page .tm-live-plat__bar { grid-area: bar; height: 3px; background: var(--tm-surface-sunken); }
.tm-ds .tm-live-page .tm-live-plat__bar > span { opacity: .9; }
.tm-ds .tm-live-page .tm-live-plat__meta { grid-area: meta; justify-self: start; flex-wrap: wrap; gap: 0 6px; font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); color: var(--tm-text-muted); white-space: normal; min-width: 0; overflow: visible; }
.tm-ds .tm-live-page .tm-live-plat__meta > span + span::before { content: '·'; margin-right: 6px; color: var(--tm-border-strong); }
.tm-ds .tm-live-page .tm-live-plat__meta .tm-live-plat__note::before { content: none; }
.tm-ds .tm-live-page .tm-live-plat__note { font-size: var(--tm-type-micro); padding: 0 6px; line-height: 16px; }
.tm-ds .tm-live-page .tm-live-plat__row.is-top .tm-live-plat__name { color: var(--tm-text-primary); }
/* Bugünün yıldızı — sessiz zemin kartı */

/* Halkanın ORTA YAZILARI fare olaylarını yutmasın: merkeze yakın hover'da dilim vurgusu düşüyordu
   (ölçüldü: center-v elementi pointer'ı kesiyor). Metin zaten bilgi, hedef değil. */
.tm-ds .tm-live-page #tmLivePlatformVanilla .ch-donut-center-v,
.tm-ds .tm-live-page #tmLivePlatformVanilla .ch-donut-center-l { pointer-events: none; }

/* Halka ↔ satır karşılıklı vurgu (2026-10-10, kullanıcı): dilimin üstüne gelince eşleşen pazaryeri
   satırı öne çıkar, ötekiler soluklaşır; satırın üstüne gelince dilim kalınlaşır (JS dispatch). */
.tm-ds .tm-live-page .tm-live-plat__row { transition: background-color var(--tm-dur-fast) var(--tm-ease), opacity var(--tm-dur-fast) var(--tm-ease); border-radius: 6px; }
.tm-ds .tm-live-page .tm-live-plat__row.is-vurgu { background: var(--tm-surface-sunken); opacity: 1; }
.tm-ds .tm-live-page .tm-live-plat__row.is-sonuk { opacity: .42; }
.tm-ds .tm-live-page .tm-live-plat__row.is-vurgu .tm-live-plat__bar > span { opacity: 1; }
.tm-ds .tm-live-page .tm-live-plat__row:hover { background: var(--tm-surface-sunken); }
/* reduced-motion: ds-primitives.css `.tm-ds *` kuralı geçiş süresini 0.001ms'e indirir — ayrı blok yok (PR-1). */

/* =================================================================
   🔴 ÜST ŞERİT SATIR SAYISI İLK ÇİZİMDE SABİT (2026-10-11 — ÖLÇÜLDÜ)
   Kullanıcı: *"sayfa içerikleri kasıyor, sıralı yüklenmiyor"*. Canlı
   Performans CLS = 0,37 (eşik 0,25 "kötü"). Kaynak: şerit ilk çizimde
   iskeletlerle TEK satır (32 px), JS değerleri yazınca çipler genişleyip
   kontroller ikinci satıra düşüyor (72 px) → KPI, grafikler ve sipariş
   tablosu ~1 sn sonra 40 px aşağı kayıyordu (kids.cjs ölçümü: şerit
   32→72, KPI satırı 141→181). Önceki ch-rezervleri ve 72 px min-height
   bu katmanda devreye girmiyordu.
   Artık satır sayısı İÇERİKTEN bağımsız:
     ≥1360 px  → her zaman TEK satır; çipler daralabilir, kontrolleri itemez.
     <1360 px  → nabız çipleri ilk çizimden itibaren kendi satırında,
                 kontroller ikinci satırda (iki satır, sabit).
   ================================================================= */
@media (min-width: 1360px) {
  .tm-ds .tm-live-page .tm-live-header { flex-wrap: nowrap; }
  .tm-ds .tm-live-page .tm-live-header > .tm-live-pulseline {
    flex: 1 1 auto;
    min-width: 0;
    flex-wrap: nowrap;
    overflow: hidden;
  }
  .tm-ds .tm-live-page .tm-live-pulseline > .tm-live-stat { flex: 0 1 auto; min-width: 0; }
  .tm-ds .tm-live-page .tm-live-stat__value,
  #tmLiveLastOrder.tm-live-stat__value,
  #tmLivePace.tm-live-stat__value,
  #tmLiveCancelRate.tm-live-stat__value {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}
@media (min-width: 768px) and (max-width: 1359.98px) {
  .tm-ds .tm-live-page .tm-live-header > .tm-live-pulseline { flex: 1 1 100%; }
  .tm-ds .tm-live-page .tm-live-header__row--controls-only { margin-inline-start: auto; }
}

/* Ortak kıyas notu — beş kartta tekrar eden alt metnin TEK kopyası (2026-10-11). */
.tm-ds .tm-live-page .tm-live-kpi-note {
  margin: 0 0 var(--tm-space-2);
  font-size: var(--tm-type-caption);
  line-height: var(--tm-type-caption-lh);
  color: var(--tm-text-muted);
}
.tm-ds .tm-live-page .tm-live-kpi-note[hidden] { display: none; }
/* Kıvılcım kartın alt kenarına yapışık çiziliyordu (kart alt payı 0; sıfır
   çizgisi kenardan 3 px yukarıda → kenarlık gibi okunuyor, uç nokta kesik).
   Canlı kartlarında alt pay 10 px; yükseklik 120 px içinde kalır. */
.tm-ds .tm-live-page .tm-live-kpi-grid .kpi-card { padding-bottom: 10px; }


/* ===== css/ds/ds-shell.css ===== */
/* =================================================================
   TRENDMETRIK DESIGN SYSTEM — SHELL (A2, 2026-09-13)
   Sidebar · top bar · demo banner · "Canlı Performansım" promo band ·
   floating support/chat button · sticky store/date nav. Presentation only —
   no route/API/state/JS changes, no id/class renames (docs/ui-audit.md Ek B).

   SCOPE (binding, docs/ui-design-log.md § Kabuk): every rule below is
   prefixed `body.tm-ds-shell`. That class is added in
   templates/layouts/base.html ONLY when the page's `tmv2_ds_scope` block
   renders "tm-ds" (dashboard_tabbed.html ds in ('overview','orders') /
   dashboard_live.html) AND `?legacy=1` is absent — i.e. exactly the ~3 DS
   routes, never the other ~200 pages that share this same shell markup.
   Proof: tests/e2e/ui-refactor/style-fingerprint.cjs on a non-DS page
   (/dashboard/products, /dashboard/xml) before/after this file = 0/0/0;
   ?legacy=1 on a DS page also drops the class.

   Custom-property trick (used throughout instead of fighting !important):
   the shell (sidebar/topbar/demo-banner/promo-FAB) sits OUTSIDE
   <main class="tm-ds">, so the `.tm-ds { --tm-radius-card: … }` block in
   ds-tokens.css is invisible here (custom properties only resolve for the
   scoping element + its descendants). Two kinds of variable used below:
     - tokens that are ALREADY global (:root, static/css/v2/tokens.css):
       --tm-shadow-card/-overlay/-modal, --tm-surface*, --tm-border*,
       --tm-text-*, --tm-accent-*, --tm-radius-md/xl/full, --tm-ink-100 —
       used as-is, no mirror needed.
     - shell-only tokens with no global equivalent (permanently-dark sidebar
       surface, control-radius mirror): declared in ds-tokens.css under the
       same `body.tm-ds-shell` selector (the one DS file the guard allows
       colour literals in) and consumed here as var(--tm-shell-*).
     - existing LEGACY custom properties the current shell CSS already
       reads (--tmv2-sb-w, --tmv2-nav-*): redeclaring them under
       `body.tm-ds-shell` re-themes every rule that consumes them, with NO
       new selector and NO !important — the cascade for custom properties
       always prefers the value declared on the nearer/more-specific match,
       so this is safe on the ~200 non-DS pages (they never get the class).

   Cascade trap: legacy shell CSS (tm-shell-v2.css, tm-header-v2.css,
   demo-banner.css, base.html's inline FAB block) carries many !important
   declarations. Per the design-log method, ds files never use !important
   (guard-enforced) — where a legacy !important rule visually fights this
   file, this file wins via HIGHER SPECIFICITY instead (adding the
   `body.tm-ds-shell` ancestor class to an equally-specific selector), or
   the legacy declaration turned out to not be !important at all (verified
   with the computed-style probe before writing the override — see
   docs/ui-design-log.md § Kabuk (A2) for the per-round table).
   ================================================================= */

/* ================= SIDEBAR =================
   Sol ray artık TEK kaynaktan geliyor: static/css/v2/components/sidebar.css
   (kılavuz rail dili, 2026-10-08).

   Burada eskiden şunlar vardı ve SİLİNDİ — hepsi "aynı ray, sayfaya göre
   başka görünüm" üretiyordu (ölçüldü 2026-10-08, gerçek DOM):
     • `--tm-shell-sidebar-bg` (#12161f) zemini → ds sayfalarında ray #12161f,
       diğer sayfalarda #0f1622, XML Sync koyu temada SAYDAM: üç farklı zemin.
     • `.nav-label { font-size: 14px }` → kanonik 12,5px'i eziyordu.
     • `--tmv2-nav-icon-slot: 18px` → ikon dairesini kırıyordu.
     • `.tmv2-pro-card { background: transparent }` → abonelik kartı ds
       sayfalarında düz satır, diğerlerinde turuncu gradyan blok: iki görünüm.
   `--tmv2-sb-w: 260px` da kalktı; theme-variables.css:271 zaten 260px veriyor
   (tek genişlik, 2026-09-23).

   🔒 Buraya sidebar kuralı GERİ EKLEME. Ray tema-bağımsız ve sayfa-bağımsız
      olmalı; testi: tests/e2e/sidebar-v3-duman.cjs "tek zemin" iddiası.
   ========================================================= */

/* ================= TOP BAR — 56-64px, plain surface, hairline border ================= */

body.tm-ds-shell header.tmv2-header {
  min-height: 60px;
  background: var(--tm-surface);
  border-bottom: 1px solid var(--tm-border);
  box-shadow: none;
}
body.tm-ds-shell header.tmv2-header .tmv2-header-inner { min-height: 60px; }
body.tm-ds-shell .tmv2-header--page,
body.tm-ds-shell .tmv2-header--inline-in-bar {
  background: transparent;
  border-bottom: 0;
}
body.tm-ds-shell .tmv2-header-title {
  font-size: 18px;
  font-weight: 600;
  color: var(--tm-text-primary);
}

/* Search — one control, control radius, no pill */
body.tm-ds-shell .tmv2-search {
  height: 34px;
  background: var(--tm-ink-100);
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-control);
  box-shadow: none;
}
body.tm-ds-shell .tmv2-search:focus-within {
  border-color: var(--tm-shell-accent);
  outline: 2px solid var(--tm-shell-accent);
  outline-offset: 1px;
}

/* Icon buttons — 36px, control radius */
body.tm-ds-shell .header-dropdown-btn {
  width: 36px;
  height: 36px;
  border-radius: var(--tm-radius-control);
}
body.tm-ds-shell .header-dropdown-btn:hover {
  background: var(--tm-ink-100);
}

/* Avatar — 32px */
body.tm-ds-shell .header-account-btn__avatar {
  width: 32px;
  height: 32px;
  box-shadow: none;
}

/* ================= DEMO BANNER — one row 40-44px, no wrap, no gradient ================= */

body.tm-ds-shell #tmDemoBanner {
  background: var(--tm-warn-bg);
  flex-wrap: nowrap;
  min-height: 40px;
  box-shadow: none;
}
body.tm-ds-shell #tmDemoBanner .tm-demo-banner__text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
/* .tm-demo-banner__icon is already a fixed 28x28 box (demo-banner.css) — the
   `<i data-lucide>` inside it is `display:inline` until lucide.js swaps it
   for an <svg> (a replaced element); reserving `inline-block` here means the
   inline width/height already set on the tag apply BEFORE that swap, so the
   swap causes no reflow (layout-lint R6 CLS source). */
body.tm-ds-shell #tmDemoBanner [data-lucide] {
  display: inline-block;
}

@media (max-width: 1024px) and (min-width: 481px) {
  body.tm-ds-shell #tmDemoBanner {
    gap: 8px;
  }
  body.tm-ds-shell #tmDemoBanner .tm-demo-banner__text {
    min-width: 4rem;
  }
}

/* ================= "Canlı Performansım" PROMO BAND — CLS fix only ================= */
/* ds-utilities.css already re-skins colour/surface for `.tm-live-promo`
   (Faz 4b). The remaining defect (layout-lint R6, CLS 0.0995 @768) is the
   same reserved-icon-box gap as the demo banner: `[data-lucide]` inside the
   promo band is `display:inline` until hydrated, so the CTA/close buttons'
   own inline width/height attributes are ignored pre-hydration → the row
   grows once lucide.js runs → `.tm-live-promo__text` (flex-wrap) reflows. */
body.tm-ds-shell .tm-live-promo [data-lucide] {
  display: inline-block;
}

/* ================= CHAT / SUPPORT FAB — stay clear of the content column ================= */
/* Floating support buttons (speed dial): legacy size/position kept. The 28px + left:100vw variant (r36–r39) broke the
   dial's stacked items in prod (items positioned for 44/52px buttons ended up clipped at the viewport edge) — reverted
   2026-09-13; the residual 16px overlap with the chart card's corner at 1640 is accepted over a broken dial. */
/* ================= STICKY STORE/DATE NAV (Genel Bakış / Siparişler) ================= */
/* Measured (shell-probe r0): its inner left edge was ALREADY 312/20/12 at
   1280/1024/375 — the same canonical gutter the coordinator's "Sayfalar
   arası tutarlılık" round already aligned across all three pages. An
   earlier version of this rule zeroed `.dashboard-toolbar--nav` padding and
   REGRESSED that alignment to 292 (measured) — reverted. Only the control
   chrome (button radius) is restyled here; the platform-picker/date-picker
   JS-driven internals are out of shell scope (dashboard_tabbed_sticky_nav.html
   is owned by the page agents). */
body.tm-ds-shell .date-range-btn {
  border-radius: var(--tm-radius-control);
}

/* ================= TOP BANNER SLIDER (A2 round 2 → slider, 2026-09-13, user decision) =================
   Under the top bar, DS-shell only (templates/includes/_shell_ticker.html, included from base.html gated on
   the same var as the body class). ONE slide visible at a time; slides change with a horizontal slide
   transition every 6 s (paused on hover/focus), dots on the right; prefers-reduced-motion = instant switch.
   Fixed 56px row from first paint (catalog slide is server-rendered) → no CLS by construction. Own class
   names (`.tm-shell-ticker__*`) so the global store_header initMarquee() never touches it. */
.tm-shell-ticker {
  height: 60px;
  min-height: 60px;
  overflow: hidden;
  position: relative;
  /* 2026-10-14 komuta çubuğu: solda ana mesaj (esner), sağda başlık çipleri (sabit). */
  display: flex; align-items: stretch;
  /* Gradyan + yavas ambiyans kaymasi (2026-09-16, kullanici: "birkac gorsel ve animasyon").
     Iki uc da TON ailesinden ve koyu uc daha KOYU -> kontrast tabandan asla dusmuyor.
     `background-position` animasyonu hareket butcesinde ambiyans olarak serbest (layout ozelligi degil). */
  background: linear-gradient(120deg, var(--tm-shell-band-bg) 0%, var(--tm-shell-band-bg-2) 50%, var(--tm-shell-band-bg) 100%);
  background-size: 220% 100%;
  /* animation TEK yerde (asagidaki gorsel blogu) — mutasyon testinde mukerrer tanim
     kilidi delmisti: birini silince digeri hayatta kaliyordu, yani kilit yalan soyluyordu. */
  border-bottom: 0;
  box-shadow: none;
  color: var(--tm-shell-band-fg);
}
.tm-shell-ticker__wrapper { height: 100%; flex: 1 1 auto; min-width: 0; overflow: hidden; position: relative; }
.tm-shell-ticker__track { position: relative; height: 100%; width: 100%; }
/* slides stack; only the active one is visible. Enter from the right, leave to the left. */
.tm-shell-ticker__item {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 var(--tm-space-4) 0 var(--tm-space-8);
  /* 2026-10-14: kayma YOK — yumuşak soluş (kullanıcı: "taktak geçiyor"). */
  opacity: 0;
  transition: opacity 480ms ease;
  pointer-events: none;
}
.tm-shell-ticker__item.is-active { opacity: 1; pointer-events: auto; }
.tm-shell-ticker__item.is-leaving { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .tm-shell-ticker__item { transition: none; transform: none; }
  .tm-shell-ticker__item.is-leaving { transform: none; }
}
.tm-shell-ticker__ic {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; flex-shrink: 0;
  border-radius: 11px; box-shadow: inset 0 0 0 1px var(--tm-shell-band-fg-18);
  background: var(--tm-shell-band-fg-18);
  color: inherit;
}
.tm-shell-ticker__ic svg,
.tm-shell-ticker__ic [data-lucide] { width: 19px; height: 19px; }
/* Ana mesaj gövdesi: üstte küçük başlık etiketi, altında metin (2026-10-14). */
.tm-shell-ticker__govde { display: flex; flex-direction: column; justify-content: center; min-width: 0; flex: 1 1 auto; }
.tm-shell-ticker__et { font-size: 11px; line-height: 14px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; opacity: .82; }
.tm-shell-ticker__govde .tm-shell-ticker__txt { font-weight: 600; }
.tm-shell-ticker__ertele {
  flex-shrink: 0; border: 0; background: transparent; color: inherit; cursor: pointer;
  font-size: 12px; text-decoration: underline; text-underline-offset: 3px; opacity: .85; white-space: nowrap;
}
.tm-shell-ticker__ertele:hover { opacity: 1; }
/* Çip paneli (sağ): bütün başlıklar sayılı; aktif çip beyaz + altında ilerleme çizgisi. */
.tm-shell-ticker__cipler {
  flex: 0 1 auto; max-width: 52%; display: flex; align-items: center; gap: 6px;
  padding: 0 var(--tm-space-4); overflow-x: auto; scrollbar-width: none;
  background: rgba(0, 0, 0, .12); box-shadow: inset 1px 0 0 var(--tm-shell-band-fg-18);
}
.tm-shell-ticker__cipler::-webkit-scrollbar { display: none; }
.tm-shell-ticker__cip {
  position: relative; display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto;
  height: 34px; padding: 0 9px; border: 0; border-radius: 9px; cursor: pointer;
  background: var(--tm-shell-band-fg-18); color: var(--tm-shell-band-fg);
  font-size: 12.5px; font-weight: 600; white-space: nowrap;
  transition: background-color 160ms ease-out, color 160ms ease-out;
}
.tm-shell-ticker__cip:hover { background: var(--tm-shell-band-fg-45); }
.tm-shell-ticker__cip svg, .tm-shell-ticker__cip [data-lucide] { width: 15px; height: 15px; }
.tm-shell-ticker__cip.is-active { background: var(--tm-shell-band-fg); color: var(--tm-shell-band-bg); }
.tm-shell-ticker__rozet {
  min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; display: inline-grid; place-items: center;
  font-size: 11.5px; font-weight: 700; font-variant-numeric: tabular-nums; background: var(--tm-shell-band-fg-18);
}
.tm-shell-ticker__cip.is-active .tm-shell-ticker__rozet { background: var(--tm-shell-band-bg); color: var(--tm-shell-band-fg); }
.tm-shell-ticker__cip .tm-shell-ticker__rozet[data-ton="danger"] { background: #ef4444; color: #fff; }
.tm-shell-ticker__cip .tm-shell-ticker__rozet[data-ton="warning"] { background: #f59e0b; color: #fff; }
/* Yer: etiket yalnız AKTİF çipte (diğerleri ikon + rozet; ad `title`'da). Geniş ekranda hepsi. */
@media (max-width: 1599px) {
  .tm-shell-ticker__cip:not(.is-active) .tm-shell-ticker__cip-ad { display: none; }
}
.tm-shell-ticker__cip-bar { position: absolute; left: 8px; right: 8px; bottom: 3px; height: 2px; border-radius: 2px; overflow: hidden; opacity: 0; }
.tm-shell-ticker__cip.is-active .tm-shell-ticker__cip-bar { opacity: 1; background: color-mix(in srgb, var(--tm-shell-band-bg) 20%, transparent); }
.tm-shell-ticker__cip-bar i { display: block; height: 100%; width: 100%; background: var(--tm-shell-band-bg); transform-origin: left; transform: scaleX(0); }
.tm-shell-ticker__cip.is-active .tm-shell-ticker__cip-bar i { animation: tmCipBar var(--tm-ticker-slide-ms, 8000ms) linear forwards; }
.tm-shell-ticker:hover .tm-shell-ticker__cip-bar i, .tm-shell-ticker:focus-within .tm-shell-ticker__cip-bar i { animation-play-state: paused; }
@keyframes tmCipBar { to { transform: scaleX(1); } }
/* Panel zemini aktif mesajın tonunu alır (uyarı turuncusu yalnız sol yarıda kalmasın). */
.tm-shell-ticker[data-ton="warning"] { background: linear-gradient(120deg, var(--tm-shell-band-warn), var(--tm-shell-band-warn-2)); }
.tm-shell-ticker[data-ton="danger"]  { background: linear-gradient(120deg, var(--tm-shell-band-danger), var(--tm-shell-band-danger-2)); }
.tm-shell-ticker[data-ton="success"] { background: linear-gradient(120deg, var(--tm-shell-band-ok), var(--tm-shell-band-ok-2)); }
.tm-shell-ticker[data-ton="warning"] .tm-shell-ticker__cip.is-active { color: var(--tm-shell-band-warn); }
.tm-shell-ticker[data-ton="danger"]  .tm-shell-ticker__cip.is-active { color: var(--tm-shell-band-danger); }
.tm-shell-ticker[data-ton="success"] .tm-shell-ticker__cip.is-active { color: var(--tm-shell-band-ok); }
@media (prefers-reduced-motion: reduce) {
  .tm-shell-ticker__cip.is-active .tm-shell-ticker__cip-bar i { animation: none; transform: scaleX(1); }
}
.tm-shell-ticker__txt {
  font-size: 14px;
  line-height: 20px;
  color: inherit;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: flex; align-items: baseline; gap: var(--tm-space-2);
}
.tm-shell-ticker__txt strong { color: inherit; font-weight: 700; font-size: 15px; }
.tm-shell-ticker__sub { opacity: 0.85; font-size: 13px; overflow: hidden; text-overflow: ellipsis; }
.tm-shell-ticker__txt .mono { font-variant-numeric: tabular-nums; font-weight: 600; color: inherit; }
.tm-shell-ticker__link { color: inherit; text-decoration: underline; text-underline-offset: 3px; font-weight: 600; }
.tm-shell-ticker__link:hover { opacity: 0.85; }
.tm-shell-ticker__cta {
  display: inline-flex; align-items: center; height: 32px; padding: 0 var(--tm-space-4); flex-shrink: 0;
  border-radius: var(--tm-radius-control); background: var(--tm-shell-band-fg); color: var(--tm-shell-band-bg);
  font-size: 13px; font-weight: 700; text-decoration: none; white-space: nowrap;
}
.tm-shell-ticker__cta:hover { opacity: 0.92; }

/* İlk-sipariş şeridinin kapatma düğmesi (2026-09-28). CTA'ya yapışmaması için
   sol boşluk; dokunmatikte kolay hedef olsun diye 28px kutu. */
.tm-shell-ticker__close {
  margin-left: 10px; flex: 0 0 auto;
  width: 28px; height: 28px; line-height: 1;
  background: transparent; border: 0; border-radius: 8px;
  color: currentColor; opacity: .75; font-size: 18px; cursor: pointer;
}
.tm-shell-ticker__close:hover { opacity: 1; background: rgba(255,255,255,.18); }
.tm-shell-ticker__dismiss {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; flex-shrink: 0; margin-left: auto;
  border: 0; border-radius: var(--tm-radius-full); background: transparent; color: inherit; opacity: 0.8; cursor: pointer;
}
.tm-shell-ticker__dismiss:hover { background: var(--tm-shell-band-fg-18); opacity: 1; }
.tm-shell-ticker__dismiss svg,
.tm-shell-ticker__dismiss [data-lucide] { width: 13px; height: 13px; }
/* dots (right edge); hidden when there is a single slide */
.tm-shell-ticker__dots { position: absolute; right: 32px; top: 0; bottom: 0; display: flex; align-items: center; gap: var(--tm-space-2); z-index: 2; }
/* 🔴 NOKTA BOZULMASI (2026-09-17, kullanıcı bildirimi "noktalarda yamulma var"):
   aktif nokta `transform: scaleX(2.2)` ile geniştiliyordu. scaleX bir DAİREYİ yatay
   ezerek ELİPS yapar — uç kavisleri de aynı oranda gerildiği için hap değil
   "yamulmuş nokta" görünür. Çözüm: ölçeklemek yerine aktif noktaya GERÇEK hap
   genişliği vermek (border-radius sabit kalır → uçlar kusursuz yarım daire).
   ⚠️ Genişlik GEÇİŞLE animate EDİLMEZ: `width` bir yerleşim özelliği ve
   docs/ui-reference-spec.md hareket bütçesi bunu yasaklıyor. Geçiş yalnız renkte. */
.tm-shell-ticker__dot {
  width: 8px; height: 8px; border: 0; padding: 0; flex: 0 0 auto;
  border-radius: 999px; background: var(--tm-shell-band-fg-45); cursor: pointer;
}
.tm-shell-ticker__dot.is-active { width: 22px; background: var(--tm-shell-band-fg); }
.tm-shell-ticker[data-count="1"] .tm-shell-ticker__dots { display: none; }
.tm-shell-ticker[data-count="1"] .tm-shell-ticker__item { padding-right: 32px; }

/* Tones — warning slide uses --tm-warn/-bg (danger when terminated), dealer-ad success/info as in
   dealer_status_panel.html; the warning tints the whole row so it is never mistaken for an advert. */
.tm-shell-ticker__item[data-tone="promo"],
.tm-shell-ticker__item[data-tone="info"]    { background: linear-gradient(120deg, var(--tm-shell-band-bg), var(--tm-shell-band-bg-2)); color: var(--tm-shell-band-fg); }
.tm-shell-ticker__item[data-tone="success"] { background: linear-gradient(120deg, var(--tm-shell-band-ok), var(--tm-shell-band-ok-2)); color: var(--tm-shell-band-fg); }
.tm-shell-ticker__item[data-tone="warning"] { background: linear-gradient(120deg, var(--tm-shell-band-warn), var(--tm-shell-band-warn-2)); color: var(--tm-shell-band-fg); }
.tm-shell-ticker__item[data-tone="danger"]  { background: linear-gradient(120deg, var(--tm-shell-band-danger), var(--tm-shell-band-danger-2)); color: var(--tm-shell-band-fg); }
.tm-shell-ticker__item[data-tone="warning"] .tm-shell-ticker__cta { color: var(--tm-shell-band-warn); }
.tm-shell-ticker__item[data-tone="danger"]  .tm-shell-ticker__cta { color: var(--tm-shell-band-danger); }

/* ---- Gorsel/hareket turu (2026-09-16, kullanici istegi) ------------------------------------
   Hepsi transform/opacity/background-position — layout ozelligi animasyonu YOK (ui-reference-spec).
   Etkilesim <=200ms; ambiyans (band kaymasi, uyari nabzi) sure-serbest; giris 420ms tek-sefer.
   prefers-reduced-motion'da HEPSI kapali ve hicbiri icerigi opacity 0'da birakmiyor. */
@keyframes tmBandDrift { 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } }
@keyframes tmBandIn    { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
@keyframes tmIcPulse   { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.08); } }

.tm-shell-ticker { animation: tmBandDrift 28s ease-in-out infinite, tmBandIn 420ms cubic-bezier(.22,.61,.36,1) backwards; }
/* Uyari/tehlike tonunda ikon nabzi: dikkat SAYIYA degil DURUMA cekiliyor; metne dokunmuyor. */
.tm-shell-ticker__item[data-tone="warning"] .tm-shell-ticker__ic,
.tm-shell-ticker__item[data-tone="danger"]  .tm-shell-ticker__ic { animation: tmIcPulse 2.4s ease-in-out infinite; }
/* Mikro-etkilesimler (<=200ms) */
.tm-shell-ticker__cta { transition: transform 160ms ease-out, opacity 160ms ease-out; }
.tm-shell-ticker__cta:hover { transform: translateY(-1px); }
.tm-shell-ticker__cta:active { transform: translateY(0); }
.tm-shell-ticker__ic { transition: transform 160ms ease-out; }
.tm-shell-ticker__item.is-active .tm-shell-ticker__ic { transform: none; }
/* Aktif nokta: `width` DEGIL `transform: scaleX` — layout animasyonu yasak. */
.tm-shell-ticker__dot { transition: background-color 160ms ease-out; }
.tm-shell-ticker__dismiss { transition: transform 160ms ease-out, background-color 160ms ease-out, opacity 160ms ease-out; }
.tm-shell-ticker__dismiss:hover { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) {
  .tm-shell-ticker,
  .tm-shell-ticker__item[data-tone="warning"] .tm-shell-ticker__ic,
  .tm-shell-ticker__item[data-tone="danger"]  .tm-shell-ticker__ic { animation: none; }
  .tm-shell-ticker__cta, .tm-shell-ticker__ic, .tm-shell-ticker__dot, .tm-shell-ticker__dismiss { transition: none; }
  .tm-shell-ticker__cta:hover, .tm-shell-ticker__dismiss:hover { transform: none; }
  /* aktif nokta genisligi transform DEGIL gercek genislik → hareket-azaltmada da dogru gorunur */
}

@media (max-width: 640px) {
  .tm-shell-ticker__item { padding: 0 calc(var(--tm-space-12) + var(--tm-space-2)) 0 var(--tm-space-3); gap: var(--tm-space-2); }
  .tm-shell-ticker__txt { font-size: 13px; white-space: normal; line-height: 17px; max-height: 34px; }
  .tm-shell-ticker__dots { right: 12px; }
  /* 2026-10-14 komuta çubuğu: mobilde çipler mesajın ALTINDA tek satır, yatay kaydırılır
     (A-1'deki "3/12" sayacının yerine — çipler zaten her başlığı sayısıyla gösteriyor). */
  .tm-shell-ticker { flex-direction: column; height: auto; min-height: 60px; }
  .tm-shell-ticker__wrapper { height: 56px; flex: 0 0 56px; }
  .tm-shell-ticker .tm-shell-ticker__item { padding-right: var(--tm-space-3); }
  .tm-shell-ticker__cipler { max-width: none; height: 42px; flex: 0 0 42px; padding: 0 var(--tm-space-3); box-shadow: inset 0 1px 0 var(--tm-shell-band-fg-18); }
  .tm-shell-ticker__cip { height: 30px; padding: 0 8px; font-size: 12px; }
  .tm-shell-ticker__et { display: none; }
  .tm-shell-ticker__ic { width: 30px; height: 30px; border-radius: 9px; }
  .tm-shell-ticker__ertele { font-size: 11px; padding: 0 2px; }
  .tm-shell-ticker__cta { height: 28px; padding: 0 var(--tm-space-3); font-size: 12px; }
}

/* content starts at the page's own 24px rhythm right under the banner (legacy main padding-top 16 stacked on it) */
body.tm-ds-shell main.tmv2-content { padding-top: 0; }


/* ═══ Şerit görsel güçlendirme (2026-09-17, kullanıcı: "güzel ama dikkat çekmiyor,
   daha fazla resim/ikon koyabiliriz") — üç ekleme, hiçbiri yerleşim animasyonu
   kullanmaz (yalnız transform/opacity; hareket bütçesi korunur). ═══ */

/* (a) İkon rozeti: 26px → 30px, çift katman (dış halka + iç dolgu) ve hafif
   yükselti. Sabit; dikkat çeken ama titremeyen bir çapa. */
.tm-shell-ticker__ic {
  width: 30px; height: 30px;
  box-shadow: 0 0 0 1px var(--tm-shell-band-fg-18), 0 2px 8px rgba(0, 0, 0, 0.14);
}
.tm-shell-ticker__ic svg,
.tm-shell-ticker__ic [data-lucide] { width: 17px; height: 17px; }

/* (b) Slayt ilerleme çubuğu: şeridin ALT kenarında 6 sn'de dolan ince çizgi.
   Hem "dönüyor" bilgisini verir hem gözü bandın üstünde tutar. transform:scaleX
   ile çizilir (layout YOK). Hover/odakta duraklar — slider'ın kendisi de durur. */
.tm-shell-ticker__prog {
  position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--tm-shell-band-fg-18); overflow: hidden; z-index: 3; pointer-events: none;
}
.tm-shell-ticker__prog::after {
  content: ""; display: block; height: 100%; width: 100%;
  background: var(--tm-shell-band-fg); opacity: 0.9;
  transform-origin: left center; transform: scaleX(0);
  animation: tmTickerProg var(--tm-ticker-slide-ms, 6000ms) linear infinite;
}
.tm-shell-ticker:hover .tm-shell-ticker__prog::after,
.tm-shell-ticker:focus-within .tm-shell-ticker__prog::after { animation-play-state: paused; }
.tm-shell-ticker[data-count="1"] .tm-shell-ticker__prog { display: none; }
@keyframes tmTickerProg { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* (c) Ürün görseli kümesi (katalog/haftalık slaytı): üst üste binen 4 yuvarlak
   thumbnail + "+N" rozeti. Gerçek katalog görselleri (/xml/catalog/weekly-top
   payload'ındaki `image`) — dekoratif çizim değil, satılabilir ürünler. */
.tm-shell-ticker__thumbs { display: inline-flex; align-items: center; flex-shrink: 0; margin-right: var(--tm-space-1); }
.tm-shell-ticker__thumb {
  width: 26px; height: 26px; border-radius: 999px; object-fit: cover;
  border: 2px solid var(--tm-shell-band-bg); background: var(--tm-shell-band-fg-18);
  margin-left: -9px; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
}
.tm-shell-ticker__thumb:first-child { margin-left: 0; }
.tm-shell-ticker__thumb-more {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; margin-left: -9px; border-radius: 999px;
  border: 2px solid var(--tm-shell-band-bg); background: var(--tm-shell-band-fg);
  color: var(--tm-shell-band-bg); font-size: 11px; font-weight: 800; font-variant-numeric: tabular-nums;
}
@media (max-width: 860px) { .tm-shell-ticker__thumbs { display: none; } }

@media (prefers-reduced-motion: reduce) {
  /* Çubuk KALIR (durum göstergesi) ama akmaz: dolu gösterilir. */
  .tm-shell-ticker__prog::after { animation: none; transform: scaleX(1); opacity: 0.55; }
}


/* 2026-09-28: şerit çizildiğinde yüksekliğini tek kaynaktan duyur — toast kabı
   (dashboard-*.css) `--tm-ticker-h` ile kendini şeridin ALTINA yerleştirir.
   `:has()` desteklenmeyen tarayıcıda değişken 0 kalır → eski davranış. */
body:is(.tmh-e6051e5a, :not(*) #tmShellTicker) { --tm-ticker-h: 56px; }
/* İLK SİPARİŞ ŞERİDİ — dar ekran (2026-09-28, ÖLÇÜLDÜ 390px).
   Metin iki satıra taşıp kırpılıyordu ("İlk sipariş…"): CTA sabit genişlikte,
   metin ise küçülemiyordu. Metin tek satır + ellipsis, CTA daralır ama okunur
   kalır; kapatma düğmesi ≥28px dokunma hedefi. */
@media (max-width: 575.98px) {
  .tm-shell-ticker__item[data-kind="first-order"] { gap: 8px; padding-right: 8px; }
  .tm-shell-ticker__item[data-kind="first-order"] .tm-shell-ticker__txt {
    min-width: 0; flex: 1 1 auto;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .tm-shell-ticker__item[data-kind="first-order"] .tm-shell-ticker__cta {
    flex: 0 0 auto; white-space: nowrap; padding: 5px 10px; font-size: 12.5px;
  }
  .tm-shell-ticker__item[data-kind="first-order"] .tm-shell-ticker__ic { display: none; }
}


/* Sabitlenmiş öğe (data-pin) varken şerit DÖNMÜYOR — slayt noktaları ve
   ilerleme çubuğu o hâlde anlamsız ve dar ekranda kapatma düğmesinin üstüne
   biniyor. `:has()` desteklenmeyen tarayıcıda eski görünüm kalır (zararsız). */
.tm-shell-ticker:has([data-pin]) .tm-shell-ticker__dots,
.tm-shell-ticker:has([data-pin]) .tm-shell-ticker__prog { display: none; }


/* ===== css/ds/ds-catalog.css ===== */
/* =================================================================
   DS — TEDARİKÇİ KATALOĞU (catalog_picker.html, 2026-09-14 migration)

   Scope: every rule below lives under .tm-ds (set on <main> once the page
   opts in via {% block tmv2_ds_scope %}tm-ds{% endblock %}) → inert on the
   ~200 pages that have not opted in. ?legacy=1 drops the scope and re-loads
   static/css/dashboard/catalog-picker-legacy-2026-09-14.css instead (the
   pre-migration presentation, verbatim).

   Reference: docs/ui-reference-spec.md (Apex /ecommerce · /products) — one
   title band, toolbar (search left · filters/sort right — tek satır yalnız
   ≥1640px'te sığar, ölçüldü 2026-09-14), product
   cards on the 16px grid, 14px card radius, hairline + one soft shadow,
   12/14/16 type, one accent (brand blue), quiet price/stock badges,
   pagination/loadmore footer. Every id/class read by JS (inventory:
   tests/e2e/ui-refactor/catalog-hook-guard.cjs) is restyled IN PLACE —
   nothing renamed. Decorative gradients / shines / pulses / hover-lifts
   from the legacy file are dropped on purpose (guard forbids colour
   literals + !important; DS pages elsewhere carry no hover lift either,
   static/css/ds/ds-primitives.css:134).
   ================================================================= */

/* ---------- Page shell — sibling spacing is .cpk's own gap, never margin ---------- */
.tm-ds .cpk { --cpk-col-min: 210px; --cpk-mono: "JetBrains Mono", ui-monospace, monospace; display: flex; flex-direction: column; gap: var(--tm-space-4); padding-bottom: var(--tm-space-12); }

/* ---------- Hero / title band (Apex 56px title-band spirit — one accent
   surface, no gradient/orb/shine) ---------- */
/* 2026-09-15 (QA #6532 re-check): KOYU MODDA hero metni kara çıkıyordu.
   `dark-mode.css`'in genel `html.dark-mode span:not(...)` kuralı `color: inherit`
   diyor ve ham özgüllükle DS kuralını yeniyor; hero yüzeyinde açık renk veren
   bir ATA olmadığı için `inherit` gövde metnine (rgb(16,24,40)) kadar tırmanıyordu
   → mavi gradient üzerinde neredeyse siyah yazı. Çözüm: renk çatışmasını
   `!important`la değil, yüzeyin KENDİSİNE açık renk vererek kesiyoruz —
   `.cpk-hero { color: var(--tm-on-accent) }`, böylece `inherit` beyaza çözülür.
   ÖLÇÜM KURALI: koyu mod `dark-mode.css` SUNUCUDA `user_dark_mode` ile gate'li;
   yalnız `html.dark-mode` sınıfını eklemek o dosyayı YÜKLEMEZ → sahte-temiz
   ölçüm verir (bu hatayı bir kez yaptım). Dosyayı da enjekte et. */
/* 2026-09-15 (QA #6532 not b): hero metinlerinde `opacity` vardı (.75-.88).
   Opaklık metni zemine harmanlar → GERÇEK kontrast `color`a bakınca görünenden
   DÜŞÜK: alt metin 3.14-3.96, hap/kicker 3.05-3.70 ölçüldü (4.5:1 altı). Önceki
   gradient PR'ımın ">=4.5:1" iddiası bu yüzden eksikti — opaklık hesaba
   katılmamıştı. Hero metinlerinde opaklık KALDIRILDI; hiyerarşi tipografi ve
   ağırlıkla kurulur (dekoratif noktalar hariç). */
/* 2026-09-15: hero düz marka-mavisiydi; kullanıcı "banner çok kötü, canlı olsun"
   dedi → marka mavisinden promo-4'ün KOYU ucuna 135° gradient. İki uç da beyaz
   metinle >=4.5:1 (ölçüldü: #0175e4 4.50, #024c74 9.18) → hiçbir noktada
   okunabilirlik düşmez. Hareket YOK (statik yüzey), renk token'dan. */
.tm-ds .cpk-hero { position: relative; display: flex; align-items: flex-start; justify-content: space-between; gap: var(--tm-space-6); flex-wrap: wrap; padding: var(--tm-space-6); border-radius: var(--tm-radius-card); color: var(--tm-on-accent); background: linear-gradient(135deg, var(--tm-accent-solid), var(--tm-promo-4-to)); overflow: hidden; box-shadow: none; }
.tm-ds .cpk-hero::before, .tm-ds .cpk-hero__shine { display: none; }
.tm-ds .cpk-hero__left { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: flex-start; gap: var(--tm-space-3); flex: 1 1 420px; max-width: 620px; }
.tm-ds .cpk-hero__kicker { display: inline-flex; align-items: center; gap: var(--tm-space-1); font-size: var(--tm-type-micro); line-height: var(--tm-type-micro-lh); font-weight: var(--tm-weight-bold); letter-spacing: .05em; text-transform: uppercase; color: var(--tm-on-accent); opacity: 1; }
.tm-ds .cpk-hero__kicker [data-lucide] { width: 13px; height: 13px; }
.tm-ds .cpk-hero__t { font-size: var(--tm-type-display-sm); line-height: var(--tm-type-display-sm-lh); font-weight: var(--tm-weight-bold); color: var(--tm-on-accent); margin: 0; letter-spacing: -.01em; }
@media (min-width: 1024px) { .tm-ds .cpk-hero__t { font-size: var(--tm-type-display); line-height: var(--tm-type-display-lh); } }
.tm-ds .cpk-hero__s { font-size: var(--tm-type-body); line-height: var(--tm-type-body-lh); color: var(--tm-on-accent); opacity: 1; margin: 0; max-width: 46ch; }
.tm-ds .cpk-lowquota { display: none; align-items: center; gap: var(--tm-space-1); font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold); color: var(--tm-danger-fg); }
.tm-ds .cpk-lowquota.is-on { display: inline-flex; }
.tm-ds .cpk-hero__pills { display: flex; align-items: center; gap: var(--tm-space-2); flex-wrap: wrap; margin-top: 0; }
/* 2026-09-15 hero-v2: bilgi hapları + haftalık highlight AYNI satırda
   (ölçüm: 1600'de sol blok 7 ayrı satıra yığılıyordu → "sıkışık"). */
.tm-ds .cpk-hero__pill { display: inline-flex; align-items: center; gap: var(--tm-space-1); height: 22px; padding: 0 var(--tm-space-2); border-radius: var(--tm-radius-full); background: transparent; border: 1px solid var(--tm-on-accent); color: var(--tm-on-accent); opacity: 1; font-size: var(--tm-type-micro); font-weight: var(--tm-weight-medium); backdrop-filter: none; }
.tm-ds .cpk-hero__pill [data-lucide] { width: 11px; height: 11px; }
/* Haftalık highlight rozetleri (Faz 4): aynı hap deseni, dolu yüzey + uyarı tonu
   → "bu hafta ne var" bilgisi kabuk rozetlerinden ayrışsın. Renk literal YOK. */
/* 2026-09-15 (QA #6539): dolu rozetin metni `--tm-accent-fg` idi; o token KOYU
   MODDA açık maviye (#93c5fd) remap ediliyor → beyaz zeminde 1.8:1, okunmuyor.
   `--tm-accent-solid` iki modda da marka mavisi ama beyaz hapın üstünde tam
   **4.5006:1** — eşiğin 0.0006 üstünde, pay YOK (QA #6539 ölçümü). Tek veri
   taşıyan öğede bıçak sırtı kabul edilmez → `--tm-promo-4` (aynı mavi ailesi,
   promo paletinden, açık mod #0369a1 = 5.93, koyu mod #02537c = 8.30). */
.tm-ds .cpk-hero__pill--hl { background: var(--tm-on-accent); border-color: var(--tm-on-accent); color: var(--tm-promo-4); opacity: 1; font-weight: var(--tm-weight-semibold); }
/* hero-v3: ikincil öğeler (açıklama + WhatsApp) CTA ile AYNI bloğa alındı;
   buton kendi satırında, ikisi altında yan yana → sol yığın bir satır kısalır. */
.tm-ds .cpk-hero__cta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--tm-space-2) var(--tm-space-3); }
/* 2026-09-16 (kullanıcı: "buton çok büyük"): `flex: 0 0 100%` butonu CTA satırının TAMAMINA
   yayıyordu — 1600/1280/1024'te hep 436px, yani metni bitince de uzayan bir şerit. Birincil
   eylem olması BÜYÜK olmasını gerektirmiyor; belirginlik ağırlıktan (zemin + gölge + parıltı)
   geliyor, genişlikten değil. İçeriği kadar yer kaplasın; alt satır (indirim hapı + WhatsApp)
   böylece yanına geçiyor ve hero bir satır daha kısalıyor. */
.tm-ds .cpk-hero__cta > .cpk-hero__importall { flex: 0 0 auto; }
.tm-ds .cpk-hero__cta-sub { display: flex; flex-wrap: wrap; align-items: center; gap: var(--tm-space-2) var(--tm-space-3); }
/* hero-v3: üç genel hap kalkınca hero'da TEK birincil eylem kaldı → CTA onu
   taşıyacak ağırlıkta olmalı (36 → 44px, yatay dolgu bir kademe artar). */
.tm-ds .cpk-hero__importall { display: inline-flex; align-items: center; gap: var(--tm-space-2); align-self: flex-start; height: 40px; padding: 0 var(--tm-space-4); border-radius: var(--tm-radius-control); border: 0; background: var(--tm-bg-surface); color: var(--tm-accent-fg); font-size: var(--tm-type-body); font-weight: var(--tm-weight-semibold); box-shadow: none; cursor: pointer; position: static; overflow: visible; }
.tm-ds .cpk-hero__importall::before, .tm-ds .cpk-hero__importall::after { display: none; }
.tm-ds .cpk-hero__importall:hover { background: var(--tm-bg-subtle); transform: none; filter: none; box-shadow: none; }
.tm-ds .cpk-hero__importall[disabled] { opacity: .5; }
.tm-ds .cpk-hero__importall [data-lucide] { width: 16px; height: 16px; }
.tm-ds .cpk-hero__cta-note { display: inline-flex; align-items: center; gap: var(--tm-space-1); font-size: var(--tm-type-micro); color: var(--tm-on-accent); opacity: 1; }
.tm-ds .cpk-hero__cta-note [data-lucide] { width: 12px; height: 12px; }
.tm-ds .cpk-hero__wa { display: inline-flex; align-items: center; gap: var(--tm-space-1); height: 24px; padding: 0 var(--tm-space-2); border-radius: var(--tm-radius-full); background: transparent; border: 1px solid var(--tm-on-accent); color: var(--tm-on-accent); font-size: var(--tm-type-micro); font-weight: var(--tm-weight-medium); text-decoration: none; width: fit-content; backdrop-filter: none; transition: none; }
.tm-ds .cpk-hero__wa:hover { background: var(--tm-bg-surface); color: var(--tm-accent-fg); transform: none; box-shadow: none; }
.tm-ds .cpk-hero__wa-icon { color: inherit; flex-shrink: 0; }
.tm-ds .cpk-hero__right { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: flex-end; gap: var(--tm-space-2); }
.tm-ds .cpk-badge { display: inline-flex; align-items: center; gap: var(--tm-space-2); height: 32px; padding: 0 var(--tm-space-3); border-radius: var(--tm-radius-control); background: var(--tm-bg-surface); color: var(--tm-text-primary); border: 0; font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold); box-shadow: none; white-space: nowrap; }
.tm-ds .cpk-badge [data-lucide] { width: 14px; height: 14px; color: var(--tm-accent-fg); }
.tm-ds .cpk-badge b { font-family: var(--cpk-mono); font-size: var(--tm-type-body); }
.tm-ds .cpk-quota-bar { width: 100%; height: 4px; background: var(--tm-bg-subtle); border-radius: var(--tm-radius-full); overflow: hidden; }
.tm-ds .cpk-quota-fill { height: 100%; background: var(--tm-accent-fg); border-radius: var(--tm-radius-full); transition: none; }
#cpkLowQuota.tm-ds, .tm-ds #cpkLowQuota { color: var(--tm-danger-fg); }
.tm-ds #cpkLowQuota a { background: var(--tm-danger-fg); color: var(--tm-on-accent); border-radius: var(--tm-radius-control); }

/* ---------- "Nasıl çalışır?" mini-flow card (inside hero) ---------- */
.tm-ds .cpk-hero__how { position: relative; z-index: 1; width: 320px; max-width: 100%; flex: 1 1 auto; display: flex; flex-direction: column; gap: var(--tm-space-2); text-align: left; color: var(--tm-on-accent); background: transparent; border: 1px solid var(--tm-on-accent); border-radius: var(--tm-radius-card); padding: var(--tm-space-3) var(--tm-space-4); cursor: pointer; overflow: hidden; transition: none; font-family: inherit; }
.tm-ds .cpk-hero__how:hover { background: var(--tm-bg-surface); color: var(--tm-accent-fg); transform: none; box-shadow: none; }
.tm-ds .cpk-hero__how:hover .cpk-hero__how-cta, .tm-ds .cpk-hero__how:hover .cpk-hero__how-title, .tm-ds .cpk-hero__how:hover .cpk-hero__how-ic, .tm-ds .cpk-hero__how:hover .cpk-hero__how-d, .tm-ds .cpk-hero__how:hover .cpk-hero__how-h, .tm-ds .cpk-hero__how:hover .cpk-hero__how-num { color: inherit; border-color: currentColor; }
.tm-ds .cpk-hero__how-head { display: flex; align-items: center; justify-content: space-between; gap: var(--tm-space-2); }
.tm-ds .cpk-hero__how-title { display: inline-flex; align-items: center; gap: var(--tm-space-1); font-size: var(--tm-type-micro); font-weight: var(--tm-weight-bold); letter-spacing: .05em; text-transform: uppercase; }
.tm-ds .cpk-hero__how-title [data-lucide] { width: 14px; height: 14px; }
.tm-ds .cpk-hero__how-cta { display: inline-flex; align-items: center; gap: var(--tm-space-1); font-size: var(--tm-type-micro); font-weight: var(--tm-weight-bold); white-space: nowrap; padding: 0 var(--tm-space-2); height: 20px; border-radius: var(--tm-radius-full); background: transparent; border: 1px solid var(--tm-on-accent); transition: none; }
.tm-ds .cpk-hero__how-cta [data-lucide] { width: 12px; height: 12px; }
.tm-ds .cpk-hero__how-body { min-height: 68px; flex: 1 1 auto; display: flex; flex-direction: column; justify-content: center; }
.tm-ds .cpk-hero__how-step { display: flex; gap: var(--tm-space-3); align-items: flex-start; animation: none; }
.tm-ds .cpk-hero__how-txt { flex: 1 1 auto; min-width: 0; }
.tm-ds .cpk-hero__how-ic { flex: 0 0 auto; width: 32px; height: 32px; border-radius: var(--tm-radius-control); display: grid; place-items: center; background: transparent; border: 1px solid var(--tm-on-accent); }
.tm-ds .cpk-hero__how-ic [data-lucide] { width: 16px; height: 16px; }
.tm-ds .cpk-hero__how-num { display: block; font-family: var(--cpk-mono); font-size: var(--tm-type-micro); font-weight: var(--tm-weight-medium); opacity: 1; }
.tm-ds .cpk-hero__how-h { display: block; font-size: var(--tm-type-body); font-weight: var(--tm-weight-bold); margin: 0; line-height: 1.3; }
.tm-ds .cpk-hero__how-d { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); opacity: 1; }
.tm-ds .cpk-hero__how-dots { display: flex; gap: var(--tm-space-1); margin-top: 0; padding-top: var(--tm-space-3); }
.tm-ds .cpk-hero__how-dot { width: 14px; height: 3px; border-radius: var(--tm-radius-full); background: var(--tm-on-accent); opacity: .4; transition: none; }
.tm-ds .cpk-hero__how-dot.is-active { opacity: 1; }
/* 2026-09-14 (QA denetimi): 701-1439px'te açıklayıcı gövde+noktalar GİZLİYDİ ve
   geniş stepper (.cpk-how-wide) DS'te hiç gösterilmiyor → 1280/1366 laptop'ta
   kullanıcı yalnız "NASIL ÇALIŞIR?" başlığı + ölü şerit görüyordu (kullanıcı
   şikâyeti: "banner açıklayıcı değil"). Dönen adım gövdesi artık HER genişlikte
   görünür; .cpk-how-wide DS'te kullanılmaz (şablondaki ≥1440 JS'i zararsız). */
.tm-ds .cpk-how-wide { display: none; }
/* hero-v2 (2026-09-15): geniş ekranda sol metin sütunu içeriğe göre büzülüp
   sağda ~400px ölü boşluk bırakıyordu → büyüsün (ölçüm satırı) ama satır
   uzunluğu okunur kalsın diye `max-width: 620px` ile sınırlı. */
@media (min-width: 1440px) { .tm-ds .cpk-hero { justify-content: space-between; gap: var(--tm-space-8); } .tm-ds .cpk-hero__left { flex: 1 1 520px; } .tm-ds .cpk-hero__right { flex: 0 0 420px; align-items: stretch; } .tm-ds .cpk-hero__how { width: 100%; max-width: none; } }
@media (min-width: 701px) and (max-width: 1439px) { .tm-ds .cpk-hero { padding: var(--tm-space-3) var(--tm-space-4); gap: var(--tm-space-2) var(--tm-space-4); } .tm-ds .cpk-hero__right { flex-direction: row; align-items: center; flex-wrap: wrap; width: 100%; gap: var(--tm-space-2) var(--tm-space-4); } .tm-ds .cpk-hero__how { flex: 1 1 320px; padding: var(--tm-space-2) var(--tm-space-3); } }
@media (max-width: 700px) { .tm-ds .cpk-hero { padding: var(--tm-space-4); } .tm-ds .cpk-hero__t { font-size: var(--tm-type-heading); } .tm-ds .cpk-hero__s { font-size: var(--tm-type-caption); } }
/* Pazarlama hapları mobilde gizli kalır (yer), ama HAFTALIK HIGHLIGHT bilgi
   taşıyor (kampanya sayısı / yeni ürün) → mobilde de görünür. QA-gate #6494
   Defect 2: `--hl` satırı `.cpk-hero__pills`'i miras aldığı için telefonda
   sessizce ölüydü. */
/* 2026-09-15 (QA #6542): buradaki `.cpk-hero__pills--hl` kuralı ÖLÜYDÜ — hero-v3'te
   kapsayıcıdan `--hl` kalktı (rozetler tek `.cpk-hero__pills` satırında), dolayısıyla
   seçici hiçbir şeyi eşlemiyordu ve mobilde rozetler GİZLİ kalıyordu. Üstteki 700px
   bloğundaki `display: none` de kaldırıldı: satır artık yalnız GERÇEK VERİ taşıyor
   (kampanya sayısı / yeni ürün), telefonda gizlenmesi için sebep yok. */

/* ═══════════════════ hero-v4 — "CANLI PAZAR" creative pass (2026-09-15) ═══════════════════
   Kullanıcı hero-v2/v3'ü "çok kötü, sıkışık, ANİMASYONSUZ ODUN GİBİ" buldu ve
   KÖKTEN yenilik + yüksek pazarlama/dönüşüm istedi. "Düz-DS / hareketsiz"
   felsefesi kullanıcı mandatıyla EZİLDİ (UI oturumu creative pass'i devretti).
   Hareket bütçesi (UI ile mutabık): yalnız transform/opacity; layout kıpırdamaz
   (CLS 0, translate reflow yaratmaz); reduced-motion'da HER ŞEY durur; içerik
   ASLA görünmez kalmaz (giriş animasyonları `backwards` → resting = doğal/görünür,
   animasyon desteklenmezse de görünür). Renk YALNIZ token (radial-gradient
   token'lı; box-shadow-literal YOK → glow yerine card-shadow + transform-lift).
   Guard: animasyon/transition/transform DENETLENMEZ; renk-literali/margin/shadow/
   spacing kuralları KORUNUR. Base gradient KALIR → metin kontrastı garanti.
   ── Katman haritası ──
   1) Yaşayan aurora arka planı (::before, köşelerde token-ışık, yavaş sürükleniş)
   2) Giriş sahnelemesi (kicker→başlık→alt-metin→rozet→CTA→sağ blok, staggered)
   3) Kahraman CTA: shimmer süpürme + hover kalkış + card-shadow
   4) Gerçek-veri highlight rozetleri: yumuşak nabız (göz çeker)
   5) "Nasıl çalışır" kartı: hover kalkış + adım geçiş fade
   6) reduced-motion: tüm hareket durur, içerik tam görünür */

/* 1) Yaşayan aurora — base gradient üstünde iki token-renkli ışık KÖŞELERDE (metin
      merkezde; ışık köşede → kontrast düşmez), 18s yavaş sürükleniş. z-index 0. */
.tm-ds .cpk-hero::before {
  content: ""; display: block; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(40% 55% at 92% 6%, var(--tm-promo-3), transparent 60%),
    radial-gradient(44% 58% at 6% 96%, var(--tm-promo-4), transparent 62%);
  opacity: .40;
  animation: cpkHeroAurora 18s ease-in-out infinite alternate;
  will-change: transform;
}
@keyframes cpkHeroAurora {
  from { transform: translate3d(-2.5%, -2%, 0) scale(1.06); }
  to   { transform: translate3d(2.5%, 2%, 0)   scale(1.14); }
}

/* 2) Giriş sahnelemesi — fade + 10px yükseliş, staggered. `backwards`: gecikme
      boyunca `from` (opacity 0), bitince DOĞAL CSS (opacity 1) → asla takılı-gizli
      kalmaz. translateY reflow yaratmaz → CLS 0. */
@keyframes cpkHeroRise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.tm-ds .cpk-hero__kicker, .tm-ds .cpk-hero__t, .tm-ds .cpk-hero__s,
.tm-ds .cpk-hero__pills, .tm-ds .cpk-hero__cta, .tm-ds .cpk-hero__right {
  animation: cpkHeroRise .5s cubic-bezier(.22, .61, .36, 1) backwards;
}
.tm-ds .cpk-hero__kicker { animation-delay: .02s; }
.tm-ds .cpk-hero__t      { animation-delay: .09s; }
.tm-ds .cpk-hero__s      { animation-delay: .16s; }
.tm-ds .cpk-hero__pills  { animation-delay: .23s; }
.tm-ds .cpk-hero__cta    { animation-delay: .30s; }
.tm-ds .cpk-hero__right  { animation-delay: .34s; }

/* 3) Kahraman CTA — tek birincil eylem, artık YAŞIYOR: hover'da kalkış + yumuşak
      card-shadow (resting yüzeyde izinli tek gölge), üstünden periyodik shimmer
      süpürme (token-renkli, opak buton üstünde parıltı; kontrat: box-shadow
      literal YOK). overflow hidden → shimmer butona kırpılır. */
.tm-ds .cpk-hero__importall { position: relative; overflow: hidden; transition: transform .18s ease, box-shadow .18s ease; }
/* CTA HER İKİ MODDA beyaz-buton + sabit-mavi metin. Hero yüzeyi iki modda da mavi
   (accent-solid→promo-4-to) → DS'in surface-default'u koyu modda butonu KARARTIP
   vuruculuğu düşürüyordu (kahraman eylem gölgede kalıyordu). on-accent=beyaz,
   accent-solid=mavi (ikisi de iki-mod-sabit) → tutarlı, dönüşüm-dostu. */
/* QA #6542: accent-solid beyaz üstünde tam 4.5006:1 (AA geçer ama PAYI YOK — bıçak
   sırtı, bir kez yaşandı) → promo-4 ile paylı (açık 5.93 / koyu 8.30; promo token'ları
   koyu modda remap OLMAZ → iki modda güvenli). */
/* Belirginlik (kullanıcı: "beyaz animasyon güzel, daha belirgin yapılabilir"):
   ① dinlenme hâlinde de gölge — mavi hero yüzeyinde beyaz buton artık yüzeye YAPIŞIK değil.
   ② parıltı DAHA GENİŞ (45% → 60%) ve DAHA SIK (4s → 3s).
   🔴 Parıltıyı KOYULAŞTIRMAK denendi ve ÖLÇÜMLE REDDEDİLDİ: sweep metnin ALTINDAN geçiyor,
      opaklık metin kontrastını doğrudan düşürüyor —
        alpha .16 → zemin (214,230,245) → kontrast 4.66  (AA sınırın hemen üstü)
        alpha .26 → zemin (189,214,239) → kontrast 3.96  ❌ AA ALTI
        alpha .30 → zemin (179,208,237) → kontrast 3.72  ❌
      (metin --tm-promo-4 #0369a1; düz beyaz üstünde 5.93.) Bu yüzden görünürlük opaklıktan
      değil GENİŞLİK + SIKLIK + gölgeden alındı: göze daha çok çarpar, okunurluk düşmez. */
.tm-ds .cpk-hero__importall { background: var(--tm-on-accent); color: var(--tm-promo-4); box-shadow: var(--tm-shadow-card); }
.tm-ds .cpk-hero__importall:hover { transform: translateY(-2px); box-shadow: var(--tm-shadow-card); background: var(--tm-on-accent); }
.tm-ds .cpk-hero__importall:active { transform: translateY(0); }
.tm-ds .cpk-hero__importall::after {
  content: ""; display: block; position: absolute; top: 0; bottom: 0; left: 0; width: 60%; z-index: 0;
  background: linear-gradient(100deg, transparent, var(--tm-accent-fg), transparent);
  opacity: .16; pointer-events: none; transform: translateX(-120%) skewX(-18deg);
  animation: cpkHeroShine 3s ease-in-out 1.2s infinite;
}
.tm-ds .cpk-hero__importall > * { position: relative; z-index: 1; }
/* QA #6542: `left` animasyonu bir LAYOUT özelliği (her karede yerleşim hesabı) →
   yalnız `transform: translateX` (compositor; görsel sonuç birebir). translateX %'i
   ELEMENT-genişliği (45%) göreli: -120% tam sola, 240% tam sağa süpürür.
   ui-reference-spec.md: `left`/`top` animasyonu YASAK. */
/* Modal sahneye ÖNE gelir: kullanıcı "modal öne çıkmalı" dedi (2026-09-16). Perde tek başına
   yetmiyordu — diyalog ZATEN oradaymış gibi beliriyordu. 180ms'lik küçük bir yaklaşma,
   "bu şimdi açıldı ve öndedir" sinyalini veriyor. Bütçe: giriş ≤600ms, yalnız
   transform/opacity, tekrarsız, `backwards` (ilk karede görünmez içerik yok).
   prefers-reduced-motion bloğu `.cpk-modal__dialog`'u zaten kapsıyor. */
@keyframes cpkModalIn { from { opacity: 0; transform: translate(-50%, -50%) scale(.97); } to { opacity: 1; transform: translate(-50%, -50%) scale(1); } }
@keyframes cpkHeroShine { 0% { transform: translateX(-120%) skewX(-18deg); } 60%, 100% { transform: translateX(240%) skewX(-18deg); } }

/* 4) Gerçek-veri highlight rozetleri — canlı SICAK zemin + yumuşak nabız → "bu hafta
      ne var"a göz çeker (yalnız --hl; kabuk hapları sabit kalır). transform-scale,
      layout kıpırdamaz.
      🔴 KOYU-MOD FIX: eski beyaz-zemin + `--tm-accent-fg` metin, `dark-mode.css`'in
      `span{color:inherit}` shim'iyle metni beyaza zorluyordu → beyaz-üstü-beyaz
      (GÖRÜNMEZ; UI'nın 3 koyu-mod kusuruyla aynı sınıf). Çözüm: sıcak promo gradient
      zemin + beyaz metin (`on-accent`); shim beyaza çözse bile sonuç DOĞRU (beyaz
      metin sıcak zeminde ≥4.5:1 iki modda) — ve mavi hero'da daha çok pop eder. */
@keyframes cpkHeroPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.045); } }
.tm-ds .cpk-hero__pill--hl { background: linear-gradient(135deg, var(--tm-promo-2-from), var(--tm-promo-2-to)); border-color: transparent; color: var(--tm-on-accent); animation: cpkHeroPulse 2.8s ease-in-out infinite; }
.tm-ds .cpk-hero__pill--hl [data-lucide] { color: var(--tm-on-accent); }

/* 5) "Nasıl çalışır" kartı — hover kalkış + oto-dönen adım geçişinde yumuşak fade
      (JS innerHTML'i değiştirince taze `.cpk-hero__how-step` animasyonu tetikler). */
.tm-ds .cpk-hero__how { transition: transform .18s ease, background .18s ease, color .18s ease, border-color .18s ease; }
.tm-ds .cpk-hero__how:hover { transform: translateY(-2px); }
.tm-ds .cpk-hero__how-step { animation: cpkHeroRise .4s ease backwards; }

/* 6) Hareket-azalt: TÜM hero hareketi durur; içerik doğal/görünür kalır. */
@media (prefers-reduced-motion: reduce) {
  .tm-ds .cpk-hero::before,
  .tm-ds .cpk-hero__kicker, .tm-ds .cpk-hero__t, .tm-ds .cpk-hero__s,
  .tm-ds .cpk-hero__pills, .tm-ds .cpk-hero__cta, .tm-ds .cpk-hero__right,
  .tm-ds .cpk-hero__importall::after, .tm-ds .cpk-hero__pill--hl,
  .tm-ds .cpk-hero__how-step { animation: none; }
  .tm-ds .cpk-hero__importall, .tm-ds .cpk-hero__how { transition: none; }
  .tm-ds .cpk-hero__importall:hover, .tm-ds .cpk-hero__how:hover { transform: none; }
}

/* ---------- Full tutorial overlay (dropshipping "how it works") ---------- */
:is(.tm-ds, body.tm-ds-shell) .cpk-tut { position: fixed; inset: 0; z-index: 2100; display: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut.is-open { display: block; }
/* Tutorial perdesi: eskiden blur YOKTU (opacity .6). Artık cpk-modal ile AYNI: görünür
   moderat blur(8px) + var(--tm-surface-overlay). (Global .tm-modal 4px; kullanıcı katalog
   modallarında 4px'i "hiç yok" buldu → burada bilinçli olarak 8px, ikisi birbiriyle tutarlı.) */
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__backdrop { position: absolute; inset: 0; background: rgba(15,23,42,.5); opacity: 1; -webkit-backdrop-filter: blur(7px); backdrop-filter: blur(7px); }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__dialog { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: min(700px, calc(100vw - 28px)); max-height: calc(100vh - 40px); display: flex; flex-direction: column; gap: var(--tm-space-2); overflow: hidden; background: var(--tm-surface); border: 1px solid var(--tm-border); border-radius: var(--tm-radius-overlay); box-shadow: var(--tm-shadow-modal); animation: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__top { position: relative; padding: var(--tm-space-4) var(--tm-space-6) 0; }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__kicker { display: inline-flex; align-items: center; gap: var(--tm-space-1); font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--tm-accent-600); }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__close { position: absolute; top: var(--tm-space-3); right: var(--tm-space-3); width: 32px; height: 32px; border-radius: var(--tm-radius-control); border: 1px solid var(--tm-border); background: var(--tm-ink-100); color: var(--tm-text-muted); display: grid; place-items: center; cursor: pointer; transition: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__close:hover { color: var(--tm-text-primary); }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__flow { display: flex; align-items: flex-start; padding: var(--tm-space-4) var(--tm-space-1) var(--tm-space-2); }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__node { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; gap: var(--tm-space-1); width: 78px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__node-ic { position: relative; width: 40px; height: 40px; border-radius: var(--tm-radius-full); display: grid; place-items: center; background: var(--tm-ink-100); border: 2px solid var(--tm-border); color: var(--tm-text-muted); transition: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__node.is-active .cpk-tut__node-ic { background: var(--tm-accent-500); border-color: var(--tm-accent-500); color: var(--tm-text-on-brand); }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__node.is-done .cpk-tut__node-ic { background: var(--tm-accent-50); border-color: var(--tm-accent-600); color: var(--tm-accent-600); }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__node-lbl { font-size: 11px; font-weight: 500; color: var(--tm-text-muted); text-align: center; line-height: 1.25; }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__node.is-active .cpk-tut__node-lbl { color: var(--tm-text-primary); }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__conn { flex: 1 1 auto; height: 2px; align-self: center; background: var(--tm-border); }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__conn.is-done { background: var(--tm-accent-600); }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__body { padding: var(--tm-space-2) var(--tm-space-6) 0; display: flex; flex-direction: column; align-items: center; gap: var(--tm-space-2); text-align: center; }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__viz { width: 100%; max-width: 300px; padding: var(--tm-space-3); background: var(--tm-ink-100); border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__viz svg { width: 100%; height: auto; max-height: 150px; display: block; }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__stepno { font-family: var(--cpk-mono); font-size: 12px; font-weight: 500; color: var(--tm-accent-600); }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__h { font-size: 18px; font-weight: 700; color: var(--tm-text-primary); margin: 0; }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__d { font-size: 14px; line-height: 20px; color: var(--tm-text-secondary); max-width: 480px; margin: 0 auto; }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__d b { color: var(--tm-text-primary); }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__foot { display: flex; align-items: center; justify-content: space-between; gap: var(--tm-space-3); padding: var(--tm-space-4) var(--tm-space-6); }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__skip { background: none; border: 0; color: var(--tm-text-muted); font-size: 14px; font-weight: 500; cursor: pointer; font-family: inherit; }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__nav { display: flex; gap: var(--tm-space-2); }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__btn { display: inline-flex; align-items: center; gap: var(--tm-space-1); height: 36px; padding: 0 var(--tm-space-4); border-radius: var(--tm-radius-control); font-size: 14px; font-weight: 600; cursor: pointer; font-family: inherit; border: 1px solid var(--tm-border); background: var(--tm-surface); color: var(--tm-text-primary); transition: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__btn--primary { background: var(--tm-accent-500); color: var(--tm-text-on-brand); border-color: transparent; box-shadow: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__btn--primary:hover { transform: none; box-shadow: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-tut__btn:disabled { opacity: .4; cursor: not-allowed; }
@media (max-width: 560px) { :is(.tm-ds, body.tm-ds-shell) .cpk-tut__node-lbl { display: none; } :is(.tm-ds, body.tm-ds-shell) .cpk-tut__node { width: 40px; } :is(.tm-ds, body.tm-ds-shell) .cpk-tut__h { font-size: 16px; } }

/* ---------- Katalog KPI kartları ---------- */
.tm-ds .cpk-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--tm-space-3); }
.tm-ds .cpk-kpi { display: flex; align-items: center; gap: var(--tm-space-3); background: var(--tm-bg-surface); border: 1px solid var(--tm-border); border-radius: var(--tm-radius-card); padding: var(--tm-space-3) var(--tm-space-4); box-shadow: var(--tm-shadow-card); transition: none; }
.tm-ds .cpk-kpi:hover { transform: none; box-shadow: var(--tm-shadow-card); }
.tm-ds .cpk-kpi__ic { flex: 0 0 auto; width: 36px; height: 36px; border-radius: var(--tm-radius-control); display: grid; place-items: center; background: var(--tm-accent-bg); color: var(--tm-accent-fg); }
.tm-ds .cpk-kpi__ic--ok { background: var(--tm-success-bg); color: var(--tm-success-fg); }
.tm-ds .cpk-kpi__ic--sale { background: var(--tm-warning-bg); color: var(--tm-warning-fg); }
.tm-ds .cpk-kpi__ic--cat { background: var(--tm-bg-subtle); color: var(--tm-text-secondary); }
.tm-ds .cpk-kpi__ic [data-lucide] { width: 18px; height: 18px; }
.tm-ds .cpk-kpi__body { min-width: 0; display: flex; flex-direction: column; gap: var(--tm-space-1); }
.tm-ds .cpk-kpi__v { font-family: var(--cpk-mono); font-variant-numeric: tabular-nums; font-size: var(--tm-type-title); font-weight: var(--tm-weight-bold); line-height: 1.1; color: var(--tm-text-primary); }
.tm-ds .cpk-kpi__l { font-size: var(--tm-type-caption); font-weight: var(--tm-weight-medium); color: var(--tm-text-muted); }
@media (max-width: 820px) { .tm-ds .cpk-kpis { grid-template-columns: repeat(2, 1fr); } }

/* ---------- Pazaryeri bağla nudge (secondary connect banner) ---------- */
.tm-ds .cpk-connect-nudge { position: relative; display: flex; align-items: center; gap: var(--tm-space-4); padding: var(--tm-space-3) var(--tm-space-4); border-radius: var(--tm-radius-card); overflow: hidden; background: var(--tm-bg-surface); border: 1px solid var(--tm-border); box-shadow: var(--tm-shadow-card); color: var(--tm-text-primary); }
.tm-ds .cpk-connect-nudge::before { display: none; }
.tm-ds .cpk-connect-nudge__ic { position: relative; z-index: 1; flex: 0 0 auto; width: 38px; height: 38px; border-radius: var(--tm-radius-control); display: flex; align-items: center; justify-content: center; background: var(--tm-accent-bg); box-shadow: none; animation: none; }
.tm-ds .cpk-connect-nudge__ic [data-lucide] { width: 20px; height: 20px; color: var(--tm-accent-fg); }
.tm-ds .cpk-connect-nudge__body { position: relative; z-index: 1; flex: 1; display: flex; flex-direction: column; gap: 0; min-width: 0; }
.tm-ds .cpk-connect-nudge__t { font-size: var(--tm-type-body); font-weight: var(--tm-weight-bold); color: var(--tm-text-primary); margin: 0; }
.tm-ds .cpk-connect-nudge__s { font-size: var(--tm-type-caption); color: var(--tm-text-secondary); margin: 0; }
.tm-ds .cpk-connect-nudge__actions { position: relative; z-index: 1; flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-end; gap: var(--tm-space-1); }
.tm-ds .cpk-connect-nudge__go { display: inline-flex; align-items: center; gap: var(--tm-space-1); font-weight: var(--tm-weight-bold); font-size: var(--tm-type-body); white-space: nowrap; text-decoration: none; color: var(--tm-on-accent); background: var(--tm-accent-solid); height: 36px; padding: 0 var(--tm-space-4); border-radius: var(--tm-radius-control); box-shadow: none; transition: none; }
.tm-ds .cpk-connect-nudge__go:hover { transform: none; box-shadow: none; color: var(--tm-on-accent); }
.tm-ds .cpk-connect-nudge__alt { font-size: var(--tm-type-micro); color: var(--tm-text-muted); text-decoration: underline; white-space: nowrap; }
@media (max-width: 720px) { .tm-ds .cpk-connect-nudge { flex-wrap: wrap; } .tm-ds .cpk-connect-nudge__actions { width: 100%; align-items: stretch; } .tm-ds .cpk-connect-nudge__go { justify-content: center; } }

/* ---------- Upsell / weekly marketing bands ---------- */
.tm-ds .cpk-upsell { position: relative; display: flex; align-items: center; gap: var(--tm-space-4); padding: var(--tm-space-3) var(--tm-space-4); border-radius: var(--tm-radius-card); overflow: hidden; background: var(--tm-bg-surface); border: 1px solid var(--tm-border); box-shadow: var(--tm-shadow-card); }
.tm-ds .cpk-upsell::before { display: none; }
.tm-ds .cpk-upsell__icon { flex: 0 0 auto; width: 36px; height: 36px; display: grid; place-items: center; border-radius: var(--tm-radius-control); background: var(--tm-warning-bg); box-shadow: none; animation: none; }
.tm-ds .cpk-upsell__icon [data-lucide] { width: 18px; height: 18px; color: var(--tm-warning-fg); }
.tm-ds .cpk-upsell__txt { position: relative; z-index: 1; flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0; }
.tm-ds .cpk-upsell__t { font-size: var(--tm-type-body); font-weight: var(--tm-weight-bold); color: var(--tm-text-primary); margin: 0; }
.tm-ds .cpk-upsell__t b { color: var(--tm-accent-fg); }
.tm-ds .cpk-upsell__s { font-size: var(--tm-type-caption); color: var(--tm-text-secondary); margin: 0; }
.tm-ds .cpk-upsell__cta { position: relative; z-index: 1; flex: 0 0 auto; display: inline-flex; align-items: center; gap: var(--tm-space-1); height: 36px; padding: 0 var(--tm-space-4); border-radius: var(--tm-radius-control); text-decoration: none; font-size: var(--tm-type-caption); font-weight: var(--tm-weight-bold); white-space: nowrap; color: var(--tm-on-accent); background: var(--tm-accent-solid); box-shadow: none; transition: none; }
.tm-ds .cpk-upsell__cta:hover { transform: none; box-shadow: none; color: var(--tm-on-accent); }

.tm-ds .cpk-weekly { display: flex; flex-direction: column; gap: var(--tm-space-3); padding: var(--tm-space-4); border-radius: var(--tm-radius-card); background: var(--tm-bg-surface); border: 1px solid var(--tm-border); box-shadow: var(--tm-shadow-card); overflow: hidden; position: relative; animation: none; }
.tm-ds .cpk-weekly::before { display: none; }
.tm-ds .cpk-weekly__head { position: relative; z-index: 1; display: flex; align-items: center; gap: var(--tm-space-2); }
/* Aktarım durumu paneli (#6592). Kullanıcı 2026-09-16: "kullanıcı filtreleme yaptığında kaç
   tane ürün aktardığını ya da aktarmadığını görebilmeli" + "bu ürünler pazaryerine gönderilmez"
   sebeplerini görmek istedi. Üç sayı + sebep çipleri; KPI'ların altında, hero'nun devamı gibi.
   ⚠ Sayılar KART DEĞİL: üç ayrı kart yapmak dikey bütçeyi şişirirdi ve kullanıcı bu panelde
   üç turdur "karmaşık, dağınık" diyor. Tek yüzey, tek satır, ayrım RENKLE değil İKONLA+renkle
   (renk körü kullanıcıda ikon taşır). Sarı/yeşil yalnız DESTEK sinyali. */
.tm-ds .cpk-transfer { display: flex; flex-direction: column; gap: var(--tm-space-2); padding: var(--tm-space-3) var(--tm-space-4); border-radius: var(--tm-radius-card); background: var(--tm-bg-surface); border: 1px solid var(--tm-border); box-shadow: var(--tm-shadow-card); }
.tm-ds .cpk-transfer__nums { display: flex; flex-wrap: wrap; align-items: center; gap: var(--tm-space-2) var(--tm-space-4); }
.tm-ds .cpk-transfer__num { display: inline-flex; align-items: center; gap: var(--tm-space-1); font-size: var(--tm-type-body); line-height: var(--tm-type-body-lh); color: var(--tm-text-secondary); }
.tm-ds .cpk-transfer__num b { font-size: var(--tm-type-heading); font-weight: var(--tm-weight-bold); color: var(--tm-text-primary); font-variant-numeric: tabular-nums; }
.tm-ds .cpk-transfer__num [data-lucide] { width: 16px; height: 16px; color: var(--tm-text-muted); }
.tm-ds .cpk-transfer__num--ok [data-lucide] { color: var(--tm-success-fg); }
.tm-ds .cpk-transfer__num--ok b { color: var(--tm-success-fg); }
.tm-ds .cpk-transfer__num--warn [data-lucide] { color: var(--tm-warning-fg); }
.tm-ds .cpk-transfer__num--warn b { color: var(--tm-warning-fg); }
/* --new: "henüz aktarmadığın" — bu bir SORUN değil, bir FIRSAT. O yüzden uyarı sarısı değil
   accent tonu: panelde üç sayı durum bildirirken bu dördüncüsü büyüme CTA'sı. */
.tm-ds .cpk-transfer__num--new [data-lucide] { color: var(--tm-accent-fg); }
.tm-ds .cpk-transfer__num--new b { color: var(--tm-accent-fg); }
/* Sebep çipleri: "gönderilemez" sayısının AÇIKLAMASI — sayının altında, ikincil ağırlıkta.
   Tıklanabilir değiller (bugün filtreye bağlı değil); o yüzden buton görünümü YOK — çip
   görünümü verip tıklanmayınca "ölü buton" yalanı üretmek istemedim (bkz. #6560). */
.tm-ds .cpk-transfer__reasons { display: flex; flex-wrap: wrap; gap: var(--tm-space-2); }
.tm-ds .cpk-transfer__reason { display: inline-flex; align-items: center; gap: var(--tm-space-1); padding: 0 var(--tm-space-2); height: 24px; border-radius: var(--tm-radius-full); background: var(--tm-warning-bg); color: var(--tm-warning-fg); font-size: var(--tm-type-caption); line-height: var(--tm-type-caption-lh); font-weight: var(--tm-weight-medium); }
.tm-ds .cpk-transfer__reason [data-lucide] { width: 13px; height: 13px; }
@media (max-width: 700px) {
  .tm-ds .cpk-transfer__nums { gap: var(--tm-space-1) var(--tm-space-3); }
  .tm-ds .cpk-transfer__num b { font-size: var(--tm-type-body); }
}

.tm-ds .cpk-weekly__ic { width: 32px; height: 32px; flex: 0 0 auto; display: grid; place-items: center; border-radius: var(--tm-radius-control); background: var(--tm-warning-bg); box-shadow: none; }
.tm-ds .cpk-weekly__ic [data-lucide] { width: 16px; height: 16px; color: var(--tm-warning-fg); }
.tm-ds .cpk-weekly__t { font-size: var(--tm-type-heading); font-weight: var(--tm-weight-bold); color: var(--tm-text-primary); margin: 0; }
/* Bu kural BAŞLIK bloğu için yazılmıştı ama `.cpk-weekly__tabs` de head'in bir `div` çocuğu;
   `> div` (0,2,1) sekmelerin kendi `.cpk-weekly__tabs` (0,2,0) kuralını YENİYORDU →
   `flex-direction: column` sekmelere de uygulanıp iki sekmeyi ALT ALTA diziyordu
   (ölçüldü 2026-09-16, 5 genişlikte aynı: tabs 101x56, buton y'leri [33, 61]).
   `:not()` ile daraltıldı; ayrıca başlık bloğu `flex: 1 1 auto` ile boşluğu yiyor, böylece
   sekmeler ve toggle `margin-left:auto` yarışına girmeden sağa yaslanıyor — iki auto margin
   boşluğu paylaşınca sekmeler ORTADA kalıyordu (1600px: tabs.x=924, toggle.x=1537). */
.tm-ds .cpk-weekly__head > div:not(.cpk-weekly__tabs) { display: flex; flex-direction: column; gap: 0; flex: 1 1 auto; min-width: 0; }
.tm-ds .cpk-weekly__s { font-size: var(--tm-type-caption); color: var(--tm-text-secondary); margin: 0; }
.tm-ds .cpk-weekly__toggle { position: relative; z-index: 2; margin-left: auto; flex: 0 0 auto; width: 30px; height: 30px; display: grid; place-items: center; border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); cursor: pointer; background: var(--tm-bg-subtle); color: var(--tm-text-secondary); transition: none; }
.tm-ds .cpk-weekly__toggle [data-lucide] { width: 16px; height: 16px; transition: none; }
.tm-ds .cpk-weekly.is-collapsed .cpk-weekly__track { display: none; }
.tm-ds .cpk-weekly.is-collapsed .cpk-weekly__toggle [data-lucide] { transform: rotate(180deg); }
.tm-ds .cpk-weekly__track { position: relative; z-index: 1; display: flex; gap: var(--tm-space-3); overflow-x: auto; padding-bottom: var(--tm-space-1); scroll-snap-type: x mandatory; scrollbar-width: thin; }
/* 2026-09-14 KÖK FIX (canlı P1): `flex-grow: 1` TEK/az kartta track'i doldurup
   `aspect-ratio: 1/1` görselini 1080px'e şişiriyordu. Kart sabit genişlikte
   kalır; şerit az kartta sola yaslanır (doğru davranış). Acil override
   `ds-catalog-promo.css:17`'de duruyor, bu kökle gereksizleşir. */
.tm-ds .cpk-wk-card { flex: 0 0 168px; max-width: 168px; min-width: 150px; scroll-snap-align: start; background: var(--tm-bg-surface); border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); overflow: hidden; display: flex; flex-direction: column; box-shadow: none; }
.tm-ds .cpk-wk-card__imgwrap { aspect-ratio: 1/1; background: var(--tm-bg-subtle); position: relative; display: grid; place-items: center; overflow: hidden; }
.tm-ds .cpk-wk-card__imgwrap img { width: 100%; height: 100%; object-fit: cover; }
.tm-ds .cpk-wk-card__ph [data-lucide] { width: 28px; height: 28px; color: var(--tm-text-muted); }
.tm-ds .cpk-wk-card__reason { position: absolute; top: var(--tm-space-1); left: var(--tm-space-1); font-size: var(--tm-type-micro); font-weight: var(--tm-weight-bold); color: var(--tm-on-accent); padding: 0 var(--tm-space-2); border-radius: var(--tm-radius-full); background: var(--tm-accent-solid); box-shadow: none; }
.tm-ds .cpk-wk-card__body { padding: var(--tm-space-2) var(--tm-space-3) var(--tm-space-3); display: flex; flex-direction: column; gap: var(--tm-space-1); flex: 1; }
.tm-ds .cpk-wk-card__name { font-size: var(--tm-type-caption); font-weight: var(--tm-weight-medium); color: var(--tm-text-primary); line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.tm-ds .cpk-wk-card__price { font-family: var(--cpk-mono); font-size: var(--tm-type-body); font-weight: var(--tm-weight-bold); color: var(--tm-text-primary); }
.tm-ds .cpk-wk-card__sales { font-size: var(--tm-type-micro); color: var(--tm-text-muted); font-family: var(--cpk-mono); }
.tm-ds .cpk-wk-card__pick { margin-top: auto; height: 30px; border-radius: var(--tm-radius-control); border: 1px solid var(--tm-border); background: var(--tm-bg-surface); color: var(--tm-accent-fg); font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: var(--tm-space-1); transition: none; }
.tm-ds .cpk-wk-card__pick.is-selected { background: var(--tm-accent-solid); color: var(--tm-on-accent); border-color: transparent; }

/* ---------- Toolbar — ONE row, search left · filters/sort right (Apex) ---------- */
/* Ölçüm (2026-09-14, 1280px): 7 kontrolün toplam genişliği 1234px + boşluklar,
   kullanılabilir 956px → TEK SATIR fiziksel olarak mümkün değil (yalnız ≥1640'ta
   sığıyor). Sözleşme: arama solda sabit, filtreler sağa yaslı; taşarsa ikinci
   satır da SAĞA yaslanır (rastgele değil, tasarlanmış görünsün). Fiyat aralığını
   filtre-popover'ına taşımak ayrı kalem (docs/backlog.md B-UI-CPK-1). */
.tm-ds .cpk-toolbar { display: flex; gap: var(--tm-space-2); flex-wrap: wrap; align-items: center; justify-content: flex-end; }
.tm-ds .cpk-search { flex: 1 1 260px; min-width: 200px; max-width: 300px; margin-right: auto; position: relative; }
.tm-ds label.cpk-search > i[data-lucide], .tm-ds label.cpk-search > svg[data-lucide] { position: absolute; left: var(--tm-space-3); top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: var(--tm-text-muted); pointer-events: none; z-index: 1; }
.tm-ds .cpk-search input { width: 100%; height: 36px; padding: 0 var(--tm-space-3) 0 var(--tm-space-8); border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); font-size: var(--tm-type-body); font-family: inherit; background: var(--tm-bg-surface); color: var(--tm-text-primary); box-sizing: border-box; box-shadow: none; }
.tm-ds .cpk-search input::placeholder { color: var(--tm-text-muted); }
.tm-ds .cpk-select { flex: 0 1 auto; max-width: 180px; height: 36px; padding: 0 var(--tm-space-6) 0 var(--tm-space-3); border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); font-size: var(--tm-type-caption); font-family: inherit; background: var(--tm-bg-surface); color: var(--tm-text-primary); min-width: 140px; box-shadow: none; }
.tm-ds .cpk-selall, .tm-ds .cpk-chip { display: inline-flex; align-items: center; gap: var(--tm-space-1); height: 36px; padding: 0 var(--tm-space-3); border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); background: var(--tm-bg-surface); color: var(--tm-text-primary); font-size: var(--tm-type-caption); font-weight: var(--tm-weight-medium); cursor: pointer; white-space: nowrap; transition: none; }
.tm-ds .cpk-chip [data-lucide], .tm-ds .cpk-selall [data-lucide] { width: 14px; height: 14px; color: var(--tm-warning-fg); }
.tm-ds .cpk-chip:hover, .tm-ds .cpk-selall:hover { background: var(--tm-bg-subtle); }
.tm-ds .cpk-chip.is-active { background: var(--tm-accent-solid); border-color: transparent; color: var(--tm-on-accent); }
.tm-ds .cpk-chip.is-active [data-lucide] { color: var(--tm-on-accent); }
.tm-ds .cpk-pricerange { display: inline-flex; align-items: center; gap: var(--tm-space-1); }
.tm-ds .cpk-price-in { width: 68px; height: 36px; padding: 0 var(--tm-space-2); box-sizing: border-box; border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); font-size: var(--tm-type-caption); font-family: inherit; color: var(--tm-text-primary); background: var(--tm-bg-surface); }
.tm-ds .cpk-pricerange__sep { color: var(--tm-text-muted); }

/* ---------- Sonuç sayacı + filtre çipleri ---------- */
.tm-ds .cpk-result-meta { font-size: var(--tm-type-caption); color: var(--tm-text-muted); display: flex; align-items: center; gap: var(--tm-space-2); }
.tm-ds .cpk-result-meta b { font-family: var(--cpk-mono); font-weight: var(--tm-weight-bold); color: var(--tm-text-primary); }
.tm-ds .cpk-filterchips { display: inline-flex; flex-wrap: wrap; gap: var(--tm-space-1); }
.tm-ds .cpk-fchip { display: inline-flex; align-items: center; gap: var(--tm-space-1); font-size: var(--tm-type-micro); font-weight: var(--tm-weight-medium); color: var(--tm-text-primary); background: var(--tm-bg-subtle); border: 1px solid var(--tm-border); border-radius: var(--tm-radius-full); padding: 0 var(--tm-space-1) 0 var(--tm-space-2); }
.tm-ds .cpk-fchip button { background: none; border: 0; cursor: pointer; color: var(--tm-text-muted); display: inline-flex; padding: 0; }
.tm-ds .cpk-fchip button:hover { color: var(--tm-danger-fg); }
.tm-ds .cpk-fchip [data-lucide] { width: 12px; height: 12px; }

/* ---------- Results column — grid/state/loadmore share gap, no margin ---------- */
.tm-ds #cpkResults { display: flex; flex-direction: column; gap: var(--tm-space-6); }
/* ---------- Grid — 16px gap, cards on the reference grid ---------- */
.tm-ds .cpk-grid, .tm-ds .cpk-skel { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--cpk-col-min), 1fr)); gap: var(--tm-space-4); align-items: stretch; }
.tm-ds .cpk-skel__c { border-radius: var(--tm-radius-card); background: var(--tm-bg-subtle); }
.tm-ds .cpk-skel__c:nth-child(odd) { height: 298px; }
.tm-ds .cpk-skel__c:nth-child(even) { height: 290px; }

/* ---------- Product card — 14px radius, hairline + one soft shadow, no lift ---------- */
.tm-ds .cpk-card { display: flex; flex-direction: column; color: var(--tm-text-primary); border: 1px solid var(--tm-border); border-radius: var(--tm-radius-card); overflow: hidden; background: var(--tm-bg-surface); box-shadow: var(--tm-shadow-card); transition: border-color 120ms ease-out, background-color 120ms ease-out; cursor: pointer; position: relative; height: 100%; animation: cpkCardIn 160ms ease-out backwards; }
.tm-ds .cpk-card:hover { transform: none; box-shadow: var(--tm-shadow-card); border-color: var(--tm-border-strong, var(--tm-border)); }
.tm-ds .cpk-card.is-selected { border-color: var(--tm-accent-fg); box-shadow: var(--tm-shadow-card); background: var(--tm-bg-surface); }
.tm-ds .cpk-card__imgwrap { aspect-ratio: 1/1; background: var(--tm-bg-subtle); display: flex; align-items: center; justify-content: center; overflow: hidden; flex-shrink: 0; position: relative; }
.tm-ds .cpk-card__imgwrap img { width: 100%; height: 100%; object-fit: contain; transition: none; }
.tm-ds .cpk-card:hover .cpk-card__imgwrap img { transform: none; }
.tm-ds .cpk-card__ph { color: var(--tm-text-muted); opacity: .5; }
.tm-ds .cpk-card__ph [data-lucide] { width: 32px; height: 32px; }
.tm-ds .cpk-card__body { padding: var(--tm-space-3); display: flex; flex-direction: column; gap: var(--tm-space-2); flex: 1; }
.tm-ds .cpk-card__name { font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold); color: var(--tm-text-primary); line-height: 1.35; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; min-height: calc(var(--tm-type-caption-lh) * 2); }
.tm-ds .cpk-card__meta { display: flex; align-items: center; justify-content: space-between; gap: var(--tm-space-2); margin-top: auto; }
.tm-ds .cpk-card__price { font-size: var(--tm-type-body); font-weight: var(--tm-weight-bold); color: var(--tm-text-primary); font-family: var(--cpk-mono); }
.tm-ds .cpk-card__profit { margin-top: auto; display: flex; flex-direction: column; gap: 0; }
.tm-ds .cpk-card__sugg { display: flex; align-items: baseline; gap: var(--tm-space-1); flex-wrap: wrap; font-size: var(--tm-type-micro); color: var(--tm-text-muted); }
.tm-ds .cpk-card__sugg b { font-size: var(--tm-type-body); font-weight: var(--tm-weight-bold); color: var(--tm-text-primary); font-family: var(--cpk-mono); }
.tm-ds .cpk-card__gain { display: inline-flex; align-items: center; gap: var(--tm-space-1); flex-wrap: wrap; font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold); color: var(--tm-success-fg); }
.tm-ds .cpk-card__gain [data-lucide] { width: 13px; height: 13px; }
.tm-ds .cpk-card__gain b { font-family: var(--cpk-mono); }
.tm-ds .cpk-card__margin { font-size: var(--tm-type-micro); font-weight: var(--tm-weight-bold); color: var(--tm-success-fg); background: var(--tm-success-bg); border-radius: var(--tm-radius-full); padding: 0 var(--tm-space-2); }
.tm-ds .cpk-card__costline { font-size: var(--tm-type-micro); color: var(--tm-text-muted); }
.tm-ds .cpk-card__howto { background: none; border: 0; padding: 0; cursor: help; font-size: var(--tm-type-micro); color: var(--tm-accent-fg); text-decoration: underline dotted; }
.tm-ds .cpk-card__badge--profit, .tm-ds .cpk-card__badge--topprofit { background: var(--tm-success-bg); color: var(--tm-success-fg); }
.tm-ds .cpk-card__badge--highmargin { background: var(--tm-warning-bg); color: var(--tm-warning-fg); }
.tm-ds .cpk-blurnum { filter: blur(5px); user-select: none; pointer-events: none; opacity: .85; }
.tm-ds .cpk-card__price--locked, .tm-ds .cpk-md-info__price--locked { display: inline-flex; align-items: center; gap: var(--tm-space-1); cursor: pointer; color: var(--tm-accent-fg); position: relative; }
.tm-ds .cpk-card__price--locked [data-lucide], .tm-ds .cpk-md-info__price--locked [data-lucide] { width: 14px; height: 14px; color: var(--tm-warning-fg); filter: none; }
.tm-ds .cpk-card__pick--upgrade { background: var(--tm-warning-fg); color: var(--tm-on-accent); border: none; }
.tm-ds .cpk-card__pick--upgrade [data-lucide] { color: var(--tm-on-accent); }
.tm-ds .cpk-card--locked::after { content: ''; position: absolute; inset: 0; border-radius: var(--tm-radius-card); outline: 1px solid var(--tm-warning-fg); outline-offset: -1px; pointer-events: none; }
.tm-ds .cpk-card__stock { display: inline-flex; align-items: center; gap: var(--tm-space-1); font-size: var(--tm-type-micro); color: var(--tm-text-muted); font-family: var(--cpk-mono); }
.tm-ds .cpk-card__stock [data-lucide] { width: 11px; height: 11px; }
.tm-ds .cpk-card__stock--oos { color: var(--tm-warning-fg); font-weight: var(--tm-weight-semibold); }
.tm-ds .cpk-card__cat { position: absolute; top: var(--tm-space-2); left: var(--tm-space-2); font-size: var(--tm-type-micro); font-weight: var(--tm-weight-bold); padding: 0 var(--tm-space-2); border-radius: var(--tm-radius-full); background: var(--tm-ink-900); opacity: .82; color: var(--tm-on-accent); text-transform: uppercase; max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-ds .cpk-card__pick { display: flex; align-items: center; justify-content: center; gap: var(--tm-space-1); height: 32px; border-radius: var(--tm-radius-control); border: 1px solid var(--tm-border); background: var(--tm-bg-surface); color: var(--tm-accent-fg); font-size: var(--tm-type-caption); font-weight: var(--tm-weight-bold); transition: none; }
/* Feed yönetim kartı (#6620): kart `mode='manage'` iken "Seç" yerine ya DÜZELT ya HAZIR gelir.
   İkisi de `.cpk-card__pick` ile AYNI kutuyu kullanır (32px, aynı radius) → kart yüksekliği
   moda göre değişmiyor, ızgara zıplamıyor.
   🔴 `--fix` bir <a>, `--ready` bir <div>: biri gidilecek bir yer, diğeri bir durum. Bu yüzden
   yalnız `--fix` imleç/hover alıyor — durum rozetine buton hissi vermek "ölü buton" yalanıdır
   (bkz. #6560 ve .cpk-transfer__reason kararı). ⚠ `cursor: default` AÇIKÇA gerekli: `.cpk-card`
   tıklanabilir olduğu için `cursor: pointer` çocuklara MİRAS kalıyor (testte yakalandı).
   ⚠ `box-sizing: border-box` de açıkça: `<a>`/`<div>` content-box kalınca 1px kenarlık kutuyu
   34px yapıyor ve `.cpk-card__pick` (32px, buton) ile hizasız duruyordu — kart yüksekliği
   moda göre zıplardı. Ölçüldü: 34 vs 32. */
.tm-ds .cpk-card__fix { box-sizing: border-box; display: flex; align-items: center; justify-content: center; gap: var(--tm-space-1); height: 32px; border-radius: var(--tm-radius-control); border: 1px solid var(--tm-warning-fg); background: var(--tm-warning-bg); color: var(--tm-warning-fg); font-size: var(--tm-type-caption); font-weight: var(--tm-weight-bold); text-decoration: none; cursor: pointer; transition: transform 160ms ease-out; }
.tm-ds .cpk-card__fix:hover { transform: translateY(-1px); }
.tm-ds .cpk-card__fix [data-lucide] { width: 13px; height: 13px; }
.tm-ds .cpk-card__ready { box-sizing: border-box; cursor: default; display: flex; align-items: center; justify-content: center; gap: var(--tm-space-1); height: 32px; border-radius: var(--tm-radius-control); border: 1px solid var(--tm-success-fg); background: var(--tm-success-bg); color: var(--tm-success-fg); font-size: var(--tm-type-caption); font-weight: var(--tm-weight-bold); }
.tm-ds .cpk-card__ready [data-lucide] { width: 13px; height: 13px; }
@media (prefers-reduced-motion: reduce) { .tm-ds .cpk-card__fix { transition: none; } .tm-ds .cpk-card__fix:hover { transform: none; } }
.tm-ds .cpk-card:hover .cpk-card__pick { border-color: var(--tm-accent-fg); background: var(--tm-accent-bg); }
.tm-ds .cpk-card.is-selected .cpk-card__pick { background: var(--tm-accent-solid); color: var(--tm-on-accent); border-color: transparent; }
.tm-ds .cpk-card__pick [data-lucide] { width: 14px; height: 14px; }
.tm-ds .cpk-checkmark { position: absolute; top: var(--tm-space-2); right: var(--tm-space-2); width: 22px; height: 22px; border-radius: var(--tm-radius-full); background: var(--tm-accent-solid); color: var(--tm-on-accent); display: none; align-items: center; justify-content: center; box-shadow: none; animation: none; }
.tm-ds .cpk-card.is-selected .cpk-checkmark { display: flex; }
.tm-ds .cpk-checkmark [data-lucide] { width: 13px; height: 13px; }
.tm-ds .cpk-card__detail, .tm-ds .cpk-card__fav { position: absolute; top: var(--tm-space-2); z-index: 3; width: 26px; height: 26px; display: grid; place-items: center; border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); cursor: pointer; background: var(--tm-bg-surface); color: var(--tm-text-secondary); box-shadow: none; transition: none; }
.tm-ds .cpk-card__detail { left: var(--tm-space-2); opacity: 0; }
.tm-ds .cpk-card:hover .cpk-card__detail { opacity: 1; }
.tm-ds .cpk-card__detail:hover { color: var(--tm-accent-fg); border-color: var(--tm-accent-fg); }
.tm-ds .cpk-card__fav { right: var(--tm-space-2); }
.tm-ds .cpk-card__fav:hover { color: var(--tm-danger-fg); transform: none; }
.tm-ds .cpk-card__fav.is-fav { color: var(--tm-danger-fg); border-color: var(--tm-danger-fg); }
.tm-ds .cpk-card__fav.is-fav [data-lucide] { fill: var(--tm-danger-fg); }
.tm-ds .cpk-card.is-selected .cpk-card__fav { right: 38px; }
.tm-ds .cpk-card__detail [data-lucide], .tm-ds .cpk-card__fav [data-lucide] { width: 14px; height: 14px; }
.tm-ds .cpk-card.has-badge .cpk-card__cat { left: auto; right: var(--tm-space-2); }
.tm-ds .cpk-card.has-badge .cpk-card__detail { top: 38px; }
.tm-ds .cpk-card__badge { position: absolute; top: var(--tm-space-2); left: var(--tm-space-2); z-index: 4; display: inline-flex; align-items: center; gap: var(--tm-space-1); padding: 0 var(--tm-space-2); border-radius: var(--tm-radius-full); font-size: var(--tm-type-micro); font-weight: var(--tm-weight-bold); color: var(--tm-on-accent); box-shadow: none; white-space: nowrap; }
.tm-ds .cpk-card__badge [data-lucide] { width: 11px; height: 11px; }
.tm-ds .cpk-card__badge--hot, .tm-ds .cpk-card__badge--strong { background: var(--tm-accent-solid); }
.tm-ds .cpk-card__badge--moderate, .tm-ds .cpk-card__badge--emerging { background: var(--tm-info-fg); }
.tm-ds .cpk-card__badge--low, .tm-ds .cpk-card__badge--popular { background: var(--tm-text-secondary); }
.tm-ds .cpk-card__badge--new { background: var(--tm-success-fg); }
.tm-ds .cpk-card__stockwarn { position: absolute; bottom: var(--tm-space-2); right: var(--tm-space-2); z-index: 4; display: inline-flex; align-items: center; gap: var(--tm-space-1); padding: 0 var(--tm-space-2); border-radius: var(--tm-radius-full); font-size: var(--tm-type-micro); font-weight: var(--tm-weight-bold); color: var(--tm-warning-fg); background: var(--tm-warning-bg); border: 1px solid var(--tm-warning-fg); box-shadow: none; }
.tm-ds .cpk-card__stockwarn [data-lucide] { width: 11px; height: 11px; }
.tm-ds .cpk-fav-toast { position: fixed; left: 50%; bottom: var(--tm-space-6); transform: translateX(-50%); background: var(--tm-ink-900); color: var(--tm-on-accent); font-size: var(--tm-type-caption); font-weight: var(--tm-weight-medium); padding: var(--tm-space-2) var(--tm-space-4); border-radius: var(--tm-radius-full); box-shadow: var(--tm-shadow-modal); display: inline-flex; align-items: center; gap: var(--tm-space-2); z-index: 3000; opacity: 0; pointer-events: none; transition: none; }
.tm-ds .cpk-fav-toast.is-show { opacity: 1; }
.tm-ds .cpk-fav-toast [data-lucide] { width: 14px; height: 14px; }
.tm-ds .cpk-fav-toast.is-add [data-lucide] { color: var(--tm-danger-fg); fill: var(--tm-danger-fg); }

/* ---------- States — boş / hata / iskelet (spirit of ds-states.css) ---------- */
.tm-ds .cpk-state { text-align: center; padding: var(--tm-space-8) var(--tm-space-4); color: var(--tm-text-secondary); display: flex; flex-direction: column; align-items: center; gap: var(--tm-space-2); }
.tm-ds .cpk-state__icon { width: 48px; height: 48px; border-radius: var(--tm-radius-full); background: var(--tm-bg-subtle); display: flex; align-items: center; justify-content: center; }
.tm-ds .cpk-state__icon [data-lucide] { width: 22px; height: 22px; color: var(--tm-text-muted); }
.tm-ds .cpk-state__title { font-size: var(--tm-type-body); font-weight: var(--tm-weight-semibold); color: var(--tm-text-primary); }
.tm-ds .cpk-state__sub { font-size: var(--tm-type-caption); color: var(--tm-text-secondary); max-width: 340px; line-height: 1.5; }
.tm-ds .cpk-state--error .cpk-state__icon { background: var(--tm-danger-bg); }
.tm-ds .cpk-state--error .cpk-state__icon [data-lucide] { color: var(--tm-danger-fg); }

/* ---------- Load-more / pagination footer ---------- */
.tm-ds .cpk-pager { display: flex; align-items: center; justify-content: center; gap: var(--tm-space-2); padding: var(--tm-space-1); }
.tm-ds .cpk-pager--top { justify-content: flex-end; }
.tm-ds .cpk-pager button { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border: 1px solid var(--tm-border); background: var(--tm-bg-surface); border-radius: var(--tm-radius-control); font-size: var(--tm-type-caption); font-weight: var(--tm-weight-medium); cursor: pointer; color: var(--tm-text-primary); transition: none; }
.tm-ds .cpk-pager button:hover:not(:disabled) { border-color: var(--tm-accent-fg); color: var(--tm-accent-fg); background: var(--tm-accent-bg); }
.tm-ds .cpk-pager button:disabled { opacity: .4; cursor: not-allowed; }
.tm-ds .cpk-pager__info { font-size: var(--tm-type-caption); color: var(--tm-text-muted); font-family: var(--cpk-mono); padding: 0 var(--tm-space-2); }
.tm-ds .cpk-loadmore { display: flex; flex-direction: column; align-items: center; gap: var(--tm-space-2); padding: var(--tm-space-1); }
.tm-ds .cpk-loadmore__btn { display: inline-flex; align-items: center; gap: var(--tm-space-2); height: 40px; padding: 0 var(--tm-space-6); border: 1px solid var(--tm-border); background: var(--tm-bg-surface); border-radius: var(--tm-radius-control); font-size: var(--tm-type-body); font-weight: var(--tm-weight-medium); color: var(--tm-text-primary); cursor: pointer; transition: none; }
.tm-ds .cpk-loadmore__btn:hover:not(:disabled) { border-color: var(--tm-accent-fg); color: var(--tm-accent-fg); background: var(--tm-accent-bg); }
.tm-ds .cpk-loadmore__btn:disabled { opacity: .55; cursor: default; }
.tm-ds .cpk-loadmore__btn.is-loading [data-lucide] { animation: cpkSpin .8s linear infinite; }
@keyframes cpkSpin { to { transform: rotate(360deg); } }
.tm-ds .cpk-loadmore__info { font-size: var(--tm-type-caption); color: var(--tm-text-muted); font-family: var(--cpk-mono); }

/* ---------- Sticky seçim çubuğu — accent bulk-bar (ds-toolbar .tm-bulkbar spirit) ---------- */
:is(.tm-ds, body.tm-ds-shell) .cpk-bar { position: fixed; bottom: var(--tm-space-4); left: calc(50vw + var(--tmv2-sb-w, 240px) / 2); transform: translateX(-50%); width: min(1040px, calc(100vw - var(--tmv2-sb-w, 240px) - 48px)); z-index: 1200; display: flex; align-items: center; justify-content: space-between; gap: var(--tm-space-4); flex-wrap: wrap; padding: var(--tm-space-3) var(--tm-space-4); border-radius: var(--tm-radius-card); background: var(--tm-surface); color: var(--tm-text-primary); border: 1px solid var(--tm-accent-600); box-shadow: var(--tm-shadow-card); animation: none; }
@media (max-width: 1024px) { :is(.tm-ds, body.tm-ds-shell) .cpk-bar { left: 50vw; width: calc(100vw - 24px); bottom: var(--tm-space-2); } }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__info { display: flex; align-items: center; gap: var(--tm-space-3); font-size: var(--tm-type-body); font-weight: var(--tm-weight-medium); flex-wrap: wrap; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__count { font-size: var(--tm-type-body); font-weight: var(--tm-weight-bold); font-family: var(--cpk-mono); color: var(--tm-text-primary); display: inline-flex; align-items: center; gap: var(--tm-space-1); }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__count::before { content: ''; display: inline-block; width: var(--tm-space-2); height: var(--tm-space-2); border-radius: var(--tm-radius-full); background: var(--tm-ok); }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__selall { background: transparent; border: 0; cursor: pointer; padding: var(--tm-space-1) var(--tm-space-2); border-radius: var(--tm-radius-control); font-family: inherit; font-size: var(--tm-type-caption); font-weight: var(--tm-weight-bold); color: var(--tm-accent-600); text-decoration: underline; transition: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__selall:hover { background: var(--tm-ink-100); }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__profit { color: var(--tm-ok); font-size: var(--tm-type-caption); }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__profit b { color: var(--tm-text-primary); font-family: var(--cpk-mono); }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__actions { display: flex; align-items: center; gap: var(--tm-space-2); }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__brand { display: flex; align-items: center; gap: var(--tm-space-1); padding: var(--tm-space-1) var(--tm-space-1) var(--tm-space-1) var(--tm-space-2); border-radius: var(--tm-radius-control); background: var(--tm-ink-100); border: 1px solid var(--tm-border); }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__brand > [data-lucide] { width: 15px; height: 15px; color: var(--tm-text-muted); flex: 0 0 auto; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__brand input { width: 190px; max-width: 42vw; height: 28px; padding: 0 var(--tm-space-2); box-sizing: border-box; background: var(--tm-surface); border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); color: var(--tm-text-primary); font-size: var(--tm-type-caption); font-family: inherit; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__brandbtn { height: 28px; padding: 0 var(--tm-space-3); border: 0; border-radius: var(--tm-radius-control); cursor: pointer; background: var(--tm-ink-100); color: var(--tm-text-primary); font-size: var(--tm-type-micro); font-weight: var(--tm-weight-bold); font-family: inherit; transition: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__brandbtn:hover { background: var(--tm-border); }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__ghost { background: transparent; color: var(--tm-text-secondary); text-decoration: none; border: 1px solid var(--tm-border); cursor: pointer; font-size: var(--tm-type-caption); font-weight: var(--tm-weight-medium); font-family: inherit; height: 36px; padding: 0 var(--tm-space-3); border-radius: var(--tm-radius-control); transition: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__ghost:hover { color: var(--tm-text-primary); background: var(--tm-ink-100); }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__cta { display: inline-flex; align-items: center; gap: var(--tm-space-2); height: 36px; padding: 0 var(--tm-space-4); border-radius: var(--tm-radius-control); border: 0; cursor: pointer; font-size: var(--tm-type-caption); font-weight: var(--tm-weight-bold); font-family: inherit; background: var(--tm-accent-500); color: var(--tm-text-on-brand); transition: none; white-space: nowrap; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__cta:disabled { opacity: .4; cursor: not-allowed; transform: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__cta:not(:disabled):hover { filter: none; transform: none; background: var(--tm-accent-600); }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar__cta [data-lucide] { width: 15px; height: 15px; }
@media (max-width: 700px) { :is(.tm-ds, body.tm-ds-shell) .cpk-bar { flex-direction: column; align-items: stretch; bottom: var(--tm-space-2); } :is(.tm-ds, body.tm-ds-shell) .cpk-bar__actions { justify-content: flex-end; flex-wrap: wrap; gap: var(--tm-space-2); } :is(.tm-ds, body.tm-ds-shell) .cpk-bar__cta { flex: 1 1 auto; justify-content: center; } :is(.tm-ds, body.tm-ds-shell) .cpk-bar__brand { width: 100%; box-sizing: border-box; } :is(.tm-ds, body.tm-ds-shell) .cpk-bar__brand input { flex: 1 1 auto; width: auto; max-width: none; }
  .tm-ds .cpk-toolbar { display: grid; grid-template-columns: 1fr 1fr; gap: var(--tm-space-2); align-items: center; }
  .tm-ds .cpk-search { grid-column: 1 / -1; flex: none; margin-right: 0; max-width: none; }
  .tm-ds .cpk-select { min-width: 0; width: 100%; max-width: none; }
  .tm-ds .cpk-chip, .tm-ds .cpk-selall { width: 100%; justify-content: center; }
  .tm-ds .cpk-pricerange { grid-column: 1 / -1; width: 100%; }
  .tm-ds .cpk-price-in { flex: 1 1 0; width: auto; min-width: 0; }
  .tm-ds .cpk { --cpk-col-min: 155px; }
  .tm-ds .cpk-grid, .tm-ds .cpk-skel { grid-template-columns: repeat(auto-fill, minmax(155px, 1fr)); }
}
@media (max-width: 400px) { .tm-ds .cpk { --cpk-col-min: 140px; } }

/* ---------- Detay / upsell / celebrate modal shells (shared) ---------- */
:is(.tm-ds, body.tm-ds-shell) .cpk-modal { position: fixed; inset: 0; z-index: 2000; display: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-modal.is-open { display: block; }
/* Perde (2026-09-18, kullanıcı akışı): eski blur(12px)+.78 "çok fazla" → global 4px'e çektim →
   kullanıcı "hiç yok" (4px fazla ince) dedi → orta nokta: GÖRÜNÜR moderat blur(8px). Ürün detay
   (cpk-modal) + tutorial (cpk-tut) AYNI değer (birbiriyle tutarlı) + var(--tm-surface-overlay).
   (Global .tm-modal 4px test-kilitli — warnings-modal-global.cjs — dokunulmadı.) */
:is(.tm-ds, body.tm-ds-shell) .cpk-modal__backdrop { position: absolute; inset: 0; background: rgba(15,23,42,.5); opacity: 1; -webkit-backdrop-filter: blur(7px); backdrop-filter: blur(7px); }
:is(.tm-ds, body.tm-ds-shell) .cpk-modal__dialog { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: min(600px, calc(100vw - 32px)); max-height: calc(100vh - 56px); overflow-y: auto; overflow-x: hidden; background: var(--tm-surface); border: 1px solid var(--tm-border-strong); border-radius: var(--tm-radius-overlay); box-shadow: var(--tm-shadow-modal); animation: cpkModalIn 180ms cubic-bezier(.22,.61,.36,1) backwards; }
:is(.tm-ds, body.tm-ds-shell) .cpk-modal__close { position: absolute; top: var(--tm-space-2); right: var(--tm-space-2); z-index: 2; width: 32px; height: 32px; display: grid; place-items: center; border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); cursor: pointer; background: var(--tm-ink-100); color: var(--tm-text-muted); box-shadow: none; transition: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-modal__close:hover { background: var(--tm-border); color: var(--tm-text-primary); }
:is(.tm-ds, body.tm-ds-shell) .cpk-modal__body { display: flex; flex-direction: column; gap: var(--tm-space-3); padding: var(--tm-space-3) var(--tm-space-4); }

/* ---------- Detail modal content (md-*). Note: cpk-md-stats/-attrs/-demand/
   -demand2/-d2-star/-profit/-brand__note/-brand__label/-brand__opt/-brand__hb are
   DEAD (renderDetail() computes but never appends them — script comments at
   catalog_picker.html confirm "KALDIRILDI 2026-08-20" / "artık çağrılmıyor
   (dead-code)"); no CSS kept for them, nothing renders those classes today. ---------- */
:is(.tm-ds, body.tm-ds-shell) .cpk-md-top { display: grid; grid-template-columns: 190px 1fr; gap: var(--tm-space-4); align-items: start; }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-gallery { display: flex; flex-direction: column; gap: var(--tm-space-2); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-gallery__main { width: 100%; aspect-ratio: 1/1; border-radius: var(--tm-radius-control); overflow: hidden; background: var(--tm-ink-100); display: grid; place-items: center; }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-gallery__main img { width: 100%; height: 100%; object-fit: contain; }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-gallery__ph [data-lucide] { width: 38px; height: 38px; color: var(--tm-text-muted); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-gallery__thumbs { display: flex; gap: var(--tm-space-1); flex-wrap: wrap; }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-thumb { width: 44px; height: 44px; border-radius: var(--tm-radius-control); overflow: hidden; cursor: pointer; border: 2px solid transparent; background: var(--tm-ink-100); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-thumb.is-active { border-color: var(--tm-accent-600); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-thumb img { width: 100%; height: 100%; object-fit: cover; }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-info { display: flex; flex-direction: column; gap: var(--tm-space-2); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-info__cat { font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--tm-accent-600); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-info__t { font-size: 14px; font-weight: 700; color: var(--tm-text-primary); margin: 0; line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-info__brand { display: flex; align-items: center; gap: var(--tm-space-1); font-size: 12px; color: var(--tm-text-primary); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-info__brand [data-lucide] { width: 14px; height: 14px; color: var(--tm-accent-600); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-info__brand--none { color: var(--tm-text-muted); font-style: italic; }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-info__row { display: flex; align-items: center; gap: var(--tm-space-3); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-info__price { font-family: var(--cpk-mono); font-size: 18px; font-weight: 700; color: var(--tm-text-primary); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-info__stock { font-size: 12px; color: var(--tm-text-muted); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 4px var(--tm-space-3); font-size: 12px; color: var(--tm-text-muted); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-bc { display: inline-flex; align-items: center; gap: var(--tm-space-1); font-family: var(--cpk-mono); font-size: 11px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-bc [data-lucide] { width: 13px; height: 13px; color: var(--tm-text-muted); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-info__desc { font-size: 12px; line-height: 1.45; color: var(--tm-text-primary); margin: 0; white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-variants { display: flex; flex-direction: column; gap: var(--tm-space-2); border-top: 1px solid var(--tm-border); padding-top: var(--tm-space-3); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-variants__label { display: flex; align-items: center; gap: var(--tm-space-1); font-size: 12px; font-weight: 700; color: var(--tm-text-primary); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-variants__label [data-lucide] { width: 15px; height: 15px; color: var(--tm-accent-600); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-variants__n { font-weight: 500; color: var(--tm-text-muted); font-size: 11px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-variants__axes { display: flex; flex-direction: column; gap: var(--tm-space-2); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-vaxis { display: flex; align-items: flex-start; gap: var(--tm-space-2); flex-wrap: wrap; }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-vaxis__k { flex: 0 0 auto; min-width: 54px; font-size: 12px; font-weight: 700; color: var(--tm-text-muted); padding-top: 0; }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-vaxis__vals { display: flex; flex-wrap: wrap; gap: var(--tm-space-1); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-chip { display: inline-block; padding: 0 var(--tm-space-2); border-radius: var(--tm-radius-full); font-size: 12px; font-weight: 500; color: var(--tm-text-primary); background: var(--tm-ink-100); border: 1px solid var(--tm-border); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-brand--compact { display: flex; flex-direction: column; gap: var(--tm-space-2); border-top: 1px solid var(--tm-border); padding-top: var(--tm-space-3); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-brand--compact .cpk-md-brand__row { display: flex; align-items: center; gap: var(--tm-space-2); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-brand--compact .cpk-md-brand__row [data-lucide] { width: 15px; height: 15px; flex: 0 0 auto; color: var(--tm-accent-600); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-brand__hint { display: flex; align-items: flex-start; gap: var(--tm-space-1); font-size: 11px; line-height: 1.35; color: var(--tm-text-muted); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-brand__hint [data-lucide] { width: 12px; height: 12px; flex: 0 0 auto; color: var(--tm-accent-600); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-brand__hint b { color: var(--tm-text-primary); font-weight: 700; }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-brand input { width: 100%; height: 38px; padding: 0 var(--tm-space-3); box-sizing: border-box; border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); font-size: 12px; font-family: inherit; color: var(--tm-text-primary); background: var(--tm-surface); }
/* Sticky footer stays inside the padded body (no negative-margin edge-bleed — DS forbids
   non-zero margin; the trade-off is a small side inset instead of true edge-to-edge). */
:is(.tm-ds, body.tm-ds-shell) .cpk-md-actions { display: flex; gap: var(--tm-space-2); position: sticky; bottom: 0; z-index: 3; padding-top: var(--tm-space-2); background: var(--tm-surface); border-top: 1px solid var(--tm-border); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-actions button { flex: 1; height: 40px; border: 0; border-radius: var(--tm-radius-control); cursor: pointer; font-size: 14px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; gap: var(--tm-space-1); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-pick { background: var(--tm-accent-500); color: var(--tm-text-on-brand); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-pick.is-selected { background: var(--tm-ok-bg); color: var(--tm-ok); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-pick [data-lucide] { width: 16px; height: 16px; }
@media (max-width: 640px) { :is(.tm-ds, body.tm-ds-shell) .cpk-md-top { grid-template-columns: 1fr; } .tm-ds .cpk-upsell { flex-wrap: wrap; } .tm-ds .cpk-upsell__cta { width: 100%; justify-content: center; } }

/* ---------- Upsell modal (XML entitlement) + celebrate modal ---------- */
:is(.tm-ds, body.tm-ds-shell) .cpk-upsellm { max-width: 440px; text-align: center; }
:is(.tm-ds, body.tm-ds-shell) .cpk-upsellm__body { padding: var(--tm-space-6) var(--tm-space-6) var(--tm-space-4); display: flex; flex-direction: column; align-items: center; gap: var(--tm-space-3); }
:is(.tm-ds, body.tm-ds-shell) .cpk-upsellm__ic, :is(.tm-ds, body.tm-ds-shell) .cpk-celebrate__ring { width: 52px; height: 52px; border-radius: var(--tm-radius-full); display: flex; align-items: center; justify-content: center; background: var(--tm-accent-500); box-shadow: none; animation: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-upsellm__ic [data-lucide] { width: 26px; height: 26px; color: var(--tm-text-on-brand); }
:is(.tm-ds, body.tm-ds-shell) .cpk-upsellm__title, :is(.tm-ds, body.tm-ds-shell) .cpk-celebrate__t { font-size: 18px; font-weight: 700; margin: 0; color: var(--tm-text-primary); }
:is(.tm-ds, body.tm-ds-shell) .cpk-upsellm__sub, :is(.tm-ds, body.tm-ds-shell) .cpk-celebrate__s { font-size: 14px; color: var(--tm-text-secondary); margin: 0; line-height: 1.5; }
:is(.tm-ds, body.tm-ds-shell) .cpk-upsellm__sub { }
:is(.tm-ds, body.tm-ds-shell) .cpk-celebrate__s b { color: var(--tm-text-primary); }
:is(.tm-ds, body.tm-ds-shell) .cpk-upsellm__benefits { list-style: none; padding: 0; margin: 0; text-align: left; display: flex; flex-direction: column; gap: var(--tm-space-2); width: 100%; }
:is(.tm-ds, body.tm-ds-shell) .cpk-upsellm__benefits li { display: flex; align-items: flex-start; gap: var(--tm-space-2); font-size: 14px; color: var(--tm-text-primary); line-height: 1.4; }
:is(.tm-ds, body.tm-ds-shell) .cpk-upsellm__benefits li::before { content: '\2713'; flex: 0 0 auto; font-weight: 700; color: var(--tm-ok); }
:is(.tm-ds, body.tm-ds-shell) .cpk-upsellm__cta, :is(.tm-ds, body.tm-ds-shell) .cpk-celebrate__cta { margin: 0; width: 100%; display: inline-flex; align-items: center; justify-content: center; gap: var(--tm-space-2); font-weight: 700; font-size: 14px; text-decoration: none; color: var(--tm-text-on-brand); background: var(--tm-accent-500); padding: var(--tm-space-3) var(--tm-space-4); border: 0; border-radius: var(--tm-radius-control); box-shadow: none; transition: none; cursor: pointer; }
:is(.tm-ds, body.tm-ds-shell) .cpk-upsellm__cta:hover, :is(.tm-ds, body.tm-ds-shell) .cpk-celebrate__cta:hover { transform: none; box-shadow: none; color: var(--tm-text-on-brand); background: var(--tm-accent-600); }
:is(.tm-ds, body.tm-ds-shell) .cpk-upsellm__cta [data-lucide], :is(.tm-ds, body.tm-ds-shell) .cpk-celebrate__cta [data-lucide] { width: 17px; height: 17px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-upsellm__dismiss, :is(.tm-ds, body.tm-ds-shell) .cpk-celebrate__dismiss { background: none; border: 0; color: var(--tm-text-muted); font-size: 12px; cursor: pointer; text-decoration: underline; padding: var(--tm-space-1); }
:is(.tm-ds, body.tm-ds-shell) .cpk-upsellm__dismiss:hover, :is(.tm-ds, body.tm-ds-shell) .cpk-celebrate__dismiss:hover { color: var(--tm-text-secondary); }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__field { display: flex; flex-direction: column; gap: var(--tm-space-1); width: 100%; text-align: left; }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__label { font-size: 13px; font-weight: 600; color: var(--tm-text-primary); }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__label em { font-style: normal; font-weight: 400; color: var(--tm-text-muted); }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__field input { width: 100%; box-sizing: border-box; font-size: 14px; padding: var(--tm-space-2) var(--tm-space-3); border: 1px solid var(--tm-border-strong); border-radius: var(--tm-radius-control); background: var(--tm-bg-surface); color: var(--tm-text-primary); }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__field input:focus { outline: 2px solid var(--tm-accent-500); outline-offset: 1px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__hint { font-size: 12px; color: var(--tm-text-muted); line-height: 1.45; }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__steps { list-style: none; display: flex; justify-content: center; gap: var(--tm-space-3); margin: 0; padding: 0; font-size: 12px; color: var(--tm-text-muted); }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__steps li { display: inline-flex; align-items: center; gap: var(--tm-space-1); }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__steps li span { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 50%; border: 1px solid var(--tm-border-strong); font-weight: 700; }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__steps li.is-active { color: var(--tm-text-primary); font-weight: 600; }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__steps li.is-active span, :is(.tm-ds, body.tm-ds-shell) .cpk-confirm__steps li.is-done span { background: var(--tm-accent-500); border-color: var(--tm-accent-500); color: var(--tm-text-on-brand); }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__step { display: flex; flex-direction: column; align-items: center; gap: var(--tm-space-3); width: 100%; }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__step[hidden] { display: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__prefix-ro { margin: 0; font-size: 13px; color: var(--tm-text-secondary); }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__actions { display: flex; gap: var(--tm-space-2); width: 100%; }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__actions [hidden] { display: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__actions .cpk-upsellm__cta { flex: 1; }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__actions .cpk-upsellm__cta:disabled { opacity: .5; cursor: not-allowed; }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__back { background: var(--tm-bg-subtle); color: var(--tm-text-primary); border: 0; border-radius: var(--tm-radius-control); padding: var(--tm-space-3) var(--tm-space-4); font-weight: 600; font-size: 14px; cursor: pointer; display: inline-flex; align-items: center; gap: var(--tm-space-1); }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm__back [data-lucide] { width: 16px; height: 16px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm .tmbo-field { width: 100%; }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm .tmbo-field input { background: var(--tm-bg-surface); color: var(--tm-text-primary); border-color: var(--tm-border-strong); }
:is(.tm-ds, body.tm-ds-shell) .cpk-confirm .tmbo-field .tmbo-ex { background: var(--tm-bg-subtle); color: var(--tm-text-secondary); margin-bottom: 0; }
:is(.tm-ds, body.tm-ds-shell) .cpk-job { display: flex; align-items: center; gap: var(--tm-space-3); margin: 0 0 var(--tm-space-3); padding: var(--tm-space-3) var(--tm-space-4); border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); background: var(--tm-bg-surface); }
:is(.tm-ds, body.tm-ds-shell) .cpk-job[hidden] { display: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-job__ic { color: var(--tm-accent-500); display: inline-flex; }
:is(.tm-ds, body.tm-ds-shell) .cpk-job__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; font-size: 13px; color: var(--tm-text-secondary); }
:is(.tm-ds, body.tm-ds-shell) .cpk-job__body b { color: var(--tm-text-primary); font-size: 14px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-job__body small { color: var(--tm-text-muted); font-size: 12px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-job__bar { display: block; height: 6px; border-radius: 3px; background: var(--tm-bg-subtle); overflow: hidden; }
:is(.tm-ds, body.tm-ds-shell) .cpk-job__bar span { display: block; height: 100%; width: 0; background: var(--tm-accent-500); transition: width .3s; }
:is(.tm-ds, body.tm-ds-shell) .cpk-job__stop { border: 1px solid var(--tm-border-strong); background: var(--tm-bg-surface); color: var(--tm-text-primary); border-radius: var(--tm-radius-control); padding: var(--tm-space-2) var(--tm-space-3); font-size: 13px; font-weight: 600; cursor: pointer; }
:is(.tm-ds, body.tm-ds-shell) .cpk-missing__list { list-style: none; margin: 0; padding: 0; width: 100%; max-height: 320px; overflow: auto; text-align: left; border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); }
:is(.tm-ds, body.tm-ds-shell) .cpk-missing__list li { padding: var(--tm-space-2) var(--tm-space-3); border-bottom: 1px solid var(--tm-border); font-size: 13px; display: flex; flex-direction: column; gap: 2px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-missing__list li:last-child { border-bottom: 0; }
:is(.tm-ds, body.tm-ds-shell) .cpk-missing__list li b { color: var(--tm-text-primary); font-weight: 600; overflow-wrap: anywhere; }
:is(.tm-ds, body.tm-ds-shell) .cpk-missing__list li span { color: var(--tm-text-muted); }
:is(.tm-ds, body.tm-ds-shell) .cpk-celebrate__missing { color: var(--tm-warning-fg); font-weight: 600; }
:is(.tm-ds, body.tm-ds-shell) .cpk-celebrate { display: flex; flex-direction: column; align-items: center; gap: var(--tm-space-3); text-align: center; padding: var(--tm-space-8) var(--tm-space-6) var(--tm-space-6); }
:is(.tm-ds, body.tm-ds-shell) .cpk-celebrate__badge { position: relative; width: 96px; height: 96px; display: grid; place-items: center; }
:is(.tm-ds, body.tm-ds-shell) .cpk-celebrate__halo { display: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-celebrate__ring { width: 84px; height: 84px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-celebrate__check { width: 48px; height: 48px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-celebrate__check-c { fill: none; stroke: var(--tm-text-on-brand); opacity: .45; stroke-width: 2.5; }
:is(.tm-ds, body.tm-ds-shell) .cpk-celebrate__check-m { fill: none; stroke: var(--tm-text-on-brand); stroke-width: 4.5; stroke-linecap: round; stroke-linejoin: round; }
:is(.tm-ds, body.tm-ds-shell) .cpk-celebrate__confetti { display: none; }
/* ---------- Hareket (2026-09-14 kullanıcı geri bildirimi: "animasyonlar yok")
   Kural: hareket YALNIZ işlevsel — (a) ızgara yenilenince kartların geldiğini
   gösteren 160 ms opaklık+4px yükselme (transform/opacity → layout shift YOK,
   CLS'e girmez; gecikme şablondaki stagger'dan, en fazla 11×30 ms), (b) iskelet
   nabzı (yükleniyor geri bildirimi), (c) kart odak/hover'ında 120 ms kenarlık
   geçişi. Dekoratif parlama/kaldırma/gradient YOK (ds-catalog.css başlığı) ve
   prefers-reduced-motion'da hepsi kapanır. ---------- */
@keyframes cpkCardIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
@keyframes cpkSkelPulse { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
.tm-ds .cpk-skel__c { animation: cpkSkelPulse 1200ms ease-in-out infinite; }

@media (prefers-reduced-motion: reduce) { .tm-ds .cpk-skel__c { animation: none; } }
@media (prefers-reduced-motion: reduce) { .tm-ds .cpk-card, .tm-ds .cpk-hero__how-step, :is(.tm-ds, body.tm-ds-shell) .cpk-tut__dialog, .tm-ds .cpk-weekly, .tm-ds .cpk-bar, :is(.tm-ds, body.tm-ds-shell) .cpk-modal__dialog { animation: none; } }

/* ═══════════════════════════════════════════════════════════════════════════
   KATALOG PLP REDESIGN (2026-09-18) — ürün-öncelikli düzen
   Dev mavi hero KALDIRILDI → kompakt topbar + kompakt utility + sol sticky filtre
   rayı + 4-kolon ürün grid. Referans: PLP best-practice (Allbirds/Fabletics/ASOS)
   + dropshipping katalog (Spocket/AutoDS). Tüm hook'lar korundu; bu yalnız düzen.
   ═══════════════════════════════════════════════════════════════════════════ */
.tm-ds .cpk-topbar{display:flex;align-items:center;gap:var(--tm-space-4);flex-wrap:wrap;
  background:var(--tm-bg-surface);border:1px solid var(--tm-border);border-radius:var(--tm-radius-card);
  padding:var(--tm-space-3) var(--tm-space-4);margin-bottom:var(--tm-space-3);box-shadow:var(--tm-shadow-card)}
.tm-ds .cpk-topbar__kicker{display:inline-flex;align-items:center;gap:var(--tm-space-1);font-size:var(--tm-type-micro);
  font-weight:var(--tm-weight-bold);letter-spacing:.1em;text-transform:uppercase;color:var(--tm-accent-fg)}
.tm-ds .cpk-topbar__kicker [data-lucide]{width:13px;height:13px}
.tm-ds .cpk-topbar__t{font-size:21px;font-weight:var(--tm-weight-bold);margin:2px 0 0;letter-spacing:-.01em;color:var(--tm-text-primary)}
.tm-ds .cpk-topbar__right{margin-left:auto;display:flex;align-items:center;gap:var(--tm-space-3);flex-wrap:wrap}
.tm-ds .cpk-topbar__quota{display:flex;align-items:center;gap:var(--tm-space-2)}
.tm-ds .cpk-topbar__how{all:unset;display:inline-flex;align-items:center;gap:var(--tm-space-1);cursor:pointer;box-sizing:border-box;
  font-weight:var(--tm-weight-semibold);font-size:var(--tm-type-caption);color:var(--tm-text-secondary);
  padding:8px 12px;border:1px solid var(--tm-border);border-radius:var(--tm-radius-control)}
.tm-ds .cpk-topbar__how:hover{border-color:var(--tm-accent-fg);color:var(--tm-accent-fg)}
.tm-ds .cpk-topbar__how .cpk-hero__how-cta,.tm-ds .cpk-topbar__how .cpk-hero__how-body,
.tm-ds .cpk-topbar__how .cpk-hero__how-dots,.tm-ds .cpk-topbar__how .cpk-how-wide{display:none !important}
.tm-ds .cpk-topbar__how .cpk-hero__how-head{display:inline;margin:0}
.tm-ds .cpk-topbar__how .cpk-hero__how-title{display:inline-flex;align-items:center;gap:var(--tm-space-1);font:inherit;text-transform:none;letter-spacing:0;color:inherit}
.tm-ds .cpk-topbar__how .cpk-hero__how-title [data-lucide]{width:15px;height:15px}
.tm-ds .cpk-topbar__importall{display:inline-flex;align-items:center;gap:var(--tm-space-2);background:var(--tm-accent-solid);
  color:var(--tm-on-accent);font-weight:var(--tm-weight-bold);font-size:var(--tm-type-body);border:0;cursor:pointer;
  padding:11px 18px;border-radius:var(--tm-radius-control);box-shadow:0 8px 18px -10px color-mix(in srgb,var(--tm-accent-solid) 70%,transparent)}
.tm-ds .cpk-topbar__importall [data-lucide]{width:17px;height:17px}
.tm-ds .cpk-topbar__importall .cpk-countup{font-family:var(--cpk-mono)}

/* Utility: KPI + transfer → kompakt yatay chip satırları (büyük kartlar değil) */
.tm-ds .cpk-kpis{display:flex;flex-wrap:wrap;gap:var(--tm-space-2);margin-bottom:var(--tm-space-2)}
.tm-ds .cpk-kpis .cpk-kpi{flex:0 0 auto;display:inline-flex;align-items:center;gap:var(--tm-space-2);
  padding:7px 12px;background:var(--tm-bg-surface);border:1px solid var(--tm-border);border-radius:999px;box-shadow:none;min-width:0}
.tm-ds .cpk-kpis .cpk-kpi__ic{width:22px;height:22px;border-radius:6px;flex:0 0 auto}
.tm-ds .cpk-kpis .cpk-kpi__ic [data-lucide]{width:13px;height:13px}
.tm-ds .cpk-kpis .cpk-kpi__body{display:flex;align-items:baseline;gap:6px;flex-direction:row}
.tm-ds .cpk-kpis .cpk-kpi__v{font-size:var(--tm-type-body);font-family:var(--cpk-mono);font-weight:var(--tm-weight-bold)}
.tm-ds .cpk-kpis .cpk-kpi__l{font-size:var(--tm-type-caption);color:var(--tm-text-secondary);white-space:nowrap}
.tm-ds .cpk-transfer{margin-bottom:var(--tm-space-3)}

/* PLP: sol sticky filtre rayı + sağ sonuç kolonu */
.tm-ds .cpk-plp{display:grid;grid-template-columns:240px minmax(0,1fr);gap:var(--tm-space-4);align-items:start}
.tm-ds .cpk-filters{position:sticky;top:var(--tm-space-3);background:var(--tm-bg-surface);border:1px solid var(--tm-border);
  border-radius:var(--tm-radius-card);box-shadow:var(--tm-shadow-card);overflow:hidden}
.tm-ds .cpk-filters__grp{padding:var(--tm-space-3) var(--tm-space-4);border-bottom:1px solid var(--tm-border)}
.tm-ds .cpk-filters__grp:last-child{border-bottom:0}
.tm-ds .cpk-filters__lbl{font-size:var(--tm-type-micro);font-weight:var(--tm-weight-bold);letter-spacing:.08em;
  text-transform:uppercase;color:var(--tm-text-muted);margin:0 0 var(--tm-space-2)}
.tm-ds .cpk-qf{display:flex;flex-direction:column;gap:4px}
.tm-ds .cpk-qf__item{all:unset;box-sizing:border-box;display:flex;align-items:center;gap:var(--tm-space-2);padding:8px 10px;
  border-radius:var(--tm-radius-control);font-weight:var(--tm-weight-semibold);font-size:var(--tm-type-caption);color:var(--tm-text-primary);cursor:pointer}
.tm-ds .cpk-qf__item [data-lucide]{width:15px;height:15px;color:var(--tm-text-muted)}
.tm-ds .cpk-qf__item:hover{background:var(--tm-accent-bg)}
.tm-ds .cpk-qf__item.is-active{background:var(--tm-accent-solid);color:var(--tm-on-accent)}
.tm-ds .cpk-qf__item.is-active [data-lucide]{color:var(--tm-on-accent)}
.tm-ds .cpk-filters .cpk-select{width:100%}
.tm-ds .cpk-filters .cpk-export{display:flex;width:100%}
.tm-ds .cpk-filters .cpk-pricerange{display:flex;width:100%;align-items:center;gap:var(--tm-space-2)}
.tm-ds .cpk-filters .cpk-price-in{flex:1;min-width:0}
.tm-ds .cpk-results-col{min-width:0}
.tm-ds .cpk-rhead{display:flex;gap:var(--tm-space-2);margin-bottom:var(--tm-space-2)}
.tm-ds .cpk-rhead .cpk-search{flex:1;min-width:0}
.tm-ds .cpk-rhead__sort{flex:0 0 190px;width:190px}

/* 4-kolon ürün grid (PLP yoğunluğu) */
.tm-ds .cpk-grid{grid-template-columns:repeat(4,minmax(0,1fr))}

/* "Filtreler" butonu: yalnız mobilde görünür (masaüstünde ray hep açık) */
.tm-ds .cpk-rhead__filterbtn{display:none}

/* ── Responsive (≤1024): mobilde chrome'u sıkıştır, filtreleri çekmeceye al ──
   Kullanıcı: "mobilde çok fazla filtre var, ürünler çok aşağıda". Çözüm (PLP mobil
   best-practice): filtre rayı VARSAYILAN GİZLİ → "Filtreler" ile açılır; üst-bar +
   metrikler tek satıra sıkışır → ürünler foldun üstünde. */
@media(max-width:1024px){
  .tm-ds .cpk-plp{grid-template-columns:1fr}
  .tm-ds .cpk-grid{grid-template-columns:repeat(2,minmax(0,1fr))}

  /* Topbar kompakt */
  .tm-ds .cpk-topbar{gap:var(--tm-space-2);padding:var(--tm-space-3)}
  .tm-ds .cpk-topbar__t{font-size:18px}
  .tm-ds .cpk-topbar__right{width:100%;margin-left:0;gap:var(--tm-space-2)}
  .tm-ds .cpk-topbar__importall{flex:1 1 auto;justify-content:center}

  /* Metrikler: 5 chip'i STACK etme → tek satır yatay kaydırma */
  .tm-ds .cpk-kpis,.tm-ds .cpk-transfer__nums,.tm-ds .cpk-transfer__reasons{
    flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;padding-bottom:2px}
  .tm-ds .cpk-kpis::-webkit-scrollbar,.tm-ds .cpk-transfer__nums::-webkit-scrollbar,.tm-ds .cpk-transfer__reasons::-webkit-scrollbar{display:none}
  .tm-ds .cpk-kpis .cpk-kpi,.tm-ds .cpk-transfer__num,.tm-ds .cpk-transfer__reason{flex:0 0 auto;white-space:nowrap}

  /* Filtre ÇEKMECESİ: ray gizli → "Filtreler" açar; ürünler üstte kalır */
  .tm-ds .cpk-filters{display:none}
  .tm-ds .cpk-filters.is-open{display:block;position:static;margin-bottom:var(--tm-space-3)}
  .tm-ds .cpk-filters.is-open .cpk-qf{flex-direction:row;flex-wrap:wrap}

  /* rhead: arama tam satır; altında [Filtreler][Sırala] yan yana */
  .tm-ds .cpk-rhead{flex-wrap:wrap}
  .tm-ds .cpk-rhead .cpk-search{flex:1 1 100%}
  .tm-ds .cpk-rhead__filterbtn{display:inline-flex;align-items:center;justify-content:center;gap:var(--tm-space-1);
    flex:1 1 0;height:42px;border:1px solid var(--tm-border);border-radius:var(--tm-radius-control);
    background:var(--tm-bg-surface);font-family:inherit;font-weight:var(--tm-weight-semibold);
    font-size:var(--tm-type-caption);color:var(--tm-text-primary);cursor:pointer}
  .tm-ds .cpk-rhead__filterbtn [data-lucide]{width:16px;height:16px}
  .tm-ds .cpk-rhead__filterbtn.is-active{background:var(--tm-accent-solid);color:var(--tm-on-accent);border-color:transparent}
  .tm-ds .cpk-rhead__sort{flex:1 1 0;width:auto}
}

/* ── 2026-10-05 sadeleştirme (kullanıcı: "etkileyici değil, anlaşılır değil") ──────────────────
   Seçici öneki `.tm-ds .cpk` (bir seviye özgül): ds-catalog-promo.css bu dosyadan SONRA yüklenir. */
.tm-ds .cpk .cpk-topbar__sub { margin: 4px 0 0; font-size: var(--tm-type-caption); color: var(--tm-text-secondary); }
/* "Tümünü aktar" ikincil: sayfanın asıl işi seçip eklemek */
.tm-ds .cpk .cpk-topbar__importall--ikincil { background: var(--tm-bg-surface); color: var(--tm-text-primary); border: 1px solid var(--tm-border);
  box-shadow: none; font-size: var(--tm-type-caption); padding: 8px 12px; font-weight: var(--tm-weight-semibold); }
.tm-ds .cpk .cpk-topbar__importall--ikincil:hover { border-color: var(--tm-accent-fg); color: var(--tm-accent-fg); }
.tm-ds .cpk .cpk-topbar__importall--ikincil .cpk-countup { font-family: inherit; }

/* pazaryeri şeridi: tek satır */
.tm-ds .cpk .cpk-connect-nudge--ince { gap: var(--tm-space-3); padding: 10px var(--tm-space-4); flex-wrap: wrap; }
.tm-ds .cpk .cpk-connect-nudge--ince .cpk-connect-nudge__ic { width: 30px; height: 30px; }
.tm-ds .cpk .cpk-connect-nudge--ince .cpk-connect-nudge__ic [data-lucide] { width: 16px; height: 16px; }
.tm-ds .cpk .cpk-connect-nudge--ince .cpk-connect-nudge__t { flex: 1 1 260px; font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold); }
.tm-ds .cpk .cpk-connect-nudge--ince .cpk-connect-nudge__go { padding: 7px 12px; font-size: var(--tm-type-caption); }

/* hızlı süzgeç çipleri — arama satırının altında, yatay */
.tm-ds .cpk .cpk-qf--chips { flex-direction: row; flex-wrap: wrap; gap: 8px; margin: 2px 0 0; }
.tm-ds .cpk .cpk-qf--chips .cpk-qf__item { padding: 7px 14px; border: 1px solid var(--tm-border); border-radius: 999px; background: var(--tm-bg-surface);
  font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold); color: var(--tm-text-primary); cursor: pointer; white-space: nowrap; }
.tm-ds .cpk .cpk-qf--chips .cpk-qf__item:hover { border-color: var(--tm-accent-fg); background: var(--tm-bg-surface); }
.tm-ds .cpk .cpk-qf--chips .cpk-qf__item.is-active { background: var(--tm-ink-900, #0f172a); border-color: transparent; color: #fff; }
.tm-ds .cpk .cpk-qf--chips .cpk-qf__item.is-active [data-lucide] { color: #fff; }
.tm-ds .cpk .cpk-qf--chips [data-cpk-showcase="campaigns"] [data-lucide] { color: #dc2626; }

/* sonuç başlığı: sayaç solda, toplu seçim sağda */
.tm-ds .cpk .cpk-result-meta { flex-wrap: wrap; }
.tm-ds .cpk .cpk-result-meta__acts { margin-left: auto; display: inline-flex; gap: var(--tm-space-4); }
.tm-ds .cpk .cpk-linkbtn { all: unset; cursor: pointer; font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold); color: var(--tm-accent-fg); }
.tm-ds .cpk .cpk-linkbtn:hover { text-decoration: underline; }
.tm-ds .cpk .cpk-linkbtn--strong { font-weight: var(--tm-weight-bold); }
.tm-ds .cpk .cpk-linkbtn[hidden] { display: none; }

/* kart: ürün sitesi gibi — marka/kategori satırı, büyük ve düz fiyat, belirgin ekle düğmesi */
.tm-ds .cpk .cpk-card { border-radius: 14px; }
.tm-ds .cpk .cpk-card:hover { box-shadow: 0 10px 24px -14px rgba(15, 23, 42, .35); }
.tm-ds .cpk .cpk-card__imgwrap { background: #fff; padding: 10px; }
.tm-ds .cpk .cpk-card__kicker { font-size: 11px; font-weight: var(--tm-weight-semibold); color: var(--tm-text-muted); text-transform: uppercase;
  letter-spacing: .04em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tm-ds .cpk .cpk-card__name { font-weight: var(--tm-weight-medium); font-size: 13.5px; }
.tm-ds .cpk .cpk-card__price { font-family: inherit; font-variant-numeric: tabular-nums; font-size: 18px; font-weight: 800; letter-spacing: -.01em; }
.tm-ds .cpk .cpk-card__price--campaign { display: inline-flex; flex-direction: column; line-height: 1.15; }
.tm-ds .cpk .cpk-card__price-was { font-size: 12px; font-weight: 500; color: var(--tm-text-muted); }
.tm-ds .cpk .cpk-card__price-now { font-size: 18px; font-weight: 800; color: #dc2626; }
.tm-ds .cpk .cpk-card__stock { font-family: inherit; font-size: 12px; color: var(--tm-success-fg); font-weight: var(--tm-weight-semibold); }
.tm-ds .cpk .cpk-card__stock--oos { color: var(--tm-text-muted); }
.tm-ds .cpk .cpk-card__pick { height: 36px; border: 0; background: var(--tm-accent-bg); color: var(--tm-accent-fg); border-radius: 10px; }
.tm-ds .cpk .cpk-card:hover .cpk-card__pick { background: var(--tm-accent-solid); color: var(--tm-on-accent); }
.tm-ds .cpk .cpk-card.is-selected .cpk-card__pick { background: var(--tm-success-fg, #15803d); color: #fff; }
.tm-ds .cpk .cpk-card.is-selected { border-color: var(--tm-success-fg, #15803d); box-shadow: 0 0 0 2px color-mix(in srgb, var(--tm-success-fg, #15803d) 25%, transparent); }
.tm-ds .cpk .cpk-card.is-selected .cpk-checkmark { background: var(--tm-success-fg, #15803d); }
.tm-ds .cpk .cpk-card__mp--on { background: var(--tm-success-bg); color: var(--tm-success-fg); border-color: transparent; font-weight: var(--tm-weight-semibold); }
.tm-ds .cpk .cpk-card__badge--campaign { background: #dc2626; }

@media (max-width: 720px) {
  .tm-ds .cpk .cpk-topbar__sub { display: none; }
  .tm-ds .cpk .cpk-qf--chips { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin-right: calc(-1 * var(--tm-space-4)); padding-right: var(--tm-space-4); }
  .tm-ds .cpk .cpk-qf--chips::-webkit-scrollbar { display: none; }
  .tm-ds .cpk .cpk-result-meta__acts { margin-left: 0; width: 100%; justify-content: space-between; }
  .tm-ds .cpk .cpk-card__price, .tm-ds .cpk .cpk-card__price-now { font-size: 16px; }
  .tm-ds .cpk .cpk-connect-nudge--ince .cpk-connect-nudge__alt { display: none; }
}
html.dark-mode .tm-ds .cpk .cpk-card__imgwrap { background: var(--color-surface, #0b0f14); }
html.dark-mode .tm-ds .cpk .cpk-qf--chips .cpk-qf__item.is-active { background: var(--color-text, #e5e7eb); color: #0b0f14; }
html.dark-mode .tm-ds .cpk .cpk-card__price-now { color: #f87171; }
@media (max-width: 720px) {
  /* üst blok telefonda kısa: başlık + tek satır düğmeler ("nasıl çalışır" yalnız simge) */
  .tm-ds .cpk .cpk-topbar__kicker { display: none; }
  .tm-ds .cpk .cpk-topbar__right { flex-wrap: nowrap; }
  .tm-ds .cpk .cpk-topbar__how .cpk-hero__how-title { font-size: 0; gap: 0; }
  .tm-ds .cpk .cpk-topbar__how .cpk-hero__how-title [data-lucide] { width: 17px; height: 17px; }
  .tm-ds .cpk .cpk-connect-nudge--ince .cpk-connect-nudge__ic { display: none; }
}
.tm-ds .cpk .cpk-card__ready { height: 36px; border-radius: 10px; border: 0; }
/* seçim çubuğu (2026-10-05): tek satır, koyu, sakin — ızgaranın üstünde iki satıra yayılmasın */
:is(.tm-ds, body.tm-ds-shell) .cpk-bar.cpk-bar { flex-wrap: nowrap; gap: 12px; padding: 10px 12px 10px 18px; border: 0; border-radius: 14px; background: #0f172a; color: #fff;
  box-shadow: 0 18px 40px -16px rgba(15, 23, 42, .55); font-size: 14px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__info { flex: 1 1 auto; min-width: 0; gap: 12px; flex-wrap: nowrap; font-size: 14px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__count { font-family: inherit; font-size: 15px; color: #fff; white-space: nowrap; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__count::before { background: #4ade80; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__selall { font-size: 13px; font-weight: 600; color: #93c5fd; text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__selall:hover { background: rgba(255, 255, 255, .08); }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__brand { background: rgba(255, 255, 255, .08); border-color: transparent; font-size: 13px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__brand input { background: transparent; border: 0; color: #fff; font-size: 13px; width: 170px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__brand input::placeholder { color: #94a3b8; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__brandbtn { background: rgba(255, 255, 255, .14); color: #fff; font-size: 12px; font-weight: 600; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__ghost { color: #cbd5e1; border-color: rgba(255, 255, 255, .2); font-size: 13px; height: 36px; padding: 0 12px; border-radius: 10px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__ghost:hover { background: rgba(255, 255, 255, .08); color: #fff; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__cta { height: 38px; border-radius: 10px; font-size: 14px; font-weight: 700; padding: 0 18px; }
@media (max-width: 900px) {
  :is(.tm-ds, body.tm-ds-shell) .cpk-bar.cpk-bar { flex-wrap: wrap; }
  :is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__brand { display: none; }   /* telefonda marka, aktarım penceresinde (1. adım) sorulur */
  :is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__info { flex-basis: 100%; }
  :is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__actions { width: 100%; }
  :is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__cta { flex: 1 1 auto; justify-content: center; }
}
:is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__ghost, :is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__cta { white-space: nowrap; }
:is(.tm-ds, body.tm-ds-shell) .cpk-bar .cpk-bar__selall b { color: inherit; font-family: inherit; }
/* detay penceresi: son 30 gün fiyat çizgisi (2026-10-05) */
:is(.tm-ds, body.tm-ds-shell) .cpk-md-fg { margin: 12px 0; padding: 12px 14px; border: 1px solid var(--tm-border); border-radius: 12px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-fg__t { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; color: var(--tm-text-primary); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-fg__t [data-lucide] { width: 15px; height: 15px; color: var(--tm-text-muted); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-fg__ind { margin-left: auto; font-size: 12px; font-weight: 700; color: #fff; background: #dc2626; border-radius: 999px; padding: 2px 8px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-fg__svg { display: block; width: 100%; height: 56px; margin: 8px 0 6px; color: var(--tm-accent-fg, #0175e4); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-fg__alt { display: flex; flex-direction: column; gap: 2px; font-size: 12px; color: var(--tm-text-secondary); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-fg__alt b { color: var(--tm-text-primary); }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-info__was { font-size: 14px; color: var(--tm-text-muted); text-decoration: line-through; margin-right: 6px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-md-info__price--ind { color: #dc2626; }

/* ── 2026-10-05 (2) kullanıcı listesi: ürünler yukarı · mobil "Tümünü aktar" küçük · balon kartı kapatmasın ·
   kart hizası · sade "Yeni" · arama/sıralama · mobil kesilmeler · seçim kutusu · boş/yükleniyor ───────────── */
/* üst alan: başlık kartı sıkı, KPI'lar onun içinde tek satır (ayrı şerit yok) */
.tm-ds .cpk .cpk-topbar { padding: 12px 18px; margin-bottom: 10px; align-items: center; }
/* üst başlık çubuğu zaten "Tedarikçi Kataloğu" diyor → kicker tekrarı kaldırıldı */
.tm-ds .cpk .cpk-topbar__kicker { display: none; }
.tm-ds .cpk .cpk-topbar__t { font-size: 20px; }
.tm-ds .cpk .cpk-kpis--ust { margin: 8px 0 0; gap: 6px; }
.tm-ds .cpk .cpk-kpis--ust .cpk-kpi { padding: 3px 10px 3px 4px; background: var(--tm-bg-subtle); border-color: transparent; }
.tm-ds .cpk .cpk-kpis--ust .cpk-kpi__ic { width: 20px; height: 20px; }
.tm-ds .cpk .cpk-kpis--ust .cpk-kpi__v { font-size: 13px; }
.tm-ds .cpk .cpk-kpis--ust .cpk-kpi__l { font-size: 12px; }
.tm-ds .cpk .cpk-connect-nudge--ince { padding: 5px 8px 5px 12px; margin-bottom: 10px; min-height: 0; }
.tm-ds .cpk .cpk-connect-nudge--ince .cpk-connect-nudge__t { margin: 0; }
.tm-ds .cpk .cpk-connect-nudge--ince .cpk-connect-nudge__go { padding: 6px 12px; }
.tm-ds .cpk .cpk-transfer { margin-bottom: 10px; }

/* arama + sıralama: aynı yükseklik, arama esnek genişlikte */
.tm-ds .cpk .cpk-rhead { align-items: center; margin-bottom: 10px; }
.tm-ds .cpk .cpk-rhead .cpk-search { flex: 1 1 auto; max-width: none; margin-right: 0; }
.tm-ds .cpk .cpk-rhead .cpk-search input, .tm-ds .cpk .cpk-rhead__sort, .tm-ds .cpk .cpk-rhead__filterbtn { height: 40px; }
.tm-ds .cpk .cpk-rhead__sort { flex: 0 0 210px; width: 210px; font-size: var(--tm-type-caption); }
.tm-ds .cpk .cpk-result-meta { margin: 6px 0 10px; }

/* kart hizası: gönderim engeli çipi adın altında; fiyat/stok/düğme tabanda, aynı satırda hizalı */
.tm-ds .cpk .cpk-card__name { line-height: 1.35; min-height: 2.7em; }
.tm-ds .cpk .cpk-card__mps:empty { display: none; }
.tm-ds .cpk .cpk-card__meta { align-items: flex-end; margin-top: auto; min-height: 40px; }
.tm-ds .cpk .cpk-card__stock { line-height: 1.6; white-space: nowrap; }

/* "Yeni" rozeti sade: dolu yeşil hap değil, ince etiket (indirim/popüler öne çıksın) */
.tm-ds .cpk .cpk-card__badge--new { background: rgba(255, 255, 255, .92); color: var(--tm-success-fg); border: 1px solid color-mix(in srgb, var(--tm-success-fg) 35%, transparent); }
html.dark-mode .tm-ds .cpk .cpk-card__badge--new { background: rgba(15, 23, 42, .85); }

/* seçim kutusu: seçilebilir her kartta boş kare, seçilince yeşil dolu + kart çerçevesi */
.tm-ds .cpk .cpk-checkmark { display: flex; top: 10px; right: 10px; width: 22px; height: 22px; border-radius: 6px; background: rgba(255, 255, 255, .95);
  border: 2px solid var(--tm-border-strong, #94a3b8); color: transparent; z-index: 3; }
.tm-ds .cpk .cpk-card:hover .cpk-checkmark { border-color: var(--tm-accent-fg); }
.tm-ds .cpk .cpk-card.is-selected .cpk-checkmark { background: var(--tm-success-fg, #15803d); border-color: var(--tm-success-fg, #15803d); color: #fff; }
.tm-ds .cpk .cpk-card.is-selected { border-color: var(--tm-success-fg, #15803d); box-shadow: 0 0 0 2px var(--tm-success-fg, #15803d); }
.tm-ds .cpk .cpk-card:has(.cpk-checkmark) .cpk-card__fav { right: 40px; }

.tm-ds .cpk .cpk-topbar__importall-kisa { display: none; }
/* boş / hata durumu eylem düğmesi + iskelet parıltısı */
.tm-ds .cpk .cpk-state__btn { all: unset; box-sizing: border-box; display: inline-flex; align-items: center; gap: 6px; margin-top: 6px; padding: 8px 14px;
  border-radius: 10px; background: var(--tm-accent-solid); color: var(--tm-on-accent); font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold); cursor: pointer; }
.tm-ds .cpk .cpk-state__btn [data-lucide] { width: 15px; height: 15px; }
.tm-ds .cpk .cpk-skel__c { background: linear-gradient(90deg, var(--tm-bg-subtle) 0%, color-mix(in srgb, var(--tm-bg-subtle) 55%, #fff) 50%, var(--tm-bg-subtle) 100%);
  background-size: 200% 100%; animation: cpkParilti 1.2s ease-in-out infinite; }
@keyframes cpkParilti { from { background-position: 100% 0; } to { background-position: -100% 0; } }
@media (prefers-reduced-motion: reduce) { .tm-ds .cpk .cpk-skel__c { animation: none; } }

/* destek balonu: kaydırırken kenara çekilir; seçim çubuğu açıkken onun üstüne çıkar; son satır altında boşluk */
body:is(.tmh-9bab4e22, :not(*) .cpk-topbar) .support-floating-buttons { transition: transform .25s ease, opacity .25s ease, bottom .2s ease; }
body.cpk-balon-gizli:is(.tmh-3b197f1f, :not(*) .cpk-topbar) .support-floating-buttons { transform: translateX(calc(100% + 28px)); opacity: 0; pointer-events: none; }
body:is(.tmh-2a24a851, :not(*) #cpkBar:not([style*="none"])) .support-floating-buttons { bottom: 92px; }
.tm-ds .cpk .cpk-results-col { padding-bottom: 72px; }

@media (max-width: 1024px) {
  /* "Tümünü aktar" telefonda tam genişlik birincil değil: küçük, içerik kadar */
  .tm-ds .cpk .cpk-topbar__right { width: auto; flex: 0 0 auto; margin-left: auto; justify-content: flex-end; }
  .tm-ds .cpk .cpk-topbar__importall { flex: 0 0 auto; font-size: 12px; padding: 7px 10px; }
  .tm-ds .cpk .cpk-rhead .cpk-search { flex: 1 1 100%; }
  .tm-ds .cpk .cpk-rhead__sort { flex: 1 1 0; width: auto; }
}
@media (max-width: 720px) {
  /* telefonda: 1. satır başlık + küçük düğmeler, 2. satır KPI'lar (tam genişlik, yatay kayar) */
  .tm-ds .cpk .cpk-topbar { flex-wrap: wrap; align-items: center; padding: 12px; row-gap: 8px; }
  .tm-ds .cpk .cpk-topbar__id { display: contents; }
  .tm-ds .cpk .cpk-topbar__t { order: 1; flex: 1 1 0; min-width: 0; margin: 0; font-size: 17px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .tm-ds .cpk .cpk-topbar__right { order: 2; }
  .tm-ds .cpk .cpk-kpis--ust { order: 3; flex: 1 1 100%; margin: 0; }
  .tm-ds .cpk .cpk-topbar__importall [data-lucide] { display: none; }
  .tm-ds .cpk .cpk-topbar__importall-uzun { display: none; }
  .tm-ds .cpk .cpk-topbar__importall-kisa { display: inline; }
  .tm-ds .cpk .cpk-kpis--ust .cpk-kpi__ic { display: none; }
  .tm-ds .cpk .cpk-kpis--ust .cpk-kpi { padding: 3px 9px; }
  /* üst başlık çubuğundaki sayfa adı telefonda "Tedarikçi …" diye kesiliyordu; başlık zaten sayfanın içinde */
  body:is(.tmh-9bab4e22, :not(*) .cpk-topbar) .tmv2-header-title { display: none; }
  .tm-ds .cpk .cpk-card__kicker { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; font-size: 10.5px; letter-spacing: .02em; }
  .tm-ds .cpk .cpk-card__meta { flex-wrap: wrap; gap: 2px 8px; }
  .tm-ds .cpk .cpk-card__stock { font-size: 11.5px; }
  .tm-ds .cpk .support-floating-buttons .tm-speeddial__trigger, body:is(.tmh-9bab4e22, :not(*) .cpk-topbar) .tm-speeddial__trigger { width: 44px; height: 44px; }
  body:is(.tmh-2a24a851, :not(*) #cpkBar:not([style*="none"])) .support-floating-buttons { bottom: 132px; }
}

/* ── 2026-10-05 (3) kart talep satırı (gerçek veri: kaç bayi mağazasına ekledi) — fiyatın hemen üstünde,
   her kartta yer tutar; tabana yaslı blok (talep + fiyat + düğme) satırdaki kartlarda aynı hizada kalır. */
.tm-ds .cpk .cpk-card__talep { margin-top: auto; min-height: 18px; display: flex; align-items: center; gap: 5px; font-size: 12px;
  font-weight: var(--tm-weight-semibold); color: var(--tm-text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tm-ds .cpk .cpk-card__talep [data-lucide] { width: 13px; height: 13px; flex: 0 0 auto; color: var(--tm-accent-fg); }
.tm-ds .cpk .cpk-card__talep--guclu { color: var(--tm-accent-fg); }
.tm-ds .cpk .cpk-card__talep + .cpk-card__meta { margin-top: 0; }
@media (max-width: 720px) { .tm-ds .cpk .cpk-card__talep { font-size: 11px; } .tm-ds .cpk .cpk-card__talep-uzun { display: none; } }

/* ── 2026-10-05 (4) görsel-2 (kullanıcı: "kartlar çok büyük · indirimler animasyonsuz · etiketler küçük ·
   fiyat grafiği tıklanabilir değil") ─────────────────────────────────────────────────────────────── */
/* daha küçük kart: geniş ekranda 5 sütun, 4:3 görsel, sıkı gövde */
/* 5 sütun yalnız kart ≥190px kalınca (1440'ta ürün alanı ~860px → 4 sütun; 5'te kart 160px'e iniyor, fiyat/stok taşıyordu — ölçüldü) */
@media (min-width: 1680px) { .tm-ds .cpk .cpk-grid, .tm-ds .cpk .cpk-skel { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
.tm-ds .cpk .cpk-grid { gap: 12px; }
.tm-ds .cpk .cpk-card__imgwrap { aspect-ratio: 16 / 10; padding: 4px; }
.tm-ds .cpk .cpk-card__price--campaign { line-height: 1.1; gap: 1px; }
.tm-ds .cpk .cpk-card__body { padding: 8px 10px 10px; gap: 5px; }
.tm-ds .cpk .cpk-card__meta { min-height: 36px; }
.tm-ds .cpk .cpk-card__pick, .tm-ds .cpk .cpk-card__ready { height: 32px; }

/* büyük, okunur etiketler */
.tm-ds .cpk .cpk-card__badge { font-size: 12px; line-height: 1.3; padding: 3px 9px; letter-spacing: .01em; box-shadow: 0 4px 10px -4px rgba(15, 23, 42, .4); }
.tm-ds .cpk .cpk-card__badge [data-lucide] { width: 13px; height: 13px; }
.tm-ds .cpk .cpk-card__stock { font-size: 13px; }
.tm-ds .cpk .cpk-card__talep { font-size: 12.5px; }
.tm-ds .cpk .cpk-card__mp--warn { font-size: 12px; }

/* canlı indirim rozeti: girişte bir kez "pop", sonra periyodik ışık süpürmesi (yalnız transform/opacity/background-position;
   docs/ui-reference-spec.md § Hareket bütçesi — pazarlama yüzeyi). Tıklanınca fiyat grafiği açılır. */
.tm-ds .cpk .cpk-card__badge--campaign { font-size: 13px; padding: 4px 10px; cursor: pointer;
  background: linear-gradient(110deg, #dc2626 0%, #dc2626 38%, #fca5a5 50%, #dc2626 62%, #dc2626 100%); background-size: 260% 100%; background-position: 100% 0;
  animation: cpkRozetPop 420ms cubic-bezier(.2, .9, .3, 1.35) backwards, cpkRozetParilti 3.2s ease-in-out 700ms infinite;
  transition: transform 150ms ease-out; }
.tm-ds .cpk .cpk-card__badge--campaign:hover { transform: scale(1.06); }
@keyframes cpkRozetPop { from { opacity: 0; transform: scale(.6); } to { opacity: 1; transform: none; } }
@keyframes cpkRozetParilti { 0%, 55% { background-position: 100% 0; } 100% { background-position: -160% 0; } }
/* fiyatta "−%X" çipi */
.tm-ds .cpk .cpk-card__price-ust { display: inline-flex; align-items: center; gap: 6px; }
.tm-ds .cpk .cpk-card__eksi { white-space: nowrap; font-size: 12px; font-weight: 800; line-height: 1.35; color: #fff; background: #dc2626; border-radius: 6px; padding: 0 6px; }
@media (prefers-reduced-motion: reduce) {
  .tm-ds .cpk .cpk-card__badge--campaign { animation: none; transition: none; background: #dc2626; }
  .tm-ds .cpk .cpk-card__badge--campaign:hover { transform: none; }
}

/* etkileşimli fiyat grafiği (detay penceresi) */
:is(.tm-ds, body.tm-ds-shell) .cpk-fg { position: relative; height: 140px; margin: 10px 0 4px; color: var(--tm-accent-fg, #0175e4); cursor: crosshair;
  outline: none; border-radius: 8px; touch-action: pan-y; user-select: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-fg:focus-visible { box-shadow: 0 0 0 2px var(--tm-accent-fg, #0175e4); }
:is(.tm-ds, body.tm-ds-shell) .cpk-fg svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; overflow: visible; }
:is(.tm-ds, body.tm-ds-shell) .cpk-fg [hidden] { display: none; }
:is(.tm-ds, body.tm-ds-shell) .cpk-fg__ylab { position: absolute; left: 4px; z-index: 1; font-size: 11px; font-weight: 600; color: var(--tm-text-muted);
  background: color-mix(in srgb, var(--tm-bg-surface, #fff) 85%, transparent); padding: 0 4px; border-radius: 4px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-fg__ylab--ust { top: 0; }
:is(.tm-ds, body.tm-ds-shell) .cpk-fg__ylab--alt { bottom: 0; }
:is(.tm-ds, body.tm-ds-shell) .cpk-fg__nokta { position: absolute; z-index: 2; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%;
  border: 2px solid #fff; box-shadow: 0 1px 4px rgba(15, 23, 42, .35); }
:is(.tm-ds, body.tm-ds-shell) .cpk-fg__nokta--min { background: #16a34a; }
:is(.tm-ds, body.tm-ds-shell) .cpk-fg__nokta--bugun { background: currentColor; }
:is(.tm-ds, body.tm-ds-shell) .cpk-fg__minlab { position: absolute; z-index: 2; font-size: 11px; font-weight: 700; color: #15803d; white-space: nowrap;
  background: color-mix(in srgb, var(--tm-bg-surface, #fff) 85%, transparent); padding: 0 4px; border-radius: 4px; }
:is(.tm-ds, body.tm-ds-shell) .cpk-fg__kilavuz { position: absolute; z-index: 1; top: 0; bottom: 0; width: 1px; background: currentColor; opacity: .4; }
:is(.tm-ds, body.tm-ds-shell) .cpk-fg__imlec { position: absolute; z-index: 3; width: 12px; height: 12px; margin: -6px 0 0 -6px; border-radius: 50%;
  background: currentColor; border: 2px solid #fff; box-shadow: 0 1px 6px rgba(15, 23, 42, .4); }
:is(.tm-ds, body.tm-ds-shell) .cpk-fg__ipucu { position: absolute; z-index: 4; top: 2px; transform: translateX(-50%); pointer-events: none; white-space: nowrap;
  background: #0f172a; color: #fff; font-size: 12px; font-weight: 600; padding: 4px 8px; border-radius: 6px; box-shadow: 0 6px 16px -6px rgba(15, 23, 42, .5); }
:is(.tm-ds, body.tm-ds-shell) .cpk-fg__xlab { display: flex; justify-content: space-between; font-size: 11px; color: var(--tm-text-muted); margin-bottom: 6px; }
html.dark-mode :is(.tm-ds, body.tm-ds-shell) .cpk-fg__ipucu { background: #e5e7eb; color: #0b0f14; }

/* ── 2026-10-05 (5) süzgeç paneli + canlı "Tümünü aktar" (kullanıcı: "filtre kutusu daha güzel ve kullanışlı;
   tümünü aktar animasyonlu ve dikkat çekici") ───────────────────────────────────────────────────────────── */
.tm-ds .cpk .cpk-sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.tm-ds .cpk .cpk-filters { top: 12px; max-height: calc(100vh - 24px); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
.tm-ds .cpk .cpk-filters__bas { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 14px; border-bottom: 1px solid var(--tm-border);
  position: sticky; top: 0; z-index: 1; background: var(--tm-bg-surface); }
.tm-ds .cpk .cpk-filters__baslik { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; font-weight: 700; color: var(--tm-text-primary); }
.tm-ds .cpk .cpk-filters__baslik [data-lucide] { width: 16px; height: 16px; color: var(--tm-accent-fg); }
.tm-ds .cpk .cpk-filters__sayi { min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; background: var(--tm-accent-solid); color: var(--tm-on-accent);
  font-size: 11px; display: inline-flex; align-items: center; justify-content: center; }
.tm-ds .cpk .cpk-filters__sayi[hidden], .tm-ds .cpk .cpk-filters__temizle[hidden], .tm-ds .cpk .cpk-fl__daha[hidden] { display: none; }
.tm-ds .cpk .cpk-filters__temizle { all: unset; cursor: pointer; font-size: 12px; font-weight: 600; color: var(--tm-accent-fg); }
.tm-ds .cpk .cpk-filters__temizle:hover { text-decoration: underline; }
.tm-ds .cpk .cpk-filters__grp { padding: 10px 14px; }
.tm-ds .cpk .cpk-filters__lbl { font-size: 11.5px; letter-spacing: .06em; margin-bottom: 6px; color: var(--tm-text-secondary); }
/* liste (kategori/marka/aktarım) */
.tm-ds .cpk .cpk-fl { display: flex; flex-direction: column; gap: 4px; }
.tm-ds .cpk .cpk-fl__ara { order: -1; width: 100%; height: 30px; box-sizing: border-box; padding: 0 10px; border: 1px solid var(--tm-border); border-radius: 8px;
  font: inherit; font-size: 12.5px; background: var(--tm-bg-subtle); color: var(--tm-text-primary); }
.tm-ds .cpk .cpk-fl__ara:focus { outline: none; border-color: var(--tm-accent-fg); background: var(--tm-bg-surface); }
.tm-ds .cpk .cpk-fl__liste { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 1px; }
.tm-ds .cpk .cpk-fl__oge { display: flex; align-items: center; gap: 8px; min-height: 28px; padding: 2px 8px; border-radius: 8px; cursor: pointer;
  font-size: 13px; color: var(--tm-text-primary); transition: background-color 120ms ease-out; }
.tm-ds .cpk .cpk-fl__oge:hover, .tm-ds .cpk .cpk-fl__oge:focus-visible { background: var(--tm-bg-subtle); outline: none; }
.tm-ds .cpk .cpk-fl__oge.is-on { background: var(--tm-accent-bg); color: var(--tm-accent-fg); font-weight: 700; }
.tm-ds .cpk .cpk-fl__ad { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-ds .cpk .cpk-fl__sayi { flex: 0 0 auto; font-size: 11.5px; font-weight: 600; color: var(--tm-text-muted); background: var(--tm-bg-subtle); border-radius: 999px; padding: 1px 7px; }
.tm-ds .cpk .cpk-fl__oge.is-on .cpk-fl__sayi { background: var(--tm-accent-solid); color: var(--tm-on-accent); }
.tm-ds .cpk .cpk-fl__bos { font-size: 12px; color: var(--tm-text-muted); padding: 4px 8px; }
.tm-ds .cpk .cpk-fl__daha { all: unset; cursor: pointer; font-size: 12px; font-weight: 600; color: var(--tm-accent-fg); padding: 2px 8px; }
/* aktarım durumu: radyo görünümü */
.tm-ds .cpk .cpk-fl--radyo .cpk-fl__oge::before { content: ""; flex: 0 0 auto; width: 14px; height: 14px; border-radius: 50%; border: 2px solid var(--tm-border-strong, #94a3b8); box-sizing: border-box; }
.tm-ds .cpk .cpk-fl--radyo .cpk-fl__oge.is-on::before { border: 4px solid var(--tm-accent-solid); }
/* hazır fiyat aralığı çipleri */
.tm-ds .cpk .cpk-fiyatcip { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 8px; }
.tm-ds .cpk .cpk-fiyatcip button { all: unset; cursor: pointer; font-size: 11.5px; font-weight: 600; padding: 4px 8px; border-radius: 999px; border: 1px solid var(--tm-border);
  color: var(--tm-text-primary); background: var(--tm-bg-surface); transition: border-color 120ms ease-out, background-color 120ms ease-out; }
.tm-ds .cpk .cpk-fiyatcip button:hover { border-color: var(--tm-accent-fg); }
.tm-ds .cpk .cpk-fiyatcip button.is-on { background: var(--tm-accent-solid); border-color: transparent; color: var(--tm-on-accent); }
.tm-ds .cpk .cpk-filters .cpk-price-in { height: 34px; border-radius: 8px; }

/* canlı "Tümünü aktar": gradyan + periyodik ışık süpürmesi (background-position) + yumuşak halka nabzı (transform/opacity);
   docs/ui-reference-spec.md § Hareket bütçesi; reduced-motion'da kapalı) */
.tm-ds .cpk .cpk-topbar__importall--canli { position: relative; overflow: visible; isolation: isolate; border: 0; color: #fff; font-weight: 800; font-size: 13.5px;
  padding: 10px 16px; border-radius: 12px; background: linear-gradient(135deg, var(--tm-accent-solid, #0175e4) 0%, #6d28d9 100%);
  box-shadow: 0 10px 22px -10px rgba(79, 70, 229, .7); transition: transform 150ms ease-out, box-shadow 150ms ease-out; }
.tm-ds .cpk .cpk-topbar__importall--canli > span, .tm-ds .cpk .cpk-topbar__importall--canli > [data-lucide], .tm-ds .cpk .cpk-topbar__importall--canli > svg { position: relative; z-index: 2; }
.tm-ds .cpk .cpk-topbar__importall--canli .cpk-countup { font-family: inherit; }
.tm-ds .cpk .cpk-topbar__importall--canli:hover { transform: translateY(-1px); box-shadow: 0 14px 26px -10px rgba(79, 70, 229, .8); }
.tm-ds .cpk .cpk-topbar__importall--canli:hover [data-lucide], .tm-ds .cpk .cpk-topbar__importall--canli:hover svg { transform: translateY(-2px); transition: transform 150ms ease-out; }
.tm-ds .cpk .cpk-topbar__importall--canli::after { content: ""; position: absolute; inset: 0; z-index: 1; border-radius: inherit; pointer-events: none; overflow: hidden;
  background: linear-gradient(110deg, transparent 40%, rgba(255, 255, 255, .5) 50%, transparent 60%) no-repeat; background-size: 250% 100%; background-position: 130% 0;
  animation: cpkAktarParilti 4s ease-in-out 1s infinite; }
.tm-ds .cpk .cpk-topbar__importall--canli::before { content: ""; position: absolute; inset: -3px; z-index: 0; border-radius: 14px; pointer-events: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, #6d28d9 45%, transparent); opacity: 0; animation: cpkAktarNabiz 2.4s ease-out infinite; }
@keyframes cpkAktarParilti { 0%, 60% { background-position: 130% 0; } 100% { background-position: -30% 0; } }
@keyframes cpkAktarNabiz { 0% { opacity: .9; transform: scale(1); } 70%, 100% { opacity: 0; transform: scale(1.12); } }
@media (prefers-reduced-motion: reduce) {
  .tm-ds .cpk .cpk-topbar__importall--canli::after, .tm-ds .cpk .cpk-topbar__importall--canli::before { animation: none; display: none; }
  .tm-ds .cpk .cpk-topbar__importall--canli, .tm-ds .cpk .cpk-topbar__importall--canli:hover { transition: none; transform: none; }
}
@media (max-width: 720px) { .tm-ds .cpk .cpk-topbar__importall--canli { font-size: 12px; padding: 7px 10px; border-radius: 10px; } }
/* mobil çekmece: sayfa akışında açılır — iç yükseklik sınırı yok (son seçenek kesilmesin) */
@media (max-width: 1024px) { .tm-ds .cpk .cpk-filters.is-open { max-height: none; overflow: visible; } .tm-ds .cpk .cpk-filters__bas { position: static; } }

/* ── 2026-10-05 (6) mobil: süzgeçler alttan açılan pencere (kullanıcı: "mobilde açılır kapanır olmalı, ürün listesi
   öncelik"). Kapalı başlar; açılınca ürünleri itmez — örtü + kaydırma kilidi; "N ürünü göster" ile kapanır. ─────── */
.tm-ds .cpk .cpk-filters__kapat, .tm-ds .cpk .cpk-filters__alt, .cpk-filters-ortu { display: none; }
.tm-ds .cpk .cpk-rhead__filtersayi { min-width: 18px; height: 18px; padding: 0 5px; margin-left: 2px; border-radius: 999px; font-size: 11px;
  display: inline-flex; align-items: center; justify-content: center; background: var(--tm-accent-solid); color: var(--tm-on-accent); }
.tm-ds .cpk .cpk-rhead__filterbtn.is-active .cpk-rhead__filtersayi { background: #fff; color: var(--tm-accent-fg); }
.tm-ds .cpk .cpk-rhead__filtersayi[hidden] { display: none; }
@media (max-width: 1024px) {
  .tm-ds .cpk .cpk-filters.is-open { display: block; position: fixed; left: 0; right: 0; bottom: 0; top: auto; z-index: 1300; margin: 0;
    max-height: 86vh; overflow-y: auto; overscroll-behavior: contain; border-radius: 16px 16px 0 0; border: 0;
    box-shadow: 0 -16px 40px -12px rgba(15, 23, 42, .45); animation: cpkPencereGir 220ms ease-out backwards; }
  .tm-ds .cpk .cpk-filters.is-open .cpk-filters__bas { position: sticky; top: 0; }
  .tm-ds .cpk .cpk-filters__kapat { all: unset; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px;
    border-radius: 8px; color: var(--tm-text-secondary); margin-left: 4px; }
  .tm-ds .cpk .cpk-filters__kapat [data-lucide] { width: 20px; height: 20px; }
  .tm-ds .cpk .cpk-filters__bas { gap: 10px; }
  .tm-ds .cpk .cpk-filters__temizle { margin-left: auto; }
  .tm-ds .cpk .cpk-filters__alt { display: block; position: sticky; bottom: 0; padding: 10px 14px calc(10px + env(safe-area-inset-bottom, 0px));
    background: var(--tm-bg-surface); border-top: 1px solid var(--tm-border); }
  .tm-ds .cpk .cpk-filters__goster { all: unset; box-sizing: border-box; width: 100%; height: 44px; display: flex; align-items: center; justify-content: center;
    border-radius: 12px; cursor: pointer; background: var(--tm-accent-solid); color: var(--tm-on-accent); font-size: 15px; font-weight: 700; }
  .cpk-filters-ortu:not([hidden]) { display: block; position: fixed; inset: 0; z-index: 1299; background: rgba(15, 23, 42, .5); }
  body.cpk-suzgec-acik { overflow: hidden; }
  body.cpk-suzgec-acik .support-floating-buttons { display: none; }
}
@keyframes cpkPencereGir { from { transform: translateY(24px); opacity: 0; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .tm-ds .cpk .cpk-filters.is-open { animation: none; } }
/* mobil: pazaryeri şeridi tek satır, kısa — ürünler ilk ekranda başlasın */
@media (max-width: 720px) {
  .tm-ds .cpk .cpk-connect-nudge--ince { flex-wrap: nowrap; gap: 8px; padding: 6px 6px 6px 10px; }
  .tm-ds .cpk .cpk-connect-nudge--ince .cpk-connect-nudge__t { flex: 1 1 auto; min-width: 0; font-size: 12px; line-height: 1.3;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  .tm-ds .cpk .cpk-connect-nudge--ince .cpk-connect-nudge__go { flex: 0 0 auto; padding: 6px 10px; font-size: 12px; white-space: nowrap; }
  .tm-ds .cpk .cpk-connect-nudge--ince .cpk-connect-nudge__go [data-lucide] { display: none; }
}


/* ===== css/ds/ds-buybox.css ===== */
/* =================================================================
   BUY BOX — KAYBEDİLEN ÜRÜNLER TABLOSU + KURAL MODALI          2026-10-08
   Kullanıcı kararı: *"amaç Buy Box kaybettiğimiz ürünleri göstermek; her
   satırda görsel · ad · barkod · stok · Buy Box sırası · maliyet · satış
   fiyatı · Buy Box fiyatı; yakınlık + maliyete göre 1-2-3 yıldız; satıra
   tıklayınca kural modalı; toplu kural."* Hedef mockup: `Buybox listesi +
   kural modalı` (IBM Plex benzeri sade, beyaz kart, 12-sütun tablo).

   Ön ek `bbk-` (kayıp tablosu) · `bbm-` (kural modalı). DS token'ları;
   sabit renk YALNIZ yıldız sarısı ve kademe tonları (dark-mode'da da okunur).
   Hareket: kart/satır hover'ı ve modal açılışı CSS-only; `prefers-reduced-
   motion` kapatır. `[data-bb3-row]:hover` DS'ten gelmez — burada tanımlı.
   ================================================================= */

/* ── Başlık sağı: son kontrol + pazaryeri ──────────────────────────────── */
.tm-ds .bbk-headright { display: flex; flex-wrap: wrap; align-items: center; gap: var(--tm-space-3); }
.tm-ds #bb3SonKontrol { white-space: nowrap; }

/* ── Özet kartları ─────────────────────────────────────────────────────── */
.tm-ds .bbk-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--tm-space-3); margin-bottom: var(--tm-space-4);
}
/* UX raporu B3 (2026-10-10): kartlar artık BİLGİ — `cursor:pointer` ve
   hover-kaldırma animasyonu KALDIRILDI (tıklanabilir DEĞİLLER, öyle
   GÖRÜNMEMELİLER). Tek istisna `.bbk-stat--link` ("Kuralı olan ürün" —
   filtre değil, "Kurallarım" sekmesine kısayol; o kendi kuralını korur). */
.tm-ds .bbk-stat {
  display: flex; flex-direction: column; gap: 4px; align-items: flex-start;
  padding: 14px 16px; text-align: left; cursor: default;
  border: 1px solid var(--tm-border); background: var(--tm-surface); color: var(--tm-text-primary);
  font: inherit;
}
.tm-ds .bbk-stat--link { cursor: pointer; transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease; }
.tm-ds .bbk-stat--link:hover { border-color: var(--tm-border-strong); box-shadow: var(--tm-card-shadow-hover); transform: translateY(-1px); }
.tm-ds .bbk-stat__lbl { display: inline-flex; align-items: center; gap: 6px; font-size: var(--tm-type-caption); color: var(--tm-text-muted); }
.tm-ds .bbk-stat__lbl svg { width: 15px; height: 15px; }
.tm-ds .bbk-stat__sub { opacity: .8; }
.tm-ds .bbk-stat__val { font-size: var(--tm-type-display-sm); line-height: 1.1; font-weight: var(--tm-weight-bold); }
.tm-ds .bbk-stat--ok .bbk-stat__val { color: var(--tm-success-fg); }
.tm-ds .bbk-stat--bad .bbk-stat__val { color: var(--tm-danger-fg); }

/* ── Görev şeridi: maliyeti eksik ürünler (UX raporu A15, 2026-10-10) ────
   "Fiyat değil / veri eksik" çipinin yerini aldı — TEK aksiyonlu, filtre
   DEĞİL. Uyarı tonu (sarı) kullanılır ama alarm değil: veri eksik, hata
   değil. `tm-hidden` iken hiç yer kaplamaz (0 ürün → şerit yok). */
.tm-ds .bbk-banner {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-bottom: var(--tm-space-3); padding: 10px 14px; border-radius: var(--tm-radius-lg, 10px);
  background: var(--tm-warning-bg, #fef3c7); color: var(--tm-warning-fg, #92400e);
  border: 1px solid color-mix(in srgb, var(--tm-warning-fg, #92400e) 25%, transparent);
  font-size: var(--tm-type-caption);
}
.tm-ds .bbk-banner svg { width: 16px; height: 16px; flex: 0 0 16px; }
.tm-ds .bbk-banner__cta {
  margin-left: auto; font-weight: var(--tm-weight-semibold); color: inherit;
  text-decoration: underline; white-space: nowrap;
}

/* ── Liste kartı: araç çubuğu ──────────────────────────────────────────── */
.tm-ds .bbk-list { overflow: hidden; }
.tm-ds .bbk-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--tm-space-3);
  padding: 12px 16px; border-bottom: 1px solid var(--tm-border);
}
.tm-ds .bbk-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.tm-ds .bbk-chip {
  display: inline-flex; align-items: center; gap: 6px; min-height: 34px; padding: 0 12px;
  border-radius: var(--tm-radius-full); border: 1px solid var(--tm-border); background: var(--tm-surface);
  color: var(--tm-text-primary); font: inherit; font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold); cursor: pointer;
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.tm-ds .bbk-chip:hover { border-color: var(--tm-border-strong); }
.tm-ds .bbk-chip.is-active { background: var(--tm-text-primary); color: var(--tm-surface); border-color: var(--tm-text-primary); }
.tm-ds .bbk-chip [data-bbk-count] { font-size: var(--tm-type-caption); opacity: .75; }
.tm-ds .bbk-chip [data-bbk-count]:empty { display: none; }
.tm-ds .bbk-bar__right { flex: 1 1 260px; display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
.tm-ds .bbk-search {
  flex: 1 1 220px; max-width: 360px; display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); padding: 0 12px; min-height: 38px; background: var(--tm-surface);
}
.tm-ds .bbk-search:focus-within { border-color: var(--tm-accent); box-shadow: 0 0 0 2px var(--tm-accent-bg); }
.tm-ds .bbk-search svg { width: 16px; height: 16px; color: var(--tm-text-muted); flex: 0 0 auto; }
.tm-ds .bbk-search input { border: 0; outline: 0; flex: 1; min-width: 0; background: transparent; font: inherit; color: var(--tm-text-primary); }
/* UX raporu B3 (2026-10-10): "Sırala" açılır menüsü MASAÜSTÜNDE KALKAR —
   başlıklar zaten tıklanınca sıralıyor (#8366+), iki aynı-işi-yapan kontrol
   kafa karıştırıyordu (A3). ≤720 px'te KALIR: mobilde başlık satırı gizli
   (`.bbk-head { display:none }`), sıralamanın TEK erişim yolu bu menü. */
.tm-ds .bbk-sort { display: none; }
.tm-ds .bbk-sort select {
  border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); min-height: 38px; padding: 0 10px;
  background: var(--tm-surface); color: var(--tm-text-primary); font: inherit; font-size: var(--tm-type-caption);
}

/* ── Yıldız açıklaması ─────────────────────────────────────────────────── */
.tm-ds .bbk-howto { padding: 8px 16px; border-bottom: 1px solid var(--tm-border); background: var(--tm-surface-sunken); font-size: var(--tm-type-caption); }
.tm-ds .bbk-howto summary { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; font-weight: var(--tm-weight-semibold); list-style: none; }
.tm-ds .bbk-howto summary::-webkit-details-marker { display: none; }
.tm-ds .bbk-howto summary::before { content: '▸'; color: var(--tm-text-muted); transition: transform .15s ease; }
.tm-ds .bbk-howto[open] summary::before { transform: rotate(90deg); }
.tm-ds .bbk-howto summary svg { width: 14px; height: 14px; color: var(--tm-warning-fg); }
.tm-ds .bbk-howto__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 6px 24px; padding: 8px 0 4px; color: var(--tm-text-muted); }

/* ── Tablo ızgarası ────────────────────────────────────────────────────── */
.tm-ds .bbk-scroll { overflow-x: auto; }
.tm-ds .bbk-table { min-width: 1060px; }
.tm-ds .bbk-head, .tm-ds .bbk-row { display: flex; align-items: stretch; border-bottom: 1px solid var(--tm-border); }
.tm-ds .bbk-head {
  background: var(--tm-surface-sunken); color: var(--tm-text-muted);
  /* 2026-10-09 (kullanıcı): başlıklar "çok büyük" görünüyordu. Sorun boyut
     DEĞİL biçimdi — 12px küçük, ama UPPERCASE + letter-spacing başlıkları
     kalın/iri gösteriyor ve "BUY BOX SIRASI" iki satıra kırılıyordu.
     Büyük-harf dönüşümü kaldırıldı, boyut 11px'e indi. */
  font-size: var(--tm-type-micro); font-weight: var(--tm-weight-semibold); letter-spacing: 0;
}
/* Tıklanabilir sütun başlığı (2026-10-09). <button> ama GÖRÜNÜM başlık:
   kullanıcı "başlıklar büyük" dediği için düğme görünümü EKLENMEDİ — yalnız
   imleç + hover + aktif vurgusu. Sıralanamayan sütunlar <span> kalır, yani
   tıklanabilir gibi DURMAZ (yanlış çağrışım yok). */
.tm-ds .bbk-th {
  border: 0; background: transparent; font: inherit; color: inherit;
  letter-spacing: inherit; text-transform: inherit; cursor: pointer;
}
.tm-ds .bbk-th:hover { color: var(--tm-text-primary); text-decoration: underline; }
.tm-ds .bbk-th:focus-visible { outline: 2px solid var(--tm-accent); outline-offset: -2px; }
.tm-ds .bbk-th.is-sorted { color: var(--tm-text-primary); font-weight: var(--tm-weight-bold); }
/* 2026-10-10 (kullanici sikayeti): oklar bozuk bir kontrol karakteri +
   "93"/"91" idi -> ekranda literal "Stok93" gibi okunuyordu. Gercek ok
   glifleri (U+2193 asagi / U+2191 yukari) escape ile; siralanmamis
   baslikta soluk cift-ok (U+2195) siralanabilir oldugunu gosterir. */
.tm-ds .bbk-th[aria-sort="descending"].is-sorted::after { content: "\2193"; margin-inline-start: 4px; }
.tm-ds .bbk-th[aria-sort="ascending"].is-sorted::after { content: "\2191"; margin-inline-start: 4px; }
.tm-ds .bbk-th:not(.is-sorted)::after { content: "\2195"; margin-inline-start: 4px; opacity: .35; }
.tm-ds .bbk-th:not(.is-sorted):hover::after { opacity: .6; }

.tm-ds .bbk-rowbtn {
  flex: 1; display: grid; align-items: center; min-width: 0;
  border: 0; background: transparent; text-align: left; font: inherit; color: inherit; cursor: pointer;
  padding: 10px 14px 10px 0;
}
.tm-ds .bbk-head, .tm-ds .bbk-rowbtn {
  /* 🔴 2026-10-10 (sadeleştirme raporu tur 2, B1/B2/B3): 9 sütundan
     ALTIYA indi — img · id · SIRA (yeni, kendi sütunu) · FİYAT (senin→Buy
     Box+fark TEK hücrede) · önerilen-fiyat · durum · aksiyon · go.
     Sıra kullanıcının BİRİNCİ şikâyetiydi ("Buy Box sırası görünmüyor") —
     artık kendi sütunu var, büyük rakamla. */
  /* 🔴 2026-10-10 — SÜTUN KÜMESİ SADELEŞTİ (kullanıcı: "tabloyu sadeleştir").
     Önce: sel · görsel · ürün · sıra · fiyat(3 sayı) · öneri(2 sayı) · durum · aksiyon
     Şimdi: sel · görsel · ürün · mevcut · önerilen · kazanç · durum · aksiyon
     Her sayı sütunu TEK sayı taşıdığı için dar ve eşit; ürün sütunu kalan yeri alır. */
  /* Aksiyon 142 → 158 px: ÖLÇÜLDÜ — yeşil "Uygula · 26.812,74 TL" düğmesi
     146 px istiyor, 142 px'lik hücreyi taşırıyordu (tur-3 kırpılma kilidi yakaladı).
     Fazlalık ürün sütunundan (1fr) geliyor, başka sütun daralmıyor. */
  /* 2026-10-11 — sütun kümesi: Ürün · SIRA · Mevcut · Buy Box · Kazanç · Aksiyon.
     Sıra fiyatların ÖNÜNDE (kullanıcı kararı: Buy Box'ta hikâye konumdur).
     Tutarlar kuruşsuz olduğu için sayı sütunları 104 → 96 px. */
  /* 2026-10-11: Kazanç sütunu KALDIRILDI (kullanıcı). Kalan: Ürün · Sıra ·
     Mevcut · Buy Box · Aksiyon. Boşalan 96 px ürün adına ve aksiyona gitti. */
  --bbk-cols: 36px minmax(300px, 1fr) 64px 104px 112px 184px 14px;
}
.tm-ds .bbk-head .bbk-cell--sel { min-height: 42px; }
.tm-ds .bbk-rowbtn { grid-template-columns: var(--bbk-cols); gap: 16px; }
/* 🔴 2026-10-11 — HİZALAMA KÖKÜ. Başlık DÜZ ızgaraydı, satır İKİ KATMANLI;
   seçim sütunundan sonraki 16 px boşluk başlığı sağa kaydırıyor, sağ dolgu da
   iki kez sayılıyordu. Artık ikisi AYNI iki katman: dış ızgara `48px 1fr`
   boşluksuz, iç ızgara `var(--bbk-cols)` + 16 px — `.bbk-headrow` ≡ `.bbk-rowbtn`.
   ⛔ Bu ikisinin `grid-template-columns`/`gap`/`padding` üçlüsü AYRILIRSA
      sütunlar yine kayar; e2e `basligHizasi` kilidi bunu ölçer. */
.tm-ds .bbk-head { display: grid; grid-template-columns: 48px minmax(0, 1fr); gap: 0; align-items: stretch; padding-right: 0; }
.tm-ds .bbk-headrow {
  display: grid; grid-template-columns: var(--bbk-cols); gap: 16px;
  align-items: center; min-width: 0; padding: 10px 14px 10px 0;
}
.tm-ds .bbk-row { display: grid; grid-template-columns: 48px minmax(0, 1fr); align-items: center; gap: 0; }
/* 2026-10-10 (kullanıcı şikâyeti): sıralama değişince satırlar sıçrayarak
   yeniden diziliyordu. `renderList()` tabloyu her yüklemede baştan çizer
   (reorder değil, yeniden-çizim) — bu yüzden gerçek FLIP yerine en az
   maliyetli yol: her yeni satır `.bbk-row--enter` ile görünmez/kaydırılmış
   başlar, ekledikten HEMEN sonra (bir sonraki frame) sınıf kaldırılır →
   fade + hafif kaydırma geçişi oynar. `prefers-reduced-motion` kapatır. */
.tm-ds .bbk-row {
  transition: opacity .18s ease, transform .18s ease, background .12s ease;
}
.tm-ds .bbk-row.bbk-row--enter { opacity: 0; transform: translateY(6px); }
.tm-ds .bbk-cell--sel { display: flex; align-items: center; justify-content: center; cursor: pointer; align-self: stretch; }
.tm-ds .bbk-cell--sel input { width: 17px; height: 17px; accent-color: var(--tm-accent); cursor: pointer; }
.tm-ds .bbk-row:hover { background: var(--tm-accent-bg); }
.tm-ds .bbk-row.is-selected { background: color-mix(in srgb, var(--tm-accent-bg) 70%, var(--tm-surface)); }
.tm-ds .bbk-rowbtn:focus-visible { outline: 2px solid var(--tm-accent); outline-offset: -2px; }
.tm-ds .bbk-cell--num { text-align: right; }
.tm-ds .bbk-cell--img, .tm-ds .bbk-detay-toggle { display: flex; align-items: center; }
/* 2026-10-10: 44 → 36 px. Görsel bir KİMLİK ipucu, bir vitrin değil; küçülünce
   satır yüksekliği düşüyor ve ürün adına 8 px daha yer kalıyor. Çerçeve de
   kaldırıldı (kullanıcı: "çerçeve kullanımını azalt") — zemin ayırmaya yetiyor. */
.tm-ds .bbk-thumb {
  width: 36px; height: 36px; border-radius: 6px; background: var(--tm-surface-sunken); border: 0;
  display: flex; align-items: center; justify-content: center; overflow: hidden; flex: 0 0 36px;
}
.tm-ds .bbk-thumb img { width: 100%; height: 100%; object-fit: contain; }
.tm-ds .bbk-thumb__ph { width: 16px; height: 16px; color: var(--tm-text-muted); }
.tm-ds .bbk-cell--id { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.tm-ds .bbk-name { font-weight: var(--tm-weight-semibold); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-ds .bbk-id-row { display: flex; align-items: center; gap: 5px; }
.tm-ds .bbk-barcode { font-family: var(--tm-font-sans); font-variant-numeric: tabular-nums; font-size: var(--tm-type-micro); color: var(--tm-text-muted); }
/* A9 (2026-10-10): pazaryeri rozeti — barkodun yanında küçük ikon. */
.tm-ds .bbk-platform-ico { width: 14px; height: 14px; border-radius: 3px; object-fit: contain; flex: 0 0 14px; }
.tm-ds .bbk-low { color: var(--tm-warning-fg); font-weight: var(--tm-weight-bold); }
/* 2026-10-10 (UX raporu A4/B1): ortak "ikinci satır, soluk metin" biçimi —
   ürün hücresinde Stok/Maliyet, Buy Box hücresinde sıra, Önerilen-fiyat
   hücresinde net kâr bu sınıfı paylaşır. Boşsa (içerik yoksa) satır
   yüksekliği bozulmasın diye `:empty` için minimum yükseklik korunur. */
.tm-ds .bbk-sub { font-size: var(--tm-type-caption); color: var(--tm-text-muted); line-height: 1.3; }
/* 🔴 2026-10-10 (sadeleştirme tur 2): `.bbk-cell--rank`/`.bbk-rank`/
   `.bbk-bbcol`/`.bbk-gapcol`/`.bbk-gap__tl` ARTIK KULLANILMIYOR —
   `_kayip_tablo.html`de bu sarmalayıcılar kaldırıldı (Buy Box sırası
   kendi sütunu oldu, `.bbk-siracol`; TL fark kaldırıldı). Eski kurallar
   SİLİNDİ (grep ile doğrulandı: üç dosyada da sıfır referans kaldı) —
   sahipsiz CSS bırakmak yerine temizlendi. */
.tm-ds .bbk-cell__main { font-weight: var(--tm-weight-semibold); }

/* ═══ 2026-10-10 — SADELEŞTİRME: tipografi hiyerarşisi + az renk/rozet/çizgi ══
   Kullanıcı: "tipografiyi baştan düzenle; başlıklar, yardımcı metinler, fiyatlar
   ve aksiyonlar net biçimde ayrışmalı · renk, rozet, ikon, çerçeve ve yatay çizgi
   kullanımını ciddi ölçüde azalt · satırlar daha ferah, hizalı, taranabilir olsun."

   SATIRDA ÜÇ KADEME, BAŞKA YOK:
     ① birincil  14px/600  → ürün adı, üç tutar (mevcut · önerilen · kazanç), sıra
     ② ikincil   12px/500  → durum etiketi, aksiyon
     ③ yardımcı  11px/400  → detaydaki künye, ipucu
   Renk de üç kademe: metin · soluk · tek vurgu (yeşil/kırmızı yalnız KAZANÇ ve
   DURUM'da; başka hiçbir yerde ton rengi yok). */
.tm-ds .bbk-row .bbk-name,
.tm-ds .bbk-row .bbk-cell__main,
.tm-ds .bbk-row .bbk-sira-num {
  font-size: var(--tm-type-body); font-weight: var(--tm-weight-semibold);
  line-height: 20px; letter-spacing: -.01em;
}
/* 🔴 2026-10-11 — RENK DİSİPLİNİ (kullanıcı: "sadece kritik eylemler renkli olsun;
   yeşil = aksiyon/kazanım, diğer her şey nötr gri/siyah").
   Tutarların İKİSİ de nötr: fiyat bir eylem değil, bir olgu. Renk yalnız iki yerde:
   KAZANÇ (yeşil / zararsa kırmızı) ve AKSİYON düğmesi. Durum artık renksiz. */
.tm-ds .bbk-row .bbk-c-mevcut .bbk-cell__main,
.tm-ds .bbk-row .bbk-c-oneri .bbk-cell__main { color: var(--tm-text-primary); }
.tm-ds .bbk-row .bbk-c-kazanc .bbk-cell__main.bbk-tone-ok { color: var(--tm-success-fg); }
.tm-ds .bbk-row .bbk-c-kazanc .bbk-cell__main.bbk-tone-bad { color: var(--tm-danger-fg); }
/* Durum (sıra) NÖTR — ton sınıfları artık görünmez bir etikette, satırda renk yok. */
.tm-ds .bbk-row .bbk-sira-num { color: var(--tm-text-primary); }

/* Durum = kazanma durumu. Sıra birincil, etiket ikincil — DOLU ROZET YOK. */
.tm-ds .bbk-cell--score { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; justify-content: center; }
.tm-ds .bbk-sira-satir { display: inline-flex; align-items: center; gap: 4px; }
.tm-ds .bbk-sira-num { cursor: default; }
.tm-ds .bbk-durum-etiket {
  font-size: var(--tm-type-caption); font-weight: var(--tm-weight-medium);
  line-height: 16px; white-space: nowrap; cursor: help;
}
/* TEK İSTİSNA: 1. sıra = Buy Box SENDE. Bu bir KAZANIMdır, renk kuralına uyar. */
.tm-ds .bbk-row .bbk-sira-num.bbk-sira-ilk { color: var(--tm-success-fg); }

/* Satır nefes alsın: yükseklik padding'den gelir, çizgiden değil. */
.tm-ds .bbk-row .bbk-rowbtn { padding-top: 12px; padding-bottom: 12px; }
/* 🔴 Yatay çizgi SAYISI aynı ama AĞIRLIĞI düşürüldü: tarama için ayırıcı gerekli,
   fakat tam kontrastlı çizgi 10 satırda ızgara hissi veriyordu (kullanıcı:
   "yatay çizgi kullanımını azalt"). Çizgi artık zemine karışan bir iz. */
.tm-ds .bbk-row { border-bottom-color: color-mix(in srgb, var(--tm-border) 45%, transparent); }

/* Detay künyesi: satırdan inen ikincil bilgiler — tek satır, etiketli. */
.tm-ds .bbk-detail__kunye {
  display: flex; flex-wrap: wrap; gap: 4px 20px; margin: 0 0 8px;
  font-size: var(--tm-type-micro); color: var(--tm-text-muted);
}
.tm-ds .bbk-detail__kunye b { font-weight: var(--tm-weight-semibold); color: var(--tm-text-primary); }

/* Sekmedeki kural sayısı (özet kartından taşındı). */
.tm-ds .tm-seg__count {
  margin-left: 6px; font-size: var(--tm-type-micro); font-weight: var(--tm-weight-semibold);
  color: var(--tm-text-muted);
}
.tm-ds .tm-seg__count:empty { display: none; }
.tm-ds .bbk-bb { font-weight: var(--tm-weight-semibold); color: var(--tm-accent); }
.tm-ds .bbk-oncol { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.tm-ds .bbk-gap { font-weight: var(--tm-weight-semibold); }
.tm-ds .bbk-cell--score { display: flex; flex-direction: column; align-items: flex-start; gap: 3px; }
.tm-ds .bbk-stars { color: #e39a0b; letter-spacing: 1px; font-size: var(--tm-type-caption); line-height: 1; }
.tm-ds .bbk-stars--sm { font-size: var(--tm-type-caption); letter-spacing: 0; }
/* 🔴 B7 → tur 3 (2026-10-10): satırdaki yıldız tamamen KALDIRILDI (şablondan da),
   Durum rozeti (`.bbk-durum-rozet`) tek gösterge. `.bbk-stars` kuralları yalnız
   FİLTRE ÇİPLERİ için duruyor (`.bbk-stars--sm`) — satır bağlamı artık yok. */
.tm-ds .bbk-score { font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold); }
.tm-ds .bbk-tone-ok { color: var(--tm-success-fg); }
.tm-ds .bbk-tone-warn { color: var(--tm-warning-fg); }
.tm-ds .bbk-tone-bad { color: var(--tm-danger-fg); }
.tm-ds .bbk-tone-muted { color: var(--tm-text-muted); }
/* 🔴 B7 — Durum TEK KELİMELİK rozet (sunucunun `yildiz_etiket`i basılır,
   bkz. `bb3-kayip.js`). `.bbk-tone-*` zaten metin rengi veriyordu; burada
   AYNI sınıfların `.bbk-durum-rozet` İLE BİRLEŞİMİ (iki sınıf → daha
   yüksek özgüllük, tek `.bbk-tone-*` kuralını EZER — ds-live.css halka
   vakasındaki özgüllük dersi burada TERSİNE çalışır: biz BİLEREK daha
   özgül bir kural yazıyoruz ki rozet arka planı da alsın) ton+arka plan
   rengini birlikte uygular. */
.tm-ds .bbk-durum-rozet {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 3px 10px; border-radius: var(--tm-radius-full);
  font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold);
  background: var(--tm-surface-sunken); color: var(--tm-text-muted);
  white-space: nowrap; order: 1;
}
.tm-ds .bbk-durum-rozet.bbk-tone-ok { background: var(--tm-success-bg); color: var(--tm-success-fg); }
.tm-ds .bbk-durum-rozet.bbk-tone-warn { background: var(--tm-warning-bg); color: var(--tm-warning-fg); }
.tm-ds .bbk-durum-rozet.bbk-tone-bad { background: var(--tm-danger-bg); color: var(--tm-danger-fg); }
.tm-ds .bbk-durum-rozet.bbk-tone-muted { background: var(--tm-surface-sunken); color: var(--tm-text-muted); }

/* ── B1 (2026-10-10, sadeleştirme tur 2) — Sıra: KENDİ sütunu ───────────
   Kullanıcının BİRİNCİ şikâyeti: "Buy Box sırası gösterilmiyor". Büyük
   rakam + "tek satıcı"/"birden fazla satıcı" metni (SAYI uydurulmaz) +
   kaynak tahminiyse soluk "tahmini" rozeti. */
.tm-ds .bbk-siracol { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.tm-ds .bbk-sira-num { font-size: var(--tm-type-body); font-weight: var(--tm-weight-bold); font-variant-numeric: tabular-nums; line-height: 1; }
.tm-ds .bbk-sira-num b { font-weight: inherit; }
/* D (korunur): sıra pill NÖTR, yalnız 1. sıra (Buy Box'ı kazandığın an) yeşil. */
.tm-ds [data-bb3-rank].bbk-sira-ilk { color: var(--tm-success-fg); }
.tm-ds .bbk-sira-tahmini {
  font-size: var(--tm-type-micro); font-weight: var(--tm-weight-semibold); color: var(--tm-text-muted);
  background: var(--tm-surface-sunken); border-radius: var(--tm-radius-sm); padding: 1px 5px; line-height: 1.4;
}
/* C — An 3 "sıra değişti" (2026-10-10): geçici "2. → 1." metni, normal
   alt metne döner (JS 4 sn sonra geri yazar). */
.tm-ds .bbk-sira-degisti { color: var(--tm-success-fg); font-weight: var(--tm-weight-semibold); }

/* ── B2 (2026-10-10, sadeleştirme tur 2) — Fiyat: TEK hücre ─────────────
   Senin fiyatın → Buy Box fiyatı + altında fark % (NÖTR, A2). */
.tm-ds .bbk-fiyatcol { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.tm-ds .bbk-fiyatcol [data-bb3-own] { font-weight: var(--tm-weight-semibold); }
.tm-ds .bbk-fiyat-ok { color: var(--tm-text-muted); margin: 0 3px; font-weight: var(--tm-weight-regular); }

/* ── C (2026-10-10, sadeleştirme tur 2, P0) — "ne oldu?" rozeti ─────────
   An 1 "Gönderildi"/An 3 "henüz uygulamadı" NÖTR (gri) — yalnız GERÇEKTEN
   doğrulanmış başarı (An 2) yeşil. Rapor Bölüm D: renk yalnız 3 yerde
   (net kâr · durum rozeti · BU rozet) — dürüstlük kuralı burada da geçerli,
   "uygulandı" YAZISI yalnız JS gerçekten doğruladığında basılır. */
.tm-ds .bbk-verify-badge {
  display: inline-flex; align-items: center; gap: 4px; max-width: 100%;
  padding: 3px 8px; border-radius: var(--tm-radius-sm, 6px);
  font-size: var(--tm-type-micro); font-weight: var(--tm-weight-semibold); line-height: 1.3;
}
.tm-ds .bbk-verify-badge.is-sent,
.tm-ds .bbk-verify-badge.is-not-effective { background: var(--tm-surface-sunken); color: var(--tm-text-muted); }
.tm-ds .bbk-verify-badge.is-verified { background: var(--tm-success-bg); color: var(--tm-success-fg); }

/* ── C — satır flaşı (renk-yalnız, "ne oldu?" geri bildirimi) ───────────
   `.bbk-row` zaten `background .12s ease` taşıyor (satır hover'ı için);
   flaş sırasında DAHA YAVAŞ bir geçiş istiyoruz (rapor: "~1,2 sn") — bu
   yüzden flaş sınıfları AYRI, daha özgül bir `transition` taşır (iki sınıf
   = tek `.bbk-row` kuralını ezer). Sınıf kalkınca normal (.12s) geçişe
   DÖNÜLÜR — "yanıp sönme" hissi budur. `prefers-reduced-motion` altta
   AYRICA kapatılır (aşağıdaki media query). */
.tm-ds .bbk-row.bbk-row--applied-flash,
.tm-ds .bbk-row.bbk-row--verify-ok,
.tm-ds .bbk-row.bbk-row--verify-wait {
  transition: background 1.1s ease;
}
.tm-ds .bbk-row.bbk-row--applied-flash,
.tm-ds .bbk-row.bbk-row--verify-wait {
  background: color-mix(in srgb, var(--tm-warning-bg, #fef3c7) 65%, var(--tm-surface));
}
.tm-ds .bbk-row.bbk-row--verify-ok {
  background: color-mix(in srgb, var(--tm-success-bg) 65%, var(--tm-surface));
}
/* 🔴 2026-10-10 — DOLU YEŞİL ROZET → DÜZ METİN (kullanıcı: "rozet, renk ve ikon
   kullanımını ciddi ölçüde azalt"). Bağlı kural bir UYARI değil, bir DURUM; dolu
   yeşil kutu onu "Kazanç" sütunundaki gerçek yeşille yarıştırıyordu. Artık soluk
   metin: varlığı görünür, dikkati çalmaz. İkon da kaldırıldı (şablonda). */
.tm-ds .bbk-rulechip {
  display: inline-flex; align-items: flex-start; gap: 6px; max-width: 100%;
  background: none; color: var(--tm-text-muted); border-radius: 0; padding: 0;
  font-size: var(--tm-type-caption); font-weight: var(--tm-weight-regular);
}
.tm-ds .bbk-rulechip svg { width: 13px; height: 13px; flex: 0 0 auto; }
/* 🔴 2026-10-10 tur 3 (KULLANICI: "yarım kalmış yazılar istemiyorum") — ÖLÇÜLDÜ:
   kural etiketi ("Buybox −1 TL · min %10", 11 px'te ~132 px) 128 px'lik Aksiyon
   sütununa sığmıyor, üç noktaya kesiliyordu. Artık KESİLMİYOR: iki satıra sarıyor
   (sütunda dikey yer var) ve tam metin `title`da da duruyor. */
.tm-ds .bbk-rulechip { align-items: flex-start; }
.tm-ds .bbk-rulechip svg { margin-top: 1px; }
.tm-ds .bbk-rulechip > span { white-space: normal; overflow-wrap: anywhere; line-height: 1.3; }
.tm-ds .bbk-rulechip.is-off { background: var(--tm-surface-sunken); color: var(--tm-text-muted); }
/* Kuralın son turu (2026-10-13): gönderildi (yeşil) · gönderilmedi/onay yok (uyarı ikonlu). */
/* 2026-10-13: `#bb3List` kartı `overflow:hidden` (köşe kırpma) → içindeki sticky toplu
   çubuk kaydırma kabına değil karta yapışıyor, hiç kalkmıyordu (ölçüldü). `clip` aynı
   kırpmayı kaydırma kabı OLUŞTURMADAN yapar. */
.tm-ds #bb3List { overflow: clip; }

.tm-ds .bbk-kuraldurum {
  display: inline-flex; align-items: flex-start; gap: 4px; max-width: 100%;
  font-size: var(--tm-type-caption); line-height: 1.3; color: var(--tm-text-muted);
  white-space: normal; overflow-wrap: anywhere;
}
.tm-ds .bbk-kuraldurum.is-ok { color: var(--tm-success-fg, #166534); font-weight: var(--tm-weight-semibold); }
.tm-ds .bbk-kuraldurum.is-warn { color: var(--tm-warning-fg, #92400e); font-weight: var(--tm-weight-semibold); cursor: help; }
/* 2026-10-13: karar tonları (bb3-karar.js) — koruma devrede · bekliyor · müdahale gerekir. */
.tm-ds .bbk-kuraldurum.is-durdu { color: var(--tm-warning-fg, #92400e); font-weight: var(--tm-weight-semibold); cursor: help; }
.tm-ds .bbk-kuraldurum.is-bekle { color: var(--tm-text-secondary); cursor: help; }
.tm-ds .bbk-kuraldurum.is-hata { color: var(--tm-danger-fg, #b91c1c); font-weight: var(--tm-weight-semibold); cursor: help; }
.tm-ds .bbk-kuraldurum svg { width: 13px; height: 13px; flex: 0 0 auto; margin-top: 1px; }
/* 2026-10-13: durum yalnız İKON (açıklama ipucunda) — kare dokunma alanı, odak halkası. */
.tm-ds .bbk-kuraldurum.is-ikon {
  align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: var(--tm-radius-full);
  cursor: help;
}
.tm-ds .bbk-kuraldurum.is-ikon svg { width: 18px; height: 18px; margin: 0; }
.tm-ds .bbk-kuraldurum.is-ikon:focus-visible,
.tm-ds .bb3rm-pt__karar:focus-visible,
.tm-ds .bb3rm-karar:focus-visible { outline: 2px solid var(--tm-accent); outline-offset: 2px; }
.tm-ds .bbk-addrule { display: inline-flex; align-items: center; gap: 4px; font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold); color: var(--tm-accent); }
.tm-ds .bbk-addrule svg { width: 14px; height: 14px; }

/* ── B2 (2026-10-10): "Fiyatı uygula" tek-aksiyon + inline onay popover ───
   ★★★ satırda birincil buton; tıklayınca modal AÇILMAZ, küçük bir popover
   içinde "NNN TL'ye iner, +KK TL net kâr — Uygula / Vazgeç" gösterilir. */
.tm-ds .bbk-apply-wrap { position: relative; }
.tm-ds .bbk-apply__btn {
  border: 0; background: transparent; padding: 0; font: inherit; cursor: pointer;
  display: inline-flex; align-items: center; font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold);
  color: var(--tm-accent); text-align: left; white-space: normal;
}
.tm-ds .bbk-apply__btn:hover, .tm-ds .bbk-apply__btn:focus-visible { text-decoration: underline; }
/* 🔴 ONAY KARTI (2026-10-14, kullanıcı: *"tasarımı çok kötü"*). 230 px düz
   metin kutusu → 272 px kart: başlık, büyük yeni fiyat, kâr çipi, kısa not,
   tam genişlik yeşil onay + sessiz vazgeç; sağ üstten düğmeye bakan ok ucu;
   açılışta pop. */
.tm-ds .bbk-apply__pop {
  position: absolute; z-index: 30; top: calc(100% + 10px); right: 0; width: 272px;
  display: flex; flex-direction: column; gap: 6px; padding: 14px 14px 12px;
  background: var(--tm-surface-raised, #fff); border: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  border-radius: 12px;
  box-shadow: 0 16px 40px rgba(15, 23, 42, .16), 0 0 0 1px rgba(15, 23, 42, .03);
  text-align: left; cursor: default;
  animation: bbk-pop-ac .18s cubic-bezier(.34, 1.4, .64, 1);
  transform-origin: 90% 0;
}
.tm-ds .bbk-apply__pop::before {
  content: ""; position: absolute; top: -6px; right: 22px; width: 10px; height: 10px;
  background: var(--tm-surface-raised, #fff); border-left: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  border-top: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10)); transform: rotate(45deg);
}
@keyframes bbk-pop-ac { from { opacity: 0; transform: scale(.92) translateY(-4px); } to { opacity: 1; transform: none; } }
.tm-ds .bbk-apply__baslik {
  font-size: 11px; line-height: 14px; letter-spacing: .04em; text-transform: uppercase;
  font-weight: var(--tm-weight-semibold); color: var(--tm-text-muted, #64748b);
}
.tm-ds .bbk-apply__fiyat {
  font-size: 20px; line-height: 24px; font-weight: var(--tm-weight-bold, 700);
  font-variant-numeric: tabular-nums; letter-spacing: -.01em; color: var(--tm-text-primary);
}
.tm-ds .bbk-apply__fiyat small { font-size: 12px; font-weight: var(--tm-weight-medium, 500); color: var(--tm-text-muted); margin-left: 4px; }
.tm-ds .bbk-apply__kar {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px; border-radius: 999px; font-size: 12px; line-height: 16px; font-weight: var(--tm-weight-semibold);
  background: rgba(22, 163, 74, .10); color: #15803d;
}
.tm-ds .bbk-apply__kar.is-zarar { background: rgba(220, 38, 38, .08); color: #b91c1c; }
.tm-ds .bbk-apply__kar:empty { display: none; }
.tm-ds .bbk-apply__msg { font-size: 11.5px; line-height: 15px; color: var(--tm-text-secondary, #475569); margin-top: 2px; }
.tm-ds .bbk-apply__err { font-size: var(--tm-type-caption); color: var(--tm-danger-fg); }
.tm-ds .bbk-apply__sinir {
  font-size: 11.5px; line-height: 15px; padding: 6px 8px; border-radius: 6px;
  background: rgba(245, 158, 11, .12); color: #92400e; border: 1px solid rgba(245, 158, 11, .35);
}
.tm-ds .bbk-apply__btns { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; }
.tm-ds .bbk-apply__ok {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 36px; padding: 0 14px; border-radius: 8px; border: 1px solid #15803d;
  background: #16a34a; color: #fff; font: inherit; font-size: 13px; font-weight: var(--tm-weight-semibold); cursor: pointer;
  transition: filter .12s ease, transform .12s ease;
}
.tm-ds .bbk-apply__ok:hover { filter: brightness(1.06); }
.tm-ds .bbk-apply__ok:active { transform: scale(.98); }
.tm-ds .bbk-apply__ok:disabled { opacity: .7; cursor: progress; }
.tm-ds .bbk-apply__vazgec {
  min-height: 30px; border: 0; background: transparent; color: var(--tm-text-secondary, #475569);
  font: inherit; font-size: 12px; cursor: pointer; border-radius: 6px;
}
.tm-ds .bbk-apply__vazgec:hover { background: var(--tm-surface-sunken, rgba(15, 23, 42, .05)); }
/* Düğme içi spinner — "Uygulanıyor…" sürerken. */
.tm-ds .bbk-apply__ok .bb3-doner-ic {
  width: 14px; height: 14px; border-radius: 50%; border: 2px solid rgba(255, 255, 255, .45);
  border-top-color: #fff; animation: bb3-don .8s linear infinite; flex: 0 0 auto;
}
@media (prefers-reduced-motion: reduce) {
  .tm-ds .bbk-apply__pop { animation: none; }
  .tm-ds .bbk-apply__ok .bb3-doner-ic { animation: none; }
}
/* 2026-10-10 (UX raporu B4, P1-b): ">" artık süsleme DEĞİL — gerçek
   `<button>`, satır detayını (neden/tazelik/"Şimdi kontrol et") aç/kapatır.
   Oklu görünüm korunur (aşağı ok, `aria-expanded=true` iken 180° döner). */
.tm-ds .bbk-detay-toggle {
  color: var(--tm-text-muted); justify-content: flex-end;
  border: 0; background: transparent; padding: 0; cursor: pointer; font: inherit;
}
.tm-ds .bbk-detay-toggle svg { width: 16px; height: 16px; transition: transform .15s ease, color .15s ease; }
.tm-ds .bbk-row:hover .bbk-detay-toggle svg, .tm-ds .bbk-detay-toggle:focus-visible svg { color: var(--tm-accent); }
.tm-ds .bbk-detay-toggle[aria-expanded="true"] svg { transform: rotate(180deg); color: var(--tm-accent); }

/* ── B4 (2026-10-10): satır detayı — "Neden kaybediyorsun?" ─────────────── */
.tm-ds .bbk-detail {
  grid-column: 1 / -1; padding: 12px 16px 14px 64px; border-top: 1px dashed var(--tm-border);
  background: var(--tm-surface-sunken); display: flex; flex-direction: column; gap: 6px;
}
.tm-ds .bbk-detail__neden { font-size: var(--tm-type-caption); color: var(--tm-text-primary); margin: 0; }
.tm-ds .bbk-detail__not { font-size: var(--tm-type-caption); color: var(--tm-text-muted); margin: 0; }
.tm-ds .bbk-detail__meta { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; font-size: var(--tm-type-caption); color: var(--tm-text-muted); }
.tm-ds .bbk-detail__err { color: var(--tm-danger-fg); }
.tm-ds .bbk-detail__taban { font-size: var(--tm-type-caption); color: var(--tm-text-muted); margin: 0; }
/* B3 (2026-10-10, sadeleştirme tur 2): Stok+Maliyet artık satırda değil,
   bu panelde — `.bbk-detail__taban` ile AYNI biçim (ikincil, soluk metin). */
.tm-ds .bbk-detail__stokmaliyet { font-size: var(--tm-type-caption); color: var(--tm-text-muted); margin: 0; }
.tm-ds .bbk-detail__stokmaliyet.bbk-low { color: var(--tm-warning-fg); font-weight: var(--tm-weight-semibold); }
.tm-ds .bbk-skel { padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.tm-ds .bbk-skel .tm-skeleton--text { width: 100%; height: 44px; }
.tm-ds #bb3Empty { padding: 40px 16px; }
.tm-ds .bbk-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 16px; }
.tm-ds .bbk-foot__btns { display: inline-flex; gap: 6px; }

/* ── Toplu işlem çubuğu ────────────────────────────────────────────────── */
/* 2026-10-13: tablonun ÜSTÜNDE, üst başlığın altına yapışık (eskiden ekranın altındaydı). */
.tm-ds .bbk-bulk {
  position: relative; z-index: 6; margin: 0 16px; width: auto; max-width: none;   /* dikey boşluk: liste kabının `gap`'i */
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
  background: var(--tm-text-primary); color: var(--tm-surface);
  border-radius: 14px; padding: 10px 10px 10px 18px; box-shadow: var(--tm-shadow-overlay);
  animation: bbk-rise .18s ease-out;
}
/* Kaydırırken sabitlenmiş hâl (bb3-kayip.js `_pinBulk`; sticky kabuk yüzünden çalışmıyor). */
.tm-ds .bbk-bulk.is-pinned { position: fixed; margin: 0; z-index: 30; animation: none; }
.tm-ds .bbk-bulk-yer { margin: 0; display: none; }
.tm-ds .bbk-bulk-yer.is-on { display: block; }
.tm-ds .bbk-bulk .tm-num { font-weight: var(--tm-weight-semibold); margin-right: auto; }
.tm-ds .bbk-bulk__clear { color: var(--tm-surface); border: 1px solid color-mix(in srgb, var(--tm-surface) 35%, transparent); }
@keyframes bbk-rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ── Kural modalı ──────────────────────────────────────────────────────── */
.tm-ds .bbm__dialog { max-width: 700px; }
/* 2026-10-09 (kullanıcı): "modal açılınca arka plan blur değil".
   Blur ASLINDA VARDI — global `v2/components/modal.css` 4px uyguluyor; o kadar
   hafif ki fark edilmiyordu. ⚠️ GLOBAL DEĞİŞTİRİLMEDİ: `warnings-modal-global.cjs`
   onu 4px'e kilitliyor; burada YALNIZ bu modalın kapsamında güçlendiriliyor.
   2026-10-10 (kullanıcı şikâyeti, tekrar): "modal arka planla iç içe,
   derinlik yok". Blur tek başına derinlik hissi vermiyordu — global perde
   rengi (`--tm-surface-overlay`) açık temada yarı saydam gri kalıyordu ve
   `.tm-modal__dialog`'un varsayılan gölgesi (`--tm-shadow-xl`) hafifti.
   Bu modal kapsamında (`.bbm`) perde KOYULAŞTIRILIYOR + gövdeye belirgin
   gölge ekleniyor; global `.tm-modal` diğer modallar için DEĞİŞMEDİ. */
.tm-ds #bb3KuralModal .tm-modal__backdrop {
  background: rgba(2, 12, 34, .55);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}
.tm-ds #bb3KuralModal .bbm__dialog {
  box-shadow: 0 32px 64px -16px rgba(2, 12, 34, .45), 0 8px 24px -8px rgba(2, 12, 34, .3);
}
.tm-ds .bbm__head { display: flex; align-items: flex-start; gap: 12px; }
.tm-ds .bbm__headtext { flex: 1; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.tm-ds .bbm__kicker { font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold); color: var(--tm-accent); letter-spacing: .04em; }
.tm-ds .bbm__sub { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: var(--tm-type-caption); color: var(--tm-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-ds .bbm__body { display: flex; flex-direction: column; gap: 18px; }
.tm-ds .bbm__facts {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px;
  background: var(--tm-border); border: 1px solid var(--tm-border); border-radius: 10px; overflow: hidden;
}
.tm-ds .bbm__fact { background: var(--tm-surface-sunken); padding: 10px 12px; display: flex; flex-direction: column; gap: 2px; }
.tm-ds .bbm__fact span { font-size: var(--tm-type-caption); color: var(--tm-text-muted); }
.tm-ds .bbm__fact b { font-weight: var(--tm-weight-semibold); }
.tm-ds .bbm__fact--bb { color: var(--tm-accent); }
.tm-ds .bbm__fs { border: 0; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.tm-ds .bbm__legend { font-weight: var(--tm-weight-semibold); font-size: var(--tm-type-caption); padding: 0; margin: 0 0 5px; }
.tm-ds .bbm__strats { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px; }
.tm-ds .bbm__strat {
  display: flex; flex-direction: column; gap: 6px; padding: 12px 14px; border-radius: 10px; cursor: pointer;
  border: 1px solid var(--tm-border); background: var(--tm-surface); transition: border-color .12s ease, background .12s ease;
}
.tm-ds .bbm__strat:hover { border-color: var(--tm-border-strong); }
.tm-ds .bbm__strat.is-active { border-color: var(--tm-accent); background: var(--tm-accent-bg); box-shadow: inset 0 0 0 1px var(--tm-accent); }
.tm-ds .bbm__strat__top { display: flex; align-items: center; gap: 8px; }
.tm-ds .bbm__strat__top input { width: 16px; height: 16px; accent-color: var(--tm-accent); margin: 0; }
.tm-ds .bbm__strat__desc { font-size: var(--tm-type-caption); color: var(--tm-text-muted); line-height: 1.35; }
.tm-ds .bbm__amount { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding-top: 4px; }
.tm-ds .bbm__amount input[type="number"] {
  width: 96px; min-height: 38px; border: 1px solid var(--tm-border-strong); border-radius: 8px; padding: 0 10px;
  font: inherit; font-size: var(--tm-type-body); font-weight: var(--tm-weight-semibold); text-align: right; background: var(--tm-surface); color: var(--tm-text-primary);
}
.tm-ds .bbm__unit { display: inline-flex; border: 1px solid var(--tm-border-strong); border-radius: 8px; overflow: hidden; }
.tm-ds .bbm__unit button { border: 0; background: var(--tm-surface); color: var(--tm-text-primary); font: inherit; font-weight: var(--tm-weight-semibold); min-height: 38px; padding: 0 12px; cursor: pointer; }
.tm-ds .bbm__unit button[aria-pressed="true"] { background: var(--tm-text-primary); color: var(--tm-surface); }
.tm-ds .bbm__cap { display: inline-flex; align-items: center; gap: 8px; }
.tm-ds .bbm__cap input { width: 72px; }
.tm-ds .bbm__guard {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  background: var(--tm-warning-bg); border: 1px solid color-mix(in srgb, var(--tm-warning-fg) 30%, transparent); border-radius: 10px; padding: 12px 14px;
}
.tm-ds .bbm__guard > svg { width: 18px; height: 18px; color: var(--tm-warning-fg); }
.tm-ds .bbm__pct { display: inline-flex; align-items: center; gap: 4px; border: 1px solid var(--tm-border-strong); border-radius: 8px; background: var(--tm-surface); padding: 0 10px; min-height: 38px; }
.tm-ds .bbm__pct span { font-weight: var(--tm-weight-semibold); color: var(--tm-text-muted); }
.tm-ds .bbm__pct input { width: 48px; border: 0; outline: 0; font: inherit; font-size: var(--tm-type-body); font-weight: var(--tm-weight-semibold); background: transparent; color: var(--tm-text-primary); }
.tm-ds .bbm__floor { flex-basis: 100%; font-size: var(--tm-type-caption); color: var(--tm-warning-fg); }
.tm-ds .bbm__prev { display: flex; flex-direction: column; gap: 8px; }
.tm-ds .bbm__prev__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 8px; }
.tm-ds .bbm__tbl { border: 1px solid var(--tm-border); border-radius: 10px; overflow: hidden; }
.tm-ds .bbm__tr { display: grid; grid-template-columns: minmax(0, 1fr) 96px 104px 64px 132px; gap: 10px; padding: 9px 12px; align-items: center; font-size: var(--tm-type-caption); border-top: 1px solid var(--tm-border); }
.tm-ds .bbm__tr--h { background: var(--tm-surface-sunken); font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold); color: var(--tm-text-muted); border-top: 0; }
.tm-ds .bbm__tr .tm-num { text-align: right; }
.tm-ds .bbm__rows { max-height: 220px; overflow-y: auto; }
.tm-ds .bbm__pname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-ds .bbm__new { font-weight: var(--tm-weight-bold); }
.tm-ds .bbm__status { font-weight: var(--tm-weight-semibold); }
.tm-ds .bbm__prev__state { padding: 10px 12px; font-size: var(--tm-type-caption); color: var(--tm-text-muted); border-top: 1px solid var(--tm-border); }
.tm-ds .bbm__err { color: var(--tm-danger-fg); margin: 0; }
.tm-ds .bbm__foot { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }

/* ── Dar ekran (≤900): yatay kaydırma kalır; kartlar/çubuk sarar ───────── */
@media (max-width: 900px) {
  .tm-ds .bbk-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tm-ds .bbk-bar__right { justify-content: stretch; }
  .tm-ds .bbk-search { max-width: none; }
  .tm-ds .bbm__facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tm-ds .bbm__tr { grid-template-columns: minmax(0, 1fr) 84px 92px 56px 110px; gap: 6px; }
}

/* ── Telefon (≤720): ÜRÜNLER İLK EKRANDA (2026-10-09, kullanıcı ekran görüntüsü:
   "mobilde ürünler çok altta kalıyor, çok fazla içerik ekranı kaplıyor").
   Ölçüldü (390 px, önceki hâl): ilk ürün satırı ~900 px'te başlıyordu —
   başlık+alt başlık 120 · pazaryeri+sekme 110 · 4 kart 2×2 200 · çipler 3
   satır 150 · arama+sıra 110 · açıklama 50 · başlık satırı 40.
   Şimdi: alt başlık gizli · kartlar tek satır dört küçük sayı · çipler tek
   satır yatay kaydırmalı · arama+sıra tek satır · açıklama gizli · tablo
   başlığı gizli, her satır KART (görsel · ad/barkod · yıldız · fiyat çifti ·
   stok/sıra/maliyet · kural). Yatay kaydırma YOK. ─────────────────────── */
@media (max-width: 720px) {
  .tm-ds #bb3Page .tm-page-header__subtitle { display: none; }
  .tm-ds #bb3Page .tm-page-header { margin-bottom: var(--tm-space-2); }
  .tm-ds .bbk-headright { gap: var(--tm-space-2); }
  .tm-ds #bb3SonKontrol { font-size: var(--tm-type-micro); }
  .tm-ds #bb3TopTabs { margin-bottom: var(--tm-space-2); }
  /* Görev şeridi (A15) mobilde kompakt: 2026-10-09 kuralı ("ürünler ilk
     ekranda") ihlal edilmesin diye tek satır, küçük yazı, az boşluk. */
  .tm-ds .bbk-banner { padding: 5px 8px; font-size: var(--tm-type-micro); line-height: 1.2; margin-bottom: var(--tm-space-1); gap: 5px; }
  .tm-ds .bbk-banner svg { width: 13px; height: 13px; flex: 0 0 13px; }
  .tm-ds .bbk-banner__cta { font-size: var(--tm-type-micro); }
  /* Dört özet kart → tek satır, küçük sayılar */
  .tm-ds .bbk-stats { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; margin-bottom: var(--tm-space-2); }
  .tm-ds .bbk-stat { padding: 8px 6px; gap: 2px; align-items: center; text-align: center; }
  .tm-ds .bbk-stat__lbl { font-size: var(--tm-type-micro); line-height: 1.15; gap: 3px; flex-direction: column; }
  .tm-ds .bbk-stat__lbl svg { width: 13px; height: 13px; }
  .tm-ds .bbk-stat__sub { display: none; }
  .tm-ds .bbk-stat__val { font-size: var(--tm-type-display-sm); }
  /* Çipler tek satır, yatay kaydırma */
  .tm-ds .bbk-bar { padding: 8px 10px; gap: 8px; }
  .tm-ds .bbk-chips { flex-wrap: nowrap; overflow-x: auto; max-width: 100%; padding-bottom: 2px; scrollbar-width: none; }
  .tm-ds .bbk-chips::-webkit-scrollbar { display: none; }
  .tm-ds .bbk-chip { min-height: 30px; padding: 0 10px; font-size: var(--tm-type-caption); white-space: nowrap; flex: 0 0 auto; }
  /* Arama + sıra aynı satır */
  .tm-ds .bbk-bar__right { flex: 1 1 100%; flex-wrap: nowrap; gap: 6px; }
  .tm-ds .bbk-search { flex: 1 1 auto; min-height: 34px; }
  /* B3: masaüstünde gizlenen "Sırala" menüsü burada GERİ GELİR — başlık
     satırı mobilde gizli (`.bbk-head { display:none }` aşağıda), tek
     sıralama erişimi bu menü. */
  .tm-ds .bbk-sort { display: flex; align-items: center; gap: 8px; }
  .tm-ds .bbk-sort > .tm-text-caption { display: none; }
  .tm-ds .bbk-sort select { min-height: 34px; max-width: 128px; font-size: var(--tm-type-caption); padding: 0 6px; }
  .tm-ds .bbk-howto { display: none; }
  /* ── Tablo → KART (mobil, 2026-10-10 yeniden kurgu) ────────────────────
     ÖLÇÜLEN KUSUR (390 px): üç tutar yan yana diziliyor, her birinin "TL"si
     alt satıra kırılıyor ve hangisinin ne olduğu YAZMIYORDU — "27.763,36 /
     26.018,00 / +6.500,00" üç anlamsız sayı. Masaüstünde anlamı SÜTUN BAŞLIĞI
     veriyor; mobilde başlık satırı gizli olduğu için anlam KAYBOLUYOR.
     Çözüm: mobilde her tutarın kendi ETİKETİ var (`::before`), tutarlar ALT
     ALTA değil, okunur bir ızgarada. Kullanıcı: "yarım kalmış yazı istemiyorum". */
  .tm-ds .bbk-table { min-width: 0; }
  .tm-ds .bbk-head { display: none; }
  .tm-ds .bbk-row { grid-template-columns: 30px minmax(0, 1fr); }
  /* 🔴 2026-10-11 — MOBİL KART BAŞTAN KURULDU (kullanıcı: "mobilde de liste
     çok kötü"). ÖLÇÜLEN KUSURLAR: seçim kutusu kartın SOL ORTASINDA havada
     duruyordu (dikey ortalı, hiçbir şeyle hizalı değil) · etiketli ÜÇ tutar
     kartı üç parçaya bölüyordu · "Kural" düz metin / "Uygula" dolu düğme
     olduğu için aksiyon satırı dengesizdi.
     YENİ DÜZEN — tek okuma yönü, üç satır:
       ① görsel + ürün adı (+ altında barkod · stok)   + sıra rozeti (sağ üst)
       ② Mevcut 27.763 TL            Buy Box 26.018 TL
       ③ [Uygula] [Kural]                              + detay oku
     Kazanç sütunu kalktığı için tutar satırı İKİ parçaya indi ve nefes aldı. */
  .tm-ds .bbk-rowbtn {
    /* 🔴 ÖZGÜLLÜK NOTU (2026-10-11, mutasyonla bulundu): bu blok `.tm-ds .bbk-rowbtn`
       (0,2,0). Masaüstü kuralı `.tm-ds .bbk-row .bbk-rowbtn` (0,3,0) daha özgül ve
       medya sorgusu özgüllüğü DEĞİŞTİRMEZ → buradaki dolgu bildirimi ÖLÜYDÜ.
       Kart 12 px dolguyla çiziliyordu ama o değer MASAÜSTÜ kuralından geliyordu;
       bu satırı değiştirmek hiçbir şeyi değiştirmiyordu (mutasyon yeşil kaldı).
       Dolgu artık aşağıda, AYNI özgüllükte ezilerek veriliyor. */
    display: grid; gap: 8px 10px; align-items: center;
    grid-template-columns: 40px minmax(0, 1fr) auto;
    grid-template-areas:
      "img    id     sira"
      "mevcut mevcut oneri"
      "rule   rule   go";
  }
  /* Dolgu: masaüstü kuralıyla AYNI özgüllük (`.bbk-row .bbk-rowbtn`), bu yüzden
     gerçekten etkin. Mutasyonla doğrulandı: 12 → 16 px yapınca kart 164 → 172 px
     olur ve mobil yükseklik kilidi KIRMIZI verir. */
  .tm-ds .bbk-row .bbk-rowbtn { padding: 12px 12px 12px 0; }
  /* Seçim kutusu kartın ÜSTÜNE hizalanır — ortada havada durmaz. */
  .tm-ds .bbk-row { grid-template-columns: 32px minmax(0, 1fr); align-items: start; }
  .tm-ds .bbk-cell--sel { padding-top: 18px; align-self: start; }
  .tm-ds .bbk-cell--img { grid-area: img; align-self: start; }
  .tm-ds .bbk-thumb { width: 40px; height: 40px; flex: 0 0 40px; }
  .tm-ds .bbk-cell--id { grid-area: id; }
  .tm-ds .bbk-name { font-size: var(--tm-type-body); white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.25; }
  .tm-ds .bbk-cell--sira { grid-area: sira; align-self: start; justify-content: flex-end; }
  .tm-ds .bbk-c-mevcut { grid-area: mevcut; }
  .tm-ds .bbk-c-oneri  { grid-area: oneri; }
  .tm-ds .bbk-rowbtn > .bbk-cell--num {
    display: flex; flex-direction: column; align-items: flex-start; gap: 0;
    text-align: left; min-width: 0;
  }
  .tm-ds .bbk-c-oneri { align-items: flex-end; text-align: right; }
  .tm-ds .bbk-rowbtn > .bbk-cell--num::before {
    font-size: var(--tm-type-micro); font-weight: var(--tm-weight-regular);
    color: var(--tm-text-muted); line-height: 14px;
  }
  .tm-ds .bbk-c-mevcut::before { content: "Mevcut"; }
  .tm-ds .bbk-c-oneri::before  { content: "Buy Box"; }
  .tm-ds .bbk-rowbtn > .bbk-cell--num .bbk-cell__main {
    font-size: var(--tm-type-body); line-height: 20px; white-space: nowrap;
  }
  .tm-ds .bbk-sira-tahmini { display: none; }
  .tm-ds .bbk-cell--rule { grid-area: rule; margin-top: 2px; }
  .tm-ds .bbk-rulechip, .tm-ds .bbk-addrule { font-size: var(--tm-type-caption); }
  /* C (2026-10-10): doğrulama rozeti mobilde TEK SATIRA sıkıştırılır —
     "Pazaryeri henüz uygulamadı" gibi uzun metin kart yüksekliğini
     şişirmesin diye kırpılır, tam metin `title`de kalır. */
  .tm-ds .bbk-verify-badge { font-size: var(--tm-type-micro); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tm-ds .bbk-cell--go { display: none; }
  /* B4: detay oku mobilde GİZLENMEZ (eski ">" süslemesinden farklı olarak
     artık işlevsel) — kendi grid-area'sı ("go") var, satırın sağ altında. */
  .tm-ds .bbk-detay-toggle { grid-area: go; justify-content: center; }
  .tm-ds .bbk-detail { padding: 10px 12px 12px 40px; }
  .tm-ds .bbk-bulk { margin: 0 8px; padding: 8px 8px 8px 12px; gap: 8px; }
}

@media (prefers-reduced-motion: reduce) {
  .tm-ds .bbk-stat--link, .tm-ds .bbk-chip, .tm-ds .bbk-detay-toggle svg, .tm-ds .bbm__strat, .tm-ds .bbk-howto summary::before { transition: none; }
  .tm-ds .bbk-bulk { animation: none; }
  .tm-ds .bbk-row, .tm-ds .bbk-row.bbk-row--enter { transition: none; opacity: 1; transform: none; }
  /* C (2026-10-10): "ne oldu?" flaşları RENK-YALNIZ geçişsiz — final renge
     anında atlar, hareket hissi vermez (kullanıcının 3. şikâyeti rengin
     KENDİSİ, geçiş süresi DEĞİL — bu yüzden renk korunur, yalnız `transition`
     kapatılır). */
  .tm-ds .bbk-row.bbk-row--applied-flash,
  .tm-ds .bbk-row.bbk-row--verify-ok,
  .tm-ds .bbk-row.bbk-row--verify-wait { transition: none; }
}

/* =================================================================
   KURALLARIM / KURAL DÜZENLEME — korunan bölümler (2026-09-18/19)
   `bb3-rules-manager.js` · `bb3-rule-edit.js` · `_rules_manager.html` ·
   `_rule_edit.html` bu sınıfları kullanmaya devam ediyor.
   ================================================================= */
/* =================================================================
   İKON DİLİ + TOOLTIP                                    2026-09-18

   Kullanıcı: *"çok fazla yazı var, bunlar yerine ikon vs kullanılabilir;
   üzerine gelince hata durumu açıklayıcı bir şekilde gösterilebilir;
   buybox sıraları da görsel olarak çok basit — ikon kullanımları, info
   tooltip kullanımı vs olmalı."*

   🔴 METİN KAYBOLMUYOR, YER DEĞİŞTİRİYOR. Her ikon `title` + `aria-label`
   taşır: fare ile üzerine gelen cümleyi görür, ekran okuyucu okur, klavye
   kullanıcısı odakta alır. "Az yazı" istendi — "az bilgi" değil. Bugün
   bütün gün düzelttiğim kusur zaten bilgiyi SESSİZCE yutmaktı.

   ⚠️ DS'te tooltip bileşeni YOK (ölçüldü: `tm-tooltip` / `[data-tooltip]`
   sıfır eşleşme). Native `title` yavaş açılır ve dokunmatikte hiç yoktur;
   bu yüzden CSS tooltip EKLENDİ — `title` da DURUYOR (erişilebilirlik ve
   tooltip CSS'i düşerse bilgi yine ulaşsın).
   ================================================================= */

/* ── İkon çipi ─────────────────────────────────────────────────────── */
.tm-ds .bbx-ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: var(--tm-radius-control, 6px);
  flex: 0 0 24px;
  cursor: help;
  position: relative;
}
.tm-ds .bbx-ico svg { width: 15px; height: 15px; }
.tm-ds .bbx-ico--danger  { color: var(--tm-danger-fg, #dc2626);  background: var(--tm-danger-bg, #fee2e2); }
.tm-ds .bbx-ico--warning { color: var(--tm-warning-fg, #d97706); background: var(--tm-warning-bg, #fef3c7); }
.tm-ds .bbx-ico--success { color: var(--tm-success-fg, #16a34a); background: var(--tm-success-bg, #dcfce7); }

/* ── Sıra rozeti: ikon + sayı ──────────────────────────────────────── */
.tm-ds .bbx-rank {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  cursor: help;
  position: relative;
}
.tm-ds .bbx-rank svg { width: 14px; height: 14px; }
.tm-ds .bbx-rank--success { color: var(--tm-success-fg, #16a34a); }
.tm-ds .bbx-rank--warning { color: var(--tm-warning-fg, #d97706); }

/* ── Tooltip — `title` içeriğini CSS ile gösterir ───────────────────
   ⚠️ `content: attr(title)` KULLANILMAZ: tarayıcı native balonu da açar,
   ikisi üst üste biner. Metin `data-tip`'e kopyalanır (JS), `title` yerinde
   kalır ama gösterim buradan olur.
   ⚠️ `position: fixed` DEĞİL: satır `overflow` taşımıyor; absolute yeterli
   ve portal gerektirmiyor (portal = bugün öğrenilen kapsam tuzağı). */
.tm-ds [data-tip] { position: relative; }
.tm-ds [data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 50;
  max-width: 280px;
  width: max-content;
  padding: 6px 9px;
  border-radius: 8px;
  background: #1e293b;
  color: #f8fafc;
  font-size: var(--tm-type-caption);
  line-height: 1.35;
  white-space: pre-line;
  text-align: left;
  box-shadow: 0 6px 18px rgba(15, 23, 42, .28);
  opacity: 0;
  pointer-events: none;
  transition: opacity .12s ease;
}
/* 🔴 2026-09-18 — ESKI ::after TOOLTIP DEVRE DISI (kullanici: "tooltip
   sisteminde sorun var, kirpiliyorlar"). `position:absolute` uc kirpan atayi
   asamiyordu (olculdu: .tm-card--flush hidden/hidden · .tm-page clip-x ·
   .tmv2-app hidden-x). Yerine `static/js/ds/tm-tip.js` — <body> altinda tek
   `position:fixed` dugum. Kural SILINMEDI: JS yuklenmezse `title` yedegi var,
   iki ipucu ust uste binmesin diye yalniz gorunurlugu kapatildi. */
.tm-ds [data-tip]:hover::after,
.tm-ds [data-tip]:focus-visible::after { opacity: 0; }
/* 🔴 2026-10-10 — ÖLÇÜLDÜ: yukarıdaki ölü balon `opacity:0` ile GÖRÜNMEZ ama hâlâ
   ÇİZİLİYOR; `width: max-content` + abspos olduğu için kapsayıcının `scrollWidth`ini
   şişiriyor ve hücreler "taşmış" görünüyor (kayıp sayfasında "+6.500,00 TL" ve
   "Hemen kazan" hayalet kırpılma verdi). Gösterim zaten `tm-tip.js`te; kutu da
   çizilmesin. Görsel sonuç AYNI (ikisinde de görünmez), yalnız yerleşim etkisi gider. */
.tm-ds [data-tip]::after { content: none; }
@media (prefers-reduced-motion: reduce) {
  .tm-ds [data-tip]::after { transition: none; }
}

/* ── "Kurallarım" zenginleştirme + kural süzgeci (2026-09-18) ────────────────
   Kullanıcı: *"madem Kurallarım sekmesi var, hangi pazaryerine ait olduğu,
   hangi ürünleri kapsadığı, özelliklerinin ne olduğu, kaç ürüne uygulandığı
   gösterilmeli · ikon kullanımını artırmalıyız, yazılar fazla ve çok büyük."*
   Hareket bütçesi: geçiş/animasyon YOK. */

/* ① Filtre butonlarındaki sayı rozeti */
.tm-ds .bb3rm-cnt {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; margin-left: var(--tm-space-1); padding: 0 5px;
  border-radius: var(--tm-radius-full);
  background: var(--tm-bg-subtle); color: var(--tm-text-secondary);
  font-size: var(--tm-type-micro); font-weight: var(--tm-weight-semibold);
  font-variant-numeric: tabular-nums; line-height: 1;
}
/* Sıfır GİZLENMEZ, yalnız soluklaşır: "0" ile "bilinmiyor" aynı şey değil. */
.tm-ds .bb3rm-cnt--zero { opacity: .55; }
.tm-ds .tm-btn--active .bb3rm-cnt { background: var(--tm-accent-bg); color: var(--tm-accent-fg); }

/* ⑦ "N ürün" — tıklanabilir olduğu GÖRÜNSÜN (düz metin gibi durmasın) */
.tm-ds .bb3rm-count {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px var(--tm-space-2);
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-sm);
  background: transparent; color: var(--tm-accent-fg);
  font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold);
  cursor: pointer; line-height: 1.5;
}
.tm-ds .bb3rm-count:hover:not(:disabled) { background: var(--tm-accent-bg); border-color: var(--tm-accent-fg); }
.tm-ds .bb3rm-count:disabled { color: var(--tm-text-muted); cursor: default; opacity: .7; }
.tm-ds .bb3rm-count:focus-visible { outline: 2px solid var(--tm-accent-fg); outline-offset: 2px; }

/* ⑥+② Kural özellikleri ve son fiyatlama — ikincil satır, küçük ve soluk */
.tm-ds .bb3rm-meta {
  display: block; width: 100%;
  font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tm-ds .bb3rm-idcol { flex-wrap: wrap; row-gap: 2px; min-width: 0; }
/* 2026-10-13: kural adı ve özellik satırı tek satıra kırpılınca kart "Kayıp tablosu …"
   diyordu — kuralın NE olduğu okunmuyordu. İki satıra kadar sarar. */
.tm-ds .bb3rm-idcol [data-bb3rm-name] {
  flex-basis: 100%; white-space: normal; font-weight: var(--tm-weight-semibold);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.tm-ds .bb3rm-idcol .bb3rm-meta { white-space: normal; }
/* Ad sütunu en az 320 px: dar kalınca sağdaki rozet/düğme şeridi alt satıra iner. */
.tm-ds [data-bb3rm-row] > .tm-card__body { flex-wrap: wrap; row-gap: 10px; }
.tm-ds [data-bb3rm-row] > .tm-card__body > .tm-grow { min-width: min(320px, 100%); }

/* ⑧ Strateji: uzun metin yerine ikon + kısa etiket (tam cümle tooltip'te) */
.tm-ds .bb3rm-strat { display: inline-flex; align-items: center; gap: 4px; }
.tm-ds .bb3rm-strat i,
.tm-ds .bb3rm-strat svg { width: 13px; height: 13px; flex-shrink: 0; }

/* ⑦ Fırsat listesindeki aktif kural süzgeci rozeti */
.tm-ds .bbx-rulechip {
  display: inline-flex; align-items: center; gap: var(--tm-space-1);
  padding: 2px var(--tm-space-2);
  border: 1px solid var(--tm-accent-fg);
  border-radius: var(--tm-radius-sm);
  background: var(--tm-accent-bg); color: var(--tm-accent-fg);
  font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold);
}
.tm-ds .bbx-rulechip i,
.tm-ds .bbx-rulechip svg { width: 13px; height: 13px; }
.tm-ds .bbx-rulechip button {
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; background: transparent; color: inherit; cursor: pointer;
  padding: 0; width: 16px; height: 16px;
}
.tm-ds .bbx-rulechip button:hover { opacity: .7; }

/* ── Kural satırı: pazaryeri ikonu · kural ikonu (2026-09-19) ────────────────
   Kullanıcı: "pazaryeri adı yerine ikonu kullanılabilir · sağda boş görsel var,
   onun yerine ikonlar koyulabilir". */
.tm-ds .bb3rm-plat {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; flex-shrink: 0;
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-sm);
  background: var(--tm-bg-surface);
  font-size: var(--tm-type-micro); color: var(--tm-text-secondary);
  overflow: hidden;
}
.tm-ds .bb3rm-plat img { width: 18px; height: 18px; object-fit: contain; }

/* Kohort kuralının ürünü yok → boş görsel kutusu yerine kuralın kendi ikonu. */
.tm-ds .bb3rm-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; flex-shrink: 0;
  border-radius: var(--tm-radius-control);
  background: var(--tm-accent-bg); color: var(--tm-accent-fg);
}
.tm-ds .bb3rm-icon--off { background: var(--tm-bg-subtle); color: var(--tm-text-muted); }
.tm-ds .bb3rm-icon i, .tm-ds .bb3rm-icon svg { width: 18px; height: 18px; }

/* Kurallarım — bağlı ürün görsel şeridi + açılır ürün listesi (2026-10-13). */
.tm-ds .bb3rm-strip { display: inline-flex; align-items: center; gap: 4px; flex-basis: 100%; margin-top: 4px; }
.tm-ds .bb3rm-strip__img {
  width: 28px; height: 28px; flex-shrink: 0; object-fit: cover;
  border-radius: 6px; border: 1px solid var(--tm-border); background: var(--tm-bg-subtle);
}
.tm-ds .bb3rm-strip__img.is-broken { visibility: hidden; }
.tm-ds .bb3rm-strip__more {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 28px; height: 28px; padding: 0 6px; border-radius: 6px;
  background: var(--tm-bg-subtle); color: var(--tm-text-secondary); font-size: 12px; font-weight: 600;
}
.tm-ds .bb3rm-plist {
  list-style: none; margin: 0; padding: 6px 16px 12px;
  border-top: 1px solid var(--tm-border); display: grid; gap: 4px;
}
.tm-ds .bb3rm-plist__item {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 12px; align-items: center;
  padding: 4px 0;
}
@media (max-width: 640px) {
  .tm-ds .bb3rm-plist__item { grid-template-columns: minmax(0, 1fr); gap: 0; }
}
.tm-ds .bb3rm-edit { color: var(--tm-accent-fg); border-color: var(--tm-accent-fg); }
.tm-ds .bb3rm-edit:hover { background: var(--tm-accent-bg); }

/* ── Kural düzenleme kipi ────────────────────────────────────────────────── */
.tm-ds .bb3re { display: flex; flex-direction: column; gap: var(--tm-space-3); }
.tm-ds .bb3re__row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--tm-space-3); }
.tm-ds .bb3re__f { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.tm-ds .bb3re__lbl {
  font-size: var(--tm-type-caption);
  font-weight: var(--tm-weight-semibold);
  color: var(--tm-text-secondary);
}
.tm-ds .bb3re__in {
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-control);
  background: var(--tm-bg-surface);
  color: var(--tm-text-primary);
  font-size: var(--tm-type-body);
  padding: 7px var(--tm-space-2);
  min-width: 0;
}
.tm-ds .bb3re__in:focus-visible { outline: 2px solid var(--tm-accent-fg); outline-offset: 1px; }
.tm-ds .bb3re__ctx { margin: 0; }
.tm-ds .bb3re__title { display: inline-flex; align-items: center; gap: 8px; }
.tm-ds .bb3re__title i, .tm-ds .bb3re__title svg { width: 18px; height: 18px; color: var(--tm-accent-fg); }
.tm-ds .bb3re__note {
  display: flex; align-items: flex-start; gap: 6px; margin: 0;
  padding: var(--tm-space-2);
  border-radius: var(--tm-radius-sm);
  background: var(--tm-warning-bg); color: var(--tm-warning-fg);
}
.tm-ds .bb3re__note i, .tm-ds .bb3re__note svg { width: 14px; height: 14px; flex-shrink: 0; margin-top: 2px; }
.tm-ds .bb3re__err {
  margin: 0; padding: var(--tm-space-2);
  border-radius: var(--tm-radius-sm);
  background: var(--tm-danger-bg); color: var(--tm-danger-fg);
  font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold);
}
@media (max-width: 560px) {
  .tm-ds .bb3re__row { grid-template-columns: 1fr; }
}






/* ═══ 2026-10-10 tur 3 (kullanıcı: "yazılar çok fazla ve gereksiz büyük, kötü fontlar") ═══
   ÖLÇÜLDÜ (1440×900, gerçek sayfa): satırda 13 görünür metin · 5 farklı font-size
   (11/12/13/14/16) · 2 font ailesi (Inter + ui-monospace). Hedef: ≤9 metin · 3 boy · 1 aile.
   ① barkod sans+tabular (yukarıda) ② 16/15/13 kademeleri kaldırıldı (yukarıda)
   ③ Durum sütununda yıldız GİZLİ: "★★★" ile "Hemen kazan" aynı bilgiyi iki kez söylüyordu;
      rozet asıl, yıldız `title`'da anlatılıyor (yıldız filtre çiplerinde KALIR).
      ⛔ Önce burada `display:none` vardı ama şablon yıldızı basmaya DEVAM ediyordu
      (JS'te "yıldız varsa göster" dalı ölü kalmıştı — bağımsız denetim ②). Artık
      yıldız ŞABLONDAN kaldırıldı; gizleyecek bir şey yok, kural da kaldırıldı. */
.tm-ds .bbk-row *, .tm-ds .bbk-head * { font-family: var(--tm-font-sans); }
.tm-ds .bbk-row .tm-num, .tm-ds .bbk-row .bbk-barcode { font-variant-numeric: tabular-nums; }
/* 🔴 2026-10-11 — ANA AKSİYON GERÇEK DÜĞME (kullanıcı: "ana odak Aksiyon (Uygula)
   ve Net Kazanç olmalı · tek tıkla aksiyon"). Önce mavi METİN bağlantısıydı; satırın
   diğer mavi sayılarıyla karışıyordu. Artık sayfadaki TEK dolu yeşil öğe. */
.tm-ds .bbk-apply__btn {
  font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold);
  background: var(--tm-success-fg); color: #fff; border: 0;
  border-radius: var(--tm-radius-control, 6px); padding: 7px 12px; cursor: pointer;
  white-space: nowrap; width: 100%; text-align: center;
}
.tm-ds .bbk-apply__btn:hover { filter: brightness(1.06); }
.tm-ds .bbk-apply__btn:focus-visible { outline: 2px solid var(--tm-focus, #2563eb); outline-offset: 2px; }
/* İkincil aksiyon: düz, nötr — birincil düğmeyle yarışmaz. */
.tm-ds .bbk-addrule { color: var(--tm-text-secondary, #475569); font-weight: var(--tm-weight-medium); }
.tm-ds .bbk-addrule:hover { color: var(--tm-text-primary); text-decoration: underline; }
/* Aksiyon hücresi TEK satır yüksekliğinde sabit kalır → sütunlar kaymaz. */
.tm-ds .bbk-cell--rule { display: flex; align-items: center; min-width: 0; }
.tm-ds .bbk-rulechip { white-space: nowrap; }
/* Doğrulama rozeti "tekrar dene" hâli (2026-10-10 tur 3): tıklanabilir görünür. */
.tm-ds .bbk-verify-badge.is-retry { cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.tm-ds .bbk-verify-badge.is-retry:hover { filter: brightness(.95); }
.tm-ds .bbk-verify-badge:focus-visible { outline: 2px solid var(--tm-focus, #2563eb); outline-offset: 2px; }

/* ═══ 2026-10-10 tur 3 — METİN YERİNE İKON (kullanıcı isteği) ═══════════════
   "çok fazla yazı istemiyorum, bazı şeyleri ikonlarla halledelim; ikonun üzerine
   gelince kısaca açıklama gösterilsin. Birbirine girmiş / yarım kalmış yazı
   istemiyorum. Fontlar birbiriyle uyumlu, boyutları ÖNCELİĞE göre olsun."
   ① "rakipli"/"tek satıcı" → users/user ikonu  ② "kâr"/"zarar" → trending ikonu
   ③ "tahmini" → circle-help ikonu. Üçünde de anlam `title` + `aria-label`da.
   İkonlar metin AKIŞINDA (inline) durur; satır yüksekliği değişmez. */
.tm-ds .bbk-row [data-bb3-rank-of] svg,
.tm-ds .bbk-row [data-bb3-netkar] svg,
.tm-ds .bbk-sira-tahmini svg {
  width: 13px; height: 13px; stroke-width: 2; vertical-align: -2px; flex: 0 0 auto;
}
.tm-ds .bbk-row [data-bb3-netkar] { display: inline-flex; align-items: center; gap: 4px; }
.tm-ds .bbk-row [data-bb3-rank-of] { display: inline-flex; align-items: center; opacity: .75; }
.tm-ds .bbk-row [data-bb3-rank-of][title], .tm-ds .bbk-sira-tahmini[title] { cursor: help; }
.tm-ds .bbk-sira-tahmini { padding: 0; background: none; border: 0; line-height: 0; }
/* Fiyat hücresi: iki sayı ÜST ALTA (çakışma düzeltmesi). İkincil satır tek satırda
   kalır; ok ile tutar arasında nefes payı, fark yüzdesi ayrı boşlukla ayrılır. */
.tm-ds .bbk-row .bbk-fiyat-alt { display: flex; align-items: baseline; gap: 5px; white-space: nowrap; }
.tm-ds .bbk-row .bbk-fiyat-alt .bbk-fiyat-ok { margin: 0 1px 0 0; }

/* 🔴 "yarım kalmış yazı" kilidi (kullanıcı): satırdaki hiçbir metin KIRPILMAZ.
   Ad uzun olursa tek yerde ve BİLEREK kısalır (üç nokta + `title` tam adı verir);
   geri kalan hücreler içeriğe göre yer açar, taşmaz. */
/* 🔴 KULLANICI: "metinler gereksiz yere kesilmesin". Ürün adı artık KESİLMİYOR:
   sığmazsa İKİ satıra sarar, üçüncü satıra taşarsa orada durur (satır yüksekliği
   patlamasın). Ölçüldü: 1440 px'te 10 adın 4'ü tek satıra sığmıyordu. */
.tm-ds .bbk-row .bbk-name {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; white-space: normal; overflow-wrap: anywhere;
}
.tm-ds .bbk-row .bbk-cell--num { min-width: 0; }
/* Ürün hücresi artık TEK şey taşıyor: adı. */
.tm-ds .bbk-cell--id { flex-direction: row; align-items: center; }
.tm-ds .bbk-cell--id .bbk-name { min-width: 0; }
.tm-ds .bbk-detail__kunye .bbk-platform-ico { width: 13px; height: 13px; vertical-align: -2px; margin-left: 4px; }
/* Başlık hücreleri, veri hücreleriyle AYNI hizada olmalı. */
.tm-ds .bbk-head .bbk-cell--num, .tm-ds .bbk-head .bbk-th.bbk-cell--num { justify-content: flex-end; text-align: right; }
.tm-ds .bbk-head .bbk-cell--score { justify-content: flex-start; text-align: left; }
.tm-ds .bbk-head .bbk-cell, .tm-ds .bbk-head .bbk-th { white-space: nowrap; flex-wrap: nowrap; }
/* Başlık ile ilk satır arasındaki ton farkı: başlık ZEMİNSİZ, yalnız küçük ve
   soluk (kullanıcı: "zemin/çerçeve azalt"). */
.tm-ds .bbk-head { background: none; }
.tm-ds .bbk-head .bbk-cell, .tm-ds .bbk-head .bbk-th {
  font-size: var(--tm-type-micro); font-weight: var(--tm-weight-medium); color: var(--tm-text-muted);
  display: flex; flex-direction: row; align-items: center; gap: 3px; line-height: 14px;
}
/* "Durum" başlığı sütun-flex'i miras alıp YUKARI kayıyordu (veri hücresi dikey,
   başlık değil). Başlıkta hepsi yatay ve ortalı. */
.tm-ds .bbk-head .bbk-cell--score { flex-direction: row; align-items: center; justify-content: flex-start; }

/* ═══ 2026-10-10 tur 3 — bağımsız denetim bulguları ═══════════════════════════
   ⑧ "Uygula · 26.018,00 TL" 1440 px'te bile iki satıra bölünüyordu (ikinci satırda
      yalnız "TL" kalıyordu, 3 satırda ölçüldü) → sarma kapalı, taşarsa üç nokta.
   ⑥ 390 px'te filtre çipleri kesiliyordu (scrollWidth 480 / clientWidth 334) ve
      kaydırılabildiğine dair hiçbir ipucu yoktu → sağ kenarda solma maskesi. */
.tm-ds .bbk-addrule { background: none; border: 0; font: inherit; cursor: pointer; padding: 0; }
.tm-ds .bbk-apply__btn { white-space: nowrap; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 720px) {
  .tm-ds .bbk-chips {
    -webkit-mask-image: linear-gradient(to right, #000 85%, transparent 100%);
    mask-image: linear-gradient(to right, #000 85%, transparent 100%);
    scroll-snap-type: x proximity;
  }
  .tm-ds .bbk-chips > * { scroll-snap-align: start; }
}

/* ═══ 2026-10-11 — TEK TAB/FİLTRE ÇUBUĞU + MOBİL AKSİYON DOLGUSU ═════════════
   Kullanıcı: "Trendyol/Hepsiburada ve Kayıp ürünler/Kurallarım sekmelerini temiz
   ve modern TEK bir tab/filtre çubuğunda birleştir" · "başlığı ve açıklamayı
   küçült/tek satıra indir" · "mobilde sağ alttaki sohbet düğmesi aksiyon alanlarını
   kapatmasın (padding-bottom)". */
.tm-ds #bb3Page .tm-page-header { margin-bottom: var(--tm-space-2); }
.tm-ds #bb3Page .tm-page-header h1, .tm-ds #bb3Page #bb3PageTitle {
  font-size: var(--tm-type-title); line-height: var(--tm-type-title-lh); margin: 0;
}
.tm-ds #bb3Page .tm-page-header__subtitle { margin: 2px 0 0; }

.tm-ds .bbk-tabbar {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: var(--tm-space-2); margin-bottom: var(--tm-space-3);
}
.tm-ds .bbk-tabbar__right { display: flex; align-items: center; gap: var(--tm-space-3); min-width: 0; }

/* 🔴 Sohbet balonu sabit ve sağ altta; mobilde SON satırın aksiyonunu örtüyordu.
   Liste kartının altına balon yüksekliği kadar dolgu eklenir (ölçü: 56 px balon
   + 24 px kenar boşluğu). Masaüstünde balon tablonun dışında kaldığı için gerekmez. */
@media (max-width: 720px) {
  .tm-ds #bb3Page .bbk-list { padding-bottom: 88px; }
  .tm-ds .bbk-tabbar { gap: var(--tm-space-1); }
  .tm-ds .bbk-tabbar__right { width: 100%; justify-content: space-between; }
}

/* ═══ 2026-10-11 — SON İKİ RENK KAYNAĞI NÖTRLENDİ ══════════════════════════
   Kullanıcı: "sadece kritik eylemler renkli olsun, diğer her şey nötr gri/siyah".
   ① Süzgeç çiplerindeki ★ turuncusu: çipin kendi METNİ ("Hemen kazan") zaten
      kademeyi söylüyordu; yıldız ikinci kez söylüyor, üstelik renkle.
   ② "Maliyet yok" şeridi: dolu sarı bir banttı. İş hâlâ duruyor ama bant artık
      zeminsiz — tek renkli öğe KALAN tek aksiyon: "Maliyet gir" bağlantısı. */
.tm-ds .bbk-chip .bbk-stars { color: var(--tm-text-muted); }
.tm-ds .bbk-banner {
  background: none; border: 0; border-bottom: 1px solid var(--tm-border);
  border-radius: 0; color: var(--tm-text-secondary, #475569);
  padding-left: 0; padding-right: 0;
}
.tm-ds .bbk-banner svg { color: var(--tm-text-muted); }

/* Mobil kart yükseklik bütçesi (140 px) — son 3 px: tutar satırı 18→16 px ve
   yeşil aksiyon düğmesinin dikey dolgusu 7→5 px. Ölçülerek alındı, göz kararı değil. */
@media (max-width: 720px) {
  .tm-ds .bbk-rowbtn > .bbk-cell--num .bbk-cell__main { line-height: 16px; }
  .tm-ds .bbk-apply__btn { padding: 5px 10px; }
}

/* 🔴 2026-10-11 — DOĞRULAMA ROZETİ TAŞIYORDU. Ölçüldü: "Kural kaydedildi ·
   gönderilmedi" 142 px'lik Aksiyon sütununa sığmıyor, hücreyi taşırıyordu
   (kullanıcı: "sütunlarda kayma var" / "yarım kalmış yazı istemiyorum").
   Metni KISALTMADIM — kısaltmak "asılı kalmıyor" kilidini anlamsızlaştırırdı
   (iki durum aynı kelimeye düşerdi). Bunun yerine rozet iki satıra sarıyor;
   bu geçici bir durum, kalıcı satır yüksekliğini etkilemiyor. */
.tm-ds .bbk-verify-badge { white-space: normal; text-align: left; }
.tm-ds .bbk-cell--rule { align-items: center; flex-wrap: wrap; row-gap: 4px; }

/* Aksiyon sarmalayıcısı ve düğmesi hücreden TAŞMAZ (fazlalık varsa düğme daralır). */
.tm-ds .bbk-apply-wrap { min-width: 0; max-width: 100%; }
.tm-ds .bbk-apply__btn { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }

/* ═══ 2026-10-11 — SIRA ROZETİ · ÜRÜN KİMLİĞİ · AKSİYON İKİLİSİ ═════════════
   Yön: yoğun, sessiz, taranabilir bir OPERASYON tablosu (günlük tekrar eden iş).
   Akılda kalan detay: SIRA ROZETİ — Buy Box'ta hikâye konumdur, tutarlar onu
   açıklar. Bu yüzden sıra satırın başında ve tek görsel işaret o. */

/* Sıra: ödül ikonu + rakam. "sıra" sözcüğü YOK (kullanıcı kararı). */
.tm-ds .bbk-cell--sira { display: flex; align-items: center; gap: 4px; min-width: 0; }
.tm-ds .bbk-rank {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px 3px 6px; border-radius: 999px;
  background: var(--tm-surface-sunken); color: var(--tm-text-secondary, #475569);
  font-variant-numeric: tabular-nums; cursor: help;
  transition-property: background-color, color; transition-duration: 120ms; transition-timing-function: ease-out;
}
.tm-ds .bbk-rank svg { width: 13px; height: 13px; flex: 0 0 13px; margin-top: -1px; }  /* optik hiza */
.tm-ds .bbk-rank b { font-size: var(--tm-type-body); font-weight: var(--tm-weight-semibold); line-height: 18px; }
/* 1. sıra = Buy Box SENDE — tek renkli istisna, kazanım bildirir. */
.tm-ds .bbk-rank.bbk-rank--ilk { background: var(--tm-success-bg); color: var(--tm-success-fg); }
/* 2026-10-13: gönderim sonrası sıra takibi (bb3-kayip-takip.js) — "kontrol ediliyor" + değişim. */
.tm-ds .bbk-rank__kontrol { display: inline-flex; color: var(--tm-text-muted); }
.tm-ds .bbk-rank__kontrol svg { width: 12px; height: 12px; flex: 0 0 12px; margin: 0; }
.tm-ds .bbk-rank__eski { color: var(--tm-text-muted); font-weight: var(--tm-weight-regular, 400); }
.tm-ds .bbk-rank__ok { color: var(--tm-text-muted); }
.tm-ds .bbk-rank.is-degisti.is-yukseldi { background: var(--tm-success-bg); color: var(--tm-success-fg);
  animation: bb3-vurgu 1.2s ease-out 2; }
.tm-ds .bbk-rank.is-degisti.is-dustu { background: var(--tm-warning-bg); color: var(--tm-warning-fg); }
@keyframes bb3-vurgu { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--tm-success-fg) 45%, transparent); }
  100% { box-shadow: 0 0 0 8px transparent; } }
/* Spinner: yalnız GERÇEK bir istek sürerken (bkz. modül başlığı). */
.tm-ds .bb3-doner svg { animation: bb3-don 0.9s linear infinite; }
@keyframes bb3-don { to { transform: rotate(360deg); } }
.tm-ds .bbk-row--isleniyor { background: var(--tm-surface-sunken); }
@media (prefers-reduced-motion: reduce) {
  .tm-ds .bb3-doner svg { animation: none; }
  .tm-ds .bbk-rank.is-degisti { animation: none; }
}

/* Ürün: ad birincil, altında barkod · stok. */
.tm-ds .bbk-cell--id { flex-direction: column; align-items: flex-start; gap: 2px; justify-content: center; }
.tm-ds .bbk-row .bbk-name { text-wrap: pretty; }
.tm-ds .bbk-kimlik {
  display: flex; align-items: center; gap: 8px; min-width: 0; max-width: 100%;
  font-size: var(--tm-type-micro); line-height: 14px; color: var(--tm-text-muted);
}
.tm-ds .bbk-kimlik .bbk-barcode { font-size: inherit; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-ds .bbk-kimlik .bbk-stok { white-space: nowrap; cursor: help; }
.tm-ds .bbk-kimlik .bbk-stok::before { content: "·"; margin-right: 8px; color: var(--tm-border-strong, #cbd5e1); }

/* Aksiyon: birincil (dolu yeşil) + ikincil (düz metin) YAN YANA. */
.tm-ds .bbk-cell--rule { gap: 10px; }
.tm-ds .bbk-apply-wrap { flex: 0 1 auto; }
.tm-ds .bbk-apply__btn { width: auto; padding: 7px 14px; }
/* Hit alanı: görünen metin küçük olsa da dokunulabilir yükseklik korunur. */
.tm-ds .bbk-addrule { min-height: 32px; display: inline-flex; align-items: center; padding: 0 2px; }
.tm-ds .bbk-apply__btn, .tm-ds .bbk-addrule {
  transition-property: background-color, color, filter; transition-duration: 120ms; transition-timing-function: ease-out;
}
.tm-ds .bbk-apply__btn:active { transform: scale(.97); }

/* Ürün görseli: kenarı zemine karışmasın (nötr alfa, marka rengi DEĞİL). */
.tm-ds .bbk-thumb img { outline: 1px solid rgba(0, 0, 0, .08); outline-offset: -1px; }

/* Mobil: pazaryeri seçici kesiliyordu (ölçüldü 390 px — "Hepsibura…"). Çubuğun
   sağ tarafı kendi satırına geçer ve seçici kalan genişliği paylaşır. */
@media (max-width: 720px) {
  .tm-ds .bbk-tabbar { flex-direction: column; align-items: stretch; }
  .tm-ds .bbk-tabbar__right { flex-wrap: wrap; gap: var(--tm-space-2); }
  .tm-ds .bbk-tabbar__right #bb3Markets { flex: 1 1 auto; min-width: 0; }
  .tm-ds .bbk-tabbar__right #bb3Markets button { flex: 1 1 0; min-width: 0; justify-content: center; }
}

/* ═══ 2026-10-11 — İKİ AKSİYON, TEK DİL (kullanıcı: "Uygula butonu ne güzel,
   yanındaki Kural butonu niye değişik") ═════════════════════════════════════
   "Uygula" dolu düğmeydi, "Kural" düz bir metin bağlantısıydı — aynı satırda iki
   FARKLI bileşen dili. Artık ikisi de DÜĞME: aynı yükseklik, aynı yarıçap, aynı
   dolgu. Ayrım yalnız AĞIRLIKTA (birincil dolu yeşil · ikincil çerçeveli nötr) —
   hiyerarşi korunuyor ama tutarsızlık bitiyor. */
.tm-ds .bbk-apply__btn,
.tm-ds .bbk-addrule {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 34px; padding: 0 14px; border-radius: var(--tm-radius-control, 6px);
  font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold);
  line-height: 1; white-space: nowrap; cursor: pointer;
  transition-property: background-color, border-color, color, filter;
  transition-duration: 120ms; transition-timing-function: ease-out;
}
.tm-ds .bbk-apply__btn { background: var(--tm-success-fg); color: #fff; border: 1px solid var(--tm-success-fg); }
.tm-ds .bbk-apply__btn:hover { filter: brightness(1.06); }
.tm-ds .bbk-addrule {
  background: var(--tm-surface); color: var(--tm-text-secondary, #475569);
  border: 1px solid var(--tm-border-strong, #cbd5e1); text-decoration: none;
}
.tm-ds .bbk-addrule:hover { background: var(--tm-surface-sunken); color: var(--tm-text-primary); text-decoration: none; }
.tm-ds .bbk-apply__btn:active, .tm-ds .bbk-addrule:active { transform: scale(.97); }
.tm-ds .bbk-cell--rule { gap: 8px; }


/* =================================================================
   KURALLARIM — KART (2026-10-13 yeniden tasarım; bb3-rule-card.js)
   Kullanıcı: "kurallar sayfasını beğenmedim". Tek sıraya sıkışmış satır yerine
   ızgara kart: cümle başlık · koruma çipleri · üç sayı · ürün görselleri · işlemler.
   ================================================================= */
.tm-ds .bb3rm-grid {
  display: grid; gap: 14px; margin-top: 12px;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 420px), 1fr));
}
.tm-ds .bb3rm-card {
  display: flex; flex-direction: column; gap: 12px; min-width: 0;
  background: var(--tm-surface); border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-card); box-shadow: var(--tm-shadow-xs);
  padding: 16px 16px 12px;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.tm-ds .bb3rm-card:hover { border-color: var(--tm-border-strong); box-shadow: var(--tm-shadow-sm); }
.tm-ds .bb3rm-card.is-paused { background: var(--tm-bg-subtle); }
.tm-ds .bb3rm-card.is-paused .bb3rm-card__name,
.tm-ds .bb3rm-card.is-paused .bb3rm-stats dd { color: var(--tm-text-secondary); }

.tm-ds .bb3rm-card__head { display: flex; align-items: flex-start; gap: 12px; min-width: 0; }
.tm-ds .bb3rm-card__ico {
  flex: none; width: 40px; height: 40px; border-radius: 12px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--tm-accent-bg); color: var(--tm-accent-fg);
}
.tm-ds .bb3rm-card__ico.is-off { background: var(--tm-surface-sunken); color: var(--tm-text-muted); }
.tm-ds .bb3rm-card__ico svg { width: 20px; height: 20px; }
.tm-ds .bb3rm-card__ico { overflow: hidden; }
.tm-ds .bb3rm-card__img { width: 100%; height: 100%; object-fit: cover; }
.tm-ds .bb3rm-card__title { flex: 1; min-width: 0; }
.tm-ds .bb3rm-card__name {
  margin: 0; font-size: var(--tm-text-base); line-height: 1.35;
  font-weight: var(--tm-weight-semibold); color: var(--tm-text-primary);
  overflow-wrap: anywhere;
}
.tm-ds .bb3rm-card__sub { margin: 2px 0 0; font-size: var(--tm-text-xs); color: var(--tm-text-muted); }
.tm-ds .bb3rm-card__head .bb3rm-plat { flex: none; margin-top: 2px; }

.tm-ds .bb3rm-pill {
  flex: none; display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; border-radius: var(--tm-radius-full);
  font-size: var(--tm-text-xs); font-weight: var(--tm-weight-semibold); white-space: nowrap;
  cursor: help;
}
.tm-ds .bb3rm-pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.tm-ds .bb3rm-pill--ok { background: var(--tm-success-bg); color: var(--tm-success-fg); }
.tm-ds .bb3rm-pill--warn { background: var(--tm-warning-bg); color: var(--tm-warning-fg); }
.tm-ds .bb3rm-pill--off { background: var(--tm-surface-sunken); color: var(--tm-text-secondary); }

.tm-ds .bb3rm-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.tm-ds .bb3rm-chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: var(--tm-radius-full);
  background: var(--tm-bg-subtle); border: 1px solid var(--tm-border);
  font-size: var(--tm-text-xs); color: var(--tm-text-secondary);
}
.tm-ds .bb3rm-chip svg { width: 12px; height: 12px; }

.tm-ds .bb3rm-stats {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin: 0;
  border: 1px solid var(--tm-border); border-radius: var(--tm-radius-lg); overflow: hidden;
}
.tm-ds .bb3rm-stats > div { padding: 8px 12px; min-width: 0; }
.tm-ds .bb3rm-stats > div + div { border-left: 1px solid var(--tm-border); }
.tm-ds .bb3rm-stats dt { font-size: 11px; color: var(--tm-text-muted); line-height: 1.3; }
.tm-ds .bb3rm-stats dd {
  margin: 2px 0 0; font-size: var(--tm-text-lg); font-weight: var(--tm-weight-semibold);
  color: var(--tm-text-primary); white-space: nowrap;
}
.tm-ds .bb3rm-stats dd.is-ok { color: var(--tm-success-fg); }

.tm-ds .bb3rm-urunler { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.tm-ds .bb3rm-card .bb3rm-strip { flex-basis: auto; margin: 0; gap: 0; }
.tm-ds .bb3rm-card .bb3rm-strip__img {
  width: 40px; height: 40px; border-radius: 10px; border: 2px solid var(--tm-surface);
  box-shadow: 0 0 0 1px var(--tm-border); background: var(--tm-bg-subtle);
}
.tm-ds .bb3rm-card .bb3rm-strip__img + .bb3rm-strip__img,
.tm-ds .bb3rm-card .bb3rm-strip__img + .bb3rm-strip__more { margin-left: -8px; }
.tm-ds .bb3rm-card .bb3rm-strip__more {
  width: 40px; height: 40px; min-width: 40px; border-radius: 10px; border: 2px solid var(--tm-surface);
  box-shadow: 0 0 0 1px var(--tm-border);
}
.tm-ds .bb3rm-more {
  display: inline-flex; align-items: center; gap: 4px; padding: 4px 2px;
  border: 0; background: none; cursor: pointer;
  font-size: var(--tm-text-sm); font-weight: var(--tm-weight-semibold); color: var(--tm-accent-fg);
}
.tm-ds .bb3rm-more svg { width: 14px; height: 14px; }
.tm-ds .bb3rm-more:disabled { color: var(--tm-text-muted); cursor: default; }
.tm-ds .bb3rm-more:focus-visible { outline: 2px solid var(--tm-accent-fg); outline-offset: 2px; border-radius: 4px; }
.tm-ds .bb3rm-card .bb3rm-plist {
  margin: 0; padding: 4px 12px; border: 1px solid var(--tm-border); border-radius: var(--tm-radius-lg);
  background: var(--tm-bg-subtle); max-height: 260px; overflow: auto;
}
.tm-ds .bb3rm-card .bb3rm-plist__item + .bb3rm-plist__item { border-top: 1px solid var(--tm-border); }

.tm-ds .bb3rm-warn {
  display: grid; gap: 4px; padding: 8px 10px; border-radius: var(--tm-radius-md);
  background: var(--tm-warning-bg); color: var(--tm-warning-fg); font-size: var(--tm-text-xs);
}
.tm-ds .bb3rm-warn p { margin: 0; display: flex; gap: 6px; align-items: flex-start; }
.tm-ds .bb3rm-warn svg { width: 14px; height: 14px; flex: none; margin-top: 1px; }

.tm-ds .bb3rm-card__foot {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin-top: auto; padding-top: 10px; border-top: 1px solid var(--tm-border);
}
.tm-ds .bb3rm-card__foot .tm-btn svg { width: 14px; height: 14px; }
.tm-ds .bb3rm-del { color: var(--tm-danger-fg); }
.tm-ds .bb3rm-del:hover { background: var(--tm-danger-bg); }

@media (max-width: 640px) {
  .tm-ds .bb3rm-card { padding: 14px 12px 10px; }
  /* Başlık sütunu daralmasın: ikon | başlık | pazaryeri, hap ikinci satırda başlığın altında. */
  .tm-ds .bb3rm-card__head {
    display: grid; grid-template-columns: 40px minmax(0, 1fr) auto; column-gap: 12px; row-gap: 6px;
  }
  .tm-ds .bb3rm-card__head .bb3rm-pill { grid-column: 2 / -1; justify-self: start; }
  .tm-ds .bb3rm-stats > div { padding: 8px; }
  .tm-ds .bb3rm-stats dd { font-size: var(--tm-text-sm); white-space: normal; }
  .tm-ds .bb3rm-card__foot { gap: 2px; }
  .tm-ds .bb3rm-card__foot .tm-btn { padding-left: 8px; padding-right: 8px; }
  .tm-ds .bb3rm-card__foot { flex-wrap: nowrap; }
  .tm-ds .bb3rm-card__foot .bb3rm-lbl { display: none; }   /* "Ürün ekle" yalnız ikon; ad aria-label'da */
}
@media (prefers-reduced-motion: reduce) { .tm-ds .bb3rm-card { transition: none; } }


/* =================================================================
   2026-10-13 — kural netliği: karar tonları · ürün tablosu · ekleme modu · modal hedef
   Tonlar (bb3-karar.js): ok = gönderildi · durdu = kâr koruması devrede (beklenen)
   · bekle = sırada / değişiklik yok · hata = bayinin müdahalesi gerekir.
   ================================================================= */
.tm-ds .bb3rm-kararlar { display: flex; flex-wrap: wrap; gap: 6px; }
.tm-ds .bb3rm-karar {
  display: inline-flex; align-items: center; gap: 4px; padding: 3px 9px; border-radius: var(--tm-radius-full);
  font-size: var(--tm-text-xs); cursor: help; border: 1px solid transparent;
}
.tm-ds .bb3rm-karar b { font-size: var(--tm-text-sm); }
.tm-ds .bb3rm-karar svg { width: 14px; height: 14px; flex: 0 0 auto; }
.tm-ds .bb3rm-karar--ok { background: var(--tm-success-bg); color: var(--tm-success-fg); }
.tm-ds .bb3rm-karar--durdu { background: var(--tm-warning-bg); color: var(--tm-warning-fg); }
.tm-ds .bb3rm-karar--bekle { background: var(--tm-surface-sunken); color: var(--tm-text-secondary); }
.tm-ds .bb3rm-karar--hata { background: var(--tm-danger-bg); color: var(--tm-danger-fg); }

/* Ürün tablosu (Kurallarım → "N ürünü gör") */
.tm-ds .bb3rm-card .bb3rm-plist { display: block; padding: 0; overflow: auto; max-height: 340px; }
.tm-ds .bb3rm-pt__r {
  display: grid; grid-template-columns: minmax(0, 1fr) 82px 92px 44px;
  gap: 8px; align-items: center; padding: 7px 12px; font-size: var(--tm-text-xs); color: var(--tm-text-primary);
}
.tm-ds .bb3rm-pt__r + .bb3rm-pt__r { border-top: 1px solid var(--tm-border); }
.tm-ds .bb3rm-pt__r--bas {
  position: sticky; top: 0; background: var(--tm-surface); z-index: 1;
  font-weight: var(--tm-weight-semibold); color: var(--tm-text-muted); text-transform: none;
}
.tm-ds .bb3rm-pt__c.tm-num { text-align: right; white-space: nowrap; }
.tm-ds .bb3rm-pt__ad { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-ds .bb3rm-pt__taban { font-weight: var(--tm-weight-semibold); }
.tm-ds .bb3rm-pt__taban.is-ust { color: var(--tm-warning-fg); cursor: help; }
.tm-ds .bb3rm-pt__karar { cursor: help; line-height: 1.3; display: inline-flex; justify-content: center; }
.tm-ds .bb3rm-pt__karar svg { width: 18px; height: 18px; }
.tm-ds .bb3rm-pt__karar.is-ok { color: var(--tm-success-fg); font-weight: var(--tm-weight-semibold); }
.tm-ds .bb3rm-pt__karar.is-durdu { color: var(--tm-warning-fg); font-weight: var(--tm-weight-semibold); }
.tm-ds .bb3rm-pt__karar.is-bekle { color: var(--tm-text-secondary); }
.tm-ds .bb3rm-pt__karar.is-hata { color: var(--tm-danger-fg); font-weight: var(--tm-weight-semibold); }
.tm-ds .bb3rm-pt__not { margin: 0; padding: 8px 12px; border-top: 1px solid var(--tm-border); }
@media (max-width: 640px) {
  .tm-ds .bb3rm-pt__r { grid-template-columns: minmax(0, 1fr) 76px 84px 32px; gap: 6px; padding: 7px 10px; }
}

/* Liste: "X kuralına ürün ekliyorsun" şeridi */
.tm-ds .bbk-hedef {
  display: flex; align-items: center; gap: 10px; margin: 0 16px; padding: 10px 12px 10px 14px;
  border-radius: 12px; background: var(--tm-accent-bg); color: var(--tm-accent-fg);
  font-weight: var(--tm-weight-semibold); font-size: var(--tm-text-sm);
}
.tm-ds .bbk-hedef span { flex: 1; min-width: 0; }
.tm-ds .bbk-hedef svg { width: 16px; height: 16px; flex: none; }
@media (max-width: 640px) { .tm-ds .bbk-hedef { margin: 0 8px; } }

/* Modal: yeni / mevcut kural seçimi */
.tm-ds .bbm__hedef-sec { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; }
.tm-ds .bbm__hedef-opt { display: inline-flex; align-items: center; gap: 6px; font-weight: var(--tm-weight-semibold); cursor: pointer; }
.tm-ds .bbm__mevcut {
  flex: 1 1 260px; min-width: 0; height: 36px; padding: 0 10px; border-radius: var(--tm-radius-control);
  border: 1px solid var(--tm-border-strong); background: var(--tm-surface); color: var(--tm-text-primary);
}
.tm-ds .bbm__mevcut:disabled { opacity: .55; }
.tm-ds .bbm__hedef-not { margin: 6px 0 0; font-size: var(--tm-text-xs); color: var(--tm-text-secondary); }
.tm-ds .bbm fieldset.is-kilitli { opacity: .7; }
.tm-ds .bbm fieldset.is-kilitli .bbm__strat { cursor: not-allowed; }

/* ═══ 2026-10-14 — TARAMA TURU: etki satırı · tazelik · aynı-fiyat · sticky ═══
   Kullanıcı kararı KORUNUR: operasyon TABLOSU, pazarlama vitrini DEĞİL.
   Bu blokta hero yok, kart yok, kova yok, sihirbaz yok — satır yüksekliği
   bütçesi (masaüstü ≤140 px) hiçbir kuralla büyütülmez: yeni göstergelerin
   HEPSİ zaten var olan satırlara/hücrelere girer. */

/* ── ① TOPLAM ETKİ: tek satır metin (KART DEĞİL) ─────────────────────────
   Blok akışı, flex DEĞİL: metin düğümleri flex'te anonim öğe olup `gap`
   yüzünden kelime aralarını açardı. İçeriği `bb3-ozet.js` yazar; boşsa
   `.tm-hidden` (0,3,0) bu kuralı yener ve satır hiç yer kaplamaz. */
.tm-ds .bbk-etki {
  display: block; margin: 0; padding: 8px 16px 0;
  font-size: var(--tm-type-caption); line-height: 18px;
  color: var(--tm-text-secondary, #475569); cursor: help;
}
.tm-ds .bbk-etki__tutar {
  color: var(--tm-success-fg); font-weight: var(--tm-weight-bold);
  font-variant-numeric: tabular-nums;
}

/* ── ② TAZELİK ROZETİ: ürün hücresinin ZATEN VAR OLAN ikinci satırında ──
   `line-height` kimlik satırının 14 px'ine EŞİT ve dikey dolgu YOK → rozet
   satır yüksekliğine 0 px ekler (ölçüldü). Nötr gri: bir uyarı değil, bir
   künye bilgisi. */
.tm-ds .bbk-kimlik .bbk-tazelik {
  white-space: nowrap; cursor: help; flex: 0 0 auto;
  line-height: 14px; padding: 0 5px; border-radius: 4px;
  /* Yedek zincir: `--tm-surface-sunken` canlıda TANIMSIZ (bkz. yapışkan başlık
     notu) → rozet zeminsiz, düz metin gibi görünüyordu. */
  background: var(--tm-surface-sunken, var(--color-surface-alt, #e3e9f2));
  color: var(--tm-text-muted);
}

/* ── ③ "Rakip aynı fiyatta" işareti: Buy Box tutarının SOLUNDA, inline ──
   Hücre `text-align: right` olduğu için ikon tutarla aynı satırda akar;
   yeni bir satır/sütun açmaz. */
.tm-ds .bbk-deger { display: inline-flex; align-items: center; gap: 5px; min-width: 0; }
.tm-ds .bbk-ayni-fiyat {
  display: inline-flex; align-items: center; flex: 0 0 auto;
  color: var(--tm-text-muted); cursor: help;
}
.tm-ds .bbk-ayni-fiyat svg { width: 13px; height: 13px; }
.tm-ds .bbk-ayni-fiyat:focus-visible { outline: 2px solid var(--tm-accent); outline-offset: 2px; border-radius: 3px; }

/* ── ④ Kurallarım arama kutusu: "Fırsatlar"takiyle aynı görünüm ───────── */
.tm-ds .bb3rm-search { flex: 0 1 320px; max-width: 320px; margin: 0 0 12px; }
@media (max-width: 640px) { .tm-ds .bb3rm-search { flex: 1 1 auto; max-width: none; } }

/* ── ⑤ YAPIŞKAN BAŞLIK (masaüstü) ────────────────────────────────────────
   🔴 Neden iki ezme gerekiyor: `position: sticky` EN YAKIN SCROLLPORT'a göre
   yapışır. `.bbk-list` (`overflow: hidden`) ve `.bbk-scroll` (`overflow-x:
   auto` → `overflow-y` de `auto` olur) İKİSİ de scroll container'dır ve
   ikisi de dikeyde HİÇ kaymaz → başlık yerinde donar, hiç yapışmaz.
     · `overflow: clip` scroll container YARATMAZ (kırpma aynı kalır) →
       `.bbk-list` yoldan çekilir.
     · Yatay kaydırma yalnız tablo sığmayınca (`min-width: 1060px`) gerekir;
       1100 px ve üstünde gereksiz → o genişlikte `overflow: visible`.
   Dar ekranda (<1100 px) yatay kaydırma KORUNUR, başlık yapışmaz — doğru
   takas: sütun hizası yapışkanlıktan önce gelir.
   ⛔ `--tm-header-h` sayfa başlığının yüksekliği; sabit sayı yazılmaz. */
.tm-ds .bbk-list { overflow: clip; }
@media (min-width: 1100px) {
  .tm-ds .bbk-scroll { overflow-x: visible; }
  .tm-ds .bbk-head {
    position: sticky; top: calc(var(--tm-header-h, 56px) - 1px); z-index: 3;
    /* 🔴 ZEMİN BURADA YENİDEN VERİLİYOR — ÖLÇÜLDÜ, varsayım değil: başlığın
       temel kuralı `background: var(--tm-surface-sunken)` diyor ama bu token
       `static/css/v2/tokens.css`te tanımlı ve O DOSYA `base.html`de
       YÜKLENMİYOR (repo içi not: `templates/includes/dashboard/
       tabbed_head_dashboard_css.html:75` — "canlıda TANIMSIZ"). Tanımsız
       `var()` → `background-color` başlangıç değerine, yani ŞEFFAFA düşer
       (harness'ta `rgba(0,0,0,0)` ölçüldü). Bugüne kadar görünmüyordu çünkü
       başlık kayıp gidiyordu; YAPIŞINCA satırlar arkasından geçer ve metin
       üst üste biner. `--color-surface-alt` HEM açık HEM koyu temada tanımlı
       (`theme-variables.css:93` / `:570`) → tema-duyarlı gerçek yedek.
       ⛔ Temel kural DEĞİŞTİRİLMEDİ: <1100 px'te başlık bugünkü görünümünde
          kalır; yalnız yapışan hâl opak olur. */
    background: var(--tm-surface-sunken, var(--color-surface-alt, #e3e9f2));
    box-shadow: 0 1px 0 var(--tm-border);
  }
}

/* ── ⑥ Tarama cilası ─────────────────────────────────────────────────────
   Satır hover'ı zaten vardı; eksik olan İMLEÇ ve seçili satırın sol kenar
   işareti. Yükseklik değişmez (kenar `inset` gölge, kutu modeli dışı). */
.tm-ds .bbk-row.is-selected { box-shadow: inset 3px 0 0 var(--tm-accent); }
/* Filtre çiplerindeki ★: nötrdü ama `--tm-text-muted` çip zemininde 2.8:1
   kalıyordu (WCAG AA 4.5 altı). Aktif çipte zemin koyu → ters yönde kırılıyordu.
   İkisi de metin rengini MİRAS alır: kontrast çipin kendi oranına eşitlenir. */
.tm-ds .bbk-chip .bbk-stars { color: currentColor; opacity: .75; }
.tm-ds .bbk-chip.is-active .bbk-stars { opacity: .9; }

/* ── ⑦ MOBİL ARAÇ ÇUBUĞU TAŞMASI (2026-10-14, ölçüldü) ───────────────────
   390 px'te `.bbk-bar` içerik kutusu 358 px, `.bbk-bar__right` 380 px →
   32 px taşma (TABANDA DA VARDI; bu tur düzeltiliyor). Kök: `flex: 1 1 100%`
   öğenin `min-width`i `auto` kalmış; esneklik hesabı min-content tabanına
   çarpıp küçülememiş. `min-width: 0` zinciri kutuyu gerçekten esnetir.
   Çip şeridinin KENDİ yatay kaydırması (450 → 338) KORUNUR — o tasarımdır. */
@media (max-width: 720px) {
  .tm-ds .bbk-bar { overflow: hidden; }
  .tm-ds .bbk-bar__right, .tm-ds .bbk-bar__right > * { min-width: 0; }
  .tm-ds .bbk-sort { flex: 0 1 auto; min-width: 0; }
  .tm-ds .bbk-sort select { flex: 0 1 128px; min-width: 0; }
}


/* ===== css/ds/ds-commission.css ===== */
/* =================================================================
   TRENDYOL KOMİSYON TARİFESİ — v2                            2026-10-09
   Kullanıcı: *"mevcut sayfanın arayüzü kullanılabilir değil."*
   Eski sayfa 3.358 satır + 12 gömülü <script> + 50 inline style idi.

   Ön ek `kom-`. Yalnız `tm-ds` kapsamında (base.html `tmv2_ds_scope`).
   Renkler DS token'larından; sabit renk YALNIZ kâr/zarar tonlarında
   (dark-mode'da da okunur). Hareket CSS-only; `prefers-reduced-motion`
   kapatır.
   ================================================================= */

/* 🔴 AÇIK TEMADA KENARLIK ÖLÜYDÜ — `--tm-border-subtle` YALNIZ `html.dark`
   altında tanımlı (`theme-variables.css:601`); açık temada çözülmüyor ve
   çözülemeyen `var()` bildirimi *computed-value time*'da geçersiz kılıp
   özelliği başlangıç değerine düşürüyor.

   [ÖLÇÜLDÜ 2026-10-10, canlı sayfa, açık tema]
     getComputedStyle(html)['--tm-border-subtle'] → ""   (boş)
     .kom-panel      border-style        → none   (panel çerçevesiz)
     .kom-head       border-bottom-style → none   (başlık alt çizgisi yok)
   Yani kural eşleşiyor, hesaplanan değer yok; konsol sessiz.

   Çözüm: kullanım yerlerinde YEDEK DEĞER. Token'ı `.tm-ds` kapsamında
   tanımlamak CAZİP ama YANLIŞ: özel özellik en YAKIN tanımlayan atadan
   miras alınır; `.tm-ds` `<main>`de, `html.dark` `<html>`de → koyu temada
   `.tm-ds` daha yakın olduğu için AÇIK renk kazanır ve koyu tema bozulur.
   Yedek yalnız token çözülmediğinde devreye girer; koyu tema aynen kalır.
   Kilit: tests/commission/test_kampanya_penceresi_ve_temizlik_2026_10_09.py
   (`test_ACIK_TEMADA_COZULMEYEN_TOKEN_YEDEKSIZ_KULLANILMAZ`). */
/* ── Başlık sağ bloğu ─────────────────────────────────────────── */
.tm-ds .kom-headright {
  display: flex;
  align-items: center;
  gap: var(--tm-space-3);
  flex-wrap: wrap;
}

/* ── ÖNERİ ŞERİDİ (`.kom-karar` + `.kom-stats`) KALDIRILDI ────────────
   🔴 2026-10-11, kullanıcı: *"yukaridaki oneriye tikladim boyle kaldi, geri
   alamiyorum, neyse bu alan tamamen kaldirilmali."* Kartın düğmesi süzgeci
   `karli`ye kilitliyordu; süzgeç kutusu kartın ALTINDA, tablonun araç
   çubuğundaydı ve kart geri dönüş yolunu söylemiyordu.

   Kurallar da silindi (sadece şablon değil): çizilmeyen elemanın kuralı
   bir sonraki yerleşimde komşusunu sessizce ezer — bu dosyada
   `.kom-bant__karoran` ile tam olarak bu yaşandı. Şeridin tek gerçek
   sinyali ("Ek kâr") `.kom-tag--kayip` rozetine, `.kom-balon`daki
   "Mevcut aralığa göre" satırına ve `.kom-indir--zararli` düğmesine
   taşındı.

   ⚠️ Kazanılan dikey alan tablonun: `.kom-table` max-height payı
   300 px → 220 px (aşağıda). */

/* ── Boş durum ────────────────────────────────────────────────── */
.tm-ds .kom-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--tm-space-3);
  padding: clamp(32px, 8vw, 72px) var(--tm-space-4);
  background: var(--tm-surface-raised);
  border: 1px dashed var(--tm-border-subtle, rgba(15, 23, 42, .10));
  border-radius: var(--tm-radius-xl);
}

.tm-ds .kom-empty__icon { width: 40px; height: 40px; color: var(--tm-text-muted); }

.tm-ds .kom-empty__title {
  margin: 0;
  font-size: 20px;
  line-height: 26px;
  font-weight: var(--tm-weight-bold);
  color: var(--tm-text-primary);
}

.tm-ds .kom-empty__text {
  margin: 0;
  max-width: 54ch;
  font-size: 13px;
  line-height: 20px;
  color: var(--tm-text-secondary);
}

/* ── Sayfa gövdesi dikey ritmi ────────────────────────────────── */
/* 🔴 BAŞLIK ALTINDA ÖLÜ BOŞLUK (2026-10-11, kullanıcı: *"yukarıda gereksiz
   boşluklar var"*). `ds-polish.css` kardeşler arasına `!important` 16 px
   koyuyor (`> * ~ *`) — ama `~` GİZLİ kardeşleri de sayar: şerit/özet/boş
   durum `.tm-hidden` iken bile panel "üçüncü kardeş" sayılıp 16 px alıyor,
   kabın kendi 16 px'iyle başlık ile tablo arasında 32 px kalıyordu
   (ölçüldü: başlık alt 135 → panel 167). Aralık yalnız GÖRÜNEN kardeşler
   arasında; değer genel standartla aynı (16 px). */
#mainContent #komPage.tm-page > * { margin-top: 0 !important; }
#mainContent #komPage.tm-page > :not(.tm-hidden) ~ :not(.tm-hidden) {
  margin-top: var(--tm-section-gap, 16px) !important;
}

/* ── Panel + araç çubuğu ──────────────────────────────────────── */
.tm-ds .kom-panel {
  background: var(--tm-surface-raised);
  border: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  border-radius: var(--tm-radius-xl);
  overflow: hidden;
  /* 🔴 YÜZEN DESTEK BALONU PAYI. `.support-floating-buttons` sağ altta
     `position: fixed` duruyor ve sayfanın SON öğesi sayfalayıcı: tam aşağı
     kaydırıldığında "son sayfa" düğmesi balonun ALTINDA kalıyordu. Emsal
     `ds-catalog.css` (`.cpk-results-col { padding-bottom: 72px }`) — aynı
     çözüm, yeni mekanizma icat edilmedi: panelin altına balon yüksekliği
     kadar pay bırakılır, balon hiçbir kontrolü örtmez. */
  margin-bottom: 84px;
}

.tm-ds .kom-bar {
  display: flex;
  align-items: center;
  gap: var(--tm-space-3);
  padding: var(--tm-space-3) var(--tm-space-4);
  border-bottom: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  flex-wrap: wrap;
}

.tm-ds .kom-bar__spacer { flex: 1 1 auto; }

/* ══════════════════════════════════════════════════════════════════════
   🔴 ARAÇ ÇUBUĞU — TEK YÜKSEKLİK, TEK SATIR (2026-10-11, ölçüldü)
   Arama kutusu 42 px, seçiciler 36 px, ikonlar 24 px'ti; 1440 px'te
   "Seçimleri temizle · 30 ürün" ikinci satıra düşüyordu. İki kök:
   ① Lucide `<i>`yi `<svg>` ile DEĞİŞTİRİR → `.kom-search i` kuralı
      çizilen ikona hiç uymuyordu (24 px varsayılan boyut kalıyordu).
   ② Global `input`/`select` kuralları yazı boyutunu 15 px'e çekiyordu.
   Artık her kontrol 36 px, ikonlar 16 px, seçiciler en çok 200 px.
   ══════════════════════════════════════════════════════════════════════ */
.tm-ds .kom-bar { --kom-kontrol-h: 36px; }

.tm-ds .kom-search {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 200px;
  flex: 1 1 220px;
  max-width: 320px;
  height: var(--kom-kontrol-h);
  padding: 0 10px;
  background: var(--tm-surface-raised, #fff);
  border: 1px solid var(--tm-border-default, rgba(15, 23, 42, .16));
  border-radius: var(--tm-radius-md);
  transition: border-color .15s ease, box-shadow .15s ease;
}

.tm-ds .kom-search:focus-within {
  border-color: var(--tm-accent-solid, #0175e4);
  box-shadow: 0 0 0 3px rgba(1, 117, 228, .14);
}

.tm-ds .kom-search i,
.tm-ds .kom-search svg {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
  color: var(--tm-text-muted);
}

.tm-ds .kom-search input,
.tm-ds .kom-search input[type="search"] {
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
  padding: 0;
  border: 0;
  box-shadow: none;
  background: transparent;
  font: inherit;
  font-size: 13px;
  color: var(--tm-text-primary);
  outline: none;
}

.tm-ds .kom-filter { display: flex; align-items: center; gap: 6px; }

.tm-ds .kom-filter select {
  height: var(--kom-kontrol-h);
  max-width: 200px;
  padding: 0 28px 0 10px;
  font-size: 13px;
  color: var(--tm-text-primary);
  background-color: var(--tm-surface-raised, #fff);
  border: 1px solid var(--tm-border-default, rgba(15, 23, 42, .16));
  border-radius: var(--tm-radius-md);
  text-overflow: ellipsis;
}

.tm-ds .kom-bar__sayac {
  font-size: 12px;
  color: var(--tm-text-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.tm-ds .kom-bar__aksiyon {
  display: flex;
  align-items: center;
  gap: var(--tm-space-2);
  margin-inline-start: auto;
}

.tm-ds .kom-bar .tm-btn svg,
.tm-ds .kom-bar .tm-btn i { width: 16px; height: 16px; flex: 0 0 auto; }
.tm-ds .kom-bar .tm-btn--primary { height: var(--kom-kontrol-h); }

/* Telefonda süzgeçler tam genişlik ve aynı hizada: etiket sabit sütun,
   seçici kalanı doldurur (önce iki seçici farklı genişlikte duruyordu). */
@media (max-width: 860px) {
  .tm-ds .kom-search { max-width: none; flex-basis: 100%; }
  .tm-ds .kom-filter { flex: 1 1 100%; }
  .tm-ds .kom-filter > span { flex: 0 0 48px; }
  .tm-ds .kom-filter select { flex: 1 1 auto; max-width: none; }
  .tm-ds .kom-bar__spacer { display: none; }
}

/* ── Tablo ────────────────────────────────────────────────────── */
/* 9 sütun: ürün · stok · esas fiyat · 4 bant · seçim
   `minmax(0, …)` ŞART: uzun ürün adı grid'i taşırır. */
/* 🔴 TABLO KENDİ KAYDIRMA KABI (QA 2026-10-11 — tek değişiklik, ÜÇ kusur).
   Eskiden yalnız `overflow-x: auto` vardı ve bu üç ayrı şeyi bozuyordu:

   ① YAPIŞKAN BAŞLIK ÖLÜYDÜ. `position: sticky; top: 0` tanımlıydı ama hiç
      tutmuyordu. Sebep: `overflow` değeri `visible` olmayan en yakın ata,
      sticky'nin kaydırma kabı olur. `.kom-table` DİKEYDE kaydırmadığı için
      `top: 0` hiç devreye girmiyordu. [ÖLÇÜLDÜ] 900 px kaydırıldığında
      `basligaUst: -485`, başlık ekranda yok. 25 satırlık sayfada kullanıcı
      sütun başlıklarını baştan sona görmüyordu.
   ② YATAY KAYDIRMA GÖRÜNMEZDİ. `.kom-panel { overflow: hidden }` taşanı
      kırpıyor, çubuk ise tablonun ~1.400 px altında kalıyordu. [ÖLÇÜLDÜ]
      1280 px'te "Manuel fiyat girişi" sütunu TAMAMEN görünmez, 4. aralık
      rakamın ortasından kesik; kullanıcı sütunun varlığını öğrenemiyordu.
   ③ SAYFA 4.000 px'E ÇIKIYORDU (25 satır × 137 px) — araç çubuğu ve
      sayfalayıcı ekrandan çıkıyor, kullanıcı sürekli yukarı-aşağı gidiyordu.

   Çözüm: tablo HER İKİ eksende kendi kabında kayar. Sticky artık buna göre
   çalışır, yatay çubuk tablonun kendi altındadır (görülür), sayfa yüksekliği
   ekrana sabitlenir — araç çubuğu ve sayfalayıcı hep görünür. */
.tm-ds .kom-table {
  display: block;
  width: 100%;
  overflow: auto;
  /* Üstte kabuk+başlık+araç çubuğu, altta sayfalayıcı için pay.
     🔴 300 → 220 px (2026-10-11): öneri şeridi (`.kom-karar`, ~110 px +
     16 px kenar boşluğu) kaldırıldı; pay eski hâlinde kalsaydı tablonun
     altında o kadar boşluk oluşurdu. Bant hücresi aynı turda üç satıra
     çıktığı için kazanılan alan doğrudan satır sayısına gidiyor. */
  max-height: calc(100vh - 220px);
  min-height: 240px;
  overscroll-behavior: contain;

  /* ── KAYDIRMA İŞARETİ — kusur "ulaşılamıyor" değil, "KEŞFEDİLEMİYOR" ──
     🔴 [ÖLÇÜLDÜ 2026-10-11, 1280×900] tablo görünen 954 · içerik 1110 ·
     taşma 156 px. Son sütun ULAŞILABİLİR (sağa kaydırınca geliyor) ama
     orada bir şey olduğunu anlamanın hiçbir yolu yok:
       · kaydırma çubuğu KAPLAMA tipi → `offsetHeight − clientHeight = 0`,
         yani sıfır yer kaplıyor ve durağan hâlde görünmüyor;
       · tablonun ALT kenarı zaten ekran dışında.
     "Çubuk zaten var" varsayımı bu yüzden yanlış yeşil verir; ölçüm
     kilide alındı.

     Çözüm: kenarda, DAHA FAZLA İÇERİK VARKEN beliren gölge. Saf CSS,
     JS yok, bilinen desen (`background-attachment: local` + `scroll`):
       · "kapak" katmanları `local` → İÇERİKLE birlikte kayar;
       · "gölge" katmanları `scroll` → kutuya sabit.
     Başa kadar kaydırıldığında soldaki kapak soldaki gölgenin üstüne
     oturur ve gölge KAYBOLUR; sona kaydırıldığında aynısı sağda olur.
     Taşma hiç yoksa iki kapak iki gölgeyi birden örter → işaret çizilmez.
     Kendi kendini yönetir; `scrollLeft` dinleyicisi gerekmez.

     `mask-image` neden değil: içeriği soldurur ama kaydırma KONUMUNU
     bilemez — bunun için `animation-timeline: scroll()` gerekir, o da
     Firefox/Safari'de yok; desteklenmeyen tarayıcıda iki kenar birden
     solar ve başlangıçta SOLDAKİ içeriği gizler. Bu desen her yerde
     çalışır ve desteklenmese bile yalnız gölge kaybolur.

     ⚠️ Gölge LİNEER, klasik reçetedeki `radial-gradient` DEĞİL. Reçete
     kısa tablolar için yazılmış: `farthest-side at 0 50%` dikeyde de
     soluyor, yani 650 px'lik bu kapta kenar boyunca uzanan bir çizgi
     değil ortada toplanmış bir LEKE üretiyordu (ilk denemede tam böyle
     göründü). Lineer gradyan kenarın tamamında aynı yoğunlukta kalır —
     söylemek istediğimiz şey "burada içerik kesiliyor".

     ⚠️ KAPAĞIN TAM OPAK KISMI GÖLGEDEN GENİŞ OLMALI (18px > 16px).
     Kapak önce `42%` ile yazılmıştı: 34 px'in %42'si = 14,3 px, yani
     16 px'lik gölgenin son 1,7 px'i kapağın SOLAN kısmına denk geliyor
     ve sızıyordu — başa kadar kaydırılmışken SOLDA ince bir gölge
     kalıyor, "solda daha içerik var" yalanını söylüyordu. Gözle fark
     edilmedi; testin piksel kıyası yakaladı. Duraklar bu yüzden yüzde
     değil PİKSEL: gölge genişliği değişirse buranın da değişmesi
     gerektiği okunur olsun.
     Kilit: tests/e2e/kom-kaydirma-isareti-2026-10-11.cjs */
  background:
    linear-gradient(to right, var(--tm-surface-raised, #fff) 18px, transparent 34px) left center,
    linear-gradient(to left,  var(--tm-surface-raised, #fff) 18px, transparent 34px) right center,
    linear-gradient(to right, rgba(15, 23, 42, .20), rgba(15, 23, 42, 0)) left center,
    linear-gradient(to left,  rgba(15, 23, 42, .20), rgba(15, 23, 42, 0)) right center;
  background-repeat: no-repeat;
  background-size: 34px 100%, 34px 100%, 16px 100%, 16px 100%;
  background-attachment: local, local, scroll, scroll;
}

/* 🔴 YAPIŞKAN BAŞLIK işareti ÖRTERDİ. `.kom-head` zemini
   `--tm-surface-raised` ve `z-index: 2` → gölgenin üstünde duruyor ve
   başlık şeridinde işaret görünmez olurdu (ekranın en üstü, yani gözün
   ilk değdiği yer). Başlık KENDİ işaretini taşır: aynı dört katman,
   aynı mekanizma, yalnız kendi yüksekliğinde.
   `background-image` ile yazılır — `background-color` yukarıdaki
   kuraldan gelmeye devam etsin diye (kısayol onu `transparent`a
   düşürürdü ve satırlar başlığın altından okunurdu). */
.tm-ds .kom-head {
  background-image:
    linear-gradient(to right, var(--tm-surface-raised, #fff) 18px, transparent 34px),
    linear-gradient(to left,  var(--tm-surface-raised, #fff) 18px, transparent 34px),
    linear-gradient(to right, rgba(15, 23, 42, .20), rgba(15, 23, 42, 0)),
    linear-gradient(to left,  rgba(15, 23, 42, .20), rgba(15, 23, 42, 0));
  background-position: left center, right center, left center, right center;
  background-repeat: no-repeat;
  background-size: 34px 100%, 34px 100%, 16px 100%, 16px 100%;
  background-attachment: local, local, scroll, scroll;
}

/* 🔴 YÜZEN BALON SÜTUNU — yalnız BEDAVA olduğu genişlikte (2026-10-11).
   Ölçüldü (1440×950): `#tmSupportFloatingButtons` 52×260 px, x=1362 →
   en sağdaki sütunun (manuel fiyat) DÖRT girdisinin üstüne biniyor.
   Emsal `report-v2.css` (A2): payı SAYFAYA değil KAYDIRMA KABINA ver,
   böylece sayfa düzeyinde yatay taşma doğmaz.
   ⚠️ Pay 1441 px ALTINDA UYGULANMAZ — orada tablo zaten milim milim
   sığıyor (1440'ta kullanılabilir 1.082 px, ızgara alt sınırı 1.078:
   4 px slak). 72 px eklemek "4. aralık ve manuel sütun görüş alanının
   dışında" kusurunu geri getirirdi; o kusur bu dosyada iki kez
   düzeltildi. 1280–1440 arasındaki kısmi örtüşme ÖLÇÜLDÜ ve açık
   bırakıldı — çözümü ya balonu kaydırmak (yeni mekanizma) ya da
   tabloyu daraltmak; ikisi de bu PR'ın kapsamı dışında. */
@media (min-width: 1441px) {
  .tm-ds .kom-table { padding-inline-end: 72px; }
}

/* 🔴 FERAH AMA KOMPAKT (ölçüldü 2026-10-09, kullanıcı: *"satırlar çok geniş"*).
   Önce: satır 126 px · bant kutusu 102 px → ekranda 10 satır 1.296 px tutuyordu.
   Kök, bant kutusunun DİKEY yığılmasıydı (oran/fiyat/kâr/kâr% alt alta).
   Artık kutu iki satır: üstte oran + kâr, altta fiyat + kâr%. Hedef ~64 px.
   `--kom-bant-sayisi` şablondan gelir (komisyon 4, avantaj 3) → boş sütun yok. */
/* ══════════════════════════════════════════════════════════════════════
   🔴 IZGARA 9 → 6 SÜTUN (2026-10-11 tasarım turu) — ÖLÇÜLMÜŞ GEREKÇE

   ESKİ BÜTÇE (ölçüldü, gerçek tarayıcı, veri yüklü):
     ürün 220 + stok 40 + maliyet 82 + satış 112 + 4×bant 120 + manuel 96
     + 8 ara = 1.110 px içerik. 1280 px'te `.kom-table` görünür alanı
     954 px → **156 px TAŞMA**; taşan: 4. bant 52 px + manuel 156 px
     (manuel sütunu ekranda HİÇ YOKTU). 1366 → 70 px taşma. 1440 → 0.

   Önceki tur bu 156 px'i sütun kısarak kapatmaya çalıştı, kapatamadı; bedel
   olarak bant hücresinden fiyat aralığını ve komisyon oranını EKRANDAN ATTI.
   Kullanıcı: *"fiyat aralıkları gözükmüyor"*, *"her şey iç içe girmiş"*.

   YENİ BÜTÇE — Stok · Maliyet · Satış fiyatı ürün künyesine taşındı
   (`kom-urun__kunye`; referansın `promo-prodcell__meta` deseni). Bilgi
   SİLİNMEDİ, yeri değişti; sıralama "Sırala" menüsünde.
     ürün 230 + N×bant 132 + manuel 104 + (N+1)×8 ara
     N=4 → 230 + 528 + 104 + 40 = **902 px**
     N=3 → 230 + 396 + 104 + 32 = **762 px**
   1280 px'te satıra kalan: 954 − 2×16 (tablo iç payı) = **922 px** → 20 px pay.
   ⚠️ `min-width` sütun ALT SINIRLARININ GERÇEK TOPLAMI olmalı; küçük
   yazılırsa bağlayıcı kısıt `minmax()` alt sınırları olur ve tablo YİNE
   taşar (bu hata 2026-10-10'da bir kez yapıldı).
   ══════════════════════════════════════════════════════════════════════ */
.tm-ds .kom-head,
.tm-ds .kom-row {
  display: grid;
  grid-template-columns:
    /* ürün + künye: görsel 44 + ara 8 + metin 178 → ad iki satır sarıyor
       (≈356 px metin kapasitesi; ölçülen ad ortalaması 358 px) ve künyenin
       dört satırı (Barkod/Stok/Maliyet/Satış fiyatı) altında duruyor. */
    minmax(230px, 1.8fr)
    /* Bant hücresi: beş bloklu "teklif kartı". Bağlayıcı olan en geniş
       metin, hapın ikinci satırı: "Zarar (−%192,97)" 11px/600 ≈ 104 px
       + 2×6 px hap payı = 116 ≤ 132 − 2×8 px hücre payı = 116. Sınırda
       değil: hap kendi içinde sarmaya da izin veriyor. */
    repeat(var(--kom-bant-sayisi, 4), minmax(132px, 1fr))
    /* Manuel: girdi + "Hesapla" + sonuç hapı alt alta. 96 → 104 px,
       çünkü "Hesapla" düğmesi 11px'te ≈ 62 px + 2×10 px pay. */
    minmax(104px, .8fr);
  gap: var(--tm-space-2);
  /* 🔴 `center` DEĞİL `stretch`: hücreler artık farklı yükseklikte
     (ürün künyesi 6 satır, bant kartı 5 blok). Ortalamak kartları
     yüzdürür ve "her şey iç içe" hissini üretir; üstten hizalamak
     sütunları birbirine PARALEL okutur. */
  align-items: stretch;
  /* 🔴 NEFES PAYI GERİ GELDİ (brief ilke 6: *"Yoğunluk sıkıştırmayla değil
     HİYERARŞİYLE çözülür"*). Önceki tur satırı 76 px'e indirmek için dikey
     payı 6 px'e kısmıştı; sonuç, kullanıcının *"her şey iç içe girmiş"*
     dediği ekran oldu. 10 px: satır ~150 px, ekranda ~4-5 ürün.
     ⚠️ Ekrana sığan satır sayısı artık SABİT DEĞİL — araç çubuğundaki
     "Sayfada 10/25/50/100" seçicisi kullanıcının elinde. */
  padding: 10px var(--tm-space-4);
  /* 🔴 min-width = sütun ALT SINIRLARININ GERÇEK TOPLAMI (bk. yukarıdaki
     bütçe bloğu). 334 = ürün 230 + manuel 104; ara boşluklar bant başına
     8 px + 1 fazla = (N+1)×8, bu yüzden formülde 8 sabiti ayrıca var.
       N=4 → 334 + 8 + 4×140 = 902 px   (1280'de kalan 922 px → sığar)
       N=3 → 334 + 8 + 3×140 = 762 px
     140 = bant 132 + ara 8. */
  min-width: calc(342px + var(--kom-bant-sayisi, 4) * 140px);
}

.tm-ds .kom-head {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--tm-surface-raised);
  border-bottom: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  /* 🔴 11px + letter-spacing 0: 2026-10-09'da kullanıcı Buy Box tablosunda
     "sütun başlıkları çok büyük" dedi; aynı ölçek burada da kullanılır. */
  font-size: 11px;
  font-weight: var(--tm-weight-semibold);
  color: var(--tm-text-muted);
  letter-spacing: 0;
}

.tm-ds .kom-row {
  border-bottom: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  font-size: 13px;
  color: var(--tm-text-primary);
}

.tm-ds .kom-row:last-child { border-bottom: 0; }
.tm-ds .kom-row:hover { background: var(--tm-surface-hover, rgba(0, 0, 0, .02)); }

.tm-ds .kom-cell { min-width: 0; }

/* 🔴 Sütun ayırıcıları (kullanıcı 2026-10-10: *"sütun çizgileri yok"*).
   Izgara `gap` ile ayrılıyordu ama boşluk tek başına sütunu SÖYLEMİYOR;
   30 sayı yan yanayken göz hangi rakamın hangi aralığa ait olduğunu
   kaybediyor. Çizgi `box-shadow` ile: ızgara `gap`ini değiştirmez,
   hizalamayı bozmaz. Son sütuna çizgi yok. */
.tm-ds .kom-row > .kom-cell:not(:last-child),
.tm-ds .kom-head > .kom-cell:not(:last-child) {
  /* 🔴 YEDEK DEĞER ZORUNLU (ölçüldü 2026-10-10): `--tm-border-subtle` bu
     kapsamda çözülmüyor ve `var()` çözülmeyince bildirim "computed-value
     time"da GEÇERSİZ olup başlangıç değerine (`none`) düşüyor — çizgi hiç
     çizilmedi, hata da vermedi. Kural eşleşiyordu (`matches()` true),
     hesaplanan değer `none`du. */
  box-shadow: inset -1px 0 0 var(--tm-border-subtle, rgba(148, 163, 184, .30));
  padding-inline-end: var(--tm-space-2);
}

/* Sebep satırı tüm genişliği kaplar — ona ayırıcı çizilmez */
.tm-ds .kom-row > .kom-eksik { box-shadow: none; }
/* Rozet kutunun üstüne taşıyor; rozet 9 → 11 px büyüdüğü için pay da 8 px. */
.tm-ds .kom-cell--bant { padding-top: var(--tm-space-2); }

/* 🔴 Sıralanabilir başlık (kullanıcı: *"sıralama butonları olsun"*).
   Buy Box kayıp tablosuyla AYNI desen (`.bbk-th`): başlık görünümü korunur,
   yalnız tıklanabilir olur. Yön SABİT — ikinci tık yönü değiştirmez; ok
   sıralamanın GERÇEK yönünü söyler, uydurma toggle çizilmez. */
.tm-ds .kom-th {
  border: 0;
  background: transparent;
  font: inherit;
  font-size: inherit;
  font-weight: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-align: inherit;
  padding: 0;
  cursor: pointer;
}

.tm-ds .kom-th:hover { color: var(--tm-text-primary); }
.tm-ds .kom-th.is-sorted { color: var(--tm-text-primary); font-weight: var(--tm-weight-bold); }
/* 🔴 YÖN OKU BOZUKTU (2026-10-11, ölçüldü): kural `content: "\2193"` olarak
   yazılmak istenmiş ama dosyaya ham bir kontrol baytı (0x11) + "93" düşmüştü —
   sıralı başlıkta ok yerine anlamsız karakter çiziliyordu. Artık KAÇIŞLI
   ve HER sıralanabilir başlıkta nötr bir ↕ var: kullanıcı hangi sütunun
   sıralanabildiğini tıklamadan görüyor (kullanıcı: *"her sütun için
   sıralama butonu koy"*). */
.tm-ds .kom-th {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border-radius: var(--tm-radius-sm, 6px);
}
.tm-ds .kom-head > .kom-cell--bant.kom-th,
.tm-ds .kom-head > .kom-cell--manuel.kom-th { justify-content: center; }
.tm-ds .kom-th::after {
  content: "\2195";               /* ↕ */
  font-size: 11px;
  line-height: 1;
  opacity: .45;
}
.tm-ds .kom-th:hover::after { opacity: .9; }
.tm-ds .kom-th[aria-sort="descending"].is-sorted::after { content: "\2193"; opacity: 1; }  /* ↓ */
.tm-ds .kom-th[aria-sort="ascending"].is-sorted::after  { content: "\2191"; opacity: 1; }  /* ↑ */
.tm-ds .kom-th:focus-visible { outline: 2px solid var(--tm-accent-solid, #0175e4); outline-offset: 2px; }
.tm-ds .kom-cell--num { text-align: right; font-variant-numeric: tabular-nums; }
.tm-ds .kom-head .kom-cell--bant,
.tm-ds .kom-head .kom-cell--sec { text-align: center; }

/* 🔴 BAŞLIK SATIRI KAYIKTI (2026-10-11, ekran görüntüsü). Satır hücresi
   için yazılan `.kom-cell--bant { padding-top }` (rozet payı) başlık
   hücresine de uyuyordu ve `align-items: stretch` ile birleşince bant
   başlıkları "Ürün"/"Manuel Fiyat Girişi"nden 5 px aşağıda duruyordu.
   Başlıkta rozet yok; tüm başlıklar aynı çizgide, dikeyde ortalı. */
.tm-ds .kom-head {
  align-items: center;
  padding-block: 10px;
}
.tm-ds .kom-head > .kom-cell {
  display: flex;
  align-items: center;
  min-height: 20px;
  padding-top: 0;
  line-height: 16px;
}
.tm-ds .kom-head > .kom-cell--bant { justify-content: center; }

/* Ürün hücresi */
/* 🔴 Grid çocuğunun varsayılanı `min-width:auto` — içerik sığmazsa hücre
   BÜYÜR ve komşu sütunun üstüne taşar (ekran görüntüsü: uzun ürün adı stok
   sütununa giriyordu). `min-width:0` zinciri KESİNTİSİZ olmalı: hücre → kutu
   → metin. Birini atlamak taşmayı geri getirir. */
.tm-ds .kom-cell--urun { min-width: 0; overflow: hidden; }
/* 🔴 `center` → `flex-start`: künye eklenince kimlik bloğu 6 satır oldu;
   ortalamak görseli metnin ortasında yüzdürüyordu. Üstten hizalama
   satırın okuma yönünü (yukarıdan aşağı) takip eder. */
.tm-ds .kom-urun { display: flex; align-items: flex-start; gap: var(--tm-space-2); min-width: 0; }
.tm-ds .kom-urun > span { min-width: 0; }
.tm-ds .kom-urun__metin { display: flex; flex-direction: column; gap: 3px; min-width: 0; }

/* ══════════════════════════════════════════════════════════════════════
   KÜNYE — Barkod · Stok · Maliyet · Satış fiyatı (2026-10-11)

   🔴 Üçü de kendi SÜTUNUNDAYDI ve ızgaranın 246 px'ini yiyordu; 1280 px'te
   tablo 156 px taşıyordu. Referansın kendi deseni bu: `promo-prodcell__meta`
   → etiket + değer, alt alta. ETİKET ZORUNLU — sütun başlığı artık yok,
   sayı kendi adını taşımak zorunda (brief ilke 1).

   İki sütunlu ızgara: etiket sabit 62 px (en uzunu "Satış fiyatı" 11px'te
   ≈ 60 px), değer kalan alanı alır ve `tabular-nums` ile dikeyde hizalanır
   → dört sayı alt alta aynı eksende okunuyor.
   ══════════════════════════════════════════════════════════════════════ */
.tm-ds .kom-urun__kunye {
  display: grid;
  grid-template-columns: 62px minmax(0, 1fr);
  gap: 0 6px;
  margin-top: 2px;
  min-width: 0;
  font-size: 11px;
  line-height: 15px;
}

.tm-ds .kom-kunye__sat { display: contents; }

.tm-ds .kom-kunye__et {
  font-weight: var(--tm-weight-regular, 400);
  color: var(--tm-text-muted, #64748b);
  white-space: nowrap;
}

.tm-ds .kom-kunye__dg {
  min-width: 0;
  color: var(--tm-text-primary);
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 🔴 METİN alanları (kategori/model) SARIYOR, sayılar SARMIYOR.
   "Elektronik > Bilgisayar Çevre Birimleri" 178 px'lik değer sütununa tek
   satırda sığmaz; `ellipsis` ile kesmek kırpılmayı GİZLER (bu dosyanın
   kuralı) ve kategori kârı belirleyen bilgidir. İki satıra kadar sarıyor,
   fazlası `title`da. Sayı alanları (stok/maliyet/fiyat) `nowrap` kalır —
   sarılmış bir tutar okunmaz. */
.tm-ds .kom-kunye__sat--kategori .kom-kunye__dg,
.tm-ds .kom-kunye__sat--model .kom-kunye__dg {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  white-space: normal;
  text-overflow: clip;
  overflow-wrap: anywhere;
}

/* Barkod uzun ve nadiren okunur — sessiz kalsın, sayılar öne çıksın. */
.tm-ds .kom-kunye__sat--bk .kom-kunye__dg { color: var(--tm-text-muted, #64748b); }
/* Maliyet ve satış fiyatı kâr denetiminin girdisi — biraz daha belirgin. */
.tm-ds .kom-kunye__sat--maliyet .kom-kunye__dg,
.tm-ds .kom-kunye__sat--satis .kom-kunye__dg {
  font-weight: var(--tm-weight-semibold, 600);
}
/* 🔴 "girilmemiş" bir EKSİKLİKTİR, sayı değil — kırmızı/yeşil kâr koduyla
   yarışmasın diye uyarı tonunda (kehribar), kalın değil. */
.tm-ds .kom-kunye__sat--eksik .kom-kunye__dg {
  color: var(--tm-warning-700, #b45309);
  font-style: italic;
}

/* Ürün görseli — 44×44 SABİT yer kaplar ki geç yüklenen görsel satırı zıplatmasın */
.tm-ds .kom-urun__gorsel {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  overflow: hidden;
  border: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  border-radius: var(--tm-radius-md);
  background: var(--tm-surface-sunken, rgba(15, 23, 42, .04));
}

.tm-ds .kom-urun__gorsel img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Görsel yok/404 → baş harf. Kırık görsel ikonu GÖSTERMİYORUZ. */
.tm-ds .kom-urun__gorsel.is-bos {
  font-size: 15px;
  font-weight: var(--tm-weight-bold);
  color: var(--tm-text-muted);
}

/* 🔴 İKİ SATIR (2026-10-11). Tek satırda kesiliyordu ve 10/10 ürün adı
   KIRPIKTI (ad kutusu 232 px, içerik ortalama 358 px) — satıcı hangi ürüne
   baktığını okuyamıyordu; "iki satır satırı 56 px yapıyor" gerekçesi artık
   geçerli değil: bant hücresi 97 → 54 px düştüğü için yükseklik bütçesini
   bantlar değil ürün adı belirliyor. 200 px × 2 satır ≈ 400 px kapasite. */
/* 🔴 Satır kimliği ZENGİN (brief ilke 5) ve adın kendisi en üstte,
   en belirgin öğe. İki satır sarıyor; ad ortalaması 358 px, kutu
   ≈178 px × 2 = 356 px → neredeyse tamamı okunuyor, kalanı `title`da.
   ÜÇÜNCÜ satır KALDIRILDI: altına künyenin dört satırı geldi, üç satır ad
   + dört satır künye kimliği "duvar" yapıyordu. */
.tm-ds .kom-urun__ad {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  font-size: 13px;
  font-weight: var(--tm-weight-semibold, 600);
  line-height: 17px;
  color: var(--tm-text-primary);
  overflow: hidden;
  overflow-wrap: anywhere;
}

/* Barkod artık künyenin içinde (etiketli). Bu sınıf yalnız mobil kartta
   ve geriye uyum için duruyor. */
.tm-ds .kom-urun__bk {
  font-size: 11px;
  /* Varsayılan `normal` tarayıcıda ~15 px'e çıkıyordu; sabitlenmezse
     satır yüksekliği bütçesi yazı tipine göre kayar. */
  line-height: 14px;
  color: var(--tm-text-muted);
  font-variant-numeric: tabular-nums;
}

/* ── Telefon manşeti + ayrıntı açıcı ──────────────────────────────────
   Masaüstünde HİÇ çizilmez: orada sütun başlıkları ve dört bant zaten
   yan yana duruyor, hüküm tekrar olurdu. Yalnız 860 px altında görünür
   (bk. mobil bölümü). Kurallar burada, çünkü ikisi de ürün hücresinin
   parçası ve okuyan kişi onları orada arar. */
.tm-ds .kom-mhukum,
.tm-ds .kom-ac { display: none; }

/* ── Bant kutusu — REFERANS TASARIM (2026-10-10, kullanıcı) ──────
   Kullanıcı: *"her sütunda seçim toggle olacak… bu görseldeki gibi olacak."*
   Düzen (üstten alta):
     fiyat (büyük)  ·  "ve altı"  ·  "Komisyon X"  ·  kâr/zarar rozeti  ·  [toggle] Seç
   Önce toggle ayrı bir "Seçim" sütunundaydı ve hangi bandın seçildiği oradan
   okunuyordu; karar bandın yanında verilmeli. */
/* 🔴 İÇ İÇE KUTU GÜRÜLTÜSÜ (tasarım denetimi 2026-10-11): her bant
   çerçeveli bir kutuydu; satır da çerçeveli, kart da çerçeveli → satır
   başına 4 kutu, ekranda ~40 çerçeve. Ölçüldü: dosyada 17 ayrı
   `border: 1px` tanımı var. Çerçeve, ayırmanın EN GÜRÜLTÜLÜ yoludur;
   boşluk ve zemin aynı işi sessizce yapar.
   Kenarlık ŞEFFAF bırakıldı (kaldırılmadı): yerleşim kaymasın ve
   üzerine gelince / seçiliyken aynı kutu görünür olsun.
   Boşluklar 4 px ızgarasına alındı (eski: 10/7/9 ve gap 5). */
/* ══════════════════════════════════════════════════════════════════════
   BANT HÜCRESİ = "TEKLİF KARTI" — beş blok, sabit anatomi

       605,30 ₺        ① fiyat      13px/600  koyu
       ve altı         ② yön        11px/400  soluk
     Komisyon %19      ③ komisyon   11px/500  nötr
   ┌──────────────┐    ④ SONUÇ      dolgulu hap, iki satır
   │  +80,68 ₺    │                 12,5px/700 tutar
   │  Kâr (%32)   │                 11px/600  kelime + yüzde
   └──────────────┘
      ( ) Seç          ⑤ karar      28×16 anahtar + 11px etiket

   🔴 BU SIRA BAĞLAYICI (kullanıcının onayladığı referans; brief ilke 1):
   *fiyat → yön → komisyon → sonuç → karar*. Okuyucu sütun başlığına
   dönmek zorunda kalmıyor. Önceki tur bunu 2 satıra sıkıştırdı, ① ② ③'ü
   sildi ya da kısalttı → *"her şey iç içe girmiş"*, *"ne olduğu belli değil"*.

   🔴 SONUÇ GİRDİLERDEN GÖRSEL OLARAK AYRI (brief ilke 2): kâr/zarar
   DOLGULU bir hapta, fiyat ve komisyon düz metin. Göz önce dolgu arar;
   dolgu tek yerde olduğu için önce sonucu bulur. (Önceki tur dolguyu
   kaldırmış, kârı 15 px düz metin yapmıştı — o da bir hiyerarşi, ama
   referansın hiyerarşisi değil ve kullanıcı referansı onayladı.)
   ══════════════════════════════════════════════════════════════════════ */
.tm-ds .kom-bant {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* 🔴 NEFES PAYI (brief ilke 6). 2 px'lik ara "iç içe" hissinin
     kaynağıydı: beş blok arasında ayrım kalmıyordu. 4 px + hapın kendi
     dolgusu, blokları birbirinden AYIRIYOR. */
  gap: 5px;
  width: 100%;
  padding: 12px 8px 10px;
  /* 🔴 TASARIM TURU (2026-10-14, kullanıcı: *"daha anlaşılır, renkler daha
     uyumlu"*): hücre artık hafif kenarlı bir KART — bantlar yan yana
     okunurken nerede bitip nerede başladığı belli. Renk dili TEK: yeşil =
     kâr/seçili, kırmızı = zarar, gri = nötr. Mavi "seçili" kalktı; aynı
     hücrede yeşil hap + mavi çerçeve iki ayrı şey söylüyordu. */
  border: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  border-radius: 10px;
  background: var(--tm-surface-raised, #fff);
  text-align: center;
  transition: border-color .16s ease, background-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.tm-ds .kom-bant:hover {
  border-color: var(--tm-border-strong, #94a3b8);
  box-shadow: 0 2px 10px rgba(15, 23, 42, .06);
}

/* ① FİYAT — hücrenin kimliği. Birimli: *"fiyat aralıkları gözükmüyor"*
   şikâyetinin yarısı, birimi atılmış çıplak sayıydı ("605,30").
   🔴 RENK NÖTR. Referansın kırmızımsı fiyat metni kâr/zarar renk koduyla
   YARIŞIYOR (brief: körlemesine kopyalanmayacak kusurlardan biri);
   kırmızı/yeşil YALNIZ sonuç hapına ait. */
.tm-ds .kom-bant__fiyat {
  font-size: 14px;
  line-height: 18px;
  font-weight: var(--tm-weight-bold, 700);
  letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
  color: var(--tm-text-primary);
  white-space: nowrap;
  min-width: 0;
}

/* ② YÖN — "ve altı" / "ve üzeri". Bu satır olmadan ① bir sayı; bu satırla
   bir EŞİK. Referansta `<small>` ile aynı rol. */
.tm-ds .kom-bant__yon {
  font-size: 11px;
  line-height: 14px;
  color: var(--tm-text-muted, #64748b);
  white-space: nowrap;
}
/* 2026-10-14: kârın dayandığı indirimli tutar — fiyatın hemen altında, sessiz. */
.tm-ds .kom-bant__net {
  font-size: 11px;
  line-height: 14px;
  color: var(--tm-warning-700, #b45309);
  white-space: nowrap;
}

/* ③ KOMİSYON — sayfanın ADINI taşıyan veri, "Komisyon" sözcüğüyle.
   Kullanıcı: *"her sutunda niye komisyon oranlari yazmiyor abicim,
   amac komisyon oranlari degil mi"*. Önceki tur "kom. %19" diye
   kısaltmıştı; kısaltma onu dipnota çeviriyordu. */
.tm-ds .kom-bant__kom {
  font-size: 11px;
  line-height: 16px;
  padding: 0 8px;
  border-radius: 999px;
  font-weight: var(--tm-weight-medium, 500);
  font-variant-numeric: tabular-nums;
  color: var(--tm-text-secondary, #475569);
  background: var(--tm-surface-sunken, rgba(15, 23, 42, .05));
  white-space: nowrap;
}

/* ⑤ Karar satırı */
.tm-ds .kom-bant__alt {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  min-width: 0;
  margin-top: 2px;
}

/* ══════════════════════════════════════════════════════════════════════
   ④ SONUÇ HAPI — tutar VE yüzde BİRLİKTE, dolgulu, kırpılmadan

   🔴 İKİ SATIR, TEK HAP (ölçüldü): referansın tek satırlık
   "₺4,43 Kâr (18,58%)" biçimi 12px/600'de ≈ 128 px; en kötü durum
   "−17.388,20 ₺ Zarar (−%192,97)" ≈ 215 px. Hücrede kullanılabilir alan
   132 − 16 = 116 px → tek satır KIRPILIR. Bilgi silinmiyor, hapın İÇİNDE
   iki satıra bölünüyor:
     ① "−17.388,20 ₺"     12,5px/700 ≈ 92 px  ✓
     ② "Zarar (−%192,97)" 11px/600   ≈ 104 px ✓
   Kırpılma kilidi: `scrollWidth <= clientWidth` (tasarım e2e'si).

   ⚠️ `text-overflow: ellipsis` KULLANILMAZ: üç nokta kırpılmayı GİZLER ve
   ölçümü sessizce yeşile çevirir. Kırpılırsa GÖRÜNSÜN ve test yakalasın.
   ══════════════════════════════════════════════════════════════════════ */
.tm-ds .kom-kar {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  width: 100%;
  min-width: 0;
  padding: 6px 8px;
  border-radius: 8px;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}

.tm-ds .kom-kar__tutar {
  font-size: 12.5px;
  line-height: 17px;
  font-weight: var(--tm-weight-bold, 700);
  white-space: nowrap;
}

/* 🔴 KELİME EKRANDA KALIR ("Kâr"/"Zarar"). Önceki tur onu yalnız
   `aria-label`a koymuştu → ekranda anlam SALT RENGE kalıyordu; renk körü
   kullanıcı için +80,68 ile −80,68 ayırt edilemez hâle geliyordu. */
.tm-ds .kom-kar__oran {
  font-size: 11px;
  line-height: 14px;
  font-weight: var(--tm-weight-semibold, 600);
  white-space: nowrap;
  opacity: .92;
}

/* Manuel fiyat sonucu AYNI hap bileşenini kullanıyor — iki ayrı görsel dil
   olmasın. Orası daha dar olduğu için yalnız ölçek küçülüyor. */
.tm-ds .kom-manuel__sonuc.kom-kar { padding: 4px 5px; }
.tm-ds .kom-manuel__sonuc.kom-kar .kom-kar__tutar { font-size: 11.5px; line-height: 15px; }
.tm-ds .kom-manuel__sonuc.kom-kar .kom-kar__oran  { font-size: 10px; line-height: 13px; }

.tm-ds .kom-kar--kar   { background: rgba(22, 163, 74, .10); color: #15803d; }
.tm-ds .kom-kar--zarar { background: rgba(220, 38, 38, .08); color: #b91c1c; }
/* Hesaplanamayan bant: dolgu YOK (sonuç yok, hap da yok) ve sebep yazılı. */
.tm-ds .kom-kar--yok {
  background: transparent;
  color: var(--tm-text-muted);
  font-size: 11px;
  line-height: 15px;
  padding: 5px 2px;
}

/* ── Bant içi seçim anahtarı ──────────────────────────────────── */
/* 🔴 ANAHTAR 34×20 → 28×16 (2026-10-11): hedef fiyatla AYNI satıra girdi.
   Ölçüm: 120 px hücre − 16 px iç boşluk = 104 px kullanılabilir;
   "605,30 ₺" 11 px'te ~48 px + 8 px ara + 28 px anahtar = 84 px. Sığıyor.
   Dokunma hedefi `.kom-bant__sec` sarmalının kendisi (yükseklik 20 px'te
   tutuluyor) — görsel küçülürken tıklanabilir alan küçülmez. */
.tm-ds .kom-bant__sec {
  display: inline-flex;
  align-items: center;
  gap: 8px;               /* etiket anahtara yapışıktı ("Seçili" ile okunmuyordu) */
  flex: 0 0 auto;
  min-height: 24px;
  padding: 2px 0;
  cursor: pointer;
  user-select: none;
}

/* 🔴 Girdi GÖRÜNÜR kalmalı (0×0 + opacity:0 DEĞİL).
   Ölçüldü 2026-10-10: `width:0;height:0;opacity:0` ile Playwright `check()`
   "element is not visible" diyip 30 sn bekleyip düşüyor — gerçek yardımcı
   teknolojiler de aynı sorunu yaşar. Doğru desen: girdiyi izin ÜSTÜNE
   bindir, şeffaf yap; boyutu ve tıklanabilirliği KORU. */
.tm-ds .kom-bant__sec { position: relative; }

.tm-ds .kom-sw {
  position: absolute;
  inset-inline-start: 0;
  top: 0;
  width: 40px;
  height: 24px;
  margin: 0;
  opacity: 0;
  cursor: pointer;
  z-index: 1;
}

/* 🔴 Kapalı toggle GÖRÜNÜR olmalı (kullanıcı 2026-10-10: *"toggle'lar çok
   kötü, belli değil"*). Önce izi `--tm-border-subtle` ile dolduruyordum:
   beyaz zeminde neredeyse kayboluyor, tıklanabilir bir şey olduğu
   anlaşılmıyordu. Artık daha koyu zemin + kenarlık + büyümüş topuz. */
/* 🔴 BÜYÜK + YEŞİL + ANİMASYONLU (2026-10-14, kullanıcı: *"seç toggle biraz
   daha büyüyebilir, tıklandığında animasyonu olabilir, yeşil olabilir"*).
   28×16 → 40×22; topuz 18 px; açılınca yeşile döner, topuz yaylı kayar ve
   hafifçe "pop" yapar, izin etrafında bir an yeşil halka parlar. */
.tm-ds .kom-sw__iz {
  position: relative;
  display: inline-block;
  width: 40px;
  height: 22px;
  border-radius: 999px;
  background: var(--tm-sw-kapali, #cbd5e1);
  border: 1px solid var(--tm-sw-kapali-kenar, #94a3b8);
  transition: background-color .22s ease, border-color .22s ease, box-shadow .3s ease;
  flex: 0 0 auto;
}

.tm-ds .kom-sw__iz::after {
  content: "";
  position: absolute;
  top: 1px;
  inset-inline-start: 1px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
  transition: transform .26s cubic-bezier(.34, 1.56, .64, 1);
}

@keyframes kom-sw-pop {
  0%   { transform: translateX(18px) scale(1); }
  45%  { transform: translateX(18px) scale(1.18); }
  100% { transform: translateX(18px) scale(1); }
}
@keyframes kom-sw-halka {
  0%   { box-shadow: 0 0 0 0 rgba(22, 163, 74, .45); }
  100% { box-shadow: 0 0 0 10px rgba(22, 163, 74, 0); }
}

/* Üzerine gelince tıklanabilir olduğu belli olsun */
.tm-ds .kom-bant__sec:hover .kom-sw__iz {
  background: var(--tm-sw-kapali-hover, #b6c2d2);
  border-color: var(--tm-text-muted);
}

.tm-ds .kom-sw:checked + .kom-sw__iz {
  background: #16a34a;
  border-color: #15803d;
  animation: kom-sw-halka .45s ease-out;
}
.tm-ds .kom-sw:checked + .kom-sw__iz::after {
  transform: translateX(18px);
  animation: kom-sw-pop .32s ease-out;
}
.tm-ds .kom-sw:focus-visible + .kom-sw__iz { outline: 2px solid #16a34a; outline-offset: 2px; }
.tm-ds .kom-sw:disabled + .kom-sw__iz { opacity: .4; cursor: not-allowed; }

/* 🔴 "Seç" METNİ EKRANA GERİ GELDİ (2026-10-11, brief anatomi ⑤).
   Önceki tur onu `clip-path: inset(50%)` ile 1×1 px'e indirmişti; gerekçe
   *"alt satır 146 px ile taşıyordu"* idi — o satırda komisyon oranı da
   vardı. Artık komisyon KENDİ satırında (③), bu satırda yalnız anahtar +
   etiket var: 28 px anahtar + 6 px ara + "Seç" 11px ≈ 24 px = **58 px**,
   hücrede kullanılabilir 116 px. Sığıyor.

   ⚠️ Etiketsiz anahtar, referansın reddedilen hâliydi: kullanıcı ekranda
   fiyatın yanında ne işe yaradığı belirsiz bir kaydırma düğmesi görüyordu
   (*"ne olduğu belli değil"*). Ayrıca 1×1 px kutu `scrollWidth >
   clientWidth` ürettiği için kırpılma ölçümünü 100/100 KIRMIZI tutuyordu. */
.tm-ds .kom-sw__ad {
  font-size: 12px;
  line-height: 16px;
  font-weight: var(--tm-weight-medium, 500);
  color: var(--tm-text-secondary, #475569);
  white-space: nowrap;
  user-select: none;
}

.tm-ds .kom-bant.is-picked .kom-sw__ad {
  color: #15803d;
  font-weight: var(--tm-weight-semibold, 600);
}

/* Durum vurguları */
/* Ürünün ŞU ANKİ bandı: kesik çizgi değil, yalnız biraz belirgin kenar +
   üstteki "şu an" rozeti. Kesik çizgi tabloyu gürültülü gösteriyordu. */
/* 🔴 KOYU KENAR → İNCE KENAR (2026-10-11). Ürünün şu anki bandı bu veride
   HER SATIRDA 1. sütun; koyu çerçeve ekranda 25 kutuluk dikey bir duvar
   üretiyordu ve "bir şey oldu" gibi okunuyordu. Nerede olduğunu zaten
   üstündeki "şu an" etiketi söylüyor; kenar yalnız hücreyi sınırlar. */
.tm-ds .kom-bant.is-current { border-color: var(--tm-border-subtle, rgba(15, 23, 42, .14)); }
.tm-ds .kom-bant.is-best { border-color: rgba(22, 163, 74, .45); }

/* 🔴 Seçili bant: zemin DEĞİL, kenar + sol şerit. Dolu mavi zemin tabloda
   ağır duruyordu ve rakamları beyaza çeviriyordu (kullanıcı: "mavi okuyor
   ama güzel durmuyor"). */
.tm-ds .kom-bant.is-picked {
  border-color: #16a34a;
  border-width: 2px;
  padding: 11px 7px 9px;                    /* 2 px kenar, boy sabit */
  background: rgba(22, 163, 74, .06);
  box-shadow: 0 0 0 3px rgba(22, 163, 74, .10);
}

/* Zarar eden bant: zemini BOYAMIYORUZ. 4 banttan 3'ü zarar ettiğinde tablo
   baştan sona kırmızı oluyordu ve sinyal yok oluyordu; kırmızı rozet tek
   başına zaten tarama sırasında yakalanıyor. */
.tm-ds .kom-bant.is-zarar { background: transparent; }

/* 🔴 ZARAR EDEN BANT ADAY DEĞİLDİR — kazananla AYNI ağırlıkta çizilmez.
   [ÖLÇÜLDÜ 2026-10-11] 40 bant hücresinin 30'u zarar ve otuzu da 15 px
   kalın bir rakamla çiziliyordu; satıcının gözüne ürün başına ~16 eşit
   ağırlıklı sayı geliyordu. "Sayı duvarı" şikâyetinin kaynağı bu.
   Zarar BİLGİDİR (tutarı görünür kalır), ADAY DEĞİLDİR: kahraman ölçeğini
   bırakır, hedef fiyatı daha da soluklaşır. Seçiliyken ve üzerine gelince
   tam okunurluk geri gelir — kullanıcı bilerek zararlı bandı seçebilir. */
/* 🔴 Buradaki `font-size`/`font-weight` kuralları ARTIK ETKİSİZ: ölçek
   hapın çocuklarında (`.kom-kar__tutar` / `__oran`). Ses kısma işi
   `.kom-kar--zarar` kuralına taşındı (dosya sonu) — ikizi burada
   bırakmak "düzelttim sandım" tuzağı üretirdi. Kalan tek şey fiyatın
   soluklaşması: zarar eden bandın HEDEF FİYATI bir aday değil. */
.tm-ds .kom-bant.is-zarar .kom-bant__fiyat { opacity: .78; }
.tm-ds .kom-bant.is-zarar:hover .kom-bant__fiyat,
.tm-ds .kom-bant.is-picked.is-zarar .kom-bant__fiyat { opacity: 1; }

/* Seçili ama ZARAR: çerçeve kırmızı — "seçtin ama para kaybediyorsun"
   hücrenin kendisinden okunur, hapa bakmaya gerek kalmaz. */
.tm-ds .kom-bant.is-picked.is-zarar {
  border-color: #dc2626;
  background: rgba(220, 38, 38, .05);
  box-shadow: 0 0 0 3px rgba(220, 38, 38, .10);
}
.tm-ds .kom-bant.is-picked.is-zarar .kom-sw:checked + .kom-sw__iz { background: #dc2626; border-color: #b91c1c; }
.tm-ds .kom-bant.is-picked.is-zarar .kom-sw__ad { color: #b91c1c; }

.tm-ds .kom-bant[disabled] { opacity: .45; }

/* Rozet akış dışında — satırı büyütmesin */
.tm-ds .kom-tag {
  position: absolute;
  top: -8px;
  inset-inline-start: 8px;
  font-size: 11px;
  line-height: 16px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--tm-surface-raised);
  border: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  color: var(--tm-text-muted);
  white-space: nowrap;
}

.tm-ds .kom-bant.is-best .kom-tag {
  border-color: rgba(22, 163, 74, .5);
  background: #f0fdf4;
  color: #15803d;
  font-weight: var(--tm-weight-semibold, 600);
}

/* 🔴 SEÇİLEN BANT PARA KAYBETTİRİYOR (2026-10-11). Kaldırılan öneri
   şeridindeki "Ek kâr −425,50 ₺" uyarısının satır seviyesindeki karşılığı.
   Şerit toplamı söylüyordu; bu rozet HANGİ ÜRÜNDE olduğunu söylüyor ve
   kullanıcının gözü zaten oraya bakıyor (seçimi orada yaptı).
   Yalnız SEÇİLİ bantta çizilir — her hücreye koymak 40 hücrenin 30'unu
   kırmızılaştırır ve sinyali yok eder. */
/* 🔴 KAYIP ROZETİ AKIŞTA ve SARIYOR (ölçüldü 2026-10-11, 1280/1366/1440).
   `.kom-tag` tabanı `position: absolute` + `white-space: nowrap`; kısa
   etiketler ("şu an en kârlı" ≈ 82 px) 132 px'lik hücreye sığıyor ama
   "mevcuda göre −280,27 ₺" ≈ 135 px SIĞMIYOR → seçili zararlı bantta
   `scrollWidth > clientWidth` oluyordu (ölçüm: 100 hücrenin 1'i, tam da
   kullanıcının SEÇTİĞİ hücre) ve rozet komşu sütunun üstüne taşıyordu.

   Metni kısaltmak ÇÖZÜM DEĞİL: bu rozet, kaldırılan öneri şeridinin
   satır-seviyesindeki karşılığı — *hangi üründe* para kaybedildiğini
   söyleyen tek yer. Bilgi kısaltılmıyor; rozet akışa alınıp SARIYOR.
   İki satır olması önemsiz: yalnız SEÇİLİ ve zarar eden bantta çıkar. */
.tm-ds .kom-tag--kayip {
  /* 🔴 2026-10-14: akıştan KÖŞEYE (kullanıcı: *"altta çıkan 'bu fiyatta zarar'
     yerine köşede zarar etiketi, animasyonlu; çok sıkışmış görünüyor"*).
     Sağ üst köşe, kırmızı, kısa metin ("zarar"); açılışta pop. "en kârlı"
     etiketi sol üstte, ikisi çakışmaz. */
  position: absolute;
  top: -9px;
  inset-inline-start: auto;
  inset-inline-end: 8px;
  width: auto;
  margin-top: 0;
  padding: 0 8px;
  line-height: 16px;
  font-size: 11px;
  font-weight: var(--tm-weight-bold, 700);
  letter-spacing: .02em;
  text-transform: uppercase;
  white-space: nowrap;
  border-color: #dc2626;
  background: #dc2626;
  color: #fff;
  box-shadow: 0 2px 6px rgba(220, 38, 38, .35);
  animation: kom-tag-pop .38s cubic-bezier(.34, 1.56, .64, 1);
  transform-origin: 100% 50%;
}
@keyframes kom-tag-pop {
  0%   { transform: scale(.4); opacity: 0; }
  60%  { transform: scale(1.12); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* ── BANT BİLGİ BALONU ──────────────────────────────────────────────────
   🔴 KULLANICI (2026-10-11): *"araligin uzerine gelince detayli popup bilgi
   verilebilir."* Yerli `title` ipucu ~1 sn gecikmeli, biçimsiz ve
   dokunmatikte yok; kaldırıldı, yerine bu kutu geldi.

   🔴 KONUM: `position: fixed` — tablo kendi içinde iki eksende kayıyor
   (`.kom-table { overflow: auto }`), `absolute` balon kaydırma kabında
   KIRPILIRDI. Yerleşimi JS ölçüyor (`balonYerlestir`) ve balonu satırın
   manuel fiyat hücresinin SOLUNA kenetliyor — "balon manuel fiyat
   girdilerinin üstünü kapatıyor" kusuru bu sayfada ÖLÇÜLDÜ, tekrarı
   kabul edilmez.

   Yuva `.tm-ds .kom-modal-yuva` içinde (bk. `govdeYuvasi`), yani bu
   kapsamlı kurallar eşleşiyor; çıplak `<body>`ye taşınsa stiller düşerdi
   (2026-10-10 dersi, modal). */
.tm-ds .kom-balon {
  position: fixed;
  z-index: 1100;
  /* 240 → 280: "3.163,49 ₺ – 3.538,11 ₺ arası" iki satıra bölünüp
     "₺ arası" yalnız kalıyordu (2026-10-11 ekran görüntüsü). */
  width: 280px;
  max-width: calc(100vw - 16px);
  padding: 10px 12px;
  display: none;
  flex-direction: column;
  gap: 4px;
  background: var(--tm-surface-raised, #fff);
  border: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .14));
  border-radius: var(--tm-radius-lg, 10px);
  box-shadow: 0 10px 28px rgba(15, 23, 42, .16);
  font-size: 12px;
  line-height: 17px;
  color: var(--tm-text-primary);
  pointer-events: none;   /* balon kendi hover'ını yakalamasın */
}

.tm-ds .kom-balon.is-open { display: flex; }

.tm-ds .kom-balon__bas {
  margin-bottom: 2px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  font-size: 12px;
  font-weight: var(--tm-weight-bold, 700);
}

.tm-ds .kom-balon__satir {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.tm-ds .kom-balon__et { color: var(--tm-text-muted, #64748b); flex: 0 0 auto; }

.tm-ds .kom-balon__dg {
  flex: 1 1 auto;
  white-space: nowrap;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: var(--tm-weight-semibold, 600);
}

.tm-ds .kom-balon__dg--kar   { color: var(--tm-success-600, #047857); }
.tm-ds .kom-balon__dg--zarar { color: var(--tm-danger-600, #b91c1c); }

/* ── Manuel fiyat sütunu ──────────────────────────────────────── */
.tm-ds .kom-manuel {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 4px;
}

/* Fiyat alanı: kutu sarmalda, "₺" sabit. Çıplak girdi düz bir etikete
   benziyordu; kullanıcı oraya yazabileceğini anlamadı. */
.tm-ds .kom-manuel__alan {
  display: flex;
  align-items: center;
  gap: 2px;
  padding-inline-end: 8px;
  background: var(--tm-surface-raised);
  border: 1px solid var(--tm-border-strong, #cbd5e1);
  border-radius: var(--tm-radius-md);
}

.tm-ds .kom-manuel__alan:focus-within {
  border-color: var(--tm-accent-solid, #0175e4);
  box-shadow: 0 0 0 3px rgba(1, 117, 228, .14);
}

.tm-ds .kom-manuel__birim { font-size: 11px; color: var(--tm-text-muted); }

/* 🔴 Sayı okları KAPALI: tarayıcı spinner'ı ~16 px yer kaplıyor, fiyatı
   0,01 adımlarla tıklayarak girmek anlamsız ve sütunu taşırıyordu. */
.tm-ds .kom-manuel__girdi::-webkit-outer-spin-button,
.tm-ds .kom-manuel__girdi::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.tm-ds .kom-manuel__girdi {
  -moz-appearance: textfield;
  appearance: textfield;
  width: 100%;
  min-width: 0;
  padding: 8px 4px 8px 8px;
  font: inherit;
  font-size: 12px;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--tm-text-primary);
  /* 🔴 Alan GÖRÜNÜR bir kutu olmalı (ekran görüntüsü 2026-10-10): şeffaf
     zemin + `--tm-border-subtle` ile sütun, tıklanabilir bir girdi değil
     soluk bir etiket gibi duruyordu — kullanıcı oraya fiyat yazabileceğini
     anlamıyor. */
  background: transparent;
  border: 0;
  outline: none;
}

.tm-ds .kom-manuel__girdi:disabled { opacity: .5; cursor: not-allowed; }

/* 🔴 `Hesapla` — referansın kendi akışı (input + düğme → sonuç hapı).
   Nötr/ghost: sayfanın birincil eylemi "Seçimlerimi kaydet ve indir";
   satır içi bir hesap düğmesi onunla yarışmamalı. (Referanstaki koyu
   bordo düğme paletle ilgisizdi — kopyalanmadı.) */
/* 🔴 `tm-btn--ghost` bu kapsamda KENARSIZ çiziliyor ve düğme, girdinin
   altında DÜZ BİR YAZI gibi duruyordu (ekran görüntüsü 2026-10-11) —
   tıklanabilir olduğu okunmuyordu. Aynı kusurun bir tur öncesi hâli
   kullanıcıya *"manuel fiyat girişi çalışmıyor"* dedirtmişti. Kenar +
   zemin veriliyor; yine de birincil eylemle (alt çubuktaki indirme)
   yarışmayacak kadar sessiz. */
.tm-ds .kom-manuel__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 5px 8px;
  border: 1px solid var(--tm-border-strong, #cbd5e1);
  border-radius: var(--tm-radius-md);
  background: var(--tm-surface-raised, #fff);
  color: var(--tm-text-secondary, #475569);
  font-size: 11px;
  line-height: 15px;
  font-weight: var(--tm-weight-semibold, 600);
  cursor: pointer;
}

.tm-ds .kom-manuel__btn:hover:not(:disabled) {
  border-color: var(--tm-accent-solid, #0175e4);
  color: var(--tm-accent-solid, #0175e4);
}

.tm-ds .kom-manuel__btn:disabled { opacity: .45; cursor: not-allowed; }

.tm-ds .kom-manuel__sonuc {
  font-size: 11px;
  line-height: 15px;
  text-align: center;
  color: var(--tm-text-muted);
  /* ⚠️ `ellipsis` YOK: üç nokta kırpılmayı GİZLER ve `scrollWidth`
     kilidini sessizce yeşile çevirir. Hap iki satıra sarıyor. */
  overflow: hidden;
}

.tm-ds .kom-manuel__hata { color: var(--tm-warning-700, #b45309); }

/* 🔴 MANUEL SONUÇ = BANT SONUCU (2026-10-11, kullanıcı: *"manuel fiyat
   girişi tutarsız"*). Sonuç `kom-kar` hapını alıyordu ama yukarıdaki
   `.kom-manuel__sonuc { color: muted; font-size: 11px }` aynı özgüllükle
   SONRA geldiği için hapın rengini ve boyunu eziyordu: bant hücrelerinde
   yeşil "+68,07 ₺", manuel hücrede gri-yeşil küçük bir yazı. Aynı veri
   (bu fiyatta kâr) artık aynı nesne. */
.tm-ds .kom-manuel__sonuc.kom-kar--kar { color: var(--tm-success-600, #047857); }
.tm-ds .kom-manuel__sonuc.kom-kar--zarar { color: var(--tm-danger-600, #b91c1c); }

/* ══════════════════════════════════════════════════════════════════════
   MANUEL FİYAT — ORTALI ve BELİRGİN (2026-10-11, kullanıcı: *"manuel fiyat
   girişi kutusunu ve butonunu ortala ve daha belirgin yap"*).
   Önce: girdi + düğme hücrenin TEPESİNE yapışık, gri ince kenarlı kutu ve
   beyaz/gri "Hesapla" — 150 px'lik satırda alt yarı boştu ve sütun bir
   giriş alanından çok soluk bir etiket gibi okunuyordu.
   Şimdi: yığın satırın dikey ORTASINDA, yatayda ortalı; girdi 36 px ve
   koyu kenarlı, değer ortalı ve kalın; "Hesapla" vurgu renginde dolgulu.
   Yine de birincil eylem (alt çubuktaki indir) DOLU mavi; bu açık mavi —
   yarışmaz.
   ══════════════════════════════════════════════════════════════════════ */
@media (min-width: 861px) {
  .tm-ds .kom-row > .kom-cell--manuel {
    justify-content: center;
    align-items: stretch;
    gap: 6px;
    padding-inline: 2px;
  }
}
.tm-ds .kom-manuel__alan {
  height: 36px;
  padding-inline-end: 10px;
  border: 1px solid var(--tm-text-muted, #94a3b8);
  background: var(--tm-surface-raised, #fff);
  box-shadow: inset 0 1px 2px rgba(15, 23, 42, .06);
}
.tm-ds .kom-manuel__alan:hover { border-color: var(--tm-accent-solid, #0175e4); }
.tm-ds .kom-manuel__girdi {
  height: 100%;
  padding: 0 4px 0 10px;
  font-size: 13px;
  font-weight: var(--tm-weight-semibold, 600);
  text-align: center;
}
.tm-ds .kom-manuel__girdi::placeholder { font-weight: 400; color: var(--tm-text-muted); }
.tm-ds .kom-manuel__birim { font-size: 12px; font-weight: 600; }
.tm-ds .kom-manuel__btn {
  height: 32px;
  padding: 0 10px;
  font-size: 12px;
  border: 1px solid var(--tm-accent-solid, #0175e4);
  background: rgba(1, 117, 228, .10);
  color: var(--tm-accent-solid, #0175e4);
}
.tm-ds .kom-manuel__btn:hover:not(:disabled) {
  background: var(--tm-accent-solid, #0175e4);
  color: #fff;
}

/* ══════════════════════════════════════════════════════════════════════
   TABLO DURUMU — yükleniyor / hata. DÖRDÜ DE SONLU (brief madde 2).

   🔴 Eski `.kom-yukleniyor` izi `#komBody`'nin içindeydi ve onu silen tek
   kod yolu `ciz()`ti; `fetch` zaman aşımsız olduğu için uç yanıt vermezse
   iz SONSUZA KADAR kalıyordu (kullanıcı: *"ürünler yükleniyor sonsuza
   kadar kalıyor"*). Artık ayrı bir bölge, tek fonksiyondan (`durumYaz`)
   yönetiliyor ve hata hâlinde "Yeniden dene" çıkıyor.
   ══════════════════════════════════════════════════════════════════════ */
.tm-ds .kom-durum {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--tm-space-2);
  padding: var(--tm-space-6, 32px) var(--tm-space-4);
  text-align: center;
}

.tm-ds .kom-durum__metin {
  margin: 0;
  max-width: 46ch;
  font-size: 13px;
  line-height: 19px;
  color: var(--tm-text-muted);
}

.tm-ds .kom-durum.is-hata .kom-durum__metin { color: var(--tm-danger-600, #b91c1c); }

.tm-ds .kom-durum__spin {
  width: 20px;
  height: 20px;
  border: 2px solid var(--tm-border-subtle, rgba(15, 23, 42, .14));
  border-top-color: var(--tm-accent-solid, #0175e4);
  border-radius: 50%;
  animation: kom-durum-don .8s linear infinite;
}

@keyframes kom-durum-don { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .tm-ds .kom-durum__spin { animation: none; }
}

/* ══════════════════════════════════════════════════════════════════════
   ALT SABİT CTA — sayfanın bitiş eylemi + seçimlerin TOPLAM ETKİSİ

   🔴 Kullanıcı bugün *"indiremiyorum"* dedi: düğme sayfanın tepesinde,
   `ghost` görünümünde ve yalnız seçim varken görünüyordu. Referans ekranda
   bu eylem ALT ÇUBUKTA, dolgulu ve her zaman orada.
   🔴 Çubuk AYNI ZAMANDA kaldırılan öneri şeridinin tek gerçek sinyalini
   taşıyor ("Ek kâr −425,50 ₺"); negatifse kırmızıya dönüyor.
   `sticky` + `bottom: 0`: tablo uzun, çubuk hep görüş alanında.
   ══════════════════════════════════════════════════════════════════════ */
.tm-ds .kom-cta {
  position: sticky;
  bottom: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: var(--tm-space-4);
  margin-top: var(--tm-space-2);
  padding: var(--tm-space-3) var(--tm-space-4);
  border-top: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  border-radius: 0 0 var(--tm-radius-lg, 12px) var(--tm-radius-lg, 12px);
  background: var(--tm-surface-raised, #fff);
  box-shadow: 0 -6px 16px -12px rgba(15, 23, 42, .35);
}

.tm-ds .kom-cta.is-zararli {
  border-top-color: var(--tm-danger-600, #b91c1c);
  background: var(--tm-danger-50, rgba(185, 28, 28, .06));
}

.tm-ds .kom-cta__bilgi {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 auto;
  min-width: 0;
}

.tm-ds .kom-cta__sayi {
  font-size: 13px;
  font-weight: var(--tm-weight-semibold, 600);
  color: var(--tm-text-primary);
}

.tm-ds .kom-cta__etki {
  font-size: 12px;
  line-height: 16px;
  font-variant-numeric: tabular-nums;
  color: var(--tm-text-muted);
}

.tm-ds .kom-cta__etki.is-kar   { color: var(--tm-success-600, #047857); font-weight: var(--tm-weight-semibold, 600); }
.tm-ds .kom-cta__etki.is-zarar { color: var(--tm-danger-600, #b91c1c);  font-weight: var(--tm-weight-semibold, 600); }

.tm-ds .kom-cta__kayit {
  flex: 0 0 auto;
  font-size: 12px;
  color: var(--tm-text-muted);
  white-space: nowrap;
}
.tm-ds .kom-cta__kayit:empty { display: none; }
.tm-ds .kom-cta__kayit.is-hata { color: var(--tm-danger-600, #b91c1c); font-weight: 600; }

.tm-ds .kom-cta__btn { flex: 0 0 auto; }
.tm-ds .kom-cta__btn:disabled { opacity: .55; cursor: not-allowed; }

@media (max-width: 860px) {
  .tm-ds .kom-cta { flex-wrap: wrap; }
  .tm-ds .kom-cta__btn { flex: 1 0 100%; justify-content: center; }
  /* İndir + Excel yükle başlıkta yan yana (2026-10-13): dar ekranda ikisi de AYNI
     tam genişlikte — biri geniş biri küçük kalmasın. */
  .tm-ds .kom-headright { flex-wrap: wrap; }
  .tm-ds .kom-headright > .tm-btn { flex: 1 0 100%; justify-content: center; }
}

/* 🔴 Veri eksikliği SEBEBİYLE gösterilir (CLAUDE.md): maliyeti olmayan ürün
   sessizce boş kalmaz, neden hesaplanamadığı yazılır. */
.tm-ds .kom-row--eksik { background: var(--tm-warning-50, rgba(180, 83, 9, .05)); }

.tm-ds .kom-eksik {
  grid-column: 3 / -1;
  font-size: 12px;
  color: var(--tm-warning-700, #b45309);
}

/* ── Sayfalama ────────────────────────────────────────────────── */
/* 🔴 ATLAMA SAYFALAYICISI (kullanıcı 2026-10-11). Eskiden ortada tek bir
   "1 / 3" ve iki ok vardı; 10.901 üründe 437 sayfa ediyor ve 300. sayfaya
   gitmenin yolu yoktu. Sol: sayfa boyutu. Sağ: ilk/geri/[no]/ileri/son.
   Sayfa numarası YAZILABİLİR — asıl atlama yolu bu. */
.tm-ds .kom-pager {
  display: flex;
  align-items: center;
  gap: var(--tm-space-2);
  padding: var(--tm-space-3) var(--tm-space-4);
  border-top: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  /* 🔴 YÜZEN DESTEK BALONU — ölçüm, tahmin değil (2026-10-11, 1440×950):
     `#tmSupportFloatingButtons` x=1362 · y=674 · 52×260 px. Sayfanın sonuna
     inildiğinde sayfalayıcıyla ÇAKIŞMASI 45×61 px ölçüldü ve çakışan yer
     tam olarak "son sayfa" düğmesi. Sayfalayıcının sağ ucu balonun 52 px'lik
     sütununun soluna çekilir; balon kaydırılmaz (emsal `ds-catalog.css`
     ile aynı yaklaşım: içerik balona yer açar, balon yeni bir mekanizmayla
     yönetilmez). */
  padding-inline-end: 76px;
}

.tm-ds .kom-pager__boy,
.tm-ds .kom-pager__git {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tm-ds .kom-pager__boy select {
  padding: 4px 8px;
  font-size: 13px;
  color: var(--tm-text-primary);
  background: transparent;
  border: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  border-radius: var(--tm-radius-md);
}

.tm-ds .kom-pager__git input {
  width: 64px;
  padding: 4px 8px;
  font: inherit;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  text-align: center;
  color: var(--tm-text-primary);
  background: var(--tm-surface-sunken, transparent);
  border: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  border-radius: var(--tm-radius-md);
}
.tm-ds .kom-pager__git input:focus-visible {
  outline: 2px solid var(--tm-accent-solid, #0175e4);
  outline-offset: 1px;
}
/* Tarayıcı artırma okları dar kutuda yeri yiyor ve yanlışlıkla tıklanıyor. */
.tm-ds .kom-pager__git input::-webkit-outer-spin-button,
.tm-ds .kom-pager__git input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.tm-ds .kom-pager__git input { -moz-appearance: textfield; }

/* ── Modal ────────────────────────────────────────────────────── */

.tm-ds .kom-modal__head,
.tm-ds .kom-modal__foot {
  display: flex;
  align-items: center;
  gap: var(--tm-space-3);
  padding: var(--tm-space-4);
}

.tm-ds .kom-modal__head { border-bottom: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10)); }
.tm-ds .kom-modal__foot { border-top: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10)); justify-content: flex-end; }
.tm-ds .kom-modal__title { margin: 0; flex: 1 1 auto; font-size: 15px; font-weight: var(--tm-weight-bold); }
.tm-ds .kom-modal__body {
  padding: var(--tm-space-4);
  display: flex;
  flex-direction: column;
  gap: var(--tm-space-3);
  /* 🔴 Takvim açılınca BÜYÜYEN taraf GÖVDE olmalı, modalın kendisi değil
     (ölçüldü 2026-10-10): takvim açıkken modal 450 → 796 px'e çıkıyor, üst
     kenarı 233 → 60 px'e tırmanıp başlık çubuğuyla birleşiyordu
     (kullanıcı: *"modal çok büyüyor, header ile birleşiyor"*).
     Artık gövde kendi içinde kayar; modal aynı boyda kalır. */
  overflow-y: auto;
  min-height: 0;
}

/* 🔴 Arka plan bulanıklığı YALNIZ bu modalın kapsamında: global
   `.tm-modal__backdrop` 4px'e kilitli (warnings-modal-global guard). */
.tm-ds #komYukleModal .tm-modal__backdrop {
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

/* ── Yükleme modalı: adımlar + bırakma alanı (2026-10-10) ─────────
   🔴 Kullanıcı: *"Excel yükleme adımları da karmaşık, modal kötü,
   renkler karmaşık, belirginlik yok."* Önce üç adım düz metin listesiydi ve
   bırakma alanıyla AYNI görsel ağırlıktaydı; gözün nereye gideceği belli
   değildi. Artık: adımlar küçük + numaralı (ikincil), bırakma alanı
   belirgin (birincil). Renk sayısı da azaldı — vurgu rengi YALNIZ bırakma
   alanında ve birincil düğmede. */
.tm-ds .kom-adim {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.tm-ds .kom-adim li {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 12px;
  line-height: 18px;
  color: var(--tm-text-secondary, #475569);
}

.tm-ds .kom-adim__no {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--tm-surface-sunken, rgba(15, 23, 42, .06));
  color: var(--tm-text-muted);
  font-size: 11px;
  font-weight: var(--tm-weight-bold);
  font-variant-numeric: tabular-nums;
}

/* Bırakma alanı — modalın ağırlık merkezi */
.tm-ds .kom-drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: var(--tm-space-6, 24px) var(--tm-space-4);
  border: 2px dashed var(--tm-accent-solid, #0175e4);
  border-radius: var(--tm-radius-lg);
  background: rgba(1, 117, 228, .04);
  cursor: pointer;
  text-align: center;
  transition: background-color .12s ease, border-color .12s ease;
}

.tm-ds .kom-drop:hover,
.tm-ds .kom-drop.is-over { background: rgba(1, 117, 228, .10); }

.tm-ds .kom-drop__ikon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--tm-accent-solid, #0175e4);
  color: #fff;
}

.tm-ds .kom-drop__ikon i { width: 20px; height: 20px; }

.tm-ds .kom-drop__text {
  font-size: 13px;
  font-weight: var(--tm-weight-semibold);
  color: var(--tm-text-primary);
}

.tm-ds .kom-drop__ek { font-size: 11px; color: var(--tm-text-muted); }

/* Dosya seçilince alan DURUM değiştirir — seçim görünür olsun */
.tm-ds .kom-drop.is-secili {
  border-style: solid;
  border-color: var(--tm-success-600, #047857);
  background: var(--tm-success-50, rgba(4, 120, 87, .08));
}

.tm-ds .kom-drop.is-secili .kom-drop__ikon { background: var(--tm-success-600, #047857); }

.tm-ds .kom-note { margin: 0; font-size: 12px; color: var(--tm-text-muted); }
.tm-ds .kom-error { margin: 0; font-size: 13px; color: var(--tm-danger-600, #b91c1c); }

/* ── MOBİL — IZGARA DEĞİL KART, KART DA KAPALI GELİR ──────────────────
   İki ayrı kusur, iki ayrı ölçüm:

   ① [ÖLÇÜLDÜ 2026-10-11] Izgara 1.078 px min-width ile yatay kayıyordu:
      390 px'te yalnız "Ürün · Stok · Mali…" görünüyor, DÖRT BANDIN
      TAMAMI — sayfanın tek içeriği — ekranın dışında kalıyordu. Yatay
      çubuk tablonun altında olduğu için kullanıcı kaydırabileceğini bile
      göremiyordu. → 860 px altında satır bir KART olur; sütun başlığı
      satırı gizlenir, her hücre adını `data-kom-etiket` / `data-kom-bant-no`
      ile kendisi yazar.

   ② [ÖLÇÜLDÜ 2026-10-11, ① uygulandıktan SONRA] Kart 444 px, sayfa
      11.591 px. Yüksekliğin ~190 px'i dört bandın İKİŞERLİ ve EŞİT boyda
      çizilmesiydi — oysa bu veride 40 bandın 30'u zarar ediyor ve
      masaüstü kuralı *"zarar eden bant aday değildir"*. Yani telefonda
      sayı duvarı aynen duruyordu, yalnız iki sütuna sarılmıştı.
      → Kart KAPALI gelir: görsel + ad + tek cümlelik hüküm (+ kâr).
        Ayrıntı — dört bant, stok, maliyet, manuel fiyat — açıcıyla gelir.
        Hiçbir şey SİLİNMEZ; satıcının kendi kataloğu ekranda kalır,
        yalnız kararın girdisi olmayan 11 sayı bir dokunuş geriye gider. */
@media (max-width: 860px) {
  .tm-ds .kom-headright { width: 100%; }
  /* (`.kom-karar__ana` / `__btn` kuralları, öneri şeridiyle birlikte
     2026-10-11'de kaldırıldı — taşıyıcı artık çizilmiyor.) */

  /* Kart yerleşiminde yatay kaydırma YOK; iç kap kartları kısa bir
     pencereye hapsediyordu — sayfa kaydırması yeterli. */
  .tm-ds .kom-table {
    overflow: visible;
    max-height: none;
    min-height: 0;
    /* Kart düzeninde yatay kaydırma YOK → kaydırma işaretinin anlamı da
       yok. Kapaklar gölgeleri zaten örterdi ama `overflow: visible` iken
       `local` davranışı `scroll`a düşüyor; açıkça kapatmak daha ucuz. */
    background: none;
  }
  .tm-ds .kom-head { display: none; }

  .tm-ds .kom-row {
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: var(--tm-space-3) var(--tm-space-2);
    padding: var(--tm-space-3) var(--tm-space-4);
    min-width: 0;
  }

  /* Kartta sütun ayırıcı çizgisi anlamsız — hücreler alt alta. */
  .tm-ds .kom-row > .kom-cell:not(:last-child) {
    box-shadow: none;
    padding-inline-end: 0;
  }

  .tm-ds .kom-cell--urun { grid-column: 1 / -1; }
  .tm-ds .kom-cell--bant { grid-column: span 3; padding-top: 0; }
  .tm-ds .kom-cell--manuel { grid-column: 1 / -1; }
  .tm-ds .kom-eksik { grid-column: 1 / -1; }

  /* 🔴 Künye telefonda da DURUYOR (kapalı kartta bile): stok/maliyet/satış
     fiyatı satıcının "bu ürün hangisi" sorusunun cevabı. Masaüstünde iki
     sütunluydu; 390 px'te etiket+değer yan yana ve sarmalı. */
  .tm-ds .kom-urun__kunye {
    grid-template-columns: 62px minmax(0, 1fr);
    font-size: 11.5px;
    line-height: 16px;
  }

  /* ── KAPALI KART ───────────────────────────────────────────────────
     Ayrıntı hücreleri çizilmez. `display:none` DOM'dan düşürmez: satırın
     çocuk sayısı sabit kalır (ızgara sözleşmesi testi buna bakıyor) ve
     açıcıya basınca aynı düğümler görünür — yeniden çizim yok. */
  .tm-ds .kom-row:not(.is-acik) > .kom-cell--bant,
  .tm-ds .kom-row:not(.is-acik) > .kom-cell--manuel { display: none; }
  .tm-ds .kom-row:not(.is-acik) { gap: 0; }

  /* Veri eksik satırda sebep MANŞETTE yazılır (`mobilHukum` onu döndürür),
     bu yüzden kapalı kartta ayrıca tekrar edilmez. Açıcı YERİNDE KALIR:
     stok / maliyet / satış fiyatı o satırda da bilgidir ve satıcının
     "neden hesaplanmadı"yı denetlemesi için gereken sayılar onlar. */
  .tm-ds .kom-row:not(.is-acik) > .kom-eksik { display: none; }

  /* Ürün bloğu: [görsel] [ad + barkod + hüküm] [açıcı] */
  .tm-ds .kom-urun { align-items: flex-start; }
  /* 🔴 Kapalı kart TARAMA yüzeyi: ad iki satır (kart 93 px, ekranda 9 ürün).
     Üçüncü satır kart başına +16 px ve ekrandaki ürünü 9 → 7'ye düşürüyor.
     Ama kullanıcı bir kartı AÇTIYSA artık taramıyor, O ÜRÜNE bakıyor —
     orada kırpılmış ad bilgi kaybıdır. Ölçüldü (390 px, 25 ürün):
     2 satırda 7 ad kırpık, 4 satırda 0. Pay yalnız açılan kartta ödenir. */
  .tm-ds .kom-urun__ad { -webkit-line-clamp: 2; line-clamp: 2; }
  .tm-ds .kom-row.is-acik .kom-urun__ad { -webkit-line-clamp: 4; line-clamp: 4; }

  .tm-ds .kom-mhukum {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 2px 6px;
    margin-top: 3px;
    font-size: 12px;
    line-height: 16px;
  }

  .tm-ds .kom-mhukum__tutar {
    font-size: 14px;
    font-weight: var(--tm-weight-bold, 700);
    font-variant-numeric: tabular-nums;
    /* `.kom-kar--kar` rengi taşıyor ama dolgusunu DEĞİL: manşette rakamın
       arkasında soluk yeşil bir blok, satır başına bir "rozet" daha
       ekliyordu — kartın tek vurgusu rakamın kendisi olmalı. */
    background: transparent;
  }

  .tm-ds .kom-mhukum__etiket { color: var(--tm-text-muted); }

  /* Aksiyon VAR: haftanın tek "git şunu yap"ı — kart manşeti de öyle okur. */
  .tm-ds .kom-mhukum.is-aksiyon .kom-mhukum__etiket {
    color: var(--tm-success-600, #047857);
    font-weight: var(--tm-weight-semibold);
  }

  /* Açıcı — 40×40 dokunma hedefi, görsel iz tek bir şevron. */
  .tm-ds .kom-ac {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    margin-inline-start: auto;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--tm-text-muted);
    cursor: pointer;
  }

  .tm-ds .kom-ac::after {
    content: "";
    width: 9px;
    height: 9px;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: translateY(-3px) rotate(45deg);
    transition: transform .15s ease;
  }

  .tm-ds .kom-row.is-acik .kom-ac::after { transform: translateY(2px) rotate(225deg); }
  .tm-ds .kom-ac:focus-visible { outline: 2px solid var(--tm-accent-solid, #0175e4); outline-offset: -2px; border-radius: var(--tm-radius-md); }

  /* ── AÇIK KART ─────────────────────────────────────────────────────
     Hüküm zaten manşette; açıkken tekrar etmesin. */
  .tm-ds .kom-row.is-acik .kom-mhukum { display: none; }

  /* Stok · Maliyet · Satış: etiket ÜSTTE iki satır ediyordu (3 × 2 = 6
     satır). Etiket aynı satırda, değer kalın — üç sayı tek şeritte. */
  .tm-ds .kom-row > .kom-cell[data-kom-etiket]::before {
    content: attr(data-kom-etiket);
    display: block;
    font-size: 11px;
    line-height: 15px;
    font-weight: var(--tm-weight-regular, 400);
    color: var(--tm-text-muted);
  }

  .tm-ds .kom-bant {
    align-items: flex-start;
    text-align: start;
    border-color: var(--tm-border-subtle, rgba(15, 23, 42, .10));
  }

  /* 🔴 SÜTUN ADI, numara DEĞİL (2026-10-11). `". aralık"` sabiti avantaj
     sayfasında YANLIŞTI: orada kademeler "Avantajlı / Çok Avantajlı /
     Süper Avantajlı" diye adlanıyor, "1. aralık" diye değil. Ad artık
     sütun başlığından okunup `data-kom-bant-adi`ya yazılıyor (bk.
     `kom-tarife.js` → `BANT_ADLARI`), iki sayfa tek kuralla doğru. */
  .tm-ds .kom-bant::before {
    content: attr(data-kom-bant-adi);
    font-size: 11px;
    line-height: 15px;
    font-weight: var(--tm-weight-semibold, 600);
    color: var(--tm-text-muted);
  }

  .tm-ds .kom-bant__alt { justify-content: space-between; }

  /* Hap telefonda tam genişlik değil — içerik kadar, solda. */
  .tm-ds .kom-kar { width: auto; align-items: flex-start; }

  /* 🔴 ZARAR EDEN BANT TELEFONDA DA ADAY DEĞİL. Masaüstünde bunu yazı
     ağırlığı söylüyordu; dar ekranda aynı işi YERLEŞİM yapar: kazanan
     bant tam genişlik ve iki satır, zarar edenler tam genişlik ve TEK
     satır (no · tutar · fiyat · anahtar). Seçilince ya da kullanıcı
     üstüne gelince tam okunurluk geri gelir — bilerek zararlı bant
     seçmek hâlâ mümkün (CLAUDE.md: kapı değil, hiyerarşi). */
  .tm-ds .kom-cell--bant { grid-column: 1 / -1; }

  .tm-ds .kom-cell--bant:has(.kom-bant.is-zarar:not(.is-picked)) .kom-bant {
    flex-direction: row;
    align-items: center;
    /* 🔴 `wrap` ZORUNLU (ölçüldü 390 px, açık kart): tek satıra zorlanınca
       `.kom-kar` hapının flex tabanı 12-15 px'e çöküyor, içerik 144 px
       kalıyor ve satır tablodan 55 px TAŞIYORDU. Yani "zarar bandını tek
       satıra indirerek yer kazanma" fikri dar ekranda kendi kendini
       bozuyordu. Sarma: sığdığı kadarı tek satır, sığmayan alta iner —
       bilgi hiçbir koşulda kırpılmaz. */
    flex-wrap: wrap;
    gap: 4px 8px;
    padding: 4px 8px;
  }

  .tm-ds .kom-cell--bant:has(.kom-bant.is-zarar:not(.is-picked)) .kom-bant__alt {
    width: auto;
    flex: 0 0 auto;
    margin-inline-start: auto;
  }

  /* 🔴 Tek satıra inen zarar bandında ① ② ③ de AYNI satıra girer — bilgi
     SİLİNMEZ, hizası değişir. `display:none` yazmak kullanıcıdan fiyat
     aralığını ve komisyon oranını geri almak olurdu; tam olarak bunu
     düzeltiyoruz. Hap da tek satıra iner (tutar + oran yan yana). */
  .tm-ds .kom-cell--bant:has(.kom-bant.is-zarar:not(.is-picked)) .kom-kar {
    flex-direction: row;
    align-items: baseline;
    /* 🔴 `0 0 auto`: varsayılan `flex-shrink: 1` hapı 12 px'e eziyordu
       (ölçüldü: clientWidth 12, scrollWidth 144 → metin kırpık). Hap
       İÇERİĞİ KADAR yer alır; sığmazsa SATIR sarar, hap küçülmez. */
    flex: 0 0 auto;
    gap: 5px;
    padding: 2px 6px;
  }
  .tm-ds .kom-cell--bant:has(.kom-bant.is-zarar:not(.is-picked)) .kom-bant__fiyat,
  .tm-ds .kom-cell--bant:has(.kom-bant.is-zarar:not(.is-picked)) .kom-bant__yon,
  .tm-ds .kom-cell--bant:has(.kom-bant.is-zarar:not(.is-picked)) .kom-bant__kom {
    flex: 0 0 auto;
  }

  /* Manuel fiyat: etiket, alan ve düğme yan yana — tam genişlik blok değil. */
  .tm-ds .kom-cell--manuel {
    flex-direction: row;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
  }

  .tm-ds .kom-cell--manuel::before { flex: 0 0 auto; }
  .tm-ds .kom-cell--manuel .kom-manuel__alan { flex: 1 1 120px; min-width: 0; }
  .tm-ds .kom-cell--manuel .kom-manuel__btn { flex: 0 0 auto; }
  .tm-ds .kom-cell--manuel .kom-manuel__sonuc { flex: 1 0 100%; }

  /* Rozet mutlak konumdayken kartın kenarlığına biniyordu — akışa alınır. */
  .tm-ds .kom-tag {
    position: static;
    align-self: flex-start;
    order: -1;
  }

  /* Sayfalayıcı 390 px'te tek satıra sıkışıp okunmaz oluyordu. */
  .tm-ds .kom-pager { flex-wrap: wrap; justify-content: center; }
  .tm-ds .kom-pager__boy { flex: 1 0 100%; justify-content: center; }
}

@media (prefers-reduced-motion: reduce) {
  .tm-ds .kom-bant { transition: none; }
}

/* Yükleme sonucu şeridi — eşleşmeyen ürünlerin sebebi burada söylenir. */
.tm-ds .kom-yukleme-ozeti {
  margin: var(--tm-space-4) 0 0;
  padding: var(--tm-space-3) var(--tm-space-4);
  font-size: 13px;
  color: var(--tm-text-secondary);
  background: var(--tm-surface-raised);
  border: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  border-inline-start: 3px solid var(--tm-accent-solid, #0175e4);
  border-radius: var(--tm-radius-md);
}

/* ── Haftalık hatırlatma şeridi ───────────────────────────────── */
.tm-ds .kom-banner {
  display: flex;
  align-items: center;
  gap: var(--tm-space-3);
  margin: var(--tm-space-4) 0 0;
  padding: var(--tm-space-3) var(--tm-space-4);
  background: rgba(1, 117, 228, .07);
  border: 1px solid var(--tm-accent-solid, #0175e4);
  border-radius: var(--tm-radius-lg);
  font-size: 13px;
  color: var(--tm-text-primary);
}

.tm-ds .kom-banner i { width: 18px; height: 18px; flex: 0 0 auto; color: var(--tm-accent-solid, #0175e4); }
.tm-ds .kom-banner__metin { flex: 1 1 auto; line-height: 19px; }

/* 🔴 BURADA ESKİDEN ÖLÜ BİR BLOK VARDI — kaldırıldı (2026-10-10).
   `.kom-bant__karoran` (grid-area: karoran) iki tasarım önceki yerleşime
   aitti, eleman artık ÇİZİLMİYOR. Ama aynı blok `.is-zarar` ve
   `.is-picked.is-zarar` için de `border-color:#b91c1c; border-style:dashed`
   yazıyordu ve dosyada YENİ kurallardan SONRA geldiği için (aynı özgüllük,
   son gelen kazanır) onları eziyordu. Sonuç: zarar eden HER bant kırmızı
   kesik çizgiyle çerçeveleniyordu — kullanıcı: *"çok sıkışık ve kırmızı
   kesik kesik çizgiler var."* Zararı artık yalnız rozet söylüyor. */

/* ── Modal alanları (tarih + toplu seçim) ─────────────────────── */
.tm-ds .kom-tarih,
.tm-ds .kom-alan {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 13px;
}

.tm-ds .kom-tarih__etiket,
.tm-ds .kom-alan > span {
  font-size: 12px;
  font-weight: var(--tm-weight-medium);
  color: var(--tm-text-secondary);
}

.tm-ds .kom-alan select,
.tm-ds .kom-alan input[type="number"] {
  /* Seçici 36, sayı alanı 38 px çiziliyordu — aynı satırda iki boy. */
  box-sizing: border-box;
  height: 36px;
  padding: 0 10px;
  font: inherit;
  font-size: 13px;
  color: var(--tm-text-primary);
  background-color: var(--tm-surface-raised, #fff);
  border: 1px solid var(--tm-border-default, rgba(15, 23, 42, .16));
  border-radius: var(--tm-radius-md);
}
.tm-ds .kom-alan select:focus,
.tm-ds .kom-alan input[type="number"]:focus {
  outline: none;
  border-color: var(--tm-accent-solid, #0175e4);
  box-shadow: 0 0 0 3px rgba(1, 117, 228, .14);
}

/* ══════════════════════════════════════════════════════════════════════
   MODAL TUTARLILIĞI (2026-10-11, kullanıcı: *"toplu seçim modalı tutarsız"*)
   Ölçülen: kapat düğmesi 48×36 px kenarlıklı KUTU (başlıktan ağır), koşul
   alanı gri dolgulu bir blok, anahtar satırı beyaz kenarlıklı kart, önizleme
   mavi şerit — dört farklı yüzey dili. Artık: tüm bölümler aynı beyaz kart
   (1 px kenar, aynı köşe, aynı iç pay); kapat düğmesi 32 px sessiz ikon.
   ══════════════════════════════════════════════════════════════════════ */
.tm-ds .kom-modal__head .tm-btn--icon {
  width: 32px;
  height: 32px;
  min-width: 32px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--tm-text-muted);
  border-radius: var(--tm-radius-md);
}
.tm-ds .kom-modal__head .tm-btn--icon:hover { background: var(--tm-surface-sunken, rgba(15, 23, 42, .06)); color: var(--tm-text-primary); }
.tm-ds .kom-modal__head .tm-btn--icon svg,
.tm-ds .kom-modal__head .tm-btn--icon i { width: 18px; height: 18px; }
.tm-ds .kom-modal__title { font-size: 16px; line-height: 22px; }
.tm-ds .kom-modal__foot .tm-btn { min-width: 96px; justify-content: center; }

/* ── Toplu seçim: iki mod ─────────────────────────────────────── */
.tm-ds .kom-toplu { gap: var(--tm-space-4); }

.tm-ds .kom-mod {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--tm-space-3);
}

/* Mod kartı — hangi yöntemin seçili olduğu bir bakışta belli olmalı.
   Kullanıcı: "her aralık için en kârlısını seç mi, yoksa değer girip
   büyükse seç mi?" — ikisi tek formda karışıktı. */
.tm-ds .kom-mod__btn {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: var(--tm-space-3);
  text-align: left;
  background: transparent;
  border: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  border-radius: var(--tm-radius-lg);
  font: inherit;
  color: var(--tm-text-primary);
  cursor: pointer;
  transition: border-color .12s ease, background-color .12s ease;
}

.tm-ds .kom-mod__btn i { width: 18px; height: 18px; color: var(--tm-text-muted); }
.tm-ds .kom-mod__btn:hover { border-color: var(--tm-text-muted); }

.tm-ds .kom-mod__btn.is-active {
  border-color: var(--tm-accent-solid, #0175e4);
  border-width: 2px;
  background: rgba(1, 117, 228, .08);
}

.tm-ds .kom-mod__btn.is-active i { color: var(--tm-accent-solid, #0175e4); }
.tm-ds .kom-mod__ad { font-size: 13px; font-weight: var(--tm-weight-semibold); }
.tm-ds .kom-mod__alt { font-size: 11px; line-height: 15px; color: var(--tm-text-muted); }

/* Koşul alanları */
.tm-ds .kom-kosul {
  display: flex;
  flex-direction: column;
  gap: var(--tm-space-3);
  padding: var(--tm-space-3);
  border: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  border-radius: var(--tm-radius-lg);
}

.tm-ds .kom-satir { display: flex; gap: var(--tm-space-3); flex-wrap: wrap; }
.tm-ds .kom-satir .kom-alan { flex: 1 1 150px; min-width: 0; }

/* Kullanıcı ne seçtiğini CÜMLE olarak görür — alan adları tek başına yetmiyor */
.tm-ds .kom-ipucu {
  margin: 0;
  font-size: 12px;
  line-height: 17px;
  color: var(--tm-text-secondary);
}

/* Toggle satırı (checkbox DEĞİL — kullanıcı isteği) */
.tm-ds .kom-anahtar {
  display: flex;
  align-items: center;
  gap: var(--tm-space-3);
  padding: var(--tm-space-3);
  border: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  border-radius: var(--tm-radius-lg);
}

.tm-ds .kom-anahtar__metin { display: flex; flex-direction: column; gap: 2px; }
.tm-ds .kom-anahtar__metin b { font-size: 13px; font-weight: var(--tm-weight-semibold); }
.tm-ds .kom-anahtar__metin small { font-size: 11px; color: var(--tm-text-muted); }

.tm-ds .kom-onizleme {
  margin: 0;
  padding: var(--tm-space-2) var(--tm-space-3);
  font-size: 13px;
  font-weight: var(--tm-weight-medium);
  color: var(--tm-accent-solid, #0175e4);
  background: rgba(1, 117, 228, .07);
  border-radius: var(--tm-radius-md);
}

.tm-ds .kom-onizleme.is-bos { color: var(--tm-text-muted); background: transparent; }

/* ── Tarih seçici MODAL İÇİNDE ────────────────────────────────────
   🔴 ÖLÇÜLDÜ 2026-10-09: takvim modalın alt kenarında KIRPILIYORDU.
   Kök: `.tm-modal__dialog` `overflow: hidden`, `.mpdr-pop` ise
   `position: absolute` → taşan kısım kesiliyor, modalın kendi
   düğmeleri bile görünmüyordu (ekran görüntüsü 03-tarih-araligi).

   Çözüm: modal içinde takvim FLOATING DEĞİL, akışa alınır. Modal gövdesi
   zaten `overflow-y: auto` → içerik uzayınca kaydırılır, hiçbir şey
   kesilmez. `z-index` ile çözmeye çalışmak işe yaramaz: sorun yığın
   sırası değil, KIRPMA. */
.tm-ds .kom-modal .mpdr-wrap { position: relative; display: block; }

.tm-ds .kom-modal .mpdr-display { width: 100%; }

.tm-ds .kom-modal .mpdr-pop {
  position: static;
  width: 100%;
  min-width: 0;
  margin-top: 8px;
  box-shadow: none;
  background: var(--tm-surface-sunken, transparent);
}

/* İki ay yan yana 520px'e sığmıyordu; modal genişletildi. */
.tm-ds .kom-modal .tm-modal__dialog {
  max-width: 640px;
  /* Tavanı ekrana göre: baş + ayak sabit, gövde kayar. `min()` ile küçük
     ekranda da taşmaz. 82vh → 1440×900'de 738 px. */
  max-height: min(738px, 82vh);
  display: flex;
  flex-direction: column;
}

.tm-ds .kom-modal__head,
.tm-ds .kom-modal__foot { flex: 0 0 auto; }
.tm-ds .kom-modal__body { flex: 1 1 auto; }
.tm-ds .kom-modal .mpdr-cal { min-width: 0; }

/* Dar ekranda aylar alt alta */
@media (max-width: 680px) {
  .tm-ds .kom-modal .mpdr-body { flex-direction: column; }
}

/* ── Modal DERİNLİĞİ ──────────────────────────────────────────────
   🔴 Kullanıcı: *"modal ile arka plan çok karışıyor, derinlik ekle."*
   Global backdrop 4px blur + hafif örtü; veri-yoğun bir tablonun
   üstünde bu yetmiyor — satırlar modalın içinden okunuyor gibi
   görünüyor. Bu iki modalın kapsamında örtü koyulaştırılır, blur
   artırılır ve dialog'a belirgin gölge + kenar verilir. */
.tm-ds #komYukleModal .tm-modal__backdrop,
.tm-ds #komTopluModal .tm-modal__backdrop {
  background: rgba(15, 23, 42, .55);
  -webkit-backdrop-filter: blur(10px) saturate(.9);
  backdrop-filter: blur(10px) saturate(.9);
}

.tm-ds #komYukleModal .tm-modal__dialog,
.tm-ds #komTopluModal .tm-modal__dialog {
  box-shadow:
    0 24px 60px rgba(15, 23, 42, .35),
    0 8px 20px rgba(15, 23, 42, .18);
  border: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
}

.tm-ds #komTopluModal .tm-modal__dialog { max-width: 620px; }

@media (prefers-reduced-motion: reduce) {
  .tm-ds .kom-mod__btn { transition: none; }
}


/* ── Meşgul perdesi + toast (2026-10-10) ─────────────────────────────────
   🔴 KULLANICI: "yükleme yapıyorum birkaç saniye hiçbir şey olmuyor".
   Uzun işin ekranda izi olmalı. Perde tıklamayı da yutar — iş sürerken
   ikinci kez yükleme tetiklenmesin. */
.kom-mesgul {
  position: fixed;
  inset: 0;
  z-index: 1200;                 /* modal (1000) üstünde */
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(15, 23, 42, .45);
  backdrop-filter: blur(2px);
}
.kom-mesgul.is-open { display: flex; }
.kom-mesgul__kutu {
  background: var(--tm-surface, #fff);
  color: var(--tm-text, #0f172a);
  border: 1px solid var(--tm-border-subtle, #e2e8f0);
  border-radius: 14px;
  padding: var(--tm-space-6, 24px) var(--tm-space-8, 32px);
  min-width: 300px;
  max-width: 440px;
  text-align: center;
  box-shadow: 0 18px 48px rgba(15, 23, 42, .22);
}
.kom-mesgul__spin {
  width: 34px;
  height: 34px;
  margin: 0 auto 16px;
  border: 3px solid var(--tm-border-subtle, #e2e8f0);
  border-top-color: var(--tm-primary, #2563eb);
  border-radius: 50%;
  animation: kom-spin .8s linear infinite;
}
@keyframes kom-spin { to { transform: rotate(360deg); } }
/* Hareketi azalt tercihine saygı: dönme durur, perde yine görünür. */
@media (prefers-reduced-motion: reduce) {
  .kom-mesgul__spin { animation: none; }
}
.kom-mesgul__metin { font-size: 15px; font-weight: 600; }
.kom-mesgul__alt {
  margin-top: 8px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--tm-text-muted, #64748b);
}

/* Sayfanın kendi bildirimi — SAĞ ALTTA, destek balonunun (52 px, alt 20 px)
   ÜSTÜNDE. Global toast üst-ortada sayfa başlığını örtüyordu (2026-10-11). */
/* 🔴 TOAST HER EKRANDA ÜST-ORTA, KÜÇÜK (2026-10-14, kullanıcı ekran görüntüsü:
   *"hâlâ ekranın sağ altında toast ile bilgi veriyor"*). İlk turda yalnız
   ≤640 px'i taşımıştım; masaüstünde sağ altta kalıyor ve "Hesapla" düğmesi +
   destek balonunun üstüne biniyordu. Artık tek kural: üst çubuğun hemen
   altında, yatay ortada, içerik kadar geniş; tıklamayı yutmaz. */
.kom-toast {
  position: fixed;
  top: calc(var(--tm-header-height, 60px) + 12px);
  left: 50%;
  right: auto;
  bottom: auto;
  z-index: 1300;
  width: max-content;
  max-width: min(440px, calc(100vw - 32px));
  padding: 9px 14px 9px 12px;
  border-radius: 999px;
  border: 1px solid var(--tm-border-subtle, rgba(15, 23, 42, .10));
  border-inline-start: 4px solid #16a34a;
  font-size: 12.5px;
  line-height: 16px;
  color: var(--tm-text-primary, #0f172a);
  background: var(--tm-surface-raised, #fff);
  box-shadow: 0 10px 28px rgba(15, 23, 42, .16);
  opacity: 0;
  transform: translate(-50%, -8px);
  pointer-events: none;
  transition: opacity .18s ease, transform .18s ease;
}
.kom-toast.is-open { opacity: 1; transform: translate(-50%, 0); }
.kom-toast--hata { border-inline-start-color: #dc2626; }

/* Veri ayrı istekle geldiği için tabloda kısa bir bekleme izi olur —
   boş ızgara göstermek "ürün yok" yanılgısı yaratırdı. */
.tm-ds .kom-yukleniyor {
  grid-column: 1 / -1;
  padding: var(--tm-space-6, 24px) var(--tm-space-4);
  text-align: center;
  font-size: 13px;
  color: var(--tm-text-muted, #64748b);
}

/* ── Başlık alt-metni ────────────────────────────────────────────────────
   🔴 `.kom-th__alt` için HİÇ KURAL YOKTU: "Satış fiyatı" ile "komisyona
   esas" aynı satıra girip birbirine yapışıyordu ("Satış fiyatıkomisyona
   esas") ve dar sütunda üç satıra bölünüyordu. Kullanıcı ekran
   görüntüsünde böyle gördü. Alt metin KENDİ satırında, küçük ve soluk. */
.tm-ds .kom-th__alt {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  letter-spacing: .01em;
  color: var(--tm-text-muted, #94a3b8);
  text-transform: none;
}

/* ── Görsel sadeleştirme (2026-10-11, kullanıcı: "güzel değil") ─────────
   🔴 Ekran görüntüsünde dört banttan üçü dolgulu KIRMIZI rozetle
   çiziliyordu. Satıcının gözü her satırda üç kırmızı uyarı görüyor ve
   asıl bilgi — hangi bant kârlı — bu gürültüde kayboluyor. Zarar BİLGİ,
   ALARM değil: dolgu kalkar, yalnız renkli metin kalır. Kâr dolgulu
   kalır çünkü aranan şey odur. */
/* 🔴 ZARAR BAĞIRMAZ. Kâr/zarar artık 15 px kahraman; zarar da kalın
   kırmızı olsaydı dört banttan üçü ekranda yanıp sönen bir uyarı gibi
   dururdu (ilk denemede tam böyle göründü). Eksi işareti ve renk zaten
   anlamı taşıyor; ağırlık ve doygunluk düşürülür. Kâr kalın kalır —
   aranan şey o. */
/* ══════════════════════════════════════════════════════════════════════
   ZARAR EDEN BANT: SESSİZ, AMA YİNE DE BİR HAP (2026-10-11 tasarım turu)

   🔴 Burada `background: transparent; opacity: .62` yazıyordu ve bu kural
   dosyanın SONUNDA olduğu için yukarıdaki `.kom-kar--zarar` dolgusunu
   EZİYORDU. Sonuç: yeşil kâr dolgulu bir hap, kırmızı zarar ÇIPLAK metin —
   yani aynı veri iki farklı nesne gibi okunuyordu ve brief ilke 2
   (*"Sonuç, girdilerden görsel olarak AYRI; kâr/zarar dolgulu bir hapta"*)
   zararda bozuluyordu.

   Ama *"zarar eden bant aday değildir"* ölçülmüş ve doğru bir gözlem
   (40 hücrenin 30'u zarar; hepsi kazananla aynı ağırlıkta çizilince
   "sayı duvarı" oluyor). İkisi birlikte: hap KALIR, sesi KISILIR —
   daha soluk dolgu + normal ağırlık. Hiyerarşi `opacity` numarasıyla
   değil DOLGU DOYGUNLUĞU ve YAZI AĞIRLIĞI ile kuruluyor; `opacity`
   metni de soluklaştırıp kontrastı AA sınırının altına düşürüyordu.
   ══════════════════════════════════════════════════════════════════════ */
.tm-ds .kom-kar--zarar {
  background: var(--tm-danger-50, rgba(185, 28, 28, .07));
  color: var(--tm-danger-600, #b91c1c);
}
.tm-ds .kom-kar--zarar .kom-kar__tutar { font-weight: var(--tm-weight-medium, 500); }
/* Seçiliyken ya da üzerine gelince tam ağırlık geri gelir — kullanıcı
   bilerek zararlı bandı seçebilir (CLAUDE.md: kapı değil, hiyerarşi). */
.tm-ds .kom-bant.is-picked .kom-kar--zarar .kom-kar__tutar,
.tm-ds .kom-bant:hover .kom-kar--zarar .kom-kar__tutar {
  font-weight: var(--tm-weight-bold, 700);
}

/* 🔴 BURAYA "seçili bant görünmüyor" diye bir kural EKLEMİŞTİM — iki
   yönden yanlıştı, ikisini de test yakaladı:
   ① Bu tasarım sisteminde tanımlı OLMAYAN renk belirteçleri kullandım;
      tanımsız bir `var()` sessizce yanlış renk üretir. Doğrusu vurgu
      renginin kanonik belirteci (yukarıdaki kuralda zaten kullanılıyor).
   ② Zaten yukarıda doğru bir `.is-picked` kuralı VAR: 2 px kenar +
      renkli zemin. Benimki onu ZAYIFLATIYORDU (1 px iç gölge).
   Varsayımı ölçmeden "görünmüyor" demiştim; baktığım ekran görüntüsünde
   seçili bant yoktu, yani aslında hiç bakmamıştım. Kaldırıldı.
   ⚠️ İlk düzeltmemde bu açıklamanın İÇİNE belirteç adını yazmıştım ve
   test yine kırmızı verdi — kural ham dosyayı tarıyor, yorum dâhil. */

/* 🔴 "Satış fiyatı / komisyona esas" başlığı ÜÇ SATIRA bölünüyordu
   (ekran görüntüsü): sütun 86 px'ti, alt metin sığmıyordu. Izgara
   tanımında 112 px'e çıkarıldı — ayrı bir değişkenle değil, çünkü
   ızgara `grid-template-columns` içinde sabit yazılı. */

/* 🔴 Toplu seçim önizlemesi KÂR DÜŞÜRÜYORSA uyarı rengi (QA 2026-10-11).
   Ölçüldü: "Zarar edenleri atla" açıkken uygulanan toplu seçim
   Ek kâr −3.831,22 ₺ üretti ve kullanıcı bunu ancak UYGULADIKTAN sonra
   gördü. Artık uygulamadan önce görüyor ve renk de uyarıyor. */
.tm-ds .kom-onizleme.is-zararli {
  color: var(--tm-danger-600, #b91c1c);
  font-weight: var(--tm-weight-semibold);
}

/* 🔴 "ve üstü" EKİ KALDIRILDI (2026-10-11) — hedef fiyat artık seçim
   anahtarıyla aynı satırda ve ek metin hücreye sığmıyordu. Kural da silindi:
   çizilmeyen elemanın kuralı, bir sonraki yerleşimde komşusunu sessizce
   ezer (bu dosyada `.kom-bant__karoran` ile tam olarak bu yaşandı).
   Tam aralık `title` + `aria-label` içinde. */

/* 🔴 `.kom-stat__v--zarar` / `--kar` KURALLARI DA SİLİNDİ (2026-10-11):
   taşıyıcıları (`#komStats`) kaldırıldı. "Negatif ek kâr kırmızı olmalı"
   dersi kaybolmadı — aynı kural `.kom-tag--kayip` ve
   `.kom-balon__dg--zarar` olarak yaşıyor. */

/* ── Boş sonuç ekranı ────────────────────────────────────────────────────
   🔴 Filtre/arama boş dönünce tablo gövdesi 0 px kalıyordu (ölçüldü) —
   kullanıcı ne olduğunu ve nasıl çıkacağını göremiyordu. */
.tm-ds .kom-bos {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--tm-space-3);
  padding: var(--tm-space-10, 40px) var(--tm-space-4);
  text-align: center;
}
.tm-ds .kom-bos__metin {
  margin: 0;
  max-width: 48ch;
  font-size: 13px;
  line-height: 20px;
  color: var(--tm-text-secondary, #475569);
}

/* "şu an en kârlı" — aksiyon GEREKMEDİĞİNİ söyleyen etiket; "en kârlı"
   gibi yeşil/çağrı tonunda olmamalı, yoksa kullanıcı aksiyon sanır. */
.tm-ds .kom-tag--durum {
  background: var(--tm-surface-sunken, rgba(15, 23, 42, .06));
  color: var(--tm-text-muted);
  border-color: transparent;
}

/* 2026-10-14 tasarım turu: hareket azaltma isteyen kullanıcıda toggle animasyonu yok. */
@media (prefers-reduced-motion: reduce) {
  .tm-ds .kom-sw__iz, .tm-ds .kom-sw__iz::after { transition: none; animation: none !important; }
  .tm-ds .kom-sw:checked + .kom-sw__iz, .tm-ds .kom-sw:checked + .kom-sw__iz::after { animation: none !important; }
  .tm-ds .kom-tag--kayip { animation: none !important; }
}


/* ===== css/ds/ds-catalog-promo.css ===== */
/* =================================================================
   TRENDMETRIK DS — KATALOG KAMPANYA (catalog-picker promo)
   Kampanya (store_promotions) indirim gösterimi + rozeti. Yalnız DS modu
   (.tm-ds). Kartlar portallanmaz → `.tm-ds` prefix'i yeterli (ds-catalog.css
   kart kurallarıyla tutarlı). Token-only: renk-literali/!important/gradient
   YOK; radius/shadow eklenmez (badge base'i radius-full'ü zaten verir).
   ================================================================= */

/* Kampanya rozeti (%X İndirim) — dikkat çeken kırmızı; metin beyaz base'ten
   (.cpk-card__badge { color: var(--tm-on-accent) }). #cpkLowQuota a ile aynı desen. */
.tm-ds .cpk-card__badge--campaign { background: var(--tm-danger-fg); }

/* 🔴 KRİTİK FIX: base `.cpk-wk-card { flex: 1 1 168px }` (flex-grow:1) TEK/az kartta track'i
   doldurup `aspect-ratio:1/1` görselini DEV yapıyordu (canlı: 1 kampanya → 1080px dev görsel).
   Grow'u kes + sabit genişlik ver → az kartta sola yaslanır, görsel imgwrap'te kalır. Yüksek
   özgüllük (track > card) + sonra-yüklenir → base'i güvenle ezer. Kök `ds-catalog.css`'te (UI). */
.tm-ds .cpk-weekly__track .cpk-wk-card { flex: 0 0 180px; max-width: 180px; }
@media (max-width: 480px) { .tm-ds .cpk-weekly__track .cpk-wk-card { flex-basis: 150px; max-width: 150px; } }

/* ═══ "FIRSAT ŞERİDİ" — canlı renkli otomatik-kayan showcase karuseli ═══
   Renkler #6511 promo paletinden (--tm-promo-N / -from / -to / -fg, açık+koyu, kontrast ≥4.5:1
   iki uçta ölçülü). JS'te hex YOK — yalnız data-promo + CSS-değişkeni (test-kilitli). Gradient
   token'lı (guard-güvenli). Ambiyans @property ile yumuşak renk geçişi; reduced-motion'da JS
   otomatik-kaydırmayı kapatır (bant sabit kalır, içerik hep görünür). */
@property --tm-promo-grad-from { syntax: "<color>"; inherits: false; initial-value: transparent; }
.tm-ds .cpk-showcase { position: relative; overflow: hidden; }
.tm-ds .cpk-showcase__ambient { position: absolute; inset: 0; z-index: 0; opacity: .16; background: linear-gradient(120deg, var(--tm-promo-grad-from), transparent 72%); transition: --tm-promo-grad-from .6s ease; pointer-events: none; }
/* Hareket-azalt: renk geçişi de kapalı (tutarlılık — kullanıcı-scroll'da bile kaymasın). */
@media (prefers-reduced-motion: reduce) { .tm-ds .cpk-showcase__ambient { transition: none; } }
.tm-ds .cpk-showcase .cpk-weekly__head, .tm-ds .cpk-showcase .cpk-weekly__track { position: relative; z-index: 1; }
/* Renkli kart: token gradient zemin + beyaz metin. */
.tm-ds .cpk-wk-card--vivid { border: 0; color: var(--tm-promo-fg); }
.tm-ds .cpk-wk-card--vivid[data-promo="1"] { background: linear-gradient(135deg, var(--tm-promo-1-from), var(--tm-promo-1-to)); }
.tm-ds .cpk-wk-card--vivid[data-promo="2"] { background: linear-gradient(135deg, var(--tm-promo-2-from), var(--tm-promo-2-to)); }
.tm-ds .cpk-wk-card--vivid[data-promo="3"] { background: linear-gradient(135deg, var(--tm-promo-3-from), var(--tm-promo-3-to)); }
.tm-ds .cpk-wk-card--vivid[data-promo="4"] { background: linear-gradient(135deg, var(--tm-promo-4-from), var(--tm-promo-4-to)); }
.tm-ds .cpk-wk-card--vivid[data-promo="5"] { background: linear-gradient(135deg, var(--tm-promo-5-from), var(--tm-promo-5-to)); }
.tm-ds .cpk-wk-card--vivid[data-promo="6"] { background: linear-gradient(135deg, var(--tm-promo-6-from), var(--tm-promo-6-to)); }
.tm-ds .cpk-wk-card--vivid .cpk-wk-card__name,
.tm-ds .cpk-wk-card--vivid .cpk-wk-card__price,
.tm-ds .cpk-wk-card--vivid .cpk-wk-card__price-now,
.tm-ds .cpk-wk-card--vivid .cpk-wk-card__price-was,
.tm-ds .cpk-wk-card--vivid .cpk-wk-card__sales { color: var(--tm-promo-fg); }
/* Ürün görseli renkli kartta aydınlık çerçevede net dursun. */
.tm-ds .cpk-wk-card--vivid .cpk-wk-card__imgwrap { background: var(--tm-bg-surface); }
/* Seç butonu renkli kartta beyaz zeminde kalır (kontrast okunur CTA). */
.tm-ds .cpk-wk-card--vivid .cpk-wk-card__pick { background: var(--tm-bg-surface); }

/* Çok-modlu showcase sekmeleri (Kampanyalar / Yeni Ürünler) — button (span-inherit muaf), token-only. */
/* Sekmeler: sağa yaslı (toggle'ın yanına) + yan yana kalır (ortada sıkışıp alt-alta binmez). */
.tm-ds .cpk-weekly__tabs { display: inline-flex; flex-direction: row; flex: 0 0 auto; flex-wrap: nowrap; gap: var(--tm-space-1); align-items: center; }
/* `flex-direction: row` acikca yazili: head'in `> div` kurali bir daha yakalarsa sessizce
   sutuna donmesin. `margin-left: auto` KALDIRILDI - toggle'da da vardi; iki auto margin
   bosluğu paylasinca sekmeler ORTADA kaliyordu. Basliginin `flex: 1 1 auto` olmasi yeterli. */
.tm-ds .cpk-weekly__tab { white-space: nowrap; }
.tm-ds .cpk-weekly__tab { display: inline-flex; align-items: center; gap: var(--tm-space-1); height: 28px; padding: 0 var(--tm-space-3); border-radius: var(--tm-radius-full); border: 1px solid var(--tm-border); background: var(--tm-bg-surface); color: var(--tm-text-secondary); font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold); cursor: pointer; }
.tm-ds .cpk-weekly__tab [data-lucide] { width: 13px; height: 13px; }
.tm-ds .cpk-weekly__tab:hover { border-color: var(--tm-accent-fg); color: var(--tm-accent-fg); }
.tm-ds .cpk-weekly__tab.is-active { background: var(--tm-accent-solid); border-color: transparent; color: var(--tm-on-accent); }
.tm-ds .cpk-weekly__tab.is-active [data-lucide] { color: var(--tm-on-accent); }

/* "Tümünü gör" (#6574, catalog oturumu): şerit yalnız ~10 ürün gösteriyor ve yatay kaydırma
   keşfedilmiyordu (ölçüm: scrollWidth 1908 / clientWidth 1534 → 10 üründen 8'i görünmüyor).
   Sekmelerle toggle ARASINDA duruyor; bir SEKME değil, bir EYLEM — o yüzden hap değil metin-buton:
   aktif sekmeyle (dolu accent hap) yarışmasın, ama tıklanabilirliği belli olsun.
   `.cpk-weekly__head > div:not(...)` seçicisine takılmaz çünkü `<button>`, `div` değil. */
.tm-ds .cpk-weekly__seeall { display: inline-flex; flex: 0 0 auto; align-items: center; gap: var(--tm-space-1); height: 28px; padding: 0 var(--tm-space-2); border: 1px solid transparent; border-radius: var(--tm-radius-control); background: transparent; color: var(--tm-accent-fg); font-size: var(--tm-type-caption); font-weight: var(--tm-weight-semibold); white-space: nowrap; cursor: pointer; }
.tm-ds .cpk-weekly__seeall [data-lucide] { width: 13px; height: 13px; }
.tm-ds .cpk-weekly__seeall:not(:disabled):not([aria-disabled="true"]):hover { background: var(--tm-accent-bg); border-color: var(--tm-accent-bg); }

/* Yatay kaydırma okları (#6574 markup + JS; CSS burada). Gerekçe ölçüm: şerit
   scrollWidth 1908 / clientWidth 1534 → 10 üründen 8'i görünmüyordu ve bunu gösteren HİÇBİR
   işaret yoktu. Önce saf-CSS kenar gölgesi denendi, ÖLÇÜLDÜ ve ÇALIŞMADI: kartlar opak ve
   track'in tüm yüksekliğini kapladığı için gölge kartların ARKASINDA kalıyor (sol kenar
   [255,255,255] == orta). Ok butonu hem görünür hem klavyeyle erişilebilir — doğru çözüm oydu.
   · Oklar track'in ÜSTÜNDE yüzer (absolute), track'e padding vermiyoruz: kart genişliği ve
     scroll-snap hizası bozulmasın.
   · `disabled` durumunu JS yönetiyor (başta prev, sonda next). #6560'ın disabled stili buraya
     oturuyor: sönük + not-allowed + hover sessiz — "buton var ama ölü" yalanı yok.
   · Kaydırılacak yer yoksa JS `.is-scrollable`'ı kaldırıyor; oklar tamamen GİZLENİYOR
     (disabled iki ok göstermek, hiç ok göstermemekten gürültülü). */
.tm-ds .cpk-weekly__viewport { position: relative; min-width: 0; }
.tm-ds .cpk-weekly__viewport:not(.is-scrollable) .cpk-weekly__nav { display: none; }
.tm-ds .cpk-weekly__nav { position: absolute; top: 50%; transform: translateY(-50%); z-index: 2; width: 32px; height: 32px; display: grid; place-items: center; padding: 0; border: 1px solid var(--tm-border); border-radius: var(--tm-radius-full); background: var(--tm-bg-surface); color: var(--tm-text-secondary); box-shadow: var(--tm-shadow-card); cursor: pointer; }
.tm-ds .cpk-weekly__nav [data-lucide] { width: 16px; height: 16px; }
.tm-ds .cpk-weekly__nav--prev { left: 0; }
.tm-ds .cpk-weekly__nav--next { right: 0; }
.tm-ds .cpk-weekly__nav:not(:disabled):not([aria-disabled="true"]):hover { border-color: var(--tm-accent-fg); color: var(--tm-accent-fg); }
.tm-ds .cpk-weekly__nav:disabled { opacity: .5; cursor: not-allowed; }
.tm-ds .cpk-wk-empty { padding: var(--tm-space-4); font-size: var(--tm-type-caption); color: var(--tm-text-muted); }

/* "Haftanın Kampanyaları" banner kartında indirim rozeti (kırmızı) — base .cpk-wk-card__reason
   accent (mavi) yerine danger. Metin base'ten --tm-on-accent. */
.tm-ds .cpk-wk-card__reason--campaign { background: var(--tm-danger-fg); }

/* Kart-üstü pazaryeri aktarım durumu çipleri (TY/HB): aktardığın=yeşil ✓, aktarmadığın=soluk ✗
   (tıkla→aktarıma ekle). Durum rengi ikonda ([data-lucide], span değil) → dark-mode span→inherit
   güvenli. Margin yok (DS guard 0/auto); gap ile hizalanır. Token-only. */
.tm-ds .cpk-card__mps { display: flex; gap: var(--tm-space-1); flex-wrap: wrap; }
.tm-ds .cpk-card__mp { display: inline-flex; align-items: center; gap: var(--tm-space-1); height: 18px; padding: 0 var(--tm-space-2); border-radius: var(--tm-radius-full); border: 1px solid var(--tm-border); font-size: var(--tm-type-micro); font-weight: var(--tm-weight-semibold); color: var(--tm-text-muted); }
.tm-ds .cpk-card__mp [data-lucide] { width: 10px; height: 10px; }
.tm-ds .cpk-card__mp--on { border-color: var(--tm-success-fg); }
.tm-ds .cpk-card__mp--on [data-lucide] { color: var(--tm-success-fg); }
.tm-ds .cpk-card__mp--off { cursor: pointer; }
/* --warn: kartın "gönderilemez" sebebi (#6592 PR-2b). "Aktardım ✓" ile YAN YANA durur — ikisi
   çelişmiyor: ürün mağazada VAR (①) ama pazaryerine gidemiyor (②③). Sebep adları sync-motorunun
   kanonik listesiyle aynı, panel ile de aynı; üç yerde tek dil.
   `--on` gibi yalnız kenarlık değil ZEMİN de alıyor: "sorun var" sinyali, "durum bilgisi"nden
   daha güçlü okunmalı. Renk tek başına taşımıyor — `alert-triangle` ikonu eşlik ediyor. */
.tm-ds .cpk-card__mp--warn { border-color: var(--tm-warning-fg); background: var(--tm-warning-bg); color: var(--tm-warning-fg); }
/* ⚠ İkon için AYRI kural YOK, bilerek: `[data-lucide]` `currentColor` kullanıyor ve rozetin
   kendi `color`'ı zaten warning-fg. `--on` kardeşinde ayrı kural VAR çünkü orada rozetin metni
   muted, yalnız ikon yeşil. Buraya da yazmıştım — mutasyonda YEŞİL kaldı (silince hiçbir şey
   değişmiyordu), yani ölü kuraldı; kaldırıldı. */
.tm-ds .cpk-card__mp--off [data-lucide] { color: var(--tm-text-muted); }
.tm-ds .cpk-card__mp--off:hover { border-color: var(--tm-accent-fg); color: var(--tm-accent-fg); }
.tm-ds .cpk-card__mp--off:hover [data-lucide] { color: var(--tm-accent-fg); }

/* Pazaryeri-aktarım filtresi — upload ikonlu chip sarmalayıcı. Taksonomi select'lerinden
   (kategori/marka) görsel ayrışır. Chip aestetiği toolbar cpk-chip deseniyle tutarlı;
   ds-catalog.css toolbar grid'ine DOKUNULMAZ (kurallar burada, UI oturumu ~140px ayırdı). */
.tm-ds .cpk-export { display: inline-flex; align-items: center; gap: var(--tm-space-1); height: 36px; padding: 0 var(--tm-space-2); border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); background: var(--tm-bg-surface); min-width: 150px; box-shadow: none; }
.tm-ds .cpk-export [data-lucide] { width: 14px; height: 14px; flex: 0 0 auto; color: var(--tm-accent-fg); }
/* İçteki select: kendi kutu-stilini (border/bg/genişlik) bırakır — sarmalayıcı taşır. */
.tm-ds .cpk-export .cpk-select--bare { border: 0; min-width: 0; max-width: none; height: auto; padding: 0 var(--tm-space-6) 0 0; background: transparent; flex: 1 1 auto; }

/* Kampanya fiyat bloğu: üstü-çizili orijinal (was) + güncel indirimli (now). */
.tm-ds .cpk-card__price--campaign { display: inline-flex; align-items: baseline; gap: var(--tm-space-2); font-family: var(--cpk-mono); }
.tm-ds .cpk-card__price-was { font-size: var(--tm-type-caption); font-weight: var(--tm-weight-medium); color: var(--tm-text-muted); text-decoration: line-through; }
.tm-ds .cpk-card__price-now { font-size: var(--tm-type-body); font-weight: var(--tm-weight-bold); color: var(--tm-danger-fg); }

/* ════════════════════════════════════════════════════════════════════════
   HERO-İÇİ HAFTALIK ŞERİT (2026-09-17 birleştirme) — "Bu Haftanın Öne
   Çıkanları" ayrı bir tam-genişlik ds beyaz-kartıydı; hero'nun İÇİNE, sol/sağ
   satırın altına tam-genişlik şerit olarak alındı (iki blok → tek banner,
   dikey yer kazancı). ds beyaz-kart (.tm-ds .cpk-weekly, ds-catalog.css:342)
   yerine hero mavisine oturan ŞEFFAF panel: bileşik seçici (.cpk-weekly.
   cpk-hero__weekly = 0,3,0) yükleme sırasından bağımsız kazanır.
   ════════════════════════════════════════════════════════════════════════ */
.tm-ds .cpk-weekly.cpk-hero__weekly {
  flex: 1 1 100%;
  width: 100%;
  z-index: 1;
  background: transparent;
  border: 0;
  border-top: 1px solid color-mix(in srgb, var(--tm-on-accent) 22%, transparent);
  border-radius: 0;
  box-shadow: none;
  /* 2026-09-18: hero'daki dikey "boş mavi void" kaldırıldı — şerit ince bir satır.
     Yüklenmeden ÖNCE yalnız başlık + sekme + slim CTA (tek satır); kartlar tıklayınca
     gelip alanı DOLDURUR. Eski büyük ortalı CTA bloğu ~150px boşluk bırakıyordu. */
  padding: var(--tm-space-3) 0 0;
  margin-top: var(--tm-space-2);
  gap: var(--tm-space-2);
}
/* Başlık/alt-başlık hero mavisi üzerinde beyaz (ds surface metni yerine on-accent). */
.tm-ds .cpk-hero__weekly .cpk-weekly__t { color: var(--tm-on-accent); }
.tm-ds .cpk-hero__weekly .cpk-weekly__s { color: var(--tm-on-accent); opacity: .78; }
/* Yüklenmemiş şeritte viewport min-yükseklik dayatmasın → boşluk oluşmaz. */
.tm-ds .cpk-hero__weekly .cpk-weekly__viewport { min-height: 0; }

/* Tıkla-yükle CTA — ilk açılışta track'te tek bu durur (FETCH YOK); tıklayınca
   loadWeekly() track.innerHTML'i ezer → CTA gider, kartlar stagger ile gelir.
   SLIM: büyük ortalı blok yerine sola yaslı tek satır (buton + ipucu yan yana) —
   hero'da dikey boşluk bırakmaz. */
.tm-ds .cpk-wk-cta {
  flex: 1 1 100%;
  display: flex; flex-direction: row; align-items: center; flex-wrap: wrap; gap: var(--tm-space-2) var(--tm-space-3);
  padding: var(--tm-space-1) 0 var(--tm-space-2);
  text-align: left;
}
.tm-ds .cpk-wk-cta__btn {
  display: inline-flex; align-items: center; gap: var(--tm-space-2);
  height: 34px; padding: 0 var(--tm-space-4);
  border: 0; border-radius: var(--tm-radius-full); cursor: pointer;
  font-family: inherit; font-size: var(--tm-type-caption); font-weight: var(--tm-weight-bold);
  color: #0b2740;
  background: linear-gradient(135deg, #ffd27a, #fd751f);
  box-shadow: var(--tm-shadow-card);
  transition: transform .14s ease, box-shadow .14s ease;
}
.tm-ds .cpk-wk-cta__btn:hover { transform: translateY(-1px); box-shadow: 0 9px 24px rgba(253,117,31,.5); }
.tm-ds .cpk-wk-cta__btn [data-lucide] { width: 15px; height: 15px; }
.tm-ds .cpk-wk-cta__hint { font-size: var(--tm-type-micro); color: var(--tm-on-accent); opacity: .66; }

/* Stagger giriş animasyonu — kartlar tıkla-yükle sonrası sırayla akar (JS animationDelay). */
@keyframes cpkWkIn {
  from { opacity: 0; transform: translateY(10px) scale(.98); }
  to   { opacity: 1; transform: none; }
}
.tm-ds .cpk-wk-card--enter { animation: cpkWkIn .38s cubic-bezier(.4,0,.2,1) both; }
@media (prefers-reduced-motion: reduce) { .tm-ds .cpk-wk-card--enter { animation: none; } }

/* Mobil: hero-içi şerit başlığı (ic + başlık + sekmeler + tümünü-gör + toggle) tek satıra
   sığmayıp başlığı tek-kelime kırıyordu → sar: başlık tam genişlik satır, sekmeler alt satır.
   Yalnız .cpk-hero__weekly kapsamı (standalone/legacy şeridi etkilenmez). */
@media (max-width: 700px) {
  .tm-ds .cpk-hero__weekly .cpk-weekly__head { flex-wrap: wrap; row-gap: var(--tm-space-2); }
  .tm-ds .cpk-hero__weekly .cpk-weekly__head > div:not(.cpk-weekly__tabs) { flex: 1 1 60%; }
  .tm-ds .cpk-hero__weekly .cpk-weekly__tabs { order: 3; flex: 1 1 100%; justify-content: flex-start; }
}


/* ===== css/ds/ds-journey.css ===== */
/* =================================================================
   TRENDMETRIK DESIGN SYSTEM — KURULUM YOLCULUĞU ŞERİDİ (PR-2, 2026-09-14)
   templates/includes/_setup_journey_band.html · [data-tm-journey]

   SCOPE — unlike ds-shell.css (body.tm-ds-shell, ~3 routes only), this band
   renders on EVERY seller-panel page (docs/onboarding-plan-2026-09-14.md §1:
   "tüm satıcı-paneli sayfalarında"), most of which never carry `.tm-ds` on
   <main> or `tm-ds-shell` on <body>. The DS guard (tests/test_ui_design_system_
   guard.py) requires DS-namespaced radius token NAMES (--tm-radius-control/
   -card/-overlay) — those are only DECLARED inside `.tm-ds {}` (ds-tokens.css)
   or the `body.tm-ds-shell {}` mirror, so a plain page here would see them as
   unset. Fix: mirror the two radius names locally on [data-tm-journey] itself,
   pointing at the ALREADY-GLOBAL v2 primitives (static/css/v2/tokens.css) —
   identical values `.tm-ds` uses, same trick ds-shell.css documents for the
   shell. Everything else below (surface/border/text/accent/shadow/spacing)
   IS already global (:root, dark-mode aware) — used as-is, no mirror needed.
   ================================================================= */

[data-tm-journey] {
  --tm-radius-control: var(--tm-radius-md);
  --tm-radius-card: var(--tm-radius-xl);

  display: flex;
  flex-direction: column;
  gap: var(--tm-space-2);
  padding: var(--tm-space-3) var(--tm-space-4);
  background: var(--tm-surface);
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-card);
  box-shadow: var(--tm-shadow-card);
}

.tm-journey-band__row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--tm-space-3);
}

.tm-journey-band__steps {
  display: flex;
  align-items: center;
  gap: var(--tm-space-2);
}

.tm-journey-band__dot {
  display: inline-block;
  width: var(--tm-space-2);
  height: var(--tm-space-2);
  border-radius: var(--tm-radius-full);
  background: var(--tm-border);
}

.tm-journey-band__dot--done {
  background: var(--tm-ok);
}

.tm-journey-band__dot--current {
  background: var(--tm-accent-500);
  outline: 2px solid var(--tm-accent-50);
  outline-offset: 1px;
}

.tm-journey-band__next {
  font-size: var(--tm-type-caption);
  line-height: var(--tm-type-caption-lh);
  color: var(--tm-text-secondary);
}

.tm-journey-band__next strong {
  color: var(--tm-text-primary);
  font-weight: var(--tm-weight-semibold);
}

/* [data-tm-journey] prefix (not bare .tm-journey-band__cta): a <button> inside
   html.dark-mode is reset by a global `html.dark-mode button { background-color:
   unset; border-color: unset; color: unset; }` (static/css/dark-mode.css:5046,
   NOT !important but 2 type-selectors -> higher specificity than a single class).
   Prefixing with the root's data-attribute selector (0,2,0) beats that (0,1,2)
   on the classes column before type-count is even compared — no !important
   needed, still guard-clean. */
[data-tm-journey] .tm-journey-band__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--tm-space-1);
  padding: var(--tm-space-1) var(--tm-space-3);
  border: 0;
  border-radius: var(--tm-radius-control);
  background: var(--tm-accent-500);
  color: var(--tm-text-on-brand);
  font-size: var(--tm-type-caption);
  font-weight: var(--tm-weight-semibold);
  font-family: inherit;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}

[data-tm-journey] .tm-journey-band__cta:hover {
  background: var(--tm-accent-600);
}

.tm-journey-band__cta svg,
.tm-journey-band__toggle svg {
  width: var(--tm-space-4);
  height: var(--tm-space-4);
}

.tm-journey-band__done-icon {
  color: var(--tm-ok);
  display: inline-flex;
}

.tm-journey-band__done-text {
  font-size: var(--tm-type-body);
  line-height: var(--tm-type-body-lh);
  font-weight: var(--tm-weight-semibold);
  color: var(--tm-text-primary);
}

/* [data-tm-journey] prefix: same html.dark-mode button reset as .tm-journey-band__cta above. */
[data-tm-journey] .tm-journey-band__toggle {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--tm-space-1);
  border: 0;
  background: transparent;
  border-radius: var(--tm-radius-control);
  color: var(--tm-text-muted);
  cursor: pointer;
}

[data-tm-journey] .tm-journey-band__toggle:hover {
  background: var(--tm-surface-sunken);
}

/* Collapsed-label: only element visible in the collapsed row besides the
   toggle. Server renders BOTH the full row and this label always (no
   JS-inserted markup, no height recalculation -> no CLS); CSS just swaps
   which one is visible based on the server-rendered --collapsed modifier. */
.tm-journey-band__collapsed-label {
  display: none;
  font-size: var(--tm-type-caption);
  color: var(--tm-text-secondary);
}

.tm-journey-band--collapsed .tm-journey-band__steps,
.tm-journey-band--collapsed .tm-journey-band__next,
.tm-journey-band--collapsed .tm-journey-band__cta,
.tm-journey-band--collapsed .tm-journey-band__done-icon,
.tm-journey-band--collapsed .tm-journey-band__done-text {
  display: none;
}

.tm-journey-band--collapsed .tm-journey-band__collapsed-label {
  display: inline;
}

.tm-journey-band--collapsed {
  padding-top: var(--tm-space-2);
  padding-bottom: var(--tm-space-2);
}

.tm-journey-band__tasks:empty {
  display: none;
}

/* PR-5 (docs/onboarding-plan-2026-09-14.md §2) — eksik-görev satırı. */
.tm-journey-band--collapsed .tm-journey-band__tasks {
  display: none;
}

.tm-journey-band__tasks-list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--tm-space-2);
}

/* [data-tm-journey] prefix: same html.dark-mode button reset as
   .tm-journey-band__cta/.tm-journey-band__toggle above — severity color
   would otherwise be forced to #60a5fa by html.dark-mode a:not(...). */
[data-tm-journey] .tm-journey-band__task {
  display: inline-flex;
  align-items: center;
  gap: var(--tm-space-1);
  padding: var(--tm-space-1) var(--tm-space-2);
  border: 1px solid var(--tm-border);
  border-radius: var(--tm-radius-control);
  background: var(--tm-surface-sunken);
  color: var(--tm-text-secondary);
  font-size: var(--tm-type-caption);
  font-family: inherit;
  white-space: nowrap;
  cursor: pointer;
}

[data-tm-journey] .tm-journey-band__task:hover {
  background: var(--tm-surface);
}

/* Global v2 primitives (--tm-warn/--tm-bad, static/css/v2/tokens.css), NOT the
   DS-scoped --tm-warning-fg/--tm-danger-fg (ds-tokens.css) which only resolve
   inside .tm-ds — same reasoning as the radius-token mirror at the top of this
   file: this band renders on plain (non-.tm-ds) pages too. */
[data-tm-journey] .tm-journey-band__task--warning {
  border-color: var(--tm-warn-border);
  color: var(--tm-warn);
}

[data-tm-journey] .tm-journey-band__task--critical {
  border-color: var(--tm-bad-border);
  color: var(--tm-bad);
}

.tm-journey-band__task-more {
  font-size: var(--tm-type-caption);
  color: var(--tm-text-muted);
}


/* ── Adım kartı (onboarding v2, 2026-09-21) — sıradaki adımın sayfasında anlatıcı ── */
.tm-journey-card {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 16px;
  align-items: center;
  margin: 0 0 16px;
  padding: 16px 20px;
  border: 1px solid var(--tm-border, #e5e7eb);
  border-left: 4px solid var(--tm-primary, #2563eb);
  border-radius: var(--tm-radius-lg, 12px);
  background: var(--tm-surface, #fff);
  box-shadow: var(--tm-shadow-sm, 0 1px 2px rgba(0,0,0,.05));
}
.tm-journey-card__step { display: flex; flex-direction: column; gap: 8px; min-width: 96px; }
.tm-journey-card__badge {
  display: inline-block; font-size: 12px; font-weight: 600; letter-spacing: .02em;
  color: var(--tm-primary, #2563eb); background: var(--tm-primary-soft, #eff6ff);
  padding: 4px 10px; border-radius: 999px; white-space: nowrap;
}
.tm-journey-card__progress { height: 6px; border-radius: 999px; background: var(--tm-border, #e5e7eb); overflow: hidden; }
.tm-journey-card__progress > span { display: block; height: 100%; background: var(--tm-primary, #2563eb); }
.tm-journey-card__title { margin: 0 0 4px; font-size: 17px; line-height: 1.3; font-weight: 700; color: var(--tm-text, #111827); }
.tm-journey-card__text { margin: 0; font-size: 14px; line-height: 1.5; color: var(--tm-text-muted, #4b5563); max-width: 72ch; }
.tm-journey-card__hint { margin: 6px 0 0; font-size: 12px; color: var(--tm-text-muted, #6b7280); }
.tm-journey-card__actions { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.tm-journey-card__cta {
  display: inline-block; padding: 10px 16px; border-radius: 8px; font-weight: 600; font-size: 14px;
  color: #fff; background: var(--tm-primary, #2563eb); text-decoration: none; white-space: nowrap;
}
.tm-journey-card__cta:hover { filter: brightness(.95); color: #fff; }
.tm-journey-card__skip {
  background: none; border: 0; padding: 4px 0; font-size: 12px; color: var(--tm-text-muted, #6b7280);
  text-decoration: underline; cursor: pointer;
}
.tm-journey-card__skip:hover { color: var(--tm-text, #111827); }
@media (max-width: 992px) {
  .tm-journey-card { grid-template-columns: 1fr; gap: 12px; padding: 14px 16px; }
  .tm-journey-card__step { flex-direction: row; align-items: center; }
  .tm-journey-card__progress { flex: 1; }
  .tm-journey-card__actions { flex-direction: row; align-items: center; justify-content: space-between; }
}
@media (max-width: 576px) {
  .tm-journey-card { margin: 0 0 12px; padding: 12px; border-radius: 12px; }
  .tm-journey-card__title { font-size: 16px; }
  .tm-journey-card__text { font-size: 13px; }
  .tm-journey-card__cta { width: 100%; text-align: center; }
  .tm-journey-card__actions { flex-direction: column; align-items: stretch; }
}


/* ===== css/ds/ds-tutorial.css ===== */
/* Paylasilan tutorial bileseni — "Nasil calisir?" adim adim anlatim (2026-09-18).
 *
 * KOKEN: katalog sayfasindaki `.cpk-tut*` bileseni (ds-catalog.css). Kullanici
 * "katalogdaki tutorial gibi olsun, yenisini yazma" dedi; bu dosya O bilesenin
 * sayfadan bagimsiz hale getirilmis kopyasidir — ayni yerlesim, ayni acilis
 * animasyonu, ayni akis-dugumleri.
 *
 * ⚠️ KOPYA BORCU (bilincli, docs/backlog.md'ye yazildi): katalog hala kendi
 * `.cpk-tut*` kurallarini kullaniyor. Iki kopyayi AYNI ANDA degistirmek yerine
 * katalogu bu bilesene tasimak dogru yol — ama bugun katalogu riske atmamak
 * icin yapilmadi. Bir sonraki katalog dokunusunda tasinmali.
 *
 * Kapsam: `.tm-ds` (DS opt-in) — DS disi sayfalarda inert.
 * Hareket butcesi (docs/ui-reference-spec.md): yalniz transform/opacity
 * animasyonu; layout ozelligi (left/top/width/height) animasyonu YOK.
 */

:is(.tm-ds, body.tm-ds-shell) .tm-tut { position: fixed; inset: 0; z-index: 2100; display: none; }

:is(.tm-ds, body.tm-ds-shell) .tm-tut.is-open { display: block; }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__backdrop { position: absolute; inset: 0; background: rgba(15,23,42,.5); opacity: 1; -webkit-backdrop-filter: blur(7px); backdrop-filter: blur(7px); }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__dialog { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: min(700px, calc(100vw - 28px)); max-height: calc(100vh - 40px); display: flex; flex-direction: column; gap: var(--tm-space-2); overflow: hidden; background: var(--tm-surface); border: 1px solid var(--tm-border); border-radius: var(--tm-radius-overlay); box-shadow: var(--tm-shadow-modal); animation: none; }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__top { position: relative; padding: var(--tm-space-4) var(--tm-space-6) 0; }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__kicker { display: inline-flex; align-items: center; gap: var(--tm-space-1); font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--tm-accent-600); }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__close { position: absolute; top: var(--tm-space-3); right: var(--tm-space-3); width: 32px; height: 32px; border-radius: var(--tm-radius-control); border: 1px solid var(--tm-border); background: var(--tm-ink-100); color: var(--tm-text-muted); display: grid; place-items: center; cursor: pointer; transition: none; }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__close:hover { color: var(--tm-text-primary); }

/* R7 2026-09-23 (audit, /buybox-control/v3/ @320): dialog width min(700px,
   100vw-28px) = 292px at 320px viewport; 4 nodes at flex:0 0 auto width:78px
   already need 312px before the 3 connector lines are even counted — the
   last node was clipped by .tm-tut__dialog's own overflow:hidden. Rather than
   shrink node/icon size (label would stop being legible), let the row itself
   scroll horizontally — same "yatay kaydırma" pattern already used for wide
   data tables elsewhere in the audit. */
:is(.tm-ds, body.tm-ds-shell) .tm-tut__flow { display: flex; align-items: flex-start; padding: var(--tm-space-4) var(--tm-space-1) var(--tm-space-2); overflow-x: auto; -webkit-overflow-scrolling: touch; }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__node { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; gap: var(--tm-space-1); width: 78px; }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__node-ic { position: relative; width: 40px; height: 40px; border-radius: var(--tm-radius-full); display: grid; place-items: center; background: var(--tm-ink-100); border: 2px solid var(--tm-border); color: var(--tm-text-muted); transition: none; }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__node.is-active .tm-tut__node-ic { background: var(--tm-accent-500); border-color: var(--tm-accent-500); color: var(--tm-text-on-brand); }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__node.is-done .tm-tut__node-ic { background: var(--tm-accent-50); border-color: var(--tm-accent-600); color: var(--tm-accent-600); }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__node-lbl { font-size: 11px; font-weight: 500; color: var(--tm-text-muted); text-align: center; line-height: 1.25; }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__node.is-active .tm-tut__node-lbl { color: var(--tm-text-primary); }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__conn { flex: 1 1 auto; height: 2px; align-self: center; background: var(--tm-border); }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__conn.is-done { background: var(--tm-accent-600); }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__body { padding: var(--tm-space-2) var(--tm-space-6) 0; display: flex; flex-direction: column; align-items: center; gap: var(--tm-space-2); text-align: center; }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__viz { width: 100%; max-width: 300px; padding: var(--tm-space-3); background: var(--tm-ink-100); border: 1px solid var(--tm-border); border-radius: var(--tm-radius-control); }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__viz svg { width: 100%; height: auto; max-height: 150px; display: block; }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__stepno { font-family: var(--cpk-mono); font-size: 12px; font-weight: 500; color: var(--tm-accent-600); }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__h { font-size: 18px; font-weight: 700; color: var(--tm-text-primary); margin: 0; }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__d { font-size: 14px; line-height: 20px; color: var(--tm-text-secondary); max-width: 480px; margin: 0 auto; }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__d b { color: var(--tm-text-primary); }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__foot { display: flex; align-items: center; justify-content: space-between; gap: var(--tm-space-3); padding: var(--tm-space-4) var(--tm-space-6); }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__skip { background: none; border: 0; color: var(--tm-text-muted); font-size: 14px; font-weight: 500; cursor: pointer; font-family: inherit; }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__nav { display: flex; gap: var(--tm-space-2); }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__btn { display: inline-flex; align-items: center; gap: var(--tm-space-1); height: 36px; padding: 0 var(--tm-space-4); border-radius: var(--tm-radius-control); font-size: 14px; font-weight: 600; cursor: pointer; font-family: inherit; border: 1px solid var(--tm-border); background: var(--tm-surface); color: var(--tm-text-primary); transition: none; }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__btn--primary { background: var(--tm-accent-500); color: var(--tm-text-on-brand); border-color: transparent; box-shadow: none; }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__btn--primary:hover { transform: none; box-shadow: none; }

:is(.tm-ds, body.tm-ds-shell) .tm-tut__btn:disabled { opacity: .4; cursor: not-allowed; }

/* ── Adim gorseli: SVG icindeki parcalar sirayla belirir ──────────────────────
   Her adim SVG'si `data-tm-tut-svg` altinda; icindeki `[data-anim]` ogeleri
   sirayla acilir. Yalniz opacity/transform — hareket butcesine uygun. */
:is(.tm-ds, body.tm-ds-shell) .tm-tut__viz { display: flex; justify-content: center; }
:is(.tm-ds, body.tm-ds-shell) .tm-tut__viz svg { width: 100%; max-width: 320px; height: auto; }
:is(.tm-ds, body.tm-ds-shell) .tm-tut__viz [data-anim] {
  opacity: 0;
  transform: translateY(6px);
  animation: tmTutPart .45s ease forwards;
}
:is(.tm-ds, body.tm-ds-shell) .tm-tut__viz [data-anim="1"] { animation-delay: .05s; }
:is(.tm-ds, body.tm-ds-shell) .tm-tut__viz [data-anim="2"] { animation-delay: .35s; }
:is(.tm-ds, body.tm-ds-shell) .tm-tut__viz [data-anim="3"] { animation-delay: .65s; }
:is(.tm-ds, body.tm-ds-shell) .tm-tut__viz [data-anim="4"] { animation-delay: .95s; }
:is(.tm-ds, body.tm-ds-shell) .tm-tut__viz [data-anim="5"] { animation-delay: 1.25s; }
@keyframes tmTutPart { to { opacity: 1; transform: translateY(0); } }

/* Fiyatin kademe kademe inisini anlatan ok — yalniz transform. */
:is(.tm-ds, body.tm-ds-shell) .tm-tut__viz [data-anim-step] {
  animation: tmTutStepDown 2.4s ease-in-out infinite;
}
@keyframes tmTutStepDown {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(10px); }
}

/* ⛔ Hareket hassasiyeti: kullanici azaltilmis hareket istiyorsa animasyon YOK —
   ama icerik GORUNUR kalir (opacity 0'da birakmak bilgiyi yutardi). */
@media (prefers-reduced-motion: reduce) {
  :is(.tm-ds, body.tm-ds-shell) .tm-tut__viz [data-anim],
  :is(.tm-ds, body.tm-ds-shell) .tm-tut__viz [data-anim-step] {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

/* "?" yeniden-acma butonu */
:is(.tm-ds, body.tm-ds-shell) .tm-tut-reopen {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: var(--tm-radius-full);
  border: 1px solid var(--tm-border, #e4e4e7);
  background: transparent; color: var(--tm-accent-fg);
  font-weight: var(--tm-weight-semibold); font-size: var(--tm-type-caption);
  cursor: pointer; line-height: 1; flex-shrink: 0;
}
:is(.tm-ds, body.tm-ds-shell) .tm-tut-reopen:hover { background: var(--tm-accent-bg); border-color: var(--tm-accent-fg); }
:is(.tm-ds, body.tm-ds-shell) .tm-tut-reopen:focus-visible { outline: 2px solid var(--tm-accent-fg); outline-offset: 2px; }


/* ===== css/ds/ds-tooltip.css ===== */
/* Paylasilan tooltip — kirpilmayan, <body> altinda tek dugum (2026-09-18).
   Gerekce ve olcum: static/js/ds/tm-tip.js dosya basligi.
   ⚠️ `.tm-ds` KAPSAMI YOK — bilerek: dugum <body>'nin dogrudan cocugu, DS
   kapsami <main> uzerinde. Kapsasaydik kural hic eslesmezdi (bu repoda
   tekrar eden `.tm-ds` soy-secici tuzagi).
   Hareket butcesi: yalniz opacity. */
.tm-tip {
  position: fixed;
  z-index: 2400;
  max-width: 280px;
  padding: 6px 10px;
  border-radius: 8px;
  background: #0f172a;
  color: #fff;
  font-size: 12px;
  line-height: 1.45;
  font-weight: 500;
  pointer-events: none;
  opacity: 0;
  box-shadow: 0 6px 20px rgba(15, 23, 42, .28);
  white-space: normal;
  word-break: break-word;
}
.tm-tip.is-open { opacity: 1; }

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


/* ===== css/ds/ds-polish.css ===== */
/* =================================================================
   CİLA V1 — "Katmanlı derinlik" (2026-09-23)
   Kaynak: docs/ui-audit/mockups/polish-v1.css (kullanıcı onaylı, page.addStyleTag
   enjeksiyonuyla doğrulanmıştı). Bu dosya AYNI görünümü kalıcı/temiz entegre eder:
   renkler token'dan (--color-*, --tm-*, --tmv2-*, --tm-brand-*, --tm-decor-*,
   --tm-polish-* — bkz. ds-tokens.css sonu), `!important` yalnız DOM'da ÖLÇÜLEREK
   (bkz. PR raporu) gerçekten ezilen background/border/box-shadow satırlarında —
   mockup'ın kendisi aynı 3 sayfada, aynı cascade konumunda (<head> sonu) bu
   !important'lar OLMADAN uygulanamamıştı (rakip page-specific CSS'ler önceden
   var/hardcode değer taşıyor). Radius/shadow için token zaten var-fallback
   zinciriyle (.kpi-card, .ch-panel …) bağlı → o ikisi için !important YOK.

   Kapsam: base.html'i extend eden TÜM sayfalar (satıcı paneli + admin kabuğu).
   Renk/zemin kuralları YALNIZ açık temada (`html:not(.dark-mode):not([data-theme="dark"])`
   öneki) — koyu tema token'larına dokunulmadı. Sidebar İSTİSNA: her temada koyu
   (v2/components/sidebar.css §20 yorumu), bu yüzden tema-bağımsız yazıldı.
   Yükleme: base.html, ds-tooltip.css'ten hemen sonra, en son <link>. */

/* ---------- 1) Sayfa kabuğu — ışık lekeleri KALDIRILDI (2026-09-24) ----------
   Buradaki iki radyal gradyan (sol üstte menekşe, sağ üstte turuncu) sayfa
   kabuğunun zeminine iki renkli bir yıkama basıyordu. İçerikle kaplanmayan her
   boşlukta görünüyordu; en belirgin yeri Genel Bakış'ta filtre çubuğu ile KPI
   kartları arasındaki 56px'lik aralıktı — kullanıcı bunu "mavi-şeftali gradyan
   bant" olarak bildirdi ve haklıydı.

   Tasarım kararı zaten "tek ton zemin" (docs/ui-reference-spec.md, Zenith:
   akromatik nötr + tek marka rengi); tasarım raporunda "V2'nin iki renkli bandı
   yok" denmişti ama bu Cila V1 katmanı onu geri getirmişti. Kaldırıldı.

   Not: `--tm-decor-violet-soft` / `--tm-decor-orange-soft` token'ları
   ds-tokens.css'te DURUYOR; başka kullanan çıkarsa diye silinmedi, yalnız bu
   kural kaldırıldı. */

/* ---------- 2) Kart yüzeyleri — kenarlık + gölge + radius, tek kural ----------
   Radius/gölge TOKEN'dan (--tm-radius-card / --tm-card-shadow, ds-tokens.css :root
   — .kpi-card ve .ch-panel zaten `var(--tm-radius-card, 12px)` / `var(--tm-card-shadow,
   …)` fallback zinciriyle yazılı, token tanımlanınca otomatik akar, !important
   GEREKMEZ). Kenarlık rengi de token (--color-border, tema-aware). */
.kpi-card,
.ch-panel,
.tmv2-panel,
.tm-ds .tm-card,
.tmv2-page .card,
.d3-orders-section-card,
.tm-live-orders-card,
.overview-widget-panel {
  border-radius: var(--tm-radius-card);
  box-shadow: var(--tm-card-shadow) !important; /* ölçüldü: dashboard-ui-enhancements.css / dashboard-tabbed-page.css aynı sınıfa hardcode box-shadow yazıyor, cascade konumu garanti değil */
  border: 1px solid var(--color-border) !important;
  transition: box-shadow var(--tm-dur-base) var(--tm-ease), transform var(--tm-dur-base) var(--tm-ease);
}
.ch-panel:hover,
.tmv2-panel:hover,
.tm-ds .tm-card:hover,
.overview-widget-panel:hover,
.tm-live-orders-card:hover,
.d3-orders-section-card:hover {
  box-shadow: var(--tm-card-shadow-hover) !important;
}

/* ---------- 3) KPI kart — değer/etiket tipografisi ---------- */
.kpi-card .kpi-value { font-weight: 700; }
/* 2026-09-24: tipografi TÜM kartlara, renk yalnız vurgu-dışına.
   Önceden tek kural `:not(.accent)` ile yazılmıştı; dışlamanın sebebi RENKTİ
   (vurgu kartının etiketi mavi zeminde, `--tm-text-muted` okunmaz olurdu) ama
   büyük-harf/boyut/ağırlık/harf-aralığı da onunla birlikte düşüyordu. Sonuç:
   "KÂR TUTARI" büyük harfken "Ciro" başlık-düzeninde kalıyordu — kullanıcı
   bunu bildirdi. Tipografi ortak, renk ayrı. */
.kpi-card .kpi-label {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.kpi-card:not(.accent) .kpi-label {
  color: var(--tm-text-muted);
}
.kpi-card .kpi-ic { border-radius: 12px; }
/* .kpi-card.accent zaten tm-kpi.css'te token-şeklinde gradient/gölge taşıyor —
   mockup'la görsel olarak zaten örtüşüyor, buraya ayrıca yazılmadı. */

/* ---------- 4) Bölüm başlıkları ---------- */
.ch-h3,
.ch-head-l h2, .ch-head h2,
/* 2026-10-10 — TIPOGRAFI DRIFTI: 17px DS olceginde YOK (24/20/18/16/14/12/11).
   Kart basligi + panel basliklari TUM sayfalarda paylasilir; heading (16px)
   belirtecine cekildi. Olculdu: bu kural ds-primitives.css'teki dogru degeri
   eziyordu ve sayfalar arasi tek fark buydu. */
.tm-ds .tm-card__title,
.tmv2-panel h2, .tmv2-panel h3,
.d3-orders-section-card h2 {
  font-size: var(--tm-type-heading);
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--tm-text-primary);
}
.ch-sub,
.ch-head-l p,
/* 2026-10-10 — TIPOGRAFI DRIFTI: ds-primitives.css:232 bu sinifa DOGRU belirteci
   (--tm-type-caption, 12px) veriyordu; buradaki "cila" kurali onu 13px e EZIYORDU.
   Kart alt basligi TUM sayfalarda paylasilir -> tek satir hepsini hizalar. */
.tm-ds .tm-card__subtitle {
  color: var(--tm-text-muted);
  font-size: var(--tm-type-caption);
}

/* ---------- 5) Header — buzlu cam (yalnız açık tema) + marka çubuğu ---------- */
html:not(.dark-mode):not([data-theme="dark"]) header#tmv2Header.tmv2-header {
  background: var(--tm-polish-header-glass) !important;
  backdrop-filter: saturate(160%) blur(10px);
  -webkit-backdrop-filter: saturate(160%) blur(10px);
  border-bottom-color: var(--color-border) !important;
  box-shadow: var(--tm-polish-header-shadow);
}
h1.tmv2-header-title {
  position: relative;
  padding-left: 14px;
}
h1.tmv2-header-title::before {
  content: "";
  position: absolute;
  left: 0; top: 4px; bottom: 4px;
  width: 4px;
  border-radius: 4px;
  background: linear-gradient(180deg, var(--color-primary), var(--color-secondary));
}
/* 2026-10-07 — KALDIRILDI (çift çerçeve kusuru, bkz. tm-header-v2.css #tmHeaderSearchInput
   yorumu): bu iki kural `.tmv2-search__input`'a 999px/40px'lik kendi kapsülünü ve
   açık temada ayrı bir arka plan/kenarlık rengini veriyordu — dış `.tmv2-search`
   pill'i (ds-shell.css "one control, no pill" — 34px, control-radius, tek kenarlık)
   zaten tam kontrolü sağlıyor; input'un kendi şekli/zemini olunca pill'in İÇİNDE
   daha uzun, farklı renkli ikinci bir kapsül görünüyordu (kullanıcı ekran görüntüsü,
   2026-10-06). Giderme tek otoriteye taşındı: tm-header-v2.css. */

/* ---------- 6) Sidebar — BU DOSYADAN KALDIRILDI (2026-10-08) ----------
   Burada `--tmv2-sidebar-bg`, `background-color: #0f1622`,
   `--tmv2-nav-active-bg` ve `.tmv2-nav-section-label { color … !important }`
   yeniden tanımlanıyordu. ds-polish.css kaskadın SONUNDA yüklendiği için
   kanonik sol ray dosyasını (v2/components/sidebar.css) sessizce eziyordu.

   Bu, "aynı ray üç farklı zemin veriyor" kusurunun DÖRDÜNCÜ kaynağıydı ve
   ölçmeden görünmüyordu: kanonik dosya #031538 yazıyor, çizilen renk
   #0f1622 çıkıyordu. (Diğer üçü: ds-shell.css, tm-shell-v2.css,
   tm-v2-reference-chrome.css — hepsi aynı gün temizlendi.)

   🔒 Sol ray'e dair HİÇBİR kural buraya geri eklenmez; tek kaynak
      static/css/v2/components/sidebar.css.
   ------------------------------------------------------------------ */

/* ---------- 7) Butonlar — tek marka gradyanı ---------- */
.btn--primary, .btn-primary, .tm-btn--primary, .btn.btn-primary, a.btn.btn-primary {
  background: linear-gradient(180deg, var(--tm-brand-400), var(--color-primary)) !important;
  border-color: var(--tm-brand-700) !important;
  border-radius: 12px;
}
.btn--primary:hover, .btn-primary:hover:not(:disabled), a.btn.btn-primary:hover {
  background: linear-gradient(180deg, var(--color-primary), var(--tm-brand-700)) !important;
}
html:not(.dark-mode):not([data-theme="dark"]) .btn--secondary,
html:not(.dark-mode):not([data-theme="dark"]) .btn--ghost {
  background: var(--color-surface) !important;
  border-color: var(--color-border) !important;
  color: var(--tm-text-secondary) !important;
}

/* ---------- 8) Tablo başlığı + zebra (yalnız açık tema) ---------- */
html:not(.dark-mode):not([data-theme="dark"]) .tm-ds .tm-table thead th,
html:not(.dark-mode):not([data-theme="dark"]) table thead th {
  background: var(--tmv2-surface-3) !important;
  color: var(--tm-text-muted) !important;
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
}
html:not(.dark-mode):not([data-theme="dark"]) .tm-ds .tm-table tbody tr:nth-child(even) > td {
  background: var(--tmv2-surface-2);
}

/* ---------- 9) Sipariş kartı (yalnız açık tema) ---------- */
html:not(.dark-mode):not([data-theme="dark"]) .order-card {
  border: 1px solid var(--tm-border-light) !important;
  border-radius: 12px;
  background: var(--color-surface) !important;
}
html:not(.dark-mode):not([data-theme="dark"]) .order-card:hover {
  border-color: var(--tm-border-dark) !important;
  box-shadow: var(--tm-card-shadow) !important;
}

/* ---------- 10) Form alanları ---------- */
.form-control, .form-select {
  height: 44px;
  border-radius: 12px;
}
html:not(.dark-mode):not([data-theme="dark"]) .form-control,
html:not(.dark-mode):not([data-theme="dark"]) .form-select {
  border-color: var(--color-border) !important;
  background: var(--tmv2-surface-2) !important;
}
html:not(.dark-mode):not([data-theme="dark"]) .form-control:focus,
html:not(.dark-mode):not([data-theme="dark"]) .form-select:focus {
  border-color: var(--color-primary) !important;
  box-shadow: var(--tmv2-form-focus-shadow) !important;
  background: var(--color-surface) !important;
}

/* ---------- 11) Demo bandı — sakin ton (yalnız açık tema; koyu zaten ayrı
   tanımlı, bkz. demo-banner.css `html.dark-mode .tm-demo-banner`) ---------- */
html:not(.dark-mode):not([data-theme="dark"]) .tm-demo-banner {
  background: linear-gradient(90deg, var(--tm-polish-demo-bg-from), var(--tm-polish-demo-bg-to)) !important;
  border-bottom-color: var(--tm-polish-demo-border) !important;
}

/* ---------- 12) tm-kpi.css `--kpi-*` namespace — yalnız html.dark-mode'da
   canonical token'a bağlıydı (dark-mode-component-overrides-2026-06-11.css);
   açık temada da aynı bağ kurulur ki #e7ebf1/#94a3b8 (eski, AA-altı) yerine
   güncel --color-border / --tm-text-muted okunur. ---------- */
html:not(.dark-mode):not([data-theme="dark"]) {
  --kpi-line: var(--color-border);
  --kpi-line-strong: var(--tm-border-light);
  --kpi-mute: var(--tm-text-muted);
}

/* ═══ CONTAINER ARALIĞI — TEK DEĞER (kullanıcı kararı 2026-09-23: "container'lar arası boşluk azaltılmalı ve
   her sayfada standart olmalı"). Ölçüm (tests/e2e/ui-audit/gap_probe.cjs, 60 panel sayfası @1280): 19 farklı
   aralık (0…90px) — kaynak sayfa-özel .mb-3/.mb-4, flex row-gap ve inline margin karışımı. Kural: sayfanın
   üst-seviye yığın kabında çocukların dikey margin'i sıfır, kardeşler arası 16px; flex/grid kaplarda row-gap
   sıfırlanır ki 16 + gap toplanmasın. Kap listesi ölçümden (gap-probe JSON `stack`). Sonuç: gap_probe ile
   yeniden ölçülür; hedef histogram tek değer (16). */
#mainContent.tmv2-page :where(.tmv2-dashboard, .rp-wrap, .admin-page-container, .x-wrap, .xa-wrap, .hc-wrap, .tm-page,
  .w-full.container, .account-container-wrapper, .subscription-container-wrapper, .integration-container-wrapper,
  .wr-page__inner, .app-container.kom-shell, .tm-fin, .he-page, .promo-page, .my-info-page, .notif-page-wrapper,
  .order-profit-page, .pd-wrap, .tm-page-wrap, .tmv2p.container-fluid, .account-main-inner, .page-stack, .xmlv2.cpk,
  .tm-stack, .en-wrap, .integration-container, .tmv2-page-body, .tmv2-page-body > .container-fluid) {
  row-gap: 0 !important;
}
#mainContent.tmv2-page :where(.tmv2-dashboard, .rp-wrap, .admin-page-container, .x-wrap, .xa-wrap, .hc-wrap, .tm-page,
  .w-full.container, .account-container-wrapper, .subscription-container-wrapper, .integration-container-wrapper,
  .wr-page__inner, .app-container.kom-shell, .tm-fin, .he-page, .promo-page, .my-info-page, .notif-page-wrapper,
  .order-profit-page, .pd-wrap, .tm-page-wrap, .tmv2p.container-fluid, .account-main-inner, .page-stack, .xmlv2.cpk,
  .tm-stack, .en-wrap, .integration-container, .tmv2-page-body, .tmv2-page-body > .container-fluid) > :not(script):not(style):not(template) {
  margin-top: 0 !important; margin-bottom: 0 !important;
}
#mainContent.tmv2-page :where(.tmv2-dashboard, .rp-wrap, .admin-page-container, .x-wrap, .xa-wrap, .hc-wrap, .tm-page,
  .w-full.container, .account-container-wrapper, .subscription-container-wrapper, .integration-container-wrapper,
  .wr-page__inner, .app-container.kom-shell, .tm-fin, .he-page, .promo-page, .my-info-page, .notif-page-wrapper,
  .order-profit-page, .pd-wrap, .tm-page-wrap, .tmv2p.container-fluid, .account-main-inner, .page-stack, .xmlv2.cpk,
  .tm-stack, .en-wrap, .integration-container, .tmv2-page-body, .tmv2-page-body > .container-fluid) > :not(script):not(style):not(template) ~ :not(script):not(style):not(template) {
  margin-top: var(--tm-section-gap, 16px) !important;
}
/* Demo bandı ≥1024: tek satır (metin ellipsis), iki CTA + X aynı satırda */
@media (min-width: 1024px) {
  .tm-demo-banner { flex-wrap: nowrap !important; }
  .tm-demo-banner__text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}

/* 2026-09-23 (responsive kalibrasyon): rapor sayfalarındaki segment düğmeleri (.rp-seg) 320px'te satırdan taşıyordu
   (ölçüldü: warnings@320 right 336 > 320, kaydırılabilir ata yok). Dar ekranda sarar. */
@media (max-width: 480px) {
  #mainContent.tmv2-page .rp-seg { flex-wrap: wrap; }
}

/* 2026-09-23 (responsive kalibrasyon, 320-414px, ölçüldü): (a) advantage-analysis .header-tool-card nowrap flex 380px >
   286px kap; (b) product-qa-settings .admin-header-right nowrap; (c) campaign-analysis boş-durum hücresi 534px genişlikte
   tablo — dar ekranda tablo kaydırılabilir blok olur (kaydırılabilir ata = erişilebilir). */
@media (max-width: 480px) {
  #mainContent.tmv2-page .header-tool-card { flex-wrap: wrap; }
  #mainContent.tmv2-page .header-tool-card > * { min-width: 0; flex: 1 1 100%; }
  #mainContent.tmv2-page .admin-header-right { flex-wrap: wrap; }
  #mainContent.tmv2-page .en-ops__group { flex-wrap: wrap; }   /* product-settings @320/375: #xmlUploadBtn 399 > 375 (2026-09-24) */
  /* (c) tablo kuralı KALDIRILDI (2026-09-24 ön-merge kontrolü): display:block tabloyu kendi sarmalayıcısında 252px'e kırpıp
     overflow-x'i etkisiz bırakıyordu; campaign-analysis'te .overflow-x-auto sarmalayıcı zaten var. */
}

/* 2026-09-24 (campaign-analysis@320): Tailwind kaydırma sarmalayıcısı içindeki tablo kendi overflow'unu kırpıyordu (table ovx=hidden,
   sarmalayıcı sw=cw) → içerik ulaşılamıyordu. Tablo taşsın, sarmalayıcı kaydırsın. */
@media (max-width: 480px) {
  #mainContent.tmv2-page .overflow-x-auto > table { overflow: visible !important; }
}

/* ---------- Genel Bakış: KPI üstü boşluk tek 16px (2026-09-24) ----------
   Ölçüldü (1280): sticky filtre çubuğunun altı 235px, KPI ızgarasının üstü
   291px → 56px. Üç ayrı aralık üst üste biniyordu:
     · #overviewTab      margin-top 16px  (`--tm-section-gap`, !important)
     · #overviewPage     padding-top 24px (`.tm-ds .tm-page`, --tm-space-6)
     · #tmOverviewKpiGrid margin-top 16px (aynı section-gap kuralı)
   Diğer panel sayfalarındaki global container aralığı 16px; sekme kabındaki
   16'yı TEK kaynak olarak bırakıp diğer ikisini sıfırlıyoruz. `!important`
   zorunlu: section-gap kuralı da !important ile geliyor (üslup değil, ölçüm). */
.tm-ds #overviewPage.tm-page { padding-top: 0; }
#mainContent.tmv2-page #tmOverviewKpiGrid { margin-top: 0 !important; }

