tamga-ui 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/dist/components/appearance.d.ts +78 -0
  3. package/dist/components/appearance.d.ts.map +1 -0
  4. package/dist/components/appearance.js +73 -0
  5. package/dist/components/chrome.d.ts +11 -1
  6. package/dist/components/chrome.d.ts.map +1 -1
  7. package/dist/components/chrome.js +19 -6
  8. package/dist/components/error-state.d.ts +7 -14
  9. package/dist/components/error-state.d.ts.map +1 -1
  10. package/dist/components/overlay.d.ts +7 -16
  11. package/dist/components/overlay.d.ts.map +1 -1
  12. package/dist/components/primitives.d.ts +7 -16
  13. package/dist/components/primitives.d.ts.map +1 -1
  14. package/dist/components/rail-link.d.ts +22 -2
  15. package/dist/components/rail-link.d.ts.map +1 -1
  16. package/dist/components/rail-link.js +12 -9
  17. package/dist/components/square-picker.d.ts +41 -0
  18. package/dist/components/square-picker.d.ts.map +1 -0
  19. package/dist/components/square-picker.js +90 -0
  20. package/dist/index.d.ts +3 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +3 -0
  23. package/dist/kit.css +237 -729
  24. package/dist/lib/color.d.ts +0 -20
  25. package/dist/lib/color.d.ts.map +1 -1
  26. package/dist/lib/color.js +0 -22
  27. package/dist/lib/image.d.ts +46 -0
  28. package/dist/lib/image.d.ts.map +1 -0
  29. package/dist/lib/image.js +95 -0
  30. package/dist/lib/palette.d.ts +0 -16
  31. package/dist/lib/palette.d.ts.map +1 -1
  32. package/dist/lib/palette.js +0 -12
  33. package/dist/patterns/app-shell.d.ts.map +1 -1
  34. package/dist/patterns/app-shell.js +2 -12
  35. package/dist/patterns/appearance-template.d.ts +105 -0
  36. package/dist/patterns/appearance-template.d.ts.map +1 -0
  37. package/dist/patterns/appearance-template.js +23 -0
  38. package/dist/patterns/index.d.ts +1 -0
  39. package/dist/patterns/index.d.ts.map +1 -1
  40. package/dist/patterns/index.js +1 -0
  41. package/dist/patterns/settings-template.d.ts +12 -1
  42. package/dist/patterns/settings-template.d.ts.map +1 -1
  43. package/dist/patterns/settings-template.js +2 -2
  44. package/dist/patterns/shared.d.ts +1 -1
  45. package/dist/patterns/shared.d.ts.map +1 -1
  46. package/dist/styles.css +1 -3
  47. package/dist/theme.css +127 -483
  48. package/package.json +4 -1
package/dist/kit.css CHANGED
@@ -1,222 +1,91 @@
1
- /* ==============================================================
2
- tamga-ui · KİT
3
-
4
- Bileşen sınıfları ve fizik. Saf CSS — Tailwind direktifi yok,
5
- Tailwind'i olmayan bir projede de çalışır.
6
-
7
- Token'lar theme.css'te. Bu dosya yalnız onları tüketir.
8
- ============================================================== */
9
-
10
- /* ==============================================================
11
- THE KIT.
12
-
13
- This was an isolated island (`.taslak`) while it was a reference. It is not a reference any more
14
- — it is the product's kit, so the scoping came off: `tamga-*` is global, the tokens sit in the same
15
- @theme as everything else, and the base layer styles the document rather than a wrapper div.
16
-
17
- What that replaced: a second, shadcn-derived kit under components/ui with twelve components
18
- duplicated by name. Two kits meant two answers to "what does a button look like", and Storybook
19
- showed both. One kit now.
20
- ============================================================== */
21
-
22
- /* ------------------------------------------------------------------ *
23
- * Measurements that are NOT on the spacing scale, and why.
24
- *
25
- * check-scale forbids invented bracket values and prescribes exactly this escape: name the value
26
- * next to the tokens with the reason, then use the `var()` form at the call site. Each of these is
27
- * a mechanic, not a spacing choice — rounding it to a 4px step would break the thing it measures.
28
- * ------------------------------------------------------------------ */
29
- /* tamga:sabit-kit — kitin kendi yapısal ölçüleri; temaya bağlı değil. */
1
+ /*! tamga-ui 0.3.0 · MIT · https://tamga.org.tr */
30
2
  :root {
31
- /* The gap an overlay floats above its trigger. 8px, so the offset shadow (2px) clears the edge
32
- with room to read as detached rather than stuck.
33
- TR: Bir katmanın tetikleyicisinin üstünde durduğu boşluk. 8px, yani 2px'lik kaydırma
34
- gölgesi kenarı yapışık değil ayrık okunacak kadar rahat geçiyor. */
3
+
35
4
  --overlay-gap: 8px;
36
- /* The whole computed offset, not just the gap: check-scale accepts a token reference, and a
37
- token that still needs arithmetic at the call site is half a token.
38
- TR: Yalnız boşluk değil hesaplanmış kaydırmanın tamamı: check-scale bir token
39
- referansını kabul ediyor, ve çağrı yerinde hâlâ aritmetik isteyen bir token yarım
40
- token. */
5
+
41
6
  --overlay-below: calc(100% + var(--overlay-gap));
42
7
  --overlay-above: calc(100% + var(--overlay-gap));
43
- /* The dial's band label sits just under the ring's baseline. Negative and tiny: a position, not
44
- a spacing step.
45
- TR: Kadranın bant etiketi halkanın taban çizgisinin hemen altında duruyor. Negatif
46
- ve çok küçük: bir boşluk adımı değil bir konum. */
8
+
47
9
  --dial-label-drop: -4px;
48
- /* Room a raised object needs BESIDE itself so its 2px offset is not clipped by the parent's
49
- overflow. 3px, one more than the offset, which is the clipping trap in §2.
50
- TR: Yükseltilmiş bir nesnenin, 2px'lik kaydırması üst öğenin taşmasıyla kırpılmasın
51
- diye YANINDA ihtiyaç duyduğu yer. 3px, kaydırmadan bir fazla; §2'deki kırpılma
52
- tuzağı tam olarak bu. */
10
+
53
11
  --offset-room: 3px;
54
- /* The instrument marks: a 2px tick and a 6px dot. Below the spacing scale on purpose: these are
55
- read as marks, not as boxes, and 4px is already too heavy for a dial tick.
56
- TR: Gösterge işaretleri: 2px'lik bir çentik ve 6px'lik bir nokta. Boşluk ölçeğinin
57
- altında, bilerek: bunlar kutu değil işaret olarak okunuyor, ve 4px bir kadran
58
- çentiği için şimdiden ağır. */
12
+
59
13
  --mark-tick: 2px;
60
14
  --mark-dot: 6px;
61
15
 
62
- /* Adım işaretinin karesi ve iki adımı bağlayan çizginin uzunluğu. Bir ölçek
63
- adımı değil: işaret, iki haneli bir sayı ile bir çentik glifinin İKİSİNİ
64
- birden tutması gereken en küçük kare. Sabit olması şart, çünkü adım
65
- tamamlandığında büyüyen bir işaret şeridin tamamını kaydırıyor.
66
- TR: Adım işaretinin karesi ve iki adımı bağlayan çizginin uzunluğu. Bir
67
- ölçek adımı değil: iki haneli bir sayıyı da çentik glifini de tutabilen en
68
- küçük kare. Sabit olmak zorunda, yoksa tamamlanan adım şeridi kaydırıyor. */
69
16
  --step-mark: 24px;
70
17
  --step-line: 28px;
71
- /* Smallest radius in the system: the checkbox tick and the skeleton block. --radius-ctl (4px)
72
- reads as a control; these are neither.
73
- TR: Sistemdeki en küçük yarıçap: onay kutusunun çentiği ve iskelet bloğu.
74
- --radius-ctl (4px) bir kontrol gibi okunuyor; bunların ikisi de kontrol değil. */
18
+
75
19
  --radius-mark: 3px;
76
- /* The ceiling for a wide dialog. Not a scale step but a LIMIT: a preview
77
- should be able to take the whole screen and still not grow without end,
78
- because at 2000px a list stops being readable. 3rem is the shell's own
79
- margin.
80
- TR: Geniş diyaloğun tavanı. Bir ölçek adımı değil bir SINIR: bir önizleme ekranın
81
- tamamını alabilmeli ama sonsuz da genişlememeli, çünkü 2000 pikselde bir liste artık
82
- okunmuyor. 3rem, kabuğun kendi kenar boşluğu. */
20
+
83
21
  --dialog-wide: min(96rem, calc(100vw - 3rem));
84
22
 
85
- /* Where a dense table stops shrinking and starts scrolling. Content-driven, not a scale step:
86
- it is the width at which the narrowest column stops being readable.
87
- TR: Sık bir tablonun küçülmeyi bırakıp kaydırmaya başladığı yer. Bir ölçek adımı
88
- değil içerikten gelen bir sayı: en dar sütunun okunmaz olduğu genişlik. */
89
23
  --table-min: 720px;
90
24
  --table-min-wide: 980px;
91
25
  --table-min-widest: 1080px;
92
26
  }
93
27
 
