| @@ -610,8 +610,19 @@ | ||
| 610 | 610 | input:checked + .mxchat-toggle-slider:before { |
| 611 | 611 | transform: translateX(26px); |
| 612 | 612 | } |
| 613 | 613 | |
| 614 | +/* Group-level ACF toggle, mixed state: some fields in the group are excluded. | |
| 615 | + Knob parks mid-track on a washed-out tint of the brand gradient until the | |
| 616 | + owner picks a side (plan bf57e0). */ | |
| 617 | +input:indeterminate + .mxchat-toggle-slider { | |
| 618 | + background: linear-gradient(135deg, #e3b8dd, #b9b6e8); | |
| 619 | +} | |
| 620 | + | |
| 621 | +input:indeterminate + .mxchat-toggle-slider:before { | |
| 622 | + transform: translateX(13px); | |
| 623 | +} | |
| 624 | + | |
| 614 | 625 | .mxchat-toggle-label { |
| 615 | 626 | font-size: 14px; |
| 616 | 627 | color: #333; |
| 617 | 628 | } |
| @@ -1211,8 +1222,12 @@ | ||
| 1211 | 1222 | .rtl input:checked + .mxchat-toggle-slider:before { |
| 1212 | 1223 | transform: translateX(-26px); |
| 1213 | 1224 | } |
| 1214 | 1225 | |
| 1226 | +.rtl input:indeterminate + .mxchat-toggle-slider:before { | |
| 1227 | + transform: translateX(-13px); | |
| 1228 | +} | |
| 1229 | + | |
| 1215 | 1230 | .rtl .mxchat-error-notice { |
| 1216 | 1231 | border-left: none; |
| 1217 | 1232 | border-right: 3px solid #f44336; |
| 1218 | 1233 | } |
| @@ -1280,20 +1295,36 @@ | ||
| 1280 | 1295 | |
| 1281 | 1296 | .mxchat-kb-modal-content { |
| 1282 | 1297 | position: relative; |
| 1283 | 1298 | background-color: #fff; |
| 1284 | - margin: 50px auto; | |
| 1299 | + margin: 24px auto; | |
| 1285 | 1300 | padding: 0; |
| 1286 | 1301 | border-radius: 8px; |
| 1287 | 1302 | box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); |
| 1288 | 1303 | width: 90%; |
| 1289 | 1304 | max-width: 1000px; |
| 1305 | + /* The box is the ONLY place height is constrained; children flex within it. | |
| 1306 | + dvh tracks the real visible viewport on mobile (vh line = older-browser fallback). */ | |
| 1290 | 1307 | max-height: 85vh; |
| 1308 | + max-height: min(85vh, calc(100dvh - 48px)); | |
| 1291 | 1309 | display: flex; |
| 1292 | 1310 | flex-direction: column; |
| 1293 | 1311 | animation: mxchat-kb-modal-appear 0.3s ease-out; |
| 1294 | 1312 | } |
| 1295 | 1313 | |
| 1314 | +/* Fixed chrome rows never grow or shrink — the results list is the only scroller. */ | |
| 1315 | +.mxchat-kb-modal-header, | |
| 1316 | +.mxchat-kb-modal-filters, | |
| 1317 | +.mxchat-kb-selection-header, | |
| 1318 | +.mxchat-kb-modal-footer { | |
| 1319 | + flex: 0 0 auto; | |
| 1320 | +} | |
| 1321 | + | |
| 1322 | +/* The footer holds the primary actions — it can never be squeezed out of the box. */ | |
| 1323 | +.mxchat-kb-modal-footer { | |
| 1324 | + flex-shrink: 0; | |
| 1325 | +} | |
| 1326 | + | |
| 1296 | 1327 | @keyframes mxchat-kb-modal-appear { |
| 1297 | 1328 | from { |
| 1298 | 1329 | opacity: 0; |
| 1299 | 1330 | transform: translateY(-30px); |
| @@ -1407,12 +1438,15 @@ | ||
| 1407 | 1438 | border-left: 3px solid #1e88e5; |
| 1408 | 1439 | } |
| 1409 | 1440 | |
| 1410 | 1441 | .mxchat-kb-content-selection { |
| 1411 | - overflow-y: auto; | |
| 1412 | - flex: 1; | |
| 1413 | - min-height: 300px; | |
| 1414 | - max-height: calc(85vh - 200px); | |
| 1442 | + /* Flexible middle region: header row stays put, the list below scrolls. | |
| 1443 | + min-height: 0 is load-bearing — without it flex refuses to shrink this | |
| 1444 | + column and the footer gets pushed out of the box (the mobile bug). */ | |
| 1445 | + flex: 1 1 auto; | |
| 1446 | + min-height: 0; | |
| 1447 | + display: flex; | |
| 1448 | + flex-direction: column; | |
| 1415 | 1449 | } |
| 1416 | 1450 | |
| 1417 | 1451 | .mxchat-kb-selection-header { |
| 1418 | 1452 | display: flex; |
| @@ -1440,8 +1474,12 @@ | ||
| 1440 | 1474 | } |
| 1441 | 1475 | |
| 1442 | 1476 | .mxchat-kb-content-list { |
| 1443 | 1477 | padding: 0; |
| 1478 | + /* The one and only scroller inside the modal. */ | |
| 1479 | + flex: 1 1 auto; | |
| 1480 | + min-height: 0; | |
| 1481 | + overflow-y: auto; | |
| 1444 | 1482 | } |
| 1445 | 1483 | |
| 1446 | 1484 | .mxchat-kb-content-item { |
| 1447 | 1485 | display: flex; |
| @@ -1470,19 +1508,23 @@ | ||
| 1470 | 1508 | align-items: flex-start; |
| 1471 | 1509 | padding-top: 3px; |
| 1472 | 1510 | } |
| 1473 | 1511 | |
| 1512 | +/* Native control, brand-tinted — identical to the "select all" checkbox above the | |
| 1513 | + list, which carries no custom styling at all and renders correctly. | |
| 1514 | + Do NOT re-add width / height / border / border-radius / background here. WP admin | |
| 1515 | + draws the tick as a 21px dashicon positioned with negative margins for its OWN | |
| 1516 | + default box, so forcing a custom box makes the tick overflow it. That mismatch | |
| 1517 | + shipped for a long time but was invisible while the tick was white-on-white. */ | |
| 1474 | 1518 | .mxchat-kb-content-checkbox input[type="checkbox"] { |
| 1475 | - width: 18px; | |
| 1476 | - height: 18px; | |
| 1477 | - border: 1px solid #8c8f94; | |
| 1478 | - border-radius: 3px; | |
| 1479 | - background: #fff; | |
| 1480 | 1519 | margin: 0; |
| 1520 | + cursor: pointer; | |
| 1521 | + accent-color: var(--mxch-primary, #7873f5); | |
| 1481 | 1522 | } |
| 1482 | 1523 | |
| 1483 | -.mxchat-kb-content-checkbox input[type="checkbox"]:checked { | |
| 1484 | - border-color: #7873f5; | |
| 1524 | +.mxchat-kb-content-checkbox input[type="checkbox"]:focus-visible { | |
| 1525 | + outline: 2px solid var(--mxch-primary, #7873f5); | |
| 1526 | + outline-offset: 2px; | |
| 1485 | 1527 | } |
| 1486 | 1528 | |
| 1487 | 1529 | .mxchat-kb-content-details { |
| 1488 | 1530 | flex: 1; |
| @@ -1854,38 +1896,70 @@ | ||
| 1854 | 1896 | |
| 1855 | 1897 | /* Modal responsive adjustments */ |
| 1856 | 1898 | .mxchat-kb-modal-content { |
| 1857 | 1899 | width: 95%; |
| 1858 | - max-height: 90vh; | |
| 1859 | - margin: 20px auto; | |
| 1900 | + /* dvh = real visible viewport (mobile vh includes the URL-bar region); | |
| 1901 | + vh line is the older-browser fallback. */ | |
| 1902 | + max-height: calc(100vh - 24px); | |
| 1903 | + max-height: calc(100dvh - 24px); | |
| 1904 | + margin: 12px auto; | |
| 1905 | + /* Last-resort scroll: on extreme-short viewports (landscape phones) | |
| 1906 | + the compacted chrome + the list's floor can still exceed the box — | |
| 1907 | + scroll inside the box rather than clipping the footer. */ | |
| 1908 | + overflow-y: auto; | |
| 1860 | 1909 | } |
| 1861 | - | |
| 1910 | + | |
| 1911 | + /* Compact the fixed chrome on mobile — stacked filters + a stacked footer | |
| 1912 | + are tall, and every saved pixel goes to the content list. */ | |
| 1913 | + .mxchat-kb-modal-header { | |
| 1914 | + padding: 12px 16px; | |
| 1915 | + } | |
| 1916 | + | |
| 1917 | + .mxchat-kb-modal-header h3 { | |
| 1918 | + font-size: 16px; | |
| 1919 | + } | |
| 1920 | + | |
| 1862 | 1921 | .mxchat-kb-modal-filters { |
| 1863 | 1922 | flex-direction: column; |
| 1864 | 1923 | align-items: stretch; |
| 1924 | + padding: 10px 16px; | |
| 1925 | + gap: 8px; | |
| 1865 | 1926 | } |
| 1866 | - | |
| 1927 | + | |
| 1867 | 1928 | .mxchat-kb-search-group { |
| 1868 | 1929 | max-width: none; |
| 1869 | 1930 | } |
| 1870 | - | |
| 1931 | + | |
| 1871 | 1932 | .mxchat-kb-filter-group { |
| 1872 | 1933 | flex-direction: column; |
| 1934 | + gap: 8px; | |
| 1873 | 1935 | } |
| 1874 | - | |
| 1875 | - .mxchat-kb-content-selection { | |
| 1876 | - max-height: calc(90vh - 250px); | |
| 1936 | + | |
| 1937 | + .mxchat-kb-filter-group select { | |
| 1938 | + padding: 6px 30px 6px 10px; | |
| 1877 | 1939 | } |
| 1878 | - | |
| 1940 | + | |
| 1879 | 1941 | .mxchat-kb-selection-header { |
| 1880 | 1942 | flex-direction: column; |
| 1881 | 1943 | align-items: flex-start; |
| 1882 | - gap: 10px; | |
| 1944 | + gap: 6px; | |
| 1945 | + padding: 10px 16px; | |
| 1883 | 1946 | } |
| 1884 | - | |
| 1947 | + | |
| 1948 | + /* Guarantee a usable slice of visible rows — reachable buttons are no | |
| 1949 | + help if there is nothing to select above them. */ | |
| 1950 | + .mxchat-kb-content-list { | |
| 1951 | + min-height: 96px; | |
| 1952 | + } | |
| 1953 | + | |
| 1954 | + .mxchat-kb-content-item { | |
| 1955 | + padding: 10px 16px; | |
| 1956 | + } | |
| 1957 | + | |
| 1885 | 1958 | .mxchat-kb-modal-footer { |
| 1886 | 1959 | flex-direction: column; |
| 1887 | - gap: 10px; | |
| 1960 | + gap: 8px; | |
| 1961 | + padding: 10px 16px; | |
| 1888 | 1962 | } |
| 1889 | 1963 | |
| 1890 | 1964 | .mxchat-kb-modal-footer .mxchat-kb-pagination { |
| 1891 | 1965 | width: 100%; |
| @@ -3755,13 +3829,18 @@ | ||
| 3755 | 3829 | } |
| 3756 | 3830 | |
| 3757 | 3831 | .mxchat-kb-edit-modal-content { |
| 3758 | 3832 | max-width: 760px; |
| 3833 | + /* Same viewport-safe cap as the content-selector modal (vh = fallback). */ | |
| 3759 | 3834 | max-height: 90vh; |
| 3835 | + max-height: min(90vh, calc(100dvh - 24px)); | |
| 3760 | 3836 | } |
| 3761 | 3837 | |
| 3762 | 3838 | .mxchat-kb-edit-body { |
| 3763 | - flex: 1; | |
| 3839 | + flex: 1 1 auto; | |
| 3840 | + /* min-height: 0 lets the body shrink inside the capped modal box so the | |
| 3841 | + footer (Save/Cancel) can never be pushed below the viewport. */ | |
| 3842 | + min-height: 0; | |
| 3764 | 3843 | display: flex; |
| 3765 | 3844 | flex-direction: column; |
| 3766 | 3845 | padding: 20px; |
| 3767 | 3846 | overflow: hidden; |
| @@ -3814,8 +3893,10 @@ | ||
| 3814 | 3893 | justify-content: space-between; |
| 3815 | 3894 | padding: 14px 20px; |
| 3816 | 3895 | border-top: 1px solid #e5e5e5; |
| 3817 | 3896 | gap: 12px; |
| 3897 | + /* Action row can never be squeezed out of the box. */ | |
| 3898 | + flex-shrink: 0; | |
| 3818 | 3899 | } |
| 3819 | 3900 | |
| 3820 | 3901 | .mxchat-kb-edit-notice { |
| 3821 | 3902 | flex: 1; |
| @@ -3835,9 +3916,11 @@ | ||
| 3835 | 3916 | match-card / chunk-detail components (admin-testing-tab.css, scoped under |
| 3836 | 3917 | .mxch-testing-results) so it looks native; this block only adds the modal |
| 3837 | 3918 | body scroll + the chunk-text container the Testing tab doesn't have. */ |
| 3838 | 3919 | .mxchat-kb-inspect-body { |
| 3839 | - flex: 1; | |
| 3920 | + flex: 1 1 auto; | |
| 3921 | + /* Same footer-pushout guard as the edit modal. */ | |
| 3922 | + min-height: 0; | |
| 3840 | 3923 | display: flex; |
| 3841 | 3924 | flex-direction: column; |
| 3842 | 3925 | padding: 20px; |
| 3843 | 3926 | overflow-y: auto; |
| @@ -3875,9 +3958,10 @@ | ||
| 3875 | 3958 | .mxchat-kb-edit-modal-content { |
| 3876 | 3959 | width: 96%; |
| 3877 | 3960 | max-width: 96%; |
| 3878 | 3961 | margin: 10px auto; |
| 3879 | - max-height: 95vh; | |
| 3962 | + max-height: calc(100vh - 20px); | |
| 3963 | + max-height: calc(100dvh - 20px); | |
| 3880 | 3964 | } |
| 3881 | 3965 | .mxchat-kb-edit-body { |
| 3882 | 3966 | padding: 14px; |
| 3883 | 3967 | } |