@kolkrabbi/kol-theme 0.154.0 → 0.156.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.
@@ -196,3 +196,31 @@
196
196
  --kol-surface-absolute-split: var(--kol-surface-ab-split);
197
197
  --kol-surface-absolute-split-inverse: var(--kol-surface-ab-split-inverse);
198
198
  }
199
+
200
+ /* ═══════════════════════════════════════════════════════════════
201
+ * THE CONTROL LADDER, AS TOKENS — and its TOUCH RUNG (ruling D5, apps review 2026-09-29)
202
+ *
203
+ * 22 · 26 · 32 · 40 (01-foundations/09-sizes.md). Every PINNED control height — an icon-only
204
+ * square, a dropdown trigger, a segmented strip, an IconFrame, a menu trigger — reads these, so the
205
+ * pinned boxes and the derived ones (padding + line-height + ring) move together.
206
+ *
207
+ * On a coarse pointer every text field must type at 16px or iOS zooms the page into it
208
+ * (OverlaySearchFieldZoomsIOS, 2026-09-01) — which put 16px text in a 26px `sm` box beside 12px
209
+ * buttons (the user: "bigger text than its relative height"). So on touch the WHOLE ladder takes
210
+ * 16 / 22 type and every box grows with it: xs 32 · sm 32 · md 36 · lg 40. One row, one height,
211
+ * on a phone as at a desk. The type rule lives with the controls (kol-components-atoms.css).
212
+ * ═══════════════════════════════════════════════════════════════ */
213
+ :root {
214
+ --kol-ctl-xs: 22px;
215
+ --kol-ctl-sm: 26px;
216
+ --kol-ctl-md: 32px;
217
+ --kol-ctl-lg: 40px;
218
+ }
219
+ @media (pointer: coarse) {
220
+ :root {
221
+ --kol-ctl-xs: 32px;
222
+ --kol-ctl-sm: 32px;
223
+ --kol-ctl-md: 36px;
224
+ --kol-ctl-lg: 40px;
225
+ }
226
+ }
@@ -296,10 +296,10 @@
296
296
  * shorter, at `xs` 2px shorter. Three families (control shell, text button,
297
297
  * segmented) already agreed on 22/26/32/40, so the squares conform to them, not
298
298
  * the other way round. Glyphs are untouched — SOLO still resolves 16/20/24. */
299
- .kol-btn-icon.kol-btn-xs { width: 22px; height: 22px; padding: 0; }
300
- .kol-btn-icon.kol-btn-sm { width: 26px; height: 26px; padding: 0; }
301
- .kol-btn-icon.kol-btn-md { width: 32px; height: 32px; padding: 0; }
302
- .kol-btn-icon.kol-btn-lg { width: 40px; height: 40px; padding: 0; }
299
+ .kol-btn-icon.kol-btn-xs { width: var(--kol-ctl-xs); height: var(--kol-ctl-xs); padding: 0; }
300
+ .kol-btn-icon.kol-btn-sm { width: var(--kol-ctl-sm); height: var(--kol-ctl-sm); padding: 0; }
301
+ .kol-btn-icon.kol-btn-md { width: var(--kol-ctl-md); height: var(--kol-ctl-md); padding: 0; }
302
+ .kol-btn-icon.kol-btn-lg { width: var(--kol-ctl-lg); height: var(--kol-ctl-lg); padding: 0; }
303
303
 
304
304
  /* ─── Variants — the ground ones are TONES now (2026-09-03) ───
305
305
  * `.kol-btn-primary` · `-secondary` · `-outline` · `-ghost` · `-grey` are
@@ -1170,10 +1170,10 @@ a.kol-icon-frame {
1170
1170
  /* pinned squares — the box never moves with glyph size (user law 2026-07-28),
1171
1171
  * on the size's HEIGHT so a frame lines up with the Button, Input and Dropdown
1172
1172
  * beside it (user ruling 2026-09-02 — see .kol-btn-icon above). 22/26/32/40. */