94
- /* tamga:kit-koyu */
95
28
  .dark {
96
29
 
97
30
  color-scheme: dark;
98
31
 
99
- /* The neutral ramp is tinted toward the accent hue, specified in LCh — never
100
- in HSL, and never by copying another product's numbers. Two earlier attempts
101
- failed and both failures are the reason this comment is long.
102
-
103
- 1st: matched Sentry's HSL saturation (14%). HSL S is not perceptual chroma —
104
- at identical S and L, violet at 258° carries ~1.4x the real chroma of blue.
105
- Matching their number guaranteed a weaker tint. The ramp read grey.
106
-
107
- 2nd: rebuilt in LCh at hue 277° with raised chroma. Still grey, for a worse
108
- reason: 277° is the middle of the Tailwind slate band (271–283°), and the
109
- chroma sat under slate's own (slate-900 is C* 14.45). A colour inside that
110
- hue band and below that chroma IS the industry-default dark grey. Raising
111
- chroma alone had only made it a more saturated slate.
112
-
113
- What actually makes a tint read as a tint is hue distance from the neutral
114
- band, not chroma. Sentry gets away with LOW chroma (5.5–12.7) because its
115
- hue sits at 299–304° — about 20° clear of slate, where nothing generic
116
- lives. Our blue does not have that luxury: blue IS the neutral band.
117
-
118
- So: hue 291°, the true LCh hue of our own primary #12245c, which clears
119
- slate's edge — and chroma pushed past slate's 14.45 to cover the fact that
120
- we clear it by 8° where Sentry clears it by 20°. Exceeding Sentry's chroma
121
- is not an inconsistency; it is what equal perception costs on a blue axis.
122
- L* is pinned exactly where it already sat, so the ramp gains colour without
123
- moving a single contrast value.
124
- L* 5.9 -> C* 16 L* 19.9 -> C* 26 L* 85.1 -> C* 6.0
125
- L* 9.3 -> C* 19 L* 27.9 -> C* 31 L* 94.4 -> C* 2.8
126
- L* 14.2 -> C* 22 L* 61.9 -> C* 11
127
- Light stays warm paper on purpose: paper by day, instrument screen by night,
128
- and a cool ground makes the warm status colours separate harder. */
129
32
  --color-page: #0f1127;
130
- /* A raised surface: cards, overlays, popovers. It is barely lighter than the
131
- page on purpose; the edge does the lifting. */
33
+
132
34
  --color-shell: #131832;
133
- /* A row under the pointer, and a selected row's neutral wash. Same value as
134
- sunk, different job. */
35
+
135
36
  --color-hover: #1c2241;
136
- /* Rail and band ARE the page in both themes — a 1px line does the dividing,
137
- never a fill. Dark briefly had them 1.9 ΔL* off the page: too small to read
138
- as a surface, too large to be the same one. */
37
+
139
38
  --color-band: #0f1127;
140
- /* The navigation rail. Also the page: a sidebar that fills itself becomes a
141
- second surface competing with the content. */
39
+
142
40
  --color-rail: #0f1127;
143
- /* Content that sits IN the page rather than on it: filter bars, table
144
- headers, code blocks, sub-panels. */
41
+
145
42
  --color-sunk: #1c2241;
146
43
  --color-line: #262d54;
147
44
  --color-edge: #363e6e;
148
45
  --color-chart-fill: #1c2241;
149
46
  --color-ink-faint: #9494a8;
150
- /* The second weight: labels, secondary rows, anything that supports the
151
- heading without competing with it. */
47
+
152
48
  --color-ink-soft: #d4d4df;
153
- /* The heaviest weight: headings, table values, anything the eye should land
154
- on first. */
49
+
155
50
  --color-ink: #efeef4;
156
51
 
157
- /* Dark inverts the face, and it has to. The rule across both themes is that
158
- the FACE is the layer furthest from the ground and the BASE is the brand
159
- navy. Light's ground is paper, so the face goes mid-dark and carries white
160
- ink. Dark's ground is near-black, and there white ink is what kills the
161
- press: it caps the fill at L* 47, while the base has to reach L* 26 just to
162
- separate from the page — leaving at most 21 ΔL* between the two layers,
163
- less than light already has. Dark ink lifts that ceiling, the face goes to
164
- L* 66, and the layers separate by 50. Hue sits at 272° rather than light's
165
- 284° to stay plainly blue at high lightness, where 284° starts to read
166
- periwinkle. */
167
52
  --color-accent: #53a4fa;
168
- --color-accent-hover: #78b4ff; /* lightens here — dark ink wants it brighter */
53
+ --color-accent-hover: #78b4ff;
169
54
  --color-accent-active: #4097eb;
170
- --color-accent-ink: #12245c; /* navy ink on the bright face — 5.62:1 */
55
+ --color-accent-ink: #12245c;
171
56
  --color-accent-line: #86a7f3;
172
- /* Must out-chroma the neutral hover it sits next to. At the old C* 16.3 it
173
- fell UNDER hover's C* 22, so a selected row read duller than a hovered one. */
57
+
174
58
  --color-accent-bg: #0f2458;
175
- /* The brand navy LIFTED, and the lift is the whole point. A base has to clear
176
- two things at once — the face above it and the ground behind it — and light
177
- manages both without help (79 ΔL* off the paper, 29 off the face). Dropped
178
- into dark unchanged, #12245c clears the face by 50 but the page by only 10,
179
- so it sinks into the page and the button loses its base entirely. Being
180
- bright next to the face is not enough; it also has to be visibly NOT the
181
- page. L* 30 buys 24 off the page and still leaves 36 off the face. */
59
+
182
60
  --color-accent-shadow: #344479;
183
61
 
184
- /* Status stays warm against the cool ground — deviation separates harder. */
185
62
  --color-critical: #ff9478;
186
- /* The wash behind a critical chip or row. A tint, not a fill: it carries no
187
- text of its own. */
63
+
188
64
  --color-critical-bg: #331a12;
189
- /* Not broken yet, but heading there. A threshold crossed, a queue growing, a
190
- stock running low. */
65
+
191
66
  --color-warn: #e8ab3c;
192
- /* The wash behind a warning chip or row. */
67
+
193
68
  --color-warn-bg: #33260f;
194
- /* Healthy, and also resolved. One green for both, because a reader should
195
- not have to learn two. */
69
+
196
70
  --color-resolved: #4fd4ac;
197
- /* The wash behind a healthy or resolved chip. */
71
+
198
72
  --color-resolved-bg: #0f2a22;
199
73
  --color-silent: #9494a8;
200
74
  --color-tick: #3f4880;
201
75
  --color-chart-1: #ada072;
202
- /* Teal, the second series. Far enough from resolved's green that a line is
203
- never mistaken for a status. */
76
+
204
77
  --color-chart-2: #5badaf;
205
- /* Blue, the third series. */
78
+
206
79
  --color-chart-3: #6ea7cc;
207
- /* Violet, the fourth series. */
80
+
208
81
  --color-chart-4: #a49ac9;
209
- /* Rose, the fifth and last. Beyond five the eye stops telling series apart
210
- and a legend stops helping. */
82
+
211
83
  --color-chart-5: #ca90a9;
212
84
 
213
- /* Same LCh treatment — these echo ramp steps and must not drift off the axis. */
214
85
  --color-nav-idle: #89899d;
215
- /* A rail item under the pointer. Darker than idle in light, brighter in
216
- dark: the label steps toward the reader. */
86
+
217
87
  --color-nav-hover: #d4d4df;
218
- /* The wash behind a hovered rail item. The current item takes an outline
219
- instead, never this fill. */
88
+
220
89
  --color-nav-hover-bg: #1c2241;
221
90
  --color-scrim: rgba(6, 6, 22, 0.62);
222
91
  }
@@ -225,14 +94,7 @@
225
94
 
