/* ============================================================================
   SECTION 08-recovery — "4.0 Recovery" — Figma node 2778:2378 (1280 x 900)
   ----------------------------------------------------------------------------
   Two sources, kept strictly apart:

   PART 1  Salient CSS this section needs that is NOT in vendor/.
           vendor/ holds only the demo's LINKED stylesheets. WPBakery emits the
           per-page utility + split-heading CSS INLINE, so it never got vendored.
           Every rule in Part 1 is byte-verbatim from the file named above it.
           The ONLY edit is the [data-section="08-recovery"] prefix, which stops
           rules that were page-global on the demo from leaking into sections
           that did not lift this component.

   PART 2  Salient rules this section REPLACES. Each one quotes the Salient
           original, then states the Figma value and the spec clause that
           authored it. Same selector text as Part 1 so "later wins" applies.

   PART 3  Figma geometry / type / colour that has no Salient analogue.

   Spec:   figma-truth/08-recovery.spec.md      Pixels: figma-truth/sections-en/08-recovery.png
   ========================================================================== */


/* ============================================================================
   PART 1 — LIFTED VERBATIM
   ========================================================================== */

/* --- inner-row position utilities ------------------------------------------
   source: salient-truth/resort/assets/inline/inline-style-3.css
           (min_width_desktop_40pct + translate_y_-50pct only exist on the
            architect page: salient-truth/architect/assets/INLINE-critical.css)
   NOTE: despite the word "desktop" in the class names, Salient does NOT gate
   these behind a media query. Verified in both inline files. The overlay stays
   absolutely positioned at every width in the demo. -------------------------- */

[data-section="08-recovery"] .vc_row.inner_row.row_position_absolute{position:absolute;}
[data-section="08-recovery"] .vc_row.inner_row.top_position_desktop_50pct{top:50%;}
[data-section="08-recovery"] .vc_row.inner_row.right_position_desktop_0px{right:0px;}
[data-section="08-recovery"] .vc_row.inner_row.min_width_desktop_40pct{min-width:40%;}
@media only screen,print{
  [data-section="08-recovery"] .vc_row.inner_row.translate_y_-50pct{-webkit-transform:translateY(-50%);transform:translateY(-50%);}
}

/* --- column element spacing ------------------------------------------------ */
[data-section="08-recovery"] .flex_gap_desktop_10px> .vc_column-inner > .wpb_wrapper{gap:10px;}
[data-section="08-recovery"] .wpb_column.el_spacing_0px > .vc_column-inner > .wpb_wrapper > div:not(:last-child),
[data-section="08-recovery"] .wpb_column.el_spacing_0px > .n-sticky > .vc_column-inner > .wpb_wrapper > div:not(:last-child){margin-bottom:0px;}
[data-section="08-recovery"] .wpb_column.child_column.el_spacing_0px > .vc_column-inner > .wpb_wrapper > div:not(:last-child),
[data-section="08-recovery"] .wpb_column.child_column.el_spacing_0px > .n-sticky > .vc_column-inner > .wpb_wrapper > div:not(:last-child){margin-bottom:0px;}

/* --- column background image position -------------------------------------- */
[data-section="08-recovery"] .column-image-bg-wrap[data-bg-pos="center center"] .column-image-bg,
.container-wrap .main-content [data-section="08-recovery"] .column-image-bg-wrap[data-bg-pos="center center"] .column-image-bg{background-position:center center;}

/* --- row side inset below desktop ------------------------------------------
   source: salient-truth/architect/assets/INLINE-critical.css (byte-identical in
   salient-truth/resort/assets/inline/inline-style-3.css).
   The lifted row already carries right_padding_tablet_8pct / left_padding_tablet_8pct,
   and the lifted copy column already carries no-extra-padding_tablet /
   no-extra-padding_phone — that pair is how the demo MOVES the side inset from the
   column to the row below 1000px. The `no-extra-padding_*` half is in vendor/
   (grid-system.css, padding:0 at 0,4,2 specificity, which beats our column rule);
   the row half is not, so without these two rules the copy sits flush against the
   viewport edge at <= 999. MEASURED at 640: text x = 0, width = 640.
   NOTE this insets the photo band too, which is what the demo does. Spec §6.4
   ("photo block: full-bleed width") is reasoned intent, not measured truth — there
   is no Figma frame below 1280. Flagged rather than silently overruled. ---------- */
@media only screen and (max-width:999px){
  #ajax-content-wrap [data-section="08-recovery"] .vc_row.right_padding_tablet_8pct > .row_col_wrap_12{padding-right:8%!important;}
  #ajax-content-wrap [data-section="08-recovery"] .vc_row.left_padding_tablet_8pct > .row_col_wrap_12{padding-left:8%!important;}
  [data-section="08-recovery"] .vc_row.right_padding_tablet_8pct > .row_col_wrap_12{padding-right:8%;}
  [data-section="08-recovery"] .vc_row.left_padding_tablet_8pct > .row_col_wrap_12{padding-left:8%;}
}

/* --- divider spacers, tablet / phone ---------------------------------------
   These four carry the demo's OWN responsive heights for exactly the two
   dividers this section lifted. Shipping them means the sub-desktop behaviour
   is Salient's, not invented (spec §6.4 / §6.5 are "reasoned intent" only). --- */
