<?php

declare(strict_types=1);

final class MyronDefinitionTemplateRenderer
{
    private MyronPublicRenderPresentation $presentation;
    private ?MyronPublicComponentDataResolver $componentDataResolver;
    private MyronSectionRendererRegistry $sectionRenderers;
    private bool $lastRenderHadCreativeSections = false;
    /** @var array<string, array{type:string,richtext:bool}> */
    private array $activeRichtextFields = [];
    private bool $activeParagraphRichtext = false;
    private string $activeMicPageId = '';
    private string $activeMicFieldKey = '';
    private string $activeMicChannel = 'public';
    /** @var array<string, mixed> */
    private array $activePublishedPage = [];

    public function __construct(
        ?MyronPublicRenderPresentation $presentation = null,
        ?MyronPublicComponentDataResolver $componentDataResolver = null,
        ?MyronSectionRendererRegistry $sectionRenderers = null,
    )
    {
        $this->presentation = $presentation ?? new MyronPublicRenderPresentation();
        $this->componentDataResolver = $componentDataResolver;
        $this->sectionRenderers = $sectionRenderers ?? new MyronSectionRendererRegistry();
        $this->registerBuiltinSectionRenderers();
    }

    public function sectionRendererRegistry(): MyronSectionRendererRegistry
    {
        return $this->sectionRenderers;
    }

    public function hadCreativeSections(): bool
    {
        return $this->lastRenderHadCreativeSections;
    }

    /**
     * @param array<string, mixed> $page
     * @param list<array<string, mixed>> $footerNavigation
     */
    public function renderPublishedPage(array $page, string $basePath, array $footerNavigation = [], string $context = MyronCustomCssRepository::CONTEXT_PUBLIC): string
    {
        myronBootstrapCoreMicTypes();
        myronMicElementRegistry()->resetIdentityCache();
        $this->activePublishedPage = $page;
        $this->activeMicPageId = (string) ($page['id'] ?? $page['page_id'] ?? '');
        $this->activeMicChannel = ((bool) ($page['preview_mode'] ?? false) || (bool) (($page['template_schema']['previewMode'] ?? false))) ? 'admin-preview' : 'public';
        $content = is_array($page['content'] ?? null) ? $page['content'] : [];
        $schema = is_array($page['template_schema'] ?? null) ? $page['template_schema'] : [];
        $rawSections = is_array($schema['sections'] ?? null) ? $schema['sections'] : [];
        $sectionBridge = $this->splitChromeFromBodySections($rawSections);
        $sections = $sectionBridge['bodySections'];
        $chrome = is_array($schema['chrome'] ?? null) ? $schema['chrome'] : [];
        $templateKey = (string) ($page['template_key'] ?? '');
        $sourceTemplateId = (string) (($schema['sourceTemplateId'] ?? '') ?: ($page['source_template_id'] ?? '') ?: ($page['template_source_template_id'] ?? ''));
        $sourceBundleId = (string) (($schema['sourceBundleId'] ?? '') ?: ($page['source_bundle_id'] ?? '') ?: ($page['template_source_bundle_id'] ?? ''));
        $liveContentEnabled = $context === MyronCustomCssRepository::CONTEXT_PUBLIC
            && (bool) ($page['preview_mode'] ?? false) === false
            && (bool) ($schema['previewMode'] ?? false) === false;
        $usesTemplateHero = $this->usesTemplateHero($sections, $sourceTemplateId);
        $usesCmsContentTitle = $this->usesCmsContentTitle($sections);
        $creativeSettings = myronSiteSettingsRepository()->creativeSettings();
        $articleAttributes = ' class="myron-public-page"'
            . ' data-template-key="' . $this->escape($templateKey) . '"'
            . ' data-source-template-id="' . $this->escape($sourceTemplateId) . '"'
            . ' data-source-bundle-id="' . $this->escape($sourceBundleId) . '"';
        if (is_string($creativeSettings['btnStyle'] ?? null) && $creativeSettings['btnStyle'] !== '') {
            $articleAttributes .= ' data-mc-btn-style="' . $this->escape($creativeSettings['btnStyle']) . '"';
        }

        $html = [];
        $html[] = '<article' . $articleAttributes . '>';
        if (!$usesTemplateHero && !$usesCmsContentTitle) {
            $html[] = $this->renderHero($page, $content, $basePath);
        }
        $html[] = '<section class="myron-public-page__body" data-definition-rendered="true">';

        $this->lastRenderHadCreativeSections = false;
        $footerSection = $sectionBridge['footerSection'];
        $sectionCssEntries = [];
        $renderedSectionEntries = [];
        if ($sections !== []) {
            $newsletterOccurrence = 0;
            $reservationFormRendered = false;
            $searchCompositionRendered = false;
            $ecomCartRendered = false;
            $ecomCheckoutRendered = false;
            $mktRenderedComponents = [];
            foreach ($sections as $index => $section) {
                if (!is_array($section)) {
                    continue;
                }
                $componentId = (string) ($section['componentId'] ?? '');
                if ($this->isChromeSection($componentId)) {
                    continue;
                }
                if ($this->isReservationTemplate($sourceTemplateId) && $this->isReservationFormComponent($componentId)) {
                    if ($reservationFormRendered) {
                        continue;
                    }
                    $reservationFormRendered = true;
                }
                if ($sourceTemplateId === 'template.search.universal.v1' && $this->isSearchCompositionComponent($componentId)) {
                    if ($searchCompositionRendered) {
                        continue;
                    }
                    $searchCompositionRendered = true;
                }
                if ($sourceTemplateId === 'template.cart.ecom.v1' && $this->isEcomCartCompositionComponent($componentId)) {
                    if ($ecomCartRendered) {
                        continue;
                    }
                    $ecomCartRendered = true;
                }
                if ($sourceTemplateId === 'template.checkout.ecom.v1' && $this->isEcomCheckoutCompositionComponent($componentId)) {
                    if ($ecomCheckoutRendered) {
                        continue;
                    }
                    $ecomCheckoutRendered = true;
                }
                if ($this->isPostSingleTemplate($sourceTemplateId, $page) && $usesCmsContentTitle && in_array($componentId, ['user-identity', 'chip'], true)) {
                    continue;
                }
                if ($this->shouldSuppressMktDuplicateSection($sourceBundleId, $sourceTemplateId, $componentId, $mktRenderedComponents)) {
                    continue;
                }
                if ($this->shouldSuppressNewsHomeDuplicateNewsletter($sourceTemplateId, $componentId, $section)) {
                    continue;
                }
                if ($componentId === 'newsletter-signup') {
                    $section['_newsletterOccurrence'] = $newsletterOccurrence;
                    $newsletterOccurrence++;
                }
                $sectionContent = myronSectionContentForInstance($content, $section, $index);
                if (is_array($section['creative'] ?? null) || $componentId === 'scrolljack-hero') {
                    $this->lastRenderHadCreativeSections = true;
                }
                $sectionHtml = $this->renderSection($section, $index, $sectionContent, $basePath, $sourceBundleId, $sourceTemplateId, $this->isPrimaryTemplateHero($sections, $index), $liveContentEnabled);
                $sectionHtml = $this->decorateRenderedSectionForEditor($sectionHtml, $section, $index, $sectionContent, $sourceTemplateId);
                $sectionCss = trim((string) ($section['customCss'] ?? ''));
                if ($sectionCss !== '') {
                    $sectionCssEntries[] = ['sectionUuid' => myronSectionUuid($section, $index), 'css' => $sectionCss];
                }
                if ($this->isMktFunnelTemplate($sourceBundleId, $sourceTemplateId)) {
                    $sectionHtml = $this->withFunnelAttributes($sectionHtml, $sourceTemplateId, trim((string) ($section['variant'] ?? '')));
                }
                $renderedSectionEntries[] = [
                    'html' => $sectionHtml,
                    'componentId' => $componentId,
                    'sectionKey' => trim((string) ($section['sectionKey'] ?? '')),
                ];
            }
        } else {
            $renderedSectionEntries[] = [
                'html' => $this->renderLegacyBody($content),
                'componentId' => 'legacy',
                'sectionKey' => '',
            ];
        }

        if ($sectionCssEntries !== []) {
            $containerSelector = '.myron-public-page[data-template-key="' . addcslashes($templateKey, "\\\"") . '"]';
            $html[] = myronCustomCssRepository()->renderSectionStylesTag($sectionCssEntries, $containerSelector, $context);
        }
        array_push($html, ...$this->arrangeBlogRailSections($renderedSectionEntries, $schema, $sourceTemplateId));
        $html[] = '</section>';
        $blogCommentsHtml = $this->renderBlogComments($page, $basePath);
        if ($blogCommentsHtml !== '') {
            $html[] = $blogCommentsHtml;
        }
        $footerChrome = is_array($chrome['footer'] ?? null) ? $chrome['footer'] : [];
        if ($footerSection !== null || $footerNavigation !== [] || $this->chromeDeclarationEnabled($footerChrome)) {
            // APO-181 Card 1 — pass the full chrome footer object (inherit + variant)
            // into the resolver so the inherit:"global" hint can be honored. Embedded
            // footerSection (legacy chrome-as-section) provides only a variant string;
            // wrap it as an explicit override (no inherit:"global" hint, just variant).
            $resolutionHint = $footerSection !== null
                ? ['variant' => trim((string) ($footerSection['variant'] ?? '')), 'inherit' => 'explicit']
                : $footerChrome;
            $html[] = $this->renderFooterNavigation($basePath, $footerNavigation, $resolutionHint, $sourceTemplateId);
        }
        $html[] = '</article>';

        return implode("\n", array_filter($html, static fn (string $part): bool => $part !== ''));
    }

    /**
     * @param list<array<string, mixed>> $sections
     * @return array{bodySections:list<array<string, mixed>>,footerSection:array<string, mixed>|null,legacyChromeSectionCount:int}
     */
    private function splitChromeFromBodySections(array $sections): array
    {
        $bodySections = [];
        $footerSection = null;
        $legacyChromeSectionCount = 0;

        foreach ($sections as $section) {
            if (!is_array($section)) {
                continue;
            }

            $componentId = trim((string) ($section['componentId'] ?? ''));
            if ($componentId === 'footer') {
                $footerSection = $section;
                $legacyChromeSectionCount++;
                continue;
            }

            if ($componentId === 'header') {
                $legacyChromeSectionCount++;
                continue;
            }

            $bodySections[] = $section;
        }

        return [
            'bodySections' => $bodySections,
            'footerSection' => $footerSection,
            'legacyChromeSectionCount' => $legacyChromeSectionCount,
        ];
    }

    /**
     * @param list<array{html:string,componentId:string,sectionKey:string}> $entries
     * @param array<string, mixed> $schema
     * @return list<string>
     */
    private function arrangeBlogRailSections(array $entries, array $schema, string $sourceTemplateId): array
    {
        $placement = $this->blogRailPlacement($schema, $sourceTemplateId);
        if ($placement === 'none' || !$this->supportsBlogRailLayout($sourceTemplateId)) {
            return array_values(array_map(static fn (array $entry): string => $entry['html'], $entries));
        }

        $railIndex = null;
        $railSectionKey = '';
        foreach ($entries as $index => $entry) {
            if ($entry['componentId'] === 'stack') {
                $railIndex = $index;
                $railSectionKey = $entry['sectionKey'];
                break;
            }
        }
        if ($railIndex === null || $railSectionKey === '') {
            return array_values(array_map(static fn (array $entry): string => $entry['html'], $entries));
        }

        $before = [];
        $main = [];
        $after = [];
        $rail = '';
        $layoutSeen = false;
        foreach ($entries as $index => $entry) {
            if ($index === $railIndex) {
                $rail = $entry['html'];
                $layoutSeen = true;
                continue;
            }
            if ($entry['sectionKey'] === $railSectionKey) {
                $main[] = $entry['html'];
                $layoutSeen = true;
                continue;
            }
            if (!$layoutSeen) {
                $before[] = $entry['html'];
            } else {
                $after[] = $entry['html'];
            }
        }

        if ($rail === '' || $main === []) {
            return array_values(array_map(static fn (array $entry): string => $entry['html'], $entries));
        }

        $layout = [];
        $layout[] = '<section class="myron-blog-rail-layout myron-blog-rail-layout--' . $this->escape($placement) . ' myron-blog-rail-layout--' . $this->escape(myronNormalizeSlug($railSectionKey)) . '" data-myron-blog-rail-layout data-rail-placement="' . $this->escape($placement) . '">';
        if ($placement === 'left') {
            $layout[] = '<div class="myron-blog-rail-layout__rail">' . $rail . '</div>';
            $layout[] = '<div class="myron-blog-rail-layout__main">' . implode("\n", $main) . '</div>';
        } else {
            $layout[] = '<div class="myron-blog-rail-layout__main">' . implode("\n", $main) . '</div>';
            $layout[] = '<div class="myron-blog-rail-layout__rail">' . $rail . '</div>';
        }
        $layout[] = '</section>';

        return array_merge($before, [implode("\n", $layout)], $after);
    }

    /**
     * @param array<string, mixed> $schema
     */
    private function blogRailPlacement(array $schema, string $sourceTemplateId): string
    {
        if (function_exists('myronRailDesignRepository')) {
            try {
                $resolved = myronRailDesignRepository()->resolveForTemplate($sourceTemplateId, $schema);
                $placement = (string) ($resolved['placement'] ?? '');
                if (in_array($placement, ['left', 'right', 'none'], true)) {
                    return $placement;
                }
            } catch (Throwable) {
                // Legacy blogRail metadata remains the compatibility fallback.
            }
        }

        $rail = is_array($schema['blogRail'] ?? null) ? $schema['blogRail'] : [];
        $placement = myronNormalizeSlug((string) ($rail['placement'] ?? ''));
        if (in_array($placement, ['left', 'right', 'none'], true)) {
            return $placement;
        }

        return $this->supportsBlogRailLayout($sourceTemplateId) ? 'right' : 'none';
    }

    private function supportsBlogRailLayout(string $sourceTemplateId): bool
    {
        return in_array($sourceTemplateId, [
            'template.blog-index.blog.v1',
            'template.post-single.blog.v1',
        ], true);
    }

    /**
     * @param array<string, mixed> $section
     * @param array<string, mixed> $content
     */
    private function decorateRenderedSectionForEditor(string $html, array $section, int $index, array $content, string $sourceTemplateId): string
    {
        if (trim($html) === '' || !str_contains($html, '<section')) {
            return $html;
        }

        $instanceKey = myronSectionInstanceKey($section, $index);
        $sectionUuid = myronSectionUuid($section, $index);
        $sectionKey = trim((string) ($section['sectionKey'] ?? ''));
        $componentId = trim((string) ($section['componentId'] ?? 'section'));
        $tokenStyle = myronSectionTokenOverrideStyle(is_array($section['tokenOverrides'] ?? null) ? $section['tokenOverrides'] : []);
        $editability = is_array($section['editing'] ?? null) && array_key_exists('contentEditable', $section['editing'])
            ? (filter_var($section['editing']['contentEditable'], FILTER_VALIDATE_BOOL, FILTER_NULL_ON_FAILURE) ? 'editable' : 'inspect-only')
            : 'inherit';
        $attributeText = ' data-myron-editor-section="true"'
            . ' data-section-uuid="' . $this->escape($sectionUuid) . '"'
            . ' data-section-instance-key="' . $this->escape($instanceKey) . '"'
            . ' data-section-key="' . $this->escape($sectionKey) . '"'
            . ' data-myron-component-id="' . $this->escape($componentId) . '"'
            . ' data-myron-editability="' . $this->escape($editability) . '"';

        $creative = is_array($section['creative'] ?? null) ? $section['creative'] : null;
        if ($creative !== null) {
            $motionProfile = trim((string) ($creative['motionProfile'] ?? ''));
            $sceneBackground = trim((string) ($creative['sceneBackground'] ?? ''));
            $heroComponent = trim((string) ($creative['heroComponent'] ?? ''));
            $params = is_array($creative['params'] ?? null) ? $creative['params'] : [];
            if ($motionProfile !== '') {
                $attributeText .= ' data-mc-motion="' . $this->escape($motionProfile) . '"';
            }
            if ($sceneBackground !== '') {
                $attributeText .= ' data-mc-scene="' . $this->escape($sceneBackground) . '"';
            }
            if ($heroComponent !== '') {
                $attributeText .= ' data-mc-hero="' . $this->escape($heroComponent) . '"';
            }
            if ($params !== []) {
                $attributeText .= ' data-mc-params="' . $this->escape((string) json_encode($params, JSON_THROW_ON_ERROR | JSON_HEX_QUOT | JSON_HEX_APOS)) . '"';
            }
        }

        $decorated = preg_replace(
            '~<section\b([^>]*)>~',
            $tokenStyle === ''
                ? '<section$1' . $attributeText . '>'
                : '<section$1' . $attributeText . ' style="' . $this->escape($tokenStyle) . '">',
            $html,
            1
        );
        $decorated = is_string($decorated) ? $decorated : $html;

        $slotMap = [
            '~<(h[1-3])\b(?![^>]*data-myron-edit-slot)([^>]*)>~' => '<$1$2 data-myron-edit-slot="headline">',
            '~<(div)\b(?![^>]*data-myron-edit-slot)([^>]*class="[^"]*(?:subhead|content|copy)[^"]*"[^>]*)>~' => '<$1$2 data-myron-edit-slot="body">',
            '~<(p)\b(?![^>]*data-myron-edit-slot)([^>]*)>~' => '<$1$2 data-myron-edit-slot="intro">',
            '~<(div)\b(?![^>]*data-myron-edit-slot)([^>]*class="[^"]*(?:media|image)[^"]*"[^>]*)>~' => '<$1$2 data-myron-edit-slot="mediaFileId">',
            '~<(img)\b(?![^>]*data-myron-edit-slot)([^>]*)>~' => '<$1$2 data-myron-edit-slot="mediaFileId">',
        ];

        foreach ($slotMap as $pattern => $replacement) {
            $updated = preg_replace($pattern, $replacement, $decorated, 1);
            $decorated = is_string($updated) ? $updated : $decorated;
        }

        return $decorated;
    }

    /**
     * @param array<string, mixed> $content
     * @return array<string, mixed>|null
     */
    private function contentFile(array $content, string $fileKey = 'mediaFileId'): ?array
    {
        $fileId = trim((string) ($content[$fileKey] ?? ''));
        if ($fileId === '') {
            return null;
        }

        try {
            $file = myronFileRepository()->getFileById($fileId);
        } catch (Throwable) {
            return null;
        }

        return is_array($file) && ($file['is_image'] ?? false) ? $file : null;
    }

    /**
     * @param array<string, mixed> $content
     */
    private function imageSlotHtml(
        array $content,
        string $className,
        string $fileKey = 'mediaFileId',
        string $altKey = 'mediaAlt',
        ?string $rendition = null,
        string $sizes = '',
        array $srcsetRenditions = [],
        bool $highPriority = false
    ): string
    {
        $file = $this->contentFile($content, $fileKey);
        if (is_array($file)) {
            $alt = trim((string) ($content[$altKey] ?? ''));
            if ($alt === '') {
                $alt = trim((string) (($file['alt_text'] ?? '') ?: ($file['title'] ?? '') ?: ($file['original_filename'] ?? '')));
            }

            $src = $this->imageUrlForRendition($file, $rendition);
            $attributes = [
                'class="' . $this->escape($className) . '"',
                'src="' . $this->escape($src) . '"',
                'alt="' . $this->escape($alt) . '"',
            ];
            $srcset = $this->imageSrcset($file, $srcsetRenditions);
            if ($srcset !== '') {
                $attributes[] = 'srcset="' . $this->escape($srcset) . '"';
            }
            if ($sizes !== '') {
                $attributes[] = 'sizes="' . $this->escape($sizes) . '"';
            }
            $dimensions = $this->imageDimensionsForRendition($file, $rendition);
            if ($dimensions !== null) {
                $attributes[] = 'width="' . (string) $dimensions['width'] . '"';
                $attributes[] = 'height="' . (string) $dimensions['height'] . '"';
            }
            $attributes[] = 'loading="' . ($highPriority || $rendition === null || $rendition === '' ? 'eager' : 'lazy') . '"';
            if ($highPriority) {
                $attributes[] = 'fetchpriority="high"';
            }
            $attributes[] = 'decoding="async"';

            return '<img ' . implode(' ', $attributes) . '>';
        }

        return '<div class="' . $this->escape($className . ' mc-component-preview__media-placeholder') . '" aria-hidden="true"><span></span></div>';
    }

    /**
     * @param array<string, mixed> $file
     */
    private function imageUrlForRendition(array $file, ?string $rendition): string
    {
        return MyronPublicCriticalResourceResolver::imageUrlForRendition($file, $rendition);
    }

    /**
     * @param array<string, mixed> $file
     * @param array<string, int> $renditions
     */
    private function imageSrcset(array $file, array $renditions): string
    {
        return MyronPublicCriticalResourceResolver::imageSrcset($file, $renditions);
    }

    /**
     * @param array<string, mixed> $file
     */
    private function imageEffectiveRenditionWidth(array $file, int $targetWidth): int
    {
        return MyronPublicCriticalResourceResolver::imageEffectiveRenditionWidth($file, $targetWidth);
    }

    /**
     * @param array<string, mixed> $file
     * @return array{width:int,height:int}|null
     */
    private function imageDimensionsForRendition(array $file, ?string $rendition): ?array
    {
        return MyronPublicCriticalResourceResolver::imageDimensionsForRendition($file, $rendition);
    }

    /**
     * @param array<string, mixed> $content
     */
    private function iconSlotHtml(array $content, string $className, string $fileKey, string $altKey, bool $renderPlaceholder = true): string
    {
        $file = $this->contentFile($content, $fileKey);
        if (is_array($file)) {
            $alt = trim((string) ($content[$altKey] ?? ''));
            if ($alt === '') {
                $alt = trim((string) (($file['alt_text'] ?? '') ?: ($file['title'] ?? '') ?: ($file['original_filename'] ?? '')));
            }

            return '<img class="' . $this->escape($className) . '" src="' . $this->escape((string) ($file['file_url'] ?? '')) . '" alt="' . $this->escape($alt) . '">';
        }

        return $renderPlaceholder
            ? '<span class="' . $this->escape($className) . '" aria-hidden="true"></span>'
            : '';
    }

    private function isChromeSection(string $componentId): bool
    {
        return in_array(trim($componentId), ['header', 'footer'], true);
    }

    private function isSiteChromeHeaderSection(string $sourceTemplateId, int $index): bool
    {
        return $index === 0 && trim($sourceTemplateId) !== '';
    }

    /**
     * @param array<string, mixed> $page
     * @param array<string, mixed> $content
     */
    private function renderHero(array $page, array $content, string $basePath): string
    {
        $title = (string) (($content['headline'] ?? '') ?: ($page['version_title'] ?? '') ?: ($page['title'] ?? ''));
        $intro = $this->publicSectionBody((string) ($content['intro'] ?? ''), '');
        $eyebrow = trim((string) ($content['eyebrow'] ?? ''));
        $ctaLabel = trim((string) ($content['ctaLabel'] ?? ''));
        $ctaHref = trim((string) ($content['ctaHref'] ?? ''));

        $html = [];
        $html[] = '<header class="myron-public-page__hero">';
        if ($eyebrow !== '') {
            $html[] = '<span class="myron-text myron-text--muted myron-public-page__eyebrow">' . $this->escape($eyebrow) . '</span>';
        }
        $html[] = '<h1 class="myron-heading myron-public-page__title">' . $this->escape($title) . '</h1>';
        if ($intro !== '') {
            $html[] = '<p class="myron-paragraph myron-paragraph--muted myron-public-page__intro">' . $this->escape($intro) . '</p>';
        }
        if ($ctaLabel !== '' && $ctaHref !== '') {
            $html[] = '<a class="' . $this->escape($this->buttonClasses('primary', 'solid', 'md', 'myron-public-page__cta')) . '" href="' . $this->escape($this->contentHref($basePath, $ctaHref)) . '">' . $this->escape($ctaLabel) . '</a>';
        }
        $html[] = '</header>';

        return implode("\n", $html);
    }

    /**
     * @param list<array<string, mixed>> $sections
     */
    private function usesTemplateHero(array $sections, string $sourceTemplateId = ''): bool
    {
        if ($sourceTemplateId === 'template.home.news.v1') {
            foreach ($sections as $section) {
                if (is_array($section) && in_array((string) ($section['componentId'] ?? ''), ['hero-with-cta', 'hero-simple'], true)) {
                    return true;
                }
            }

            return false;
        }

        foreach ($sections as $index => $section) {
            if (!is_array($section)) {
                continue;
            }
            $componentId = (string) ($section['componentId'] ?? '');
            if (in_array($componentId, ['hero-with-cta', 'hero-simple'], true)) {
                return true;
            }
            if ($componentId !== 'header') {
                return false;
            }
        }

        return false;
    }

    /**
     * @param list<array<string, mixed>> $sections
     */
    private function isPrimaryTemplateHero(array $sections, int $candidateIndex): bool
    {
        foreach ($sections as $index => $section) {
            if (!is_array($section)) {
                continue;
            }
            $componentId = trim((string) ($section['componentId'] ?? ''));
            if (in_array($componentId, ['header', 'footer'], true)) {
                continue;
            }
            if (in_array($componentId, ['hero-with-cta', 'hero-simple'], true)) {
                return $index === $candidateIndex;
            }

            return false;
        }

        return false;
    }

    /**
     * @param array<string, mixed> $chromeSide
     */
    private function chromeDeclarationEnabled(array $chromeSide): bool
    {
        $inherit = trim((string) ($chromeSide['inherit'] ?? $chromeSide['source'] ?? ''));
        $variant = trim((string) ($chromeSide['variant'] ?? ''));

        return $inherit !== '' || $variant !== '';
    }

    /**
     * @param list<array<string, mixed>> $sections
     */
    private function usesCmsContentTitle(array $sections): bool
    {
        foreach ($sections as $section) {
            if (is_array($section) && (string) ($section['componentId'] ?? '') === 'cms-content-title') {
                return true;
            }
        }

        return false;
    }

    private function isReservationTemplate(string $sourceTemplateId): bool
    {
        return in_array($sourceTemplateId, ['template.reservation.rst.v1', 'template.reservation.bkg.v1'], true);
    }

    private function isReservationFormComponent(string $componentId): bool
    {
        return in_array($componentId, ['form-field', 'datepicker', 'timepicker', 'select', 'textarea', 'button'], true);
    }

    private function isSearchCompositionComponent(string $componentId): bool
    {
        return in_array($componentId, ['combobox', 'list', 'pagination', 'empty-state'], true);
    }

    private function isEcomCartCompositionComponent(string $componentId): bool
    {
        return in_array($componentId, ['cart-table', 'order-summary', 'button'], true);
    }

    private function isEcomCheckoutCompositionComponent(string $componentId): bool
    {
        return in_array($componentId, ['checkout-stepper', 'checkout-address-form', 'shipping-method-selector', 'payment-form', 'checkout-review', 'order-summary', 'button'], true);
    }

    /**
     * @param array<string, int> $renderedComponents
     */
    private function shouldSuppressMktDuplicateSection(string $sourceBundleId, string $sourceTemplateId, string $componentId, array &$renderedComponents): bool
    {
        if ($sourceBundleId !== 'site-type.mkt') {
            return false;
        }

        $limits = [
            'template.home.mkt.v1' => [
                'blog-teaser' => 1,
                'cta-band' => 1,
            ],
            'template.post-single.mkt.v1' => [
                'blog-teaser' => 1,
            ],
        ];
        $limit = $limits[$sourceTemplateId][$componentId] ?? null;
        if ($limit === null) {
            return false;
        }

        $key = $sourceTemplateId . ':' . $componentId;
        $renderedComponents[$key] = ($renderedComponents[$key] ?? 0) + 1;

        return $renderedComponents[$key] > $limit;
    }

    /**
     * @param array<string, mixed> $section
     */
    private function shouldSuppressNewsHomeDuplicateNewsletter(string $sourceTemplateId, string $componentId, array $section): bool
    {
        if ($sourceTemplateId !== 'template.home.news.v1' || $componentId !== 'newsletter-signup') {
            return false;
        }

        return myronNormalizeSlug((string) ($section['variant'] ?? '')) === 'footer-embedded';
    }

    /**
     * Façade for `MyronPrimitiveRenderer::renderById()`.
     *
     * Renders a single section's HTML directly (no `<article class="myron-public-page">` wrapper)
     * given a canonical (componentId, props, archetypeContext) tuple. The component viewer and the
     * Primitive Explorer use this to invoke the same render code paths as the live page renderer
     * without regex-extracting the body out of a wrapped page.
     *
     * @param array<string, mixed> $props {
     *   variant?: string, title?: string, body?: string, notes?: string,
     *   content?: array<string, mixed>, _newsletterOccurrence?: int,
     * }
     * @param array<string, mixed> $archetypeContext {
     *   bundleId?: string, templateId?: string, basePath?: string,
     * }
     */
    public function renderSingleSection(string $componentId, array $props, array $archetypeContext): string
    {
        $section = [
            'componentId' => $componentId,
            'variant' => (string) ($props['variant'] ?? ''),
            'notes' => (string) ($props['notes'] ?? ''),
        ];
        if (array_key_exists('mediaLayout', $props)) {
            $section['mediaLayout'] = (string) $props['mediaLayout'];
        }
        if (isset($props['_newsletterOccurrence'])) {
            $section['_newsletterOccurrence'] = (int) $props['_newsletterOccurrence'];
        }
        $content = is_array($props['content'] ?? null) ? $props['content'] : [];
        if (!isset($content['headline']) && isset($props['title'])) {
            $content['headline'] = (string) $props['title'];
        }
        if (!isset($content['body']) && isset($props['body'])) {
            $content['body'] = (string) $props['body'];
        }
        $basePath = (string) ($archetypeContext['basePath'] ?? '/');
        $sourceBundleId = (string) ($archetypeContext['bundleId'] ?? '');
        $sourceTemplateId = (string) ($archetypeContext['templateId'] ?? '');
        if ($componentId === 'header' && $this->isSiteChromeHeaderSection($sourceTemplateId, 0)) {
            return '';
        }
        $primaryHeading = in_array($componentId, ['hero-with-cta', 'hero-simple'], true);
        $html = $this->renderSection($section, 0, $content, $basePath, $sourceBundleId, $sourceTemplateId, $primaryHeading);
        if ($this->isMktFunnelTemplate($sourceBundleId, $sourceTemplateId)) {
            $html = $this->withFunnelAttributes($html, $sourceTemplateId, (string) ($section['variant'] ?? ''));
        }

        return $html;
    }

    private function renderSection(array $section, int $index, array $content, string $basePath, string $sourceBundleId, string $sourceTemplateId, bool $primaryHeading = false, bool $liveContentEnabled = false): string
    {
        $componentId = trim((string) ($section['componentId'] ?? 'section'));
        $variant = trim((string) ($section['variant'] ?? ''));
        $notes = trim((string) ($section['notes'] ?? ''));
        $previewMode = (bool) ($section['_previewMode'] ?? false);
        $this->activeRichtextFields = $this->richtextFieldMap($section, $index, $content);
        $title = trim((string) ($content['headline'] ?? '')) ?: $this->sectionTitle($componentId);
        $body = $this->sectionBody($componentId, $index, $content, $notes, $previewMode);
        $bodyFieldKey = trim((string) ($content['body'] ?? '')) !== '' ? 'body' : 'intro';
        $this->activeMicFieldKey = $bodyFieldKey;
        $this->activeParagraphRichtext = (bool) ($this->activeRichtextFields[$bodyFieldKey]['richtext'] ?? false);
        $classes = 'myron-definition-section myron-definition-section--' . myronNormalizeSlug($componentId);
        $intent = myronNormalizeSlug($notes !== '' ? $notes : ($variant !== '' ? $variant : $componentId));
        if ($componentId === 'feature-grid' && str_contains($intent, 'process-flow')) {
            $intent = 'process-flow';
        } elseif ($componentId === 'feature-grid' && str_contains($intent, 'why-us')) {
            $intent = 'why-us';
        }

        $runtimeData = is_array($this->activePublishedPage['_runtimeData'] ?? null)
            ? $this->activePublishedPage['_runtimeData']
            : [];
        $context = new MyronSectionRenderContext(
            $componentId,
            $variant,
            $notes,
            $intent,
            $index,
            $section,
            $content,
            $basePath,
            $sourceBundleId,
            $sourceTemplateId,
            $primaryHeading,
            $liveContentEnabled,
            $previewMode,
            $title,
            $body,
            $classes,
            $this->activePublishedPage,
            $this->activeRichtextFields,
            $this->activeMicPageId,
            $this->activeMicFieldKey,
            $this->activeMicChannel,
            $runtimeData,
        );

        return $this->sectionRenderers->render($context);
    }

