PluginProbe
Darkify – Dark Mode & Night Mode for Website & Admin (Dark Theme Included) / 2.1.3
Darkify – Dark Mode & Night Mode for Website & Admin (Dark Theme Included) v2.1.3
2.1.3 2.1.2 2.1.1 2.1.0 2.0.4 2.0.3 2.0.2 2.0.1 2.0.0 1.5.5 1.5.4 1.5.3 1.5.2 1.5.1 1.5.0 trunk 1.0.1 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 All 57 releases
darkify / src / assets / css / client_main.css

client_main.css in Darkify – Dark Mode & Night Mode for Website & Admin (Dark Theme Included) 2.1.3, at src/assets/css/client_main.css

901 lines 31.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /*
2 * The colour rules below set `background-color`, never the `background`
3 * shorthand — and that distinction is load-bearing, not a style preference.
4 *
5 * `background` resets every background property it does not mention, so a rule
6 * of the form `background: <colour> !important` does not just repaint an
7 * element: it sets `background-image: none` on it. Everything a design paints
8 * through that property disappears — a select's dropdown chevron, an icon on a
9 * button, a sprite, a texture, a pattern, a gradient. And because the rule is
10 * `!important`, it outranks even an inline `background-image`, so nothing the
11 * engine writes inline can put the image back.
12 *
13 * The pairing was invisible while every rule also declared `background-color`
14 * on the next line with the same value: the shorthand contributed nothing to
15 * the colour and only did the damage. Dropping it changes no colour anywhere
16 * and lets the design's own imagery survive into dark mode.
17 */
18
19 .darkify_dark_mode_enabled
20 .darkify_style_all:not(
21 .darkify_switch,
22 .darkify_switch *,
23 .darkify_ignore,
24 .darkify_ignore *
25 ) {
26 background-color: var(--darkify_dark_mode_bg) !important;
27 color: var(--darkify_dark_mode_text_color) !important;
28 border-right-color: var(--darkify_dark_mode_border_color) !important;
29 border-left-color: var(--darkify_dark_mode_border_color) !important;
30 border-top-color: var(--darkify_dark_mode_border_color) !important;
31 border-bottom-color: var(--darkify_dark_mode_border_color) !important;
32 }
33 .darkify_dark_mode_enabled
34 .darkify_style_bg_txt:not(
35 .darkify_switch,
36 .darkify_switch *,
37 .darkify_ignore,
38 .darkify_ignore *
39 ) {
40 background-color: var(--darkify_dark_mode_bg) !important;
41 color: var(--darkify_dark_mode_text_color) !important;
42 }
43 .darkify_dark_mode_enabled
44 .darkify_style_bg_border:not(
45 .darkify_switch,
46 .darkify_switch *,
47 .darkify_ignore,
48 .darkify_ignore *
49 ) {
50 background-color: var(--darkify_dark_mode_bg) !important;
51 border-right-color: var(--darkify_dark_mode_border_color) !important;
52 border-left-color: var(--darkify_dark_mode_border_color) !important;
53 border-top-color: var(--darkify_dark_mode_border_color) !important;
54 border-bottom-color: var(--darkify_dark_mode_border_color) !important;
55 }
56 .darkify_dark_mode_enabled
57 .darkify_style_txt_border:not(
58 .darkify_switch,
59 .darkify_switch *,
60 .darkify_ignore,
61 .darkify_ignore *
62 ) {
63 color: var(--darkify_dark_mode_text_color) !important;
64 border-right-color: var(--darkify_dark_mode_border_color) !important;
65 border-left-color: var(--darkify_dark_mode_border_color) !important;
66 border-top-color: var(--darkify_dark_mode_border_color) !important;
67 border-bottom-color: var(--darkify_dark_mode_border_color) !important;
68 }
69 .darkify_dark_mode_enabled
70 .darkify_style_bg:not(
71 .darkify_switch,
72 .darkify_switch *,
73 .darkify_ignore,
74 .darkify_ignore *
75 ) {
76 background-color: var(--darkify_dark_mode_bg) !important;
77 }
78 .darkify_dark_mode_enabled
79 .darkify_style_txt:not(
80 .darkify_switch,
81 .darkify_switch *,
82 .darkify_ignore,
83 .darkify_ignore *
84 ) {
85 color: var(--darkify_dark_mode_text_color) !important;
86 }
87 .darkify_dark_mode_enabled
88 .darkify_style_border:not(
89 .darkify_switch,
90 .darkify_switch *,
91 .darkify_ignore,
92 .darkify_ignore *
93 ) {
94 border-right-color: var(--darkify_dark_mode_border_color) !important;
95 border-left-color: var(--darkify_dark_mode_border_color) !important;
96 border-top-color: var(--darkify_dark_mode_border_color) !important;
97 border-bottom-color: var(--darkify_dark_mode_border_color) !important;
98 }
99 .darkify_dark_mode_enabled
100 .darkify_style_secondary_bg:not(
101 .darkify_switch,
102 .darkify_switch *,
103 .darkify_ignore,
104 .darkify_ignore *
105 ) {
106 background-color: var(--darkify_dark_mode_secondary_bg) !important;
107 }
108
109 /*Handle Link Style*/
110 .darkify_dark_mode_enabled
111 .darkify_style_link:not(
112 .darkify_switch,
113 .darkify_switch *,
114 .darkify_ignore,
115 .darkify_ignore *,
116 .darkify-nav ul li a
117 ) {
118 color: var(--darkify_dark_mode_link_color) !important;
119 }
120 .darkify_dark_mode_enabled
121 .darkify_style_link:not(
122 .darkify_switch,
123 .darkify_switch *,
124 .darkify_ignore,
125 .darkify_ignore *
126 ):hover {
127 color: var(--darkify_dark_mode_link_hover_color) !important;
128 }
129
130 /*
131 * Colour overrides ("Replace Individual Colors").
132 *
133 * The value arrives as a custom property set inline by
134 * darkify_process_color_overrides(); these rules are what actually apply it.
135 * It used to be written straight onto the property as an inline `!important`,
136 * which outranks every author rule in the cascade — so an overridden element
137 * could never show its dark-mode `:hover` colour. Moving the application into
138 * the stylesheet puts it back into normal specificity competition.
139 *
140 * The selector shape is deliberate, load-bearing, and measured against the
141 * rules it has to sit between:
142 *
143 * .darkify_dark_mode_enabled .darkify_style_x:not(...) = (0,3,0)
144 * .darkify_dark_mode_enabled .darkify_style_link:not(...) = (0,3,3)
145 * ^ higher than its siblings because its :not() list carries
146 * `.darkify-nav ul li a`, and :not() takes the specificity of its most
147 * specific argument — three type selectors' worth.
148 * .darkify_dark_mode_enabled .darkify_style_x:not(...):hover = (0,4,0)
149 *
150 * So the override must be ABOVE (0,3,3) and BELOW (0,4,0): that means exactly
151 * three classes and at least four types. The repeated class buys the classes;
152 * `html:is(html):is(html):is(html)` buys the types without changing what the
153 * selector matches, since :is() takes its argument's specificity and every
154 * argument here is the element the rule already starts from.
155 *
156 * Do NOT add a `:not()` or another class — a fourth class ties the hover rules
157 * on class count and the override starts winning hover again, which is the
158 * exact bug this replaced. Elements inside `.darkify_switch` /
159 * `.darkify_ignore` are never processed, so they never carry these classes.
160 */
161 html:is(html):is(html):is(html).darkify_dark_mode_enabled .darkify_ovr_bg.darkify_ovr_bg {
162 background-color: var(--darkify-ovr-bg) !important;
163 }
164 html:is(html):is(html):is(html).darkify_dark_mode_enabled .darkify_ovr_color.darkify_ovr_color {
165 color: var(--darkify-ovr-color) !important;
166 }
167 html:is(html):is(html):is(html).darkify_dark_mode_enabled .darkify_ovr_bt.darkify_ovr_bt {
168 border-top-color: var(--darkify-ovr-bt) !important;
169 }
170 html:is(html):is(html):is(html).darkify_dark_mode_enabled .darkify_ovr_br.darkify_ovr_br {
171 border-right-color: var(--darkify-ovr-br) !important;
172 }
173 html:is(html):is(html):is(html).darkify_dark_mode_enabled .darkify_ovr_bb.darkify_ovr_bb {
174 border-bottom-color: var(--darkify-ovr-bb) !important;
175 }
176 html:is(html):is(html):is(html).darkify_dark_mode_enabled .darkify_ovr_bl.darkify_ovr_bl {
177 border-left-color: var(--darkify-ovr-bl) !important;
178 }
179
180 /*Handle Form Element Style*/
181 .darkify_dark_mode_enabled
182 .darkify_style_form_element:not(
183 .darkify_switch,
184 .darkify_switch *,
185 .darkify_ignore,
186 .darkify_ignore *
187 ) {
188 background-color: var(--darkify_dark_mode_input_bg) !important;
189 color: var(--darkify_dark_mode_input_text_color) !important;
190 }
191 .darkify_dark_mode_enabled
192 .darkify_style_form_element:not(
193 .darkify_switch,
194 .darkify_switch *,
195 .darkify_ignore,
196 .darkify_ignore *
197 )::placeholder {
198 color: var(--darkify_dark_mode_input_placeholder_color) !important;
199 }
200
201 /*Handle Button Style*/
202 .darkify_dark_mode_enabled
203 .darkify_style_button:not(
204 .darkify_switch,
205 .darkify_switch *,
206 .darkify_ignore,
207 .darkify_ignore *
208 ) {
209 background-color: var(--darkify_dark_mode_btn_bg) !important;
210 color: var(--darkify_dark_mode_btn_text_color) !important;
211 /*
212 * Buttons carry their own border token rather than the page's.
213 *
214 * The classifier takes `darkify_style_all` off an element the moment it calls
215 * it a button, so until these four lines existed a button's border was the
216 * one colour on the page dark mode never touched: an outline button kept the
217 * light design's brand edge — a teal ring around a grey fill — and no setting
218 * could reach it. A button also cannot simply borrow the generic border
219 * colour, because its border belongs to the button's own colour set: it is
220 * usually the fill or a shade of it, which is why the default for these
221 * tokens mirrors the button background.
222 */
223 border-right-color: var(--darkify_dark_mode_btn_border_color) !important;
224 border-left-color: var(--darkify_dark_mode_btn_border_color) !important;
225 border-top-color: var(--darkify_dark_mode_btn_border_color) !important;
226 border-bottom-color: var(--darkify_dark_mode_btn_border_color) !important;
227 }
228 /* the hover state */
229 .darkify_dark_mode_enabled
230 .darkify_style_button:not(
231 .darkify_switch,
232 .darkify_switch *,
233 .darkify_ignore,
234 .darkify_ignore *
235 ):hover {
236 background-color: var(--darkify_dark_mode_btn_hover_bg) !important;
237 color: var(--darkify_dark_mode_btn_text_hover_color) !important;
238 border-right-color: var(--darkify_dark_mode_btn_hover_border_color) !important;
239 border-left-color: var(--darkify_dark_mode_btn_hover_border_color) !important;
240 border-top-color: var(--darkify_dark_mode_btn_hover_border_color) !important;
241 border-bottom-color: var(--darkify_dark_mode_btn_hover_border_color) !important;
242 }
243
244
245 /* ========================
246 Borders the design does not draw
247 ===========================*/
248 /*
249 * A side marked here had a width in the light design but no colour — the
250 * `border: 8px solid transparent` idiom themes and block grids use for gutters
251 * and alignment. It occupies space and paints nothing.
252 *
253 * The rules above cannot tell those sides apart from real ones: they set all
254 * four border colours at once, because a class cannot carry per-side
255 * information. Painting a gutter turns invisible spacing into a visible line,
256 * and an element ringed by four of them grows a box that the light design never
257 * had — the effect that made WooCommerce product cards appear boxed in dark
258 * mode while looking open in light.
259 *
260 * The classifier stamps these markers on exactly the sides it measured as
261 * transparent, so each one is pinned back to transparent regardless of which
262 * colour rule matched. They repeat the `:not(...)` shape of the rules they
263 * override so the specificity matches, and sit after them so they win the tie.
264 */
265 .darkify_dark_mode_enabled
266 .darkify_border_keep_top:not(
267 .darkify_switch,
268 .darkify_switch *,
269 .darkify_ignore,
270 .darkify_ignore *
271 ) {
272 border-top-color: transparent !important;
273 }
274 .darkify_dark_mode_enabled
275 .darkify_border_keep_right:not(
276 .darkify_switch,
277 .darkify_switch *,
278 .darkify_ignore,
279 .darkify_ignore *
280 ) {
281 border-right-color: transparent !important;
282 }
283 .darkify_dark_mode_enabled
284 .darkify_border_keep_bottom:not(
285 .darkify_switch,
286 .darkify_switch *,
287 .darkify_ignore,
288 .darkify_ignore *
289 ) {
290 border-bottom-color: transparent !important;
291 }
292 .darkify_dark_mode_enabled
293 .darkify_border_keep_left:not(
294 .darkify_switch,
295 .darkify_switch *,
296 .darkify_ignore,
297 .darkify_ignore *
298 ) {
299 border-left-color: transparent !important;
300 }
301
302 /* ========================
303 Pre-paint baseline (FOUC)
304 ===========================*/
305 /*
306 * Dark mode is decided in the <head>, but the colours come from a DOM walk that
307 * cannot start until the DOM exists. Something has to cover that gap.
308 *
309 * It cannot be a colour wash on the elements themselves. The engine derives
310 * each dark colour by *reading* the element's computed light colour, so any
311 * rule that restyles elements beforehand destroys its input — everything reads
312 * back as the wash and nothing can be derived.
313 *
314 * A `brightness()` filter on <html> used to fill the gap. It painted only, so
315 * `getComputedStyle` still reported the design's real colours, but it dimmed
316 * the *whole viewport* — on a slow page that reads as a grey overlay sitting
317 * over the site for the entire load, and it repeats on every navigation. The
318 * filter is gone for that reason.
319 *
320 * What is left is the page backdrop alone: the root paints the configured dark
321 * background from the first frame, so the gap before the walk is a dark page
322 * rather than a white one. Content that has already painted keeps its light
323 * colours for those few frames — a much smaller artefact than dimming the
324 * entire viewport.
325 *
326 * Deliberately temporary: the class comes off the moment the first walk has
327 * assigned real colours.
328 */
329 html.darkify_dark_mode_enabled.darkify_prepaint {
330 background-color: var(--darkify_dark_mode_bg) !important;
331 }
332
333 /*
334 * The gap the backdrop above cannot cover.
335 *
336 * `html`'s dark background is only visible while nothing paints over it, and
337 * on essentially every theme `body` carries its own opaque light background,
338 * which does. So the intent of the rule above — "the gap before the walk is a
339 * dark page rather than a white one" — was defeated in practice: reloading with
340 * dark mode on showed the site's full light design for as long as the walk took,
341 * then flipped. That flip is the flicker.
342 *
343 * It cannot be fixed by washing the elements: the engine derives every dark
344 * colour by reading the element's computed light colour, so a colour applied
345 * beforehand becomes the input and the derivation collapses. `visibility` is
346 * the one property that hides the artefact without being read — it does not
347 * change any computed colour, and unlike `display` it keeps layout, so the walk
348 * measures exactly what it would have measured anyway.
349 *
350 * Scoped to its own class rather than `darkify_prepaint` so it can be dropped
351 * the instant the first walk has assigned colours, which is earlier than the
352 * backdrop is dropped. The inline script in the page head clears it on a
353 * failsafe timer regardless, so a failed or missing engine can never leave the
354 * page hidden.
355 */
356 html.darkify_dark_mode_enabled.darkify_fouc_guard body {
357 visibility: hidden !important;
358 }
359
360 /* ========================
361 Admin Bar Menu Design
362 ===========================*/
363 .darkify_admin_bar_switch_container {
364 cursor: pointer !important;
365 display: flex;
366 align-items: center;
367 justify-content: center;
368 width: 40px !important;
369 height: 32px !important;
370 }
371 /* On Darkify's own settings/help screens the admin-bar node is always rendered
372 so the React admin can reveal it the instant "Admin Panel Dark Mode" is
373 switched on (see WpAdminBarBridge) rather than only after a reload. It starts
374 hidden whenever the option is off. */
375 .darkify_admin_bar_switch_container.darkify_admin_bar_hidden {
376 display: none !important;
377 }
378 .darkify_admin_bar_switch_container .ab-item {
379 height: 18px !important;
380 cursor: pointer !important;
381 background-color: #ffffff !important;
382 -webkit-mask: url(../../Admin/assets/images/switch_apple_light.svg) no-repeat center;
383 mask: url(../../Admin/assets/images/switch_apple_light.svg) no-repeat center;
384 }
385 .darkify_dark_mode_enabled .darkify_admin_bar_switch_container .ab-item {
386 -webkit-mask: url(../../Admin/assets/images/switch_apple_dark.svg) no-repeat center;
387 mask: url(../../Admin/assets/images/switch_apple_dark.svg) no-repeat center;
388 }
389
390 /* ========================
391 Block Editor Menu Design
392 ===========================*/
393 .darkify_block_editor_switch {
394 height: 33px;
395 cursor: pointer;
396 -webkit-appearance: none;
397 -moz-appearance: none;
398 outline: 0;
399 border: 0;
400 background: #121116;
401 border-radius: 3px;
402 padding: 0 12px;
403 margin-right: 8px;
404 }
405 .darkify_dark_mode_enabled .darkify_block_editor_switch {
406 background: #ffffff;
407 }
408 .darkify_block_editor_switch .icon {
409 width: 20px;
410 height: 20px;
411 background-color: #ffffff !important;
412 -webkit-mask: url(../../Admin/assets/images/switch_apple_light.svg) no-repeat center;
413 mask: url(../../Admin/assets/images/switch_apple_light.svg) no-repeat center;
414 }
415
416 .darkify_dark_mode_enabled .darkify_block_editor_switch .icon {
417 background-color: #171717 !important;
418 -webkit-mask: url(../../Admin/assets/images/switch_apple_dark.svg) no-repeat center;
419 mask: url(../../Admin/assets/images/switch_apple_dark.svg) no-repeat center;
420 }
421
422 /* ========================
423 Switch Design
424 ===========================*/
425
426 .darkify_switch,
427 .darkify_switch * {
428 box-sizing: border-box;
429 }
430 .darkify_switch.darkify_top_left,
431 .darkify_switch.darkify_top_right,
432 .darkify_switch.darkify_bottom_left,
433 .darkify_switch.darkify_bottom_right {
434 position: fixed;
435 z-index: 99999;
436 }
437 .darkify_switch.darkify_top_left {
438 top: var(--darkify_switch_position_from_top_left_top);
439 left: var(--darkify_switch_position_from_top_left_left);
440 }
441 .darkify_switch.darkify_top_right {
442 top: var(--darkify_switch_position_from_top_right_top);
443 right: var(--darkify_switch_position_from_top_right_right);
444 }
445 .darkify_switch.darkify_bottom_left {
446 bottom: var(--darkify_switch_position_from_bottom_left_bottom);
447 left: var(--darkify_switch_position_from_bottom_left_left);
448 }
449 .darkify_switch.darkify_bottom_right {
450 bottom: var(--darkify_switch_position_from_bottom_right_bottom);
451 right: var(--darkify_switch_position_from_bottom_right_right);
452 }
453 .darkify_switch.darkify_absolute_position {
454 position: absolute;
455 }
456
457 @media only screen and (max-width: 600px) {
458 .darkify_switch.darkify_hide_on_mobile {
459 display: none;
460 }
461 }
462
463 @media only screen and (max-width: 600px) {
464 .darkify_switch.darkify_top_left_in_mobile,
465 .darkify_switch.darkify_top_right_in_mobile,
466 .darkify_switch.darkify_bottom_left_in_mobile,
467 .darkify_switch.darkify_bottom_right_in_mobile {
468 position: fixed;
469 }
470 .darkify_switch.darkify_top_left_in_mobile {
471 top: var(--darkify_switch_position_from_top_left_top_in_mobile);
472 left: var(--darkify_switch_position_from_top_left_left_in_mobile);
473 bottom: unset;
474 right: unset;
475 }
476 .darkify_switch.darkify_top_right_in_mobile {
477 top: var(--darkify_switch_position_from_top_right_top_in_mobile);
478 right: var(--darkify_switch_position_from_top_right_right_in_mobile);
479 bottom: unset;
480 left: unset;
481 }
482 .darkify_switch.darkify_bottom_left_in_mobile {
483 bottom: var(--darkify_switch_position_from_bottom_left_bottom_in_mobile);
484 left: var(--darkify_switch_position_from_bottom_left_left_in_mobile);
485 top: unset;
486 right: unset;
487 }
488 .darkify_switch.darkify_bottom_right_in_mobile {
489 bottom: var(--darkify_switch_position_from_bottom_right_bottom_in_mobile);
490 right: var(--darkify_switch_position_from_bottom_right_right_in_mobile);
491 top: unset;
492 left: unset;
493 }
494 }
495
496 .darkify_tooltip .darkify_tooltiptext {
497 visibility: hidden;
498 width: 120px;
499 background-color: var(--darkify_switch_tooltip_bg_color);
500 color: var(--darkify_switch_tooltip_text_color);
501 font-size: 12px;
502 text-align: center;
503 border-radius: 0;
504 padding: 5px 5px;
505 position: absolute;
506 z-index: 1;
507 border-radius: 3px;
508 }
509 .darkify_tooltip .darkify_tooltiptext::after {
510 content: "";
511 position: absolute;
512 border-width: 5px;
513 border-style: solid;
514 }
515 .darkify_tooltip:hover .darkify_tooltiptext {
516 visibility: visible;
517 }
518 .darkify_tooltip.darkify_tooltip_top .darkify_tooltiptext {
519 bottom: calc(100% + 10px);
520 left: 50%;
521 margin-left: -60px;
522 }
523 .darkify_tooltip.darkify_tooltip_top .darkify_tooltiptext::after {
524 left: 50%;
525 margin-left: -5px;
526 top: 100%;
527 border-color: var(--darkify_switch_tooltip_bg_color) transparent transparent
528 transparent;
529 }
530 .darkify_tooltip.darkify_tooltip_bottom .darkify_tooltiptext {
531 top: calc(100% + 10px);
532 left: 50%;
533 margin-left: -60px;
534 }
535 .darkify_tooltip.darkify_tooltip_bottom .darkify_tooltiptext::after {
536 left: 50%;
537 margin-left: -5px;
538 bottom: 100%;
539 border-color: transparent transparent var(--darkify_switch_tooltip_bg_color)
540 transparent;
541 }
542 .darkify_tooltip.darkify_tooltip_left .darkify_tooltiptext {
543 right: calc(100% + 10px);
544 top: calc(50% - 15px);
545 }
546 .darkify_tooltip.darkify_tooltip_left .darkify_tooltiptext::after {
547 top: 50%;
548 left: 100%;
549 margin-top: -5px;
550 border-color: transparent transparent transparent
551 var(--darkify_switch_tooltip_bg_color);
552 }
553 .darkify_tooltip.darkify_tooltip_right .darkify_tooltiptext {
554 left: calc(100% + 10px);
555 top: calc(50% - 15px);
556 }
557 .darkify_tooltip.darkify_tooltip_right .darkify_tooltiptext::after {
558 top: 50%;
559 right: 100%;
560 margin-top: -5px;
561 border-color: transparent var(--darkify_switch_tooltip_bg_color) transparent
562 transparent;
563 }
564
565 /* ==============
566 Switch Style
567 ============== */
568
569 .darkify_switch_style {
570 cursor: pointer;
571 z-index: 9999;
572 width: calc(60px * var(--darkify-switch-scale, 1));
573 height: calc(60px * var(--darkify-switch-scale, 1));
574 border-radius: var(--darkify_switch_border_radius);
575 background: var(--darkify_switch_light_mode_bg);
576 display: flex;
577 align-items: center;
578 justify-content: center;
579 border-width: var(--darkify_switch_border);
580 border-style: solid;
581 border-color: var(--darkify_switch_border_light_color);
582 }
583
584 .darkify_dark_mode_enabled .darkify_switch_style {
585 border-color: var(--darkify_switch_border_dark_color);
586 }
587 .darkify_switch_style .theme-toggle {
588 display: flex;
589 align-items: center;
590 justify-content: center;
591 }
592 .darkify_switch_style svg {
593 width: calc(40px * var(--darkify-switch-scale, 1));
594 height: calc(40px * var(--darkify-switch-scale, 1));
595 color: var(--darkify_switch_light_mode_color);
596 stroke: var(--darkify_switch_light_mode_color);
597 }
598 .darkify_dark_mode_enabled .darkify_switch_style {
599 background: var(--darkify_switch_dark_mode_bg);
600 }
601 .darkify_dark_mode_enabled .darkify_switch_style svg {
602 color: var(--darkify_switch_dark_mode_color);
603 stroke: var(--darkify_switch_dark_mode_color);
604 }
605 .switch-orbit,
606 .switch-duality,
607 .switch-dual,
608 .switch-shift {
609 box-sizing: content-box;
610 }
611 .darkify_dark_mode_enabled
612 .block-editor-page.post-content-style-boxed
613 .editor-styles-wrapper:before {
614 background-color: unset;
615 }
616 .darkify_dark_mode_enabled h3#color-palette-1-0,
617 .darkify_dark_mode_enabled .components-color-palette__custom-color-name {
618 color: var(--darkify_dark_mode_text_color)!important;
619 }
620 .darkify-dropdown {
621 position: relative;
622 width: 160px;
623 margin-left: 8px;
624 }
625
626 .darkify-dropdown .darkify-selected {
627 padding: 5px;
628 background: #fff;
629 color: #000;
630 cursor: pointer;
631 border-radius: 3px;
632 border: 1px solid #c0c0c0;
633 }
634
635 .darkify-dropdown .darkify-options {
636 display: none;
637 position: absolute;
638 width: 100%;
639 background: #fff;
640 border-radius: 6px;
641 margin-top: 5px;
642 overflow: hidden;
643 z-index: 1000;
644 box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
645 color: #000;
646 top: 30px;
647 }
648
649 .darkify-dropdown .darkify-options.show {
650 display: block;
651 }
652
653 .darkify-dropdown .darkify-option {
654 padding: 8px;
655 cursor: pointer;
656 display: flex;
657 align-items: center;
658 gap: 4px;
659 }
660 .darkify-dropdown .darkify-pro-option {
661 cursor: not-allowed;
662 opacity: 0.55;
663 pointer-events: none;
664 gap: 4px;
665 }
666 .darkify-option-pro-badge {
667 margin-left: auto;
668 font-size: 10px;
669 font-weight: 600;
670 background: #cbd6df;
671 color: #5e6e7d;
672 padding: 2px 5px;
673 border-radius: 3px;
674 white-space: nowrap;
675 flex-shrink: 0;
676 }
677 .darkify-dropdown .darkify-selected {
678 display: flex;
679 align-items: center;
680 width: 100%;
681 gap: 4px;
682 }
683 .darkify-dropdown .theme_color {
684 display: inline-block;
685 width: 20px;
686 height: 20px;
687 border-radius: 50%;
688 border: 1px solid gray;
689 }
690 .darkify-dropdown .default {
691 background-color: #fff;
692 }
693 /*
694 * "Auto" has no single colour to show — Dark Reader derives one per element —
695 * so the swatch shows a gradient rather than claiming a flat value the way the
696 * named presets legitimately can.
697 */
698 .darkify-dropdown .auto_palette {
699 background-image: linear-gradient(135deg, #0f0f0f 0%, #3a3a3a 50%, #8f8f8f 100%);
700 }
701 .darkify-dropdown .carbon_mist {
702 background-color: #171717;
703 }
704 .darkify-dropdown .midnight_reverie {
705 background-color: #4e478d;
706 }
707 .darkify-dropdown .verdant_depths {
708 background-color: #073d2f;
709 }
710 .darkify-dropdown .celestial_tide {
711 background-color: #144e78;
712 }
713 .darkify-dropdown .emberwood {
714 background-color: #372911;
715 }
716 .darkify-dropdown .glacier_drift {
717 background-color: #123d52;
718 }
719 .darkify-dropdown .indigo_veil {
720 background-color: #46598c;
721 }
722 .darkify-dropdown .duskmire {
723 background-color: #403953;
724 }
725 .darkify-dropdown .tidal_frost {
726 background-color: #286f8d;
727 }
728 .darkify-dropdown .blue_bastion {
729 background-color: #244892;
730 }
731 .darkify-dropdown .crimson_veil {
732 background-color: #440649;
733 }
734
735 .darkify_dark_mode_enabled .darkify-dropdown,
736 .darkify_dark_mode_enabled .darkify-options.show {
737 background-color: var(--darkify_dark_mode_bg) !important;
738 }
739
740 /* Switch Attention Effects */
741 @keyframes darkify_attention_pulse {
742 0%, 100% { transform: scale(1); }
743 50% { transform: scale(1.1); }
744 }
745 @keyframes darkify_attention_radiance {
746 0%, 100% { box-shadow: 0 0 0 0 rgba(100, 100, 100, 0.45); }
747 50% { box-shadow: 0 0 0 14px rgba(100, 100, 100, 0); }
748 }
749 @keyframes darkify_attention_leap {
750 0%, 55%, 100% { transform: translateY(0); }
751 30% { transform: translateY(-14px); }
752 45% { transform: translateY(-8px); }
753 }
754 @keyframes darkify_attention_swing {
755 0%, 100% { transform: rotate(0deg); transform-origin: center bottom; }
756 20% { transform: rotate(-9deg); transform-origin: center bottom; }
757 40% { transform: rotate(7deg); transform-origin: center bottom; }
758 60% { transform: rotate(-5deg); transform-origin: center bottom; }
759 80% { transform: rotate(3deg); transform-origin: center bottom; }
760 }
761 @keyframes darkify_attention_drift {
762 0%, 100% { transform: translateY(0); }
763 50% { transform: translateY(-8px); }
764 }
765 @keyframes darkify_attention_nudge {
766 0%, 65%, 100% { transform: translateX(0); }
767 10% { transform: translateX(-6px); }
768 20% { transform: translateX(6px); }
769 30% { transform: translateX(-4px); }
770 40% { transform: translateX(4px); }
771 50% { transform: translateX(-2px); }
772 57% { transform: translateX(2px); }
773 }
774 .darkify_switch.darkify_attention_pulse {
775 animation: darkify_attention_pulse 2s ease-in-out 2s infinite;
776 }
777 .darkify_switch.darkify_attention_radiance {
778 animation: darkify_attention_radiance 2s ease-in-out 2s infinite;
779 }
780 .darkify_switch.darkify_attention_leap {
781 animation: darkify_attention_leap 2.5s ease-in-out 2s infinite;
782 }
783 .darkify_switch.darkify_attention_swing {
784 animation: darkify_attention_swing 1.6s ease-in-out 2s infinite;
785 }
786 .darkify_switch.darkify_attention_drift {
787 animation: darkify_attention_drift 3s ease-in-out 2s infinite;
788 }
789 .darkify_switch.darkify_attention_nudge {
790 animation: darkify_attention_nudge 2.5s ease-in-out 2s infinite;
791 }
792 .darkify_switch.darkify_attention_pulse:hover,
793 .darkify_switch.darkify_attention_radiance:hover,
794 .darkify_switch.darkify_attention_leap:hover,
795 .darkify_switch.darkify_attention_swing:hover,
796 .darkify_switch.darkify_attention_drift:hover,
797 .darkify_switch.darkify_attention_nudge:hover {
798 animation-play-state: paused;
799 }
800 /*
801 * Transition suppression for the duration of an engine pass.
802 *
803 * The engine classifies an element from its computed colours, and a colour
804 * mid-transition computes to an interpolated value that belongs to neither the
805 * start nor the end state — so a pass that runs while the page is animating
806 * reads colours the design never actually paints. Suppressing transitions for
807 * the length of the pass makes every read a settled one.
808 *
809 * This replaces an inline `transition-property: none !important` that was
810 * written to, and then removed from, every element individually. Writing a
811 * style and then reading a computed style off the same element forces a
812 * synchronous style recalculation, so that pattern cost one full recalc per
813 * element; as one class on the root it costs one invalidation per pass.
814 *
815 * `!important` is warranted here and is the reason the declaration can stay a
816 * single rule: it has to beat inline transitions written by builders and
817 * animation libraries, which is precisely the case it exists to neutralise. It
818 * is present only while a pass is running — never in the page's resting state.
819 */
820 /*
821 * The switcher is deliberately outside this suppression, and leaving it in was
822 * a real bug: it silently removed the toggle's animation.
823 *
824 * The switcher is the one animated thing on the page that the engine does not
825 * manage — it never receives `darkify_processed`, its colours are never read to
826 * classify it, and its whole visual job is to animate between the two states.
827 * Suppressing transitions on it therefore protects nothing and costs the
828 * feature.
829 *
830 * The damage is not obvious from reading the rule, because the class is added
831 * and removed inside a single synchronous task, so it is never painted. What
832 * matters is that the pass calls `getComputedStyle` thousands of times while
833 * the class is on, and every one of those forces a style recalculation. A
834 * recalculation that sees `transition-property: none` *cancels the transitions
835 * already running* — and the switcher's transitions started moments earlier,
836 * when the state class flipped. Removing the class afterwards does not revive
837 * them; the values have already been committed to their end state. Measured on
838 * the stress page: 17 transitions created on `d`, `opacity` and `transform`,
839 * all with `currentTime` still 0, gone by the next frame — the toggle snapped
840 * instead of animating.
841 *
842 * `.darkify_ignore` is excluded for the same reason it is excluded from every
843 * other rule in this file: it marks a subtree the plugin has been told to keep
844 * its hands off, and cancelling its animations is exactly the interference the
845 * marker exists to prevent.
846 *
847 * This costs nothing. The exclusion is evaluated only while a pass is running,
848 * and it removes work rather than adding it — the excluded subtrees are the
849 * ones the engine was never going to read.
850 */
851 html.darkify_suspend_transitions,
852 html.darkify_suspend_transitions
853 *:not(
854 .darkify_switch,
855 .darkify_switch *,
856 .darkify_ignore,
857 .darkify_ignore *
858 ) {
859 transition-property: none !important;
860 }
861
862 /*
863 * The same suppression, scoped to a single element — and now to a single case.
864 *
865 * The rule above is correct for the two passes that read the whole document —
866 * the first walk and the dark-mode state sweep — because at those moments the
867 * page is either not yet interactive or is being repainted wholesale anyway.
868 * This rule covers the incremental passes, where exactly one of the two things
869 * that reach them wants it:
870 *
871 * - An element being coloured for the FIRST time (a node that arrived after
872 * the initial walk) gets the class. Without it, dark mode *animates* onto
873 * the element and it fades from its light colour to its dark one in full
874 * view. On a hard reload, with nothing in cache, far more of the page
875 * arrives late and is coloured here rather than by the walk the FOUC guard
876 * hides — which is what made backgrounds visibly wash from white to dark.
877 *
878 * - An element being RE-READ because its class list changed (an accordion
879 * opening, a dropdown, a hover state) must NOT get it, so the animation
880 * that triggered the pass still eases. Applying it here was what made those
881 * snap to their end state.
882 *
883 * The class is applied around the read and released on the next frame rather
884 * than synchronously (see darkify_release_no_transition in client_main.js): a
885 * same-task removal means the browser only ever computes the finished state —
886 * new colour with transitions live — and eases into it, which is the very thing
887 * being prevented.
888 *
889 * `transition-property` is not inherited, so this cancels the element's own
890 * transitions and nothing below it. It is also a reasonable thing to put on an
891 * element by hand.
892 */
893 .darkify_no_transition:not(
894 .darkify_switch,
895 .darkify_switch *,
896 .darkify_ignore,
897 .darkify_ignore *
898 ) {
899 transition-property: none !important;
900 }
901