@media only screen and (max-width:999px){
  [data-section="08-recovery"] .divider-wrap.height_tablet_70svh > .divider{height:70svh!important;}
  [data-section="08-recovery"] .divider-wrap.height_tablet_40svh > .divider{height:40svh!important;}
}
@media only screen and (max-width:690px){
  [data-section="08-recovery"] .divider-wrap.height_phone_60svh > .divider{height:60svh!important;}
  [data-section="08-recovery"] .divider-wrap.height_phone_35svh > .divider{height:35svh!important;}
}

/* --- .nectar-split-heading, line-reveal-by-space ---------------------------
   The complete block, lifted whole. It is the resting state + transition for
   the dominant motion primitive (298 occurrences page-wide, DECISION-framework
   §2). init.js generates the per-word <span><span class="inner"> markup and
   adds .markup-generated / .animated-in / .animated; without this CSS the
   reveal does not exist. Do not edit inside the block — Part 2 overrides the
   two line-height rules from outside, so the lift stays diffable. ------------- */

[data-section="08-recovery"] .nectar-split-heading .heading-line{display:block;overflow:hidden;position:relative}
[data-section="08-recovery"] .nectar-split-heading .heading-line >div{display:block;transform:translateY(200%);-webkit-transform:translateY(200%)}
[data-section="08-recovery"] .nectar-split-heading h1{margin-bottom:0}
[data-section="08-recovery"] .nectar-split-heading > * > *{text-indent:0;}
@media only screen and (min-width:1000px){
  [data-section="08-recovery"] .nectar-split-heading[data-custom-font-size="true"] h1,
  [data-section="08-recovery"] .nectar-split-heading[data-custom-font-size="true"] h2,
  [data-section="08-recovery"] .nectar-split-heading[data-custom-font-size="true"] h3,
  [data-section="08-recovery"] .nectar-split-heading[data-custom-font-size="true"] h4,
  [data-section="08-recovery"] .nectar-split-heading[data-custom-font-size="true"] h5,
  [data-section="08-recovery"] .nectar-split-heading[data-custom-font-size="true"] h6,
  [data-section="08-recovery"] .nectar-split-heading[data-custom-font-size="true"] i{font-size:inherit;line-height:inherit;}
}
[data-section="08-recovery"] .nectar-split-heading[data-animation-type="line-reveal-by-space"]:not(.markup-generated){opacity:0;}
[data-section="08-recovery"] .nectar-split-heading[data-animation-type="line-reveal-by-space"]:not(.markup-generated).animated-in{opacity:1;}
[data-section="08-recovery"] .nectar-split-heading[data-animation-type="line-reveal-by-space"] > * > span{position:relative;display:inline-block;overflow:hidden;}
[data-section="08-recovery"] .nectar-split-heading[data-animation-type="line-reveal-by-space"] span{vertical-align:bottom;}
[data-section="08-recovery"] .nectar-split-heading[data-animation-type="line-reveal-by-space"] span{line-height:1.2;}
@media only screen and (min-width:1000px){
  [data-section="08-recovery"] .nectar-split-heading[data-animation-type="line-reveal-by-space"]:not(.markup-generated):not([data-text-effect="none"]) > *{line-height:1.2;}
}
@media only screen and (max-width:999px){
  [data-section="08-recovery"] .nectar-split-heading[data-animation-type="line-reveal-by-space"]:not([data-m-rm-animation="true"]):not(.markup-generated):not([data-text-effect="none"]) > *{line-height:1.2;}
}
[data-section="08-recovery"] .nectar-split-heading[data-animation-type="line-reveal-by-space"][data-stagger="true"]:not([data-text-effect*="letter-reveal"]) span .inner{transition:transform 1.2s cubic-bezier(0.25,1,0.5,1),opacity 1.2s cubic-bezier(0.25,1,0.5,1),filter 1.2s cubic-bezier(0.25,1,0.5,1);}
[data-section="08-recovery"] .nectar-split-heading[data-animation-type="line-reveal-by-space"] span .inner{position:relative;display:inline-block;-webkit-transform:translateY(1.3em);transform:translateY(1.3em);}
[data-section="08-recovery"] .nectar-split-heading[data-animation-type="line-reveal-by-space"] span .inner.animated{-webkit-transform:none;transform:none;opacity:1;}
[data-section="08-recovery"] .nectar-split-heading[data-text-effect="none"]{opacity:1!important;}
[data-section="08-recovery"] .nectar-split-heading[data-animation-type="line-reveal-by-space"][data-align="left"]{display:flex;justify-content:flex-start;}
@media only screen and (max-width:999px){
  [data-section="08-recovery"] .nectar-split-heading[data-m-rm-animation="true"]{opacity:1!important;}
}


/* ============================================================================
   PART 2 — SALIENT RULES THIS SECTION REPLACES
   Each block: the Salient original, then the Figma value that supersedes it.
   ========================================================================== */

/* Salient: .vc_row.inner_row.min_width_desktop_40pct{min-width:40%;}
   Figma  : "image 30" (2778:2386) is a FIXED 300 x 450 at BOTH 1280 and 1440
            (§1.4, §2.1). It is not a percentage of anything.
   Scoped >= 1000 so the demo's own 40% governs the stacked layout below that. */
@media only screen and (min-width:1000px){
  [data-section="08-recovery"] .vc_row.inner_row.min_width_desktop_40pct{min-width:300px;width:300px;}
}

