| @@ -9,9 +9,11 @@ | ||
| 9 | 9 | [data-theme="dark"] { |
| 10 | 10 | --dashboard-bg: #0f1419; |
| 11 | 11 | --dashboard-card-bg: #1a1f26; |
| 12 | 12 | --dashboard-card-hover: #222831; |
| 13 | + --dashboard-input-bg: #22272e; | |
| 13 | 14 | --dashboard-text-primary: #ffffff; |
| 15 | + --dashboard-text: #ffffff; | |
| 14 | 16 | --dashboard-text-secondary: #9ca3af; |
| 15 | 17 | --dashboard-accent: #3b82f6; |
| 16 | 18 | --dashboard-accent-hover: #2563eb; |
| 17 | 19 | --dashboard-success: #10b981; |
| @@ -28,9 +30,11 @@ | ||
| 28 | 30 | [data-theme="light"] { |
| 29 | 31 | --dashboard-bg: #f8f9fa; |
| 30 | 32 | --dashboard-card-bg: #ffffff; |
| 31 | 33 | --dashboard-card-hover: #f1f3f5; |
| 34 | + --dashboard-input-bg: #ffffff; | |
| 32 | 35 | --dashboard-text-primary: #1a1f26; |
| 36 | + --dashboard-text: #1a1f26; | |
| 33 | 37 | --dashboard-text-secondary: #6b7280; |
| 34 | 38 | --dashboard-accent: #3b82f6; |
| 35 | 39 | --dashboard-accent-hover: #2563eb; |
| 36 | 40 | --dashboard-success: #10b981; |
| @@ -123,8 +127,19 @@ | ||
| 123 | 127 | border-left-color: var(--dashboard-error) !important; |
| 124 | 128 | background: rgba(239, 68, 68, 0.15) !important; |
| 125 | 129 | } |
| 126 | 130 | |
| 131 | +/* Specific warning notice styling ONLY in plugin. | |
| 132 | + Without this, warning notices fell through to the base .notice rule above | |
| 133 | + (blue border-left, plain card background) because that rule is !important | |
| 134 | + and the .notice-warning colours defined further down this file are not — | |
| 135 | + !important always wins regardless of source order, so the warning never | |
| 136 | + actually rendered yellow/amber. Mirrors the .notice-error override above. */ | |
| 137 | +.metasync-dashboard-wrap .notice.notice-warning { | |
| 138 | + border-left-color: var(--dashboard-warning) !important; | |
| 139 | + background: rgba(245, 158, 11, 0.15) !important; | |
| 140 | +} | |
| 141 | + | |
| 127 | 142 | /* License mismatch notice specific styling ONLY in plugin */ |
| 128 | 143 | .metasync-dashboard-wrap .notice:has(.dashicons-warning):before, |
| 129 | 144 | .metasync-dashboard-wrap .notice[class*="license"]:before, |
| 130 | 145 | .metasync-dashboard-wrap .notice[class*="mismatch"]:before { |
| @@ -283,8 +298,15 @@ | ||
| 283 | 298 | .metasync-header[data-current-theme="dark"] .metasync-logo-light { |
| 284 | 299 | display: none; |
| 285 | 300 | } |
| 286 | 301 | |
| 302 | +/* Light theme must explicitly show the light logo: its base state is | |
| 303 | + display:none, and hiding the dark logo alone would leave no logo visible. */ | |
| 304 | +[data-theme="light"] .metasync-logo-light, | |
| 305 | +.metasync-header[data-current-theme="light"] .metasync-logo-light { | |
| 306 | + display: block; | |
| 307 | +} | |
| 308 | + | |
| 287 | 309 | /* Default (non-whitelabel) SA logo: invert on light theme so the white asset |
| 288 | 310 | stays visible against a light background. Dark theme keeps the original. */ |
| 289 | 311 | [data-theme="light"] .metasync-logo-default, |
| 290 | 312 | .metasync-header[data-current-theme="light"] .metasync-logo-default { |
| @@ -558,9 +580,10 @@ | ||
| 558 | 580 | .metasync-dashboard-wrap .form-table { |
| 559 | 581 | background: transparent; |
| 560 | 582 | border: none; |
| 561 | 583 | border-collapse: separate; |
| 562 | - border-spacing: 0; | |
| 584 | + /* Vertical spacing between each settings row (tr); horizontal stays 0 so th/td join */ | |
| 585 | + border-spacing: 0 12px; | |
| 563 | 586 | width: 100%; |
| 564 | 587 | } |
| 565 | 588 | |
| 566 | 589 | .metasync-dashboard-wrap .form-table th { |
| @@ -584,24 +607,9 @@ | ||
| 584 | 607 | padding: 16px 20px; |
| 585 | 608 | vertical-align: top; |
| 586 | 609 | } |
| 587 | 610 | |
| 588 | -.metasync-dashboard-wrap .form-table tr { | |
| 589 | - margin-bottom: 16px; | |
| 590 | -} | |
| 591 | - | |
| 592 | -.metasync-dashboard-wrap .form-table tr:not(:last-child) th, | |
| 593 | -.metasync-dashboard-wrap .form-table tr:not(:last-child) td { | |
| 594 | - border-bottom: none; | |
| 595 | -} | |
| 596 | - | |
| 597 | -/* Simple, clean spacing between form table rows */ | |
| 598 | -.metasync-dashboard-wrap .form-table tr + tr th, | |
| 599 | -.metasync-dashboard-wrap .form-table tr + tr td { | |
| 600 | - padding-top: 24px; | |
| 601 | -} | |
| 602 | - | |
| 603 | -/* Ensure proper internal padding for all cells */ | |
| 611 | +/* Each row is a self-contained card; vertical gaps come from border-spacing above */ | |
| 604 | 612 | .metasync-dashboard-wrap .form-table th, |
| 605 | 613 | .metasync-dashboard-wrap .form-table td { |
| 606 | 614 | padding: 16px 12px; |
| 607 | 615 | } |
| @@ -1035,9 +1043,9 @@ | ||
| 1035 | 1043 | |
| 1036 | 1044 | /* Disabled state — needed because the base .button-primary rule keeps the |
| 1037 | 1045 | full gradient even when prop('disabled', true) is set. Without this, |
| 1038 | 1046 | the Sync Now button stays blue/purple while the cooldown countdown is |
| 1039 | - active (WP-350 QA report). | |
| 1047 | + active (QA report). | |
| 1040 | 1048 | |
| 1041 | 1049 | The .is-throttled class is the primary driver for the Sync Now cooldown |
| 1042 | 1050 | visual because earlier code in the AJAX callback chain calls |
| 1043 | 1051 | .prop('disabled', false) before our refresh runs, and in some browsers |
| @@ -1054,9 +1062,9 @@ | ||
| 1054 | 1062 | .metasync-dashboard-wrap .button-primary.is-throttled, |
| 1055 | 1063 | .metasync-dashboard-wrap .button-secondary.is-throttled { |
| 1056 | 1064 | /* Replace the blue/purple gradient with a solid grey. The base rule sets |
| 1057 | 1065 | `background: var(--dashboard-gradient-primary)`, so opacity + grayscale |
| 1058 | - alone left the button a dimmed blue (WP-350 QA: "still blue on Elementor"). | |
| 1066 | + alone left the button a dimmed blue (QA: "still blue on Elementor"). | |
| 1059 | 1067 | background/filter/pointer-events carry !important so a page-builder's |
| 1060 | 1068 | admin stylesheet (Elementor ships more than Divi) can't override them. */ |
| 1061 | 1069 | background: #d5d7da !important; |
| 1062 | 1070 | background-image: none !important; |
| @@ -1346,9 +1354,13 @@ | ||
| 1346 | 1354 | border-color: var(--dashboard-error); |
| 1347 | 1355 | /* Removed translateY animation - was too distracting */ |
| 1348 | 1356 | } |
| 1349 | 1357 | |
| 1350 | -/* Connect Status Messages - Dashboard Style */ | |
| 1358 | +/* Connect Status Messages - Dashboard Style | |
| 1359 | + The box holds two block children — .metasync-sa-connect-status-content and | |
| 1360 | + .metasync-sa-connect-actions — so it must stack. As a row, the actions block | |
| 1361 | + sized to its buttons while the content block (flex: 1, so flex-basis: 0) was | |
| 1362 | + squeezed into whatever was left, wrapping the message one word per line. */ | |
| 1351 | 1363 | .metasync-dashboard-wrap .metasync-sa-connect-status, |
| 1352 | 1364 | .metasync-dashboard-wrap #sa-connect-status-message { |
| 1353 | 1365 | margin-top: 16px; |
| 1354 | 1366 | padding: 16px 20px; |
| @@ -1353,9 +1365,10 @@ | ||
| 1353 | 1365 | margin-top: 16px; |
| 1354 | 1366 | padding: 16px 20px; |
| 1355 | 1367 | border-radius: 12px; |
| 1356 | 1368 | display: flex; |
| 1357 | - align-items: flex-start; | |
| 1369 | + flex-direction: column; | |
| 1370 | + align-items: stretch; | |
| 1358 | 1371 | gap: 12px; |
| 1359 | 1372 | font-weight: 500; |
| 1360 | 1373 | /* Removed slideInNotice animation - was too distracting */ |
| 1361 | 1374 | backdrop-filter: blur(10px); |
| @@ -1611,9 +1624,14 @@ | ||
| 1611 | 1624 | } |
| 1612 | 1625 | |
| 1613 | 1626 | /* Connect Status Message Content */ |
| 1614 | 1627 | .metasync-dashboard-wrap .metasync-sa-connect-status-content { |
| 1615 | - flex: 1; | |
| 1628 | + /* min-width: 0 keeps a long unbroken string (a pasted URL, a UUID) from | |
| 1629 | + setting the flex item's min-content width and re-inflating the box. */ | |
| 1630 | + flex: 0 0 auto; | |
| 1631 | + min-width: 0; | |
| 1632 | + /* Spacing between content and actions is the container's gap now. */ | |
| 1633 | + margin-bottom: 0; | |
| 1616 | 1634 | } |
| 1617 | 1635 | |
| 1618 | 1636 | .metasync-dashboard-wrap .metasync-sa-connect-status-title { |
| 1619 | 1637 | font-weight: 600; |
| @@ -1618,11 +1636,15 @@ | ||
| 1618 | 1636 | .metasync-dashboard-wrap .metasync-sa-connect-status-title { |
| 1619 | 1637 | font-weight: 600; |
| 1620 | 1638 | font-size: 15px; |
| 1621 | 1639 | margin-bottom: 8px; |
| 1622 | - display: flex; | |
| 1623 | - align-items: center; | |
| 1624 | - gap: 8px; | |
| 1640 | + /* Block, not flex. WordPress core's emoji script rewrites the leading | |
| 1641 | + emoji into <img class="emoji">; as a flex container that image became a | |
| 1642 | + flex item of its own and, under align-items: center, floated to the | |
| 1643 | + vertical middle of a wrapped title. Inline flow keeps it on the first | |
| 1644 | + line and wraps with the text. The title string already carries the | |
| 1645 | + separating space, so the old gap is not needed. */ | |
| 1646 | + display: block; | |
| 1625 | 1647 | } |
| 1626 | 1648 | |
| 1627 | 1649 | .metasync-dashboard-wrap .metasync-sa-connect-status-message { |
| 1628 | 1650 | font-size: 14px; |
| @@ -1627,14 +1649,14 @@ | ||
| 1627 | 1649 | .metasync-dashboard-wrap .metasync-sa-connect-status-message { |
| 1628 | 1650 | font-size: 14px; |
| 1629 | 1651 | line-height: 1.5; |
| 1630 | 1652 | opacity: 0.9; |
| 1631 | - margin-bottom: 12px; | |
| 1653 | + margin-bottom: 0; | |
| 1632 | 1654 | } |
| 1633 | 1655 | |
| 1634 | 1656 | /* Existing Connect Actions Container */ |
| 1635 | 1657 | .metasync-dashboard-wrap .metasync-sa-connect-actions { |
| 1636 | - margin-top: 16px; | |
| 1658 | + margin-top: 0; | |
| 1637 | 1659 | display: flex; |
| 1638 | 1660 | gap: 12px; |
| 1639 | 1661 | flex-wrap: wrap; |
| 1640 | 1662 | align-items: center; |
| @@ -1711,10 +1733,8 @@ | ||
| 1711 | 1733 | |
| 1712 | 1734 | .metasync-dashboard-wrap .metasync-sa-connect-status { |
| 1713 | 1735 | padding: 16px; |
| 1714 | 1736 | margin-top: 12px; |
| 1715 | - flex-direction: column; | |
| 1716 | - align-items: flex-start; | |
| 1717 | 1737 | gap: 8px; |
| 1718 | 1738 | } |
| 1719 | 1739 | |
| 1720 | 1740 | .metasync-dashboard-wrap .metasync-sa-connect-status-title { |
| @@ -2466,9 +2486,13 @@ | ||
| 2466 | 2486 | /* Sync Log Header */ |
| 2467 | 2487 | .sync-log-header { |
| 2468 | 2488 | display: flex; |
| 2469 | 2489 | justify-content: space-between; |
| 2470 | - align-items: flex-start; | |
| 2490 | + /* Centred rather than flex-start: the title section used to be a two-line | |
| 2491 | + * block (24px heading + description) that read fine top-aligned, but it is | |
| 2492 | + * now a single line of copy sitting beside a 34px control row. Top-aligning | |
| 2493 | + * a one-line block against that row leaves the text visibly high. */ | |
| 2494 | + align-items: center; | |
| 2471 | 2495 | margin-bottom: 30px; |
| 2472 | 2496 | gap: 20px; |
| 2473 | 2497 | } |
| 2474 | 2498 | |
| @@ -2475,14 +2499,11 @@ | ||
| 2475 | 2499 | .sync-log-title-section { |
| 2476 | 2500 | flex: 1; |
| 2477 | 2501 | } |
| 2478 | 2502 | |
| 2479 | -.sync-log-title-section h2 { | |
| 2480 | - color: var(--dashboard-text-primary); | |
| 2481 | - margin-bottom: 8px; | |
| 2482 | - font-size: 24px; | |
| 2483 | - font-weight: 600; | |
| 2484 | -} | |
| 2503 | +/* The card no longer renders an <h2> — the page title and description come | |
| 2504 | + * from the layout header (render_layout_open), and the card carries only the | |
| 2505 | + * 90-day retention hint. See admin/class-metasync-admin.php. */ | |
| 2485 | 2506 | |
| 2486 | 2507 | /* Sync Log Filters */ |
| 2487 | 2508 | .sync-log-filters { |
| 2488 | 2509 | flex-shrink: 0; |
| @@ -2488,34 +2509,73 @@ | ||
| 2488 | 2509 | flex-shrink: 0; |
| 2489 | 2510 | display: flex; |
| 2490 | 2511 | align-items: center; |
| 2491 | 2512 | justify-content: flex-end; |
| 2513 | + gap: 10px; | |
| 2492 | 2514 | } |
| 2493 | 2515 | |
| 2494 | 2516 | .sync-filters-form { |
| 2495 | - display: grid; | |
| 2496 | - grid-template-columns: 1fr 1fr; | |
| 2517 | + display: flex !important; | |
| 2518 | + flex-direction: row !important; | |
| 2519 | + flex-wrap: nowrap; | |
| 2497 | 2520 | gap: 12px; |
| 2498 | 2521 | align-items: center; |
| 2499 | - justify-content: end; | |
| 2500 | - width: auto; | |
| 2501 | - min-width: 280px; | |
| 2502 | 2522 | } |
| 2503 | 2523 | |
| 2504 | 2524 | /* Large screens - optimize filter spacing */ |
| 2505 | 2525 | @media (min-width: 1200px) { |
| 2506 | 2526 | .sync-filters-form { |
| 2507 | - min-width: 320px; | |
| 2508 | 2527 | gap: 16px; |
| 2509 | 2528 | } |
| 2510 | - | |
| 2529 | + | |
| 2511 | 2530 | .sync-filter-select { |
| 2512 | 2531 | min-width: 150px; |
| 2513 | 2532 | } |
| 2514 | 2533 | } |
| 2515 | 2534 | |
| 2535 | +/* | |
| 2536 | + * Changes Log toolbar — one shared height for the Clear Log button and the two | |
| 2537 | + * filter selects. | |
| 2538 | + * | |
| 2539 | + * The button is styled inline in the renderer (padding:6px 14px, no height) and | |
| 2540 | + * rendered ~29px, while the selects picked up WordPress core's own | |
| 2541 | + * `select { min-height: 40px }` (wp-admin forms.css) on top of | |
| 2542 | + * .sync-filter-select's padding — so the button sat noticeably shorter than the | |
| 2543 | + * controls beside it. | |
| 2544 | + * | |
| 2545 | + * min-height is the load-bearing declaration here: core's min-height:40px beats | |
| 2546 | + * a plain height:34px no matter how specific the selector, because min-height | |
| 2547 | + * wins over height by definition. Setting both pins the row at 34px. | |
| 2548 | + */ | |
| 2549 | +#metasync-clear-sync-log-btn, | |
| 2550 | +.sync-log-filters .sync-filter-select { | |
| 2551 | + height: 34px; | |
| 2552 | + min-height: 34px; | |
| 2553 | + box-sizing: border-box; | |
| 2554 | +} | |
| 2555 | + | |
| 2556 | +/* Vertical padding is zeroed so the fixed height above is what the row sees; | |
| 2557 | + * .sync-filter-select's own padding:8px 12px would otherwise fight it. The base | |
| 2558 | + * padding-right (34px, reserving space for the chevron) is !important there and | |
| 2559 | + * still applies. */ | |
| 2560 | +.sync-log-filters .sync-filter-select { | |
| 2561 | + padding-top: 0; | |
| 2562 | + padding-bottom: 0; | |
| 2563 | + line-height: 32px; | |
| 2564 | +} | |
| 2565 | + | |
| 2566 | +/* The button keeps its inline padding:6px 14px, which leaves a 20px content box | |
| 2567 | + * inside the 34px border-box height — too short for a 32px line-height, so the | |
| 2568 | + * label would sit off-centre. Flex centering makes line-height irrelevant. */ | |
| 2569 | +#metasync-clear-sync-log-btn { | |
| 2570 | + display: inline-flex; | |
| 2571 | + align-items: center; | |
| 2572 | + justify-content: center; | |
| 2573 | + line-height: 1; | |
| 2574 | +} | |
| 2575 | + | |
| 2516 | 2576 | .sync-filter-select { |
| 2517 | - background: var(--dashboard-card-bg); | |
| 2577 | + background-color: var(--dashboard-card-bg); | |
| 2518 | 2578 | border: 1px solid var(--dashboard-border); |
| 2519 | 2579 | color: var(--dashboard-text-primary); |
| 2520 | 2580 | padding: 8px 12px; |
| 2521 | 2581 | border-radius: 6px; |
| @@ -2523,16 +2583,16 @@ | ||
| 2523 | 2583 | width: 100%; |
| 2524 | 2584 | min-width: 130px; |
| 2525 | 2585 | transition: all 0.2s ease; |
| 2526 | 2586 | cursor: pointer; |
| 2527 | - appearance: none; | |
| 2528 | - -webkit-appearance: none; | |
| 2529 | - -moz-appearance: none; | |
| 2530 | - background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6,9 12,15 18,9'%3e%3c/polyline%3e%3c/svg%3e"); | |
| 2531 | - background-repeat: no-repeat; | |
| 2532 | - background-position: right 8px center; | |
| 2533 | - background-size: 16px; | |
| 2534 | - padding-right: 32px; | |
| 2587 | + appearance: none !important; | |
| 2588 | + -webkit-appearance: none !important; | |
| 2589 | + -moz-appearance: none !important; | |
| 2590 | + background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23d1d5db' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6,9 12,15 18,9'%3e%3c/polyline%3e%3c/svg%3e") !important; | |
| 2591 | + background-repeat: no-repeat !important; | |
| 2592 | + background-position: right 10px center !important; | |
| 2593 | + background-size: 14px !important; | |
| 2594 | + padding-right: 34px !important; | |
| 2535 | 2595 | white-space: nowrap; |
| 2536 | 2596 | box-sizing: border-box; |
| 2537 | 2597 | } |
| 2538 | 2598 | |
| @@ -2706,13 +2766,20 @@ | ||
| 2706 | 2766 | opacity: 0.6; |
| 2707 | 2767 | color: var(--dashboard-text-secondary); |
| 2708 | 2768 | } |
| 2709 | 2769 | |
| 2710 | -.sync-log-empty h3 { | |
| 2770 | +/* The empty-state heading is an <h2>: the card's own <h2> is gone, so the | |
| 2771 | + * layout's <h1> is the only heading above it and an <h3> here would skip a | |
| 2772 | + * level. Scoped through .metasync-dashboard-wrap to out-specify | |
| 2773 | + * ".metasync-dashboard-wrap .dashboard-card h2" (0,3,1) above, which would | |
| 2774 | + * otherwise impose its 1.5rem card-title sizing and flex display on what is | |
| 2775 | + * a centred empty-state message. Sizing matches the previous <h3>. */ | |
| 2776 | +.metasync-dashboard-wrap .sync-log-empty h2 { | |
| 2711 | 2777 | color: var(--dashboard-text-primary); |
| 2712 | - margin-bottom: 8px; | |
| 2778 | + margin: 0 0 8px 0; | |
| 2713 | 2779 | font-size: 18px; |
| 2714 | 2780 | font-weight: 600; |
| 2781 | + display: block; | |
| 2715 | 2782 | } |
| 2716 | 2783 | |
| 2717 | 2784 | .sync-log-empty p { |
| 2718 | 2785 | font-size: 14px; |
| @@ -2742,8 +2809,61 @@ | ||
| 2742 | 2809 | align-items: center; |
| 2743 | 2810 | gap: 8px; |
| 2744 | 2811 | } |
| 2745 | 2812 | |
| 2813 | +/* | |
| 2814 | + * Rows-per-page selector on the Changes Log footer. | |
| 2815 | + * | |
| 2816 | + * .metasync-per-page-select is emitted by Metasync_Per_Page_Helper::render_selector() | |
| 2817 | + * on four screens (Redirections, 404 Monitor, Changes Log, Media Library), but | |
| 2818 | + * only the other three style it. On the Changes Log it fell through to the | |
| 2819 | + * generic ".metasync-dashboard-wrap select" rule — width:100%, max-width:400px, | |
| 2820 | + * padding:12px 16px — so a two-digit control rendered ~295px wide and 64px tall | |
| 2821 | + * next to 34px dashboard controls. | |
| 2822 | + * | |
| 2823 | + * Scoped to .sync-log-pagination-info, a Changes Log-only wrapper, rather than | |
| 2824 | + * to the shared class: the other three screens already size this control via | |
| 2825 | + * their own rules (".wrap .tablenav select" for Redirections and 404 Monitor, | |
| 2826 | + * "#metasync-image-library-form .tablenav select" for Media Library), and a | |
| 2827 | + * shared rule here would be one more thing competing with them. Keeping it | |
| 2828 | + * page-scoped means those screens are untouched by construction, not by | |
| 2829 | + * winning a specificity tie. | |
| 2830 | + * | |
| 2831 | + * min-height pairs with height for the same reason as the toolbar rule above — | |
| 2832 | + * core's select{min-height:40px} would otherwise inflate it back to 40px. | |
| 2833 | + * | |
| 2834 | + * Sizing only: admin/js/metasync-per-page.js drives behaviour off the element's | |
| 2835 | + * data-* attributes, which CSS must not disturb. | |
| 2836 | + */ | |
| 2837 | +.sync-log-pagination-info .metasync-per-page-select { | |
| 2838 | + height: 34px; | |
| 2839 | + min-height: 34px; | |
| 2840 | + line-height: 32px; | |
| 2841 | + padding: 0 28px 0 10px; | |
| 2842 | + font-size: 13px; | |
| 2843 | + width: auto; | |
| 2844 | + border-radius: 6px; | |
| 2845 | + box-sizing: border-box; | |
| 2846 | + vertical-align: middle; | |
| 2847 | + cursor: pointer; | |
| 2848 | + appearance: none; | |
| 2849 | + -webkit-appearance: none; | |
| 2850 | + -moz-appearance: none; | |
| 2851 | + background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23d1d5db' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6,9 12,15 18,9'%3e%3c/polyline%3e%3c/svg%3E"); | |
| 2852 | + background-repeat: no-repeat; | |
| 2853 | + background-position: right 10px center; | |
| 2854 | + background-size: 14px; | |
| 2855 | +} | |
| 2856 | + | |
| 2857 | +/* Mirrors .sync-filter-select option. The rule above is the first to apply | |
| 2858 | + * appearance:none to this control, and dark-theme <option> popups need their | |
| 2859 | + * colours stated explicitly rather than inherited. */ | |
| 2860 | +.sync-log-pagination-info .metasync-per-page-select option { | |
| 2861 | + background: var(--dashboard-card-bg); | |
| 2862 | + color: var(--dashboard-text-primary); | |
| 2863 | + padding: 8px; | |
| 2864 | +} | |
| 2865 | + | |
| 2746 | 2866 | .sync-pagination-btn { |
| 2747 | 2867 | display: inline-flex; |
| 2748 | 2868 | align-items: center; |
| 2749 | 2869 | justify-content: center; |
| @@ -2795,16 +2915,16 @@ | ||
| 2795 | 2915 | justify-content: center; |
| 2796 | 2916 | } |
| 2797 | 2917 | |
| 2798 | 2918 | .sync-filters-form { |
| 2799 | - display: grid; | |
| 2800 | - grid-template-columns: 1fr 1fr; | |
| 2919 | + display: flex !important; | |
| 2920 | + flex-direction: row !important; | |
| 2921 | + flex-wrap: nowrap; | |
| 2801 | 2922 | gap: 10px; |
| 2923 | + align-items: center; | |
| 2802 | 2924 | justify-content: center; |
| 2803 | - min-width: 260px; | |
| 2804 | - width: auto; | |
| 2805 | 2925 | } |
| 2806 | - | |
| 2926 | + | |
| 2807 | 2927 | .sync-filter-select { |
| 2808 | 2928 | min-width: 120px; |
| 2809 | 2929 | font-size: 13px; |
| 2810 | 2930 | } |
| @@ -2836,16 +2956,20 @@ | ||
| 2836 | 2956 | } |
| 2837 | 2957 | |
| 2838 | 2958 | @media (max-width: 480px) { |
| 2839 | 2959 | .sync-filters-form { |
| 2840 | - display: grid; | |
| 2841 | - grid-template-columns: 1fr 1fr; | |
| 2960 | + display: flex !important; | |
| 2961 | + flex-direction: row !important; | |
| 2962 | + flex-wrap: nowrap; | |
| 2842 | 2963 | gap: 8px; |
| 2843 | - min-width: 240px; | |
| 2844 | 2964 | width: 100%; |
| 2845 | - max-width: 320px; | |
| 2846 | 2965 | } |
| 2847 | 2966 | |
| 2967 | + /* The vertical half of this padding is intentionally overridden by | |
| 2968 | + * ".sync-log-filters .sync-filter-select" (0,2,0) above, which pins the | |
| 2969 | + * toolbar row at 34px. Do NOT re-declare padding here under that | |
| 2970 | + * descendant selector: it would tie on specificity, win on source order, | |
| 2971 | + * and silently restore the misalignment this rule set exists to avoid. */ | |
| 2848 | 2972 | .sync-filter-select { |
| 2849 | 2973 | min-width: 110px; |
| 2850 | 2974 | font-size: 13px; |
| 2851 | 2975 | padding: 6px 8px; |
| @@ -3366,5 +3490,60 @@ | ||
| 3366 | 3490 | font-size: 24px; |
| 3367 | 3491 | width: 24px; |
| 3368 | 3492 | height: 24px; |
| 3369 | 3493 | color: var(--dashboard-text-secondary); |
| 3494 | +} | |
| 3495 | + | |
| 3496 | +/* Dismiss button on plugin notices. | |
| 3497 | + The dashboard script appends a .notice-dismiss to every notice inside | |
| 3498 | + .metasync-dashboard-wrap, but the notice itself was never given a | |
| 3499 | + positioning context, so WordPress core's `position: absolute` on the | |
| 3500 | + button resolved against whatever ancestor happened to be positioned | |
| 3501 | + instead of the notice box — landing the icon mid-text rather than in the | |
| 3502 | + notice's own top-right corner. Anchor it explicitly to the notice. */ | |
| 3503 | +.metasync-dashboard-wrap .notice { | |
| 3504 | + position: relative; | |
| 3505 | +} | |
| 3506 | + | |
| 3507 | +.metasync-dashboard-wrap .notice-dismiss { | |
| 3508 | + position: absolute; | |
| 3509 | + top: 8px; | |
| 3510 | + right: 8px; | |
| 3511 | + width: 28px; | |
| 3512 | + height: 28px; | |
| 3513 | + display: flex; | |
| 3514 | + align-items: center; | |
| 3515 | + justify-content: center; | |
| 3516 | +} | |
| 3517 | + | |
| 3518 | +/* WordPress core colours the dismiss icon a near-black grey (#1e1e1e), which | |
| 3519 | + reads fine on the light theme but is effectively invisible against the dark | |
| 3520 | + theme's card background. Give it a theme-aware colour instead. !important | |
| 3521 | + because the icon's colour otherwise wins on specificity alone, the same way | |
| 3522 | + the base .notice rule above needs !important to beat WP core. | |
| 3523 | + `.metasync-dashboard-wrap[data-theme="dark"]` matches the common case: the | |
| 3524 | + wrap carries data-theme itself (set server-side on page load). The plain | |
| 3525 | + `[data-theme="dark"] .metasync-dashboard-wrap` descendant form is kept too, | |
| 3526 | + since the in-page theme switcher additionally stamps data-theme on <html> | |
| 3527 | + once the user toggles it, and either could be the one present. */ | |
| 3528 | +.metasync-dashboard-wrap[data-theme="dark"] .notice-dismiss::before, | |
| 3529 | +[data-theme="dark"] .metasync-dashboard-wrap .notice-dismiss::before { | |
| 3530 | + color: var(--dashboard-text-secondary) !important; | |
| 3531 | +} | |
| 3532 | + | |
| 3533 | +.metasync-dashboard-wrap[data-theme="dark"] .notice-dismiss:hover::before, | |
| 3534 | +.metasync-dashboard-wrap[data-theme="dark"] .notice-dismiss:focus::before, | |
| 3535 | +[data-theme="dark"] .metasync-dashboard-wrap .notice-dismiss:hover::before, | |
| 3536 | +[data-theme="dark"] .metasync-dashboard-wrap .notice-dismiss:focus::before { | |
| 3537 | + color: var(--dashboard-text-primary) !important; | |
| 3538 | +} | |
| 3539 | + | |
| 3540 | +/* Remove WordPress footer space on MetaSync admin pages. */ | |
| 3541 | +body:has(.metasync-dashboard-wrap) #wpbody-content, | |
| 3542 | +body:has(.metasync-otto-debug) #wpbody-content { | |
| 3543 | + padding-bottom: 0; | |
| 3544 | +} | |
| 3545 | + | |
| 3546 | +body:has(.metasync-dashboard-wrap) #wpfooter, | |
| 3547 | +body:has(.metasync-otto-debug) #wpfooter { | |
| 3548 | + display: none; | |
| 3370 | 3549 | } |