| @@ -1,17 +1,17 @@ | ||
| 1 | 1 | /** |
| 2 | - * Desktop Mode — Chromeless Overrides. | |
| 2 | + * OpenStation — Chromeless Overrides. | |
| 3 | 3 | * |
| 4 | - * CSS adjustments for legacy admin pages rendered inside desktop mode | |
| 5 | - * iframes (chromeless mode). All rules are scoped to .desktop-mode-chromeless | |
| 4 | + * CSS adjustments for legacy admin pages rendered inside OpenStation | |
| 5 | + * iframes (chromeless mode). All rules are scoped to .os-chromeless | |
| 6 | 6 | * so they never affect the classic admin or the desktop shell. |
| 7 | 7 | * |
| 8 | 8 | * Plugin and theme developers: to add your own chromeless overrides, |
| 9 | - * enqueue a stylesheet on the 'desktop_mode_chromeless_styles' action. | |
| 10 | - * Your CSS just needs to target .desktop-mode-chromeless as the body class. | |
| 9 | + * enqueue a stylesheet on the 'openstation_chromeless_styles' action. | |
| 10 | + * Your CSS just needs to target .os-chromeless as the body class. | |
| 11 | 11 | * |
| 12 | 12 | * Example: |
| 13 | - * add_action( 'desktop_mode_chromeless_styles', function() { | |
| 13 | + * add_action( 'openstation_chromeless_styles', function() { | |
| 14 | 14 | * wp_enqueue_style( 'my-plugin-chromeless', plugin_dir_url( __FILE__ ) . 'chromeless.css' ); |
| 15 | 15 | * } ); |
| 16 | 16 | * |
| 17 | 17 | * @since 0.1.0 |
| @@ -21,17 +21,42 @@ | ||
| 21 | 21 | * Hide the classic admin chrome elements. These would otherwise |
| 22 | 22 | * reserve space (sidebar gutter, footer, admin bar) around the |
| 23 | 23 | * chromeless page content. |
| 24 | 24 | * --------------------------------------------------------------- */ |
| 25 | -.desktop-mode-chromeless #adminmenuwrap, | |
| 26 | -.desktop-mode-chromeless #adminmenuback, | |
| 27 | -.desktop-mode-chromeless #wpfooter, | |
| 28 | -.desktop-mode-chromeless #wpadminbar, | |
| 29 | -.desktop-mode-chromeless .wp-responsive-toggle, | |
| 30 | -.desktop-mode-chromeless #collapse-menu { | |
| 25 | +.os-chromeless #adminmenuwrap, | |
| 26 | +.os-chromeless #adminmenuback, | |
| 27 | +.os-chromeless #wpfooter, | |
| 28 | +.os-chromeless #wpadminbar, | |
| 29 | +.os-chromeless .wp-responsive-toggle, | |
| 30 | +.os-chromeless #collapse-menu { | |
| 31 | 31 | display: none !important; |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | +/* --------------------------------------------------------------- | |
| 35 | + * The iframe paints its own canvas. | |
| 36 | + * | |
| 37 | + * An admin page leaves whole regions unpainted — the gutter around | |
| 38 | + * `#wpbody-content`, the strip behind `.subsubsub` and `.tablenav`, | |
| 39 | + * everything below short content. In a normal admin tab the browser | |
| 40 | + * canvas is white underneath, so nobody notices. Inside an iframe the | |
| 41 | + * canvas is TRANSPARENT, and what shows through is the window element | |
| 42 | + * behind it — `--os-window-bg`. | |
| 43 | + * | |
| 44 | + * That was invisible while the window body was white and became a | |
| 45 | + * black band the moment the station's palette made it Obsidian. It is | |
| 46 | + * a real coupling either way: the look of a wp-admin page must not | |
| 47 | + * depend on the colour of the frame around it. | |
| 48 | + * | |
| 49 | + * So the chromeless document paints itself, in the colour the browser | |
| 50 | + * canvas would have been. Deliberately a literal and deliberately NOT | |
| 51 | + * a token: nothing about the shell's palette — or any desktop theme — | |
| 52 | + * should reach a real admin page. **An admin page in a window renders | |
| 53 | + * exactly as it does outside one.** | |
| 54 | + * --------------------------------------------------------------- */ | |
| 55 | +body.os-chromeless { | |
| 56 | + background: #fff; | |
| 57 | +} | |
| 58 | + | |
| 34 | 59 | /* |
| 35 | 60 | * _wp_admin_html_begin() adds the `wp-toolbar` class to <html> whenever |
| 36 | 61 | * is_admin_bar_showing() is true — which, in admin, is unconditional. |
| 37 | 62 | * The class carries a `padding-top: var(--wp-admin--admin-bar--height)` |
| @@ -48,9 +73,9 @@ | ||
| 48 | 73 | * to clear the bar. Without this override they reserve a 32px (or 46px |
| 49 | 74 | * on small screens) gap that no longer exists, producing visible jumps |
| 50 | 75 | * on first paint and dead space at the top of the content area. |
| 51 | 76 | */ |
| 52 | -html.wp-toolbar:has( body.desktop-mode-chromeless ) { | |
| 77 | +html.wp-toolbar:has( body.os-chromeless ) { | |
| 53 | 78 | padding-top: 0 !important; |
| 54 | 79 | --wp-admin--admin-bar--height: 0px; |
| 55 | 80 | --wp-admin--admin-bar--position-offset: 0px; |
| 56 | 81 | } |
| @@ -55,9 +80,9 @@ | ||
| 55 | 80 | --wp-admin--admin-bar--position-offset: 0px; |
| 56 | 81 | } |
| 57 | 82 | |
| 58 | 83 | /* Remove the sidebar gutter on #wpcontent and let the body fill the frame. */ |
| 59 | -.desktop-mode-chromeless #wpcontent { | |
| 84 | +.os-chromeless #wpcontent { | |
| 60 | 85 | margin-inline-start: 0 !important; |
| 61 | 86 | padding-inline-start: 0 !important; |
| 62 | 87 | } |
| 63 | 88 | |
| @@ -89,12 +114,40 @@ | ||
| 89 | 114 | * iframe edge as WC's design intended, the gray strip disappears, |
| 90 | 115 | * and the header's content uses the full window width. No |
| 91 | 116 | * transform / overflow / visibility tricks needed. |
| 92 | 117 | */ |
| 93 | -.desktop-mode-chromeless .woocommerce-layout__header { | |
| 118 | +.os-chromeless .woocommerce-layout__header { | |
| 94 | 119 | width: 100% !important; |
| 95 | 120 | } |
| 96 | 121 | |
| 122 | +/* | |
| 123 | + * MailPoet top-bar overlap fix. | |
| 124 | + * | |
| 125 | + * MailPoet mounts a 64px-tall brand bar on its screens as | |
| 126 | + * `.wrap .mailpoet-top-bar { position: absolute; top: 0 }` — | |
| 127 | + * anchored to `#wpbody` (core's `position: relative`), overlaying | |
| 128 | + * whatever the page's first 64px contain. In classic admin nothing | |
| 129 | + * is visibly covered only by accident of geometry: the in-flow | |
| 130 | + * space above `.wrap` — the `#screen-meta-links` row plus `.wrap`'s | |
| 131 | + * own top margin — happens to add up to more than the bar's height, | |
| 132 | + * so the content starts below it (measured: `.wrap` at y=114 vs | |
| 133 | + * bar bottom at y=96). | |
| 134 | + * | |
| 135 | + * Chromeless collapses exactly that space on purpose — screen-meta | |
| 136 | + * links are hidden (the window title bar owns those buttons) and | |
| 137 | + * `.wrap` margins are trimmed — which slides MailPoet's content up | |
| 138 | + * underneath the overlaid bar. Symptom: the page's heading sits | |
| 139 | + * half-hidden behind the white logo bar inside the window. | |
| 140 | + * | |
| 141 | + * Reserve the bar's height in flow instead. `:has()` scopes the | |
| 142 | + * rule to precisely the pages that render the in-wrap bar — | |
| 143 | + * whatever MailPoet screen shape it is, present or future — and to | |
| 144 | + * nothing else. | |
| 145 | + */ | |
| 146 | +.os-chromeless .wrap:has( .mailpoet-top-bar ) { | |
| 147 | + padding-top: 64px; | |
| 148 | +} | |
| 149 | + | |
| 97 | 150 | /* --------------------------------------------------------------- |
| 98 | 151 | * Screen Meta (Screen Options / Help panels) |
| 99 | 152 | * The toggle buttons (#screen-meta-links) are hidden because |
| 100 | 153 | * the parent desktop shell adds its own buttons to the window |
| @@ -103,14 +156,14 @@ | ||
| 103 | 156 | * |
| 104 | 157 | * Collapse all margins on the hidden links and the panel container |
| 105 | 158 | * so they don't leave a gap at the top of the iframe content. |
| 106 | 159 | * --------------------------------------------------------------- */ |
| 107 | -.desktop-mode-chromeless #screen-meta-links { | |
| 160 | +.os-chromeless #screen-meta-links { | |
| 108 | 161 | display: none; |
| 109 | 162 | margin: 0; |
| 110 | 163 | } |
| 111 | 164 | |
| 112 | -.desktop-mode-chromeless #screen-meta { | |
| 165 | +.os-chromeless #screen-meta { | |
| 113 | 166 | margin: 0; |
| 114 | 167 | border: none; |
| 115 | 168 | } |
| 116 | 169 | |
| @@ -118,9 +171,9 @@ | ||
| 118 | 171 | * Wrap container |
| 119 | 172 | * Remove the default left margin that accounts for the sidebar |
| 120 | 173 | * which doesn't exist in chromeless mode. |
| 121 | 174 | * --------------------------------------------------------------- */ |
| 122 | -.desktop-mode-chromeless .wrap { | |
| 175 | +.os-chromeless .wrap { | |
| 123 | 176 | margin: 0; |
| 124 | 177 | } |
| 125 | 178 | |
| 126 | 179 | /* --------------------------------------------------------------- |
| @@ -132,28 +185,30 @@ | ||
| 132 | 185 | * |
| 133 | 186 | * `.page-title-action` (the "Add New" / "Add Order" button next to |
| 134 | 187 | * the H1) stays VISIBLE by default — it's the only entry point to |
| 135 | 188 | * the add-new flow on many plugin pages (WooCommerce Orders, custom |
| 136 | - * CPTs, plugin settings pages, etc.). Earlier versions of this CSS | |
| 137 | - * hid it on the assumption that the submenu tab strip exposed the | |
| 138 | - * same action — which holds for WP Core pages with a registered | |
| 139 | - * "Add New" submenu (Posts, Pages, Users) but breaks every third- | |
| 140 | - * party plugin page that has no submenu equivalent. A small bit of | |
| 141 | - * redundancy with the submenu strip on Core pages is the better | |
| 142 | - * trade-off vs. losing the primary affordance on plugin pages | |
| 143 | - * entirely. | |
| 189 | + * CPTs, plugin settings pages, etc.). A blanket hide would break | |
| 190 | + * every third-party plugin page that has no submenu equivalent, so | |
| 191 | + * the button is only removed where the window's own tab strip | |
| 192 | + * demonstrably leads to the same place — see | |
| 193 | + * `includes/render/chromeless-title-actions.php`, which emits one | |
| 194 | + * `[href="…"]` rule per submenu tab URL of the current screen. | |
| 144 | 195 | * |
| 145 | - * Sites that prefer the cleaner Core-page look can hide the button | |
| 146 | - * on specific pages via the `desktop_mode_chromeless_styles` | |
| 147 | - * action — e.g.: | |
| 196 | + * Sites that want to hide it somewhere that rule deliberately | |
| 197 | + * doesn't reach can add their own via the | |
| 198 | + * `openstation_chromeless_styles` action — e.g. WooCommerce's "Add | |
| 199 | + * order", which we keep because it points at `&action=new` and the | |
| 200 | + * Orders tab doesn't: | |
| 148 | 201 | * |
| 149 | - * body.edit-php .wrap > .page-title-action { display: none; } | |
| 202 | + * body.woocommerce_page_wc-orders .wrap > .page-title-action { | |
| 203 | + * display: none; | |
| 204 | + * } | |
| 150 | 205 | * |
| 151 | 206 | * --------------------------------------------------------------- */ |
| 152 | -.desktop-mode-chromeless .wrap > h1, | |
| 153 | -.desktop-mode-chromeless .wrap > h1.wp-heading-inline, | |
| 154 | -.desktop-mode-chromeless #wpbody-content > .wrap > h1, | |
| 155 | -.desktop-mode-chromeless .wrap > .wp-header-end { | |
| 207 | +.os-chromeless .wrap > h1, | |
| 208 | +.os-chromeless .wrap > h1.wp-heading-inline, | |
| 209 | +.os-chromeless #wpbody-content > .wrap > h1, | |
| 210 | +.os-chromeless .wrap > .wp-header-end { | |
| 156 | 211 | display: none; |
| 157 | 212 | } |
| 158 | 213 | |
| 159 | 214 | /* |
| @@ -158,27 +213,64 @@ | ||
| 158 | 213 | |
| 159 | 214 | /* |
| 160 | 215 | * The H1 above it is hidden, so the button would float at the very |
| 161 | 216 | * top of the iframe area without breathing room — give it a small |
| 162 | - * margin so it lands cleanly. inline-block matches WP Core's | |
| 163 | - * computed style on this element (matters for vertical-align with | |
| 164 | - * any adjacent inline content like the `.subsubsub` filter row). | |
| 217 | + * margin so it lands cleanly. | |
| 165 | 218 | * |
| 219 | + * `block` + `fit-content` instead of Core's `inline-block`: with the | |
| 220 | + * H1 hidden, an inline button ends up on the same line as the | |
| 221 | + * floated `.subsubsub` filter row and reads as one more filter link | |
| 222 | + * ("All (6) | Published (4) | Trash (2) Add Post"). Its own row is | |
| 223 | + * also what the screen already looks like when an admin notice is | |
| 224 | + * showing. `clear` keeps it below anything floated before it. | |
| 225 | + * | |
| 166 | 226 | * Themes.php's native "Add Theme" button lives in the submenu tab |
| 167 | - * strip via `desktop_mode_inject_appearance_tabs` | |
| 227 | + * strip via `openstation_inject_appearance_tabs` | |
| 168 | 228 | * (includes/themes-tabs.php), so its in-page page-title-action is |
| 169 | - * redundant on that one screen — keep the per-page hide rule below | |
| 170 | - * so we don't ship two "Add Theme" entry points. | |
| 229 | + * redundant on that one screen. The generic href-matching hide in | |
| 230 | + * `includes/render/chromeless-title-actions.php` only matches exact | |
| 231 | + * URLs, and the injected tab points at | |
| 232 | + * `theme-install.php?browse=popular` while the button points at | |
| 233 | + * plain `theme-install.php`. Hence the per-page rule below. | |
| 171 | 234 | */ |
| 172 | -.desktop-mode-chromeless .wrap > .page-title-action { | |
| 173 | - display: inline-block; | |
| 235 | +.os-chromeless .wrap > .page-title-action { | |
| 236 | + display: block; | |
| 237 | + width: fit-content; | |
| 174 | 238 | margin-top: 12px; |
| 239 | + margin-bottom: 12px; | |
| 240 | + clear: both; | |
| 175 | 241 | } |
| 176 | 242 | |
| 177 | -.desktop-mode-chromeless.themes-php .wrap > .page-title-action { | |
| 243 | +.os-chromeless.themes-php .wrap > .page-title-action { | |
| 178 | 244 | display: none; |
| 179 | 245 | } |
| 180 | 246 | |
| 247 | +/* | |
| 248 | + * Core offsets every title action by `top: -3px` (common.css) so it | |
| 249 | + * sits on the H1's baseline. Chromeless hides the H1, and the first | |
| 250 | + * thing in the frame has nothing above it to overlap: the offset | |
| 251 | + * pulls the button's top border under the window's content edge and | |
| 252 | + * it renders cropped. The offset has no baseline left to meet here, | |
| 253 | + * so drop it. | |
| 254 | + * | |
| 255 | + * The margins are the same 12px the rule above gives a lone button, | |
| 256 | + * applied to whatever element a plugin grouped its buttons in. On a | |
| 257 | + * Jetpack site that is `div.wpcom-media-library-action-buttons` | |
| 258 | + * (external-media moves core's "Add Media File" into it so it can | |
| 259 | + * append "Import Media"; Big Sky adds "Generate Image" beside them), | |
| 260 | + * and a group is not a `.page-title-action`, so it picks up neither | |
| 261 | + * the margin nor the block layout and lands flush against the top. | |
| 262 | + * `:has()` reaches the group whatever a plugin decided to call it. | |
| 263 | + */ | |
| 264 | +.os-chromeless .wrap .page-title-action { | |
| 265 | + top: 0; | |
| 266 | +} | |
| 267 | + | |
| 268 | +.os-chromeless .wrap :has( > .page-title-action ) { | |
| 269 | + margin-top: 12px; | |
| 270 | + margin-bottom: 12px; | |
| 271 | +} | |
| 272 | + | |
| 181 | 273 | /* --------------------------------------------------------------- |
| 182 | 274 | * WooCommerce "embed page" header overlay — page-scoped. |
| 183 | 275 | * |
| 184 | 276 | * Background: WC renders TWO layouts simultaneously on "connected" |
| @@ -218,25 +310,50 @@ | ||
| 218 | 310 | * Activity Panel from every WC screen). |
| 219 | 311 | * |
| 220 | 312 | * @since 0.8.9 |
| 221 | 313 | */ |
| 222 | -.desktop-mode-chromeless.woocommerce_page_wc-orders .woocommerce-layout__header, | |
| 223 | -.desktop-mode-chromeless.woocommerce_page_wc-orders--shop_order .woocommerce-layout__header { | |
| 314 | +.os-chromeless.woocommerce_page_wc-orders .woocommerce-layout__header, | |
| 315 | +.os-chromeless.woocommerce_page_wc-orders--shop_order .woocommerce-layout__header { | |
| 224 | 316 | display: none !important; |
| 225 | 317 | } |
| 226 | -.desktop-mode-chromeless.woocommerce_page_wc-orders #wpbody, | |
| 227 | -.desktop-mode-chromeless.woocommerce_page_wc-orders--shop_order #wpbody { | |
| 318 | +.os-chromeless.woocommerce_page_wc-orders #wpbody, | |
| 319 | +.os-chromeless.woocommerce_page_wc-orders--shop_order #wpbody { | |
| 228 | 320 | margin-top: 0 !important; |
| 229 | 321 | } |
| 230 | 322 | |
| 231 | 323 | /* --------------------------------------------------------------- |
| 324 | + * Revisions screen — page-scoped. | |
| 325 | + * | |
| 326 | + * "← Go to editor" is a back button for a screen the user navigated | |
| 327 | + * into. Here they didn't: the editor is open in its own window | |
| 328 | + * behind this one, and closing this window is the way back. | |
| 329 | + * | |
| 330 | + * The revision tooltip is positioned upward from the bottom of | |
| 331 | + * `.revisions-control-frame` and clears the top of the viewport only | |
| 332 | + * thanks to the screen H1, which chromeless hides. An iframe can't | |
| 333 | + * overflow its box, so the space has to be given back: 48px covers | |
| 334 | + * both slider modes. | |
| 335 | + * | |
| 336 | + * The padding goes on `.revisions`, not on the frame — the frame is | |
| 337 | + * the positioned ancestor for the compare-mode checkbox and the | |
| 338 | + * tooltip, so padding it would leave both behind at the old top edge. | |
| 339 | + * --------------------------------------------------------------- */ | |
| 340 | +.os-chromeless.revision-php .wrap > h1.long-header + a { | |
| 341 | + display: none; | |
| 342 | +} | |
| 343 | + | |
| 344 | +.os-chromeless.revision-php .revisions { | |
| 345 | + padding-top: 48px; | |
| 346 | +} | |
| 347 | + | |
| 348 | +/* --------------------------------------------------------------- | |
| 232 | 349 | * Dashboard welcome panel |
| 233 | 350 | * The default 16px top margin pushes the panel down and creates a |
| 234 | 351 | * visible gap at the top of the iframe. Collapse it in chromeless |
| 235 | 352 | * mode so the panel sits flush with the top of the window body. |
| 236 | 353 | * --------------------------------------------------------------- */ |
| 237 | -.desktop-mode-chromeless #welcome-panel, | |
| 238 | -.desktop-mode-chromeless .welcome-panel { | |
| 354 | +.os-chromeless #welcome-panel, | |
| 355 | +.os-chromeless .welcome-panel { | |
| 239 | 356 | margin-top: 0.5em; |
| 240 | 357 | } |
| 241 | 358 | |
| 242 | 359 | /* --------------------------------------------------------------- |
| @@ -243,9 +360,9 @@ | ||
| 243 | 360 | * Footer |
| 244 | 361 | * The classic footer is not rendered in chromeless mode, |
| 245 | 362 | * but some pages have bottom padding assuming it exists. |
| 246 | 363 | * --------------------------------------------------------------- */ |
| 247 | -.desktop-mode-chromeless #wpbody-content { | |
| 364 | +.os-chromeless #wpbody-content { | |
| 248 | 365 | margin: 0; |
| 249 | 366 | padding: 0 8px 8px; |
| 250 | 367 | float: none; |
| 251 | 368 | width: auto; |
| @@ -251,8 +368,85 @@ | ||
| 251 | 368 | width: auto; |
| 252 | 369 | } |
| 253 | 370 | |
| 254 | 371 | /* --------------------------------------------------------------- |
| 372 | + * Metabox screens — the one-column breakpoint is 160px too early. | |
| 373 | + * | |
| 374 | + * Core collapses every `#poststuff` two-column screen (the classic | |
| 375 | + * post editor, any CPT editor, a WooCommerce order) to one column | |
| 376 | + * at `max-width: 850px`. That number is a VIEWPORT width, and it is | |
| 377 | + * sized for a viewport that still has the 160px admin menu in it: | |
| 378 | + * at 851px core leaves roughly 650px of usable content — less than | |
| 379 | + * the 763px the two columns actually need (`#post-body-content`'s | |
| 380 | + * 463px floor plus the 300px sidebar reservation), which is why | |
| 381 | + * core's own two-column layout scrolls sideways just above the | |
| 382 | + * breakpoint. | |
| 383 | + * | |
| 384 | + * A chromeless iframe hides the admin menu, so the same 851px gives | |
| 385 | + * 835px of content — comfortably two columns — and core stacks it | |
| 386 | + * anyway. The sidebar then lands BELOW the editor, and since the | |
| 387 | + * classic editor grows to fit its text, a long post pushes Publish, | |
| 388 | + * Categories, Tags and Featured image thousands of pixels down the | |
| 389 | + * page. The user's word for that is "vanished". | |
| 390 | + * | |
| 391 | + * Same shape as the WooCommerce header fix at the top of this file: | |
| 392 | + * the page reserved space for a sidebar we removed, so reclaim the | |
| 393 | + * reservation. Two columns stay until the content really stops | |
| 394 | + * fitting: 763px of content, plus the 16px `#wpbody-content` gutter | |
| 395 | + * above, plus up to 17px for a classic vertical scrollbar — which a | |
| 396 | + * media query does NOT subtract from the width it matches on, the | |
| 397 | + * same reason `100vw` overflows a scrolling page. That is 796px. | |
| 398 | + * Below it, core's one-column layout is correct and stays. | |
| 399 | + * | |
| 400 | + * The reservation is written flow-relative rather than as core's | |
| 401 | + * `margin-right` / `float: right`, because core ships the mirrored | |
| 402 | + * values in a separate `edit-rtl.css` and this file has no RTL | |
| 403 | + * build — one logical declaration lands on the correct side in | |
| 404 | + * both directions. `float: right` stays ahead of `float: | |
| 405 | + * inline-end` as the fallback. | |
| 406 | + * | |
| 407 | + * Attachments keep core's own, wider, 1200px breakpoint: the media | |
| 408 | + * editor's sidebar carries the whole attachment form and needs the | |
| 409 | + * room. `.post-type-attachment` is excluded rather than re-stacked | |
| 410 | + * so that rule keeps working untouched. | |
| 411 | + * | |
| 412 | + * Verifying: open a post with a few thousand words in a window | |
| 413 | + * ~800px wide. Publish/Categories/Tags sit beside the editor, not | |
| 414 | + * under it, and the page has no horizontal scrollbar. | |
| 415 | + * --------------------------------------------------------------- */ | |
| 416 | +@media only screen and ( min-width: 796px ) and ( max-width: 850px ) { | |
| 417 | + .os-chromeless:not( .post-type-attachment ) #wpbody-content #poststuff #post-body.columns-2 { | |
| 418 | + margin-inline-end: 300px; | |
| 419 | + } | |
| 420 | + | |
| 421 | + .os-chromeless:not( .post-type-attachment ) #wpbody-content #post-body.columns-2 #postbox-container-1 { | |
| 422 | + float: right; | |
| 423 | + float: inline-end; | |
| 424 | + margin-inline-end: -300px; | |
| 425 | + width: 280px; | |
| 426 | + } | |
| 427 | + | |
| 428 | + .os-chromeless:not( .post-type-attachment ) #poststuff #post-body.columns-2 #side-sortables { | |
| 429 | + min-height: 250px; | |
| 430 | + width: 280px; | |
| 431 | + } | |
| 432 | + | |
| 433 | + /* | |
| 434 | + * Core hides the Layout radios with the two-column layout. They | |
| 435 | + * are the way back to one column, so they come back with it. | |
| 436 | + * | |
| 437 | + * `edit.css` is part of the `wp-admin` bundle and loads on every | |
| 438 | + * screen, so that hide reaches the Dashboard's own 1-4 column | |
| 439 | + * radios too. Only un-hide them where this block actually gave a | |
| 440 | + * layout back. | |
| 441 | + */ | |
| 442 | + .os-chromeless:not( .post-type-attachment ):has( #post-body.columns-2 ) .screen-layout, | |
| 443 | + .os-chromeless:not( .post-type-attachment ):has( #post-body.columns-2 ) .columns-prefs { | |
| 444 | + display: block; | |
| 445 | + } | |
| 446 | +} | |
| 447 | + | |
| 448 | +/* --------------------------------------------------------------- | |
| 255 | 449 | * Block Editor — hide Gutenberg chrome that would break the window. |
| 256 | 450 | * |
| 257 | 451 | * The fullscreen-mode close button (the "W" logo top-left of the editor) |
| 258 | 452 | * is an <a href="/wp-admin/edit.php"> that navigates the iframe to a |
| @@ -272,15 +466,15 @@ | ||
| 272 | 466 | * dismissal to user meta the moment they close it, so the override |
| 273 | 467 | * was permanently stealing the one-time orientation tour from every |
| 274 | 468 | * user who never got to see it. Modal's focus trap is Tab-only and |
| 275 | 469 | * doesn't fight the shell. Let it run. (See git history for the |
| 276 | - * removed `desktop_mode_chromeless_editor_preferences` override.) | |
| 470 | + * removed `openstation_chromeless_editor_preferences` override.) | |
| 277 | 471 | * --------------------------------------------------------------- */ |
| 278 | -.desktop-mode-chromeless .edit-post-fullscreen-mode-close, | |
| 279 | -.desktop-mode-chromeless .edit-post-fullscreen-mode-close__view-mode-toggle, | |
| 280 | -.desktop-mode-chromeless .edit-site-navigation-link, | |
| 281 | -.desktop-mode-chromeless .edit-site-site-hub, | |
| 282 | -.desktop-mode-chromeless .edit-site-site-hub__toggle { | |
| 472 | +.os-chromeless .edit-post-fullscreen-mode-close, | |
| 473 | +.os-chromeless .edit-post-fullscreen-mode-close__view-mode-toggle, | |
| 474 | +.os-chromeless .edit-site-navigation-link, | |
| 475 | +.os-chromeless .edit-site-site-hub, | |
| 476 | +.os-chromeless .edit-site-site-hub__toggle { | |
| 283 | 477 | display: none !important; |
| 284 | 478 | } |
| 285 | 479 | |
| 286 | 480 | /* --------------------------------------------------------------- |
| @@ -289,11 +483,11 @@ | ||
| 289 | 483 | * panels, etc.). Any padding around #wpbody-content crops the |
| 290 | 484 | * editor and breaks its layout, so reset to zero on those pages |
| 291 | 485 | * and let the editor render edge-to-edge. |
| 292 | 486 | * --------------------------------------------------------------- */ |
| 293 | -.desktop-mode-chromeless.block-editor-page #wpbody-content, | |
| 294 | -.desktop-mode-chromeless.site-editor-php #wpbody-content, | |
| 295 | -.desktop-mode-chromeless.is-fullscreen-mode #wpbody-content { | |
| 487 | +.os-chromeless.block-editor-page #wpbody-content, | |
| 488 | +.os-chromeless.site-editor-php #wpbody-content, | |
| 489 | +.os-chromeless.is-fullscreen-mode #wpbody-content { | |
| 296 | 490 | padding: 0; |
| 297 | 491 | } |
| 298 | 492 | |
| 299 | 493 | /* --------------------------------------------------------------- |
| @@ -306,13 +500,13 @@ | ||
| 306 | 500 | * the window. Zero the padding for any page hosting a boot layout |
| 307 | 501 | * — detection is purely structural (`:has()`), so a plugin that |
| 308 | 502 | * adopts the same container class inherits the fix automatically. |
| 309 | 503 | * --------------------------------------------------------------- */ |
| 310 | -.desktop-mode-chromeless #wpbody-content:has( .boot-layout-container ) { | |
| 504 | +.os-chromeless #wpbody-content:has( .boot-layout-container ) { | |
| 311 | 505 | padding: 0; |
| 312 | 506 | } |
| 313 | 507 | |
| 314 | -.desktop-mode-chromeless:has( .boot-layout-container ) #wpwrap { | |
| 508 | +.os-chromeless:has( .boot-layout-container ) #wpwrap { | |
| 315 | 509 | /* Neutralize the inline dark background so any stray overflow |
| 316 | 510 | * matches the window body instead of flashing black. */ |
| 317 | 511 | background: transparent; |
| 318 | 512 | } |
| @@ -324,11 +518,11 @@ | ||
| 324 | 518 | * a desktop window the surface IS the content — rounded corners and |
| 325 | 519 | * side margins leave ugly bleed at the edges. Collapse it to a plain |
| 326 | 520 | * edge-to-edge surface. |
| 327 | 521 | */ |
| 328 | -.desktop-mode-chromeless .boot-layout__surfaces, | |
| 329 | -.desktop-mode-chromeless .boot-layout__stage, | |
| 330 | -.desktop-mode-chromeless .boot-layout__canvas { | |
| 522 | +.os-chromeless .boot-layout__surfaces, | |
| 523 | +.os-chromeless .boot-layout__stage, | |
| 524 | +.os-chromeless .boot-layout__canvas { | |
| 331 | 525 | border-radius: 0 !important; |
| 332 | 526 | margin: 0 !important; |
| 333 | 527 | } |
| 334 | 528 | |
| @@ -338,10 +532,10 @@ | ||
| 338 | 532 | * shows the page title in its title bar, so the in-page title is |
| 339 | 533 | * redundant. Visually hide it but keep it in the DOM for screen readers |
| 340 | 534 | * and for the boot app's own focus management. |
| 341 | 535 | */ |
| 342 | -.desktop-mode-chromeless .boot-navigation-screen__title, | |
| 343 | -.desktop-mode-chromeless .boot-navigation-screen__title-icon { | |
| 536 | +.os-chromeless .boot-navigation-screen__title, | |
| 537 | +.os-chromeless .boot-navigation-screen__title-icon { | |
| 344 | 538 | position: absolute; |
| 345 | 539 | width: 1px; |
| 346 | 540 | height: 1px; |
| 347 | 541 | padding: 0; |
| @@ -365,15 +559,15 @@ | ||
| 365 | 559 | * |
| 366 | 560 | * Pin them flush to the bottom of the iframe and make sure nothing |
| 367 | 561 | * in the window chrome can occlude them. |
| 368 | 562 | * |
| 369 | - * Triggering a snackbar to verify (desktop mode enabled): | |
| 563 | + * Triggering a snackbar to verify (OpenStation enabled): | |
| 370 | 564 | * - Open Posts → Add New, save/publish → "Post published" toast. |
| 371 | 565 | * - Open Media, upload a file → "Uploaded" toast. |
| 372 | 566 | * - Open Appearance → Fonts, install a Google Font → toast. |
| 373 | 567 | * --------------------------------------------------------------- */ |
| 374 | -.desktop-mode-chromeless .components-snackbar-list, | |
| 375 | -.desktop-mode-chromeless .boot-notices__snackbar { | |
| 568 | +.os-chromeless .components-snackbar-list, | |
| 569 | +.os-chromeless .boot-notices__snackbar { | |
| 376 | 570 | bottom: 16px !important; |
| 377 | 571 | z-index: 100000; |
| 378 | 572 | } |
| 379 | 573 | |
| @@ -389,9 +583,9 @@ | ||
| 389 | 583 | * off in classic admin carry that preference into chromeless via the |
| 390 | 584 | * shared persistence layer. This rule keeps chromeless rendering |
| 391 | 585 | * edge-to-edge either way. |
| 392 | 586 | */ |
| 393 | -.desktop-mode-chromeless .interface-interface-skeleton { | |
| 587 | +.os-chromeless .interface-interface-skeleton { | |
| 394 | 588 | top: 0 !important; |
| 395 | 589 | left: 0 !important; |
| 396 | 590 | right: 0 !important; |
| 397 | 591 | bottom: 0 !important; |
| @@ -400,9 +594,9 @@ | ||
| 400 | 594 | /* --------------------------------------------------------------- |
| 401 | 595 | * Notices |
| 402 | 596 | * Give notices a bit of top margin since there's no admin bar above. |
| 403 | 597 | * --------------------------------------------------------------- */ |
| 404 | -.desktop-mode-chromeless .notice:first-child { | |
| 598 | +.os-chromeless .notice:first-child { | |
| 405 | 599 | margin-top: 4px; |
| 406 | 600 | } |
| 407 | 601 | |
| 408 | 602 | /* --------------------------------------------------------------- |
| @@ -408,12 +602,12 @@ | ||
| 408 | 602 | /* --------------------------------------------------------------- |
| 409 | 603 | * Update nag |
| 410 | 604 | * Core's global update / maintenance nags are detached server-side |
| 411 | 605 | * inside chromeless iframes (see |
| 412 | - * `desktop_mode_chromeless_suppress_update_nags()`) and re-surfaced | |
| 606 | + * `openstation_chromeless_suppress_update_nags()`) and re-surfaced | |
| 413 | 607 | * once by the shell as a single notice. |
| 414 | 608 | * --------------------------------------------------------------- */ |
| 415 | -.desktop-mode-chromeless .update-nag { | |
| 609 | +.os-chromeless .update-nag { | |
| 416 | 610 | display: none !important; |
| 417 | 611 | } |
| 418 | 612 | |
| 419 | 613 | /* --------------------------------------------------------------- |
| @@ -423,8 +617,602 @@ | ||
| 423 | 617 | * palette via another path (programmatic dispatch, a menu item) |
| 424 | 618 | * the dialog would still render. Hide it so the shell's palette |
| 425 | 619 | * stays the only surface users ever see. |
| 426 | 620 | * --------------------------------------------------------------- */ |
| 427 | -.desktop-mode-chromeless .commands-command-menu__container, | |
| 428 | -.desktop-mode-chromeless .commands-command-menu { | |
| 621 | +.os-chromeless .commands-command-menu__container, | |
| 622 | +.os-chromeless .commands-command-menu { | |
| 429 | 623 | display: none !important; |
| 624 | +} | |
| 625 | + | |
| 626 | +/* --------------------------------------------------------------- | |
| 627 | + * A file drag over a native upload box. | |
| 628 | + * | |
| 629 | + * The chromeless bridge hands an OS-file drop to Core's own | |
| 630 | + * `<input type="file">` when it lands on one, or anywhere on the | |
| 631 | + * `form.wp-upload-form` box around it (Upload Plugin, Upload | |
| 632 | + * Theme), and stamps `data-os-file-drop-active` on that box while | |
| 633 | + * the drag is over it. Outside the shell the box gives no sign it | |
| 634 | + * will take a drop; inside, the shell used to take the file | |
| 635 | + * instead, so people learned it would not. Say so while it can. | |
| 636 | + * | |
| 637 | + * Core's own admin colour, read the way common.css reads it, not | |
| 638 | + * the station's: this is a wp-admin control on a wp-admin page. | |
| 639 | + * --------------------------------------------------------------- */ | |
| 640 | +.os-chromeless [data-os-file-drop-active] { | |
| 641 | + outline: 2px dashed var( --wp-admin-theme-color, #3858e9 ); | |
| 642 | + outline-offset: -2px; | |
| 643 | +} | |
| 644 | + | |
| 645 | +/* --------------------------------------------------------------- | |
| 646 | + * Appearance → Themes workspace | |
| 647 | + * | |
| 648 | + * Core's one-theme state renders the Theme Details dialog inline and | |
| 649 | + * removes its header. Inside a short desktop window that leaves a large, | |
| 650 | + * unexplained panel whose actions fall below the fold. Treat it as an | |
| 651 | + * active-site identity card instead: screenshot first, useful context at | |
| 652 | + * the side, and actions kept in the card's visible edge. | |
| 653 | + * | |
| 654 | + * With multiple installed themes the native cards become a deliberate | |
| 655 | + * library grid and Core's details view remains a dialog. All selectors are | |
| 656 | + * scoped to the chromeless Themes screen; the classic wp-admin page keeps | |
| 657 | + * Core's own presentation and the shell's palette cannot leak in here. | |
| 658 | + * --------------------------------------------------------------- */ | |
| 659 | +.os-chromeless.themes-php #wpbody-content { | |
| 660 | + padding: 10px 16px; | |
| 661 | + background: #f6f7f7; | |
| 662 | +} | |
| 663 | + | |
| 664 | +.os-chromeless.themes-php .openstation-themes-intro { | |
| 665 | + display: flex; | |
| 666 | + align-items: center; | |
| 667 | + justify-content: space-between; | |
| 668 | + gap: 24px; | |
| 669 | + margin: 0 0 8px; | |
| 670 | + padding: 14px 18px; | |
| 671 | + background: #fff; | |
| 672 | + border: 1px solid #dcdcde; | |
| 673 | + border-radius: 12px; | |
| 674 | + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04); | |
| 675 | + box-sizing: border-box; | |
| 676 | +} | |
| 677 | + | |
| 678 | +.os-chromeless.themes-php .openstation-themes-intro__copy { | |
| 679 | + max-width: 680px; | |
| 680 | +} | |
| 681 | + | |
| 682 | +.os-chromeless.themes-php .openstation-themes-intro__eyebrow { | |
| 683 | + margin: 0 0 5px; | |
| 684 | + color: var(--wp-admin-theme-color, #2271b1); | |
| 685 | + font-size: 11px; | |
| 686 | + font-weight: 700; | |
| 687 | + letter-spacing: 0.08em; | |
| 688 | + line-height: 1.4; | |
| 689 | + text-transform: uppercase; | |
| 690 | +} | |
| 691 | + | |
| 692 | +.os-chromeless.themes-php .openstation-themes-intro h1 { | |
| 693 | + margin: 0; | |
| 694 | + color: #1d2327; | |
| 695 | + font-size: clamp(22px, 2.8vw, 30px); | |
| 696 | + font-weight: 650; | |
| 697 | + letter-spacing: -0.025em; | |
| 698 | + line-height: 1.12; | |
| 699 | +} | |
| 700 | + | |
| 701 | +.os-chromeless.themes-php .openstation-themes-intro__copy > p:last-child { | |
| 702 | + max-width: 650px; | |
| 703 | + margin: 6px 0 0; | |
| 704 | + color: #50575e; | |
| 705 | + font-size: 13px; | |
| 706 | + line-height: 1.45; | |
| 707 | +} | |
| 708 | + | |
| 709 | +.os-chromeless.themes-php .openstation-themes-intro__count { | |
| 710 | + display: grid; | |
| 711 | + flex: 0 0 auto; | |
| 712 | + min-width: 104px; | |
| 713 | + margin: 0; | |
| 714 | + padding: 10px 14px; | |
| 715 | + background: #f6f7f7; | |
| 716 | + border: 1px solid #dcdcde; | |
| 717 | + border-radius: 9px; | |
| 718 | + box-sizing: border-box; | |
| 719 | + text-align: center; | |
| 720 | +} | |
| 721 | + | |
| 722 | +.os-chromeless.themes-php .openstation-themes-intro__count strong { | |
| 723 | + color: #1d2327; | |
| 724 | + font-size: 22px; | |
| 725 | + font-weight: 650; | |
| 726 | + letter-spacing: -0.03em; | |
| 727 | + line-height: 1; | |
| 728 | +} | |
| 729 | + | |
| 730 | +.os-chromeless.themes-php .openstation-themes-intro__count span { | |
| 731 | + margin-top: 5px; | |
| 732 | + color: #646970; | |
| 733 | + font-size: 10px; | |
| 734 | + font-weight: 600; | |
| 735 | + letter-spacing: 0.04em; | |
| 736 | + line-height: 1.25; | |
| 737 | + text-transform: uppercase; | |
| 738 | +} | |
| 739 | + | |
| 740 | +.os-chromeless.themes-php .wrap { | |
| 741 | + margin: 0; | |
| 742 | +} | |
| 743 | + | |
| 744 | +.os-chromeless.themes-php .search-form { | |
| 745 | + display: flex; | |
| 746 | + margin: 0 0 16px; | |
| 747 | + padding: 0; | |
| 748 | +} | |
| 749 | + | |
| 750 | +.os-chromeless.themes-php .wp-filter-search { | |
| 751 | + width: min(320px, 100%); | |
| 752 | + min-height: 36px; | |
| 753 | + padding-inline: 12px; | |
| 754 | + background: #fff; | |
| 755 | + border-color: #8c8f94; | |
| 756 | + border-radius: 7px; | |
| 757 | +} | |
| 758 | + | |
| 759 | +/* Searching a library of one is noise, so the field goes away in Core's | |
| 760 | + * single-theme state. The general sibling combinator rather than `+`: | |
| 761 | + * themes.php emits `wp_admin_notice()` output between the search form and | |
| 762 | + * `.theme-browser` on `?activated`, `?deleted`, `?broken` and | |
| 763 | + * `?delete-active-child` — exactly the loads that follow activating or | |
| 764 | + * deleting a theme — which breaks strict adjacency. */ | |
| 765 | +.os-chromeless.themes-php | |
| 766 | + .search-form:has(~ .theme-browser .themes.single-theme) { | |
| 767 | + display: none; | |
| 768 | +} | |
| 769 | + | |
| 770 | +/* Installed-theme library. The Add Theme destination already has its own | |
| 771 | + * persistent window tab, so Core's duplicate dashed card is unnecessary. */ | |
| 772 | +.os-chromeless.themes-php .theme-browser .themes:not(.single-theme) { | |
| 773 | + display: grid; | |
| 774 | + grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); | |
| 775 | + gap: 18px; | |
| 776 | + clear: both; | |
| 777 | +} | |
| 778 | + | |
| 779 | +.os-chromeless.themes-php .theme-browser .themes:not(.single-theme) > .theme { | |
| 780 | + float: none; | |
| 781 | + width: auto; | |
| 782 | + margin: 0; | |
| 783 | + background: #fff; | |
| 784 | + border: 1px solid #c3c4c7; | |
| 785 | + border-radius: 10px; | |
| 786 | + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04); | |
| 787 | + overflow: hidden; | |
| 788 | + transition: | |
| 789 | + border-color 120ms ease, | |
| 790 | + box-shadow 120ms ease, | |
| 791 | + transform 120ms ease; | |
| 792 | +} | |
| 793 | + | |
| 794 | +.os-chromeless.themes-php | |
| 795 | + .theme-browser | |
| 796 | + .themes:not(.single-theme) | |
| 797 | + > .theme:hover, | |
| 798 | +.os-chromeless.themes-php | |
| 799 | + .theme-browser | |
| 800 | + .themes:not(.single-theme) | |
| 801 | + > .theme.focus { | |
| 802 | + border-color: #8c8f94; | |
| 803 | + box-shadow: 0 7px 20px rgba(0, 0, 0, 0.1); | |
| 804 | + transform: translateY(-2px); | |
| 805 | +} | |
| 806 | + | |
| 807 | +.os-chromeless.themes-php | |
| 808 | + .theme-browser | |
| 809 | + .themes:not(.single-theme) | |
| 810 | + > .theme.active { | |
| 811 | + border-color: var(--wp-admin-theme-color, #2271b1); | |
| 812 | + box-shadow: | |
| 813 | + 0 0 0 1px var(--wp-admin-theme-color, #2271b1), | |
| 814 | + 0 7px 20px rgba(0, 0, 0, 0.08); | |
| 815 | +} | |
| 816 | + | |
| 817 | +.os-chromeless.themes-php | |
| 818 | + .theme-browser | |
| 819 | + .themes:not(.single-theme) | |
| 820 | + > .add-new-theme { | |
| 821 | + display: none; | |
| 822 | +} | |
| 823 | + | |
| 824 | +.os-chromeless.themes-php | |
| 825 | + .theme-browser | |
| 826 | + .themes:not(.single-theme) | |
| 827 | + .theme-screenshot { | |
| 828 | + background: #f0f0f1; | |
| 829 | +} | |
| 830 | + | |
| 831 | +.os-chromeless.themes-php | |
| 832 | + .theme-browser | |
| 833 | + .themes:not(.single-theme) | |
| 834 | + .theme-id-container { | |
| 835 | + display: flex; | |
| 836 | + align-items: center; | |
| 837 | + justify-content: space-between; | |
| 838 | + min-height: 58px; | |
| 839 | + background: #fff; | |
| 840 | +} | |
| 841 | + | |
| 842 | +.os-chromeless.themes-php .theme-browser .themes:not(.single-theme) .theme-name, | |
| 843 | +.os-chromeless.themes-php | |
| 844 | + .theme-browser | |
| 845 | + .themes:not(.single-theme) | |
| 846 | + .theme.active | |
| 847 | + .theme-name { | |
| 848 | + flex: 1 1 auto; | |
| 849 | + height: auto; | |
| 850 | + min-width: 0; | |
| 851 | + margin: 0; | |
| 852 | + padding: 14px 12px 14px 14px; | |
| 853 | + background: #fff; | |
| 854 | + box-shadow: none; | |
| 855 | + color: #1d2327; | |
| 856 | + font-size: 14px; | |
| 857 | + font-weight: 600; | |
| 858 | + line-height: 1.3; | |
| 859 | +} | |
| 860 | + | |
| 861 | +.os-chromeless.themes-php | |
| 862 | + .theme-browser | |
| 863 | + .themes:not(.single-theme) | |
| 864 | + .theme.active | |
| 865 | + .theme-name | |
| 866 | + span { | |
| 867 | + display: block; | |
| 868 | + margin-bottom: 2px; | |
| 869 | + color: var(--wp-admin-theme-color, #2271b1); | |
| 870 | + font-size: 10px; | |
| 871 | + font-weight: 700; | |
| 872 | + letter-spacing: 0.06em; | |
| 873 | + line-height: 1.2; | |
| 874 | + text-transform: uppercase; | |
| 875 | +} | |
| 876 | + | |
| 877 | +.os-chromeless.themes-php | |
| 878 | + .theme-browser | |
| 879 | + .themes:not(.single-theme) | |
| 880 | + .theme-actions, | |
| 881 | +.os-chromeless.themes-php | |
| 882 | + .theme-browser | |
| 883 | + .themes:not(.single-theme) | |
| 884 | + .theme.active | |
| 885 | + .theme-actions { | |
| 886 | + display: flex; | |
| 887 | + align-items: center; | |
| 888 | + flex: 0 0 auto; | |
| 889 | + position: static; | |
| 890 | + opacity: 1; | |
| 891 | + padding: 10px 12px 10px 0; | |
| 892 | + background: #fff; | |
| 893 | + border: 0; | |
| 894 | + box-shadow: none; | |
| 895 | + transform: none; | |
| 896 | +} | |
| 897 | + | |
| 898 | +/* Multiple-theme details remain a modal, but fit the iframe rather than | |
| 899 | + * reserving the classic admin sidebar's 160px gutter. */ | |
| 900 | +.os-chromeless.themes-php .theme-overlay.active .theme-backdrop { | |
| 901 | + position: fixed; | |
| 902 | + left: 0; | |
| 903 | + background: rgba(29, 35, 39, 0.62); | |
| 904 | + backdrop-filter: blur(2px); | |
| 905 | +} | |
| 906 | + | |
| 907 | +.os-chromeless.themes-php .theme-overlay.active .theme-wrap { | |
| 908 | + top: 18px; | |
| 909 | + right: 18px; | |
| 910 | + bottom: 18px; | |
| 911 | + left: 18px; | |
| 912 | + border: 1px solid #c3c4c7; | |
| 913 | + border-radius: 12px; | |
| 914 | + box-shadow: 0 20px 55px rgba(0, 0, 0, 0.28); | |
| 915 | + overflow: hidden; | |
| 916 | +} | |
| 917 | + | |
| 918 | +.os-chromeless.themes-php .theme-overlay.active .theme-header { | |
| 919 | + background: #fff; | |
| 920 | +} | |
| 921 | + | |
| 922 | +.os-chromeless.themes-php .theme-overlay.active .theme-about { | |
| 923 | + padding: 24px; | |
| 924 | +} | |
| 925 | + | |
| 926 | +.os-chromeless.themes-php .theme-overlay.active .theme-actions { | |
| 927 | + justify-content: flex-end; | |
| 928 | + padding: 10px 16px 5px; | |
| 929 | +} | |
| 930 | + | |
| 931 | +/* Single-theme mode is a workspace card, not a stranded modal. */ | |
| 932 | +.os-chromeless.themes-php .themes.single-theme { | |
| 933 | + display: block; | |
| 934 | + margin: 0; | |
| 935 | +} | |
| 936 | + | |
| 937 | +.os-chromeless.themes-php .themes.single-theme .theme-overlay.active { | |
| 938 | + display: block; | |
| 939 | + position: static; | |
| 940 | +} | |
| 941 | + | |
| 942 | +.os-chromeless.themes-php | |
| 943 | + .themes.single-theme | |
| 944 | + .theme-overlay.active | |
| 945 | + .theme-backdrop, | |
| 946 | +.os-chromeless.themes-php | |
| 947 | + .themes.single-theme | |
| 948 | + .theme-overlay.active | |
| 949 | + .theme-header { | |
| 950 | + display: none; | |
| 951 | +} | |
| 952 | + | |
| 953 | +.os-chromeless.themes-php | |
| 954 | + .themes.single-theme | |
| 955 | + .theme-overlay.active | |
| 956 | + .theme-wrap { | |
| 957 | + display: grid; | |
| 958 | + grid-template-columns: minmax(320px, 0.95fr) minmax(300px, 1.05fr); | |
| 959 | + grid-template-areas: "screenshot details"; | |
| 960 | + column-gap: 24px; | |
| 961 | + align-items: start; | |
| 962 | + position: relative; | |
| 963 | + top: auto; | |
| 964 | + right: auto; | |
| 965 | + bottom: auto; | |
| 966 | + left: auto; | |
| 967 | + min-height: 0; | |
| 968 | + padding: 12px 16px; | |
| 969 | + background: #fff; | |
| 970 | + border: 1px solid #c3c4c7; | |
| 971 | + border-radius: 12px; | |
| 972 | + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08); | |
| 973 | + overflow: visible; | |
| 974 | + z-index: 10; | |
| 975 | +} | |
| 976 | + | |
| 977 | +.os-chromeless.themes-php | |
| 978 | + .themes.single-theme | |
| 979 | + .theme-overlay.active | |
| 980 | + .theme-about { | |
| 981 | + display: contents; | |
| 982 | +} | |
| 983 | + | |
| 984 | +.os-chromeless.themes-php | |
| 985 | + .themes.single-theme | |
| 986 | + .theme-overlay.active | |
| 987 | + .theme-screenshots { | |
| 988 | + grid-area: screenshot; | |
| 989 | + float: none; | |
| 990 | + width: 100%; | |
| 991 | + max-width: none; | |
| 992 | + margin: 0; | |
| 993 | +} | |
| 994 | + | |
| 995 | +.os-chromeless.themes-php | |
| 996 | + .themes.single-theme | |
| 997 | + .theme-overlay.active | |
| 998 | + .screenshot { | |
| 999 | + background: #f0f0f1; | |
| 1000 | + border: 0; | |
| 1001 | + border-radius: 8px; | |
| 1002 | + box-shadow: 0 0 0 1px #dcdcde; | |
| 1003 | + overflow: hidden; | |
| 1004 | +} | |
| 1005 | + | |
| 1006 | +.os-chromeless.themes-php | |
| 1007 | + .themes.single-theme | |
| 1008 | + .theme-overlay.active | |
| 1009 | + .theme-info { | |
| 1010 | + grid-area: details; | |
| 1011 | + align-self: start; | |
| 1012 | + float: none; | |
| 1013 | + width: auto; | |
| 1014 | + max-height: 240px; | |
| 1015 | + padding: 2px 10px 2px 0; | |
| 1016 | + overflow: auto; | |
| 1017 | + scrollbar-gutter: stable; | |
| 1018 | +} | |
| 1019 | + | |
| 1020 | +.os-chromeless.themes-php | |
| 1021 | + .themes.single-theme | |
| 1022 | + .theme-overlay.active | |
| 1023 | + .current-label { | |
| 1024 | + margin: 0 0 10px; | |
| 1025 | + padding: 4px 9px; | |
| 1026 | + background: #e7f5ed; | |
| 1027 | + border: 1px solid #9ad7b5; | |
| 1028 | + border-radius: 999px; | |
| 1029 | + color: #0a5c36; | |
| 1030 | + font-size: 10px; | |
| 1031 | + font-weight: 700; | |
| 1032 | + letter-spacing: 0.05em; | |
| 1033 | + line-height: 1.4; | |
| 1034 | + text-transform: uppercase; | |
| 1035 | +} | |
| 1036 | + | |
| 1037 | +.os-chromeless.themes-php | |
| 1038 | + .themes.single-theme | |
| 1039 | + .theme-overlay.active | |
| 1040 | + .theme-name { | |
| 1041 | + margin: 0; | |
| 1042 | + color: #1d2327; | |
| 1043 | + font-size: clamp(25px, 3vw, 34px); | |
| 1044 | + font-weight: 650; | |
| 1045 | + letter-spacing: -0.03em; | |
| 1046 | + line-height: 1.12; | |
| 1047 | +} | |
| 1048 | + | |
| 1049 | +.os-chromeless.themes-php | |
| 1050 | + .themes.single-theme | |
| 1051 | + .theme-overlay.active | |
| 1052 | + .theme-version { | |
| 1053 | + margin-left: 8px; | |
| 1054 | + color: #646970; | |
| 1055 | + font-size: 11px; | |
| 1056 | + font-weight: 500; | |
| 1057 | + letter-spacing: 0; | |
| 1058 | +} | |
| 1059 | + | |
| 1060 | +.os-chromeless.themes-php | |
| 1061 | + .themes.single-theme | |
| 1062 | + .theme-overlay.active | |
| 1063 | + .theme-author { | |
| 1064 | + margin: 8px 0 14px; | |
| 1065 | + color: #646970; | |
| 1066 | + font-size: 13px; | |
| 1067 | +} | |
| 1068 | + | |
| 1069 | +.os-chromeless.themes-php | |
| 1070 | + .themes.single-theme | |
| 1071 | + .theme-overlay.active | |
| 1072 | + .theme-autoupdate { | |
| 1073 | + margin: 0 0 14px; | |
| 1074 | + padding: 9px 10px; | |
| 1075 | + background: #f6f7f7; | |
| 1076 | + border: 1px solid #dcdcde; | |
| 1077 | + border-radius: 6px; | |
| 1078 | + font-size: 12px; | |
| 1079 | +} | |
| 1080 | + | |
| 1081 | +.os-chromeless.themes-php | |
| 1082 | + .themes.single-theme | |
| 1083 | + .theme-overlay.active | |
| 1084 | + .theme-description { | |
| 1085 | + margin: 0; | |
| 1086 | + color: #3c434a; | |
| 1087 | + font-size: 13px; | |
| 1088 | + line-height: 1.55; | |
| 1089 | +} | |
| 1090 | + | |
| 1091 | +.os-chromeless.themes-php | |
| 1092 | + .themes.single-theme | |
| 1093 | + .theme-overlay.active | |
| 1094 | + .theme-tags, | |
| 1095 | +.os-chromeless.themes-php | |
| 1096 | + .themes.single-theme | |
| 1097 | + .theme-overlay.active | |
| 1098 | + .parent-theme { | |
| 1099 | + margin-top: 16px; | |
| 1100 | + padding-top: 12px; | |
| 1101 | + border-top-width: 1px; | |
| 1102 | + color: #646970; | |
| 1103 | + font-size: 11px; | |
| 1104 | + line-height: 1.5; | |
| 1105 | +} | |
| 1106 | + | |
| 1107 | +.os-chromeless.themes-php | |
| 1108 | + .themes.single-theme | |
| 1109 | + .theme-overlay.active | |
| 1110 | + .theme-actions { | |
| 1111 | + display: flex; | |
| 1112 | + grid-area: details; | |
| 1113 | + align-items: center; | |
| 1114 | + align-self: end; | |
| 1115 | + justify-content: flex-start; | |
| 1116 | + position: static; | |
| 1117 | + padding: 14px 0 0; | |
| 1118 | + background: transparent; | |
| 1119 | + border-top: 1px solid #dcdcde; | |
| 1120 | + text-align: left; | |
| 1121 | +} | |
| 1122 | + | |
| 1123 | +.os-chromeless.themes-php | |
| 1124 | + .themes.single-theme | |
| 1125 | + .theme-overlay.active | |
| 1126 | + .theme-actions | |
| 1127 | + .active-theme { | |
| 1128 | + display: flex; | |
| 1129 | + flex-wrap: wrap; | |
| 1130 | + gap: 7px; | |
| 1131 | +} | |
| 1132 | + | |
| 1133 | +.os-chromeless.themes-php | |
| 1134 | + .themes.single-theme | |
| 1135 | + .theme-overlay.active | |
| 1136 | + .theme-actions | |
| 1137 | + .inactive-theme { | |
| 1138 | + display: none; | |
| 1139 | +} | |
| 1140 | + | |
| 1141 | +.os-chromeless.themes-php | |
| 1142 | + .themes.single-theme | |
| 1143 | + .theme-overlay.active | |
| 1144 | + .theme-actions | |
| 1145 | + .button { | |
| 1146 | + margin: 0; | |
| 1147 | +} | |
| 1148 | + | |
| 1149 | +@media (max-width: 760px) { | |
| 1150 | + .os-chromeless.themes-php #wpbody-content { | |
| 1151 | + padding: 12px; | |
| 1152 | + } | |
| 1153 | + | |
| 1154 | + .os-chromeless.themes-php .openstation-themes-intro { | |
| 1155 | + align-items: flex-start; | |
| 1156 | + gap: 16px; | |
| 1157 | + padding: 16px; | |
| 1158 | + } | |
| 1159 | + | |
| 1160 | + .os-chromeless.themes-php .openstation-themes-intro__copy > p:last-child { | |
| 1161 | + display: none; | |
| 1162 | + } | |
| 1163 | + | |
| 1164 | + .os-chromeless.themes-php | |
| 1165 | + .themes.single-theme | |
| 1166 | + .theme-overlay.active | |
| 1167 | + .theme-wrap { | |
| 1168 | + grid-template-columns: minmax(0, 1fr); | |
| 1169 | + grid-template-areas: | |
| 1170 | + "screenshot" | |
| 1171 | + "info" | |
| 1172 | + "actions"; | |
| 1173 | + padding: 16px; | |
| 1174 | + } | |
| 1175 | + | |
| 1176 | + .os-chromeless.themes-php | |
| 1177 | + .themes.single-theme | |
| 1178 | + .theme-overlay.active | |
| 1179 | + .theme-info { | |
| 1180 | + grid-area: info; | |
| 1181 | + max-height: none; | |
| 1182 | + padding-right: 0; | |
| 1183 | + overflow: visible; | |
| 1184 | + } | |
| 1185 | + | |
| 1186 | + .os-chromeless.themes-php | |
| 1187 | + .themes.single-theme | |
| 1188 | + .theme-overlay.active | |
| 1189 | + .theme-actions { | |
| 1190 | + grid-area: actions; | |
| 1191 | + } | |
| 1192 | + | |
| 1193 | + .os-chromeless.themes-php .theme-overlay.active .theme-wrap { | |
| 1194 | + top: 10px; | |
| 1195 | + right: 10px; | |
| 1196 | + bottom: 10px; | |
| 1197 | + left: 10px; | |
| 1198 | + } | |
| 1199 | +} | |
| 1200 | + | |
| 1201 | +@media (max-width: 480px) { | |
| 1202 | + .os-chromeless.themes-php .openstation-themes-intro__count { | |
| 1203 | + display: none; | |
| 1204 | + } | |
| 1205 | + | |
| 1206 | + .os-chromeless.themes-php .openstation-themes-intro h1 { | |
| 1207 | + font-size: 21px; | |
| 1208 | + } | |
| 1209 | +} | |
| 1210 | + | |
| 1211 | +@media (prefers-reduced-motion: reduce) { | |
| 1212 | + .os-chromeless.themes-php | |
| 1213 | + .theme-browser | |
| 1214 | + .themes:not(.single-theme) | |
| 1215 | + > .theme { | |
| 1216 | + transition: none; | |
| 1217 | + } | |
| 430 | 1218 | } |