/* Salient: .vc_row.inner_row.right_position_desktop_0px{right:0px;}
   Figma  : the overlay's right edge is 503 inside a 443-wide column, i.e. it
            deliberately OVERHANGS by 60 (§1.4). It stops 60px short of the
            copy's left edge (563), so there is no collision at 1280 or 1440.
   Scoped >= 1000: below that the images block is full-width, and a negative
   right inset would push 60px of image outside the viewport. Salient's own
   right:0px stands there — which is also spec §6.4's "retire the overhang". */
@media only screen and (min-width:1000px){
  [data-section="08-recovery"] .vc_row.inner_row.right_position_desktop_0px{right:-60px;}
}

/* Salient: #ajax-content-wrap .vc_row.inner_row.right_padding_20pct >
            .row_col_wrap_12_inner{padding-right:20%;}
   Figma  : "kitchen 1" (2778:2385) is 443 wide — the FULL width of the 443
            column (§1.3). There is no right inset on the photo. */
[data-section="08-recovery"] .vc_row.inner_row.right_padding_20pct > .row_col_wrap_12_inner{padding-right:0;}

/* Salient: (architect INLINE-critical.css, >= 1000px)
            .column_container:not(.vc_col-sm-12) .col.padding-8-percent >
            .vc_column-inner{padding:calc((100vw - 180px) * 0.04);}
   Figma  : "Text" (2778:2379) padding is top 96 / right 120 / bottom 96 /
            left 120 (§1.5) — a FIXED inset, 14.3% of the 837 column, and
            identical at 1280 and 1440 (§2.1). --mk-page-x is the page-wide
            120 and already steps down below 1050 (grid.css §6); --mk-space-96
            is the 96. Content box therefore computes to 597 x 708 (§1.5). */
[data-section="08-recovery"] .col.padding-8-percent > .vc_column-inner,
[data-section="08-recovery"] .col.padding-8-percent > .n-sticky > .vc_column-inner{
  padding: var(--mk-space-96) var(--mk-page-x);
  box-sizing: border-box;
}

/* Salient: .flex_gap_desktop_10px> .vc_column-inner > .wpb_wrapper{gap:10px;}
   Figma  : "Text group" (2778:2380) itemSpacing is 24, and the measured gaps
            are 270->294 = 24 and 414->438 = 24 (§1.6, §1.7). The nested
            wrappers each hold a single child, so their gap is 0. */
[data-section="08-recovery"] .flex_gap_desktop_10px> .vc_column-inner > .wpb_wrapper{gap:0;}
[data-section="08-recovery"] .mk-recovery__copy > .vc_column-inner > .wpb_wrapper{
  /* Salient's gap utility presupposes a flex .wpb_wrapper. js_composer only makes
     it flex when it is a DIRECT child of .vc_column_container
     (`.vc_row-flex>.span_12>.vc_column_container>.wpb_wrapper`), and Salient's own
     markup nests it one level deeper inside .vc_column-inner — so on this page the
     wrapper stays a block and `gap` is inert. MEASURED: without this the three
     copy blocks butt together at 0 instead of 24. */
  display: flex;
  flex-direction: column;
  gap: var(--mk-space-24);
}

/* Salient: .nectar-split-heading[...="line-reveal-by-space"] span{line-height:1.2}
            and the same 1.2 on the heading element itself at >= 1000px.
   Figma  : the headline's line box is 60px (120px over 2 lines, §3.2) and the
            body's is 36px (20px at the authored 179.99999523162842%, §3.3).
            1.2 would give 57.6 and 24. The generated word spans are
            display:inline-block + vertical-align:bottom, so a short line-height
            on them also drops the glyphs below the baseline. Both restored. */
[data-section="08-recovery"] .nectar-split-heading.mk-recovery__headline[data-animation-type="line-reveal-by-space"] span{line-height:var(--mk-lh-display);}
[data-section="08-recovery"] .nectar-split-heading.mk-recovery__body[data-animation-type="line-reveal-by-space"] span{line-height:var(--mk-lh-body);}
@media only screen and (min-width:1000px){
  [data-section="08-recovery"] .nectar-split-heading.mk-recovery__headline[data-animation-type="line-reveal-by-space"]:not(.markup-generated):not([data-text-effect="none"]) > *{line-height:var(--mk-lh-display);}
}
@media only screen and (max-width:999px){
  [data-section="08-recovery"] .nectar-split-heading.mk-recovery__headline[data-animation-type="line-reveal-by-space"]:not([data-m-rm-animation="true"]):not(.markup-generated):not([data-text-effect="none"]) > *{line-height:var(--mk-lh-display);}
}

/* Salient: .wpb_content_element,.wpb_row{margin-bottom:35px} and
            .wpb_wrapper>div{margin-bottom:24px}   (vendor style.css)
   Figma  : every gap in this section comes from an itemSpacing, and the two
            that exist are 24 (copy stack) and 0 (everything else). Driving them
            with `gap` instead of trailing margins is what keeps the 24 exact. */
[data-section="08-recovery"] .wpb_row,
[data-section="08-recovery"] .wpb_content_element,
[data-section="08-recovery"] .wpb_wrapper > div{margin-bottom:0;}

/* Salient: .wpb_row.full-width-content{ left:50%;
              margin-left:calc(-50vw + var(--scroll-bar-w)/2 + …);
              width:calc(100vw - var(--scroll-bar-w) - …)!important }   (style.css)
   That breakout exists so a CONTAINED WordPress row can span the viewport. Here
   the row's parent is <section class="mk-section">, which grid.css already makes
   full-bleed, so the breakout double-applies. MEASURED at 1280: row lands at
   x = -1 with width 1282, dragging the photo column to -1 and the overlay to 202.
   The declarations below are Salient's own containment values, lifted verbatim
   from its .force-contained-rows rule in the same stylesheet. The !important is
   forced by Salient's own !important on width — CONVENTIONS trap 6. */