    private function registerBuiltinSectionRenderers(): void
    {
        $component = static fn (string ...$ids): callable => static fn (MyronSectionRenderContext $c): bool => in_array($c->componentId, $ids, true);
        $variant = static fn (string $componentId, string $variantId): callable => static fn (MyronSectionRenderContext $c): bool => $c->componentId === $componentId && myronNormalizeSlug($c->variant) === $variantId;
        $variantRules = [
            ['logo-ticker', $variant('logo', 'ticker'), fn (MyronSectionRenderContext $c): string => $this->renderLogoTickerSection($c), $this->builtinSectionContract('logo-ticker')],
            ['hero-with-cta-cinematic', $variant('hero-with-cta', 'cinematic'), fn (MyronSectionRenderContext $c): string => $this->renderHeroWithCtaSection($c->variant, $c->title, $c->body, $c->basePath, $c->sourceBundleId, $c->sourceTemplateId, $c->intent, $c->primaryHeading, $c->content, $c->section), $this->builtinSectionContract('hero-with-cta')],
            ['feature-grid-editorial', $variant('feature-grid', 'editorial'), fn (MyronSectionRenderContext $c): string => $this->renderFeatureGridEditorialSection($c), $this->builtinSectionContract('feature-grid')],
            ['testimonial-grid-featured-band', $variant('testimonial-grid', 'featured-band'), fn (MyronSectionRenderContext $c): string => $this->renderTestimonialFeaturedBandSection($c), $this->builtinSectionContract('testimonial-grid')],
            ['services-grid-image-card', $variant('services-grid', 'image-card'), fn (MyronSectionRenderContext $c): string => $this->renderServicesImageCardSection($c), $this->builtinSectionContract('services-grid-image-card')],
            ['cta-band-background-image', $variant('cta-band', 'background-image'), fn (MyronSectionRenderContext $c): string => $this->renderCtaBackgroundImageSection($c), $this->builtinSectionContract('cta-band-background-image')],
            ['cta-band-image-right', $variant('cta-band', 'image-right'), fn (MyronSectionRenderContext $c): string => $this->renderCtaImageRightSection($c), $this->builtinSectionContract('cta-band-image-right')],
        ];
        foreach ($variantRules as $rule) {
            [$id, $matcher, $renderer, $contract] = $rule;
            $this->sectionRenderers->register(new MyronCallableSectionRenderer(
                'core.' . $id,
                $matcher,
                $renderer,
                200,
                $contract,
            ));
        }
        $rules = [
            ['marketing-offer', static fn (MyronSectionRenderContext $c): bool => $c->sourceBundleId === 'site-type.mkt' && in_array($c->componentId, ['featured-offer-card', 'lead-magnet-card'], true)],
            ['portfolio-grid', $component('portfolio-grid')],
            ['banner', $component('banner')],
            ['creative-hero-parallax', $component('creative-hero-parallax')],
            ['scrolljack-hero', $component('scrolljack-hero')],
            ['hero-with-cta', $component('hero-with-cta')],
            ['hero-simple', $component('hero-simple')],
            ['search-composition', fn (MyronSectionRenderContext $c): bool => $c->sourceTemplateId === 'template.search.universal.v1' && $this->isSearchCompositionComponent($c->componentId)],
            ['cms-content-title', $component('cms-content-title')],
            ['cms-content-body', $component('cms-content-body')],
            ['cms-featured-media', $component('cms-featured-media')],
            ['cms-embed', $component('cms-embed')],
            ['header', $component('header')],
            ['pagination', $component('pagination')],
            ['product-filters', $component('product-filters')],
            ['faq-list', $component('faq-list')],
            ['kv-row', $component('kv-row')],
            ['list', $component('list')],
            ['link', $component('link')],
            ['sub-nav-bar', $component('sub-nav-bar')],
            ['menu-block', $component('menu-block')],
            ['legal-doc-toc', $component('legal-doc-toc')],
            ['alert', $component('alert')],
            ['avatar', $component('avatar')],
            ['badge', $component('badge')],
            ['button', $component('button')],
            ['card', $component('card')],
            ['carousel', $component('carousel')],
            ['choice', $component('checkbox', 'radio')],
            ['checkout-confirmation', $component('checkout-confirmation')],
            ['chip', $component('chip')],
            ['form-control', $component('combobox', 'datetime-picker')],
            ['empty-state', $component('empty-state')],
            ['image', $component('image')],
            ['progress-bar', $component('progress-bar')],
            ['resources-item-card', $component('resources-item-card')],
            ['user-identity', $component('user-identity')],
            ['video', $component('video')],
            ['reservation-form', fn (MyronSectionRenderContext $c): bool => $this->isReservationTemplate($c->sourceTemplateId) && $this->isReservationFormComponent($c->componentId)],
            ['generic-form-control', static fn (MyronSectionRenderContext $c): bool => in_array($c->componentId, ['form-field', 'datepicker', 'timepicker', 'select', 'textarea'], true) && $c->sourceBundleId !== 'site-type.bkg'],
            ['contact-form-with-info', $component('contact-form-with-info')],
            ['feature-grid', $component('feature-grid')],
            ['services-grid', $component('services-grid')],
            ['section-band', $component('section-band')],
            ['stats-tile', $component('stats-tile')],
            ['testimonial-grid', $component('testimonial-grid')],
            ['team-grid', $component('team-grid')],
            ['course-catalog', $component('course-catalog')],
            ['pricing-table', $component('pricing-table')],
            ['blog-teaser', $component('blog-teaser')],
            ['logo', $component('logo')],
            ['contact-cta-suppression', static fn (MyronSectionRenderContext $c): bool => $c->componentId === 'cta-band' && $c->sourceTemplateId === 'template.contact.universal.v1'],
            ['cta-band', $component('cta-band')],
            ['newsletter-signup', $component('newsletter-signup')],
            ['commerce-catalog', $component('product-grid', 'product-sort-control')],
            ['product-detail', $component('product-gallery', 'product-details', 'variant-selector', 'quantity-stepper', 'rating-summary')],
            ['cart-template-composition', fn (MyronSectionRenderContext $c): bool => $c->sourceTemplateId === 'template.cart.ecom.v1' && $this->isEcomCartCompositionComponent($c->componentId)],
            ['cart-summary', $component('cart-table', 'order-summary')],
            ['checkout-template-composition', fn (MyronSectionRenderContext $c): bool => $c->sourceTemplateId === 'template.checkout.ecom.v1' && $this->isEcomCheckoutCompositionComponent($c->componentId)],
            ['checkout', $component('checkout-stepper', 'checkout-address-form', 'shipping-method-selector', 'payment-form', 'checkout-review')],
            ['booking-form-control', static fn (MyronSectionRenderContext $c): bool => in_array($c->componentId, ['form-field', 'datepicker', 'timepicker', 'select', 'textarea'], true) && $c->sourceBundleId === 'site-type.bkg'],
            ['stack', $component('stack')],
            ['switch', $component('switch')],
            ['tier-comparison-matrix', $component('tier-comparison-matrix')],
            ['sidebar-nav', $component('sidebar-nav')],
            ['profile-panel', $component('profile-panel')],
            ['settings-layout', $component('settings-layout')],
            ['marketing-funnel', fn (MyronSectionRenderContext $c): bool => $this->isMktFunnelTemplate($c->sourceBundleId, $c->sourceTemplateId)],
        ];

        foreach ($rules as $rule) {
            [$id, $matcher] = $rule;
            $this->sectionRenderers->register(new MyronCallableSectionRenderer(
                'core.' . $id,
                $matcher,
                fn (MyronSectionRenderContext $context): string => $this->renderRegisteredSection((string) $id, $context),
                100,
                $this->builtinSectionContract((string) $id),
            ));
        }
        $this->sectionRenderers->register(new MyronCallableSectionRenderer(
            'core.generic-fallback',
            static fn (MyronSectionRenderContext $context): bool => true,
            fn (MyronSectionRenderContext $context): string => $this->renderGenericFallbackSection($context),
            -1000,
        ));
    }

    private function builtinSectionContract(string $id): ?MyronSectionContract
    {
        $field = static function (string $key, string $label, string $type = 'text'): array {
            $record = [
                'key' => $key,
                'label' => $label,
                'type' => $type,
                'required' => false,
                'binding' => 'content.sections.{instanceKey}.' . $key,
            ];
            if ($type === 'image') {
                $record['assetKind'] = 'image';
            }
            return $record;
        };
        $enumField = static function (string $key, string $label, array $acceptedValues, string $default, string $description = '') use ($field): array {
            $record = $field($key, $label);
            $record['default'] = $default;
            $record['constraints'] = [
                'acceptedValues' => array_values($acceptedValues),
            ];
            if ($description !== '') {
                $record['constraints']['description'] = $description;
            }
            return $record;
        };
        $copy = [
            $field('headline', 'Headline'),
            $field('intro', 'Intro', 'textarea'),
            $field('body', 'Body', 'textarea'),
            $field('mediaFileId', 'Media Asset', 'image'),
            $field('mediaAlt', 'Media Alt Text'),
        ];
        $cta = array_merge([
            $field('eyebrow', 'Eyebrow'),
        ], $copy, [
            $field('ctaLabel', 'Primary CTA Label'),
            $field('ctaHref', 'Primary CTA Link', 'url'),
            $field('ctaSecondaryLabel', 'Secondary CTA Label'),
            $field('ctaSecondaryHref', 'Secondary CTA Link', 'url'),
            $enumField('contentAlign', 'Content Alignment', ['left', 'center'], 'left', 'Cinematic heroes only.'),
            $enumField('contentPosition', 'Content Position', ['top', 'center', 'bottom'], 'center', 'Cinematic heroes only.'),
            $enumField('contentWidth', 'Content Width', ['sm', 'md', 'lg'], 'sm', 'Cinematic heroes only.'),
            $enumField('copyWidth', 'Copy Width', ['match', 'narrow'], 'match', 'Cinematic heroes only. Narrow constrains body copy independently to the governed 560px measure.'),
            $enumField('subheadSize', 'Subhead Size', ['md', 'lg'], 'md', 'Cinematic lg is the governed 20px editorial preset.'),
            $enumField('eyebrowTone', 'Eyebrow Tone', ['default', 'accent', 'muted'], 'default', 'Cinematic heroes only.'),
            $enumField('eyebrowWeight', 'Eyebrow Weight', ['governed', 'regular', 'bold'], 'governed', 'Cinematic heroes only. Governed follows the active eyebrow font role.'),
            $enumField('overlay', 'Readability Overlay', ['off', 'faint', 'subtle', 'medium', 'strong'], 'medium', 'Cinematic heroes only. Off and faint require image-specific contrast review.'),
        ]);
        return match ($id) {
            'hero-simple' => new MyronSectionContract($copy),
            'hero-with-cta' => new MyronSectionContract($cta),
            'feature-grid' => new MyronSectionContract(array_merge(
                [$field('headline', 'Headline'), $field('intro', 'Intro', 'textarea'), $field('body', 'Body', 'textarea')],
                ...array_map(static fn (int $index): array => [
                    $field('item' . $index . 'Title', 'Highlight ' . $index . ' Title'),
                    $field('item' . $index . 'Body', 'Highlight ' . $index . ' Body', 'textarea'),
                    $field('item' . $index . 'IconFileId', 'Highlight ' . $index . ' Icon Asset', 'image'),
                    $field('item' . $index . 'IconAlt', 'Highlight ' . $index . ' Icon Alt Text'),
                ], [1, 2, 3]),
            )),
            'testimonial-grid' => new MyronSectionContract(array_merge(
                array_merge(
                    [$field('headline', 'Headline'), $field('intro', 'Intro', 'textarea'), $field('body', 'Body', 'textarea')],
                    ...array_map(static fn (int $index): array => [
                        $field('testimonial' . $index . 'Quote', 'Quote ' . $index),
                        $field('testimonial' . $index . 'Author', 'Quote ' . $index . ' Author'),
                        $field('testimonial' . $index . 'Organization', 'Quote ' . $index . ' Organization'),
                    ], [1, 2, 3]),
                ),
                [
                    $enumField('bandTone', 'Band Tone', ['accent-tint', 'surface-alt'], 'accent-tint', 'Featured-band testimonials only.'),
                    $enumField('eyebrowTone', 'Eyebrow Tone', ['default', 'accent'], 'default', 'Featured-band testimonials only.'),
                    $enumField('quoteSize', 'Quote Size', ['md', 'lg'], 'md', 'Featured-band testimonials only.'),
                ],
            )),
            'blog-teaser' => new MyronSectionContract([
                $field('headline', 'Headline'),
                $field('intro', 'Intro', 'textarea'),
                $field('body', 'Body', 'textarea'),
                array_merge($field('sourceMode', 'Post Source Mode'), [
                    'default' => 'default',
                    'constraints' => ['enum' => ['default', 'recent', 'sourcePath']],
                ]),
                $field('sourcePath', 'Source Path', 'url'),
                array_merge($field('postsLimit', 'Post Limit', 'number'), [
                    'default' => 6,
                    'constraints' => ['min' => 0, 'max' => 100],
                ]),
                $field('viewAllCtaLabel', 'View All CTA Label'),
                $field('viewAllCtaHref', 'View All CTA Href', 'url'),
            ]),
            'logo' => new MyronSectionContract(array_merge(
                [$field('headline', 'Headline'), $field('intro', 'Intro', 'textarea'), $field('body', 'Body', 'textarea')],
                ...array_map(static fn (int $index): array => [
                    $field('logo' . $index . 'FileId', 'Logo ' . $index . ' Asset', 'image'),
                    $field('logo' . $index . 'Alt', 'Logo ' . $index . ' Alt Text'),
                ], [1, 2, 3, 4, 5, 6]),
            )),
            'logo-ticker' => new MyronSectionContract(
                [
                    $field('headline', 'Headline'),
                    $field('marquee', 'Animate Logo Ticker', 'boolean'),
                    array_merge($field('speed', 'Ticker Speed'), [
                        'default' => 'normal',
                        'constraints' => ['enum' => ['slow', 'normal', 'fast']],
                    ]),
                    $enumField('density', 'Logo Density', ['comfortable', 'compact'], 'comfortable'),
                ],
                [[
                    'key' => 'logos',
                    'label' => 'Logos',
                    'itemLabel' => 'Logo',
                    'type' => 'repeater',
                    'minItems' => 0,
                    'maxItems' => 50,
                    'binding' => 'content.sections.{instanceKey}.logos',
                    'fields' => [
                        $field('mediaFileId', 'Logo Asset', 'image'),
                        $field('mediaAlt', 'Logo Alt Text'),
                    ],
                ]],
            ),
            'services-grid-image-card' => new MyronSectionContract(array_merge(
                [$field('headline', 'Headline'), $field('intro', 'Intro', 'textarea'), $field('body', 'Body', 'textarea')],
                ...array_map(static fn (int $index): array => [
                    $field('service' . $index . 'Title', 'Service ' . $index . ' Title'),
                    $field('service' . $index . 'Body', 'Service ' . $index . ' Body', 'textarea'),
                    $field('service' . $index . 'Href', 'Service ' . $index . ' Link', 'url'),
                    $field('service' . $index . 'CtaLabel', 'Service ' . $index . ' CTA Label'),
                    $field('service' . $index . 'ImageFileId', 'Service ' . $index . ' Image', 'image'),
                    $field('service' . $index . 'ImageAlt', 'Service ' . $index . ' Image Alt Text'),
                ], [1, 2, 3]),
            )),
            'cta-band-image-right' => new MyronSectionContract([
                $field('headline', 'Headline'),
                $field('intro', 'Intro', 'textarea'),
                $field('body', 'Body', 'textarea'),
                $field('ctaLabel', 'CTA Label'),
                $field('ctaHref', 'CTA Link', 'url'),
                $field('mediaFileId', 'Media Asset', 'image'),
                $field('mediaAlt', 'Media Alt Text'),
            ]),
            'cta-band-background-image' => new MyronSectionContract([
                $field('headline', 'Headline'),
                $field('intro', 'Intro', 'textarea'),
                $field('body', 'Body', 'textarea'),
                $field('ctaLabel', 'CTA Label'),
                $field('ctaHref', 'CTA Link', 'url'),
                $field('mediaFileId', 'Media Asset', 'image'),
                $field('mediaAlt', 'Media Alt Text'),
            ]),
            default => null,
        };
    }

