@cahyo-dimas/freeday 3.6.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.
@@ -2,7 +2,7 @@
2
2
  .fdy-pagination__list{display:flex;align-items:center;gap:var(--space-1);list-style:none;margin:0;padding:0;}
3
3
  .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);}
4
4
  .fdy-pagination__link:hover{background:var(--color-surface-2);border-color:var(--color-border);}
5
- .fdy-pagination__link:focus-visible{outline:none;box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary) 26%,transparent);}
5
+ .fdy-pagination__link:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
6
6
  .fdy-pagination__link[aria-current="page"]{background:var(--color-primary);color:var(--color-on-primary);}
7
7
  .fdy-pagination__link[aria-disabled="true"],.fdy-pagination__link:disabled{opacity:.5;cursor:not-allowed;pointer-events:none;}
8
8
  .fdy-pagination__ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:2.25rem;height:2.25rem;color:var(--color-text-subtle);}
@@ -14,7 +14,7 @@
14
14
  .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);}
15
15
  .fdy-check input:checked,.fdy-radio input:checked{background:var(--color-primary);border-color:var(--color-primary);}
16
16
  .fdy-check input:checked::before,.fdy-radio input:checked::before{transform:scale(1);}
17
- .fdy-check input:focus-visible,.fdy-radio input:focus-visible,.fdy-switch input:focus-visible{outline:none;box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary) 26%,transparent);}
17
+ .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);}
18
18
  .fdy-check input:disabled,.fdy-radio input:disabled,.fdy-switch input:disabled{opacity:.5;cursor:not-allowed;}
19
19
  .fdy-check:has(input:disabled),.fdy-radio:has(input:disabled),.fdy-switch:has(input:disabled){cursor:not-allowed;}
20
20
  .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);}
@@ -34,5 +34,5 @@
34
34
  .fdy-checkbox:checked,.fdy-checkbox:indeterminate{background:var(--color-primary);border-color:var(--color-primary);}
35
35
  .fdy-checkbox:checked::before{transform:scale(1);}
36
36
  .fdy-checkbox:indeterminate::before{width:.6rem;height:2px;transform:scale(1);clip-path:none;box-shadow:none;background:var(--color-on-primary);}
37
- .fdy-checkbox:focus-visible{outline:none;box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary) 26%,transparent);}
37
+ .fdy-checkbox:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
38
38
  .fdy-checkbox:disabled{opacity:.5;cursor:not-allowed;}
@@ -1,5 +1,5 @@
1
1
  /* Freeday. Skeleton */
2
- .fdy-skeleton{display:block;border-radius:var(--radius-sm);background:var(--color-surface-3);background-image:linear-gradient(90deg,transparent,color-mix(in srgb,var(--color-surface) 60%,transparent),transparent);background-size:200% 100%;background-repeat:no-repeat;animation:fdy-skeleton 1.4s ease-in-out infinite;}
2
+ .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;}
3
3
  .fdy-skeleton--text{height:.8rem;margin:.3rem 0;}
4
4
  .fdy-skeleton--title{height:1.2rem;width:40%;}
5
5
  .fdy-skeleton--circle{border-radius:var(--radius-full);}
@@ -31,7 +31,7 @@
31
31
  .fdy-stepper[aria-busy="true"]{opacity:.72;}
32
32
  .fdy-step.is-active .fdy-step__label{color:var(--color-text);font-weight:var(--weight-semibold);}
33
33
  .fdy-step__btn:focus-visible{outline:none;}
34
- .fdy-step__btn:focus-visible .fdy-step__marker{box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary) 30%,transparent);}
34
+ .fdy-step__btn:focus-visible .fdy-step__marker{box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.3);}
35
35
 
36
36
  .fdy-step-panels{margin-top:var(--space-5);}
37
37
  .fdy-step-nav{display:flex;justify-content:space-between;gap:var(--space-2);margin-top:var(--space-5);}
@@ -14,10 +14,15 @@
14
14
  invisible on every second row. The tint is HALF a surface step rather than --color-surface-2
15
15
  itself, for the same reason: hover paints the full step, so the two must not be the same colour.
