@cahyo-dimas/freeday 3.5.0 → 3.7.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/CHANGELOG.md +130 -0
- package/COMPONENTS.md +251 -8
- package/README.id.md +19 -6
- package/README.md +17 -5
- package/USAGE.md +42 -0
- package/adapters/blazor/FdyDateRange.razor.cs +10 -0
- package/adapters/blazor/FdyTable.razor +6 -2
- package/adapters/blazor/FdyTable.razor.cs +21 -0
- package/adapters/blazor/TableTypes.cs +4 -0
- package/adapters/react/components/FdyDateRange.tsx +8 -2
- package/adapters/react/components/FdyTable.tsx +24 -3
- package/adapters/react/index.d.ts +1 -1
- package/adapters/vue/components/FdyDateRange.vue +11 -5
- package/adapters/vue/components/FdyTable.vue +18 -2
- package/dist/freeday-confirm.js +101 -0
- package/dist/freeday-copy.js +58 -0
- package/dist/freeday-datepicker.js +17 -2
- package/dist/freeday-form.js +30 -1
- package/dist/freeday-search.js +77 -0
- package/dist/freeday.bundle.css +544 -122
- package/dist/freeday.css +241 -118
- package/dist/freeday.d.ts +17 -2
- package/dist/freeday.js +286 -3
- package/dist/freeday.tokens.css +303 -4
- package/docs/agent-onboarding.md +8 -0
- package/docs/getting-started.md +1 -1
- package/package.json +2 -2
- package/src/base.css +1 -1
- package/src/components/accordion.css +1 -1
- package/src/components/alert.css +5 -5
- package/src/components/app-shell.css +2 -2
- package/src/components/appbar.css +3 -3
- package/src/components/avatar.css +17 -9
- package/src/components/badge.css +18 -14
- package/src/components/breadcrumb.css +1 -1
- package/src/components/button.css +21 -13
- package/src/components/card.css +7 -0
- package/src/components/carousel.css +3 -3
- package/src/components/cascade.css +4 -4
- package/src/components/chip.css +33 -15
- package/src/components/combo.css +5 -5
- package/src/components/composition.css +36 -0
- package/src/components/datepicker.css +8 -8
- package/src/components/description-list.css +11 -1
- package/src/components/file-upload.css +9 -4
- package/src/components/input-group.css +2 -2
- package/src/components/input.css +2 -2
- package/src/components/menu.css +3 -3
- package/src/components/pagination.css +1 -1
- package/src/components/selection.css +8 -2
- package/src/components/skeleton.css +1 -1
- package/src/components/states.css +7 -0
- package/src/components/stepper.css +1 -1
- package/src/components/table.css +25 -11
- package/src/components/tabs.css +1 -1
- package/src/components/timepicker.css +3 -3
- package/src/components/toast.css +1 -1
- package/src/components/tree.css +1 -1
- package/tokens/tokens.json +57 -4
package/dist/freeday.css
CHANGED
|
@@ -12,7 +12,7 @@ body {
|
|
|
12
12
|
-webkit-font-smoothing: antialiased;
|
|
13
13
|
}
|
|
14
14
|
h1, h2, h3, h4 { font-family: var(--font-display); font-weight: var(--weight-bold); letter-spacing: var(--tracking-tighter); line-height: var(--leading-snug); margin: 0; }
|
|
15
|
-
a { color: var(--color-primary); }
|
|
15
|
+
a { color: var(--color-primary-strong); }
|
|
16
16
|
:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: var(--focus-ring-width); border-radius: var(--radius-xs); }
|
|
17
17
|
:where(button, input, select, textarea) { font: inherit; }
|
|
18
18
|
/* Hidden from sight, kept for assistive tech. `clip` hides PAINTING, not LAYOUT: the box still
|
|
@@ -52,7 +52,7 @@ a { color: var(--color-primary); }
|
|
|
52
52
|
.fdy-accordion__item > summary::after{content:"";margin-left:auto;margin-top:-.15rem;flex:none;width:.5rem;height:.5rem;border-right:2px solid var(--color-text-subtle);border-bottom:2px solid var(--color-text-subtle);transform:rotate(45deg);transition:transform var(--dur-fast) var(--ease-standard);}
|
|
53
53
|
.fdy-accordion__item[open] > summary::after{transform:rotate(225deg);margin-top:.1rem;}
|
|
54
54
|
.fdy-accordion__item > summary:hover{background:var(--color-surface-2);}
|
|
55
|
-
.fdy-accordion__item > summary:focus-visible{outline:none;box-shadow:inset 0 0 0 2px
|
|
55
|
+
.fdy-accordion__item > summary:focus-visible{outline:none;box-shadow:inset 0 0 0 2px rgba(var(--color-primary-rgb),.45);}
|
|
56
56
|
.fdy-accordion__panel{padding:0 var(--space-4) var(--space-4);color:var(--color-text-muted);font-size:var(--text-sm);line-height:var(--leading-normal);}
|
|
57
57
|
/* Content reveal on open (fade + rise). Native <details> can't animate its own height cross-
|
|
58
58
|
* browser without JS, so we animate the revealed panel instead, cheap, safe, reduced-motion gated. */
|
|
@@ -67,14 +67,14 @@ a { color: var(--color-primary); }
|
|
|
67
67
|
.fdy-alert__text{color:var(--color-text);line-height:var(--leading-normal);}
|
|
68
68
|
.fdy-alert__close{flex:none;align-self:flex-start;border:0;background:transparent;color:var(--color-text-muted);cursor:pointer;font-size:var(--text-lg);line-height:1;padding:0 var(--space-1);border-radius:var(--radius-sm);}
|
|
69
69
|
.fdy-alert__close:hover{color:var(--color-text);}
|
|
70
|
-
.fdy-alert__close:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
71
|
-
.fdy-alert--info{background:var(--color-info-soft);border-color:
|
|
70
|
+
.fdy-alert__close:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
71
|
+
.fdy-alert--info{background:var(--color-info-soft);border-color:rgba(var(--color-info-rgb),.26);}
|
|
72
72
|
.fdy-alert--info .fdy-alert__title,.fdy-alert--info .fdy-alert__icon{color:var(--color-info-strong);}
|
|
73
|
-
.fdy-alert--success{background:var(--color-success-soft);border-color:
|
|
73
|
+
.fdy-alert--success{background:var(--color-success-soft);border-color:rgba(var(--color-success-rgb),.26);}
|
|
74
74
|
.fdy-alert--success .fdy-alert__title,.fdy-alert--success .fdy-alert__icon{color:var(--color-success-strong);}
|
|
75
|
-
.fdy-alert--warning{background:var(--color-warning-soft);border-color:
|
|
75
|
+
.fdy-alert--warning{background:var(--color-warning-soft);border-color:rgba(var(--color-warning-rgb),.26);}
|
|
76
76
|
.fdy-alert--warning .fdy-alert__title,.fdy-alert--warning .fdy-alert__icon{color:var(--color-warning-strong);}
|
|
77
|
-
.fdy-alert--danger{background:var(--color-danger-soft);border-color:
|
|
77
|
+
.fdy-alert--danger{background:var(--color-danger-soft);border-color:rgba(var(--color-danger-rgb),.26);}
|
|
78
78
|
.fdy-alert--danger .fdy-alert__title,.fdy-alert--danger .fdy-alert__icon{color:var(--color-danger-strong);}
|
|
79
79
|
|
|
80
80
|
/* Freeday. App Shell.
|
|
@@ -123,7 +123,7 @@ a { color: var(--color-primary); }
|
|
|
123
123
|
.fdy-nav__item:hover{background:var(--color-surface-2);color:var(--color-text);}
|
|
124
124
|
/* Active indicator stays in the primary ramp so it never clashes with a re-themed accent. */
|
|
125
125
|
.fdy-nav__item[aria-current="page"]{background:var(--color-primary-soft);color:var(--color-primary-strong);font-weight:var(--weight-semibold);}
|
|
126
|
-
.fdy-nav__item:focus-visible{outline:none;box-shadow:0 0 0 2px
|
|
126
|
+
.fdy-nav__item:focus-visible{outline:none;box-shadow:0 0 0 2px rgba(var(--color-primary-rgb),.45);}
|
|
127
127
|
/* Sidebar-menu extras: per-node icon (leading), count badge (trailing), and a
|
|
128
128
|
* text label that truncates. Any of these are optional, a bare text item works. */
|
|
129
129
|
.fdy-nav__icon{flex:none;display:inline-flex;width:1.15rem;height:1.15rem;}
|
|
@@ -141,7 +141,7 @@ a { color: var(--color-primary); }
|
|
|
141
141
|
.fdy-nav__grouplabel{list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);padding:var(--space-3) var(--space-3) var(--space-1);font-size:var(--text-xs);text-transform:uppercase;letter-spacing:var(--tracking-wide);font-weight:var(--weight-semibold);color:var(--color-text-muted);}
|
|
142
142
|
.fdy-nav__grouplabel::-webkit-details-marker{display:none;}
|
|
143
143
|
.fdy-nav__grouplabel:hover{color:var(--color-text-muted);}
|
|
144
|
-
.fdy-nav__grouplabel:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:0 0 0 2px
|
|
144
|
+
.fdy-nav__grouplabel:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:0 0 0 2px rgba(var(--color-primary-rgb),.45);}
|
|
145
145
|
.fdy-nav__grouplabel::after{content:"";flex:none;width:.45rem;height:.45rem;margin-right:var(--space-1);border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(-45deg);transition:transform var(--dur-fast) var(--ease-standard);opacity:.7;}
|
|
146
146
|
.fdy-nav__group[open] > .fdy-nav__grouplabel::after{transform:rotate(45deg);}
|
|
147
147
|
/* --flat: calmer, non-collapsible grouped nav, hide the caret, drop the
|
|
@@ -242,13 +242,13 @@ a { color: var(--color-primary); }
|
|
|
242
242
|
is the same component whether the nav is a sidebar column or a top row. */
|
|
243
243
|
/* Controls on a coloured app bar go on-colour (icons stay legible, hover is a light wash) */
|
|
244
244
|
.fdy-appbar--primary .fdy-btn--ghost{background:transparent;border-color:transparent;color:var(--color-on-primary);box-shadow:none;}
|
|
245
|
-
.fdy-appbar--primary .fdy-btn--ghost:hover{background:
|
|
245
|
+
.fdy-appbar--primary .fdy-btn--ghost:hover{background:rgba(var(--color-on-primary-rgb),.16);color:var(--color-on-primary);transform:none;}
|
|
246
246
|
/* Nav links on a coloured bar: full on-colour ink in every state (a dimmed variant would trade away
|
|
247
247
|
the contrast the bar's own token pair guarantees). The current page is carried by the background
|
|
248
248
|
wash plus the semibold weight the base rule already applies, and by `aria-current` itself. */
|
|
249
249
|
.fdy-appbar--primary .fdy-nav__item{color:var(--color-on-primary);}
|
|
250
|
-
.fdy-appbar--primary .fdy-nav__item:hover{background:
|
|
251
|
-
.fdy-appbar--primary .fdy-nav__item[aria-current="page"]{background:
|
|
250
|
+
.fdy-appbar--primary .fdy-nav__item:hover{background:rgba(var(--color-on-primary-rgb),.16);color:var(--color-on-primary);}
|
|
251
|
+
.fdy-appbar--primary .fdy-nav__item[aria-current="page"]{background:rgba(var(--color-on-primary-rgb),.24);color:var(--color-on-primary);}
|
|
252
252
|
|
|
253
253
|
/* Freeday. Autocomplete (text input + filtered suggestion listbox, APG editable combobox).
|
|
254
254
|
* Enhanced by freeday-autocomplete.js. */
|
|
@@ -273,6 +273,8 @@ a { color: var(--color-primary); }
|
|
|
273
273
|
.fdy-avatar--xs{width:1.5rem;height:1.5rem;font-size:var(--text-xs);}
|
|
274
274
|
.fdy-avatar--sm{width:2rem;height:2rem;font-size:var(--text-xs);}
|
|
275
275
|
.fdy-avatar--lg{width:3.5rem;height:3.5rem;font-size:var(--text-lg);}
|
|
276
|
+
/* Square: a mark that is not a person (a company logo, a card's icon chip, #070). */
|
|
277
|
+
.fdy-avatar--square{border-radius:var(--radius-md);}
|
|
276
278
|
.fdy-avatar-group{display:inline-flex;}
|
|
277
279
|
.fdy-avatar-group .fdy-avatar{border:2px solid var(--color-surface);margin-left:calc(var(--space-2)*-1);}
|
|
278
280
|
.fdy-avatar-group .fdy-avatar:first-child{margin-left:0;}
|
|
@@ -280,22 +282,28 @@ a { color: var(--color-primary); }
|
|
|
280
282
|
* text-leaning foreground so initials keep WCAG AA (verified >=4.5:1 in light & dark by
|
|
281
283
|
* test/contrast.test.mjs). Use to disambiguate same-initial avatars (e.g. many "PT …" names):
|
|
282
284
|
* hash a stable 1..8 index off the FULL name in your app, then apply .fdy-avatar--tone-<n>. */
|
|
283
|
-
.
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
.
|
|
289
|
-
.
|
|
290
|
-
.fdy-avatar--tone-
|
|
291
|
-
.fdy-avatar--tone-
|
|
285
|
+
/* One flat token per half, computed in advance by tokens/build.mjs: --tone-N-bg is 18% of the
|
|
286
|
+
* tone over --color-surface, --tone-N-ink is 50% of it toward --color-text, both per theme.
|
|
287
|
+
* They USED to be mixed here, with the hue injected per element through a private custom
|
|
288
|
+
* property — which put var() inside color-mix(), the one shape that cannot be rescued: valid at
|
|
289
|
+
* parse time, invalid at computed-value time, and there `background` and `color` drop to their
|
|
290
|
+
* INITIAL values, not to any fallback. @supports answered it for exactly as long as somebody
|
|
291
|
+
* remembered to write the counterpart; a precomputed token removes the question. */
|
|
292
|
+
.fdy-avatar--tone-1{background:var(--tone-1-bg);color:var(--tone-1-ink);}
|
|
293
|
+
.fdy-avatar--tone-2{background:var(--tone-2-bg);color:var(--tone-2-ink);}
|
|
294
|
+
.fdy-avatar--tone-3{background:var(--tone-3-bg);color:var(--tone-3-ink);}
|
|
295
|
+
.fdy-avatar--tone-4{background:var(--tone-4-bg);color:var(--tone-4-ink);}
|
|
296
|
+
.fdy-avatar--tone-5{background:var(--tone-5-bg);color:var(--tone-5-ink);}
|
|
297
|
+
.fdy-avatar--tone-6{background:var(--tone-6-bg);color:var(--tone-6-ink);}
|
|
298
|
+
.fdy-avatar--tone-7{background:var(--tone-7-bg);color:var(--tone-7-ink);}
|
|
299
|
+
.fdy-avatar--tone-8{background:var(--tone-8-bg);color:var(--tone-8-ink);}
|
|
292
300
|
|
|
293
301
|
/* Freeday. Badge */
|
|
294
|
-
.fdy-badge{display:inline-flex;align-items:center;gap:var(--space-1);font-family:var(--font-body);font-size:var(--text-xs);font-weight:var(--weight-semibold);line-height:1;white-space:nowrap;padding:.35em .7em;border-radius:var(--radius-full);color:var(--color-primary-strong);background:var(--color-primary-soft);border:var(--bw) solid
|
|
295
|
-
.fdy-badge--success{color:var(--color-success-strong);background:var(--color-success-soft);border-color:
|
|
296
|
-
.fdy-badge--warning{color:var(--color-warning-strong);background:var(--color-warning-soft);border-color:
|
|
297
|
-
.fdy-badge--danger{color:var(--color-danger-strong);background:var(--color-danger-soft);border-color:
|
|
298
|
-
.fdy-badge--info{color:var(--color-info-strong);background:var(--color-info-soft);border-color:
|
|
302
|
+
.fdy-badge{display:inline-flex;align-items:center;gap:var(--space-1);font-family:var(--font-body);font-size:var(--text-xs);font-weight:var(--weight-semibold);line-height:1;white-space:nowrap;padding:.35em .7em;border-radius:var(--radius-full);color:var(--color-primary-strong);background:var(--color-primary-soft);border:var(--bw) solid rgba(var(--color-primary-rgb),.22);box-shadow:0 1px 1.5px rgba(16,14,30,.05);}
|
|
303
|
+
.fdy-badge--success{color:var(--color-success-strong);background:var(--color-success-soft);border-color:rgba(var(--color-success-rgb),.26);}
|
|
304
|
+
.fdy-badge--warning{color:var(--color-warning-strong);background:var(--color-warning-soft);border-color:rgba(var(--color-warning-rgb),.26);}
|
|
305
|
+
.fdy-badge--danger{color:var(--color-danger-strong);background:var(--color-danger-soft);border-color:rgba(var(--color-danger-rgb),.26);}
|
|
306
|
+
.fdy-badge--info{color:var(--color-info-strong);background:var(--color-info-soft);border-color:rgba(var(--color-info-rgb),.26);}
|
|
299
307
|
.fdy-badge--outline{background:transparent;border-color:var(--color-border-strong);color:var(--color-text-muted);box-shadow:none;}
|
|
300
308
|
|
|
301
309
|
/* Categorical tone badges, a status vocabulary larger than the semantic palette, from the
|
|
@@ -307,15 +315,19 @@ a { color: var(--color-primary); }
|
|
|
307
315
|
* cannot. A back-office document list carrying Draft, Submitted, Approved, Completed, Settled,
|
|
308
316
|
* Closed, Transferred, InDeclaration, Open and Rejected in ONE column collapsed to three colours,
|
|
309
317
|
* which is the report this shipped for. */
|
|
310
|
-
|
|
311
|
-
.
|
|
312
|
-
|
|
313
|
-
.
|
|
314
|
-
.
|
|
315
|
-
.fdy-badge--tone-
|
|
316
|
-
.fdy-badge--tone-
|
|
317
|
-
.fdy-badge--tone-
|
|
318
|
-
.fdy-badge--tone-
|
|
318
|
+
/* Precomputed tone tokens, the same --tone-N-bg / --tone-N-ink the avatar and the chip read, so
|
|
319
|
+
* one contrast assertion still covers all three. --tone-N-border-soft is the badge's own edge:
|
|
320
|
+
* 26% of the tone over transparent, which is a translucent colour and therefore stays rgba()
|
|
321
|
+
* rather than flattening to a hex. See avatar.css for why none of this is mixed in the
|
|
322
|
+
* component any more, and tokens/build.mjs for where the mixing moved to. */
|
|
323
|
+
.fdy-badge--tone-1{background:var(--tone-1-bg);color:var(--tone-1-ink);border-color:var(--tone-1-border-soft);}
|
|
324
|
+
.fdy-badge--tone-2{background:var(--tone-2-bg);color:var(--tone-2-ink);border-color:var(--tone-2-border-soft);}
|
|
325
|
+
.fdy-badge--tone-3{background:var(--tone-3-bg);color:var(--tone-3-ink);border-color:var(--tone-3-border-soft);}
|
|
326
|
+
.fdy-badge--tone-4{background:var(--tone-4-bg);color:var(--tone-4-ink);border-color:var(--tone-4-border-soft);}
|
|
327
|
+
.fdy-badge--tone-5{background:var(--tone-5-bg);color:var(--tone-5-ink);border-color:var(--tone-5-border-soft);}
|
|
328
|
+
.fdy-badge--tone-6{background:var(--tone-6-bg);color:var(--tone-6-ink);border-color:var(--tone-6-border-soft);}
|
|
329
|
+
.fdy-badge--tone-7{background:var(--tone-7-bg);color:var(--tone-7-ink);border-color:var(--tone-7-border-soft);}
|
|
330
|
+
.fdy-badge--tone-8{background:var(--tone-8-bg);color:var(--tone-8-ink);border-color:var(--tone-8-border-soft);}
|
|
319
331
|
|
|
320
332
|
/* Overlay badge, anchors a small count/dot/icon badge to a corner of any element
|
|
321
333
|
* (icon, button, text). Wrap the content in .fdy-badge-wrap; add .fdy-badge-ov as a
|
|
@@ -406,7 +418,7 @@ a { color: var(--color-primary); }
|
|
|
406
418
|
.fdy-breadcrumb__item{display:inline-flex;align-items:center;gap:var(--space-2);color:var(--color-text-muted);}
|
|
407
419
|
.fdy-breadcrumb__link{color:var(--color-text-muted);text-decoration:none;border-radius:var(--radius-sm);}
|
|
408
420
|
.fdy-breadcrumb__link:hover{color:var(--color-primary-strong);text-decoration:underline;}
|
|
409
|
-
.fdy-breadcrumb__link:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
421
|
+
.fdy-breadcrumb__link:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
410
422
|
.fdy-breadcrumb__item[aria-current="page"]{color:var(--color-text);font-weight:var(--weight-medium);}
|
|
411
423
|
.fdy-breadcrumb__sep{color:var(--color-text-subtle);user-select:none;}
|
|
412
424
|
|
|
@@ -476,16 +488,24 @@ a { color: var(--color-primary); }
|
|
|
476
488
|
}
|
|
477
489
|
|
|
478
490
|
/* Freeday. Button */
|
|
491
|
+
/* The fill is a FLAT colour with a black veil laid over it, not a gradient between two shades.
|
|
492
|
+
* It used to be `linear-gradient(primary, color-mix(in srgb, #000 10%, primary))`, and that is the
|
|
493
|
+
* same colour at every stop — veiling a solid base with black 0 -> .1 darkens it by exactly 10% —
|
|
494
|
+
* but the mix form carries var(), so on Safari <= 16.1 the whole declaration failed at
|
|
495
|
+
* computed-value time and the button lost its fill rather than falling back. Measured identical to
|
|
496
|
+
* the mix it replaces (within the 1/255 the gradient's own 8-bit rounding costs); see
|
|
497
|
+
* test/color-mix.test.mjs for the rule and tokens/build.mjs for why none of these may use
|
|
498
|
+
* color-mix(). Pressed states veil from the TOP, which is the same trick read upside down. */
|
|
479
499
|
.fdy-btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);
|
|
480
500
|
height:var(--control-h);padding:0 var(--space-4);
|
|
481
501
|
font-family:var(--font-body);font-size:var(--text-sm);font-weight:var(--weight-semibold);
|
|
482
502
|
line-height:1;white-space:nowrap;cursor:pointer;text-decoration:none;color:var(--color-on-primary);
|
|
483
|
-
background:
|
|
503
|
+
background:var(--color-primary) linear-gradient(180deg,rgba(0,0,0,0),rgba(0,0,0,.1));
|
|
484
504
|
border:var(--bw) solid transparent;border-radius:var(--radius-md);
|
|
485
|
-
box-shadow:0 2px 9px -1px
|
|
505
|
+
box-shadow:0 2px 9px -1px rgba(var(--color-primary-rgb),.5),inset 0 1px 0 rgba(255,255,255,.26);
|
|
486
506
|
transition:background var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard),transform var(--dur-fast) var(--ease-standard);}
|
|
487
|
-
.fdy-btn:hover{transform:translateY(-1px);box-shadow:0 6px 18px -2px
|
|
488
|
-
.fdy-btn:active{transform:translateY(1px);box-shadow:0 1px 4px -1px
|
|
507
|
+
.fdy-btn:hover{transform:translateY(-1px);box-shadow:0 6px 18px -2px rgba(var(--color-primary-rgb),.6),inset 0 1px 0 rgba(255,255,255,.26);}
|
|
508
|
+
.fdy-btn:active{transform:translateY(1px);box-shadow:0 1px 4px -1px rgba(var(--color-primary-rgb),.46);}
|
|
489
509
|
.fdy-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none;}
|
|
490
510
|
/* Pressed / toggle. `aria-pressed` is already the right attribute for a toggle button, so this adds
|
|
491
511
|
no class and no new markup contract, and it is what makes .fdy-btn-group a complete segmented
|
|
@@ -493,8 +513,8 @@ a { color: var(--color-primary); }
|
|
|
493
513
|
defines its OWN pressed look below; a single shared rule cannot work, because a gradient is a
|
|
494
514
|
background-IMAGE and would blank the ghost variant's background-color. Solid: invert the gradient
|
|
495
515
|
and sink the shadow inward, so a held button reads as depressed, not merely primary-coloured. */
|
|
496
|
-
.fdy-btn[aria-pressed="true"]{background:linear-gradient(180deg,
|
|
497
|
-
.fdy-btn[aria-pressed="true"]:hover{transform:none;box-shadow:inset 0 2px 6px
|
|
516
|
+
.fdy-btn[aria-pressed="true"]{background:var(--color-primary) linear-gradient(180deg,rgba(0,0,0,.12),rgba(0,0,0,0));box-shadow:inset 0 2px 6px rgba(0,0,0,.22);}
|
|
517
|
+
.fdy-btn[aria-pressed="true"]:hover{transform:none;box-shadow:inset 0 2px 6px rgba(0,0,0,.22);}
|
|
498
518
|
|
|
499
519
|
.fdy-btn--ghost{background:var(--color-surface);color:var(--color-primary-strong);border-color:var(--color-border-strong);box-shadow:var(--shadow-1);}
|
|
500
520
|
.fdy-btn--ghost:hover{transform:none;background:var(--color-primary-soft);border-color:var(--color-primary-border);box-shadow:var(--shadow-1);}
|
|
@@ -506,15 +526,15 @@ a { color: var(--color-primary); }
|
|
|
506
526
|
screen. `.fdy-menu__item--danger` has always modelled the quiet form (red text, not a red block);
|
|
507
527
|
the pairing rules below bring it to the button. They are more specific than this one and come
|
|
508
528
|
after it, so this rule needs no :not() guard of its own, one mechanism, not two. */
|
|
509
|
-
.fdy-btn--danger{background:
|
|
510
|
-
.fdy-btn--danger:hover{transform:translateY(-1px);box-shadow:0 6px 18px -2px
|
|
529
|
+
.fdy-btn--danger{background:var(--color-danger-btn) linear-gradient(180deg,rgba(0,0,0,0),rgba(0,0,0,.12));color:var(--color-on-danger);box-shadow:0 2px 9px -1px rgba(var(--color-danger-btn-rgb),.46),inset 0 1px 0 rgba(255,255,255,.22);}
|
|
530
|
+
.fdy-btn--danger:hover{transform:translateY(-1px);box-shadow:0 6px 18px -2px rgba(var(--color-danger-btn-rgb),.54),inset 0 1px 0 rgba(255,255,255,.22);}
|
|
511
531
|
.fdy-btn--danger:active{transform:translateY(1px);}
|
|
512
532
|
/* Quiet destructive: the variant keeps its own ground and only the ink turns. */
|
|
513
|
-
.fdy-btn--ghost.fdy-btn--danger{background:transparent;color:var(--color-danger-strong);border-color:
|
|
533
|
+
.fdy-btn--ghost.fdy-btn--danger{background:transparent;color:var(--color-danger-strong);border-color:rgba(var(--color-danger-rgb),.4);box-shadow:none;}
|
|
514
534
|
.fdy-btn--ghost.fdy-btn--danger:hover{background:var(--color-danger-soft);border-color:var(--color-danger);color:var(--color-danger-strong);}
|
|
515
535
|
.fdy-btn--text.fdy-btn--danger{background:none;color:var(--color-danger-strong);border-color:transparent;box-shadow:none;}
|
|
516
536
|
.fdy-btn--text.fdy-btn--danger:hover{background:var(--color-danger-soft);color:var(--color-danger-strong);}
|
|
517
|
-
.fdy-btn--danger[aria-pressed="true"]{background:
|
|
537
|
+
.fdy-btn--danger[aria-pressed="true"]{background:var(--color-danger-btn) linear-gradient(180deg,rgba(0,0,0,.14),rgba(0,0,0,0));box-shadow:inset 0 2px 6px rgba(0,0,0,.24);}
|
|
518
538
|
|
|
519
539
|
.fdy-btn--sm{height:calc(var(--control-h) - var(--space-2));padding:0 var(--space-3);font-size:var(--text-xs);border-radius:var(--radius-sm);}
|
|
520
540
|
.fdy-btn--lg{height:calc(var(--control-h) + var(--space-2));padding:0 var(--space-6);font-size:var(--text-base);border-radius:var(--radius-lg);}
|
|
@@ -563,7 +583,7 @@ a { color: var(--color-primary); }
|
|
|
563
583
|
.fdy-btn-group .fdy-btn:last-child{border-top-right-radius:var(--radius-md);border-bottom-right-radius:var(--radius-md);}
|
|
564
584
|
|
|
565
585
|
/* FAB, circular elevated action button (icon), optional extended pill with label */
|
|
566
|
-
.fdy-fab{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);width:3.5rem;height:3.5rem;padding:0;border:var(--bw) solid transparent;border-radius:var(--radius-full);cursor:pointer;color:var(--color-on-primary);background:
|
|
586
|
+
.fdy-fab{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);width:3.5rem;height:3.5rem;padding:0;border:var(--bw) solid transparent;border-radius:var(--radius-full);cursor:pointer;color:var(--color-on-primary);background:var(--color-primary) linear-gradient(180deg,rgba(0,0,0,0),rgba(0,0,0,.1));box-shadow:var(--shadow-3);transition:transform var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard);}
|
|
567
587
|
.fdy-fab:hover{transform:translateY(-1px);box-shadow:var(--shadow-4);}
|
|
568
588
|
.fdy-fab:active{transform:translateY(1px);}
|
|
569
589
|
.fdy-fab:focus-visible{border-radius:var(--radius-full);}
|
|
@@ -572,8 +592,8 @@ a { color: var(--color-primary); }
|
|
|
572
592
|
.fdy-fab--sm{width:2.5rem;height:2.5rem;}
|
|
573
593
|
.fdy-fab--sm svg{width:1.25rem;height:1.25rem;}
|
|
574
594
|
.fdy-fab--extended{width:auto;padding:0 var(--space-5);font-family:var(--font-body);font-size:var(--text-sm);font-weight:var(--weight-semibold);}
|
|
575
|
-
.fdy-fab--danger{background:
|
|
576
|
-
.fdy-fab--accent{background:
|
|
595
|
+
.fdy-fab--danger{background:var(--color-danger-btn) linear-gradient(180deg,rgba(0,0,0,0),rgba(0,0,0,.12));color:var(--color-on-danger);}
|
|
596
|
+
.fdy-fab--accent{background:var(--color-accent) linear-gradient(180deg,rgba(0,0,0,0),rgba(0,0,0,.1));color:var(--color-on-accent);}
|
|
577
597
|
|
|
578
598
|
/* Freeday. Card */
|
|
579
599
|
/* position:relative, containing block for out-of-flow card content (see base.css); it also gives
|
|
@@ -609,6 +629,13 @@ a { color: var(--color-primary); }
|
|
|
609
629
|
absolutely positioned dismiss button back into the flow. Do not merge these two rules. */
|
|
610
630
|
:where(:is(.fdy-card,.fdy-list__row):has(.fdy-btn--stretch) :is(a[href],button,input,select,textarea,[tabindex]):not(.fdy-btn--stretch)){position:relative;}
|
|
611
631
|
.fdy-card__body{padding:var(--space-5);}
|
|
632
|
+
/* Header band (#070): an identity mark, the title, and the card's way out pinned right. Beside the
|
|
633
|
+
title the action sits in one place on every card; under the content it moved each time the
|
|
634
|
+
content grew. Outside __body's padding, so its rule spans the card edge to edge. The mark is an
|
|
635
|
+
.fdy-avatar (--sm --square --tone-N), so its tints are the ones the contrast gate already covers. */
|
|
636
|
+
.fdy-card__head{display:flex;align-items:center;gap:var(--space-3);padding:var(--space-4) var(--space-5);border-bottom:var(--bw) solid var(--color-border-muted);}
|
|
637
|
+
.fdy-card__head .fdy-card__title{flex:1 1 auto;min-width:0;margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
638
|
+
.fdy-card__action{flex:none;display:inline-flex;align-items:center;gap:var(--space-2);}
|
|
612
639
|
.fdy-card__title{font-family:var(--font-display);font-size:var(--text-lg);font-weight:var(--weight-semibold);letter-spacing:var(--tracking-tight);color:var(--color-text);margin:0 0 var(--space-1);}
|
|
613
640
|
.fdy-card__desc{font-size:var(--text-sm);color:var(--color-text-muted);margin:0;line-height:var(--leading-normal);}
|
|
614
641
|
.fdy-card__footer{padding:var(--space-3) var(--space-5);border-top:var(--bw) solid var(--color-border-muted);background:linear-gradient(180deg,var(--color-surface),var(--color-surface-2));display:flex;gap:var(--space-2);justify-content:flex-end;}
|
|
@@ -621,9 +648,9 @@ a { color: var(--color-primary); }
|
|
|
621
648
|
.fdy-carousel__viewport{position:relative;display:flex;overflow-x:auto;scroll-snap-type:x mandatory;scroll-behavior:smooth;border-radius:var(--radius-lg);scrollbar-width:none;-ms-overflow-style:none;}
|
|
622
649
|
.fdy-carousel__viewport::-webkit-scrollbar{display:none;}
|
|
623
650
|
.fdy-carousel__slide{flex:0 0 100%;min-width:0;scroll-snap-align:center;}
|
|
624
|
-
.fdy-carousel__arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:2;display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;border:0;border-radius:var(--radius-full);background:
|
|
651
|
+
.fdy-carousel__arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:2;display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;border:0;border-radius:var(--radius-full);background:rgba(var(--color-surface-rgb),.86);color:var(--color-text);box-shadow:var(--shadow-2);cursor:pointer;transition:background var(--dur-fast) var(--ease-standard);}
|
|
625
652
|
.fdy-carousel__arrow:hover{background:var(--color-surface);}
|
|
626
|
-
.fdy-carousel__arrow:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
653
|
+
.fdy-carousel__arrow:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.4);}
|
|
627
654
|
.fdy-carousel__arrow:disabled{opacity:.4;cursor:not-allowed;}
|
|
628
655
|
.fdy-carousel__arrow--prev{left:var(--space-3);}
|
|
629
656
|
.fdy-carousel__arrow--next{right:var(--space-3);}
|
|
@@ -631,7 +658,7 @@ a { color: var(--color-primary); }
|
|
|
631
658
|
.fdy-carousel__dots{display:flex;justify-content:center;gap:var(--space-2);margin-top:var(--space-3);}
|
|
632
659
|
.fdy-carousel__dot{width:.5rem;height:.5rem;padding:0;border:0;border-radius:var(--radius-full);background:var(--color-border-strong);cursor:pointer;transition:background var(--dur-fast) var(--ease-standard),width var(--dur-fast) var(--ease-standard);}
|
|
633
660
|
.fdy-carousel__dot[aria-current="true"]{background:var(--color-primary);width:1.25rem;}
|
|
634
|
-
.fdy-carousel__dot:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
661
|
+
.fdy-carousel__dot:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.4);}
|
|
635
662
|
@media (prefers-reduced-motion:reduce){.fdy-carousel__viewport{scroll-behavior:auto;}}
|
|
636
663
|
|
|
637
664
|
/* Freeday. Cascade select (hierarchical drill-down picker).
|
|
@@ -643,14 +670,14 @@ a { color: var(--color-primary); }
|
|
|
643
670
|
.fdy-cascade{position:relative;display:inline-block;width:100%;max-width:22rem;}
|
|
644
671
|
.fdy-cascade__trigger{display:inline-flex;align-items:center;justify-content:space-between;gap:var(--space-2);width:100%;height:var(--control-h);padding:0 var(--space-3);text-align:left;cursor:pointer;font-family:var(--font-body);font-size:var(--text-sm);color:var(--color-text);background:var(--color-surface);border:1.5px solid var(--color-control-border);border-radius:var(--radius-md);box-shadow:inset 0 1px 2px rgba(16,14,30,.06);transition:border-color var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard);}
|
|
645
672
|
.fdy-cascade__trigger:hover{border-color:var(--color-text-muted);}
|
|
646
|
-
.fdy-cascade__trigger:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px
|
|
647
|
-
.fdy-cascade__trigger.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px
|
|
673
|
+
.fdy-cascade__trigger:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
674
|
+
.fdy-cascade__trigger.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
648
675
|
.fdy-cascade__trigger:disabled,.fdy-cascade__trigger[aria-disabled="true"]{opacity:.5;cursor:not-allowed;}
|
|
649
676
|
.fdy-cascade__trigger[aria-readonly="true"]{background:var(--color-surface-2);border-color:var(--color-border);cursor:default;}
|
|
650
677
|
.fdy-cascade__trigger[aria-readonly="true"]:hover{border-color:var(--color-border);}
|
|
651
678
|
.fdy-cascade__trigger[aria-readonly="true"]:focus-visible{border-color:var(--color-border-strong);box-shadow:none;}
|
|
652
679
|
.fdy-cascade--error .fdy-cascade__trigger,.fdy-cascade__trigger[aria-invalid="true"]{border-color:var(--color-danger);}
|
|
653
|
-
.fdy-cascade--error .fdy-cascade__trigger:focus-visible,.fdy-cascade--error .fdy-cascade__trigger.is-open,.fdy-cascade__trigger[aria-invalid="true"]:focus-visible{border-color:var(--color-danger);box-shadow:0 0 0 3px
|
|
680
|
+
.fdy-cascade--error .fdy-cascade__trigger:focus-visible,.fdy-cascade--error .fdy-cascade__trigger.is-open,.fdy-cascade__trigger[aria-invalid="true"]:focus-visible{border-color:var(--color-danger);box-shadow:0 0 0 3px rgba(var(--color-danger-rgb),.26);}
|
|
654
681
|
.fdy-cascade__value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
655
682
|
.fdy-cascade__value--placeholder{color:var(--color-text-subtle);}
|
|
656
683
|
.fdy-cascade__trigger::after{content:"";flex:none;width:.5rem;height:.5rem;margin-top:-.15rem;border-right:2px solid var(--color-text-subtle);border-bottom:2px solid var(--color-text-subtle);transform:rotate(45deg);transition:transform var(--dur-fast) var(--ease-standard);}
|
|
@@ -662,7 +689,7 @@ a { color: var(--color-primary); }
|
|
|
662
689
|
.fdy-cascade__head{display:flex;align-items:center;gap:var(--space-2);padding:var(--space-1) var(--space-1) var(--space-2);margin-bottom:var(--space-1);border-bottom:var(--bw) solid var(--color-border);}
|
|
663
690
|
.fdy-cascade__back{display:inline-flex;align-items:center;justify-content:center;flex:none;width:1.5rem;height:1.5rem;padding:0;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-muted);cursor:pointer;}
|
|
664
691
|
.fdy-cascade__back:hover{background:var(--color-surface-3);color:var(--color-text);}
|
|
665
|
-
.fdy-cascade__back:focus-visible{outline:none;box-shadow:0 0 0 2px
|
|
692
|
+
.fdy-cascade__back:focus-visible{outline:none;box-shadow:0 0 0 2px rgba(var(--color-primary-rgb),.45);}
|
|
666
693
|
.fdy-cascade__back[hidden]{display:none;}
|
|
667
694
|
.fdy-cascade__back svg{display:block;width:1rem;height:1rem;}
|
|
668
695
|
.fdy-cascade__crumb{min-width:0;flex:1;font-size:var(--text-xs);font-weight:var(--weight-semibold);color:var(--color-text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
@@ -825,30 +852,48 @@ a { color: var(--color-primary); }
|
|
|
825
852
|
|
|
826
853
|
/* Freeday. Chip (tag / removable filter) */
|
|
827
854
|
.fdy-chip{display:inline-flex;align-items:center;gap:var(--space-2);height:1.75rem;padding:0 var(--space-3);border-radius:var(--radius-full);font-size:var(--text-xs);font-weight:var(--weight-medium);color:var(--color-text);background:var(--color-surface-3);border:var(--bw) solid var(--color-border);}
|
|
828
|
-
.fdy-chip--primary{color:var(--color-primary-strong);background:var(--color-primary-soft);border-color:
|
|
855
|
+
.fdy-chip--primary{color:var(--color-primary-strong);background:var(--color-primary-soft);border-color:rgba(var(--color-primary-rgb),.22);}
|
|
829
856
|
/* Categorical tone chips, non-semantic category tags / legend swatches, from the general
|
|
830
857
|
* --tone-1..8 palette. Same validated AA formula as .fdy-avatar--tone-* (text >=4.5:1 both themes,
|
|
831
858
|
* gated by test/contrast.test.mjs). */
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
.
|
|
835
|
-
.
|
|
836
|
-
.fdy-chip--tone-
|
|
837
|
-
.fdy-chip--tone-
|
|
838
|
-
.fdy-chip--tone-
|
|
839
|
-
.fdy-chip--tone-
|
|
840
|
-
.fdy-chip--tone-
|
|
841
|
-
.fdy-
|
|
842
|
-
.fdy-
|
|
843
|
-
.fdy-
|
|
859
|
+
/* Precomputed tone tokens, the same --tone-N-bg / --tone-N-ink the avatar and the badge read.
|
|
860
|
+
* --tone-N-border is the chip's edge: 30% of the tone over --color-border, opaque, which is a
|
|
861
|
+
* different edge from the badge's translucent one and so a different token. See avatar.css for
|
|
862
|
+
* why the mix left the component, and tokens/build.mjs for where it went. */
|
|
863
|
+
.fdy-chip--tone-1{background:var(--tone-1-bg);color:var(--tone-1-ink);border-color:var(--tone-1-border);}
|
|
864
|
+
.fdy-chip--tone-2{background:var(--tone-2-bg);color:var(--tone-2-ink);border-color:var(--tone-2-border);}
|
|
865
|
+
.fdy-chip--tone-3{background:var(--tone-3-bg);color:var(--tone-3-ink);border-color:var(--tone-3-border);}
|
|
866
|
+
.fdy-chip--tone-4{background:var(--tone-4-bg);color:var(--tone-4-ink);border-color:var(--tone-4-border);}
|
|
867
|
+
.fdy-chip--tone-5{background:var(--tone-5-bg);color:var(--tone-5-ink);border-color:var(--tone-5-border);}
|
|
868
|
+
.fdy-chip--tone-6{background:var(--tone-6-bg);color:var(--tone-6-ink);border-color:var(--tone-6-border);}
|
|
869
|
+
.fdy-chip--tone-7{background:var(--tone-7-bg);color:var(--tone-7-ink);border-color:var(--tone-7-border);}
|
|
870
|
+
.fdy-chip--tone-8{background:var(--tone-8-bg);color:var(--tone-8-ink);border-color:var(--tone-8-border);}
|
|
871
|
+
.fdy-chip__remove{position:relative;display:inline-flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;margin-right:calc(var(--space-1)*-1);border:0;padding:0;border-radius:var(--radius-full);background:transparent;color:currentColor;opacity:.6;cursor:pointer;font-size:var(--text-sm);line-height:1;}
|
|
872
|
+
/* The hover wash is 16% of the chip's OWN ink, and the chip's ink is whatever the variant set:
|
|
873
|
+
* --color-text, --color-primary-strong, --tone-N-ink. So no token can stand in for it, which is why
|
|
874
|
+
* this was the last color-mix() in the kit — and the only one whose two-line fallback actually
|
|
875
|
+
* worked, the mix carrying no var() and therefore being rejected at parse time.
|
|
876
|
+
*
|
|
877
|
+
* It is a VEIL now, the same trick the button gradients use (button.css): currentColor at .16 over
|
|
878
|
+
* the chip, which is algebraically the colour the mix produced — `F·.16 + (1-.16)·ground` either
|
|
879
|
+
* way, including at the glyph's antialiased edges, where the veil's colour equals the glyph's and so
|
|
880
|
+
* composites back to itself. No @supports, no fallback line, and nothing newer than Safari 4.
|
|
881
|
+
*
|
|
882
|
+
* Absolutely positioned, so it paints above the × as well as the background; `border-radius:inherit`
|
|
883
|
+
* keeps it inside the pill. No transition: the mix had none, and a veil that fades is a different
|
|
884
|
+
* component. */
|
|
885
|
+
.fdy-chip__remove::before{content:"";position:absolute;inset:0;border-radius:inherit;background:currentColor;opacity:0;}
|
|
886
|
+
.fdy-chip__remove:hover{opacity:1;}
|
|
887
|
+
.fdy-chip__remove:hover::before{opacity:.16;}
|
|
888
|
+
.fdy-chip__remove:focus-visible{outline:none;opacity:1;box-shadow:0 0 0 2px rgba(var(--color-primary-rgb),.45);}
|
|
844
889
|
/* Group wrapper for a row of chips (choice / filter). */
|
|
845
890
|
.fdy-chips{display:flex;flex-wrap:wrap;gap:var(--space-2);}
|
|
846
891
|
/* Interactive chips: choice (toggle) + filter (toggle with a check when on).
|
|
847
892
|
* Rendered as <button aria-pressed> and enhanced by freeday-chip.js. */
|
|
848
893
|
.fdy-chip--choice,.fdy-chip--filter{cursor:pointer;font-family:inherit;background:var(--color-surface);border-color:var(--color-border);transition:background var(--dur-fast) var(--ease-standard),border-color var(--dur-fast) var(--ease-standard),color var(--dur-fast) var(--ease-standard);}
|
|
849
894
|
.fdy-chip--choice:hover,.fdy-chip--filter:hover{background:var(--color-surface-3);border-color:var(--color-text-subtle);}
|
|
850
|
-
.fdy-chip--choice:focus-visible,.fdy-chip--filter:focus-visible{outline:none;box-shadow:0 0 0 2px
|
|
851
|
-
.fdy-chip--choice[aria-pressed="true"],.fdy-chip--filter[aria-pressed="true"]{color:var(--color-primary-strong);background:var(--color-primary-soft);border-color:
|
|
895
|
+
.fdy-chip--choice:focus-visible,.fdy-chip--filter:focus-visible{outline:none;box-shadow:0 0 0 2px rgba(var(--color-primary-rgb),.45);}
|
|
896
|
+
.fdy-chip--choice[aria-pressed="true"],.fdy-chip--filter[aria-pressed="true"]{color:var(--color-primary-strong);background:var(--color-primary-soft);border-color:rgba(var(--color-primary-rgb),.4);}
|
|
852
897
|
.fdy-chip--choice:disabled,.fdy-chip--filter:disabled,.fdy-chip--choice[aria-disabled="true"],.fdy-chip--filter[aria-disabled="true"]{opacity:.5;cursor:not-allowed;}
|
|
853
898
|
.fdy-chip__check{display:none;flex:none;width:.85rem;height:.85rem;margin-left:calc(var(--space-1)*-1);}
|
|
854
899
|
.fdy-chip__check svg{display:block;width:100%;height:100%;}
|
|
@@ -858,8 +903,8 @@ a { color: var(--color-primary); }
|
|
|
858
903
|
.fdy-combo{position:relative;display:block;max-width:22rem;}
|
|
859
904
|
.fdy-combo__button{display:inline-flex;align-items:center;justify-content:space-between;gap:var(--space-2);width:100%;height:var(--control-h);padding:0 var(--space-3);text-align:left;cursor:pointer;font-family:var(--font-body);font-size:var(--text-sm);color:var(--color-text);background:var(--color-surface);border:1.5px solid var(--color-control-border);border-radius:var(--radius-md);box-shadow:inset 0 1px 2px rgba(16,14,30,.06);transition:border-color var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard);}
|
|
860
905
|
.fdy-combo__button:hover{border-color:var(--color-text-muted);}
|
|
861
|
-
.fdy-combo__button:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px
|
|
862
|
-
.fdy-combo__button.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px
|
|
906
|
+
.fdy-combo__button:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
907
|
+
.fdy-combo__button.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
863
908
|
.fdy-combo__button:disabled,.fdy-combo__button[aria-disabled="true"]{opacity:.5;cursor:not-allowed;}
|
|
864
909
|
/* Read-only: stays focusable & shows its value at full contrast but can't open, muted surface,
|
|
865
910
|
softened border, default cursor, no focus-ring escalation (matches input[readonly], #39). */
|
|
@@ -867,7 +912,7 @@ a { color: var(--color-primary); }
|
|
|
867
912
|
.fdy-combo__button[aria-readonly="true"]:hover{border-color:var(--color-border);}
|
|
868
913
|
.fdy-combo__button[aria-readonly="true"]:focus-visible{border-color:var(--color-border-strong);box-shadow:none;}
|
|
869
914
|
.fdy-combo--error .fdy-combo__button,.fdy-combo__button[aria-invalid="true"]{border-color:var(--color-danger);}
|
|
870
|
-
.fdy-combo--error .fdy-combo__button:focus-visible,.fdy-combo--error .fdy-combo__button.is-open,.fdy-combo__button[aria-invalid="true"]:focus-visible{border-color:var(--color-danger);box-shadow:0 0 0 3px
|
|
915
|
+
.fdy-combo--error .fdy-combo__button:focus-visible,.fdy-combo--error .fdy-combo__button.is-open,.fdy-combo__button[aria-invalid="true"]:focus-visible{border-color:var(--color-danger);box-shadow:0 0 0 3px rgba(var(--color-danger-rgb),.26);}
|
|
871
916
|
.fdy-combo__value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
872
917
|
.fdy-combo__value--placeholder{color:var(--color-text-subtle);}
|
|
873
918
|
.fdy-combo__button::after{content:"";flex:none;width:.5rem;height:.5rem;margin-top:-.15rem;border-right:2px solid var(--color-text-subtle);border-bottom:2px solid var(--color-text-subtle);transform:rotate(45deg);transition:transform var(--dur-fast) var(--ease-standard);}
|
|
@@ -882,14 +927,14 @@ a { color: var(--color-primary); }
|
|
|
882
927
|
.fdy-combo__option{display:flex;align-items:center;gap:var(--space-2);padding:var(--space-2) var(--space-3);border-radius:var(--radius-sm);font-size:var(--text-sm);color:var(--color-text);cursor:pointer;white-space:nowrap;}
|
|
883
928
|
.fdy-combo__option.is-highlighted{background:var(--color-surface-3);}
|
|
884
929
|
.fdy-combo__option[aria-selected="true"]{background:var(--color-primary-soft);color:var(--color-primary-strong);font-weight:var(--weight-semibold);}
|
|
885
|
-
.fdy-combo__option.is-highlighted[aria-selected="true"]{box-shadow:inset 0 0 0 2px
|
|
930
|
+
.fdy-combo__option.is-highlighted[aria-selected="true"]{box-shadow:inset 0 0 0 2px rgba(var(--color-primary-rgb),.55);}
|
|
886
931
|
/* The tick is CSS, not content (#004 §2). Inside role="option" it joined the option's ACCESSIBLE
|
|
887
932
|
NAME, so the selected option announced "✓August" while every other announced "August": the state
|
|
888
933
|
was read twice, once as aria-selected, once as decoration, and a test asking for an option by
|
|
889
934
|
its own label stopped matching the one that was selected. The `/ ""` is alt text: the glyph is
|
|
890
935
|
painted, the accessibility tree gets nothing. Same reasoning as .fdy-label--required (1.29.0).
|
|
891
936
|
The empty box still reserves its width, so labels stay aligned whether selected or not. */
|
|
892
|
-
.fdy-combo__check{display:inline-flex;justify-content:center;width:var(--space-4);flex:none;font-weight:var(--weight-bold);color:var(--color-primary);}
|
|
937
|
+
.fdy-combo__check{display:inline-flex;justify-content:center;width:var(--space-4);flex:none;font-weight:var(--weight-bold);color:var(--color-primary-strong);}
|
|
893
938
|
.fdy-combo__option[aria-selected="true"] .fdy-combo__check::after{content:"✓" / "";}
|
|
894
939
|
@media (prefers-reduced-motion:no-preference){.fdy-combo__listbox:not([hidden]){animation:fdy-combo-in var(--dur-fast) var(--ease-standard);}}
|
|
895
940
|
@keyframes fdy-combo-in{from{opacity:0;transform:translateY(-4px);}to{opacity:1;transform:none;}}
|
|
@@ -991,6 +1036,42 @@ a { color: var(--color-primary); }
|
|
|
991
1036
|
.fdy-text-success{color:var(--color-success-strong);}
|
|
992
1037
|
.fdy-text-warning{color:var(--color-warning-strong);}
|
|
993
1038
|
.fdy-text-danger{color:var(--color-danger-strong);}
|
|
1039
|
+
/* Document columns (#065): a form or record page with an optional identity rail on the left
|
|
1040
|
+
* (__lead) and a summary rail on the right (__aside). The widths follow which rails are PRESENT,
|
|
1041
|
+
* so the layout is decided once here and not again by every screen:
|
|
1042
|
+
* __main alone one column
|
|
1043
|
+
* __main + __aside 8 / 4 (from md)
|
|
1044
|
+
* __lead + __main 3 / 9 (from md)
|
|
1045
|
+
* all three 3 / 6 / 3 (from lg; between md and lg both rails share the left)
|
|
1046
|
+
* Stacked, the summary rail comes FIRST: last, it sits under every section, and its button with it.
|
|
1047
|
+
* From md each rail is sticky and scrolls on its own, so the total and the status stay answerable
|
|
1048
|
+
* while the main column scrolls with the page, and a rail taller than the screen never hangs its
|
|
1049
|
+
* end off it. Screen only: a printed page is not held to a window. */
|
|
1050
|
+
.fdy-page__columns{--_fdy-rail-top:var(--fdy-page-sticky-top,var(--space-4));display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-6);align-items:start;}
|
|
1051
|
+
/* Under the shell the sticky topbar is in the way; --fdy-page-sticky-top overrides either default. */
|
|
1052
|
+
.fdy-app .fdy-page__columns{--_fdy-rail-top:var(--fdy-page-sticky-top,calc(var(--space-16) + var(--space-4)));}
|
|
1053
|
+
.fdy-page__columns > *{min-width:0;}
|
|
1054
|
+
@media (max-width:959.98px){.fdy-page__aside{order:-1;}}
|
|
1055
|
+
@media (min-width:960px){
|
|
1056
|
+
.fdy-page__columns:has(> .fdy-page__aside){grid-template-columns:minmax(0,2fr) minmax(0,1fr);}
|
|
1057
|
+
.fdy-page__columns:has(> .fdy-page__lead){grid-template-columns:minmax(0,1fr) minmax(0,3fr);}
|
|
1058
|
+
/* Both rails, two columns: they stack on the left while __main spans both rows on the right. */
|
|
1059
|
+
.fdy-page__columns:has(> .fdy-page__lead):has(> .fdy-page__aside) > .fdy-page__main{grid-row:span 2;}
|
|
1060
|
+
}
|
|
1061
|
+
@media (min-width:1280px){
|
|
1062
|
+
.fdy-page__columns:has(> .fdy-page__lead):has(> .fdy-page__aside){grid-template-columns:minmax(0,1fr) minmax(0,2fr) minmax(0,1fr);}
|
|
1063
|
+
.fdy-page__columns:has(> .fdy-page__lead):has(> .fdy-page__aside) > .fdy-page__main{grid-row:auto;}
|
|
1064
|
+
}
|
|
1065
|
+
/* The padding, taken back by the margin, is room for a focus ring at a card's edge: a scrolling box
|
|
1066
|
+
clips whatever draws outside it. */
|
|
1067
|
+
@media screen and (min-width:960px){
|
|
1068
|
+
.fdy-page__lead,.fdy-page__aside{position:sticky;top:var(--_fdy-rail-top);max-height:calc(100dvh - var(--_fdy-rail-top) - var(--space-4));overflow-y:auto;overscroll-behavior:contain;padding:var(--space-1);margin:calc(var(--space-1) * -1);}
|
|
1069
|
+
}
|
|
1070
|
+
/* Two sticky rails in ONE column would slide over each other: between md and lg, with both rails
|
|
1071
|
+
present, they scroll with the page instead. */
|
|
1072
|
+
@media screen and (min-width:960px) and (max-width:1279.98px){
|
|
1073
|
+
.fdy-page__columns:has(> .fdy-page__lead):has(> .fdy-page__aside) > :is(.fdy-page__lead,.fdy-page__aside){position:static;max-height:none;overflow:visible;}
|
|
1074
|
+
}
|
|
994
1075
|
|
|
995
1076
|
/* Freeday. Date picker (input-styled trigger + calendar popover).
|
|
996
1077
|
* Built by freeday-datepicker.js from an empty [data-fdy-datepicker] wrapper. */
|
|
@@ -1003,10 +1084,10 @@ a { color: var(--color-primary); }
|
|
|
1003
1084
|
.fdy-field>.fdy-datepicker,.fdy-field>.fdy-timepicker,.fdy-field>.fdy-daterange{max-width:none;}
|
|
1004
1085
|
.fdy-datepicker__trigger{display:inline-flex;align-items:center;gap:var(--space-2);width:100%;height:var(--control-h);padding:0 var(--space-3);text-align:left;cursor:pointer;font-family:var(--font-body);font-size:var(--text-sm);color:var(--color-text);background:var(--color-surface);border:1.5px solid var(--color-control-border);border-radius:var(--radius-md);box-shadow:inset 0 1px 2px rgba(16,14,30,.06);transition:border-color var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard);}
|
|
1005
1086
|
.fdy-datepicker__trigger:hover{border-color:var(--color-text-muted);}
|
|
1006
|
-
.fdy-datepicker__trigger:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px
|
|
1007
|
-
.fdy-datepicker__trigger.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px
|
|
1087
|
+
.fdy-datepicker__trigger:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1088
|
+
.fdy-datepicker__trigger.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1008
1089
|
.fdy-datepicker--error .fdy-datepicker__trigger,.fdy-datepicker__trigger[aria-invalid="true"]{border-color:var(--color-danger);}
|
|
1009
|
-
.fdy-datepicker--error .fdy-datepicker__trigger:focus-visible,.fdy-datepicker--error .fdy-datepicker__trigger.is-open,.fdy-datepicker__trigger[aria-invalid="true"]:focus-visible{border-color:var(--color-danger);box-shadow:0 0 0 3px
|
|
1090
|
+
.fdy-datepicker--error .fdy-datepicker__trigger:focus-visible,.fdy-datepicker--error .fdy-datepicker__trigger.is-open,.fdy-datepicker__trigger[aria-invalid="true"]:focus-visible{border-color:var(--color-danger);box-shadow:0 0 0 3px rgba(var(--color-danger-rgb),.26);}
|
|
1010
1091
|
.fdy-datepicker__trigger:disabled,.fdy-datepicker__trigger[aria-disabled="true"]{opacity:.5;cursor:not-allowed;}
|
|
1011
1092
|
.fdy-datepicker__trigger[aria-readonly="true"]{background:var(--color-surface-2);border-color:var(--color-border);cursor:default;}
|
|
1012
1093
|
.fdy-datepicker__trigger[aria-readonly="true"]:hover{border-color:var(--color-border);}
|
|
@@ -1021,7 +1102,7 @@ a { color: var(--color-primary); }
|
|
|
1021
1102
|
.fdy-datepicker__icon.is-hidden{visibility:hidden;}
|
|
1022
1103
|
.fdy-datepicker__clear{position:absolute;top:50%;right:var(--space-3);transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:1.15rem;height:1.15rem;padding:0;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-subtle);cursor:pointer;transition:color var(--dur-fast) var(--ease-standard),background var(--dur-fast) var(--ease-standard);}
|
|
1023
1104
|
.fdy-datepicker__clear:hover{color:var(--color-text);background:var(--color-surface-2);}
|
|
1024
|
-
.fdy-datepicker__clear:focus-visible{outline:none;color:var(--color-text);box-shadow:0 0 0 3px
|
|
1105
|
+
.fdy-datepicker__clear:focus-visible{outline:none;color:var(--color-text);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1025
1106
|
.fdy-datepicker__clear svg{display:block;width:.9rem;height:.9rem;}
|
|
1026
1107
|
|
|
1027
1108
|
.fdy-datepicker__panel{position:absolute;top:calc(100% + var(--space-1));left:0;z-index:130;padding:var(--space-3);background:var(--color-surface);color:var(--color-text);border:var(--bw) solid var(--color-border-strong);border-radius:var(--radius-md);box-shadow:var(--shadow-3);}
|
|
@@ -1033,16 +1114,16 @@ a { color: var(--color-primary); }
|
|
|
1033
1114
|
reset and the same hover/focus treatment as the arrows beside it. */
|
|
1034
1115
|
.fdy-cal__title{flex:1;appearance:none;border:0;background:transparent;margin:0;padding:var(--space-1) var(--space-2);border-radius:var(--radius-sm);text-align:center;font-family:inherit;font-weight:var(--weight-semibold);font-size:var(--text-sm);color:var(--color-text);text-transform:capitalize;cursor:pointer;}
|
|
1035
1116
|
.fdy-cal__title:hover{background:var(--color-surface-2);}
|
|
1036
|
-
.fdy-cal__title:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1117
|
+
.fdy-cal__title:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1037
1118
|
.fdy-cal__month,.fdy-cal__year{display:inline-flex;align-items:center;justify-content:center;height:2.25rem;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--color-text);font-family:inherit;font-size:var(--text-sm);text-transform:capitalize;cursor:pointer;}
|
|
1038
1119
|
.fdy-cal__month:hover,.fdy-cal__year:hover{background:var(--color-surface-2);}
|
|
1039
|
-
.fdy-cal__month:focus-visible,.fdy-cal__year:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1120
|
+
.fdy-cal__month:focus-visible,.fdy-cal__year:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1040
1121
|
.fdy-cal__month:disabled,.fdy-cal__year:disabled{opacity:.4;cursor:not-allowed;background:transparent;}
|
|
1041
1122
|
.fdy-cal__month.is-today,.fdy-cal__year.is-today{font-weight:var(--weight-bold);box-shadow:inset 0 0 0 1.5px var(--color-border-strong);}
|
|
1042
1123
|
.fdy-cal__month.is-selected,.fdy-cal__year.is-selected{background:var(--color-primary);color:var(--color-on-primary);font-weight:var(--weight-semibold);}
|
|
1043
1124
|
.fdy-cal__nav{display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;flex:none;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-muted);font-size:var(--text-lg);line-height:1;cursor:pointer;}
|
|
1044
1125
|
.fdy-cal__nav:hover{background:var(--color-surface-2);color:var(--color-text);}
|
|
1045
|
-
.fdy-cal__nav:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1126
|
+
.fdy-cal__nav:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1046
1127
|
.fdy-cal__grid{display:grid;grid-template-columns:repeat(7,2rem);gap:2px;}
|
|
1047
1128
|
/* Month grid. 3×4 over the same track width as the 7-column day grid, so the panel does not resize
|
|
1048
1129
|
when you drill and the pointer does not have to travel.
|
|
@@ -1054,7 +1135,7 @@ a { color: var(--color-primary); }
|
|
|
1054
1135
|
.fdy-cal__dow{display:flex;align-items:center;justify-content:center;height:1.75rem;font-size:var(--text-xs);font-weight:var(--weight-semibold);color:var(--color-text-muted);text-transform:capitalize;}
|
|
1055
1136
|
.fdy-cal__day{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--color-text);font-size:var(--text-sm);font-variant-numeric:tabular-nums;cursor:pointer;}
|
|
1056
1137
|
.fdy-cal__day:hover{background:var(--color-surface-2);}
|
|
1057
|
-
.fdy-cal__day:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1138
|
+
.fdy-cal__day:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1058
1139
|
.fdy-cal__day.is-outside{color:var(--color-text-subtle);opacity:.55;}
|
|
1059
1140
|
.fdy-cal__day.is-today{font-weight:var(--weight-bold);box-shadow:inset 0 0 0 1.5px var(--color-border-strong);}
|
|
1060
1141
|
.fdy-cal__day.in-range{background:var(--color-primary-soft);color:var(--color-primary-strong);border-radius:0;}
|
|
@@ -1086,9 +1167,19 @@ a { color: var(--color-primary); }
|
|
|
1086
1167
|
/* Freeday. Description list (key-value detail view) */
|
|
1087
1168
|
.fdy-dl{display:grid;grid-template-columns:auto 1fr;gap:var(--space-2) var(--space-5);margin:0;}
|
|
1088
1169
|
.fdy-dl dt{color:var(--color-text-muted);font-size:var(--text-sm);}
|
|
1089
|
-
|
|
1170
|
+
/* overflow-wrap: an email, an order code or a 13-digit phone number is one unbreakable token, and
|
|
1171
|
+
without it the value prints over whatever sits beside it (#066). */
|
|
1172
|
+
.fdy-dl dd{margin:0;min-width:0;color:var(--color-text);font-size:var(--text-sm);font-weight:var(--weight-medium);overflow-wrap:anywhere;}
|
|
1090
1173
|
.fdy-dl--rows{grid-template-columns:1fr;gap:var(--space-1);}
|
|
1091
1174
|
.fdy-dl--rows dt{margin-top:var(--space-2);}
|
|
1175
|
+
/* Facts grid (#066): each pair a <div> (allowed inside <dl>), caption above value, as many columns
|
|
1176
|
+
as the list's OWN width holds, never more than three. Sized by the element rather than the
|
|
1177
|
+
window, so a grid in a narrow side rail stays one column with no modifier: a window breakpoint
|
|
1178
|
+
gave a rail two columns of about 110px. min(100%, …) keeps a single column from overflowing a
|
|
1179
|
+
rail narrower than the column floor. */
|
|
1180
|
+
.fdy-dl--grid{grid-template-columns:repeat(auto-fill,minmax(min(100%,max(var(--fdy-dl-col-min,14rem),calc((100% - 2 * var(--space-6)) / 3))),1fr));gap:var(--space-5) var(--space-6);}
|
|
1181
|
+
.fdy-dl--grid > div{min-width:0;}
|
|
1182
|
+
.fdy-dl--grid dd{margin-top:var(--space-1);}
|
|
1092
1183
|
|
|
1093
1184
|
/* Freeday. Divider */
|
|
1094
1185
|
.fdy-divider{border:0;border-top:var(--bw) solid var(--color-border);margin:var(--space-4) 0;}
|
|
@@ -1125,11 +1216,11 @@ a { color: var(--color-primary); }
|
|
|
1125
1216
|
* Enhanced by freeday-upload.js; states: idle · drag-over · uploading · done · error. */
|
|
1126
1217
|
.fdy-dropzone{display:flex;flex-direction:column;align-items:center;gap:var(--space-2);padding:var(--space-6);text-align:center;border:2px dashed var(--color-control-border);border-radius:var(--radius-lg);background:var(--color-surface-2);color:var(--color-text-muted);cursor:pointer;transition:border-color var(--dur-fast) var(--ease-standard),background var(--dur-fast) var(--ease-standard),color var(--dur-fast) var(--ease-standard);}
|
|
1127
1218
|
.fdy-dropzone:hover{border-color:var(--color-text-muted);}
|
|
1128
|
-
.fdy-dropzone:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:0 0 0 3px
|
|
1219
|
+
.fdy-dropzone:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1129
1220
|
.fdy-dropzone.is-dragover{border-color:var(--color-primary);background:var(--color-primary-soft);color:var(--color-primary-strong);}
|
|
1130
1221
|
.fdy-dropzone[aria-disabled="true"],.fdy-dropzone.is-disabled{opacity:.55;cursor:not-allowed;pointer-events:none;}
|
|
1131
1222
|
.fdy-dropzone__icon{color:var(--color-text-subtle);}
|
|
1132
|
-
.fdy-dropzone.is-dragover .fdy-dropzone__icon{color:var(--color-primary);}
|
|
1223
|
+
.fdy-dropzone.is-dragover .fdy-dropzone__icon{color:var(--color-primary-strong);}
|
|
1133
1224
|
.fdy-dropzone__icon svg{display:block;width:2rem;height:2rem;}
|
|
1134
1225
|
.fdy-dropzone__title{font-size:inherit;font-weight:var(--weight-medium);color:var(--color-text);margin:0;}
|
|
1135
1226
|
.fdy-dropzone__hint{font-size:var(--text-xs);}
|
|
@@ -1156,9 +1247,14 @@ a { color: var(--color-primary); }
|
|
|
1156
1247
|
.fdy-file__progress{margin-top:var(--space-2);}
|
|
1157
1248
|
.fdy-file__remove{flex:none;display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-muted);font-size:var(--text-lg);line-height:1;cursor:pointer;}
|
|
1158
1249
|
.fdy-file__remove:hover{background:var(--color-surface-2);color:var(--color-text);}
|
|
1159
|
-
.fdy-file__remove:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1250
|
+
.fdy-file__remove:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1160
1251
|
.fdy-file--success .fdy-file__icon{color:var(--color-success);}
|
|
1161
|
-
|
|
1252
|
+
/* 40% of --color-danger over --color-border, as a token rather than as a mix written here: it blends
|
|
1253
|
+
* two ROLES, so no channel triple can state it, and mixing it in the component carried var() into
|
|
1254
|
+
* color-mix() — the shape that goes invalid at computed-value time and drops border-color to its
|
|
1255
|
+
* initial currentColor, which is the black box an iPhone 7 drew around a failed upload. The blend is
|
|
1256
|
+
* now computed per theme by tokens/build.mjs. */
|
|
1257
|
+
.fdy-file--error{border-color:var(--color-danger-border);}
|
|
1162
1258
|
.fdy-file--error .fdy-file__icon{color:var(--color-danger);}
|
|
1163
1259
|
.fdy-file--error .fdy-file__sub{color:var(--color-danger-strong);}
|
|
1164
1260
|
|
|
@@ -1230,7 +1326,7 @@ a { color: var(--color-primary); }
|
|
|
1230
1326
|
/* Freeday. Input group (prefix/suffix addons, e.g. Rp / % / icon) */
|
|
1231
1327
|
.fdy-input-group{display:flex;align-items:stretch;height:var(--control-h);max-width:22rem;background:var(--color-surface);border:1.5px solid var(--color-control-border);border-radius:var(--radius-md);box-shadow:inset 0 1px 2px rgba(16,14,30,.06);overflow:hidden;transition:border-color var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard);}
|
|
1232
1328
|
.fdy-input-group:hover{border-color:var(--color-text-muted);}
|
|
1233
|
-
.fdy-input-group:focus-within{border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px
|
|
1329
|
+
.fdy-input-group:focus-within{border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1234
1330
|
/* The group owns the height; the input fills whatever the border leaves. It used to subtract 3px
|
|
1235
1331
|
for two 1.5px borders, which is arithmetic the engine is free to round: at dpr 1 each border
|
|
1236
1332
|
resolves to 1px, so the group rendered 1px short of every control beside it (#018). Stretching
|
|
@@ -1259,7 +1355,7 @@ a { color: var(--color-primary); }
|
|
|
1259
1355
|
.fdy-input-group__btn:disabled:hover{background:var(--color-surface-2);color:var(--color-text-muted);}
|
|
1260
1356
|
/* Error state must win over the neutralizing rules above, promote to the wrapper. */
|
|
1261
1357
|
.fdy-input-group:has(.fdy-input--error),.fdy-input-group:has(.fdy-combo--error),.fdy-input-group:has([aria-invalid="true"]){border-color:var(--color-danger);}
|
|
1262
|
-
.fdy-input-group:has(.fdy-input--error):focus-within,.fdy-input-group:has(.fdy-combo--error):focus-within,.fdy-input-group:has([aria-invalid="true"]):focus-within{border-color:var(--color-danger);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px
|
|
1358
|
+
.fdy-input-group:has(.fdy-input--error):focus-within,.fdy-input-group:has(.fdy-combo--error):focus-within,.fdy-input-group:has([aria-invalid="true"]):focus-within{border-color:var(--color-danger);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px rgba(var(--color-danger-rgb),.26);}
|
|
1263
1359
|
|
|
1264
1360
|
/* Freeday. Field & Input */
|
|
1265
1361
|
.fdy-field{display:flex;flex-direction:column;gap:var(--space-2);max-width:22rem;}
|
|
@@ -1295,7 +1391,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1295
1391
|
.fdy-input::placeholder,.fdy-textarea::placeholder{color:var(--color-text-subtle);}
|
|
1296
1392
|
.fdy-textarea{height:auto;min-height:5.5rem;padding:var(--space-3);line-height:var(--leading-normal);resize:vertical;}
|
|
1297
1393
|
.fdy-input:hover,.fdy-textarea:hover{border-color:var(--color-text-muted);}
|
|
1298
|
-
.fdy-input:focus,.fdy-textarea:focus{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px
|
|
1394
|
+
.fdy-input:focus,.fdy-textarea:focus{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1299
1395
|
.fdy-input:disabled,.fdy-textarea:disabled,.fdy-input[aria-disabled="true"],.fdy-textarea[aria-disabled="true"]{opacity:.5;cursor:not-allowed;}
|
|
1300
1396
|
/* Read-only (#39): the value is real and may be read/copied, only not edited. Full contrast (unlike
|
|
1301
1397
|
:disabled which dims to placeholder-grey), muted surface + softened border so it still reads as
|
|
@@ -1312,7 +1408,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1312
1408
|
.fdy-input[type="number"]{appearance:textfield;-webkit-appearance:textfield;}
|
|
1313
1409
|
.fdy-input[type="number"]::-webkit-outer-spin-button,.fdy-input[type="number"]::-webkit-inner-spin-button{appearance:none;-webkit-appearance:none;margin:0;}
|
|
1314
1410
|
.fdy-input--error,.fdy-input[aria-invalid="true"],.fdy-textarea[aria-invalid="true"]{border-color:var(--color-danger);}
|
|
1315
|
-
.fdy-input--error:focus,.fdy-input[aria-invalid="true"]:focus,.fdy-textarea[aria-invalid="true"]:focus{border-color:var(--color-danger);box-shadow:0 0 0 3px
|
|
1411
|
+
.fdy-input--error:focus,.fdy-input[aria-invalid="true"]:focus,.fdy-textarea[aria-invalid="true"]:focus{border-color:var(--color-danger);box-shadow:0 0 0 3px rgba(var(--color-danger-rgb),.26);}
|
|
1316
1412
|
/* Required marker. The control already carries `required`, so the asterisk is decoration: the
|
|
1317
1413
|
`/ ""` is CSS alt text, the glyph is painted but exposes NOTHING to the accessibility tree, so a
|
|
1318
1414
|
screen reader does not read "star" after every label. That is stricter than a <span> an app has to
|
|
@@ -1378,7 +1474,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1378
1474
|
/* Focus is not hover. The enhancer moves real DOM focus (freeday-menu.js `.focus()`), so this is
|
|
1379
1475
|
the only thing a keyboard user has to go on, with the hover fill alone, arrowing through the
|
|
1380
1476
|
menu is invisible. Same ring as .fdy-nav__item, which got this right. Reported twice. */
|
|
1381
|
-
.fdy-menu__item:focus-visible{outline:none;background:var(--color-surface-3);box-shadow:0 0 0 2px
|
|
1477
|
+
.fdy-menu__item:focus-visible{outline:none;background:var(--color-surface-3);box-shadow:0 0 0 2px rgba(var(--color-primary-rgb),.45);}
|
|
1382
1478
|
.fdy-menu__item:disabled{opacity:.5;cursor:not-allowed;background:transparent;}
|
|
1383
1479
|
.fdy-menu__item--danger{color:var(--color-danger-strong);}
|
|
1384
1480
|
.fdy-menu__item svg{display:block;width:1rem;height:1rem;flex:none;}
|
|
@@ -1395,8 +1491,8 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1395
1491
|
.fdy-btn-split__toggle{padding:0 var(--space-2);margin-left:calc(var(--bw) * -1);border-top-left-radius:0;border-bottom-left-radius:0;}
|
|
1396
1492
|
/* Hairline divider between the halves (outranks the segment rule above). */
|
|
1397
1493
|
.fdy-btn-split > .fdy-btn-split__toggle{box-shadow:inset 0 1px 0 rgba(255,255,255,.26),inset 1px 0 0 rgba(0,0,0,.16);}
|
|
1398
|
-
.fdy-btn-split:hover{transform:translateY(-1px);box-shadow:0 6px 18px -2px
|
|
1399
|
-
.fdy-btn-split:active{transform:translateY(1px);box-shadow:0 1px 4px -1px
|
|
1494
|
+
.fdy-btn-split:hover{transform:translateY(-1px);box-shadow:0 6px 18px -2px rgba(var(--color-primary-rgb),.55);}
|
|
1495
|
+
.fdy-btn-split:active{transform:translateY(1px);box-shadow:0 1px 4px -1px rgba(var(--color-primary-rgb),.46);}
|
|
1400
1496
|
.fdy-btn-split__toggle:hover,.fdy-btn-split__toggle:focus-visible{z-index:1;}
|
|
1401
1497
|
.fdy-btn-split__toggle svg{display:block;width:1rem;height:1rem;}
|
|
1402
1498
|
|
|
@@ -1427,7 +1523,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1427
1523
|
.fdy-pagination__list{display:flex;align-items:center;gap:var(--space-1);list-style:none;margin:0;padding:0;}
|
|
1428
1524
|
.fdy-pagination__link{display:inline-flex;align-items:center;justify-content:center;min-width:2.25rem;height:2.25rem;padding:0 var(--space-2);border-radius:var(--radius-md);font-size:var(--text-sm);font-weight:var(--weight-medium);color:var(--color-text);background:transparent;border:var(--bw) solid transparent;text-decoration:none;cursor:pointer;transition:background var(--dur-fast) var(--ease-standard),border-color var(--dur-fast) var(--ease-standard);}
|
|
1429
1525
|
.fdy-pagination__link:hover{background:var(--color-surface-2);border-color:var(--color-border);}
|
|
1430
|
-
.fdy-pagination__link:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1526
|
+
.fdy-pagination__link:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1431
1527
|
.fdy-pagination__link[aria-current="page"]{background:var(--color-primary);color:var(--color-on-primary);}
|
|
1432
1528
|
.fdy-pagination__link[aria-disabled="true"],.fdy-pagination__link:disabled{opacity:.5;cursor:not-allowed;pointer-events:none;}
|
|
1433
1529
|
.fdy-pagination__ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:2.25rem;height:2.25rem;color:var(--color-text-subtle);}
|
|
@@ -1473,13 +1569,19 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1473
1569
|
.fdy-radio input::before{content:"";width:.55rem;height:.55rem;border-radius:50%;transform:scale(0);transition:transform var(--dur-fast) var(--ease-spring);box-shadow:inset 1rem 1rem var(--color-on-primary);}
|
|
1474
1570
|
.fdy-check input:checked,.fdy-radio input:checked{background:var(--color-primary);border-color:var(--color-primary);}
|
|
1475
1571
|
.fdy-check input:checked::before,.fdy-radio input:checked::before{transform:scale(1);}
|
|
1476
|
-
.fdy-check input:focus-visible,.fdy-radio input:focus-visible,.fdy-switch input:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1572
|
+
.fdy-check input:focus-visible,.fdy-radio input:focus-visible,.fdy-switch input:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1477
1573
|
.fdy-check input:disabled,.fdy-radio input:disabled,.fdy-switch input:disabled{opacity:.5;cursor:not-allowed;}
|
|
1478
1574
|
.fdy-check:has(input:disabled),.fdy-radio:has(input:disabled),.fdy-switch:has(input:disabled){cursor:not-allowed;}
|
|
1479
1575
|
.fdy-switch input{appearance:none;-webkit-appearance:none;flex:none;position:relative;width:var(--control-switch-w);height:var(--control-switch-h);margin:0;border-radius:var(--radius-full);background:var(--color-control-border);cursor:pointer;transition:background var(--dur-base) var(--ease-standard);}
|
|
1480
1576
|
.fdy-switch input::before{content:"";position:absolute;top:2px;left:2px;width:calc(var(--control-switch-h) - 4px);height:calc(var(--control-switch-h) - 4px);border-radius:50%;background:var(--color-switch-thumb);box-shadow:var(--shadow-1);transition:transform var(--dur-base) var(--ease-spring);}
|
|
1481
1577
|
.fdy-switch input:checked{background:var(--color-primary);}
|
|
1482
1578
|
.fdy-switch input:checked::before{transform:translateX(calc(var(--control-switch-w) - var(--control-switch-h)));}
|
|
1579
|
+
/* State hint (#068): one line saying what the CURRENT state means, never "on means X, off means Y",
|
|
1580
|
+
which leaves the reader to work out which half applies. The control's aria-describedby points at
|
|
1581
|
+
the .fdy-help WRAPPING both lines: a hidden child of a referenced node is skipped, so a screen
|
|
1582
|
+
reader hears only the line on screen. Point it at the two children and both are read. */
|
|
1583
|
+
.fdy-field:has(:is(.fdy-switch,.fdy-check) input:checked) [data-fdy-when="off"],
|
|
1584
|
+
.fdy-field:not(:has(:is(.fdy-switch,.fdy-check) input:checked)) [data-fdy-when="on"]{display:none;}
|
|
1483
1585
|
|
|
1484
1586
|
/* Standalone checkbox (e.g. table row/select-all), supports :indeterminate */
|
|
1485
1587
|
.fdy-checkbox{appearance:none;-webkit-appearance:none;flex:none;width:var(--control-box);height:var(--control-box);margin:0;border:1.5px solid var(--color-control-border);border-radius:var(--radius-sm);background:var(--color-surface);box-shadow:inset 0 1px 2px var(--color-shadow-inset);cursor:pointer;display:grid;place-content:center;transition:background var(--dur-fast) var(--ease-standard),border-color var(--dur-fast) var(--ease-standard);}
|
|
@@ -1487,11 +1589,11 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1487
1589
|
.fdy-checkbox:checked,.fdy-checkbox:indeterminate{background:var(--color-primary);border-color:var(--color-primary);}
|
|
1488
1590
|
.fdy-checkbox:checked::before{transform:scale(1);}
|
|
1489
1591
|
.fdy-checkbox:indeterminate::before{width:.6rem;height:2px;transform:scale(1);clip-path:none;box-shadow:none;background:var(--color-on-primary);}
|
|
1490
|
-
.fdy-checkbox:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1592
|
+
.fdy-checkbox:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1491
1593
|
.fdy-checkbox:disabled{opacity:.5;cursor:not-allowed;}
|
|
1492
1594
|
|
|
1493
1595
|
/* Freeday. Skeleton */
|
|
1494
|
-
.fdy-skeleton{display:block;border-radius:var(--radius-sm);background:var(--color-surface-3);background-image:linear-gradient(90deg,transparent,
|
|
1596
|
+
.fdy-skeleton{display:block;border-radius:var(--radius-sm);background:var(--color-surface-3);background-image:linear-gradient(90deg,transparent,rgba(var(--color-surface-rgb),.6),transparent);background-size:200% 100%;background-repeat:no-repeat;animation:fdy-skeleton 1.4s ease-in-out infinite;}
|
|
1495
1597
|
.fdy-skeleton--text{height:.8rem;margin:.3rem 0;}
|
|
1496
1598
|
.fdy-skeleton--title{height:1.2rem;width:40%;}
|
|
1497
1599
|
.fdy-skeleton--circle{border-radius:var(--radius-full);}
|
|
@@ -1531,6 +1633,13 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1531
1633
|
.fdy-state__text{font-size:var(--text-sm);color:var(--color-text-muted);max-width:24rem;line-height:var(--leading-normal);}
|
|
1532
1634
|
.fdy-state__actions{margin-top:var(--space-2);display:flex;gap:var(--space-2);flex-wrap:wrap;justify-content:center;}
|
|
1533
1635
|
.fdy-state--danger .fdy-state__icon{color:var(--color-danger-strong);}
|
|
1636
|
+
/* Compact (#069): the same state inside a small card, one line of icon and text instead of a
|
|
1637
|
+
page-sized block. Danger matters most here: a widget that renders zero for a failed request
|
|
1638
|
+
reads as "nothing to do", the opposite of what happened. */
|
|
1639
|
+
.fdy-state--compact{flex-direction:row;align-items:flex-start;text-align:left;gap:var(--space-2);padding:var(--space-2) 0;}
|
|
1640
|
+
.fdy-state--compact .fdy-state__icon{width:1rem;height:1rem;flex:none;}
|
|
1641
|
+
.fdy-state--compact .fdy-state__text{font-size:var(--text-xs);max-width:none;}
|
|
1642
|
+
.fdy-state--compact .fdy-state__actions{margin:0 0 0 auto;}
|
|
1534
1643
|
|
|
1535
1644
|
/* Freeday. Stepper / Wizard (progress header + optional panels).
|
|
1536
1645
|
* Enhanced by freeday-stepper.js for prev/next navigation. */
|
|
@@ -1565,7 +1674,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1565
1674
|
.fdy-stepper[aria-busy="true"]{opacity:.72;}
|
|
1566
1675
|
.fdy-step.is-active .fdy-step__label{color:var(--color-text);font-weight:var(--weight-semibold);}
|
|
1567
1676
|
.fdy-step__btn:focus-visible{outline:none;}
|
|
1568
|
-
.fdy-step__btn:focus-visible .fdy-step__marker{box-shadow:0 0 0 3px
|
|
1677
|
+
.fdy-step__btn:focus-visible .fdy-step__marker{box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.3);}
|
|
1569
1678
|
|
|
1570
1679
|
.fdy-step-panels{margin-top:var(--space-5);}
|
|
1571
1680
|
.fdy-step-nav{display:flex;justify-content:space-between;gap:var(--space-2);margin-top:var(--space-5);}
|
|
@@ -1586,9 +1695,23 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1586
1695
|
invisible on every second row. The tint is HALF a surface step rather than --color-surface-2
|
|
1587
1696
|
itself, for the same reason: hover paints the full step, so the two must not be the same colour.
|
|
1588
1697
|
Exposed as a Tier-3 token through the var() FALLBACK, never as a declaration — a custom property
|
|
1589
|
-
set here would outrank a host's own :root override.
|
|
1590
|
-
|
|
1591
|
-
.
|
|
1698
|
+
set here would outrank a host's own :root override.
|
|
1699
|
+
The tint arrives as --color-surface-stripe, already flattened, rather than as a color-mix() of
|
|
1700
|
+
two surfaces. A custom property cannot carry color-mix(): the `background` that finally reads it
|
|
1701
|
+
contains var(), so on Safari <= 16.1 it failed at computed-value time and the stripe vanished,
|
|
1702
|
+
and a preceding declaration is never consulted in that path. The token is also OPAQUE on
|
|
1703
|
+
purpose, which the frozen column below depends on. */
|
|
1704
|
+
/* The resting colour is also published as --_fdy-row-rest, so a row that must not answer the
|
|
1705
|
+
pointer can hover back to exactly what it was (see --hover-actionable). */
|
|
1706
|
+
.fdy-table--striped tbody tr:nth-child(even){--_fdy-row-rest:var(--fdy-table-stripe,var(--color-surface-stripe));background:var(--_fdy-row-rest);}
|
|
1707
|
+
.fdy-table tbody tr:hover{background:var(--_fdy-row-hover,var(--color-surface-2));}
|
|
1708
|
+
/* Opt-in (#064): only a row that DOES something answers the pointer. A tint on a row with no click
|
|
1709
|
+
handler promises a target that is not there: people click the row, nothing happens, and the
|
|
1710
|
+
button they had to aim at was elsewhere in it. Striping, not hover, is what keeps the eye on a
|
|
1711
|
+
line. The inert row's hover resolves to its own resting colour, so a stripe survives it; a frozen
|
|
1712
|
+
cell falls back to its opaque surface, because it scrolls over its neighbours. */
|
|
1713
|
+
.fdy-table--hover-actionable tbody tr:not(.fdy-table__row--activatable){--_fdy-row-hover:var(--_fdy-row-rest,transparent);}
|
|
1714
|
+
.fdy-table--hover-actionable tbody tr:not(.fdy-table__row--activatable) td.fdy-table__freeze{--_fdy-row-hover:var(--_fdy-row-rest,var(--color-surface));}
|
|
1592
1715
|
/* Monospace data, ids, codes, IPs, timestamps. Alignment-neutral so it works in any cell
|
|
1593
1716
|
or inline (`<span class="fdy-mono">`), not just numeric columns. */
|
|
1594
1717
|
.fdy-mono{font-family:var(--font-mono);font-variant-numeric:tabular-nums;}
|
|
@@ -1597,20 +1720,20 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1597
1720
|
.fdy-table__num{text-align:right;font-variant-numeric:tabular-nums;font-family:var(--font-mono);}
|
|
1598
1721
|
/* Loading / empty state cell (FdyTable spans it across all columns). */
|
|
1599
1722
|
.fdy-table__state{text-align:center;color:var(--color-text-muted);padding:var(--space-6) var(--space-4);}
|
|
1600
|
-
/* Activatable row (FdyTable rowActivatable): pointer + keyboard focus ring. The hover tint
|
|
1601
|
-
|
|
1723
|
+
/* Activatable row (FdyTable rowActivatable): pointer + keyboard focus ring. The hover tint comes from
|
|
1724
|
+
the base `.fdy-table tbody tr:hover` rule, which --hover-actionable keeps for these rows only. */
|
|
1602
1725
|
.fdy-table__row--activatable{cursor:pointer;}
|
|
1603
1726
|
.fdy-table__row--activatable:focus-visible{outline:2px solid var(--color-primary);outline-offset:-2px;}
|
|
1604
1727
|
/* Expandable detail row (FdyTable row-detail slot): a muted panel under its row, no hover tint. */
|
|
1605
1728
|
.fdy-table__detailrow>td,.fdy-table__detailrow:hover>td{background:var(--color-surface-2);}
|
|
1606
1729
|
.fdy-table th[aria-sort]{cursor:pointer;}
|
|
1607
|
-
.fdy-table th[aria-sort="ascending"]::after{content:" ↑";color:var(--color-primary);}
|
|
1608
|
-
.fdy-table th[aria-sort="descending"]::after{content:" ↓";color:var(--color-primary);}
|
|
1730
|
+
.fdy-table th[aria-sort="ascending"]::after{content:" ↑";color:var(--color-primary-strong);}
|
|
1731
|
+
.fdy-table th[aria-sort="descending"]::after{content:" ↓";color:var(--color-primary-strong);}
|
|
1609
1732
|
|
|
1610
1733
|
/* Sortable header button (accessible click target inside th) */
|
|
1611
1734
|
.fdy-table__sortbtn{appearance:none;border:0;background:transparent;font:inherit;color:inherit;text-transform:inherit;letter-spacing:inherit;font-weight:inherit;cursor:pointer;padding:0;}
|
|
1612
1735
|
.fdy-table__sortbtn:hover{color:var(--color-text);}
|
|
1613
|
-
.fdy-table__sortbtn:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:0 0 0 3px
|
|
1736
|
+
.fdy-table__sortbtn:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1614
1737
|
|
|
1615
1738
|
/* Selection column + selected row */
|
|
1616
1739
|
.fdy-table__selcol{width:1px;white-space:nowrap;}
|
|
@@ -1657,8 +1780,8 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1657
1780
|
stripe — and deliberately WITHOUT `.fdy-table--sticky` in the selector, which would push this to
|
|
1658
1781
|
(0,4,3) and beat the hover rule below. At (0,3,3) it ties, and the later rule wins, so a hovered
|
|
1659
1782
|
row still bands unbroken across the freeze line. */
|
|
1660
|
-
.fdy-table--striped tbody tr:nth-child(even) td.fdy-table__freeze{background:var(--fdy-table-stripe,
|
|
1661
|
-
.fdy-table--sticky tbody tr:hover td.fdy-table__freeze{background:var(--color-surface-2);}
|
|
1783
|
+
.fdy-table--striped tbody tr:nth-child(even) td.fdy-table__freeze{background:var(--fdy-table-stripe,var(--color-surface-stripe));}
|
|
1784
|
+
.fdy-table--sticky tbody tr:hover td.fdy-table__freeze{background:var(--_fdy-row-hover,var(--color-surface-2));}
|
|
1662
1785
|
/* A frozen header cell is stuck on both axes wherever the head is frozen too, so
|
|
1663
1786
|
it has to outrank both. */
|
|
1664
1787
|
.fdy-table--sticky thead .fdy-table__freeze{z-index:3;}
|
|
@@ -1694,7 +1817,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1694
1817
|
.fdy-table__filterwrap{display:inline-flex;align-items:center;vertical-align:middle;}
|
|
1695
1818
|
.fdy-table__filterbtn{appearance:none;display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin-left:var(--space-1);padding:0;vertical-align:middle;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-subtle);cursor:pointer;}
|
|
1696
1819
|
.fdy-table__filterbtn:hover{background:var(--color-surface-3);color:var(--color-text);}
|
|
1697
|
-
.fdy-table__filterbtn:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1820
|
+
.fdy-table__filterbtn:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1698
1821
|
.fdy-table__filterbtn.is-active{color:var(--color-primary-strong);}
|
|
1699
1822
|
.fdy-table__filterbtn svg{width:.85rem;height:.85rem;}
|
|
1700
1823
|
|
|
@@ -1750,7 +1873,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1750
1873
|
a panel per tab) for in-page tabs; use these classes on plain links for routed ones, and
|
|
1751
1874
|
`.fdy-nav--horizontal` for an application's PRIMARY navigation. */
|
|
1752
1875
|
.fdy-tabs__tab[aria-selected="true"],.fdy-tabs__tab[aria-current="page"]{color:var(--color-primary-strong);border-bottom-color:var(--color-primary);}
|
|
1753
|
-
.fdy-tabs__tab:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:0 0 0 3px
|
|
1876
|
+
.fdy-tabs__tab:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1754
1877
|
.fdy-tabs__panel{padding:var(--space-5) 0;}
|
|
1755
1878
|
.fdy-tabs__panel[hidden]{display:none;}
|
|
1756
1879
|
/* Reveal the newly-shown panel on tab switch (fade + rise), reduced-motion gated. */
|
|
@@ -1775,10 +1898,10 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1775
1898
|
.fdy-timepicker{position:relative;display:inline-block;width:100%;max-width:11rem;}
|
|
1776
1899
|
.fdy-timepicker__trigger{display:inline-flex;align-items:center;gap:var(--space-2);width:100%;height:var(--control-h);padding:0 var(--space-3);text-align:left;cursor:pointer;font-family:var(--font-body);font-size:var(--text-sm);color:var(--color-text);background:var(--color-surface);border:1.5px solid var(--color-control-border);border-radius:var(--radius-md);box-shadow:inset 0 1px 2px rgba(16,14,30,.06);transition:border-color var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard);}
|
|
1777
1900
|
.fdy-timepicker__trigger:hover{border-color:var(--color-text-muted);}
|
|
1778
|
-
.fdy-timepicker__trigger:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px
|
|
1779
|
-
.fdy-timepicker__trigger.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px
|
|
1901
|
+
.fdy-timepicker__trigger:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1902
|
+
.fdy-timepicker__trigger.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1780
1903
|
.fdy-timepicker--error .fdy-timepicker__trigger,.fdy-timepicker__trigger[aria-invalid="true"]{border-color:var(--color-danger);}
|
|
1781
|
-
.fdy-timepicker--error .fdy-timepicker__trigger:focus-visible,.fdy-timepicker--error .fdy-timepicker__trigger.is-open,.fdy-timepicker__trigger[aria-invalid="true"]:focus-visible{border-color:var(--color-danger);box-shadow:0 0 0 3px
|
|
1904
|
+
.fdy-timepicker--error .fdy-timepicker__trigger:focus-visible,.fdy-timepicker--error .fdy-timepicker__trigger.is-open,.fdy-timepicker__trigger[aria-invalid="true"]:focus-visible{border-color:var(--color-danger);box-shadow:0 0 0 3px rgba(var(--color-danger-rgb),.26);}
|
|
1782
1905
|
.fdy-timepicker__trigger:disabled,.fdy-timepicker__trigger[aria-disabled="true"]{opacity:.5;cursor:not-allowed;}
|
|
1783
1906
|
.fdy-timepicker__value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums;}
|
|
1784
1907
|
.fdy-timepicker__value--placeholder{color:var(--color-text-subtle);}
|
|
@@ -1818,7 +1941,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1818
1941
|
.fdy-toast__text{opacity:.88;line-height:var(--leading-normal);}
|
|
1819
1942
|
.fdy-toast__close{flex:none;border:0;background:transparent;color:var(--color-inverse-text);opacity:.7;cursor:pointer;font-size:var(--text-lg);line-height:1;padding:0 var(--space-1);border-radius:var(--radius-sm);}
|
|
1820
1943
|
.fdy-toast__close:hover{opacity:1;}
|
|
1821
|
-
.fdy-toast__close:focus-visible{outline:none;opacity:1;box-shadow:0 0 0 3px
|
|
1944
|
+
.fdy-toast__close:focus-visible{outline:none;opacity:1;box-shadow:0 0 0 3px rgba(var(--color-inverse-text-rgb),.4);}
|
|
1822
1945
|
.fdy-toast.is-leaving{opacity:0;transform:translateX(16px);transition:opacity var(--dur-base) var(--ease-standard),transform var(--dur-base) var(--ease-standard);}
|
|
1823
1946
|
@media (prefers-reduced-motion:no-preference){.fdy-toast{animation:fdy-toast-in var(--dur-base) var(--ease-spring);}}
|
|
1824
1947
|
@keyframes fdy-toast-in{from{opacity:0;transform:translateY(14px);}to{opacity:1;transform:none;}}
|
|
@@ -1838,7 +1961,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1838
1961
|
.fdy-tree__branch > summary{list-style:none;cursor:pointer;}
|
|
1839
1962
|
.fdy-tree__branch > summary::-webkit-details-marker{display:none;}
|
|
1840
1963
|
.fdy-tree__branch > summary:hover,.fdy-tree__leaf:hover{background:var(--color-surface-2);}
|
|
1841
|
-
.fdy-tree__branch > summary:focus-visible{outline:none;box-shadow:inset 0 0 0 2px
|
|
1964
|
+
.fdy-tree__branch > summary:focus-visible{outline:none;box-shadow:inset 0 0 0 2px rgba(var(--color-primary-rgb),.45);}
|
|
1842
1965
|
.fdy-tree__chevron{flex:none;width:.9rem;height:.9rem;color:var(--color-text-subtle);transition:transform var(--dur-fast) var(--ease-standard);}
|
|
1843
1966
|
.fdy-tree__branch[open] > summary .fdy-tree__chevron{transform:rotate(90deg);}
|
|
1844
1967
|
.fdy-tree__icon{flex:none;width:1rem;height:1rem;color:var(--color-text-muted);}
|