/* ==========================================================================
   KB Home Creations (Section 03) — Atlasyn × Khaoula Bouabidi
   Scoped strictly to .kb-home-creations. All values driven by tokens.css.

   Desktop composition (final):
     Section outer: full-bleed Porcelain surface, padded 100px top + 100px
     bottom using --kb-section-space-desktop so the visible gap from
     Section 02 is exactly the design-system spacing — no Elementor
     container margin, no duplicate theme padding, no arbitrary offset.

     Inner composition: aligned to var(--kb-content-width) (1140px),
     three-column CSS grid split ≈ 30% / 50% / 20%:
       LEFT    — eyebrow / H2 / intro paragraph
       CENTER  — stable aspect-ratio artboard hosting the three 3-image
                 slide compositions stacked on top of each other. The
                 active slide is fully visible; the inactive slides
                 are absolutely positioned inside the same artboard
                 so the section height NEVER jumps between slides.
       RIGHT   — tablist (01 | 02 | 03), active-creation info block
                 (large number + name + subtitle + restrained
                 editorial text link "Découvrir →"), prev/next square
                 outline controls, and a bottom index listing the two
                 non-active creations.

   Elementor contract: every image is still a real <img> selected
   through MEDIA content controls. No inline style="background-image"
   is ever emitted by the widget. All visual layering lives here in
   the child-theme CSS. Figures have NO background, padding, border,
   radius, shadow or overflow — they exist only for position, width
   and z-index, so the transparent pixels of each PNG are preserved.

   State architecture (vanilla JS, no Swiper/Slick):
     .kb-home-creations__slide.is-active         → visible
     .kb-home-creations__tab.is-active           → gold + underline
     .kb-home-creations__info-panel.is-active    → visible

     The script lives in assets/js/home-creations.js and is registered
     as a script dependency of the widget. The script is the single
     source of truth (activeIndex). It atomically toggles .is-active
     on slide, tab, info panel and lower-list item in one pass.

     Crossfade transitions (no horizontal slider movement, no scale):
       - image slide: opacity + translateY 6px → 0, 950ms
       - info panel:  opacity + translateY 6px → 0, 750ms
       - easing:      --kb-reveal-easing
                      (cubic-bezier(0.22, 1, 0.36, 1))

     Visual state uses ONLY opacity + pointer-events + z-index.
     `visibility` is intentionally NOT used (it was making the
     fade harder to reason about). Accessibility (aria-hidden /
     inert / tabindex on inactive links) is owned by JS.

     There are three complete independent .kb-home-creations__info-panel
     elements (one per creation, each permanently carrying its own
     number / name / subtitle / Découvrir link) and only one ever
     carries .is-active at a time. Inactive panels are
     opacity: 0 + pointer-events: none + z-index: 1.
     The active panel is opacity: 1 + pointer-events: auto + z-index: 2.

     The lower alternate list is three compact <li> rows. The one
     matching the active creation is display:none via .is-hidden,
     so the list always shows exactly the two non-active creations.
   ========================================================================== */

/* ==========================================================================
   FULL-BLEED ESCAPE — Section 03
   ------------------------------------------------------------
   Same surgical pattern as Sections 01 and 02. The parent theme's
   .atlasyn-container + Elementor's .e-con would otherwise center
   this section with side margins and add default block padding
   on top of our 100px, producing a 200px gap. Scoped strictly via
   :has(.kb-home-creations) so unrelated .e-con containers stay
   untouched.
   ========================================================================== */

.e-con:has(.kb-home-creations) {
    --container-default-width: 100% !important;
    --container-max-width: 100% !important;
    --container-default-padding: 0px !important;
    --container-default-padding-block: 0px !important;
    --container-default-padding-inline: 0px !important;
    width: 100% !important;
    max-width: 100% !important;
    margin-inline: 0 !important;
    padding-inline: 0 !important;
    padding-block: 0 !important;
}

.e-con:has(.kb-home-creations) > .e-con-inner {
    width: 100% !important;
    max-width: 100% !important;
    margin: 0 !important;
    padding: 0 !important;
    --container-default-padding: 0px !important;
    --container-default-padding-block: 0px !important;
    --container-default-padding-inline: 0px !important;
}

/* ==========================================================================
   Section root
   Single source of truth for the 100px gap to Section 02 above AND
   the 100px gap to Section 04 below. Elementor / theme / .e-con
   padding is already neutralized above.
   ========================================================================== */