16
16
  Exposed as a Tier-3 token through the var() FALLBACK, never as a declaration — a custom property
17
- set here would outrank a host's own :root override. */
17
+ set here would outrank a host's own :root override.
18
+ The tint arrives as --color-surface-stripe, already flattened, rather than as a color-mix() of
19
+ two surfaces. A custom property cannot carry color-mix(): the `background` that finally reads it
20
+ contains var(), so on Safari <= 16.1 it failed at computed-value time and the stripe vanished,
21
+ and a preceding declaration is never consulted in that path. The token is also OPAQUE on
22
+ purpose, which the frozen column below depends on. */
18
23
  /* The resting colour is also published as --_fdy-row-rest, so a row that must not answer the
19
24
  pointer can hover back to exactly what it was (see --hover-actionable). */
20
- .fdy-table--striped tbody tr:nth-child(even){--_fdy-row-rest:var(--fdy-table-stripe,color-mix(in srgb,var(--color-surface-2) 55%,var(--color-surface)));background:var(--_fdy-row-rest);}
25
+ .fdy-table--striped tbody tr:nth-child(even){--_fdy-row-rest:var(--fdy-table-stripe,var(--color-surface-stripe));background:var(--_fdy-row-rest);}
21
26
  .fdy-table tbody tr:hover{background:var(--_fdy-row-hover,var(--color-surface-2));}
22
27
  /* Opt-in (#064): only a row that DOES something answers the pointer. A tint on a row with no click
23
28
  handler promises a target that is not there: people click the row, nothing happens, and the
@@ -41,13 +46,13 @@
41
46
  /* Expandable detail row (FdyTable row-detail slot): a muted panel under its row, no hover tint. */
42
47
  .fdy-table__detailrow>td,.fdy-table__detailrow:hover>td{background:var(--color-surface-2);}
43
48
  .fdy-table th[aria-sort]{cursor:pointer;}
44
- .fdy-table th[aria-sort="ascending"]::after{content:" ↑";color:var(--color-primary);}
45
- .fdy-table th[aria-sort="descending"]::after{content:" ↓";color:var(--color-primary);}
49
+ .fdy-table th[aria-sort="ascending"]::after{content:" ↑";color:var(--color-primary-strong);}
50
+ .fdy-table th[aria-sort="descending"]::after{content:" ↓";color:var(--color-primary-strong);}
46
51
 
47
52
  /* Sortable header button (accessible click target inside th) */
48
53
  .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;}
49
54
  .fdy-table__sortbtn:hover{color:var(--color-text);}
50
- .fdy-table__sortbtn:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary) 26%,transparent);}
55
+ .fdy-table__sortbtn:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
51
56
 
52
57
  /* Selection column + selected row */
53
58
  .fdy-table__selcol{width:1px;white-space:nowrap;}
@@ -94,7 +99,7 @@
94
99
  stripe — and deliberately WITHOUT `.fdy-table--sticky` in the selector, which would push this to
95
100
  (0,4,3) and beat the hover rule below. At (0,3,3) it ties, and the later rule wins, so a hovered
96
101
  row still bands unbroken across the freeze line. */
97
- .fdy-table--striped tbody tr:nth-child(even) td.fdy-table__freeze{background:var(--fdy-table-stripe,color-mix(in srgb,var(--color-surface-2) 55%,var(--color-surface)));}
102
+ .fdy-table--striped tbody tr:nth-child(even) td.fdy-table__freeze{background:var(--fdy-table-stripe,var(--color-surface-stripe));}
98
103
  .fdy-table--sticky tbody tr:hover td.fdy-table__freeze{background:var(--_fdy-row-hover,var(--color-surface-2));}
99
104
  /* A frozen header cell is stuck on both axes wherever the head is frozen too, so
100
105
  it has to outrank both. */
@@ -131,7 +136,7 @@
131
136
  .fdy-table__filterwrap{display:inline-flex;align-items:center;vertical-align:middle;}
132
137
  .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;}
133
138
  .fdy-table__filterbtn:hover{background:var(--color-surface-3);color:var(--color-text);}
