PluginProbe
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN / 1.3.3
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN v1.3.3
1.3.3 1.3.2 1.3.1 1.3.0 1.2.4 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 All 29 releases
← All changes | assets/theme.css +93 -3 1.1.51.3.3 View file →
@@ -29,9 +29,9 @@
29 29 --primary-hover: #1E9089;
30 30 --primary-tint: #E6F5F3;
31 31 --on-primary: #FFFFFF;
32 32 /* Text/heading colour for content sitting ON a primary/info tint. */
33 - --on-tint: #1E8079;
33 + --on-tint: #1A7770; /* 4.79:1 on --primary-tint, 5.37:1 on --paper — small Pro badge text sits on the tint */
34 34 --primary-glow: 0 2px 12px rgba(42, 167, 160, .30);
35 35
36 36 /* Surfaces */
37 37 --canvas: #FBFBFC;
@@ -42,9 +42,32 @@
42 42
43 43 /* Text */
44 44 --text: #0E0F13;
45 45 --text-secondary: #5C6270;
46 - --muted: #8A909D;
46 + /* WCAG AA (#84). Was #8A909D, which measured 3.10 on --canvas, 3.20 on
47 + --paper and 2.96 on --panel — the last being the "Off" status pill, the
48 + only state indicator on a group-landing card and the smallest type on
49 + screen. Fixing the token rather than the call sites covers all 102
50 + usages at once — including Pro's panels, which render inside
51 + #xspeed-app and ship no tokens of their own.
52 +
53 + The first pass at this (#6B7180) only measured the three neutral
54 + surfaces and missed a fourth class: the TINTS. text-muted is never
55 + paired with a *-tint class on the same element — the tint sits on an
56 + ancestor upsell card — so a source grep finds nothing and only a
57 + rendered-DOM measurement catches it. #6B7180 failed on all four
58 + (4.35 / 4.43 / 4.49 / 4.28).
59 +
60 + #686D7C is the lightest value on the same hue that clears 4.5:1 on
61 + every surface a muted string can land on:
62 +
63 + canvas 4.99 · paper 5.16 · panel 4.77
64 + primary+info-tint 4.60 · success-tint 4.68
65 + warning-tint 4.74 · danger-tint 4.52
66 +
67 + Still visibly lighter than --text-secondary (5.91 on canvas), so the
68 + hint/secondary distinction the palette relies on survives. */
69 + --muted: #686D7C;
47 70 --faint: #A2A8B4;
48 71
49 72 /* Semantic (color + tint) */
50 73 --success: #10B981;
@@ -84,9 +107,17 @@
84 107 --line: #282C34;
85 108 --line-strong: #333845;
86 109 --text: #E7E9EE;
87 110 --text-secondary: #9AA1AE;
88 - --muted: #7E8593;
111 + /* Same tint gap as light mode (#84). #7E8593 measured 4.29 on
112 + --primary-tint and 4.32 on --success-tint, and cleared --panel by
113 + exactly 4.50 — no headroom, so any future surface tweak would have
114 + broken it silently. #868D9B clears every dark surface:
115 + canvas 5.74 · paper 5.33 · panel 5.01 · primary+info-tint 4.77
116 + success-tint 4.81 · warning-tint 5.03 · danger-tint 5.17
117 + Dark was never actually at "0 failures" on tints; this is what makes
118 + that true rather than assumed. */
119 + --muted: #868D9B;
89 120 --faint: #6A707D;
90 121 /* Teal, a touch lighter so it reads on the dark surfaces. */
91 122 --primary: #34C0B7;
92 123 --primary-hover: #2AA7A0;
@@ -102,12 +133,71 @@
102 133 /* ---- Signature motion (used by the shell + later screens) -------------- */
103 134 @keyframes xspeed-boltpulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .45; transform: scale(.82); } }
104 135 @keyframes xspeed-sweep { 0% { background-position: -220px 0; } 100% { background-position: 320px 0; } }
105 136 @keyframes xspeed-ringfill { from { stroke-dashoffset: 326.7; } to { stroke-dashoffset: 26.1; } }
137 +@keyframes xspeed-drain { from { transform: scaleX(1); } to { transform: scaleX(0); } }
138 +@keyframes xspeed-pop { from { opacity: 0; transform: scale(.6); } to { opacity: 1; transform: none; } }
106 139
107 140 /* Signature-motion utility classes (reduced-motion aware via the rule below). */
108 141 .xspeed-anim-boltpulse { animation: xspeed-boltpulse 1.8s ease-in-out infinite; }
109 142 .xspeed-anim-sweep { background-size: 220px 100%; animation: xspeed-sweep 1.5s linear infinite; }
143 +/* Purge result (§24.38). The resting state is the END state, so the reduced-motion
144 + rule below leaves the hairline undrawn and the icon simply present. */
145 +.xspeed-anim-drain { transform: scaleX(0); transform-origin: left; animation: xspeed-drain .6s cubic-bezier(.3, .7, .3, 1) both; }
146 +.xspeed-anim-pop { animation: xspeed-pop .2s ease-out both; }
110 147
111 148 @media (prefers-reduced-motion: reduce) {
112 149 #xspeed-app [class*="xspeed-anim"] { animation: none !important; }
150 +}
151 +
152 +/* ---- MCP discovery card (Overview, disconnected) ----------------------- */
153 +/*
154 + * Three tinted surfaces for the "Control and optimize your site with AI" card.
155 + * They live here rather than in a component because Tailwind cannot express an
156 + * ALPHA of a var()-backed colour: with `primary: 'var(--primary)'` in the theme,
157 + * `border-primary/45` silently emits the colour at full strength. Deriving them
158 + * from --primary with color-mix() keeps the card on-brand in both themes with
159 + * no new tokens — change --primary and all three follow.
160 + *
161 + * Every rule declares a neutral fallback FIRST. color-mix() is ~2023-era, and
162 + * where it is unsupported the declaration is dropped: without the fallback the
163 + * card's border-color would fall back to currentColor, painting a near-black
164 + * hairline around a white card. The fallback degrades to the plain --line
165 + * border and no wash, which is simply the standard card treatment.
166 + */
167 +#xspeed-app .xspeed-mcp-card {
168 + border-color: var(--line);
169 + border-color: color-mix(in srgb, var(--primary) 45%, transparent);
170 + background-image: radial-gradient(120% 150% at 100% 0%,
171 + color-mix(in srgb, var(--primary) 9%, transparent) 0%, transparent 58%);
172 +}
173 +
174 +/* The miniature session sits in a recessed teal well, not a second white
175 + plane — white-on-white read as a stray box rather than an inset surface. */
176 +#xspeed-app .xspeed-mcp-well {
177 + border-color: var(--line);
178 + border-color: color-mix(in srgb, var(--primary) 20%, transparent);
179 + background-image: linear-gradient(180deg,
180 + color-mix(in srgb, var(--primary) 3%, transparent) 0%,
181 + color-mix(in srgb, var(--primary) 7%, transparent) 100%);
182 +}
183 +
184 +#xspeed-app .xspeed-mcp-glow {
185 + background-image: radial-gradient(58% 62% at 62% 46%,
186 + color-mix(in srgb, var(--primary) 13%, transparent) 0%, transparent 72%);
187 +}
188 +
189 +/* Dark needs more alpha for the same apparent lift: a 3% teal that reads as a
190 + tint over #FFFFFF is invisible over #16181D. */
191 +#xspeed-app.dark .xspeed-mcp-card {
192 + border-color: color-mix(in srgb, var(--primary) 38%, transparent);
193 +}
194 +#xspeed-app.dark .xspeed-mcp-well {
195 + border-color: color-mix(in srgb, var(--primary) 26%, transparent);
196 + background-image: linear-gradient(180deg,
197 + color-mix(in srgb, var(--primary) 6%, transparent) 0%,
198 + color-mix(in srgb, var(--primary) 11%, transparent) 100%);
199 +}
200 +#xspeed-app.dark .xspeed-mcp-glow {
201 + background-image: radial-gradient(58% 62% at 62% 46%,
202 + color-mix(in srgb, var(--primary) 16%, transparent) 0%, transparent 72%);
113 203 }