.kb-home-creations {
    position: relative;
    width: 100%;
    background-color: var(--kb-porcelain);
    color: var(--kb-ink);
    /* Section-to-section gap is owned by THIS section's top padding
       only (no matching bottom padding). The previous section has
       padding-bottom: 0, so the visual gap to this section is
       exactly --kb-section-space-desktop. The next section will
       own its own top padding. */
    padding-top: var(--kb-section-space-desktop);
    overflow: hidden;
}

/* ==========================================================================
   Inner composition — 1140px content frame
   Three-column grid: left editorial copy (~30fr) + center stage
   (~50fr) + right control panel (~20fr). Same 1140px ceiling as
   the global token, no side gutters above 1140px. Centered
   horizontally. align-items: center so the left copy and the
   center artboard share a common vertical center; the right
   panel uses align-self: stretch so the editorial controls can
   sit in their natural reading column.
   ========================================================================== */
.kb-home-creations__inner {
    width: 100%;
    max-width: var(--kb-content-width);
    margin-inline: auto;
    display: grid;
    /* Three-column editorial spread.
       Side columns are sized with minmax so they hold a fixed
       editorial reading width even when the viewport is wider
       than 1140px; the center column is the dominant 1fr so the
       image stage always claims the remaining space. */
    grid-template-columns:
        minmax(240px, 270px)
        minmax(0, 1fr)
        minmax(180px, 210px);
    /* Luxury breathing room between the three blocks. Scales
       fluidly with the viewport but never collapses below 48px
       and never exceeds 64px so the rhythm stays editorial. */
    column-gap: clamp(48px, 4vw, 64px);
    align-items: center;
    position: relative;
    z-index: 1;
}

/* ==========================================================================
   LEFT — editorial copy column
   Vertical rhythm follows the design system hierarchy:
   eyebrow -> title -> intro paragraph.
   The right column is the action surface; the left never
   receives CTAs, buttons or the carousel controls.
   ========================================================================== */
.kb-home-creations__left {
    min-width: 0;
    display: flex;
    align-items: center;
}

.kb-home-creations__copy {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    min-width: 0;
    max-width: 28ch;
}

/* Eyebrow — typography + spacing owned by the canonical
   .kb-section-eyebrow primitive in base.css. No leading or trailing
   Gold hairline. No title underline. */
.kb-home-creations__eyebrow {
    /* No-op — typography / color / spacing owned by .kb-section-eyebrow. */
}

.kb-home-creations__title {
    margin: 0 0 var(--kb-space-l) 0;
    font-family: var(--kb-font-display);
    font-size: 44px;
    font-weight: 300;
    line-height: 1.1;
    letter-spacing: -0.005em;
    color: var(--kb-ink);
    text-wrap: balance;
}

.kb-home-creations__intro {
    margin: 0;
    font-family: var(--kb-font-body);
    font-size: 15px;
    font-weight: 400;
    line-height: 1.7;
    color: var(--kb-ink);
    text-wrap: pretty;
}

/* ==========================================================================
   CENTER — stable artboard + slide compositions
   The stage is a single relative box with a fixed aspect-ratio
   so that switching ÉCLAT → AURA → NOIR never changes the section
   height. Every slide is absolutely positioned inside the same
   artboard; only the active one is opaque + non-translated.
   Inactive slides remain in the DOM (no mount/unmount) so the
   browser never reflows.

   The collage inside each slide uses three transparent cutout
   layers (main / portrait / landscape) placed at percentage
   positions. Figures are wrappers only — no background, no
   padding, no border, no radius, no overflow — so the
   transparent pixels of every PNG are preserved exactly.
   ========================================================================== */
.kb-home-creations__center {
    min-width: 0;
}

.kb-home-creations__stage {
    position: relative;
    width: 100%;
    aspect-ratio: 0.86 / 1; /* slightly taller than wide, like the reference spread */
    overflow: visible;
    background: transparent;
}

/* Slide base — one wrapper, three layers. The whole wrapper
   is the single object that animates on slide change so the
   three images never enter independently.

   Pure editorial crossfade. NO horizontal movement, NO scale.
   Only a barely-there vertical lift (translateY 6px → 0) so the
   new composition arrives with a faint breath. 950ms with the
   shared --kb-reveal-easing (cubic-bezier(0.22, 1, 0.36, 1))
   for the calmest, most couture hand-off.

   Inactive slides sit below the active one (z-index 1) so the
   active one always wins the crossfade overlap. */
