Merge pull request 'feat(frontend): adopt zibll site-layout-1/2/3 float dual-column system' (#139) from worktree-site-layout-zibll into main

Reviewed-on: CYL/wordpress-theme-aksrt#139
This commit is contained in:
2026-07-15 00:32:56 +08:00
15 changed files with 354 additions and 168 deletions
@@ -14,7 +14,7 @@ export const layoutSchema = {
container_max_width: 1200,
sidebar_enabled: true,
sidebar_position: 'right',
sidebar_width: 300,
sidebar_width: 311,
sidebar_home_enabled: true,
sidebar_category_enabled: true,
sidebar_tag_enabled: true,
@@ -112,14 +112,10 @@
}
}
/* Dual-column geometry is owned by body.site-layout-* float rules in layout.css. */
.aksrt-homepage__content-layout {
gap: 20px;
}
@media (min-width: 992px) {
.aksrt-homepage__content-layout {
grid-template-columns: minmax(0, 1fr) var(--sidebar-width, 311px);
}
display: block;
gap: 0;
}
@media (max-width: 1200px) {
+92 -32
View File
@@ -109,62 +109,122 @@
font-weight: 600;
}
.content-layout {
display: grid;
grid-template-columns: 1fr;
gap: 20px;
align-items: start;
/* ============================================================
* Site shell — Zibll site-layout-1/2/3 float dual-column
* body.site-layout-1 = no sidebar
* body.site-layout-2 = sidebar right
* body.site-layout-3 = sidebar left
* ============================================================ */
main.container,
main.content-shell,
.site-main.container {
position: relative;
}
@media (min-width: 992px) {
.content-layout {
grid-template-columns: minmax(0, 1fr) var(--sidebar-width, 311px);
gap: 20px;
}
main.container::after,
main.content-shell::after,
.site-main.container::after {
content: "";
display: table;
clear: both;
}
.content-wrap {
float: left;
width: 100%;
min-width: 0;
}
.content-layout {
display: block;
width: 100%;
min-width: 0;
margin-right: 0;
margin-left: 0;
}
.content-layout__primary {
min-width: 0;
max-width: 100%;
}
.content-layout__aside {
.content-layout__aside,
.sidebar {
min-width: 0;
}
/* No sidebar */
body.site-layout-1 .sidebar {
display: none;
}
body.site-layout-1 .content-layout,
body.site-layout-1 .content-layout--no-sidebar {
margin-left: 0;
margin-right: 0;
}
/* Compat: templates may still stamp content-layout--no-sidebar */
.content-layout--no-sidebar {
margin-left: 0 !important;
margin-right: 0 !important;
}
/* Sidebar RIGHT (layout 2) — Zibll default */
body.site-layout-2 .content-layout {
margin-right: calc(var(--sidebar-width, 311px) + 15px);
margin-left: 0;
}
body.site-layout-2 .sidebar {
float: left;
width: var(--sidebar-width, 311px);
margin-left: calc(0px - var(--sidebar-width, 311px));
position: relative;
}
/* Sidebar LEFT (layout 3) */
body.site-layout-3 .content-layout {
margin-left: calc(var(--sidebar-width, 311px) + 15px);
margin-right: unset;
}
body.site-layout-3 .sidebar {
float: left;
width: var(--sidebar-width, 311px);
margin-left: -100%;
position: relative;
}
/* Sticky widgets inside sidebar */
@media (min-width: 992px) {
body.site-layout-2 .sidebar .posts-nav-box,
body.site-layout-3 .sidebar .posts-nav-box,
.sidebar .content-layout__aside,
.content-layout__aside {
position: sticky;
top: calc(var(--nav-height, 60px) + 16px);
align-self: start;
}
/* WordPress Admin Bar 已全局禁用,无需偏移规则 */
}
@media (min-width: 992px) {
.has-static-nav .sidebar .posts-nav-box,
.has-static-nav .content-layout__aside {
top: 16px;
}
}
.content-layout--no-sidebar {
grid-template-columns: 1fr;
}
.content-layout--no-sidebar .content-layout__primary {
width: 100%;
max-width: var(--content-no-sidebar-max, 1080px);
margin: 0 auto;
}
/* 三栏布局变体:侧边栏在左侧 */
@media (min-width: 992px) {
.content-layout--sidebar-left {
grid-template-columns: var(--sidebar-width, 311px) minmax(0, 1fr);
/* Mobile collapse (Zibll max-width: 991px) */
@media (max-width: 991.98px) {
body.site-layout-2 .content-layout,
body.site-layout-3 .content-layout {
margin-left: auto;
margin-right: auto;
}
.content-layout--sidebar-left .content-layout__aside {
order: -1;
body.site-layout-2 .sidebar,
body.site-layout-3 .sidebar,
.sidebar {
display: none;
}
}
+3 -2
View File
@@ -1,7 +1,8 @@
/* ========== 侧边栏 — 对齐 zibll sidebar ========== */
/* Width/float geometry is owned by body.site-layout-* in layout.css.
* Keep only non-layout chrome here. */
.sidebar {
width: var(--sidebar-width, 311px);
flex-shrink: 0;
box-sizing: border-box;
}
.sidebar-inner {
+9 -87
View File
@@ -1,44 +1,11 @@
/* Single page shell — dual column + fixed-nav safe top spacing */
/*
* Global layout.css turns .content-layout into a 2-col grid that expects
* .content-layout__primary + .content-layout__aside children.
* Single posts put breadcrumb / article / author / related / comments as
* direct children of .content-layout, and render .sidebar as a sibling of
* .content-wrap under main.container. Force a page-owned layout here.
*/
body.single main.container {
position: relative;
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 20px;
align-items: start;
box-sizing: border-box;
width: 100%;
}
/* Extra breathing room under fixed header (body.nav-fixed already reserves
* --nav-height; this keeps breadcrumb from sitting flush under the bar). */
body.single.nav-fixed main.container {
padding-top: 12px;
}
body.single main.container > .content-wrap {
float: none;
width: auto;
min-width: 0;
max-width: 100%;
grid-column: 1;
grid-row: 1;
}
/* Single page shell — relies on body.site-layout-1/2/3 float dual-column
* defined in layout.css (Zibll 1:1). Page-owned overrides stay minimal. */
/* Single article stack lives inside .content-layout as direct children;
* do not re-enable the legacy primary/aside grid here. */
body.single main.container .content-layout {
display: block;
grid-template-columns: none;
gap: 0;
width: 100%;
min-width: 0;
margin-right: 0 !important; /* kill residual float-layout reservation */
}
body.single main.container .content-layout > * {
@@ -46,7 +13,7 @@ body.single main.container .content-layout > * {
max-width: 100%;
}
/* Breadcrumb must stay in the content flow and under the fixed header. */
/* Breadcrumb sits under fixed header (body.nav-fixed already pads top). */
body.single main.container .content-layout > .breadcrumb,
body.single main.container .content-layout > ul.breadcrumb,
body.single main.container .content-layout > .breadcrumb-nav,
@@ -58,58 +25,13 @@ body.single main.container .content-layout > .breadcrumbs-wrap {
padding-top: 2px;
}
/* Sidebar is a direct child of main.container (not inside .content-layout). */
body.single main.container > .sidebar {
float: none;
position: relative;
width: 100%;
min-width: 0;
max-width: 100%;
margin-left: 0;
grid-column: 1;
}
/* Desktop: content | sidebar in one row (no negative-margin float hack). */
@media (min-width: 992px) {
body.single main.container:not(.container--no-sidebar) {
grid-template-columns: minmax(0, 1fr) var(--sidebar-width, 300px);
column-gap: 20px;
}
body.single main.container:not(.container--no-sidebar) > .content-wrap {
grid-column: 1;
grid-row: 1;
}
body.single main.container:not(.container--no-sidebar) > .sidebar {
grid-column: 2;
grid-row: 1;
width: 100%;
margin-left: 0;
align-self: start;
}
}
@media (max-width: 991.98px) {
body.single main.container > .sidebar {
display: none;
}
}
/* Sidebar widgets spacing */
body.single .sidebar .zib-widget,
body.single .sidebar .widget {
margin-bottom: 15px;
}
/* Sticky TOC widget in sidebar */
body.single .sidebar .posts-nav-box.toc-widget {
position: sticky;
top: calc(var(--nav-height, 60px) + 16px);
}
/* Override generic sidebar.css absolute widths (280/311) so the grid cell owns sizing */
@media (min-width: 992px) {
body.single main.container > .sidebar {
width: 100%;
}
body.single .sidebar .zib-widget,
body.single .sidebar .widget {
margin-bottom: 15px;
}
+26
View File
@@ -176,6 +176,21 @@ class AKSRT_Post_Meta_Box {
<option value="mini" <?php selected($meta['layout_override'], 'mini'); ?>><?php esc_html_e('迷你', 'aksrt'); ?></option>
</select>
<p><strong><?php esc_html_e('侧栏布局(Zibll show_layout)', 'aksrt'); ?></strong></p>
<?php
$show_layout = (string) get_post_meta($post->ID, '_aksrt_show_layout', true);
if (!in_array($show_layout, ['no_sidebar', 'sidebar_left', 'sidebar_right'], true)) {
$show_layout = '';
}
?>
<select name="aksrt_show_layout" class="widefat">
<option value="" <?php selected($show_layout, ''); ?>><?php esc_html_e('跟随全局', 'aksrt'); ?></option>
<option value="no_sidebar" <?php selected($show_layout, 'no_sidebar'); ?>><?php esc_html_e('无侧栏', 'aksrt'); ?></option>
<option value="sidebar_right" <?php selected($show_layout, 'sidebar_right'); ?>><?php esc_html_e('右侧栏', 'aksrt'); ?></option>
<option value="sidebar_left" <?php selected($show_layout, 'sidebar_left'); ?>><?php esc_html_e('左侧栏', 'aksrt'); ?></option>
</select>
<p class="description"><?php esc_html_e('覆盖全局侧栏开关与左右位置,仅影响本文/本页。', 'aksrt'); ?></p>
<p><strong><?php esc_html_e('头图模式', 'aksrt'); ?></strong></p>
<select name="aksrt_post_meta[header_image_mode]" class="widefat">
<option value="" <?php selected($meta['header_image_mode'], ''); ?>><?php esc_html_e('跟随全局', 'aksrt'); ?></option>
@@ -349,6 +364,17 @@ class AKSRT_Post_Meta_Box {
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (!current_user_can('edit_post', $post_id)) return;
// Zibll show_layout (independent of list layout_override).
$show_layout = isset($_POST['aksrt_show_layout']) ? sanitize_key((string) wp_unslash($_POST['aksrt_show_layout'])) : '';
if (!in_array($show_layout, ['no_sidebar', 'sidebar_left', 'sidebar_right'], true)) {
$show_layout = '';
}
if ($show_layout !== '') {
update_post_meta($post_id, '_aksrt_show_layout', $show_layout);
} else {
delete_post_meta($post_id, '_aksrt_show_layout');
}
// §3.8 Quick / Bulk edit — separate code path (merge mode)
if (!empty($_POST['aksrt_qe_flag'])) {
$this->save_quick_edit($post_id);
@@ -119,6 +119,13 @@ trait AKSRT_Scripts_Part_2 {
$classes[] = 'auth-page';
}
// Zibll site-layout-1/2/3 (no sidebar / right / left).
if (function_exists('aksrt_body_layout_classes')) {
foreach (aksrt_body_layout_classes() as $layout_class) {
$classes[] = $layout_class;
}
}
return $classes;
}
@@ -483,7 +483,7 @@ class AKSRT_Settings_Theme_Search {
$s = AKSRT_Settings::get_all();
$position = sanitize_key((string) ($s['sidebar_position'] ?? 'right'));
$width = max(200, min(400, (int) ($s['sidebar_width'] ?? 300)));
$width = max(200, min(400, (int) ($s['sidebar_width'] ?? 311)));
return [
'enabled' => !isset($s['sidebar_enabled']) || !empty($s['sidebar_enabled']),
+9 -15
View File
@@ -275,26 +275,19 @@ if (!function_exists('aksrt_archive_has_sidebar')) :
/**
* Resolve whether a stream page should show an aside.
*
* @param string $preferred Preferred sidebar id.
* @param string $preferred Preferred sidebar id (compat only).
* @param bool $enabled Page-level sidebar toggle.
*/
function aksrt_archive_has_sidebar(string $preferred = '', bool $enabled = true): bool {
if (!$enabled || wp_is_mobile()) {
// $preferred kept for call-site compat; visibility is settings/meta driven (zibll).
unset($preferred);
if (!$enabled) {
return false;
}
if ($preferred !== '' && is_active_sidebar($preferred)) {
return true;
}
if (function_exists('aksrt_is_show_sidebar')) {
return aksrt_is_show_sidebar();
}
$fallback = function_exists('aksrt_resolve_sidebar_id') ? aksrt_resolve_sidebar_id() : 'sidebar-blog';
return is_active_sidebar($fallback)
|| is_active_sidebar('all_sidebar_top')
|| is_active_sidebar('all_sidebar_bottom');
return !wp_is_mobile();
}
endif;
@@ -440,6 +433,7 @@ endif;
if (!function_exists('aksrt_archive_close_shell')) :
/**
* Close a shared archive shell.
* Sidebar is a sibling of .content-wrap (Zibll float dual-column).
*
* @param array<string,mixed> $args Shell args.
*/
@@ -450,11 +444,11 @@ if (!function_exists('aksrt_archive_close_shell')) :
]);
?>
</div>
<?php if (!empty($args['has_sidebar'])) : ?>
<?php get_sidebar(); ?>
<?php endif; ?>
</div>
</div>
<?php if (!empty($args['has_sidebar'])) : ?>
<?php get_sidebar(); ?>
<?php endif; ?>
<?php
if (!empty($args['bottom_fluid']) && is_array($args['bottom_fluid'])) {
aksrt_archive_render_widget_zone($args['bottom_fluid'], 'fluid-widget-wrap');
+5 -2
View File
@@ -532,6 +532,9 @@ if (!function_exists('aksrt_homepage_has_sidebar')) {
* Whether the fixed homepage should render an aside column.
*/
function aksrt_homepage_has_sidebar(): bool {
if (function_exists('aksrt_is_show_sidebar')) {
return aksrt_is_show_sidebar();
}
return aksrt_homepage_has_active_sidebars([
'all_sidebar_top',
'home_sidebar',
@@ -986,10 +989,10 @@ if (!function_exists('aksrt_homepage_render_layout')) {
);
?>
</div>
<?php aksrt_homepage_render_sidebar(); ?>
</div>
</div>
<?php aksrt_homepage_render_sidebar(); ?>
</main>
<?php
aksrt_homepage_render_widget_zone(
+6 -6
View File
@@ -99,9 +99,9 @@ if (!function_exists('aksrt_single_build_context')) :
$show_pay_box = false;
}
$aside_widgets = is_active_sidebar('sidebar-article')
|| is_active_sidebar('all_sidebar_top')
|| is_active_sidebar('all_sidebar_bottom');
$show_aside = function_exists('aksrt_is_show_sidebar')
? aksrt_is_show_sidebar()
: false;
return [
'post_id' => $post_id,
@@ -138,7 +138,7 @@ if (!function_exists('aksrt_single_build_context')) :
'paid_box_position' => $paid_box_position,
'breadcrumbs_html' => $breadcrumbs_html,
'status_badge' => $status_badge,
'show_aside' => $aside_widgets || $show_toc || $has_download || $show_pay_box,
'show_aside' => $show_aside,
'toc_title' => __('文章目录', 'aksrt'),
];
}
@@ -948,7 +948,7 @@ if (!function_exists('aksrt_single_render_aside')) :
return;
}
?>
<aside class="sidebar content-layout__aside" role="complementary" aria-label="<?php esc_attr_e('侧栏', 'aksrt'); ?>">
<div class="sidebar" role="complementary" aria-label="<?php esc_attr_e('侧栏', 'aksrt'); ?>">
<?php if (!empty($ctx['has_download'])) : ?>
<?php get_template_part('templates/parts/resource-meta-box'); ?>
<?php endif; ?>
@@ -971,7 +971,7 @@ if (!function_exists('aksrt_single_render_aside')) :
<?php if (is_active_sidebar('all_sidebar_bottom')) : ?>
<?php dynamic_sidebar('all_sidebar_bottom'); ?>
<?php endif; ?>
</aside>
</div>
<?php
}
endif;
+181 -4
View File
@@ -46,23 +46,200 @@ function aksrt_resolve_sidebar_id(): string {
return 'page_sidebar_' . get_queried_object_id();
}
if (is_home() || is_front_page()) {
return 'home_sidebar';
}
return 'sidebar-blog';
}
endif;
if (!function_exists('aksrt_get_post_show_layout')):
/**
* Zibll-compatible post/page layout override.
*
* Meta key: `_aksrt_show_layout`
* Values: '' (follow) | no_sidebar | sidebar_left | sidebar_right
*
* @param int|null $post_id Post ID.
*/
function aksrt_get_post_show_layout($post_id = null): string {
$post_id = $post_id ? (int) $post_id : (int) get_queried_object_id();
if ($post_id <= 0) {
return '';
}
$value = (string) get_post_meta($post_id, '_aksrt_show_layout', true);
return in_array($value, ['no_sidebar', 'sidebar_left', 'sidebar_right'], true) ? $value : '';
}
endif;
if (!function_exists('aksrt_get_sidebar_config_safe')):
/**
* @return array{enabled:bool,position:string,width:int,home:bool,category:bool,tag:bool,single:bool,page:bool,search:bool}
*/
function aksrt_get_sidebar_config_safe(): array {
if (class_exists('AKSRT_Settings') && method_exists('AKSRT_Settings', 'get_sidebar_config')) {
$cfg = AKSRT_Settings::get_sidebar_config();
if (is_array($cfg)) {
return $cfg;
}
}
return [
'enabled' => true,
'position' => 'right',
'width' => 311,
'home' => true,
'category' => true,
'tag' => true,
'single' => true,
'page' => true,
'search' => true,
];
}
endif;
if (!function_exists('aksrt_is_show_sidebar')):
/**
* 统一判断当前页面是否展示侧栏。
* Zibll-strict sidebar visibility (settings + post meta, not widget presence).
*
* Filter: aksrt_is_show_sidebar
*
* @return bool
*/
function aksrt_is_show_sidebar(): bool {
if (wp_is_mobile()) {
$show = aksrt_is_show_sidebar_filter();
return (bool) apply_filters('aksrt_is_show_sidebar', $show);
}
endif;
if (!function_exists('aksrt_is_show_sidebar_filter')):
/**
* Core sidebar visibility decision (Zibll zib_is_show_sidebar_filter parity).
*/
function aksrt_is_show_sidebar_filter(): bool {
if (function_exists('wp_is_mobile') && wp_is_mobile()) {
return false;
}
$sidebar_id = aksrt_resolve_sidebar_id();
return is_active_sidebar($sidebar_id) || is_active_sidebar('all_sidebar_top') || is_active_sidebar('all_sidebar_bottom');
$cfg = aksrt_get_sidebar_config_safe();
if (empty($cfg['enabled'])) {
return false;
}
// Single / page: post meta can force show/hide (Zibll show_layout).
if (is_singular()) {
$layout = aksrt_get_post_show_layout(get_queried_object_id());
if ($layout === 'no_sidebar') {
return false;
}
if ($layout === 'sidebar_left' || $layout === 'sidebar_right') {
return true;
}
}
if ((is_home() || is_front_page()) && empty($cfg['home'])) {
return false;
}
if (is_single() && empty($cfg['single'])) {
return false;
}
if (is_page() && empty($cfg['page'])) {
return false;
}
if (is_category() && empty($cfg['category'])) {
return false;
}
if (is_tag() && empty($cfg['tag'])) {
return false;
}
if (is_search() && empty($cfg['search'])) {
return false;
}
// Category/tag term meta can still force off (existing AKSRT contract).
if ((is_category() || is_tag()) && class_exists('AKSRT_Term_Meta') && method_exists('AKSRT_Term_Meta', 'resolve_archive_settings')) {
$term_id = (int) get_queried_object_id();
if ($term_id > 0) {
$resolved = AKSRT_Term_Meta::resolve_archive_settings($term_id);
if (is_array($resolved) && array_key_exists('show_sidebar', $resolved) && empty($resolved['show_sidebar'])) {
return false;
}
}
}
// Search page display setting can force off.
if (is_search() && class_exists('AKSRT_Settings') && method_exists('AKSRT_Settings', 'get_other_page_settings')) {
$other = AKSRT_Settings::get_other_page_settings();
if (is_array($other) && array_key_exists('page_search_sidebar', $other) && empty($other['page_search_sidebar'])) {
return false;
}
}
// Scene switches above already gated; when enabled, show the column
// (widgets may be empty — matches zibll empty sidebar column policy).
if (is_home() || is_front_page()) {
return !empty($cfg['home']);
}
if (is_single()) {
return !empty($cfg['single']);
}
if (is_page()) {
return !empty($cfg['page']);
}
if (is_category()) {
return !empty($cfg['category']);
}
if (is_tag()) {
return !empty($cfg['tag']);
}
if (is_search()) {
return !empty($cfg['search']);
}
// Author / other archives: follow global enabled.
return true;
}
endif;
if (!function_exists('aksrt_get_site_layout')):
/**
* Zibll site-layout mode: 1=no sidebar, 2=right, 3=left.
*/
function aksrt_get_site_layout(): int {
if (!aksrt_is_show_sidebar()) {
return 1;
}
$position = 'right';
if (is_singular()) {
$meta = aksrt_get_post_show_layout(get_queried_object_id());
if ($meta === 'sidebar_left') {
$position = 'left';
} elseif ($meta === 'sidebar_right') {
$position = 'right';
} else {
$cfg = aksrt_get_sidebar_config_safe();
$position = ($cfg['position'] ?? 'right') === 'left' ? 'left' : 'right';
}
} else {
$cfg = aksrt_get_sidebar_config_safe();
$position = ($cfg['position'] ?? 'right') === 'left' ? 'left' : 'right';
}
return $position === 'left' ? 3 : 2;
}
endif;
if (!function_exists('aksrt_body_layout_classes')):
/**
* @return string[] e.g. ['site-layout-2']
*/
function aksrt_body_layout_classes(): array {
$layout = aksrt_get_site_layout();
if (!in_array($layout, [1, 2, 3], true)) {
$layout = 1;
}
return ['site-layout-' . $layout];
}
endif;
+4 -4
View File
@@ -91,13 +91,13 @@ $show_sidebar = function_exists('aksrt_is_show_sidebar') ? aksrt_is_show_sidebar
<?php dynamic_sidebar('page_bottom_content_' . $page_id); ?>
<?php endif; ?>
</div>
<?php if ($show_sidebar) : ?>
<?php get_sidebar(); ?>
<?php endif; ?>
</div>
</div>
<?php if ($show_sidebar) : ?>
<?php get_sidebar(); ?>
<?php endif; ?>
<?php if (is_active_sidebar('page_bottom_fluid_' . $page_id)) : ?>
<div class="fluid-widget-wrap">
<?php dynamic_sidebar('page_bottom_fluid_' . $page_id); ?>
+6 -6
View File
@@ -3,6 +3,8 @@
* Sidebar template for generic pages.
*
* Single/home own their asides. This template only serves archive/page contexts.
* Callers only include this when aksrt_is_show_sidebar() is true.
* Keep the column even if widgets are empty (zibll parity).
*
* @package AKSRT
*/
@@ -16,12 +18,6 @@ if (wp_is_mobile()) {
$sidebar_id = function_exists('aksrt_resolve_sidebar_id')
? aksrt_resolve_sidebar_id()
: 'sidebar-blog';
if (!is_active_sidebar($sidebar_id)
&& !is_active_sidebar('all_sidebar_top')
&& !is_active_sidebar('all_sidebar_bottom')) {
return;
}
?>
<div class="sidebar" role="complementary" aria-label="<?php esc_attr_e('侧栏', 'aksrt'); ?>">
@@ -31,6 +27,10 @@ if (!is_active_sidebar($sidebar_id)
<?php if (is_active_sidebar($sidebar_id)) : ?>
<?php dynamic_sidebar($sidebar_id); ?>
<?php elseif ((is_home() || is_front_page()) && is_active_sidebar('home_sidebar')) : ?>
<?php dynamic_sidebar('home_sidebar'); ?>
<?php elseif ((is_home() || is_front_page()) && is_active_sidebar('sidebar-blog')) : ?>
<?php dynamic_sidebar('sidebar-blog'); ?>
<?php endif; ?>
<?php if (is_active_sidebar('all_sidebar_bottom')) : ?>
+1 -1
View File
@@ -27,7 +27,7 @@ while (have_posts()) :
}
$settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
$show_aside = !empty($ctx['show_aside']) && !wp_is_mobile();
$show_aside = !empty($ctx['show_aside']); // body site-layout-* is authoritative
get_header();
?>