[data-section="08-recovery"] > .wpb_row.full-width-content{
  left: 0;
  margin-left: 0;
  width: 100% !important;
}


/* ============================================================================
   PART 3 — FIGMA GEOMETRY, TYPE AND COLOUR
   ========================================================================== */

/* --- the band -------------------------------------------------------------- */
[data-section="08-recovery"]{
  background-color: var(--mk-surface-mist);   /* §1.1 fill #f4f9fb, single SOLID */

  /* REQUIRED, not decoration. vendor style.css carries
       body .wpb_row .column-image-bg-wrap{z-index:-1}
     and <section class="mk-section"> is position:relative with z-index:auto, so
     it is NOT a stacking context. Without this the two photos paint BEHIND this
     section's own background-color and the column renders empty mist. */
  isolation: isolate;
}

/* --- the two blocks: fixed widths, SPACE_BETWEEN ---------------------------
   §1.1 the section frame is HORIZONTAL / SPACE_BETWEEN / counterAxis CENTER.
   §5.3 is emphatic that this is NOT a 12-column layout: both blocks are fixed
   px at both authored widths and ALL extra viewport width becomes the gap
   (0 at 1280, 160 at 1440). itemSpacing:43 on the frame is a red herring — the
   children consume the container exactly at 1280, so it never renders (§1.1).
   ------------------------------------------------------------------------- */
/* The selector is deliberately long. js_composer ships
   `.vc_row.vc_row-flex > .span_12{flex-wrap:wrap}` at specificity 0,3,0; a plain
   `[data-section] .row_col_wrap_12` is only 0,2,0 and LOSES. MEASURED at 1024:
   443 + 837 exceeds the viewport, the copy block wraps to a second flex line and
   the section becomes 1800 tall. This chain is 0,5,0 and holds. */
[data-section="08-recovery"] > .wpb_row.vc_row-flex > .row_col_wrap_12.span_12{
  display: flex;
  flex-wrap: nowrap;
  align-items: center;              /* §1.1 counterAxisAlignItems: CENTER */
  justify-content: space-between;   /* §1.1 primaryAxisAlignItems: SPACE_BETWEEN */
  width: 100%;
}
/* CONVENTIONS trap 7, and it is invisible until 1440. .row_col_wrap_12 carries
   Salient's .col clearfix ::before/::after; once the element is display:flex they
   become flex ITEMS, so space-between distributes the slack across THREE gaps
   instead of one. MEASURED at 1440: 160px of slack split 80 + 80, putting the text
   block at x = 523 instead of 603 and leaving an 80px hole at the right margin.
   At 1280 the slack is 0, so the bug is silent there. */
[data-section="08-recovery"] > .wpb_row.vc_row-flex > .row_col_wrap_12.span_12::before,
[data-section="08-recovery"] > .wpb_row.vc_row-flex > .row_col_wrap_12.span_12::after{ display: none; }

@media only screen and (min-width:1000px){
  [data-section="08-recovery"] > .wpb_row.vc_row-flex > .row_col_wrap_12.span_12{min-height:900px;}   /* §1.1 */

  /* §1.2 — 443 fixed, flush to x = 0, no margin on this side of the page.
     flex-shrink 0: the photo is a fixed-crop asset, it must never narrow. */
  [data-section="08-recovery"] .mk-recovery__images{
    flex: 0 0 443px;
    align-self: stretch;            /* identical to CENTER here: the block is
                                       exactly the row height (§2.1) */
  }

  /* §1.5 — 837 fixed. flex-shrink 1 + min-width 0 is the one concession: at a
     viewport under 1280 (e.g. 1280 minus a classic 15px scrollbar) something
     has to give, and §6.3's reasoned intent is that the TEXT block absorbs it
     and the copy re-wraps. At a true 1280 it resolves to exactly 837/597. */
  [data-section="08-recovery"] .mk-recovery__copy{
    flex: 0 1 837px;
    min-width: 0;
    align-self: stretch;
  }

  /* §1.2 — the Images frame is 443 x 900 with padding top 4 / bottom 4, which
     is why kitchen 1 is 892 tall and sits at y = 4. Height is on the padding
     box so the overlay's top:50% still resolves against a 900 box -> 225. */
  [data-section="08-recovery"] .mk-recovery__images > .vc_column-inner{
    height: 900px;
    padding: var(--mk-space-4) 0;   /* 4 */
    box-sizing: border-box;
  }

  /* §1.5 — the Text frame is 837 x 900; 900 - 96 - 96 = 708 content height,
     which is what makes the CENTER alignment of the copy stack land on 246. */
  [data-section="08-recovery"] .mk-recovery__copy > .vc_column-inner{height:900px;}
}

/* --- the photo column (2778:2384 / 2778:2385) ------------------------------ */

/* §1.2 clipsContent is not serialised by the MCP; the renders prove it is
   FALSE — image 30 visibly crosses the 443 edge in BOTH languages. Say so
   explicitly rather than relying on a default. */
[data-section="08-recovery"] .mk-recovery__images,
[data-section="08-recovery"] .mk-recovery__images > .vc_column-inner{overflow:visible;}

