/*
 * v2 progressive preview layout.
 *
 * The live journey now renders the real CMS site in an iframe. The older
 * .ai-wf rules remain below temporarily so the engine can be removed in a
 * separate, low-risk cleanup after the new preview has completed staging.
 */

.ai-v2-layout-grid {
    display: flex;
    flex-direction: column;
    gap: 2rem;
}

.ai-v2-wf-panel {
    width: 100%;
}

@media (min-width: 992px) {
    .ai-step-card.ai-step-card--builder {
        max-width: 1120px;
    }

    .ai-v2-layout-grid {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(390px, 0.9fr);
        align-items: start;
        gap: 2.25rem;
    }

    .ai-v2-wf-panel {
        position: sticky;
        top: 1.25rem;
    }
}

.ai-v2-wf-caption {
    text-align: center;
    margin-top: 0.75rem;
    font-size: 0.85rem;
}

/* ── Real-site progressive preview ─────────────────────────────────── */
.ai-v2-site-preview {
    /* Preview-only Seamless starting recommendation. JavaScript reads these
       tokens before Colours; it never persists them as a tenant palette. */
    --seamless-preview-primary: #111111;
    --seamless-preview-secondary: #ffffff;
    --seamless-preview-background: #111111;
    border: 1px solid #d8dee8;
    border-radius: 16px;
    background: #ffffff;
    box-shadow: 0 18px 45px rgba(15, 23, 42, 0.10);
    overflow: hidden;
}

.ai-v2-site-preview__topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.9rem 1rem;
    background: #f8fafc;
    border-bottom: 1px solid #e2e8f0;
}

.ai-v2-site-preview__eyebrow,
.ai-v2-site-preview__headline {
    display: block;
}

