@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/card.css
CHANGED
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
card once `sent` and a `Card` with `leave` read the same two knobs; the time is --motion-sheet. `.card--leaver` is a card whose app may ask it
|
|
30
30
|
to go (it holds the transition, so it comes back as it went); `.card--away` is one that has been asked. A knob of the time would read dead:
|
|
31
31
|
the knob walk switches motion off */
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
.card--leaver { transition: translate var(--motion-sheet) var(--ease), rotate var(--motion-sheet) var(--ease); }
|
|
33
|
+
.card--away { --_y: calc(var(--leave-rise, 160%) * -1); rotate: var(--leave-turn, calc(var(--tilt-base) * -5)); }
|
|
34
34
|
.card--away { translate: 0 var(--_y); }
|
|
35
|
-
@media (prefers-reduced-motion: reduce) {
|
|
35
|
+
@media (prefers-reduced-motion: reduce) { .card--leaver { transition: none; } }
|
|
36
36
|
|
|
37
37
|
/* each tone is a fill and a side; its words and glyphs follow from the side (tokens.css) */
|
|
38
38
|
.card--2 { --card-bg: var(--card-2-bg); --dark: var(--card-2-dark); }
|
|
@@ -49,18 +49,13 @@
|
|
|
49
49
|
multi-line title can opt back out with .card__head--top. */
|
|
50
50
|
.card__head {
|
|
51
51
|
display: flex;
|
|
52
|
-
flex-wrap: wrap;
|
|
52
|
+
flex-wrap: var(--card-head-wrap, wrap); /* the caption takes a line of its own — no wrapper div */
|
|
53
53
|
align-items: center;
|
|
54
54
|
justify-content: space-between;
|
|
55
55
|
column-gap: var(--card-head-col-gap, var(--sp-3));
|
|
56
56
|
row-gap: var(--card-head-row-gap, var(--sp-0));
|
|
57
|
+
min-height: var(--card-head-min-h, auto);
|
|
57
58
|
}
|
|
58
|
-
/* flat head markup (Lh 2026-09-16 — no <p>, no wrapper, only padding and gap tokens):
|
|
59
|
-
<div class="card__head"><h2 class="t-h2">…</h2><span class="t-caption t-muted">…</span><button class="icon-btn icon-btn--sm">…</button></div>
|
|
60
|
-
The heading and the far-right thing share the first row; a caption sits on
|
|
61
|
-
a row below (order 1), whatever the DOM order — so an author writes the
|
|
62
|
-
words in reading order. */
|
|
63
|
-
.card__head > :is(.t-caption, .t-body) { flex: 1 1 100%; order: 1; margin: 0; }
|
|
64
59
|
.card__head--top { align-items: flex-start; }
|
|
65
60
|
|
|
66
61
|
.card__media { border-radius: var(--card-media-radius, var(--r-media)); overflow: hidden; position: relative; } /* relative: corner badges */
|
|
@@ -80,12 +75,23 @@
|
|
|
80
75
|
.card__head > :is(h1, h2, h3, div, p):first-child { flex: 1; min-width: 0; }
|
|
81
76
|
|
|
82
77
|
/* Skeleton head — the heading in a card's OWN head, and only there.
|
|
83
|
-
The heading wraps
|
|
84
|
-
2026-
|
|
85
|
-
|
|
78
|
+
The heading wraps, no squeeze, up to three lines and cut there with an
|
|
79
|
+
ellipsis (Lh 2026-10-21: "มันควรจะ max สามบรรทัด" — a request's title ran to
|
|
80
|
+
four lines on a phone; reverses 2026-09-16's "no clamp"). The count is the knob
|
|
81
|
+
--card-head-title-lines. The group that holds heading ·
|
|
86
82
|
caption is the head's own wrapping row (above) — no wrapper element, no
|
|
87
83
|
height, only the row gap. */
|
|
88
|
-
.card__head :is(h1, h2, h3) {
|
|
84
|
+
.card__head :is(h1, h2, h3) {
|
|
85
|
+
overflow-wrap: anywhere;
|
|
86
|
+
display: -webkit-box;
|
|
87
|
+
-webkit-box-orient: vertical;
|
|
88
|
+
-webkit-line-clamp: var(--card-head-title-lines, 3);
|
|
89
|
+
line-clamp: var(--card-head-title-lines, 3);
|
|
90
|
+
overflow: hidden;
|
|
91
|
+
padding-block-start: var(--_mark-room); /* a stacked Thai mark rises over the first line's box: room inside the clip, given back outside */
|
|
92
|
+
margin-block-start: calc(-1 * var(--_mark-room));
|
|
93
|
+
--_mark-room: 0.2em;
|
|
94
|
+
}
|
|
89
95
|
|
|
90
96
|
/* a Stamp in a card's head (`Card end={<Stamp …/>}`): the words stand at the left, the stamp at the right BESIDE BOTH LINES — the heading and the
|
|
91
97
|
caption pair up beside it, not the stamp beside the heading alone with the caption left under it. The stamp is its own size (--stamp-size,
|
|
@@ -93,15 +99,13 @@
|
|
|
93
99
|
<div class="card__head"><h2 class="t-h2">…</h2><span class="t-caption t-muted">…</span><span class="stamp">…</span></div> */
|
|
94
100
|
.card__head:has(> .stamp) { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
|
|
95
101
|
.card__head:has(> .stamp) > :is(h1, h2, h3) { grid-column: 1; grid-row: 1; align-self: end; }
|
|
96
|
-
.card__head:has(> .stamp) > :is(.t-caption, .t-body) { grid-column: 1; grid-row: 2; align-self: start; }
|
|
97
|
-
.card__head > .stamp { grid-column: 2; grid-row: 1 / span 2; margin-inline: 0; }
|
|
98
102
|
|
|
99
103
|
/* a JourneyBadge at the edge of the card's own first head (the date box in the top-left or top-right corner) keeps its corner concentric
|
|
100
104
|
with the card's: the card's corner (--r-card) less the room the padding leaves round it. journey.css reads it behind the theme's --tile-badge-radius,
|
|
101
105
|
so a theme that sets that knob still wins. */
|
|
102
106
|
.card > .card__head:first-child > .tile-badge:is(:first-child, :last-child) { --_badge-radius: calc(var(--r-card) - var(--card-pad)); }
|
|
103
107
|
|
|
104
|
-
/* ---- paper bands: the two-tone card (`Card paper="bands"`, Lh 2026-10-19): the head and the foot are
|
|
108
|
+
/* ---- paper bands: the two-tone card (`Card paper="bands"`, Lh 2026-10-19): the head and the foot are paper bands edge to
|
|
105
109
|
edge over the card's padding, no hairline; the middle between them keeps the card's tone, lightened (--card-middle-bg). The card
|
|
106
110
|
clips, so the bands keep its corners. A two-faced card (below) carries the look on each face. */
|
|
107
111
|
:is(.card--bands, .card--bands > .card__face) {
|
|
@@ -122,12 +126,14 @@
|
|
|
122
126
|
|
|
123
127
|
/* ---- two faces: the WHOLE card turns (`Card back`, Lh 2026-10-19). The article is the turning box (.flip, base.css) and only that;
|
|
124
128
|
each face is the card's paper — head · middle · foot — and both lie in one grid cell. The head and the foot are the same on both
|
|
125
|
-
faces; the
|
|
129
|
+
faces; the card is as tall as its taller face and each face fills it, the middle taking what the head and the foot leave (2026-10-21,
|
|
130
|
+
timebank: a fixed middle left a short front a tall empty band), so the card never changes height as it turns; --card-middle-h fixes
|
|
131
|
+
the middle's height instead, the theme's call. The hidden
|
|
126
132
|
face is inert. Each face holds an unseen turn button: the keyboard's way to turn it; its ring is drawn on the face. */
|
|
127
133
|
.card--turns { background: none; border: 0; padding: 0; cursor: pointer; touch-action: manipulation; }
|
|
128
134
|
.card__face {
|
|
129
|
-
display:
|
|
130
|
-
|
|
135
|
+
display: flex;
|
|
136
|
+
flex-direction: column;
|
|
131
137
|
gap: var(--card-gap);
|
|
132
138
|
min-width: 0;
|
|
133
139
|
padding: var(--card-pad);
|
|
@@ -138,13 +144,10 @@
|
|
|
138
144
|
position: relative;
|
|
139
145
|
}
|
|
140
146
|
.card__face > * { min-width: 0; }
|
|
141
|
-
.card__middle { display: grid; align-content: start; gap: var(--card-gap); height: var(--card-middle-h,
|
|
142
|
-
.card__turn { position: absolute; inset: 0; width:
|
|
147
|
+
.card__middle { flex: 1 0 auto; display: grid; align-content: start; gap: var(--card-gap); height: var(--card-middle-h, auto); overflow: hidden; }
|
|
148
|
+
.card__turn { position: absolute; inset: 0; width: var(--px); height: var(--px); padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); }
|
|
143
149
|
.card__face:has(> .card__turn:focus-visible) { outline: var(--focus); outline-offset: calc(-1 * var(--sp-1)); }
|
|
144
|
-
|
|
145
|
-
.card__head > .chip-row { flex: 1 1 100%; order: 2; max-height: calc(2 * (var(--fs-sm) * 1.5 + 2 * var(--chip-sm-pad-y, var(--sp-0)) + 2 * var(--border-w)) + var(--sp-2)); overflow: hidden; }
|
|
146
|
-
.card__head > .chip-row > .chip { display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: 1.5; }
|
|
147
|
-
.card__head > .chip-row > .chip > .icon { display: inline-block; vertical-align: -0.15em; margin-inline-end: var(--chip-sm-gap, var(--sp-1)); }
|
|
150
|
+
.card__head > .chip-row > .chip > .icon { --icon-display: inline-block; --icon-align: -0.15em; --icon-margin: 0 var(--chip-sm-gap, var(--sp-1)) 0 0; }
|
|
148
151
|
|
|
149
152
|
/* ---- bleed: a scrolling track that runs to the container's edges ----
|
|
150
153
|
For a horizontal strip inside a padded container — .avatar-pick, .chip-row,
|
|
@@ -165,15 +168,15 @@
|
|
|
165
168
|
nothing jumps. Chromium/Safari paint it through the ::-webkit-scrollbar
|
|
166
169
|
parts; Firefox gets its thin bar in the same ink. */
|
|
167
170
|
.bleed {
|
|
168
|
-
margin-inline: calc(-1 * var(--card-pad,
|
|
169
|
-
padding-inline: var(--card-pad,
|
|
171
|
+
margin-inline: calc(-1 * var(--card-pad, 0rem));
|
|
172
|
+
padding-inline: var(--card-pad, 0rem);
|
|
170
173
|
padding-block-end: var(--sp-2);
|
|
171
|
-
scroll-padding-inline: var(--card-pad,
|
|
174
|
+
scroll-padding-inline: var(--card-pad, 0rem);
|
|
172
175
|
flex-wrap: nowrap;
|
|
173
176
|
overflow-x: auto;
|
|
174
177
|
}
|
|
175
178
|
.bleed::-webkit-scrollbar { height: var(--scroll-w); }
|
|
176
|
-
.bleed::-webkit-scrollbar-track { background: transparent; margin-inline: var(--card-pad,
|
|
179
|
+
.bleed::-webkit-scrollbar-track { background: transparent; margin-inline: var(--card-pad, 0rem); }
|
|
177
180
|
.bleed::-webkit-scrollbar-thumb { background: transparent; }
|
|
178
181
|
.bleed:is(:hover, .is-scrolling)::-webkit-scrollbar-thumb { background: currentColor; }
|
|
179
182
|
@supports not selector(::-webkit-scrollbar) {
|
|
@@ -187,29 +190,28 @@
|
|
|
187
190
|
/* foot: the card's action buttons on one line. One button takes the width,
|
|
188
191
|
up to four share it in even parts — so the gaps read even too — and from
|
|
189
192
|
three on they drop their side padding so the labels keep the room. */
|
|
190
|
-
.card__foot { display: flex; gap: var(--card-foot-gap, var(--sp-2)); align-items: center; }
|
|
191
|
-
.card__foot > .btn {
|
|
192
|
-
/* …unless the button says its own size: `Btn form` is as wide as its words in a foot too, centred (Lh 2026-10-10: one button filling
|
|
193
|
-
a card's foot read too big — which button a card wears is the project's choice, so the foot must not undo it) */
|
|
194
|
-
.card__foot > .btn--form { flex: 0 1 auto; }
|
|
195
|
-
.card__foot:has(> :nth-child(3)) > .btn { padding-inline: var(--sp-2); }
|
|
193
|
+
.card__foot { display: flex; gap: var(--card-foot-gap, var(--sp-2)); align-items: center; color: var(--card-foot-ink, inherit); }
|
|
194
|
+
.card__foot:has(> :nth-child(3)) > .btn { --btn-pad-x: var(--sp-2); }
|
|
196
195
|
/* a small link under the buttons (CardFoot link — Lh 2026-09-23, as the ActionBar's ctaLink): the row wraps, the link takes a
|
|
197
196
|
whole short row of its own, centred — it never shares the buttons' line */
|
|
198
197
|
.card__foot--link { flex-wrap: wrap; align-content: end; row-gap: var(--card-foot-link-gap, var(--sp-1)); }
|
|
199
198
|
.card__foot-link { flex: 1 0 100%; display: flex; justify-content: center; }
|
|
199
|
+
/* round (CardFoot round): the foot holds a few round IconBtns, each its own size (they never share the line), as ONE group in the middle with
|
|
200
|
+
a gap that does not follow the card's width. The gap is wider than the Btns' (a miss between two round targets): --card-foot-gap sets it */
|
|
201
|
+
.card__foot--round { justify-content: center; gap: var(--card-foot-gap, var(--sp-6)); }
|
|
200
202
|
|
|
201
203
|
/* media placeholder for wireframes — currentColor so it survives any palette */
|
|
202
204
|
.ph {
|
|
203
205
|
background:
|
|
204
|
-
linear-gradient(to top right, transparent calc(50% -
|
|
205
|
-
linear-gradient(to top left, transparent calc(50% -
|
|
206
|
+
linear-gradient(to top right, transparent calc(50% - var(--px)), currentColor calc(50% - var(--px)), currentColor calc(50% + var(--px)), transparent calc(50% + var(--px))),
|
|
207
|
+
linear-gradient(to top left, transparent calc(50% - var(--px)), currentColor calc(50% - var(--px)), currentColor calc(50% + var(--px)), transparent calc(50% + var(--px)));
|
|
206
208
|
border: var(--border-w) solid currentColor;
|
|
207
209
|
border-radius: var(--r-media);
|
|
208
210
|
opacity: var(--off);
|
|
209
|
-
min-height:
|
|
211
|
+
min-height: calc(var(--tap-base) * 10 / 3);
|
|
210
212
|
}
|
|
211
|
-
.ph--sm { min-height:
|
|
212
|
-
.ph--md { min-height:
|
|
213
|
+
.ph--sm { min-height: calc(var(--tap-base) * 5 / 2); }
|
|
214
|
+
.ph--md { min-height: calc(var(--tap-base) * 3); }
|
|
213
215
|
/* ---- centred card: one thing to read, at the human centre of a fill screen ----
|
|
214
216
|
(.screen__centre below is the same placement for a small GROUP of things)
|
|
215
217
|
Where the centre of a phone IS, to the person holding it: the bottom fifth is
|
|
@@ -222,8 +224,7 @@
|
|
|
222
224
|
The card hugs its words and keeps the screen's inset. It is capped so that it
|
|
223
225
|
never reaches the title bar above it nor the bar's room below it — past that it
|
|
224
226
|
scrolls inside — from the same tokens those bars reserve their room with. */
|
|
225
|
-
.card--centre
|
|
226
|
-
.screen--fill > .screen__centre {
|
|
227
|
+
.card--centre {
|
|
227
228
|
position: absolute;
|
|
228
229
|
top: var(--screen-centre);
|
|
229
230
|
translate: 0 -50%;
|
|
@@ -240,38 +241,6 @@
|
|
|
240
241
|
:is(.topbar, .appbar) ~ :is(.card--centre, .screen__centre) { --_lead: var(--header-h); }
|
|
241
242
|
.card--centre { inset-inline: var(--screen-pad); }
|
|
242
243
|
|
|
243
|
-
/* ---- centred block: the same place, for one thing to read that is not a
|
|
244
|
-
lone card — an empty state, a card with its quiet second button and the
|
|
245
|
-
pager under it. The block runs edge to
|
|
246
|
-
edge and keeps the screen's inset as padding, and
|
|
247
|
-
its children stack at the screen's own rhythm (Lh, 2026-09-11):
|
|
248
|
-
<div class="screen screen--fill"><header class="topbar">…</header>
|
|
249
|
-
<div class="screen__centre"><article class="card">…</article><button class="btn btn--quiet btn--block">…</button></div>
|
|
250
|
-
</div> */
|
|
251
|
-
.screen__centre {
|
|
252
|
-
inset-inline: 0;
|
|
253
|
-
padding-inline: var(--screen-pad);
|
|
254
|
-
display: grid;
|
|
255
|
-
gap: var(--screen-gap);
|
|
256
|
-
align-content: start;
|
|
257
|
-
}
|
|
258
|
-
.screen__centre > * { min-width: 0; }
|
|
259
|
-
|
|
260
|
-
/* ---- the same group on a plain .screen: centred when short, as long as it
|
|
261
|
-
likes when not (Lh, 2026-09-12) ----
|
|
262
|
-
The member sees one content area — whatever is between the top bar and the
|
|
263
|
-
bar — and reads it as a whole page: a short card sits at its middle, a long
|
|
264
|
-
one simply makes the page longer, runs under the bar (a sticky last row,
|
|
265
|
-
actions.css) and scrolls up like any page — nothing is capped, nothing
|
|
266
|
-
shrinks, no scroll box inside a box.
|
|
267
|
-
So on a .screen that is NOT --fill the group is in flow: the column is at
|
|
268
|
-
least one phone tall (step.css), the group takes the room after the top bar and
|
|
269
|
-
centres its children in it. The screen's own inset stays the inset.
|
|
270
|
-
<div class="screen"><header class="topbar">…</header>
|
|
271
|
-
<div class="screen__centre"><article class="card">…</article><div class="pager__at">…</div></div>
|
|
272
|
-
</div><div class="action-bar">…</div> */
|
|
273
|
-
.screen:not(.screen--fill) > .screen__centre { flex: 1; padding-inline: 0; align-content: center; }
|
|
274
|
-
|
|
275
244
|
/* ---- the card that changes slides: out one side, the next in from the other ----
|
|
276
245
|
A .screen__centre group that walks pages (data-slide="next" | "back" on the
|
|
277
246
|
root while a step changes) turns its card like a page: the old card slides
|
|
@@ -300,7 +269,7 @@
|
|
|
300
269
|
user-select: none; /* a walk is dragged, not read-and-selected — without this, a finger crossing the words highlights them instead of turning the page (timebank #59) */
|
|
301
270
|
touch-action: pan-y; /* leaves vertical scroll to the browser; horizontal is the app's own drag, never a native pan */
|
|
302
271
|
}
|
|
303
|
-
.pages >
|
|
272
|
+
.pages > .card { grid-area: 1 / 1; align-content: start; } /* stretched to the cell, the words stay at the top */
|
|
304
273
|
.pages > [inert] { visibility: hidden; }
|
|
305
274
|
/* pages of WORDS (Lh, 2026-09-20): the same walk with .page pages, on the base — in a .step the
|
|
306
275
|
.pages is the reading block (step.css), the round pager in the bar turns it, the same slideTo().
|
|
@@ -312,7 +281,7 @@
|
|
|
312
281
|
::view-transition-old(centre-card-out), ::view-transition-new(centre-card-in),
|
|
313
282
|
::view-transition-old(screen-out), ::view-transition-new(screen-in) { /* screen-*: slideScreen — one whole screen to the next (Lh 2026-09-25) */
|
|
314
283
|
animation-duration: var(--motion-slide);
|
|
315
|
-
animation-timing-function: ease-out;
|
|
284
|
+
animation-timing-function: var(--ease-out);
|
|
316
285
|
mix-blend-mode: normal;
|
|
317
286
|
}
|
|
318
287
|
:root[data-slide="next"]::view-transition-old(centre-card-out), :root[data-slide="next"]::view-transition-old(screen-out) { animation-name: centre-card-out-left; }
|
|
@@ -327,9 +296,6 @@
|
|
|
327
296
|
::view-transition-old(centre-card-out), ::view-transition-new(centre-card-in),
|
|
328
297
|
::view-transition-old(screen-out), ::view-transition-new(screen-in) { animation: none; }
|
|
329
298
|
}
|
|
330
|
-
/* the page dots under the card sit centred under it — the indicator belongs
|
|
331
|
-
with the page that changes, never in the bar (Lh, 2026-09-12) */
|
|
332
|
-
.screen__centre > .pager__at { justify-self: center; }
|
|
333
299
|
|
|
334
300
|
/* compact card inside a card (nested note, promo) */
|
|
335
301
|
.card--sm { padding: var(--card-sm-pad, var(--sp-4)); --card-gap: var(--sp-2); border-radius: var(--card-sm-radius, var(--r-card)); }
|
|
@@ -338,7 +304,7 @@
|
|
|
338
304
|
stack.css; a stacked sheet is a plain .card, the material */
|
|
339
305
|
|
|
340
306
|
/* trailing icon cluster in a card header */
|
|
341
|
-
.icon-row { display: flex; align-items: center; gap: var(--icon-row-gap, var(--sp-4)); opacity:
|
|
307
|
+
.icon-row { display: flex; align-items: center; gap: var(--icon-row-gap, var(--sp-4)); opacity: var(--fade-near); }
|
|
342
308
|
|
|
343
309
|
/* ---- card list: rows, each row its own boundary ---- */
|
|
344
310
|
.card-list { display: grid; gap: var(--card-list-gap, var(--sp-3)); }
|
|
@@ -374,7 +340,7 @@
|
|
|
374
340
|
.card__remove {
|
|
375
341
|
--_size: var(--card-remove-size, calc(var(--tap-base) / 2));
|
|
376
342
|
position: relative;
|
|
377
|
-
z-index:
|
|
343
|
+
z-index: var(--z-over);
|
|
378
344
|
flex: none;
|
|
379
345
|
align-self: flex-start;
|
|
380
346
|
display: grid;
|
|
@@ -392,7 +358,7 @@
|
|
|
392
358
|
cursor: pointer;
|
|
393
359
|
}
|
|
394
360
|
.card__remove::after { content: ""; position: absolute; inset: 50% auto auto 50%; translate: -50% -50%; width: max(var(--tap-floor), var(--_size)); aspect-ratio: 1; border-radius: 50%; }
|
|
395
|
-
.card__remove > .icon {
|
|
361
|
+
.card__remove > .icon { --icon-size: 62%; }
|
|
396
362
|
.card__remove:focus-visible { outline: var(--focus); outline-offset: var(--sp-0); }
|
|
397
363
|
|
|
398
364
|
/* leading thumb/icon in a row */
|
|
@@ -435,7 +401,7 @@
|
|
|
435
401
|
.feed-card__rest > :first-child { margin-top: var(--card-gap); }
|
|
436
402
|
.feed-card--small .feed-card__rest { overflow: clip; visibility: hidden; }
|
|
437
403
|
@media (prefers-reduced-motion: no-preference) {
|
|
438
|
-
.feed-card__more { transition: grid-template-rows var(--motion-sheet) ease; }
|
|
404
|
+
.feed-card__more { transition: grid-template-rows var(--motion-sheet) var(--ease); }
|
|
439
405
|
.feed-card--small .feed-card__rest { transition: visibility 0s var(--motion-sheet); }
|
|
440
406
|
}
|
|
441
407
|
|
|
@@ -446,7 +412,7 @@
|
|
|
446
412
|
|
|
447
413
|
.delta {
|
|
448
414
|
font: var(--delta-font, var(--type-caption));
|
|
449
|
-
font-weight:
|
|
415
|
+
font-weight: var(--fw-bold);
|
|
450
416
|
padding: var(--delta-pad-y, var(--sp-1)) var(--delta-pad-x, var(--sp-2));
|
|
451
417
|
border-radius: var(--delta-radius, var(--r-chip));
|
|
452
418
|
background: var(--delta-bg, var(--card-3-bg));
|
|
@@ -473,4 +439,283 @@
|
|
|
473
439
|
scroll-snap-align: start; scroll-snap-stop: always;
|
|
474
440
|
display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--card-gap); align-content: start;
|
|
475
441
|
}
|
|
476
|
-
|
|
442
|
+
|
|
443
|
+
/* ==== the card's variants another family draws: Cover and the fold (media), Band (numbers) (#62: a block is written in its own file) ==== */
|
|
444
|
+
|
|
445
|
+
/* ---- cover: the image IS the card; text over a scrim ----
|
|
446
|
+
<article class="card card--cover"><div class="ph" role="img"></div>
|
|
447
|
+
<div class="card__head"><button class="icon-btn icon-btn--sm">♥</button></div>
|
|
448
|
+
<div><h2 class="t-h1">Art Institute</h2><p class="t-body">111 South Michigan Ave</p></div>
|
|
449
|
+
<div class="row">…meta…</div></article> */
|
|
450
|
+
.card--cover {
|
|
451
|
+
--card-bg: var(--card-3-bg);
|
|
452
|
+
--dark: var(--card-3-dark);
|
|
453
|
+
--accent: var(--card-ink);
|
|
454
|
+
--accent-dark: calc(1 - var(--dark));
|
|
455
|
+
min-height: var(--_cover-min-h);
|
|
456
|
+
align-content: space-between;
|
|
457
|
+
overflow: hidden;
|
|
458
|
+
isolation: isolate;
|
|
459
|
+
}
|
|
460
|
+
.card--cover > img,
|
|
461
|
+
.card--cover > .ph {
|
|
462
|
+
position: absolute;
|
|
463
|
+
inset: 0;
|
|
464
|
+
width: 100%;
|
|
465
|
+
height: 100%;
|
|
466
|
+
object-fit: cover;
|
|
467
|
+
z-index: var(--z-under-2);
|
|
468
|
+
border: 0;
|
|
469
|
+
border-radius: 0;
|
|
470
|
+
min-height: 0;
|
|
471
|
+
}
|
|
472
|
+
/* scrim: dark at both ends so the meta stays readable */
|
|
473
|
+
.card--cover::before {
|
|
474
|
+
content: "";
|
|
475
|
+
position: absolute;
|
|
476
|
+
inset: 0;
|
|
477
|
+
z-index: var(--z-under);
|
|
478
|
+
background: linear-gradient(to bottom, var(--scrim), transparent 40% 60%, var(--scrim));
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/* ---- fold: a sticky-note corner on any card (decorative) ----
|
|
482
|
+
No border. The card's outline follows its border box, so it ran straight
|
|
483
|
+
across the squared bottom-right corner and cut through the fold's diagonal —
|
|
484
|
+
the corner read as a notch with a line through it rather than a lifted flap.
|
|
485
|
+
The COLOUR goes transparent rather than the border going to 0, so the box
|
|
486
|
+
keeps its geometry and a fold card still measures the same as the cards
|
|
487
|
+
beside it. */
|
|
488
|
+
.card--fold {
|
|
489
|
+
border-color: transparent;
|
|
490
|
+
border-bottom-right-radius: 0;
|
|
491
|
+
background-image: linear-gradient(to top left,
|
|
492
|
+
var(--card-bg) 0 50%, /* the card's own background, not --surface (the page's) — a mismatch here drew a seam at the flap's edge */
|
|
493
|
+
color-mix(in srgb, currentColor 18%, var(--card-bg)) 50% 100%);
|
|
494
|
+
background-repeat: no-repeat;
|
|
495
|
+
background-position: bottom right;
|
|
496
|
+
background-size: var(--sp-8) var(--sp-8);
|
|
497
|
+
background-origin: border-box; /* the flap sits on the true corner, not inside the (transparent) border */
|
|
498
|
+
/* the corner is CUT: the triangle under the flap shows what is behind the card. Painted in the card's own colour it
|
|
499
|
+
read as the square corner of a second card underneath (Lh 2026-09-23). The polygon reaches --sp-12 past the other
|
|
500
|
+
edges so a coloured palette's shadow is not clipped there. */
|
|
501
|
+
clip-path: polygon(calc(-1 * var(--sp-12)) calc(-1 * var(--sp-12)), calc(100% + var(--sp-12)) calc(-1 * var(--sp-12)), calc(100% + var(--sp-12)) calc(100% - var(--sp-8) - var(--sp-12)),
|
|
502
|
+
calc(100% - var(--sp-8) - var(--sp-12)) calc(100% + var(--sp-12)), calc(-1 * var(--sp-12)) calc(100% + var(--sp-12)));
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/* ---- band: data card; numbers.css draws its parts and the band stack ---- */
|
|
506
|
+
.card--band {
|
|
507
|
+
grid-template-columns: 1fr auto;
|
|
508
|
+
grid-template-areas: "label num" "foot num";
|
|
509
|
+
align-items: end;
|
|
510
|
+
gap: var(--sp-2) var(--sp-4);
|
|
511
|
+
min-height: var(--card-band-min-h, var(--tile-h));
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/* ---- where it sits in what base.css draws (docs/reference.md rule 15) ---- */
|
|
515
|
+
.page > :is(img, .ph) { max-height: var(--page-media-h, calc(var(--tap-base) * 14 / 3)); width: auto; height: auto; max-width: 100%; object-fit: contain; justify-self: start; align-self: start; } /* height auto: an <img> with width/height attributes keeps its ratio inside the cap — no band under the picture */
|
|
516
|
+
.page > .ph { width: 100%; height: var(--page-media-h, calc(var(--tap-base) * 14 / 3)); }
|
|
517
|
+
/* ---- where it sits in what stack.css draws (docs/reference.md rule 15) ---- */
|
|
518
|
+
.sheet-stack > .card {
|
|
519
|
+
grid-area: 1 / 1; /* every card shares the stack's cell; later ones offset down */
|
|
520
|
+
border-bottom-left-radius: 0;
|
|
521
|
+
border-bottom-right-radius: 0;
|
|
522
|
+
border-bottom: 0;
|
|
523
|
+
align-content: start;
|
|
524
|
+
align-self: start; /* own natural height (padding + head) by default */
|
|
525
|
+
z-index: var(--level, var(--z-over)); /* explicit paint order, 1 = back of the stack */
|
|
526
|
+
}
|
|
527
|
+
/* THE FRONT SHEET is the last .card, not the last child: a --closed stack
|
|
528
|
+
may carry a .sheet-stack__base after its sheets (below). Written once here
|
|
529
|
+
as "a card no card follows" so every rule about the front sheet agrees. */
|
|
530
|
+
.sheet-stack > .card:not(:has(~ .card)) {
|
|
531
|
+
align-self: stretch; /* the front card fills the remaining stack height */
|
|
532
|
+
}
|
|
533
|
+
.sheet-stack > .card:nth-child(2) { margin-top: var(--stack-step); }
|
|
534
|
+
.sheet-stack > .card:nth-child(3) { margin-top: calc(2 * var(--stack-step)); }
|
|
535
|
+
.sheet-stack > .card:nth-child(4) { margin-top: calc(3 * var(--stack-step)); }
|
|
536
|
+
.sheet-stack > .card:nth-child(5) { margin-top: calc(4 * var(--stack-step)); }
|
|
537
|
+
/* stack headers: uniform — [back?] title left, icons right, one height,
|
|
538
|
+
same gap to content on every card */
|
|
539
|
+
.sheet-stack > .card > .card__head {
|
|
540
|
+
align-items: center;
|
|
541
|
+
justify-content: flex-start;
|
|
542
|
+
min-height: var(--tap);
|
|
543
|
+
}
|
|
544
|
+
.sheet-stack--display > .card > .card__head { align-items: start; min-height: 0; }
|
|
545
|
+
/* ============================================================
|
|
546
|
+
.sheet-stack--tap — tap a peeked sheet open; a back button returns it.
|
|
547
|
+
|
|
548
|
+
A sheet (a .card — the material, sheet.css's single sheet is the same
|
|
549
|
+
stuff) is rigid: it can move in, move out, or be covered — it can
|
|
550
|
+
never change shape. So every sheet here is the SAME full height,
|
|
551
|
+
always, set once and never touched again by anything. A "peek" is
|
|
552
|
+
not a short sheet; it's a full sheet the next one happens to cover,
|
|
553
|
+
showing only the strip above it, exactly like a sheet of paper part
|
|
554
|
+
way out of a real stack.
|
|
555
|
+
|
|
556
|
+
Because of that, the whole animation is one property: translate.
|
|
557
|
+
Nothing resizes, nothing re-stacks — z-index is the plain resting
|
|
558
|
+
--level order and is never touched, since the order already says
|
|
559
|
+
what has to happen. Cards after the tapped one sit IN FRONT of it,
|
|
560
|
+
so they're what's covering it, so they're what must leave. Cards
|
|
561
|
+
before it are already BEHIND it, so they need do nothing at all
|
|
562
|
+
except let themselves be covered as it rises over them.
|
|
563
|
+
|
|
564
|
+
.is-open — the tapped card, moved up to the top of the stack. Its
|
|
565
|
+
own resting offset is margin-top (below); opening just
|
|
566
|
+
translates that offset back off, landing it flush at
|
|
567
|
+
the stack's top with its full height exactly filling
|
|
568
|
+
to the bottom.
|
|
569
|
+
.is-before — an earlier card, nudged one step down so it slips
|
|
570
|
+
under the next card's resting strip and is covered
|
|
571
|
+
there. Each carries its own --stagger (set in JS: 0
|
|
572
|
+
for the one nearest the tapped card, counting up
|
|
573
|
+
further back) so they tuck away, and later un-tuck,
|
|
574
|
+
one at a time.
|
|
575
|
+
.is-after — a later card, moved out below, together, no stagger.
|
|
576
|
+
============================================================ */
|
|
577
|
+
.sheet-stack--tap > .card {
|
|
578
|
+
height: 100%; /* every card identical and full length, always — the one
|
|
579
|
+
size in this whole component, never toggled, never transitioned. At a
|
|
580
|
+
resting margin-top of n steps it simply overhangs the stack's bottom
|
|
581
|
+
by n steps (clipped by .screen--fill), so translating it up by exactly
|
|
582
|
+
that much lands it filling the stack precisely. */
|
|
583
|
+
overflow: clip;
|
|
584
|
+
transition: translate var(--motion-sheet) var(--ease); /* the only animated property here */
|
|
585
|
+
transition-delay: calc(var(--stagger, 0) * var(--motion-stagger)); /* 0 for everything
|
|
586
|
+
except a staggered is-before card: the card renders --stagger as it tucks or un-tucks */
|
|
587
|
+
}
|
|
588
|
+
.sheet-stack--tap > .card.is-open {
|
|
589
|
+
/* up by its own resting offset — pure movement, nothing resizes */
|
|
590
|
+
translate: 0 calc(-1 * var(--slot, 0) * var(--stack-step) + var(--_pull, 0rem));
|
|
591
|
+
cursor: default;
|
|
592
|
+
overflow-y: auto;
|
|
593
|
+
overflow-x: clip;
|
|
594
|
+
overscroll-behavior: contain;
|
|
595
|
+
}
|
|
596
|
+
.sheet-stack--tap > .card.is-open.is-dragging { transition: none; }
|
|
597
|
+
.sheet-stack--tap > .card > .card__head { touch-action: none; }
|
|
598
|
+
.sheet-stack--tap > .card.is-open:not(:has(> .sheet__body)) {
|
|
599
|
+
padding-top: calc(var(--card-pad) + var(--_refresh, 0rem));
|
|
600
|
+
transition: translate var(--motion-sheet) var(--ease), padding-top var(--motion-sheet) var(--ease);
|
|
601
|
+
}
|
|
602
|
+
/* the front sheet — the one open on arrival — never travels up (it is not
|
|
603
|
+
tappable), so its resting offset would leave its last n steps below the
|
|
604
|
+
screen forever, unreachable by any scroll (timebank home, 2026-09-13). It
|
|
605
|
+
alone is cut to the room it actually has, and it scrolls like an opened
|
|
606
|
+
sheet does. Every other sheet keeps the one full height. */
|
|
607
|
+
.sheet-stack--tap:not(.sheet-stack--closed) > .card:not(:has(~ .card)) {
|
|
608
|
+
height: calc(100% - var(--slot, 0) * var(--stack-step));
|
|
609
|
+
overflow-y: auto;
|
|
610
|
+
overflow-x: clip;
|
|
611
|
+
overscroll-behavior: contain;
|
|
612
|
+
}
|
|
613
|
+
/* a scrolling sheet shows no scrollbar (a desktop with a mouse would paint one
|
|
614
|
+
down the card's edge — Lh 2026-09-15); it still scrolls, like the page itself
|
|
615
|
+
(the hiding rule is base.css's, shared with every other scrolling track) */
|
|
616
|
+
.sheet-stack--tap > .card.is-before { translate: 0 var(--stack-step); }
|
|
617
|
+
.sheet-stack--tap > .card.is-after { translate: 0 100vh; }
|
|
618
|
+
.sheet-stack--closed > .card { translate: 0 calc(var(--_headroom) - var(--_lift, 0rem)); }
|
|
619
|
+
.sheet-stack--closed > .card.is-dragging { transition: none; }
|
|
620
|
+
.sheet-stack--tap:not(.sheet-stack--closed) > .card.is-dragging:not(.is-open) {
|
|
621
|
+
translate: 0 calc(-1 * var(--_lift, 0rem));
|
|
622
|
+
transition: none;
|
|
623
|
+
}
|
|
624
|
+
.sheet-stack--closed > .card.is-before { translate: 0 calc(var(--_headroom) + var(--stack-step)); }
|
|
625
|
+
.sheet-stack--closed > .card.is-after { translate: 0 100vh; }
|
|
626
|
+
/* a card standing in this room is FLAT (Lh 2026-10-09): the room clips at its own edges, and a card's shadow cut there drew a straight
|
|
627
|
+
line under the bar and along the first sheet. Its ground and its radius are what say "card" here. */
|
|
628
|
+
:is([data-palette], [data-finish]) .sheet-stack__base .card { box-shadow: none; }
|
|
629
|
+
/* at the screen's top the open sheet's top corners are SQUARE (Lh 2026-10-08): round, they left two small pockets of the
|
|
630
|
+
bar's ground at the glass. They square as the sheet rises and round again as it folds, in the slide's own time. Paint
|
|
631
|
+
only, the sheet's size is untouched. A pull on the head keeps them square until the finger lets go. */
|
|
632
|
+
.sheet-stack--flood > .card { transition: translate var(--motion-sheet) var(--ease), border-radius var(--motion-sheet) var(--ease); }
|
|
633
|
+
.sheet-stack--flood > .card.is-open { border-top-left-radius: 0; border-top-right-radius: 0; }
|
|
634
|
+
:is(.sheet-stack--tap > .card, .sheet-stack--tap > :not(.card, .sheet-stack__base) > .card) > .card__head {
|
|
635
|
+
position: relative;
|
|
636
|
+
padding-left: 0;
|
|
637
|
+
transition: padding-left var(--motion-sheet) var(--ease);
|
|
638
|
+
}
|
|
639
|
+
/* ---- a stacked sheet with a SheetBody has the ONE sheet shape (Lh 2026-09-23, the home layout): sheet head
|
|
640
|
+
pinned at the top · sheet body scrolls, as long as it needs · sheet foot (a CardFoot, the CTA) at the bottom.
|
|
641
|
+
The card becomes a flex column and stops scrolling itself — only the body does. A sheet with no SheetBody
|
|
642
|
+
keeps the old way: the whole open card scrolls. ---- */
|
|
643
|
+
.sheet-stack--tap > .card:has(> .sheet__body) { display: flex; flex-direction: column; gap: var(--card-gap); }
|
|
644
|
+
.sheet-stack--tap > .card:has(> .sheet__body).is-open { overflow: clip; }
|
|
645
|
+
/* a paper stack's foot is paper to the card's edges, and it covers the tinted flex gap above it so the
|
|
646
|
+
button does not sit on a colour stripe. The head's gap stays: it is outside this foot. The button stays
|
|
647
|
+
where it was — the padding gives back what the bleed takes. */
|
|
648
|
+
.sheet-stack > .card.sheet--paper > .card__foot {
|
|
649
|
+
background: var(--action-bg);
|
|
650
|
+
color: var(--card-ink);
|
|
651
|
+
margin-top: calc(-1 * var(--card-gap));
|
|
652
|
+
margin-inline: calc(-1 * var(--card-pad));
|
|
653
|
+
margin-bottom: calc(-1 * var(--card-pad));
|
|
654
|
+
padding-top: var(--card-gap);
|
|
655
|
+
padding-inline: var(--card-pad);
|
|
656
|
+
padding-bottom: var(--card-pad);
|
|
657
|
+
}
|
|
658
|
+
.stack-sheet > .card__head { flex-wrap: nowrap; }
|
|
659
|
+
/* ---- the back button, SMALL (Lh 2026-09-23: "give the sheet head more room" — and then "a glyph alone does not read as
|
|
660
|
+
tappable"): a SMALL DISC — its ring kept, 32px instead of 44, the chevron in it at 20 — so the head gives it 32px + a gap
|
|
661
|
+
(was 56px). Its tap target stays 44px: an invisible ::after around the disc. ---- */
|
|
662
|
+
.sheet-stack--tap > .card.is-open > .card__head:has(> .sheet-stack__back:not(.sheet-stack__back--end)) { padding-left: var(--stack-back-room, calc(var(--_back-size) + var(--sp-2))); }
|
|
663
|
+
:is(.sheet-stack--tap > .card, .sheet-stack--tap > :not(.card, .sheet-stack__base) > .card) > .card__head:has(> .sheet-stack__back--end) { transition: padding-right var(--motion-sheet) var(--ease); }
|
|
664
|
+
.sheet-stack--tap > .card.is-open > .card__head:has(> .sheet-stack__back--end) { padding-right: var(--stack-back-room, calc(var(--_back-size) + var(--sp-2))); }
|
|
665
|
+
/* a stacked sheet is a control until it is open — tapped, never read into: no text selection (a drag, a double tap, a long press),
|
|
666
|
+
no grey flash, no iOS callout; its head stays one when open. Only the OPEN sheet's body is text to select (Lh 2026-09-23) */
|
|
667
|
+
.sheet-stack--tap > .card, .sheet-stack > .card > .card__head { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
|
|
668
|
+
/* ---- where it sits in what sheet.css draws (docs/reference.md rule 15) ---- */
|
|
669
|
+
.sheet > .card__foot {
|
|
670
|
+
position: absolute; inset: calc(-1 * var(--border-w)) 0 0; z-index: var(--z-over); /* the sheet's border box: the same height the sheet's own % reads */
|
|
671
|
+
align-items: end;
|
|
672
|
+
align-content: end;
|
|
673
|
+
padding: 0 var(--card-pad) calc(var(--card-pad) + var(--_safe-b-open));
|
|
674
|
+
background: linear-gradient(var(--card-bg), var(--card-bg)) bottom / 100% var(--_foot) no-repeat;
|
|
675
|
+
pointer-events: none;
|
|
676
|
+
translate: 0 calc(-1 * var(--_y) - var(--_drag, 0rem));
|
|
677
|
+
transition: translate var(--motion-sheet) var(--ease), visibility 0s;
|
|
678
|
+
}
|
|
679
|
+
.sheet.is-dragging > .card__foot { transition: none; }
|
|
680
|
+
/* at peek and away the foot is NOT held on the box's edge: it stands on the sheet's own bottom edge (no counter-slide), so it
|
|
681
|
+
LEAVES AND ARRIVES WITH ITS SHEET — solid the whole way, hidden only once the slide is over. It used to stay in place and
|
|
682
|
+
fade: the body slid through the strip behind a half-transparent button (timebank, Lh 2026-10-01: "ตัวหนังสือลอดใต้ปุ่ม"). */
|
|
683
|
+
:is(.sheet--peek, .sheet--away) > .card__foot { translate: 0 0; visibility: hidden; transition: translate var(--motion-sheet) var(--ease), visibility 0s var(--ease-linear) var(--motion-sheet); }
|
|
684
|
+
/* ---- where it sits in what step.css draws (docs/reference.md rule 15) ---- */
|
|
685
|
+
/* a WALK (Pages of Page) — Lh 2026-09-23, third call: no top; the picture and the words are ONE run that scrolls up together
|
|
686
|
+
(the picture is never pinned). Each page starts at the screen's lead and ends with the same room under it — the lead as
|
|
687
|
+
padding above AND below — so the words begin near the middle and, when a big text size runs them long, scroll up clear.
|
|
688
|
+
The walk shows no scrollbar. */
|
|
689
|
+
.step > .pages { touch-action: pan-y; } /* pan-y: the walk scrolls itself up and down; a sideways swipe is the Walkthrough's (it turns the page) */ /* the scrolling box is the whole content: from the step's top edge, edge to edge — no margin, the default (Lh 2026-09-23) */
|
|
690
|
+
.step > .pages > .page > :is(img, .ph):first-child {
|
|
691
|
+
width: calc(100% + 2 * var(--screen-pad)); /* the content's width: the page's inset given back */
|
|
692
|
+
max-width: none;
|
|
693
|
+
margin-inline: calc(-1 * var(--screen-pad));
|
|
694
|
+
height: calc(var(--_lead, 0rem) + var(--page-media-h, calc(var(--tap-base) * 14 / 3)));
|
|
695
|
+
max-height: none;
|
|
696
|
+
border-radius: 0;
|
|
697
|
+
border-inline: 0;
|
|
698
|
+
border-top: 0;
|
|
699
|
+
object-fit: cover;
|
|
700
|
+
}
|
|
701
|
+
/* ---- where it sits in what numbers.css draws (docs/reference.md rule 15) ---- */
|
|
702
|
+
.band-stack > .card--band { border: 0; border-radius: 0; box-shadow: none; }
|
|
703
|
+
.band-stack > .card--band + .card--band { border-top: var(--border-w) solid var(--hairline); }
|
|
704
|
+
/* ---- where it sits in what sticky.css draws (docs/reference.md rule 15) ---- */
|
|
705
|
+
.sticky__head > .ph { flex: 1 1 0; min-width: 0; } /* a picture in the head takes the note's width */
|
|
706
|
+
.sticky__head:has(> .sticky-date) > .ph { flex: none; width: var(--sticky-pic-size, calc(var(--tap) * 1.5)); min-height: 0; aspect-ratio: 1; } /* beside a date the picture is a small square at the start */
|
|
707
|
+
|
|
708
|
+
/* ---- where it sits in what media.css draws: a postcard's picture (docs/reference.md rule 15) ---- */
|
|
709
|
+
.postcard__front .postcard__turn > .ph { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border: 0; border-radius: 0; min-height: 0; }
|
|
710
|
+
|
|
711
|
+
/* ---- where it sits in what stack.css draws: a sheet pulled to refresh holds still (docs/reference.md rule 15) ---- */
|
|
712
|
+
.sheet-stack--tap > .card.is-open.is-refreshing:not(:has(> .sheet__body)) { transition: none; }
|
|
713
|
+
|
|
714
|
+
/* ---- where it sits in what step.css draws: the reading block, a walk of pages (docs/reference.md rule 15) ---- */
|
|
715
|
+
.step:has(> .sheet--peek) > .pages { padding-bottom: var(--sheet-peek); }
|
|
716
|
+
.step > .pages {
|
|
717
|
+
flex: 0 1 auto;
|
|
718
|
+
min-height: 0;
|
|
719
|
+
overflow-y: auto;
|
|
720
|
+
overscroll-behavior: contain;
|
|
721
|
+
}
|