    private function renderRegisteredSection(string $id, MyronSectionRenderContext $c): string
    {
        return match ($id) {
            'marketing-offer' => $this->renderMarketingOfferSection($c->classes, $c->variant, $c->componentId, $c->title, $c->body, $c->basePath, $c->sourceTemplateId, $c->intent),
            'portfolio-grid' => $this->renderPortfolioGridSection($c->classes, $c->variant, $c->title, $c->body, $c->basePath, $c->sourceBundleId, $c->content, $c->liveContentEnabled),
            'banner' => $this->renderBannerSection($c->classes, $c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->sourceBundleId, $c->intent),
            'creative-hero-parallax' => $this->renderCreativeHeroParallax($c->section, $c->variant, $c->content, $c->primaryHeading),
            'scrolljack-hero' => $this->renderScrolljackHero($c->variant, $c->content, $c->primaryHeading),
            'hero-with-cta' => $this->renderHeroWithCtaSection($c->variant, $c->title, $c->body, $c->basePath, $c->sourceBundleId, $c->sourceTemplateId, $c->intent, $c->primaryHeading, $c->content, $c->section),
            'hero-simple' => $this->renderHeroSimpleSection($c->variant, $c->title, $c->body, $c->basePath, $c->sourceBundleId, $c->sourceTemplateId, $c->intent, $c->primaryHeading, $c->content, $c->section),
            'search-composition' => $this->renderSearchResultsSection($c->variant, $c->sourceTemplateId, $c->intent, $c->runtimeData),
            'cms-content-title' => $this->renderRegisteredCmsContentTitle($c),
            'cms-content-body' => $this->renderCmsContentBodySection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'cms-featured-media' => $this->renderCmsFeaturedMediaSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent, $c->content),
            'cms-embed' => $this->renderCmsEmbedSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'header' => $this->renderHeaderSection($c->variant, $c->title, $c->body, $c->basePath, $c->sourceTemplateId, $c->intent),
            'pagination' => $this->renderPaginationSection($c->variant, $c->sourceTemplateId, $c->intent),
            'product-filters' => $this->renderProductFiltersSection($c->variant, $c->title, $c->sourceBundleId, $c->sourceTemplateId, $c->intent, $c->liveContentEnabled),
            'faq-list' => $this->renderFaqListSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'kv-row' => $this->renderKvRowSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'list' => $this->renderListSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'link' => $this->renderLinkSection($c->variant, $c->title, $c->body, $c->basePath, $c->sourceTemplateId, $c->intent),
            'sub-nav-bar' => $this->renderSubNavBarSection($c->variant, $c->title, $c->body, $c->basePath, $c->sourceTemplateId, $c->intent),
            'menu-block' => $this->renderMenuBlockSection($c->variant, $c->title, $c->body, $c->basePath, $c->sourceTemplateId, $c->intent),
            'legal-doc-toc' => $this->renderLegalDocTocSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'alert' => $this->renderAlertSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'avatar' => $this->renderAvatarSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'badge' => $c->sourceTemplateId === 'template.legal.universal.v1' ? '' : $this->renderBadgeSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'button' => $this->renderButtonSection($c->variant, $c->title, $c->body, $c->basePath, $c->sourceTemplateId, $c->intent),
            'card' => $this->renderCardSection($c->variant, $c->title, $c->body, $c->basePath, $c->sourceTemplateId, $c->intent),
            'carousel' => $this->renderCarouselSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'choice' => $this->renderChoiceSection($c->componentId, $c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'checkout-confirmation' => $this->renderCheckoutConfirmationSection($c->variant, $c->title, $c->body, $c->basePath, $c->sourceTemplateId, $c->intent),
            'chip' => $this->renderChipSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'form-control' => $this->renderFormControlSection($c->componentId, $c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'empty-state' => $this->renderEmptyStateSection($c->variant, $c->title, $c->body, $c->basePath, $c->sourceTemplateId, $c->intent),
            'image' => $this->renderImageSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'progress-bar' => $this->renderProgressBarSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'resources-item-card' => $this->renderResourcesItemCardSection($c->variant, $c->title, $c->body, $c->basePath, $c->sourceTemplateId, $c->intent),
            'user-identity' => $this->renderUserIdentitySection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'video' => $this->renderVideoSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'reservation-form' => $this->renderBookingSection($c->classes, $c->variant, 'reservation-form', 'Reservation Details', $c->body, $c->sourceTemplateId),
            'generic-form-control' => $this->renderGenericFormControlSection($c->componentId, $c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent),
            'contact-form-with-info' => $this->renderContactFormWithInfoSection($c->variant, $c->title, $c->body, $c->basePath, $c->sourceTemplateId, $c->intent),
            'feature-grid' => $this->renderFeatureGridSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent, $c->content),
            'services-grid' => $this->renderServicesGridSection($c->variant, $c->title, $c->body, $c->basePath, $c->sourceTemplateId, $c->intent, $c->content),
            'section-band' => $this->renderSectionBandSection($c->variant, $c->title, $c->body, $c->basePath, $c->sourceTemplateId, $c->intent, $c->content),
            'stats-tile' => $this->renderStatsStripSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent, $c->content),
            'testimonial-grid' => $this->renderTestimonialGridSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent, $c->content),
            'team-grid' => $this->renderTeamGridSection($c->classes, $c->variant, $c->title, $c->body, $c->content),
            'course-catalog' => $this->renderCourseCatalogSection($c->classes, $c->variant, $c->title, $c->body, $c->basePath, $c->sourceTemplateId, $c->intent),
            'pricing-table' => $this->renderPricingTableSection($c->classes, $c->variant, $c->title, $c->body, $c->basePath, $c->sourceBundleId, $c->sourceTemplateId, $c->intent),
            'blog-teaser' => $this->renderBlogTeaserSection($c->variant, $c->title, $c->body, $c->basePath, $c->sourceBundleId, $c->sourceTemplateId, $c->intent, $c->content, $c->liveContentEnabled),
            'logo' => $this->renderLogoGridSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent, $c->content),
            'contact-cta-suppression' => '',
            'cta-band' => $this->renderCtaBandSection($c->variant, $c->title, $c->body, $c->basePath, $c->sourceTemplateId, $c->intent, $c->content),
            'newsletter-signup' => $this->renderNewsletterSignupSection($c->variant, (int) ($c->section['_newsletterOccurrence'] ?? 0)),
            'commerce-catalog' => $this->renderCommerceCatalogSection($c->classes, $c->variant, $c->componentId, $c->title, $c->body, $c->basePath, $c->sourceTemplateId),
            'product-detail' => $this->renderProductDetailSection($c->classes, $c->variant, $c->componentId, $c->title, $c->body, $c->basePath, $c->sourceTemplateId),
            'cart-template-composition' => $this->renderCartSummarySection($c->classes, $c->variant, 'cart-table', 'Cart Items', $c->body, $c->basePath, $c->sourceTemplateId),
            'cart-summary' => $this->renderCartSummarySection($c->classes, $c->variant, $c->componentId, $c->title, $c->body, $c->basePath, $c->sourceTemplateId),
            'checkout-template-composition' => $this->renderCheckoutSection($c->classes, $c->variant, 'payment-form', 'Checkout', $c->body, $c->basePath, $c->sourceTemplateId),
            'checkout' => $this->renderCheckoutSection($c->classes, $c->variant, $c->componentId, $c->title, $c->body, $c->basePath, $c->sourceTemplateId),
            'booking-form-control' => $this->renderBookingSection($c->classes, $c->variant, $c->componentId, $c->title, $c->body, $c->sourceTemplateId),
            'stack' => str_contains($c->intent, 'social-links-row')
                ? $this->renderSocialLinksRowSection($c->variant, $c->title, $c->body, $c->sourceTemplateId, $c->intent)
                : $this->renderEditorialStackSection($c->classes, $c->variant, $c->title, $c->body, $c->sourceBundleId, $c->basePath, $c->liveContentEnabled),
            'switch' => $this->renderBillingSwitchSection($c->classes, $c->variant, $c->sourceTemplateId, $c->intent),
            'tier-comparison-matrix' => $this->renderTierComparisonMatrixSection($c->classes, $c->variant, $c->title, $c->body, $c->basePath, $c->sourceTemplateId, $c->intent),
            'sidebar-nav' => $this->renderSidebarNavSection($c->classes, $c->variant),
            'profile-panel' => $this->renderProfilePanelSection($c->classes, $c->variant),
            'settings-layout' => $this->renderSettingsLayoutSection($c->classes, $c->variant),
            'marketing-funnel' => $this->renderFunnelSection($c->classes, $c->variant, $c->componentId, $c->title, $c->body, $c->basePath, $c->sourceTemplateId, $c->intent, $c->primaryHeading),
            default => throw new LogicException('Unknown built-in section renderer: ' . $id),
        };
    }

    private function renderRegisteredCmsContentTitle(MyronSectionRenderContext $c): string
    {
        if ($this->isPostSingleTemplate($c->sourceTemplateId, $this->activePublishedPage)) {
            $postTitle = trim((string) ($c->content['headline'] ?? '')) ?: $this->activePageTitle();
            return $this->renderPostTitleMetaSection($c->variant, $postTitle, $c->sourceTemplateId, $c->intent);
        }
        return $this->renderCmsContentTitleSection($c->variant, $this->activePageTitle() ?: $c->title, $c->sourceTemplateId, $c->intent);
    }

    private function renderGenericFallbackSection(MyronSectionRenderContext $c): string
    {
        $html = [];
        $html[] = '<section class="' . $this->escape($c->classes) . '" data-component-id="' . $this->escape($c->componentId) . '" data-section-intent="' . $this->escape($c->intent) . '" data-source-template-id="' . $this->escape($c->sourceTemplateId) . '">';
        $html[] = '<div class="myron-definition-section__meta">';
        $html[] = '<span class="myron-definition-section__component">' . $this->escape($c->componentId) . '</span>';
        if ($c->variant !== '') {
            $html[] = '<span class="myron-definition-section__variant">' . $this->escape($c->variant) . '</span>';
        }
        $html[] = '</div>';
        $html[] = '<h2 class="myron-heading myron-definition-section__title">' . $this->escape($c->title) . '</h2>';
        $html[] = '<div class="myron-definition-section__content">' . $this->paragraphs($c->body) . '</div>';
        if (str_contains($c->componentId, 'cta') || $c->componentId === 'contact-form-with-info') {
            $label = str_contains($c->componentId, 'contact') ? 'Start with a message' : 'Continue';
            $href = str_contains($c->componentId, 'contact') ? '/contact' : '/';
            $html[] = '<a class="' . $this->escape($this->buttonClasses()) . '" href="' . $this->escape($this->routeHref($c->basePath, $href)) . '">' . $this->escape($label) . '</a>';
        }
        $html[] = '</section>';
        return implode("\n", $html);
    }

    /**
     * @param array<string, mixed> $content
     */
    private function renderLegacyBody(array $content): string
    {
        return '<section class="myron-definition-section myron-definition-section--legacy">' . $this->paragraphs((string) ($content['body'] ?? ''), false) . '</section>';
    }

    private function renderFunnelSection(string $classes, string $variant, string $componentId, string $title, string $body, string $basePath, string $sourceTemplateId, string $intent, bool $primaryHeading = false): string
    {
        $stepKey = $this->funnelStepKey($sourceTemplateId);
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : $stepKey);
        $cta = $this->funnelCta($stepKey, $componentId);
        $copy = $this->publicSectionBody($body, $this->funnelFallbackBody($stepKey, $componentId));
        $html = [];
        $html[] = '<section class="' . $this->escape($classes . ' myron-funnel-section myron-funnel-section--' . $normalizedVariant) . '" data-component-id="' . $this->escape($componentId) . '" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-funnel-hook="tripwire" data-funnel-step="' . $this->escape($stepKey) . '" data-section-intent="' . $this->escape($intent) . '">';
        $headingTag = $primaryHeading && in_array($componentId, ['hero-with-cta', 'hero-simple'], true) ? 'h1' : 'h2';
        $html[] = '<' . $headingTag . ' class="myron-heading myron-definition-section__title">' . $this->escape($this->funnelTitle($stepKey, $title)) . '</' . $headingTag . '>';
        if ($copy !== '') {
            $html[] = '<div class="myron-definition-section__content">' . $this->paragraphs($copy) . '</div>';
        }

        if (in_array($componentId, ['lead-magnet-card', 'checkout-address-form', 'payment-form'], true)) {
            $html[] = '<form class="myron-funnel-section__form" method="post" action="' . $this->escape($this->routeHref($basePath, $cta['href'])) . '" data-funnel-form="' . $this->escape($componentId) . '">';
            $html[] = $this->renderPassivePublicFormProtection('funnel-' . $componentId);
            $html[] = '<label><span>Email address</span><input type="email" name="email" autocomplete="email" placeholder="you@example.com"></label>';
            if ($componentId === 'payment-form') {
                $html[] = '<label><span>Test reference</span><input type="text" name="test_reference" value="TEST-TRIPWIRE" readonly></label>';
                $html[] = '<p class="myron-text myron-text--muted" data-funnel-disclosure="test-payment">Test adapter only. No payment credential is captured.</p>';
            }
            $html[] = '<button class="' . $this->escape($this->buttonClasses()) . '" type="submit">' . $this->escape($cta['label']) . '</button>';
            $html[] = '</form>';
        } else {
            $html[] = '<a class="' . $this->escape($this->buttonClasses()) . '" href="' . $this->escape($this->routeHref($basePath, $cta['href'])) . '">' . $this->escape($cta['label']) . '</a>';
        }

        if (in_array($stepKey, ['sales', 'checkout', 'upsell', 'downsell'], true)) {
            $html[] = '<p class="myron-paragraph myron-paragraph--muted" data-funnel-disclosure="offer-terms">Offer terms, deadline eligibility, and cancellation policy are surfaced for quality review.</p>';
        }
        if ($stepKey === 'expired') {
            $html[] = '<p class="myron-paragraph myron-paragraph--muted" data-funnel-expired="true">This route is the deterministic expired-offer destination.</p>';
        }

        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function isMktFunnelTemplate(string $sourceBundleId, string $sourceTemplateId): bool
    {
        return $sourceBundleId === 'site-type.mkt' && str_starts_with($sourceTemplateId, 'template.funnel.');
    }

    private function withFunnelAttributes(string $html, string $sourceTemplateId, string $variant): string
    {
        if (trim($html) === '' || !str_contains($html, '<section')) {
            return $html;
        }

        $stepKey = $this->funnelStepKey($sourceTemplateId);
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : $stepKey);
        $result = preg_replace_callback(
            '~<section\b([^>]*)>~',
            function (array $matches) use ($stepKey, $normalizedVariant): string {
                $attributes = (string) ($matches[1] ?? '');
                $classes = 'myron-funnel-section myron-funnel-section--' . $normalizedVariant;

                if (preg_match('~\sclass="([^"]*)"~', $attributes, $classMatch) === 1) {
                    $classValue = (string) $classMatch[1];
                    foreach (explode(' ', $classes) as $className) {
                        if ($className !== '' && !in_array($className, preg_split('~\s+~', trim($classValue)) ?: [], true)) {
                            $classValue .= ' ' . $className;
                        }
                    }
                    $attributes = preg_replace('~\sclass="[^"]*"~', ' class="' . $this->escape(trim($classValue)) . '"', $attributes, 1) ?? $attributes;
                } else {
                    $attributes = ' class="' . $this->escape($classes) . '"' . $attributes;
                }

                if (!str_contains($attributes, 'data-funnel-hook=')) {
                    $attributes .= ' data-funnel-hook="tripwire"';
                }
                if (!str_contains($attributes, 'data-funnel-step=')) {
                    $attributes .= ' data-funnel-step="' . $this->escape($stepKey) . '"';
                }
                if ($stepKey === 'expired' && !str_contains($attributes, 'data-funnel-expired=')) {
                    $attributes .= ' data-funnel-expired="true"';
                }

                return '<section' . $attributes . '>';
            },
            $html,
            1
        );

        return is_string($result) ? $result : $html;
    }

    private function renderMarketingOfferSection(string $classes, string $variant, string $componentId, string $title, string $body, string $basePath, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'marketing-offer');
        $href = $componentId === 'lead-magnet-card' ? '/squeeze' : '/sales';
        $label = $componentId === 'lead-magnet-card' ? 'Join the list' : 'View offer';
        if (str_starts_with($sourceTemplateId, 'template.funnel.')) {
            $cta = $this->funnelCta($this->funnelStepKey($sourceTemplateId), $componentId);
            $href = $cta['href'];
            $label = $cta['label'];
        }
        $copy = $this->publicSectionBody($body, '');
        $html = [];
        $sectionClass = 'myron-public-component myron-public-component--contained myron-public-component--' . $componentId . ' myron-marketing-offer myron-marketing-offer--' . $normalizedVariant;
        $cardClass = $componentId === 'lead-magnet-card'
            ? 'myron-lead-magnet-card myron-lead-magnet-card--stacked-card'
            : 'myron-featured-offer-card myron-featured-offer-card--default';
        $bodyClass = $componentId === 'lead-magnet-card'
            ? 'myron-lead-magnet-card__body'
            : 'myron-featured-offer-card__body';
        $titleClass = $componentId === 'lead-magnet-card'
            ? 'myron-lead-magnet-card__title'
            : 'myron-featured-offer-card__title';
        $copyClass = $componentId === 'lead-magnet-card'
            ? 'myron-lead-magnet-card__benefit'
            : 'myron-featured-offer-card__outcome';

        $html[] = '<section class="' . $this->escape($sectionClass) . '" data-component-id="' . $this->escape($componentId) . '" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-marketing-hook="offer" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<article class="' . $this->escape($cardClass) . '">';
        $html[] = '<div class="' . $this->escape($bodyClass) . '">';
        $html[] = '<h2 class="myron-heading ' . $this->escape($titleClass) . '">' . $this->escape($title) . '</h2>';
        if ($copy !== '') {
            $html[] = '<p class="myron-paragraph ' . $this->escape($copyClass) . '">' . $this->escape($copy) . '</p>';
        }
        $html[] = '<a class="' . $this->escape($this->buttonClasses()) . '" href="' . $this->escape($this->routeHref($basePath, $href)) . '">' . $this->escape($label) . '</a>';
        $html[] = '</div>';
        $html[] = '</article>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    /**
     * @param list<array<string, mixed>> $footerNavigation
     * @param array<string, mixed>|string $resolutionHint  APO-181 Card 1 — accept either
     *     the full chrome footer object (with inherit + variant) OR a bare variant string
     *     for backward compatibility with any older callers.
     */
    private function renderFooterNavigation(string $basePath, array $footerNavigation, array|string $resolutionHint = '', string $templateId = ''): string
    {
        $chromeFooter = is_array($resolutionHint)
            ? $resolutionHint
            : ['variant' => (string) $resolutionHint, 'inherit' => 'explicit'];
        $resolvedVariant = $this->resolveFooterVariant($chromeFooter, $templateId);
        $zoneVisibility  = $this->loadFooterZoneVisibility($resolvedVariant);
        $activeZones     = myronFooterVariantCompositionService()->orderedZonesFor($resolvedVariant);
        $allZoneContent  = $this->loadAllFooterZoneContent($resolvedVariant);

        $variantSlug  = $resolvedVariant !== '' ? myronNormalizeSlug($resolvedVariant) : '';
        $variantClass = $variantSlug !== '' ? ' myron-site__footer--' . $variantSlug : '';

        $html = ['<footer class="myron-site__footer' . $this->escape($variantClass) . '" aria-label="Site footer" data-component-id="footer" data-footer-variant="' . $this->escape($resolvedVariant) . '">'];
        $html[] = '<div class="myron-footer__zones">';

        foreach ($activeZones as $zoneId) {
            if (isset($zoneVisibility[$zoneId]) && $zoneVisibility[$zoneId] === false) {
                continue;
            }
            $zoneContent = is_array($allZoneContent[$zoneId] ?? null) ? $allZoneContent[$zoneId] : [];
            $html[] = $this->renderFooterZone(
                $zoneId,
                $zoneContent,
                $basePath,
                $footerNavigation,
                ['preview' => false]
            );
        }

        if ($activeZones === [] && $footerNavigation !== []) {
            foreach ($footerNavigation as $navItem) {
                $html[] = '<a href="' . $this->escape($this->routeHref($basePath, (string) ($navItem['path'] ?? '/'))) . '">' . $this->escape((string) ($navItem['label'] ?? 'Page')) . '</a>';
            }
        }

        $html[] = '</div>';
        $html[] = '</footer>';

        return implode("\n", $html);
    }

    /**
     * APO-180 Card 1 — Zone HTML emission dispatcher.
     *
     * Renders a single footer zone with its zone-specific HTML shape. Every zone
     * carries `data-zone-id` and `data-zone-populated` attributes for AI
     * consumption and verifier introspection. Empty zones produce a stub with
     * `data-zone-populated="false"` and no internal content (no orphan markup).
     *
     * @param array<string, mixed> $zoneContent
     * @param list<array<string, mixed>> $footerNavigation
     * @param array{preview:bool,inactive?:bool} $options
     */
    private function renderFooterZone(
        string $zoneId,
        array $zoneContent,
        string $basePath,
        array $footerNavigation = [],
        array $options = []
    ): string {
        $zoneSlug = myronNormalizeSlug($zoneId);
        $isPopulated = $this->isZoneContentPopulated($zoneContent);
        $isInactive = (bool) ($options['inactive'] ?? false);
        $isPreview = (bool) ($options['preview'] ?? false);

        $classes = 'myron-footer__zone myron-footer__zone--' . $zoneSlug;
        if ($isPreview) {
            $classes .= ' myron-footer__zone--preview';
        }
        if ($isInactive) {
            $classes .= ' myron-footer__zone--inactive';
        }

        $attrs = ' data-zone-id="' . $this->escape($zoneId) . '"'
            . ' data-zone-populated="' . ($isPopulated ? 'true' : 'false') . '"';
        if ($isInactive) {
            $attrs .= ' data-zone-active="false"';
        }

        $inner = $this->renderFooterZoneInner($zoneId, $zoneContent, $basePath, $footerNavigation);
        if ($isInactive && $isPreview) {
            // Preserve rendered shape but overlay a Hidden badge so the operator
            // still recognises the zone (Card 4 contract).
            $inner = '<span class="myron-footer__zone-hidden-badge" aria-hidden="true">Hidden</span>' . $inner;
        }

        return '<div class="' . $this->escape($classes) . '"' . $attrs . '>'
            . $inner
            . '</div>';
    }

    /**
     * @param array<string, mixed> $zoneContent
     */
    private function isZoneContentPopulated(array $zoneContent): bool
    {
        if ($zoneContent === []) {
            return false;
        }
        foreach ($zoneContent as $value) {
            if (is_array($value)) {
                if ($value !== []) {
                    return true;
                }
                continue;
            }
            if (trim((string) $value) !== '') {
                return true;
            }
        }
        return false;
    }

    /**
     * @param array<string, mixed> $zoneContent
     * @param list<array<string, mixed>> $footerNavigation
     */
    private function renderFooterZoneInner(
        string $zoneId,
        array $zoneContent,
        string $basePath,
        array $footerNavigation
    ): string {
        return match ($zoneId) {
            'zone.brand'                => $this->renderFooterZoneBrand($zoneContent),
            'zone.nav-col'              => $this->renderFooterZoneNavCol($zoneContent, $basePath),
            'zone.newsletter'           => $this->renderFooterZoneNewsletter($zoneContent),
            'zone.cta-band'             => $this->renderFooterZoneCtaBand($zoneContent, $basePath),
            'zone.social'               => $this->renderFooterZoneSocial($zoneContent, $basePath),
            'zone.trust-signals'        => $this->renderFooterZoneTrustSignals($zoneContent, $basePath),
            'zone.payment-logos'        => $this->renderFooterZonePaymentLogos($zoneContent),
            'zone.app-badges'           => $this->renderFooterZoneAppBadges($zoneContent, $basePath),
            'zone.nap-hours'            => $this->renderFooterZoneNapHours($zoneContent, $basePath),
            'zone.availability-status'  => $this->renderFooterZoneAvailabilityStatus($zoneContent, $basePath),
            'zone.provider-cta'         => $this->renderFooterZoneProviderCta($zoneContent, $basePath),
            'zone.disclaimer'           => $this->renderFooterZoneDisclaimer($zoneContent),
            'zone.legal-strip'          => $this->renderFooterZoneLegalStrip($zoneContent, $basePath, $footerNavigation),
            default                     => '',
        };
    }

    /** @param array<string, mixed> $c */
    private function renderFooterZoneBrand(array $c): string
    {
        $logoUrl  = trim((string) ($c['logo_url'] ?? ''));
        $logoAlt  = trim((string) ($c['logo_alt'] ?? ''));
        $siteName = trim((string) ($c['site_name'] ?? ''));
        $tagline  = trim((string) ($c['tagline'] ?? ''));
        $parts = [];
        if ($logoUrl !== '') {
            $parts[] = '<img src="' . $this->escape($logoUrl) . '" alt="' . $this->escape($logoAlt) . '" class="myron-footer__logo">';
        }
        if ($siteName !== '') {
            $parts[] = '<span class="myron-footer__site-name">' . $this->escape($siteName) . '</span>';
        }
        if ($tagline !== '') {
            $parts[] = '<p class="myron-footer__tagline">' . $this->escape($tagline) . '</p>';
        }
        return implode('', $parts);
    }

    /** @param array<string, mixed> $c */
    private function renderFooterZoneNavCol(array $c, string $basePath): string
    {
        $heading = trim((string) ($c['heading'] ?? ''));
        $links = is_array($c['links'] ?? null) ? $c['links'] : [];
        $linkItems = [];
        foreach ($links as $link) {
            if (!is_array($link)) {
                continue;
            }
            $url   = trim((string) ($link['url'] ?? ''));
            $label = trim((string) ($link['label'] ?? ''));
            if ($url === '' || $label === '') {
                continue;
            }
            $linkItems[] = '<li class="myron-footer__nav-col-item">'
                . '<a class="myron-footer__nav-col-link" href="'
                . $this->escape($this->routeHref($basePath, $url)) . '">'
                . $this->escape($label) . '</a></li>';
        }
        if ($heading === '' && $linkItems === []) {
            return '';
        }
        $parts = [];
        if ($heading !== '') {
            $parts[] = '<h3 class="myron-footer__nav-col-heading">' . $this->escape($heading) . '</h3>';
        }
        if ($linkItems !== []) {
            $parts[] = '<ul class="myron-footer__nav-col-list">' . implode('', $linkItems) . '</ul>';
        }
        return implode('', $parts);
    }

    /** @param array<string, mixed> $c */
    private function renderFooterZoneNewsletter(array $c): string
    {
        $heading      = trim((string) ($c['heading'] ?? ''));
        $supporting   = trim((string) ($c['supporting_copy'] ?? ''));
        $placeholder  = trim((string) ($c['email_placeholder'] ?? 'you@example.com'));
        // submit_label and email_placeholder are renderer-defaulted aesthetic values;
        // they don't on their own constitute operator-meaningful zone content.
        $submitLabel  = trim((string) ($c['submit_label'] ?? '')) ?: 'Subscribe';
        $consent      = trim((string) ($c['consent_note'] ?? ''));
        if ($heading === '' && $supporting === '' && $consent === '' && trim((string) ($c['submit_label'] ?? '')) === '') {
            return '';
        }
        $html = ['<div class="myron-newsletter-signup myron-newsletter-signup--footer">'];
        if ($heading !== '') {
            $html[] = '<div class="myron-newsletter-signup__heading"><h3 class="myron-footer__newsletter-heading">' . $this->escape($heading) . '</h3></div>';
        }
        if ($supporting !== '') {
            $html[] = '<div class="myron-newsletter-signup__body"><p class="myron-footer__newsletter-supporting">' . $this->escape($supporting) . '</p></div>';
        }
        $html[] = '<form class="myron-newsletter-signup__form myron-footer__newsletter-form" method="post" action="" novalidate>';
        $html[] = $this->renderPassivePublicFormProtection('footer-newsletter');
        $html[] = '<div class="myron-newsletter-signup__fields">';
        // APO-182 Card 2 — single-source accessible name on the input itself via
        // aria-label. The previous implementation wrapped the input in a label
        // containing a visually-hidden span; that span depended on a CSS utility
        // class that never shipped on the public side, so the label rendered
        // visibly. aria-label on the input is the canonical accessible-name path.
        $html[] = '<input class="myron-footer__newsletter-input" type="email" name="email" id="myron-footer-newsletter-email" placeholder="' . $this->escape($placeholder) . '" autocomplete="email" aria-label="Email address">';
        $html[] = '<button class="' . $this->escape($this->buttonClasses('neutral', 'solid', 'md', 'myron-footer__newsletter-submit')) . '" type="submit">'
            . $this->escape($submitLabel) . '</button>';
        $html[] = '</div>';
        if ($consent !== '') {
            $html[] = '<p class="myron-newsletter-signup__consent myron-footer__newsletter-consent">' . $this->escape($consent) . '</p>';
        }
        $html[] = '</form>';
        $html[] = '</div>';
        return implode('', $html);
    }

    /** @param array<string, mixed> $c */
    private function renderFooterZoneCtaBand(array $c, string $basePath): string
    {
        $headline       = trim((string) ($c['headline'] ?? ''));
        $supporting     = trim((string) ($c['supporting_copy'] ?? ''));
        $primaryLabel   = trim((string) ($c['primary_cta_label'] ?? ''));
        $primaryUrl     = trim((string) ($c['primary_cta_url'] ?? ''));
        $secondaryLabel = trim((string) ($c['secondary_cta_label'] ?? ''));
        $secondaryUrl   = trim((string) ($c['secondary_cta_url'] ?? ''));
        $trustMicro     = trim((string) ($c['trust_microcopy'] ?? ''));

        if ($headline === '' && $supporting === '' && $primaryLabel === '' && $secondaryLabel === '') {
            return '';
        }

        $html = ['<div class="myron-cta-band myron-cta-band--tone-default myron-cta-band--layout-centered myron-footer__cta-band">'];
        $html[] = '<div class="myron-cta-band__inner">';
        if ($headline !== '') {
            $html[] = '<h2 class="myron-footer__cta-band-headline">' . $this->escape($headline) . '</h2>';
        }
        if ($supporting !== '') {
            $html[] = '<p class="myron-cta-band__body myron-footer__cta-band-supporting">' . $this->escape($supporting) . '</p>';
        }
        if ($primaryLabel !== '' || $secondaryLabel !== '') {
            $html[] = '<div class="myron-cta-band__actions myron-footer__cta-band-actions">';
            if ($primaryLabel !== '') {
                $url = $primaryUrl !== '' ? $this->routeHref($basePath, $primaryUrl) : '#';
                $html[] = '<a class="' . $this->escape($this->buttonClasses('neutral', 'solid', 'md', 'myron-footer__cta-band-primary')) . '" href="' . $this->escape($url) . '">'
                    . $this->escape($primaryLabel) . '</a>';
            }
            if ($secondaryLabel !== '') {
                $url = $secondaryUrl !== '' ? $this->routeHref($basePath, $secondaryUrl) : '#';
                $html[] = '<a class="' . $this->escape($this->buttonClasses('neutral', 'outline', 'md', 'myron-footer__cta-band-secondary')) . '" href="' . $this->escape($url) . '">'
                    . $this->escape($secondaryLabel) . '</a>';
            }
            $html[] = '</div>';
        }
        if ($trustMicro !== '') {
            $html[] = '<p class="myron-footer__cta-band-trust">' . $this->escape($trustMicro) . '</p>';
        }
        $html[] = '</div>';
        $html[] = '</div>';
        return implode('', $html);
    }

    /** @param array<string, mixed> $c */
    private function renderFooterZoneSocial(array $c, string $basePath): string
    {
        $platforms = is_array($c['platforms'] ?? null) ? $c['platforms'] : [];
        $items = [];
        foreach ($platforms as $platform) {
            if (!is_array($platform)) {
                continue;
            }
            $url   = trim((string) ($platform['url'] ?? ''));
            $label = trim((string) ($platform['label'] ?? ''));
            $platformId = trim((string) ($platform['platform_id'] ?? ''));
            $iconUrl = trim((string) ($platform['icon_url'] ?? ''));
            if ($url === '' && $label === '' && $iconUrl === '') {
                continue;
            }
            $accessibleLabel = $label !== '' ? $label : ($platformId !== '' ? ucfirst($platformId) : 'Social link');
            $hrefAttr = $url !== '' ? $this->escape($this->routeHref($basePath, $url)) : '#';
            $iconHtml = $iconUrl !== ''
                ? '<img class="myron-footer__social-icon" src="' . $this->escape($iconUrl) . '" alt="">'
                : '<span class="myron-footer__social-icon-fallback" aria-hidden="true">' . $this->escape(strtoupper(substr($platformId !== '' ? $platformId : $accessibleLabel, 0, 1))) . '</span>';
            // APO-182 Card 2 — the link's aria-label is the canonical accessible
            // name; the inner icon-or-fallback span is intentionally aria-hidden.
            // No redundant visually-hidden text node is needed.
            $items[] = '<li class="myron-footer__social-item"><a class="myron-footer__social-link" href="' . $hrefAttr . '" aria-label="' . $this->escape($accessibleLabel) . '">'
                . $iconHtml
                . '</a></li>';
        }
        if ($items === []) {
            return '';
        }
        return '<ul class="myron-footer__social-list" aria-label="Social links">' . implode('', $items) . '</ul>';
    }

    /** @param array<string, mixed> $c */
    private function renderFooterZoneTrustSignals(array $c, string $basePath): string
    {
        $badges = is_array($c['badges'] ?? null) ? $c['badges'] : [];
        $items = [];
        foreach ($badges as $badge) {
            if (!is_array($badge)) {
                continue;
            }
            $imageUrl = trim((string) ($badge['image_url'] ?? ''));
            $alt      = trim((string) ($badge['alt'] ?? ''));
            $linkUrl  = trim((string) ($badge['link_url'] ?? ''));
            if ($imageUrl === '' && $alt === '') {
                continue;
            }
            $imgHtml = $imageUrl !== ''
                ? '<img class="myron-footer__trust-image" src="' . $this->escape($imageUrl) . '" alt="' . $this->escape($alt) . '">'
                : '<span class="myron-footer__trust-text">' . $this->escape($alt) . '</span>';
            if ($linkUrl !== '') {
                $items[] = '<li class="myron-footer__trust-item"><a class="myron-footer__trust-link" href="' . $this->escape($this->routeHref($basePath, $linkUrl)) . '">' . $imgHtml . '</a></li>';
            } else {
                $items[] = '<li class="myron-footer__trust-item">' . $imgHtml . '</li>';
            }
        }
        if ($items === []) {
            return '';
        }
        return '<ul class="myron-footer__trust-list">' . implode('', $items) . '</ul>';
    }

    /** @param array<string, mixed> $c */
    private function renderFooterZonePaymentLogos(array $c): string
    {
        $methods = is_array($c['methods'] ?? null) ? $c['methods'] : [];
        $items = [];
        foreach ($methods as $method) {
            if (!is_array($method)) {
                continue;
            }
            $imageUrl = trim((string) ($method['image_url'] ?? ''));
            $alt      = trim((string) ($method['alt'] ?? ''));
            $methodId = trim((string) ($method['method_id'] ?? ''));
            if ($imageUrl === '' && $alt === '' && $methodId === '') {
                continue;
            }
            $altResolved = $alt !== '' ? $alt : ($methodId !== '' ? ucfirst($methodId) : 'Payment method');
            $imgHtml = $imageUrl !== ''
                ? '<img class="myron-footer__payment-image" src="' . $this->escape($imageUrl) . '" alt="' . $this->escape($altResolved) . '">'
                : '<span class="myron-footer__payment-text">' . $this->escape($altResolved) . '</span>';
            $items[] = '<li class="myron-footer__payment-item">' . $imgHtml . '</li>';
        }
        if ($items === []) {
            return '';
        }
        return '<ul class="myron-footer__payment-list" aria-label="Accepted payment methods">' . implode('', $items) . '</ul>';
    }

    /** @param array<string, mixed> $c */
    private function renderFooterZoneAppBadges(array $c, string $basePath): string
    {
        $badges = is_array($c['badges'] ?? null) ? $c['badges'] : [];
        $items = [];
        foreach ($badges as $badge) {
            if (!is_array($badge)) {
                continue;
            }
            $imageUrl = trim((string) ($badge['image_url'] ?? ''));
            $url      = trim((string) ($badge['url'] ?? ''));
            $alt      = trim((string) ($badge['alt'] ?? ''));
            $storeId  = trim((string) ($badge['store_id'] ?? ''));
            if ($imageUrl === '' && $url === '' && $alt === '' && $storeId === '') {
                continue;
            }
            $altResolved = $alt !== '' ? $alt : ($storeId !== '' ? 'Available on ' . ucfirst($storeId) : 'Mobile app');
            $imgHtml = $imageUrl !== ''
                ? '<img class="myron-footer__app-badge-image" src="' . $this->escape($imageUrl) . '" alt="' . $this->escape($altResolved) . '">'
                : '<span class="myron-footer__app-badge-fallback">' . $this->escape($altResolved) . '</span>';
            $href = $url !== '' ? $this->routeHref($basePath, $url) : '#';
            $items[] = '<li class="myron-footer__app-badges-item"><a class="myron-footer__app-badges-link" href="' . $this->escape($href) . '" aria-label="' . $this->escape($altResolved) . '">' . $imgHtml . '</a></li>';
        }
        if ($items === []) {
            return '';
        }
        return '<ul class="myron-footer__app-badges">' . implode('', $items) . '</ul>';
    }

    /** @param array<string, mixed> $c */
    private function renderFooterZoneNapHours(array $c, string $basePath): string
    {
        $businessName  = trim((string) ($c['business_name'] ?? ''));
        $streetAddress = trim((string) ($c['street_address'] ?? ''));
        $cityStateZip  = trim((string) ($c['city_state_zip'] ?? ''));
        $phone         = trim((string) ($c['phone'] ?? ''));
        $email         = trim((string) ($c['email'] ?? ''));
        $mapsUrl       = trim((string) ($c['maps_url'] ?? ''));
        $hours         = is_array($c['hours'] ?? null) ? $c['hours'] : [];

        if ($businessName === '' && $streetAddress === '' && $cityStateZip === '' && $phone === '' && $email === '' && $hours === []) {
            return '';
        }

        $html = ['<address class="myron-footer__nap">'];
        if ($businessName !== '') {
            $html[] = '<span class="myron-footer__nap-name">' . $this->escape($businessName) . '</span>';
        }
        if ($streetAddress !== '' || $cityStateZip !== '') {
            $html[] = '<span class="myron-footer__nap-address">';
            if ($streetAddress !== '') {
                $html[] = '<span class="myron-footer__nap-street">' . $this->escape($streetAddress) . '</span>';
            }
            if ($cityStateZip !== '') {
                $html[] = '<span class="myron-footer__nap-locality">' . $this->escape($cityStateZip) . '</span>';
            }
            $html[] = '</span>';
        }
        if ($phone !== '') {
            $telHref = 'tel:' . preg_replace('/[^0-9+]/', '', $phone);
            $html[] = '<a class="myron-footer__nap-phone" href="' . $this->escape($telHref) . '">' . $this->escape($phone) . '</a>';
        }
        if ($email !== '') {
            $html[] = '<a class="myron-footer__nap-email" href="mailto:' . $this->escape($email) . '">' . $this->escape($email) . '</a>';
        }
        if ($mapsUrl !== '') {
            $html[] = '<a class="myron-footer__nap-directions" href="' . $this->escape($mapsUrl) . '" rel="noopener" target="_blank">Get directions</a>';
        }
        if ($hours !== []) {
            $html[] = '<dl class="myron-footer__nap-hours">';
            foreach ($hours as $row) {
                if (!is_array($row)) {
                    continue;
                }
                $day  = trim((string) ($row['day'] ?? ''));
                $open = trim((string) ($row['open_time'] ?? ''));
                $close = trim((string) ($row['close_time'] ?? ''));
                if ($day === '' && $open === '' && $close === '') {
                    continue;
                }
                $hoursLabel = $open === '' ? '' : ($close === '' ? $open : $open . ' – ' . $close);
                $html[] = '<dt class="myron-footer__nap-hours-day">' . $this->escape($day) . '</dt>';
                $html[] = '<dd class="myron-footer__nap-hours-time">' . $this->escape($hoursLabel) . '</dd>';
            }
            $html[] = '</dl>';
        }
        $html[] = '</address>';
        return implode('', $html);
    }

    /** @param array<string, mixed> $c */
    private function renderFooterZoneAvailabilityStatus(array $c, string $basePath): string
    {
        $statusText = trim((string) ($c['status_text'] ?? ''));
        $contactUrl = trim((string) ($c['contact_url'] ?? ''));
        if ($statusText === '') {
            return '';
        }
        $html = ['<div class="myron-footer__availability">'];
        $html[] = '<span class="myron-footer__availability-dot" aria-hidden="true"></span>';
        $html[] = '<span class="myron-footer__availability-text">' . $this->escape($statusText) . '</span>';
        if ($contactUrl !== '') {
            $html[] = '<a class="myron-footer__availability-link" href="' . $this->escape($this->routeHref($basePath, $contactUrl)) . '">Get in touch</a>';
        }
        $html[] = '</div>';
        return implode('', $html);
    }

    /** @param array<string, mixed> $c */
    private function renderFooterZoneProviderCta(array $c, string $basePath): string
    {
        $heading = trim((string) ($c['heading'] ?? ''));
        $links = is_array($c['links'] ?? null) ? $c['links'] : [];
        $items = [];
        foreach ($links as $link) {
            if (!is_array($link)) {
                continue;
            }
            $url   = trim((string) ($link['url'] ?? ''));
            $label = trim((string) ($link['label'] ?? ''));
            if ($url === '' || $label === '') {
                continue;
            }
            $items[] = '<li class="myron-footer__provider-cta-item"><a class="myron-footer__provider-cta-link" href="'
                . $this->escape($this->routeHref($basePath, $url)) . '">' . $this->escape($label) . '</a></li>';
        }
        if ($heading === '' && $items === []) {
            return '';
        }
        $html = ['<div class="myron-footer__provider-cta">'];
        if ($heading !== '') {
            $html[] = '<h3 class="myron-footer__provider-cta-heading">' . $this->escape($heading) . '</h3>';
        }
        if ($items !== []) {
            $html[] = '<ul class="myron-footer__provider-cta-list">' . implode('', $items) . '</ul>';
        }
        $html[] = '</div>';
        return implode('', $html);
    }

    /** @param array<string, mixed> $c */
    private function renderFooterZoneDisclaimer(array $c): string
    {
        $text = trim((string) ($c['disclaimer_text'] ?? ''));
        if ($text === '') {
            return '';
        }
        return '<p class="myron-footer__disclaimer">' . $this->escape($text) . '</p>';
    }

    /**
     * @param array<string, mixed> $c
     * @param list<array<string, mixed>> $footerNavigation
     */
    private function renderFooterZoneLegalStrip(array $c, string $basePath, array $footerNavigation): string
    {
        $copyright = trim((string) ($c['copyright_text'] ?? ''));
        $links = is_array($c['links'] ?? null) ? $c['links'] : [];
        $html = [];
        if ($copyright !== '') {
            $html[] = '<span class="myron-footer__copyright">' . $this->escape($copyright) . '</span>';
        }
        $linkHtml = [];
        if ($links !== []) {
            foreach ($links as $link) {
                if (!is_array($link)) {
                    continue;
                }
                $url   = trim((string) ($link['url'] ?? ''));
                $label = trim((string) ($link['label'] ?? ''));
                if ($url !== '' && $label !== '') {
                    $linkHtml[] = '<a class="myron-footer__legal-link" href="' . $this->escape($this->routeHref($basePath, $url)) . '">' . $this->escape($label) . '</a>';
                }
            }
        } elseif ($footerNavigation !== []) {
            foreach ($footerNavigation as $navItem) {
                $linkHtml[] = '<a class="myron-footer__legal-link" href="' . $this->escape($this->routeHref($basePath, (string) ($navItem['path'] ?? '/'))) . '">'
                    . $this->escape((string) ($navItem['label'] ?? 'Page')) . '</a>';
            }
        }
        if ($linkHtml !== []) {
            $html[] = '<nav class="myron-footer__legal-links" aria-label="Legal">' . implode('', $linkHtml) . '</nav>';
        }
        return implode('', $html);
    }

    /**
     * APO-180 Card 4 — Render a footer preview for the Design footer workspace
     * with parity to the public render.
     *
     * The preview reuses renderFooterZone (Card 1) so each zone produces the
     * same designed-component HTML as on the live site. Inactive zones still
     * appear, with the rendered shape preserved beneath a corner Hidden badge,
     * so the operator can recognise the zone they have hidden.
     *
     * @param array<string, mixed> $zoneVisibility
     * @param array<string, string> $zoneLabels  (kept for backward-compatible
     *     signature; the preview no longer renders zone-label-only stacks)
     */
    public function renderFooterPreview(string $basePath, string $variant, array $zoneVisibility, array $zoneLabels): string
    {
        $activeZones    = myronFooterVariantCompositionService()->orderedZonesFor($variant);
        $allZoneContent = $this->loadAllFooterZoneContent($variant);
        $variantSlug    = $variant !== '' ? myronNormalizeSlug($variant) : '';
        $variantClass   = $variantSlug !== '' ? ' myron-site__footer--' . $variantSlug : '';

        $html = ['<footer class="myron-site__footer myron-site__footer--preview' . $this->escape($variantClass) . '" aria-label="Footer preview" data-footer-variant="' . $this->escape($variant) . '">'];
        $html[] = '<div class="myron-footer__zones">';

        foreach ($activeZones as $zoneId) {
            $isActive = !isset($zoneVisibility[$zoneId]) || $zoneVisibility[$zoneId] !== false;
            $zoneContent = is_array($allZoneContent[$zoneId] ?? null) ? $allZoneContent[$zoneId] : [];
            $html[] = $this->renderFooterZone(
                $zoneId,
                $zoneContent,
                $basePath,
                [],
                ['preview' => true, 'inactive' => !$isActive]
            );
        }

        if ($activeZones === []) {
            $html[] = '<span class="myron-text myron-text--muted">Select a footer variant to preview its zones.</span>';
        }

        $html[] = '</div>';
        $html[] = '</footer>';

        return implode("\n", $html);
    }

    /**
     * APO-181 Card 1 — Resolve the footer variant for a page render with full
     * inherit-flag awareness.
     *
     * Resolution chain (in priority order):
     *   1. Per-template chrome assignment (template_chrome_assignments row) — operator
     *      pinned this template to a specific variant via Templates Manager. Wins.
     *   2. chrome.footer.inherit === "global" — the template explicitly says "follow the
     *      live default." Return the live global default. The cached `variant` string at
     *      this branch is intentionally ignored (it's a baked-in cache from authoring time
     *      that should not pin the page to a stale value).
     *   3. chrome.footer.variant non-empty (no inherit hint, or inherit !== "global") —
     *      explicit per-template override. Honor the variant string.
     *   4. Fallback — live global default.
     *
     * @param array<string, mixed> $chromeFooter  the chrome.footer object from the
     *     page schema (or an explicit synthetic wrapper from a legacy footerSection
     *     embed). Reads `inherit` and `variant` keys.
     */
    private function resolveFooterVariant(array $chromeFooter, string $templateId = ''): string
    {
        $inherit    = trim((string) ($chromeFooter['inherit'] ?? $chromeFooter['source'] ?? ''));
        $seedVariant = trim((string) ($chromeFooter['variant'] ?? ''));

        try {
            // (1) Per-template chrome assignment wins.
            $assignment = trim($templateId) !== '' ? myronTemplateChromeAssignmentRepository()->getForTemplate($templateId) : null;
            $assignedVariant = is_array($assignment) ? trim((string) ($assignment['footer_variant_id'] ?? '')) : '';
            if ($assignedVariant !== '') {
                return $assignedVariant;
            }

            // (2) inherit:"global" routes to live global default.
            if ($inherit === 'global') {
                $default = myronFooterDesignRepository()->getDefault();
                $defaultVariant = (string) ($default['variant_id'] ?? '');
                if ($defaultVariant !== '') {
                    return $defaultVariant;
                }
                // Fall through to seed variant if the default is somehow unset.
            }

            // (3) Explicit per-template variant override.
            if ($seedVariant !== '') {
                return $seedVariant;
            }

            // (4) Final fallback — live global default.
            $default = myronFooterDesignRepository()->getDefault();
            return (string) ($default['variant_id'] ?? 'footer.standard');
        } catch (Throwable) {
            return $seedVariant !== '' ? $seedVariant : 'footer.standard';
        }
    }

    /**
     * @return array<string, bool>
     */
    private function loadFooterZoneVisibility(string $variant = ''): array
    {
        try {
            $row = myronFooterDesignRepository()->getByVariantId($variant);
            $visibility = $row['zone_visibility'] ?? [];
            return is_array($visibility) ? $visibility : [];
        } catch (Throwable) {
            return [];
        }
    }

    /**
     * @return array<string, array<string, mixed>>
     */
    private function loadAllFooterZoneContent(string $variant = ''): array
    {
        try {
            $row = myronFooterDesignRepository()->getByVariantId($variant);
            $content = $row['zone_content'] ?? [];
            $content = is_array($content) ? $content : [];
            if (!$this->footerContentMapHasContent($content) && function_exists('myronFooterContentSeedService')) {
                $primaryBundleId = '';
                if (function_exists('myronBundleActivationRepository')) {
                    $primaryBundleId = trim((string) (myronBundleActivationRepository()->getPrimaryBundleId() ?? ''));
                }
                $seedContent = myronFooterContentSeedService()->seedContentForSiteTypeAndVariant($primaryBundleId, $variant);
                if ($seedContent !== []) {
                    $content = $seedContent;
                }
            }
            return $this->interpolateFooterZoneContent($content);
        } catch (Throwable) {
            return [];
        }
    }

    /**
     * @param array<string, array<string, mixed>> $contentByZone
     */
    private function footerContentMapHasContent(array $contentByZone): bool
    {
        foreach ($contentByZone as $zoneContent) {
            if (is_array($zoneContent) && $this->isZoneContentPopulated($zoneContent)) {
                return true;
            }
        }

        return false;
    }

    /**
     * APO-179 — render-time interpolation for footer zone content.
     *
     * Resolves the locked seed-time tokens at render time so that:
     *   - {{site_settings.site_title}} reflects the current site title (auto-propagates)
     *   - {{year}} reflects the current year (auto-rolls over)
     * Any other braces or operator-edited literal values pass through unchanged.
     * Non-string values, including numbers and arrays' non-string items, are preserved
     * structurally; only string fields and string fields nested inside repeater item
     * arrays are interpolated.
     *
     * @param array<string, array<string, mixed>> $contentByZone
     * @return array<string, array<string, mixed>>
     */
    private function interpolateFooterZoneContent(array $contentByZone): array
    {
        $vars = $this->footerInterpolationVariables();
        if ($vars === []) {
            return $contentByZone;
        }

        $interpolate = function ($value) use ($vars, &$interpolate) {
            if (is_string($value)) {
                if (!str_contains($value, '{{')) {
                    return $value;
                }
                $rendered = $value;
                foreach ($vars as $token => $resolved) {
                    if (str_contains($rendered, $token)) {
                        $rendered = str_replace($token, $resolved, $rendered);
                    }
                }
                return $rendered;
            }
            if (is_array($value)) {
                $out = [];
                foreach ($value as $k => $v) {
                    $out[$k] = $interpolate($v);
                }
                return $out;
            }
            return $value;
        };

        $output = [];
        foreach ($contentByZone as $zoneId => $zoneContent) {
            if (!is_array($zoneContent)) {
                $output[$zoneId] = $zoneContent;
                continue;
            }
            $output[$zoneId] = $interpolate($zoneContent);
        }
        return $output;
    }

    /**
     * @return array<string, string>
     */
    private function footerInterpolationVariables(): array
    {
        try {
            $siteTitle = function_exists('myronSiteTitle') ? (string) myronSiteTitle() : 'MyronCMS';
        } catch (Throwable) {
            $siteTitle = 'MyronCMS';
        }
        return [
            '{{site_settings.site_title}}' => $siteTitle,
            '{{year}}' => (string) (int) date('Y'),
        ];
    }

    private function sectionTitle(string $componentId): string
    {
        $titles = [
            'hero-with-cta' => 'Start Here',
            'banner' => 'Trending',
            'hero-simple' => 'Overview',
            'feature-grid' => 'Highlights',
            'portfolio-grid' => 'Selected Work',
            'product-grid' => 'Products',
            'product-filters' => 'Filters',
            'product-sort-control' => 'Sort',
            'product-gallery' => 'Product Gallery',
            'product-details' => 'Product Details',
            'variant-selector' => 'Options',
            'quantity-stepper' => 'Quantity',
            'rating-summary' => 'Reviews',
            'cart-table' => 'Cart Items',
            'order-summary' => 'Order Summary',
            'checkout-stepper' => 'Checkout Steps',
            'checkout-address-form' => 'Delivery Details',
            'shipping-method-selector' => 'Delivery Method',
            'payment-form' => 'Payment',
            'checkout-review' => 'Review',
            'datepicker' => 'Date',
            'timepicker' => 'Time',
            'select' => 'Party Size',
            'textarea' => 'Requests',
            'form-field' => 'Booking Details',
            'services-grid' => 'Services',
            'section-band' => 'About This Work',
            'stats-tile' => 'Proof Points',
            'testimonial-grid' => 'What People Say',
            'team-grid' => 'Team',
            'course-catalog' => 'Courses',
            'pricing-table' => 'Enrollment Options',
            'logo' => 'Trusted By',
            'blog-teaser' => 'Latest Insights',
            'cta-band' => 'Next Step',
            'cms-embed' => 'Embedded Content',
            'cms-featured-media' => 'Featured Media',
            'cms-content-title' => 'Project',
            'contact-form-with-info' => 'Contact Details',
            'legal-doc-toc' => 'Document Sections',
            'cms-content-body' => 'Details',
            'kv-row' => 'Project Details',
            'pagination' => 'More Work',
            'badge' => 'Status',
            'chip' => 'Topics',
            'faq-list' => 'Questions',
            'lead-magnet-card' => 'Lead Magnet',
            'featured-offer-card' => 'Featured Offer',
            'button' => 'Continue',
            'user-identity' => 'Author',
            'switch' => 'Billing Period',
            'tier-comparison-matrix' => 'Compare Plans',
            'sidebar-nav' => 'Account Navigation',
            'profile-panel' => 'Profile',
            'settings-layout' => 'Account Settings',
        ];

        return $titles[$componentId] ?? ucwords(str_replace('-', ' ', $componentId));
    }

    /**
     * @param array<string, mixed> $content
     */
    private function sectionBody(string $componentId, int $index, array $content, string $notes, bool $previewMode = false): string
    {
        if ($componentId === 'cms-featured-media') {
            return '';
        }

        if ($componentId === 'cms-content-body' || $index === 0) {
            $body = trim((string) ($content['body'] ?? ''));
            if ($body !== '') {
                return $body;
            }
        }

        if ($previewMode && $notes !== '') {
            return $notes;
        }

        // APO-061 R6: in preview mode, surface explicit [unset] markers for slots
        // that have neither real content nor a notes field — so previews don't
        // pretend to be content. Live pages keep the canonical placeholder.
        if ($previewMode) {
            return '[unset]';
        }

        $source = trim((string) ($content['intro'] ?? ''));
        if ($source !== '') {
            return $source;
        }

        return 'This governed section is rendered from the active runtime template definition.';
    }

    private function renderPortfolioGridSection(string $classes, string $variant, string $title, string $body, string $basePath, string $sourceBundleId, array $content = [], bool $liveContentEnabled = false): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'standard');
        $projectHref = $sourceBundleId === 'site-type.agy' ? '/work/project' : '/portfolio/project';
        $projects = $liveContentEnabled ? $this->liveProjectCards($sourceBundleId, 6) : [];
        if ($projects === []) {
            $projects = array_values(array_filter((array) ($content['projects'] ?? []), static fn (mixed $item): bool => is_array($item)));
        }
        if ($projects === []) {
            $projects = [
                ['title' => 'First Project', 'summary' => 'Add your project details in Content.', 'href' => $projectHref],
                ['title' => 'Second Project', 'summary' => 'Add your project details in Content.', 'href' => $projectHref],
                ['title' => 'Third Project', 'summary' => 'Add your project details in Content.', 'href' => $projectHref],
            ];
        }
        $copy = $this->publicSectionBody($body, 'Selected work will appear here once approved project details are published.');
        $html = [];
        $html[] = '<section class="' . $this->escape('myron-portfolio-grid myron-portfolio-grid--' . $normalizedVariant . ' myron-public-component myron-public-component--contained myron-public-component--portfolio-grid') . '" data-component-id="portfolio-grid">';
        $html[] = '<div class="myron-portfolio-grid__header">';
        $html[] = '<h2 class="myron-heading myron-portfolio-grid__heading">' . $this->escape($title) . '</h2>';
        $html[] = $this->paragraphs($copy);
        $html[] = '</div>';
        $html[] = '<ul class="myron-portfolio-grid__items" aria-label="Portfolio projects">';

        foreach ($projects as $project) {
            $projectTitle = trim((string) ($project['title'] ?? '')) ?: 'Untitled Project';
            $projectSummary = trim((string) ($project['summary'] ?? '')) ?: 'Add your project details in Content.';
            $projectItemHref = trim((string) ($project['href'] ?? '')) ?: $projectHref;
            $html[] = '<li class="myron-portfolio-grid__item">';
            $html[] = '<a class="myron-portfolio-grid__link" href="' . $this->escape($this->contentHref($basePath, $projectItemHref)) . '">';
            $html[] = '<span class="myron-portfolio-grid__media">' . $this->imageSlotHtml($project, 'myron-portfolio-grid__image', 'mediaFileId', 'mediaAlt') . '</span>';
            $html[] = '<span class="myron-portfolio-grid__caption">';
            $html[] = '<span class="myron-portfolio-grid__title">' . $this->escape($projectTitle) . '</span>';
            $html[] = '<span class="myron-text myron-text--muted">' . $this->escape($projectSummary) . '</span>';
            $html[] = '</span>';
            $html[] = '</a>';
            $html[] = '</li>';
        }

        $html[] = '</ul>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderTeamGridSection(string $classes, string $variant, string $title, string $body, array $content = []): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'standard');
        $copy = $this->publicSectionBody($body, 'Add real team members when the organization is ready to publish them.');
        $html = [];
        $html[] = '<section class="' . $this->escape('myron-team-grid myron-team-grid--' . $normalizedVariant . ' myron-public-component myron-public-component--contained myron-public-component--team-grid') . '" data-component-id="team-grid">';
        $html[] = '<div class="myron-team-grid__header">';
        $html[] = '<h2 class="myron-heading myron-team-grid__heading">' . $this->escape($title) . '</h2>';
        $html[] = $this->paragraphs($copy);
        $html[] = '</div>';
        $html[] = '<ul class="myron-team-grid__members" aria-label="Team members">';

        foreach (['Strategy Lead', 'Creative Lead', 'Delivery Lead'] as $index => $memberTitle) {
            $fieldIndex = $index + 1;
            $resolvedName = trim((string) ($content['person' . $fieldIndex . 'Name'] ?? '')) ?: $memberTitle;
            $resolvedTitle = trim((string) ($content['person' . $fieldIndex . 'Title'] ?? '')) ?: 'Add team member details in Content.';
            $html[] = '<li class="myron-team-grid__member">';
            $photo = $this->contentFile($content, 'person' . $fieldIndex . 'FileId');
            if (is_array($photo)) {
                $photoAlt = trim((string) ($content['person' . $fieldIndex . 'Alt'] ?? '')) ?: $resolvedName;
                $html[] = '<img class="myron-team-grid__avatar" src="' . $this->escape((string) ($photo['file_url'] ?? '')) . '" alt="' . $this->escape($photoAlt) . '">';
            } else {
                $html[] = '<span class="myron-team-grid__avatar" aria-hidden="true"></span>';
            }
            $html[] = '<span class="myron-team-grid__body">';
            $html[] = '<span class="myron-team-grid__name">' . $this->escape($resolvedName) . '</span>';
            $html[] = '<span class="myron-text myron-text--muted">' . $this->escape($resolvedTitle) . '</span>';
            $html[] = '</span>';
            $html[] = '</li>';
        }

        $html[] = '</ul>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderCourseCatalogSection(string $classes, string $variant, string $title, string $body, string $basePath, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'featured-shelf');
        $copy = $this->publicSectionBody(
            $body,
            $normalizedVariant === 'catalog-index'
                ? 'Browse available courses by topic, format, and readiness.'
                : 'Featured courses will appear here once learning content is published.'
        );
        $courses = [
            [
                'title' => 'Design System Foundations',
                'category' => 'Foundations',
                'instructor' => 'Instructor team',
                'rating' => '4.8',
                'duration' => '6 lessons',
                'price' => 'Free preview',
                'href' => '/courses/course',
            ],
            [
                'title' => 'Applied Content Workflow',
                'category' => 'Content',
                'instructor' => 'Education faculty',
                'rating' => '4.7',
                'duration' => '8 lessons',
                'price' => '$49',
                'href' => '/courses/course',
            ],
            [
                'title' => 'Launch Readiness Studio',
                'category' => 'Publishing',
                'instructor' => 'Course staff',
                'rating' => '4.9',
                'duration' => '5 lessons',
                'price' => '$79',
                'href' => '/courses/course',
            ],
        ];
        if ($normalizedVariant === 'catalog-index') {
            $courses[] = [
                'title' => 'Accessible Page Patterns',
                'category' => 'Accessibility',
                'instructor' => 'Program team',
                'rating' => '4.8',
                'duration' => '7 lessons',
                'price' => '$59',
                'href' => '/courses/course',
            ];
        }

        $html = [];
        $html[] = '<section class="' . $this->escape($classes . ' myron-public-component myron-public-component--contained myron-public-component--course-catalog myron-course-catalog myron-course-catalog--' . $normalizedVariant) . '" data-component-id="course-catalog" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-course-catalog__header">';
        $html[] = '<h2 class="myron-heading myron-definition-section__title myron-course-catalog__heading">' . $this->escape($title) . '</h2>';
        if ($copy !== '') {
            $html[] = '<div class="myron-definition-section__content">' . $this->paragraphs($copy) . '</div>';
        }
        $html[] = '</div>';
        if ($normalizedVariant === 'catalog-index') {
            $html[] = '<div class="myron-course-catalog__toolbar">';
            $html[] = '<span class="myron-text myron-text--muted">' . count($courses) . ' courses available</span>';
            $html[] = '<a class="' . $this->escape($this->buttonClasses('neutral', 'outline', 'sm')) . '" href="' . $this->escape($this->routeHref($basePath, '/courses')) . '">Browse all</a>';
            $html[] = '</div>';
        }
        $html[] = '<ul class="myron-course-catalog__courses" aria-label="Courses">';

        foreach ($courses as $course) {
            $html[] = '<li class="myron-course-catalog__course">';
            $html[] = '<a class="myron-course-catalog__media" href="' . $this->escape($this->routeHref($basePath, $course['href'])) . '" aria-label="' . $this->escape('View ' . $course['title']) . '">';
            $html[] = '<span class="myron-course-catalog__image" aria-hidden="true"></span>';
            $html[] = '</a>';
            $html[] = '<div class="myron-course-catalog__body">';
            $html[] = '<span class="myron-chip">' . $this->escape($course['category']) . '</span>';
            $html[] = '<h3 class="myron-heading myron-course-catalog__title">' . $this->escape($course['title']) . '</h3>';
            $html[] = '<p class="myron-paragraph myron-course-catalog__summary">A structured, self-paced course ready for enrollment content.</p>';
            $html[] = '<div class="myron-course-catalog__meta">';
            $html[] = '<span>' . $this->escape($course['instructor']) . '</span>';
            $html[] = '<span class="myron-rating-summary" aria-label="' . $this->escape('Rating ' . $course['rating'] . ' out of 5') . '"><span class="myron-rating-summary__stars" aria-hidden="true">*****</span><span class="myron-rating-summary__count">' . $this->escape($course['rating']) . '</span></span>';
            $html[] = '<span>' . $this->escape($course['duration']) . '</span>';
            $html[] = '</div>';
            $html[] = '<div class="myron-course-catalog__actions">';
            $html[] = '<span class="myron-price-display"><span class="myron-price-display__current">' . $this->escape($course['price']) . '</span></span>';
            $html[] = '<a class="' . $this->escape($this->buttonClasses('primary', 'solid', 'sm')) . '" href="' . $this->escape($this->routeHref($basePath, $course['href'])) . '">Enroll</a>';
            $html[] = '</div>';
            $html[] = '</div>';
            $html[] = '</li>';
        }

        $html[] = '</ul>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderPricingTableSection(string $classes, string $variant, string $title, string $body, string $basePath, string $sourceBundleId, string $sourceTemplateId, string $intent): string
    {
        $isStickyEnrollment = $sourceBundleId === 'site-type.edu' && str_contains($intent, 'sticky-enrollment-card');
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : ($isStickyEnrollment ? 'sticky-enrollment-card' : 'standard'));
        $copy = $this->publicSectionBody(
            $body,
            $sourceBundleId === 'site-type.edu'
                ? 'Choose the course access path that fits the learner or team.'
                : 'Choose the plan that fits the current workflow.'
        );
        $tiers = $sourceBundleId === 'site-type.edu'
            ? [
                ['name' => 'Single Course', 'price' => '$49', 'detail' => 'One course, lifetime lesson access.', 'cta' => 'Enroll', 'href' => '/account'],
                ['name' => 'Course Library', 'price' => '$149', 'detail' => 'All current courses plus new releases.', 'cta' => 'Start Learning', 'href' => '/account'],
                ['name' => 'Team Learning', 'price' => 'Contact', 'detail' => 'Shared access for organization training.', 'cta' => 'Contact', 'href' => '/contact'],
            ]
            : [
                ['name' => 'Starter', 'price' => '$29/mo', 'detail' => 'Core tools for a focused launch.', 'cta' => 'Start Free Trial', 'href' => '/signup'],
                ['name' => 'Pro', 'price' => '$79/mo', 'detail' => 'More workflows and publishing support.', 'cta' => 'Start Free Trial', 'href' => '/signup'],
                ['name' => 'Team', 'price' => '$199/mo', 'detail' => 'Shared operating space for teams.', 'cta' => 'Contact Sales', 'href' => '/contact'],
            ];

        $html = [];
        $html[] = '<section class="' . $this->escape('myron-public-component myron-public-component--contained myron-public-component--pricing-table myron-pricing-table myron-pricing-table--' . $normalizedVariant) . '" data-component-id="pricing-table" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '"' . ($isStickyEnrollment ? ' data-myron-sticky-enrollment' : '') . '>';
        $html[] = '<div class="myron-pricing-table__inner">';
        $html[] = '<h2 class="myron-heading myron-pricing-table__title">' . $this->escape($isStickyEnrollment ? 'Enroll in this course' : $title) . '</h2>';
        if ($copy !== '') {
            $html[] = '<div class="myron-definition-section__content">' . $this->paragraphs($copy) . '</div>';
        }
        $html[] = '<div class="myron-pricing-table__tiers">';
        foreach ($tiers as $tier) {
            $html[] = '<article class="' . $this->escape($this->cardClasses('default', 'thin', 'md', 'myron-pricing-table__tier')) . '">';
            $html[] = '<h3 class="myron-heading">' . $this->escape($tier['name']) . '</h3>';
            $html[] = '<p class="myron-price-display"><span class="myron-price-display__current">' . $this->escape($tier['price']) . '</span></p>';
            $html[] = '<p class="myron-paragraph myron-paragraph--muted">' . $this->escape($tier['detail']) . '</p>';
            $html[] = '<a class="' . $this->escape($this->buttonClasses('primary', 'solid', 'sm')) . '" href="' . $this->escape($this->routeHref($basePath, $tier['href'])) . '">' . $this->escape($tier['cta']) . '</a>';
            $html[] = '</article>';
        }
        $html[] = '</div>';
        if ($isStickyEnrollment) {
            $html[] = '<p class="myron-paragraph myron-paragraph--muted">Enrollment actions are ready for account or checkout integration.</p>';
        }
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderBannerSection(string $classes, string $variant, string $title, string $body, string $sourceTemplateId, string $sourceBundleId, string $intent): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'standard');
        $copyFallback = $sourceTemplateId === 'template.home.news.v1' || $sourceBundleId === 'site-type.news'
            ? 'Top headlines and timely updates are ready for editorial curation.'
            : 'Featured products and timely updates are ready for editorial curation.';
        $copy = $this->publicSectionBody($body, $copyFallback);
        $html = [];
        $html[] = '<section class="' . $this->escape($classes . ' myron-public-component myron-public-component--contained myron-public-component--banner myron-banner myron-banner--tone-info myron-banner--' . $normalizedVariant) . '" data-component-id="banner" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-banner__content">';
        $html[] = '<strong>' . $this->escape($title) . '</strong>';
        $html[] = '<span>' . $this->escape($copy) . '</span>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderCmsContentTitleSection(string $variant, string $title, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = $variant !== '' ? myronNormalizeSlug($variant) : 'default';
        $resolvedTitle = $title !== '' ? $title : 'Untitled';
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--cms-content-title myron-cms-content-title-section myron-cms-content-title-section--' . $this->escape($normalizedVariant) . '" data-component-id="cms-content-title" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<h1 class="myron-heading myron-cms-content-title">' . $this->escape($resolvedTitle) . '</h1>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderPostTitleMetaSection(string $variant, string $title, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = $variant !== '' ? myronNormalizeSlug($variant) : 'default';
        $resolvedTitle = $title !== '' ? $title : 'Article';
        $author = $this->activePostAuthor();
        $authorName = trim((string) ($author['authorName'] ?? ''));
        $authorBio = trim((string) ($author['bio'] ?? ''));
        $categories = $this->activePostCategories();
        $dateLabel = $this->publishedDateLabel((string) ($this->activePublishedPage['published_at'] ?? ''));
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--post-header myron-post-header myron-post-header--' . $this->escape($normalizedVariant) . '" data-component-id="cms-content-title" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<h1 class="myron-heading myron-cms-content-title myron-post-header__title">' . $this->escape($resolvedTitle) . '</h1>';
        $html[] = '<div class="myron-post-header__meta">';
        if ($authorName !== '') {
            $html[] = '<div class="myron-user-identity myron-user-identity--inline myron-user-identity--sm myron-post-header__author" data-component-id="user-identity">';
            $html[] = '<div class="myron-avatar myron-avatar--sm myron-avatar--circle" aria-hidden="true"><span class="myron-avatar__initials">' . $this->escape($this->initialsForName($authorName)) . '</span></div>';
            $html[] = '<div class="myron-user-identity__info"><span class="myron-user-identity__name">' . $this->escape($authorName) . '</span><span class="myron-text myron-text--muted">' . $this->escape($authorBio !== '' ? $authorBio : $dateLabel) . '</span></div>';
            $html[] = '</div>';
        }
        if ($dateLabel !== '') {
            $html[] = '<p class="myron-post-header__date">' . $this->escape($dateLabel) . '</p>';
        }
        if ($categories !== []) {
            $html[] = '<ul class="myron-chip-row__items myron-post-header__topics" role="list" data-component-id="chip">';
            foreach ($categories as $category) {
                $label = trim((string) ($category['title'] ?? ''));
                $slug = trim((string) ($category['slug'] ?? ''));
                if ($label === '') {
                    continue;
                }
                $href = $slug !== '' ? $this->categoryArchiveHref($slug) : '';
                $chip = '<span class="myron-chip">' . $this->escape($label) . '</span>';
                $html[] = '<li class="myron-chip-row__item">' . ($href !== '' ? '<a class="myron-chip myron-chip--link" href="' . $this->escape($href) . '">' . $this->escape($label) . '</a>' : $chip) . '</li>';
            }
            $html[] = '</ul>';
        }
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderCmsContentBodySection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = $variant !== '' ? myronNormalizeSlug($variant) : 'default';
        $copy = $this->publicSectionBody($body, 'Published article body renders here through governed text primitives.');
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--cms-content-body myron-cms-content-body-section myron-cms-content-body-section--' . $this->escape($normalizedVariant) . '" data-component-id="cms-content-body" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-cms-content-body">' . $this->paragraphs($copy) . '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderCmsFeaturedMediaSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent, array $content = []): string
    {
        $normalizedVariant = $variant !== '' ? myronNormalizeSlug($variant) : 'default';
        $caption = $this->publicSectionBody($body, '');
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--cms-featured-media myron-cms-featured-media-section myron-cms-featured-media-section--' . $this->escape($normalizedVariant) . '" data-component-id="cms-featured-media" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<figure class="myron-figure myron-cms-featured-media myron-cms-featured-media--aspect-auto">';
        $html[] = $this->imageSlotHtml($content, 'myron-image myron-cms-featured-media__fill');
        if ($caption !== '') {
            $html[] = '<figcaption class="myron-text myron-text--muted">' . $this->escape($caption) . '</figcaption>';
        }
        $html[] = '</figure>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderCmsEmbedSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = $variant !== '' ? myronNormalizeSlug($variant) : 'default';
        $headline = $title !== '' ? $title : 'Embedded content';
        $copy = $this->publicSectionBody($body, 'Third-party output is framed by governed card and text primitives.');
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--cms-embed myron-cms-embed-section myron-cms-embed-section--' . $this->escape($normalizedVariant) . '" data-component-id="cms-embed" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="' . $this->escape($this->cardClasses('default', 'thin', 'md', 'myron-cms-embed')) . '">';
        $html[] = '<h3 class="myron-heading">' . $this->escape($headline) . '</h3>';
        $html[] = '<div class="myron-cms-embed__body">' . $this->paragraphs($copy) . '</div>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderGenericFormControlSection(string $componentId, string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $label = $title !== '' ? $title : ucwords(str_replace('-', ' ', $componentId));
        $hint = $this->publicSectionBody($body, '');
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--' . $this->escape($componentId) . '" data-component-id="' . $this->escape($componentId) . '" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<label class="mc-component-preview__field myron-form-field"><span class="myron-text">' . $this->escape($label) . '</span>';
        switch ($componentId) {
            case 'datepicker':
                $html[] = '<input class="myron-input" type="date">';
                break;
            case 'timepicker':
                $html[] = '<input class="myron-input" type="time">';
                break;
            case 'select':
                $html[] = '<select class="myron-select"><option>Select an option</option><option>Option two</option><option>Option three</option></select>';
                break;
            case 'textarea':
                $html[] = '<textarea class="myron-textarea" rows="3" placeholder="Add your message..."></textarea>';
                break;
            case 'form-field':
            default:
                $html[] = '<input class="myron-input" type="text" placeholder="' . $this->escape($label) . '">';
                break;
        }
        if (trim($hint) !== '') {
            $html[] = '<span class="myron-text myron-text--muted">' . $this->escape($hint) . '</span>';
        }
        $html[] = '</label>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderContactFormWithInfoSection(string $variant, string $title, string $body, string $basePath, string $sourceTemplateId, string $intent): string
    {
        $headline = $title !== '' ? $title : 'Contact us';
        $copy = $this->publicSectionBody($body, 'Send us a message and we will respond shortly.');
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'default');
        $html = [];
        $html[] = '<section class="' . $this->escape('myron-contact-form-with-info myron-contact-form-with-info--' . $normalizedVariant . ' myron-public-component myron-public-component--contained myron-public-component--contact-form-with-info') . '" data-component-id="contact-form-with-info" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-public-section-header myron-contact-form-with-info__header"><h2 class="myron-heading">' . $this->escape($headline) . '</h2><p class="myron-paragraph">' . $this->escape($copy) . '</p></div>';
        $html[] = '<div class="myron-contact-form-with-info__layout">';
        $html[] = '<form class="myron-contact-form-with-info__form" method="post" action="' . $this->escape($this->routeHref($basePath, '/contact')) . '">';
        $html[] = $this->renderPassivePublicFormProtection('contact-form');
        $html[] = '<div class="myron-contact-form-with-info__fields">';
        $html[] = '<label class="myron-form-field"><span class="myron-text">Name</span><input class="myron-input" type="text" name="name" autocomplete="name"></label>';
        $html[] = '<label class="myron-form-field"><span class="myron-text">Email</span><input class="myron-input" type="email" name="email" autocomplete="email"></label>';
        $html[] = '<label class="myron-form-field"><span class="myron-text">Message</span><textarea class="myron-textarea" name="message" rows="4"></textarea></label>';
        $html[] = '</div>';
        $html[] = '<button class="' . $this->escape($this->buttonClasses()) . '" type="submit">Send message</button>';
        $html[] = '</form>';
        $html[] = '<aside class="myron-contact-form-with-info__info">';
        $html[] = '<h3 class="myron-heading">Other ways to reach us</h3>';
        $html[] = '<dl class="myron-contact-form-with-info__items">';
        $html[] = '<div class="myron-kv-row myron-kv-row--md myron-contact-form-with-info__item"><dt class="myron-kv-row__key">Email</dt><dd class="myron-kv-row__value">hello@example.com</dd></div>';
        $html[] = '<div class="myron-kv-row myron-kv-row--md myron-contact-form-with-info__item"><dt class="myron-kv-row__key">Phone</dt><dd class="myron-kv-row__value">(555) 555-0100</dd></div>';
        $html[] = '<div class="myron-kv-row myron-kv-row--md myron-contact-form-with-info__item"><dt class="myron-kv-row__key">Hours</dt><dd class="myron-kv-row__value">Mon-Fri, 9am-5pm</dd></div>';
        $html[] = '</dl>';
        $html[] = '</aside>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderAlertSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $tone = in_array($variant, ['tone-success', 'tone-warning', 'tone-danger', 'tone-info', 'success', 'warning', 'danger', 'info'], true)
            ? 'myron-alert--' . myronNormalizeSlug(str_starts_with($variant, 'tone-') ? $variant : 'tone-' . $variant)
            : 'myron-alert--tone-info';
        $headline = $title !== '' ? $title : 'Heads up';
        $copy = $this->publicSectionBody($body, 'Add a short message to highlight an important update.');
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--alert" data-component-id="alert" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-alert ' . $this->escape($tone) . '" role="alert">';
        $html[] = '<span class="myron-alert__icon" aria-hidden="true">i</span>';
        $html[] = '<div class="myron-alert__body"><p class="myron-text myron-alert__title">' . $this->escape($headline) . '</p><p class="myron-paragraph">' . $this->escape($copy) . '</p></div>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderAvatarSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $size = in_array($variant, ['xs', 'sm', 'md', 'lg', 'xl'], true) ? 'myron-avatar--' . $variant : 'myron-avatar--md';
        $name = $title !== '' ? $title : 'Member name';
        $copy = $this->publicSectionBody($body, '');
        $initials = strtoupper(substr(preg_replace('~[^A-Za-z]~', '', $name) ?: 'MC', 0, 2));
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--avatar" data-component-id="avatar" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-avatar ' . $this->escape($size) . ' myron-avatar--circle" aria-label="' . $this->escape($name) . '"><span class="myron-avatar__initials">' . $this->escape($initials) . '</span></div>';
        if (trim($copy) !== '') {
            $html[] = '<p class="myron-paragraph myron-paragraph--muted">' . $this->escape($copy) . '</p>';
        }
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderBadgeSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $label = $title !== '' ? $title : 'Status';
        $copy = $this->publicSectionBody($body, '');
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--badge" data-component-id="badge" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<span class="myron-badge">' . $this->escape($label) . '</span>';
        if (trim($copy) !== '') {
            $html[] = '<p class="myron-paragraph">' . $this->escape($copy) . '</p>';
        }
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderButtonSection(string $variant, string $title, string $body, string $basePath, string $sourceTemplateId, string $intent): string
    {
        $label = $title !== '' ? $title : 'Continue';
        $href = '/';
        if (str_starts_with($sourceTemplateId, 'template.funnel.')) {
            $cta = $this->funnelCta($this->funnelStepKey($sourceTemplateId), 'button');
            $label = $cta['label'];
            $href = $cta['href'];
        }
        $buttonIntent = in_array($variant, ['primary', 'neutral', 'danger'], true) ? $variant : 'primary';
        $copy = $this->publicSectionBody($body, '');
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--button" data-component-id="button" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        if (trim($copy) !== '') {
            $html[] = '<p class="myron-paragraph">' . $this->escape($copy) . '</p>';
        }
        $html[] = '<a class="' . $this->escape($this->buttonClasses($buttonIntent)) . '" href="' . $this->escape($this->routeHref($basePath, $href)) . '">' . $this->escape($label) . '</a>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderCardSection(string $variant, string $title, string $body, string $basePath, string $sourceTemplateId, string $intent): string
    {
        $headline = $title !== '' ? $title : 'Card title';
        $copy = $this->publicSectionBody($body, 'Card body content uses governed paragraph primitives.');
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--card" data-component-id="card" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<article class="' . $this->escape($this->cardClasses()) . '">';
        $html[] = '<header class="myron-card__header"><h3 class="myron-heading">' . $this->escape($headline) . '</h3></header>';
        $html[] = '<div class="myron-card__body"><p class="myron-paragraph">' . $this->escape($copy) . '</p></div>';
        $html[] = '<footer class="myron-card__footer"><a class="' . $this->escape($this->buttonClasses('neutral', 'outline', 'sm')) . '" href="' . $this->escape($this->routeHref($basePath, '/')) . '">View details</a></footer>';
        $html[] = '</article>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderCarouselSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'default');
        $headline = $title !== '' ? $title : 'Featured Collection';
        $copy = $this->publicSectionBody($body, 'Feature a seasonal collection, campaign, or hero product story.');
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--carousel myron-carousel myron-carousel--' . $this->escape($normalizedVariant) . '" data-component-id="carousel" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-public-section-header"><h2 class="myron-heading">' . $this->escape($headline) . '</h2>';
        if (trim($copy) !== '') {
            $html[] = '<p class="myron-paragraph">' . $this->escape($copy) . '</p>';
        }
        $html[] = '</div>';
        $html[] = '<ul class="myron-carousel__items" role="list">';
        foreach (['Slide one', 'Slide two', 'Slide three'] as $label) {
            $html[] = '<li class="myron-carousel__item">';
            $html[] = '<div class="myron-image mc-component-preview__media-placeholder" aria-hidden="true"></div>';
            $html[] = '<p class="myron-text myron-text--muted">' . $this->escape($label) . '</p>';
            $html[] = '</li>';
        }
        $html[] = '</ul>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderChoiceSection(string $componentId, string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $controlClass = $componentId === 'radio' ? 'myron-radio' : 'myron-checkbox';
        $inputClass = $controlClass . '__input';
        $labelClass = $controlClass . '__label';
        $headline = $title !== '' ? $title : ucfirst($componentId);
        $copy = $this->publicSectionBody($body, '');
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--' . $this->escape($componentId) . '" data-component-id="' . $this->escape($componentId) . '" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<fieldset class="myron-fieldset myron-public-choice-group">';
        $html[] = '<legend class="myron-heading">' . $this->escape($headline) . '</legend>';
        if (trim($copy) !== '') {
            $html[] = '<p class="myron-paragraph">' . $this->escape($copy) . '</p>';
        }
        $html[] = '<div class="myron-public-choice-group__options">';
        foreach (['Option one', 'Option two', 'Option three'] as $i => $optionLabel) {
            $name = $componentId === 'radio' ? ' name="preview-radio-group"' : '';
            $checked = $componentId === 'radio' && $i === 0 ? ' checked' : '';
            $html[] = '<label class="' . $this->escape($controlClass) . '"><input class="' . $this->escape($inputClass) . '" type="' . $componentId . '"' . $name . $checked . '><span class="' . $this->escape($labelClass) . '">' . $this->escape($optionLabel) . '</span></label>';
        }
        $html[] = '</div>';
        $html[] = '</fieldset>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderCheckoutConfirmationSection(string $variant, string $title, string $body, string $basePath, string $sourceTemplateId, string $intent): string
    {
        $headline = $title !== '' ? $title : 'Order confirmed';
        $copy = $this->publicSectionBody($body, 'A confirmation summary will appear here once an order is placed.');
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--checkout-confirmation" data-component-id="checkout-confirmation" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<article class="' . $this->escape($this->cardClasses()) . '">';
        $html[] = '<h2 class="myron-heading">' . $this->escape($headline) . '</h2>';
        $html[] = '<p class="myron-paragraph">' . $this->escape($copy) . '</p>';
        $html[] = '<dl class="myron-kv-row__items">';
        foreach ([['Order', '#TEST-1001'], ['Total', '$0.00'], ['Status', 'Confirmed']] as $row) {
            $html[] = '<div class="myron-kv-row__item"><dt class="myron-kv-row__key">' . $this->escape($row[0]) . '</dt><dd class="myron-kv-row__value">' . $this->escape($row[1]) . '</dd></div>';
        }
        $html[] = '</dl>';
        $html[] = '<a class="' . $this->escape($this->buttonClasses()) . '" href="' . $this->escape($this->routeHref($basePath, '/')) . '">Continue shopping</a>';
        $html[] = '</article>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderChipSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $copy = $this->publicSectionBody($body, '');
        $chips = [];
        if (str_contains($intent, 'dietary-legend')) {
            $chips = ['Vegetarian', 'Gluten-free', 'Spicy'];
        } elseif ($title !== '') {
            $chips = array_map('trim', explode(',', $title));
            $chips = array_filter($chips, static fn (string $c): bool => $c !== '');
        }
        if ($chips === []) {
            $chips = ['Topic one', 'Topic two', 'Topic three'];
        }
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--chip myron-chip-row" data-component-id="chip" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        if (trim($copy) !== '') {
            $html[] = '<p class="myron-paragraph">' . $this->escape($copy) . '</p>';
        }
        $html[] = '<ul class="myron-chip-row__items" role="list">';
        foreach ($chips as $chip) {
            $html[] = '<li class="myron-chip-row__item"><span class="myron-chip">' . $this->escape((string) $chip) . '</span></li>';
        }
        $html[] = '</ul>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderFormControlSection(string $componentId, string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $headline = $title !== '' ? $title : ucwords(str_replace('-', ' ', $componentId));
        $copy = $this->publicSectionBody($body, '');
        $isDate = $componentId === 'datetime-picker';
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--' . $this->escape($componentId) . '" data-component-id="' . $this->escape($componentId) . '" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<label class="mc-component-preview__field myron-form-field"><span class="myron-text">' . $this->escape($headline) . '</span>';
        if ($isDate) {
            $html[] = '<input class="myron-input" type="datetime-local">';
        } else {
            $html[] = '<input class="myron-input" type="text" list="preview-' . $this->escape($componentId) . '" placeholder="Type to search...">';
            $html[] = '<datalist id="preview-' . $this->escape($componentId) . '"><option value="Option one"><option value="Option two"><option value="Option three"></datalist>';
        }
        if (trim($copy) !== '') {
            $html[] = '<span class="myron-text myron-text--muted">' . $this->escape($copy) . '</span>';
        }
        $html[] = '</label>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderEmptyStateSection(string $variant, string $title, string $body, string $basePath, string $sourceTemplateId, string $intent): string
    {
        $headline = $title !== '' ? $title : 'Nothing here yet';
        $copy = $this->publicSectionBody($body, 'Once content is published, it will appear in this space.');
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-empty" data-component-id="empty-state" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<h2 class="myron-public-empty__title">' . $this->escape($headline) . '</h2>';
        $html[] = '<p class="myron-public-empty__text myron-paragraph">' . $this->escape($copy) . '</p>';
        $html[] = '<div class="myron-public-empty__actions">';
        $html[] = '<a class="' . $this->escape($this->buttonClasses()) . '" href="' . $this->escape($this->routeHref($basePath, '/')) . '">Return home</a>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderImageSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $copy = $this->publicSectionBody($body, '');
        $caption = $copy !== '' ? $copy : ($title !== '' ? $title : '');
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--image" data-component-id="image" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<figure class="myron-figure">';
        $html[] = '<div class="myron-image mc-component-preview__media-placeholder" aria-hidden="true"></div>';
        if ($caption !== '') {
            $html[] = '<figcaption class="myron-text myron-text--muted">' . $this->escape($caption) . '</figcaption>';
        }
        $html[] = '</figure>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderProgressBarSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $headline = $title !== '' ? $title : 'Progress';
        $copy = $this->publicSectionBody($body, '');
        $value = is_numeric($variant) ? max(0, min(100, (int) $variant)) : 60;
        $html = [];
        $valueClass = in_array($value, [25, 40, 45, 60, 80], true) ? (string) $value : '60';
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--progress-bar" data-component-id="progress-bar" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<p class="myron-text">' . $this->escape($headline) . '</p>';
        $html[] = '<div class="myron-progress-bar myron-progress-bar--md myron-progress-bar--value-' . $this->escape($valueClass) . '" aria-hidden="true"><span class="myron-progress-bar__track"></span></div>';
        $html[] = '<progress class="myron-progress-bar myron-progress-bar__native" value="' . $value . '" max="100" aria-label="' . $this->escape($headline) . '"></progress>';
        if (trim($copy) !== '') {
            $html[] = '<p class="myron-paragraph myron-paragraph--muted">' . $this->escape($copy) . '</p>';
        }
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderResourcesItemCardSection(string $variant, string $title, string $body, string $basePath, string $sourceTemplateId, string $intent): string
    {
        $headline = $title !== '' ? $title : 'Resource';
        $copy = $this->publicSectionBody($body, 'A short summary of this resource appears here.');
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--resources-item-card" data-component-id="resources-item-card" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<article class="' . $this->escape($this->cardClasses('default', 'thin', 'md', 'myron-resources-item-card')) . '">';
        $html[] = '<span class="myron-chip">Resource</span>';
        $html[] = '<h3 class="myron-heading">' . $this->escape($headline) . '</h3>';
        $html[] = '<p class="myron-paragraph">' . $this->escape($copy) . '</p>';
        $html[] = '<a class="' . $this->escape($this->buttonClasses('neutral', 'outline', 'sm')) . '" href="' . $this->escape($this->routeHref($basePath, '/')) . '">Open resource</a>';
        $html[] = '</article>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderUserIdentitySection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $name = $title !== '' ? $title : 'Author name';
        $copy = $this->publicSectionBody($body, 'Author bio appears here once content is published.');
        $initials = strtoupper(substr(preg_replace('~[^A-Za-z]~', '', $name) ?: 'MC', 0, 2));
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--user-identity myron-user-identity myron-user-identity--inline myron-user-identity--md" data-component-id="user-identity" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-avatar myron-avatar--md myron-avatar--circle" aria-hidden="true"><span class="myron-avatar__initials">' . $this->escape($initials) . '</span></div>';
        $html[] = '<div class="myron-user-identity__body">';
        $html[] = '<h3 class="myron-heading myron-user-identity__name">' . $this->escape($name) . '</h3>';
        $html[] = '<p class="myron-paragraph myron-paragraph--muted">' . $this->escape($copy) . '</p>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderVideoSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $copy = $this->publicSectionBody($body, '');
        $caption = $copy !== '' ? $copy : ($title !== '' ? $title : '');
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--video" data-component-id="video" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<figure class="myron-figure myron-figure--video">';
        $html[] = '<div class="myron-image mc-component-preview__media-placeholder" aria-hidden="true" data-myron-video-placeholder="true"></div>';
        if ($caption !== '') {
            $html[] = '<figcaption class="myron-text myron-text--muted">' . $this->escape($caption) . '</figcaption>';
        }
        $html[] = '</figure>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderHeaderSection(string $variant, string $title, string $body, string $basePath, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = $variant !== '' ? myronNormalizeSlug($variant) : 'default';
        $headline = $title !== '' ? $title : 'Section';
        $copy = $this->publicSectionBody($body, '');
        $links = ['Home', 'Pricing', 'Resources', 'Contact'];
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--header myron-public-section-header myron-public-section-header--' . $this->escape($normalizedVariant) . '" data-component-id="header" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-public-section-header__title"><h2 class="myron-heading">' . $this->escape($headline) . '</h2>';
        if (trim($copy) !== '') {
            $html[] = '<p class="myron-paragraph myron-paragraph--muted">' . $this->escape($copy) . '</p>';
        }
        $html[] = '</div>';
        $html[] = '<nav class="myron-public-section-header__nav" aria-label="Section navigation">';
        foreach ($links as $label) {
            $html[] = '<a class="myron-link" href="' . $this->escape($this->routeHref($basePath, '/' . myronNormalizeSlug($label))) . '">' . $this->escape($label) . '</a>';
        }
        $html[] = '</nav>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderPaginationSection(string $variant, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = $variant !== '' ? myronNormalizeSlug($variant) : 'default';
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--pagination myron-pagination myron-pagination--' . $this->escape($normalizedVariant) . '" data-component-id="pagination" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<nav class="myron-pagination__nav" aria-label="Pagination">';
        $html[] = '<ol class="myron-pagination__list" role="list">';
        $html[] = '<li class="myron-pagination__item"><a class="myron-pagination__link" href="#" rel="prev" aria-label="Previous page">Previous</a></li>';
        foreach ([1, 2, 3] as $n) {
            $current = $n === 1 ? ' aria-current="page"' : '';
            $html[] = '<li class="myron-pagination__item"><a class="myron-pagination__link"' . $current . ' href="#">' . $this->escape((string) $n) . '</a></li>';
        }
        $html[] = '<li class="myron-pagination__item"><a class="myron-pagination__link" href="#" rel="next" aria-label="Next page">Next</a></li>';
        $html[] = '</ol>';
        $html[] = '</nav>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderProductFiltersSection(string $variant, string $title, string $sourceBundleId, string $sourceTemplateId, string $intent, bool $liveContentEnabled = false): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'horizontal');
        $liveCategories = $liveContentEnabled && $this->componentDataResolver instanceof MyronPublicComponentDataResolver
            ? $this->componentDataResolver->listActiveCategoriesWithPublishedPostUsage($this->liveContentBundleScope($sourceBundleId))
            : [];
        $liveCategories = array_values(array_filter($liveCategories, static function (array $category): bool {
            return trim((string) ($category['title'] ?? '')) !== '' && trim((string) ($category['slug'] ?? '')) !== '';
        }));
        $hasLiveCategoryFilters = $liveCategories !== [];
        $filterScope = $this->publicArchiveFilterScope($sourceBundleId, $sourceTemplateId);
        $totalPosts = $liveContentEnabled ? count($this->livePostCards($sourceBundleId, 1000)) : 0;
        $rootAttributes = $hasLiveCategoryFilters
            ? ' data-myron-public-archive-filter data-myron-public-filter-scope="' . $this->escape($filterScope) . '"'
            : '';
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--product-filters myron-product-filters myron-product-filters--' . $this->escape($normalizedVariant) . '" data-component-id="product-filters" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '"' . $rootAttributes . '>';
        $html[] = '<div class="myron-product-filters__header">';
        $html[] = '<h2 class="myron-heading myron-product-filters__title">' . $this->escape($title) . '</h2>';
        $html[] = '<p class="myron-paragraph myron-paragraph--muted">Browse published editorial content by category.</p>';
        $html[] = '</div>';
        $html[] = '<div class="myron-product-filters__groups" aria-label="Editorial filters">';
        $html[] = '<div class="myron-product-filters__group"' . ($hasLiveCategoryFilters ? ' data-myron-public-filter-group data-myron-public-filter-param="category"' : '') . '>';
        $html[] = '<span class="myron-product-filters__group-toggle">Category</span>';
        $html[] = '<div class="myron-product-filters__group-body">';
        $html[] = '<button class="myron-product-filters__option" type="button" aria-pressed="true"' . ($hasLiveCategoryFilters ? ' data-myron-public-filter-all' : '') . '>All</button>';
        if ($hasLiveCategoryFilters) {
            foreach ($liveCategories as $category) {
                $html[] = '<button class="myron-product-filters__option" type="button" aria-pressed="false" data-myron-public-filter-value="' . $this->escape((string) ($category['slug'] ?? '')) . '">' . $this->escape((string) ($category['title'] ?? '')) . '</button>';
            }
        } elseif (!$liveContentEnabled) {
            foreach (['Strategy', 'Design', 'Delivery'] as $optionLabel) {
                $html[] = '<button class="myron-product-filters__option" type="button" aria-pressed="false" disabled>' . $this->escape($optionLabel) . '</button>';
            }
        }
        $html[] = '</div>';
        $html[] = '</div>';
        $html[] = '<div class="myron-product-filters__group">';
        $html[] = '<span class="myron-product-filters__group-toggle">Sort</span>';
        $html[] = '<div class="myron-product-filters__group-body">';
        $html[] = '<button class="myron-product-filters__option" type="button" aria-pressed="true" disabled>Latest</button>';
        $html[] = '</div>';
        $html[] = '</div>';
        $html[] = '</div>';
        if ($hasLiveCategoryFilters) {
            $html[] = '<p class="myron-paragraph myron-paragraph--muted" data-myron-public-filter-count>' . $this->escape((string) $totalPosts . ' ' . ($totalPosts === 1 ? 'post' : 'posts')) . '</p>';
        }
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderFaqListSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = $variant !== '' ? myronNormalizeSlug($variant) : 'default';
        $headline = $title !== '' ? $title : 'Frequently Asked Questions';
        $copy = $this->publicSectionBody($body, '');
        $items = [
            ['q' => 'What does this product do?', 'a' => 'Replace this answer with the value you deliver to your customers.'],
            ['q' => 'How do I get started?', 'a' => 'Outline the first practical step a new visitor can take with you.'],
            ['q' => 'Is there a guarantee?', 'a' => 'State your refund or satisfaction policy here.'],
        ];
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--faq-list myron-faq-list myron-faq-list--' . $this->escape($normalizedVariant) . '" data-component-id="faq-list" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-public-section-header"><h2 class="myron-heading">' . $this->escape($headline) . '</h2>';
        if (trim($copy) !== '') {
            $html[] = '<p class="myron-paragraph">' . $this->escape($copy) . '</p>';
        }
        $html[] = '</div>';
        $html[] = '<div class="myron-faq-list__items">';
        foreach ($items as $index => $item) {
            $open = $index === 0 ? ' open' : '';
            $html[] = '<details class="myron-faq-list__item"' . $open . '>';
            $html[] = '<summary class="myron-faq-list__question">' . $this->escape($item['q']) . '</summary>';
            $html[] = '<div class="myron-faq-list__answer"><p class="myron-paragraph">' . $this->escape($item['a']) . '</p></div>';
            $html[] = '</details>';
        }
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderKvRowSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = $variant !== '' ? myronNormalizeSlug($variant) : 'default';
        $headline = $title !== '' ? $title : 'Details';
        $copy = $this->publicSectionBody($body, '');
        $rows = str_contains($intent, 'client') && str_contains($intent, 'discipline') ? [
            ['k' => 'Client', 'v' => 'Add the client or project owner'],
            ['k' => 'Year', 'v' => 'Add the project year'],
            ['k' => 'Discipline', 'v' => 'Add the project discipline'],
        ] : [
            ['k' => 'Service', 'v' => 'Add the offering name'],
            ['k' => 'Duration', 'v' => 'Add the duration or timeline'],
            ['k' => 'Price', 'v' => 'Add the price or starting rate'],
        ];
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--kv-row myron-kv-row-section myron-kv-row-section--' . $this->escape($normalizedVariant) . '" data-component-id="kv-row" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-public-section-header myron-kv-row-section__header">';
        $html[] = '<h2 class="myron-heading">' . $this->escape($headline) . '</h2>';
        if (trim($copy) !== '') {
            $html[] = '<p class="myron-paragraph">' . $this->escape($copy) . '</p>';
        }
        $html[] = '</div>';
        $html[] = '<dl class="myron-kv-row__items">';
        foreach ($rows as $row) {
            $html[] = '<div class="myron-kv-row myron-kv-row--md myron-kv-row__item">';
            $html[] = '<dt class="myron-kv-row__key">' . $this->escape($row['k']) . '</dt>';
            $html[] = '<dd class="myron-kv-row__value">' . $this->escape($row['v']) . '</dd>';
            $html[] = '</div>';
        }
        $html[] = '</dl>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderListSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = $variant !== '' ? myronNormalizeSlug($variant) : 'default';
        $headline = $title !== '' ? $title : 'List';
        $copy = $this->publicSectionBody($body, '');
        $items = ['First item', 'Second item', 'Third item'];
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--list myron-public-component--contained" data-component-id="list" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<h2 class="myron-heading">' . $this->escape($headline) . '</h2>';
        if (trim($copy) !== '') {
            $html[] = '<p class="myron-paragraph">' . $this->escape($copy) . '</p>';
        }
        $html[] = '<ul class="myron-list myron-list--' . $this->escape($normalizedVariant) . '">';
        foreach ($items as $item) {
            $html[] = '<li class="myron-list__item">' . $this->escape($item) . '</li>';
        }
        $html[] = '</ul>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderSearchResultsSection(string $variant, string $sourceTemplateId, string $intent, array $runtimeData = []): string
    {
        $normalizedVariant = $variant !== '' ? myronNormalizeSlug($variant) : 'results';
        $search = is_array($runtimeData['search'] ?? null) ? $runtimeData['search'] : null;
        if (is_array($search)) {
            $query = (string) ($search['query'] ?? '');
            $results = is_array($search['results'] ?? null) ? $search['results'] : [];
            $total = (int) ($search['total'] ?? 0);
            $html = [];
            $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--search-results myron-search-results myron-search-results--' . $this->escape($normalizedVariant) . '" data-component-id="search-results" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
            $html[] = '<form class="myron-search-results__form" role="search" action="/search" method="get" data-component-id="combobox">';
            $html[] = '<label class="myron-form-field myron-search-results__field"><span class="myron-form-field__label">Search</span><input class="myron-input" type="search" name="q" value="' . $this->escape($query) . '" placeholder="Search the site"></label>';
            $html[] = '<button class="' . $this->escape($this->buttonClasses('primary', 'solid', 'md')) . '" type="submit">Search</button>';
            $html[] = '</form>';
            $html[] = '<div class="myron-search-results__body" data-component-id="list">';
            $html[] = '<h2 class="myron-heading myron-search-results__heading">Results</h2>';
            if (!empty($search['unavailable'])) {
                $html[] = '<p class="myron-paragraph myron-paragraph--muted myron-public-search__error">Search isn&rsquo;t available on this site yet. An administrator needs to apply pending updates.</p>';
            } elseif (!empty($search['transientError'])) {
                $html[] = '<p class="myron-paragraph myron-paragraph--muted myron-public-search__error">Search is temporarily unavailable. Please try again.</p>';
                if ((string) ($search['exceptionDetails'] ?? '') !== '') {
                    $html[] = '<details class="myron-public-search__dev-details"><summary>Developer details</summary><pre>' . $this->escape((string) $search['exceptionDetails']) . '</pre></details>';
                }
            } elseif ($query === '') {
                $html[] = '<p class="myron-paragraph myron-paragraph--muted myron-public-search__empty">Enter a query above to search published pages.</p>';
            } elseif ($results === []) {
                $html[] = '<p class="myron-paragraph myron-paragraph--muted myron-public-search__empty">No results for <strong>' . $this->escape($query) . '</strong>.</p>';
            } else {
                $html[] = '<p class="myron-paragraph myron-paragraph--muted myron-public-search__summary">' . $total . ' result' . ($total === 1 ? '' : 's') . ' for <strong>' . $this->escape($query) . '</strong>.</p>';
                $html[] = '<ol class="myron-list myron-search-results__list myron-public-search__results" role="list">';
                foreach ($results as $hit) {
                    if (!is_array($hit)) {
                        continue;
                    }
                    $title = (string) ($hit['title'] ?? 'Untitled');
                    $path = trim((string) ($hit['path'] ?? ''));
                    $href = $path !== '' ? $path : (string) ($hit['url'] ?? '');
                    $snippet = (string) ($hit['snippet'] ?? '');
                    $html[] = '<li class="myron-list__item myron-search-results__item myron-public-search__result"><a class="myron-public-search__result-link" href="' . $this->escape($href) . '"><h3 class="myron-heading myron-public-search__result-title">' . $this->escape($title) . '</h3></a><p class="myron-public-search__result-url">' . $this->escape($href) . '</p>' . ($snippet !== '' ? '<p class="myron-paragraph myron-public-search__result-snippet">' . $snippet . '</p>' : '') . '</li>';
                }
                $html[] = '</ol>';
            }
            $html[] = '</div>';
            $html[] = '</section>';
            return implode("\n", $html);
        }
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--search-results myron-search-results myron-search-results--' . $this->escape($normalizedVariant) . '" data-component-id="search-results" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<form class="myron-search-results__form" role="search" action="#" method="get" data-component-id="combobox">';
        $html[] = '<label class="myron-form-field myron-search-results__field"><span class="myron-form-field__label">Search</span><input class="myron-input" type="search" name="q" placeholder="Search the site"></label>';
        $html[] = '<button class="' . $this->escape($this->buttonClasses('primary', 'solid', 'md')) . '" type="submit">Search</button>';
        $html[] = '</form>';
        $html[] = '<div class="myron-search-results__body" data-component-id="list">';
        $html[] = '<h2 class="myron-heading myron-search-results__heading">Results</h2>';
        $html[] = '<p class="myron-paragraph myron-paragraph--muted">Published pages will appear here after search indexing is configured.</p>';
        $html[] = '<ul class="myron-list myron-search-results__list" role="list">';
        foreach (['First matching page', 'Second matching page', 'Third matching page'] as $item) {
            $html[] = '<li class="myron-list__item myron-search-results__item">' . $this->escape($item) . '</li>';
        }
        $html[] = '</ul>';
        $html[] = '</div>';
        $html[] = '<nav class="myron-pagination myron-search-results__pagination" aria-label="Search pagination" data-component-id="pagination">';
        $html[] = '<ol class="myron-pagination__list" role="list">';
        foreach (['Previous', '1', '2', '3', 'Next'] as $index => $label) {
            $current = $label === '1' ? ' aria-current="page"' : '';
            $rel = $label === 'Previous' ? ' rel="prev"' : ($label === 'Next' ? ' rel="next"' : '');
            $html[] = '<li class="myron-pagination__item"><a class="myron-pagination__link" href="#"' . $current . $rel . '>' . $this->escape($label) . '</a></li>';
        }
        $html[] = '</ol>';
        $html[] = '</nav>';
        $html[] = '<div class="myron-public-empty myron-search-results__empty" data-component-id="empty-state" data-search-empty-state="true">';
        $html[] = '<h2 class="myron-public-empty__title">No results yet</h2>';
        $html[] = '<p class="myron-public-empty__text myron-paragraph">When no published content matches the query, this governed empty state appears inside the search results section.</p>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderLinkSection(string $variant, string $title, string $body, string $basePath, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = $variant !== '' ? myronNormalizeSlug($variant) : 'default';
        $label = $title !== '' ? $title : 'Continue';
        $copy = $this->publicSectionBody($body, '');
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--link myron-link-section myron-link-section--' . $this->escape($normalizedVariant) . '" data-component-id="link" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        if (trim($copy) !== '') {
            $html[] = '<p class="myron-paragraph">' . $this->escape($copy) . '</p>';
        }
        $html[] = '<a class="' . $this->escape($this->buttonClasses('neutral', 'outline')) . '" href="' . $this->escape($this->routeHref($basePath, '/')) . '">' . $this->escape($label) . '</a>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderSubNavBarSection(string $variant, string $title, string $body, string $basePath, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = $variant !== '' ? myronNormalizeSlug($variant) : 'default';
        $links = ['Overview', 'Details', 'Reviews', 'FAQs'];
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--sub-nav-bar myron-sub-nav-bar myron-sub-nav-bar--' . $this->escape($normalizedVariant) . '" data-component-id="sub-nav-bar" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        if ($title !== '') {
            $html[] = '<span class="myron-text myron-text--muted">' . $this->escape($title) . '</span>';
        }
        $html[] = '<nav class="myron-sub-nav-bar__nav" aria-label="Section sub-navigation">';
        foreach ($links as $label) {
            $current = $label === 'Overview' ? ' aria-current="page"' : '';
            $html[] = '<a class="myron-sub-nav-bar__item" href="#' . $this->escape(myronNormalizeSlug($label)) . '"' . $current . '>' . $this->escape($label) . '</a>';
        }
        $html[] = '</nav>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderMenuBlockSection(string $variant, string $title, string $body, string $basePath, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = $variant !== '' ? myronNormalizeSlug($variant) : 'default';
        $headline = $title !== '' ? $title : 'Menu';
        $items = [
            ['name' => 'House Special', 'desc' => 'Signature dish description.'],
            ['name' => 'Seasonal Plate', 'desc' => 'Seasonal dish description.'],
            ['name' => 'Chef Selection', 'desc' => 'Chef-curated dish description.'],
        ];
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--menu-block myron-menu-block myron-menu-block--' . $this->escape($normalizedVariant) . '" data-component-id="menu-block" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<h2 class="myron-heading">' . $this->escape($headline) . '</h2>';
        $html[] = '<ul class="myron-menu-block__items" role="list">';
        foreach ($items as $item) {
            $html[] = '<li class="myron-menu-block__item">';
            $html[] = '<h3 class="myron-heading myron-menu-block__name">' . $this->escape($item['name']) . '</h3>';
            $html[] = '<p class="myron-paragraph myron-menu-block__description">' . $this->escape($item['desc']) . '</p>';
            $html[] = '</li>';
        }
        $html[] = '</ul>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderLegalDocTocSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = $variant !== '' ? myronNormalizeSlug($variant) : 'default';
        $headline = $title !== '' ? $title : 'Document Sections';
        $sectionsList = ['Overview', 'Definitions', 'User Obligations', 'Privacy', 'Contact'];
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--legal-doc-toc myron-legal-doc-toc myron-legal-doc-toc--' . $this->escape($normalizedVariant) . '" data-component-id="legal-doc-toc" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<h2 class="myron-heading myron-legal-doc-toc__heading">' . $this->escape($headline) . '</h2>';
        $html[] = '<ol class="myron-legal-doc-toc__list">';
        foreach ($sectionsList as $i => $name) {
            $html[] = '<li class="myron-legal-doc-toc__item"><a class="myron-legal-doc-toc__link" href="#section-' . ($i + 1) . '">' . $this->escape($name) . '</a></li>';
        }
        $html[] = '</ol>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderHeroSimpleSection(string $variant, string $title, string $body, string $basePath, string $sourceBundleId, string $sourceTemplateId, string $intent, bool $primaryHeading = false, array $content = [], array $section = []): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'layout-split');
        $layout = $normalizedVariant === 'centered' || $normalizedVariant === 'layout-centered' ? 'centered' : 'split';
        $copy = $this->publicSectionBody($body, 'Introduce the page in a single sentence so visitors know they are in the right place.');
        $headline = $sourceBundleId === 'site-type.news' ? 'Lead Story' : ($title !== '' ? $title : 'Headline');
        if (str_starts_with($sourceTemplateId, 'template.funnel.')) {
            $headline = $this->funnelTitle($this->funnelStepKey($sourceTemplateId), $headline);
        }
        $mediaLayout = MyronPublicHeroImagePolicy::mediaLayoutForSection($section);
        $imagePolicy = MyronPublicHeroImagePolicy::forSection('hero-simple', $normalizedVariant, $mediaLayout);
        $html = [];
        $html[] = '<section class="' . $this->escape($this->presentation->heroSimpleClasses($normalizedVariant, $layout)) . '" data-component-id="hero-simple" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-hero-simple__inner">';
        $html[] = '<div class="myron-hero-simple__content">';
        $headingTag = $primaryHeading ? 'h1' : 'h2';
        $html[] = '<' . $headingTag . ' class="myron-heading myron-hero-simple__headline">' . $this->escape($headline) . '</' . $headingTag . '>';
        $html[] = '<div class="myron-hero-simple__subhead">' . $this->paragraphs($copy) . '</div>';
        $html[] = '</div>';
        $html[] = $this->imageSlotHtml(
            $content,
            'myron-hero-simple__media myron-public-hero-media',
            'mediaFileId',
            'mediaAlt',
            (string) $imagePolicy['rendition'],
            (string) $imagePolicy['sizes'],
            $imagePolicy['srcset'],
            $primaryHeading
        );
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderHeroWithCtaSection(string $variant, string $title, string $body, string $basePath, string $sourceBundleId, string $sourceTemplateId, string $intent, bool $primaryHeading = false, array $content = [], array $section = []): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'layout-split');
        $copyFallback = $sourceBundleId === 'site-type.news'
            ? 'The latest lead story is ready for newsroom curation once editors publish the front-page article.'
            : 'Introduce what your business does, who it helps, and the next action visitors should take.';
        $copy = $this->publicSectionBody($body, $copyFallback);
        $hasMedia = is_array($this->contentFile($content, 'mediaFileId'));
        $extraClasses = $normalizedVariant === 'cinematic'
            ? $this->cinematicHeroControlClasses($content)
            : [];
        if ($normalizedVariant === 'cinematic' && $hasMedia) {
            $extraClasses[] = 'myron-hero-with-cta--has-media';
        }
        $heroClasses = $this->presentation->heroWithCtaClasses(
            $normalizedVariant,
            $extraClasses
        );
        $html = [];
        $html[] = '<section class="' . $this->escape($heroClasses) . '" data-component-id="hero-with-cta" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-hero-simple__inner">';
        $html[] = '<div class="myron-hero-simple__content">';
        $headingTag = $primaryHeading ? 'h1' : 'h2';
        $headline = $sourceBundleId === 'site-type.news' ? 'Lead Story' : $title;
        if (str_starts_with($sourceTemplateId, 'template.funnel.')) {
            $headline = $this->funnelTitle($this->funnelStepKey($sourceTemplateId), $headline);
        }
        $mediaLayout = MyronPublicHeroImagePolicy::mediaLayoutForSection($section);
        $imagePolicy = MyronPublicHeroImagePolicy::forSection(
            'hero-with-cta',
            $normalizedVariant === 'cinematic' ? 'full-bleed' : $normalizedVariant,
            $mediaLayout
        );
        $eyebrow = trim((string) ($content['eyebrow'] ?? ''));
        if ($eyebrow !== '') {
            $html[] = '<p class="myron-hero-with-cta__eyebrow">' . $this->escape($eyebrow) . '</p>';
        }
        $html[] = '<' . $headingTag . ' class="myron-heading myron-hero-simple__headline">' . $this->escape($headline) . '</' . $headingTag . '>';
        $html[] = '<div class="myron-hero-simple__subhead">' . $this->paragraphs($copy) . '</div>';
        $primaryLabel = trim((string) ($content['ctaLabel'] ?? ''));
        $primaryHref = trim((string) ($content['ctaHref'] ?? ''));
        $secondaryLabel = trim((string) ($content['ctaSecondaryLabel'] ?? ''));
        $secondaryHref = trim((string) ($content['ctaSecondaryHref'] ?? ''));
        $actions = [];
        if ($primaryLabel !== '' && $primaryHref !== '') {
            $actions[] = '<a class="' . $this->escape($this->buttonClasses()) . '" href="' . $this->escape($this->routeHref($basePath, $primaryHref)) . '">' . $this->escape($primaryLabel) . '</a>';
        }
        if ($secondaryLabel !== '' && $secondaryHref !== '') {
            $actions[] = '<a class="' . $this->escape($this->buttonClasses('neutral', 'outline')) . '" href="' . $this->escape($this->routeHref($basePath, $secondaryHref)) . '">' . $this->escape($secondaryLabel) . '</a>';
        }
        if ($actions !== []) {
            $html[] = '<div class="myron-hero-with-cta__actions">' . implode('', $actions) . '</div>';
        }
        $html[] = '</div>';
        $html[] = $this->imageSlotHtml(
            $content,
            'myron-hero-simple__media myron-public-hero-media',
            'mediaFileId',
            'mediaAlt',
            (string) $imagePolicy['rendition'],
            (string) $imagePolicy['sizes'],
            $imagePolicy['srcset'],
            $primaryHeading
        );
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    /**
     * @param array<string, mixed> $content
     * @return list<string>
     */
    private function cinematicHeroControlClasses(array $content): array
    {
        $classes = [
            'myron-hero-with-cta--content-align-' . $this->boundedPresentationValue($content, 'contentAlign', ['left', 'center'], 'left'),
            'myron-hero-with-cta--content-position-' . $this->boundedPresentationValue($content, 'contentPosition', ['top', 'center', 'bottom'], 'center'),
            'myron-hero-with-cta--content-width-' . $this->boundedPresentationValue($content, 'contentWidth', ['sm', 'md', 'lg'], 'sm'),
            'myron-hero-with-cta--copy-width-' . $this->boundedPresentationValue($content, 'copyWidth', ['match', 'narrow'], 'match'),
            'myron-hero-with-cta--subhead-size-' . $this->boundedPresentationValue($content, 'subheadSize', ['md', 'lg'], 'md'),
            'myron-hero-with-cta--eyebrow-tone-' . $this->boundedPresentationValue($content, 'eyebrowTone', ['default', 'accent', 'muted'], 'default'),
            'myron-hero-with-cta--overlay-' . $this->boundedPresentationValue($content, 'overlay', ['off', 'faint', 'subtle', 'medium', 'strong'], 'medium'),
        ];
        $eyebrowWeight = $this->boundedPresentationValue($content, 'eyebrowWeight', ['governed', 'regular', 'bold'], 'governed');
        if ($eyebrowWeight !== 'governed') {
            $classes[] = 'myron-hero-with-cta--eyebrow-weight-' . $eyebrowWeight;
        }
        return $classes;
    }

    /**
     * @param array<string, mixed> $content
     * @param list<string> $accepted
     */
    private function boundedPresentationValue(array $content, string $key, array $accepted, string $fallback): string
    {
        $raw = $content[$key] ?? '';
        $normalized = is_scalar($raw) ? strtolower(trim((string) $raw)) : '';
        return in_array($normalized, $accepted, true) ? $normalized : $fallback;
    }

    private function renderFeatureGridSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent, array $content = []): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : '3-col');
        [$headline, $copy, $items] = $this->featureGridContent($title, $body, $intent, $content);

        $html = [];
        $html[] = '<section class="' . $this->escape($this->presentation->featureGridClasses($normalizedVariant, 'md')) . '" data-component-id="feature-grid" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-feature-grid__inner">';
        $html[] = '<div class="myron-feature-grid__title">';
        $html[] = '<h2 class="myron-heading">' . $this->escape($headline) . '</h2>';
        $html[] = $this->paragraphs($copy);
        $html[] = '</div>';
        $html[] = '<div class="myron-feature-grid__items" role="list" aria-label="Business highlights">';
        foreach ($items as $item) {
            $html[] = '<article class="' . $this->escape($this->cardClasses('default', 'thin', 'md', 'myron-public-feature-card')) . '" role="listitem">';
            $html[] = '<div class="myron-card__header">' . $this->iconSlotHtml($item, 'myron-public-feature-card__icon', 'iconFileId', 'iconAlt') . '<h3 class="myron-heading">' . $this->escape($item['title']) . '</h3></div>';
            $html[] = '<div class="myron-card__body"><p class="myron-paragraph myron-paragraph--muted">' . $this->escape($item['body']) . '</p></div>';
            $html[] = '</article>';
        }
        $html[] = '</div>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    /**
     * @return array{0:string,1:string,2:list<array{title:string,body:string,iconFileId:string,iconAlt:string}>}
     */
    private function featureGridContent(string $title, string $body, string $intent, array $content): array
    {
        $fallback = $this->featureGridFallback($intent);
        $headline = $title !== '' && !str_contains($intent, 'process-flow') && !str_contains($intent, 'why-us')
            ? $title
            : $fallback['title'];
        $copy = $this->publicSectionBody($body, $fallback['body']);
        $items = $fallback['items'];
        foreach ($items as $index => $item) {
            $fieldIndex = $index + 1;
            $items[$index]['title'] = trim((string) ($content['item' . $fieldIndex . 'Title'] ?? '')) ?: $item['title'];
            $items[$index]['body'] = trim((string) ($content['item' . $fieldIndex . 'Body'] ?? '')) ?: $item['body'];
            $items[$index]['iconFileId'] = trim((string) ($content['item' . $fieldIndex . 'IconFileId'] ?? ''));
            $items[$index]['iconAlt'] = trim((string) ($content['item' . $fieldIndex . 'IconAlt'] ?? ''));
        }

        return [$headline, $copy, $items];
    }

    private function renderFeatureGridEditorialSection(MyronSectionRenderContext $c): string
    {
        [$headline, $copy, $items] = $this->featureGridContent($c->title, $c->body, $c->intent, $c->content);
        $html = [];
        $html[] = '<section class="' . $this->escape($this->presentation->featureGridClasses('editorial', 'md')) . '" data-component-id="feature-grid" data-source-template-id="' . $this->escape($c->sourceTemplateId) . '" data-section-intent="' . $this->escape($c->intent) . '">';
        $html[] = '<div class="myron-feature-grid__inner">';
        $html[] = '<div class="myron-feature-grid__title">';
        $html[] = '<h2 class="myron-heading">' . $this->escape($headline) . '</h2>';
        $html[] = $this->paragraphs($copy);
        $html[] = '</div>';
        $html[] = '<div class="myron-feature-grid__items" role="list" aria-label="Business highlights">';
        foreach ($items as $item) {
            $icon = $this->iconSlotHtml($item, 'myron-feature-grid__editorial-icon', 'iconFileId', 'iconAlt', false);
            $html[] = '<article class="myron-feature-grid__editorial-item" role="listitem">';
            if ($icon !== '') {
                $html[] = $icon;
            }
            $html[] = '<h3 class="myron-heading myron-feature-grid__editorial-heading">' . $this->escape($item['title']) . '</h3>';
            $html[] = '<p class="myron-paragraph myron-paragraph--muted myron-feature-grid__editorial-copy">' . $this->escape($item['body']) . '</p>';
            $html[] = '</article>';
        }
        $html[] = '</div>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    /**
     * @return array{title:string,body:string,items:list<array{title:string,body:string}>}
     */
    private function featureGridFallback(string $intent): array
    {
        if (str_contains($intent, 'process-flow')) {
            return [
                'title' => 'How It Works',
                'body' => 'Show the practical path from first conversation to useful delivery.',
                'items' => [
                    ['title' => 'Discover', 'body' => 'Clarify needs, constraints, and the right next step before work begins.'],
                    ['title' => 'Shape', 'body' => 'Turn the plan into a clear scope, timeline, and decision path.'],
                    ['title' => 'Deliver', 'body' => 'Move approved work into practice with a steady review rhythm.'],
                ],
            ];
        }

        if (str_contains($intent, 'why-us')) {
            return [
                'title' => 'Why Work With Us',
                'body' => 'Give visitors a quick scan of the qualities that make this team a fit.',
                'items' => [
                    ['title' => 'Focused approach', 'body' => 'Keep the work grounded in the client goal instead of unnecessary complexity.'],
                    ['title' => 'Clear communication', 'body' => 'Set expectations early and keep decisions visible as the project moves.'],
                    ['title' => 'Built for trust', 'body' => 'Reserve space for proof, experience, and outcomes once real content is added.'],
                ],
            ];
        }

        return [
            'title' => 'Highlights',
            'body' => 'Give visitors a quick scan of what makes this business useful, credible, and easy to contact.',
            'items' => [
            ['title' => 'Clarify the offer', 'body' => 'Summarize the core value in plain language visitors can act on.'],
            ['title' => 'Show the path', 'body' => 'Guide people from first impression to the right service or contact route.'],
            ['title' => 'Build trust', 'body' => 'Reserve space for proof, experience, and outcomes once real content is added.'],
            ],
        ];
    }

    private function renderServicesGridSection(string $variant, string $title, string $body, string $basePath, string $sourceTemplateId, string $intent, array $content = []): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'compact');
        $copy = $this->publicSectionBody($body, 'Use this section to present the main ways clients can work with the business.');
        $services = [
            ['title' => 'Consultation', 'body' => 'A focused starting point for understanding needs, goals, and next steps.', 'href' => '/services'],
            ['title' => 'Implementation', 'body' => 'A structured delivery track for moving approved plans into practice.', 'href' => '/services'],
            ['title' => 'Ongoing Support', 'body' => 'A retained support path for iteration, maintenance, and improvement.', 'href' => '/services'],
        ];
        foreach ($services as $index => $service) {
            $fieldIndex = $index + 1;
            $services[$index]['title'] = trim((string) ($content['service' . $fieldIndex . 'Title'] ?? '')) ?: $service['title'];
            $services[$index]['body'] = trim((string) ($content['service' . $fieldIndex . 'Body'] ?? '')) ?: $service['body'];
            $services[$index]['href'] = trim((string) ($content['service' . $fieldIndex . 'Href'] ?? '')) ?: $service['href'];
            $services[$index]['ctaLabel'] = trim((string) ($content['service' . $fieldIndex . 'CtaLabel'] ?? ''));
            $services[$index]['iconFileId'] = trim((string) ($content['service' . $fieldIndex . 'IconFileId'] ?? ''));
            $services[$index]['iconAlt'] = trim((string) ($content['service' . $fieldIndex . 'IconAlt'] ?? ''));
        }

        $html = [];
        $html[] = '<section class="' . $this->escape('myron-services-grid myron-services-grid--' . $normalizedVariant . ' myron-public-component myron-public-component--contained myron-public-component--services-grid') . '" data-component-id="services-grid" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-services-grid__header">';
        $html[] = '<h2 class="myron-heading myron-services-grid__heading">' . $this->escape($title) . '</h2>';
        $html[] = $this->paragraphs($copy);
        $html[] = '</div>';
        $html[] = '<ul class="myron-services-grid__items" aria-label="Services">';
        foreach ($services as $service) {
            $html[] = '<li class="myron-services-grid__item">';
            $html[] = $this->iconSlotHtml($service, 'myron-services-grid__icon', 'iconFileId', 'iconAlt');
            $html[] = '<h3 class="myron-heading myron-services-grid__title">' . $this->escape($service['title']) . '</h3>';
            $html[] = '<p class="myron-services-grid__body">' . $this->escape($service['body']) . '</p>';
            $ctaLabel = trim((string) ($service['ctaLabel'] ?? '')) ?: 'View ' . (string) $service['title'];
            $html[] = '<a class="myron-link myron-link--standalone" href="' . $this->escape($this->routeHref($basePath, $service['href'])) . '">' . $this->escape($ctaLabel) . '</a>';
            $html[] = '</li>';
        }
        $html[] = '</ul>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderSectionBandSection(string $variant, string $title, string $body, string $basePath, string $sourceTemplateId, string $intent, array $content = []): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'about');
        $fallback = $this->sectionBandFallback($intent, $title);
        $copy = $this->publicSectionBody($body, $fallback['body']);
        $html = [];
        $html[] = '<section class="' . $this->escape($this->presentation->sectionBandClasses('alt', 'md', $normalizedVariant, ['myron-public-component', 'myron-public-component--section-band'])) . '" data-component-id="section-band" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-section-band__inner myron-public-about">';
        $html[] = '<div class="myron-public-about__copy">';
        $html[] = '<h2 class="myron-heading">' . $this->escape($fallback['title']) . '</h2>';
        $html[] = $this->paragraphs($copy);
        $ctaLabel = trim((string) ($content['ctaLabel'] ?? '')) ?: $fallback['cta'];
        $ctaHref = trim((string) ($content['ctaHref'] ?? '')) ?: $fallback['href'];
        $html[] = '<a class="' . $this->escape($this->buttonClasses('neutral', 'outline')) . '" href="' . $this->escape($this->routeHref($basePath, $ctaHref)) . '">' . $this->escape($ctaLabel) . '</a>';
        $html[] = '</div>';
        $html[] = $this->imageSlotHtml($content, 'myron-content-featured-media myron-content-featured-media--aspect-4-3 myron-public-about__media');
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    /**
     * @return array{title:string, body:string, cta:string, href:string}
     */
    private function sectionBandFallback(string $intent, string $defaultTitle): array
    {
        $normalizedIntent = myronNormalizeSlug($intent);

        if (str_contains($normalizedIntent, 'how-we-work') || str_contains($normalizedIntent, 'process')) {
            return [
                'title' => 'How We Work',
                'body' => 'Outline the process visitors can expect, from first conversation through delivery, review, and ongoing improvement.',
                'cta' => 'Start a conversation',
                'href' => '/contact',
            ];
        }

        if (str_contains($normalizedIntent, 'materials')) {
            return [
                'title' => 'Our Process',
                'body' => 'Describe the materials, standards, and operating choices that shape the finished work.',
                'cta' => 'Read about our process',
                'href' => '/about',
            ];
        }

        return [
            'title' => $defaultTitle !== '' ? $defaultTitle : 'About This Work',
            'body' => 'Introduce the company story, approach, and operating style. Replace this starter copy with details that make the business specific.',
            'cta' => 'About the business',
            'href' => '/about',
        ];
    }

    private function renderStatsStripSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent, array $content = []): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'strip');
        $copy = $this->publicSectionBody($body, 'Add real metrics when the business has approved proof points to publish.');
        $stats = [
            ['label' => 'Template state', 'value' => 'Ready', 'trend' => 'Replace with a real metric'],
            ['label' => 'Proof source', 'value' => 'Editable', 'trend' => 'Use verified business data'],
            ['label' => 'Publish posture', 'value' => 'Governed', 'trend' => 'Reviewed before launch'],
        ];
        foreach ($stats as $index => $stat) {
            $fieldIndex = $index + 1;
            $stats[$index]['label'] = trim((string) ($content['stat' . $fieldIndex . 'Label'] ?? '')) ?: $stat['label'];
            $stats[$index]['value'] = trim((string) ($content['stat' . $fieldIndex . 'Value'] ?? '')) ?: $stat['value'];
            $stats[$index]['trend'] = trim((string) ($content['stat' . $fieldIndex . 'Trend'] ?? '')) ?: $stat['trend'];
        }

        $html = [];
        $html[] = '<section class="' . $this->escape($this->presentation->sectionBandClasses('default', 'sm', $normalizedVariant, ['myron-public-component', 'myron-public-component--stats-tile', 'myron-public-stats', 'myron-public-stats--' . $normalizedVariant])) . '" data-component-id="stats-tile" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-section-band__inner">';
        $html[] = '<div class="myron-public-section-header">';
        $html[] = '<h2 class="myron-heading">' . $this->escape($title) . '</h2>';
        $html[] = $this->paragraphs($copy);
        $html[] = '</div>';
        $html[] = '<div class="myron-public-stat-grid" role="list" aria-label="Proof points">';
        foreach ($stats as $stat) {
            $html[] = '<article class="myron-stats-tile" role="listitem">';
            $html[] = '<span class="myron-stats-tile__label">' . $this->escape($stat['label']) . '</span>';
            $html[] = '<span class="myron-stats-tile__value">' . $this->escape($stat['value']) . '</span>';
            $html[] = '<span class="myron-stats-tile__trend">' . $this->escape($stat['trend']) . '</span>';
            $html[] = '</article>';
        }
        $html[] = '</div>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderTestimonialGridSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent, array $content = []): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'empty-state');
        $copy = $this->publicSectionBody($body, 'Publish approved customer quotes here when real testimonials are available.');
        $html = [];
        $html[] = '<section class="' . $this->escape('myron-testimonial-grid myron-testimonial-grid--' . $normalizedVariant . ' myron-public-component myron-public-component--contained myron-public-component--testimonial-grid') . '" data-component-id="testimonial-grid" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-testimonial-grid__inner">';
        $html[] = '<div class="myron-testimonial-grid__title">';
        $html[] = '<h2 class="myron-heading">' . $this->escape($title) . '</h2>';
        $html[] = $this->paragraphs($copy);
        $html[] = '</div>';
        $testimonials = $this->testimonialGridContent($content);
        if ($testimonials === []) {
            $html[] = '<div class="myron-testimonial-grid__empty"><p class="myron-paragraph myron-paragraph--muted">Add an approved customer quote in Content to publish testimonials here.</p></div>';
        } else {
            $html[] = '<div class="myron-testimonial-grid__items" role="list" aria-label="Testimonials">';
            foreach ($testimonials as $testimonial) {
            $html[] = '<article class="' . $this->escape($this->cardClasses('alt', 'thin', 'md', 'myron-public-testimonial-card')) . '" role="listitem">';
                $html[] = '<div class="myron-card__body"><p class="myron-paragraph myron-paragraph--muted">' . $this->escape($testimonial['quote']) . '</p></div>';
                if ($testimonial['credit'] !== '') {
                    $html[] = '<div class="myron-card__footer"><span class="myron-text myron-text--muted">' . $this->escape($testimonial['credit']) . '</span></div>';
                }
            $html[] = '</article>';
            }
            $html[] = '</div>';
        }
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    /**
     * @param array<string, mixed> $content
     * @return list<array{quote:string,credit:string}>
     */
    private function testimonialGridContent(array $content): array
    {
        $testimonials = [];
        for ($index = 1; $index <= 3; $index++) {
            $quote = trim((string) ($content['testimonial' . $index . 'Quote'] ?? ''));
            if ($quote === '') {
                continue;
            }
            $author = trim((string) ($content['testimonial' . $index . 'Author'] ?? ''));
            $organization = trim((string) ($content['testimonial' . $index . 'Organization'] ?? ''));
            $credit = trim($author . ($organization !== '' ? ' · ' . $organization : ''));
            $testimonials[] = ['quote' => $quote, 'credit' => $credit];
        }

        return $testimonials;
    }

    private function renderTestimonialFeaturedBandSection(MyronSectionRenderContext $c): string
    {
        $copy = $this->publicSectionBody($c->body, '');
        $testimonials = $this->testimonialGridContent($c->content);
        $classes = [
            'myron-testimonial-grid',
            'myron-testimonial-grid--featured-band',
            'myron-testimonial-grid--band-tone-' . $this->boundedPresentationValue($c->content, 'bandTone', ['accent-tint', 'surface-alt'], 'accent-tint'),
            'myron-testimonial-grid--eyebrow-tone-' . $this->boundedPresentationValue($c->content, 'eyebrowTone', ['default', 'accent'], 'default'),
            'myron-testimonial-grid--quote-size-' . $this->boundedPresentationValue($c->content, 'quoteSize', ['md', 'lg'], 'md'),
            'myron-public-component',
            'myron-public-component--testimonial-grid',
        ];
        $html = [];
        $html[] = '<section class="' . $this->escape(implode(' ', $classes)) . '" data-component-id="testimonial-grid" data-source-template-id="' . $this->escape($c->sourceTemplateId) . '" data-section-intent="' . $this->escape($c->intent) . '">';
        $html[] = '<div class="myron-testimonial-grid__inner">';
        $html[] = '<div class="myron-testimonial-grid__title">';
        $html[] = '<h2 class="myron-testimonial-grid__eyebrow">' . $this->escape($c->title) . '</h2>';
        $html[] = $this->paragraphs($copy);
        $html[] = '</div>';
        if ($testimonials === []) {
            $html[] = '<div class="myron-testimonial-grid__empty"><p class="myron-paragraph myron-paragraph--muted">Add an approved customer quote in Content to publish testimonials here.</p></div>';
        } else {
            $html[] = '<div class="myron-testimonial-grid__items myron-testimonial-grid__items--featured" role="list" aria-label="Testimonials">';
            foreach ($testimonials as $testimonial) {
                $html[] = '<figure class="myron-testimonial-grid__featured-quote" role="listitem">';
                $html[] = '<blockquote><p>“' . $this->escape($testimonial['quote']) . '”</p></blockquote>';
                if ($testimonial['credit'] !== '') {
                    $html[] = '<figcaption>' . $this->escape($testimonial['credit']) . '</figcaption>';
                }
                $html[] = '</figure>';
            }
            $html[] = '</div>';
        }
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderLogoTickerSection(MyronSectionRenderContext $c): string
    {
        $speed = $this->boundedPresentationValue($c->content, 'speed', ['slow', 'normal', 'fast'], 'normal');
        $density = $this->boundedPresentationValue($c->content, 'density', ['comfortable', 'compact'], 'comfortable');
        $marquee = !array_key_exists('marquee', $c->content)
            || filter_var($c->content['marquee'], FILTER_VALIDATE_BOOL);
        $logos = array_values(array_filter(
            is_array($c->content['logos'] ?? null) ? $c->content['logos'] : [],
            static fn (mixed $item): bool => is_array($item)
        ));
        $items = [];
        foreach ($logos as $logo) {
            if (!$this->contentFile($logo, 'mediaFileId')) {
                continue;
            }
            $items[] = '<li class="myron-logo-ticker__item"><span class="myron-logo myron-logo--mode-light myron-logo--orientation-horizontal">'
                . $this->imageSlotHtml($logo, 'myron-logo-ticker__image', 'mediaFileId', 'mediaAlt', 'thumb')
                . '</span></li>';
        }

        $classes = [
            'myron-logo-ticker',
            'myron-logo-ticker--speed-' . $speed,
            'myron-logo-ticker--density-' . $density,
            $marquee && count($items) > 1 ? 'myron-logo-ticker--marquee' : 'myron-logo-ticker--static',
            'myron-public-component',
            'myron-public-component--logo',
        ];
        $html = [];
        $html[] = '<section class="' . $this->escape(implode(' ', $classes)) . '" data-component-id="logo" data-source-template-id="' . $this->escape($c->sourceTemplateId) . '" data-section-intent="' . $this->escape($c->intent) . '">';
        $html[] = '<div class="myron-logo-ticker__inner">';
        $headline = trim((string) ($c->content['headline'] ?? ''));
        if ($headline !== '') {
            $html[] = '<div class="myron-public-section-header myron-logo-ticker__header">';
            $html[] = '<h2 class="myron-logo-ticker__eyebrow">' . $this->escape($headline) . '</h2>';
            $html[] = '</div>';
        }
        $html[] = '<div class="myron-logo-ticker__viewport">';
        $html[] = '<div class="myron-logo-ticker__track">';
        $html[] = '<ul class="myron-logo-ticker__set" aria-label="Client logos">' . implode('', $items) . '</ul>';
        if ($marquee && count($items) > 1) {
            $html[] = '<ul class="myron-logo-ticker__set" aria-hidden="true">' . implode('', $items) . '</ul>';
        }
        $html[] = '</div>';
        $html[] = '</div>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", array_filter($html, static fn (string $line): bool => $line !== ''));
    }

    private function renderServicesImageCardSection(MyronSectionRenderContext $c): string
    {
        $html = [];
        $html[] = '<section class="myron-services-grid myron-services-grid--image-card myron-public-component myron-public-component--contained myron-public-component--services-grid" data-component-id="services-grid" data-source-template-id="' . $this->escape($c->sourceTemplateId) . '" data-section-intent="' . $this->escape($c->intent) . '">';
        $html[] = '<div class="myron-services-grid__header">';
        if (trim((string) ($c->content['headline'] ?? '')) !== '') {
            $html[] = '<h2 class="myron-heading myron-services-grid__heading">' . $this->escape(trim((string) $c->content['headline'])) . '</h2>';
        }
        $html[] = $this->paragraphs(trim((string) ($c->content['intro'] ?? '')));
        $html[] = $this->paragraphs(trim((string) ($c->content['body'] ?? '')));
        $html[] = '</div>';
        $html[] = '<ul class="myron-services-grid__items" aria-label="Services">';
        for ($index = 1; $index <= 3; $index++) {
            $prefix = 'service' . $index;
            $title = trim((string) ($c->content[$prefix . 'Title'] ?? ''));
            $body = trim((string) ($c->content[$prefix . 'Body'] ?? ''));
            $href = trim((string) ($c->content[$prefix . 'Href'] ?? ''));
            $ctaLabel = trim((string) ($c->content[$prefix . 'CtaLabel'] ?? ''));
            $html[] = '<li class="myron-services-grid__item">';
            $html[] = '<div class="myron-services-grid__image-wrap">' . $this->imageSlotHtml(
                $c->content,
                'myron-services-grid__image',
                $prefix . 'ImageFileId',
                $prefix . 'ImageAlt',
                'card',
                '(max-width: 720px) 100vw, 33vw',
                ['card' => 400, 'card-lg' => 960]
            ) . '</div>';
            if ($title !== '') {
                $html[] = '<h3 class="myron-heading myron-services-grid__title">' . $this->escape($title) . '</h3>';
            }
            if ($body !== '') {
                $html[] = '<p class="myron-services-grid__body">' . $this->escape($body) . '</p>';
            }
            if ($href !== '' && $ctaLabel !== '') {
                $html[] = '<a class="myron-link myron-link--standalone" href="' . $this->escape($this->routeHref($c->basePath, $href)) . '">' . $this->escape($ctaLabel) . '</a>';
            }
            $html[] = '</li>';
        }
        $html[] = '</ul>';
        $html[] = '</section>';

        return implode("\n", array_filter($html, static fn (string $line): bool => $line !== ''));
    }

    private function renderCtaImageRightSection(MyronSectionRenderContext $c): string
    {
        $headline = trim((string) ($c->content['headline'] ?? ''));
        $ctaLabel = trim((string) ($c->content['ctaLabel'] ?? ''));
        $ctaHref = trim((string) ($c->content['ctaHref'] ?? ''));
        $html = [];
        $html[] = '<section class="myron-cta-band myron-cta-band--tone-alt myron-cta-band--layout-split myron-cta-band--image-right myron-public-component myron-public-component--cta-band" data-component-id="cta-band" data-source-template-id="' . $this->escape($c->sourceTemplateId) . '" data-section-intent="' . $this->escape($c->intent) . '">';
        $html[] = '<div class="myron-cta-band__inner">';
        $html[] = '<div class="myron-cta-band__copy">';
        $html[] = '<div class="myron-cta-band__body">';
        if ($headline !== '') {
            $html[] = '<h2 class="myron-heading">' . $this->escape($headline) . '</h2>';
        }
        $html[] = $this->paragraphs(trim((string) ($c->content['intro'] ?? '')));
        $html[] = $this->paragraphs(trim((string) ($c->content['body'] ?? '')));
        $html[] = '</div>';
        if ($ctaLabel !== '' && $ctaHref !== '') {
            $html[] = '<div class="myron-cta-band__actions"><a class="' . $this->escape($this->buttonClasses()) . '" href="' . $this->escape($this->routeHref($c->basePath, $ctaHref)) . '">' . $this->escape($ctaLabel) . '</a></div>';
        }
        $html[] = '</div>';
        $html[] = '<div class="myron-cta-band__media">' . $this->imageSlotHtml(
            $c->content,
            'myron-cta-band__image',
            'mediaFileId',
            'mediaAlt',
            'card-lg',
            '(max-width: 720px) 100vw, 50vw',
            ['card' => 400, 'card-lg' => 960, 'preview' => 1280]
        ) . '</div>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", array_filter($html, static fn (string $line): bool => $line !== ''));
    }

    private function renderCtaBackgroundImageSection(MyronSectionRenderContext $c): string
    {
        $headline = trim((string) ($c->content['headline'] ?? ''));
        $intro = trim((string) ($c->content['intro'] ?? ''));
        $body = trim((string) ($c->content['body'] ?? ''));
        $ctaLabel = trim((string) ($c->content['ctaLabel'] ?? ''));
        $ctaHref = trim((string) ($c->content['ctaHref'] ?? ''));
        $hasMedia = is_array($this->contentFile($c->content, 'mediaFileId'));
        $stateClass = $hasMedia ? 'myron-cta-band--has-media' : 'myron-cta-band--copy-only';

        $html = [];
        $html[] = '<section class="myron-cta-band myron-cta-band--tone-alt myron-cta-band--background-image ' . $stateClass . ' myron-public-component myron-public-component--cta-band" data-component-id="cta-band" data-source-template-id="' . $this->escape($c->sourceTemplateId) . '" data-section-intent="' . $this->escape($c->intent) . '">';
        if ($hasMedia) {
            $html[] = '<div class="myron-cta-band__background">' . $this->imageSlotHtml(
                $c->content,
                'myron-cta-band__background-image',
                'mediaFileId',
                'mediaAlt',
                'preview',
                '100vw',
                ['card' => 400, 'card-lg' => 960, 'preview' => 1280, 'hero' => 1920]
            ) . '</div>';
        }
        $html[] = '<div class="myron-cta-band__inner">';
        $html[] = '<div class="myron-cta-band__copy">';
        $html[] = '<div class="myron-cta-band__body">';
        if ($headline !== '') {
            $html[] = '<h2 class="myron-heading">' . $this->escape($headline) . '</h2>';
        }
        $html[] = $this->paragraphs($intro);
        $html[] = $this->paragraphs($body);
        $html[] = '</div>';
        if ($ctaLabel !== '' && $ctaHref !== '') {
            $html[] = '<div class="myron-cta-band__actions"><a class="' . $this->escape($this->buttonClasses()) . '" href="' . $this->escape($this->routeHref($c->basePath, $ctaHref)) . '">' . $this->escape($ctaLabel) . '</a></div>';
        }
        $html[] = '</div>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", array_filter($html, static fn (string $line): bool => $line !== ''));
    }

    private function renderLogoGridSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent, array $content = []): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'client-logo-grid');
        $copy = $this->publicSectionBody($body, 'Add approved client, partner, or certification logos when those assets are available.');
        $html = [];
        $html[] = '<section class="' . $this->escape($this->presentation->sectionBandClasses('alt', 'sm', $normalizedVariant, ['myron-client-logo-grid', 'myron-client-logo-grid--' . $normalizedVariant, 'myron-public-component', 'myron-public-component--logo'])) . '" data-component-id="logo" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-section-band__inner">';
        $html[] = '<div class="myron-public-section-header">';
        $html[] = '<h2 class="myron-heading">' . $this->escape($title) . '</h2>';
        $html[] = $this->paragraphs($copy);
        $html[] = '</div>';
        $html[] = '<ul class="myron-client-logo-grid__items" aria-label="Client logo slots">';
        for ($index = 1; $index <= 6; $index++) {
            $logo = $this->contentFile($content, 'logo' . $index . 'FileId');
            $logoAlt = trim((string) ($content['logo' . $index . 'Alt'] ?? '')) ?: 'Logo slot ' . $index;
            $html[] = '<li class="myron-client-logo-grid__item">';
            $html[] = '<span class="myron-logo myron-logo--mode-light myron-logo--orientation-horizontal">';
            if (is_array($logo)) {
                $html[] = '<img class="myron-logo__image-ref" src="' . $this->escape((string) ($logo['file_url'] ?? '')) . '" alt="' . $this->escape($logoAlt) . '">';
            } else {
                $html[] = '<span class="myron-logo__image-ref" aria-hidden="true"></span>';
            }
            $html[] = '<span class="myron-logo__label">' . $this->escape($logoAlt) . '</span>';
            $html[] = '</span>';
            $html[] = '</li>';
        }
        $html[] = '</ul>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderCtaBandSection(string $variant, string $title, string $body, string $basePath, string $sourceTemplateId, string $intent, array $content = []): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'layout-split');
        $copy = $this->publicSectionBody($body, 'Invite visitors to start a conversation, request a quote, or choose the next step.');
        $html = [];
        $html[] = '<section class="' . $this->escape('myron-cta-band myron-cta-band--tone-alt myron-cta-band--layout-split myron-cta-band--' . $normalizedVariant . ' myron-public-component myron-public-component--cta-band') . '" data-component-id="cta-band" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-cta-band__inner">';
        $html[] = '<div class="myron-cta-band__body">';
        $html[] = '<h2 class="myron-heading">' . $this->escape($title) . '</h2>';
        $html[] = $this->paragraphs($copy);
        $html[] = '</div>';
        $html[] = '<div class="myron-cta-band__actions">';
        $ctaLabel = trim((string) ($content['ctaLabel'] ?? '')) ?: 'Contact us';
        $ctaHref = trim((string) ($content['ctaHref'] ?? '')) ?: '/contact';
        $html[] = '<a class="' . $this->escape($this->buttonClasses()) . '" href="' . $this->escape($this->routeHref($basePath, $ctaHref)) . '">' . $this->escape($ctaLabel) . '</a>';
        $html[] = '</div>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderBlogTeaserSection(string $variant, string $title, string $body, string $basePath, string $sourceBundleId, string $sourceTemplateId, string $intent, array $content = [], bool $liveContentEnabled = false): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'card-grid');
        $archiveHref = match ($sourceBundleId) {
            'site-type.agy' => '/insights',
            'site-type.news' => '/news',
            default => '/blog',
        };
        $sourcePath = trim((string) ($content['sourcePath'] ?? ''));
        if ($sourcePath !== '') {
            try {
                $archiveHref = myronNormalizePath($sourcePath);
            } catch (InvalidArgumentException) {
                $sourcePath = '';
            }
        }
        $resolvedTitle = $title;
        $copyFallback = 'Recent posts will appear here after editorial content is published.';
        $meta = $sourceBundleId === 'site-type.news' ? 'Newsroom empty state' : 'Editorial empty state';
        $emptyTitle = 'Your first post will appear here.';
        $emptyCopy = 'Create and publish a post to populate this editorial section without fake dated placeholder content.';
        $buttonLabel = 'View insights';
        if ($sourceTemplateId === 'template.home.news.v1') {
            if (str_contains($intent, 'featured')) {
                $resolvedTitle = 'Editor Picks';
                $copyFallback = 'Curated front-page stories will appear here when editors mark published articles as featured reads.';
                $meta = 'Editor picks empty state';
                $emptyTitle = 'Featured reads will appear here.';
                $emptyCopy = 'Mark published stories as editor picks to populate this governed front-page shelf.';
                $buttonLabel = 'View news';
            } elseif (str_contains($intent, 'per-category')) {
                $resolvedTitle = 'Sections';
                $copyFallback = 'Category shelves will appear here as newsroom sections receive published stories.';
                $meta = 'Sections empty state';
                $emptyTitle = 'Section stories will appear here.';
                $emptyCopy = 'Publish stories by section to populate Politics, Business, Culture, Sports, and Opinion without fake placeholders.';
                $buttonLabel = 'Browse sections';
            } elseif (str_contains($intent, 'you-may-have-missed')) {
                $resolvedTitle = 'You May Have Missed';
                $copyFallback = 'A secondary shelf will surface recent stories that should stay visible after the lead story changes.';
                $meta = 'Recent shelf empty state';
                $emptyTitle = 'Recent stories will appear here.';
                $emptyCopy = 'Publish additional stories to populate this lower front-page shelf.';
                $buttonLabel = 'View all news';
            }
        }
        if ($sourceTemplateId === 'template.home.blog.v1' && $normalizedVariant === 'list-dense') {
            $resolvedTitle = 'Editor Picks';
            $copyFallback = 'Curated posts will appear here when the editorial team marks featured reads.';
            $meta = 'Curated empty state';
            $emptyTitle = 'Featured reads will appear here.';
            $emptyCopy = 'Mark published posts as editor picks to populate this governed editorial shelf.';
            $buttonLabel = 'Browse the archive';
        }
        $copy = $this->publicSectionBody($body, $copyFallback);
        $postsLimit = $this->blogTeaserPostsLimit($content);
        $posts = $liveContentEnabled ? $this->liveBlogTeaserPostCards($sourceBundleId, $content, $postsLimit) : [];
        $viewAllCtaHref = $this->blogTeaserViewAllHref($content, $archiveHref);
        $viewAllCtaLabel = $this->blogTeaserViewAllLabel($content, $buttonLabel);
        $html = [];
        $html[] = '<section class="' . $this->escape('myron-blog-teaser myron-blog-teaser--' . $normalizedVariant . ' myron-public-component myron-public-component--contained myron-public-component--blog-teaser') . '" data-component-id="blog-teaser" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-blog-teaser__header">';
        $html[] = '<h2 class="myron-heading myron-blog-teaser__heading">' . $this->escape($resolvedTitle) . '</h2>';
        $html[] = $this->paragraphs($copy);
        $html[] = '</div>';
        $filterScope = $this->publicArchiveFilterScope($sourceBundleId, $sourceTemplateId);
        $html[] = '<div class="myron-blog-teaser__posts" role="list" aria-label="Editorial posts">';
        if ($posts !== []) {
            foreach ($posts as $post) {
                $postTitle = trim((string) ($post['title'] ?? '')) ?: 'Untitled Post';
                $postExcerpt = trim((string) ($post['summary'] ?? '')) ?: 'Read the published editorial entry.';
                $postHref = trim((string) ($post['href'] ?? '')) ?: $archiveHref;
                $postAuthor = is_array($post['author'] ?? null) ? (array) $post['author'] : [];
                $authorName = trim((string) ($postAuthor['authorName'] ?? ''));
                $featuredMedia = is_array($post['featured_media'] ?? null) ? (array) $post['featured_media'] : [];
                $categories = is_array($post['categories'] ?? null) ? (array) $post['categories'] : [];
                $categoryValues = $this->postCategoryFilterValues($post);
                $filterAttributes = $categoryValues !== []
                    ? ' data-myron-public-filter-row data-myron-public-filter-scope="' . $this->escape($filterScope) . '" data-filter-category="' . $this->escape(implode('||', $categoryValues)) . '"'
                    : ' data-myron-public-filter-row data-myron-public-filter-scope="' . $this->escape($filterScope) . '" data-filter-category=""';
                $html[] = '<article class="myron-blog-teaser__post" role="listitem"' . $filterAttributes . '>';
                if (trim((string) ($featuredMedia['mediaFileId'] ?? '')) !== '') {
                    $html[] = '<a class="myron-blog-teaser__media" href="' . $this->escape($this->routeHref($basePath, $postHref)) . '" aria-label="' . $this->escape($postTitle) . '">';
                    $html[] = $this->imageSlotHtml(
                        $featuredMedia,
                        'myron-blog-teaser__image',
                        'mediaFileId',
                        'mediaAlt',
                        'card',
                        '(max-width: 720px) 100vw, 33vw',
                        ['card' => 400]
                    );
                    $html[] = '</a>';
                }
                $html[] = '<div class="myron-blog-teaser__body">';
                $approvedCommentCount = max(0, (int) ($post['approved_comment_count'] ?? 0));
                $commentMeta = $approvedCommentCount === 1 ? ' · 1 comment' : ($approvedCommentCount > 1 ? ' · ' . $approvedCommentCount . ' comments' : '');
                $authorMeta = $authorName !== '' ? ' · ' . $authorName : '';
                $html[] = '<p class="myron-blog-teaser__meta">' . $this->escape($this->publishedDateLabel((string) ($post['published_at'] ?? '')) . $authorMeta . $commentMeta) . '</p>';
                if ($categories !== []) {
                    $html[] = '<ul class="myron-blog-teaser__chips" role="list">';
                    foreach ($categories as $category) {
                        if (!is_array($category)) {
                            continue;
                        }
                        $label = trim((string) ($category['title'] ?? ''));
                        $slug = trim((string) ($category['slug'] ?? ''));
                        if ($label === '') {
                            continue;
                        }
                        $categoryArchiveBase = $sourcePath !== '' ? $archiveHref : $this->blogTeaserArchiveBaseForPost($postHref, $archiveHref);
                        $href = $slug !== '' ? $this->categoryArchiveHref($slug, $categoryArchiveBase) : '';
                        $html[] = '<li>' . ($href !== '' ? '<a class="myron-chip myron-chip--link" href="' . $this->escape($href) . '">' . $this->escape($label) . '</a>' : '<span class="myron-chip">' . $this->escape($label) . '</span>') . '</li>';
                    }
                    $html[] = '</ul>';
                }
                $html[] = '<h3 class="myron-heading myron-blog-teaser__title"><a href="' . $this->escape($this->routeHref($basePath, $postHref)) . '">' . $this->escape($postTitle) . '</a></h3>';
                $html[] = '<p class="myron-paragraph myron-blog-teaser__excerpt">' . $this->escape($postExcerpt) . '</p>';
                $html[] = '<a class="' . $this->escape($this->buttonClasses('neutral', 'outline', 'sm')) . '" href="' . $this->escape($this->routeHref($basePath, $postHref)) . '">Read post</a>';
                $html[] = '</div>';
                $html[] = '</article>';
            }
        } else {
            $html[] = '<article class="myron-blog-teaser__post myron-blog-teaser__post--empty" role="listitem">';
            $html[] = '<div class="myron-blog-teaser__body">';
            $html[] = '<p class="myron-blog-teaser__meta">' . $this->escape($meta) . '</p>';
            $html[] = '<h3 class="myron-heading myron-blog-teaser__title">' . $this->escape($emptyTitle) . '</h3>';
            $html[] = '<p class="myron-paragraph myron-blog-teaser__excerpt">' . $this->escape($emptyCopy) . '</p>';
            $html[] = '<a class="' . $this->escape($this->buttonClasses('neutral', 'outline', 'sm')) . '" href="' . $this->escape($this->routeHref($basePath, $archiveHref)) . '">' . $this->escape($buttonLabel) . '</a>';
            $html[] = '</div>';
            $html[] = '</article>';
        }
        $html[] = '</div>';
        if ($posts !== []) {
            $html[] = '<div class="myron-blog-teaser__post myron-blog-teaser__post--empty" role="status" data-myron-public-filter-empty data-myron-public-filter-scope="' . $this->escape($filterScope) . '" hidden>';
            $html[] = '<div class="myron-blog-teaser__body">';
            $html[] = '<p class="myron-blog-teaser__meta">No matching posts</p>';
            $html[] = '<h3 class="myron-heading myron-blog-teaser__title">No posts match this category.</h3>';
            $html[] = '<p class="myron-paragraph myron-blog-teaser__excerpt">Choose All to restore the full archive.</p>';
            $html[] = '</div>';
            $html[] = '</div>';
        }
        if ($posts !== [] && $viewAllCtaHref !== '') {
            $html[] = '<div class="myron-blog-teaser__footer">';
            $ctaBasePath = $basePath === '/' ? '' : $basePath;
            $html[] = '<a class="' . $this->escape($this->buttonClasses('neutral', 'outline', 'sm')) . '" href="' . $this->escape($this->routeHref($ctaBasePath, $viewAllCtaHref)) . '">' . $this->escape($viewAllCtaLabel) . '</a>';
            $html[] = '</div>';
        }
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderNewsletterSignupSection(string $variant, int $occurrence): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'inline-band');
        $sectionId = $occurrence === 0 ? 'subscribe' : 'subscribe-' . (string) ($occurrence + 1);
        $html = [];
        $html[] = '<section id="' . $this->escape($sectionId) . '" class="' . $this->escape('myron-public-component myron-public-component--contained myron-public-component--newsletter-signup myron-newsletter-signup myron-newsletter-signup--' . $normalizedVariant) . '" data-component-id="newsletter-signup" data-myron-newsletter-signup data-state="default">';
        $html[] = '<div class="myron-newsletter-signup__body">';
        $html[] = '<h2 class="myron-heading myron-definition-section__title">Subscribe</h2>';
        $html[] = '<p class="myron-paragraph myron-paragraph--muted">Get new editorial updates when they are published.</p>';
        $html[] = '</div>';
        $html[] = '<form class="myron-newsletter-signup__form" method="post" action="#' . $this->escape($sectionId) . '">';
        $html[] = $this->renderPassivePublicFormProtection('newsletter-signup');
        $html[] = '<div class="myron-newsletter-signup__fields">';
        $html[] = '<label class="myron-form-field">';
        $html[] = '<span class="myron-form-field__label">Email address</span>';
        $html[] = '<input class="myron-input" type="email" name="email" autocomplete="email" placeholder="you@example.com">';
        $html[] = '</label>';
        $html[] = '<button class="' . $this->escape($this->buttonClasses()) . '" type="submit">Subscribe</button>';
        $html[] = '</div>';
        $html[] = '<label class="myron-newsletter-signup__consent">';
        $html[] = '<input type="checkbox" name="consent" value="1">';
        $html[] = '<span>I agree to receive editorial updates and can unsubscribe anytime.</span>';
        $html[] = '</label>';
        $html[] = '<p class="myron-newsletter-signup__message" data-myron-newsletter-message></p>';
        $html[] = '</form>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderEditorialStackSection(string $classes, string $variant, string $title, string $body, string $sourceBundleId, string $basePath, bool $liveContentEnabled = false): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'editorial-sidebar');
        $copy = $this->publicSectionBody($body, '');
        $liveCategories = $liveContentEnabled ? $this->liveCategoryItems($sourceBundleId) : [];
        $items = $liveCategories !== [] ? $liveCategories : ($sourceBundleId === 'site-type.news'
            ? ['Latest headlines', 'Sections', 'About this newsroom']
            : ['About this blog', 'Recent posts', 'Categories']);
        $html = [];
        $html[] = '<aside class="' . $this->escape($classes . ' myron-public-component myron-public-component--contained myron-public-component--editorial-stack myron-stack myron-stack--gap-md myron-editorial-sidebar myron-editorial-sidebar--' . $normalizedVariant) . '" data-component-id="stack" aria-label="Editorial sidebar">';
        $html[] = '<h2 class="myron-heading myron-definition-section__title">' . $this->escape($title) . '</h2>';
        if ($copy !== '') {
            $html[] = '<div class="myron-definition-section__content">' . $this->paragraphs($copy) . '</div>';
        }
        foreach ($items as $item) {
            $itemTitle = is_array($item) ? trim((string) ($item['title'] ?? '')) : trim((string) $item);
            $itemDescription = is_array($item) ? trim((string) ($item['description'] ?? '')) : 'This editorial widget is ready for configured content.';
            $itemHref = is_array($item) ? trim((string) ($item['href'] ?? '')) : '';
            $html[] = '<section class="myron-definition-section myron-editorial-sidebar__widget">';
            if ($itemHref !== '') {
                $html[] = '<h3 class="myron-heading"><a href="' . $this->escape($this->routeHref($basePath, $itemHref)) . '">' . $this->escape($itemTitle) . '</a></h3>';
            } else {
                $html[] = '<h3 class="myron-heading">' . $this->escape($itemTitle) . '</h3>';
            }
            $html[] = '<p class="myron-paragraph myron-paragraph--muted">' . $this->escape($itemDescription) . '</p>';
            $html[] = '</section>';
        }
        $html[] = '</aside>';

        return implode("\n", $html);
    }

    private function renderSocialLinksRowSection(string $variant, string $title, string $body, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'inline');
        $copy = $this->publicSectionBody($body, '');
        $links = [
            ['label' => 'Instagram', 'href' => '#instagram'],
            ['label' => 'LinkedIn', 'href' => '#linkedin'],
            ['label' => 'Email', 'href' => 'mailto:hello@example.com'],
        ];
        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--social-links-row myron-social-links-row myron-social-links-row--' . $this->escape($normalizedVariant) . '" data-component-id="stack" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        if ($title !== '') {
            $html[] = '<h2 class="myron-heading myron-social-links-row__title">' . $this->escape($title) . '</h2>';
        }
        if ($copy !== '') {
            $html[] = '<p class="myron-paragraph myron-paragraph--muted">' . $this->escape($copy) . '</p>';
        }
        $html[] = '<ul class="myron-social-links-row__items" role="list" aria-label="Social links">';
        foreach ($links as $link) {
            $html[] = '<li class="myron-social-links-row__item"><a class="myron-link myron-social-links-row__link" href="' . $this->escape($link['href']) . '">' . $this->escape($link['label']) . '</a></li>';
        }
        $html[] = '</ul>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    /**
     * @return list<array<string, mixed>>
     */
    private function livePostCards(string $sourceBundleId, int $limit): array
    {
        if (!$this->componentDataResolver instanceof MyronPublicComponentDataResolver) {
            return [];
        }

        return $this->componentDataResolver->listPublishedPosts($this->liveContentBundleScope($sourceBundleId), $limit);
    }

    /**
     * @param array<string, mixed> $content
     * @return list<array<string, mixed>>
     */
    private function liveBlogTeaserPostCards(string $sourceBundleId, array $content, int $limit): array
    {
        if (!$this->componentDataResolver instanceof MyronPublicComponentDataResolver) {
            return [];
        }

        $mode = strtolower(str_replace(['-', '_', ' '], '', trim((string) ($content['sourceMode'] ?? 'default'))));
        $sourcePath = trim((string) ($content['sourcePath'] ?? ''));
        if ($sourcePath !== '' && $mode !== 'recent') {
            return $this->componentDataResolver->listPublishedPostsBySourcePath($sourcePath, null, $limit);
        }

        if ($mode === 'recent') {
            return $this->componentDataResolver->listPublishedPosts(null, $limit);
        }

        return $this->componentDataResolver->listPublishedPosts($this->liveContentBundleScope($sourceBundleId), $limit);
    }

    /**
     * @param array<string, mixed> $content
     */
    private function blogTeaserPostsLimit(array $content): int
    {
        $rawLimit = $content['postsLimit'] ?? null;
        if ($rawLimit === null || $rawLimit === '' || !is_numeric($rawLimit)) {
            return 6;
        }

        $limit = (int) floor((float) $rawLimit);
        if ($limit <= 0) {
            return 0;
        }

        return min(100, $limit);
    }

    /**
     * @param array<string, mixed> $page
     */
    private function renderBlogComments(array $page, string $basePath): string
    {
        $pageId = trim((string) ($page['id'] ?? ''));
        if ($pageId === '') {
            return '';
        }

        $commentService = myronBlogCommentService();
        if (!$commentService->canDisplayPublicCommentsForPage($page)) {
            return '';
        }

        $approvedCount = $commentService->countApprovedForPage($pageId);
        $acceptingComments = $commentService->canAcceptPublicSubmissionForPage($page);
        if ($approvedCount === 0 && !$acceptingComments) {
            return '';
        }

        $approvedComments = $approvedCount > 0
            ? $commentService->listForPage($pageId, BlogCommentRepository::STATUS_APPROVED, 100, 0)
            : [];
        $commentLabel = $approvedCount === 1 ? '1 approved comment' : (string) $approvedCount . ' approved comments';
        $formKey = $commentService->publicSubmissionFormKey($pageId);
        $action = $this->routeHref($basePath, '/api/v1/content/pages/' . rawurlencode($pageId) . '/comments');

        $html = [];
        $html[] = '<section class="myron-public-component myron-public-component--contained myron-public-component--blog-comments myron-blog-comments" data-myron-blog-comments data-approved-comment-count="' . $this->escape((string) $approvedCount) . '">';
        $html[] = '<header class="myron-blog-comments__header">';
        $html[] = '<h2 class="myron-heading myron-blog-comments__title">Comments</h2>';
        $html[] = '<p class="myron-paragraph myron-paragraph--muted myron-blog-comments__count">' . $this->escape($commentLabel) . '</p>';
        $html[] = '</header>';
        if ($approvedComments !== []) {
            $html[] = '<ol class="myron-blog-comments__list" role="list">';
            foreach ($approvedComments as $comment) {
                $payload = $commentService->publicPayload($comment);
                $author = trim((string) ($payload['author_name'] ?? 'Reader')) ?: 'Reader';
                $body = trim((string) ($payload['body'] ?? ''));
                $submittedAt = trim((string) ($payload['submitted_at'] ?? ''));
                if ($body === '') {
                    continue;
                }
                $html[] = '<li class="myron-blog-comments__item">';
                $html[] = '<article class="myron-blog-comments__comment">';
                $html[] = '<header class="myron-blog-comments__comment-header">';
                $html[] = '<h3 class="myron-heading myron-blog-comments__author">' . $this->escape($author) . '</h3>';
                if ($submittedAt !== '') {
                    $html[] = '<time class="myron-blog-comments__date" datetime="' . $this->escape($submittedAt) . '">' . $this->escape($submittedAt) . '</time>';
                }
                $html[] = '</header>';
                $html[] = '<p class="myron-paragraph myron-blog-comments__body">' . nl2br($this->escape($body), false) . '</p>';
                $html[] = '</article>';
                $html[] = '</li>';
            }
            $html[] = '</ol>';
        }
        if ($acceptingComments) {
            $html[] = '<form class="myron-blog-comments__form" method="post" action="' . $this->escape($action) . '">';
            $html[] = '<input type="hidden" name="page_id" value="' . $this->escape($pageId) . '">';
            $html[] = '<label class="myron-form-field"><span class="myron-form-field__label">Name</span><input class="myron-input" type="text" name="author_name" autocomplete="name" required></label>';
            $html[] = '<label class="myron-form-field"><span class="myron-form-field__label">Email</span><input class="myron-input" type="email" name="author_email" autocomplete="email" required></label>';
            $html[] = '<label class="myron-form-field myron-blog-comments__field--full"><span class="myron-form-field__label">Comment</span><textarea class="myron-input" name="body" rows="5" required></textarea></label>';
            $html[] = myronVerificationRender($formKey);
            $html[] = '<button class="' . $this->escape($this->buttonClasses()) . '" type="submit">Submit Comment</button>';
            $html[] = '<p class="myron-paragraph myron-paragraph--muted myron-blog-comments__notice">Comments are reviewed before publication.</p>';
            $html[] = '</form>';
        }
        $html[] = '</section>';

        return implode("\n", $html);
    }

    /**
     * @return list<array<string, mixed>>
     */
    private function liveProjectCards(string $sourceBundleId, int $limit): array
    {
        if (!$this->componentDataResolver instanceof MyronPublicComponentDataResolver) {
            return [];
        }

        return $this->componentDataResolver->listPublishedProjects($this->liveContentBundleScope($sourceBundleId), $limit);
    }

    /**
     * @return list<array{title:string,description:string,href:string}>
     */
    private function liveCategoryItems(string $sourceBundleId): array
    {
        if (!$this->componentDataResolver instanceof MyronPublicComponentDataResolver) {
            return [];
        }

        $categories = $this->componentDataResolver->listActiveCategoriesWithPublishedPostUsage($this->liveContentBundleScope($sourceBundleId));
        $items = [];
        foreach ($categories as $category) {
            $title = trim((string) ($category['title'] ?? ''));
            $slug = trim((string) ($category['slug'] ?? ''));
            if ($title === '' || $slug === '') {
                continue;
            }

            $count = (int) ($category['page_count'] ?? 0);
            $items[] = [
                'title' => $title,
                'description' => $count === 1 ? '1 published post' : (string) $count . ' published posts',
                'href' => '',
            ];
        }

        return $items;
    }

    private function liveContentBundleScope(string $sourceBundleId): ?string
    {
        $bundle = trim($sourceBundleId);
        return $bundle !== '' ? $bundle : null;
    }

    private function publicArchiveFilterScope(string $sourceBundleId, string $sourceTemplateId): string
    {
        $bundle = myronNormalizeSlug(str_replace('site-type.', '', trim($sourceBundleId)));
        $template = myronNormalizeSlug(str_replace(['template.', '.v1'], ['', ''], trim($sourceTemplateId)));
        $parts = array_values(array_filter([$bundle, $template], static fn (string $part): bool => $part !== ''));

        return 'archive-' . ($parts !== [] ? implode('-', $parts) : 'default');
    }

    /**
     * @param array<string, mixed> $page
     */
    private function isPostSingleTemplate(string $sourceTemplateId, array $page = []): bool
    {
        foreach ([
            $sourceTemplateId,
            (string) ($page['source_template_id'] ?? ''),
            (string) ($page['template_source_template_id'] ?? ''),
            (string) ($page['template_key'] ?? ''),
            (string) ($page['template_id'] ?? ''),
        ] as $candidate) {
            $candidate = trim($candidate);
            if ($candidate !== '' && MyronTemplateDefinitionRepository::templateClassForTemplateId($candidate) === 'post-single') {
                return true;
            }
        }

        return false;
    }

    private function activePageTitle(): string
    {
        foreach (['version_title', 'title', 'page_title'] as $field) {
            $title = trim((string) ($this->activePublishedPage[$field] ?? ''));
            if ($title !== '') {
                return $title;
            }
        }

        return 'Untitled';
    }

    /**
     * @return array<string, string>
     */
    private function activePostAuthor(): array
    {
        $content = is_array($this->activePublishedPage['content'] ?? null) ? (array) $this->activePublishedPage['content'] : [];
        $meta = is_array($content['_postMeta'] ?? null) ? (array) $content['_postMeta'] : [];
        $author = is_array($meta['author'] ?? null) ? (array) $meta['author'] : [];

        return [
            'authorName' => trim((string) ($author['authorName'] ?? '')),
            'authorUserId' => trim((string) ($author['authorUserId'] ?? '')),
            'avatarFileId' => trim((string) ($author['avatarFileId'] ?? '')),
            'bio' => trim((string) ($author['bio'] ?? '')),
        ];
    }

    /**
     * @return list<array<string, mixed>>
     */
    private function activePostCategories(): array
    {
        return array_values(array_filter(
            is_array($this->activePublishedPage['categories'] ?? null) ? (array) $this->activePublishedPage['categories'] : [],
            'is_array'
        ));
    }

    private function initialsForName(string $name): string
    {
        $parts = array_values(array_filter(preg_split('/\s+/', trim($name)) ?: [], static fn (string $part): bool => $part !== ''));
        if ($parts === []) {
            return 'AU';
        }
        $first = strtoupper(substr((string) $parts[0], 0, 1));
        $last = count($parts) > 1 ? strtoupper(substr((string) $parts[count($parts) - 1], 0, 1)) : '';

        return substr($first . $last, 0, 2);
    }

    private function blogTeaserViewAllHref(array $content, string $archiveHref): string
    {
        $overrideHref = $this->safeRootRelativeHref((string) ($content['viewAllCtaHref'] ?? ''));
        if ($overrideHref !== '') {
            return $overrideHref;
        }

        return $this->safeRootRelativeHref($archiveHref);
    }

    /**
     * @param array<string, mixed> $content
     */
    private function blogTeaserViewAllLabel(array $content, string $fallbackLabel): string
    {
        $label = trim((string) ($content['viewAllCtaLabel'] ?? ''));
        return $label !== '' ? $label : $fallbackLabel;
    }

    private function blogTeaserArchiveBaseForPost(string $postHref, string $fallbackArchiveHref): string
    {
        try {
            $postPath = myronNormalizePath($postHref);
        } catch (InvalidArgumentException) {
            return $fallbackArchiveHref;
        }

        $parent = rtrim((string) dirname($postPath), '/');
        if ($parent === '' || $parent === '.' || $parent === '/') {
            return $fallbackArchiveHref;
        }

        return $parent;
    }

    private function safeRootRelativeHref(string $href): string
    {
        $trimmed = trim($href);
        if ($trimmed === '') {
            return '';
        }

        if (preg_match('#^(https?:)?//#i', $trimmed) === 1 || preg_match('#^[a-z][a-z0-9+.-]*:#i', $trimmed) === 1) {
            return '';
        }

        if (!str_starts_with($trimmed, '/')) {
            return '';
        }

        try {
            return $this->routeHref('', $trimmed);
        } catch (InvalidArgumentException) {
            return '';
        }
    }

    private function categoryArchiveHref(string $slug, string $archiveBase = ''): string
    {
        $archive = $this->safeRootRelativeHref($archiveBase);
        if ($archive === '') {
            $bundle = (string) (($this->activePublishedPage['source_bundle_id'] ?? '') ?: ($this->activePublishedPage['template_source_bundle_id'] ?? ''));
            $archive = match ($bundle) {
                'site-type.agy' => '/insights',
                'site-type.news' => '/news',
                default => '/blog',
            };
        }

        return $archive . '?category=' . rawurlencode($slug);
    }

    /**
     * @param array<string, mixed> $post
     * @return list<string>
     */
    private function postCategoryFilterValues(array $post): array
    {
        $categories = is_array($post['categories'] ?? null) ? $post['categories'] : [];
        $values = [];
        foreach ($categories as $category) {
            if (!is_array($category)) {
                continue;
            }

            $slug = trim((string) ($category['slug'] ?? ''));
            if ($slug !== '') {
                $values[] = $slug;
            }
        }

        return array_values(array_unique($values));
    }

    private function publishedDateLabel(string $publishedAt): string
    {
        $timestamp = strtotime($publishedAt);
        if ($timestamp === false) {
            return 'Published';
        }

        return 'Published ' . date('M j, Y', $timestamp);
    }

    private function renderBillingSwitchSection(string $classes, string $variant, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'billing-toggle');
        $html = [];
        $html[] = '<section class="' . $this->escape($classes . ' myron-public-component myron-public-component--contained myron-public-component--switch myron-billing-switch myron-definition-section--switch myron-definition-section--' . $normalizedVariant) . '" data-component-id="switch" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '">';
        $html[] = '<div class="myron-tier-comparison-matrix__billing-toggle" aria-label="Billing period preview">';
        $html[] = '<label class="myron-switch myron-switch--size-sm">';
        $html[] = '<input class="myron-switch__input" type="radio" role="switch" name="billing-period-preview" value="monthly" data-myron-billing-period="monthly" checked>';
        $html[] = '<span class="myron-switch__label">Monthly</span>';
        $html[] = '</label>';
        $html[] = '<label class="myron-switch myron-switch--size-sm">';
        $html[] = '<input class="myron-switch__input" type="radio" role="switch" name="billing-period-preview" value="annual" data-myron-billing-period="annual">';
        $html[] = '<span class="myron-switch__label">Annual</span>';
        $html[] = '</label>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderTierComparisonMatrixSection(string $classes, string $variant, string $title, string $body, string $basePath, string $sourceTemplateId, string $intent): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'standard');
        $copy = $this->publicSectionBody($body, 'Compare access levels, included capabilities, and support options.');
        $tiers = [
            ['name' => 'Starter', 'monthly' => '$29/mo', 'annual' => '$290/yr', 'cta' => 'Start Free Trial'],
            ['name' => 'Pro', 'monthly' => '$79/mo', 'annual' => '$790/yr', 'cta' => 'Start Free Trial'],
            ['name' => 'Team', 'monthly' => '$199/mo', 'annual' => '$1,990/yr', 'cta' => 'Contact Sales'],
        ];
        $rows = [
            ['group' => 'Core', 'feature' => 'Projects', 'values' => ['3', 'Unlimited', 'Unlimited']],
            ['group' => 'Core', 'feature' => 'Team seats', 'values' => ['1', '5', '25']],
            ['group' => 'Automation', 'feature' => 'API access', 'values' => ['-', 'Included', 'Included']],
            ['group' => 'Support', 'feature' => 'Priority support', 'values' => ['-', 'Included', 'Dedicated']],
        ];

        $html = [];
        $html[] = '<section class="' . $this->escape($classes . ' myron-public-component myron-public-component--contained myron-public-component--tier-comparison-matrix myron-tier-comparison-matrix myron-tier-comparison-matrix--' . $normalizedVariant) . '" data-component-id="tier-comparison-matrix" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-section-intent="' . $this->escape($intent) . '" data-myron-tier-comparison data-billing-period="monthly">';
        $html[] = '<div class="myron-tier-comparison-matrix__header">';
        $html[] = '<h2 class="myron-heading myron-definition-section__title">' . $this->escape($title) . '</h2>';
        if ($copy !== '') {
            $html[] = '<div class="myron-definition-section__content">' . $this->paragraphs($copy) . '</div>';
        }
        $html[] = '<div class="myron-tier-comparison-matrix__billing-toggle" aria-label="Billing period">';
        foreach (['monthly' => 'Monthly', 'annual' => 'Annual'] as $value => $label) {
            $html[] = '<label class="myron-switch myron-switch--size-sm">';
            $html[] = '<input class="myron-switch__input" type="radio" role="switch" name="tier-comparison-billing" value="' . $this->escape($value) . '" data-myron-billing-period="' . $this->escape($value) . '"' . ($value === 'monthly' ? ' checked' : '') . '>';
            $html[] = '<span class="myron-switch__label">' . $this->escape($label) . '</span>';
            $html[] = '</label>';
        }
        $html[] = '</div>';
        $html[] = '</div>';
        $html[] = '<div class="myron-tier-comparison-matrix__scroller">';
        $html[] = '<table class="myron-tier-comparison-matrix__table">';
        $html[] = '<thead><tr><th scope="col">Feature</th>';
        foreach ($tiers as $tier) {
            $html[] = '<th scope="col"><span class="myron-tier-comparison-matrix__tier"><span>' . $this->escape($tier['name']) . '</span><span class="myron-tier-comparison-matrix__price" data-price-monthly="' . $this->escape($tier['monthly']) . '" data-price-annual="' . $this->escape($tier['annual']) . '">' . $this->escape($tier['monthly']) . '</span><a class="' . $this->escape($this->buttonClasses('primary', 'solid', 'sm')) . '" href="' . $this->escape($this->routeHref($basePath, $tier['cta'] === 'Contact Sales' ? '/contact' : '/signup')) . '">' . $this->escape($tier['cta']) . '</a></span></th>';
        }
        $html[] = '</tr></thead>';
        $html[] = '<tbody>';
        $lastGroup = '';
        foreach ($rows as $row) {
            if ($row['group'] !== $lastGroup) {
                $html[] = '<tr><th class="myron-tier-comparison-matrix__feature-group" scope="rowgroup" colspan="' . (count($tiers) + 1) . '">' . $this->escape($row['group']) . '</th></tr>';
                $lastGroup = $row['group'];
            }
            $html[] = '<tr><th scope="row">' . $this->escape($row['feature']) . '</th>';
            foreach ($row['values'] as $value) {
                $class = $value === '-' ? '' : ' class="myron-tier-comparison-matrix__included"';
                $html[] = '<td' . $class . '>' . $this->escape($value) . '</td>';
            }
            $html[] = '</tr>';
        }
        $html[] = '</tbody></table>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderSidebarNavSection(string $classes, string $variant): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'account');
        $items = ['Overview', 'Subscription', 'Billing', 'API keys', 'Team'];
        $html = [];
        $html[] = '<section class="' . $this->escape($classes . ' myron-public-component myron-public-component--contained myron-public-component--sidebar-nav myron-account-nav myron-account-nav--' . $normalizedVariant . ' myron-definition-section--account-nav myron-definition-section--' . $normalizedVariant) . '" data-component-id="sidebar-nav">';
        $html[] = '<nav class="myron-sidebar-nav" aria-label="Account navigation">';
        $html[] = '<div class="myron-sidebar-nav__group">';
        $html[] = '<span class="myron-sidebar-nav__group-label">Account</span>';
        foreach ($items as $index => $item) {
            $active = $index === 0 ? ' myron-sidebar-nav__item--active" aria-current="page' : '';
            $html[] = '<a class="myron-sidebar-nav__item' . $active . '" href="#account-' . $this->escape(myronNormalizeSlug($item)) . '">' . $this->escape($item) . '</a>';
        }
        $html[] = '</div>';
        $html[] = '</nav>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderProfilePanelSection(string $classes, string $variant): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'account');
        $html = [];
        $html[] = '<section class="' . $this->escape($classes . ' myron-public-component myron-public-component--contained myron-public-component--profile-panel myron-account-panel myron-account-panel--' . $normalizedVariant . ' myron-profile-panel myron-profile-panel--' . $normalizedVariant) . '" data-component-id="profile-panel" id="account-overview">';
        $html[] = '<div>';
        $html[] = '<p class="myron-profile-panel__name">Account preview</p>';
        $html[] = '<p class="myron-profile-panel__meta">Signed-in customer details render here when account data is available.</p>';
        $html[] = '</div>';
        $html[] = '<div class="myron-profile-panel__actions">';
        $html[] = '<a class="' . $this->escape($this->buttonClasses('neutral', 'outline', 'sm')) . '" href="#account-billing">Billing</a>';
        $html[] = '<a class="' . $this->escape($this->buttonClasses('primary', 'solid', 'sm')) . '" href="/login">Login</a>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderSettingsLayoutSection(string $classes, string $variant): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'account');
        $html = [];
        $html[] = '<section class="' . $this->escape($classes . ' myron-public-component myron-public-component--contained myron-public-component--settings-layout myron-account-settings myron-account-settings--' . $normalizedVariant . ' myron-settings-layout myron-settings-layout--' . $normalizedVariant) . '" data-component-id="settings-layout" id="account-billing">';
        $html[] = '<div class="myron-settings-layout__nav">';
        $html[] = '<nav class="myron-sidebar-nav" aria-label="Account settings">';
        foreach (['Profile', 'Billing', 'Team'] as $index => $item) {
            $html[] = '<a class="myron-sidebar-nav__item' . ($index === 0 ? ' myron-sidebar-nav__item--active" aria-current="page' : '') . '" href="#account-' . $this->escape(myronNormalizeSlug($item)) . '">' . $this->escape($item) . '</a>';
        }
        $html[] = '</nav>';
        $html[] = '</div>';
        $html[] = '<div class="myron-settings-layout__content">';
        $html[] = '<h2 class="myron-heading myron-definition-section__title">Account settings</h2>';
        $html[] = '<p class="myron-paragraph myron-paragraph--muted">Subscription, team, and API settings use this governed shell before live provider data is connected.</p>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderCommerceCatalogSection(string $classes, string $variant, string $componentId, string $title, string $body, string $basePath, string $sourceTemplateId): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'catalog');
        $isEducationTemplate = str_contains($sourceTemplateId, '.edu.');
        $copy = $this->publicSectionBody(
            $body,
            $isEducationTemplate
                ? 'Course sorting controls are ready for published learning content.'
                : 'Featured products will appear here once catalog content is published.'
        );
        $products = [
            ['id' => 'everyday-tote', 'title' => 'Everyday Tote', 'priceCents' => 4800, 'price' => '$48.00', 'href' => '/shop/sample-product'],
            ['id' => 'desk-tray', 'title' => 'Desk Tray', 'priceCents' => 3400, 'price' => '$34.00', 'href' => '/shop/sample-product'],
            ['id' => 'travel-pouch', 'title' => 'Travel Pouch', 'priceCents' => 2800, 'price' => '$28.00', 'href' => '/shop/sample-product'],
        ];
        $html = [];
        $html[] = '<section class="' . $this->escape($classes . ' myron-public-component myron-public-component--contained myron-public-component--product-grid myron-commerce-catalog myron-commerce-catalog--' . $normalizedVariant) . '" data-component-id="' . $this->escape($componentId) . '" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-commerce-hook="catalog">';
        $html[] = '<div class="myron-product-grid__header">';
        $html[] = '<h2 class="myron-heading myron-definition-section__title myron-product-grid__title">' . $this->escape($title) . '</h2>';
        if ($copy !== '') {
            $html[] = '<div class="myron-definition-section__content">' . $this->paragraphs($copy) . '</div>';
        }
        $html[] = '</div>';
        if ($componentId === 'product-filters') {
            $html[] = '<div class="myron-product-grid__filters" aria-label="Product filters"><span>Category</span><span>Price</span><span>Availability</span></div>';
        } elseif ($componentId === 'product-sort-control') {
            $html[] = '<div class="myron-product-grid__sort" aria-label="' . ($isEducationTemplate ? 'Course sort' : 'Product sort') . '">' . ($isEducationTemplate ? 'Featured courses first' : 'Featured first') . '</div>';
        } else {
            $html[] = '<ul class="myron-product-grid__items" aria-label="Products">';
            foreach ($products as $product) {
                $html[] = '<li class="myron-product-grid__item">';
                $html[] = '<article class="myron-commerce-product-card">';
                $html[] = '<a class="myron-product-grid__link" href="' . $this->escape($this->routeHref($basePath, $product['href'])) . '">';
                $html[] = '<span class="myron-product-grid__media" aria-hidden="true"></span>';
                $html[] = '<span class="myron-commerce-product-card__body">';
                $html[] = '<span class="myron-product-grid__name">' . $this->escape($product['title']) . '</span>';
                $html[] = '<span class="myron-product-grid__price">' . $this->escape($product['price']) . '</span>';
                $html[] = '</span>';
                $html[] = '</a>';
                $html[] = '<button class="' . $this->escape($this->buttonClasses('primary', 'solid', 'sm')) . '" type="button" data-myron-cart-add data-myron-product-id="' . $this->escape($product['id']) . '" data-myron-product-title="' . $this->escape($product['title']) . '" data-myron-product-url="' . $this->escape($this->routeHref($basePath, $product['href'])) . '" data-myron-product-price-cents="' . $this->escape((string) $product['priceCents']) . '" data-myron-product-price-label="' . $this->escape($product['price']) . '" data-myron-product-quantity="1">Add to cart</button>';
                $html[] = '</article>';
                $html[] = '</li>';
            }
            $html[] = '</ul>';
        }
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderProductDetailSection(string $classes, string $variant, string $componentId, string $title, string $body, string $basePath, string $sourceTemplateId): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'detail');
        $copy = $this->publicSectionBody($body, 'Product details will appear here once catalog content is published.');
        $product = ['id' => 'everyday-tote', 'title' => 'Everyday Tote', 'priceCents' => 4800, 'price' => '$48.00', 'href' => '/shop/sample-product'];
        $html = [];
        $html[] = '<section class="' . $this->escape($classes . ' myron-public-component myron-public-component--contained myron-public-component--product-detail myron-product-detail myron-product-detail--' . $normalizedVariant) . '" data-component-id="' . $this->escape($componentId) . '" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-commerce-hook="product-detail">';
        $html[] = '<h2 class="myron-heading myron-definition-section__title">' . $this->escape($title) . '</h2>';
        $html[] = '<div class="myron-definition-section__content">' . $this->paragraphs($copy) . '</div>';
        $html[] = '<div class="myron-product-detail__actions"><span class="myron-product-detail__price">' . $this->escape($product['price']) . '</span><button class="' . $this->escape($this->buttonClasses()) . '" type="button" data-myron-cart-add data-myron-product-id="' . $this->escape($product['id']) . '" data-myron-product-title="' . $this->escape($product['title']) . '" data-myron-product-url="' . $this->escape($this->routeHref($basePath, $product['href'])) . '" data-myron-product-price-cents="' . $this->escape((string) $product['priceCents']) . '" data-myron-product-price-label="' . $this->escape($product['price']) . '" data-myron-product-quantity="1">Add to cart</button></div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderCartSummarySection(string $classes, string $variant, string $componentId, string $title, string $body, string $basePath, string $sourceTemplateId): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'cart');
        $copy = $this->publicSectionBody($body, 'Review cart items, totals, and proceed to checkout when commerce data is connected.');
        $html = [];
        $html[] = '<section class="' . $this->escape($classes . ' myron-public-component myron-public-component--contained myron-public-component--cart-summary myron-cart-summary myron-cart-summary--' . $normalizedVariant) . '" data-component-id="' . $this->escape($componentId) . '" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-commerce-hook="cart" data-myron-commerce-cart="cart" data-state="empty">';
        $html[] = '<div class="myron-public-section-header myron-cart-summary__header">';
        $html[] = '<h2 class="myron-heading myron-definition-section__title">' . $this->escape($title) . '</h2>';
        $html[] = '<p class="myron-paragraph myron-paragraph--muted">' . $this->escape($copy) . '</p>';
        $html[] = '</div>';
        $html[] = '<div class="myron-cart-summary__layout">';
        $html[] = '<div class="myron-cart-summary__items" aria-label="Cart items" data-myron-cart-items>';
        $html[] = '<p class="myron-cart-summary__empty" data-myron-cart-empty>Your cart is empty.</p>';
        $html[] = '</div>';
        $html[] = '<aside class="myron-cart-summary__panel" aria-label="Order summary">';
        $html[] = '<dl class="myron-cart-summary__totals"><div><dt>Subtotal</dt><dd data-myron-cart-subtotal>$0.00</dd></div><div><dt>Estimated total</dt><dd data-myron-cart-total>$0.00</dd></div></dl>';
        $html[] = '<a class="' . $this->escape($this->buttonClasses()) . '" href="' . $this->escape($this->routeHref($basePath, '/checkout')) . '">Checkout</a>';
        $html[] = '</aside>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderCheckoutSection(string $classes, string $variant, string $componentId, string $title, string $body, string $basePath, string $sourceTemplateId): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'checkout');
        $copy = $this->publicSectionBody($body, 'Complete delivery, payment, and review steps using the test checkout adapter.');
        $html = [];
        $html[] = '<section class="' . $this->escape($classes . ' myron-public-component myron-public-component--contained myron-public-component--checkout myron-checkout myron-checkout--' . $normalizedVariant) . '" data-component-id="' . $this->escape($componentId) . '" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-commerce-hook="checkout">';
        $html[] = '<div class="myron-public-section-header myron-checkout__header">';
        $html[] = '<h2 class="myron-heading myron-definition-section__title">' . $this->escape($title) . '</h2>';
        $html[] = '<p class="myron-paragraph myron-paragraph--muted">' . $this->escape($copy) . '</p>';
        $html[] = '</div>';
        $html[] = '<ol class="myron-checkout-stepper" aria-label="Checkout progress">';
        foreach ([['Cart', 'done'], ['Details', 'current'], ['Payment', 'upcoming'], ['Review', 'upcoming']] as $stepIndex => $step) {
            $stateClass = $step[1] === 'done' ? ' myron-checkout-stepper__step--done' : '';
            $current = $step[1] === 'current' ? ' aria-current="step"' : '';
            $html[] = '<li class="myron-checkout-stepper__step' . $stateClass . '"' . $current . '><span class="myron-checkout-stepper__step-indicator">' . ($stepIndex + 1) . '</span><span class="myron-checkout-stepper__step-label">' . $this->escape($step[0]) . '</span></li>';
        }
        $html[] = '</ol>';
        $html[] = '<div class="myron-checkout__layout">';
        $html[] = '<form class="myron-payment-form myron-checkout__form" data-commerce-hook="test-payment">';
        $html[] = '<label class="myron-form-field"><span class="myron-form-field__label">Email</span><input class="myron-input" type="email" name="email" autocomplete="email" placeholder="you@example.com"></label>';
        $html[] = '<label class="myron-form-field"><span class="myron-form-field__label">ZIP</span><input class="myron-input" type="text" name="postal_code" inputmode="numeric" placeholder="00000"></label>';
        $html[] = '<label class="myron-form-field myron-payment-form__full"><span class="myron-form-field__label">Test adapter reference</span><input class="myron-input" type="text" name="test_reference" value="TEST-CHECKOUT" readonly></label>';
        $html[] = '<p class="myron-payment-form__notice">Test adapter only. No payment credential is captured.</p>';
        $html[] = '<button class="' . $this->escape($this->buttonClasses()) . '" type="submit">Place test order</button>';
        $html[] = '</form>';
        $html[] = '<aside class="myron-cart-summary__panel myron-checkout__summary" aria-label="Order summary" data-myron-commerce-cart="checkout" data-state="empty">';
        $html[] = '<h3 class="myron-heading">Order summary</h3>';
        $html[] = '<div class="myron-cart-summary__items myron-checkout__summary-items" aria-label="Checkout cart items" data-myron-cart-items><p class="myron-cart-summary__empty" data-myron-cart-empty>Your cart is empty.</p></div>';
        $html[] = '<dl class="myron-cart-summary__totals"><div><dt>Subtotal</dt><dd data-myron-cart-subtotal>$0.00</dd></div><div><dt>Shipping</dt><dd>Calculated next</dd></div><div><dt>Estimated total</dt><dd data-myron-cart-total>$0.00</dd></div></dl>';
        $html[] = '</aside>';
        $html[] = '</div>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderBookingSection(string $classes, string $variant, string $componentId, string $title, string $body, string $sourceTemplateId): string
    {
        $normalizedVariant = myronNormalizeSlug($variant !== '' ? $variant : 'booking');
        $copy = $this->publicSectionBody($body, 'Choose a date, time, and party size. We will confirm availability before the reservation is final.');
        $html = [];
        $html[] = '<section class="' . $this->escape($classes . ' myron-public-component myron-public-component--contained myron-public-component--booking-form myron-booking-form myron-booking-form--' . $normalizedVariant) . '" data-component-id="' . $this->escape($componentId) . '" data-source-template-id="' . $this->escape($sourceTemplateId) . '" data-booking-hook="reservation">';
        $html[] = '<div class="myron-public-section-header myron-booking-form__header">';
        $html[] = '<h2 class="myron-heading myron-definition-section__title">' . $this->escape($title) . '</h2>';
        $html[] = '<p class="myron-paragraph myron-paragraph--muted">' . $this->escape($copy) . '</p>';
        $html[] = '</div>';
        $html[] = '<form class="myron-booking-form__fields" action="#" method="post">';
        $html[] = $this->renderPassivePublicFormProtection('booking-form');
        $html[] = '<label class="myron-form-field"><span class="myron-form-field__label">Date</span><input class="myron-input" type="date" name="reservation_date"></label>';
        $html[] = '<label class="myron-form-field"><span class="myron-form-field__label">Time</span><input class="myron-input" type="time" name="reservation_time"></label>';
        $html[] = '<label class="myron-form-field"><span class="myron-form-field__label">Party size</span><select class="myron-select" name="party_size"><option>2 guests</option><option>4 guests</option><option>6 guests</option></select></label>';
        $html[] = '<label class="myron-form-field myron-booking-form__requests"><span class="myron-form-field__label">Requests</span><textarea class="myron-textarea" name="requests" rows="4" placeholder="Add notes for the team"></textarea></label>';
        $html[] = '<button class="' . $this->escape($this->buttonClasses()) . '" type="submit">Continue</button>';
        $html[] = '</form>';
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function funnelStepKey(string $sourceTemplateId): string
    {
        $map = [
            'template.funnel.squeeze.mkt.v1' => 'squeeze',
            'template.funnel.bridge.mkt.v1' => 'bridge',
            'template.funnel.sales-long-form.mkt.v1' => 'sales',
            'template.funnel.checkout.mkt.v1' => 'checkout',
            'template.funnel.upsell.mkt.v1' => 'upsell',
            'template.funnel.downsell.mkt.v1' => 'downsell',
            'template.funnel.confirmation.mkt.v1' => 'confirmation',
            'template.funnel.expired.mkt.v1' => 'expired',
            'template.funnel.application.mkt.v1' => 'application',
            'template.funnel.challenge-enrollment.mkt.v1' => 'challenge-enrollment',
            'template.funnel.cancellation-retention.mkt.v1' => 'cancellation-retention',
            'template.funnel.free-plus-shipping-checkout.mkt.v1' => 'free-plus-shipping-checkout',
            'template.funnel.quiz.mkt.v1' => 'quiz',
            'template.funnel.reverse-squeeze.mkt.v1' => 'reverse-squeeze',
            'template.funnel.summit-hub.mkt.v1' => 'summit-hub',
            'template.funnel.vsl.mkt.v1' => 'vsl',
            'template.funnel.webinar-broadcast.mkt.v1' => 'webinar-broadcast',
            'template.funnel.webinar-confirmation.mkt.v1' => 'webinar-confirmation',
            'template.funnel.webinar-registration.mkt.v1' => 'webinar-registration',
            'template.funnel.webinar-replay.mkt.v1' => 'webinar-replay',
        ];

        return $map[$sourceTemplateId] ?? myronNormalizeSlug(str_replace(['template.funnel.', '.mkt.v1'], '', $sourceTemplateId));
    }

    private function funnelTitle(string $stepKey, string $fallback): string
    {
        $titles = [
            'squeeze' => 'Join the List',
            'bridge' => 'Watch the Bridge',
            'sales' => 'Tripwire Offer',
            'checkout' => 'Checkout',
            'upsell' => 'One-Time Upgrade',
            'downsell' => 'Alternate Offer',
            'confirmation' => 'Confirmation',
            'expired' => 'Offer Expired',
            'application' => 'Application',
            'challenge-enrollment' => 'Challenge Enrollment',
            'cancellation-retention' => 'Cancellation Retention',
            'free-plus-shipping-checkout' => 'Free Plus Shipping Checkout',
            'quiz' => 'Quiz',
            'reverse-squeeze' => 'Join the List',
            'summit-hub' => 'Summit Hub',
            'vsl' => 'Video Sales Letter',
            'webinar-broadcast' => 'Webinar Broadcast',
            'webinar-confirmation' => 'Webinar Confirmation',
            'webinar-registration' => 'Webinar Registration',
            'webinar-replay' => 'Webinar Replay',
        ];

        return $titles[$stepKey] ?? $fallback;
    }

    /**
     * @return array{label:string,href:string}
     */
    private function funnelCta(string $stepKey, string $componentId): array
    {
        $map = [
            'squeeze' => ['label' => 'Continue', 'href' => '/bridge'],
            'bridge' => ['label' => 'View the offer', 'href' => '/sales'],
            'sales' => ['label' => 'Start checkout', 'href' => '/checkout'],
            'checkout' => ['label' => 'Complete test checkout', 'href' => '/upsell'],
            'upsell' => ['label' => 'Add upgrade', 'href' => '/confirmation'],
            'downsell' => ['label' => 'Accept alternate offer', 'href' => '/confirmation'],
            'confirmation' => ['label' => 'Browse resources', 'href' => '/resources'],
            'expired' => ['label' => 'See current offers', 'href' => '/featured-offers'],
            'application' => ['label' => 'Submit application', 'href' => '/confirmation'],
            'challenge-enrollment' => ['label' => 'Join the challenge', 'href' => '/confirmation'],
            'cancellation-retention' => ['label' => 'Review options', 'href' => '/confirmation'],
            'free-plus-shipping-checkout' => ['label' => 'Complete test checkout', 'href' => '/upsell'],
            'quiz' => ['label' => 'See your result', 'href' => '/bridge'],
            'reverse-squeeze' => ['label' => 'Continue', 'href' => '/bridge'],
            'summit-hub' => ['label' => 'Start learning', 'href' => '/resources'],
            'vsl' => ['label' => 'Start checkout', 'href' => '/checkout'],
            'webinar-broadcast' => ['label' => 'Watch replay', 'href' => '/webinar-replay'],
            'webinar-confirmation' => ['label' => 'Join the webinar', 'href' => '/webinar-broadcast'],
            'webinar-registration' => ['label' => 'Reserve your spot', 'href' => '/webinar-confirmation'],
            'webinar-replay' => ['label' => 'View the offer', 'href' => '/sales'],
        ];

        if ($componentId === 'order-summary') {
            return ['label' => 'Review offer terms', 'href' => '/checkout'];
        }

        return $map[$stepKey] ?? ['label' => 'Continue', 'href' => '/'];
    }

    private function funnelFallbackBody(string $stepKey, string $componentId): string
    {
        if ($componentId === 'cms-embed') {
            return 'Video or embedded content will appear here once configured.';
        }
        if (in_array($componentId, ['checkout-address-form', 'payment-form', 'checkout-review', 'order-summary'], true)) {
            return 'Offer terms, deadline eligibility, and cancellation policy are surfaced for quality review.';
        }
        if (in_array($stepKey, ['application', 'quiz', 'webinar-registration'], true)) {
            return 'Collect the details needed to route this visitor to the right next step.';
        }
        if (in_array($stepKey, ['expired', 'confirmation'], true)) {
            return 'Confirm the current status and point visitors to the next governed destination.';
        }

        return 'Use this governed section to move visitors through the funnel.';
    }

    private function publicSectionBody(string $body, string $fallback): string
    {
        $trimmed = trim($body);
        if ($trimmed === '') {
            return $fallback;
        }

        $placeholderNeedles = [
            'This page was instantiated from',
            'This governed section is rendered from',
            'The active bundle supplied this page template',
            'The active bundle supplied this',
            'composition',
            'client / year / discipline metadata',
            'why-us-differentiators-block',
            'multiple instances in a grid',
            'grid of logo atoms',
        ];
        foreach ($placeholderNeedles as $needle) {
            if (str_contains($trimmed, $needle)) {
                return $fallback;
            }
        }

        return $trimmed;
    }

    private function paragraphs(string $value, ?bool $richtext = null): string
    {
        $trimmed = trim($value);
        if ($trimmed === '') {
            return '';
        }
        $renderRichtext = $richtext ?? $this->activeParagraphRichtext;
        if ($renderRichtext) {
            return $this->resolveMics(myronRichtextSanitize($trimmed));
        }

        $paragraphs = preg_split("/\\R{2,}/", $trimmed) ?: [$trimmed];
        $html = [];
        foreach ($paragraphs as $paragraph) {
            $html[] = '<p class="myron-paragraph">' . nl2br($this->escape(trim($paragraph))) . '</p>';
        }

        return implode("\n", $html);
    }

    private function routeHref(string $basePath, string $path): string
    {
        $trimmed = trim($path);
        if (str_starts_with($trimmed, '#')) {
            return $trimmed;
        }

        // STN-013-005: External / protocol-bearing URLs bypass path normalization.
        // Mirror contentHref's allowlist so reservation pages, contact CTAs, and
        // future tel:/mailto:/sms: links pass through unchanged. Without this guard,
        // myronNormalizePath() rejected `tel:+15551234567` and broke template renders.
        if (
            preg_match('#^(https?:)?//#i', $trimmed) === 1
            || preg_match('#^(mailto:|tel:|sms:)#i', $trimmed) === 1
        ) {
            return $trimmed;
        }

        // APO-184 Card 2 — split the input into (path, suffix) where suffix is
        // everything from the first `#` or `?` onward (whichever appears first).
        // Normalize only the path; re-append the suffix unchanged. This lets
        // internal URLs like `/contact#directions` or `/search?q=hello` pass
        // through `routeHref` without crashing `myronNormalizePath` (which
        // rejects `#` and `?` in its allowlist).
        $hashIdx  = strpos($trimmed, '#');
        $queryIdx = strpos($trimmed, '?');
        $cuts = array_filter([$hashIdx, $queryIdx], static fn ($i) => $i !== false);
        if ($cuts !== []) {
            $cutIdx   = min($cuts);
            $pathOnly = substr($trimmed, 0, $cutIdx);
            $suffix   = substr($trimmed, $cutIdx);
        } else {
            $pathOnly = $trimmed;
            $suffix   = '';
        }
        if ($pathOnly === '') {
            $pathOnly = '/';
        }

        $normalizedPath = myronNormalizePath($pathOnly);
        $siteRoot = $basePath === '' ? '' : $basePath;

        if ($normalizedPath === '/') {
            return ($siteRoot === '' ? '' : $siteRoot) . '/' . ltrim($suffix, '/');
        }

        return ($siteRoot === '' ? '' : $siteRoot) . $normalizedPath . $suffix;
    }

    private function contentHref(string $basePath, string $href): string
    {
        $trimmed = trim($href);
        if ($trimmed === '') {
            return '';
        }

        if (
            preg_match('#^(https?:)?//#i', $trimmed) === 1 ||
            preg_match('#^(mailto:|tel:|sms:)#i', $trimmed) === 1 ||
            str_starts_with($trimmed, '#')
        ) {
            return $trimmed;
        }

        if (str_starts_with($trimmed, '/')) {
            return $this->routeHref($basePath, $trimmed);
        }

        return $trimmed;
    }

    private function escape(string $value): string
    {
        return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
    }

    private function escapeRichtext(string $value, bool $singleLine): string
    {
        return $singleLine ? myronRichtextSanitize($value, ['singleLine' => true]) : $this->resolveMics(myronRichtextSanitize($value));
    }

    private function resolveMics(string $html): string
    {
        if ($html === '' || !str_contains($html, '[mic-')) {
            return $html;
        }

        $context = [
            'pageId' => $this->activeMicPageId,
            'fieldKey' => $this->activeMicFieldKey,
            'channel' => $this->activeMicChannel,
            'userScopes' => MyronApiScopes::ALL_BASE,
        ];

        return preg_replace_callback(
            '/\[mic-([a-z0-9._-]+)-(mic_[a-f0-9]{16})\]/',
            static function (array $matches) use ($context): string {
                $type = (string) ($matches[1] ?? '');
                $id = (string) ($matches[2] ?? '');
                $resolved = myronMicElementRegistry()->resolve($type, $id, $context);
                if (is_string($resolved) && $resolved !== '') {
                    return $resolved;
                }
                if ((string) ($context['channel'] ?? 'public') === 'public') {
                    return '';
                }
                return '<span class="myron-mic-missing" data-mic-id="' . myronEscape($id) . '">[missing: ' . myronEscape($type . '-' . $id) . ']</span>';
            },
            $html
        ) ?? $html;
    }

    /**
     * @param array<string, mixed> $section
     * @param array<string, mixed> $content
     * @return array<string, array{type:string,richtext:bool}>
     */
    private function richtextFieldMap(array $section, int $index, array $content): array
    {
        $map = [];
        $schemaService = function_exists('myronSectionContentSchemaService')
            ? myronSectionContentSchemaService()
            : new MyronSectionContentSchemaService($this->sectionRenderers);
        $schema = $schemaService->schemaForSection($section, $index, $content);
        $collect = static function (array $field) use (&$map): void {
            $key = (string) ($field['key'] ?? '');
            if ($key === '') {
                return;
            }
            $map[$key] = [
                'type' => (string) ($field['type'] ?? 'text'),
                'richtext' => filter_var($field['richtext'] ?? false, FILTER_VALIDATE_BOOL),
            ];
        };
        foreach ($schema['fields'] as $field) {
            if (is_array($field)) {
                $collect($field);
            }
        }
        foreach ($schema['repeaters'] as $repeater) {
            foreach (is_array($repeater['fields'] ?? null) ? $repeater['fields'] : [] as $field) {
                if (is_array($field)) {
                    $collect($field);
                }
            }
        }

        return $map;
    }

    private function buttonClasses(string $intent = 'primary', string $appearance = 'solid', string $size = 'md', string $extra = ''): string
    {
        return $this->presentation->buttonClasses($intent, $appearance, $size, $extra !== '' ? [$extra] : []);
    }

    private function cardClasses(string $tone = 'default', string $border = 'thin', string $padding = 'md', string $extra = ''): string
    {
        return $this->presentation->cardClasses($tone, $border, $padding, $extra !== '' ? [$extra] : []);
    }

    private function renderCreativeHeroParallax(array $section, string $variant, array $content, bool $primaryHeading = false): string
    {
        $safeVariant  = in_array($variant, ['dark', 'light'], true) ? $variant : 'default';
        $headline     = $this->escape(trim((string) ($content['headline'] ?? '')));
        $body         = $this->escape(trim((string) ($content['body']     ?? '')));
        $ctaLabel     = $this->escape(trim((string) ($content['cta']     ?? '')));
        $ctaHref      = $this->escape(trim((string) ($content['ctaHref'] ?? '#')));

        $headingTag = $primaryHeading ? 'h1' : 'h2';
        $headingClass = 'myron-creative-hero-parallax__headline';
        $headingHtml  = $headline !== '' ? "<{$headingTag} class=\"{$headingClass}\">{$headline}</{$headingTag}>" : '';
        $bodyHtml     = $body     !== '' ? "<p class=\"myron-creative-hero-parallax__body\">{$body}</p>" : '';
        $ctaClass     = $this->escape($this->buttonClasses('primary', 'solid', 'lg', 'myron-creative-hero-parallax__cta'));
        $ctaHtml      = $ctaLabel !== '' ? "<a class=\"{$ctaClass}\" href=\"{$ctaHref}\">{$ctaLabel}</a>" : '';

        return '<section class="myron-creative-hero-parallax myron-creative-hero-parallax--' . $safeVariant . '">'
            . '<div class="myron-creative-hero-parallax__content">'
            . $headingHtml
            . $bodyHtml
            . ($ctaHtml !== '' ? '<div class="myron-creative-hero-parallax__cta-wrapper">' . $ctaHtml . '</div>' : '')
            . '</div>'
            . '</section>';
    }

    private function renderScrolljackHero(string $variant, array $content, bool $primaryHeading = false): string
    {
        $safeVariant = myronNormalizeSlug($variant !== '' ? $variant : 'default');
        $stateCount = 0;
        for ($i = 1; $i <= 4; $i++) {
            $headline = trim((string) ($content['state_' . $i . '_headline'] ?? ''));
            $body = trim((string) ($content['state_' . $i . '_body'] ?? ''));
            $cta = trim((string) ($content['state_' . $i . '_cta_label'] ?? ''));
            if ($headline !== '' || $body !== '' || $cta !== '') {
                $stateCount = $i;
            }
        }
        $stateCount = max(2, min(4, $stateCount));

        $html = [];
        $html[] = '<section class="myron-scrolljack-hero myron-scrolljack-hero--' . $this->escape($safeVariant) . '" data-component-id="scrolljack-hero">';
        for ($i = 1; $i <= $stateCount; $i++) {
            $headline = trim((string) ($content['state_' . $i . '_headline'] ?? '')) ?: ($i === 1 ? 'Landing State One' : 'Landing State ' . $i);
            $body = trim((string) ($content['state_' . $i . '_body'] ?? '')) ?: 'Add CMS-managed landing copy for this state.';
            $ctaLabel = trim((string) ($content['state_' . $i . '_cta_label'] ?? ''));
            $ctaHref = trim((string) ($content['state_' . $i . '_cta_href'] ?? '/'));
            $headingTag = $primaryHeading && $i === 1 ? 'h1' : 'h2';
            $html[] = '<div class="myron-scrolljack-hero__state' . ($i === 1 ? ' is-active' : '') . '" data-mc-scrolljack-state="' . $i . '">';
            $html[] = '<div class="myron-scrolljack-hero__content">';
            $html[] = '<' . $headingTag . ' class="myron-scrolljack-hero__headline">' . $this->escape($headline) . '</' . $headingTag . '>';
            $html[] = '<p class="myron-scrolljack-hero__body">' . $this->escape($body) . '</p>';
            if ($ctaLabel !== '') {
                $html[] = '<div><a class="' . $this->escape($this->buttonClasses('primary', 'solid', 'lg')) . '" href="' . $this->escape($this->routeHref('/', $ctaHref)) . '">' . $this->escape($ctaLabel) . '</a></div>';
            }
            $html[] = '</div>';
            $html[] = '</div>';
        }
        $html[] = '</section>';

        return implode("\n", $html);
    }

    private function renderPassivePublicFormProtection(string $formKey): string
    {
        $issuedAt = (string) time();
        return '<input type="text" name="myron_company" value="" tabindex="-1" autocomplete="off" aria-hidden="true" hidden>'
            . '<input type="hidden" name="myron_form_key" value="' . $this->escape($formKey) . '">'
            . '<input type="hidden" name="myron_form_issued_at" value="' . $this->escape($issuedAt) . '">';
    }
}
