/* ==========================================================================
   Case studies — listing + detail
   ==========================================================================
   The detail page is a web rebuild of the supplied CorelDRAW case-study PDFs,
   so the design language here is theirs, not the rest of the site's:

     - section headings are RIBBONS: a solid bar with a V notch cut into the
       right edge (see .cs-ribbon)
     - images run FULL BLEED to the page edge rather than sitting inside the
       container
     - whole sections can sit on a full-width colour band
     - the closing strip is the CLIENT's, in three panels

   Everything that varies per client is a CSS custom property set inline on the
   page wrapper:

       --cs-accent     primary (maroon for Rose & Crown)
       --cs-accent-2   secondary / call-to-action (gold)
       --cs-accent-3   band colour (olive)
       --cs-deep       dark hero background
       --cs-soft       pale tint

   So a new case study gets its own look from the admin form. No new CSS. The
   values are validated by asire_cs_colour() before they reach a style
   attribute — they are admin-editable and land in inline CSS.
   ========================================================================== */

/* ==========================================================================
   LISTING
   ========================================================================== */
.case-studies-page-header{
    min-height: 340px;
    display: flex;
    align-items: center;
    background-position: center;
    background-repeat: no-repeat;
    background-size: cover;
    padding: 150px 0 88px;
}

.case-studies-page-header::after{
    background: linear-gradient(180deg, rgba(255,255,255,0.34) 0%, rgba(255,255,255,0.2) 50%, rgba(255,255,255,0.42) 100%);
    opacity: var(--page-overlay, 1);
}

.case-studies-page-header .page-header-box h1{
    color: #000;
    font-size: 52px;
    margin-bottom: 10px;
}

.case-studies-page-header .page-header-box p{
    max-width: 620px;
    color: var(--primary-color);
    font-size: 16px;
    font-weight: 700;
    line-height: 1.55em;
    margin: 0 auto;
}

.cs-index-section{ padding: 92px 0 80px; background: var(--white-color); }

.cs-index-lead{
    max-width: 720px;
    margin: 0 0 54px;
    font-size: 18px;
    line-height: 1.7em;
    color: var(--text-color);
}

/* ── Listing cards ───────────────────────────────────────────────────────────
   Each card is dressed in its own client's palette — the media panel is tinted
   with their dark colour and carries their mark, so three case studies read as
   three different pieces of work rather than three photos in a row.

   The first one runs wide, the rest sit in a grid. A uniform row of three looks
   thin; a page of a dozen identical wide rows is just scrolling.             */
.cs-entry{
    display: grid;
    grid-template-columns: minmax(0, 1.08fr) minmax(0, 1fr);
    align-items: stretch;
    border-radius: 20px;
    overflow: hidden;
    background: var(--white-color);
    border: 1px solid rgba(3,29,54,0.09);
    transition: transform .35s ease, box-shadow .35s ease;
}

.cs-entry:hover{ transform: translateY(-4px); box-shadow: 0 22px 48px rgba(3,29,54,.14); }

.cs-entry-grid{
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
    gap: 26px;
    margin-top: 26px;
}

/* Stacked in the grid, side by side when featured.
   `grid-template-rows: auto 1fr` is load-bearing, not tidiness. The cards in a
   row are stretched to the tallest one, and with implicit `auto auto` rows the
   leftover height was handed to the PICTURE — whose `aspect-ratio: 16/10` then
   grew its width to match, so a 406px card held a 467px panel and the card's
   `overflow: hidden` sliced the photo and the sector chip off at the right
   edge. Pinning the picture to `auto` and letting the body take the slack
   keeps every panel at the card's own width. */
.cs-entry-grid .cs-entry{
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto 1fr;
}