/* §1.2 / §1.3 per-corner radius: topLeft 0, topRight 4, bottomRight 4,
   bottomLeft 0 — the column is flush to the viewport edge on the left, so only
   the inboard corners are rounded. .column-image-bg-wrap already has
   overflow:hidden (vendor style.css), so the radius clips the photo. */
[data-section="08-recovery"] .mk-recovery__photo-row .column-image-bg-wrap{
  border-radius: 0 var(--mk-radius-card) var(--mk-radius-card) 0;
}

/* §1.4 image 30 carries a uniform 4 on all four corners. */
[data-section="08-recovery"] .mk-recovery__overlay-row .column-image-bg-wrap,
[data-section="08-recovery"] .mk-recovery__overlay-row .column-bg-overlay-wrap{
  border-radius: var(--mk-radius-card);
}

/* --- type ------------------------------------------------------------------
   §3.1 / §3.2 / §3.3. Salient's demo stylesheet sets h2/h5 faces, weights and
   colours in the theme layer; this file loads after it, and the selectors below
   are attribute+class+element, which beats every one of them without
   !important. If a value ever stops landing, measure the computed style before
   adding one (CONVENTIONS trap 6).
   ------------------------------------------------------------------------- */

[data-section="08-recovery"] .mk-recovery__eyebrow h5{
  margin: 0;
  font-family: var(--mk-font-sans);
  font-weight: var(--mk-w-light);            /* Poppins Light 300 */
  font-size: var(--mk-size-base);            /* 16 */
  line-height: var(--mk-lh-node);            /* 24 — AUTO in Figma, measured */
  letter-spacing: var(--mk-track-eyebrow);   /* 3 PIXELS (= 0.1875em at 16) */
  text-transform: uppercase;                 /* textCase UPPER, render-proven */
  color: var(--mk-ink-strong);               /* #000000, not --mk-ink-body */
}

[data-section="08-recovery"] .mk-recovery__headline h2{
  margin: 0;
  font-family: var(--mk-font-serif);
  /* opsz pin REMOVED 2026-08-16. It restated the old CONVENTIONS §8.4 trap-4
     value, which the six-size sweep measured wrong at exactly this 48px size
     (+4.2..+4.8 % ink). Family is still pinned here because Salient's resort
     dynamic sheet ships `body h2{font-family:Cormorant}` and losing the
     `.mk-page` ancestor would swap the face. Optical size now comes from
     tokens.css "MERRIWEATHER OPTICAL SIZE" — auto, i.e. opsz = 48. */
  font-optical-sizing: auto;
  font-variation-settings: "wdth" 100;
  font-weight: var(--mk-w-light);            /* Merriweather Light 300 */
  font-size: var(--mk-size-display);         /* 48 */
  line-height: var(--mk-lh-display);         /* 60 — AUTO, 120px / 2 lines */
  letter-spacing: 0;                         /* none reported -> 0 */
  color: var(--mk-ink-strong);               /* #000000 */
}

[data-section="08-recovery"] .mk-recovery__body p{
  /* Salient puts the paragraph rhythm on PADDING, not margin (computed
     padding-bottom: 30px, measured). Zeroing only `margin` leaves the body block
     216 + 30 = 246 tall, which pushes the whole centred stack up by 15px. */
  margin: 0;
  padding: 0;
  font-family: var(--mk-font-sans);
  font-weight: var(--mk-w-regular);          /* Poppins Regular 400 */
  font-size: var(--mk-size-body);            /* 20 */
  line-height: var(--mk-lh-body);            /* 180% -> 36 (authored, payload-read) */
  letter-spacing: 0;
  color: var(--mk-ink-body);                 /* #1a2328 — NOT black */
}


/* ============================================================================
   RESPONSIVE
   1280 and 1440 are measured. Everything below 1280 is reasoned intent (spec
   §6.3-§6.5) and is flagged as such; above 1440 is undefined by the design and
   is deliberately NOT capped here — see NOTES.
   ========================================================================== */

/* Salient's own header/layout breakpoint, and the one spec §6.4 cites. */
@media only screen and (max-width:999px){
  [data-section="08-recovery"] > .wpb_row.vc_row-flex > .row_col_wrap_12.span_12{
    flex-direction: column;           /* §6.4 — photo block first, copy second,
                                         matching source order Images -> Text */
    align-items: stretch;
    min-height: 0;
  }
  [data-section="08-recovery"] .mk-recovery__images,
  [data-section="08-recovery"] .mk-recovery__copy{
    flex: 0 0 auto;
    width: 100%;
    max-width: 100%;
  }
  /* the divider heights (70svh / 40svh, then 60svh / 35svh under 690) come from
     Salient's own classes in PART 1 — no invented band height. */
}


/* ============================================================================
   REDUCED MOTION
   Spec §7.5: not specified in Figma or in the founder notes. This is an
   IMPLEMENTATION DECISION, recorded as one. It disables the two scroll-driven
   motions outright and collapses the entrance reveals to their end state.
   tokens.css's reduced-motion block cannot do it: Salient's durations come from
   <body data-cad>, and the drift/parallax transforms are inline styles written
   by a rAF loop, so only !important can win against them.
   ========================================================================== */