.ai-v2-site-preview__eyebrow {
    color: #64748b;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

.ai-v2-site-preview__headline {
    color: #0f172a;
    font-size: 0.9rem;
}

.ai-v2-site-preview__open,
.ai-v2-site-preview__close {
    border: 0;
    background: #0f2742;
    color: #ffffff;
    border-radius: 8px;
    padding: 0.6rem 0.8rem;
    font-weight: 700;
}

.ai-v2-site-preview__open,
.ai-v2-site-preview__close {
    display: none;
}

.ai-v2-site-preview__stage {
    position: relative;
    min-height: 250px;
    background: #eef2f7;
}

.ai-v2-site-preview__nav {
    position: relative;
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.55rem 0.7rem;
    background: #ffffff;
    border-bottom: 1px solid #e2e8f0;
}

.ai-v2-site-preview__mode {
    color: #64748b;
    font-size: 0.72rem;
    font-weight: 700;
}

.ai-v2-site-preview__pages {
    display: flex;
    gap: 0.3rem;
}

.ai-v2-site-preview__page {
    border: 1px solid #d8dee8;
    border-radius: 999px;
    padding: 0.3rem 0.62rem;
    background: #ffffff;
    color: #475569;
    font-size: 0.72rem;
    font-weight: 700;
}

.ai-v2-site-preview__page:hover,
.ai-v2-site-preview__page--active {
    border-color: #0f2742;
    background: #0f2742;
    color: #ffffff;
}

.ai-v2-site-preview__viewport {
    width: 100%;
    overflow: hidden;
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 0.45s ease, transform 0.45s ease;
}

.ai-v2-site-preview--ready .ai-v2-site-preview__viewport {
    opacity: 1;
    transform: translateY(0);
}

.ai-v2-site-preview iframe {
    display: block;
    border: 0;
    transform-origin: top left;
    pointer-events: auto;
    background: #ffffff;
}

.ai-v2-site-preview__loading {
    position: absolute;
    z-index: 2;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.65rem;
    color: #334155;
    font-weight: 700;
    background: rgba(248, 250, 252, 0.88);
    backdrop-filter: blur(3px);
    transition: opacity 0.35s ease;
}

.ai-v2-site-preview__loading.d-none {
    display: none !important;
}

.ai-v2-site-preview__spark {
    width: 13px;
    height: 13px;
    border-radius: 4px;
    background: #2f6fed;
    transform: rotate(45deg);
    animation: ai-preview-spark 1.15s ease-in-out infinite;
}

.ai-v2-site-preview--working .ai-v2-site-preview__stage::after {
    content: '';
    position: absolute;
    z-index: 1;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(105deg, transparent 30%, rgba(255,255,255,0.65) 49%, transparent 68%);
    background-size: 240% 100%;
    animation: ai-preview-wash 1.8s linear infinite;
}

.ai-v2-site-preview__hint {
    margin: 0;
    padding: 0.7rem 1rem;
    color: #64748b;
    font-size: 0.78rem;
    text-align: center;
    border-top: 1px solid #e2e8f0;
}

@keyframes ai-preview-spark {
    0%, 100% { transform: rotate(45deg) scale(0.75); opacity: 0.55; }
    50% { transform: rotate(135deg) scale(1.15); opacity: 1; }
}

@keyframes ai-preview-wash {
    from { background-position: 140% 0; }
    to { background-position: -80% 0; }
}

@media (prefers-reduced-motion: reduce) {
    .ai-v2-site-preview__spark,
    .ai-v2-site-preview--working .ai-v2-site-preview__stage::after {
        animation: none;
    }
    .ai-v2-site-preview__viewport {
        transition: none;
    }
}

@media (max-width: 767px) {
    .ai-v2-site-preview {
        box-shadow: none;
        overflow: visible;
    }

    .ai-v2-site-preview__open {
        display: inline-flex;
    }

    .ai-v2-site-preview__stage,
    .ai-v2-site-preview__hint {
        display: none;
    }

    .ai-v2-site-preview--open {
        position: fixed;
        z-index: 1080;
        inset: 0;
        border: 0;
        border-radius: 0;
        background: #eef2f7;
    }

    .ai-v2-site-preview--open .ai-v2-site-preview__stage {
        display: block;
        height: calc(100vh - 70px);
        overflow: auto;
    }

    .ai-v2-site-preview__nav {
        flex-wrap: wrap;
    }

    .ai-v2-site-preview--open .ai-v2-site-preview__hint,
    .ai-v2-site-preview--open .ai-v2-site-preview__close {
        display: block;
    }

    .ai-v2-site-preview--open .ai-v2-site-preview__open {
        display: none;
    }

    .ai-v2-site-preview--open iframe {
        pointer-events: auto;
    }

    body.ai-v2-preview-open {
        overflow: hidden;
    }
}

.ai-wf {
    --wf-primary:    #d1d5db;
    --wf-secondary:  #9ca3af;
    --wf-background: #f3f4f6;
    --wf-highlight-bg: #e5e7eb;
    --wf-highlight-text: #9ca3af;
    --wf-block:      #e5e7eb;
    --wf-block-mid:  #d1d5db;
    --wf-radius:     10px;
    --wf-font:       Georgia, 'Times New Roman', serif;

    position: relative;
    background: var(--wf-background);
    border-radius: 16px;
    border: 1px solid rgba(0, 0, 0, 0.06);
    padding: 0;
    overflow: hidden;
    transition: background-color 0.6s ease, border-radius 0.4s ease;
}

/* ── Entrance — blocks converge into place rather than uniformly fading
   up, closer to pieces assembling than a single slide. Alternating
   --wf-from-x per block (set in JS) makes them visibly approach from
   different sides; scale(0.85) plus an overshoot ("back out") easing
   gives a satisfying snap as each one settles, rather than a plain
   linear arrival. Delay is set per-block via inline --wf-delay by
   wizard-wireframe.js at render time, not nth-child, since block count
   varies between multi/scroll layouts. ── */
.ai-wf-block {
    opacity: 0;
    transform: scale(0.85) translate(var(--wf-from-x, 0), 14px);
    animation: ai-wf-enter 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
    animation-delay: var(--wf-delay, 0s);
}

@keyframes ai-wf-enter {
    to { opacity: 1; transform: scale(1) translate(0, 0); }
}

/* ── Ambient movement — one continuous light wave passing across the
   whole panel, not each block animating independently. A single overlay
   on the container itself (clipped neatly by .ai-wf's own overflow:hidden
   and rounded corners, no extra work needed) reads as one coherent
   "something is happening" motion, closer to a real loading wave than a
   handful of blocks pulsing out of sync would. Previously an opacity
   breathe on individual blocks, deliberately not a wave, specifically to
   avoid the "still loading" connotation — the wave shown here now is a
   considered reversal of that choice, not something that changed by
   accident. Off entirely for anyone who's asked for less motion. ── */
@media (prefers-reduced-motion: no-preference) {
    .ai-wf::after {
        content: '';
        position: absolute;
        inset: 0;
        pointer-events: none;
        background: linear-gradient(
            100deg,
            transparent 30%,
            rgba(255, 255, 255, 0.35) 48%,
            rgba(255, 255, 255, 0.55) 50%,
            rgba(255, 255, 255, 0.35) 52%,
            transparent 70%
        );
        background-size: 300% 100%;
        animation: ai-wf-wave 3.2s ease-in-out 1s infinite;
    }
}

@keyframes ai-wf-wave {
    0%   { background-position: 130% 0; }
    100% { background-position: -30% 0; }
}

/* ── Vibe reactivity — "subtle" softens corners with a light hue shift,
   a genuinely small change since it's meant to read as barely different
   from the default. "Seamless" is not a hue shift — it's an actual dark
   mode: dark background, light text, since that's how it's expected to
   be used in practice. Originally built as a couple of hex values apart
   from the default, which — confirmed directly, not assumed — looked
   near-identical to Colour blocks at this small scale. Rebuilt as
   explicit per-element overrides rather than relying on the two shared
   --wf-block/--wf-block-mid variables alone: those two are used
   inconsistently across this file for both "surface" and "text-ish
   line" purposes depending on the element (traced through by hand
   before rebuilding this — several elements would have gone invisible,
   dark text on a dark background, if the variables alone were swapped),
   so correctness here means naming every element that needs to flip,
   not hoping two variables cascade correctly through rules that don't
   share one consistent meaning. ── */
.ai-wf--subtle {
    --wf-block: #ede9e4;
    --wf-block-mid: #ddd5c8;
    border-radius: 22px;
}
.ai-wf--subtle .ai-wf-nav,
.ai-wf--subtle .ai-wf-photo,
.ai-wf--subtle .ai-wf-btn,
.ai-wf--subtle .ai-wf-logo,
.ai-wf--subtle .ai-wf-page-card,
.ai-wf--subtle .ai-wf-section-block {
    border-radius: 14px;
}

/* Seamless's whole dark treatment used to be dozens of hardcoded
   per-selector overrides below (nav, footer, cards, every text line,
   photo placeholders, each given their own explicit dark/light colour).
   Replaced with overriding just the root custom properties instead — now
   that every consuming rule genuinely references --wf-primary/-secondary/
   -background/-block/-nav-text/-text-on-bg rather than being hardcoded
   itself, Seamless doesn't need its own special-cased version of each
   one; it falls out automatically from primary and background being
   equal, the same way it does on the real site (see the hero/nav
   comments above — Seamless isn't a distinct code path there either,
   it's just what these same universal rules produce once the two
   colours match). This is what "we don't want hardcoded colours
   anywhere" means in practice, applied to the wireframe's own vibe
   defaults, not just the real site's tenant colours. */
.ai-wf--seamless {
    --wf-primary:    #1f2937;
    --wf-secondary:  #e5e7eb;
    --wf-background: #1f2937;
    --wf-block:      #6b7280;
    --wf-block-mid:  #6b7280;
}

/* ── Tone reactivity — purely a corner/weight signal, not colour (no
   real palette exists yet at Basics, where tone is chosen — that comes
   later at Colours). The point is visual flow: picking a tone should
   visibly react on the page you're already looking at, the same way
   every other choice in this wizard already does, not just get quietly
   recorded for later. Corporate & trusted deliberately gets no override
   at all — it's the baseline the other four are variations from, not
   an oversight. ── */
.ai-wf--tone-bold .ai-wf-nav,
.ai-wf--tone-bold .ai-wf-photo,
.ai-wf--tone-bold .ai-wf-btn,
.ai-wf--tone-bold .ai-wf-logo,
.ai-wf--tone-bold .ai-wf-page-card,
.ai-wf--tone-bold .ai-wf-section-block,
.ai-wf--tone-bold .ai-wf-mini-photo {
    border-radius: 4px;
}
.ai-wf--tone-bold { border-radius: 8px; }
.ai-wf--tone-bold .ai-wf-line--lg,
.ai-wf--tone-bold .ai-wf-headline-text {
    font-weight: 800;
}

.ai-wf--tone-warm .ai-wf-nav,
.ai-wf--tone-warm .ai-wf-photo,
.ai-wf--tone-warm .ai-wf-btn,
.ai-wf--tone-warm .ai-wf-logo,
.ai-wf--tone-warm .ai-wf-page-card,
.ai-wf--tone-warm .ai-wf-section-block,
.ai-wf--tone-warm .ai-wf-mini-photo {
    border-radius: 18px;
}
.ai-wf--tone-warm { border-radius: 26px; }

.ai-wf--tone-minimal .ai-wf-nav,
.ai-wf--tone-minimal .ai-wf-photo,
.ai-wf--tone-minimal .ai-wf-btn,
.ai-wf--tone-minimal .ai-wf-logo,
.ai-wf--tone-minimal .ai-wf-page-card,
.ai-wf--tone-minimal .ai-wf-section-block,
.ai-wf--tone-minimal .ai-wf-mini-photo,
.ai-wf--tone-minimal .ai-wf-line,
.ai-wf--tone-minimal .ai-wf-line--sm {
    border-radius: 2px;
}
.ai-wf--tone-minimal { border-radius: 4px; }
.ai-wf--tone-minimal .ai-wf-line,
.ai-wf--tone-minimal .ai-wf-line--sm {
    opacity: 0.75;
}

.ai-wf--tone-modern .ai-wf-nav,
.ai-wf--tone-modern .ai-wf-photo,
.ai-wf--tone-modern .ai-wf-logo,
.ai-wf--tone-modern .ai-wf-page-card,
.ai-wf--tone-modern .ai-wf-section-block,
.ai-wf--tone-modern .ai-wf-mini-photo {
    border-radius: 14px;
}
.ai-wf--tone-modern { border-radius: 20px; }
.ai-wf--tone-modern .ai-wf-btn {
    border-radius: 999px;
}

/* ── Nav ── */
.ai-wf-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 20px;
    /* Confirmed directly against tenant_themes.css:
       .navbar { background-color: var(--brand-hero-bg) !important; }
       — the navbar always matches the hero's colour on the real site,
       every template, not something specific to any one vibe. This was
       previously the page background, matching nothing about the real
       templates for any vibe other than the ones where primary happens
       to equal background anyway. */
    background-color: var(--wf-primary);
    border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}