134
- .fdy-table__filterbtn:focus-visible{outline:none;box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary) 26%,transparent);}
139
+ .fdy-table__filterbtn:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
135
140
  .fdy-table__filterbtn.is-active{color:var(--color-primary-strong);}
136
141
  .fdy-table__filterbtn svg{width:.85rem;height:.85rem;}
137
142
 
@@ -27,7 +27,7 @@
27
27
  a panel per tab) for in-page tabs; use these classes on plain links for routed ones, and
28
28
  `.fdy-nav--horizontal` for an application's PRIMARY navigation. */
29
29
  .fdy-tabs__tab[aria-selected="true"],.fdy-tabs__tab[aria-current="page"]{color:var(--color-primary-strong);border-bottom-color:var(--color-primary);}
30
- .fdy-tabs__tab:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary) 26%,transparent);}
30
+ .fdy-tabs__tab:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
31
31
  .fdy-tabs__panel{padding:var(--space-5) 0;}
32
32
  .fdy-tabs__panel[hidden]{display:none;}
33
33
  /* Reveal the newly-shown panel on tab switch (fade + rise), reduced-motion gated. */
@@ -4,10 +4,10 @@
4
4
  .fdy-timepicker{position:relative;display:inline-block;width:100%;max-width:11rem;}
5
5
  .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);}
6
6
  .fdy-timepicker__trigger:hover{border-color:var(--color-text-muted);}
7
- .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 color-mix(in srgb,var(--color-primary) 26%,transparent);}
8
- .fdy-timepicker__trigger.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary) 26%,transparent);}
7
+ .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);}
8
+ .fdy-timepicker__trigger.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
9
9
  .fdy-timepicker--error .fdy-timepicker__trigger,.fdy-timepicker__trigger[aria-invalid="true"]{border-color:var(--color-danger);}
10
- .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 color-mix(in srgb,var(--color-danger) 26%,transparent);}
10
+ .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);}
11
11
  .fdy-timepicker__trigger:disabled,.fdy-timepicker__trigger[aria-disabled="true"]{opacity:.5;cursor:not-allowed;}
12
12
  .fdy-timepicker__value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums;}
13
13
  .fdy-timepicker__value--placeholder{color:var(--color-text-subtle);}
@@ -23,7 +23,7 @@
23
23
  .fdy-toast__text{opacity:.88;line-height:var(--leading-normal);}
24
24
  .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);}
25
25
  .fdy-toast__close:hover{opacity:1;}
26
- .fdy-toast__close:focus-visible{outline:none;opacity:1;box-shadow:0 0 0 3px color-mix(in srgb,var(--color-inverse-text) 40%,transparent);}
26
+ .fdy-toast__close:focus-visible{outline:none;opacity:1;box-shadow:0 0 0 3px rgba(var(--color-inverse-text-rgb),.4);}
27
27
  .fdy-toast.is-leaving{opacity:0;transform:translateX(16px);transition:opacity var(--dur-base) var(--ease-standard),transform var(--dur-base) var(--ease-standard);}
28
28
  @media (prefers-reduced-motion:no-preference){.fdy-toast{animation:fdy-toast-in var(--dur-base) var(--ease-spring);}}
29
29
  @keyframes fdy-toast-in{from{opacity:0;transform:translateY(14px);}to{opacity:1;transform:none;}}
@@ -6,7 +6,7 @@
6
6
  .fdy-tree__branch > summary{list-style:none;cursor:pointer;}
7
7
  .fdy-tree__branch > summary::-webkit-details-marker{display:none;}
8
8
  .fdy-tree__branch > summary:hover,.fdy-tree__leaf:hover{background:var(--color-surface-2);}
9
- .fdy-tree__branch > summary:focus-visible{outline:none;box-shadow:inset 0 0 0 2px color-mix(in srgb,var(--color-primary) 45%,transparent);}
9
+ .fdy-tree__branch > summary:focus-visible{outline:none;box-shadow:inset 0 0 0 2px rgba(var(--color-primary-rgb),.45);}
10
10
  .fdy-tree__chevron{flex:none;width:.9rem;height:.9rem;color:var(--color-text-subtle);transition:transform var(--dur-fast) var(--ease-standard);}
