<?php
declare(strict_types=1);

if (!defined('ABSPATH')) { exit; }

/**
 * Freeform (column-row layout grid) element renderer (shared).
 *
 * Phase 1, step 8 — second structural-container extraction.
 *
 * Freeform is a column-first CSS Grid where each column holds a list
 * of cells stacked vertically. Children are tagged with `_cell_col` /
 * `_cell_row` and grouped on render. Compare to rows which is
 * row-first flex.
 *
 * Pre-extraction notes:
 *
 *   - Both renderers had container bg_color/image dropped 2026-05-04
 *     (per-cell only).
 *   - Editor pre-resolves per-device via `impulse_get_responsive`;
 *     frontend reads desktop direct and emits @media queries for
 *     tablet/mobile container + cell overrides.
 *   - Editor emits `data-columns` JSON attr for the resize JS.
 *   - Editor: selected-cell highlight (.selected), empty-cell tint +
 *     plus indicator (gated on impulse_is_edit_mode).
 *   - Both: default cell valign scales with child count
 *     (1 → center, 2+ → top).
 *   - 3D depth + cell tilt: same gating in both.
 *
 * @param array|object $el           Element node.
 * @param array        $settings     Raw or pre-resolved settings.
 * @param array        $children     Pre-collected child elements.
 * @param string       $context      'frontend' or 'editor'.
 * @param callable     $renderChild  Recursion callable.
 *
 * @return string Inner HTML.
 *
 * @sideeffect Primes $GLOBALS['impulse_needs_cell_depth']; calls
 *             wp_add_inline_style for responsive @media (both contexts).
 */