.cs-entry-media{
    position: relative;
    display: block;
    min-height: 330px;
    background: var(--cs-deep, #101828);
    overflow: hidden;
}

.cs-entry-grid .cs-entry-media{ min-height: 0; aspect-ratio: 16 / 10; }

/* Direct child only. The client's mark also lives inside .cs-entry-media, and a
   loose `.cs-entry-media img` was stretching a 900x172 logo to fill the panel
   and cropping it. */
.cs-entry-media > img{
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover; display: block;
    transition: transform .6s cubic-bezier(.2,.7,.3,1);
}

.cs-entry:hover .cs-entry-media > img{ transform: scale(1.05); }

/* The client's dark colour laid over the photo, heaviest at the foot where the
   mark sits. Without it a light photo leaves the mark unreadable, and the card
   loses the one thing that makes it look like that client's. */
.cs-entry-veil{
    position: absolute; inset: 0;
    background: linear-gradient(
        150deg,
        color-mix(in srgb, var(--cs-deep, #101828) 25%, transparent) 0%,
        color-mix(in srgb, var(--cs-deep, #101828) 72%, transparent) 62%,
        color-mix(in srgb, var(--cs-deep, #101828) 92%, transparent) 100%);
}

@supports not (background: color-mix(in srgb, red 10%, white)){
    .cs-entry-veil{ background: linear-gradient(150deg, rgba(16,24,40,.25), rgba(16,24,40,.9)); }
}

/* A light plate for the client's mark.
   Rose & Crown's is line art that could be painted white straight onto the
   veil, but the other two are full-colour logos designed for light backgrounds
   — navy on gold, black on grey. Giving all three the same plate shows every
   client's real mark and keeps the row consistent, instead of one logo and two
   names in type. */
.cs-entry-mark{
    position: absolute; left: 26px; bottom: 24px;
    display: flex; align-items: center; justify-content: center;
    /* min-height keeps every badge the same depth whether it holds a squarish
       mark or a 5:1 horizontal logo; only the width varies. */
    min-width: 92px; min-height: 64px;
    padding: 11px 16px;
    border-radius: 12px;
    background: rgba(255,255,255,.94);
    box-shadow: 0 10px 26px rgba(0,0,0,.22);
}

/* Flipped for a light-ink logo — Vidhi Events is gold, which needs the dark
   plate its own brand puts it on. */
.cs-entry-mark.is-dark{
    background: var(--cs-deep, #101828);
    box-shadow: 0 10px 26px rgba(0,0,0,.3), inset 0 0 0 1px rgba(255,255,255,.14);
}

/* Height-led rather than width-led, so a squarish mark and a 5:1 horizontal
   logo end up in badges of similar size instead of one tall and one wide. */
.cs-entry-mark .cs-logo{
    --cs-logo-ink: var(--cs-deep, #101828);
    width: auto; max-width: 150px;
    height: 42px;
}

.cs-entry-mark .cs-logo-img{ max-width: 142px; max-height: 40px; width: auto; }

.cs-entry-grid .cs-entry-mark .cs-logo{ height: 38px; }
.cs-entry-grid .cs-entry-mark .cs-logo-img{ max-width: 118px; max-height: 34px; }

/* No mark on file at all — the client's name does the job. */
.cs-entry-wordmark{
    font-size: 19px; font-weight: 700; line-height: 1.2;
    color: var(--cs-deep, #101828);
}

.cs-entry-no{
    position: absolute; left: 30px; top: 24px; z-index: 2;
    font-size: 13px; font-weight: 700; letter-spacing: .14em;
    color: var(--cs-on-accent, #fff); background: var(--cs-accent, #0A49A6);
    padding: 7px 13px; border-radius: 999px;
}

.cs-entry-sector{
    position: absolute; right: 26px; top: 24px; z-index: 2;
    font-size: 12px; font-weight: 700; letter-spacing: .05em;
    color: #fff;
    background: rgba(255,255,255,.16);
    border: 1px solid rgba(255,255,255,.3);
    backdrop-filter: blur(6px);
    padding: 6px 13px; border-radius: 999px;
}

.cs-entry-body{
    padding: 40px 42px;
    display: flex; flex-direction: column;
    align-items: flex-start; justify-content: center;
}

/* Top-aligned in the grid, and the link pinned to the foot by `margin-top:
   auto`. Centring the body is right for the one wide featured card, but in a
   row of three the titles run to one, two and four lines each, and centring
   left every "Read the case study" at a different height — the row read as
   three unrelated boxes rather than a set. */
.cs-entry-grid .cs-entry-body{ padding: 26px 26px 30px; justify-content: flex-start; }
.cs-entry-grid .cs-entry-link{ margin-top: auto; padding-top: 6px; }

.cs-entry-client{
    margin: 0 0 8px;
    font-size: 13px; font-weight: 700;
    letter-spacing: .1em; text-transform: uppercase;
    color: var(--cs-accent, #0A49A6);
}

.cs-entry-title{
    margin: 0 0 14px;
    font-size: 30px; line-height: 1.24em; font-weight: 700;
    color: var(--primary-color);
}

.cs-entry-grid .cs-entry-title{ font-size: 21px; margin-bottom: 12px; }

.cs-entry-title a{
    color: inherit; text-decoration: none;
    background-image: linear-gradient(var(--cs-accent, #0A49A6), var(--cs-accent, #0A49A6));
    background-size: 0 2px; background-repeat: no-repeat; background-position: 0 100%;
    transition: background-size .35s ease, color .25s ease;
}

.cs-entry:hover .cs-entry-title a{ color: var(--cs-accent, #0A49A6); background-size: 100% 2px; }

.cs-entry-summary{ margin: 0 0 20px; font-size: 16px; line-height: 1.7em; color: var(--text-color); }

.cs-entry-link{
    display: inline-flex; align-items: center; gap: 9px;
    font-size: 15px; font-weight: 700;
    color: var(--cs-accent, #0A49A6);
    text-decoration: none;
}
.cs-entry-link:hover{ color: var(--cs-accent, #0A49A6); text-decoration: underline; }

.cs-entry-link svg{ transition: transform .3s ease; }
.cs-entry:hover .cs-entry-link svg{ transform: translateX(5px); }

.cs-chips{
    display: flex; flex-wrap: wrap; gap: 8px;
    list-style: none; margin: 0 0 26px; padding: 0;
}

.cs-chip{
    display: inline-block;
    font-size: 13px; font-weight: 600; line-height: 1.35;
    padding: 6px 13px; border-radius: 999px;
    color: var(--cs-accent, #0A49A6);
    background: color-mix(in srgb, var(--cs-accent, #0A49A6) 9%, #fff);
    border: 1px solid color-mix(in srgb, var(--cs-accent, #0A49A6) 22%, #fff);
}

/* color-mix is well supported now but not universal; without this, older
   engines drop the declaration and the chip loses its background. */
@supports not (background: color-mix(in srgb, red 10%, white)){
    .cs-chip{ background: rgba(10,73,166,0.08); border-color: rgba(10,73,166,0.2); }
}

.cs-chip-sector{
    margin-bottom: 16px;
    background: var(--cs-accent, #0A49A6);
    border-color: var(--cs-accent, #0A49A6);
    color: #fff; letter-spacing: .04em;
}

.cs-chip-more{ opacity: .75; }

.cs-empty{ text-align: center; padding: 60px 0 80px; }
.cs-empty h2{ font-size: 28px; margin-bottom: 10px; color: var(--primary-color); }

.cs-index-cta{ padding: 0 0 100px; background: var(--white-color); }

.cs-index-cta-box{
    border-radius: 22px; padding: 58px 40px; text-align: center;
    background: var(--primary-color); color: #fff;
}

.cs-index-cta-box h2{ color: #fff; font-size: 32px; margin-bottom: 12px; }
.cs-index-cta-box p{ color: rgba(255,255,255,0.78); max-width: 560px; margin: 0 auto 26px; }

/* ==========================================================================
   DETAIL
   ========================================================================== */
/* ── Type scale, taken from the flyer ────────────────────────────────────────
   The PDF is a 460.8pt page set in Mona Sans — the site's own face — at:

       body            4.0pt        pills / labels  5.0pt
       ribbon heading  8.0pt        CTA button      5.6pt
       hero headline   8.6pt        footer tagline  7.5pt
       type sample     9.2pt        small caption   3.0pt

   The thing to notice is that the hero headline is barely larger than a
   section heading — 8.6 against 8.0. Sizing the h1 like a normal web hero
   (44px against a 26px heading) is most of why the first build did not look
   like the flyer.

   TWO SCALES, on purpose. The layout scale is 3.057 — a 1072px content column
   against the flyer's 350.7pt one. Display type is set at THAT scale, because
   a ribbon or a button has a measured width to fit: at the larger scale
   "06. Functions, Weddings & Celebrations" broke onto two lines where the
   flyer sets it on one, and "View Live Website" did the same inside its
   button. Body copy flows, so it keeps a readable 15px rather than the 12.2px
   the layout scale would give.
   ────────────────────────────────────────────────────────────────────────── */
.cs-detail{
    --cs-accent: #0A49A6;
    --cs-accent-2: #C8962A;
    --cs-accent-3: #61634B;
    --cs-deep: #101828;
    --cs-soft: #F4F7FB;
    --cs-header-h: 101px;

    /* One source of truth for the column width. --cs-bleed is the distance from
       the container edge out to the viewport edge, so a full-bleed image knows
       how far to escape. These two drifted apart once already — the wrap was
       narrowed to 1120 and the bleed still assumed 1300, leaving section 01's
       image stopping 90px short of the edge it is supposed to touch. */
    --cs-wrap-max: 1120px;
    --cs-bleed: calc(max(0px, (100vw - var(--cs-wrap-max)) / 2) + 24px);

    --cs-fs-body:    15px;   /* flows — readable size, not the layout scale */
    --cs-fs-small:   11px;
    --cs-fs-label:   15px;   /* 5.0pt  x 3.057 */
    --cs-fs-cta:     17px;   /* 5.6pt  x 3.057 */
    --cs-fs-ribbon:  24px;   /* 8.0pt  x 3.057 */
    --cs-fs-h1:      26px;   /* 8.6pt  x 3.057 */
    --cs-fs-type:    28px;   /* 9.2pt  x 3.057 */
    --cs-fs-tagline: 23px;   /* 7.5pt  x 3.057 */

    overflow-x: clip;   /* full-bleed children must not create a scrollbar */
}

/* Inner column.
   Narrower than the site's 1300px .container on purpose: the flyer's content
   sits inside 12.3%-88.4% of the page, i.e. about 76% of the width. 1300px in
   a 1440px window is 90%, which spread every section wider and flatter than
   the printed page. 1120px lands at 78% — close to the flyer, and still
   centred, so it reads as a deliberately narrower long-form column rather
   than a page that has drifted out of alignment. */
.cs-wrap{
    max-width: var(--cs-wrap-max, 1120px);
    margin: 0 auto;
    padding: 0 24px;
}

/* ── Ribbon heading ──────────────────────────────────────────────────────────
   The PDF's signature: a solid bar with a V notch cut INTO the right edge.
   clip-path rather than a background image, so it takes the client's colour
   and any length of heading without a new export. */
.cs-ribbon{
    display: inline-block;
    margin: 0 0 22px;
    /* The flyer's bar is 21.6pt tall around 8pt text — 2.7x the type size.
       12px of padding on a 30px face gives only 2.0x, which reads as a thin
       label rather than the chunky ribbon on the page. */
    padding: 18px 54px 18px 22px;
    background: var(--cs-accent);
    color: var(--cs-on-accent, #fff);
    font-size: var(--cs-fs-ribbon);
    line-height: 1.2;
    font-weight: 700;
    -webkit-clip-path: polygon(0 0, 100% 0, calc(100% - 34px) 50%, 100% 100%, 0 100%);
            clip-path: polygon(0 0, 100% 0, calc(100% - 34px) 50%, 100% 100%, 0 100%);
}

/* ── Block ribbons ─────────────────────────────────────────────────────────
   Not every flyer uses the pointed bar. Elite Realty prints plain rectangles
   — navy with gold type, and gold with navy type on its sand band — so the
   case study picks its ribbon shape rather than the stylesheet assuming one.
   See ribbon_style in includes/case-studies-data.php. */
.cs-detail.has-block-ribbons .cs-ribbon{
    -webkit-clip-path: none; clip-path: none;
    padding: 14px 26px;
    border-radius: 3px;
    color: var(--cs-accent-2, #E0BD6C);
}
.cs-detail.has-block-ribbons .cs-ribbon .cs-ribbon-no{ color: var(--cs-accent-2, #E0BD6C); }

/* On a banded section the ribbon switches to the secondary colour, exactly as
   the gold "04. Food & Drink" ribbon does on the olive band in the PDF. */
.cs-section.is-band .cs-ribbon{ background: var(--cs-accent-2); color: var(--cs-on-accent-2, #fff); }

/* Gold bar, navy type — the flip the flyer uses on its sand band. */
.cs-detail.has-block-ribbons .cs-section.is-band .cs-ribbon,
.cs-detail.has-block-ribbons .cs-section.is-band .cs-ribbon .cs-ribbon-no{
    color: var(--cs-accent, #26404F);
}

.cs-ribbon-no{ opacity: .9; }

/* ── Hero ────────────────────────────────────────────────────────────────────
   Three columns: client mark + CTA | headline and copy | device shot bleeding
   off the right edge. The background is a left-to-right ramp from --cs-deep
   into --cs-accent-3, which is what the flyer does. */
/* --cs-hero-bg, when a case study supplies the flyer's own gradient artwork, is
   an exact match; the CSS ramp underneath is the fallback for one that does
   not. Both are painted, so the artwork sits over a sane colour while it
   loads. */
/* Wrapper for the hero + anything that must cross its bottom edge. The padding
   is the room the overhanging tiles and mockup need on the white below, so the
   first section does not run into them. */
.cs-hero-shell{ position: relative; }
.cs-hero-shell:has(.is-copy-left){ padding-bottom: 92px; }

/* The flyer's ornament, sitting astride the foot of the colour band: on the
   Vidhi Events page a pair of gold rings, half on the navy and half on the
   white below. Width is taken from the flyer — 8.8% of the paper, which is
   11.7% of the content column. Dropped in as hero-emblem.png; a case study
   without one simply has no element here. */
.cs-hero-emblem{
    position: absolute;
    left: 50%; bottom: 0;
    transform: translate(-50%, 50%);
    width: clamp(86px, 11.7vw, 132px);
    height: auto;
    z-index: 3;
    pointer-events: none;
    filter: drop-shadow(0 10px 22px rgba(0,0,0,.35));
}

.cs-hero{
    position: relative;
    background-color: var(--cs-deep);
    background-image: var(--cs-hero-bg, none),
        linear-gradient(100deg,
            color-mix(in srgb, var(--cs-deep) 96%, #000) 0%,
            var(--cs-deep) 38%,
            color-mix(in srgb, var(--cs-accent-3) 78%, var(--cs-deep)) 100%);
    background-size: cover, auto;
    background-position: center, center;
    color: #fff;
    padding: 170px 0 0;
    /* Clip sideways only. The media column carries a negative margin to reach
       the page edge and would otherwise widen the document — but on the
       copy-left hero the tiles and the mockup are MEANT to cross the bottom
       edge onto the white, which plain `overflow: hidden` prevented.
       overflow-x: clip is the one value that does both. */
    overflow-x: clip;
    overflow-y: visible;
}

/* Browsers without `clip` keep the old behaviour rather than a sideways
   scrollbar — the overhang is a refinement, a horizontal scroll is a bug. */
@supports not (overflow-x: clip){
    .cs-hero{ overflow: hidden; }
}

@supports not (background: color-mix(in srgb, red 10%, white)){
    .cs-hero{ background-image: var(--cs-hero-bg, none),
        linear-gradient(100deg, #000 0%, var(--cs-deep) 38%, var(--cs-accent-3) 100%); }
}

/* ── Pale hero ─────────────────────────────────────────────────────────────
   Care Home Investments opens on a wash of its own light beige into its
   taupe, with the copy in the brand's charcoal. Set in the CLIENT's colours
   like everything else, so a second pale flyer needs no new CSS.

   The flyer prints its headline in white over the mid-taupe. That is about
   2.5:1 against the background — fine on paper, well under the 4.5:1 a screen
   needs — so the ink here is the charcoal the flyer already uses for
   "Case Study" and for the logo. Same palette, same arrangement, readable. */
.cs-hero.is-light{
    background-image: var(--cs-hero-bg, none),
        linear-gradient(100deg,
            color-mix(in srgb, var(--cs-accent-3) 34%, #fff) 0%,
            var(--cs-soft) 30%,
            color-mix(in srgb, var(--cs-accent-2) 72%, #fff) 100%);
    color: var(--cs-deep, #454640);
}

@supports not (background: color-mix(in srgb, red 10%, white)){
    .cs-hero.is-light{ background-image: var(--cs-hero-bg, none),
        linear-gradient(100deg, #fff 0%, var(--cs-soft) 30%, var(--cs-accent-2) 100%); }
}

.cs-hero.is-light .cs-hero-kicker,
.cs-hero.is-light h1,
.cs-hero.is-light .cs-hero-intro,
.cs-hero.is-light .cs-hero-name{ color: var(--cs-deep, #454640); }

/* The paragraphs, not just their wrapper: .cs-hero-intro p sets its own
   rgba(255,255,255,.88) further down, which beats a colour inherited from the
   parent and left the intro all but invisible on the pale band. */
.cs-hero.is-light .cs-hero-intro p,
.cs-hero.is-light .cs-hero-intro li,
.cs-hero.is-light .cs-hero-intro strong{ color: color-mix(in srgb, var(--cs-deep, #454640) 88%, #fff); }

/* The call to action takes the flyer's sage, which only reads on a pale band. */
.cs-hero.is-light .cs-hero-cta{
    background: var(--cs-accent-3);
    color: var(--cs-on-accent-3, #10131a);
}

/* Column proportions MEASURED off the Rose & Crown flyer, expressed against the
   content column (the flyer's 12.3%–88.4% band):

       client mark + button   0.7% →  19.3%
       gap                             5.7%
       headline and copy     25.0% →  69.6%
       device                69.6% → 111.2%   ← past the container, NOT to the
                                                page edge: the laptop stops at
                                                96.9% of the paper.

   The first build ran the device all the way out to the viewport edge, which is
   what made it read as a full-bleed band rather than a device sitting on the
   hero. */
.cs-hero-inner{
    /* Same box as .cs-wrap, so the hero columns line up with every section
       below them. Without it the grid spans the whole viewport, the client
       mark starts hard against the left edge, and the device — which carries a
       negative margin to reach the edge — overshoots past it. */
    max-width: var(--cs-wrap-max, 1120px);
    margin: 0 auto;
    /* The flyer's hero band is 37.3% of the page width tall, which is 49% of
       the content column. Held as a proportion of that column's real width —
       a percentage min-height would not resolve, because nothing above it has
       a definite height. */
    min-height: calc(min(var(--cs-wrap-max, 1120px) - 48px, 100vw - 48px) * 0.49);
    padding: 0 24px 56px;

    display: grid;
    grid-template-columns:
        minmax(0, 18.6fr) minmax(0, 5.7fr)
        minmax(0, 44.6fr) minmax(0, 0.001fr)
        minmax(0, 30.4fr);
    align-items: start;
}

/* grid-row: 1 on all three. The DOM order is brand, copy, media, and on the
   media-middle layout the media belongs in column 3 — BEHIND the copy's column
   5. Grid auto-placement only ever moves forward, so it could not fit there and
   silently dropped the device onto a row of its own: the Vidhi Events hero came
   out nearly twice the height of the printed one, with the laptop stranded
   under the copy instead of between the mark and the text. Same trap as
   .cs-split-text / .cs-split-media further down. */
/* The copy and the media SPAN both rows, so row 1 is sized by the mark alone
   and the button in row 2 sits straight underneath it. Without the span, row 1
   took the full height of the copy column and the button sank to the foot of
   the hero. */
.cs-hero-brand{ grid-column: 1; grid-row: 1; align-self: end; }
.cs-hero-copy { grid-column: 3; grid-row: 1 / span 2; }
.cs-hero-media{ grid-column: 5; grid-row: 1 / span 2; align-self: center; }

/* The button used to live inside .cs-hero-brand. It is a grid child now so a
   hero style can move it; for the two original styles it goes straight back
   under the mark, which is where it has always been. */
.cs-hero-cta{ grid-column: 1; grid-row: 2; justify-self: start; align-self: start; margin-top: 22px; }

/* Vidhi Events runs the device down the MIDDLE with the copy on the right:
   mark 20.6%, gap 2.3%, device 39%, gap 0.6%, copy 37.5% of the content column.
   Same five tracks, different occupants — and the device no longer bleeds,
   because on that flyer it does not touch the paper edge. */
.cs-hero-inner.is-media-middle{
    grid-template-columns:
        minmax(0, 20.6fr) minmax(0, 2.3fr)
        minmax(0, 39fr)   minmax(0, 0.6fr)
        minmax(0, 37.5fr);
    align-items: center;
}

.cs-hero-inner.is-media-middle .cs-hero-media{ grid-column: 3; margin-right: 0; }
.cs-hero-inner.is-media-middle .cs-hero-copy { grid-column: 5; }

/* Care Home Investments: everything the reader reads is in ONE left column —
   "Case Study", the mark, the headline, the subtitle, the intro and the button
   all stack there — with a block of service tiles in the middle and the flyer
   mockup on the right. Measured off the page:

       copy    12.8% →  ~39%
       tiles     38% →   63%
       mockup  60.4% → 95.8%   ← past the content column, hence the overhang

   Expressed against the content column (12.3%–88.4%) that is 35 : 0 : 33 :
   0 : 32, with the mockup allowed to run out to the right. */
.cs-hero-inner.is-copy-left{
    grid-template-columns:
        minmax(0, 35fr) minmax(0, 0.001fr)
        minmax(0, 33fr) minmax(0, 0.001fr)
        minmax(0, 32fr);
    align-items: center;
    column-gap: 20px;
}

/* Both text blocks share column 1, stacked — grid-row is explicit because the
   auto-placement cursor only moves forward and would otherwise push the
   second of them onto a row of its own. */
.cs-hero-inner.is-copy-left .cs-hero-brand{ grid-column: 1; grid-row: 1; align-self: end; }
.cs-hero-inner.is-copy-left .cs-hero-copy { grid-column: 1; grid-row: 2; align-self: start; }
.cs-hero-inner.is-copy-left .cs-hero-cta  { grid-column: 1; grid-row: 3; margin-top: 20px; }

/* Both of these CROSS the bottom edge of the band and finish on the white
   below it. They are taken OUT OF FLOW to do it: as grid items their own
   height set the row height, so a negative margin just pulled the band down
   with them and the overhang came out at six pixels instead of a hundred and
   forty. Positioned, the band is sized by the copy column alone — which is
   what sets it on the page — and these two hang past it.

   left/width are the flyer's own measurements expressed against the content
   column: tiles 36%-65%, mockup 66%-115%. The mockup running past 100% is
   deliberate; it reaches 95.8% of the PAPER, well outside the text column. */
.cs-hero-inner.is-copy-left{ position: relative; }

/* grid-area: auto is load-bearing. An absolutely positioned GRID ITEM takes
   its GRID AREA as the containing block, not the grid container — so with the
   placement left in, left/width resolved against a 341px column and the mockup
   came out a sixth of the size it should be. */
/* The site name under the mark — "(thelax.art)" on the LAX flyer, set small
   and bold just beneath the logo. Rendered from live_url, so it only appears
   on a hero that has one and uses that arrangement. */
.cs-hero-site{
    margin: 14px 0 0;
    font-size: 20px; font-weight: 700; letter-spacing: -0.01em;
    color: #fff;
}
.cs-hero.is-light .cs-hero-site{ color: var(--cs-deep, #0C0C0A); }

/* Service pills BELOW the band, on the white. Two rows of three on the LAX
   flyer, measured x 15.2%-62.3% of the paper — so they start at the content
   column and stop well short of the easel standing on the right.
   max-width keeps them clear of it instead of guessing a column count, which
   would break the moment a case study has five services or seven. */
.cs-hero-pills{
    list-style: none;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 14px;
    margin: 28px auto 0;
    padding: 0;
    width: min(var(--cs-wrap-max, 1120px) - 48px, 100vw - 48px);
    /* The grid spans the content column and is then squeezed into its LEFT
       portion with padding, rather than being narrowed with a percentage
       max-width — that resolved against the full-width shell, not the column,
       and let the right-hand pills run under the easel.

       On the flyer the pills occupy x 15.2%-62.3% of the paper. Against the
       13%-87% content column that is its left 66.6%, so the remaining third is
       reserved for the easel standing beside them. */
    padding-right: 24%;
}
.cs-hero-pills li{
    display: flex; align-items: center; justify-content: center;
    min-height: 56px;
    padding: 12px 18px;
    border-radius: 10px;
    background: var(--cs-deep, #0C0C0A);
    color: #fff;
    font-size: 15px; font-weight: 600; text-align: center;
    text-decoration: underline;
    text-underline-offset: 3px;
}

@media (max-width: 991px){
    /* Below the breakpoint the easel drops under the band, so the pills
       get the full column back. */
    .cs-hero-pills{ grid-template-columns: repeat(2, minmax(0, 1fr)); padding-right: 0; }
}
@media (max-width: 575px){
    .cs-hero-pills{ grid-template-columns: minmax(0, 1fr); }
}

/* ── London Art Exchange ───────────────────────────────────────────────────
   The easel stands further right and is narrower than Care Home's mockup.
   From LAX_Case Study.pdf: the easel box runs x 68.5%-92.5% of the paper, and
   the content column is x 13%-87%, so against that column it starts at
   (68.5-13)/74 = 75% and is 24/74 = 32.4% wide. It overhangs the band further
   too — the legs finish well below it. */
.cs-cs--lax .cs-hero-inner.is-copy-left{
    --cs-hero-media-left: 75%;
    --cs-hero-media-w: 32.4%;
    --cs-hero-media-bottom: -26%;
}
.cs-cs--lax .cs-hero-shell:has(.is-copy-left){ padding-bottom: 150px; }

.cs-hero-inner.is-copy-left .cs-hero-tiles{
    position: absolute;
    grid-area: auto;
    left: 36.4%; width: 27.2%;
    bottom: -24%;
}
.cs-hero-inner.is-copy-left .cs-hero-media{
    position: absolute;
    grid-area: auto;
    /* Defaults are Care Home Investments' measurements. Expressed as custom
       properties because the same arrangement — copy left, object standing on
       the right and overhanging the band — turns up on flyers that place the
       object quite differently. A case study overrides them in its own
       .cs-cs--<slug> block below rather than needing a new hero_style. */
    left:   var(--cs-hero-media-left, 65%);
    width:  var(--cs-hero-media-w, 47.6%);
    bottom: var(--cs-hero-media-bottom, -7%);
    margin: 0;
}

.cs-hero-inner.is-copy-left .cs-hero-brand .cs-logo-img{ max-width: 230px; }
.cs-hero-inner.is-copy-left h1{ margin-top: 18px; margin-bottom: 4px; }

/* The services line the flyer sets hard under the headline, in bold. */
.cs-hero-intro p.cs-hero-sub{
    font-weight: 700;
    font-size: var(--cs-fs-label, 15px);
    line-height: 1.4em;
    margin: 0 0 14px;
}
.cs-hero.is-light .cs-hero-intro p.cs-hero-sub{ color: var(--cs-deep, #454640); }
.cs-hero-inner.is-media-middle .cs-hero h1,
.cs-hero-inner.is-media-middle h1{ max-width: none; }

.cs-hero-kicker{
    display: block;
    font-size: var(--cs-fs-h1);
    font-weight: 700;
    line-height: 1.2;
    color: #fff;
    margin: 0 0 22px;
}

/* The client mark is a PNG ALPHA MASK, not a picture: RGB is black, alpha is
   the ink. Painting it with background-color lets the same file render pale on
   the dark hero and dark on the light brand card, which is what the PDF does,
   without two exports that drift apart. */
.cs-logo{
    display: block;
    width: 100%;
    max-width: 168px;
    /* Set per file by asire_cs_logo_style() — the masks are not one shape. */
    aspect-ratio: var(--cs-logo-ratio, 1);
    background-color: var(--cs-logo-ink, #fff);
    -webkit-mask-image: var(--cs-logo-src);
            mask-image: var(--cs-logo-src);
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
    -webkit-mask-position: center;  mask-position: center;
    -webkit-mask-size: contain;     mask-size: contain;
}

/* If mask-image is unsupported the element would be a solid coloured block —
   worse than nothing. Only paint it where masking actually works. */
@supports not ((-webkit-mask-image: url(x)) or (mask-image: url(x))){
    .cs-logo{ display: none; }
}

/* A full-colour client logo — shown as-is, so it only ever goes on a light
   panel. See asire_cs_logo_kind(). */
.cs-logo-img{
    display: block;
    width: 100%;
    max-width: 190px;
    height: auto;
}

.cs-hero-name{
    font-size: 21px; font-weight: 700; line-height: 1.3;
    color: rgba(255,255,255,.9);
    margin: 0 0 22px;
}

.cs-hero-brand .cs-logo{ --cs-logo-ink: color-mix(in srgb, var(--cs-accent-3) 45%, #fff); margin-bottom: 26px; }

/* The flyer gives the headline a NARROWER measure than the body beneath it —
   31.3%-49.5% against 31.3%-63.5% — which is what makes it break into three
   short lines instead of running the full column width. */
.cs-hero h1{
    color: #fff;
    font-size: var(--cs-fs-h1);
    line-height: 1.22em;
    margin: 0 0 18px;
    max-width: 62%;
}

.cs-hero-intro p{
    color: rgba(255,255,255,0.88);
    font-size: var(--cs-fs-body);
    line-height: 1.62em;
    margin: 0 0 11px;
}

.cs-hero-intro p:last-child{ margin-bottom: 0; }

/* nowrap and a slightly smaller face than the type scale would give. The scale
   is pinned to a 15px body so the page reads on screen, which makes the type
   about a quarter larger relative to the layout than it is on the flyer — fine
   for flowing copy, but "View Live Website" then broke onto two lines inside a
   button the flyer sets on one. */
.cs-hero-cta{
    display: inline-flex; align-items: center; gap: 10px;
    padding: 12px 20px;
    border-radius: 999px;
    font-weight: 700; font-size: var(--cs-fs-cta);
    white-space: nowrap;
    text-decoration: none;
    color: var(--cs-on-accent-2, #fff);
    background: var(--cs-accent-2);
    transition: transform .25s ease, box-shadow .25s ease;
}

.cs-hero-cta:hover{ transform: translateY(-2px); box-shadow: 0 14px 30px rgba(0,0,0,.35); color: var(--cs-deep); }

.cs-hero-services{
    display: flex; flex-wrap: wrap; gap: 8px;
    list-style: none; margin: 24px 0 0; padding: 0;
}

.cs-hero-services li{
    font-size: 12px; font-weight: 600;
    padding: 6px 13px; border-radius: 999px;
    color: #fff;
    background: rgba(255,255,255,.1);
    border: 1px solid rgba(255,255,255,.22);
}

/* Bleeds off the right edge, as the laptop does on the flyer. */
/* The device's right edge lands at 96.9% of the viewport — where the flyer puts
   it, short of the paper edge. Worked out from the container rather than as a
   percentage of the column: a percentage margin on a grid item resolves against
   the grid's inline size, not the item's, so -11.2% overhung by 37px when 136
   were needed. min(0px, …) stops it pushing INWARD on narrow screens, where the
   container already reaches past 96.9%. */
.cs-hero-media{
    margin-right: min(0px, calc(var(--cs-wrap-max, 1120px) / 2 - 24px - 46.9vw));
}
.cs-hero-media img{ width: 100%; height: auto; display: block; }

/* ── Results strip ─────────────────────────────────────────────────────────── */
.cs-results{ background: var(--cs-soft); padding: 30px 0; }
.cs-results-grid{ display: flex; flex-wrap: wrap; gap: 18px 60px; justify-content: center; }
.cs-result-value{ display: block; font-size: 34px; font-weight: 700; line-height: 1.1; color: var(--cs-accent); }
.cs-result-label{ display: block; font-size: 14px; font-weight: 600; color: var(--text-color); }

/* ── Sections ────────────────────────────────────────────────────────────── */
.cs-body{ background: var(--white-color); }

/* The flyer is tight — only 59pt between the "07. Community & Events" and
   "08. Content & Local SEO" ribbons, with three paragraphs in between. 44px
   here is the same rhythm at the 3.75x scale. */
.cs-section{
    padding: 44px 0;
    scroll-margin-top: calc(var(--cs-header-h) + 16px);
}

.cs-section.is-band{
    background: var(--cs-band, var(--cs-accent-3));
    color: #fff;
    padding: 44px 0 52px;
}

.cs-section.is-band .cs-prose p,
.cs-section.is-band .cs-steps-footnote{ color: rgba(255,255,255,.92); }

.cs-section-sub{
    font-size: var(--cs-fs-label); font-weight: 600;
    color: var(--cs-accent); margin: -14px 0 18px;
}

.cs-section.is-band .cs-section-sub{ color: #fff; }

.cs-prose p{
    font-size: var(--cs-fs-body);
    line-height: 1.62em;
    color: var(--text-color);
    margin: 0 0 12px;
}

.cs-prose p:last-child{ margin-bottom: 0; }
.cs-prose strong{ color: var(--primary-color); }

/* The flyer sets these closing remarks as ordinary body copy — no rule, no
   tint. cs-note only controls WHERE the paragraph lands (after the list it
   refers to), not how it looks. */
.cs-prose p.cs-note{
    margin-top: 18px;
    font-size: var(--cs-fs-body);
}

.cs-section.is-band .cs-prose p.cs-note{ border-left-color: #fff; }

/* The flyer's full-width sections run to about 81% of the content column
   ("07. Community & Events" measures 12.3%-74.0% of a 12.3%-88.4% column).
   A conventional 70-80ch web measure is far narrower than that and was making
   these sections look nothing like the printed page. */
/* The flyer gives each full-width section its OWN measure — "07. Community &
   Events" runs to 81% of the content column, "08. Content & Local SEO" to 74%,
   "09. The Result" to only 48%. One shared width made section 09 two-thirds
   too wide. Sections carry --cs-measure when they need something other than
   the default. */
.cs-text-narrow{ max-width: var(--cs-measure, 82%); }

/* ── Split ───────────────────────────────────────────────────────────────────
   Measured off the flyer. Section 03 sets text and image both INSIDE the
   content column:

       text   12.3% → 51.2%   (38.8% of the page)
       gap                     4.0%
       image  55.2% → 89.1%   (33.9%)

   which is the 38.8 : 4 : 33.9 below. Only ONE section on the whole flyer
   bleeds an image to the paper edge — "01. The Challenge" — so bleeding is
   opt-in per section rather than the default the first build made it.

   Images keep their natural aspect ratio. The flyer's own crops already match
   (section 01's is 2.12:1 on the page and 920x433 = 2.12 as a file), so
   object-fit: cover would only re-crop artwork that was already right. */
/* --cs-split is set per section from the flyer's own measurements (see
   case-study-details.php). It has to be a variable rather than one fixed
   ratio because every flyer divides its splits differently: the Rose & Crown
   "01" is a narrow column of copy beside a wide bleeding photo, while the
   Vidhi Events "01" is nearly all copy with a small portrait beside it. The
   literal below is the fallback for a section that carries no measurement. */
.cs-split{
    display: grid;
    grid-template-columns: var(--cs-split, minmax(0, 38.8fr) minmax(0, 4fr) minmax(0, 33.9fr));
    align-items: center;
}

/* A "lead" split has already printed its heading and its opening copy at full
   width above, so the two columns are only a short paragraph and a picture.
   Centring them would float the paragraph in the middle of a tall photo; the
   flyer hangs both from the same top line. */
.cs-split.is-lead{ align-items: start; margin-top: 18px; }

/* grid-row: 1 on both is not decoration. Auto-placement walks the children in
   DOM order and only ever moves forward, so in a flipped split — where the
   text is in column 3 and the picture in column 1 — the picture cannot fit
   after the text on row 1 and silently drops to a row of its own. The section
   then reads as a column of copy with the image stranded underneath it, which
   is what left a white gap beside "03. Brand Development". */
.cs-split-text { grid-column: 1; grid-row: 1; }
.cs-split-media{ grid-column: 3; grid-row: 1; }

.cs-split-media img{ width: 100%; height: auto; display: block; }

/* See --cs-panel-bg in case-study-details.php: the column fills the row height
   in the artwork's own background colour so a flat-lay does not float in white. */
.cs-split-media.has-panel{
    align-self: stretch;
    display: grid;
    place-items: center;
    background: var(--cs-panel-bg, #7a5c28);
}

.cs-split.is-flipped .cs-split-text { grid-column: 3; grid-row: 1; }
.cs-split.is-flipped .cs-split-media{ grid-column: 1; grid-row: 1; }

/* "01. The Challenge": on the page that is text 12.3%-40.3%, gap, image
   52.1%-100%. Expressed against the CONTENT COLUMN (12.3%-88.4%) rather than
   the whole page, that is 36.8 : 15.5 : 47.7 — the grid only ever divides the
   container, and the image reaches the paper edge through the negative margin
   below. Using the page-relative 28 : 11.8 : 47.9 here made the text column
   five points too narrow. */
.cs-split.is-bleed{ grid-template-columns: var(--cs-split, minmax(0, 36.8fr) minmax(0, 15.5fr) minmax(0, 47.7fr)); }
.cs-split.is-bleed .cs-split-media{ margin-right: calc(var(--cs-bleed) * -1); }
.cs-split.is-bleed.is-flipped .cs-split-media{ margin-right: 0; margin-left: calc(var(--cs-bleed) * -1); }

/* A split whose media column holds two images instead of one — section 06
   pairs two venue photos at 16.3% each with a 1.6% gutter between them. */
.cs-split-media .cs-stack{ display: grid; grid-template-columns: 1fr 1fr; gap: 4.5%; }
.cs-split-media .cs-stack img{ width: 100%; height: 100%; object-fit: cover; aspect-ratio: 1 / 1; display: block; }

/* ── Galleries ───────────────────────────────────────────────────────────── */
.cs-gallery{
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: 16px;
    margin-top: 26px;
}

.cs-gallery img{
    width: 100%; height: 100%;
    object-fit: cover; display: block;
    aspect-ratio: 4 / 3;
}

/* --cs-media is the flyer's own width for this picture, as a share of the
   content column. Default 100% keeps the previous behaviour; a section that
   prints its artwork smaller sets its own and it centres. */
.cs-figure{ margin: 26px auto 0; max-width: var(--cs-media, 100%); }
.cs-figure img{ width: 100%; height: auto; display: block; }

/* Band gallery: images and the prose share one row, the way the flyer sets
   photo / photo / text / photo across the olive band. */
/* The flyer sets this row as photo 16.9% / photo 16.9% / copy 19.2% / photo
   16.9% of the page — the copy column is a shade wider than the pictures, not
   an equal quarter. auto-fit made all four the same and squeezed the copy. */
.cs-bandrow{
    display: grid;
    grid-template-columns: 16.9fr 16.9fr 19.2fr 16.9fr;
    gap: 18px;
    align-items: stretch;
    margin-top: 24px;
}

/* Flyer crops these portrait — 16.9% of the page wide against 89pt tall. */
.cs-bandrow img{ width: 100%; height: 100%; aspect-ratio: 0.88; object-fit: cover; display: block; }
.cs-bandrow .cs-prose{ align-self: center; }
.cs-bandrow .cs-prose p{ font-size: 14px; line-height: 1.7em; }

/* ── Cards ───────────────────────────────────────────────────────────────── */
.cs-cards{
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 18px; margin-top: 26px; list-style: none; padding: 0;
}

.cs-card{
    background: #fff;
    border: 1px solid rgba(3,29,54,.09);
    border-top: 3px solid var(--cs-accent);
    padding: 24px 22px;
}

.cs-card h3{ font-size: 16px; line-height: 1.4em; margin: 0 0 8px; color: var(--primary-color); }
.cs-card p{ font-size: 14px; line-height: 1.66em; color: var(--text-color); margin: 0; }

/* ── Keyword pills ───────────────────────────────────────────────────────────
   Alternating olive / gold, matching "08. Content & Local SEO". */
.cs-pills{
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 12px; margin: 26px 0 0; padding: 0; list-style: none;
}

.cs-pill{
    display: flex; align-items: center; justify-content: center;
    text-align: center;
    padding: 10px 18px;
    border-radius: 999px;
    font-size: var(--cs-fs-label); font-weight: 600;
    color: var(--cs-on-accent-3, #fff);
    background: var(--cs-accent-3);
}

.cs-pill:nth-child(even){ background: var(--cs-accent-2); color: var(--cs-on-accent-2, #fff); }

/* The flyer lays these out four-up and colours them as a CHECKERBOARD, not a
   simple alternation: row one runs olive, gold, olive, gold and row two starts
   on gold again. Straight nth-child(even) puts two olives under each other.
   Only applied where the grid really is four columns — below that the count
   varies with the viewport and a checkerboard keyed to four would be wrong. */
@media (min-width: 992px){
    .cs-pills{ grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .cs-pill:nth-child(8n+1),
    .cs-pill:nth-child(8n+3),
    .cs-pill:nth-child(8n+6),
    .cs-pill:nth-child(8n+8){ background: var(--cs-accent-3); color: var(--cs-on-accent-3, #fff); }
    .cs-pill:nth-child(8n+2),
    .cs-pill:nth-child(8n+4),
    .cs-pill:nth-child(8n+5),
    .cs-pill:nth-child(8n+7){ background: var(--cs-accent-2); color: var(--cs-on-accent-2, #fff); }
}

/* ── Tiles ───────────────────────────────────────────────────────────────────
   A captioned image grid. The artwork arrives already cut to shape with
   transparency — hexagons, circles, gold laurels — so nothing here clips or
   masks it; `shape` only decides how many fit across and how large they run.

   auto-fit rather than a fixed count: the flyer sets nine hexagons to a row,
   which is fine on paper and unreadable on a laptop, let alone a phone.      */
.cs-tiles{
    display: grid;
    gap: 22px 14px;
    margin: 26px 0 0;
    padding: 0;
    list-style: none;
}

.cs-tiles.is-hex   { grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); }
.cs-tiles.is-round { grid-template-columns: repeat(auto-fit, minmax(104px, 1fr)); }
.cs-tiles.is-square{ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.cs-tiles.is-wide  { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 26px 22px; }

.cs-tile{
    display: flex; flex-direction: column; align-items: center;
    text-align: center; gap: 9px;
}

.cs-tile-art{ display: block; width: 100%; }

/* `width: auto` rather than 100%: the supplied artwork ranges from 100px icons
   to 900px emblems, and stretching every one to fill its cell blew the small
   ones up threefold and softened them. This way an image renders at its own
   size, shrinks if the cell is narrower, and never grows past it — no
   per-shape magic numbers to keep in step with the files. */
.cs-tile-art img{
    width: auto; max-width: 100%; height: auto;
    display: block; margin: 0 auto;
    transition: transform .3s ease;
}

.cs-tile:hover .cs-tile-art img{ transform: translateY(-3px) scale(1.03); }

.cs-tile-label{
    font-size: 13px; font-weight: 700; line-height: 1.3;
    color: var(--primary-color);
}

.cs-section.is-band .cs-tile-label{ color: #fff; }

.cs-tile-note{
    font-size: 13px; line-height: 1.55em;
    color: var(--text-color);
    max-width: 30ch;
}

.cs-tiles.is-wide .cs-tile-label{ font-size: 15px; }

/* ── Brand panel row ─────────────────────────────────────────────────────── */
/* Flyer: logo card 12.3%-34.6%, gap 5.6%, copy 40.2%-87.8%. */
.cs-brand{
    display: grid;
    grid-template-columns: minmax(0, 22.3fr) minmax(0, 5.6fr) minmax(0, 47.6fr);
    align-items: start;
}

.cs-brand-card{ grid-column: 1; }
.cs-brand-copy{ grid-column: 3; }

.cs-brand-card{
    background: #EFEFEF;
    padding: 22px;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    min-height: 220px;
}

.cs-brand-card .cs-panel-label{ align-self: flex-start; }
.cs-brand-card .cs-logo{ --cs-logo-ink: #3F412F; max-width: 150px; }

/* ── Banded brand section (LAX) ────────────────────────────────────────────
   Rose & Crown prints this block on white with the logo on a card beside the
   copy. LAX prints it on a near-black band: copy across the top, then one row
   of logo + colour field + typography, then the artwork strip.

   Measured off LAX_Case Study.pdf against the 13%-87% content column:
     logo        x 13.0%-37.0%  ->   0%-32%
     colours     x 43.3%-63.0%  ->  41%-67.6%
     typography  x 64.7%-84.4%  ->  70%-96.5%
   The logo stands apart; the two panels nearly butt together. */
.cs-brand-row{
    display: grid;
    grid-template-columns:
        minmax(0, 32fr) minmax(0, 9fr)
        minmax(0, 59fr);
    align-items: center;
    margin-top: 34px;
}
.cs-brand-row > .cs-brand-mark{ grid-column: 1; }
.cs-brand-row > .cs-panels{ grid-column: 3; max-width: none; margin: 0; }

/* No plate behind it — on the flyer the wordmark sits straight on the band. */
.cs-brand-mark{ display: flex; align-items: center; }
.cs-brand-mark .cs-logo-img{ width: 100%; max-width: 300px; height: auto; }
.cs-brand-mark .cs-logo{ --cs-logo-ink: #fff; width: 100%; max-width: 300px; height: 64px; }

/* Two panels of equal width, all but touching, as printed. */
.cs-brand-row .cs-panels{
    display: grid;
    grid-template-columns: minmax(0, 45fr) minmax(0, 3fr) minmax(0, 45fr);
}
.cs-brand-row .cs-panels > .cs-panel:first-child{ grid-column: 1; }
.cs-brand-row .cs-panels > .cs-panel:last-child { grid-column: 3; }

/* The colour field is a grey plate carrying the two circles; the typography
   panel is white. Both are the flyer's own, not the page palette. */
.cs-section.is-band .cs-panel-colors{ background: #8E8E8E; }
.cs-section.is-band .cs-panel-type  { background: #fff; }
.cs-section.is-band .cs-panel{ min-height: 150px; }

/* Circles, not the small squares the unbanded version uses. */
.cs-section.is-band .cs-swatches{ gap: 18px; justify-content: center; align-items: center; }
.cs-section.is-band .cs-swatch{
    width: 86px; height: 86px;
    border-radius: 50%;
    border: 0;
}

/* Copy on a dark band has to flip to light ink. */
.cs-section.is-band .cs-section-sub,
.cs-section.is-band .cs-prose{ color: rgba(255,255,255,.88); }
.cs-section.is-band .cs-section-sub{ color: #fff; }

/* …but the panels INSIDE that band carry their own pale plates, so their ink
   has to flip straight back. White-on-white is how "Montserrat" and the two
   panel labels vanished entirely on the first pass. */
.cs-section.is-band .cs-panel .cs-panel-label,
.cs-section.is-band .cs-panel .cs-type-sample{ color: var(--cs-deep, #0C0C0A); }

/* The ribbon is a white plate with near-black type on this flyer, not the
   grey the shared block style would give it on a pale section. */
.cs-section.is-band .cs-ribbon{
    background: #fff;
    color: var(--cs-deep, #0C0C0A);
}
.cs-section.is-band .cs-ribbon .cs-ribbon-no{ color: var(--cs-deep, #0C0C0A); }

.cs-brand-below{ margin-top: 40px; }
.cs-brand-below img{ width: 100%; height: auto; display: block; }

@media (max-width: 991px){
    .cs-brand-row{ grid-template-columns: minmax(0, 1fr); gap: 24px; }
    .cs-brand-row > .cs-brand-mark,
    .cs-brand-row > .cs-panels{ grid-column: 1; }
    .cs-brand-row .cs-panels{ grid-template-columns: minmax(0, 1fr); gap: 14px; }
    .cs-brand-row .cs-panels > .cs-panel:first-child,
    .cs-brand-row .cs-panels > .cs-panel:last-child{ grid-column: 1; }
}

/* Flyer: swatch panel 12.3%-34.6%, menu photo 39.3%-61.5%, type panel
   62.0%-77.6%. Note the photo and the type panel BUTT TOGETHER while the first
   panel stands apart, and the row stops well short of the right margin — it is
   not a full-width three-up. */
.cs-panels{
    display: grid;
    grid-template-columns:
        minmax(0, 22.3fr) minmax(0, 4.7fr)
        minmax(0, 22.2fr) minmax(0, 0.5fr)
        minmax(0, 15.6fr);
    margin-top: 20px;
    max-width: 86.5%;
}

.cs-panels > .cs-panel:nth-of-type(1){ grid-column: 1; }
.cs-panels > .cs-panel:nth-of-type(2){ grid-column: 3; }
.cs-panels > .cs-panel:nth-of-type(3){ grid-column: 5; }

.cs-panel{ position: relative; min-height: 190px; padding: 18px; }
.cs-panel-colors,
.cs-panel-type{ background: var(--cs-accent-3); color: #fff; }
.cs-panel-image{ padding: 0; }
.cs-panel-image img{ width: 100%; height: 100%; object-fit: cover; display: block; }

.cs-panel-label{
    display: block;
    font-size: var(--cs-fs-small); font-weight: 700;
    letter-spacing: .12em; text-transform: uppercase;
    margin-bottom: 14px;
}

.cs-swatches{ display: flex; flex-wrap: wrap; gap: 14px; align-items: center; justify-content: center; height: calc(100% - 30px); }
/* The panel behind these is the band colour, and a client's palette usually
   CONTAINS that colour — so without a ring the matching swatch vanishes into
   the background and the row silently shows one fewer colour than it should. */
.cs-swatch{
    width: 48px; height: 48px; border-radius: 50%; display: block;
    box-shadow: 0 0 0 1px rgba(255,255,255,.55);
}

.cs-type-sample{
    font-size: var(--cs-fs-type); line-height: 1.22em; font-weight: 700;
    display: flex; align-items: center; height: calc(100% - 30px);
}

/* ── Customer journey ────────────────────────────────────────────────────────
   A numbered rail with icon badges alternating above and below it, then the
   chevron path. Built from clip-path and flex rather than the flyer's flat
   artwork, so the labels stay real text and it reflows on a phone. */
.cs-journey{ margin-top: 34px; }

.cs-rail-track{
    position: relative;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    align-items: center;
    padding: 0;
    margin: 0;
    list-style: none;
}

/* The line itself. Inset by half a column so it starts and ends at the first
   and last node rather than floating past them. */
.cs-rail-track::before{
    content: "";
    position: absolute;
    left: 8%; right: 8%;
    top: 50%;
    height: 3px;
    background: #111;
    transform: translateY(-1.5px);
}

/* Tall enough for a two-line label plus the hexagon plus the 46px leader on
   BOTH sides of the line. At 260px the upper badges overflowed the top of the
   section and ate into the ribbon's breathing room. */
.cs-stop{
    position: relative;
    display: flex; flex-direction: column; align-items: center;
    min-height: 310px;
    justify-content: center;
}

.cs-stop-num{
    position: relative; z-index: 2;
    width: 26px; height: 26px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: 12px; font-weight: 700;
    background: #fff; color: #111;
    border: 2px solid var(--cs-accent-3);
}

.cs-stop.is-gold .cs-stop-num{ border-color: var(--cs-accent-2); }

/* The dotted leader between the node and its badge. */
.cs-stop-leader{
    position: absolute; left: 50%; width: 0;
    border-left: 2px dotted #7a7a7a;
    z-index: 1;
}

.cs-stop.is-above .cs-stop-leader{ bottom: 50%; height: 46px; }
.cs-stop.is-below .cs-stop-leader{ top: 50%; height: 46px; }

.cs-stop-badge{
    position: absolute; left: 50%; transform: translateX(-50%);
    display: flex; flex-direction: column; align-items: center; gap: 8px;
    width: 140px; text-align: center;
}

.cs-stop.is-above .cs-stop-badge{ bottom: calc(50% + 46px); }
.cs-stop.is-below .cs-stop-badge{ top: calc(50% + 46px); }

.cs-stop-label{ font-size: 13px; font-weight: 700; color: #111; line-height: 1.3; }

/* Hexagon ring: an outer coloured hexagon with a white one inset inside it. */
.cs-hex{
    position: relative;
    width: 54px; height: 60px;
    background: var(--cs-hex, var(--cs-accent-3));
    -webkit-clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
            clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
    display: flex; align-items: center; justify-content: center;
}

.cs-hex::before{
    content: "";
    position: absolute; inset: 4px;
    background: #fff;
    -webkit-clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
            clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

.cs-hex svg{ position: relative; z-index: 1; width: 24px; height: 24px; color: #2b2b2b; }
.cs-stop.is-gold .cs-hex{ --cs-hex: var(--cs-accent-2); }

/* ── Chevron path ────────────────────────────────────────────────────────────
   On the flyer this runs 12.3%-68.4% of the page — about 74% of the content
   column, not the full width — with hexagon badges alternating above and below
   it, the same way the numbered rail above does.

   Three fixed rows per cell rather than a flex column, so every chevron sits on
   the same line whether or not its cell has a badge. */
.cs-chevrons{
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: 3px;
    margin: 34px 0 0; padding: 0; list-style: none;
    /* The flyer runs this to 74% of the content column, but its labels are set
       at 4pt on a 350pt column. Web body copy has to be ~15px in a 1070px
       column, which is proportionally larger, so at 74% every label wraps onto
       two lines — and a chevron path whose steps are two lines tall looks
       nothing like the printed one. 92% keeps them on a single line, which is
       the detail that actually reads. */
    max-width: 92%;
}

.cs-chev-cell{
    display: grid;
    grid-template-rows: 74px auto 74px;
    align-items: center;
    justify-items: center;
}

.cs-chev-cell .cs-chev       { grid-row: 2; }
.cs-chev-cell.is-above .cs-chev-badge{ grid-row: 1; }
.cs-chev-cell.is-below .cs-chev-badge{ grid-row: 3; }

.cs-chev{
    width: 100%;
    display: flex; align-items: center; justify-content: center;
    text-align: center;
    padding: 11px 20px 11px 26px;
    font-size: 13px; font-weight: 700; color: var(--cs-on-accent-3, #fff);
    background: var(--cs-accent-3);
    -webkit-clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 50%, calc(100% - 14px) 100%, 0 100%, 14px 50%);
            clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 50%, calc(100% - 14px) 100%, 0 100%, 14px 50%);
}

.cs-chev-cell:nth-child(even) .cs-chev{ background: var(--cs-accent-2); color: var(--cs-on-accent-2, #fff); }
.cs-chev-cell:nth-child(even) .cs-hex{ --cs-hex: var(--cs-accent-2); }

/* ── Client closing strip ────────────────────────────────────────────────── */
/* Flyer: three equal panels, 37pt tall on a 460.8pt page — about 8% of the
   page width, which is 110px against a 1300px container. */
.cs-clientfoot{
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: center;
    min-height: 110px;
}

.cs-cf-panel{
    display: flex; align-items: center; justify-content: center; gap: 16px;
    height: 100%; padding: 22px 26px; text-align: center;
}

.cs-cf-mark{ background: color-mix(in srgb, var(--cs-accent-2) 45%, #fff); }
@supports not (background: color-mix(in srgb, red 10%, white)){ .cs-cf-mark{ background: #E9BF7D; } }

.cs-cf-mark .cs-logo{ --cs-logo-ink: #3F412F; max-width: 68px; }
/* The mark on its own is squarer than the stacked lockup. */
.cs-cf-mark .cs-logo-mark{ aspect-ratio: 305 / 318; max-width: 62px; }
.cs-cf-mark .cs-cf-name{
    font-size: var(--cs-fs-label); font-weight: 700;
    letter-spacing: .06em; text-transform: uppercase; color: #3F412F;
}

.cs-cf-tag{ background: var(--primary-color); color: #fff; font-size: var(--cs-fs-tagline); font-weight: 700; }

/* A light-ink client lockup needs a dark plate to sit on — see the $footDark
   branch in case-study-details.php. */
.cs-cf-mark.is-dark{ background: var(--cs-deep, #0C0C0A); }
.cs-cf-mark.is-dark .cs-logo-img{ max-width: 210px; }

/* LAX prints the middle panel pale with black type rather than the navy the
   other flyers use. Measured off page 11 of the flyer. */
.cs-cs--lax .cs-cf-tag{
    background: #D9D9D6;
    color: var(--cs-deep, #0C0C0A);
}

.cs-cf-by{ background: #ECECEC; flex-direction: column; gap: 8px; }
.cs-cf-by span{ font-size: var(--cs-fs-label); font-weight: 700; color: var(--accent-color); }
.cs-cf-by img{ width: 130px; height: auto; }

/* ── Asire outro + related ───────────────────────────────────────────────── */
.cs-outro{ background: var(--cs-deep); color: #fff; padding: 70px 0; text-align: center; }
.cs-outro h2{ color: #fff; font-size: 32px; margin: 0 0 14px; }
.cs-outro p{ color: rgba(255,255,255,.78); max-width: 600px; margin: 0 auto 26px; }
.cs-outro-actions{ display: flex; flex-wrap: wrap; gap: 14px; justify-content: center; }

.cs-outro-actions a{
    display: inline-flex; align-items: center; gap: 9px;
    padding: 14px 28px; border-radius: 999px;
    font-weight: 700; text-decoration: none;
    transition: transform .25s ease;
}

.cs-outro-actions a:hover{ transform: translateY(-2px); }
.cs-outro-primary{ background: var(--cs-accent-2); color: var(--cs-deep); }
.cs-outro-primary:hover{ color: var(--cs-deep); }
.cs-outro-ghost{ background: transparent; color: #fff; border: 1px solid rgba(255,255,255,.35); }
.cs-outro-ghost:hover{ color: #fff; }

/* ==========================================================================
   Paired sections — two of them sharing one row
   ==========================================================================
   See "pair" in case-study-details.php. The two sections keep their own
   ribbons and their own ids (the jump rail still reaches both); only their
   boxes are set side by side. Each drops its own vertical padding so the pair
   reads as one spread rather than two stacked blocks squeezed together. */
.cs-pair{
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 0 48px;
    align-items: start;
}
.cs-pair > .cs-section{ padding-top: 0; padding-bottom: 0; }
.cs-pair{ padding: 54px 0; }
.cs-pair .cs-wrap{ padding-left: 0; padding-right: 0; max-width: none; }

/* The wrapper itself carries the page gutter, since its children gave theirs up. */
.cs-body > .cs-pair{
    max-width: var(--cs-wrap-max, 1120px);
    margin-left: auto; margin-right: auto;
    padding-left: 24px; padding-right: 24px;
}

/* The image the page prints under a whole paired spread. */
.cs-pair-after{ padding: 0 0 54px; }

/* A section that is nothing but its artwork — the supplied panel already has
   the heading and the copy printed on it. */
.cs-section.is-bare{ padding: 30px 0; }

/* ── Captioned image columns (extras.columns) ─────────────────────────────── */
.cs-cols{
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 34px;
    margin-top: 26px;
    align-items: start;
}
.cs-col{ display: flex; flex-direction: column; align-items: center; text-align: center; }

/* Labels as plain type rather than pills, everything left-aligned — the shape
   "02. Campaign Examples" takes, where "Campaign 01 / Abbey Row, Liverpool" is
   a two-line heading over the artwork, not a button. */
.cs-cols.is-plain .cs-col{ align-items: stretch; text-align: left; }
.cs-cols.is-plain .cs-col-label{
    background: none; padding: 0; border-radius: 0;
    color: var(--cs-ink, #10131a);
    font-size: var(--cs-fs-type, 22px); font-weight: 400; line-height: 1.25;
}
.cs-cols.is-plain .cs-col-label strong{ display: block; font-weight: 700; }
.cs-cols.is-plain .cs-col-note{ margin-top: 0; }
.cs-cols.is-plain .cs-col > img{ margin-top: 20px; max-width: 100%; }

/* A columns row set as one dark panel — the Elite Realty "The Objective" block,
   where the artwork and the copy share a single navy card rather than sitting
   as two separate centred columns. */
.cs-cols.is-panel{
    background: var(--cs-accent, #26404F);
    border-radius: 4px;
    overflow: hidden;
    gap: 0;
    align-items: stretch;
    margin-top: 26px;
}
.cs-cols.is-panel .cs-col{ text-align: left; align-items: stretch; }
.cs-cols.is-panel .cs-col > img{ margin: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 0; }
.cs-cols.is-panel .cs-col:last-child{ padding: 22px 26px; justify-content: center; }
.cs-cols.is-panel .cs-col-label{
    background: none; padding: 0; margin-bottom: 10px;
    color: #fff; font-size: var(--cs-fs-type, 22px); line-height: 1.2;
}
.cs-cols.is-panel .cs-col-note{ margin: 0; color: rgba(255,255,255,.88); }

/* When the heading lives in one of the columns the row has no header above it,
   so it starts at the top of the section rather than under one. */
.cs-cols.has-header{ margin-top: 0; align-items: start; }

/* That column's heading block is left-aligned prose, not the centred caption
   the other columns carry. */
.cs-col-header{ width: 100%; text-align: left; margin-bottom: 8px; }
.cs-col-header .cs-ribbon{ margin-top: 0; }

.cs-col-label{
    display: inline-block;
    padding: 9px 30px;
    border-radius: 999px;
    background: var(--cs-accent-2, #A5897D);
    color: var(--cs-on-accent-2, #fff);
    font-size: var(--cs-fs-cta, 17px);
    font-weight: 700;
    line-height: 1.2;
}

.cs-col-note{
    margin: 14px 0 0;
    font-size: var(--cs-fs-body, 15px);
    line-height: 1.6em;
    color: var(--cs-ink-soft, #4a5260);
}

/* Natural proportions. These columns pair a tall email creative with a wide
   screenshot, which is exactly the case a fixed aspect-ratio or object-fit
   would distort. */
.cs-col img{
    margin-top: 18px;
    width: auto; max-width: 100%; height: auto;
    display: block;
    border-radius: 6px;
}

/* ── Icon list (extras.list) ──────────────────────────────────────────────── */
.cs-iconlist{ list-style: none; margin: 22px 0 0; padding: 0; display: grid; gap: 16px; }

.cs-iconrow{ display: grid; grid-template-columns: 34px minmax(0, 1fr); gap: 16px; align-items: center; }

/* Several across rather than one stacked column, each in its own outlined box
   — the shape "05. The Result" takes on the Elite Realty flyer. */
.cs-iconlist.is-grid{
    grid-template-columns: repeat(var(--cs-list-cols, 3), minmax(0, 1fr));
    gap: 14px;
}
.cs-iconlist.is-grid .cs-iconrow{
    padding: 14px 18px;
    border: 1px solid rgba(3,29,54,.16);
    border-radius: 12px;
    grid-template-columns: 30px minmax(0, 1fr);
    gap: 13px;
    align-items: center;
}
@media only screen and (max-width: 991px){
    .cs-iconlist.is-grid{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media only screen and (max-width: 575px){
    .cs-iconlist.is-grid{ grid-template-columns: minmax(0, 1fr); }
}

.cs-iconrow-art{ display: block; }
.cs-iconrow-art img{ width: 100%; height: auto; display: block; }

.cs-iconrow-text{
    font-size: var(--cs-fs-body, 15px);
    line-height: 1.55em;
    color: var(--cs-ink, #10131a);
}

/* ── Section call to action (extras.cta) ──────────────────────────────────── */
.cs-cta-row{ margin: 30px 0 0; text-align: center; }

.cs-cta{
    display: inline-flex; align-items: center; gap: 10px;
    padding: 13px 32px;
    border-radius: 999px;
    background: var(--cs-accent-2, #A5897D);
    color: var(--cs-on-accent-2, #fff);
    font-size: var(--cs-fs-cta, 17px);
    font-weight: 700;
    text-decoration: none;
    transition: transform .25s ease, box-shadow .25s ease;
}
.cs-cta:hover{
    color: var(--cs-on-accent-2, #fff);
    transform: translateY(-2px);
    box-shadow: 0 12px 26px rgba(3,29,54,.18);
}
.cs-cta svg{ transition: transform .25s ease; }
.cs-cta:hover svg{ transform: translate(2px, -2px); }

/* ==========================================================================
   Banner hero — one photograph behind the whole band
   ==========================================================================
   The Rumble Rooms flyer does not put a device beside the copy: the bar
   photograph IS the band, veiled in the brand's red, with the copy over it and
   a row of service chips underneath. hero-bg.jpg supplies the photograph
   through the same file convention the other heroes use. */
.cs-hero-inner.is-banner{
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
}
.cs-hero-inner.is-banner > *{ grid-column: 1; }
.cs-hero-inner.is-banner .cs-hero-brand{ grid-row: 1; align-self: start; }
.cs-hero-inner.is-banner .cs-hero-copy { grid-row: 2; max-width: 640px; }
.cs-hero-inner.is-banner .cs-hero-cta  { grid-row: 3; }
.cs-hero-inner.is-banner .cs-hero-chips{ grid-row: 4; }
.cs-hero-inner.is-banner .cs-hero-media{ display: none; }

/* Elite Realty sets its five services out as one radial diagram, centred and
   crossing the foot of the band onto the white. Same overhang reasoning as the
   copy-left hero: .cs-hero clips sideways only, so this can hang below. */
.cs-hero-inner.is-banner .cs-hero-tiles{
    grid-row: 5;
    justify-self: center;
    width: 100%; max-width: 360px;
    margin-bottom: -22%;
}
/* Room on the white for the part of the diagram that hangs below the band.
   It has to clear the overhang, which is a share of the grid's width — hence
   the same basis here rather than a flat pixel guess. At 96px the diagram
   landed 73px INTO section 01. */
.cs-hero-shell:has(.is-banner .cs-hero-tiles){
    padding-bottom: calc(min(var(--cs-wrap-max, 1120px) - 48px, 100vw - 48px) * 0.18);
}

/* The mark leads this hero and is printed large — a quarter of the band's
   width on the flyer, not the badge-sized lockup the other layouts use. */
.cs-hero-inner.is-banner .cs-hero-brand .cs-logo-img,
.cs-hero-inner.is-banner .cs-hero-brand .cs-logo{
    max-width: 340px; width: 100%; height: auto;
}
.cs-hero-inner.is-banner h1{ max-width: 620px; }

/* The photograph is a background layer, so the veil cannot be a background too
   — it would sit under it. An overlay element is the only way to get the red
   over the picture and the copy over the red. */
.cs-hero.is-banner{ position: relative; }
.cs-hero.is-banner::before{
    content: '';
    position: absolute; inset: 0;
    /* The warm end is the client's accent DARKENED toward their deep colour,
       not the accent or the secondary raw. Rumble Rooms' accent is a bright
       #E31E24 and Elite Realty's secondary is gold — either used neat gives a
       veil too light to read white type on. Mixing to roughly the flyer's own
       printed tone works for both and needs no per-client knob. */
    --cs-veil: color-mix(in srgb, var(--cs-accent, #811F1F) 55%, var(--cs-deep, #1C0C0C));
    background: linear-gradient(95deg,
        color-mix(in srgb, var(--cs-veil) 93%, transparent) 0%,
        color-mix(in srgb, var(--cs-veil) 74%, transparent) 55%,
        color-mix(in srgb, var(--cs-deep, #1C0C0C) 86%, transparent) 100%);
    pointer-events: none;
}
@supports not (background: color-mix(in srgb, red 10%, white)){
    .cs-hero.is-banner::before{ background: linear-gradient(95deg, rgba(40,20,20,.92), rgba(28,12,12,.86)); }
}
.cs-hero.is-banner > *{ position: relative; z-index: 1; }

/* ── Fact cards with a badge straddling the top edge ──────────────────────── */
/* Flex, not grid, and deliberately. A grid leaves a trailing part-row hard
   left — five cards come out as three then two tucked under the first two.
   The flyer centres that last pair, which is what justify-content does here
   and what no grid track listing can. --cs-card-cols is set per section. */
.cs-cards.has-badges{
    display: flex; flex-wrap: wrap; justify-content: center;
    margin-top: 58px;   /* room for the badges, which sit half outside */
    gap: 18px;
}
.cs-cards.has-badges > .cs-card{
    flex: 0 1 calc((100% - (var(--cs-card-cols, 4) - 1) * 18px) / var(--cs-card-cols, 4));
}
@media only screen and (max-width: 991px){
    .cs-cards.has-badges > .cs-card{ flex-basis: calc((100% - 18px) / 2); }
}
@media only screen and (max-width: 575px){
    .cs-cards.has-badges > .cs-card{ flex-basis: 100%; }
}
.cs-cards.has-badges .cs-card{
    position: relative;
    overflow: visible;
    padding-top: 42px;
    text-align: center;
}

.cs-card-badge{
    position: absolute;
    top: 0; left: 50%;
    transform: translate(-50%, -50%);
    width: 62px; height: 62px;
    display: grid; place-items: center;
    border-radius: 50%;
    background: var(--cs-deep, #1C0C0C);
}
.cs-card-badge img{ width: 32px; height: 32px; object-fit: contain; display: block; }

/* The outcome cards badge in the brand's dark red rather than its near-black. */
.cs-cards.is-accent .cs-card-badge{ background: var(--cs-accent-2, #811F1F); }

/* ── Inline cards: icon beside the label ──────────────────────────────────────
   The LAX flyer's "Key Outcomes" row. The supplied PNGs are already a filled
   black disc with a white glyph and transparent corners, so the badge here
   carries NO plate of its own — giving it one would print a dark square behind
   the disc. Flex for the same reason as .has-badges above: a trailing part-row
   centres instead of hanging left. */
.cs-cards-title{
    font-size: 24px; line-height: 1.3em; font-weight: 700;
    color: var(--cs-deep, var(--primary-color));
    margin: 34px 0 0;
}
.cs-cards-title + .cs-cards{ margin-top: 16px; }

.cs-cards.is-inline{
    display: flex; flex-wrap: wrap; justify-content: flex-start;
    gap: 18px;
}
.cs-cards.is-inline > .cs-card{
    flex: 0 1 calc((100% - (var(--cs-card-cols, 4) - 1) * 18px) / var(--cs-card-cols, 4));
    display: flex; align-items: center; gap: 14px;
    padding: 10px 14px;
    border: 1px solid rgba(12,12,10,.22);
    border-top: 2px solid var(--cs-deep, #0C0C0A);
    text-align: left;
}
.cs-cards.is-inline .cs-card h3{
    margin: 0;
    font-size: 14px; line-height: 1.35em;
    color: var(--cs-deep, var(--primary-color));
}
.cs-cards.is-inline .cs-card-badge{
    position: static; transform: none;
    flex: 0 0 auto;
    width: 46px; height: 46px;
    background: none; border-radius: 0;
}
.cs-cards.is-inline .cs-card-badge img{ width: 46px; height: 46px; }

@media only screen and (max-width: 991px){
    .cs-cards.is-inline > .cs-card{ flex-basis: calc((100% - 18px) / 2); }
}
@media only screen and (max-width: 575px){
    .cs-cards.is-inline > .cs-card{ flex-basis: 100%; }
}

/* Artwork inside a card body — the client's mark on the CLIENT card. */
.cs-card-art{
    width: auto; max-width: 76%; height: auto;
    margin: 14px auto 0;
    display: block;
}

/* ── Hero service chips ───────────────────────────────────────────────────── */
.cs-hero-chips{
    list-style: none; margin: 30px 0 0; padding: 0;
    display: flex; flex-wrap: wrap; gap: 14px;
}
.cs-hero-chips li{
    display: flex; flex-direction: column; align-items: center; gap: 12px;
    min-width: 150px;
}

/* Fixed HEIGHT, free width. The four supplied icons are 100x129, 100x85,
   100x86 and 100x89, so sizing them by width — which is what the first version
   did — rendered four different heights and left each one sitting at its own
   distance above its pill. Height is what has to match for them to line up;
   object-fit keeps each one's own proportions inside that box. */
.cs-hero-chips img{
    width: auto; height: 34px; max-width: 54px;
    object-fit: contain; object-position: center bottom;
    display: block;
}
.cs-hero-chips span{
    display: block; width: 100%;
    padding: 11px 20px;
    border: 1px solid rgba(255,255,255,.55);
    border-radius: 999px;
    font-size: var(--cs-fs-label, 15px);
    font-weight: 700;
    line-height: 1.3;
    text-align: center;
    color: #fff;
}

/* ── Hero service tiles ───────────────────────────────────────────────────── */
.cs-hero-tiles{ display: block; }
.cs-hero-tiles img{ width: 100%; height: auto; display: block; }

/* ==========================================================================
   "More work" — the row of other case studies at the foot of one
   ==========================================================================
   This used to be a bare heading over three raw client photos, and it read as
   a stock gallery rather than as three pieces of work: nothing on a card said
   whose it was until you got to the caption. It now borrows the listing's own
   device — each photo veiled in that client's dark colour and badged with
   their real mark — so the row is recognisably three brands. Each card
   carries its own palette in a style attribute, which is why these rules are
   all written against custom properties. */
.cs-related{
    padding: 80px 0 88px;
    /* A tint of the CURRENT case study's soft colour, so the foot of the page
       still belongs to the client whose page it is, while the cards inside
       belong to theirs. */
    background: linear-gradient(180deg, var(--cs-soft, #F5F6F2) 0%, var(--white-color) 70%);
}

.cs-related-head{
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: 24px; margin-bottom: 30px;
    padding-bottom: 20px;
    border-bottom: 1px solid rgba(3,29,54,.1);
}

.cs-related-eyebrow{
    display: block; margin-bottom: 8px;
    font-size: 12px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
    color: var(--cs-accent, #0A49A6);
}

.cs-related h2{ font-size: 30px; line-height: 1.2; margin: 0; color: var(--primary-color); }

.cs-related-all{
    flex: none;
    display: inline-flex; align-items: center; gap: 8px;
    font-size: 14px; font-weight: 700; text-decoration: none;
    color: var(--cs-accent, #0A49A6);
    padding-bottom: 3px;
    border-bottom: 2px solid transparent;
    transition: border-color .25s ease;
}
.cs-related-all:hover{ border-bottom-color: currentColor; }
.cs-related-all svg{ transition: transform .25s ease; }
.cs-related-all:hover svg{ transform: translateX(3px); }

.cs-related-grid{
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
    gap: 24px;
}

.cs-related-card{
    display: flex; flex-direction: column;
    border-radius: 18px; overflow: hidden; text-decoration: none;
    background: var(--white-color);
    box-shadow: 0 1px 0 rgba(3,29,54,.1), 0 10px 24px rgba(3,29,54,.06);
    transition: transform .3s ease, box-shadow .3s ease;
}

.cs-related-card:hover{
    transform: translateY(-5px);
    box-shadow: 0 1px 0 rgba(3,29,54,.1), 0 22px 44px rgba(3,29,54,.15);
}

/* ── Media panel — the listing's veil-and-badge treatment, one size down ──── */
.cs-related-media{
    position: relative; display: block;
    /* 16:10 rather than 4:3. This row sits under a very long page, so three
       tall cards make the foot feel heavier than the case study above it. */
    aspect-ratio: 16 / 10;
    background: var(--cs-deep, #101828);
    overflow: hidden;
}

/* Direct child only: the client's mark also lives in here, and a loose
   `img` rule stretches a 5:1 logo to fill the panel. Same trap as
   .cs-entry-media above. */
.cs-related-media > img{
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover; display: block;
    transition: transform .6s cubic-bezier(.2,.7,.3,1);
}
.cs-related-card:hover .cs-related-media > img{ transform: scale(1.06); }

.cs-related-veil{
    position: absolute; inset: 0;
    background: linear-gradient(
        150deg,
        color-mix(in srgb, var(--cs-deep, #101828) 30%, transparent) 0%,
        color-mix(in srgb, var(--cs-deep, #101828) 74%, transparent) 60%,
        color-mix(in srgb, var(--cs-deep, #101828) 94%, transparent) 100%);
}

@supports not (background: color-mix(in srgb, red 10%, white)){
    .cs-related-veil{ background: linear-gradient(150deg, rgba(16,24,40,.3), rgba(16,24,40,.94)); }
}

.cs-related-mark{
    position: absolute; left: 18px; bottom: 16px;
    display: flex; align-items: center; justify-content: center;
    min-width: 76px; min-height: 52px;
    padding: 9px 13px;
    border-radius: 10px;
    background: rgba(255,255,255,.94);
    box-shadow: 0 8px 20px rgba(0,0,0,.22);
}

/* A light-ink mark needs the dark plate its own brand puts it on. */
.cs-related-mark.is-dark{
    background: var(--cs-deep, #101828);
    box-shadow: 0 8px 20px rgba(0,0,0,.3), inset 0 0 0 1px rgba(255,255,255,.14);
}

.cs-related-mark .cs-logo{
    --cs-logo-ink: var(--cs-deep, #101828);
    width: auto; max-width: 112px; height: 32px;
}
.cs-related-mark .cs-logo-img{ max-width: 108px; max-height: 30px; width: auto; }

.cs-related-wordmark{
    font-size: 16px; font-weight: 700; line-height: 1.2;
    color: var(--cs-deep, #101828);
}

/* ── Body ─────────────────────────────────────────────────────────────────── */
.cs-related-body{
    display: flex; flex-direction: column; align-items: flex-start;
    gap: 7px;
    padding: 20px 22px 22px;
    /* Pushes the read link to the foot so three cards of unequal title length
       still line their links up. */
    flex: 1 1 auto;
}

.cs-related-sector{
    font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
    color: var(--cs-on-accent, #fff);
    background: var(--cs-accent, #0A49A6);
    padding: 4px 10px; border-radius: 999px;
}

.cs-related-client{
    font-size: 12px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
    color: rgba(3,29,54,.5);
    margin-top: 3px;
}

.cs-related-title{
    font-size: 18px; line-height: 1.34em; font-weight: 700;
    color: var(--primary-color);
}

.cs-related-link{
    display: inline-flex; align-items: center; gap: 7px;
    margin-top: auto; padding-top: 14px;
    font-size: 13px; font-weight: 700;
    color: var(--cs-accent, #0A49A6);
}
.cs-related-link svg{ transition: transform .25s ease; }
.cs-related-card:hover .cs-related-link svg{ transform: translateX(4px); }

/* ==========================================================================
   Right-side section rail
   ==========================================================================
   Fixed to the right edge, follows the scroll and highlights the section in
   view. Labels are hidden until hover/focus so the rail stays a slim column
   of numbers and does not sit on top of the content.
   ========================================================================== */
.cs-rail{
    position: fixed;
    top: 50%;
    right: 18px;
    transform: translateY(-50%);
    z-index: 45;
    max-height: 78vh;
    overflow-y: auto;
    scrollbar-width: none;
}

.cs-rail::-webkit-scrollbar{ display: none; }

.cs-rail-list{ list-style: none; margin: 0; padding: 6px 0; display: flex; flex-direction: column; gap: 2px; }

.cs-rail-link{
    display: flex; align-items: center; justify-content: flex-end; gap: 10px;
    padding: 5px 8px;
    text-decoration: none;
    color: var(--text-color);
}

.cs-rail-label{
    font-size: 12px; font-weight: 700;
    white-space: nowrap;
    background: var(--cs-accent);
    color: #fff;
    padding: 5px 11px;
    border-radius: 4px;
    opacity: 0; transform: translateX(8px);
    transition: opacity .2s ease, transform .2s ease;
    pointer-events: none;
}

.cs-rail-dot{
    width: 9px; height: 9px; border-radius: 50%;
    background: rgba(3,29,54,.24);
    flex: 0 0 auto;
    transition: background .2s ease, transform .2s ease;
}

.cs-rail-link:hover .cs-rail-label,
.cs-rail-link:focus-visible .cs-rail-label{ opacity: 1; transform: translateX(0); }

.cs-rail-link:hover .cs-rail-dot{ background: var(--cs-accent); }

.cs-rail-link.is-active .cs-rail-dot{ background: var(--cs-accent); transform: scale(1.5); }
.cs-rail-link.is-active .cs-rail-label{ opacity: 1; transform: translateX(0); }

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width: 1399px){
    .cs-detail{ --cs-fs-h1: 28px; --cs-fs-ribbon: 26px; --cs-fs-type: 29px; --cs-fs-tagline: 24px; }
}

@media (max-width: 1199px){
    /* Not enough side room for a floating rail without it covering copy, so it
       becomes a horizontal strip under the hero. */
    .cs-rail{
        position: static;
        transform: none;
        max-height: none;
        margin: 0 auto;
        padding: 10px 0;
        background: #fff;
        border-bottom: 1px solid rgba(3,29,54,.09);
    }

    .cs-rail-list{
        flex-direction: row;
        gap: 6px;
        overflow-x: auto;
        scrollbar-width: none;
        padding: 0 24px;
    }

    .cs-rail-list::-webkit-scrollbar{ display: none; }

    .cs-rail-link{ flex: 0 0 auto; padding: 0; }
    .cs-rail-dot{ display: none; }

    .cs-rail-label{
        opacity: 1; transform: none; pointer-events: auto;
        background: rgba(3,29,54,.06);
        color: var(--text-color);
        font-weight: 600;
        padding: 8px 14px;
        border-radius: 999px;
    }

    .cs-rail-link.is-active .cs-rail-label,
    .cs-rail-link:hover .cs-rail-label{ background: var(--cs-accent); color: #fff; }

    /* No room for the device shot once the three hero columns tighten — drop
       it rather than squeeze the copy that carries the story.
       The .is-media-middle variant has to be named explicitly: it is a
       two-class selector and outranks a bare .cs-hero-inner here. */
    .cs-hero-inner,
    .cs-hero-inner.is-media-middle{ grid-template-columns: minmax(0, 17.3fr) minmax(0, 7fr) minmax(0, 75.7fr); }
    .cs-hero-inner.is-media-middle .cs-hero-copy{ grid-column: 3; }
    .cs-hero-media{ display: none; }
}

@media (max-width: 991px){
    .cs-index-section{ padding: 68px 0 60px; }

    /* The heading and the "All case studies" link sit on one line on desktop.
       At this width the heading wraps to two or three lines and the link gets
       squeezed into the corner, so they stack instead. */
    .cs-related{ padding: 58px 0 64px; }
    .cs-related-head{ flex-direction: column; align-items: flex-start; gap: 14px; }
    .cs-related h2{ font-size: 25px; }

    .cs-entry{ grid-template-columns: minmax(0, 1fr); }
    .cs-entry-media{ min-height: 0; aspect-ratio: 16 / 9; }
    .cs-entry-body{ padding: 28px 26px 32px; }
    .cs-entry-title{ font-size: 24px; }
    .cs-entry-grid{ grid-template-columns: minmax(0, 1fr); gap: 22px; }

    .cs-detail{ --cs-fs-h1: 24px; --cs-fs-ribbon: 21px; --cs-fs-type: 24px;
                --cs-fs-tagline: 20px; --cs-fs-label: 16px; --cs-fs-cta: 17px; }

    .cs-hero{ padding-top: 140px; }
    .cs-hero-inner,
    .cs-hero-inner.is-media-middle{
        grid-template-columns: minmax(0, 1fr);
        gap: 22px;
        padding-bottom: 42px;
        row-gap: 22px;
    }
    .cs-hero-brand{ grid-column: 1; display: flex; flex-direction: column; align-items: flex-start; }
    .cs-hero-copy,
    .cs-hero-inner.is-media-middle .cs-hero-copy{ grid-column: 1; }
    .cs-hero h1{ max-width: none; }   /* one column — the narrow measure would just look cramped */
    .cs-hero-kicker{ margin-bottom: 16px; }

    .cs-section{ padding: 36px 0; }
    .cs-ribbon{ padding: 10px 48px 10px 18px;
                -webkit-clip-path: polygon(0 0, 100% 0, calc(100% - 26px) 50%, 100% 100%, 0 100%);
                        clip-path: polygon(0 0, 100% 0, calc(100% - 26px) 50%, 100% 100%, 0 100%); }

    /* One column, image after the copy — including for the flipped and bleed
       variants, so every section stacks in the same reading order. */
    .cs-split,
    .cs-split.is-flipped,
    .cs-split.is-bleed{ grid-template-columns: minmax(0, 1fr); gap: 22px; }

    .cs-split-text,
    .cs-split.is-flipped .cs-split-text { grid-column: 1; grid-row: 1; }
    /* .cs-split.is-bleed .cs-split-media has to be named here too. It carries
       the negative bleed margin at two class levels of specificity, so a reset
       written only against .cs-split-media loses to it and the stacked image
       hangs 24px off one edge. */
    .cs-split-media,
    .cs-split.is-flipped .cs-split-media,
    .cs-split.is-bleed .cs-split-media,
    .cs-split.is-bleed.is-flipped .cs-split-media{ grid-column: 1; grid-row: 2; margin-left: 0; margin-right: 0; }

    .cs-brand{ grid-template-columns: minmax(0, 1fr); gap: 22px; }
    .cs-brand-card,
    .cs-brand-copy{ grid-column: 1; }

    .cs-panels{ grid-template-columns: minmax(0, 1fr); gap: 14px; max-width: none; }
    .cs-panels > .cs-panel:nth-of-type(1),
    .cs-panels > .cs-panel:nth-of-type(2),
    .cs-panels > .cs-panel:nth-of-type(3){ grid-column: 1; }
    .cs-panel{ min-height: 0; }
    .cs-panel-image{ min-height: 200px; }

    /* Four portrait crops side by side get far too narrow on a phone. */
    .cs-bandrow{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .cs-bandrow .cs-prose{ grid-column: 1 / -1; }

    /* The timeline stops being a rail and becomes a plain list — six labelled
       badges side by side on a 375px screen is unreadable at any font size. */
    .cs-rail-track{ grid-auto-flow: row; gap: 14px; }
    .cs-rail-track::before{ display: none; }
    .cs-stop{ min-height: 0; flex-direction: row; gap: 14px; justify-content: flex-start; }
    .cs-stop-leader{ display: none; }
    .cs-stop-num{ flex: 0 0 auto; }
    .cs-stop-badge{
        position: static; transform: none; width: auto;
        flex-direction: row; align-items: center; gap: 12px; text-align: left;
    }
    .cs-stop.is-above .cs-stop-badge,
    .cs-stop.is-below .cs-stop-badge{ bottom: auto; top: auto; }
    .cs-hex{ width: 44px; height: 49px; }
    .cs-hex svg{ width: 19px; height: 19px; }

    /* Tiles get bigger, not smaller, on a phone — a 118px hexagon in a
       375px column would be four to a row and illegible. */
    .cs-tiles.is-hex,
    .cs-tiles.is-round{ grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); }
    .cs-tiles.is-wide { grid-template-columns: minmax(0, 1fr); }

    /* Six interlocking chevrons across a phone is unreadable — stack them. */
    .cs-chevrons{ grid-auto-flow: row; grid-auto-columns: auto; gap: 8px; max-width: none; }
    .cs-chev-cell{ grid-template-rows: auto; grid-template-columns: auto 1fr; justify-items: stretch; gap: 12px; }
    .cs-chev-cell .cs-chev{ grid-row: 1; grid-column: 2; }
    .cs-chev-cell.is-above .cs-chev-badge,
    .cs-chev-cell.is-below .cs-chev-badge{ grid-row: 1; grid-column: 1; }

    .cs-clientfoot{ grid-template-columns: minmax(0, 1fr); }
    .cs-outro h2{ font-size: 26px; }
}

@media (max-width: 575px){
    .case-studies-page-header .page-header-box h1{ font-size: 34px; }
    .cs-index-lead{ font-size: 16px; margin-bottom: 36px; }
    .cs-entry-body{ padding: 24px 20px 28px; }
    .cs-entry-title{ font-size: 21px; }
    .cs-entry-mark{ left: 20px; right: 20px; bottom: 20px; }
    .cs-entry-no{ left: 20px; top: 18px; }
    .cs-entry-sector{ right: 18px; top: 18px; }
    .cs-entry-wordmark{ font-size: 20px; }

    .cs-detail{ --cs-fs-h1: 21px; --cs-fs-ribbon: 18px; --cs-fs-body: 14px; }
    .cs-hero{ padding-top: 120px; }
    .cs-section{ padding: 30px 0; }
    .cs-index-cta-box{ padding: 40px 22px; }
    .cs-index-cta-box h2{ font-size: 25px; }
    .cs-outro{ padding: 50px 0; }
    .cs-outro h2{ font-size: 23px; }
    .cs-outro-actions a{ width: 100%; justify-content: center; }
    .cs-results-grid{ gap: 16px 34px; }
    .cs-result-value{ font-size: 27px; }
    .cs-pills{ grid-template-columns: minmax(0, 1fr); }
}

/* Hover transforms and the image zoom are decoration, and vestibular triggers
   for some people. */
@media (prefers-reduced-motion: reduce){
    .cs-entry, .cs-entry-media img, .cs-entry-link svg, .cs-related-card,
    .cs-hero-cta, .cs-outro-actions a, .cs-rail-label, .cs-rail-dot{ transition: none; }
    .cs-entry:hover, .cs-related-card:hover, .cs-hero-cta:hover, .cs-outro-actions a:hover{ transform: none; }
    .cs-entry:hover .cs-entry-media img{ transform: none; }
}

/* ── Service chip in the hero ─────────────────────────────────────────────
   Which service this piece of work sits under. Kept to a chip rather than a
   second button: "View Live Website" is the hero's call to action and two
   full-size buttons under the mark crowd it. */
.cs-hero-svc{ display: flex; flex-wrap: wrap; gap: 8px; margin: 16px 0 0; }
.cs-hero-svc a{
    display: inline-block;
    padding: 6px 14px;
    border: 1px solid rgba(255,255,255,.38);
    border-radius: 999px;
    font-size: 13px; font-weight: 600; text-decoration: none;
    color: rgba(255,255,255,.92);
    transition: background .25s ease, border-color .25s ease;
}
.cs-hero-svc a:hover{ background: rgba(255,255,255,.14); border-color: rgba(255,255,255,.7); color: #fff; }

/* On a pale hero the chip has to flip to the dark ink the rest of it uses. */
.cs-hero.is-light .cs-hero-svc a{
    border-color: color-mix(in srgb, var(--cs-deep, #454640) 32%, transparent);
    color: var(--cs-deep, #454640);
}
.cs-hero.is-light .cs-hero-svc a:hover{
    background: color-mix(in srgb, var(--cs-deep, #454640) 8%, transparent);
    border-color: color-mix(in srgb, var(--cs-deep, #454640) 55%, transparent);
    color: var(--cs-deep, #454640);
}
@supports not (background: color-mix(in srgb, red 10%, white)){
    .cs-hero.is-light .cs-hero-svc a{ border-color: rgba(0,0,0,.3); color: #333; }
}