11
11
  .fdy-tree__branch[open] > summary .fdy-tree__chevron{transform:rotate(90deg);}
12
12
  .fdy-tree__icon{flex:none;width:1rem;height:1rem;color:var(--color-text-muted);}
@@ -105,8 +105,9 @@
105
105
  "primary-hover": { "$value": "{primary.700}", "$dark": "{primary.400}" },
106
106
  "primary-active": { "$value": "{primary.800}", "$dark": "{primary.300}" },
107
107
  "on-primary": { "$value": "{slate.0}", "$dark": "{slate.0}" },
108
- "primary-soft": { "$value": "{primary.50}", "$dark": "color-mix(in srgb, {primary.600} 20%, transparent)" },
109
- "primary-border": { "$value": "{primary.100}", "$dark": "color-mix(in srgb, {primary.400} 28%, transparent)" },
108
+ "_comment_primary_alpha": { "$value": "A custom property can NEVER hold color-mix(): the declaration that finally uses it contains var(), so it is assumed valid at parse time and only fails at computed-value time, where the property drops to its INITIAL value instead of to a preceding fallback. There is no earlier line to catch it and @supports cannot reach inside a var() chain. Both of these said color-mix() until v3.7.0, which is why a dark-theme chip on Safari <= 16.1 lost its wash entirely. rgba() over a channel triple is the same colour, stated statically." },
109
+ "primary-soft": { "$value": "{primary.50}", "$dark": "rgba({primary.600.rgb}, .2)" },
110
+ "primary-border": { "$value": "{primary.100}", "$dark": "rgba({primary.400.rgb}, .28)" },
110
111
 
111
112
  "accent": { "$value": "{sky.600}", "$dark": "{sky.400}" },
112
113
  "accent-hover": { "$value": "{sky.700}", "$dark": "{sky.300}" },
@@ -117,6 +118,7 @@
117
118
  "surface": { "$value": "{slate.0}", "$dark": "{slate.950}" },
118
119
  "surface-2": { "$value": "{slate.50}", "$dark": "{slate.900}" },
119
120
  "surface-3": { "$value": "{slate.100}", "$dark": "{slate.800}" },
121
+ "surface-stripe": { "$comment": "The zebra tint: 55% of --color-surface-2 over --color-surface, flattened. OPAQUE on purpose, and that is the whole reason it is a token rather than a mix written in the table: a frozen column paints this and scrolls over its neighbours, so a translucent stripe would show the rows travelling underneath it. Both values are MEASURED against the mix they replace (rgb(251,251,252) light, rgb(19,23,33) dark, identical to the byte) — see test/color-mix.test.mjs.", "$value": "#fbfbfc", "$dark": "#131721" },
120
122
  "surface-raised": { "$comment": "How transparent glass may be is decided by the CONTRAST GATE, not by taste: below .79 (light) / .88 (dark) the muted ink and primary-strong stop clearing 4.5:1 once the panel is composited over an arbitrary ground. Measured, and asserted in test/contrast.test.mjs. The frost people actually see comes from --surface-filter's blur, not from the alpha.", "$value": "{color.surface}", "$dark": "{color.surface}", "$glass": "rgba(255,255,255,.82)", "$glassDark": "rgba(23,27,38,.90)" },
121
123
  "scrim": { "$value": "rgba(10,12,25,.5)", "$comment": "Overlay dim. Deliberately the SAME in both themes: a scrim darkens whatever sits behind it, so it does not flip with the palette. The literal matches the modal/drawer ::backdrop, which states it literally because ::backdrop does not inherit a custom property in every engine." },
122
124
 
@@ -140,11 +142,25 @@
140
142
  "danger": { "$value": "{red.600}", "$dark": "{red.400}" }, "danger-soft": { "$value": "{red.100}", "$dark": "rgba(248,113,113,.18)" },
141
143
  "info": { "$value": "{blue.600}", "$dark": "{blue.400}" }, "info-soft": { "$value": "{blue.100}", "$dark": "rgba(96,165,250,.18)" },
142
144
 
