@usableapp/cardds 0.2.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -107
- package/cardds.js +6 -449
- package/css/actions.css +41 -35
- package/css/base.css +9 -9
- package/css/card.css +26 -25
- package/css/choice.css +50 -50
- package/css/forms.css +18 -18
- package/css/journey.css +16 -16
- package/css/layover.css +45 -45
- package/css/lists.css +43 -43
- package/css/media.css +33 -33
- package/css/numbers.css +25 -25
- package/css/people.css +11 -11
- package/css/sheet.css +29 -29
- package/css/step.css +6 -6
- package/css/theme.template.css +6 -3
- package/css/tokens.css +2 -0
- package/dist/actions/Btn.d.ts +109 -108
- package/dist/actions/BtnRow.d.ts +2 -2
- package/dist/actions/Chip.d.ts +102 -101
- package/dist/actions/Dot.d.ts +2 -2
- package/dist/actions/Dropdown.d.ts +36 -19
- package/dist/actions/Dropdown.js +41 -11
- package/dist/actions/Fab.d.ts +2 -2
- package/dist/actions/IconBtn.d.ts +298 -10
- package/dist/actions/IconBtn.js +6 -8
- package/dist/actions/Link.d.ts +105 -104
- package/dist/actions/Segment.d.ts +3 -3
- package/dist/cardds.css +354 -345
- package/dist/cards/Card.d.ts +99 -98
- package/dist/cards/CardFoot.d.ts +2 -2
- package/dist/cards/CardHead.d.ts +2 -2
- package/dist/cards/CardParts.d.ts +7 -7
- package/dist/cards/Placeholder.d.ts +2 -2
- package/dist/cards/Stat.d.ts +7 -5
- package/dist/cards/Stat.js +2 -2
- package/dist/choice/Calendar.d.ts +17 -6
- package/dist/choice/Calendar.js +9 -3
- package/dist/choice/Check.d.ts +3 -3
- package/dist/choice/DayStrip.d.ts +3 -3
- package/dist/choice/Mood.d.ts +2 -2
- package/dist/choice/Slider.d.ts +3 -3
- package/dist/choice/Slider.js +12 -8
- package/dist/forms/AddRow.d.ts +2 -2
- package/dist/forms/Composer.d.ts +2 -2
- package/dist/forms/Field.d.ts +2 -2
- package/dist/forms/FileBtn.d.ts +2 -2
- package/dist/forms/Pin.d.ts +10 -7
- package/dist/forms/Pin.js +47 -18
- package/dist/journey/NoteRow.d.ts +2 -2
- package/dist/journey/Route.d.ts +2 -2
- package/dist/journey/TileBadge.d.ts +2 -2
- package/dist/layover/Banner.d.ts +2 -2
- package/dist/layover/Callout.d.ts +2 -2
- package/dist/layover/Deck.d.ts +3 -3
- package/dist/lists/Bubble.d.ts +3 -3
- package/dist/lists/Kv.d.ts +5 -5
- package/dist/lists/Legend.d.ts +3 -3
- package/dist/lists/Row.d.ts +5 -4
- package/dist/lists/Timeline.d.ts +3 -3
- package/dist/media/MapArea.d.ts +2 -2
- package/dist/media/Mosaic.d.ts +3 -3
- package/dist/media/Postcard.d.ts +9 -5
- package/dist/media/Postcard.js +8 -3
- package/dist/media/Quote.d.ts +2 -2
- package/dist/media/Tile.d.ts +5 -4
- package/dist/numbers/Badge.d.ts +2 -2
- package/dist/numbers/Band.d.ts +3 -3
- package/dist/numbers/Bars.d.ts +3 -3
- package/dist/numbers/DotGrid.d.ts +2 -2
- package/dist/numbers/Picker.d.ts +20 -8
- package/dist/numbers/Picker.js +51 -13
- package/dist/numbers/Ring.d.ts +2 -2
- package/dist/numbers/Track.d.ts +3 -3
- package/dist/people/Avatar.d.ts +100 -99
- package/dist/people/AvatarPick.d.ts +3 -3
- package/dist/scaffold/ActionBar.d.ts +3 -3
- package/dist/scaffold/AppBar.d.ts +2 -2
- package/dist/scaffold/BaseContent.d.ts +7 -7
- package/dist/scaffold/BaseContent.js +4 -4
- package/dist/scaffold/Centre.d.ts +3 -3
- package/dist/scaffold/EmptyState.d.ts +2 -2
- package/dist/scaffold/FilterRow.d.ts +2 -2
- package/dist/scaffold/FloatBar.d.ts +105 -104
- package/dist/scaffold/PagerAt.d.ts +2 -2
- package/dist/scaffold/Screen.d.ts +100 -99
- package/dist/scaffold/TopBar.d.ts +2 -2
- package/dist/sheets/CardBack.d.ts +2 -2
- package/dist/sheets/Drawer.d.ts +19 -8
- package/dist/sheets/Drawer.js +29 -5
- package/dist/sheets/Sheet.d.ts +29 -16
- package/dist/sheets/Sheet.js +157 -11
- package/dist/sheets/SheetBody.d.ts +2 -2
- package/dist/sheets/SheetHead.d.ts +2 -2
- package/dist/sheets/SheetStack.d.ts +15 -3
- package/dist/sheets/SheetStack.js +74 -2
- package/dist/sheets/SheetStage.d.ts +2 -2
- package/dist/sheets/Step.d.ts +2 -2
- package/dist/type/Icon.d.ts +22 -7
- package/dist/type/Icon.js +27 -4
- package/dist/type/Text.d.ts +7 -1
- package/dist/type/Text.js +2 -2
- package/package.json +3 -2
package/dist/cardds.css
CHANGED
|
@@ -90,6 +90,8 @@
|
|
|
90
90
|
--chip-h: calc(var(--tap-base) * 19 / 24); /* 38 chip height */
|
|
91
91
|
--bar-h: calc(var(--tap-base) * 4 / 3); /* 64 float bar, day cell, deck actions */
|
|
92
92
|
--header-h: calc(var(--tap-base) * 5 / 4); /* 60 top bar — .topbar and .appbar alike */
|
|
93
|
+
--card-pad-rest: var(--sp-5); /* 20 a card's padding before any variant — .card publishes it as --card-pad; the sheet's peek strip is built from it where no card is in scope */
|
|
94
|
+
--card-gap-rest: var(--sp-4); /* 16 …and its gap */
|
|
93
95
|
--screen-pad: var(--sp-4); /* 16 the screen's inset — .sheet-stack cancels it */
|
|
94
96
|
--map-ring: calc(var(--tap-base) * 10 / 3); /* the rough-area ring on a map (sheet.css .map__ring) — a neighbourhood, not a house */
|
|
95
97
|
--fab: calc(var(--tap-base) * 3 / 2); /* 72 square floating action */
|
|
@@ -415,10 +417,10 @@ img, svg { display: block; max-width: 100%; }
|
|
|
415
417
|
button { font: inherit; cursor: pointer; }
|
|
416
418
|
|
|
417
419
|
/* icon from icons.svg sprite: <svg class="icon"><use href="icons.svg#bell"/></svg> */
|
|
418
|
-
.icon { width: var(--icon); height: var(--icon); flex: none; }
|
|
419
|
-
.icon--sm { width: var(--icon-sm); height: var(--icon-sm); }
|
|
420
|
-
.icon--xs { width: var(--icon-xs); height: var(--icon-xs); } /* inside captions, chips, links */
|
|
421
|
-
.icon--lg { width: var(--icon-lg); height: var(--icon-lg); } /* empty states */
|
|
420
|
+
.icon { width: var(--icon-size, var(--icon)); height: var(--icon-size, var(--icon)); flex: none; }
|
|
421
|
+
.icon--sm { width: var(--icon-sm-size, var(--icon-sm)); height: var(--icon-sm-size, var(--icon-sm)); }
|
|
422
|
+
.icon--xs { width: var(--icon-xs-size, var(--icon-xs)); height: var(--icon-xs-size, var(--icon-xs)); } /* inside captions, chips, links */
|
|
423
|
+
.icon--lg { width: var(--icon-lg-size, var(--icon-lg)); height: var(--icon-lg-size, var(--icon-lg)); } /* empty states */
|
|
422
424
|
|
|
423
425
|
/* mobile screen column — the standard horizontal inset, and nothing vertical.
|
|
424
426
|
Top and bottom are zero on purpose: vertical room is only ever a RESERVE for
|
|
@@ -485,9 +487,9 @@ button { font: inherit; cursor: pointer; }
|
|
|
485
487
|
In a .step it is the reading block and step.css adds the flex/scroll rule ---- */
|
|
486
488
|
.base-content {
|
|
487
489
|
display: grid;
|
|
488
|
-
gap: var(--sp-3);
|
|
490
|
+
gap: var(--base-content-gap, var(--sp-3));
|
|
489
491
|
align-content: start; /* a tall column never stretches the rows — the words hug the top */
|
|
490
|
-
padding-block: var(--sp-4);
|
|
492
|
+
padding-block: var(--base-content-pad-y, var(--sp-4));
|
|
491
493
|
}
|
|
492
494
|
.base-content > .t-body { color: var(--on-surface-muted); max-width: 34ch; }
|
|
493
495
|
.base-content .cta-pack {
|
|
@@ -503,9 +505,9 @@ button { font: inherit; cursor: pointer; }
|
|
|
503
505
|
display: grid;
|
|
504
506
|
justify-items: center;
|
|
505
507
|
text-align: center;
|
|
506
|
-
gap: var(--sp-2);
|
|
507
|
-
padding: var(--sp-12) var(--sp-6);
|
|
508
|
-
color: var(--on-surface); /* full ink, icon and words alike: muted read as "disabled" at the middle of an empty screen (Lh 2026-09-16) — muted is for meta, not a sentence */
|
|
508
|
+
gap: var(--empty-state-gap, var(--sp-2));
|
|
509
|
+
padding: var(--empty-state-pad-y, var(--sp-12)) var(--empty-state-pad-x, var(--sp-6));
|
|
510
|
+
color: var(--empty-state-ink, var(--on-surface)); /* full ink, icon and words alike: muted read as "disabled" at the middle of an empty screen (Lh 2026-09-16) — muted is for meta, not a sentence */
|
|
509
511
|
}
|
|
510
512
|
.empty-state__action { margin-top: var(--sp-2); }
|
|
511
513
|
/* inside a card (a section's "nothing yet"): the card's ink */
|
|
@@ -521,12 +523,12 @@ button { font: inherit; cursor: pointer; }
|
|
|
521
523
|
.card {
|
|
522
524
|
--card-bg: var(--card-1-bg); /* the slot, readable by children (avatar rings, fold) */
|
|
523
525
|
--card-ink: var(--card-1-ink);
|
|
524
|
-
--card-pad: var(--
|
|
525
|
-
--card-gap: var(--
|
|
526
|
+
--card-pad: var(--card-pad-rest); /* published so .bleed can cancel it exactly */
|
|
527
|
+
--card-gap: var(--card-gap-rest); /* published so a sheet's peek strip (sheet.css) is exact */
|
|
526
528
|
background: var(--card-bg);
|
|
527
529
|
color: var(--card-ink);
|
|
528
530
|
border: var(--border-w) solid var(--card-border);
|
|
529
|
-
border-radius: var(--r-card);
|
|
531
|
+
border-radius: var(--card-radius, var(--r-card));
|
|
530
532
|
padding: var(--card-pad);
|
|
531
533
|
display: grid;
|
|
532
534
|
gap: var(--card-gap);
|
|
@@ -557,8 +559,8 @@ button { font: inherit; cursor: pointer; }
|
|
|
557
559
|
flex-wrap: wrap; /* the caption / overline take a line of their own — no wrapper div */
|
|
558
560
|
align-items: center;
|
|
559
561
|
justify-content: space-between;
|
|
560
|
-
column-gap: var(--sp-3);
|
|
561
|
-
row-gap: var(--sp-0);
|
|
562
|
+
column-gap: var(--card-head-col-gap, var(--sp-3));
|
|
563
|
+
row-gap: var(--card-head-row-gap, var(--sp-0));
|
|
562
564
|
}
|
|
563
565
|
/* flat head markup (Lh 2026-09-16 — no <p>, no wrapper, only padding and gap tokens):
|
|
564
566
|
<div class="card__head"><span class="t-overline t-muted">…</span><h2 class="t-h2">…</h2><span class="t-caption t-muted">…</span><button class="icon-btn icon-btn--sm">…</button></div>
|
|
@@ -569,8 +571,8 @@ button { font: inherit; cursor: pointer; }
|
|
|
569
571
|
.card__head > .t-overline { order: -1; }
|
|
570
572
|
.card__head--top { align-items: flex-start; }
|
|
571
573
|
|
|
572
|
-
.card__media { border-radius: var(--r-media); overflow: hidden; position: relative; } /* relative: corner badges */
|
|
573
|
-
.card__end { text-align: right; display: grid; gap: var(--sp-0); justify-items: end; } /* trailing value + caption */
|
|
574
|
+
.card__media { border-radius: var(--card-media-radius, var(--r-media)); overflow: hidden; position: relative; } /* relative: corner badges */
|
|
575
|
+
.card__end { text-align: right; display: grid; gap: var(--card-end-gap, var(--sp-0)); justify-items: end; } /* trailing value + caption */
|
|
574
576
|
.card__media > img { width: 100%; height: auto; object-fit: cover; }
|
|
575
577
|
|
|
576
578
|
/* ---- the card skeleton: head · content · foot ----
|
|
@@ -634,7 +636,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
634
636
|
/* foot: the card's action buttons on one line. One button takes the width,
|
|
635
637
|
up to four share it in even parts — so the gaps read even too — and from
|
|
636
638
|
three on they drop their side padding so the labels keep the room. */
|
|
637
|
-
.card__foot { display: flex; gap: var(--sp-2); align-items: center; }
|
|
639
|
+
.card__foot { display: flex; gap: var(--card-foot-gap, var(--sp-2)); align-items: center; }
|
|
638
640
|
.card__foot > .btn { flex: 1 1 0; min-width: 0; }
|
|
639
641
|
.card__foot:has(> :nth-child(3)) > .btn { padding-inline: var(--sp-2); }
|
|
640
642
|
|
|
@@ -768,51 +770,52 @@ button { font: inherit; cursor: pointer; }
|
|
|
768
770
|
.screen__centre > .pager__at { justify-self: center; }
|
|
769
771
|
|
|
770
772
|
/* compact card inside a card (nested note, promo) */
|
|
771
|
-
.card--sm { padding: var(--sp-4); --card-gap: var(--sp-2); border-radius: var(--r-card); }
|
|
773
|
+
.card--sm { padding: var(--card-sm-pad, var(--sp-4)); --card-gap: var(--sp-2); border-radius: var(--card-sm-radius, var(--r-card)); }
|
|
772
774
|
|
|
773
775
|
/* the sheet stack (.sheet-stack) — sheets stacked, heads peeking — lives in
|
|
774
776
|
stack.css; a stacked sheet is a plain .card, the material */
|
|
775
777
|
|
|
776
778
|
/* trailing icon cluster in a card header */
|
|
777
|
-
.icon-row { display: flex; align-items: center; gap: var(--sp-4); opacity: 0.85; }
|
|
779
|
+
.icon-row { display: flex; align-items: center; gap: var(--icon-row-gap, var(--sp-4)); opacity: 0.85; }
|
|
778
780
|
|
|
779
781
|
/* ---- card list: rows, each row its own boundary ---- */
|
|
780
|
-
.card-list { display: grid; gap: var(--sp-3); }
|
|
782
|
+
.card-list { display: grid; gap: var(--card-list-gap, var(--sp-3)); }
|
|
781
783
|
|
|
782
784
|
.card--row {
|
|
783
|
-
border-radius: var(--r-card);
|
|
784
|
-
padding: var(--sp-4);
|
|
785
|
+
border-radius: var(--card-row-radius, var(--r-card));
|
|
786
|
+
padding: var(--card-row-pad, var(--sp-4));
|
|
785
787
|
display: flex;
|
|
786
788
|
align-items: center;
|
|
787
|
-
gap: var(--sp-3);
|
|
789
|
+
gap: var(--card-row-gap, var(--sp-3));
|
|
788
790
|
}
|
|
789
791
|
.card--row .card__body { flex: 1; display: grid; gap: var(--sp-0); }
|
|
790
792
|
|
|
791
793
|
/* leading thumb/icon in a row */
|
|
792
794
|
.card__thumb {
|
|
793
|
-
width: var(--tap-sm); height: var(--tap-sm);
|
|
795
|
+
width: var(--card-thumb-size, var(--tap-sm)); height: var(--card-thumb-size, var(--tap-sm));
|
|
794
796
|
flex: none;
|
|
795
|
-
border-radius: var(--r-control);
|
|
797
|
+
border-radius: var(--card-thumb-radius, var(--r-control));
|
|
796
798
|
border: var(--border-w) solid currentColor;
|
|
797
799
|
display: grid;
|
|
798
800
|
place-items: center;
|
|
799
|
-
font: var(--type-label);
|
|
801
|
+
font: var(--card-thumb-font, var(--type-label));
|
|
800
802
|
opacity: 0.85;
|
|
801
803
|
}
|
|
802
804
|
|
|
803
805
|
/* ---- inline stat block (revenue-style) ---- */
|
|
804
|
-
.stat { display: grid; gap: var(--sp-1); }
|
|
805
|
-
.
|
|
806
|
+
.stat { display: grid; gap: var(--stat-gap, var(--sp-1)); }
|
|
807
|
+
.stat--centre { text-align: center; justify-items: center; } /* the one number of a sheet or a stage, under a centred avatar */
|
|
808
|
+
.stat__row { display: flex; align-items: center; justify-content: space-between; gap: var(--stat-row-gap, var(--sp-3)); }
|
|
806
809
|
|
|
807
810
|
.delta {
|
|
808
|
-
font: var(--type-caption);
|
|
811
|
+
font: var(--delta-font, var(--type-caption));
|
|
809
812
|
font-weight: 700;
|
|
810
|
-
padding: var(--sp-1) var(--sp-2);
|
|
811
|
-
border-radius: var(--r-chip);
|
|
812
|
-
background: var(--card-3-bg);
|
|
813
|
-
color: var(--card-3-ink);
|
|
813
|
+
padding: var(--delta-pad-y, var(--sp-1)) var(--delta-pad-x, var(--sp-2));
|
|
814
|
+
border-radius: var(--delta-radius, var(--r-chip));
|
|
815
|
+
background: var(--delta-bg, var(--card-3-bg));
|
|
816
|
+
color: var(--delta-ink, var(--card-3-ink));
|
|
814
817
|
}
|
|
815
|
-
.delta--neg { background: var(--neg); color: var(--card-3-ink); } /* light ink on the signal color in every slot */
|
|
818
|
+
.delta--neg { background: var(--delta-neg-bg, var(--neg)); color: var(--delta-neg-ink, var(--card-3-ink)); } /* light ink on the signal color in every slot */
|
|
816
819
|
|
|
817
820
|
/* ---- css/stack.css — sheet stack: .sheet-stack — the menu, sheets stacked, heads peek, tap opens ---- */
|
|
818
821
|
/* ============================================================
|
|
@@ -1105,7 +1108,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
1105
1108
|
page. Many sheets stacked as the app's menu are the other system,
|
|
1106
1109
|
.sheet-stack (stack.css): the same material, its own class and file.
|
|
1107
1110
|
|
|
1108
|
-
<article class="card sheet sheet--half"
|
|
1111
|
+
<article class="card sheet sheet--half">
|
|
1109
1112
|
A tap on the handle TOGGLES the sheet between its own state and peek
|
|
1110
1113
|
(Lh 2026-09-16) — never a step-by-step climb; a drag snaps to any of
|
|
1111
1114
|
the listed states, and the state it lands on becomes the one a tap
|
|
@@ -1123,14 +1126,12 @@ button { font: inherit; cursor: pointer; }
|
|
|
1123
1126
|
============================================================ */
|
|
1124
1127
|
|
|
1125
1128
|
.sheet {
|
|
1126
|
-
--_handle: var(--sp-1);
|
|
1127
1129
|
/* the strip a peeked sheet shows: the card's own top padding, the handle,
|
|
1128
1130
|
the gap, one title row (--tap — the head rule below makes every head at
|
|
1129
1131
|
least that tall) and the gap under it, so the cut lands exactly where
|
|
1130
1132
|
the first control starts and nothing of it leaks through. Published
|
|
1131
1133
|
(and registered in tokens.css) so a sheet whose head is taller can
|
|
1132
1134
|
retune it: .my-sheet { --sheet-peek: … } */
|
|
1133
|
-
--sheet-peek: calc(var(--card-pad) + var(--_handle) + 2 * var(--card-gap) + var(--tap));
|
|
1134
1135
|
--sheet-half: 0.5; /* a share of the sheet's own height */
|
|
1135
1136
|
--sheet-3q: 0.25; /* three quarters showing: slid by a quarter */
|
|
1136
1137
|
/* the sheet's own height, seen from inside it: the box it slides in is the
|
|
@@ -1159,20 +1160,22 @@ button { font: inherit; cursor: pointer; }
|
|
|
1159
1160
|
overflow: clip;
|
|
1160
1161
|
border-radius: var(--r-card) var(--r-card) 0 0;
|
|
1161
1162
|
border-bottom: 0;
|
|
1162
|
-
box-shadow: var(--shadow-sheet);
|
|
1163
|
+
box-shadow: var(--sheet-shadow, var(--shadow-sheet));
|
|
1163
1164
|
}
|
|
1164
1165
|
.sheet--full { --_y: 0%; --_cover: 0rem; }
|
|
1165
1166
|
.sheet--half { --_y: calc(var(--sheet-half) * 100%); --_cover: calc(var(--sheet-half) * var(--_box)); }
|
|
1166
1167
|
.sheet--3q { --_y: calc(var(--sheet-3q) * 100%); --_cover: calc(var(--sheet-3q) * var(--_box)); }
|
|
1167
1168
|
.sheet--peek { --_y: calc(100% - var(--sheet-peek)); --_cover: calc(var(--_box) - var(--sheet-peek)); }
|
|
1169
|
+
/* --sheet-peek is declared on the BOX the sheet slides in, not on the sheet: the words behind a peeked sheet
|
|
1170
|
+
have to read it too (step.css keeps that much room under them), and a token only flows down. The sheet
|
|
1171
|
+
inherits it. A sheet whose head is taller retunes it on the box. */
|
|
1172
|
+
:is(.step, .sheet-stage) { --_handle: var(--sp-1); --sheet-peek: calc(var(--card-pad-rest) + var(--_handle) + 2 * var(--card-gap-rest) + var(--tap)); }
|
|
1173
|
+
|
|
1168
1174
|
/* ---- called sheets (Lh, 2026-09-20): a .step whose .base-content has buttons that each CALL a sheet ----
|
|
1169
1175
|
.sheet--away = not on the screen: slid all the way out (translate, like every state — the material never
|
|
1170
1176
|
changes), and hidden once it has left so its shadow does not lie on the step's bottom edge; write it
|
|
1171
|
-
with `inert
|
|
1172
|
-
|
|
1173
|
-
sheet up to full and sends any other one away; the handle takes it down to peek, never further, so the
|
|
1174
|
-
words and the other buttons are back in reach; the same button again raises it from peek to full.
|
|
1175
|
-
Nothing waits at peek before the first call. No bar on such a screen (actions.css).
|
|
1177
|
+
with `inert` (the React Sheet does). WHO brings it onto the screen is the app's business — a button, a route:
|
|
1178
|
+
cardds ties no component to another. Nothing waits at peek before the first call.
|
|
1176
1179
|
WHAT IT IS FOR: the base offers WAYS IN — sign in · new phone · join — and each button calls a sheet
|
|
1177
1180
|
that holds that way's WHOLE form, its submit on the sheet's foot, leading to the next page. The base
|
|
1178
1181
|
carries no control. It is NOT for a form taken apart — one sheet per field, a "send" left on the base:
|
|
@@ -1255,7 +1258,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
1255
1258
|
opacity: 0.3;
|
|
1256
1259
|
width: var(--tap-sm);
|
|
1257
1260
|
height: var(--_handle);
|
|
1258
|
-
border-radius: var(--r-chip);
|
|
1261
|
+
border-radius: var(--sheet-handle-radius, var(--r-chip));
|
|
1259
1262
|
margin: 0 auto;
|
|
1260
1263
|
padding: 0;
|
|
1261
1264
|
touch-action: none;
|
|
@@ -1287,8 +1290,8 @@ button { font: inherit; cursor: pointer; }
|
|
|
1287
1290
|
min-height: var(--tap);
|
|
1288
1291
|
text-align: center;
|
|
1289
1292
|
}
|
|
1290
|
-
.sheet__title { font: var(--type-h2); letter-spacing: var(--track-h2); margin: 0; }
|
|
1291
|
-
.sheet__sub { font: var(--type-caption); color: var(--card-muted); }
|
|
1293
|
+
.sheet__title { font: var(--sheet-title-font, var(--type-h2)); letter-spacing: var(--track-h2); margin: 0; }
|
|
1294
|
+
.sheet__sub { font: var(--sheet-sub-font, var(--type-caption)); color: var(--sheet-sub-ink, var(--card-muted)); }
|
|
1292
1295
|
|
|
1293
1296
|
/* ============================================================
|
|
1294
1297
|
.sheet-stage — the overlay stage: a page-height box the sheet
|
|
@@ -1310,7 +1313,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
1310
1313
|
margin-inline: auto;
|
|
1311
1314
|
overflow: clip; /* not hidden: a clipped box is not a scroll container, so revealing a focused field never shifts the stage */
|
|
1312
1315
|
container-type: size; /* the sheet's body reads this box's height as 100cqh (--_box above) */
|
|
1313
|
-
background: var(--surface);
|
|
1316
|
+
background: var(--sheet-stage-bg, var(--surface));
|
|
1314
1317
|
}
|
|
1315
1318
|
/* on an app screen the stage is the page: it takes the screen's inset back (edge to
|
|
1316
1319
|
edge, like a step) and, after a fixed .appbar, the room the screen reserved for
|
|
@@ -1345,7 +1348,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
1345
1348
|
position: absolute;
|
|
1346
1349
|
inset: 0;
|
|
1347
1350
|
isolation: isolate; /* the ring and the hint stack inside the map only — a sheet over the map covers them */
|
|
1348
|
-
color: var(--on-surface);
|
|
1351
|
+
color: var(--map-ink, var(--on-surface));
|
|
1349
1352
|
background:
|
|
1350
1353
|
repeating-linear-gradient(75deg, transparent 0 5.5rem, var(--hairline) 5.5rem 6.25rem),
|
|
1351
1354
|
repeating-linear-gradient(-18deg, transparent 0 8.75rem, var(--ink-tint) 8.75rem 9.25rem),
|
|
@@ -1363,9 +1366,9 @@ button { font: inherit; cursor: pointer; }
|
|
|
1363
1366
|
height: var(--map-ring);
|
|
1364
1367
|
translate: -50% -50%;
|
|
1365
1368
|
border-radius: 50%;
|
|
1366
|
-
border: var(--border-w) solid var(--accent);
|
|
1367
|
-
background: color-mix(in srgb, var(--accent) 22%, transparent);
|
|
1368
|
-
box-shadow: var(--shadow-float);
|
|
1369
|
+
border: var(--border-w) solid var(--map-ring-border, var(--accent));
|
|
1370
|
+
background: var(--map-ring-bg, color-mix(in srgb, var(--accent) 22%, transparent));
|
|
1371
|
+
box-shadow: var(--map-ring-shadow, var(--shadow-float));
|
|
1369
1372
|
pointer-events: none;
|
|
1370
1373
|
z-index: 1; /* above the engine's panes (Leaflet's tiles sit at 200, but inside their own stacking context) */
|
|
1371
1374
|
}
|
|
@@ -1374,10 +1377,10 @@ button { font: inherit; cursor: pointer; }
|
|
|
1374
1377
|
right: var(--sp-2);
|
|
1375
1378
|
bottom: var(--sp-2);
|
|
1376
1379
|
padding: var(--sp-0) var(--sp-2);
|
|
1377
|
-
border-radius: var(--r-chip);
|
|
1378
|
-
background: color-mix(in srgb, var(--surface) 80%, transparent);
|
|
1379
|
-
color: var(--on-surface-muted);
|
|
1380
|
-
font: var(--type-caption);
|
|
1380
|
+
border-radius: var(--map-credit-radius, var(--r-chip));
|
|
1381
|
+
background: var(--map-credit-bg, color-mix(in srgb, var(--surface) 80%, transparent));
|
|
1382
|
+
color: var(--map-credit-ink, var(--on-surface-muted));
|
|
1383
|
+
font: var(--map-credit-font, var(--type-caption));
|
|
1381
1384
|
pointer-events: none;
|
|
1382
1385
|
z-index: 1;
|
|
1383
1386
|
}
|
|
@@ -1388,12 +1391,12 @@ button { font: inherit; cursor: pointer; }
|
|
|
1388
1391
|
translate: -50% 0;
|
|
1389
1392
|
max-width: calc(100% - 2 * var(--sp-4));
|
|
1390
1393
|
padding: var(--sp-2) var(--sp-4);
|
|
1391
|
-
border-radius: var(--r-chip);
|
|
1392
|
-
background: var(--card-3-bg);
|
|
1393
|
-
color: var(--card-3-ink);
|
|
1394
|
-
font: var(--type-label);
|
|
1394
|
+
border-radius: var(--map-hint-radius, var(--r-chip));
|
|
1395
|
+
background: var(--map-hint-bg, var(--card-3-bg));
|
|
1396
|
+
color: var(--map-hint-ink, var(--card-3-ink));
|
|
1397
|
+
font: var(--map-hint-font, var(--type-label));
|
|
1395
1398
|
text-align: center;
|
|
1396
|
-
box-shadow: var(--shadow-float);
|
|
1399
|
+
box-shadow: var(--map-hint-shadow, var(--shadow-float));
|
|
1397
1400
|
pointer-events: none;
|
|
1398
1401
|
z-index: 1;
|
|
1399
1402
|
}
|
|
@@ -1407,7 +1410,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
1407
1410
|
the sheet gives it up itself, as --_lift — the same token a raised sheet floats on. */
|
|
1408
1411
|
.sheet-stage > .sheet { --_lift: var(--kb, 0rem); bottom: var(--_lift); }
|
|
1409
1412
|
.sheet-stage > .sheet--raised { --_lift: calc(var(--tap-lg) + var(--kb, 0rem)); }
|
|
1410
|
-
.sheet--raised { --_lift: var(--tap-lg); bottom: var(--_lift); border-radius: var(--r-card); border-bottom: var(--border-w) solid var(--card-border); }
|
|
1413
|
+
.sheet--raised { --_lift: var(--tap-lg); bottom: var(--_lift); border-radius: var(--sheet-raised-radius, var(--r-card)); border-bottom: var(--border-w) solid var(--card-border); }
|
|
1411
1414
|
.sheet-stage__foot {
|
|
1412
1415
|
position: absolute;
|
|
1413
1416
|
inset-inline: 0;
|
|
@@ -1416,8 +1419,8 @@ button { font: inherit; cursor: pointer; }
|
|
|
1416
1419
|
margin: 0;
|
|
1417
1420
|
display: grid;
|
|
1418
1421
|
place-items: center;
|
|
1419
|
-
font: var(--type-caption);
|
|
1420
|
-
color: var(--card-3-ink);
|
|
1422
|
+
font: var(--sheet-stage-foot-font, var(--type-caption));
|
|
1423
|
+
color: var(--sheet-stage-foot-ink, var(--card-3-ink));
|
|
1421
1424
|
z-index: 2;
|
|
1422
1425
|
}
|
|
1423
1426
|
|
|
@@ -1497,8 +1500,9 @@ button { font: inherit; cursor: pointer; }
|
|
|
1497
1500
|
:has(> .action-bar) .step { margin-bottom: calc(var(--bar-reserve) + var(--kb, 0rem)); }
|
|
1498
1501
|
/* LAYERS (Lh, 2026-09-20): the base, then the sheet over it, then the top bar. A bar is the BASE's — the
|
|
1499
1502
|
move of a page of words — so a step with a sheet has NO bar: the sheet finishes on its own .card__foot
|
|
1500
|
-
(sheet.css), and a form lives whole in ONE sheet, never item by item on the base.
|
|
1501
|
-
|
|
1503
|
+
(sheet.css), and a form lives whole in ONE sheet, never item by item on the base. That is how cardds's
|
|
1504
|
+
own screens are composed (the guide); the framework does not police it — a component never changes
|
|
1505
|
+
because another one is there. */
|
|
1502
1506
|
|
|
1503
1507
|
/* the reading block: a .base-content (base.css) — the same words-on-the-base
|
|
1504
1508
|
block as anywhere else (it was .step__card, and a .card before 2026-09-16;
|
|
@@ -1517,11 +1521,10 @@ button { font: inherit; cursor: pointer; }
|
|
|
1517
1521
|
color: var(--on-surface);
|
|
1518
1522
|
}
|
|
1519
1523
|
/* the reading block is the .base-content — or the .pages that holds several of them, a walk of words
|
|
1520
|
-
(card.css).
|
|
1521
|
-
|
|
1522
|
-
|
|
1524
|
+
(card.css). Behind a PEEKED sheet the words keep the strip's room under them, so whatever is down there
|
|
1525
|
+
(the buttons that call the other sheets) scrolls clear of it — CSS alone: the box declares --sheet-peek. */
|
|
1526
|
+
.step:has(> .sheet--peek) > :is(.base-content, .pages) { padding-bottom: var(--sheet-peek); }
|
|
1523
1527
|
.step > :is(.base-content, .pages) {
|
|
1524
|
-
padding-bottom: var(--sheet-room, 0rem);
|
|
1525
1528
|
flex: 0 1 auto;
|
|
1526
1529
|
}
|
|
1527
1530
|
.step > :is(.base-content, .pages) {
|
|
@@ -1541,13 +1544,13 @@ button { font: inherit; cursor: pointer; }
|
|
|
1541
1544
|
.field {
|
|
1542
1545
|
display: flex;
|
|
1543
1546
|
align-items: center;
|
|
1544
|
-
gap: var(--sp-2);
|
|
1545
|
-
border: var(--border-w) solid var(--action-border);
|
|
1546
|
-
border-radius: var(--r-control);
|
|
1547
|
-
background: var(--action-bg);
|
|
1548
|
-
color: var(--action-ink);
|
|
1549
|
-
padding-inline: var(--sp-4);
|
|
1550
|
-
min-height: var(--tap);
|
|
1547
|
+
gap: var(--field-gap, var(--sp-2));
|
|
1548
|
+
border: var(--border-w) solid var(--field-border, var(--action-border));
|
|
1549
|
+
border-radius: var(--field-radius, var(--r-control));
|
|
1550
|
+
background: var(--field-bg, var(--action-bg));
|
|
1551
|
+
color: var(--field-ink, var(--action-ink));
|
|
1552
|
+
padding-inline: var(--field-pad-x, var(--sp-4));
|
|
1553
|
+
min-height: var(--field-min-h, var(--tap));
|
|
1551
1554
|
min-width: 0;
|
|
1552
1555
|
}
|
|
1553
1556
|
|
|
@@ -1564,7 +1567,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
1564
1567
|
.field input::placeholder { color: inherit; opacity: 0.55; }
|
|
1565
1568
|
|
|
1566
1569
|
/* field with its action inside: date pick, send, go — the button sits flush right */
|
|
1567
|
-
.field--action { padding-right: var(--sp-1); min-height: var(--tap-lg); }
|
|
1570
|
+
.field--action { padding-right: var(--sp-1); min-height: var(--field-action-min-h, var(--tap-lg)); }
|
|
1568
1571
|
.field--action > .icon-btn { margin-left: auto; }
|
|
1569
1572
|
|
|
1570
1573
|
/* colored palettes drop the visible outline elsewhere — fields keep one */
|
|
@@ -1574,25 +1577,25 @@ button { font: inherit; cursor: pointer; }
|
|
|
1574
1577
|
.add-row {
|
|
1575
1578
|
display: inline-flex;
|
|
1576
1579
|
align-items: center;
|
|
1577
|
-
gap: var(--sp-2);
|
|
1580
|
+
gap: var(--add-row-gap, var(--sp-2));
|
|
1578
1581
|
border: 0;
|
|
1579
1582
|
background: none;
|
|
1580
1583
|
color: inherit;
|
|
1581
|
-
font: var(--type-label);
|
|
1582
|
-
font-size: var(--fs-body);
|
|
1583
|
-
padding: var(--sp-2) 0;
|
|
1584
|
-
min-height: var(--tap-sm);
|
|
1584
|
+
font: var(--add-row-font, var(--type-label));
|
|
1585
|
+
font-size: var(--add-row-font-size, var(--fs-body));
|
|
1586
|
+
padding: var(--add-row-pad-y, var(--sp-2)) var(--add-row-pad-x, 0);
|
|
1587
|
+
min-height: var(--add-row-min-h, var(--tap-sm));
|
|
1585
1588
|
}
|
|
1586
1589
|
.add-row__plus {
|
|
1587
|
-
width: var(--icon);
|
|
1588
|
-
height: var(--icon);
|
|
1590
|
+
width: var(--add-row-plus-size, var(--icon));
|
|
1591
|
+
height: var(--add-row-plus-size, var(--icon));
|
|
1589
1592
|
flex: none;
|
|
1590
1593
|
border-radius: 50%;
|
|
1591
|
-
background: var(--accent);
|
|
1592
|
-
color: var(--on-accent);
|
|
1594
|
+
background: var(--add-row-plus-bg, var(--accent));
|
|
1595
|
+
color: var(--add-row-plus-ink, var(--on-accent));
|
|
1593
1596
|
display: grid;
|
|
1594
1597
|
place-items: center;
|
|
1595
|
-
font-size: var(--fs-md);
|
|
1598
|
+
font-size: var(--add-row-plus-font-size, var(--fs-md));
|
|
1596
1599
|
line-height: 1;
|
|
1597
1600
|
}
|
|
1598
1601
|
.add-row__plus .icon { width: var(--icon-xs); height: var(--icon-xs); }
|
|
@@ -1605,40 +1608,40 @@ button { font: inherit; cursor: pointer; }
|
|
|
1605
1608
|
============================================================ */
|
|
1606
1609
|
|
|
1607
1610
|
/* ---- route: endpoint · dotted connector (icon in middle) · endpoint ---- */
|
|
1608
|
-
.route { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; column-gap: var(--sp-1); } /* line → icon: --sp-1, as the via always had; code → line is the code row's own --sp-3 */
|
|
1611
|
+
.route { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; column-gap: var(--route-col-gap, var(--sp-1)); } /* line → icon: --sp-1, as the via always had; code → line is the code row's own --sp-3 */
|
|
1609
1612
|
/* the two endpoints get EQUAL columns whatever their words measure, so the via
|
|
1610
1613
|
(the icon alone) sits at the card's centre; each dotted run lives on ITS
|
|
1611
1614
|
endpoint's code row and fills that side's leftover — with short names the
|
|
1612
1615
|
runs are long and equal, a long place name wraps in its half instead of
|
|
1613
1616
|
pushing the plane (Lh 2026-09-16) */
|
|
1614
1617
|
|
|
1615
|
-
.route__point { display: grid; gap: var(--sp-0); min-width: 0; }
|
|
1618
|
+
.route__point { display: grid; gap: var(--route-point-gap, var(--sp-0)); min-width: 0; }
|
|
1616
1619
|
.route__point--end { text-align: right; }
|
|
1617
1620
|
|
|
1618
|
-
.route__code { font: var(--type-h2); letter-spacing: var(--track-h2); display: flex; align-items: center; gap: var(--sp-3); }
|
|
1621
|
+
.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)); }
|
|
1619
1622
|
.route__code::after, .route__point--end .route__code::before { content: ""; flex: 1; border-top: var(--rule-w) dotted currentColor; opacity: 0.65; }
|
|
1620
1623
|
.route__point--end .route__code::after { content: none; }
|
|
1621
|
-
.route__time { font: var(--type-body); font-variant-numeric: tabular-nums; }
|
|
1622
|
-
.route__place { font: var(--type-caption); color: var(--card-muted); }
|
|
1624
|
+
.route__time { font: var(--route-time-font, var(--type-body)); font-variant-numeric: tabular-nums; }
|
|
1625
|
+
.route__place { font: var(--route-place-font, var(--type-caption)); color: var(--route-place-ink, var(--card-muted)); }
|
|
1623
1626
|
.card--3 .route__place { color: inherit; opacity: 0.7; }
|
|
1624
1627
|
|
|
1625
|
-
.route__via { display: flex; align-items: center; opacity: 0.65; font-size: var(--fs-body); }
|
|
1628
|
+
.route__via { display: flex; align-items: center; opacity: 0.65; font-size: var(--route-via-font-size, var(--fs-body)); }
|
|
1626
1629
|
|
|
1627
1630
|
/* ---- tile badge: tiny label over a big value (gate, seat, zone) ---- */
|
|
1628
1631
|
.tile-badge {
|
|
1629
1632
|
display: inline-grid;
|
|
1630
1633
|
justify-items: center;
|
|
1631
|
-
gap: var(--sp-0);
|
|
1632
|
-
padding: var(--sp-1) var(--sp-2);
|
|
1633
|
-
border-radius: var(--r-badge);
|
|
1634
|
-
background: var(--card-3-bg);
|
|
1635
|
-
color: var(--card-3-ink);
|
|
1634
|
+
gap: var(--tile-badge-gap, var(--sp-0));
|
|
1635
|
+
padding: var(--tile-badge-pad-y, var(--sp-1)) var(--tile-badge-pad-x, var(--sp-2));
|
|
1636
|
+
border-radius: var(--tile-badge-radius, var(--r-badge));
|
|
1637
|
+
background: var(--tile-badge-bg, var(--card-3-bg));
|
|
1638
|
+
color: var(--tile-badge-ink, var(--card-3-ink));
|
|
1636
1639
|
}
|
|
1637
|
-
.tile-badge__label { font: var(--type-overline); letter-spacing: var(--track-overline); text-transform: uppercase; opacity: 0.7; }
|
|
1640
|
+
.tile-badge__label { font: var(--tile-badge-label-font, var(--type-overline)); letter-spacing: var(--track-overline); text-transform: uppercase; opacity: 0.7; }
|
|
1638
1641
|
.tile-badge__value { font: 800 var(--fs-lg)/1.1 var(--font-display); font-variant-numeric: tabular-nums; }
|
|
1639
1642
|
|
|
1640
1643
|
/* plain: no fill — a date box beside a title (Jun / 18) */
|
|
1641
|
-
.tile-badge--plain { background: transparent; color: inherit; padding: 0; min-width: var(--tap-sm); }
|
|
1644
|
+
.tile-badge--plain { background: transparent; color: inherit; padding: 0; min-width: var(--tile-badge-plain-min-w, var(--tap-sm)); }
|
|
1642
1645
|
.tile-badge--plain .tile-badge__value { font: 800 var(--fs-h1)/1 var(--font-display); }
|
|
1643
1646
|
|
|
1644
1647
|
/* corner badge: pin a tile badge on media (rating, price) — .card__media is relative */
|
|
@@ -1648,9 +1651,9 @@ button { font: inherit; cursor: pointer; }
|
|
|
1648
1651
|
.note-row {
|
|
1649
1652
|
display: flex;
|
|
1650
1653
|
align-items: center;
|
|
1651
|
-
gap: var(--sp-2);
|
|
1652
|
-
font: var(--type-caption);
|
|
1653
|
-
color: var(--card-muted);
|
|
1654
|
+
gap: var(--note-row-gap, var(--sp-2));
|
|
1655
|
+
font: var(--note-row-font, var(--type-caption));
|
|
1656
|
+
color: var(--note-row-ink, var(--card-muted));
|
|
1654
1657
|
}
|
|
1655
1658
|
.card--3 .note-row { color: inherit; opacity: 0.7; }
|
|
1656
1659
|
|
|
@@ -1660,6 +1663,14 @@ button { font: inherit; cursor: pointer; }
|
|
|
1660
1663
|
topbar, chips, buttons, selects, bottom CTA pack
|
|
1661
1664
|
============================================================ */
|
|
1662
1665
|
|
|
1666
|
+
/* KNOBS (Lh 2026-09-21) — cardds is a framework: a project adjusts ONE component from outside, without touching this file.
|
|
1667
|
+
A knob is a custom property a rule reads WITH ITS DEFAULT AS THE FALLBACK — `padding-inline: var(--btn-pad-x, var(--sp-6))` —
|
|
1668
|
+
so it is declared nowhere: unset, nothing moves (tests/style-snapshot proves it); set in the project's theme.css it retunes
|
|
1669
|
+
that component everywhere; set on any element it retunes the components inside that element only. Names: --<component>-<what>
|
|
1670
|
+
(--btn-pad-x, --chip-bg, --icon-btn-size, --appbar-pad-x); a variant says so (--btn-primary-bg, --chip-on-ink, --icon-btn-sm-size).
|
|
1671
|
+
The sizes that already were root tokens (--btn-h, --chip-h, --bar-h, --header-h, --fab…) are knobs too — set them the same way.
|
|
1672
|
+
Prefer a BASE when the whole system should move (tokens.css); reach for a knob when ONE component should. `npm run knobs` lists them all. */
|
|
1673
|
+
|
|
1663
1674
|
/* ---- the bars across the top of a screen: one height, whatever they carry ----
|
|
1664
1675
|
.topbar (screen title) and .appbar (app context) are the same bar with
|
|
1665
1676
|
different contents, so the height is declared here once rather than left to
|
|
@@ -1670,8 +1681,8 @@ button { font: inherit; cursor: pointer; }
|
|
|
1670
1681
|
.topbar, .appbar {
|
|
1671
1682
|
display: flex;
|
|
1672
1683
|
align-items: center;
|
|
1673
|
-
gap: var(--sp-3);
|
|
1674
|
-
padding-block: var(--sp-2);
|
|
1684
|
+
gap: var(--bar-gap, var(--sp-3));
|
|
1685
|
+
padding-block: var(--bar-pad-y, var(--sp-2));
|
|
1675
1686
|
min-height: var(--header-h);
|
|
1676
1687
|
}
|
|
1677
1688
|
|
|
@@ -1700,9 +1711,9 @@ button { font: inherit; cursor: pointer; }
|
|
|
1700
1711
|
top: 0;
|
|
1701
1712
|
max-width: var(--screen-w);
|
|
1702
1713
|
margin-inline: auto;
|
|
1703
|
-
padding-inline: var(--screen-pad); /* fixed + full-bleed: the screen's own inset, so the bar's contents line up with the title bar under it (Lh 2026-09-15) */
|
|
1714
|
+
padding-inline: var(--appbar-pad-x, var(--screen-pad)); /* fixed + full-bleed: the screen's own inset, so the bar's contents line up with the title bar under it (Lh 2026-09-15) */
|
|
1704
1715
|
z-index: 40; /* topmost — card animations never cover it */
|
|
1705
|
-
background: var(--surface); /* solid: sliding cards never show through */
|
|
1716
|
+
background: var(--appbar-bg, var(--surface)); /* solid: sliding cards never show through */
|
|
1706
1717
|
}
|
|
1707
1718
|
/* fixed, so it covers the top of the screen it sits in — reserve its height
|
|
1708
1719
|
there, from the same token, the way the bottom bars reserve theirs. The
|
|
@@ -1719,19 +1730,19 @@ button { font: inherit; cursor: pointer; }
|
|
|
1719
1730
|
|
|
1720
1731
|
/* ---- icon button (round) ---- */
|
|
1721
1732
|
.icon-btn {
|
|
1722
|
-
width: var(--tap); height: var(--tap);
|
|
1733
|
+
width: var(--icon-btn-size, var(--tap)); height: var(--icon-btn-size, var(--tap));
|
|
1723
1734
|
flex: none;
|
|
1724
|
-
border-radius: var(--r-chip);
|
|
1725
|
-
border: var(--border-w) solid var(--outline); /* see .btn — same reason */
|
|
1726
|
-
background: var(--action-bg);
|
|
1727
|
-
color: var(--action-ink);
|
|
1735
|
+
border-radius: var(--icon-btn-radius, var(--r-chip));
|
|
1736
|
+
border: var(--border-w) solid var(--icon-btn-border, var(--outline)); /* see .btn — same reason */
|
|
1737
|
+
background: var(--icon-btn-bg, var(--action-bg));
|
|
1738
|
+
color: var(--icon-btn-ink, var(--action-ink));
|
|
1728
1739
|
display: grid;
|
|
1729
1740
|
place-items: center;
|
|
1730
1741
|
font-size: var(--fs-lg);
|
|
1731
1742
|
line-height: 1;
|
|
1732
1743
|
}
|
|
1733
|
-
.icon-btn--invert { background: var(--accent); color: var(--on-accent); border-color: transparent; }
|
|
1734
|
-
.icon-btn--sm { width: var(--tap-sm); height: var(--tap-sm); font-size: var(--fs-title); }
|
|
1744
|
+
.icon-btn--invert { background: var(--icon-btn-invert-bg, var(--accent)); color: var(--icon-btn-invert-ink, var(--on-accent)); border-color: transparent; }
|
|
1745
|
+
.icon-btn--sm { width: var(--icon-btn-sm-size, var(--tap-sm)); height: var(--icon-btn-sm-size, var(--tap-sm)); font-size: var(--fs-title); }
|
|
1735
1746
|
/* fab: the square floating action, bottom-right of a stage or screen */
|
|
1736
1747
|
.fab { width: var(--fab); height: var(--fab); border-radius: var(--r-card); position: absolute; right: var(--sp-4); bottom: calc(var(--sp-5) + var(--bar-h) + var(--sp-3)); box-shadow: var(--shadow-float); z-index: 31; }
|
|
1737
1748
|
|
|
@@ -1740,21 +1751,21 @@ button { font: inherit; cursor: pointer; }
|
|
|
1740
1751
|
/* --outline, not --action-border: same reason as .chip — on a palette where
|
|
1741
1752
|
--card-1-bg equals --action-bg a transparent border makes a plain button
|
|
1742
1753
|
invisible on a white card. --primary and --quiet set their own edge. */
|
|
1743
|
-
border: var(--border-w) solid var(--outline);
|
|
1744
|
-
background: var(--action-bg);
|
|
1745
|
-
color: var(--action-ink);
|
|
1746
|
-
border-radius: var(--r-chip);
|
|
1747
|
-
padding: var(--sp-4) var(--sp-6);
|
|
1754
|
+
border: var(--border-w) solid var(--btn-border, var(--outline));
|
|
1755
|
+
background: var(--btn-bg, var(--action-bg));
|
|
1756
|
+
color: var(--btn-ink, var(--action-ink));
|
|
1757
|
+
border-radius: var(--btn-radius, var(--r-chip));
|
|
1758
|
+
padding: var(--btn-pad-y, var(--sp-4)) var(--btn-pad-x, var(--sp-6));
|
|
1748
1759
|
font: var(--type-label);
|
|
1749
|
-
font-size: var(--fs-md);
|
|
1760
|
+
font-size: var(--btn-font-size, var(--fs-md));
|
|
1750
1761
|
display: inline-flex;
|
|
1751
1762
|
align-items: center;
|
|
1752
1763
|
justify-content: center;
|
|
1753
|
-
gap: var(--sp-2);
|
|
1764
|
+
gap: var(--btn-gap, var(--sp-2));
|
|
1754
1765
|
min-height: var(--btn-h);
|
|
1755
1766
|
text-decoration: none; /* .btn works as <a> too */
|
|
1756
1767
|
}
|
|
1757
|
-
.btn--primary { background: var(--accent); color: var(--on-accent); border-color: transparent; }
|
|
1768
|
+
.btn--primary { background: var(--btn-primary-bg, var(--accent)); color: var(--btn-primary-ink, var(--on-accent)); border-color: transparent; }
|
|
1758
1769
|
/* quiet keeps a faint outline so it still reads as a button on colored palettes;
|
|
1759
1770
|
it is ink on whatever it sits on — inherit, or on the dark slot (card--3) it
|
|
1760
1771
|
would take the light-card action ink and vanish */
|
|
@@ -1774,25 +1785,25 @@ button { font: inherit; cursor: pointer; }
|
|
|
1774
1785
|
.chip {
|
|
1775
1786
|
display: inline-flex;
|
|
1776
1787
|
align-items: center;
|
|
1777
|
-
gap: var(--sp-2);
|
|
1778
|
-
border-radius: var(--r-chip);
|
|
1788
|
+
gap: var(--chip-gap, var(--sp-2));
|
|
1789
|
+
border-radius: var(--chip-radius, var(--r-chip));
|
|
1779
1790
|
/* --outline, not --action-border: a chip is a control, and on a palette
|
|
1780
1791
|
where --card-1-bg == --action-bg (field, roast, hydro) a transparent
|
|
1781
1792
|
border makes it invisible on a white card. Same edge fields, checks,
|
|
1782
1793
|
toggles, tiles and the dropdown already use. */
|
|
1783
|
-
border: var(--border-w) solid var(--outline);
|
|
1784
|
-
background: var(--action-bg);
|
|
1785
|
-
color: var(--action-ink);
|
|
1786
|
-
padding: var(--sp-2) var(--sp-3);
|
|
1794
|
+
border: var(--border-w) solid var(--chip-border, var(--outline));
|
|
1795
|
+
background: var(--chip-bg, var(--action-bg));
|
|
1796
|
+
color: var(--chip-ink, var(--action-ink));
|
|
1797
|
+
padding: var(--chip-pad-y, var(--sp-2)) var(--chip-pad-x, var(--sp-3));
|
|
1787
1798
|
font: var(--type-label);
|
|
1788
|
-
font-size: var(--fs-sm);
|
|
1799
|
+
font-size: var(--chip-font-size, var(--fs-sm));
|
|
1789
1800
|
min-height: var(--chip-h);
|
|
1790
1801
|
text-decoration: none;
|
|
1791
1802
|
justify-self: start; /* as a grid child it hugs its text, never stretches */
|
|
1792
1803
|
}
|
|
1793
1804
|
.dot { width: var(--dot); height: var(--dot); flex: none; border-radius: 50%; background: var(--dot-a); } /* signal dot: chips, legends */
|
|
1794
1805
|
.dot--b { background: var(--dot-b); }
|
|
1795
|
-
.chip--on { background: var(--accent); color: var(--on-accent); border-color: transparent; }
|
|
1806
|
+
.chip--on { background: var(--chip-on-bg, var(--accent)); color: var(--chip-on-ink, var(--on-accent)); border-color: transparent; }
|
|
1796
1807
|
/* dark-slot inversion lives in card.css (.card--3 :is(...)) */
|
|
1797
1808
|
|
|
1798
1809
|
.chip-row { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
|
|
@@ -1896,14 +1907,9 @@ button { font: inherit; cursor: pointer; }
|
|
|
1896
1907
|
<button class="icon-btn icon-btn--invert" aria-label="ถัดไป">…</button>
|
|
1897
1908
|
</div> — or the same two in an .action-bar__tier--pager under a control */
|
|
1898
1909
|
.action-bar--pager { align-items: center; }
|
|
1899
|
-
/* The bar belongs to the BASE
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
foot (sheet.css). So a pager never works beside a sheet — that screen has work that cannot be walked
|
|
1903
|
-
past — and neither does any other bar: while a sheet is on (only .sheet--away, a sheet not called yet,
|
|
1904
|
-
is not), the bar takes no pointer here and cardds.js makes it inert, so the keyboard cannot reach what
|
|
1905
|
-
the eye cannot see. */
|
|
1906
|
-
:has(.step > .sheet:not(.sheet--away)) > .action-bar { pointer-events: none; }
|
|
1910
|
+
/* The bar belongs to the BASE: the move of a page of words — a pager turning them, or one wide button. A screen
|
|
1911
|
+
with a sheet finishes on the sheet's own foot instead (sheet.css). Guidance for composing, not a rule the
|
|
1912
|
+
CSS enforces: a component never changes because another one is there. */
|
|
1907
1913
|
/* the page dots: under the card in a .screen__centre group; tight gaps */
|
|
1908
1914
|
.pager__at { flex: 0 1 auto; min-width: 0; overflow: hidden; display: flex; align-items: center; gap: var(--sp-1); }
|
|
1909
1915
|
.pager__at > * {
|
|
@@ -1933,6 +1939,9 @@ button { font: inherit; cursor: pointer; }
|
|
|
1933
1939
|
|
|
1934
1940
|
/* the first round button sits at the left edge, the last at the right; a skip link between them stays centred */
|
|
1935
1941
|
:is(.action-bar--pager, .action-bar__tier--pager) > .icon-btn:first-child { margin-right: auto; }
|
|
1942
|
+
/* …and whatever goes BETWEEN the two (a "skip" link) stands in the middle: the bar places it, never the link itself */
|
|
1943
|
+
:is(.action-bar--pager, .action-bar__tier--pager) > :not(.icon-btn):not(:first-child):not(:last-child) { margin-inline: auto; }
|
|
1944
|
+
:is(.action-bar--pager, .action-bar__tier--pager):has(> :nth-child(3)) > .icon-btn:first-child { margin-right: 0; }
|
|
1936
1945
|
|
|
1937
1946
|
/* .screen's default bottom padding is a constant; derive the reserve from the
|
|
1938
1947
|
bar instead, so a taller button (a longer label, a script with more leading)
|
|
@@ -1976,8 +1985,8 @@ button { font: inherit; cursor: pointer; }
|
|
|
1976
1985
|
mask: radial-gradient(farthest-side, transparent calc(100% - var(--_w) - 1px), currentColor calc(100% - var(--_w)));
|
|
1977
1986
|
-webkit-mask: radial-gradient(farthest-side, transparent calc(100% - var(--_w) - 1px), currentColor calc(100% - var(--_w)));
|
|
1978
1987
|
}
|
|
1979
|
-
.ring__value { font: var(--type-stat); letter-spacing: var(--track-display); }
|
|
1980
|
-
.ring__label { font: var(--type-caption); color: var(--card-muted); }
|
|
1988
|
+
.ring__value { font: var(--ring-value-font, var(--type-stat)); letter-spacing: var(--track-display); }
|
|
1989
|
+
.ring__label { font: var(--ring-label-font, var(--type-caption)); color: var(--ring-label-ink, var(--card-muted)); }
|
|
1981
1990
|
.card--3 .ring__label { color: inherit; opacity: 0.7; }
|
|
1982
1991
|
.ring--sm { --_size: var(--avatar-xl); --_w: var(--sp-3); }
|
|
1983
1992
|
.ring--sm .ring__value { font: 800 var(--fs-2xl)/1 var(--font-display); }
|
|
@@ -1997,10 +2006,10 @@ button { font: inherit; cursor: pointer; }
|
|
|
1997
2006
|
--on-accent: var(--_bg);
|
|
1998
2007
|
list-style: none;
|
|
1999
2008
|
margin: 0;
|
|
2000
|
-
padding: var(--sp-2);
|
|
2009
|
+
padding: var(--track-pad, var(--sp-2));
|
|
2001
2010
|
display: flex;
|
|
2002
2011
|
align-items: center;
|
|
2003
|
-
border-radius: var(--r-chip);
|
|
2012
|
+
border-radius: var(--track-radius, var(--r-chip));
|
|
2004
2013
|
background: var(--_bg);
|
|
2005
2014
|
color: var(--_ink);
|
|
2006
2015
|
}
|
|
@@ -2041,9 +2050,9 @@ button { font: inherit; cursor: pointer; }
|
|
|
2041
2050
|
grid-template-areas: "label num" "foot num";
|
|
2042
2051
|
align-items: end;
|
|
2043
2052
|
gap: var(--sp-2) var(--sp-4);
|
|
2044
|
-
min-height: var(--tile-h);
|
|
2053
|
+
min-height: var(--card-band-min-h, var(--tile-h));
|
|
2045
2054
|
}
|
|
2046
|
-
.band__label { grid-area: label; align-self: start; font: var(--type-label); font-size: var(--fs-body); line-height: 1.2; }
|
|
2055
|
+
.band__label { grid-area: label; align-self: start; font: var(--band-label-font, var(--type-label)); font-size: var(--band-label-font-size, var(--fs-body)); line-height: 1.2; }
|
|
2047
2056
|
.band__num {
|
|
2048
2057
|
grid-area: num;
|
|
2049
2058
|
font: 800 var(--fs-giant) / 0.9 var(--font-display);
|
|
@@ -2051,14 +2060,14 @@ button { font: inherit; cursor: pointer; }
|
|
|
2051
2060
|
font-variant-numeric: tabular-nums;
|
|
2052
2061
|
}
|
|
2053
2062
|
.band__num small { font-size: 0.5em; font-weight: 700; margin-right: 0.1em; } /* unit or % */
|
|
2054
|
-
.band__foot { grid-area: foot; font: var(--type-caption); color: var(--card-muted); }
|
|
2063
|
+
.band__foot { grid-area: foot; font: var(--band-foot-font, var(--type-caption)); color: var(--band-foot-ink, var(--card-muted)); }
|
|
2055
2064
|
.card--3 .band__foot { color: inherit; opacity: 0.7; }
|
|
2056
2065
|
/* band stack: ONE card boundary; bands are frameless inside it, a hairline
|
|
2057
2066
|
between each. Bands may still carry slot tints (card--2 / card--3). */
|
|
2058
2067
|
.band-stack {
|
|
2059
2068
|
display: grid;
|
|
2060
|
-
border: var(--border-w) solid var(--card-border);
|
|
2061
|
-
border-radius: var(--r-card);
|
|
2069
|
+
border: var(--border-w) solid var(--band-stack-border, var(--card-border));
|
|
2070
|
+
border-radius: var(--band-stack-radius, var(--r-card));
|
|
2062
2071
|
overflow: hidden;
|
|
2063
2072
|
}
|
|
2064
2073
|
.band-stack > .card--band { border: 0; border-radius: 0; box-shadow: none; }
|
|
@@ -2109,7 +2118,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
2109
2118
|
|
|
2110
2119
|
/* ---- picker: horizontal snap picker, centre value big ----
|
|
2111
2120
|
<div class="picker"><div class="picker__rail"><button class="picker__item">100</button>…</div><span class="picker__unit">ml</span></div> */
|
|
2112
|
-
.picker { display: grid; gap: var(--sp-1); justify-items: center; position: relative; }
|
|
2121
|
+
.picker { display: grid; gap: var(--picker-gap, var(--sp-1)); justify-items: center; position: relative; }
|
|
2113
2122
|
.picker__rail {
|
|
2114
2123
|
width: 100%;
|
|
2115
2124
|
display: grid;
|
|
@@ -2117,7 +2126,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
2117
2126
|
/* side padding = one third of the rail, so the first and last value can sit
|
|
2118
2127
|
in the centre; the content box is then one third wide, and each column
|
|
2119
2128
|
fills it (percent columns resolve against the content box) */
|
|
2120
|
-
padding-inline: calc(100% / 3);
|
|
2129
|
+
padding-inline: var(--picker-rail-pad-x, calc(100% / 3));
|
|
2121
2130
|
grid-auto-columns: 100%;
|
|
2122
2131
|
overflow-x: auto;
|
|
2123
2132
|
scroll-snap-type: x mandatory;
|
|
@@ -2130,8 +2139,8 @@ button { font: inherit; cursor: pointer; }
|
|
|
2130
2139
|
border: 0;
|
|
2131
2140
|
background: transparent;
|
|
2132
2141
|
color: inherit;
|
|
2133
|
-
padding: var(--sp-2) 0;
|
|
2134
|
-
font: var(--type-stat);
|
|
2142
|
+
padding: var(--picker-item-pad-y, var(--sp-2)) var(--picker-item-pad-x, 0);
|
|
2143
|
+
font: var(--picker-item-font, var(--type-stat));
|
|
2135
2144
|
letter-spacing: var(--track-display);
|
|
2136
2145
|
font-variant-numeric: tabular-nums;
|
|
2137
2146
|
opacity: 0.3;
|
|
@@ -2150,7 +2159,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
2150
2159
|
left: calc(100% / 3);
|
|
2151
2160
|
}
|
|
2152
2161
|
.picker::after { left: auto; right: calc(100% / 3); }
|
|
2153
|
-
.picker__unit { font: var(--type-caption); color: var(--card-muted); }
|
|
2162
|
+
.picker__unit { font: var(--picker-unit-font, var(--type-caption)); color: var(--picker-unit-ink, var(--card-muted)); }
|
|
2154
2163
|
.card--3 .picker__unit { color: inherit; opacity: 0.7; }
|
|
2155
2164
|
/* the scrolled-to item lights up by position — no JS */
|
|
2156
2165
|
@supports (animation-timeline: view(x)) {
|
|
@@ -2166,30 +2175,30 @@ button { font: inherit; cursor: pointer; }
|
|
|
2166
2175
|
.badge {
|
|
2167
2176
|
display: inline-grid;
|
|
2168
2177
|
place-items: center;
|
|
2169
|
-
min-width: var(--badge);
|
|
2170
|
-
height: var(--badge);
|
|
2171
|
-
padding: 0 var(--sp-2);
|
|
2172
|
-
border-radius: var(--r-chip);
|
|
2173
|
-
background: var(--accent);
|
|
2174
|
-
color: var(--on-accent);
|
|
2175
|
-
font: var(--type-label);
|
|
2178
|
+
min-width: var(--badge-min-w, var(--badge));
|
|
2179
|
+
height: var(--badge-h, var(--badge));
|
|
2180
|
+
padding: var(--badge-pad-y, 0) var(--badge-pad-x, var(--sp-2));
|
|
2181
|
+
border-radius: var(--badge-radius, var(--r-chip));
|
|
2182
|
+
background: var(--badge-bg, var(--accent));
|
|
2183
|
+
color: var(--badge-ink, var(--on-accent));
|
|
2184
|
+
font: var(--badge-font, var(--type-label));
|
|
2176
2185
|
font-variant-numeric: tabular-nums;
|
|
2177
2186
|
vertical-align: middle;
|
|
2178
2187
|
}
|
|
2179
|
-
.badge--soft { background: var(--ink-tint); color: inherit; }
|
|
2188
|
+
.badge--soft { background: var(--badge-soft-bg, var(--ink-tint)); color: inherit; }
|
|
2180
2189
|
|
|
2181
2190
|
/* ---- bars: three or four bars with a count on top — the glance chart ----
|
|
2182
2191
|
<div class="bars"><div class="bar" style="--v: 16"><span>+16</span></div>… --max on the parent */
|
|
2183
|
-
.bars { --max: 20; --_h: 5rem; display: flex; align-items: end; gap: var(--sp-2); height: calc(var(--_h) + var(--sp-8)); }
|
|
2192
|
+
.bars { --max: 20; --_h: 5rem; display: flex; align-items: end; gap: var(--bars-gap, var(--sp-2)); height: calc(var(--_h) + var(--sp-8)); }
|
|
2184
2193
|
.bar {
|
|
2185
2194
|
flex: 1;
|
|
2186
2195
|
min-width: 0;
|
|
2187
2196
|
display: grid;
|
|
2188
2197
|
align-content: end;
|
|
2189
2198
|
justify-items: center;
|
|
2190
|
-
gap: var(--sp-1);
|
|
2199
|
+
gap: var(--bar-gap, var(--sp-1));
|
|
2191
2200
|
height: 100%;
|
|
2192
|
-
font: var(--type-caption);
|
|
2201
|
+
font: var(--bar-font, var(--type-caption));
|
|
2193
2202
|
font-weight: 700;
|
|
2194
2203
|
}
|
|
2195
2204
|
.bar::after {
|
|
@@ -2220,9 +2229,9 @@ button { font: inherit; cursor: pointer; }
|
|
|
2220
2229
|
border-radius: 50%;
|
|
2221
2230
|
display: grid;
|
|
2222
2231
|
place-items: center;
|
|
2223
|
-
background: var(--card-2-bg);
|
|
2224
|
-
color: var(--card-2-ink);
|
|
2225
|
-
font: var(--type-label);
|
|
2232
|
+
background: var(--avatar-bg, var(--card-2-bg));
|
|
2233
|
+
color: var(--avatar-ink, var(--card-2-ink));
|
|
2234
|
+
font: var(--avatar-font, var(--type-label));
|
|
2226
2235
|
font-size: calc(var(--_size) * 0.3);
|
|
2227
2236
|
text-transform: uppercase;
|
|
2228
2237
|
letter-spacing: 0.02em;
|
|
@@ -2235,10 +2244,10 @@ button { font: inherit; cursor: pointer; }
|
|
|
2235
2244
|
.avatar--lg { --_size: var(--avatar-lg); }
|
|
2236
2245
|
.avatar--xl { --_size: var(--avatar-xl); } /* sheet head icon ring */
|
|
2237
2246
|
/* outline avatar: no fill, an edge — icons in a ring, "add" slots */
|
|
2238
|
-
.avatar--outline { background: transparent; color: inherit; border: var(--border-w) solid var(--outline); }
|
|
2239
|
-
.avatar--add { background: transparent; color: inherit; border: var(--border-w) dashed var(--outline); cursor: pointer; }
|
|
2247
|
+
.avatar--outline { background: transparent; color: inherit; border: var(--border-w) solid var(--avatar-outline-border, var(--outline)); }
|
|
2248
|
+
.avatar--add { background: transparent; color: inherit; border: var(--border-w) dashed var(--avatar-add-border, var(--outline)); cursor: pointer; }
|
|
2240
2249
|
/* accent avatar: the "+7" tail, the selected person */
|
|
2241
|
-
.avatar--on { background: var(--accent); color: var(--on-accent); }
|
|
2250
|
+
.avatar--on { background: var(--avatar-on-bg, var(--accent)); color: var(--avatar-on-ink, var(--on-accent)); }
|
|
2242
2251
|
/* halo: faint concentric rings behind a hero avatar (decorative) */
|
|
2243
2252
|
.avatar--halo::before {
|
|
2244
2253
|
content: "";
|
|
@@ -2260,7 +2269,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
2260
2269
|
<div class="avatar-pick"><button class="avatar-pick__item"><span class="avatar avatar--lg avatar--add">+</span><span class="avatar-pick__name">Add</span><span class="avatar-pick__role">member</span></button>…</div> */
|
|
2261
2270
|
.avatar-pick {
|
|
2262
2271
|
display: flex;
|
|
2263
|
-
gap: var(--sp-4);
|
|
2272
|
+
gap: var(--avatar-pick-gap, var(--sp-4));
|
|
2264
2273
|
overflow-x: auto;
|
|
2265
2274
|
scroll-snap-type: x proximity;
|
|
2266
2275
|
scrollbar-width: none; /* starts at the card's padding edge, like every row */
|
|
@@ -2269,18 +2278,18 @@ button { font: inherit; cursor: pointer; }
|
|
|
2269
2278
|
.avatar-pick__item {
|
|
2270
2279
|
scroll-snap-align: start;
|
|
2271
2280
|
flex: none;
|
|
2272
|
-
width: var(--avatar-lg);
|
|
2281
|
+
width: var(--avatar-pick-item-w, var(--avatar-lg));
|
|
2273
2282
|
display: grid;
|
|
2274
2283
|
justify-items: center;
|
|
2275
|
-
gap: var(--sp-2);
|
|
2284
|
+
gap: var(--avatar-pick-item-gap, var(--sp-2));
|
|
2276
2285
|
border: 0;
|
|
2277
2286
|
background: transparent;
|
|
2278
2287
|
color: inherit;
|
|
2279
2288
|
padding: 0;
|
|
2280
2289
|
text-align: center;
|
|
2281
2290
|
}
|
|
2282
|
-
.avatar-pick__name { font: var(--type-label); font-size: var(--fs-sm); }
|
|
2283
|
-
.avatar-pick__role { font: var(--type-caption); color: var(--card-muted); margin-top: calc(-1 * var(--sp-1)); }
|
|
2291
|
+
.avatar-pick__name { font: var(--avatar-pick-name-font, var(--type-label)); font-size: var(--avatar-pick-name-font-size, var(--fs-sm)); }
|
|
2292
|
+
.avatar-pick__role { font: var(--avatar-pick-role-font, var(--type-caption)); color: var(--avatar-pick-role-ink, var(--card-muted)); margin-top: calc(-1 * var(--sp-1)); }
|
|
2284
2293
|
.card--3 .avatar-pick__role { color: inherit; opacity: 0.7; }
|
|
2285
2294
|
|
|
2286
2295
|
/* ---- css/choice.css — check, toggle, toggle chip, chip grid, days, calendar, mood, pin, composer ---- */
|
|
@@ -2298,13 +2307,13 @@ button { font: inherit; cursor: pointer; }
|
|
|
2298
2307
|
<input type="checkbox" class="check" aria-label="Done"> */
|
|
2299
2308
|
.check {
|
|
2300
2309
|
appearance: none;
|
|
2301
|
-
width: var(--tap);
|
|
2302
|
-
height: var(--tap);
|
|
2310
|
+
width: var(--check-size, var(--tap));
|
|
2311
|
+
height: var(--check-size, var(--tap));
|
|
2303
2312
|
flex: none;
|
|
2304
2313
|
margin: 0;
|
|
2305
2314
|
border-radius: 50%;
|
|
2306
|
-
border: var(--border-w) solid var(--outline);
|
|
2307
|
-
background: var(--action-bg);
|
|
2315
|
+
border: var(--border-w) solid var(--check-border, var(--outline));
|
|
2316
|
+
background: var(--check-bg, var(--action-bg));
|
|
2308
2317
|
display: grid;
|
|
2309
2318
|
place-items: center;
|
|
2310
2319
|
cursor: pointer;
|
|
@@ -2321,7 +2330,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
2321
2330
|
.check:checked { background: var(--accent); border-color: transparent; }
|
|
2322
2331
|
.check:checked::after { opacity: 1; }
|
|
2323
2332
|
.check:focus-visible { outline: var(--focus); outline-offset: var(--sp-1); }
|
|
2324
|
-
.check--sm { width: var(--tap-sm); height: var(--tap-sm); }
|
|
2333
|
+
.check--sm { width: var(--check-sm-size, var(--tap-sm)); height: var(--check-sm-size, var(--tap-sm)); }
|
|
2325
2334
|
|
|
2326
2335
|
/* ---- toggle: big switch ----
|
|
2327
2336
|
<input type="checkbox" role="switch" class="toggle" aria-label="Private"> */
|
|
@@ -2334,9 +2343,9 @@ button { font: inherit; cursor: pointer; }
|
|
|
2334
2343
|
height: var(--_h);
|
|
2335
2344
|
flex: none;
|
|
2336
2345
|
margin: 0;
|
|
2337
|
-
border-radius: var(--r-chip);
|
|
2338
|
-
border: var(--border-w) solid var(--outline);
|
|
2339
|
-
background: var(--action-bg);
|
|
2346
|
+
border-radius: var(--toggle-radius, var(--r-chip));
|
|
2347
|
+
border: var(--border-w) solid var(--toggle-border, var(--outline));
|
|
2348
|
+
background: var(--toggle-bg, var(--action-bg));
|
|
2340
2349
|
position: relative;
|
|
2341
2350
|
cursor: pointer;
|
|
2342
2351
|
transition: background 0.2s ease;
|
|
@@ -2365,7 +2374,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
2365
2374
|
.chip-grid {
|
|
2366
2375
|
display: grid;
|
|
2367
2376
|
grid-template-columns: repeat(auto-fill, minmax(min(5.5rem, 100%), 1fr));
|
|
2368
|
-
gap: var(--sp-2);
|
|
2377
|
+
gap: var(--chip-grid-gap, var(--sp-2));
|
|
2369
2378
|
}
|
|
2370
2379
|
/* .chip hugs its text as a loose grid child (justify-self: start); inside a
|
|
2371
2380
|
chip grid the whole point is equal, full-width pick targets, so stretch.
|
|
@@ -2392,7 +2401,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
2392
2401
|
|
|
2393
2402
|
/* ---- day strip: a week, one day selected ----
|
|
2394
2403
|
<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> */
|
|
2395
|
-
.day-strip { display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--sp-1); }
|
|
2404
|
+
.day-strip { display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--day-strip-gap, var(--sp-1)); }
|
|
2396
2405
|
.day {
|
|
2397
2406
|
display: grid;
|
|
2398
2407
|
/* three rows, always: name · number · dot. The dot's row is reserved even on
|
|
@@ -2402,33 +2411,33 @@ button { font: inherit; cursor: pointer; }
|
|
|
2402
2411
|
grid-template-rows: auto auto var(--dot-xs);
|
|
2403
2412
|
align-content: center; /* the group sits centred in the cell, not spread out */
|
|
2404
2413
|
justify-items: center;
|
|
2405
|
-
gap: var(--sp-0);
|
|
2414
|
+
gap: var(--day-gap, var(--sp-0));
|
|
2406
2415
|
min-width: 0;
|
|
2407
|
-
min-height: var(--bar-h);
|
|
2408
|
-
padding-block: var(--sp-3); /* equal air top and bottom, so the selected pill
|
|
2416
|
+
min-height: var(--day-min-h, var(--bar-h));
|
|
2417
|
+
padding-block: var(--day-pad-y, var(--sp-3)); /* equal air top and bottom, so the selected pill
|
|
2409
2418
|
is the same shape on every day */
|
|
2410
2419
|
padding-inline: 0;
|
|
2411
2420
|
border: 0;
|
|
2412
|
-
border-radius: var(--r-chip);
|
|
2421
|
+
border-radius: var(--day-radius, var(--r-chip));
|
|
2413
2422
|
background: transparent;
|
|
2414
2423
|
color: inherit;
|
|
2415
2424
|
opacity: 0.6;
|
|
2416
2425
|
}
|
|
2417
|
-
.day__name { font: var(--type-caption); }
|
|
2426
|
+
.day__name { font: var(--day-name-font, var(--type-caption)); }
|
|
2418
2427
|
.day__num { font: 700 var(--fs-lg)/1.1 var(--font-display); font-variant-numeric: tabular-nums; }
|
|
2419
|
-
.day[aria-selected="true"] { background: var(--accent); color: var(--on-accent); opacity: 1; }
|
|
2420
|
-
.day__dot { grid-row: 3; align-self: center; width: var(--dot-xs); height: var(--dot-xs); border-radius: 50%; background: currentColor; }
|
|
2428
|
+
.day[aria-selected="true"] { background: var(--day-selected-bg, var(--accent)); color: var(--day-selected-ink, var(--on-accent)); opacity: 1; }
|
|
2429
|
+
.day__dot { grid-row: 3; align-self: center; width: var(--day-dot-size, var(--dot-xs)); height: var(--day-dot-size, var(--dot-xs)); border-radius: 50%; background: currentColor; }
|
|
2421
2430
|
|
|
2422
2431
|
/* ---- calendar: month grid, 44px cells, one accent day, optional marks ----
|
|
2423
2432
|
<div class="calendar"><div class="calendar__head">…</div><div class="calendar__grid"><span class="calendar__wd">Mo</span>×7 <button class="calendar__day" style="--start: 3">1</button>…</div></div> */
|
|
2424
|
-
.calendar { display: grid; gap: var(--sp-3); }
|
|
2425
|
-
.calendar__head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); }
|
|
2426
|
-
.calendar__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--sp-1); justify-items: center; }
|
|
2427
|
-
.calendar__wd { font: var(--type-overline); letter-spacing: var(--track-overline); text-transform: uppercase; color: var(--card-muted); padding-block: var(--sp-2); }
|
|
2433
|
+
.calendar { display: grid; gap: var(--calendar-gap, var(--sp-3)); }
|
|
2434
|
+
.calendar__head { display: flex; align-items: center; justify-content: space-between; gap: var(--calendar-head-gap, var(--sp-2)); }
|
|
2435
|
+
.calendar__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--calendar-grid-gap, var(--sp-1)); justify-items: center; }
|
|
2436
|
+
.calendar__wd { font: var(--calendar-wd-font, var(--type-overline)); letter-spacing: var(--track-overline); text-transform: uppercase; color: var(--calendar-wd-ink, var(--card-muted)); padding-block: var(--calendar-wd-pad-y, var(--sp-2)); }
|
|
2428
2437
|
.card--3 .calendar__wd { color: inherit; opacity: 0.7; }
|
|
2429
2438
|
.calendar__day {
|
|
2430
2439
|
width: 100%;
|
|
2431
|
-
max-width: var(--tap);
|
|
2440
|
+
max-width: var(--calendar-day-max-w, var(--tap));
|
|
2432
2441
|
aspect-ratio: 1;
|
|
2433
2442
|
display: grid;
|
|
2434
2443
|
place-items: center;
|
|
@@ -2440,9 +2449,9 @@ button { font: inherit; cursor: pointer; }
|
|
|
2440
2449
|
font-variant-numeric: tabular-nums;
|
|
2441
2450
|
grid-column-start: var(--start, auto); /* --start on the 1st: weekday column 1–7 */
|
|
2442
2451
|
}
|
|
2443
|
-
.calendar__day--mark { background: var(--accent-soft); }
|
|
2444
|
-
.calendar__day--mark2 { background: var(--accent-mid); color: var(--on-accent); }
|
|
2445
|
-
.calendar__day[aria-selected="true"] { background: var(--accent); color: var(--on-accent); font-weight: 700; }
|
|
2452
|
+
.calendar__day--mark { background: var(--calendar-day-mark-bg, var(--accent-soft)); }
|
|
2453
|
+
.calendar__day--mark2 { background: var(--calendar-day-mark2-bg, var(--accent-mid)); color: var(--calendar-day-mark2-ink, var(--on-accent)); }
|
|
2454
|
+
.calendar__day[aria-selected="true"] { background: var(--calendar-day-selected-bg, var(--accent)); color: var(--calendar-day-selected-ink, var(--on-accent)); font-weight: 700; }
|
|
2446
2455
|
.calendar__day:disabled { opacity: 0.3; }
|
|
2447
2456
|
|
|
2448
2457
|
/* ---- mood: five dots in a pill, the picked one grows ----
|
|
@@ -2450,19 +2459,19 @@ button { font: inherit; cursor: pointer; }
|
|
|
2450
2459
|
.mood {
|
|
2451
2460
|
margin: 0;
|
|
2452
2461
|
min-inline-size: 0; /* fieldset UA default is min-content — it must shrink with the card */
|
|
2453
|
-
padding: var(--sp-1);
|
|
2454
|
-
border: var(--border-w) solid var(--outline);
|
|
2455
|
-
border-radius: var(--r-chip);
|
|
2456
|
-
background: var(--action-bg);
|
|
2457
|
-
color: var(--action-ink);
|
|
2462
|
+
padding: var(--mood-pad, var(--sp-1));
|
|
2463
|
+
border: var(--border-w) solid var(--mood-border, var(--outline));
|
|
2464
|
+
border-radius: var(--mood-radius, var(--r-chip));
|
|
2465
|
+
background: var(--mood-bg, var(--action-bg));
|
|
2466
|
+
color: var(--mood-ink, var(--action-ink));
|
|
2458
2467
|
display: flex;
|
|
2459
2468
|
justify-content: space-between;
|
|
2460
2469
|
}
|
|
2461
|
-
.mood__opt { flex: 1 1 0; max-width: var(--tap); min-width: 0; height: var(--tap); display: grid; place-items: center; position: relative; cursor: pointer; }
|
|
2470
|
+
.mood__opt { flex: 1 1 0; max-width: var(--mood-opt-max-w, var(--tap)); min-width: 0; height: var(--mood-opt-h, var(--tap)); display: grid; place-items: center; position: relative; cursor: pointer; }
|
|
2462
2471
|
.mood__opt > input { appearance: none; position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
|
|
2463
2472
|
.mood__dot {
|
|
2464
|
-
width: var(--icon-xs);
|
|
2465
|
-
height: var(--icon-xs);
|
|
2473
|
+
width: var(--mood-dot-size, var(--icon-xs));
|
|
2474
|
+
height: var(--mood-dot-size, var(--icon-xs));
|
|
2466
2475
|
border-radius: 50%;
|
|
2467
2476
|
background: var(--_mood, currentColor);
|
|
2468
2477
|
transition: scale 0.2s ease, box-shadow 0.2s ease;
|
|
@@ -2477,18 +2486,18 @@ button { font: inherit; cursor: pointer; }
|
|
|
2477
2486
|
|
|
2478
2487
|
/* ---- pin: big code entry, one digit per pill ----
|
|
2479
2488
|
<div class="pin"><input class="pin__cell" inputmode="numeric" maxlength="1" placeholder=" ">×4</div> */
|
|
2480
|
-
.pin { display: flex; gap: var(--sp-3); }
|
|
2489
|
+
.pin { display: flex; gap: var(--pin-gap, var(--sp-3)); }
|
|
2481
2490
|
.pin__cell {
|
|
2482
2491
|
flex: 1;
|
|
2483
2492
|
min-width: 0;
|
|
2484
|
-
max-width: var(--fab);
|
|
2493
|
+
max-width: var(--pin-cell-max-w, var(--fab));
|
|
2485
2494
|
aspect-ratio: 2 / 3;
|
|
2486
|
-
border: var(--border-w) solid var(--outline);
|
|
2487
|
-
border-radius: var(--r-chip);
|
|
2488
|
-
background: var(--action-bg);
|
|
2489
|
-
color: var(--action-ink);
|
|
2495
|
+
border: var(--border-w) solid var(--pin-cell-border, var(--outline));
|
|
2496
|
+
border-radius: var(--pin-cell-radius, var(--r-chip));
|
|
2497
|
+
background: var(--pin-cell-bg, var(--action-bg));
|
|
2498
|
+
color: var(--pin-cell-ink, var(--action-ink));
|
|
2490
2499
|
text-align: center;
|
|
2491
|
-
font: var(--type-stat);
|
|
2500
|
+
font: var(--pin-cell-font, var(--type-stat));
|
|
2492
2501
|
font-variant-numeric: tabular-nums;
|
|
2493
2502
|
caret-color: currentColor;
|
|
2494
2503
|
}
|
|
@@ -2498,7 +2507,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
2498
2507
|
/* ---- composer: big text area with a bottom bar (icon · hint · send) ----
|
|
2499
2508
|
<div class="composer"><textarea class="composer__input" placeholder="What do you need?"></textarea>
|
|
2500
2509
|
<div class="composer__bar"><button class="icon-btn">…</button><span class="composer__hint">Your idea is born</span><button class="icon-btn icon-btn--invert">↑</button></div></div> */
|
|
2501
|
-
.composer { display: grid; gap: var(--sp-3); }
|
|
2510
|
+
.composer { display: grid; gap: var(--composer-gap, var(--sp-3)); }
|
|
2502
2511
|
.composer__input {
|
|
2503
2512
|
width: 100%;
|
|
2504
2513
|
min-height: 11rem;
|
|
@@ -2512,8 +2521,8 @@ button { font: inherit; cursor: pointer; }
|
|
|
2512
2521
|
outline: none;
|
|
2513
2522
|
}
|
|
2514
2523
|
.composer__input::placeholder { color: inherit; opacity: 0.4; }
|
|
2515
|
-
.composer__bar { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
|
|
2516
|
-
.composer__hint { font: var(--type-caption); color: var(--card-muted); }
|
|
2524
|
+
.composer__bar { display: flex; align-items: center; justify-content: space-between; gap: var(--composer-bar-gap, var(--sp-3)); }
|
|
2525
|
+
.composer__hint { font: var(--composer-hint-font, var(--type-caption)); color: var(--composer-hint-ink, var(--card-muted)); }
|
|
2517
2526
|
.card--3 .composer__hint { color: inherit; opacity: 0.7; }
|
|
2518
2527
|
|
|
2519
2528
|
/* ---- slider: one value along a track, a thumb-size knob ----
|
|
@@ -2522,7 +2531,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
2522
2531
|
slider does, the input's aria-label is enough. The track is a hairline rail;
|
|
2523
2532
|
the knob is a full --tap, and the whole range is --tap tall, so the thumb has
|
|
2524
2533
|
a real target anywhere along it. The value is the input's own. */
|
|
2525
|
-
.slider { display: grid; gap: var(--sp-1); flex: 1; min-width: 0; position: relative; } /* relative: the glyph rides the knob */
|
|
2534
|
+
.slider { display: grid; gap: var(--slider-gap, var(--sp-1)); flex: 1; min-width: 0; position: relative; } /* relative: the glyph rides the knob */
|
|
2526
2535
|
/* ---- the sample glyph: one letter IN the knob, on-accent, at the type size
|
|
2527
2536
|
the slider sets — so a text-size slider shows the size before anything is
|
|
2528
2537
|
read (Lh, 2026-09-12). cardds.js publishes the knob's place on the .slider
|
|
@@ -2533,8 +2542,8 @@ button { font: inherit; cursor: pointer; }
|
|
|
2533
2542
|
position: absolute;
|
|
2534
2543
|
bottom: 0;
|
|
2535
2544
|
left: calc(var(--tap) / 2 + (100% - var(--tap)) * var(--slider-at, 0));
|
|
2536
|
-
width: var(--tap);
|
|
2537
|
-
height: var(--tap);
|
|
2545
|
+
width: var(--slider-glyph-size, var(--tap));
|
|
2546
|
+
height: var(--slider-glyph-size, var(--tap));
|
|
2538
2547
|
/* the eye centres the INK, not the line box: a letter that stands on the
|
|
2539
2548
|
baseline (ก) has no descender, while the face's box keeps 0.30em under it
|
|
2540
2549
|
(fonts.css) — so the ink lands low when the box is centred; lifted 0.15em
|
|
@@ -2542,15 +2551,15 @@ button { font: inherit; cursor: pointer; }
|
|
|
2542
2551
|
translate: -50% -0.15em;
|
|
2543
2552
|
display: grid;
|
|
2544
2553
|
place-items: center;
|
|
2545
|
-
font: var(--type-h2);
|
|
2546
|
-
color: var(--on-accent);
|
|
2554
|
+
font: var(--slider-glyph-font, var(--type-h2));
|
|
2555
|
+
color: var(--slider-glyph-ink, var(--on-accent));
|
|
2547
2556
|
pointer-events: none;
|
|
2548
2557
|
}
|
|
2549
|
-
.slider__label { font: var(--type-label); }
|
|
2558
|
+
.slider__label { font: var(--slider-label-font, var(--type-label)); }
|
|
2550
2559
|
.slider__range {
|
|
2551
2560
|
appearance: none;
|
|
2552
2561
|
width: 100%;
|
|
2553
|
-
height: var(--tap);
|
|
2562
|
+
height: var(--slider-range-h, var(--tap));
|
|
2554
2563
|
margin: 0;
|
|
2555
2564
|
background: transparent;
|
|
2556
2565
|
cursor: pointer;
|
|
@@ -2591,8 +2600,8 @@ button { font: inherit; cursor: pointer; }
|
|
|
2591
2600
|
.row {
|
|
2592
2601
|
display: flex;
|
|
2593
2602
|
align-items: center;
|
|
2594
|
-
gap: var(--sp-3);
|
|
2595
|
-
min-height: var(--tap); /* the tap target's room — the row's only vertical size */
|
|
2603
|
+
gap: var(--row-gap, var(--sp-3));
|
|
2604
|
+
min-height: var(--row-min-h, var(--tap)); /* the tap target's room — the row's only vertical size */
|
|
2596
2605
|
min-width: 0;
|
|
2597
2606
|
color: inherit;
|
|
2598
2607
|
text-decoration: none; /* .row works as <a> too — it is a tap target */
|
|
@@ -2601,20 +2610,20 @@ button { font: inherit; cursor: pointer; }
|
|
|
2601
2610
|
Space BETWEEN rows is .rows' gap; a lone row as card content takes the card's
|
|
2602
2611
|
gap. (.row--flush, which zeroed the old padding, is gone — every row is flush.) */
|
|
2603
2612
|
.row__lead {
|
|
2604
|
-
width: var(--tap);
|
|
2605
|
-
height: var(--tap);
|
|
2613
|
+
width: var(--row-lead-size, var(--tap));
|
|
2614
|
+
height: var(--row-lead-size, var(--tap));
|
|
2606
2615
|
flex: none;
|
|
2607
|
-
border-radius: var(--r-control);
|
|
2608
|
-
border: var(--border-w) solid var(--outline);
|
|
2616
|
+
border-radius: var(--row-lead-radius, var(--r-control));
|
|
2617
|
+
border: var(--border-w) solid var(--row-lead-border, var(--outline));
|
|
2609
2618
|
display: grid;
|
|
2610
2619
|
place-items: center;
|
|
2611
2620
|
}
|
|
2612
|
-
.row__body { flex: 1; min-width: 0; display: grid; gap: var(--sp-0); }
|
|
2613
|
-
.row__title { font: var(--type-title); overflow-wrap: anywhere; } /* wraps freely — no clip, so no padding trick for Thai marks (Lh 2026-09-16, same call as the card heading) */
|
|
2614
|
-
.row__meta { font: var(--type-caption); color: var(--card-muted); display: flex; align-items: center; gap: var(--sp-1); }
|
|
2621
|
+
.row__body { flex: 1; min-width: 0; display: grid; gap: var(--row-body-gap, var(--sp-0)); }
|
|
2622
|
+
.row__title { font: var(--row-title-font, var(--type-title)); overflow-wrap: anywhere; } /* wraps freely — no clip, so no padding trick for Thai marks (Lh 2026-09-16, same call as the card heading) */
|
|
2623
|
+
.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)); }
|
|
2615
2624
|
.card--3 .row__meta { color: inherit; opacity: 0.7; }
|
|
2616
|
-
.row__end { margin-left: auto; text-align: right; display: grid; gap: var(--sp-0); justify-items: end; flex: none; }
|
|
2617
|
-
.row--lg { min-height: var(--fab); } /* menu rows: a taller target, round arrow at the end; .rows gives them more air */
|
|
2625
|
+
.row__end { margin-left: auto; text-align: right; display: grid; gap: var(--row-end-gap, var(--sp-0)); justify-items: end; flex: none; }
|
|
2626
|
+
.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 */
|
|
2618
2627
|
.row--lg .row__title { font: 700 var(--fs-lg)/1.2 var(--font-display); }
|
|
2619
2628
|
/* a finished item in a checklist (a to-do list, an onboarding "complete your introduction" list):
|
|
2620
2629
|
the words go muted, a filled tick sits at the end, and the row is no longer a tap target —
|
|
@@ -2624,13 +2633,13 @@ button { font: inherit; cursor: pointer; }
|
|
|
2624
2633
|
.row--done .row__title { color: var(--card-muted); }
|
|
2625
2634
|
.card--3 .row--done .row__title { color: inherit; opacity: 0.7; }
|
|
2626
2635
|
.row__done {
|
|
2627
|
-
width: var(--tap-sm);
|
|
2628
|
-
height: var(--tap-sm);
|
|
2636
|
+
width: var(--row-done-size, var(--tap-sm));
|
|
2637
|
+
height: var(--row-done-size, var(--tap-sm));
|
|
2629
2638
|
flex: none;
|
|
2630
2639
|
margin-left: auto;
|
|
2631
2640
|
border-radius: 50%;
|
|
2632
|
-
background: var(--accent);
|
|
2633
|
-
color: var(--on-accent);
|
|
2641
|
+
background: var(--row-done-bg, var(--accent));
|
|
2642
|
+
color: var(--row-done-ink, var(--on-accent));
|
|
2634
2643
|
display: grid;
|
|
2635
2644
|
place-items: center;
|
|
2636
2645
|
}
|
|
@@ -2651,20 +2660,20 @@ button { font: inherit; cursor: pointer; }
|
|
|
2651
2660
|
/* ---- kv: label left, value right ----
|
|
2652
2661
|
<dl class="kv"><div class="kv__row"><dt class="kv__key">Pay with</dt><dd class="kv__val">GHO</dd></div>…</dl> */
|
|
2653
2662
|
.kv { margin: 0; display: grid; }
|
|
2654
|
-
.kv__row { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); min-height: var(--tap); }
|
|
2663
|
+
.kv__row { display: flex; align-items: center; justify-content: space-between; gap: var(--kv-row-gap, var(--sp-3)); min-height: var(--kv-row-min-h, var(--tap)); }
|
|
2655
2664
|
.kv--lined > .kv__row + .kv__row { border-top: var(--border-w) solid var(--hairline); }
|
|
2656
|
-
.kv__key { font: var(--type-body); color: var(--card-muted); }
|
|
2665
|
+
.kv__key { font: var(--kv-key-font, var(--type-body)); color: var(--kv-key-ink, var(--card-muted)); }
|
|
2657
2666
|
.card--3 .kv__key { color: inherit; opacity: 0.7; }
|
|
2658
|
-
.kv__val { margin: 0; font: var(--type-title); display: inline-flex; align-items: center; gap: var(--sp-2); text-align: right; min-width: 0; }
|
|
2667
|
+
.kv__val { margin: 0; font: var(--kv-val-font, var(--type-title)); display: inline-flex; align-items: center; gap: var(--kv-val-gap, var(--sp-2)); text-align: right; min-width: 0; }
|
|
2659
2668
|
|
|
2660
2669
|
/* ---- kv grid: value over label, cells split by a rule (Sex | Weight) ----
|
|
2661
2670
|
<div class="kv-grid"><div class="kv-cell"><svg class="icon"/><span class="kv-cell__val">15.6 kg</span><span class="kv-cell__key">Weight</span></div>…</div> */
|
|
2662
|
-
.kv-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(var(--tile-min), 100%), 1fr)); gap: var(--sp-4); }
|
|
2671
|
+
.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)); }
|
|
2663
2672
|
.kv-grid > .kv-cell + .kv-cell { border-left: var(--border-w) solid var(--hairline); padding-left: var(--sp-4); }
|
|
2664
|
-
.kv-cell { display: grid; gap: var(--sp-0); align-content: start; min-width: 0; }
|
|
2673
|
+
.kv-cell { display: grid; gap: var(--kv-cell-gap, var(--sp-0)); align-content: start; min-width: 0; }
|
|
2665
2674
|
.kv-cell > .icon { margin-bottom: var(--sp-1); }
|
|
2666
|
-
.kv-cell__val { font: var(--type-h2); letter-spacing: var(--track-h2); font-variant-numeric: tabular-nums; }
|
|
2667
|
-
.kv-cell__key { font: var(--type-caption); color: var(--card-muted); }
|
|
2675
|
+
.kv-cell__val { font: var(--kv-cell-val-font, var(--type-h2)); letter-spacing: var(--track-h2); font-variant-numeric: tabular-nums; }
|
|
2676
|
+
.kv-cell__key { font: var(--kv-cell-key-font, var(--type-caption)); color: var(--kv-cell-key-ink, var(--card-muted)); }
|
|
2668
2677
|
.card--3 .kv-cell__key { color: inherit; opacity: 0.7; }
|
|
2669
2678
|
|
|
2670
2679
|
/* ---- bubble: a chat message — theirs on the left, mine on the right (Lh 2026-09-18, replaces the chip's tail) ----
|
|
@@ -2676,7 +2685,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
2676
2685
|
<div class="bubble"><p class="bubble__body">…</p><span class="bubble__actions">…icon-btns…</span><span class="bubble__meta">Dec 4 · 8:15</span></div>
|
|
2677
2686
|
<div class="bubble bubble--right">…</div>
|
|
2678
2687
|
</div> */
|
|
2679
|
-
.thread { display: grid; gap: var(--sp-4); }
|
|
2688
|
+
.thread { display: grid; gap: var(--thread-gap, var(--sp-4)); }
|
|
2680
2689
|
/* two columns: the message (max-content, but it gives way — minmax(0) — so a long one shrinks
|
|
2681
2690
|
and wraps while the actions stay beside it) and the actions; the meta on a second row under the message */
|
|
2682
2691
|
.bubble {
|
|
@@ -2696,12 +2705,12 @@ button { font: inherit; cursor: pointer; }
|
|
|
2696
2705
|
.bubble__body {
|
|
2697
2706
|
margin: 0;
|
|
2698
2707
|
min-width: 0;
|
|
2699
|
-
padding: var(--sp-3) var(--sp-4);
|
|
2700
|
-
border-radius: var(--r-card);
|
|
2708
|
+
padding: var(--bubble-body-pad-y, var(--sp-3)) var(--bubble-body-pad-x, var(--sp-4));
|
|
2709
|
+
border-radius: var(--bubble-body-radius, var(--r-card));
|
|
2701
2710
|
border-bottom-left-radius: var(--r-control);
|
|
2702
|
-
background: var(--card-2-bg);
|
|
2703
|
-
color: var(--card-2-ink);
|
|
2704
|
-
font: var(--type-body);
|
|
2711
|
+
background: var(--bubble-body-bg, var(--card-2-bg));
|
|
2712
|
+
color: var(--bubble-body-ink, var(--card-2-ink));
|
|
2713
|
+
font: var(--bubble-body-font, var(--type-body));
|
|
2705
2714
|
overflow-wrap: anywhere;
|
|
2706
2715
|
}
|
|
2707
2716
|
.bubble--right > .bubble__body {
|
|
@@ -2711,8 +2720,8 @@ button { font: inherit; cursor: pointer; }
|
|
|
2711
2720
|
color: var(--on-accent);
|
|
2712
2721
|
text-align: right;
|
|
2713
2722
|
}
|
|
2714
|
-
.bubble__actions { display: flex; gap: var(--sp-1); flex: none; opacity: 0.7; }
|
|
2715
|
-
.bubble__meta { display: flex; align-items: center; gap: var(--sp-1); font: var(--type-caption); color: var(--on-surface-muted); }
|
|
2723
|
+
.bubble__actions { display: flex; gap: var(--bubble-actions-gap, var(--sp-1)); flex: none; opacity: 0.7; }
|
|
2724
|
+
.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(--on-surface-muted)); }
|
|
2716
2725
|
.bubble--right > .bubble__meta { justify-self: end; }
|
|
2717
2726
|
.bubble__meta > .icon { color: var(--accent); }
|
|
2718
2727
|
.card--3 .bubble__meta { color: inherit; opacity: 0.7; }
|
|
@@ -2724,7 +2733,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
2724
2733
|
margin: 0;
|
|
2725
2734
|
padding: 0 0 0 var(--sp-6);
|
|
2726
2735
|
display: grid;
|
|
2727
|
-
gap: var(--sp-5);
|
|
2736
|
+
gap: var(--timeline-gap, var(--sp-5));
|
|
2728
2737
|
position: relative;
|
|
2729
2738
|
}
|
|
2730
2739
|
.timeline::before {
|
|
@@ -2735,7 +2744,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
2735
2744
|
bottom: var(--sp-3);
|
|
2736
2745
|
border-left: var(--border-w) solid var(--hairline);
|
|
2737
2746
|
}
|
|
2738
|
-
.timeline__item { display: grid; gap: var(--sp-2); position: relative; min-width: 0; }
|
|
2747
|
+
.timeline__item { display: grid; gap: var(--timeline-item-gap, var(--sp-2)); position: relative; min-width: 0; }
|
|
2739
2748
|
.timeline__item::before {
|
|
2740
2749
|
content: "";
|
|
2741
2750
|
position: absolute;
|
|
@@ -2748,37 +2757,37 @@ button { font: inherit; cursor: pointer; }
|
|
|
2748
2757
|
}
|
|
2749
2758
|
.timeline__mark {
|
|
2750
2759
|
justify-self: start;
|
|
2751
|
-
font: var(--type-overline);
|
|
2760
|
+
font: var(--timeline-mark-font, var(--type-overline));
|
|
2752
2761
|
letter-spacing: var(--track-overline);
|
|
2753
2762
|
text-transform: uppercase;
|
|
2754
|
-
padding: var(--sp-1) var(--sp-2);
|
|
2755
|
-
border-radius: var(--r-chip);
|
|
2756
|
-
background: var(--ink-tint);
|
|
2763
|
+
padding: var(--timeline-mark-pad-y, var(--sp-1)) var(--timeline-mark-pad-x, var(--sp-2));
|
|
2764
|
+
border-radius: var(--timeline-mark-radius, var(--r-chip));
|
|
2765
|
+
background: var(--timeline-mark-bg, var(--ink-tint));
|
|
2757
2766
|
}
|
|
2758
2767
|
|
|
2759
2768
|
/* ---- legend: signal dots with captions ----
|
|
2760
2769
|
<div class="legend"><span class="legend__item"><span class="dot"></span> very high</span>…</div> */
|
|
2761
|
-
.legend { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); font: var(--type-caption); color: var(--card-muted); }
|
|
2770
|
+
.legend { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); font: var(--legend-font, var(--type-caption)); color: var(--legend-ink, var(--card-muted)); }
|
|
2762
2771
|
.card--3 .legend { color: inherit; opacity: 0.8; }
|
|
2763
|
-
.legend__item { display: inline-flex; align-items: center; gap: var(--sp-2); min-height: var(--icon); }
|
|
2772
|
+
.legend__item { display: inline-flex; align-items: center; gap: var(--legend-item-gap, var(--sp-2)); min-height: var(--legend-item-min-h, var(--icon)); }
|
|
2764
2773
|
|
|
2765
2774
|
/* ---- link: "See all ↗" in a card head, big enough to tap ----
|
|
2766
2775
|
<a class="link" href="#">See all <svg class="icon icon--xs"/></a> */
|
|
2767
2776
|
.link {
|
|
2768
2777
|
display: inline-flex;
|
|
2769
2778
|
align-items: center;
|
|
2770
|
-
gap: var(--sp-1);
|
|
2771
|
-
min-height: var(--tap-sm);
|
|
2779
|
+
gap: var(--link-gap, var(--sp-1));
|
|
2780
|
+
min-height: var(--link-min-h, var(--tap-sm));
|
|
2772
2781
|
color: inherit;
|
|
2773
2782
|
text-decoration: none;
|
|
2774
|
-
font: var(--type-label);
|
|
2775
|
-
font-size: var(--fs-body);
|
|
2783
|
+
font: var(--link-font, var(--type-label));
|
|
2784
|
+
font-size: var(--link-font-size, var(--fs-body));
|
|
2776
2785
|
border: 0;
|
|
2777
2786
|
background: transparent;
|
|
2778
2787
|
padding: 0;
|
|
2779
2788
|
cursor: pointer;
|
|
2780
2789
|
}
|
|
2781
|
-
.link--muted { color: var(--card-muted); }
|
|
2790
|
+
.link--muted { color: var(--link-muted-ink, var(--card-muted)); }
|
|
2782
2791
|
.card--3 .link--muted { color: inherit; opacity: 0.7; }
|
|
2783
2792
|
|
|
2784
2793
|
/* ---- css/media.css — cover card, quote, tile grid, fold, mosaic, wave ---- */
|
|
@@ -2827,16 +2836,16 @@ button { font: inherit; cursor: pointer; }
|
|
|
2827
2836
|
|
|
2828
2837
|
/* ---- quote: giant mark, big text, attribution ----
|
|
2829
2838
|
<blockquote class="quote"><p class="quote__text">It's overcast…</p><footer class="quote__by">Wednesday 15</footer></blockquote> */
|
|
2830
|
-
.quote { margin: 0; display: grid; gap: var(--sp-3); }
|
|
2839
|
+
.quote { margin: 0; display: grid; gap: var(--quote-gap, var(--sp-3)); }
|
|
2831
2840
|
.quote::before {
|
|
2832
2841
|
content: "\201C";
|
|
2833
2842
|
font: 900 calc(var(--fs-h1) * 3)/0.55 var(--font-display);
|
|
2834
2843
|
height: var(--sp-10);
|
|
2835
2844
|
opacity: 0.9;
|
|
2836
2845
|
}
|
|
2837
|
-
.quote__text { margin: 0; font: var(--type-h1); letter-spacing: var(--track-h1); text-wrap: balance; }
|
|
2846
|
+
.quote__text { margin: 0; font: var(--quote-text-font, var(--type-h1)); letter-spacing: var(--track-h1); text-wrap: balance; }
|
|
2838
2847
|
.quote--sm .quote__text { font: var(--type-h2); letter-spacing: var(--track-h2); }
|
|
2839
|
-
.quote__by { font: var(--type-overline); letter-spacing: var(--track-overline); text-transform: uppercase; color: var(--card-muted); }
|
|
2848
|
+
.quote__by { font: var(--quote-by-font, var(--type-overline)); letter-spacing: var(--track-overline); text-transform: uppercase; color: var(--quote-by-ink, var(--card-muted)); }
|
|
2840
2849
|
.card--3 .quote__by { color: inherit; opacity: 0.7; }
|
|
2841
2850
|
|
|
2842
2851
|
/* ---- tile grid: big square tiles — icon top, label bottom ----
|
|
@@ -2845,36 +2854,36 @@ button { font: inherit; cursor: pointer; }
|
|
|
2845
2854
|
.tile-grid {
|
|
2846
2855
|
display: grid;
|
|
2847
2856
|
grid-template-columns: repeat(auto-fill, minmax(min(var(--tile-min), 100%), 1fr));
|
|
2848
|
-
gap: var(--sp-3);
|
|
2857
|
+
gap: var(--tile-grid-gap, var(--sp-3));
|
|
2849
2858
|
}
|
|
2850
2859
|
.tile-grid--3 { --tile-min: 6rem; } /* three across on a phone (attachments, upload kinds) */
|
|
2851
2860
|
.tile {
|
|
2852
2861
|
display: grid;
|
|
2853
2862
|
align-content: space-between;
|
|
2854
2863
|
justify-items: start;
|
|
2855
|
-
gap: var(--sp-5);
|
|
2856
|
-
min-height: var(--tile-h);
|
|
2864
|
+
gap: var(--tile-gap, var(--sp-5));
|
|
2865
|
+
min-height: var(--tile-min-h, var(--tile-h));
|
|
2857
2866
|
min-width: 0;
|
|
2858
|
-
padding: var(--sp-4);
|
|
2859
|
-
border: var(--border-w) solid var(--outline);
|
|
2860
|
-
border-radius: var(--r-card);
|
|
2861
|
-
background: var(--action-bg);
|
|
2862
|
-
color: var(--action-ink);
|
|
2867
|
+
padding: var(--tile-pad, var(--sp-4));
|
|
2868
|
+
border: var(--border-w) solid var(--tile-border, var(--outline));
|
|
2869
|
+
border-radius: var(--tile-radius, var(--r-card));
|
|
2870
|
+
background: var(--tile-bg, var(--action-bg));
|
|
2871
|
+
color: var(--tile-ink, var(--action-ink));
|
|
2863
2872
|
font: inherit;
|
|
2864
2873
|
text-align: left;
|
|
2865
2874
|
position: relative;
|
|
2866
2875
|
cursor: pointer;
|
|
2867
2876
|
}
|
|
2868
|
-
.tile__label { font: var(--type-title); }
|
|
2869
|
-
.tile__value { font: var(--type-h2); letter-spacing: var(--track-h2); font-variant-numeric: tabular-nums; }
|
|
2870
|
-
.tile__sub { font: var(--type-caption); opacity: 0.7; }
|
|
2871
|
-
.tile__text { display: grid; gap: var(--sp-0); }
|
|
2872
|
-
.tile--on { background: var(--accent); color: var(--on-accent); border-color: transparent; }
|
|
2877
|
+
.tile__label { font: var(--tile-label-font, var(--type-title)); }
|
|
2878
|
+
.tile__value { font: var(--tile-value-font, var(--type-h2)); letter-spacing: var(--track-h2); font-variant-numeric: tabular-nums; }
|
|
2879
|
+
.tile__sub { font: var(--tile-sub-font, var(--type-caption)); opacity: 0.7; }
|
|
2880
|
+
.tile__text { display: grid; gap: var(--tile-text-gap, var(--sp-0)); }
|
|
2881
|
+
.tile--on { background: var(--tile-on-bg, var(--accent)); color: var(--tile-on-ink, var(--on-accent)); border-color: transparent; }
|
|
2873
2882
|
.tile--pick > input { appearance: none; position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
|
|
2874
2883
|
.tile--pick:has(:checked) { background: var(--accent); color: var(--on-accent); border-color: transparent; }
|
|
2875
2884
|
.tile--pick:has(:focus-visible) { outline: var(--focus); outline-offset: var(--sp-1); }
|
|
2876
2885
|
.tile--wide { grid-column: 1 / -1; }
|
|
2877
|
-
.tile--stat { min-height: var(--avatar-xl); gap: var(--sp-3); grid-template-columns: auto 1fr; align-items: center; }
|
|
2886
|
+
.tile--stat { min-height: var(--tile-stat-min-h, var(--avatar-xl)); gap: var(--tile-stat-gap, var(--sp-3)); grid-template-columns: auto 1fr; align-items: center; }
|
|
2878
2887
|
/* upload: dashed, centred plus + label */
|
|
2879
2888
|
.tile--upload {
|
|
2880
2889
|
border-style: dashed;
|
|
@@ -2882,12 +2891,12 @@ button { font: inherit; cursor: pointer; }
|
|
|
2882
2891
|
color: inherit;
|
|
2883
2892
|
align-content: center;
|
|
2884
2893
|
justify-items: center;
|
|
2885
|
-
gap: var(--sp-2);
|
|
2894
|
+
gap: var(--tile-upload-gap, var(--sp-2));
|
|
2886
2895
|
text-align: center;
|
|
2887
2896
|
}
|
|
2888
2897
|
/* tinted tiles: slot colors inside a card (schedule, notes) */
|
|
2889
|
-
.tile--2 { background: var(--card-2-bg); color: var(--card-2-ink); border-color: transparent; }
|
|
2890
|
-
.tile--3 { background: var(--card-3-bg); color: var(--card-3-ink); border-color: transparent; }
|
|
2898
|
+
.tile--2 { background: var(--tile-2-bg, var(--card-2-bg)); color: var(--tile-2-ink, var(--card-2-ink)); border-color: transparent; }
|
|
2899
|
+
.tile--3 { background: var(--tile-3-bg, var(--card-3-bg)); color: var(--tile-3-ink, var(--card-3-ink)); border-color: transparent; }
|
|
2891
2900
|
|
|
2892
2901
|
/* ---- fold: a sticky-note corner on any card (decorative) ----
|
|
2893
2902
|
No border. The card's outline follows its border box, so it ran straight
|
|
@@ -2911,7 +2920,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
2911
2920
|
<span class="wave"></span> — sits in a .row__body, fills the width */
|
|
2912
2921
|
.wave {
|
|
2913
2922
|
display: block;
|
|
2914
|
-
height: var(--icon);
|
|
2923
|
+
height: var(--wave-h, var(--icon));
|
|
2915
2924
|
width: 100%;
|
|
2916
2925
|
background: repeating-linear-gradient(90deg, currentColor 0 var(--sp-1), transparent var(--sp-1) var(--sp-2));
|
|
2917
2926
|
/* masks only read alpha: currentColor = "opaque" without naming a color */
|
|
@@ -2926,9 +2935,9 @@ button { font: inherit; cursor: pointer; }
|
|
|
2926
2935
|
display: grid;
|
|
2927
2936
|
grid-template-columns: 2fr 1fr;
|
|
2928
2937
|
grid-auto-rows: 1fr;
|
|
2929
|
-
gap: var(--sp-1);
|
|
2938
|
+
gap: var(--mosaic-gap, var(--sp-1));
|
|
2930
2939
|
aspect-ratio: 4 / 3;
|
|
2931
|
-
border-radius: var(--r-media);
|
|
2940
|
+
border-radius: var(--mosaic-radius, var(--r-media));
|
|
2932
2941
|
overflow: hidden;
|
|
2933
2942
|
}
|
|
2934
2943
|
.mosaic > :first-child { grid-row: span 2; }
|
|
@@ -2958,16 +2967,16 @@ button { font: inherit; cursor: pointer; }
|
|
|
2958
2967
|
position: relative;
|
|
2959
2968
|
aspect-ratio: 3 / 2;
|
|
2960
2969
|
perspective: 60rem;
|
|
2961
|
-
border-radius: var(--r-media);
|
|
2970
|
+
border-radius: var(--postcard-radius, var(--r-media));
|
|
2962
2971
|
}
|
|
2963
2972
|
.postcard__face {
|
|
2964
2973
|
position: absolute;
|
|
2965
2974
|
inset: 0;
|
|
2966
2975
|
display: grid;
|
|
2967
2976
|
align-content: end;
|
|
2968
|
-
padding: var(--sp-4);
|
|
2969
|
-
gap: var(--sp-2);
|
|
2970
|
-
border: var(--border-w) solid var(--card-border);
|
|
2977
|
+
padding: var(--postcard-face-pad, var(--sp-4));
|
|
2978
|
+
gap: var(--postcard-face-gap, var(--sp-2));
|
|
2979
|
+
border: var(--border-w) solid var(--postcard-face-border, var(--card-border));
|
|
2971
2980
|
border-radius: inherit;
|
|
2972
2981
|
overflow: hidden;
|
|
2973
2982
|
isolation: isolate;
|
|
@@ -2976,11 +2985,11 @@ button { font: inherit; cursor: pointer; }
|
|
|
2976
2985
|
backface-visibility: hidden;
|
|
2977
2986
|
-webkit-backface-visibility: hidden;
|
|
2978
2987
|
transition: transform var(--motion-flip) ease-in-out;
|
|
2979
|
-
box-shadow: var(--shadow-float);
|
|
2988
|
+
box-shadow: var(--postcard-face-shadow, var(--shadow-float));
|
|
2980
2989
|
}
|
|
2981
2990
|
.postcard__face:focus-visible { outline: var(--focus); outline-offset: var(--sp-1); }
|
|
2982
2991
|
/* the front: the photo (or the wireframe box) fills it, the name reads on a scrim */
|
|
2983
|
-
.postcard__front { background: var(--card-3-bg); color: var(--card-3-ink); }
|
|
2992
|
+
.postcard__front { background: var(--postcard-front-bg, var(--card-3-bg)); color: var(--postcard-front-ink, var(--card-3-ink)); }
|
|
2984
2993
|
.postcard__front > img,
|
|
2985
2994
|
.postcard__front > .ph {
|
|
2986
2995
|
position: absolute;
|
|
@@ -3002,13 +3011,13 @@ button { font: inherit; cursor: pointer; }
|
|
|
3002
3011
|
}
|
|
3003
3012
|
/* the back: paper — the words, big enough to read at arm's length */
|
|
3004
3013
|
.postcard__back {
|
|
3005
|
-
background: var(--card-2-bg);
|
|
3006
|
-
color: var(--card-2-ink);
|
|
3014
|
+
background: var(--postcard-back-bg, var(--card-2-bg));
|
|
3015
|
+
color: var(--postcard-back-ink, var(--card-2-ink));
|
|
3007
3016
|
align-content: space-between;
|
|
3008
3017
|
transform: rotateY(180deg);
|
|
3009
3018
|
}
|
|
3010
|
-
.postcard__caption { margin: 0; font: var(--type-title); text-wrap: pretty; }
|
|
3011
|
-
.postcard__label { font: var(--type-overline); letter-spacing: var(--track-overline); text-transform: uppercase; opacity: 0.85; }
|
|
3019
|
+
.postcard__caption { margin: 0; font: var(--postcard-caption-font, var(--type-title)); text-wrap: pretty; }
|
|
3020
|
+
.postcard__label { font: var(--postcard-label-font, var(--type-overline)); letter-spacing: var(--track-overline); text-transform: uppercase; opacity: 0.85; }
|
|
3012
3021
|
.postcard.is-flipped > .postcard__front { transform: rotateY(-180deg); }
|
|
3013
3022
|
.postcard.is-flipped > .postcard__back { transform: rotateY(0); }
|
|
3014
3023
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -3064,7 +3073,7 @@ button { font: inherit; cursor: pointer; }
|
|
|
3064
3073
|
display: grid;
|
|
3065
3074
|
grid-template-rows: minmax(0, 1fr) auto;
|
|
3066
3075
|
overflow: clip;
|
|
3067
|
-
box-shadow: var(--shadow-sheet);
|
|
3076
|
+
box-shadow: var(--modal-shadow, var(--shadow-sheet));
|
|
3068
3077
|
}
|
|
3069
3078
|
.modal__lift {
|
|
3070
3079
|
padding: var(--card-pad);
|
|
@@ -3078,15 +3087,15 @@ button { font: inherit; cursor: pointer; }
|
|
|
3078
3087
|
.modal__drawer {
|
|
3079
3088
|
height: var(--drawer-h);
|
|
3080
3089
|
box-sizing: border-box;
|
|
3081
|
-
padding: var(--sp-5);
|
|
3090
|
+
padding: var(--modal-drawer-pad, var(--sp-5));
|
|
3082
3091
|
overflow: clip;
|
|
3083
3092
|
display: grid;
|
|
3084
3093
|
align-content: center;
|
|
3085
3094
|
justify-items: center;
|
|
3086
|
-
gap: var(--sp-1);
|
|
3095
|
+
gap: var(--modal-drawer-gap, var(--sp-1));
|
|
3087
3096
|
text-align: center;
|
|
3088
|
-
background: var(--card-3-bg);
|
|
3089
|
-
color: var(--card-3-ink);
|
|
3097
|
+
background: var(--modal-drawer-bg, var(--card-3-bg));
|
|
3098
|
+
color: var(--modal-drawer-ink, var(--card-3-ink));
|
|
3090
3099
|
--accent: var(--card-3-ink); /* the one solid button inverts on the dark drawer */
|
|
3091
3100
|
--on-accent: var(--card-3-bg);
|
|
3092
3101
|
}
|
|
@@ -3102,14 +3111,14 @@ button { font: inherit; cursor: pointer; }
|
|
|
3102
3111
|
}
|
|
3103
3112
|
@keyframes modal-open {
|
|
3104
3113
|
0%, 50% { height: 0; padding-block: 0; } /* inside the card */
|
|
3105
|
-
100% { height: var(--drawer-h); padding-block: var(--sp-5); } /* 2. out below, the lift up, together */
|
|
3114
|
+
100% { height: var(--drawer-h); padding-block: var(--modal-drawer-pad, var(--sp-5)); } /* 2. out below, the lift up, together — the same knob the rule reads: a keyframe that pinned the value would make the knob dead */
|
|
3106
3115
|
}
|
|
3107
3116
|
}
|
|
3108
3117
|
|
|
3109
|
-
.btn-trio { display: flex; align-items: center; gap: var(--sp-3); margin-top: var(--sp-3); }
|
|
3118
|
+
.btn-trio { display: flex; align-items: center; gap: var(--btn-trio-gap, var(--sp-3)); margin-top: var(--sp-3); }
|
|
3110
3119
|
.btn-trio__dots {
|
|
3111
|
-
width: var(--sp-5);
|
|
3112
|
-
height: var(--sp-1);
|
|
3120
|
+
width: var(--btn-trio-dots-w, var(--sp-5));
|
|
3121
|
+
height: var(--btn-trio-dots-h, var(--sp-1));
|
|
3113
3122
|
background: radial-gradient(circle, currentColor var(--sp-0), transparent calc(var(--sp-0) + 0.5px)) 0 0 / calc(var(--sp-5) / 2) 100% repeat-x;
|
|
3114
3123
|
opacity: 0.4;
|
|
3115
3124
|
}
|
|
@@ -3130,31 +3139,31 @@ button { font: inherit; cursor: pointer; }
|
|
|
3130
3139
|
display: none; /* explicit closed state — never display on the base rule */
|
|
3131
3140
|
margin: 0;
|
|
3132
3141
|
inset: auto;
|
|
3133
|
-
border: var(--border-w) solid var(--action-border);
|
|
3134
|
-
border-radius: var(--r-card);
|
|
3142
|
+
border: var(--border-w) solid var(--menu-border, var(--action-border));
|
|
3143
|
+
border-radius: var(--menu-radius, var(--r-card));
|
|
3135
3144
|
--menu-pad: var(--sp-2); /* published: a row's radius is concentric with the panel's */
|
|
3136
3145
|
padding: var(--menu-pad);
|
|
3137
3146
|
min-width: 12rem;
|
|
3138
|
-
background: var(--action-bg);
|
|
3139
|
-
color: var(--action-ink);
|
|
3140
|
-
box-shadow: var(--shadow-float);
|
|
3147
|
+
background: var(--menu-bg, var(--action-bg));
|
|
3148
|
+
color: var(--menu-ink, var(--action-ink));
|
|
3149
|
+
box-shadow: var(--menu-shadow, var(--shadow-float));
|
|
3141
3150
|
}
|
|
3142
3151
|
.menu:popover-open { display: grid; }
|
|
3143
3152
|
.menu:not([popover]) { display: grid; position: relative; } /* inline usage (no attribute) */
|
|
3144
3153
|
.menu__item {
|
|
3145
3154
|
display: flex;
|
|
3146
3155
|
align-items: center;
|
|
3147
|
-
gap: var(--sp-3);
|
|
3148
|
-
min-height: var(--tap);
|
|
3156
|
+
gap: var(--menu-item-gap, var(--sp-3));
|
|
3157
|
+
min-height: var(--menu-item-min-h, var(--tap));
|
|
3149
3158
|
width: 100%;
|
|
3150
|
-
padding: 0 var(--sp-3);
|
|
3159
|
+
padding: var(--menu-item-pad-y, 0) var(--menu-item-pad-x, var(--sp-3));
|
|
3151
3160
|
border: 0;
|
|
3152
3161
|
/* concentric with the panel: the card radius minus the panel's padding, so the
|
|
3153
3162
|
highlight's curve follows the outer corner (Lh 2026-09-16) */
|
|
3154
3163
|
border-radius: calc(var(--r-card) - var(--menu-pad, var(--sp-2)));
|
|
3155
3164
|
background: transparent;
|
|
3156
3165
|
color: inherit;
|
|
3157
|
-
font: var(--type-title);
|
|
3166
|
+
font: var(--menu-item-font, var(--type-title));
|
|
3158
3167
|
text-align: left;
|
|
3159
3168
|
cursor: pointer;
|
|
3160
3169
|
}
|
|
@@ -3182,12 +3191,12 @@ button { font: inherit; cursor: pointer; }
|
|
|
3182
3191
|
/* ---- banner: a chip that opens into a tinted card, no JS ----
|
|
3183
3192
|
<details class="banner"><summary class="chip chip--on">Save $30 on orders over $70 <svg class="icon icon--xs"/></summary>
|
|
3184
3193
|
<div class="card card--3 banner__body">…</div></details> */
|
|
3185
|
-
.banner { display: grid; gap: var(--sp-2); justify-items: start; }
|
|
3194
|
+
.banner { display: grid; gap: var(--banner-gap, var(--sp-2)); justify-items: start; }
|
|
3186
3195
|
.banner > summary { list-style: none; cursor: pointer; }
|
|
3187
3196
|
.banner > summary::-webkit-details-marker { display: none; }
|
|
3188
3197
|
.banner > summary .icon { transition: rotate 0.2s ease; }
|
|
3189
3198
|
.banner[open] > summary .icon { rotate: 180deg; }
|
|
3190
|
-
.banner__body { width: 100%; padding: var(--sp-4) var(--sp-5); --card-gap: var(--sp-1); }
|
|
3199
|
+
.banner__body { width: 100%; padding: var(--banner-body-pad-y, var(--sp-4)) var(--banner-body-pad-x, var(--sp-5)); --card-gap: var(--sp-1); }
|
|
3191
3200
|
.banner::details-content { width: 100%; } /* Chromium wraps the content in this pseudo; justify-items: start shrink-wrapped it, so the body never reached the width */
|
|
3192
3201
|
@supports (interpolate-size: allow-keywords) {
|
|
3193
3202
|
@media (prefers-reduced-motion: no-preference) {
|
|
@@ -3205,9 +3214,9 @@ button { font: inherit; cursor: pointer; }
|
|
|
3205
3214
|
bottom: var(--sp-5);
|
|
3206
3215
|
max-width: var(--screen-w);
|
|
3207
3216
|
margin-inline: auto;
|
|
3208
|
-
padding-inline: var(--sp-4);
|
|
3217
|
+
padding-inline: var(--float-bar-pad-x, var(--sp-4));
|
|
3209
3218
|
display: flex;
|
|
3210
|
-
gap: var(--sp-2);
|
|
3219
|
+
gap: var(--float-bar-gap, var(--sp-2));
|
|
3211
3220
|
align-items: center;
|
|
3212
3221
|
z-index: 30;
|
|
3213
3222
|
}
|
|
@@ -3222,29 +3231,29 @@ button { font: inherit; cursor: pointer; }
|
|
|
3222
3231
|
display: flex;
|
|
3223
3232
|
justify-content: space-around;
|
|
3224
3233
|
align-items: center;
|
|
3225
|
-
min-height: var(--bar-h);
|
|
3226
|
-
padding: var(--sp-1);
|
|
3227
|
-
border-radius: var(--r-chip);
|
|
3228
|
-
border: var(--border-w) solid var(--action-border);
|
|
3229
|
-
background: color-mix(in srgb, var(--action-bg) 82%, transparent);
|
|
3230
|
-
color: var(--action-ink);
|
|
3234
|
+
min-height: var(--float-bar-pill-min-h, var(--bar-h));
|
|
3235
|
+
padding: var(--float-bar-pill-pad, var(--sp-1));
|
|
3236
|
+
border-radius: var(--float-bar-pill-radius, var(--r-chip));
|
|
3237
|
+
border: var(--border-w) solid var(--float-bar-pill-border, var(--action-border));
|
|
3238
|
+
background: var(--float-bar-pill-bg, color-mix(in srgb, var(--action-bg) 82%, transparent));
|
|
3239
|
+
color: var(--float-bar-pill-ink, var(--action-ink));
|
|
3231
3240
|
backdrop-filter: blur(var(--sp-3));
|
|
3232
3241
|
-webkit-backdrop-filter: blur(var(--sp-3));
|
|
3233
|
-
box-shadow: var(--shadow-float);
|
|
3242
|
+
box-shadow: var(--float-bar-pill-shadow, var(--shadow-float));
|
|
3234
3243
|
}
|
|
3235
3244
|
.float-bar__item {
|
|
3236
3245
|
flex: 1;
|
|
3237
3246
|
min-width: 0;
|
|
3238
3247
|
display: grid;
|
|
3239
3248
|
justify-items: center;
|
|
3240
|
-
gap: var(--sp-0);
|
|
3241
|
-
min-height: var(--tap-lg);
|
|
3242
|
-
padding: var(--sp-1);
|
|
3249
|
+
gap: var(--float-bar-item-gap, var(--sp-0));
|
|
3250
|
+
min-height: var(--float-bar-item-min-h, var(--tap-lg));
|
|
3251
|
+
padding: var(--float-bar-item-pad, var(--sp-1));
|
|
3243
3252
|
border: 0;
|
|
3244
|
-
border-radius: var(--r-chip);
|
|
3253
|
+
border-radius: var(--float-bar-item-radius, var(--r-chip));
|
|
3245
3254
|
background: transparent;
|
|
3246
3255
|
color: inherit;
|
|
3247
|
-
font: var(--type-caption);
|
|
3256
|
+
font: var(--float-bar-item-font, var(--type-caption));
|
|
3248
3257
|
text-decoration: none;
|
|
3249
3258
|
opacity: 0.6;
|
|
3250
3259
|
overflow: hidden;
|
|
@@ -3262,15 +3271,15 @@ button { font: inherit; cursor: pointer; }
|
|
|
3262
3271
|
.callout {
|
|
3263
3272
|
position: absolute;
|
|
3264
3273
|
display: grid;
|
|
3265
|
-
gap: var(--sp-0);
|
|
3274
|
+
gap: var(--callout-gap, var(--sp-0));
|
|
3266
3275
|
width: max-content;
|
|
3267
3276
|
max-width: 15rem;
|
|
3268
|
-
padding: var(--sp-3) var(--sp-4);
|
|
3269
|
-
border: var(--border-w) solid var(--action-border);
|
|
3270
|
-
border-radius: var(--r-card);
|
|
3271
|
-
background: var(--action-bg);
|
|
3272
|
-
color: var(--action-ink);
|
|
3273
|
-
box-shadow: var(--shadow-float);
|
|
3277
|
+
padding: var(--callout-pad-y, var(--sp-3)) var(--callout-pad-x, var(--sp-4));
|
|
3278
|
+
border: var(--border-w) solid var(--callout-border, var(--action-border));
|
|
3279
|
+
border-radius: var(--callout-radius, var(--r-card));
|
|
3280
|
+
background: var(--callout-bg, var(--action-bg));
|
|
3281
|
+
color: var(--callout-ink, var(--action-ink));
|
|
3282
|
+
box-shadow: var(--callout-shadow, var(--shadow-float));
|
|
3274
3283
|
text-align: center;
|
|
3275
3284
|
}
|
|
3276
3285
|
.callout::after {
|
|
@@ -3287,16 +3296,16 @@ button { font: inherit; cursor: pointer; }
|
|
|
3287
3296
|
border-top: 0;
|
|
3288
3297
|
border-left: 0;
|
|
3289
3298
|
}
|
|
3290
|
-
.callout__title { font: var(--type-title); }
|
|
3291
|
-
.callout__sub { font: var(--type-caption); opacity: 0.7; }
|
|
3299
|
+
.callout__title { font: var(--callout-title-font, var(--type-title)); }
|
|
3300
|
+
.callout__sub { font: var(--callout-sub-font, var(--type-caption)); opacity: 0.7; }
|
|
3292
3301
|
/* ---- deck: swipe cards; the last child is on top ----
|
|
3293
3302
|
<div class="deck"><article class="card">…</article><article class="card">…</article><article class="card card--fold">front</article></div>
|
|
3294
3303
|
<div class="deck__actions"><button class="icon-btn">×</button><button class="icon-btn icon-btn--invert">✓</button></div> */
|
|
3295
|
-
.deck { display: grid; place-items: center; padding: var(--sp-4) var(--sp-4) var(--sp-6); }
|
|
3304
|
+
.deck { display: grid; place-items: center; padding: var(--deck-pad-top, var(--sp-4)) var(--deck-pad-x, var(--sp-4)) var(--deck-pad-bottom, var(--sp-6)); }
|
|
3296
3305
|
.deck > .card { grid-area: 1 / 1; width: min(100%, 20rem); min-height: 12.5rem; transition: rotate 0.3s ease, translate 0.3s ease; }
|
|
3297
3306
|
.deck > .card:nth-last-child(2) { rotate: -4deg; translate: calc(-1 * var(--sp-2)) var(--sp-2); opacity: 0.85; }
|
|
3298
3307
|
.deck > .card:nth-last-child(3) { rotate: 5deg; translate: var(--sp-3) var(--sp-4); opacity: 0.6; }
|
|
3299
3308
|
.deck > .card:nth-last-child(n + 4) { display: none; }
|
|
3300
|
-
.deck__actions { display: flex; justify-content: center; gap: var(--sp-8); }
|
|
3309
|
+
.deck__actions { display: flex; justify-content: center; gap: var(--deck-actions-gap, var(--sp-8)); }
|
|
3301
3310
|
.deck__actions > .icon-btn { width: var(--bar-h); height: var(--bar-h); }
|
|
3302
3311
|
|