@media (prefers-reduced-motion: reduce){
  /* (a) column entrance */
  [data-section="08-recovery"] .wpb_column.has-animation{opacity:1!important;transform:none!important;}
  /* (a) per-word split-heading reveal */
  [data-section="08-recovery"] .nectar-split-heading[data-animation-type="line-reveal-by-space"]{opacity:1!important;}
  [data-section="08-recovery"] .nectar-split-heading[data-animation-type="line-reveal-by-space"] span .inner{transform:none!important;}
  /* (b) overlay scroll drift — Pe writes transform on > .vc_column-inner */
  [data-section="08-recovery"] .wpb_column[data-scroll-animation="true"] > .vc_column-inner{transform:none!important;}
  /* (c) background parallax — qe writes transform on .parallax-layer */
  [data-section="08-recovery"] .column-image-bg.parallax-layer{transform:translateZ(0)!important;}
}


/* ============================================================================
   R7-09 · REQ-ZEBRA-3 — ONE BREATH AT BOTH EDGES OF THE RECOVERY INTRO
   ----------------------------------------------------------------------------
   THE RULE (founder-trace/FT-20260821-jehnean-round7 R7-09, derived by lane
   `r7:zebra`; full derivation in sections/01-who-why.css §8):

     ONE BREATH. The empty space between any two neighbouring things on this
     page is one breath, and a breath is always the same fraction of the screen
     you are looking at: one fifth of its SHORTER side, never under 96px and
     never over 208px. A section whose photograph runs to its own edge spends
     no breath there and its neighbour supplies the whole one.

       --mk-breath: clamp(96px, 20vmin, 208px)
         1280x900 -> 180   1440x900 -> 180   1750x980 -> 196
          834x1112 -> 166.8   390x844 -> 96 (floor)

   Both neighbours bleed. `07-building`'s gallery frame stops 4px short of its
   own bottom edge and `09-recovery-42` is a tiled panel with a 4px gutter, so
   this section carries the whole breath at BOTH edges and the seams land at
   breath + 4.

   MEASURED BEFORE — FROM PIXELS (review/r7/r7-seams/pxseam.py; five fresh
   headless viewports, served bytes SHA-verified against disk):

       seam 07 -> 08     98 /  98 / **146** /  0  /  0
       seam 08 -> 09     98 /  98 / **146** / 57  / 30
       one breath       180 / 180 / **196** / 166.8 / 96

   and the section's own edge-to-photo space is 94 / 94 / **142** on desktop.

   ⚠ THE FILED REQUEST SAID `07 -> 08` WAS 0 AND IT IS NOT. REQ-ZEBRA-3 read
   that boundary as an OVERLAP — "07-building's ground overflows past its own
   section bottom by 189.8 at 1280 and 225.9 at 1750". That number is a
   `getBoundingClientRect` reading of `07`'s `.box-bg` cards, and those cards
   live inside `.flickity-viewport { overflow: hidden }`: the rect extends past
   the section, the PAINT does not. There is no overlap. There is a 98/98/146px
   empty band, and the screenshot shows it
   (review/r7/r7-seams/shots/px-b08-07-1750x980.png). Recorded rather than
   quietly corrected, because the same reading appears in
   review/r7/zebra-spacing-table.md §2 and will mislead the next reader.

   ---------------------------------------------------------------------------
   DESKTOP — THE BAND IS THE PHOTOGRAPH PLUS TWO BREATHS
   ---------------------------------------------------------------------------
   The photograph is a fixed 892 (§1.2: the Images frame is 443 x 900 with
   padding 4 top / 4 bottom, so kitchen 1 is 892 and sits at y = 4). It does NOT
   stretch with the band — verified at 1750x980, where the column inner is
   already 1176 and the photo is still 892, centred. So the visible edge space
   is pure centring slack:

       edge = 4 + (band - 8 - 892) / 2

   Set `band = 892 + 2 x breath` and that identity collapses to `edge = breath`
   exactly, at every width, with no per-breakpoint number to re-pick. It is the
   same shape sections/03-unique.css B13 uses: state the band as
   `content + gapTop + gapBot` rather than as a ratio, and the gaps become
   arithmetic instead of luck.

       band       1080 -> 1252 · 1080 -> 1252 · **1176 -> 1284**
       edge space   94 -> 180  ·   94 -> 180  ·   **142 -> 196**

   ALL THREE BOXES MOVE TOGETHER OR THE SECTION TEARS, and css/rhythm.css §2
   says so in its own words for this exact section: the row carries the
   min-height and BOTH columns carry a definite `height` on their
   `.vc_column-inner` (§1.2 / §1.5 above), because the photograph's 4px band and
   the copy's CENTER alignment both resolve against it. Raising only the row
   leaves two short columns top-aligned inside a taller band — which is
   precisely the defect this lane found in 16-amenities-52, where the column was
   the one box rhythm.css did not name.

   B04 IS DEEPENED, NOT REVERSED. R3-B's B04 asked for the recovery-plan
   sections to be "markedly taller"; this takes 08 from 1.2 screens to 1.39 at
   1280 and 1.31 at her band. The section is still >= one screen at every
   width, so the co-visibility property rhythm.css bought is intact.

   ---------------------------------------------------------------------------
   BELOW 1000px — ONLY THE BOTTOM, AND HERE IS WHY THE TOP IS LEFT ALONE
   ---------------------------------------------------------------------------
   The layout stacks and the photograph moves to the top, where it OVERFLOWS the
   section's own top edge (census `topSpaceAll` = -60 at 834x1112, -13.9 at
   390x844) and paints continuously across the boundary. Pixels agree: the
   `07 -> 08` seam measures 0 at both widths, "ink on the boundary row". A ground
   that runs to its own edge spends no breath — zero is the rule's answer there,
   exactly as it is for the `09 -> 13` tile run, so the top is NOT touched.

   The BOTTOM at those widths is the opposite case: the last box in the section
   is a `<p>` sitting flush at `sectionBottom - 0`, and 09's photo panel starts
   4px later. Text 4px from a photograph is the pinch REQ-ZEBRA-3 names.

   THE SECTION'S OWN `padding-bottom` IS THE ONLY LEVER THAT CANNOT BE MISSED.
   The copy column's `padding: var(--mk-space-96) var(--mk-page-x)` (PART 2
   above) is displaced below 1000 by Salient's own `no-extra-padding_tablet` /
   `_phone` pair — `grid-system.css` sets `padding: 0` at (0,4,2), which this
   file's own header at the top records as the mechanism that MOVES the side
   inset from the column to the row. So padding the copy column there is a
   no-op. The section's padding-block is 0 at every width (census `padT`/`padB`
   in review/r7/r7-seams/before-*.json), so nothing is being fought.

   ---------------------------------------------------------------------------
   MECHANICS
   ---------------------------------------------------------------------------
   ID-SCOPED, because it has to be. css/rhythm.css is linked LAST (index.html
   line 192, after every section sheet) and its three rules for this section are
   (0,6,0) and (0,4,0) — heavier than this file's own (0,5,0) and (0,3,0), and
   later in the cascade besides. `#s08-recovery` carries an id, so (1,4,0) and
   (1,2,0) win on weight. CONVENTIONS §8.6: the rules being overridden are named
   above. This is a FOLD-BACK — rhythm.css §2's own header says every §2 rule is
   a candidate to move into its section's sheet once the concurrent round
   closes; REQ-SEAMS-1 asks its owner to delete the 08 entries rather than leave
   two rules describing one band.

   THE BREATH IS A `var()` WITH A LITERAL FALLBACK ON PURPOSE. `--mk-breath`
   belongs in css/tokens.css (REQ-ZEBRA-1, not yet landed; tokens.css is
   single-owner). Until it does the fallback IS the value.
   ========================================================================== */