145
+ "_comment_danger_border": { "$value": "The edge of a row that failed, 40% of --color-danger over --color-border: enough to read as wrong from across the list without the full-strength outline that makes one bad upload shout louder than the dialog around it. Computed at build time (see tokens/build.mjs) because it blends two ROLES, which no channel triple can express — written in the component it was the one non-tone color-mix() left, and like all of them it carried var(), so on Safari <= 16.1 border-color dropped to its initial currentColor and the row drew a black box." },
146
+ "danger-border": { "$value": "color-mix(in srgb, {color.danger} 40%, {color.border})" },
147
+
143
148
  "primary-strong": { "$value": "{primary.700}", "$dark": "{primary.300}" },
144
149
  "success-strong": { "$value": "{green.800}", "$dark": "{green.400}" },
145
150
  "warning-strong": { "$value": "{amber.800}", "$dark": "{amber.400}" },
146
151
  "danger-strong": { "$value": "{red.700}", "$dark": "{red.300}" },
147
- "info-strong": { "$value": "{blue.700}", "$dark": "{blue.300}" }
152
+ "info-strong": { "$value": "{blue.700}", "$dark": "{blue.300}" },
153
+
154
+ "_comment_rgb": { "$value": "Channel triples, the kit's way of putting an alpha on a role. `rgba(var(--color-primary-rgb), .26)` is exactly `color-mix(in srgb, var(--color-primary) 26%, transparent)` and works back to Safari 9; the mix form does not survive Safari <= 16.1, and because it carries var() it fails at computed-value time, where a preceding fallback declaration is never consulted. Each triple MUST stay the channels of the role it is named after, in every theme and every palette; test/color-mix.test.mjs asserts exactly that, scope by scope." },
155
+ "primary-rgb": { "$value": "{primary.600.rgb}", "$dark": "{primary.500.rgb}" },
156
+ "on-primary-rgb": { "$value": "{slate.0.rgb}" },
157
+ "danger-rgb": { "$value": "{red.600.rgb}", "$dark": "{red.400.rgb}" },
158
+ "danger-btn-rgb": { "$value": "{red.600.rgb}" },
159
+ "success-rgb": { "$value": "{green.600.rgb}", "$dark": "{green.500.rgb}" },
160
+ "warning-rgb": { "$comment": "The one triple written out rather than referenced: --color-warning's light value is itself a literal (#c2740a, a darkened amber with no ramp step of its own), so there is no reference to follow. The drift that invites is what the per-scope assertion in test/color-mix.test.mjs is for.", "$value": "194,116,10", "$dark": "{amber.500.rgb}" },
161
+ "info-rgb": { "$value": "{blue.600.rgb}", "$dark": "{blue.400.rgb}" },
162
+ "surface-rgb": { "$value": "{slate.0.rgb}", "$dark": "{slate.950.rgb}" },
163
+ "inverse-text-rgb": { "$value": "{slate.0.rgb}", "$dark": "{slate.900.rgb}" }
148
164
  },
149
165
 
150
166
  "chart": {
@@ -161,6 +177,7 @@
161
177
  },
162
178
 
163
179
  "_comment_tone": "General categorical palette: the same 8 validated hues as chart, aliased under a chart-neutral name for avatars, chips, tags, legend swatches (theme-follows via chart's own $dark).",