.ai-wf-logo {
    width: 76px;
    height: 16px;
    border-radius: 4px;
    /* --wf-nav-text, not --wf-primary — the logo placeholder now sits on
       a primary-coloured navbar, so it needs the same contrast check as
       nav links, not the brand colour itself (which would make an
       unfilled logo invisible against a nav that's the same colour). */
    background-color: var(--wf-nav-text, var(--wf-block-mid));
    background-size: cover;
    background-position: center;
}

.ai-wf-logo--filled {
    background-color: transparent;
}

.ai-wf-nav-links {
    display: flex;
    gap: 14px;
}

.ai-wf-nav-links .ai-wf-line {
    width: 34px;
    height: 8px;
    /* Same reasoning as the logo above — nav links sit on the primary-
       coloured navbar now, not a neutral background, so they need
       contrast against that specifically. */
    background-color: var(--wf-nav-text, var(--wf-block-mid));
}

/* ── Generic filled elements ── */
.ai-wf-line {
    height: 10px;
    border-radius: 4px;
    background: var(--wf-block-mid);
}

.ai-wf-line--lg  { height: 22px; width: 70%; border-radius: 6px; background: var(--wf-primary); }
.ai-wf-line--md  { height: 14px; width: 55%; }
.ai-wf-line--sm  { height: 9px;  width: 40%; background: var(--wf-block); }

