@usableapp/cardds 0.7.103 → 0.7.105
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.
- package/CHANGELOG.md +43 -0
- package/css/actions.css +112 -37
- package/css/base.css +139 -15
- package/css/card.css +331 -86
- package/css/choice.css +25 -33
- package/css/finish.css +29 -28
- package/css/forms.css +6 -14
- package/css/journey.css +8 -6
- package/css/layover.css +26 -24
- package/css/lists.css +8 -6
- package/css/media.css +13 -74
- package/css/numbers.css +37 -32
- package/css/palette.css +2 -2
- package/css/people.css +3 -8
- package/css/post.css +23 -19
- package/css/sheet.css +84 -56
- package/css/stack.css +40 -216
- package/css/stamp.css +41 -29
- package/css/step.css +1 -107
- package/css/sticky.css +43 -41
- package/css/theme.template.css +12 -0
- package/css/tokens.css +101 -26
- package/dist/actions/Chip.d.ts +1 -1
- package/dist/actions/Chip.js +3 -2
- package/dist/actions/IconBtn.d.ts +12 -3
- package/dist/actions/IconBtn.js +9 -3
- package/dist/cardds.css +1094 -881
- package/dist/cards/Card.d.ts +8 -6
- package/dist/cards/Card.js +4 -4
- package/dist/cards/CardFeed.js +7 -9
- package/dist/cards/CardFoot.d.ts +7 -2
- package/dist/cards/CardFoot.js +4 -3
- package/dist/catalog.json +1 -1
- package/dist/journey/JourneyBadge.d.ts +1 -1
- package/dist/journey/JourneyBadge.js +1 -1
- package/dist/layover/Snackbar.js +2 -2
- package/dist/lists/Bubble.d.ts +1 -1
- package/dist/lists/Bubble.js +1 -1
- package/dist/lists/Row.js +5 -7
- package/dist/numbers/Picker.js +11 -18
- package/dist/people/Avatar.d.ts +1 -1
- package/dist/people/Avatar.js +3 -2
- package/dist/post/PostDesk.js +6 -9
- package/dist/post/PostLetter.js +4 -4
- package/dist/pressable.d.ts +9 -0
- package/dist/pressable.js +6 -0
- package/dist/room.d.ts +5 -0
- package/dist/room.js +9 -0
- package/dist/scaffold/Panes.js +8 -14
- package/dist/sheets/Sheet.d.ts +1 -1
- package/dist/sheets/Sheet.js +2 -3
- package/dist/sheets/SheetSteps.js +3 -3
- package/dist/sheets/StackSheet.d.ts +1 -1
- package/dist/sheets/sheetStepsPile.js +2 -3
- package/dist/sheets/stackCard.js +67 -115
- package/dist/state.d.ts +21 -0
- package/dist/state.js +28 -1
- package/dist/sticky/Sticky.js +3 -7
- package/dist/templates/Home.d.ts +1 -1
- package/dist/templates/Splash.js +2 -2
- package/dist/templates/Walkthrough.js +4 -5
- package/docs/reference.md +76 -12
- package/lib/catalog.mjs +23 -7
- package/lint/rules.mjs +7 -5
- package/lint/values.mjs +144 -0
- package/package.json +6 -4
package/css/choice.css
CHANGED
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
--dark: var(--action-dark); /* the paper's side: its knob at rest is the paper's muted ink, on the accent the accent's */
|
|
53
53
|
color: var(--card-ink);
|
|
54
54
|
position: relative;
|
|
55
|
-
transition: background-color var(--motion-press) ease-out, border-color var(--motion-press) ease-out;
|
|
55
|
+
transition: background-color var(--motion-press) var(--ease-out), border-color var(--motion-press) var(--ease-out);
|
|
56
56
|
}
|
|
57
57
|
.toggle::after {
|
|
58
58
|
content: "";
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
height: calc(var(--_h) - 2 * var(--_pad) - 2 * var(--border-w));
|
|
64
64
|
border-radius: 50%;
|
|
65
65
|
background: var(--card-muted); /* a glyph: a shade of its side, never an opacity (0.45 of the ink was 2.4:1 on the paper) */
|
|
66
|
-
transition: translate var(--motion-quick) ease;
|
|
66
|
+
transition: translate var(--motion-quick) var(--ease);
|
|
67
67
|
}
|
|
68
68
|
.toggle:checked { background: var(--accent); border-color: transparent; }
|
|
69
69
|
.toggle:checked::after { translate: calc(var(--_w) - var(--_h)) 0; background: var(--on-accent); }
|
|
@@ -75,34 +75,18 @@
|
|
|
75
75
|
<div class="chip-row"><label class="chip chip--pick chip--sign"><input type="checkbox">Nature</label>…</div> */
|
|
76
76
|
.chip-grid {
|
|
77
77
|
display: grid;
|
|
78
|
-
grid-template-columns: repeat(auto-fill, minmax(min(
|
|
78
|
+
grid-template-columns: repeat(auto-fill, minmax(min(calc(var(--tap-base) * 11 / 6), 100%), 1fr));
|
|
79
79
|
gap: var(--chip-grid-gap, var(--sp-2));
|
|
80
80
|
}
|
|
81
81
|
/* .chip hugs its text as a loose grid child (justify-self: start); inside a
|
|
82
82
|
chip grid the whole point is equal, full-width pick targets, so stretch.
|
|
83
83
|
Matters most in scripts without word spaces (Thai): min-content is the
|
|
84
84
|
whole string, tracks get wide, and hugging chips leave a ragged grid. */
|
|
85
|
-
.chip-grid > .chip {
|
|
86
|
-
.chip--pick { position: relative; } /* the input covers the whole chip, on a row as in a grid */
|
|
85
|
+
.chip-grid > .chip { --chip-self: stretch; --chip-justify: center; --chip-min-h: var(--btn-h); --chip-pad-x: var(--sp-2); }
|
|
87
86
|
/* the hidden input, the same shape wherever a native radio/checkbox drives a picked look:
|
|
88
87
|
a chip, a mood dot, a tile (media.css), a sticky's tone swatch (sticky.css), a place on a map (sheet.css), a card that is a label round a radio
|
|
89
88
|
(a pickable row card: the app gives the picked one its `tone`) — the native input lies over its whole box, unseen */
|
|
90
89
|
:is(.chip--pick, .mood__opt, .tile--pick, .sticky-pick__swatch, .map-pick) > input, label.card > input[type="radio"] { appearance: none; position: absolute; inset: 0; margin: 0; opacity: 0; cursor: inherit; }
|
|
91
|
-
:is(.chip--pick, .tile--pick):has(:checked) { background: var(--accent); --dark: var(--accent-dark); color: var(--card-ink); border-color: transparent; }
|
|
92
|
-
/* --sign: the trailing + that turns 45° into an × when picked — one mask, one rotate, no swap (Lh 2026-09-16) */
|
|
93
|
-
.chip--sign { padding-right: var(--sp-2); }
|
|
94
|
-
.chip--sign::after {
|
|
95
|
-
content: "";
|
|
96
|
-
width: var(--icon-xs);
|
|
97
|
-
height: var(--icon-xs);
|
|
98
|
-
flex: none;
|
|
99
|
-
background: currentColor;
|
|
100
|
-
mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2.5" stroke-linecap="round"><path d="M5 12h14"/><path d="M12 5v14"/></svg>') center / contain no-repeat;
|
|
101
|
-
-webkit-mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2.5" stroke-linecap="round"><path d="M5 12h14"/><path d="M12 5v14"/></svg>') center / contain no-repeat;
|
|
102
|
-
}
|
|
103
|
-
.chip--sign:has(:checked)::after { rotate: 45deg; }
|
|
104
|
-
@media (prefers-reduced-motion: no-preference) { .chip--sign::after { transition: rotate var(--motion-slide); } }
|
|
105
|
-
|
|
106
90
|
/* ---- day strip: a week, one day selected, today a light tone ----
|
|
107
91
|
<div class="day-strip" role="tablist"><button class="day" role="tab" aria-selected="true"><span class="day__name">Thu</span><span class="day__num">16</span></button>…</div> */
|
|
108
92
|
.day-strip { display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--day-strip-gap, var(--sp-1)); }
|
|
@@ -125,7 +109,7 @@
|
|
|
125
109
|
color: var(--day-rest-ink, var(--card-muted)); /* an unpicked day at rest: the muted words of the ground it stands on (an opacity faded it under AA) */
|
|
126
110
|
}
|
|
127
111
|
.day__name { font: var(--day-name-font, var(--type-caption)); }
|
|
128
|
-
.day__num { font:
|
|
112
|
+
.day__num { font: var(--fw-bold) var(--fs-lg) / var(--lh-tight) var(--font-display); font-variant-numeric: tabular-nums; }
|
|
129
113
|
/* today: a light tone, no louder than a rest; the selected pill below wins when it is both (it comes after and weighs more) */
|
|
130
114
|
.day--today { background: var(--day-today-bg, var(--ink-tint)); color: var(--day-today-ink, var(--card-ink)); }
|
|
131
115
|
.day[aria-selected="true"] { background: var(--day-selected-bg, var(--accent)); color: var(--day-selected-ink, var(--on-accent)); }
|
|
@@ -144,7 +128,7 @@
|
|
|
144
128
|
display: grid;
|
|
145
129
|
place-items: center;
|
|
146
130
|
border-radius: 50%;
|
|
147
|
-
font:
|
|
131
|
+
font: var(--fw-medium) var(--fs-title) / var(--lh-solid) var(--font-ui);
|
|
148
132
|
font-variant-numeric: tabular-nums;
|
|
149
133
|
grid-column-start: var(--start, auto); /* --start on the 1st: weekday column 1–7 */
|
|
150
134
|
}
|
|
@@ -152,8 +136,8 @@
|
|
|
152
136
|
strong mark adds a ring of the accent. A stronger fill sat at the middle, where neither the ink nor --on-accent holds 4.5:1 */
|
|
153
137
|
.calendar__day--mark { background: var(--calendar-day-mark-bg, color-mix(in srgb, var(--accent) 12%, transparent)); }
|
|
154
138
|
.calendar__day--mark2 { background: var(--calendar-day-mark2-bg, color-mix(in srgb, var(--accent) 12%, transparent)); color: var(--calendar-day-mark2-ink, inherit); box-shadow: var(--calendar-day-mark2-shadow, inset 0 0 0 var(--border-w) var(--accent)); }
|
|
155
|
-
.calendar__day[aria-selected="true"] { background: var(--calendar-day-selected-bg, var(--accent)); color: var(--calendar-day-selected-ink, var(--on-accent)); font-weight:
|
|
156
|
-
.calendar__day:disabled { opacity:
|
|
139
|
+
.calendar__day[aria-selected="true"] { background: var(--calendar-day-selected-bg, var(--accent)); color: var(--calendar-day-selected-ink, var(--on-accent)); font-weight: var(--fw-bold); }
|
|
140
|
+
.calendar__day:disabled { opacity: var(--fade-dim); }
|
|
157
141
|
.calendar__day[aria-current="date"] { text-decoration: underline; text-underline-offset: 0.2em; }
|
|
158
142
|
|
|
159
143
|
/* ---- calendar weeks: a run of week rows that scrolls week by week, `show` rows in sight; the head sticks at the top of the box
|
|
@@ -166,12 +150,12 @@
|
|
|
166
150
|
overflow-y: auto;
|
|
167
151
|
overscroll-behavior: contain;
|
|
168
152
|
scroll-snap-type: y mandatory;
|
|
169
|
-
scroll-padding-block-start: var(--_weeks-lead,
|
|
153
|
+
scroll-padding-block-start: var(--_weeks-lead, 0rem);
|
|
170
154
|
overflow-anchor: none; /* a pick rerenders the rows; the browser must not shift the scroll to keep an anchor */
|
|
171
155
|
scrollbar-width: none;
|
|
172
156
|
}
|
|
173
157
|
.calendar--weeks::-webkit-scrollbar { display: none; }
|
|
174
|
-
.calendar__weeks-head { position: sticky; inset-block-start: 0; z-index:
|
|
158
|
+
.calendar__weeks-head { position: sticky; inset-block-start: 0; z-index: var(--z-over); display: grid; gap: var(--calendar-head-gap, var(--sp-2)); background: var(--calendar-weeks-head-bg, var(--card-bg)); }
|
|
175
159
|
.calendar__label { font: var(--calendar-label-font, var(--type-label)); color: var(--calendar-label-ink, inherit); justify-self: start; }
|
|
176
160
|
button.calendar__label { appearance: none; border: 0; padding: 0; background: none; cursor: pointer; border-radius: var(--sp-1); }
|
|
177
161
|
button.calendar__label:focus-visible { outline: var(--focus); outline-offset: var(--sp-0); }
|
|
@@ -196,14 +180,14 @@ button.calendar__label:focus-visible { outline: var(--focus); outline-offset: va
|
|
|
196
180
|
height: var(--mood-dot-size, var(--icon-xs));
|
|
197
181
|
border-radius: 50%;
|
|
198
182
|
background: var(--_mood, currentColor);
|
|
199
|
-
transition: scale
|
|
183
|
+
transition: scale var(--motion-quick) var(--ease), box-shadow var(--motion-quick) var(--ease);
|
|
200
184
|
}
|
|
201
185
|
.mood__opt:nth-child(1) { --_mood: var(--neg); }
|
|
202
186
|
.mood__opt:nth-child(2) { --_mood: color-mix(in srgb, var(--neg) 50%, var(--dot-b)); }
|
|
203
187
|
.mood__opt:nth-child(3) { --_mood: var(--dot-b); }
|
|
204
188
|
.mood__opt:nth-child(4) { --_mood: color-mix(in srgb, var(--pos) 50%, var(--dot-b)); }
|
|
205
189
|
.mood__opt:nth-child(5) { --_mood: var(--pos); }
|
|
206
|
-
.mood__opt:has(:checked) > .mood__dot { scale:
|
|
190
|
+
.mood__opt:has(:checked) > .mood__dot { scale: var(--scale-pick); box-shadow: 0 0 0 var(--sp-2) color-mix(in srgb, var(--_mood, currentColor) 25%, transparent); }
|
|
207
191
|
.mood__opt:has(:focus-visible) { outline: var(--focus); outline-offset: var(--sp-0); border-radius: 50%; }
|
|
208
192
|
|
|
209
193
|
/* ---- pin: big code entry, one digit per pill ----
|
|
@@ -243,7 +227,7 @@ button.calendar__label:focus-visible { outline: var(--focus); outline-offset: va
|
|
|
243
227
|
background-position: center;
|
|
244
228
|
background-repeat: no-repeat;
|
|
245
229
|
}
|
|
246
|
-
.pin--secret .pin__cell.is-fresh:not(:placeholder-shown) { animation: pin-flash var(--pin-flash-time,
|
|
230
|
+
.pin--secret .pin__cell.is-fresh:not(:placeholder-shown) { animation: pin-flash var(--pin-flash-time, var(--motion-flash)) var(--ease-step); }
|
|
247
231
|
@keyframes pin-flash { 0% { -webkit-text-fill-color: currentColor; background-size: 0 0; } }
|
|
248
232
|
.pin--secret .pin__cell::selection { background: transparent; } /* its digit is selected when the cell takes the cursor: nothing to show of it */
|
|
249
233
|
.pin__cell:focus { outline: none; }
|
|
@@ -254,12 +238,12 @@ button.calendar__label:focus-visible { outline: var(--focus); outline-offset: va
|
|
|
254
238
|
.pin--asleep .pin__cell:focus:placeholder-shown { background-image: none; animation: none; }
|
|
255
239
|
.pin__cell:is(:focus, [data-cursor]):placeholder-shown {
|
|
256
240
|
background-image: linear-gradient(currentColor, currentColor);
|
|
257
|
-
background-size: var(--pin-caret-w,
|
|
241
|
+
background-size: var(--pin-caret-w, var(--hairline-w)) var(--pin-caret-h, 1em);
|
|
258
242
|
background-position: center;
|
|
259
243
|
background-repeat: no-repeat;
|
|
260
244
|
}
|
|
261
245
|
@media (prefers-reduced-motion: no-preference) {
|
|
262
|
-
.pin__cell:is(:focus, [data-cursor]):placeholder-shown { animation: pin-caret
|
|
246
|
+
.pin__cell:is(:focus, [data-cursor]):placeholder-shown { animation: pin-caret var(--motion-blink) var(--ease-step) infinite; }
|
|
263
247
|
@keyframes pin-caret { 50% { background-size: 0 0; } }
|
|
264
248
|
}
|
|
265
249
|
|
|
@@ -271,13 +255,13 @@ button.calendar__label:focus-visible { outline: var(--focus); outline-offset: va
|
|
|
271
255
|
.composer { display: grid; gap: var(--composer-gap, var(--sp-3)); }
|
|
272
256
|
.composer__input {
|
|
273
257
|
width: 100%;
|
|
274
|
-
min-height: var(--composer-input-min-h,
|
|
258
|
+
min-height: var(--composer-input-min-h, calc(var(--tap-base) * 11 / 3));
|
|
275
259
|
resize: none;
|
|
276
260
|
border: 0;
|
|
277
261
|
padding: 0;
|
|
278
262
|
background: transparent;
|
|
279
263
|
color: inherit;
|
|
280
|
-
font: var(--composer-input-font,
|
|
264
|
+
font: var(--composer-input-font, var(--fw-bold) var(--fs-2xl) / var(--lh-h2) var(--font-display));
|
|
281
265
|
letter-spacing: var(--track-h2);
|
|
282
266
|
outline: none;
|
|
283
267
|
}
|
|
@@ -363,3 +347,11 @@ button.calendar__label:focus-visible { outline: var(--focus); outline-offset: va
|
|
|
363
347
|
-webkit-user-select: none; user-select: none;
|
|
364
348
|
flex: none;
|
|
365
349
|
}
|
|
350
|
+
|
|
351
|
+
/* ==== the pin's wrong code: red cells and one shake (#62: a block is written in its own file) ==== */
|
|
352
|
+
.pin.pin--error .pin__cell, .pin.pin--error .pin__cell:focus { border-color: var(--pin-error-border, var(--signal-error)); color: var(--pin-error-ink, var(--signal-error)); } /* ALL the cells, edge and digit — the one the cursor waits in too (Lh 2026-09-24); the wrong digits stay in red until the member types again */
|
|
353
|
+
/* a code that does not match (Pin match): the row shakes once, sideways, then the Pin empties itself for a new try (Lh 2026-09-25) */
|
|
354
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
355
|
+
.pin--shake { animation: pin-shake var(--pin-shake-time, var(--motion-shake)) var(--ease-in-out); }
|
|
356
|
+
}
|
|
357
|
+
@keyframes pin-shake { 0%, 100% { translate: 0; } 20%, 60% { translate: calc(-1 * var(--pin-shake-x, var(--sp-2))); } 40%, 80% { translate: var(--pin-shake-x, var(--sp-2)); } }
|
package/css/finish.css
CHANGED
|
@@ -33,28 +33,28 @@
|
|
|
33
33
|
============================================================ */
|
|
34
34
|
[data-finish="lit"] {
|
|
35
35
|
--_shade: var(--on-surface);
|
|
36
|
-
--finish-edge: inset 0
|
|
37
|
-
--finish-ring: 0 0 0
|
|
36
|
+
--finish-edge: inset 0 0.0625rem 0 rgb(255 255 255 / 0.55); /* the lit top edge */
|
|
37
|
+
--finish-ring: 0 0 0 0.0625rem color-mix(in srgb, var(--_shade) 7%, transparent); /* the hairline round a raised thing */
|
|
38
38
|
|
|
39
39
|
/* the three shadows every component already reads — layered: one close and crisp, one far and soft */
|
|
40
40
|
--shadow-card: var(--finish-edge), var(--finish-ring),
|
|
41
|
-
0
|
|
41
|
+
0 0.0625rem 0.125rem color-mix(in srgb, var(--_shade) 8%, transparent),
|
|
42
42
|
0 0.375rem 0.75rem -0.125rem color-mix(in srgb, var(--_shade) 8%, transparent),
|
|
43
43
|
0 1.25rem 2.5rem -0.75rem color-mix(in srgb, var(--_shade) 14%, transparent);
|
|
44
44
|
--shadow-float: var(--finish-edge), var(--finish-ring),
|
|
45
|
-
0
|
|
45
|
+
0 0.0625rem 0.125rem color-mix(in srgb, var(--_shade) 12%, transparent),
|
|
46
46
|
0 0.5rem 1.25rem -0.25rem color-mix(in srgb, var(--_shade) 22%, transparent);
|
|
47
47
|
--shadow-sheet: var(--finish-edge), var(--finish-ring),
|
|
48
|
-
0 -
|
|
48
|
+
0 -0.0625rem 0.125rem color-mix(in srgb, var(--_shade) 6%, transparent),
|
|
49
49
|
0 -0.75rem 2.5rem color-mix(in srgb, var(--_shade) 18%, transparent);
|
|
50
50
|
|
|
51
51
|
/* a control: its own small lift, and the sheen that runs down its face */
|
|
52
52
|
--finish-control: var(--finish-edge), var(--finish-ring),
|
|
53
|
-
0
|
|
53
|
+
0 0.0625rem 0.125rem color-mix(in srgb, var(--_shade) 12%, transparent),
|
|
54
54
|
0 0.25rem 0.5rem -0.125rem color-mix(in srgb, var(--_shade) 12%, transparent);
|
|
55
|
-
--finish-control-down: var(--finish-ring), inset 0
|
|
55
|
+
--finish-control-down: var(--finish-ring), inset 0 0.0625rem 0.125rem color-mix(in srgb, var(--_shade) 18%, transparent);
|
|
56
56
|
--finish-sheen: linear-gradient(to bottom, rgb(255 255 255 / 0.16), rgb(255 255 255 / 0) 60%);
|
|
57
|
-
--finish-sunk: inset 0
|
|
57
|
+
--finish-sunk: inset 0 0.0625rem 0.125rem color-mix(in srgb, var(--_shade) 14%, transparent), 0 0.0625rem 0 rgb(255 255 255 / 0.5);
|
|
58
58
|
|
|
59
59
|
--outline: color-mix(in srgb, currentColor 14%, transparent);
|
|
60
60
|
}
|
|
@@ -76,9 +76,9 @@
|
|
|
76
76
|
}
|
|
77
77
|
/* the main button throws its own colour */
|
|
78
78
|
[data-finish="lit"] .btn--primary,
|
|
79
|
-
[data-finish="lit"] .icon-btn--invert:not(.icon-btn-group > *) {
|
|
79
|
+
[data-finish="lit"] :is(.icon-btn--invert, .icon-btn--primary):not(.icon-btn-group > *) {
|
|
80
80
|
box-shadow: var(--finish-edge),
|
|
81
|
-
0
|
|
81
|
+
0 0.0625rem 0.125rem color-mix(in srgb, var(--_shade) 20%, transparent),
|
|
82
82
|
0 0.5rem 1rem -0.25rem color-mix(in srgb, var(--accent) 45%, transparent);
|
|
83
83
|
}
|
|
84
84
|
/* a peeked stack tab is the icon alone: no sheen and no shadow until its sheet is open (the fill fades with the sheet) */
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
}
|
|
93
93
|
[data-finish="lit"] .icon-btn-group { box-shadow: var(--finish-control); }
|
|
94
94
|
[data-finish="lit"] .toggle { box-shadow: var(--finish-sunk); }
|
|
95
|
-
[data-finish="lit"] .toggle::after { box-shadow: 0
|
|
95
|
+
[data-finish="lit"] .toggle::after { box-shadow: 0 0.0625rem 0.125rem color-mix(in srgb, var(--_shade) 35%, transparent); }
|
|
96
96
|
|
|
97
97
|
/* ---- sunk: what the member types into ---- */
|
|
98
98
|
[data-finish="lit"] :is(.field, .pin__cell) { box-shadow: var(--finish-sunk); }
|
|
@@ -110,12 +110,12 @@
|
|
|
110
110
|
}
|
|
111
111
|
[data-finish="print"] .card {
|
|
112
112
|
border: var(--border-w) solid var(--_ink);
|
|
113
|
-
box-shadow: var(--print-off,
|
|
113
|
+
box-shadow: var(--print-off, 0.1875rem) var(--print-off, 0.1875rem) 0 0 color-mix(in srgb, var(--card-ink) 28%, transparent);
|
|
114
114
|
isolation: isolate; /* the grain's blend stays inside the card */
|
|
115
115
|
}
|
|
116
116
|
/* the grain: a ::after, not ::before — .card--cover's scrim is its ::before. Over everything in the card (z-index 1, the foot's own level), touches pass through it */
|
|
117
117
|
[data-finish="print"] .card::after {
|
|
118
|
-
content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; z-index:
|
|
118
|
+
content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; z-index: var(--z-over);
|
|
119
119
|
opacity: var(--print-grain, 0.32); mix-blend-mode: multiply;
|
|
120
120
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.3 0 0 0 0 0.25 0 0 0 0 0.2 0 0 0 0.9 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
|
|
121
121
|
}
|
|
@@ -127,10 +127,11 @@
|
|
|
127
127
|
}
|
|
128
128
|
[data-finish="print"] :is(.btn, .chip) {
|
|
129
129
|
border-color: var(--_ink);
|
|
130
|
-
box-shadow:
|
|
130
|
+
box-shadow: 0.125rem 0.125rem 0 0 color-mix(in srgb, currentColor 35%, transparent);
|
|
131
131
|
}
|
|
132
|
-
[data-finish="print"] .
|
|
133
|
-
[data-finish="print"]
|
|
132
|
+
[data-finish="print"] .chip { border-color: var(--chip-border, var(--_ink)); } /* a holder that clears a chip's edge (a note's chips) clears it in print too */
|
|
133
|
+
[data-finish="print"] .btn--primary { box-shadow: 0.125rem 0.125rem 0 0 color-mix(in srgb, var(--card-ink) 60%, transparent); }
|
|
134
|
+
[data-finish="print"] :is(.btn, .chip):active { box-shadow: none; translate: 0.125rem 0.125rem; }
|
|
134
135
|
[data-finish="print"] .card__thumb { border-style: dashed; }
|
|
135
136
|
|
|
136
137
|
/* ============================================================
|
|
@@ -142,28 +143,28 @@
|
|
|
142
143
|
[data-finish="sticker"] { --outline: color-mix(in srgb, currentColor 18%, transparent); }
|
|
143
144
|
[data-finish="sticker"] .card {
|
|
144
145
|
box-shadow:
|
|
145
|
-
0 0 0 var(--sticker-cut,
|
|
146
|
-
0 calc(var(--sticker-cut,
|
|
147
|
-
0 calc(var(--sticker-cut,
|
|
146
|
+
0 0 0 var(--sticker-cut, 0.3125rem) #fff,
|
|
147
|
+
0 calc(var(--sticker-cut, 0.3125rem) + 0.25rem) 0 0 color-mix(in srgb, var(--on-surface) 16%, transparent),
|
|
148
|
+
0 calc(var(--sticker-cut, 0.3125rem) + 0.75rem) 1.25rem -0.5rem color-mix(in srgb, var(--on-surface) 22%, transparent);
|
|
148
149
|
}
|
|
149
150
|
[data-finish="sticker"] .card:not(.sheet, .modal, .card--away, .sheet-stack *, .card-list > *, .card-feed > *) { rotate: var(--sticker-tilt, 0.8deg); }
|
|
150
151
|
[data-finish="sticker"] .card:not(.sheet, .modal, .card--away, .sheet-stack *, .card-list > *, .card-feed > *):nth-of-type(even) { rotate: calc(-1 * var(--sticker-tilt, 0.8deg)); }
|
|
151
152
|
[data-finish="sticker"] .card-list { gap: var(--sp-5); }
|
|
152
153
|
[data-finish="sticker"] .btn {
|
|
153
|
-
box-shadow: 0
|
|
154
|
+
box-shadow: 0 0.1875rem 0 0 color-mix(in srgb, currentColor 30%, transparent);
|
|
154
155
|
border-color: color-mix(in srgb, currentColor 25%, transparent);
|
|
155
156
|
}
|
|
156
|
-
[data-finish="sticker"] .btn--primary { box-shadow: 0
|
|
157
|
-
[data-finish="sticker"] .btn:active { box-shadow: none; translate: 0
|
|
158
|
-
[data-finish="sticker"] .chip { box-shadow: 0 0 0
|
|
157
|
+
[data-finish="sticker"] .btn--primary { box-shadow: 0 0.1875rem 0 0 color-mix(in srgb, var(--btn-primary-bg, var(--accent)) 55%, var(--on-surface)); }
|
|
158
|
+
[data-finish="sticker"] .btn:active { box-shadow: none; translate: 0 0.1875rem; }
|
|
159
|
+
[data-finish="sticker"] .chip { box-shadow: 0 0 0 0.1875rem #fff; }
|
|
159
160
|
|
|
160
161
|
/* ============================================================
|
|
161
162
|
ink — a poster / comic print: --ink-w of the surface's ink round every boundary and control, and a hard
|
|
162
163
|
offset of --ink-off in the same ink. The two wireframe borders come back as that line.
|
|
163
164
|
============================================================ */
|
|
164
165
|
[data-finish="ink"] { --card-border: var(--on-surface); --action-border: var(--on-surface); --outline: currentColor; }
|
|
165
|
-
[data-finish="ink"] .card { border: var(--ink-w,
|
|
166
|
-
[data-finish="ink"] :is(.btn, .chip, .icon-btn:not(.icon-btn-group > *)) { border: var(--ink-w,
|
|
167
|
-
[data-finish="ink"] .btn--primary { border-color: var(--on-surface); box-shadow:
|
|
168
|
-
[data-finish="ink"] .toggle { box-shadow:
|
|
169
|
-
[data-finish="ink"] .card__thumb { border-width: var(--ink-w,
|
|
166
|
+
[data-finish="ink"] .card { border: var(--ink-w, 0.15625rem) solid var(--on-surface); box-shadow: var(--ink-off, 0.3125rem) var(--ink-off, 0.3125rem) 0 0 var(--on-surface); }
|
|
167
|
+
[data-finish="ink"] :is(.btn, .chip, .icon-btn:not(.icon-btn-group > *)) { border: var(--ink-w, 0.15625rem) solid currentColor; box-shadow: 0.1875rem 0.1875rem 0 0 currentColor; }
|
|
168
|
+
[data-finish="ink"] .btn--primary { border-color: var(--on-surface); box-shadow: 0.1875rem 0.1875rem 0 0 var(--on-surface); }
|
|
169
|
+
[data-finish="ink"] .toggle { box-shadow: 0.125rem 0.125rem 0 0 var(--on-surface); }
|
|
170
|
+
[data-finish="ink"] .card__thumb { border-width: var(--ink-w, 0.15625rem); }
|
package/css/forms.css
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
.field select,
|
|
24
24
|
.field textarea,
|
|
25
25
|
.field--rows {
|
|
26
|
-
font: var(--field-font,
|
|
26
|
+
font: var(--field-font, var(--fw-regular) var(--fs-lg) / var(--lh-field) var(--font-ui)); /* 26: the words being typed read a size up from body (Lh 2026-09-22); the Composer already does. .field--rows too, so 1lh is the textarea's line for its icon */
|
|
27
27
|
}
|
|
28
28
|
.field input,
|
|
29
29
|
.field select,
|
|
@@ -37,17 +37,16 @@
|
|
|
37
37
|
caret-color: currentColor;
|
|
38
38
|
}
|
|
39
39
|
.field input::placeholder,
|
|
40
|
-
.field textarea::placeholder { color: inherit; opacity:
|
|
40
|
+
.field textarea::placeholder { color: inherit; opacity: var(--fade-hint); font-size: calc(1em * var(--_ph-fit, 1)); } /* --_ph-fit: Field's measure — a placeholder longer than the box shrinks to show whole (Lh 2026-09-25) */
|
|
41
41
|
/* several lines in the same frame (Field rows): the textarea is as tall as its `rows` × line, the frame grows round it, the icon and the action stay at the top (Lh 2026-10-19) */
|
|
42
42
|
.field--rows { align-items: flex-start; padding-block: var(--field-rows-pad-y, var(--sp-3)); }
|
|
43
43
|
.field textarea { flex: 1; resize: none; display: block; }
|
|
44
|
-
.field--rows > .icon { margin
|
|
44
|
+
.field--rows > .icon { --icon-margin: calc((1lh - var(--icon-sm)) / 2) 0 0; } /* centred on the first line */
|
|
45
45
|
/* the field the cursor is in: its own border goes full ink, in every palette (the coloured ones fade it to 25% at rest) */
|
|
46
46
|
.field:has(:focus, [data-cursor]) { border-color: var(--field-active-border, currentColor); } /* [data-cursor]: SheetSteps holds the phone's keyboard for this field */
|
|
47
47
|
|
|
48
48
|
/* field with its action inside: date pick, send, go — the button sits flush right */
|
|
49
49
|
.field--action { padding-right: var(--sp-1); min-height: var(--field-action-min-h, var(--tap-lg)); }
|
|
50
|
-
.field--action > .icon-btn { margin-left: auto; }
|
|
51
50
|
|
|
52
51
|
/* colored palettes drop the visible outline elsewhere — fields keep one */
|
|
53
52
|
[data-palette] .field:not(:has(:focus)) { border-color: color-mix(in srgb, currentColor 25%, transparent); }
|
|
@@ -72,22 +71,15 @@
|
|
|
72
71
|
display: grid;
|
|
73
72
|
place-items: center;
|
|
74
73
|
font-size: var(--add-row-plus-font-size, var(--fs-md));
|
|
75
|
-
line-height:
|
|
74
|
+
line-height: var(--lh-solid);
|
|
76
75
|
}
|
|
77
|
-
.add-row__plus .icon {
|
|
76
|
+
.add-row__plus .icon { --icon-size: var(--icon-xs); }
|
|
78
77
|
|
|
79
78
|
/* ---- a wrong value, and the line that says so (Lh 2026-09-24) ----
|
|
80
79
|
--signal-error is the one colour the wireframe has; it never speaks alone — the line carries an icon and words.
|
|
81
80
|
<p class="form-note form-note--error" role="alert"><svg class="icon icon--xs">…</svg>Not a phone number</p>
|
|
82
81
|
<p class="form-note form-note--busy" role="status"><svg …/>Sending the code…</p> (the ring turns) */
|
|
83
82
|
.field.field--error, [data-palette] .field.field--error { border-color: var(--field-error-border, var(--signal-error)); }
|
|
84
|
-
.pin.pin--error .pin__cell, .pin.pin--error .pin__cell:focus { border-color: var(--pin-error-border, var(--signal-error)); color: var(--pin-error-ink, var(--signal-error)); } /* ALL the cells, edge and digit — the one the cursor waits in too (Lh 2026-09-24); the wrong digits stay in red until the member types again */
|
|
85
|
-
/* a code that does not match (Pin match): the row shakes once, sideways, then the Pin empties itself for a new try (Lh 2026-09-25) */
|
|
86
|
-
@media (prefers-reduced-motion: no-preference) {
|
|
87
|
-
.pin--shake { animation: pin-shake var(--pin-shake-time, 0.4s) ease-in-out; }
|
|
88
|
-
}
|
|
89
|
-
@keyframes pin-shake { 0%, 100% { translate: 0; } 20%, 60% { translate: calc(-1 * var(--pin-shake-x, var(--sp-2))); } 40%, 80% { translate: var(--pin-shake-x, var(--sp-2)); } }
|
|
90
83
|
.form-note { display: flex; align-items: center; justify-content: center; gap: var(--sp-2); margin: 0; font: var(--form-note-font, var(--type-caption)); color: var(--form-note-ink, var(--card-muted)); text-align: center; }
|
|
91
|
-
.form-note > .icon { flex: none; }
|
|
92
84
|
.form-note--error { color: var(--form-note-error-ink, var(--signal-error)); }
|
|
93
|
-
@media (prefers-reduced-motion: no-preference) { .form-note--busy > .icon {
|
|
85
|
+
@media (prefers-reduced-motion: no-preference) { .form-note--busy > .icon { --icon-spin: turn var(--motion-spin) var(--ease-linear) infinite; } } /* `turn`: tokens.css */
|
package/css/journey.css
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
.route__time { grid-row: 3; align-self: start; }
|
|
23
23
|
|
|
24
24
|
.route__code { font: var(--route-code-font, var(--type-h2)); letter-spacing: var(--track-h2); display: flex; align-items: center; gap: var(--route-code-gap, var(--sp-3)); }
|
|
25
|
-
.route__code::after, .route__point--end .route__code::before { content: ""; flex: 1; border-top: var(--rule-w) dotted currentColor; opacity:
|
|
25
|
+
.route__code::after, .route__point--end .route__code::before { content: ""; flex: 1; border-top: var(--rule-w) dotted currentColor; opacity: var(--fade-mild); }
|
|
26
26
|
.route__point--end .route__code::after { content: none; }
|
|
27
27
|
.route__time { font: var(--route-time-font, var(--type-body)); font-variant-numeric: tabular-nums; }
|
|
28
28
|
.route__place { font: var(--route-place-font, var(--type-caption)); color: var(--route-place-ink, var(--card-muted)); }
|
|
@@ -43,17 +43,19 @@
|
|
|
43
43
|
/* the label is the badge's own ink, smaller: a badge is a small fill of any colour (a palette paints it yellow), and only its own ink is
|
|
44
44
|
sure to hold 4.5:1 on it; --dim faded it to 2.4:1 */
|
|
45
45
|
.tile-badge__label { font: var(--tile-badge-label-font, var(--type-caption)); color: var(--tile-badge-label-ink, inherit); }
|
|
46
|
-
.tile-badge__value { font:
|
|
46
|
+
.tile-badge__value { font: var(--fw-heavy) var(--fs-lg) / var(--lh-tight) var(--font-display); font-variant-numeric: tabular-nums; }
|
|
47
47
|
|
|
48
48
|
/* plain: no fill — a date box beside a title (Jun / 18) */
|
|
49
49
|
.tile-badge--plain { background: transparent; --dark: inherit; color: inherit; padding: 0; min-width: var(--tile-badge-plain-min-w, var(--tap-sm)); }
|
|
50
|
-
.tile-badge--plain .tile-badge__value { font:
|
|
50
|
+
.tile-badge--plain .tile-badge__value { font: var(--fw-heavy) var(--fs-h1) / var(--lh-solid) var(--font-display); }
|
|
51
51
|
|
|
52
52
|
/* stretch: a date in a head (Lh 2026-10-19) — as tall as the title block beside it and no taller (the head stretches it; size
|
|
53
53
|
containment keeps its own words from adding height). Its height picks the form: short (a one-line title) = two lines, the day name
|
|
54
|
-
over the number and the month on one line; tall (a two-line title) = three lines, day · number · month.
|
|
54
|
+
over the number and the month on one line; tall (a two-line title) = three lines, day · number · month. It grows no taller than
|
|
55
|
+
its three lines (2026-10-21, timebank: beside a four-line title it was a tall empty block); held there, it stands at the head's top. */
|
|
55
56
|
.tile-badge--stretch {
|
|
56
57
|
align-self: stretch;
|
|
58
|
+
max-block-size: calc((2 * var(--fs-caption) + var(--fs-lg)) * var(--tile-badge-line, var(--lh-badge)) + 2 * var(--sp-3));
|
|
57
59
|
container-type: size;
|
|
58
60
|
inline-size: calc(var(--fs-lg) * 3.25);
|
|
59
61
|
grid-template-columns: auto auto;
|
|
@@ -63,11 +65,11 @@
|
|
|
63
65
|
column-gap: var(--sp-1);
|
|
64
66
|
row-gap: 0;
|
|
65
67
|
padding-block: var(--sp-3);
|
|
66
|
-
line-height: var(--tile-badge-line,
|
|
68
|
+
line-height: var(--tile-badge-line, var(--lh-badge));
|
|
67
69
|
}
|
|
68
70
|
.tile-badge--stretch > * { line-height: inherit; }
|
|
69
71
|
.tile-badge--stretch > :first-child { grid-column: 1 / -1; }
|
|
70
|
-
@container (min-height:
|
|
72
|
+
@container (min-height: 3.5rem) { /* just under the three lines' own height, the most the badge grows to */
|
|
71
73
|
.tile-badge--stretch > * { grid-column: 1 / -1; }
|
|
72
74
|
}
|
|
73
75
|
|
package/css/layover.css
CHANGED
|
@@ -31,14 +31,14 @@
|
|
|
31
31
|
sets open={false}).
|
|
32
32
|
Reduced motion: the finished state, no beats; closing fires at once. */
|
|
33
33
|
.modal {
|
|
34
|
-
--drawer-h:
|
|
34
|
+
--drawer-h: calc(var(--tap-base) * 14 / 3);
|
|
35
35
|
position: absolute; /* at the stage's centre, and kept there as it grows: its middle is pinned at 50% and */
|
|
36
36
|
top: 50%; /* translate -50% of its OWN height re-centres it on every height. NOT inset 0 + margin auto + */
|
|
37
37
|
inset-inline: 0; /* align-self: center — Safari 18 ignores align-self on an absolute box in a block container, */
|
|
38
38
|
margin-inline: auto; /* so the card stretched to the whole stage (iOS 18.6, Lh 2026-09-24); nor height: fit-content */
|
|
39
39
|
translate: 0 -50%;
|
|
40
40
|
width: calc(100% - 2 * var(--screen-pad));
|
|
41
|
-
z-index: 2; /* over the dim stage's scrim (z 1) */
|
|
41
|
+
z-index: var(--z-over-2); /* over the dim stage's scrim (z 1) */
|
|
42
42
|
max-height: calc(100cqh - 2 * var(--sp-5)); /* cqh: the stage (a size container) */
|
|
43
43
|
padding: 0; /* the parts pad themselves */
|
|
44
44
|
border: 0; /* no frame on the modal (Lh 2026-09-16) — its edge is the shadow */
|
|
@@ -83,18 +83,17 @@
|
|
|
83
83
|
}
|
|
84
84
|
/* the CONFIRM: a Modal with no ModalBody: the ModalAsk IS the card, as tall as its words (no fixed band, no second beat) */
|
|
85
85
|
.modal:not(:has(> .modal__lift)) > .modal__drawer { height: auto; padding-block: var(--modal-confirm-pad-y, var(--sp-6)); animation: none; }
|
|
86
|
-
.modal__drawer .t-caption {
|
|
86
|
+
.modal__drawer .t-caption { --t-caption-ink: var(--modal-drawer-caption-ink, var(--card-muted)); }
|
|
87
87
|
.modal__drawer > h2:focus { outline: none; } /* the question takes the cursor when the modal arrives (for a screen reader, the keyboard's way in) — it is not a control: no ring */
|
|
88
88
|
/* the answers as WORD buttons (a BtnRow of Btns; Lh 2026-10-11): the row fills the ask with room over it and each button keeps its words on one
|
|
89
89
|
line — left to its words' width the row squeezed two buttons into round blobs, their words on two lines. A quiet button is an outline only,
|
|
90
90
|
so on the ask its edge is the ask's ink at full strength (light on the dark end, dark on --light). The BtnTrio of round buttons is not touched. */
|
|
91
|
-
.modal__drawer
|
|
92
|
-
.modal__drawer .btn
|
|
93
|
-
.modal__drawer .icon-btn {
|
|
94
|
-
.modal__drawer .icon-btn--invert { background: var(--accent); color: var(--on-accent); border-color: transparent; width: var(--tap-lg); height: var(--tap-lg); }
|
|
91
|
+
.modal__drawer .btn--quiet { --btn-quiet-border: var(--modal-drawer-quiet-border, currentColor); }
|
|
92
|
+
.modal__drawer .icon-btn { --icon-btn-bg: transparent; --icon-btn-ink: currentColor; --icon-btn-border: var(--ink-rail); }
|
|
93
|
+
.modal__drawer .icon-btn--invert { --icon-btn-size: var(--tap-lg); }
|
|
95
94
|
@media (prefers-reduced-motion: no-preference) {
|
|
96
|
-
.modal { animation: modal-drop calc(2 * var(--motion-sheet)) ease both; }
|
|
97
|
-
.modal__drawer { animation: modal-open calc(2 * var(--motion-sheet)) ease both; }
|
|
95
|
+
.modal { animation: modal-drop calc(2 * var(--motion-sheet)) var(--ease) both; }
|
|
96
|
+
.modal__drawer { animation: modal-open calc(2 * var(--motion-sheet)) var(--ease) both; }
|
|
98
97
|
@keyframes modal-drop {
|
|
99
98
|
0% { translate: 0 calc(-50% - 100cqh); } /* above the stage */
|
|
100
99
|
50%, 100% { translate: 0 -50%; } /* 1. at the centre — and it stays: beat 2 is the drawer's */
|
|
@@ -109,8 +108,8 @@
|
|
|
109
108
|
.btn-trio__dots {
|
|
110
109
|
width: var(--btn-trio-dots-w, var(--sp-5));
|
|
111
110
|
height: var(--btn-trio-dots-h, var(--sp-1));
|
|
112
|
-
background: radial-gradient(circle, currentColor var(--sp-0), transparent calc(var(--sp-0) +
|
|
113
|
-
opacity:
|
|
111
|
+
background: radial-gradient(circle, currentColor var(--sp-0), transparent calc(var(--sp-0) + var(--px) / 2)) 0 0 / calc(var(--sp-5) / 2) 100% repeat-x;
|
|
112
|
+
opacity: var(--fade-soft);
|
|
114
113
|
}
|
|
115
114
|
|
|
116
115
|
/* ---- popover menu: a card anchored to its button, rows of icon + label ----
|
|
@@ -133,7 +132,7 @@
|
|
|
133
132
|
border-radius: var(--menu-radius, var(--r-card));
|
|
134
133
|
--menu-pad: var(--sp-2); /* published: a row's radius is concentric with the panel's */
|
|
135
134
|
padding: var(--menu-pad);
|
|
136
|
-
min-width:
|
|
135
|
+
min-width: calc(var(--tap-base) * 4);
|
|
137
136
|
align-content: start; /* rows keep their own height: WebKit stretches a popover grid's rows to the whole room under its anchor (iOS 26.5, 2026-10-08) */
|
|
138
137
|
--_menu-max: min(60dvh, calc(100dvh - 2 * var(--sp-5)));
|
|
139
138
|
max-height: var(--menu-max-h, var(--_menu-max)); /* a long list (twenty neighbours) scrolls inside the panel — it ran off the screen's foot, the last names out of reach (timebank, 2026-10-08) */
|
|
@@ -167,7 +166,7 @@
|
|
|
167
166
|
.menu[popover] {
|
|
168
167
|
position-area: block-end span-inline-end;
|
|
169
168
|
margin-top: var(--sp-2);
|
|
170
|
-
min-width: max(
|
|
169
|
+
min-width: max(calc(var(--tap-base) * 4), anchor-size(width)); /* at least as wide as its trigger */
|
|
171
170
|
position-try-fallbacks: flip-block, flip-inline;
|
|
172
171
|
}
|
|
173
172
|
.menu--end[popover] { position-area: block-end span-inline-start; }
|
|
@@ -200,11 +199,11 @@
|
|
|
200
199
|
.banner__summary {
|
|
201
200
|
list-style: none;
|
|
202
201
|
display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2);
|
|
203
|
-
padding-block: var(--banner-summary-pad-y, calc(var(--sp-base) * 1.5)); font: var(--banner-summary-font, var(--type-caption)); font-weight:
|
|
202
|
+
padding-block: var(--banner-summary-pad-y, calc(var(--sp-base) * 1.5)); font: var(--banner-summary-font, var(--type-caption)); font-weight: var(--fw-regular);
|
|
204
203
|
}
|
|
205
204
|
.banner__summary::-webkit-details-marker { display: none; }
|
|
206
|
-
.banner__summary .icon {
|
|
207
|
-
.banner[open] .banner__summary .icon {
|
|
205
|
+
.banner__summary .icon { --icon-motion: rotate var(--motion-quick) var(--ease); }
|
|
206
|
+
.banner[open] .banner__summary .icon { --icon-turn: 180deg; }
|
|
208
207
|
/* the band's words never run past it: one column that cannot be wider than the band (a grid track is as wide as its longest
|
|
209
208
|
word otherwise), and a word with no break in it — a link — breaks where it must (mailpool, Lh 2026-10-01) */
|
|
210
209
|
.banner__body { display: grid; grid-template-columns: minmax(0, 1fr); overflow-wrap: anywhere; gap: var(--banner-body-gap, var(--sp-1)); padding-bottom: var(--sp-4); }
|
|
@@ -212,7 +211,7 @@
|
|
|
212
211
|
@supports (interpolate-size: allow-keywords) {
|
|
213
212
|
@media (prefers-reduced-motion: no-preference) {
|
|
214
213
|
.banner { interpolate-size: allow-keywords; }
|
|
215
|
-
.banner::details-content { block-size: 0; overflow: clip; transition: block-size var(--motion-quick) ease, content-visibility var(--motion-quick) allow-discrete; }
|
|
214
|
+
.banner::details-content { block-size: 0; overflow: clip; transition: block-size var(--motion-quick) var(--ease), content-visibility var(--motion-quick) allow-discrete; }
|
|
216
215
|
.banner[open]::details-content { block-size: auto; }
|
|
217
216
|
}
|
|
218
217
|
}
|
|
@@ -271,7 +270,7 @@
|
|
|
271
270
|
/* aria-current="false" is the correct way to mark the OTHER tabs, so the
|
|
272
271
|
bare attribute selector lights every one of them up */
|
|
273
272
|
.float-bar__item[aria-current]:not([aria-current="false"]) { background: var(--accent); color: var(--on-accent); }
|
|
274
|
-
.float-bar > .icon-btn {
|
|
273
|
+
.float-bar > .icon-btn { --icon-btn-size: var(--bar-h); --icon-btn-shadow: var(--shadow-float); }
|
|
275
274
|
|
|
276
275
|
/* ---- callout: a small card with a tail — over a map, a media, a mascot ----
|
|
277
276
|
<div class="callout" style="top: 30%; left: 40%"><span class="callout__title">Telok Ayer Park</span><span class="callout__sub">1.2 km</span></div> */
|
|
@@ -280,7 +279,7 @@
|
|
|
280
279
|
display: grid;
|
|
281
280
|
gap: var(--callout-gap, var(--sp-0));
|
|
282
281
|
width: max-content;
|
|
283
|
-
max-width:
|
|
282
|
+
max-width: calc(var(--tap-base) * 5);
|
|
284
283
|
padding: var(--callout-pad-y, var(--sp-3)) var(--callout-pad-x, var(--sp-4));
|
|
285
284
|
border: var(--border-w) solid var(--callout-border, var(--action-border));
|
|
286
285
|
border-radius: var(--callout-radius, var(--r-card));
|
|
@@ -313,7 +312,7 @@
|
|
|
313
312
|
<p class="splash__text">…</p></div></section>
|
|
314
313
|
The group's MIDDLE is on --screen-centre (40% down), the same line a centred card uses. The mark is the app's own content —
|
|
315
314
|
a lottie box often carries empty room around its drawing — the app sets the knobs below, cardds does not guess it. */
|
|
316
|
-
.splash { position: relative; background: var(--splash-bg, var(--surface)); transition: opacity var(--motion-sheet) ease; }
|
|
315
|
+
.splash { position: relative; background: var(--splash-bg, var(--surface)); transition: opacity var(--motion-sheet) var(--ease); }
|
|
317
316
|
.splash--leaving { opacity: 0; }
|
|
318
317
|
.splash__group {
|
|
319
318
|
position: absolute; inset-inline: var(--screen-pad); top: var(--splash-at, var(--screen-centre)); translate: 0 -50%;
|
|
@@ -335,13 +334,13 @@
|
|
|
335
334
|
position: fixed; inset-inline: 0; top: calc(var(--sp-3) + var(--safe-top));
|
|
336
335
|
max-width: var(--screen-w); margin-inline: auto; padding-inline: var(--screen-pad, var(--sp-4));
|
|
337
336
|
display: grid; justify-items: center;
|
|
338
|
-
z-index: calc(var(--z-top) +
|
|
337
|
+
z-index: calc(var(--z-top) + var(--z-over));
|
|
339
338
|
pointer-events: none; visibility: hidden;
|
|
340
339
|
translate: 0 calc(var(--_out) * (100% + var(--sp-8) + var(--safe-top)));
|
|
341
|
-
transition: translate var(--motion-sheet) ease, visibility 0s var(--motion-sheet);
|
|
340
|
+
transition: translate var(--motion-sheet) var(--ease), visibility 0s var(--motion-sheet);
|
|
342
341
|
}
|
|
343
342
|
.screen--fill > .snackbar, .sheet-stage > .snackbar { position: absolute; }
|
|
344
|
-
.snackbar--bottom { --_out: 1; top: auto; bottom: calc(var(--sp-3) + var(--bottom-h,
|
|
343
|
+
.snackbar--bottom { --_out: 1; top: auto; bottom: calc(var(--sp-3) + var(--bottom-h, 0rem) + max(var(--safe-bottom), var(--kb, 0rem))); }
|
|
345
344
|
.snackbar--open { translate: 0; visibility: visible; transition-delay: 0s; }
|
|
346
345
|
.snackbar__body {
|
|
347
346
|
display: flex; align-items: center; gap: var(--snackbar-gap, var(--sp-3));
|
|
@@ -356,8 +355,11 @@
|
|
|
356
355
|
font: inherit; text-align: start;
|
|
357
356
|
pointer-events: auto;
|
|
358
357
|
}
|
|
359
|
-
.snackbar__body > .icon {
|
|
358
|
+
.snackbar__body > .icon { --icon-ink: var(--snackbar-icon-ink, var(--signal-ok)); }
|
|
360
359
|
.snackbar__words { display: grid; min-width: 0; overflow-wrap: anywhere; }
|
|
361
360
|
.snackbar__text { font: var(--snackbar-text-font, var(--type-body)); }
|
|
362
361
|
.snackbar__caption { font: var(--snackbar-caption-font, var(--type-caption)); color: var(--snackbar-caption-ink, inherit); } /* on the signal's soft ground the full ink: a muted shade there fell under AA */
|
|
363
362
|
@media (prefers-reduced-motion: reduce) { .snackbar { transition: none; } }
|
|
363
|
+
|
|
364
|
+
/* ---- where it sits in what actions.css draws (docs/reference.md rule 15) ---- */
|
|
365
|
+
.dropdown--end .menu[popover] { position-area: block-end span-inline-start; } /* right-aligned trigger: panel grows leftwards (= .menu--end, layover.css) */
|
package/css/lists.css
CHANGED
|
@@ -34,15 +34,15 @@
|
|
|
34
34
|
.row__meta { font: var(--row-meta-font, var(--type-caption)); color: var(--row-meta-ink, var(--card-muted)); display: flex; align-items: center; gap: var(--row-meta-gap, var(--sp-1)); }
|
|
35
35
|
.row__end { margin-left: auto; text-align: right; display: grid; gap: var(--row-end-gap, var(--sp-0)); justify-items: end; flex: none; }
|
|
36
36
|
.row--lg { min-height: var(--row-lg-min-h, var(--fab)); } /* menu rows: a taller target, round arrow at the end; .rows gives them more air */
|
|
37
|
-
.row--lg .row__title { font:
|
|
37
|
+
.row--lg .row__title { font: var(--fw-bold) var(--fs-lg) / var(--lh-h1) var(--font-display); }
|
|
38
38
|
/* a row that EXPANDS (Lh 2026-09-22): the row is a <details>' summary, what it shows comes out under it —
|
|
39
39
|
who liked a postcard, the rest of a list. An end chevron turns when open. The app owns the list.
|
|
40
40
|
<details class="row-expand"><summary class="row">…lead · body · end…</summary><div class="row-expand__more">…</div></details> */
|
|
41
41
|
.row-expand { display: block; }
|
|
42
42
|
.row-expand > summary { list-style: none; }
|
|
43
43
|
.row-expand > summary::-webkit-details-marker { display: none; }
|
|
44
|
-
.row-expand > summary > .icon:last-child {
|
|
45
|
-
.row-expand[open] > summary > .icon:last-child {
|
|
44
|
+
.row-expand > summary > .icon:last-child { --icon-motion: rotate var(--motion-slide); }
|
|
45
|
+
.row-expand[open] > summary > .icon:last-child { --icon-turn: 180deg; }
|
|
46
46
|
.row-expand__more { padding-top: var(--row-expand-gap, var(--sp-3)); }
|
|
47
47
|
/* a finished item in a checklist (a to-do list, an onboarding "complete your introduction" list):
|
|
48
48
|
the words go muted, a filled tick sits at the end, and the row is no longer a tap target —
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
.kv-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(var(--tile-min), 100%), 1fr)); gap: var(--kv-grid-gap, var(--sp-4)); }
|
|
92
92
|
.kv-grid > .kv-cell + .kv-cell { border-left: var(--border-w) solid var(--hairline); padding-left: var(--sp-4); }
|
|
93
93
|
.kv-cell { display: grid; gap: var(--kv-cell-gap, var(--sp-0)); align-content: start; min-width: 0; }
|
|
94
|
-
.kv-cell > .icon { margin
|
|
94
|
+
.kv-cell > .icon { --icon-margin: 0 0 var(--sp-1); }
|
|
95
95
|
.kv-cell__val { font: var(--kv-cell-val-font, var(--type-h2)); letter-spacing: var(--track-h2); font-variant-numeric: tabular-nums; }
|
|
96
96
|
.kv-cell__key { font: var(--kv-cell-key-font, var(--type-caption)); color: var(--kv-cell-key-ink, var(--card-muted)); }
|
|
97
97
|
|
|
@@ -136,7 +136,7 @@
|
|
|
136
136
|
}
|
|
137
137
|
.bubble__meta { display: flex; align-items: center; gap: var(--bubble-meta-gap, var(--sp-1)); font: var(--bubble-meta-font, var(--type-caption)); color: var(--bubble-meta-ink, var(--card-muted)); }
|
|
138
138
|
.bubble--right > .bubble__meta { justify-self: end; }
|
|
139
|
-
.bubble__meta > .icon {
|
|
139
|
+
.bubble__meta > .icon { --icon-ink: var(--bubble-meta-icon-ink, var(--accent-ink)); }
|
|
140
140
|
|
|
141
141
|
/* ---- timeline: a hairline with date chips, entries to the right ----
|
|
142
142
|
<ol class="timeline"><li class="timeline__item"><span class="timeline__mark">Wed 14</span><p class="t-body">…</p></li>…</ol> */
|
|
@@ -207,5 +207,7 @@
|
|
|
207
207
|
.bullets { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--bullets-gap, var(--sp-3)); font: var(--bullets-font, var(--type-body)); }
|
|
208
208
|
.bullets__item { display: flex; align-items: start; gap: var(--bullets-pic-gap, var(--sp-3)); min-width: 0; }
|
|
209
209
|
.bullets__pic { flex: none; inline-size: var(--bullets-pic-size, 1lh); block-size: var(--bullets-pic-size, 1lh); min-height: 0; object-fit: contain; border-radius: var(--bullets-pic-radius, 0rem); display: grid; place-items: center; }
|
|
210
|
-
.bullets__pic.ph { border-radius: var(--bullets-pic-radius, 0rem); }
|
|
211
210
|
.bullets__text { flex: 1; min-width: 0; }
|
|
211
|
+
|
|
212
|
+
/* ---- where it sits in what sheet.css draws (docs/reference.md rule 15) ---- */
|
|
213
|
+
.sheet-step__inner > .link { justify-self: center; } /* a link of its own row in a step (skip, "change number", "set PIN again"): centred under the step, as the skip (Lh 2026-09-25) */
|