226
95
  body {
227
96
  background: var(--color-shell);
228
- /* PUNTO DA BURADA, ve uzun süre değildi.
229
- Kit `--text-body: 13px`i "THE default: rows, cells, body copy" diye
230
- tanımlıyordu ama hiçbir yer onu BODY'ye uygulamıyordu. Sonuç: sınıfı
231
- olan her metin ölçekte, sınıfı olmayan her metin tarayıcının 16px'inde,
232
- yani aynı ekranda iki ayrı ölçek. Doküman sitesinde görünmedi çünkü o
233
- kendi okuma ölçeğini yazıyor; bir tüketici panelinde tablo hücreleri %23
234
- büyük çıktı ve fark oradan yakalandı.
235
- Tüketici kendi ölçeğini isterse yine yazabilir; bu bir varsayılan. */
97
+
236
98
  font-size: var(--text-body);
237
99
  line-height: 1.5;
238
100
  font-variant-numeric: tabular-nums;
@@ -256,7 +118,7 @@
256
118
  *::-webkit-scrollbar-track {
257
119
  background: transparent;
258
120
  }
259
- /* native checkboxes are restyled so tables and the kit look identical */
121
+
260
122
  input[type="checkbox"] {
261
123
  appearance: none;
262
124
  -webkit-appearance: none;
@@ -307,27 +169,15 @@
307
169
 
308
170
  @layer components {
309
171
 
310
- /* ---------- structure ---------- */
311
-
312
- /* the one left line every page shares */
313
172
  .tamga-gutter {
314
173
  padding-left: var(--gutter);
315
174
  padding-right: var(--gutter);
316
175
  }
317
176
 
318
- /* a full-bleed rule, still used for page bands and inside cards */
319
177
  .tamga-section {
320
178
  border-bottom: 1px solid var(--color-line);
321
179
  }
322
180
 
323
- /* a card is a button that grew: same 1px edge, same soft 2px offset */
324
- /* The working surface: one card that holds a whole screen.
325
- The chrome around it — rail, header, ground — is all --color-page and has
326
- no dividing line, so it reads as one continuous frame. This is the only
327
- thing on top of that frame, which is why it takes the control radius
328
- rather than the card radius: at this size the sharper corner keeps it
329
- reading as a plane, and it stays in the same family as the buttons inside
330
- it. A softer corner here would make the whole screen look like a widget. */
331
181
  .tamga-surface {
332
182
  background: var(--color-page);
333
183
  border: 1px solid var(--color-edge);
@@ -341,26 +191,15 @@
341
191
  box-shadow: 2px 2px 0 var(--color-edge);
342
192
  overflow: hidden;
343
193
  }
344
- /* Kırpmayı kapatan kaçış yolu.
345
194
 
346
- `.tamga-card`'ın `overflow: hidden`'ı tabloların köşe yuvarlaması için
347
- gerekli — ve aynı satır, kartın İÇİNDE açılan her paneli kesiyor:
348
- bir Combobox listesi, bir DatePicker takvimi, bir satır menüsü. Panel
349
- çalışıyor, tıklanıyor, ama yarısı görünmüyor. Z-index bunu çözmez;
350
- hiçbir yığın sırası bir `overflow` kırpmasını aşamaz.
351
-
352
- `CellActions` aynı tuzağın tablo hücresi karşılığıydı ve ayrı çözülmüştü;
353
- bu, kart seviyesindeki hâli. */
354
195
  .tamga-card-open {
355
196
  overflow: visible;
356
197
  }
357
198
 
358
- /* a second column, opened by one full-height rule */
359
199
  .tamga-col {
360
200
  border-left: 1px solid var(--color-line);
361
201
  }
362
202
 
363
- /* section heading sits on the gutter with no box of its own */
364
203
  .tamga-head {
365
204
  display: flex;
366
205
  flex-wrap: wrap;
@@ -371,32 +210,12 @@
371
210
  padding-bottom: 8px;
372
211
  }
373
212
 
374
- /* rail item: outlined and lifted when active — never a solid fill */
375
- /*
376
- * KAYAN BİR RAY, YÜKSELEN BİR KONTROLÜ KIRPAR.
377
- *
378
- * Ölçülen hata: menüsü uzun olan bir kenar çubuğunda `overflow-y: auto`
379
- * gerekiyor, ama CSS bir eksende `visible` dışında bir değer görünce ÖTEKİ
380
- * ekseni de `auto`ya çeviriyor. Yani dikey kaydırma isteyen bir kap yatayda
381
- * da kırpıyor, ve seçili ray girişinin 2px sert kaydırması tam kenarda
382
- * kesiliyor: düğme sağdan ve alttan eksik görünüyor. Hover'da kaydırma 3px'e
383
- * çıkıyor, basılınca yer değiştiriyor — üçü de kırpılıyor.
384
- *
385
- * Çözüm z-index DEĞİL: hiçbir yığın sırası bir `overflow` kırpmasını aşmaz.
386
- * Kaydırmanın sığacağı yer AÇILIYOR (`--offset-room`, kaydırmadan bir fazla).
387
- */
388
213
  .tamga-rail-scroll {
389
214
  min-height: 0;
390
215
  overflow-y: auto;
391
- /* DÖRT YANDAN DA YER, yalnız sağ ve alttan değil.
392
- İlk hâli kaydırma gölgesini (sağ+alt) düşünüp hover'ı unutmuştu: seçili
393
- giriş hover'da `translate(-1px, -1px)` ile YUKARI ve SOLA kayıyor, ve
394
- sol kenarda yer olmadığı için oradan kesiliyordu. Simetrik dolgu ayrıca
395
- ikinci bir şeyi düzeltiyor: dar rayda `items-center` artık gerçekten
396
- ortalıyor — tek yönlü dolgu ikonları 1.5 piksel sola çekiyordu. */
216
+
397
217
  padding: var(--offset-room);
398
- /* Kaydırma çubuğu gizli: ray dar ve bir çubuk orada ikonların yerini
399
- daraltıyor. Kaydırma yine çalışıyor. */
218
+
400
219
  scrollbar-width: none;
401
220
  }
402
221
  .tamga-rail-scroll::-webkit-scrollbar {
@@ -417,10 +236,7 @@
417
236
  transition: color var(--duration-press) var(--ease-standard), background var(--duration-press) var(--ease-standard), border-color var(--duration-press) var(--ease-standard),
418
237
  box-shadow var(--duration-press) var(--ease-standard), transform var(--duration-press) var(--ease-standard);
419
238
  }
420
- /* ETİKETLİ HÂLİ. Aynı kontrolün ikinci genişliği, ayrı bir bileşen değil:
421
- dar ray yalnız ikon taşır, geniş kenar çubuğu ikonun yanına etiketi açar.
422
- İkiye bölünseydi hover, seçili ve odak fizikleri iki yerde yaşardı ve
423
- zamanla ayrışırdı. */
239
+
424
240
  .tamga-rail-link-wide {
425
241
  width: 100%;
426
242
  justify-content: flex-start;
@@ -448,20 +264,6 @@
448
264
  box-shadow: 0 0 0 var(--color-accent-line);
449
265
  }
450
266
 
451
- /* ------------------------------------------------------------------ *
452
- * Press snaps, release eases.
453
- *
454
- * Both directions used the same 100ms ease, and on a trackpad TAP that meant the press was never
455
- * seen: `:active` lasts about 10–40ms on a tap, so the control got a third of the way down and
456
- * turned round. Holding a physical click gives it the full 100ms, which is why the same button
457
- * felt right under a click and dead under a tap.
458
- *
459
- * So the press is instant and only the RETURN is animated. Even a 15ms tap now bottoms the
460
- * control out completely, and the 100ms float back is the part the eye actually reads as a
461
- * click — perception needs the movement, not the dwell.
462
- *
463
- * Only the duration changes. Travel, shadow and colour are untouched.
464
- * ------------------------------------------------------------------ */
465
267
  .tamga-btn:not(:disabled):active,
466
268
  .tamga-icon-btn:not(:disabled):active,
467
269
  .tamga-mini-btn:not(:disabled):active,
@@ -471,24 +273,6 @@
471
273
  transition-duration: 0s;
472
274
  }
473
275
 
474
- /* ------------------------------------------------------------------ *
475
- * The press-travel hit fix.
476
- *
477
- * A raised control moves down-right when pressed — hover sits at −1,−1 and active at +2,+2 (the
478
- * primary goes to +3,+3), so the box travels 3–4px out from under the pointer. A transform moves
479
- * the HIT AREA with it, so a pointer resting within that band along the top or left edge ends up
480
- * over the parent by the time the button comes up. `mousedown` lands on the button, `mouseup`
481
- * lands on its container, and a `click` event is never born — the control simply does nothing.
482
- *
483
- * It shows up on a trackpad TAP far more than on a physical click: a tap has no dwell time and
484
- * the finger drifts a pixel or two, while a real click holds the pointer still while the box
485
- * moves. Same defect, different odds — which is exactly why it read as "tap is broken".
486
- *
487
- * The fix is a hit extender that reaches back up and left by the travel distance. It rides along
488
- * with the transform, so once the control has moved it covers precisely the ground the control
489
- * left behind. It only ever grows up and left, never down or right, so it cannot reach into the
490
- * next control in a row or a column.
491
- * ------------------------------------------------------------------ */
492
276
  .tamga-btn,
493
277
  .tamga-icon-btn,
494
278
  .tamga-mini-btn,
@@ -501,15 +285,11 @@
501
285
  .tamga-rail-link::after {
502
286
  content: "";
503
287
  position: absolute;
504
- /* 4px covers the deepest travel in the kit (the primary's +3 from a −1 hover). */
288
+
505
289
  inset: -4px 0 0 -4px;
506
290
  border-radius: inherit;
507
291
  }
508
292
 
509
- /* ---------- raised objects ---------- */
510
- /* buttons and the few genuinely detached cards share one soft edge:
511
- a 1px rule plus the same rule offset by 2px. No hard black. */
512
-
513
293
  .tamga-raised {
514
294
  border-radius: var(--radius-card);
515
295
  border: 1px solid var(--color-edge);
@@ -517,28 +297,6 @@
517
297
  box-shadow: 2px 2px 0 var(--color-edge);
518
298
  }
519
299
 
520
- /* ------------------------------------------------------------------ *
521
- * TWO PHYSICS, ONE GRAMMAR.
522
- *
523
- * RAISED — sits on top of the page, and pressing puts it back down.
524
- * 1px edge + N px hard offset; press travels the offset and collapses it.
525
- * Buttons, cards, rail items, segments, the primary action.
526
- *
527
- * SEATED — is part of its surface and never lifts at all. It answers by
528
- * FILLING or by drawing a rule, not by travelling.
529
- * Tabs (underline), switches (filled track), checkboxes and radios
530
- * (filled box), chips (edge only — and chips are not even interactive).
531
- *
532
- * The split is not decoration. A tab is not an object lying on the page,
533
- * it is part of the bar; pushing it "down" would be a lie about what it is.
534
- * v5 inherits the same two-physics idea under the names .press-surface and
535
- * .seated-surface — the grammar matches even though the surfaces differ.
536
- *
537
- * The rule that follows from it: DEPTH MEANS PRESSABLE. Anything that
538
- * cannot be pressed does not get an offset, which is exactly why the chip
539
- * lost the one it briefly had.
540
- * ------------------------------------------------------------------ */
541
-
542
300
  .tamga-btn {
543
301
  border-radius: var(--radius-ctl);
544
302
  display: inline-flex;
@@ -558,7 +316,7 @@
558
316
  cursor: pointer;
559
317
  white-space: nowrap;
560
318
  }
561
- /* a real button: lifts under the cursor, presses flat when clicked */
319
+
562
320
  .tamga-btn:not(:disabled):hover {
563
321
  background: var(--color-hover);
564
322
  transform: translate(-1px, -1px);
@@ -568,15 +326,7 @@
568
326
  transform: translate(2px, 2px);
569
327
  box-shadow: 0 0 0 var(--color-edge);
570
328
  }
571
- /* KAPALI BİR DÜĞME YASAK DEĞİL, ATIL. `not-allowed` imleci "buna hakkın
572
- yok" diyor; oysa kaydet düğmesi değişiklik olmadığı için kapalı, ve
573
- kullanıcı bir şey yanlış yapmış değil. İmleç bir suçlama taşımamalı. */
574
- /* SÜRERKEN YÜKSELMİYOR AMA SOLMUYOR DA. `disabled` görünümü "bu düğme
575
- kapalı" der; oysa çalışan bir düğme kapalı değil MEŞGUL, ve soldurmak
576
- kullanıcıya işin durduğunu düşündürüyor. Spinner zaten durumu söylüyor. */
577
- /* `:disabled` de eşleşiyor (kilit onunla kuruluyor) ve aynı özgüllükte,
578
- sonra geldiği için kazanıyordu: meşgul bir düğme "atıl" imleci
579
- gösteriyordu. İkisi birden yazılıyor, böylece sıra değil anlam kazanıyor. */
329
+
580
330
  .tamga-btn[data-busy]:disabled {
581
331
  opacity: 1;
582
332
  cursor: progress;
@@ -593,9 +343,6 @@
593
343
  cursor: default;
594
344
  }
595
345
 
596
- /* The edge is the BASE colour, not the pressed colour. A keycap and the base
597
- it sits on are one object seen from two sides, so they share an outline —
598
- that is what stops a bright face from floating free of its own shadow. */
599
346
  .tamga-btn-primary {
600
347
  background: var(--color-accent);
601
348
  border-color: var(--color-accent-shadow);
@@ -613,14 +360,6 @@
613
360
  box-shadow: 0 0 0 var(--color-accent-shadow);
614
361
  }
615
362
 
616
- /* Success and danger are the same object in two colours: outlined, never
617
- filled. The fill belongs to the one primary action on a page — publishing a
618
- draft and deleting a record are both important, but neither is THE
619
- action, and filling them would put two shouting buttons in one view.
620
- This rule was missing entirely for a while: the class was used in five
621
- places and defined in none, so every "success" button silently rendered as
622
- a plain neutral one. Green belongs to resolved, which is exactly what this
623
- button does — it is the one place the resolved colour touches a control. */
624
363
  .tamga-btn-success {
625
364
  background: var(--color-shell);
626
365
  border-color: var(--color-resolved);
@@ -649,12 +388,6 @@
649
388
  box-shadow: 0 0 0 var(--color-critical);
650
389
  }
651
390
 
652
- /* The one member of the family that is not an object on the page: no edge,
653
- no offset, and therefore no lift. Cancel and dismiss have to stay out of
654
- the way, and anything raised competes with the action beside it.
655
- This rule was missing entirely — the class was used and never written, so
656
- every ghost button silently rendered as a full secondary button, edge and
657
- offset included. The same hole .tamga-btn-success had. */
658
391
  .tamga-btn-ghost {
659
392
  background: transparent;
660
393
  border-color: transparent;
@@ -674,12 +407,6 @@
674
407
  transform: none;
675
408
  }
676
409
 
677
- /* A button that reads as a link. Same element, same keyboard behaviour, no
678
- surface at all — for the rare navigation that sits in a row of buttons and
679
- must not compete with them.
680
- It is a BUTTON, not an <a>: use this when the click runs code. If it
681
- navigates, use a real anchor with .tamga-link, because a link that is not an
682
- anchor cannot be opened in a new tab and is a lie to a screen reader. */
683
410
  .tamga-btn-link {
684
411
  height: auto;
685
412
  padding: 0;
@@ -732,33 +459,8 @@
732
459
  box-shadow: 0 0 0 var(--color-edge);
733
460
  }
734
461
 
735
- /* Sayı girdisinin artır/azalt okları.
736
-
737
- `mini-btn` KULLANILAMAZ ve ilk sürüm onu kullanıyordu: o 32×32 bir
738
- kontrol, ikisi üst üste 65px eder, girdi ise 40px. Oklar kutunun dışına
739
- taşıyordu — çalışıyorlardı ama alanın içinde durmuyorlardı.
740
-
741
- Bir spinner ayrı bir şekildir: alanın SAĞ KENARINA yapışır, yüksekliğini
742
- ondan alır ve kendi kutusu yoktur — girdiden tek bir dikey kuralla
743
- ayrılır. Yükselmez; bu boyutta bir offset kenardan taşar (mini butonun
744
- yükselmemesiyle aynı gerekçe, Yasa 1'in boyut istisnası). */
745
- /* Sayfalayıcının sayfa düğmesi.
746
-
747
- `.tamga-option` KULLANILAMAZ ve ilk sürüm onu kullanıyordu — üstelik
748
- kodun yanındaki yorumda "seçili sayfa dolgu almaz" yazarken. Yorum
749
- doğruydu, sınıf yalanlıyordu: `.tamga-option[data-selected]` bir DOLGU ve
750
- sola oturan bir iç iz veriyor. Sonuç ekranda üç ayrı yanlış oldu — dolu
751
- bir blok, sayının solunda başıboş duran dikey bir çizgi, ve `width: 100%`
752
- olduğu için esneyen bir kutu.
753
-
754
- Sayfa düğmesi rail'in dilini konuşur: seçili olan YÜKSELMEZ, oturur —
755
- kabuk zemini, aksan kenarı, 2px sert offset. Yasa 2: "buradasın" bir
756
- eylem değildir. */
757
462
  .tamga-page {
758
- /* İMLEÇ. Kitteki her tıklanabilir sınıf bunu taşıyor (`btn`, `icon-btn`,
759
- `mini-btn`, `tab`, `segment`, `option`, `switch`); sayfalayıcı tek
760
- istisnaydı ve bu bir gözden kaçmaydı. Tailwind v4 önyüklemesi artık
761
- `button`a imleç vermiyor, yani eksiklik doğrudan görünüyor. */
463
+
762
464
  cursor: pointer;
763
465
  display: inline-flex;
764
466
  height: 40px;
@@ -863,24 +565,12 @@
863
565
  border: 1px solid var(--color-edge);
864
566
  background: var(--color-shell);
865
567
  color: var(--color-ink);
866
- /* Room for a LEADING ICON is opt-in. It used to be baked in at 40px, so every plain field —
867
- name, title, email — opened with an empty inset that read as a rendering fault. A field
868
- reserves space for a thing it has only when it has it. */
568
+
869
569
  padding: 0 16px;
870
570
  font-size: var(--text-body);
871
571
  outline: none;
872
572
  }
873
- /* Çok satırlı hâli.
874
573
 
875
- `.tamga-input` `padding: 0 16px` taşıyor ve tek satır için bu DOĞRU: sabit
876
- `height` metni zaten dikeyde ortalıyor, dikey padding eklemek onu bozardı.
877
-
878
- Ama bir `<textarea>` aynı sınıfı alıp yüksekliğini `rows`'tan aldığında o
879
- sıfır padding görünür bir hataya dönüşüyor: ilk satır üst kenara YAPIŞIYOR.
880
- Aynı sınıfın iki farklı yükseklik modelinde farklı davranması gerekiyor, ve
881
- ayrım elemanın kendisinde — o yüzden seçici `textarea`, bir modifier değil.
882
- Çağıranın hatırlaması gereken bir sınıf olsaydı, unutulduğu her yerde metin
883
- kenara yapışırdı. */
884
574
  textarea.tamga-input {
885
575
  height: auto;
886
576
  padding-top: 10px;
@@ -893,41 +583,16 @@
893
583
  padding-left: 40px;
894
584
  }
895
585
 
896
- /* Yoğun bir yerdeki alan: bir tablo başlığındaki filtre satırı, bir araç
897
- çubuğu, bir satır içi düzeltme.
898
-
899
- NEDEN AYRI BİR ÖLÇÜ DEĞİL. 32px `.tamga-btn-sm` ile AYNI basamak, ve bu
900
- tesadüf değil: filtre kutusunun yanında duran "Temizle" düğmesi de `sm`
901
- oluyor, ikisi aynı satırda birbirini tutuyor. Yeni bir yükseklik uydurmak,
902
- yan yana gelen iki kontrolün 2px kayması demekti.
903
-
904
- NE ZAMAN KULLANILMAZ. Bir formun kendi alanları. Orada alan ASIL iştir ve
905
- 40px onun hakkı; küçültmek yalnız yardımcı bir yüzeyde, verinin kendisinden
906
- daha çok yer kaplamasın diye. */
907
586
  .tamga-input-sm {
908
587
  height: 32px;
909
588
  padding: 0 10px;
910
589
  font-size: var(--text-small);
911
590
  }
912
- /* Küçük alanda ikon da içeri geliyor: 40px'lik oyuk 32px'lik bir kutuda
913
- alanın yarısını yutuyordu. */
591
+
914
592
  .tamga-input-sm[data-leading="true"] {
915
593
  padding-left: 30px;
916
594
  }
917
595
 
918
- /* `Code`'un dış kutusu.
919
- *
920
- * KOPYALAMA DÜĞMESİ MUTLAK KONUMLU ve sağ üste sabitli. Tek satırlık bir
921
- * gövdede bu bir hataya dönüşüyordu: kutu 42px, düğme 32px, üstte 9px altta
922
- * 1.5px kalıyordu; düğme ortalı değil ALTA YAPIŞIK görünüyordu.
923
- *
924
- * İki kural birlikte çözüyor. `min-height` düğmenin altına ve üstüne eşit
925
- * boşluk bırakacak kadar yer açıyor (8 + 32 + 8), ve dikey ortalama tek
926
- * satırlık gövdeyi o yüksekliğin ortasına alıyor, yani metnin ortası ile
927
- * düğmenin ortası aynı yere düşüyor. Çok satırlı bir gövdede kutu zaten
928
- * daha uzun: ortalamanın etkisi kalmıyor, düğme sağ üstte kalıyor ve orası
929
- * bir kod bloğu için doğru yer.
930
- */
931
596
  .tamga-code-block {
932
597
  min-height: 48px;
933
598
  display: flex;
@@ -935,41 +600,10 @@
935
600
  justify-content: center;
936
601
  }
937
602
 
938
- /*
939
- * YAZAR METNİ. Bir ürünün açıklaması, bir bilgi tabanı yazısı, bir notun
940
- * gövdesi: kitin denetlemediği, insanın yazdığı HTML.
941
- *
942
- * NEDEN BİR SINIF, BİLEŞEN DEĞİL. Buraya gelen şey zaten bir HTML dizgisi;
943
- * sarmalayan bir bileşen ona `dangerouslySetInnerHTML`den başka bir şey
944
- * yapamaz, ve o kararı çağıran vermeli. Kitin katkısı biçim: gelen etiketler
945
- * kitin kendi ölçeğinde ve kendi renginde çizilsin.
946
- *
947
- * NE TEMİZLEMEZ. Bu bir güvenlik sınırı DEĞİL. Hangi etiketin geçeceğine
948
- * ürün karar veriyor, çünkü beyaz liste ürünün vitrinine ait bir kural.
949
- *
950
- * SIFIRLAMA GEREKİYOR ÇÜNKÜ tarayıcının kendi başlık ve liste ölçüleri
951
- * kitin ölçeğiyle ilgisiz: `h3` 1.17em, `ul` 40px girinti. Ölçek dışından
952
- * gelen bir sayı, uydurulmuş bir sayı kadar yanlış.
953
- */
954
- /*
955
- * EDİTÖR: araç çubuğu + yazma alanı, tek bir kutu gibi.
956
- *
957
- * Çubuk ile alan AYRI ÖĞELER ama TEK bir kenarlık taşıyorlar; iki ayrı
958
- * kutu, aralarındaki çift çizgiyle "burada iki şey var" der, oysa burada
959
- * bir tane var.
960
- *
961
- * ODAK DIŞ KUTUDA. Yazılan yer içerideki `contenteditable`; odak halkası
962
- * ona verilirse çubuk halkanın dışında kalıyor ve kontrolün sınırı
963
- * belirsizleşiyor. `:focus-within` odağı dışarı taşıyor.
964
- */
965
603
  .tamga-editor {
966
604
  border: 1px solid var(--color-edge);
967
605
  border-radius: var(--radius-ctl);
968
- /* ZEMİN `--color-shell`, `--color-input` DEĞİL. Ölçüldü ve düzeltildi:
969
- `--color-input` shadcn geleneğinden gelen bir KENAR rengi (#d2cec8),
970
- dolgu değil. Onunla boyanan alan girdiden çok DEVRE DIŞI bir kutuya
971
- benziyordu. Metin kutularının gerçek zemini `--color-shell`, ve editör
972
- de bir metin kutusu. */
606
+
973
607
  background: var(--color-shell);
974
608
  overflow: hidden;
975
609
  }
@@ -990,8 +624,6 @@
990
624
  background: var(--color-sunk);
991
625
  }
992
626
 
993
- /* Biçim düğmesi. AÇIK OLAN DURUM DOLU ZEMİNLE söyleniyor, yalnız renkle
994
- değil: bir düğmenin basılı olduğunu tek başına renk anlatamaz. */
995
627
  .tamga-editor-btn {
996
628
  display: inline-flex;
997
629
  align-items: center;
@@ -999,7 +631,7 @@
999
631
  min-width: 28px;
1000
632
  height: 28px;
1001
633
  padding: 0 6px;
1002
- border-radius: var(--radius-mark);
634
+ border-radius: var(--radius-sm);
1003
635
  color: var(--color-ink-soft);
1004
636
  font-size: var(--text-caption);
1005
637
  cursor: pointer;
@@ -1016,9 +648,6 @@
1016
648
  cursor: default;
1017
649
  }
1018
650
 
1019
- /* Bağlantı adresi satırı: çubuğun ALTINDA açılıyor, üstünde değil, çünkü
1020
- çubuk yerinde kalmalı; açılan bir şey düğmelerin yerini oynatırsa
1021
- kullanıcı ikinci düğmeyi kaybediyor. */
1022
651
  .tamga-editor-link {
1023
652
  display: flex;
1024
653
  align-items: center;
@@ -1089,10 +718,6 @@
1089
718
  color: var(--color-ink-faint);
1090
719
  }
1091
720
 
1092
- /* An invalid field carries the critical colour on its edge only — never a
1093
- wash. The message under it is what explains the problem; the field just
1094
- has to be findable. Paired with aria-invalid by the Input component, so
1095
- the state is not only visible. */
1096
721
  .tamga-input-invalid, .tamga-input-invalid:focus {
1097
722
  border-color: var(--color-critical);
1098
723
  box-shadow: 2px 2px 0 var(--color-critical);
@@ -1103,13 +728,6 @@
1103
728
  outline: none;
1104
729
  }
1105
730
 
1106
- /* A chip is FLAT, and that is load-bearing rather than shy.
1107
- In this system depth means "you can press this" — so a raised chip promises
1108
- a press it cannot deliver. It carried a 2px offset for two days and the
1109
- promise was the problem: nothing about a status label is clickable.
1110
- Weight comes from the 1px edge in its own colour instead. Anything that
1111
- genuinely needs to be pressed stops being a chip and becomes a mini button,
1112
- which already exists and already lifts. */
1113
731
  .tamga-chip {
1114
732
  border-radius: var(--radius-ctl);
1115
733
  display: inline-flex;
@@ -1127,20 +745,6 @@
1127
745
  font-size: var(--text-caption);
1128
746
  }
1129
747
 
1130
- /* AKTİF ÇİZGİ SEKMENİN KENDİ KENARLIĞI, dışarı taşan bir `::after` değil.
1131
- *
1132
- * Önce şöyleydi: `position: absolute; bottom: -1px`, yani işaret sekmenin
1133
- * kutusunun BİR PİKSEL ALTINA çiziliyordu ve şeridin kendi alt çizgisinin
1134
- * üstüne oturuyordu. Duran bir şeritte doğru görünüyor.
1135
- *
1136
- * Ama şerit KAYDIRILABİLİR olduğu anda kayboluyor. `overflow-x: auto` veren
1137
- * bir kap, CSS gereği `overflow-y`yi de `auto` yapıyor (bir eksen `visible`
1138
- * değilse öteki de olamaz), ve kutunun dışına çizilen o bir piksel kırpılıyor.
1139
- * On dokuz sekmeli bir şeritte aktif sekme işaretsiz kalıyordu: şerit kitin
1140
- * şeridine "benzemiyordu" ve sebebi buydu.
1141
- *
1142
- * Kenarlık kutunun İÇİNDE: kırpılacak bir taşma yok. Saydam bir kenarlık
1143
- * her sekmede duruyor ki aktif olunca yükseklik değişmesin. */
1144
748
  .tamga-tab {
1145
749
  display: inline-flex;
1146
750
  align-items: center;
@@ -1155,8 +759,6 @@
1155
759
  border-color var(--duration-press) var(--ease-standard);
1156
760
  }
1157
761
 
1158
- /* Kapalı sekme: yerinde ama gidilemez. Solgun ve tıklanamaz, ama YOK
1159
- değil, çünkü orada bir şey olduğunu bilmek kullanıcının işine yarıyor. */
1160
762
  .tamga-tab[data-disabled] {
1161
763
  color: var(--color-ink-faint);
1162
764
  cursor: default;
@@ -1170,16 +772,12 @@
1170
772
  border-bottom-color: var(--color-accent-line);
1171
773
  }
1172
774
 
1173
- /* segmented control: one of N, so it follows the rail — outlined and
1174
- lifted when chosen, never filled. Filling is reserved for actions. */
1175
775
  .tamga-segment {
1176
776
  display: inline-flex;
1177
777
  align-items: center;
1178
778
  gap: 8px;
1179
779
  }
1180
- /* Inactive labels take ink-faint, not nav-idle. nav-idle is an ICON colour —
1181
- icons clear at 3:1, text needs 4.5:1, and as text it measured 3.29:1 on
1182
- paper. Same glyph colour, wrong job. */
780
+
1183
781
  .tamga-segment > button {
1184
782
  display: inline-flex;
1185
783
  align-items: center;
@@ -1215,26 +813,15 @@
1215
813
  box-shadow: 0 0 0 var(--color-accent-line);
1216
814
  }
1217
815
 
1218
- /* ---------- overlay plane ---------- */
1219
- /* Same language as everything else — 1px edge, hard offset, no blur.
1220
- The offset jumps to 6px, past the 4px page maximum, and that gap is
1221
- what says "this is floating, not part of the page". */
1222
816
  .tamga-overlay {
1223
817
  border: 1px solid var(--color-edge);
1224
818
  border-radius: var(--radius-card);
1225
819
  background: var(--color-shell);
1226
820
  box-shadow: 6px 6px 0 var(--color-edge);
1227
- /* KENDİ YÜZEYİ, kendi hizası. Bir panel ağaçta nerede doğduysa oranın
1228
- hizasını miras alıyordu: bir tablo hücresinin içinde açıldığında
1229
- (`.tamga-cell-actions` sağa yaslar) panelin İÇİNDEKİ metin de sağa
1230
- yaslanıyordu. Bir yüzey başladığı yerde metin akışı da yeniden başlar. */
821
+
1231
822
  text-align: start;
1232
823
  }
1233
- /* TAM EKRAN PANEL: bir çalışma yüzeyi, bir kutu değil.
1234
- Kenar, yarıçap ve kaydırma gölgesi kalkıyor — üçü de "bu şey sayfanın
1235
- üstünde duruyor" demek için var, ve sayfanın tamamını kaplayan bir şeyin
1236
- altında sayfa kalmıyor. Dikey akış: başlık ile ayak yerinde kalırken gövde
1237
- kendi içinde kayıyor. */
824
+
1238
825
  .tamga-overlay-full {
1239
826
  display: flex;
1240
827
  height: 100%;
@@ -1243,25 +830,7 @@
1243
830
  border-radius: 0;
1244
831
  box-shadow: none;
1245
832
  }
1246
- /* ---------- steps ---------- */
1247
- /*
1248
- * ADIM ŞERİDİ, ve üç durumu üç FARKLI FİZİKLE söylüyor.
1249
- *
1250
- * Önce üçü de aynı şeydi: ince kenarlı bir daire, yalnız rengi değişiyordu.
1251
- * Renk tek başına bir hiyerarşi kurmuyor — ve daire, kitin hiçbir yerde
1252
- * kullanmadığı bir şekil. Kit tam yuvarlağı yalnız avatarda ve noktada
1253
- * kullanıyor; bir adım işareti bir kontrol boyunda bir işarettir, o yüzden
1254
- * kontrolün yarıçapını alıyor.
1255
- *
1256
- * ÜÇ DURUM, ÜÇ FİZİK (13 Yasa 1: 1px kenar + kaydırılmış tam renk):
1257
- * gelecek düz durur — henüz bir şey olmadı
1258
- * şimdiki YÜKSELİR — 2px sert kaydırma, aksan renginde: buradasın
1259
- * biten OTURUR — dolu aksan, kaydırma yok: bitmiş bir iş kalkmaz
1260
- *
1261
- * ÇİZGİ DE BİLGİ TAŞIYOR. Geçilen aralık aksan, kalanı kenar rengi: şerit
1262
- * yalnız adımları saymıyor, ne kadar yol alındığını da gösteriyor. 1px
1263
- * `--color-line` idi ve kâğıdın üstünde neredeyse görünmüyordu.
1264
- */
833
+
1265
834
  .tamga-step-mark {
1266
835
  display: inline-flex;
1267
836
  width: var(--step-mark);
@@ -1283,9 +852,10 @@
1283
852
  color: var(--color-accent-line);
1284
853
  box-shadow: 2px 2px 0 0 var(--color-accent-line);
1285
854
  }
855
+
1286
856
  .tamga-step-mark[data-state="done"] {
1287
- border-color: var(--color-accent-line);
1288
- background: var(--color-accent-line);
857
+ border-color: var(--color-accent-shadow);
858
+ background: var(--color-accent);
1289
859
  color: var(--color-accent-ink);
1290
860
  }
1291
861
  .tamga-step-line {
@@ -1296,28 +866,13 @@
1296
866
  background: var(--color-edge);
1297
867
  }
1298
868
  .tamga-step-line[data-done="true"] {
1299
- background: var(--color-accent-line);
869
+ background: var(--color-accent);
1300
870
  }
1301
871
 
1302
872
  .tamga-scrim {
1303
873
  background: var(--color-scrim);
1304
874
  }
1305
875
 
1306
- /* ---------- form controls ---------- */
1307
- /* checkbox and radio carry the same 1px edge and 1px offset as a mini
1308
- button, so they read as part of the family rather than browser chrome */
1309
- /*
1310
- * SEÇENEK İŞARETİ İLK SATIRIN ORTASINA.
1311
- *
1312
- * Etiket tek satırken kutuyu dikeyde ortalamak doğru duruyor; altına bir
1313
- * açıklama satırı eklenince işaret İKİ SATIRIN ortasına kaçıyor ve neyi
1314
- * işaretlediği belirsizleşiyor. İşaret ilk satıra ait.
1315
- *
1316
- * Sayı UYDURULMUYOR, satırdan hesaplanıyor: `1lh` öğenin kendi satır
1317
- * kutusu, `18px` de işaretin boyu (yukarıdaki kuralın kendisi), ve fark
1318
- * ikiye bölününce işaret ilk satırın tam ortasına oturuyor. Punto ya da
1319
- * satır aralığı değişirse hizalama kendiliğinden düzeliyor.
1320
- */
1321
876
  .tamga-choice-mark {
1322
877
  align-self: flex-start;
1323
878
  margin-top: calc((1lh - 18px) / 2);
@@ -1342,9 +897,10 @@
1342
897
  border-color: var(--color-accent-line);
1343
898
  box-shadow: 1px 1px 0 var(--color-accent-line);
1344
899
  }
900
+
1345
901
  .tamga-check[data-checked="true"] {
1346
902
  background: var(--color-accent);
1347
- border-color: var(--color-accent);
903
+ border-color: var(--color-accent-shadow);
1348
904
  box-shadow: 1px 1px 0 var(--color-accent-shadow);
1349
905
  }
1350
906
  .tamga-radio[data-checked="true"] {
@@ -1389,23 +945,6 @@
1389
945
  transform: translateX(16px);
1390
946
  }
1391
947
 
1392
-
1393
- /* A skeleton breathes; it never shimmers. A sweeping gradient is the
1394
- default-SaaS tell and this product has no gradients anywhere else, so one
1395
- here would be the single exception — and it would be the loudest thing on
1396
- a page whose whole point is that nothing has arrived yet.
1397
- Two blocks, not one: the ground never animates, only the bar on top of it.
1398
- That keeps a floor under the shape so it stays a placeholder at every point
1399
- in the cycle instead of fading toward the page and back. */
1400
- /* Progress is an instrument scale, not a bar. The ticks let the value be read
1401
- without reading the number, which is what a gauge is for.
1402
- Deliberately NOT the segmented strip form: a segmented horizontal strip is a
1403
- timeline — one mark per bucket, colour as state — and reusing that shape for
1404
- completion would read as history rather than as progress.
1405
- Neutral throughout — progress reports completion, never health, so a status
1406
- colour here would be a false signal.
1407
- Note it carries a 2px offset, so it paints outside its box: reserve room in
1408
- the container or the offset lands on whatever sits below. */
1409
948
  .tamga-progress {
1410
949
  position: relative;
1411
950
  height: 16px;
@@ -1455,9 +994,7 @@
1455
994
  color: var(--color-ink-soft);
1456
995
  cursor: pointer;
1457
996
  }
1458
- /* KLAVYE VURGUSU FARE HOVER'IYLA AYNI GÖRÜNÜR.
1459
- İki ayrı görünüş vermek, aynı anlamı ("Enter buna basacak") iki dille
1460
- anlatmak olurdu; kullanıcının ikisini de öğrenmesi gerekirdi. */
997
+
1461
998
  .tamga-option:hover,
1462
999
  .tamga-option[data-active] {
1463
1000
  background: var(--color-hover);
@@ -1469,9 +1006,6 @@
1469
1006
  box-shadow: inset 2px 0 0 var(--color-accent-line);
1470
1007
  }
1471
1008
 
1472
- /* ---------- feedback and structure ---------- */
1473
-
1474
- /* inline banner — status wash, no fill, a left rule carries the state */
1475
1009
  .tamga-alert {
1476
1010
  display: flex;
1477
1011
  gap: 16px;
@@ -1482,7 +1016,6 @@
1482
1016
  background: var(--color-shell);
1483
1017
  }
1484
1018
 
1485
- /* the live mark — neutral by rule: running is not a deviation */
1486
1019
  .tamga-beacon {
1487
1020
  display: inline-block;
1488
1021
  width: 8px;
@@ -1494,7 +1027,6 @@
1494
1027
  animation: tamga-pulse var(--duration-beacon) var(--ease-breath) infinite;
1495
1028
  }
1496
1029
 
1497
- /* keeps a button's width when its label swaps for a loading label */
1498
1030
  .tamga-swap {
1499
1031
  display: grid;
1500
1032
  place-items: center;
@@ -1511,7 +1043,6 @@
1511
1043
  visibility: hidden;
1512
1044
  }
1513
1045
 
1514
-
1515
1046
  .tamga-rule-h {
1516
1047
  height: 1px;
1517
1048
  width: 100%;
@@ -1523,15 +1054,6 @@
1523
1054
  background: var(--color-line);
1524
1055
  }
1525
1056
 
1526
- /* ---------- lists and tables ---------- */
1527
- /* row height is fixed so a list never breathes with its content */
1528
-
1529
- /* Slider topuzu.
1530
-
1531
- `appearance: none` çubuğu bize bırakıyor ama TOPUZU DA SİLİYOR — ve
1532
- silinen topuz hata vermiyor, sadece kaydırıcı tutulamaz hâle geliyor.
1533
- WebKit ve Firefox iki ayrı sözde-eleman kullanıyor; ikisi de yazılmak
1534
- zorunda, biri unutulursa o tarayıcıda topuz yok. */
1535
1057
  .tamga-slider::-webkit-slider-thumb {
1536
1058
  appearance: none;
1537
1059
  width: 16px;
@@ -1556,16 +1078,6 @@
1556
1078
  outline-offset: 4px;
1557
1079
  }
1558
1080
 
1559
- /* THE GUTTER IS THE ROW'S, not the caller's.
1560
- *
1561
- * This class carried no horizontal padding, and every single caller added
1562
- * `tamga-gutter` by hand: the settings sub-nav, both skeletons, the docs
1563
- * example. Five out of five is not a convention, it is a missing rule, and
1564
- * the sixth caller (a blocks recipe) forgot it and rendered edge to edge.
1565
- *
1566
- * `.tamga-table` was already doing this correctly through
1567
- * `td:first-child { padding-left: var(--gutter) }`. A row and a cell sit on
1568
- * the same left rule; one of them should not need reminding. */
1569
1081
  .tamga-list-row {
1570
1082
  display: flex;
1571
1083
  align-items: center;
@@ -1596,29 +1108,7 @@
1596
1108
  white-space: nowrap;
1597
1109
  text-overflow: ellipsis;
1598
1110
  }
1599
- /* A cell that HOSTS AN OVERLAY cannot clip its own content.
1600
- The truncation trio above (overflow:hidden + nowrap + ellipsis) is right for text and fatal for
1601
- a row's action menu: the panel is absolutely positioned inside the cell, so `overflow:hidden`
1602
- cuts it off at the cell's edge. Measured 2026-08-20 — the menu rendered, looked fine, and
1603
- swallowed every click, because `elementFromPoint` returned the td.
1604
- Actions never need truncating, so the cell opts out of all three rather than the table losing
1605
- ellipsis everywhere.
1606
-
1607
- AND IT REALLY IS ALL THREE. The comment said three, the rule reset two: `white-space: nowrap`
1608
- stayed, and it is inherited, so every panel opened inside this cell inherited it too. A popover
1609
- listing an order's products rendered each line on one unbreakable line and spilled past its own
1610
- edge. The overlay looked broken; the cause was a table rule three levels up. Found 2026-09-09
1611
- in a consumer panel.
1612
-
1613
- KIRPMA VE HİZA AYRI İKİ ŞEY. Bu kaçış uzun süre tek parçaydı ve sağa
1614
- yaslamayı da beraberinde getiriyordu, yani sola yaslı bir hücrede bir ipucu
1615
- ya da açılır panel barındırmak isteyen, hizasını da feda etmek zorunda
1616
- kalıyordu. Yakalandığı yer: bir tüketici listesinde durum rozetinin ipucu
1617
- hücre kenarında kesiliyordu, ve tek çare hücreyi sağa yaslamaktı.
1618
-
1619
- SEÇİCİ `.tamga-table td` KADAR SPESİFİK OLMAK ZORUNDA: düz
1620
- `.tamga-cell-open` (0,1,0) yazılırsa kırpma kuralı `.tamga-table td`
1621
- (0,1,1) onu yener ve sınıf hiçbir şey yapmaz. */
1111
+
1622
1112
  .tamga-table td.tamga-cell-open,
1623
1113
  .tamga-table th.tamga-cell-open {
1624
1114
  overflow: visible;
@@ -1659,13 +1149,7 @@
1659
1149
  .tamga-table tbody tr[data-selected="true"] td:first-child {
1660
1150
  box-shadow: inset 2px 0 0 var(--color-accent-line);
1661
1151
  }
1662
- /* SEÇİLİ SATIR İKİ ADLA GELEBİLİYOR, VE BİRİ BOYANMIYORDU.
1663
- `SettingsTemplate` menüsündeki açık bölümü `data-active` ile işaretliyor
1664
- (bir GEZİNME satırı: hangi sayfadasın), liste satırları ise `data-selected`
1665
- ile (bir SEÇİM: hangi kayıtları işaretledin). İkisi farklı anlam ama aynı
1666
- görünüm, ve kural yalnız ikincisi için yazılmıştı: ayarlar menüsünde
1667
- hangi bölümde olduğun hiç görünmüyordu. Hiçbir şey patlamadı, çünkü
1668
- tarayıcı bilmediği bir nitelik seçicisini sessizce atlıyor. */
1152
+
1669
1153
  .tamga-list-row[data-active="true"],
1670
1154
  .tamga-list-row[data-selected="true"] {
1671
1155
  background: var(--color-accent-bg);
@@ -1676,28 +1160,13 @@
1676
1160
  color: var(--color-accent-line);
1677
1161
  font-weight: 500;
1678
1162
  text-underline-offset: 3px;
1679
- /* `<a href>` pointer'ı tarayıcıdan alır; `href`siz bir `<a>`, bir `<span>`
1680
- ya da link gibi görünen bir `<button>` almaz ve imleç `auto` kalır. Sınıf
1681
- kendi imlecini söylemeli. */
1163
+
1682
1164
  cursor: pointer;
1683
1165
  }
1684
1166
  .tamga-link:hover {
1685
1167
  text-decoration: underline;
1686
1168
  }
1687
1169
 
1688
- /* ------------------------------------------------------------------ *
1689
- * KPI KAROSU: tek bir sayı, büyük.
1690
- *
1691
- * REFERANS NOKTASI YUMUŞAK KARTTI (daire ikon rozeti, bulanık gölge, kenar
1692
- * yok); buradaki karşılığı 1. yasa: 1px kenar, BULANIKSIZ kaymış gölge, ve
1693
- * daire yerine KARE karo. Kit hiçbir yerde daire kullanmıyor (avatar ve
1694
- * nokta dışında) ve tek bir daire, kartı ödünç alınmış gösteriyor.
1695
- *
1696
- * İKON KARONUN ZEMİNİ `--color-hover`, marka rengi DEĞİL. Bir panoda dört
1697
- * karo yan yana duruyor; dördünün de ikonu marka renginde parlarsa hiçbiri
1698
- * öne çıkmıyor ve göz asıl bakması gereken sayıyı en son buluyor. Renk
1699
- * kartın kendi verisinin (`accent` şeridi) ve dikkat isteyen sayının hakkı.
1700
- * ------------------------------------------------------------------ */
1701
1170
  .tamga-kpi {
1702
1171
  position: relative;
1703
1172
  display: flex;
@@ -1726,18 +1195,6 @@
1726
1195
  color: var(--color-ink-soft);
1727
1196
  }
1728
1197
 
1729
- /*
1730
- * FİZİK YALNIZ TIKLANABİLİR KARODA.
1731
- *
1732
- * `.tamga-kpi-live` bir stil değil bir SÖZ: bu karo tıklanıyor. Okunan bir
1733
- * karo hover'da yükselirse tıklanabilir göründüğü hâlde hiçbir şey yapmıyor,
1734
- * ve kullanıcı bir kez tıklayıp bir daha denemiyor.
1735
- *
1736
- * Kaymalar 1. yasanın kendisi: hover'da -1/-1 ve 3px gölge, basınca +2/+2 ve
1737
- * gölge yok. `--offset-room` tuzağı burada da geçerli — bu karolar bir
1738
- * ızgarada duruyor ve ızgaranın kendisi kırpmıyor, ama kaydırılan bir kabın
1739
- * içine konulursa `.tamga-rail-scroll` gibi bir dolgu gerekir.
1740
- */
1741
1198
  .tamga-kpi-live {
1742
1199
  cursor: pointer;
1743
1200
  transition:
@@ -1745,11 +1202,7 @@
1745
1202
  box-shadow var(--duration-press, 120ms) var(--ease-press, ease-out),
1746
1203
  background var(--duration-press, 120ms);
1747
1204
  }
1748
- /* HOVER'DA KENAR RENGİ DEĞİŞMİYOR, ve ilk sürümde değişiyordu. Kitin
1749
- 1. yasasında hover üç şey yapar: zemin bir tık koyulaşır, kontrol
1750
- -1/-1 yükselir, gölge 3px'e çıkar. Kenarın renklenmesi bu dilde yok
1751
- (`tamga-btn`de de, `tamga-icon-btn`de de yok) ve tek başına bir kartta
1752
- yapıldığında kart ötekilerden farklı bir şey konuşuyor. */
1205
+
1753
1206
  .tamga-kpi-live:hover {
1754
1207
  background: var(--color-hover);
1755
1208
  transform: translate(-1px, -1px);
@@ -1760,9 +1213,6 @@
1760
1213
  box-shadow: 0 0 0 var(--color-edge);
1761
1214
  }
1762
1215
 
1763
- /* SEÇİLİ HÂL NÖTR, VURGU RENGİ DEĞİL. Vurgu rengi bir EYLEMİN rengi (kaydet,
1764
- sil); bir filtrenin açık olması bir eylem değil bir DURUM. Vurguya
1765
- boyandığında listede bir sorun varmış gibi okunuyordu. */
1766
1216
  .tamga-kpi-live[data-pressed] {
1767
1217
  border-color: var(--color-ink);
1768
1218
  background: var(--color-hover);
@@ -1775,18 +1225,6 @@
1775
1225
  box-shadow: 0 0 0 var(--color-ink);
1776
1226
  }
1777
1227
 
1778
- /*
1779
- * KAROLARIN IZGARASI.
1780
- *
1781
- * SÜTUN SAYISI KARO SAYISINDAN geliyor (`--tamga-kpi-cols`), ekrandan
1782
- * verilmiyor. Elle verilen bir sütun sayısı yeni bir karo eklendiğinde
1783
- * yalnız o ekranda güncelleniyor, ve tek başına kalan bir karo bütün satırı
1784
- * kaplayıp panoyu dengesiz gösteriyor.
1785
- *
1786
- * Dar ekranda iki sütun, geniş ekranda karo sayısı kadar: bir karo 40px
1787
- * ikon ve display boyunda bir sayı taşıyor, üçten dar bir sütunda sayı
1788
- * sarıyor.
1789
- */
1790
1228
  .tamga-kpi-grid {
1791
1229
  display: grid;
1792
1230
  gap: 16px;
@@ -1803,8 +1241,6 @@
1803
1241
  }
1804
1242
  }
1805
1243
 
1806
- /* Çekmece kenardan kayarak girer; yön `side` ile aynı olmak zorunda, yoksa
1807
- kapatma hareketi ters öğretilir. Gerekçe: /docs/sheet */
1808
1244
  .tamga-sheet-start {
1809
1245
  animation: tamga-sheet-start var(--duration-base) var(--ease-standard);
1810
1246
  }
@@ -1812,14 +1248,179 @@
1812
1248
  animation: tamga-sheet-end var(--duration-base) var(--ease-standard);
1813
1249
  }