180
+ "_comment_tone_parts": "The four colours a tone modifier is MADE of, computed at build time (tokens/build.mjs flattens the color-mix() below, per theme, and never ships it). They exist as tokens because the alternative does not work: .fdy-avatar--tone-N / .fdy-badge--tone-N / .fdy-chip--tone-N used to inject the hue through a private custom property and mix it in the component, which put var() inside a color-mix() — assumed valid at parse time, invalid at computed-value time, and there the property drops to its INITIAL value rather than to any fallback. On Safari <= 16.1 that left the avatars on a shift-change roster screen with no fill and no ink at all. -bg is the tint the modifier sits on, -ink the text-leaning foreground that keeps it AA (test/contrast.test.mjs measures THESE, not the formula), -border the chip's opaque edge over --color-border, -border-soft the badge's translucent one. Both themes come out of one line each, so a retuned surface retunes every tint derived from it.",
164
181
  "tone": {
165
182
  "1": { "$value": "{chart.1}" },
166
183
  "2": { "$value": "{chart.2}" },
@@ -169,7 +186,43 @@
169
186
  "5": { "$value": "{chart.5}" },
170
187
  "6": { "$value": "{chart.6}" },
171
188
  "7": { "$value": "{chart.7}" },
172
- "8": { "$value": "{chart.8}" }
189
+ "8": { "$value": "{chart.8}" },
190
+
191
+ "1-bg": { "$value": "color-mix(in srgb, {tone.1} 18%, {color.surface})" },
192
+ "2-bg": { "$value": "color-mix(in srgb, {tone.2} 18%, {color.surface})" },
193
+ "3-bg": { "$value": "color-mix(in srgb, {tone.3} 18%, {color.surface})" },
194
+ "4-bg": { "$value": "color-mix(in srgb, {tone.4} 18%, {color.surface})" },
195
+ "5-bg": { "$value": "color-mix(in srgb, {tone.5} 18%, {color.surface})" },
196
+ "6-bg": { "$value": "color-mix(in srgb, {tone.6} 18%, {color.surface})" },
197
+ "7-bg": { "$value": "color-mix(in srgb, {tone.7} 18%, {color.surface})" },
198
+ "8-bg": { "$value": "color-mix(in srgb, {tone.8} 18%, {color.surface})" },
199
+
200
+ "1-ink": { "$value": "color-mix(in srgb, {tone.1} 50%, {color.text})" },
201
+ "2-ink": { "$value": "color-mix(in srgb, {tone.2} 50%, {color.text})" },
202
+ "3-ink": { "$value": "color-mix(in srgb, {tone.3} 50%, {color.text})" },
203
+ "4-ink": { "$value": "color-mix(in srgb, {tone.4} 50%, {color.text})" },
204
+ "5-ink": { "$value": "color-mix(in srgb, {tone.5} 50%, {color.text})" },
205
+ "6-ink": { "$value": "color-mix(in srgb, {tone.6} 50%, {color.text})" },
206
+ "7-ink": { "$value": "color-mix(in srgb, {tone.7} 50%, {color.text})" },
207
+ "8-ink": { "$value": "color-mix(in srgb, {tone.8} 50%, {color.text})" },
208
+
209
+ "1-border": { "$value": "color-mix(in srgb, {tone.1} 30%, {color.border})" },
210
+ "2-border": { "$value": "color-mix(in srgb, {tone.2} 30%, {color.border})" },
211
+ "3-border": { "$value": "color-mix(in srgb, {tone.3} 30%, {color.border})" },
212
+ "4-border": { "$value": "color-mix(in srgb, {tone.4} 30%, {color.border})" },
213
+ "5-border": { "$value": "color-mix(in srgb, {tone.5} 30%, {color.border})" },
214
+ "6-border": { "$value": "color-mix(in srgb, {tone.6} 30%, {color.border})" },
215
+ "7-border": { "$value": "color-mix(in srgb, {tone.7} 30%, {color.border})" },
216
+ "8-border": { "$value": "color-mix(in srgb, {tone.8} 30%, {color.border})" },
217
+
218
+ "1-border-soft": { "$value": "color-mix(in srgb, {tone.1} 26%, transparent)" },
219
+ "2-border-soft": { "$value": "color-mix(in srgb, {tone.2} 26%, transparent)" },
220
+ "3-border-soft": { "$value": "color-mix(in srgb, {tone.3} 26%, transparent)" },
221
+ "4-border-soft": { "$value": "color-mix(in srgb, {tone.4} 26%, transparent)" },
222
+ "5-border-soft": { "$value": "color-mix(in srgb, {tone.5} 26%, transparent)" },
223
+ "6-border-soft": { "$value": "color-mix(in srgb, {tone.6} 26%, transparent)" },
224
+ "7-border-soft": { "$value": "color-mix(in srgb, {tone.7} 26%, transparent)" },
225
+ "8-border-soft": { "$value": "color-mix(in srgb, {tone.8} 26%, transparent)" }
173
226
  },
174
227
 
175
228
  "surface-filter": { "$value": "none", "$glass": "blur(14px) saturate(150%)" },