function impulse_element_render_columns($el, array $settings, array $children, string $context, callable $renderChild): string {
    if (is_object($el)) $el = (array) $el;
    $elId     = preg_replace('/[^A-Za-z0-9_-]/', '', (string) ($el['id'] ?? '0'));
    $isEditor = ($context === 'editor');
    $device   = $isEditor ? ($GLOBALS['impulse_preview_device'] ?? 'desktop') : 'desktop';

    $read = function (string $key, $default) use ($settings, $isEditor) {
        if ($isEditor && function_exists('impulse_get_responsive')) {
            return impulse_get_responsive($settings, $key, $default);
        }
        return $settings[$key] ?? $default;
    };

    $gridCols = $settings['columns'] ?? [
        ['width' => 50, 'cells' => [['_empty' => true]]],
        ['width' => 50, 'cells' => [['_empty' => true], ['_empty' => true], ['_empty' => true]]],
    ];
    if (is_string($gridCols)) {
        $gridCols = json_decode($gridCols, true) ?: [];
    }

    $colGap          = intval($read('col_gap', 16));
    $cellGap         = intval($read('cell_gap', 16));
    $minHeight       = intval($read('min_height', 200));
    $cellRadius      = intval($read('cell_radius', 0));
    $paddingSides    = intval($read('padding_sides', 0));
    $paddingTop      = intval($read('padding_top', 0));
    $paddingBottom   = intval($read('padding_bottom', 0));
    $containerRadius = intval($read('border_radius', 0));
    $marginTop       = intval($read('margin_top', 0));
    $marginBottom    = intval($read('margin_bottom', 0));

    $selectedCells = $settings['_selected_cells'] ?? [];
    if (is_string($selectedCells)) $selectedCells = json_decode($selectedCells, true) ?: [];
    if (!is_array($selectedCells)) $selectedCells = [];

    $numCols      = count($gridCols);
    $mobileLayout = (string) ($settings['mobile_layout'] ?? 'stack');

    // ── grid-template-columns ────────────────────────────────────
    // Editor: pre-resolve based on device tab (so the editor's mobile
    // preview shows the stacked layout). Frontend: emit desktop values
    // and let @media rules below stack/2col on real mobile.
    if ($isEditor && $device === 'mobile' && $mobileLayout === 'stack') {
        $colTemplate = '1fr';
    } elseif ($isEditor && $device === 'mobile' && $mobileLayout === '2col') {
        $colTemplate = 'repeat(' . min(2, $numCols) . ', 1fr)';
    } else {
        $colTemplate = implode(' ', array_map(function ($col) use ($numCols) {
            return round($col['width'] ?? (100 / max(1, $numCols)), 2) . 'fr';
        }, $gridCols));
    }

    // ── Container style ──────────────────────────────────────────
    if ($isEditor) {
        $containerStyle = 'display:grid;grid-template-columns:' . $colTemplate . ';gap:' . $colGap . 'px;';
    } else {
        $containerStyle = 'width:100%;display:grid;grid-template-columns:' . $colTemplate . ';gap:' . $colGap . 'px;';
    }
    if ($minHeight > 0)    $containerStyle .= 'min-height:' . $minHeight . 'px;';
    if ($marginTop > 0)    $containerStyle .= 'margin-top:' . $marginTop . 'px;';
    if ($marginBottom > 0) $containerStyle .= 'margin-bottom:' . $marginBottom . 'px;';

    $contentWidth = function_exists('impulse_resolve_content_width')
        ? impulse_resolve_content_width($settings)
        : '100%';
    $containerStyle .= 'margin-left:auto;margin-right:auto;max-width:' . $contentWidth . ';';

    if ($paddingTop > 0 || $paddingSides > 0 || $paddingBottom > 0) {
        $containerStyle .= 'padding:' . $paddingTop . 'px ' . $paddingSides . 'px ' . $paddingBottom . 'px ' . $paddingSides . 'px;';
    }
    if ($containerRadius > 0) $containerStyle .= 'border-radius:' . $containerRadius . 'px;overflow:hidden;';

    // Container border (4-sided).
    $cbW = intval($settings['container_border_width'] ?? 0);
    if ($cbW > 0) {
        $cbColor = (string) ($settings['container_border_color'] ?? '#e0e0e0');
        $cbT = (($settings['container_border_top']    ?? null) === '0' || ($settings['container_border_top']    ?? null) === 0 || ($settings['container_border_top']    ?? null) === false) ? '0' : $cbW . 'px';
        $cbR = (($settings['container_border_right']  ?? null) === '0' || ($settings['container_border_right']  ?? null) === 0 || ($settings['container_border_right']  ?? null) === false) ? '0' : $cbW . 'px';
        $cbB = (($settings['container_border_bottom'] ?? null) === '0' || ($settings['container_border_bottom'] ?? null) === 0 || ($settings['container_border_bottom'] ?? null) === false) ? '0' : $cbW . 'px';
        $cbL = (($settings['container_border_left']   ?? null) === '0' || ($settings['container_border_left']   ?? null) === 0 || ($settings['container_border_left']   ?? null) === false) ? '0' : $cbW . 'px';
        $containerStyle .= 'border-width:' . $cbT . ' ' . $cbR . ' ' . $cbB . ' ' . $cbL . ';border-style:solid;border-color:' . esc_attr($cbColor) . ';';
    }

    // ── Animation + visibility (frontend only) ────────────────────
    $animAttrs = (!$isEditor && function_exists('impulse_get_animation_attrs'))
        ? impulse_get_animation_attrs($settings)
        : ['class' => '', 'style' => ''];
    if (!empty($animAttrs['style'])) $containerStyle .= $animAttrs['style'];

    $containerClass = 'impulse-layout-grid';
    if (!$isEditor && function_exists('impulse_get_visibility_classes')) {
        $vc = impulse_get_visibility_classes($settings);
        if ($vc !== '') $containerClass .= ' ' . $vc;
    }
    if (!empty($animAttrs['class'])) $containerClass .= ' ' . $animAttrs['class'];

    // ── Cell border (global fallback) ────────────────────────────
    $cellBorderWidth = intval($settings['cell_border_width'] ?? 0);
    $cellBorderColor = (string) ($settings['cell_border_color'] ?? '#e0e0e0');
    $celltVal = $settings['cell_border_top']    ?? null;
    $cellrVal = $settings['cell_border_right']  ?? null;
    $cellbVal = $settings['cell_border_bottom'] ?? null;
    $celllVal = $settings['cell_border_left']   ?? null;
    $cellBorderTop    = !($celltVal === '0' || $celltVal === 0 || $celltVal === false);
    $cellBorderRight  = !($cellrVal === '0' || $cellrVal === 0 || $cellrVal === false);
    $cellBorderBottom = !($cellbVal === '0' || $cellbVal === 0 || $cellbVal === false);
    $cellBorderLeft   = !($celllVal === '0' || $celllVal === 0 || $celllVal === false);

    // ── Group children by cellKey (col-row) ──────────────────────
    $childrenMap = [];
    foreach ($children as $child) {
        $cs = is_object($child) ? ((array) ($child->settings ?? new stdClass())) : ($child['settings'] ?? []);
        if (is_object($cs)) $cs = (array) $cs;
        $key = ($cs['_cell_col'] ?? 0) . '-' . ($cs['_cell_row'] ?? 0);
        if (!isset($childrenMap[$key])) $childrenMap[$key] = [];
        $childrenMap[$key][] = $child;
    }

    // ── 3D depth + cell tilt ─────────────────────────────────────
    $depthIntensity = max(0, min(100, intval($read('depth_intensity', 0))));
    $tiltIntensity  = max(0, min(100, intval($read('tilt_intensity',  0))));
    $GLOBALS['impulse_needs_cell_depth'] = true;

    if (!$isEditor && !empty($GLOBALS['impulse_use_fill_wrapper'])) {
        $containerStyle .= 'height:100%;';
    }

    // ── Container id ─────────────────────────────────────────────
    $lgId = 'impulse-lg-' . ($elId ?: uniqid());

    // Tablet wrap fallback (frontend only).
    if (!$isEditor && function_exists('wp_add_inline_style')) {
        if ($numCols > 2 && !isset($settings['columns_tablet'])) {
            wp_add_inline_style('instinctor-page-inline', '@media(max-width:1024px)and(min-width:768px){#' . $lgId . '{grid-template-columns:1fr 1fr!important}}');
        }
    }

    // ── Collect frontend-only responsive overrides ───────────────
    $responsiveTablet = [];
    $responsiveMobile = [];
    if (!$isEditor) {
        $containerResponsiveKeys = ['col_gap', 'cell_gap', 'min_height', 'padding_sides', 'padding_top', 'padding_bottom', 'cell_radius'];
        foreach ($containerResponsiveKeys as $rk) {
            if (isset($settings[$rk . '_tablet'])) $responsiveTablet['container'][$rk] = intval($settings[$rk . '_tablet']);
            if (isset($settings[$rk . '_mobile'])) $responsiveMobile['container'][$rk] = intval($settings[$rk . '_mobile']);
        }
    }

    $hasShapes  = !empty($settings['bg_shapes']) && $settings['bg_shapes'] !== '[]';
    $outerStyle = 'position:relative;' . $containerStyle . ($hasShapes ? 'overflow:hidden;' : '');

    ob_start();
    echo '<div id="' . esc_attr($lgId) . '" class="' . esc_attr($containerClass) . '"';
    if ($isEditor) {
        echo ' data-columns=\'' . esc_attr(wp_json_encode($gridCols)) . '\'';
    }
    echo ' style="' . esc_attr($outerStyle) . '" data-depth-intensity="' . esc_attr((string) $depthIntensity) . '" data-tilt-intensity="' . esc_attr((string) $tiltIntensity) . '">';

    if (function_exists('impulse_render_bg_shapes')) {
        impulse_render_bg_shapes($settings, $device, $isEditor);
    }
    if ($isEditor && function_exists('impulse_visibility_badge')) {
        echo wp_kses(impulse_visibility_badge($settings), impulse_svg_allowed());
    }

    $bgCellSelectors = []; // editor-only mobile min-height tracker

    foreach ($gridCols as $colIdx => $col) {
        $cells = $col['cells'] ?? [[]];
        $colStyle = 'display:flex;flex-direction:column;gap:' . $cellGap . 'px;position:relative;z-index:3;';
        echo '<div class="impulse-layout-col" data-col="' . esc_attr($colIdx) . '" style="' . esc_attr($colStyle) . '">';

        foreach ($cells as $rowIdx => $cellData) {
            if (!is_array($cellData)) $cellData = [];
            $cellKey      = $colIdx . '-' . $rowIdx;
            $hasChildren  = !empty($childrenMap[$cellKey]);

            // Per-device visibility classes (cell-level).
            $cellVisClass = '';
            if (!empty($cellData['hide_desktop']) && ($cellData['hide_desktop'] === '1' || $cellData['hide_desktop'] === 1)) $cellVisClass .= ' impulse-hide-desktop';
            if (!empty($cellData['hide_tablet'])  && ($cellData['hide_tablet']  === '1' || $cellData['hide_tablet']  === 1)) $cellVisClass .= ' impulse-hide-tablet';
            if (!empty($cellData['hide_mobile']) && ($cellData['hide_mobile'] === '1' || $cellData['hide_mobile'] === 1)) $cellVisClass .= ' impulse-hide-mobile';

            // Unset valign defaults to TOP (Sergei 2026-07-04): content in a
            // cell taller than its content sits at the top instead of centering.
            // Matches the editor default (admin-core.js) + grid/rows. Explicit
            // center/bottom is honoured.
            $cellValign = array_key_exists('valign', $cellData)
                ? (string) $cellData['valign']
                : 'top';
            $cellHalign = (string) ($cellData['halign'] ?? 'center');

            $cPadT = intval($cellData['padding_top']    ?? 0);
            $cPadS = intval($cellData['padding_sides']  ?? 0);
            $cPadB = intval($cellData['padding_bottom'] ?? 0);

            // Collect responsive cell overrides for the @media emit (frontend only).
            if (!$isEditor) {
                foreach (['padding_sides', 'padding_top', 'padding_bottom', 'valign'] as $crk) {
                    if (isset($cellData[$crk . '_tablet'])) $responsiveTablet['cells'][$cellKey][$crk] = $cellData[$crk . '_tablet'];
                    if (isset($cellData[$crk . '_mobile'])) $responsiveMobile['cells'][$cellKey][$crk] = $cellData[$crk . '_mobile'];
                }
            }

            $cellStyle = 'position:relative;flex:1;display:flex;flex-direction:column;';
            if ($cellRadius > 0) $cellStyle .= 'overflow:hidden;border-radius:' . $cellRadius . 'px;';
            if ($cPadT || $cPadS || $cPadB) {
                $cellStyle .= 'padding:' . $cPadT . 'px ' . $cPadS . 'px ' . $cPadB . 'px ' . $cPadS . 'px;';
            }
            if (!empty($cellData['bg_color']) && $cellData['bg_color'] !== 'transparent') {
                $cellStyle .= 'background-color:' . esc_attr((string) $cellData['bg_color']) . ';';
            }
            if (!empty($cellData['bg_image'])) {
                $bgFit = (string) ($cellData['bg_fit']      ?? 'cover');
                $bgPos = (string) ($cellData['bg_position'] ?? 'center');
                $cellStyle .= 'background-image:url(' . esc_url((string) $cellData['bg_image']) . ');background-size:' . esc_attr($bgFit) . ';background-position:' . esc_attr($bgPos) . ';background-repeat:no-repeat;';
            }

            // Container-level frosted glass — one checkbox frosts every
            // cell (moved up from per-cell, Sergei 2026-06-10). See rows.php
            // for the full rationale; emitted after bg_color so the frosted
            // bg wins.
            if (!empty($settings['frosted_glass']) && $settings['frosted_glass'] !== '0') {
                $cellStyle .= 'background-color:rgba(255,255,255,0.18);';
                $cellStyle .= 'backdrop-filter:blur(20px) saturate(180%) brightness(1.15);';
                $cellStyle .= '-webkit-backdrop-filter:blur(20px) saturate(180%) brightness(1.15);';
            }

            // Cell border: individual overrides global.
            $thisCellBorderW = intval($cellData['border_width'] ?? 0);
            if ($thisCellBorderW > 0) {
                $thisCellBorderColor = (string) ($cellData['border_color'] ?? '#e0e0e0');
                $T = (($cellData['border_top']    ?? null) === '0' || ($cellData['border_top']    ?? null) === 0 || ($cellData['border_top']    ?? null) === false) ? '0' : $thisCellBorderW . 'px';
                $R = (($cellData['border_right']  ?? null) === '0' || ($cellData['border_right']  ?? null) === 0 || ($cellData['border_right']  ?? null) === false) ? '0' : $thisCellBorderW . 'px';
                $B = (($cellData['border_bottom'] ?? null) === '0' || ($cellData['border_bottom'] ?? null) === 0 || ($cellData['border_bottom'] ?? null) === false) ? '0' : $thisCellBorderW . 'px';
                $L = (($cellData['border_left']   ?? null) === '0' || ($cellData['border_left']   ?? null) === 0 || ($cellData['border_left']   ?? null) === false) ? '0' : $thisCellBorderW . 'px';
                $cellStyle .= 'border-width:' . $T . ' ' . $R . ' ' . $B . ' ' . $L . ';border-style:solid;border-color:' . esc_attr($thisCellBorderColor) . ';';
            } elseif ($cellBorderWidth > 0) {
                $T = $cellBorderTop    ? $cellBorderWidth . 'px' : '0';
                $R = $cellBorderRight  ? $cellBorderWidth . 'px' : '0';
                $B = $cellBorderBottom ? $cellBorderWidth . 'px' : '0';
                $L = $cellBorderLeft   ? $cellBorderWidth . 'px' : '0';
                $cellStyle .= 'border-width:' . $T . ' ' . $R . ' ' . $B . ' ' . $L . ';border-style:solid;border-color:' . esc_attr($cellBorderColor) . ';';
            }

            $cellClass      = 'impulse-layout-cell' . $cellVisClass;
            $hasCellBg      = (!empty($cellData['bg_color']) && $cellData['bg_color'] !== 'transparent') || !empty($cellData['bg_image']);

            if ($isEditor) {
                if (in_array($cellKey, $selectedCells, true)) $cellClass .= ' selected';
                if (!$hasChildren && !$hasCellBg && !empty($GLOBALS['impulse_is_edit_mode'])) {
                    // Marker class instead of inline tint — same rationale as
                    // rows.php. CSS paints the tint on the empty marker,
                    // and a `:has(.impulse-el)` catch-all strips it the moment
                    // content lands in the cell, regardless of which code path
                    // added that content. Locked 2026-05-27.
                    $cellClass .= ' impulse-layout-cell-empty';
                }
                if ($hasCellBg && !$hasChildren) {
                    $bgCellSelectors[] = '[data-col="' . $colIdx . '"][data-row="' . $rowIdx . '"]';
                }
            }

            echo '<div class="' . esc_attr(trim($cellClass)) . '" data-col="' . esc_attr($colIdx) . '" data-row="' . esc_attr($rowIdx) . '" style="' . esc_attr($cellStyle) . '"';
            if ($depthIntensity > 0) {
                echo ' data-depth-row="' . esc_attr((string) $rowIdx) . '" data-depth-col="' . esc_attr((string) $colIdx) . '"';
            }
            echo '>';

            $valignMap   = ['top' => 'flex-start', 'center' => 'center', 'bottom' => 'flex-end'];
            $halignMap   = ['left' => 'flex-start', 'center' => 'center', 'right' => 'flex-end'];
            $cellJustify = $valignMap[$cellValign] ?? 'flex-start';
            $cellAlign   = $halignMap[$cellHalign] ?? 'center';

            $cgGap        = intval($settings['content_gap'] ?? 0);
            $cgGapStyle   = $cgGap > 0 ? 'gap:' . $cgGap . 'px;' : '';
            $contentStyle = 'position:relative;z-index:1;flex:1;display:flex;flex-direction:column;justify-content:' . $cellJustify . ';align-items:' . $cellAlign . ';' . $cgGapStyle;

            if ($hasChildren) {
                echo '<div class="impulse-cell-content" style="' . esc_attr($contentStyle) . '">';
                foreach ($childrenMap[$cellKey] as $childEl) {
                    $renderChild($childEl);
                }
                echo '</div>';
            } elseif ($isEditor) {
                echo '<div class="impulse-cell-content" style="' . esc_attr($contentStyle) . '">';
                if (!$hasCellBg && !empty($GLOBALS['impulse_is_edit_mode'])) {
                    echo '<span class="impulse-cell-empty-indicator" style="font-size:20px;color:' . esc_attr($GLOBALS['impulse_cell_empty_fg'] ?? 'rgba(128,128,128,0.15)') . '">+</span>';
                }
                echo '</div>';
            }

            echo '</div>'; // .impulse-layout-cell
        }

        echo '</div>'; // .impulse-layout-col
    }

    echo '</div>'; // .impulse-layout-grid

    // ── Responsive @media emission ───────────────────────────────
    $elSelector = '#' . $lgId;
    if (!$isEditor && function_exists('wp_add_inline_style')) {
        $tabletCss = '';
        $mobileCss = '';

        if (!empty($responsiveTablet['container'])) {
            $rc = $responsiveTablet['container'];
            $containerSel = $elSelector;
            $colSel = $elSelector . ' .impulse-layout-col';
            if (isset($rc['col_gap']))    $tabletCss .= $containerSel . '{gap:' . $rc['col_gap'] . 'px!important}';
            if (isset($rc['cell_gap']))   $tabletCss .= $colSel . '{gap:' . $rc['cell_gap'] . 'px!important}';
            if (isset($rc['min_height'])) $tabletCss .= $containerSel . '{min-height:' . $rc['min_height'] . 'px!important}';
            if (isset($rc['padding_sides']) || isset($rc['padding_top']) || isset($rc['padding_bottom'])) {
                $tpt = $rc['padding_top']    ?? $paddingTop;
                $tps = $rc['padding_sides']  ?? $paddingSides;
                $tpb = $rc['padding_bottom'] ?? $paddingBottom;
                $tabletCss .= $containerSel . '{padding:' . $tpt . 'px ' . $tps . 'px ' . $tpb . 'px ' . $tps . 'px!important}';
            }
            if (isset($rc['cell_radius'])) {
                $tabletCss .= $elSelector . ' .impulse-layout-cell{border-radius:' . $rc['cell_radius'] . 'px!important}';
            }
        }
        if (!empty($responsiveMobile['container'])) {
            $rc = $responsiveMobile['container'];
            $containerSel = $elSelector;
            $colSel = $elSelector . ' .impulse-layout-col';
            if (isset($rc['col_gap']))    $mobileCss .= $containerSel . '{gap:' . $rc['col_gap'] . 'px!important}';
            if (isset($rc['cell_gap']))   $mobileCss .= $colSel . '{gap:' . $rc['cell_gap'] . 'px!important}';
            if (isset($rc['min_height'])) $mobileCss .= $containerSel . '{min-height:' . $rc['min_height'] . 'px!important}';
            if (isset($rc['padding_sides']) || isset($rc['padding_top']) || isset($rc['padding_bottom'])) {
                $mpt = $rc['padding_top']    ?? ($responsiveTablet['container']['padding_top']    ?? $paddingTop);
                $mps = $rc['padding_sides']  ?? ($responsiveTablet['container']['padding_sides']  ?? $paddingSides);
                $mpb = $rc['padding_bottom'] ?? ($responsiveTablet['container']['padding_bottom'] ?? $paddingBottom);
                $mobileCss .= $containerSel . '{padding:' . $mpt . 'px ' . $mps . 'px ' . $mpb . 'px ' . $mps . 'px!important}';
            }
            if (isset($rc['cell_radius'])) {
                $mobileCss .= $elSelector . ' .impulse-layout-cell{border-radius:' . $rc['cell_radius'] . 'px!important}';
            }
        }

        foreach (['tablet' => &$tabletCss, 'mobile' => &$mobileCss] as $dev => &$devCss) {
            $devData = $dev === 'tablet' ? ($responsiveTablet['cells'] ?? []) : ($responsiveMobile['cells'] ?? []);
            foreach ($devData as $ck => $cv) {
                $parts = explode('-', $ck);
                $cellSel    = $elSelector . ' .impulse-layout-cell[data-col="' . $parts[0] . '"][data-row="' . $parts[1] . '"]';
                $contentSel = $cellSel . ' .impulse-cell-content';
                if (isset($cv['padding_sides']) || isset($cv['padding_top']) || isset($cv['padding_bottom'])) {
                    $col = intval($parts[0]); $row = intval($parts[1]);
                    $base = $gridCols[$col]['cells'][$row] ?? [];
                    $dpt = intval($cv['padding_top']    ?? ($dev === 'mobile' && isset($responsiveTablet['cells'][$ck]['padding_top'])    ? $responsiveTablet['cells'][$ck]['padding_top']    : ($base['padding_top']    ?? 0)));
                    $dps = intval($cv['padding_sides']  ?? ($dev === 'mobile' && isset($responsiveTablet['cells'][$ck]['padding_sides'])  ? $responsiveTablet['cells'][$ck]['padding_sides']  : ($base['padding_sides']  ?? 0)));
                    $dpb = intval($cv['padding_bottom'] ?? ($dev === 'mobile' && isset($responsiveTablet['cells'][$ck]['padding_bottom']) ? $responsiveTablet['cells'][$ck]['padding_bottom'] : ($base['padding_bottom'] ?? 0)));
                    $devCss .= $cellSel . '{padding:' . $dpt . 'px ' . $dps . 'px ' . $dpb . 'px ' . $dps . 'px!important}';
                }
                if (isset($cv['valign'])) {
                    $va = $cv['valign'];
                    $jc = $va === 'top' ? 'flex-start' : ($va === 'bottom' ? 'flex-end' : 'center');
                    $devCss .= $contentSel . '{justify-content:' . $jc . '!important}';
                }
            }
        }
        unset($devCss);

        if ($tabletCss || $mobileCss) {
            $css = '';
            if ($tabletCss) $css .= '@media(min-width:768px) and (max-width:1024px){' . $tabletCss . '}';
            if ($mobileCss) $css .= '@media(max-width:767px){' . $mobileCss . '}';
            wp_add_inline_style('instinctor-page-inline', $css);
        }
    }

    // Editor: emit the user-selected mobile layout (stack/2col) plus
    // bg-only-cell min-height for the editor's mobile device tab parity.
    if ($isEditor && $mobileLayout !== 'keep' && function_exists('wp_add_inline_style')) {
        $sel = '.impulse-el[data-id="' . esc_attr((string) $elId) . '"] .impulse-layout-grid';
        $css = '';
        if ($mobileLayout === 'stack') {
            $css .= '@media(max-width:767px){' . $sel . '{grid-template-columns:1fr!important}}';
        } elseif ($mobileLayout === '2col') {
            $css .= '@media(max-width:767px){' . $sel . '{grid-template-columns:repeat(' . min(2, $numCols) . ',1fr)!important}}';
        }
        if (!empty($bgCellSelectors)) {
            $bgCellCss = implode(',', array_map(function ($s) use ($sel) { return $sel . ' .impulse-layout-cell' . $s; }, $bgCellSelectors));
            $css .= '@media(max-width:767px){' . $bgCellCss . '{min-height:' . max(60, $minHeight) . 'px!important}}';
        }
        if ($css) wp_add_inline_style('instinctor-page-inline', $css);
    }

    return ob_get_clean();
}