1814
1250
 
1251
+ .tamga-swatch {
1252
+ display: inline-flex;
1253
+ width: var(--control);
1254
+ height: var(--control);
1255
+ align-items: center;
1256
+ justify-content: center;
1257
+ border: 1px solid var(--color-edge);
1258
+ border-radius: var(--radius-ctl);
1259
+ background: var(--color-shell);
1260
+ cursor: pointer;
1261
+ transition:
1262
+ transform var(--duration-press) var(--ease-standard),
1263
+ box-shadow var(--duration-press) var(--ease-standard);
1264
+ }
1265
+ .tamga-swatch > span {
1266
+ width: 20px;
1267
+ height: 20px;
1268
+ border-radius: var(--radius-mark);
1269
+ }
1270
+ .tamga-swatch:hover {
1271
+ transform: translate(-1px, -1px);
1272
+ box-shadow: 3px 3px 0 var(--color-edge);
1273
+ }
1274
+ .tamga-swatch[data-selected="true"] {
1275
+ border-color: var(--color-accent-line);
1276
+ box-shadow: 2px 2px 0 var(--color-accent-line);
1277
+ }
1278
+ .tamga-swatch:active {
1279
+ transform: translate(2px, 2px);
1280
+ box-shadow: 0 0 0 var(--color-edge);
1281
+ }
1282
+
1283
+ .tamga-color-input {
1284
+ width: 36px;
1285
+ height: 36px;
1286
+ padding: 2px;
1287
+ border: 1px solid var(--color-edge);
1288
+ border-radius: var(--radius-ctl);
1289
+ background: var(--color-shell);
1290
+ cursor: pointer;
1291
+ }
1292
+
1293
+ .tamga-theme-card {
1294
+ display: flex;
1295
+ flex-direction: column;
1296
+ gap: 8px;
1297
+ padding: 0;
1298
+ border: 0;
1299
+ background: none;
1300
+ cursor: pointer;
1301
+ text-align: center;
1302
+ }
1303
+ .tamga-theme-box {
1304
+ position: relative;
1305
+ display: flex;
1306
+ overflow: hidden;
1307
+ width: 112px;
1308
+ height: 72px;
1309
+ border: 1px solid var(--color-edge);
1310
+ border-radius: var(--radius-card);
1311
+ box-shadow: 2px 2px 0 var(--color-edge);
1312
+ transition:
1313
+ transform var(--duration-press) var(--ease-standard),
1314
+ box-shadow var(--duration-press) var(--ease-standard),
1315
+ border-color var(--duration-press) var(--ease-standard);
1316
+ }
1317
+ .tamga-theme-card:hover .tamga-theme-box {
1318
+ transform: translate(-1px, -1px);
1319
+ box-shadow: 3px 3px 0 var(--color-edge);
1320
+ }
1321
+ .tamga-theme-card:active .tamga-theme-box {
1322
+ transform: translate(2px, 2px);
1323
+ box-shadow: 0 0 0 var(--color-edge);
1324
+ }
1325
+ .tamga-theme-card[data-selected="true"] .tamga-theme-box {
1326
+ border-color: var(--color-accent-line);
1327
+ box-shadow: 2px 2px 0 var(--color-accent-line);
1328
+ }
1329
+ .tamga-theme-name {
1330
+ font-size: var(--text-small);
1331
+ color: var(--color-ink-faint);
1332
+ }
1333
+ .tamga-theme-card[data-selected="true"] .tamga-theme-name {
1334
+ font-weight: 500;
1335
+ color: var(--color-ink);
1336
+ }
1337
+
1338
+ .tamga-theme-half {
1339
+ display: flex;
1340
+ min-width: 0;
1341
+ flex: 1;
1342
+ gap: 4px;
1343
+ padding: 6px;
1344
+ }
1345
+ .tamga-theme-half[data-theme="light"] { background: #f4f2ee; }
1346
+ .tamga-theme-half[data-theme="dark"] { background: #16161a; }
1347
+
1348
+ .tamga-theme-rail {
1349
+ display: flex;
1350
+ width: 12px;
1351
+ flex-shrink: 0;
1352
+ flex-direction: column;
1353
+ gap: 3px;
1354
+ border-radius: 3px;
1355
+ padding: 3px;
1356
+ }
1357
+ .tamga-theme-half[data-theme="light"] .tamga-theme-rail { background: #fcfcfc; }
1358
+ .tamga-theme-half[data-theme="dark"] .tamga-theme-rail { background: #232327; }
1359
+
1360
+ .tamga-theme-body {
1361
+ display: flex;
1362
+ min-width: 0;
1363
+ flex: 1;
1364
+ flex-direction: column;
1365
+ gap: 3px;
1366
+ border-radius: 3px;
1367
+ padding: 4px;
1368
+ }
1369
+ .tamga-theme-half[data-theme="light"] .tamga-theme-body { background: #fcfcfc; }
1370
+ .tamga-theme-half[data-theme="dark"] .tamga-theme-body { background: #232327; }
1371
+
1372
+ .tamga-theme-line {
1373
+ height: 3px;
1374
+ border-radius: 2px;
1375
+ }
1376
+ .tamga-theme-half[data-theme="light"] .tamga-theme-line { background: #d8d4cf; }
1377
+ .tamga-theme-half[data-theme="dark"] .tamga-theme-line { background: #3a3a42; }
1378
+
1379
+ .tamga-theme-half .tamga-theme-line[data-accent="true"] {
1380
+ background: var(--color-accent);
1381
+ }
1382
+
1383
+ .tamga-theme-dot {
1384
+ height: 5px;
1385
+ width: 5px;
1386
+ border-radius: 2px;
1387
+ }
1388
+ .tamga-theme-half[data-theme="light"] .tamga-theme-dot { background: #d8d4cf; }
1389
+ .tamga-theme-half[data-theme="dark"] .tamga-theme-dot { background: #3a3a42; }
1390
+ .tamga-theme-half .tamga-theme-dot[data-accent="true"] {
1391
+ background: var(--color-accent);
1392
+ }
1393
+
1394
+ .tamga-image-field {
1395
+ display: flex;
1396
+ align-items: center;
1397
+ justify-content: center;
1398
+ height: 72px;
1399
+ min-width: 96px;
1400
+ padding: 10px 14px;
1401
+ border: 1px solid var(--color-edge);
1402
+ border-radius: var(--radius-card);
1403
+ background: var(--color-shell);
1404
+ box-shadow: 2px 2px 0 var(--color-edge);
1405
+ }
1406
+
1407
+ .tamga-image-field[data-empty] {
1408
+ border-style: dashed;
1409
+ box-shadow: none;
1410
+ color: var(--color-ink-faint);
1411
+ font-size: var(--text-small);
1412
+ }
1413
+
1414
+ .tamga-settings-panel-accent {
1415
+ border-left: 4px solid var(--color-accent);
1416
+ }
1417
+
1815
1418
  .tamga-label {
1816
1419
  font-size: var(--text-caption);
1817
1420
  font-weight: 500;
1818
1421
  color: var(--color-ink-faint);
1819
1422
  }
1820
1423
 
1821
- /* an identifier-shaped micro-label above a title: mono, wide, quiet. It says
1822
- what KIND of thing this is before the title says which one. */
1823
1424
  .tamga-kicker {
1824
1425
  font-family: var(--font-mono);
1825
1426
  font-size: var(--text-micro);
@@ -1829,25 +1430,12 @@
1829
1430
  color: var(--color-ink-faint);
1830
1431
  }
1831
1432
 
1832
- /* ---------- the mascot's furniture ---------- */
1833
- /* The mascot lives INSIDE the instrument, never floating on top of it.
1834
- Everything here exists to say that in the language the rest of the kit
1835
- already speaks: a seated recess, ruled paper, a hard floor, a hard
1836
- shadow. Drop the art on a plain coloured plane and you get somebody
1837
- else's product with our artwork pasted into it. */
1838
-
1839
- /* The well: a recess carved into the panel. SEATED physics — sunk ground,
1840
- no offset, never lifts. The ground defaults to --color-sunk; a call site
1841
- may pass --art-ground to tint it. */
1842
1433
  .tamga-art-well {
1843
1434
  position: relative;
1844
1435
  background: var(--art-ground, var(--color-sunk));
1845
1436
  overflow: hidden;
1846
1437
  }
1847
- /* Ruled paper. The art direction is "an instrument on paper", so the ground
1848
- the figure stands on is squared paper — the same 8px module the layout uses.
1849
- It also does real work: the grid gives the eye a scale, which is what
1850
- stops a large drawing from reading as a decorative blob. */
1438
+
1851
1439
  .tamga-art-well::before {
1852
1440
  content: "";
1853
1441
  position: absolute;
@@ -1858,28 +1446,20 @@
1858
1446
  opacity: 0.7;
1859
1447
  pointer-events: none;
1860
1448
  }
1861
- /* content sits above the ruling */
1449
+
1862
1450
  .tamga-art-well > * {
1863
1451
  position: relative;
1864
1452
  }
1865
1453
 
1866
- /* The floor. A character standing on a hard rule reads as standing; the same
1867
- character with nothing under it reads as falling. One line fixes it. */
1868
1454
  .tamga-art-floor {
1869
1455
  border-bottom: 1px solid var(--color-edge);
1870
1456
  }
1871
1457
 
1872
- /* The cast shadow: the elevation formula applied to a character. Our light
1873
- has always come from the upper left — every offset in the kit lands down
1874
- and to the right — so the figure's shadow does too. A BAR rather than a copy of
1875
- his silhouette, deliberately: a body-shaped offset would read as the
1876
- pressable-object signature, and artwork is not pressable (Yasa: depth means
1877
- pressable). A bar reads as ground, not as affordance. */
1878
1458
  .tamga-art-fig {
1879
1459
  position: relative;
1880
1460
  display: inline-block;
1881
1461
  }
1882
- /* Off at portrait size: a 3px bar under 30px of art is noise, not ground. */
1462
+
1883
1463
  .tamga-art-fig[data-ground="true"]::after {
1884
1464
  content: "";
1885
1465
  position: absolute;
@@ -1891,11 +1471,6 @@
1891
1471
  pointer-events: none;
1892
1472
  }
1893
1473
 
1894
- /* The portrait: the figure framed in a window, for use inside a row.
1895
- 72px, not 46px. Every drawing is a SCENE — a figure at a desk, a figure in a
1896
- boat — and a scene under about 50px is a smudge: the frame reads, the
1897
- character does not, so the whole thing becomes decoration that costs a row.
1898
- If it cannot be seen it should not be there. */
1899
1474
  .tamga-art-port {
1900
1475
  display: flex;
1901
1476
  align-items: flex-end;
@@ -1908,12 +1483,6 @@
1908
1483
  border-radius: var(--radius-sm);
1909
1484
  }
1910
1485
 
1911
- /* The base plate: what happens next, as an instrument's legend.
1912
- A whole-surface empty state that is one short paragraph and two buttons
1913
- leaves the reader with nothing to do but read the buttons. The steps are
1914
- the actual answer to "what IS this screen for" — and they are what earns
1915
- the full width, instead of stretching two sentences across it.
1916
- Seated: sunk ground, no offset, so it never competes with the action. */
1917
1486
  .tamga-art-steps {
1918
1487
  display: grid;
1919
1488
  border-top: 1px solid var(--color-edge);
@@ -1942,7 +1511,7 @@
1942
1511
  border-left: 0;
1943
1512
  }
1944
1513
  }
1945
- /* mono, because it is a SEQUENCE and not a quantity */
1514
+
1946
1515
  .tamga-art-step-n {
1947
1516
  flex-shrink: 0;
1948
1517
  font-family: var(--font-mono);
@@ -1951,9 +1520,6 @@
1951
1520
  color: var(--color-accent-line);
1952
1521
  }
1953
1522
 
1954
- /* The stage: the empty state is ONE object made of two materials — a seated
1955
- well on the left, the raised face on the right, divided by a real edge.
1956
- Both physics visible at once, which is the whole idea of the kit. */
1957
1523
  .tamga-art-stage {
1958
1524
  display: flex;
1959
1525
  align-items: flex-end;
@@ -1964,9 +1530,6 @@
1964
1530
  border-right: 1px solid var(--color-edge);
1965
1531
  }
1966
1532
 
1967
- /* A full-width shallow band of ruled paper with a floor under it — the
1968
- mascot's stage when the composition runs on ONE vertical axis rather than
1969
- splitting left and right. */
1970
1533
  .tamga-art-band {
1971
1534
  display: flex;
1972
1535
  align-items: flex-end;
@@ -1976,21 +1539,11 @@
1976
1539
  border-bottom: 1px solid var(--color-edge);
1977
1540
  }
1978
1541
 
1979
- /* The ticket's divider. It was drawn as a PERFORATION — a dashed rule meaning
1980
- "tear here" — and v5 proved that wrong on contact: dashed already means
1981
- "not real content yet" (the logo bounding box,
1982
- the logo bounding box). A second meaning for the same mark makes a finished
1983
- empty state read as a placeholder, which is the opposite of what it says.
1984
- Solid, in the edge colour, like every other divider. Changed here too so
1985
- the two do not drift — a kit whose copy disagrees with it is not a kit. */
1986
1542
  .tamga-art-divider {
1987
1543
  height: 0;
1988
1544
  border-top: 1px solid var(--color-edge);
1989
1545
  }
1990
1546
 
1991
- /* A way in, offered as a row rather than a button. An empty screen with two
1992
- buttons asks a yes/no question; a list of routes answers "what can I even
1993
- do here", which is the actual question somebody arriving has. */
1994
1547
  .tamga-art-route {
1995
1548
  display: flex;
1996
1549
  width: 100%;
@@ -2018,9 +1571,6 @@
2018
1571
  box-shadow: 0 0 0 var(--color-edge);
2019
1572
  }
2020
1573
 
2021
- /* A logo tile. The mascot's portrait window is 72px because a SCENE needs the room; a service
2022
- mark is a single glyph and reads at 48. Same frame, different job — sharing the portrait class
2023
- made every integration card look like it was missing something. */
2024
1574
  .tamga-logo-tile {
2025
1575
  display: flex;
2026
1576
  align-items: center;
@@ -2037,16 +1587,11 @@
2037
1587
  height: 40px;
2038
1588
  }
2039
1589
 
2040
- /* No box at all. For a whole body with nothing in it, where a bordered panel
2041
- would be a box drawn around a void — the floor rule is the only structure,
2042
- and it is as wide as the artwork rather than as wide as the screen. */
2043
1590
  .tamga-art-blank-floor {
2044
1591
  height: 1px;
2045
1592
  background: var(--color-edge);
2046
1593
  }
2047
1594
 
2048
- /* The tile: a card you PICK, so it is raised and it presses — a template
2049
- that cannot be chosen has no business looking like a card. */
2050
1595
  .tamga-art-tile {
2051
1596
  display: flex;
2052
1597
  flex-direction: column;
@@ -2062,23 +1607,17 @@
2062
1607
  box-shadow var(--duration-press) var(--ease-standard),
2063
1608
  border-color var(--duration-press) var(--ease-standard);
2064
1609
  }
1610
+
2065
1611
  .tamga-art-tile:hover {
2066
1612
  transform: translate(-1px, -1px);
2067
- box-shadow: 3px 3px 0 var(--color-edge);
1613
+ box-shadow: 3px 3px 0 var(--color-accent-line);
2068
1614
  border-color: var(--color-accent-line);
2069
1615
  }
2070
1616
  .tamga-art-tile:active {
2071
1617
  transform: translate(2px, 2px);
2072
1618
  box-shadow: 0 0 0 var(--color-edge);
2073
1619
  }
2074
- /* The category colour is a RULE, not a field. A wall of coloured banners
2075
- would out-shout a real event; a 3px spine under the art carries the
2076
- same information and outranks nothing. */
2077
- /* The five tones are spelled out rather than composed from a custom property:
2078
- Tailwind only emits an @theme variable that something actually references,
2079
- and a var() built inside a template literal is invisible to it — the token
2080
- resolves to nothing at runtime and the rule silently goes grey. Naming them
2081
- here is what keeps them alive. */
1620
+
2082
1621
  .tamga-art-spine {
2083
1622
  height: 3px;
2084
1623
  background: var(--color-edge);
@@ -2171,11 +1710,6 @@
2171
1710
  animation: tamga-pulse var(--duration-beacon) var(--ease-breath) infinite;
2172
1711
  }
2173
1712
 
2174
- /* Deep breath, chosen over the shallow one. The shallow version was correct in
2175
- principle and invisible in practice — on a real page you could not tell a
2176
- loading panel from a settled one at a glance, which is the only job it has.
2177
- 0.78 → 0.06 at 1.1s is far enough and fast enough to register peripherally
2178
- without ever becoming a shimmer. */
2179
1713
  @keyframes tamga-breathe {
2180
1714
  0%,
2181
1715
  100% {
@@ -2186,18 +1720,6 @@
2186
1720
  }
2187
1721
  }
2188
1722
 
2189
- /* Al breathing. Slow and tiny on purpose — a mascot that moves a lot turns into
2190
- a distraction on a screen people watch for events. Whole pixels only, or
2191
- the pixel art lands on a half pixel and blurs on the way past. */
2192
- /* Al floats; he never pulses — and that distinction is the whole reason a
2193
- mascot can share a screen with the beacon at all.
2194
- Law 3 (v2, 13-design-soul) says the beacon is the only thing that pulses.
2195
- The mascot is exempt because it moves in a different CHANNEL: the beacon
2196
- changes BRIGHTNESS, Al changes POSITION. The eye reads a brightness change
2197
- as "look here" and a slow drift as "this thing is alive", so the two do not
2198
- compete for the same attention.
2199
- The price of that exemption: this animation must never touch opacity. If it
2200
- ever does, Al starts competing with the one real signal on the screen. */
2201
1723
  @keyframes tamga-float-loop {
2202
1724
  0%,
2203
1725
  100% {
@@ -2215,8 +1737,7 @@
2215
1737
  .tamga-rise, .tamga-live, .tamga-float, .tamga-beacon[data-live="true"] {
2216
1738
  animation: none;
2217
1739
  }
2218
- /* a stopped skeleton must still read as a placeholder, so it keeps the bar —
2219
- parked near the middle of the breath rather than at either end */
1740
+
2220
1741
  .tamga-skeleton::after {
2221
1742
  animation: none;
2222
1743
  opacity: 0.42;
@@ -2224,19 +1745,18 @@
2224
1745
  .tamga-toast {
2225
1746
  animation: none;
2226
1747
  }
2227
- /* Duran bir çekmece yine de AÇIK olmalı: kayma gidiyor, panel yerinde
2228
- beliriyor. */
1748
+
2229
1749
  .tamga-sheet-start,
2230
1750
  .tamga-sheet-end {
2231
1751
  animation: none;
2232
1752
  }
2233
- /* a stopped spinner must still be a visible mark, never an empty box */
1753
+
2234
1754
  .tamga-spin-part {
2235
1755
  animation: none !important;
2236
1756
  opacity: 0.6 !important;
2237
1757
  transform: none !important;
2238
1758
  }
2239
- /* keeps a button's width when its label swaps for a loading label */
1759
+
2240
1760
  .tamga-swap {
2241
1761
  display: grid;
2242
1762
  place-items: center;
@@ -2256,19 +1776,7 @@
2256
1776
  }
2257
1777
 
2258
1778
  @layer components {
2259
- /* ------------------------------------------------------------------ *
2260
- * SAVE BAR — stuck to the bottom of a scrolling surface.
2261
- *
2262
- * WHY THE `::after`. `position: sticky; bottom: 0` aligns the bar's bottom
2263
- * edge with the surface's CONTENT box, but a surface carries its own bottom
2264
- * padding, and content was flowing THROUGH the bar in that gap. The
2265
- * extension covers exactly that padding; the ground is the same colour, so
2266
- * the seam is invisible. The gap is read from `--surface-pad`, which the
2267
- * consumer sets on the scrolling surface.
2268
- *
2269
- * NEGATIVE MARGIN, not a full-bleed trick: the bar spans the surface edge to
2270
- * edge while its content stays on the same left rule as everything else.
2271
- * ------------------------------------------------------------------ */
1779
+
2272
1780
  .tamga-save-bar {
2273
1781
  position: sticky;
2274
1782
  bottom: 0;