.kb-home-creations__slide {
    position: absolute;
    inset: 0;
    margin: 0;
    padding: 0;
    background: transparent;
    opacity: 0;
    transform: translate3d(0, 6px, 0);
    transition:
        opacity 950ms var(--kb-reveal-easing),
        transform 950ms var(--kb-reveal-easing);
    pointer-events: none;
    z-index: 1;
}

.kb-home-creations__slide.is-active {
    opacity: 1;
    transform: translate3d(0, 0, 0);
    pointer-events: auto;
    z-index: 3;
}

/* Layer base — figures exist ONLY for position, width, z-index.
   No background, no padding, no border, no radius, no overflow.
   The <img> renders at its natural aspect ratio
   (display:block; width:100%; height:auto) so the transparent
   pixels of every PNG are preserved. */
.kb-home-creations__layer {
    position: absolute;
    margin: 0;
    background: transparent;
    padding: 0;
    border: 0;
    box-shadow: none;
    overflow: visible;
}

.kb-home-creations__layer img {
    display: block;
    width: 100%;
    height: auto;
    max-width: none;
    background: transparent;
}

/* Placeholder surface — ONLY renders when an image control is
   empty. It is a 1px Gold hairlined frame so the editor
   previews are still legible before assets are uploaded.
   Production always replaces the placeholder with a real <img>. */
.kb-home-creations__layer--placeholder {
    background-color: color-mix(in srgb, var(--kb-gold) 6%, transparent);
    border: 1px dashed color-mix(in srgb, var(--kb-gold) 30%, transparent);
    aspect-ratio: 3 / 4;
    height: auto;
}

/* MAIN — upper/right-center, dominant portrait. */
.kb-home-creations__layer--main {
    right: 0;
    top: 0;
    width: 80%;
    z-index: 2;
}

/* PORTRAIT DETAIL — overlapping main image toward the left-middle. */
.kb-home-creations__layer--portrait {
    left: 0;
    top: 25%;
    width: 32%;
    z-index: 4;
}

/* LANDSCAPE DETAIL — wide image overlapping the lower section. */
.kb-home-creations__layer--landscape {
    left: 6%;
    bottom: 0;
    width: 86%;
    z-index: 5;
}

/* ==========================================================================
   RIGHT — editorial control panel
   The right column is the action surface: tablist at the top,
   then the active creation info block, then prev/next nav
   controls, then the bottom index of remaining creations.
   No radius anywhere. Square outline nav controls. Restraint
   before novelty.
   ========================================================================== */
.kb-home-creations__right {
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--kb-space-l);
}

.kb-home-creations__panel-eyebrow {
    margin: 0;
    font-family: var(--kb-font-body);
    font-size: 11px;
    font-weight: 500;
    line-height: 1.2;
    text-transform: uppercase;
    letter-spacing: 0.22em;
    color: var(--kb-gold);
}

/* ---- Tabs (01 | 02 | 03) --------------------------------------------- */
.kb-home-creations__tabs {
    display: flex;
    align-items: center;
    gap: 18px;
    margin-top: -4px; /* optical pull-up to the eyebrow */
}

.kb-home-creations__tab {
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 0;
    padding: 6px 0;
    margin: 0;
    font-family: var(--kb-font-body);
    font-size: 14px;
    font-weight: 400;
    line-height: 1;
    letter-spacing: 0.18em;
    color: color-mix(in srgb, var(--kb-ink) 55%, transparent);
    cursor: pointer;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    transition:
        color var(--kb-transition-ui),
        opacity var(--kb-transition-ui);
}

.kb-home-creations__tab:hover {
    color: var(--kb-gold);
}

.kb-home-creations__tab.is-active {
    color: var(--kb-gold);
    font-weight: 500;
}

.kb-home-creations__tab-num {
    display: block;
}

.kb-home-creations__tab-indicator {
    display: block;
    width: 18px;
    height: 1px;
    background: currentColor;
    opacity: 0;
    transform: scaleX(0.4);
    transform-origin: center;
    transition:
        opacity var(--kb-transition-ui),
        transform var(--kb-transition-ui);
}