1173
- .kol-icon-frame-xs { width: 22px; height: 22px; }
1174
- .kol-icon-frame-sm { width: 26px; height: 26px; }
1175
- .kol-icon-frame-md { width: 32px; height: 32px; }
1176
- .kol-icon-frame-lg { width: 40px; height: 40px; }
1173
+ .kol-icon-frame-xs { width: var(--kol-ctl-xs); height: var(--kol-ctl-xs); }
1174
+ .kol-icon-frame-sm { width: var(--kol-ctl-sm); height: var(--kol-ctl-sm); }
1175
+ .kol-icon-frame-md { width: var(--kol-ctl-md); height: var(--kol-ctl-md); }
1176
+ .kol-icon-frame-lg { width: var(--kol-ctl-lg); height: var(--kol-ctl-lg); }
1177
1177
 
1178
1178
  /* `.kol-icon-frame-{primary,secondary,accent,outline,ghost,nav,grey,danger}` — tone aliases, see TONE */
1179
1179
  .kol-icon-frame-plate {
@@ -1310,6 +1310,15 @@ a.kol-icon-frame {
1310
1310
  * own; it exists so the floor below keys on every body plan the DS ships,
1311
1311
  * including the chrome-less one. */
1312
1312
  @media (pointer: coarse) {
1313
+ /* THE TOUCH RUNG (D5, 2026-09-29 — see kol-base-tokens.css): every text control types 16 / 22 on
1314
+ * touch, so a derived box grows exactly as the pinned tokens do — xs/sm 4+4+22+2 = 32, md
1315
+ * 6+6+22+2 = 36, lg 40. Two classes, so it outranks the size's own kol-mono-* class. */
1316
+ .kol-btn.kol-btn-xs, .kol-btn.kol-btn-sm, .kol-btn.kol-btn-md, .kol-btn.kol-btn-lg,
1317
+ .kol-control.kol-control-xs, .kol-control.kol-control-sm, .kol-control.kol-control-md, .kol-control.kol-control-lg,
1318
+ .kol-seg .kol-seg-cell, .kol-menu-btn.kol-menu-btn {
1319
+ font-size: 16px;
1320
+ line-height: 22px;
1321
+ }
1313
1322
  .kol-control input,
1314
1323
  .kol-control--bare input,
1315
1324
  .kol-expand input {
@@ -59,10 +59,10 @@
59
59
  gap: 0;
60
60
  position: relative;
61
61
  }
62
- .kol-dd-trigger.kol-btn-xs { height: 22px; padding-block: 0; }
63
- .kol-dd-trigger.kol-btn-sm { height: 26px; padding-block: 0; }
64
- .kol-dd-trigger.kol-btn-md { height: 32px; padding-block: 0; }
65
- .kol-dd-trigger.kol-btn-lg { height: 40px; padding-block: 0; }
62
+ .kol-dd-trigger.kol-btn-xs { height: var(--kol-ctl-xs); padding-block: 0; }
63
+ .kol-dd-trigger.kol-btn-sm { height: var(--kol-ctl-sm); padding-block: 0; }
64
+ .kol-dd-trigger.kol-btn-md { height: var(--kol-ctl-md); padding-block: 0; }
65
+ .kol-dd-trigger.kol-btn-lg { height: var(--kol-ctl-lg); padding-block: 0; }
66
66
  /* REST AND OPEN ARE THE ONLY STATES (2026-07-15, re-called 2026-08-09 and
67
67
  * 2026-08-28). No :hover or :active rules for the trigger live here any more —
68
68
  * kol-components-atoms.css excludes `.kol-dd-trigger` from every variant's
@@ -581,14 +581,14 @@
581
581
  * forced the pin). Same principle as .kol-btn-icon's pinned square:
582
582
  * the box never moves. */
583
583
  box-sizing: border-box;
584
- height: 32px; /* md — .kol-btn-md */
584
+ height: var(--kol-ctl-md); /* md — .kol-btn-md */
585
585
  }
586
586
 
587
587
  /* Sizes mirror .kol-btn-{sm,md,lg} exactly: pinned height above + cell
588
588
  * padding per size (below) + mono type (12/14/16) applied in JSX. */
589
- .kol-seg--xs { height: 22px; }
590
- .kol-seg--sm { height: 26px; }
591
- .kol-seg--lg { height: 40px; }
589
+ .kol-seg--xs { height: var(--kol-ctl-xs); }
590
+ .kol-seg--sm { height: var(--kol-ctl-sm); }
591
+ .kol-seg--lg { height: var(--kol-ctl-lg); }
592
592
  .kol-seg--xs .kol-seg-cell { padding: 4px 8px; }
593
593
  .kol-seg--sm .kol-seg-cell { padding: 4px 12px; }
594
594
  .kol-seg--lg .kol-seg-cell { padding: 8px 20px; }
@@ -918,7 +918,13 @@
918
918
  position: relative;
919
919
  width: 100%;
920
920
  overflow: hidden;
921
- background-color: var(--kol-surface-primary);
921
+ /* THE PANEL LIFTS OFF THE PAGE (2026-09-28, user: the search overlay "is very
922
+ * faint, and the input text is also very faint"). It painted the page's own
923
+ * surface, so over a dark page and a scrim it read as a hole rather than a
924
+ * panel. `oq-04` is the lift the shortcuts sheet already wears (2026-09-03):
925
+ * opaque, one step off the ground, in both themes. */
926
+ background-color: var(--kol-oq-04);
927
+ color: var(--kol-oq-96);
922
928
  /* NO BORDER, NO SHADOW (user 2026-08-01). Both were tried and both were
923
929
  * wrong: the shadow was another product's floating-card idiom, and the
924
930
  * hairline left an empty palette reading as a bordered empty box. The SCRIM
@@ -932,6 +938,10 @@
932
938
  * and is deleted with it: it solved the wrong problem. */
933
939
  }
934
940
 
941
+ /* the query field inside a panel reads at full ink; its placeholder at 48 */
942
+ .kol-overlay-panel .kol-control--bare input { color: var(--kol-oq-96); }
943
+ .kol-overlay-panel .kol-control--bare input::placeholder { color: var(--kol-oq-48); }
944
+
935
945
  /* ── Section — .kol-section-* ─────────────────────────────────────────────
936
946
  * Between-siblings rhythm for stacked inspector sections (InspectorSectionRhythm,
937
947
  * filed from kol-fxr 2026-08-15).
@@ -41,7 +41,9 @@
41
41
  .kol-shell-page {
42
42
  display: flex;
43
43
  flex-direction: column;
44
- min-height: 100vh;
44
+ /* less the phone bar (`--kol-shell-bar-h`, set by AppShell `touch="bar"`): the content column
45
+ * already pads for it, so a full-height page ends above the bar, not under it (2026-09-29) */
46
+ min-height: calc(100vh - var(--kol-shell-bar-h, 0px));
45
47
  padding: var(--kol-shell-page-pad);
46
48
  /* PageShellScrollbarGutter (kol-monitor 2026-08-28): in `fixed` mode this
47
49
  * element IS the scroll container and reserves the gutter; in `scroll` mode
@@ -58,7 +60,7 @@
58
60
  }
59
61
  /* `mode="fixed"` — the element is the scroll container; pair with a
60
62
  * `flex:1 overflow:auto` body (the settings idiom) */
61
- .kol-shell-page--fixed { min-height: 0; height: 100vh; overflow: hidden; }
63
+ .kol-shell-page--fixed { min-height: 0; height: calc(100vh - var(--kol-shell-bar-h, 0px)); overflow: hidden; }
62
64
  /* `width="capped"` — the SITE tier: the framework container ladder, centred.
63
65
  * `bleed` (the default, unclassed) fills the window — the app tier. The one
64
66
  * real difference between a shell page and a `.kol-page`, and it is a prop
@@ -202,6 +204,34 @@
202
204
  background: color-mix(in srgb, var(--kol-color-ab-black) 48%, transparent);
203
205
  }
204
206
 
207
+ /* ── THE PHONE BAR (AppShell `touch="bar"`, apps review 2026-09-29) — the rail as kol-component's
208
+ * MobileTabBar below 768; past five destinations the fifth tab is More, and More is this sheet,
209
+ * floated just above the bar. The scrim sits under the bar, so More stays tappable to close. */
210
+ .kol-phone-nav-scrim {
211
+ position: fixed;
212
+ inset: 0;
213
+ z-index: calc(var(--kol-z-sticky) - 1);
214
+ border: 0;
215
+ padding: 0;
216
+ cursor: default;
217
+ }
218
+ .kol-phone-nav-more {
219
+ position: fixed;
220
+ left: 12px;
221
+ right: 12px;
222
+ bottom: calc(56px + env(safe-area-inset-bottom, 0px) + 8px);
223
+ z-index: var(--kol-z-sticky);
224
+ display: flex;
225
+ flex-direction: column;
226
+ gap: 2px;
227
+ max-height: 60dvh;
228
+ overflow-y: auto;
229
+ padding: 8px;
230
+ border-radius: var(--kol-radius-sm);
231
+ background: var(--kol-surface-primary);
232
+ border: 1px solid var(--kol-oq-08);
233
+ }
234
+
205
235
  /* ── THE TAP OPENER IS THE LINE (ShellRailCollapsedWithTapOpen, kol-mirror
206
236
  * 2026-09-01; corrected by RailGrabTapIsALine, kol-monitor 2026-09-02 — user:
207
237
  * "it was a thicker line" · "who decided it should be a chevron?"). `touch=
@@ -82,11 +82,65 @@
82
82
  scrollbar-width: none;
83
83
  }
84
84
 
85
- /* Shell content grid — the rail/main/toc gutter. The gap lives HERE, not as a
86
- * utility on the element: a gap-8 in the JSX outranked this layer at every
87
- * width and made the 48px wide step (below, ≥1600px) dead code. */
85
+ /* THE SHELL'S ONE SCROLL REGION (showcase refinement 2026-09-28). It used to
86
+ * be three: each rail and #main scrolled themselves inside a grid wrapped in
87
+ * the chrome inset, so main's scrollbar sat 24px in from the window edge and
88
+ * ended at main's right edge, beside the TOC rather than at the window's.
89
+ * Now the region below the header scrolls as one, edge to edge; the rails are
90
+ * sticky inside it and still scroll their own overflow. `container-type: size`
91
+ * lets a rail be exactly one region tall (100cqh) without measuring anything.
92
+ *
93
+ * ONE SPACE BETWEEN A RAIL AND THE PAGE, NOT TWO. The grid had a 32/48px gap
94
+ * AND pages padded themselves with --kol-pad-section-x, so rail text sat up to
95
+ * ~100px from the page's. The gap is gone: a rail ends in an opaque 08 seam
96
+ * (the seam law) with the chrome inset inside it, and main pads the page
97
+ * ladder from the seam. Pages do not pad themselves on x. */
98
+ .shell-scroll {
99
+ container-type: size;
100
+ scrollbar-gutter: stable;
101
+ overscroll-behavior: none;
102
+ }
103
+
88
104
  .shell-content-grid {
89
- gap: 32px;
105
+ gap: 0;
106
+ min-height: 100%;
107
+ }
108
+
109
+ .shell-rail {
110
+ position: sticky;
111
+ top: 0;
112
+ align-self: start;
113
+ height: 100cqh;
114
+ overflow-y: auto;
115
+ overflow-x: hidden;
116
+ overscroll-behavior: contain;
117
+ }
118
+
119
+ .shell-rail--nav {
120
+ border-right: 1px solid var(--kol-oq-08);
121
+ padding-inline-end: var(--kol-pad-chrome-x);
122
+ }
123
+
124
+ .shell-rail--toc {
125
+ border-left: 1px solid var(--kol-oq-08);
126
+ padding-inline-start: var(--kol-pad-chrome-x);
127
+ }
128
+
129
+ .shell-main {
130
+ min-width: 0;
131
+ }
132
+
133
+ /* THE TYPED WORDMARK — the shell's second mark as live type in the Tight cut
134
+ * (2026-09-28), sized so its caps stand as tall as the drawn KOLKRABBI mark
135
+ * beside it (h-6). The display voice is uppercase by contract. */
136
+ .shell-wordmark-label {
137
+ font-family: var(--kol-font-family-sans-tight);
138
+ font-size: 33px;
139
+ line-height: 24px;
140
+ font-weight: 500;
141
+ text-transform: uppercase;
142
+ letter-spacing: 0;
143
+ white-space: nowrap;
90
144
  }
91
145
 
92
146
  .shell-sidebar-sticky::-webkit-scrollbar {
@@ -463,10 +517,6 @@
463
517
  font-size: 13px;
464
518
  }
465
519
 
466
- /* Wide grid gap */
467
- .shell-content-grid {
468
- gap: 48px;
469
- }
470
520
  }
471
521
 
472
522
  /* =============================================================================
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kolkrabbi/kol-theme",
3
- "version": "0.154.0",
3
+ "version": "0.156.0",
4
4
  "description": "KOL (Kolkrabbi) design-system tokens + base CSS — brand-neutral. The canonical token/cascade layer every other KOL package and consumer builds on.",
5
5
  "license": "MIT",
6
6
  "type": "module",