/* ── Real headline text — replaces the grey placeholder line once a
   company name is known. Uses --wf-font, not the page's own default body
   font — the previous version only set weight/size/colour and inherited
   whatever the surrounding page used, which read as plain text rather
   than an actual heading. Defaults to a generic serif so it looks like a
   real headline from the start; once a real font is chosen at Colours,
   --wf-font is updated to match it, so the wireframe's own text starts
   genuinely previewing the real typeface, not just its size and weight.
   Colour comes from --wf-text-on-bg, not a fixed value — set from JS in
   applyStyle(): a sensible dark/light default from vibe before any real
   palette exists, then a genuine YIQ contrast check against the real
   background colour once one's chosen, so the headline stays readable
   regardless of what's actually behind it rather than assuming dark
   text always works. The #1a1a1a here is only the fallback for the rare
   case the property is never set at all (shouldn't happen in practice,
   since every render()/update() call already provides a vibe) — matches
   cms/utils.py's own _yiq_contrast dark value exactly, not a different
   dark colour that happens to look similar. ── */
.ai-wf-line.ai-wf-headline-text {
    height: auto;
    width: auto;
    max-width: 100%;
    border-radius: 0;
    background: none;
    animation: ai-wf-enter 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
    animation-delay: var(--wf-delay, 0s);
    font-family: var(--wf-font);
    font-weight: 700;
    font-size: 1.15rem;
    line-height: 1.3;
    color: var(--wf-text-on-bg, #1a1a1a);
    overflow-wrap: break-word;
}

.ai-wf-photo {
    background: var(--wf-block);
    border-radius: var(--wf-radius);
    background-size: cover;
    background-position: center;
}

/* The hero's own subtext line — the one .ai-wf-line--sm that lives
   directly in hero-content, not inside a section/page-card. Previously
   used the same fixed --wf-block grey as every other subtext line on
   the page, which was already wrong before this pass whenever a real
   primary colour happened to be dark: hero-content now always sits on
   --wf-primary (except "photo behind", where --wf-text-on-bg already
   accounts for that — see applyStyle()'s own comments), so this needs
   the same computed contrast the headline right above it already gets,
   not a flat neutral colour that doesn't react to what's actually behind
   it. */
.ai-wf-hero-content .ai-wf-line--sm {
    background-color: var(--wf-text-on-bg, var(--wf-block));
}

.ai-wf-btn {
    height: 30px;
    width: 96px;
    border-radius: 999px;
    /* Confirmed directly against tenant_themes.css: .btn-primary uses
       --brand-secondary, not --brand-primary, in both the hero and body
       contexts. This was previously primary. */
    background: var(--wf-secondary);
}


/* ── Hero — layout varies by photo placement, set via a modifier class
   from wizard-wireframe.js rather than separate markup per placement. ── */
.ai-wf-hero {
    padding: 28px 20px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    /* Confirmed directly against tenant_themes.css:
       .hero-section { background-color: var(--brand-primary) !important; }
       applies unconditionally on the real site — every hero variant, not
       just the no-photo one. For "photo behind", the photo covers this
       entirely (harmless to still set it underneath); for "photo left/
       right", the text column's own background genuinely is this colour
       on the real site, which the wireframe didn't show at all before
       this pass — it was previously transparent for every photo variant,
       matching nothing about the real templates. */
    background-color: var(--wf-primary);
}

/* Hero colour is now set universally on .ai-wf-hero itself, above — this
   modifier only ever needed the layout change (single-column, no photo
   flex sibling), not its own colour rule. Seamless no longer needs a
   special-case override here either: once primary and background are
   equal, .ai-wf-hero's own background-color naturally matches the page
   underneath it, with no separate rule required to make that happen. */
.ai-wf-hero--behind {
    position: relative;
    padding: 40px 20px;
    min-height: 140px;
    justify-content: center;
}

.ai-wf-hero--behind .ai-wf-photo {
    position: absolute;
    inset: 0;
    border-radius: 0;
    z-index: 0;
}

.ai-wf-hero--behind .ai-wf-hero-content {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.ai-wf-hero--side {
    flex-direction: row;
    align-items: center;
    gap: 20px;
}

.ai-wf-hero--side.ai-wf-hero--left  { flex-direction: row-reverse; }

.ai-wf-hero--side .ai-wf-photo {
    flex: 0 0 38%;
    height: 100px;
}

.ai-wf-hero--side .ai-wf-hero-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.ai-wf-hero--no-photo .ai-wf-hero-content {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* ── Sections — multi-page shows separate page cards; scroll shows
   stacked full-width sections. Same block language, different shape,
   so switching layout mid-wizard reads as a real structural change. ── */
.ai-wf-sections {
    padding: 18px 20px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.ai-wf-sections--pages {
    flex-direction: row;
    gap: 10px;
}

.ai-wf-page-card {
    flex: 1;
    background: var(--wf-highlight-bg, var(--wf-block));
    border-radius: var(--wf-radius);
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* Confirmed directly against tenant_themes.css:
   .agency-site section:not(.hero-section) h1/h2/h3/p { color: var(--brand-secondary); }
   — body text outside the hero is coloured with secondary on the real
   site, not a neutral grey. This was previously a flat rgba(255,255,255,.6)
   placeholder value, matching nothing about the real templates. Highlight/
   "why work with us" cards are a genuine exception on the real site —
   governed by their own separate branching in cms/utils.py's
   _compute_highlight_colours (Executive uses background, Bold/Impact/
   Pulse use primary, everything else uses secondary) — not reflected
   here, since the wireframe doesn't have a dedicated highlight-card
   element distinct from these generic section/page-card surfaces; About/
   Jobs/Contact aren't the same thing as the real "why work with us"
   cards at all. */
.ai-wf-page-card .ai-wf-line { background-color: var(--wf-highlight-text, var(--wf-secondary)); }

.ai-wf-section-block {
    background: var(--wf-highlight-bg, var(--wf-block));
    border-radius: var(--wf-radius);
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.ai-wf-section-block .ai-wf-line { background-color: var(--wf-highlight-text, var(--wf-secondary)); }

/* ── Team/about photo — the one place a photo appears inside the sections
   area rather than the hero or nav. Only the About card/section gets one
   (Jobs and Contact stay text-only), matching where the team photo
   actually appears on the real site. Smaller and squarer than the hero
   photo — a supporting image, not the page's main visual. ── */
.ai-wf-mini-photo {
    width: 36px;
    height: 36px;
    border-radius: 8px;
    background: var(--wf-block-mid);
    background-size: cover;
    background-position: center;
    flex-shrink: 0;
}

.ai-wf-mini-photo--filled {
    background-color: transparent;
}

/* ── Footer ── */
.ai-wf-footer {
    padding: 16px 20px;
    border-top: 1px solid rgba(0, 0, 0, 0.06);
    display: flex;
    gap: 24px;
    /* Confirmed directly against tenant_themes.css: footer uses
       --brand-bg for its own background (not primary — it isn't
       nav/hero-coloured) and --brand-secondary for its text. This was
       previously unset (inheriting the page's own --wf-background
       implicitly, which happens to be correct by coincidence, not
       because this rule said so) — made explicit here so it's no longer
       accidental. */
    background-color: var(--wf-background);
}

.ai-wf-footer .ai-wf-line {
    width: 60px;
    height: 7px;
    background-color: var(--wf-secondary);
}


/* ── Mobile ── */
@media (max-width: 576px) {
    .ai-wf-hero--side { flex-direction: column; }
    .ai-wf-hero--side.ai-wf-hero--left { flex-direction: column; }
    .ai-wf-hero--side .ai-wf-photo { width: 100%; flex-basis: auto; }
    .ai-wf-sections--pages { flex-direction: column; }
}