#s08-recovery {
  /* 892 is the photograph, §1.2. Two breaths, one at each edge. */
  --mk-08-band: calc(892px + 2 * var(--mk-breath, clamp(96px, 20vmin, 208px)));
}

@media only screen and (min-width: 1000px) {
  #s08-recovery > .wpb_row.vc_row-flex > .row_col_wrap_12.span_12 {
    min-height: var(--mk-08-band);
  }
  #s08-recovery .mk-recovery__images > .vc_column-inner,
  #s08-recovery .mk-recovery__copy   > .vc_column-inner {
    height: var(--mk-08-band);
  }
}

@media only screen and (max-width: 999px) {
  #s08-recovery {
    padding-bottom: var(--mk-breath, clamp(96px, 20vmin, 208px));
  }
}


/* ============================================================================
   M1 · MOBILE ROUND (2026-08-31, lane recintro) — TEXT FIRST + INSET-OVERHANG
   ----------------------------------------------------------------------------
   Founder feedback for the <=999px stacked layout only, mirroring the
   03-unique treatment. Every rule below is inside the max-width:999px gate;
   >=1000px resolves not one declaration from this block.

   1  TEXT ABOVE IMAGES. The RESPONSIVE block above stacks the row in source
      order Images -> Text; the founder wants the copy read FIRST. `order` on
      the two flex items, not an HTML move: the source order IS the desktop
      truth (§6.4 "matching source order Images -> Text") and must keep
      composing >=1000px byte-identically. The two columns are the container's
      only flex items, so 1/2 is exhaustive.

   2  INSET + OVERHANG, mirrored from the Salient architect strip (background
      inset on one side, floating card overhanging that edge by ~half the
      inset; ours is the RIGHT-side mirror). The photo row's own demo mechanic
      is reused: right_padding_20pct put the inset ON `.row_col_wrap_12_inner`
      and the bg-wrap covers the narrowed column. PART 2 zeroes that padding
      (0,5,0, unscoped); the rule below is the same 5-class weight and LATER,
      so it lands. ARITHMETIC at <=999px: the row inset already holds both
      columns 8vw off the viewport edge (PART 1, 8% of a full-width row), so
      +8vw here puts the photo's right edge 16vw from the viewport — the
      "~16% of viewport" inset — while the overlay row's Salient-own right:0
      (PART 2 keeps -60px behind a >=1000 gate) leaves the card's right edge
      at 92vw: an 8vw overhang, half the inset, card untouched. Parallax /
      drift mechanics untouched — no transform, position, or data- change.

   SEAMS, because the flip moves which content faces each neighbour (R7-09
   above is the desktop derivation; these are its mobile consequences):
     · TOP: was the photo painting across the 07 boundary (seam 0, the rule's
       answer for a bleeding ground — R7-09 "the top is NOT touched"). Now the
       top is TEXT, and 07-building's gallery bleeds to its own bottom edge,
       so this section supplies the whole breath — same reasoning R7-09 used
       for the desktop edges. padding-top on the section: the copy column's
       own padding is displaced below 1000 by no-extra-padding_tablet/_phone
       (grid-system.css, 0,4,2 — R7-09 names it), so the section is again the
       only lever that cannot be missed.
     · INTERNAL: copy bottom -> photo top gets one --mk-space-96 via row-gap
       on the stacked container — order-independent, and there is no
       competing gap: PART 2 zeroed the Salient 10px on the column wrappers,
       never on this container.
     · BOTTOM: R7-09's padding-bottom stays. The face is now the photo, not
       the flush <p>, but 09's tiled panel still starts 4px later and the
       founder's note — 09's recovery-plan heading crowding this section —
       is relieved by keeping the full breath there.
   ========================================================================== */