.kb-home-creations__tab.is-active .kb-home-creations__tab-indicator {
    opacity: 1;
    transform: scaleX(1);
}

.kb-home-creations__tab:focus-visible {
    outline: 2px solid var(--kb-gold);
    outline-offset: 6px;
}

/* ---- Active creation info panel ---------------------------------------
   Three complete .kb-home-creations__info-panel elements are
   rendered (one per creation) inside the same stable region.
   Each panel permanently owns its own number, name, subtitle
   and Découvrir link — we ONLY toggle .is-active on a single
   panel, so the four fields can never desynchronize.

   The whole panel animates AS ONE GROUP (no per-field stagger):
   opacity 0 → 1 + translate3d(0, 6px, 0) → 0. 750ms, shared
   --kb-reveal-easing. The vertical lift is the only motion,
   purely editorial.

   Stack architecture — defensive:
     - Parent .kb-home-creations__info is position: relative with
       a tall enough min-height to contain the full panel content
       (number + rule + name + subtitle + Découvrir link) without
       any visual reflow when the active panel changes.
     - Every .kb-home-creations__info-panel is position: absolute,
       inset: 0, so all three panels occupy the SAME coordinates.
     - Inactive panels: opacity 0, pointer-events: none, z-index 1.
     - Active panel:    opacity 1, pointer-events: auto, z-index 2.

   Visual state is driven ONLY by opacity + pointer-events +
   z-index — no `visibility` involved (it was making the fade
   harder to reason about). Accessibility (aria-hidden + inert +
   tabindex on inactive links) is set in JS. CSS and a11y are
   independent, so a CSS or JS failure in one layer cannot leak
   the hidden panel into the visible column. */
.kb-home-creations__info {
    position: relative;
    width: 100%;
    /* Tall enough to fit number (36px) + rule (1px) + name (~35px) +
       subtitle (~20px) + link (~13px) + their internal margins +
       the gap to the next column element. Stable across creations. */
    min-height: 180px;
}

.kb-home-creations__info-panel {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    opacity: 0;
    transform: translate3d(0, 6px, 0);
    transition:
        opacity 750ms var(--kb-reveal-easing),
        transform 750ms var(--kb-reveal-easing);
    pointer-events: none;
    z-index: 1;
}

.kb-home-creations__info-panel.is-active {
    opacity: 1;
    transform: translate3d(0, 0, 0);
    pointer-events: auto;
    z-index: 2;
}

.kb-home-creations__info-number {
    margin: 0 0 var(--kb-space-s) 0;
    font-family: var(--kb-font-display);
    font-size: 36px;
    font-weight: 300;
    line-height: 1;
    letter-spacing: 0.04em;
    color: var(--kb-gold);
    text-wrap: balance;
}

.kb-home-creations__info-rule {
    display: block;
    width: 36px;
    height: 1px;
    background: var(--kb-gold);
    margin: 0 0 var(--kb-space-s) 0;
    opacity: 0.85;
}

.kb-home-creations__info-name {
    margin: 0 0 6px 0;
    font-family: var(--kb-font-display);
    font-size: 30px;
    font-weight: 300;
    line-height: 1.15;
    letter-spacing: 0.01em;
    color: var(--kb-ink);
    text-transform: uppercase;
    text-wrap: balance;
}

.kb-home-creations__info-subtitle {
    margin: 0 0 var(--kb-space-m) 0;
    font-family: var(--kb-font-body);
    font-size: 14px;
    font-weight: 500;
    line-height: 1.4;
    letter-spacing: 0.04em;
    color: var(--kb-gold);
}

/* Editorial text link — NOT a button. Lives at the END of the
   active creation info flow per the global CTA rule. Restrained
   underline that animates on hover. */
.kb-home-creations__info-link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: auto; /* push to the bottom of the info block */
    font-family: var(--kb-font-body);
    font-size: 13px;
    font-weight: 500;
    line-height: 1;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    text-decoration: none;
    color: var(--kb-gold);
    position: relative;
    padding-bottom: 4px;
    transition: color var(--kb-transition-ui);
}

.kb-home-creations__info-link-label,
.kb-home-creations__info-link-arrow {
    position: relative;
}

/* Subtle editorial underline — short line under the label only. */
.kb-home-creations__info-link-label::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -2px;
    height: 1px;
    background: currentColor;
    transform: scaleX(1);
    transform-origin: left center;
    transition: transform var(--kb-transition-ui);
}

