| @@ -1238,8 +1238,65 @@ | ||
| 1238 | 1238 | //Doc Layout 7 Controls End |
| 1239 | 1239 | |
| 1240 | 1240 | /** Single Doc Start **/ |
| 1241 | 1241 | |
| 1242 | +/** | |
| 1243 | + * Single Doc Content Area Width / Maximum Width. | |
| 1244 | + * | |
| 1245 | + * One pair of settings, three selectors — each layout family caps its content | |
| 1246 | + * wrapper through a different rule in the stylesheet, so the override has to | |
| 1247 | + * match the rule it is replacing: | |
| 1248 | + * | |
| 1249 | + * layouts 8 / 9 / 10 .betterdocs-wrapper.betterdocs-single-layout-8 ... | |
| 1250 | + * (9 and 10 also carry the layout-8 class) | |
| 1251 | + * layouts 1 / 6 ...:not(.betterdocs-fluid-wrapper) — these two are the | |
| 1252 | + * only single layouts without the fluid class | |
| 1253 | + * layout 5 .betterdocs-single-layout-5 ... | |
| 1254 | + * | |
| 1255 | + * The 1/6 selector is additionally scoped to .betterdocs-single-wrapper: the | |
| 1256 | + * docs-archive and category-archive wrappers are also non-fluid, and they have | |
| 1257 | + * their own width controls (betterdocs_doc_page_content_* / | |
| 1258 | + * betterdocs_archive_content_area_*) that this would otherwise override. | |
| 1259 | + * | |
| 1260 | + * Layouts 2, 3 and 4 are deliberately absent — they are full-bleed and both | |
| 1261 | + * controls are hidden for them in customizer-condition.js. | |
| 1262 | + */ | |
| 1263 | +/** | |
| 1264 | + * Each selector is prefixed with `body` purely to win the cascade. The base | |
| 1265 | + * caps live in common/_normalizer.scss and templates/single.scss, which are | |
| 1266 | + * @imported into a dozen front-end bundles (single.css, article-summary.css, | |
| 1267 | + * category-grid.css, reactions.css, …), so the identical 0,3,0 rule is emitted | |
| 1268 | + * many times over and several of those stylesheets load *after* this inline | |
| 1269 | + * block in wp_head. At equal specificity the last one would win and the | |
| 1270 | + * setting would silently do nothing. One element selector takes us to 0,3,1 | |
| 1271 | + * and beats every copy without resorting to !important. | |
| 1272 | + */ | |
| 1273 | +$betterdocs_single_content_width_selectors = [ | |
| 1274 | + 'body .betterdocs-wrapper.betterdocs-single-layout-8 .betterdocs-content-wrapper', | |
| 1275 | + 'body .betterdocs-wrapper.betterdocs-single-wrapper:not(.betterdocs-fluid-wrapper) .betterdocs-content-wrapper', | |
| 1276 | + 'body .betterdocs-single-layout-5 .betterdocs-content-wrapper' | |
| 1277 | +]; | |
| 1278 | + | |
| 1279 | +$css->add_rule( | |
| 1280 | + $betterdocs_single_content_width_selectors, | |
| 1281 | + $css->properties( | |
| 1282 | + [ | |
| 1283 | + 'width' => 'betterdocs_single_doc_content_width' | |
| 1284 | + ], | |
| 1285 | + '%' | |
| 1286 | + ) | |
| 1287 | +); | |
| 1288 | + | |
| 1289 | +$css->add_rule( | |
| 1290 | + $betterdocs_single_content_width_selectors, | |
| 1291 | + $css->properties( | |
| 1292 | + [ | |
| 1293 | + 'max-width' => 'betterdocs_single_doc_content_max_width' | |
| 1294 | + ], | |
| 1295 | + 'px' | |
| 1296 | + ) | |
| 1297 | +); | |
| 1298 | + | |
| 1242 | 1299 | //Single Doc Common Controllers Content Area Background Color |
| 1243 | 1300 | $css->add_rule( |
| 1244 | 1301 | '.betterdocs-wrapper.betterdocs-single-wrapper .betterdocs-content-wrapper', |
| 1245 | 1302 | $css->properties( |
| @@ -10008,8 +10065,335 @@ | ||
| 10008 | 10065 | 'padding-top' => 'betterdocs_doc_single_content_est_reading_padding_top', |
| 10009 | 10066 | 'padding-right' => 'betterdocs_doc_single_content_est_reading_padding_right', |
| 10010 | 10067 | 'padding-bottom' => 'betterdocs_doc_single_content_est_reading_padding_bottom', |
| 10011 | 10068 | 'padding-left' => 'betterdocs_doc_single_content_est_reading_padding_left' |
| 10069 | + ], | |
| 10070 | + 'px' | |
| 10071 | + ) | |
| 10072 | +); | |
| 10073 | + | |
| 10074 | +//ai actions background + border | |
| 10075 | +// Background, border and radius go on the WRAPPER, not on the two halves. | |
| 10076 | +// scss/template-parts/ai-actions.scss paints the pill on .betterdocs-ai-actions | |
| 10077 | +// and leaves both halves transparent with `border: 0`; the halves only own the | |
| 10078 | +// split divider and the :hover fill. Writing a background onto | |
| 10079 | +// .betterdocs-ai-actions-primary here would beat its own `:hover` rule and kill | |
| 10080 | +// hover feedback outright. | |
| 10081 | +// | |
| 10082 | +// Every selector in this block is deliberately TWO classes. The block editor and | |
| 10083 | +// Elementor write their per-instance rules at three, so an author who styles one | |
| 10084 | +// instance still beats these site-wide defaults — which are real values now, not | |
| 10085 | +// the empty strings that used to make this section emit nothing. Add a third | |
| 10086 | +// class here and every block and widget instance inside a classic single-doc | |
| 10087 | +// template silently freezes at the Customizer's values. | |
| 10088 | +$css->add_rule( | |
| 10089 | + '.betterdocs-content-area .betterdocs-ai-actions', | |
| 10090 | + $css->properties( | |
| 10091 | + [ | |
| 10092 | + 'background-color' => 'betterdocs_doc_single_content_ai_actions_bg_color', | |
| 10093 | + 'border-color' => 'betterdocs_doc_single_content_ai_actions_border_color', | |
| 10094 | + // Literal, not a setting: the stylesheet ships `border: 0`, which is | |
| 10095 | + // shorthand for `border-style: none`, and a border-width with no style | |
| 10096 | + // draws nothing. Without this the Border Width and Border Color | |
| 10097 | + // controls both appeared dead — they were writing values the browser | |
| 10098 | + // then had no reason to paint. Harmless at the default width of 0. | |
| 10099 | + 'border-style' => 'solid' | |
| 10100 | + ] | |
| 10101 | + ) | |
| 10102 | +); | |
| 10103 | + | |
| 10104 | +// The divider between the label and the caret is a pseudo-element on the toggle | |
| 10105 | +// — a centred 14px line rather than a full-height border — so it takes the | |
| 10106 | +// border colour through `background-color`, not `border-inline-start-color`. | |
| 10107 | +$css->add_rule( | |
| 10108 | + '.betterdocs-content-area .betterdocs-ai-actions-toggle::before', | |
| 10109 | + $css->properties( | |
| 10110 | + [ | |
| 10111 | + 'background-color' => 'betterdocs_doc_single_content_ai_actions_border_color' | |
| 10112 | + ] | |
| 10113 | + ) | |
| 10114 | +); | |
| 10115 | + | |
| 10116 | +$css->add_rule( | |
| 10117 | + '.betterdocs-content-area .betterdocs-ai-actions', | |
| 10118 | + $css->properties( | |
| 10119 | + [ | |
| 10120 | + 'border-width' => 'betterdocs_doc_single_content_ai_actions_border_width', | |
| 10121 | + 'border-radius' => 'betterdocs_doc_single_content_ai_actions_border_radius' | |
| 10122 | + ], | |
| 10123 | + 'px' | |
| 10124 | + ) | |
| 10125 | +); | |
| 10126 | + | |
| 10127 | +// The wrapper cannot clip its halves — .betterdocs-ai-actions-menu is absolutely | |
| 10128 | +// positioned and `overflow: hidden` would cut the dropdown off — so each half | |
| 10129 | +// carries its own outer corners, 16px in the stylesheet. Left alone, a user-set | |
| 10130 | +// radius leaves the halves square enough that the :hover fill visibly overhangs | |
| 10131 | +// the wrapper's curve. Re-emit the corners each half actually owns. | |
| 10132 | +$css->add_rule( | |
| 10133 | + '.betterdocs-content-area .betterdocs-ai-actions-primary', | |
| 10134 | + $css->properties( | |
| 10135 | + [ | |
| 10136 | + 'border-start-start-radius' => 'betterdocs_doc_single_content_ai_actions_border_radius', | |
| 10137 | + 'border-end-start-radius' => 'betterdocs_doc_single_content_ai_actions_border_radius' | |
| 10138 | + ], | |
| 10139 | + 'px' | |
| 10140 | + ) | |
| 10141 | +); | |
| 10142 | + | |
| 10143 | +$css->add_rule( | |
| 10144 | + '.betterdocs-content-area .betterdocs-ai-actions-toggle', | |
| 10145 | + $css->properties( | |
| 10146 | + [ | |
| 10147 | + 'border-start-end-radius' => 'betterdocs_doc_single_content_ai_actions_border_radius', | |
| 10148 | + 'border-end-end-radius' => 'betterdocs_doc_single_content_ai_actions_border_radius' | |
| 10149 | + ], | |
| 10150 | + 'px' | |
| 10151 | + ) | |
| 10152 | +); | |
| 10153 | + | |
| 10154 | +// With "Copy page" switched off there is no primary half and the disclosure owns | |
| 10155 | +// the whole control, so it needs all four corners rather than just the end pair. | |
| 10156 | +// Unscoped by `.betterdocs-content-area` on purpose: that would be the third | |
| 10157 | +// class this block cannot afford, and `-no-primary` is a class only this feature | |
| 10158 | +// ever emits. Declared after the rule above, at equal specificity, so the | |
| 10159 | +// shorthand wins. | |
| 10160 | +$css->add_rule( | |
| 10161 | + '.betterdocs-ai-actions-no-primary .betterdocs-ai-actions-toggle', | |
| 10162 | + $css->properties( | |
| 10163 | + [ | |
| 10164 | + 'border-radius' => 'betterdocs_doc_single_content_ai_actions_border_radius' | |
| 10165 | + ], | |
| 10166 | + 'px' | |
| 10167 | + ) | |
| 10168 | +); | |
| 10169 | + | |
| 10170 | +//ai actions label colour + typography | |
| 10171 | +$css->add_rule( | |
| 10172 | + '.betterdocs-content-area .betterdocs-ai-actions-label', | |
| 10173 | + $css->properties( | |
| 10174 | + [ | |
| 10175 | + 'color' => 'betterdocs_doc_single_content_ai_actions_color', | |
| 10176 | + 'font-weight' => 'betterdocs_doc_single_content_ai_actions_font_weight' | |
| 10177 | + ] | |
| 10178 | + ) | |
| 10179 | +); | |
| 10180 | + | |
| 10181 | +$css->add_rule( | |
| 10182 | + '.betterdocs-content-area .betterdocs-ai-actions-label', | |
| 10183 | + $css->properties( | |
| 10184 | + [ | |
| 10185 | + 'font-size' => 'betterdocs_doc_single_content_ai_actions_font_size' | |
| 10186 | + ], | |
| 10187 | + 'px' | |
| 10188 | + ) | |
| 10189 | +); | |
| 10190 | + | |
| 10191 | +//ai actions icon colour | |
| 10192 | +// One declaration covers the copy glyph, the copied tick, the failure mark and | |
| 10193 | +// the caret: every icon AIActions::icon() draws is stroked with `currentColor`, | |
| 10194 | +// so setting `color` on the svg itself is enough, and an entry that supplies | |
| 10195 | +// its own `fill="currentColor"` follows too. Same two selectors as the size | |
| 10196 | +// rule below — two classes, keeping this section's specificity contract. | |
| 10197 | +$css->add_rule( | |
| 10198 | + [ | |
| 10199 | + '.betterdocs-content-area .betterdocs-ai-actions-primary svg', | |
| 10200 | + '.betterdocs-content-area .betterdocs-ai-actions-toggle svg' | |
| 10201 | + ], | |
| 10202 | + $css->properties( | |
| 10203 | + [ | |
| 10204 | + 'color' => 'betterdocs_doc_single_content_ai_actions_icon_color' | |
| 10205 | + ] | |
| 10206 | + ) | |
| 10207 | +); | |
| 10208 | + | |
| 10209 | +//ai actions icon size | |
| 10210 | +// The primary half carries three icons — idle, copied, failed — and CSS shows | |
| 10211 | +// one at a time, so sizing every svg in the half keeps the button from changing | |
| 10212 | +// width when the state flips. | |
| 10213 | +$css->add_rule( | |
| 10214 | + [ | |
| 10215 | + '.betterdocs-content-area .betterdocs-ai-actions-primary svg', | |
| 10216 | + '.betterdocs-content-area .betterdocs-ai-actions-toggle svg' | |
| 10217 | + ], | |
| 10218 | + $css->properties( | |
| 10219 | + [ | |
| 10220 | + 'width' => 'betterdocs_doc_single_content_ai_actions_icon_size', | |
| 10221 | + 'height' => 'betterdocs_doc_single_content_ai_actions_icon_size' | |
| 10222 | + ], | |
| 10223 | + 'px' | |
| 10224 | + ) | |
| 10225 | +); | |
| 10226 | + | |
| 10227 | +//ai actions padding top, right, bottom, left | |
| 10228 | +// Applied to both halves, matching the block and the Elementor widget. The | |
| 10229 | +// stylesheet ships 5px 10px on the primary and 5px 8px on the toggle, so a | |
| 10230 | +// single control makes the caret half as wide as the label half. | |
| 10231 | +$css->add_rule( | |
| 10232 | + [ | |
| 10233 | + '.betterdocs-content-area .betterdocs-ai-actions-primary', | |
| 10234 | + '.betterdocs-content-area .betterdocs-ai-actions-toggle' | |
| 10235 | + ], | |
| 10236 | + $css->properties( | |
| 10237 | + [ | |
| 10238 | + 'padding-top' => 'betterdocs_doc_single_content_ai_actions_padding_top', | |
| 10239 | + 'padding-right' => 'betterdocs_doc_single_content_ai_actions_padding_right', | |
| 10240 | + 'padding-bottom' => 'betterdocs_doc_single_content_ai_actions_padding_bottom', | |
| 10241 | + 'padding-left' => 'betterdocs_doc_single_content_ai_actions_padding_left' | |
| 10242 | + ], | |
| 10243 | + 'px' | |
| 10244 | + ) | |
| 10245 | +); | |
| 10246 | + | |
| 10247 | +//listen background + border | |
| 10248 | +// The pill is one element — `.betterdocs-listen` — so unlike AI Actions there are | |
| 10249 | +// no halves to keep symmetrical and the background, border and radius all go in | |
| 10250 | +// one place. The `overflow: hidden` that clips the morph lives there too, which is | |
| 10251 | +// also why the radius needs no second rule: nothing sticks out of it to round. | |
| 10252 | +// | |
| 10253 | +// Every selector in this block is deliberately TWO classes. The block editor and | |
| 10254 | +// Elementor write their per-instance rules at three, so an author who styles one | |
| 10255 | +// instance still beats these site-wide defaults — which are real values, not the | |
| 10256 | +// empty strings an untouched section would carry. Add a third class here and every | |
| 10257 | +// block and widget instance inside a classic single-doc template silently freezes | |
| 10258 | +// at the Customizer's values. | |
| 10259 | +$css->add_rule( | |
| 10260 | + '.betterdocs-content-area .betterdocs-listen', | |
| 10261 | + $css->properties( | |
| 10262 | + [ | |
| 10263 | + 'background-color' => 'betterdocs_doc_single_content_listen_bg_color', | |
| 10264 | + 'border-color' => 'betterdocs_doc_single_content_listen_border_color', | |
| 10265 | + // Literal, not a setting: the stylesheet ships `border: 0`, which is | |
| 10266 | + // shorthand for `border-style: none`, and a border-width with no style | |
| 10267 | + // draws nothing. Without this the Border Width and Border Color | |
| 10268 | + // controls both appear dead. Harmless at the default width of 0. | |
| 10269 | + 'border-style' => 'solid' | |
| 10270 | + ] | |
| 10271 | + ) | |
| 10272 | +); | |
| 10273 | + | |
| 10274 | +$css->add_rule( | |
| 10275 | + '.betterdocs-content-area .betterdocs-listen', | |
| 10276 | + $css->properties( | |
| 10277 | + [ | |
| 10278 | + 'border-width' => 'betterdocs_doc_single_content_listen_border_width', | |
| 10279 | + 'border-radius' => 'betterdocs_doc_single_content_listen_border_radius' | |
| 10280 | + ], | |
| 10281 | + 'px' | |
| 10282 | + ) | |
| 10283 | +); | |
| 10284 | + | |
| 10285 | +// The collapsed pill's own corner. It fills the wrapper, so with `overflow: | |
| 10286 | +// hidden` above this is belt and braces — but the trigger is the element a theme's | |
| 10287 | +// `button { border-radius }` would hit, and listen.scss states the corner there | |
| 10288 | +// for that reason. A Customizer radius that stopped at the wrapper would leave a | |
| 10289 | +// theme's square button showing through the moment somebody changed it. | |
| 10290 | +$css->add_rule( | |
| 10291 | + '.betterdocs-content-area .betterdocs-listen-trigger', | |
| 10292 | + $css->properties( | |
| 10293 | + [ | |
| 10294 | + 'border-radius' => 'betterdocs_doc_single_content_listen_border_radius' | |
| 10295 | + ], | |
| 10296 | + 'px' | |
| 10297 | + ) | |
| 10298 | +); | |
| 10299 | + | |
| 10300 | +//listen label colour | |
| 10301 | +$css->add_rule( | |
| 10302 | + '.betterdocs-content-area .betterdocs-listen-label', | |
| 10303 | + $css->properties( | |
| 10304 | + [ | |
| 10305 | + 'color' => 'betterdocs_doc_single_content_listen_color' | |
| 10306 | + ] | |
| 10307 | + ) | |
| 10308 | +); | |
| 10309 | + | |
| 10310 | +//listen typography | |
| 10311 | +// Both on the WRAPPER, not on the label, and that placement is load-bearing twice | |
| 10312 | +// over: | |
| 10313 | +// | |
| 10314 | +// - The player's readout is sized in `em`, so a font-size here scales the pill and | |
| 10315 | +// the player together. On the label alone the clock would stay at 12.6px however | |
| 10316 | +// large the label grew. | |
| 10317 | +// - The block and Elementor both write their Listen typography on the wrapper too. | |
| 10318 | +// A `font-weight` declared directly on `.betterdocs-listen-label` would beat one | |
| 10319 | +// the label merely INHERITS from the wrapper no matter how specific that rule is | |
| 10320 | +// — specificity never enters into it — so this section would silently kill the | |
| 10321 | +// per-instance Font Weight control on every classic single-doc template. It did, | |
| 10322 | +// from the moment Defaults.php started shipping a real `normal` instead of ''. | |
| 10323 | +$css->add_rule( | |
| 10324 | + '.betterdocs-content-area .betterdocs-listen', | |
| 10325 | + $css->properties( | |
| 10326 | + [ | |
| 10327 | + 'font-weight' => 'betterdocs_doc_single_content_listen_font_weight' | |
| 10328 | + ] | |
| 10329 | + ) | |
| 10330 | +); | |
| 10331 | + | |
| 10332 | +$css->add_rule( | |
| 10333 | + '.betterdocs-content-area .betterdocs-listen', | |
| 10334 | + $css->properties( | |
| 10335 | + [ | |
| 10336 | + 'font-size' => 'betterdocs_doc_single_content_listen_font_size' | |
| 10337 | + ], | |
| 10338 | + 'px' | |
| 10339 | + ) | |
| 10340 | +); | |
| 10341 | + | |
| 10342 | +//listen player accent — play button fill, progress fill, scrubber ring | |
| 10343 | +// One custom property, declared on the player, inherited by all three. Written as | |
| 10344 | +// its own rule with nothing else in it so the value is unambiguous; see | |
| 10345 | +// scss/template-parts/listen.scss, which publishes the same property with the | |
| 10346 | +// default as its fallback. | |
| 10347 | +$css->add_rule( | |
| 10348 | + '.betterdocs-content-area .betterdocs-listen-player', | |
| 10349 | + $css->properties( | |
| 10350 | + [ | |
| 10351 | + '--bd-listen-accent' => 'betterdocs_doc_single_content_listen_accent_color' | |
| 10352 | + ] | |
| 10353 | + ) | |
| 10354 | +); | |
| 10355 | + | |
| 10356 | +//listen icon colour | |
| 10357 | +// The headset glyph on the collapsed pill. Stroked with `currentColor`, so a | |
| 10358 | +// `color` on the svg is the whole job. The player's own glyphs are deliberately | |
| 10359 | +// left out: the play triangle is white on the accent fill and the close cross | |
| 10360 | +// belongs to the player's muted chrome, and neither reads as "the icon colour" the | |
| 10361 | +// way the pill's headset does. | |
| 10362 | +$css->add_rule( | |
| 10363 | + '.betterdocs-content-area .betterdocs-listen-trigger svg', | |
| 10364 | + $css->properties( | |
| 10365 | + [ | |
| 10366 | + 'color' => 'betterdocs_doc_single_content_listen_icon_color' | |
| 10367 | + ] | |
| 10368 | + ) | |
| 10369 | +); | |
| 10370 | + | |
| 10371 | +//listen icon size | |
| 10372 | +$css->add_rule( | |
| 10373 | + '.betterdocs-content-area .betterdocs-listen-trigger svg', | |
| 10374 | + $css->properties( | |
| 10375 | + [ | |
| 10376 | + 'width' => 'betterdocs_doc_single_content_listen_icon_size', | |
| 10377 | + 'height' => 'betterdocs_doc_single_content_listen_icon_size' | |
| 10378 | + ], | |
| 10379 | + 'px' | |
| 10380 | + ) | |
| 10381 | +); | |
| 10382 | + | |
| 10383 | +//listen padding top, right, bottom, left | |
| 10384 | +// On the trigger, which is the only element in flow and therefore the one that | |
| 10385 | +// gives the pill its size. The player is absolutely positioned with `inset-block: | |
| 10386 | +// 0`, so it inherits that height without being told — which is what keeps the | |
| 10387 | +// design's promise that nothing below the pill moves when it opens. | |
| 10388 | +$css->add_rule( | |
| 10389 | + '.betterdocs-content-area .betterdocs-listen-trigger', | |
| 10390 | + $css->properties( | |
| 10391 | + [ | |
| 10392 | + 'padding-top' => 'betterdocs_doc_single_content_listen_padding_top', | |
| 10393 | + 'padding-right' => 'betterdocs_doc_single_content_listen_padding_right', | |
| 10394 | + 'padding-bottom' => 'betterdocs_doc_single_content_listen_padding_bottom', | |
| 10395 | + 'padding-left' => 'betterdocs_doc_single_content_listen_padding_left' | |
| 10012 | 10396 | ], |
| 10013 | 10397 | 'px' |
| 10014 | 10398 | ) |
| 10015 | 10399 | ); |