@media only screen and (max-width:999px){
  [data-section="08-recovery"] .mk-recovery__copy{ order: 1; }
  [data-section="08-recovery"] .mk-recovery__images{ order: 2; }

  [data-section="08-recovery"] > .wpb_row.vc_row-flex > .row_col_wrap_12.span_12{
    row-gap: var(--mk-space-96);
  }

  #s08-recovery{
    padding-top: var(--mk-breath, clamp(96px, 20vmin, 208px));
  }

  /* photo right edge -> 16vw off the viewport (8vw row inset + 8vw here) */
  [data-section="08-recovery"] .vc_row.inner_row.mk-recovery__photo-row > .row_col_wrap_12_inner{
    padding-right: 8vw;
  }
}


/* ============================================================================
   M2 · MOBILE ROUND 2 (2026-08-31, lane reveal) — TEXT VISIBILITY IS NOT
   ALLOWED TO DEPEND ON LAZILY-PROMOTED JS AT <=999px
   ----------------------------------------------------------------------------
   FOUNDER (real Pixel 7): the "Recovery plan" eyebrow row and the "[Combined
   with an effective recovery plan]" headline NEVER appear on mobile — "it's
   gone gone". MEASURED resting state at 412x780 fresh load: the eyebrow's
   ancestor column and the headline wrapper sit at computed opacity 0 (the
   inner h5/h2 report 1 — the WRAPPERS are the hidden layer).

   WHERE THE HIDDEN STATE COMES FROM — three independent layers:
     1  vendor style.css  `.wpb_column.has-animation{opacity:0}` +
        `[data-animation=fade-in-from-bottom]{transform:translateY(75px)}`
        on BOTH copy rows' columns (eyebrow row AND body row).
     2  this file, PART 1 line-reveal block:
        `.nectar-split-heading[...]:not(.markup-generated){opacity:0}` on the
        headline wrapper.
     3  the same block once init.js HAS split the markup: every generated
        `span .inner` rests at translateY(1.3em) inside an overflow:hidden
        line box until `.animated` lands — transform-hidden, not
        opacity-hidden, so an opacity pin alone is NOT sufficient.
   Every one of those layers is released ONLY by Salient's init.js, which is a
   `type="salientlazyscript"` tag promoted on the visitor's first gesture and
   then armed via Waypoints. Under synthetic CDP probes that chain happens to
   survive; on the founder's real phone it did not, and a text wrapper whose
   visible state depends on that chain at all is the defect class this round
   retires (round-1 blind spot: fullpage.py's settle-walk pre-fired every
   reveal and masked exactly this).

   THE FIX at <=999px: the Salient-owned hidden states are neutralised
   STATICALLY — the text is simply there, no entrance choreography. The
   eyebrow KEEPS its fade-in: that entrance belongs to js/myk-motion.js
   (`[data-mv]`/`.mv-in`), a synchronous <head> script armed by
   IntersectionObserver with a scrolled-past failsafe and a fail-open gate
   (html.mv) — mobile-armed by construction, and none of the pins below touch
   a `[data-mv]` element.

   !important is required and stated: layer 1 is re-written per-frame as
   INLINE styles by anime.js once init.js does run (see js/myk-pacing.js §1 —
   "a per-frame inline write cannot be beaten by a stylesheet at any
   specificity"), and layer 2's release rule in PART 1 already carries the
   same weight. Pinned at 1, the inline writes lose and the element never
   leaves its final state — on mobile that is the intent.

   >=1000px resolves not one declaration from this block; the desktop
   choreography is byte-untouched.
   ========================================================================== */
/* 2026-09-02 — ALL WIDTHS NOW, not <=999px. Same finding and same decision as
   sections/03-unique.css B14: on desktop Salient's line-reveal put the H2 on
   screen before the eyebrow's column fade and long before the paragraph's.
   The founder wants one order everywhere (overline -> title -> paragraph), so
   the three Salient-owned layers are pinned open at every width and the trio
   belongs to js/myk-motion.js (`data-mv-adopt` on the h2 + p; the eyebrow's
   wrapper is already adopted through `[class*="__eyebrow"]`). */
@media all{
  /* layer 1 — both copy rows' entrance columns (eyebrow + body) */
  [data-section="08-recovery"] .wpb_column.has-animation{
    opacity: 1 !important;
    transform: none !important;
  }
  /* layer 2 — the headline wrapper's pre-split hold */
  [data-section="08-recovery"] .nectar-split-heading.mk-recovery__headline{
    opacity: 1 !important;
  }
  /* layer 3 — the post-split per-word masks, whether or not .animated ever
     lands. Covers both markup shapes init.js can emit for this element. */
  [data-section="08-recovery"] .mk-recovery__headline span .inner{
    -webkit-transform: none !important;
    transform: none !important;
    opacity: 1 !important;
    filter: none !important;
    transition: none !important;
  }
  [data-section="08-recovery"] .mk-recovery__headline .heading-line > div{
    -webkit-transform: none !important;
    transform: none !important;
  }
}