.kb-home-creations__info-link:hover .kb-home-creations__info-link-label::after {
    transform: scaleX(0);
    transform-origin: right center;
}

.kb-home-creations__info-link-arrow {
    display: inline-block;
    transition: transform var(--kb-transition-ui);
}

.kb-home-creations__info-link:hover .kb-home-creations__info-link-arrow {
    transform: translateX(4px);
}

.kb-home-creations__info-link:visited {
    color: var(--kb-gold);
}

.kb-home-creations__info-link:focus-visible {
    outline: 2px solid var(--kb-gold);
    outline-offset: 4px;
}

/* ---- Prev / Next nav controls ----------------------------------------- */
.kb-home-creations__nav {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: var(--kb-space-s);
}

/* ==========================================================================
   Carousel arrow controls — shared canonical interaction style.

   Previous (←) and Next (→) are MIRROR-SYMMETRIC: same default,
   same hover, same press. The palette exactly matches the Hero
   secondary CTA "DÉCOUVRIR LES CRÉATIONS":

     NORMAL: transparent ground, 1px Gold border, Gold arrow icon
     HOVER : Gold ground, Ink arrow icon, Gold border
     PRESS : 1px down
     FOCUS : keyboard-only Gold outline (no fill change)

   The arrow icon is rendered as a typographic character inside
   .kb-home-creations__nav-arrow, so it inherits `color` from the
   button automatically. If the markup is ever swapped to an SVG
   the icon must use stroke: currentColor / fill: currentColor so
   the same palette rule continues to work without a CSS change.

   Four independent states, each its own selector — never combined.
   ========================================================================== */

/* Shared base — size, shape, transitions, default palette. */
.kb-home-creations__nav-btn,
.kb-home-creations__nav-btn--filled {
    appearance: none;
    -webkit-appearance: none;
    width: 56px;
    height: 56px;
    padding: 0;
    margin: 0;
    background: transparent;
    border: 1px solid var(--kb-gold);
    color: var(--kb-gold);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition:
        background-color 500ms cubic-bezier(0.22, 1, 0.36, 1),
        color            500ms cubic-bezier(0.22, 1, 0.36, 1),
        border-color     500ms cubic-bezier(0.22, 1, 0.36, 1),
        transform        180ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* Normal — Gold outline, transparent ground.
   The legacy .kb-home-creations__nav-btn--filled modifier is
   included in this declaration so it can never again paint the
   next button as a Gold ground by default. */
.kb-home-creations__nav-btn,
.kb-home-creations__nav-btn--filled,
.kb-home-creations__nav-btn:visited,
.kb-home-creations__nav-btn--filled:visited {
    background: transparent;
    color: var(--kb-gold);
    border-color: var(--kb-gold);
}

/* Icon color inheritance — the arrow character / future SVG must
   follow the button's current `color` value so a single token
   change cascades to the icon. */
.kb-home-creations__nav-arrow,
.kb-home-creations__nav-btn svg,
.kb-home-creations__nav-btn--filled svg {
    color: currentColor;
    stroke: currentColor;
    fill: currentColor;
}

/* Active (press) — restrained 1px press, no fill change.
   Clears the instant the user releases. */
.kb-home-creations__nav-btn:active,
.kb-home-creations__nav-btn--filled:active {
    transform: translateY(1px);
}

/* Focus-visible — keyboard-only outline, base palette preserved.
   No fill change so a mouse click never leaves a permanent
   hover-like focus state. */
.kb-home-creations__nav-btn:focus,
.kb-home-creations__nav-btn--filled:focus {
    outline: none;
}
.kb-home-creations__nav-btn:focus-visible,
.kb-home-creations__nav-btn--filled:focus-visible {
    outline: 2px solid var(--kb-gold);
    outline-offset: 3px;
}

/* Hover — only on devices that actually hover.
   BOTH arrows invert to a Gold ground / Ink text. Same canonical
   gesture as the Hero secondary CTA: Gold outline → Gold fill. */
@media (hover: hover) and (pointer: fine) {
    .kb-home-creations__nav-btn:hover,
    .kb-home-creations__nav-btn--filled:hover {
        background-color: var(--kb-gold);
        color: var(--kb-ink);
        border-color: var(--kb-gold);
    }
}

.kb-home-creations__nav-arrow {
    display: inline-block;
    font-size: 18px;
    line-height: 1;
    letter-spacing: 0;
}

/* ==========================================================================
   Tablet (≤ 1199px)
   Only basic overflow protection. The full mobile design for
   Section 03 will be done in a separate pass after desktop is
   approved — per spec, this block is a guard rail, not a redesign.
   ========================================================================== */
@media (max-width: 1199px) {
    .kb-home-creations {
        padding-top: var(--kb-section-space-tablet);
    }

    .kb-home-creations__inner {
        padding-inline: var(--kb-gutter-tablet);
    }

    .kb-home-creations__title {
        font-size: 44px;
    }

    .kb-home-creations__intro {
        font-size: 15px;
    }

    .kb-home-creations__info-name {
        font-size: 26px;
    }
}

/* ==========================================================================
   Tablet (768px – 1024px) — typography refinement
   ------------------------------------------------------------
   Narrower override on top of the wider tablet band (≤ 1199px)
   above so the section title reads as the visual middle point
   between the desktop 44px and the mobile 36px specs. Intro text
   stays at 15px (same as desktop and the wider tablet band).
   The eyebrow is owned by .kb-section-eyebrow in base.css.
   ========================================================================== */
@media (min-width: 768px) and (max-width: 1024px) {
    .kb-home-creations__title {
        font-size: 40px;
    }
}

/* ==========================================================================
   Mobile (≤ 767px) — proper single-column editorial layout.

   Desktop is a 3-column grid: copy | stage | controls. On mobile we
   collapse that into ONE vertical flow with this exact order:

       1. eyebrow
       2. title
       3. intro paragraph
       4. image stage (the 3-image collage as ONE artboard)
       5. DÉCOUVRIR NOS CRÉATIONS (panel-eyebrow)
       6. 01 02 03 tabs
       7. active info panel
       8. prev / next arrows
       9. compact alternate list

   The panel-eyebrow, tabs, info, nav and index live inside the
   desktop right column (.__right). On mobile we set .__right to
   `display: contents` so its children become direct grid children,
   then pin each one to its row in a single-column grid via
   grid-template-areas. No DOM change — desktop is byte-identical.

   The image stage now sits IMMEDIATELY after the copy (the previous
   grid order placed the carousel header and tabs between copy and
   stage, which is what produced the huge Porcelain gap on mobile).
   Desktop right-column positioning (position: absolute, grid-column
   offsets, left/right/transform) is fully neutralized on the mobile
   controls wrapper so the entire control block participates in
   normal document flow under the collage.

   Reveal: each of the five control children now carries its own
   data-kb-reveal="fade-up" attribute (set in the widget template),
   so the global IntersectionObserver reveals them individually as
   they enter the viewport, regardless of `display: contents` on the
   parent. No CSS-only reveal inheritance is needed.
   ========================================================================== */
@media (max-width: 767px) {
    .kb-home-creations {
        padding-top: var(--kb-section-space-mobile);
    }

    .kb-home-creations__inner {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas:
            "left"
            "center"
            "header"
            "tabs"
            "info"
            "nav";
        column-gap: 0;
        row-gap: 0;
        align-items: stretch;
        padding-inline: var(--kb-gutter-mobile);
    }

    .kb-home-creations__left {
        grid-area: left;
        align-items: flex-start;
        /* paragraph → image collage: ~28px (was var(--kb-space-xl) = 32px
           plus the leftover stacking of header+tabs between copy and
           stage, which produced the 120–150px Porcelain gap). */
        margin-bottom: 28px;
    }

    .kb-home-creations__copy {
        max-width: 100%;
    }

    .kb-home-creations__center {
        grid-area: center;
        /* image collage → carousel heading: ~30px */
        margin-bottom: 30px;
    }

    /* Desktop right-column used position: relative / absolute to host
       the absolutely positioned control panel. On mobile that entire
       block MUST lose desktop positioning and live in normal flow. */
    .kb-home-creations__right {
        display: contents;
    }

    .kb-home-creations__panel-eyebrow {
        grid-area: header;
        width: 100%;
        /* heading → tabs: ~16px */
        margin-bottom: 16px;
    }

    .kb-home-creations__tabs {
        grid-area: tabs;
        /* tabs → active info: ~28px */
        margin-bottom: 28px;
        gap: 28px;
    }

    .kb-home-creations__info {
        grid-area: info;
        /* active info → arrows: ~24px */
        margin-bottom: 24px;
        /* Stable height so the four-field block does not reflow
           between creations. Tuned to the smallest stable value
           that comfortably fits number + rule + name + subtitle +
           Découvrir link on a 360px viewport. */
        min-height: 168px;
    }

    .kb-home-creations__nav {
        grid-area: nav;
        /* arrows → next element: ~24px */
        margin-bottom: 24px;
    }

    /* ---- Copy typography ---------------------------------------------- */
    /* Eyebrow size + spacing owned by the canonical .kb-section-eyebrow
       primitive in base.css (11px on mobile via the @media query
       inside base.css). No per-section mobile override needed. */

    .kb-home-creations__title {
        font-size: 36px;
        line-height: 1.1;
        text-wrap: balance;
    }

    .kb-home-creations__intro {
        font-size: 16px;
        line-height: 1.7;
    }

    /* ---- Image composition — same layered collage as desktop ----------
       The three layers keep their editorial overlap so the 4:5 main
       portrait, the vertical detail and the 3:1 landscape still
       read as ONE couture composition, not three stacked images.
       Numbers are tuned slightly for a 360–390px viewport but stay
       inside the spec bands (78–82% / 34–38% / 88–94%). */
    .kb-home-creations__stage {
        aspect-ratio: 0.82 / 1;
    }

    .kb-home-creations__layer--main {
        right: 0;
        top: 0;
        width: 80%;
    }

    .kb-home-creations__layer--portrait {
        left: 0;
        top: 26%;
        width: 36%;
    }

    .kb-home-creations__layer--landscape {
        left: 5%;
        bottom: 0;
        width: 90%;
    }

    /* ---- Active creation info — full mobile width ---------------------
       Each info panel is a full-width editorial block. Number grows
       to 44px for editorial presence; name and subtitle keep the
       approved mobile rhythm; Découvrir stays a text link, not a
       full-width button. */
    .kb-home-creations__info-number {
        font-size: 44px;
    }

    .kb-home-creations__info-rule {
        width: 32px;
    }

    .kb-home-creations__info-name {
        font-size: 30px;
    }

    .kb-home-creations__info-subtitle {
        font-size: 14px;
    }

    .kb-home-creations__info-link {
        font-size: 12px;
    }
}

/* ==========================================================================
   SECTION 03 — SCROLL REVEAL
   ------------------------------------------------------------
   Three visual groups animate as their own editorial units:
     0ms    — Left content       (fade-up, 900ms, 20px → 0)
     100ms  — Center stage       (fade-up, 1050ms, 24px → 0)
     180ms  — Right control panel(fade-up, 900ms, 20px → 0)

   No individual image reveal. The collage enters as ONE object
   via the .kb-home-creations__center reveal. The slide swap
   (700ms, --kb-reveal-easing) is a separate carousel state
   transition and runs only when the user actively changes slides.
   ========================================================================== */
.kb-home-creations__left[data-kb-reveal="fade-up"] {
    transition-delay: 0ms;
    transition-duration: 900ms;
    --kb-reveal-distance: 20px;
}

.kb-home-creations__center[data-kb-reveal="fade-up"] {
    transition-delay: 100ms;
    transition-duration: 1050ms;
    --kb-reveal-distance: 24px;
}

.kb-home-creations__right[data-kb-reveal="fade-up"] {
    transition-delay: 180ms;
    transition-duration: 900ms;
    --kb-reveal-distance: 20px;
}

/* Mobile: same architecture, shorter distance / duration. */
@media (max-width: 767px) {
    .kb-home-creations__left[data-kb-reveal="fade-up"],
    .kb-home-creations__right[data-kb-reveal="fade-up"] {
        --kb-reveal-distance: 14px;
        transition-duration: 800ms;
    }

    .kb-home-creations__center[data-kb-reveal="fade-up"] {
        --kb-reveal-distance: 16px;
        transition-duration: 900ms;
    }
}

/* ==========================================================================
   Reduced motion — already handled globally by base.css via the
   universal transition-duration: 0.01ms !important rule. Carousel
   state changes still happen but the visual transition collapses
   to near-instant. No additional code required here.
   ========================================================================== */
