/* ==========================================================================
   Product pages — polish layer
   ==========================================================================

   The legacy product pages already have the right structure: picture cards
   and text cards live in separate sections, each section has one card design
   with one job, and the icons are a consistent 56px. None of that is changed
   here. This sheet only modernises the surfaces, tightens the icon alignment
   and adds the interaction the pages were missing.

   It rides on top of the legacy class names, so the markup is untouched.

   Per-product accent
   ------------------
   Each product owns a colour: qgold is gold, qsales pink, qvirtue terracotta.
   Legacy carried those as `gradient_N_after` on the heading rule only. Here
   the pair becomes two custom properties so the same accent can drive the
   heading rule, card hover and list markers.

   Global.css sets `* { background-color: black }`, so anything meant to show
   what is behind it has to say so explicitly. That is why `transparent`
   appears more often below than it otherwise would.
   ========================================================================== */

.qgold_our_services_container,
.qgold_benefits_container,
.qgold_why_choose_us_container {
    /* qgold's gold, the default of the three */
    --qp-a1: #EBCB66;
    --qp-a2: #F89833;
    --qp-tint: rgba(235, 203, 102, 0.38);
    --qp-glow: rgba(235, 203, 102, 0.16);
    --qp-aura: rgba(235, 203, 102, 0.14);

    --qp-surface: #141416;
    --qp-line: rgba(255, 255, 255, 0.09);
    --qp-text: #F5F5F7;
    --qp-dim: #A9A9B4;
}

/* qsales — pink */
.gradient_2_after.qgold_our_services_container,
.gradient_2_after .qgold_our_services_container,
body:has(.gradient_2_after) .qgold_our_services_container,
body:has(.gradient_2_after) .qgold_benefits_container,
body:has(.gradient_2_after) .qgold_why_choose_us_container {
    --qp-a1: #FFD8FE;
    --qp-a2: #FF8EFA;
    --qp-tint: rgba(255, 142, 250, 0.38);
    --qp-glow: rgba(255, 142, 250, 0.16);
    --qp-aura: rgba(255, 142, 250, 0.14);
}

/* qvirtue — terracotta */
body:has(.gradient_5_after) .qgold_our_services_container,
body:has(.gradient_5_after) .qgold_benefits_container,
body:has(.gradient_5_after) .qgold_why_choose_us_container {
    --qp-a1: rgb(191, 140, 132);
    --qp-a2: rgb(185, 114, 102);
    --qp-tint: rgba(185, 114, 102, 0.42);
    --qp-glow: rgba(185, 114, 102, 0.18);
    --qp-aura: rgba(185, 114, 102, 0.17);
}

/* --- section headings ----------------------------------------------------
   Legacy ruled a line under the heading and left-aligned it. Both stay; the
   rule simply picks up the product's own accent and a softer weight.
   ------------------------------------------------------------------------ */

.qgold_heading_texts {
    background-color: transparent;
}

.qgold_heading_texts h1 {
    font-size: clamp(28px, 3.1vw, 44px);
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--qp-text);
}

.qgold_heading_texts h1::after {
    height: 3px;
    border-radius: 3px;
    background-image: linear-gradient(to right, var(--qp-a1), var(--qp-a2));
}

/* Legacy scopes the intro paragraph once per section container, so a rule on
   `.qgold_heading_texts p` alone never reaches it -- it has to be named the
   same way, per container. */
.qgold_our_services_container .qgold_heading_texts p,
.qgold_benefits_container .qgold_heading_texts p,
.qgold_why_choose_us_container .qgold_heading_texts p {
    margin-top: 14px;
    font-size: clamp(14px, 1.15vw, 16.5px);
    line-height: 1.7;
    color: var(--qp-dim);
    background-color: transparent;
}

/* --- boxed icon card (Our Services) --------------------------------------
   Legacy: 25px padding, a left-to-right grey gradient, 10px radius, flat.
   Now a single dark surface with a hairline edge, and it answers the cursor.
   ------------------------------------------------------------------------ */

/* Legacy writes this one as
   `.qgold_our_services_container .qgold_our_services_container .card_container
    .main_cards .cards` -- the container class repeated, five classes deep.
   Matching that shape is what lets these declarations land; a shorter
   selector silently loses on radius, padding and the background gradient. */
.qgold_our_services_container .qgold_our_services_container .card_container .main_cards .cards {
    height: 100%;
    padding: clamp(22px, 2vw, 28px);
    border: 1px solid var(--qp-line);
    border-radius: 16px;
    background-color: var(--qp-surface);
    background-image: none;
    transition: transform 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
}

.qgold_our_services_container .qgold_our_services_container .card_container .main_cards .cards:hover {
    transform: translateY(-4px);
    border-color: var(--qp-tint);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.5), 0 0 26px var(--qp-glow);
}

/* the mark ---------------------------------------------------------------
   The same visual role is written three different ways across these pages:
   `.img_bg` on qsales and qvirtue, a class-less `<div>` on qgold, and
   `.pt_img_container` in Why Choose Us. Keying on the wrapper's POSITION
   instead of its class catches all three, which is what makes the marks line
   up across the three products rather than only on the two that got a class.

   Legacy sized the wrapper but set `overflow: visible` on the artwork, so a
   picture bigger than the disc simply spilled out of it -- qvirtue's Our
   Services mixes 32px icons with 150x150 and 200x150 illustrations, and the
   big ones escaped the circle. The box is fixed at 56px here and the artwork
   is bounded by max-width/max-height rather than width/height: bounding it
   scales the large ones DOWN to fit and leaves the 32px ones at their own
   size. Setting width/height instead would blow a 32px PNG up to 56px and
   pixelate it. Nothing is cropped, nothing is stretched. */
.qgold_our_services_container .qgold_our_services_container .card_container .main_cards .cards > div:first-child {
    display: flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    aspect-ratio: 1;
}

.qgold_our_services_container .qgold_our_services_container .card_container .main_cards .cards > div:first-child img {
    width: auto;
    height: auto;
    max-width: 56px;
    max-height: 56px;
    object-fit: contain;
    background-color: transparent;
}

/* --- artwork inset, where the mark sits on a disc -------------------------
   The classed wrappers -- `.img_bg`, `.pt_img_container`, `.benefits_img` --
   are the ones legacy paints a coloured circle behind, on qsales and qvirtue.
   Art on a disc has to be inset or it touches the rim, and the great majority
   of that art is already drawn at 32px inside the 56px circle. So 32px is the
   size the set was designed to, and the handful of odd ones out are brought
   to it rather than the other way round.

   qgold has no disc on any of its marks and no classed wrapper either, so it
   is untouched by these rules: its 56px artwork keeps filling the 56px box.
   Each page ends up internally consistent, which is the level a reader sees.
   ------------------------------------------------------------------------ */

.qgold_our_services_container .qgold_our_services_container .card_container .main_cards .cards > div:first-child.img_bg img,
.qgold_benefits_container .benefits_secondary_container .benefits_secondary_cards > div:first-child.benefits_img img,
.qgold_why_choose_us_container .propositions_container > div .propositions_points_container > div > div:first-child.pt_img_container img {
    width: 32px;
    height: 32px;
    object-fit: contain;
}

/* Both of these are <p> elements, so a rule on `.cards p` would hit the title
   as well as the copy. Legacy names them by class six deep; these do the same.
   Without the repeated container class they lost outright and the cards kept
   legacy's flat 20px/16px pair at every screen size. */
.qgold_our_services_container .qgold_our_services_container .card_container .main_cards .cards .card_heading {
    margin-top: 18px;
    font-size: clamp(17px, 1.45vw, 20px);
    font-weight: 700;
    line-height: 1.3;
    color: var(--qp-text);
}

.qgold_our_services_container .qgold_our_services_container .card_container .main_cards .cards .card_info {
    margin-top: 10px;
    font-size: clamp(13.5px, 1.08vw, 15px);
    line-height: 1.7;
    color: var(--qp-dim);
    background-color: transparent;
}

/* --- benefit list pills --------------------------------------------------
   Legacy gave each line a bordered pill. The border becomes the theme's
   hairline and each pill gains the accent bar the design implied.
   ------------------------------------------------------------------------ */

.qgold_benefits_container .benefits_main_container .benefits_list_container ul li {
    position: relative;
    overflow: hidden;
    padding: 15px 18px 15px 24px;
    border: 1px solid var(--qp-line);
    border-radius: 12px;
    background-color: var(--qp-surface);
    font-size: clamp(14px, 1.1vw, 16px);
    line-height: 1.55;
    color: var(--qp-text);
    transition: border-color 0.3s ease, transform 0.3s ease;
}

.qgold_benefits_container .benefits_main_container .benefits_list_container ul li::before {
    content: "";
    position: absolute;
    top: 10px;
    bottom: 10px;
    left: 0;
    width: 4px;
    border-radius: 4px;
    background-image: linear-gradient(to bottom, var(--qp-a1), var(--qp-a2));
}

.qgold_benefits_container .benefits_main_container .benefits_list_container ul li:hover {
    transform: translateX(3px);
    border-color: var(--qp-tint);
}

/* --- bare icon tile (Benefits) -------------------------------------------
   No box, by design: this section is deliberately lighter than Our Services.
   Only the mark and the rhythm are tidied.
   ------------------------------------------------------------------------ */

.qgold_benefits_container .benefits_secondary_container .benefits_secondary_cards {
    background-color: transparent;
}

/* The disc behind each mark is drawn INSIDE the SVG, not by CSS -- so the
   colour difference between these and the Our Services marks lives in the
   artwork and is not ours to change here. What CSS must do is stop the
   `* { background-color: black }` rule painting a black square behind any
   part of the artwork that is transparent, and hold every mark to one size. */
.qgold_benefits_container .benefits_secondary_container .benefits_secondary_cards > div:first-child {
    display: flex;
    align-items: center;
    height: 56px;
    background-color: transparent;
}

/* Horizontal alignment is deliberately NOT set above. qsales and qvirtue wrap
   the mark in `.benefits_img`, a 56px disc that legacy already centres its art
   inside and positions with Bootstrap's `m-auto m-md-0`. qgold has no disc:
   its mark is a bare image in a `text-center text-md-start` wrapper, and
   turning that wrapper into a flex box takes text-align out of play -- so the
   same centred-on-phone, flush-left-from-md behaviour has to be restated, and
   only for the wrapper that lost it. Getting this wrong leaves the mark hard
   left on a phone while the heading and copy under it are centred. */
.qgold_benefits_container .benefits_secondary_container .benefits_secondary_cards > div:first-child:not(.benefits_img) {
    justify-content: center;
}

@media (min-width: 768px) {
    .qgold_benefits_container .benefits_secondary_container .benefits_secondary_cards > div:first-child:not(.benefits_img) {
        justify-content: flex-start;
    }
}

/* bounded, not sized -- qsales and qvirtue ship 32px art here and stretching
   it to 56px is the pixelation you see on the live page today */
.qgold_benefits_container .benefits_secondary_container .benefits_secondary_cards > div:first-child img {
    flex: none;
    width: auto;
    height: auto;
    max-width: 56px;
    max-height: 56px;
    object-fit: contain;
    background-color: transparent;
}

/* There is no h3 or h4 in this tile -- the title is `p.benefits_headings` and
   the copy is a bare <p> beside it. A rule on `.benefits_content p` therefore
   hits the title too, and loses to legacy's more specific heading rule, so
   name the two apart. `:not(.benefits_headings)` also buys the copy rule the
   extra class it needs to beat legacy's own paragraph rule. */
.qgold_benefits_container .benefits_secondary_container .benefits_secondary_cards .benefits_content .benefits_headings {
    margin-top: 16px;
    font-size: clamp(17px, 1.45vw, 20px);
    font-weight: 700;
    color: var(--qp-text);
}

.qgold_benefits_container .benefits_secondary_container .benefits_secondary_cards .benefits_content p:not(.benefits_headings) {
    margin-top: 9px;
    font-size: clamp(13.5px, 1.08vw, 15px);
    line-height: 1.7;
    color: var(--qp-dim);
    background-color: transparent;
}

/* --- proposition panel (Why Choose Us) -----------------------------------
   A panel per proposition: mark on the left, heading and points beside it.
   ------------------------------------------------------------------------ */

/* Legacy scopes these four deep and also sets a 6% right padding plus negative
   margins so the panels slide under the phone artwork. Those offsets are the
   composition and are left alone; only the surface is restated. */
.qgold_why_choose_us_container .propositions_container > div .propositions_points_container > div {
    gap: 18px;
    border: 1px solid var(--qp-line);
    border-radius: 16px;
    background-color: var(--qp-surface);
    background-image: none;
    transition: border-color 0.35s ease, box-shadow 0.35s ease;
}

.qgold_why_choose_us_container .propositions_container > div .propositions_points_container > div:hover {
    border-color: var(--qp-tint);
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.45);
}

/* The proposition mark, again addressed by position: qsales and qvirtue carry
   `.pt_img_container` here, qgold carries nothing, and only the classed ones
   were getting a size. Left unsized, qgold's wrapper stretched to whatever the
   panel happened to be tall -- 69px next to a two-line proposition, 153px next
   to a five-line one -- so the marks sat at eight different heights down the
   column. Pinning the box makes them agree.

   No background is set here on purpose. qsales and qvirtue colour the disc
   from their own `:nth-child` rules and those still apply; qgold's artwork
   carries its own colour and does not want a disc behind it. */
.qgold_why_choose_us_container .propositions_container > div .propositions_points_container > div > div:first-child {
    display: flex;
    flex: none;
    align-self: flex-start;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    aspect-ratio: 1;
}

.qgold_why_choose_us_container .propositions_container > div .propositions_points_container > div > div:first-child img {
    width: auto;
    height: auto;
    max-width: 56px;
    max-height: 56px;
    object-fit: contain;
    background-color: transparent;
}

/* Same story as the marker: legacy scopes the panel's type four classes deep,
   so anything written shorter here silently lost its font-size. These follow
   legacy's shape so the responsive scale actually applies. */
.qgold_why_choose_us_container .propositions_container > div .propositions_points_container > div .propositions_points_info_container h3 {
    margin: 0 0 10px;
    font-size: clamp(17px, 1.45vw, 20px);
    font-weight: 700;
    color: var(--qp-text);
}

.qgold_why_choose_us_container .propositions_container > div .propositions_points_container > div .propositions_points_info_container ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

.qgold_why_choose_us_container .propositions_container > div .propositions_points_container > div .propositions_points_info_container ul li {
    position: relative;
    margin: 0;
    padding-left: 20px;
    font-size: clamp(13.5px, 1.08vw, 15px);
    line-height: 1.65;
    color: var(--qp-dim);
}

.qgold_why_choose_us_container .propositions_container > div .propositions_points_container > div .propositions_points_info_container ul li + li {
    margin-top: 8px;
}

/* Legacy draws this marker as a white "•" glyph, scoped four classes deep.
   A shorter selector does NOT simply lose -- the cascade resolves property by
   property, so `content` and `top` stayed legacy's while `width`, `height`,
   `border-radius` and `background` came from here. The result was a 6px gold
   box with legacy's bullet glyph spilling out of it: two markers per line.
   Matching legacy's selector exactly means this rule wins every property it
   sets (same specificity, later sheet) and there is only one marker again. */
.qgold_why_choose_us_container .propositions_container > div .propositions_points_container > div .propositions_points_info_container ul li::before {
    content: "";
    position: absolute;
    top: 0.62em;
    left: 2px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background-image: linear-gradient(to bottom right, var(--qp-a1), var(--qp-a2));
    font-size: 0;
}

/* the phone mockups are artwork: never let one upscale past its own pixels */
.proposition_mobile_img img,
.benefits_image_container img {
    width: auto;
    max-width: 100%;
    height: auto;
    background-color: transparent;
}

/* --- narrow screens ------------------------------------------------------ */

@media (max-width: 767px) {
    .propositions_points_container > div {
        gap: 14px;
        padding: 20px;
    }

    .qgold_our_services_container .card_container .main_cards .cards {
        padding: 22px;
    }
}

/* ==========================================================================
   qbot
   ==========================================================================

   qbot does not share the qgold class vocabulary -- it has its own, and five
   distinct card designs across four sections:

     value_proposition   4 cards, icon + line of copy, arrows between them
     function            2 cards, icon + heading + copy
     function_stroke     3 cards, text only, drawn with a gradient hairline
     technology          2 cards, one of which holds a partner logo strip
     usecase             6 cards, numbered heading + bullets, accent bar left

   Legacy keeps each design to its own section, which is the structure worth
   keeping. What it does not do is give them a common surface: three of the
   five use the old grey-to-black card gradient, one is pure black and one is
   transparent, so the page reads as five unrelated card styles rather than
   one family. Below they share a surface, a radius and a hover, and each
   keeps the feature that makes it itself -- the arrows, the gradient stroke,
   the accent bar.

   qbot's accent is the house gradient, which is what legacy already rules
   under its section headings.
   ========================================================================== */

.qbot_wrapper {
    --qp-a1: #F89833;
    --qp-a2: #EA396E;
    --qp-tint: rgba(234, 57, 110, 0.38);
    --qp-glow: rgba(234, 57, 110, 0.15);
    --qp-aura: rgba(234, 57, 110, 0.15);

    --qp-surface: #141416;
    --qp-line: rgba(255, 255, 255, 0.09);
    --qp-text: #F5F5F7;
    --qp-dim: #A9A9B4;

    /* One mark size for the whole page. Legacy stepped the function-card icon
       down to 46px and then 38px on narrower screens but left the value-card
       icon at 56px throughout, so the two sections disagreed on a phone.
       Holding the size in a property steps them together. */
    --qb-mark: 56px;
}

@media (max-width: 992px) {
    .qbot_wrapper {
        --qb-mark: 48px;
    }
}

@media (max-width: 576px) {
    .qbot_wrapper {
        --qb-mark: 44px;
    }
}

/* --- value proposition: the flow row ------------------------------------- */

.qbot_wrapper .qbot_value_section .qbot_value_proposition_cards_container .qbot_value_proposition_cards {
    padding: clamp(20px, 1.7vw, 25px);
    border: 1px solid var(--qp-line);
    border-radius: 16px;
    background: var(--qp-surface);
    transition: transform 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
}

.qbot_wrapper .qbot_value_section .qbot_value_proposition_cards_container .qbot_value_proposition_cards:hover {
    transform: translateY(-4px);
    border-color: var(--qp-tint);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.5), 0 0 26px var(--qp-glow);
}

.qbot_wrapper .qbot_value_section .qbot_value_proposition_cards_container .qbot_value_proposition_cards img {
    width: var(--qb-mark);
    height: var(--qb-mark);
    max-width: var(--qb-mark);
    max-height: var(--qb-mark);
    object-fit: contain;
    background: transparent;
}

.qbot_wrapper .qbot_value_section .qbot_value_proposition_cards_container .qbot_value_proposition_cards p {
    margin-top: 14px;
    font-size: clamp(13px, 1.02vw, 14px);
    line-height: 1.6;
    color: var(--qp-dim);
    background: transparent;
}

/* --- functional enablers: the two icon cards ----------------------------- */

.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_cards {
    padding: clamp(20px, 1.7vw, 25px);
    border: 1px solid var(--qp-line);
    border-radius: 16px;
    background: var(--qp-surface);
    transition: transform 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
}

.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_cards:hover {
    transform: translateY(-4px);
    border-color: var(--qp-tint);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.5), 0 0 26px var(--qp-glow);
}

.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_cards img {
    width: var(--qb-mark);
    height: var(--qb-mark);
    object-fit: contain;
    background: transparent;
}

.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_cards h3 {
    margin-top: 16px;
    font-size: clamp(17px, 1.45vw, 20px);
    font-weight: 700;
    line-height: 1.3;
    color: var(--qp-text);
    background: transparent;
}

.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_cards p {
    margin-top: 10px;
    font-size: clamp(13.5px, 1.08vw, 15px);
    line-height: 1.7;
    color: var(--qp-dim);
    background: transparent;
}

/* --- functional enablers: the three stroke cards -------------------------
   These are drawn as a 0.5px-padded gradient wrapper with a filled card
   inside, so the "border" is really the wrapper showing through. That trick
   is kept exactly as legacy built it; only the radius is brought in line with
   the rest of the page and the inner fill is lifted off pure black so the
   three stroke cards sit on the same surface as their neighbours.
   ------------------------------------------------------------------------ */

.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_stroke_cards_container .qbot_function_cards_stroke {
    padding: 1px;
    border-radius: 16px;
    background: linear-gradient(299.85deg, rgba(255, 255, 255, 0.22) -14.19%, rgba(255, 255, 255, 0.04) 109.56%);
}

.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_stroke_cards_container .qbot_function_cards_stroke .qbot_function_gradient_border_cards {
    padding: clamp(18px, 1.5vw, 22px);
    border-radius: 15px;
    background: var(--qp-surface);
}

.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_stroke_cards_container .qbot_function_cards_stroke .qbot_function_gradient_border_cards h4 {
    font-size: clamp(16px, 1.35vw, 19px);
    font-weight: 700;
    line-height: 1.3;
    color: var(--qp-text);
    background: transparent;
}

.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_stroke_cards_container .qbot_function_cards_stroke .qbot_function_gradient_border_cards p {
    margin-top: 8px;
    font-size: clamp(13.5px, 1.08vw, 15px);
    line-height: 1.7;
    color: var(--qp-dim);
    background: transparent;
}

/* --- technology enablers ------------------------------------------------- */

.qbot_wrapper .qbot_technology_section .qbot_technology_cards_container .qbot_technology_cards {
    padding: clamp(20px, 1.7vw, 25px);
    border: 1px solid var(--qp-line);
    border-radius: 16px;
    background: var(--qp-surface);
    transition: transform 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
}

.qbot_wrapper .qbot_technology_section .qbot_technology_cards_container .qbot_technology_cards:hover {
    transform: translateY(-4px);
    border-color: var(--qp-tint);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.5), 0 0 26px var(--qp-glow);
}

/* The partner logo strip.
   Legacy fixed the BOX at 100px wide and let each logo's own ratio decide its
   height. Salesforce is a near-square cloud and the other two are wide
   wordmarks, so that produced a 53px mark beside two 23px ones -- the row
   read as one big logo and two small ones. A logo strip has to be normalised
   on HEIGHT instead: matching the cap height is what makes marks of different
   shapes carry the same weight. Widths then differ, which is correct. */
.qbot_wrapper .qbot_technology_section .qbot_technology_cards_container .qbot_technology_cards .qbot_technology_cards_logos {
    display: flex;
    align-items: center;
    justify-content: center;
    width: auto;
    height: 40px;
    background: transparent;
}

.qbot_wrapper .qbot_technology_section .qbot_technology_cards_container .qbot_technology_cards .qbot_technology_cards_logos img {
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: 26px;
    margin: 0;
    object-fit: contain;
    background: transparent;
}

/* Equal height only holds while HEIGHT is the binding constraint. These three
   sit in Bootstrap columns roughly 84-118px wide depending on the breakpoint,
   and the two wordmarks are about 4.4:1 -- so above a certain cap the column
   width binds first, the wordmarks shrink and the heights diverge again. The
   cap therefore has to stay under what the narrowest column can hold: the
   tightest case is ~84px just above the md breakpoint, which at 4.43:1 allows
   18px. Raising either number re-introduces the mismatch. */
@media (max-width: 991.98px) {
    .qbot_wrapper .qbot_technology_section .qbot_technology_cards_container .qbot_technology_cards .qbot_technology_cards_logos img {
        max-height: 18px;
    }

    .qbot_wrapper .qbot_technology_section .qbot_technology_cards_container .qbot_technology_cards .qbot_technology_cards_logos {
        height: 30px;
    }
}

/* --- use cases -----------------------------------------------------------
   The only card here that already had a considered surface: a masked gradient
   hairline drawn with ::before and a coloured accent bar drawn with ::after,
   in three colourways. Both pseudo-elements are left alone. The card gets the
   shared fill and radius so it belongs with the rest -- ::before inherits the
   radius, so the hairline follows it round.
   ------------------------------------------------------------------------ */

.qbot_wrapper .qbot_usecases_section .qbot_usecase_cards_container .qbot_usecase_cards {
    padding: clamp(20px, 1.7vw, 25px);
    border-radius: 16px;
    background: var(--qp-surface);
    box-shadow: none;
    transition: transform 0.35s ease, box-shadow 0.35s ease;
}

.qbot_wrapper .qbot_usecases_section .qbot_usecase_cards_container .qbot_usecase_cards:hover {
    transform: translateY(-4px);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.5), 0 0 26px var(--qp-glow);
}

/* ==========================================================================
   Motion
   ==========================================================================

   Two layers: a scroll reveal as a section arrives, and hover behaviour once
   it is there. Both are built on `transform`, `translate` and `opacity` only,
   so they stay on the compositor and never reflow the page.

   The hidden state below is gated on `html.qp-anim`, which qf-product-reveal.js
   adds *after* it has an observer ready to take it off again. Nothing here can
   leave content stranded invisible: no script, no observer, no class, no
   hidden state. Reduced motion is honoured twice over -- the script returns
   early, and the block at the end of this file stands everything down.

   The reveal moves with `translate` rather than `transform` on purpose. The
   cards lift with `transform` on hover, and one property cannot serve both:
   whichever was written last would wipe the other out mid-interaction.
   ========================================================================== */

.qp-anim .qp-reveal {
    opacity: 0;
    translate: 0 14px;
    transition:
        opacity 0.42s cubic-bezier(0.22, 0.61, 0.36, 1) var(--qd, 0s),
        translate 0.42s cubic-bezier(0.22, 0.61, 0.36, 1) var(--qd, 0s);
}

.qp-anim .qp-reveal.is-in {
    opacity: 1;
    translate: 0 0;
}

/* Scrolled past too fast for the fade to be worth playing -- see the comment
   in qf-product-reveal.js. The element is already well up the screen, so it
   is shown outright rather than animated from nothing in front of the reader.
   The two nested reveals below (the pill's accent bar and the heading rule)
   are scoped as deeply as the rules they have to switch off. */
.qp-anim .qp-reveal.qp-now,
.qp-anim .qp-reveal.qp-now::before,
.qp-anim .qp-reveal.qp-now h1::after {
    transition: none;
}

.qp-anim .qgold_benefits_container .benefits_main_container .benefits_list_container ul li.qp-reveal.qp-now::before {
    transition: none;
}

/* --- section headings ----------------------------------------------------
   The rule under the heading draws itself in from the left as the heading
   arrives, instead of being there from the first frame.
   ------------------------------------------------------------------------ */

.qp-anim .qgold_heading_texts.qp-reveal h1::after,
.qp-anim .qbot_value_heading_container.qp-reveal h1::after,
.qp-anim .qbot_function_Section_heading.qp-reveal h1::after,
.qp-anim .qbot_technology_heading_container.qp-reveal h1::after,
.qp-anim .qbot_usecases_heading.qp-reveal h1::after {
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform 0.75s cubic-bezier(0.22, 0.61, 0.36, 1) 0.15s;
}

.qp-anim .qgold_heading_texts.qp-reveal.is-in h1::after,
.qp-anim .qbot_value_heading_container.qp-reveal.is-in h1::after,
.qp-anim .qbot_function_Section_heading.qp-reveal.is-in h1::after,
.qp-anim .qbot_technology_heading_container.qp-reveal.is-in h1::after,
.qp-anim .qbot_usecases_heading.qp-reveal.is-in h1::after {
    transform: scaleX(1);
}

/* --- the how-it-works panel ----------------------------------------------
   Legacy fills this section and its heading block with the same charcoal
   gradient, which makes it the only section on the page still painting a
   slab -- every other one sits straight on the page black. Both go
   transparent so it matches its neighbours.
   ------------------------------------------------------------------------ */

.qkonnect_cti_wrapper .product_qkonnect_work_section,
.qkonnect_cti_wrapper .product_qkonnect_work_section .product_qkonnect_work_heading {
    background-image: none;
    background-color: transparent;
}

/* --- card surfaces -------------------------------------------------------
   A depth highlight along the top edge, and an accent texture bleeding out of
   the bottom-right corner in the manner of the reference cards.

   The texture is drawn entirely in CSS gradients -- no image files -- and is
   confined to the corner by a radial mask rather than by clipping the card,
   so the mark's hover ring is still free to sit outside the card's box. Where
   masks are unsupported the texture simply covers the whole card at the same
   low opacity, which degrades quietly instead of breaking.

   Four variants cycle across a grid so nine cards do not read as nine copies
   of one card. They are all the product's own accent; only the geometry
   changes.
   ------------------------------------------------------------------------ */

.qgold_our_services_container .qgold_our_services_container .card_container .main_cards .cards,
.qbot_wrapper .qbot_value_section .qbot_value_proposition_cards_container .qbot_value_proposition_cards,
.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_cards,
.qbot_wrapper .qbot_technology_section .qbot_technology_cards_container .qbot_technology_cards {
    position: relative;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
}

.qgold_our_services_container .qgold_our_services_container .card_container .main_cards .cards::before,
.qbot_wrapper .qbot_value_section .qbot_value_proposition_cards_container .qbot_value_proposition_cards::before,
.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_cards::before,
.qbot_wrapper .qbot_technology_section .qbot_technology_cards_container .qbot_technology_cards::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    border-radius: inherit;
    pointer-events: none;
    opacity: 0.42;
    transition: opacity 0.4s ease;
    -webkit-mask-image: radial-gradient(92% 92% at 112% 112%, #000 0%, rgba(0, 0, 0, 0.45) 42%, transparent 70%);
    mask-image: radial-gradient(92% 92% at 112% 112%, #000 0%, rgba(0, 0, 0, 0.45) 42%, transparent 70%);
    /* variant 1 of 4: a field of dots */
    background-image: radial-gradient(circle at center, var(--qp-a2) 1.7px, transparent 2px);
    background-size: 14px 14px;
}

.qgold_our_services_container .qgold_our_services_container .card_container .main_cards .cards:hover::before,
.qbot_wrapper .qbot_value_section .qbot_value_proposition_cards_container .qbot_value_proposition_cards:hover::before,
.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_cards:hover::before,
.qbot_wrapper .qbot_technology_section .qbot_technology_cards_container .qbot_technology_cards:hover::before {
    opacity: 0.6;
}

/* variant 2: diagonal rule */
.qgold_our_services_container .card_container .main_cards:nth-of-type(4n + 2) .cards::before,
.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_cards::before {
    background-image: repeating-linear-gradient(48deg, var(--qp-a2) 0 2px, transparent 2px 11px);
    background-size: auto;
}

/* variant 3: chevrons */
.qgold_our_services_container .card_container .main_cards:nth-of-type(4n + 3) .cards::before,
.qbot_wrapper .qbot_technology_section .qbot_technology_cards_container .qbot_technology_cards::before {
    background-image:
        repeating-linear-gradient(135deg, var(--qp-a2) 0 2px, transparent 2px 13px),
        repeating-linear-gradient(45deg, var(--qp-a2) 0 2px, transparent 2px 13px);
    background-size: auto;
}

/* variant 4: concentric arcs */
.qgold_our_services_container .card_container .main_cards:nth-of-type(4n) .cards::before,
.qbot_wrapper .qbot_value_section .qbot_value_proposition_cards_container .qbot_value_proposition_cards:nth-of-type(2n)::before {
    background-image: repeating-radial-gradient(circle at 118% 118%, var(--qp-a2) 0 2px, transparent 2px 17px);
    background-size: auto;
}

/* --- the mark as a rounded square ----------------------------------------
   The reference sets its icon on a solid rounded-square colour tile. That is
   only possible where the coloured badge is drawn by CSS and the artwork is a
   plain glyph sitting on it -- true on qsales and qvirtue, where a 32px glyph
   sits on a 56px disc.

   qgold and qbot are not like that: their badge is painted into the SVG and
   fills its whole box, so the shape the reader sees belongs to the picture,
   not to any rule here. Rounding a wrapper behind it would change nothing,
   and boxing a round badge inside a square would just look like a mistake.
   Those two keep their badges and take the corner texture only.
   ------------------------------------------------------------------------ */

.qgold_our_services_container .qgold_our_services_container .card_container .main_cards .cards > div:first-child.img_bg,
.qgold_why_choose_us_container .propositions_container > div .propositions_points_container > div > div:first-child.pt_img_container {
    border-radius: 15px;
}

/* An accent wash in the card's top corner, behind the mark.
   On a near-black surface a white sheen alone barely registers -- what reads
   as warmth is colour, so each card also lifts its own product accent as the
   cursor arrives. It is the ::after because ::before is already the sheen;
   both sit under the content and neither takes a hit-test. */
.qgold_our_services_container .qgold_our_services_container .card_container .main_cards .cards::after,
.qbot_wrapper .qbot_value_section .qbot_value_proposition_cards_container .qbot_value_proposition_cards::after,
.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_cards::after,
.qbot_wrapper .qbot_technology_section .qbot_technology_cards_container .qbot_technology_cards::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    border-radius: inherit;
    pointer-events: none;
    background-image: radial-gradient(125% 95% at 6% 0%, var(--qp-aura), transparent 62%);
    opacity: 0;
    transition: opacity 0.45s ease;
}

.qgold_our_services_container .qgold_our_services_container .card_container .main_cards .cards:hover::after,
.qbot_wrapper .qbot_value_section .qbot_value_proposition_cards_container .qbot_value_proposition_cards:hover::after,
.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_cards:hover::after,
.qbot_wrapper .qbot_technology_section .qbot_technology_cards_container .qbot_technology_cards:hover::after {
    opacity: 1;
}

/* the card's own content has to sit above the sheen */
.qgold_our_services_container .qgold_our_services_container .card_container .main_cards .cards > *,
.qbot_wrapper .qbot_value_section .qbot_value_proposition_cards_container .qbot_value_proposition_cards > *,
.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_cards > *,
.qbot_wrapper .qbot_technology_section .qbot_technology_cards_container .qbot_technology_cards > * {
    position: relative;
    z-index: 1;
}

/* --- the icon marks ------------------------------------------------------
   The mark leans in when its card is hovered. Where the mark sits on a
   coloured disc it also grows a ring in the product's accent; where there is
   no disc -- qgold -- a ring would be drawn around nothing, so those get the
   lift alone.
   ------------------------------------------------------------------------ */

.qgold_our_services_container .qgold_our_services_container .card_container .main_cards .cards > div:first-child,
.qgold_why_choose_us_container .propositions_container > div .propositions_points_container > div > div:first-child,
.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_cards img,
.qbot_wrapper .qbot_value_section .qbot_value_proposition_cards_container .qbot_value_proposition_cards img {
    transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.4s ease;
}

.qgold_our_services_container .qgold_our_services_container .card_container .main_cards .cards:hover > div:first-child,
.qbot_wrapper .qbot_function_section .qbot_function_cards_container .qbot_function_cards:hover img,
.qbot_wrapper .qbot_value_section .qbot_value_proposition_cards_container .qbot_value_proposition_cards:hover img {
    transform: scale(1.09) rotate(-3deg);
}

.qgold_our_services_container .qgold_our_services_container .card_container .main_cards .cards:hover > div:first-child.img_bg,
.qgold_why_choose_us_container .propositions_container > div .propositions_points_container > div:hover > div:first-child.pt_img_container {
    box-shadow: 0 0 0 6px var(--qp-glow);
}

.qgold_why_choose_us_container .propositions_container > div .propositions_points_container > div:hover > div:first-child {
    transform: scale(1.07);
}

/* --- benefit pills -------------------------------------------------------
   The accent bar grows from the middle as each pill arrives. The bar is
   legacy's own ::before and its colour is set with !important, so only the
   transform is touched here -- the alternating orange and yellow stay.
   ------------------------------------------------------------------------ */

.qp-anim .qgold_benefits_container .benefits_main_container .benefits_list_container ul li.qp-reveal::before {
    transform: scaleY(0);
    transition: transform 0.55s cubic-bezier(0.22, 0.61, 0.36, 1) calc(var(--qd, 0s) + 0.12s);
}

.qp-anim .qgold_benefits_container .benefits_main_container .benefits_list_container ul li.qp-reveal.is-in::before {
    transform: scaleY(1);
}

/* --- proposition panels -------------------------------------------------- */

.qgold_why_choose_us_container .propositions_container > div .propositions_points_container > div:hover {
    transform: translateY(-3px);
}

/* --- qbot: the flow row --------------------------------------------------
   The arrows between the four value-proposition cards carry a slow drift, so
   the row reads as a sequence rather than four separate boxes. It is small on
   purpose -- 4px over 2.6s -- because this loops for as long as the section is
   on screen, and anything larger becomes something to look away from.
   ------------------------------------------------------------------------ */

@keyframes qp-flow {
    0%, 100% { translate: 0 0; opacity: 0.55; }
    50% { translate: 4px 0; opacity: 1; }
}

.qp-anim .qbot_wrapper .qbot_value_section .qbot_value_proposition_cards_container .qbot_value_proposition_arrow_container.is-in img {
    animation: qp-flow 2.6s ease-in-out infinite;
}

/* --- qbot: use-case cards ------------------------------------------------
   Both pseudo elements are legacy's, so nothing new is added: the accent bar
   it already draws simply widens on hover.
   ------------------------------------------------------------------------ */

.qbot_wrapper .qbot_usecases_section .qbot_usecase_cards_container .qbot_usecase_cards::after {
    transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
    transform-origin: left center;
}

.qbot_wrapper .qbot_usecases_section .qbot_usecase_cards_container .qbot_usecase_cards:hover::after {
    transform: scaleX(1.8);
}

/* --- reduced motion ------------------------------------------------------
   The reveal script already returns early here, so `qp-anim` is never added
   and none of the scroll work applies. This stands down the hover and loop
   animations as well, which are not the script's to decide.
   ------------------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
    .qgold_our_services_container .cards,
    .qgold_our_services_container .cards::before,
    .qgold_why_choose_us_container .propositions_points_container > div,
    .qbot_wrapper .qbot_value_proposition_cards,
    .qbot_wrapper .qbot_value_proposition_arrow_container img,
    .qbot_wrapper .qbot_function_cards,
    .qbot_wrapper .qbot_technology_cards,
    .qbot_wrapper .qbot_usecase_cards,
    .qbot_wrapper .qbot_usecase_cards::after {
        animation: none !important;
        transition: none !important;
    }
}

/* ==========================================================================
   Hero
   ==========================================================================

   Built to the reference: a full-height split, with the banner bleeding off
   the right edge and dissolving into the page on its left, a hairline down
   the middle, and the copy stacked on the left as eyebrow, headline in two
   tones, a short paragraph and two actions, with a scroll cue at the foot.

   This one DOES crop the banner, and that is worth stating plainly because it
   is the opposite of the rule the card sections follow. A full-height image
   column is roughly 3:4, the four banners are 1.50 to 2.23, and `cover` is
   the only way to fill that column edge to edge. So the crop is chosen rather
   than accepted: `object-position` is set per page to keep each subject in
   frame -- qvirtue's figure sits on the right of its photograph, qbot's robot
   left of centre. Below the lg breakpoint the image goes back to its natural
   height and is not cropped at all.

   The GSAP timeline at the foot of each page still owns the <img> element's
   clip-path and transform, so nothing here animates the image itself.
   ========================================================================== */

.qgold_banner_container {
    --qp-a1: #EBCB66;
    --qp-a2: #F89833;
    --qp-glow: rgba(235, 203, 102, 0.16);
    --qp-aura: rgba(235, 203, 102, 0.22);
}

body:has(.gradient_2_after) .qgold_banner_container {
    --qp-a1: #FFD8FE;
    --qp-a2: #FF8EFA;
    --qp-glow: rgba(255, 142, 250, 0.16);
    --qp-aura: rgba(255, 142, 250, 0.20);
}

body:has(.gradient_5_after) .qgold_banner_container {
    --qp-a1: rgb(191, 140, 132);
    --qp-a2: rgb(185, 114, 102);
    --qp-glow: rgba(185, 114, 102, 0.18);
    --qp-aura: rgba(185, 114, 102, 0.26);
}

body:has(.qbot_wrapper) .qgold_banner_container {
    --qp-a1: #F89833;
    --qp-a2: #EA396E;
    --qp-glow: rgba(234, 57, 110, 0.16);
    --qp-aura: rgba(234, 57, 110, 0.24);
}

/* --- the split ----------------------------------------------------------- */

.qgold_banner_container.fluid-container {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.06fr);
    align-items: stretch;
    gap: 0;
    padding: 0;
    /* svh rather than vh so a phone's collapsing toolbar does not make the
       hero taller than the screen it is measured against */
    min-height: min(100vh, 900px);
    min-height: min(100svh, 900px);
    isolation: isolate;
}

/* --- copy column --------------------------------------------------------- */

.qgold_banner_container.fluid-container .qgold_banner_texts {
    position: relative;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    padding: clamp(112px, 13vh, 154px) clamp(30px, 3.6vw, 60px) clamp(74px, 9vh, 112px) 4vw;
    /* the hairline down the middle of the reference */
    border-right: 1px solid rgba(255, 255, 255, 0.07);
}

/* The product mark. Its gradient rule is dropped in this layout -- between the
   eyebrow pill above it and a two-tone headline below, a third accent in the
   same 120px of space was one too many. */
.qgold_banner_container.fluid-container .qgold_banner_texts h1 {
    margin: 0 0 clamp(16px, 2vh, 24px);
    line-height: 0;
}

.qgold_banner_container.fluid-container .qgold_banner_texts h1::after {
    display: none;
}

.qgold_banner_container.fluid-container .qgold_banner_texts h1 img {
    display: block;
    width: auto;
    max-width: 100%;
    height: auto;
    max-height: clamp(30px, 3vw, 42px);
}

/* Two tones, and `.qp-hl` is a block so the break lands in the same place the
   reference puts it rather than wherever the column happens to run out. */
.qgold_banner_container.fluid-container .qgold_banner_texts h2 {
    padding: 0;
    margin: 0;
    font-size: clamp(30px, 3.6vw, 64px);
    font-weight: 600;
    line-height: 1.08;
    letter-spacing: -0.03em;
    color: rgba(255, 255, 255, 0.5);
}

.qgold_banner_container.fluid-container .qgold_banner_texts h2 .qp-hl {
    display: block;
    font-weight: 800;
    color: #FFFFFF;
    background-color: transparent;
}

.qgold_banner_container.fluid-container .qgold_banner_texts p {
    max-width: 74ch;
    margin: clamp(18px, 2.4vh, 26px) 0 0;
    font-size: clamp(14px, 1.05vw, 17px);
    line-height: 1.7;
    color: rgba(255, 255, 255, 0.62);
}

/* --- actions ------------------------------------------------------------- */

.qp-hero-cta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: clamp(14px, 2vw, 26px);
    margin-top: clamp(26px, 3.6vh, 42px);
    background-color: transparent;
}

.qp-hero-cta .qp-cta-link {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    font-size: 15px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.78);
    text-decoration: none;
    background-color: transparent;
    transition: color 0.3s ease;
}

.qp-hero-cta .qp-cta-link span {
    background-color: transparent;
    transition: translate 0.3s ease;
}

.qp-hero-cta .qp-cta-link:hover {
    color: #FFFFFF;
}

.qp-hero-cta .qp-cta-link:hover span {
    translate: 5px 0;
}

/* the fixed header would otherwise sit over the top of the jump target */
#explore {
    scroll-margin-top: 88px;
}

/* --- image column -------------------------------------------------------- */

.qgold_banner_container.fluid-container .ggold_banner_img {
    position: relative;
    z-index: 1;
    align-self: stretch;
    width: 100%;
    padding: 0;
    overflow: hidden;
    background-color: transparent;
}

.qgold_banner_container.fluid-container .ggold_banner_img img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    border-radius: 0;
    box-shadow: none;
}

/* Keeping each subject in frame under the crop. */
body:has(.gradient_5_after) .qgold_banner_container.fluid-container .ggold_banner_img img {
    object-position: 72% center;
}

body:has(.qbot_wrapper) .qgold_banner_container.fluid-container .ggold_banner_img img {
    object-position: 42% center;
}

/* The left edge dissolving into the page, with the product's accent blooming
   where the photograph meets the copy. This is what stops the split reading
   as two rectangles pushed together. */
.qgold_banner_container.fluid-container .ggold_banner_img::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background-image:
        linear-gradient(to right,
            #000000 0%,
            rgba(0, 0, 0, 0.94) 9%,
            rgba(0, 0, 0, 0.62) 22%,
            rgba(0, 0, 0, 0.22) 40%,
            rgba(0, 0, 0, 0) 62%),
        radial-gradient(58% 72% at 2% 50%, var(--qp-aura), transparent 72%);
}

/* and a fade at the foot so the hero hands off to the first section */
.qgold_banner_container.fluid-container .ggold_banner_img::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background-image: linear-gradient(to top, #000000 0%, rgba(0, 0, 0, 0) 24%);
}

/* --- scroll cue ---------------------------------------------------------- */

.qp-scroll {
    position: absolute;
    left: 0;
    right: 0;
    bottom: clamp(16px, 3vh, 32px);
    z-index: 3;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 9px;
    pointer-events: none;
    background-color: transparent;
}

.qp-scroll span {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.42);
    background-color: transparent;
}

.qp-scroll i {
    width: 9px;
    height: 9px;
    border-right: 1.5px solid rgba(255, 255, 255, 0.5);
    border-bottom: 1.5px solid rgba(255, 255, 255, 0.5);
    rotate: 45deg;
    background-color: transparent;
}

/* --- narrow screens ------------------------------------------------------
   One column, and the image returns to its own height: there is no tall
   column to fill down here, so there is no reason to crop it.
   ------------------------------------------------------------------------ */

@media (max-width: 991.98px) {
    .qgold_banner_container.fluid-container {
        grid-template-columns: minmax(0, 1fr);
        min-height: 0;
    }

    .qgold_banner_container.fluid-container .qgold_banner_texts {
        padding: clamp(104px, 22vw, 128px) 5% clamp(32px, 6vw, 46px) 4vw;
        border-right: 0;
    }

    .qgold_banner_container.fluid-container .ggold_banner_img img {
        position: static;
        height: auto;
    }

    /* the fade moves to the top edge, which is where it now meets the copy */
    .qgold_banner_container.fluid-container .ggold_banner_img::before {
        background-image:
            linear-gradient(to bottom,
                #000000 0%,
                rgba(0, 0, 0, 0.45) 14%,
                rgba(0, 0, 0, 0) 42%),
            radial-gradient(80% 60% at 50% 0%, var(--qp-aura), transparent 70%);
    }

    .qgold_banner_container.fluid-container .ggold_banner_img::after {
        background-image: linear-gradient(to top, #000000 0%, rgba(0, 0, 0, 0) 18%);
    }

    /* nothing to point at on a phone -- the next section is already adjacent */
    .qp-scroll {
        display: none;
    }
}

@media (max-width: 575.98px) {
    .qgold_banner_container.fluid-container .qgold_banner_texts h2 .qp-hl {
        display: inline;
    }
}

/* --- entrance ------------------------------------------------------------
   Above the fold, so this is a plain load-time animation with no observer to
   wait on. The whole block sits inside a reduced-motion guard: when motion is
   not wanted these rules do not exist and the hero simply renders.
   ------------------------------------------------------------------------ */

@media (prefers-reduced-motion: no-preference) {
    @keyframes qp-hero-rise {
        from { opacity: 0; translate: 0 16px; }
        to { opacity: 1; translate: 0 0; }
    }

    @keyframes qp-hero-reveal {
        from { opacity: 0; clip-path: inset(0 0 0 22%); }
        to { opacity: 1; clip-path: inset(0 0 0 0); }
    }

    @keyframes qp-scroll-bob {
        0%, 100% { translate: 0 0; opacity: 0.5; }
        50% { translate: 0 5px; opacity: 1; }
    }

    .qgold_banner_container.fluid-container .qgold_banner_texts h1,
    .qgold_banner_container.fluid-container .qgold_banner_texts h2,
    .qgold_banner_container.fluid-container .qgold_banner_texts p,
    .qp-hero-cta {
        animation: qp-hero-rise 0.62s cubic-bezier(0.22, 0.61, 0.36, 1) both;
    }

    .qgold_banner_container.fluid-container .qgold_banner_texts h1 { animation-delay: 0.06s; }
    .qgold_banner_container.fluid-container .qgold_banner_texts h2 { animation-delay: 0.13s; }
    .qgold_banner_container.fluid-container .qgold_banner_texts p { animation-delay: 0.2s; }
    .qp-hero-cta { animation-delay: 0.27s; }

    /* the column, never the <img> -- GSAP owns that element */
    .qgold_banner_container.fluid-container .ggold_banner_img {
        animation: qp-hero-reveal 1s cubic-bezier(0.22, 0.61, 0.36, 1) 0.1s both;
    }

    .qp-scroll i {
        animation: qp-scroll-bob 2.2s ease-in-out infinite;
    }
}

/* ==========================================================================
   qkonnect-cti
   ==========================================================================

   The largest of the five product pages: ten sections and eight card
   families. Its class vocabulary is its own, so the rules below repeat the
   values the other pages use rather than extending their selector lists --
   safer than threading a ninth and tenth selector through twenty working
   rules, at the cost of some duplication.

   Its hero turns out to be the same two-child shape as the rest (a heading
   block and an image block in one container), so the reference layout applies
   without restructuring anything.

   Every legacy card selector here is exactly three classes deep, so scoping
   to `.qkonnect_cti_wrapper` puts these at four and they land cleanly.
   ========================================================================== */

.qkonnect_cti_wrapper,
.product_qkonnect_banner {
    /* qkonnect rules its headings with the house gradient, same as qbot */
    --qp-a1: #F89833;
    --qp-a2: #EA396E;
    --qp-tint: rgba(234, 57, 110, 0.38);
    --qp-glow: rgba(234, 57, 110, 0.15);
    --qp-aura: rgba(234, 57, 110, 0.18);

    --qp-surface: #141416;
    --qp-line: rgba(255, 255, 255, 0.09);
    --qp-text: #F5F5F7;
    --qp-dim: #A9A9B4;
}

/* --- hero ---------------------------------------------------------------- */

.product_qkonnect_banner.container-fluid {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.06fr);
    align-items: stretch;
    gap: 0;
    padding: 0;
    min-height: min(100vh, 900px);
    min-height: min(100svh, 900px);
    isolation: isolate;
}

.product_qkonnect_banner.container-fluid .product_qkonnect_heading {
    position: relative;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    padding: clamp(112px, 13vh, 154px) clamp(30px, 3.6vw, 60px) clamp(74px, 9vh, 112px) 4vw;
    border-right: 1px solid rgba(255, 255, 255, 0.07);
}

.product_qkonnect_banner.container-fluid .product_qkonnect_heading h1 {
    margin: 0 0 clamp(16px, 2vh, 24px);
    line-height: 0;
}

.product_qkonnect_banner.container-fluid .product_qkonnect_heading h1::after {
    display: none;
}

.product_qkonnect_banner.container-fluid .product_qkonnect_heading h1 img {
    display: block;
    width: auto;
    max-width: 100%;
    height: auto;
    max-height: clamp(30px, 3vw, 42px);
}

.product_qkonnect_banner.container-fluid .product_qkonnect_heading h3 {
    padding: 0;
    margin: 0;
    font-size: clamp(30px, 3.6vw, 64px);
    font-weight: 600;
    line-height: 1.08;
    letter-spacing: -0.03em;
    color: rgba(255, 255, 255, 0.5);
}

.product_qkonnect_banner.container-fluid .product_qkonnect_heading h3 .qp-hl {
    display: block;
    font-weight: 800;
    color: #FFFFFF;
    background-color: transparent;
}

.product_qkonnect_banner.container-fluid .product_qkonnect_heading p {
    max-width: 74ch;
    margin: clamp(18px, 2.4vh, 26px) 0 0;
    font-size: clamp(14px, 1.05vw, 17px);
    line-height: 1.7;
    color: rgba(255, 255, 255, 0.62);
}

.product_qkonnect_banner.container-fluid .industries_aio_img {
    position: relative;
    z-index: 1;
    align-self: stretch;
    width: 100%;
    padding: 0;
    overflow: hidden;
    background-color: transparent;
}

/* Legacy parks this image at `scale: 0.7` behind a sliver clip-path and
   relies on the GSAP timeline at the foot of the page to open it. That is a
   real animation here, unlike on the sibling pages where it was a leftover
   no-op -- but it also means a script failure leaves the hero image as a
   slice. Neutralising the start state costs nothing (GSAP still animates to
   the same finished state, and writes inline styles that win regardless) and
   means the hero cannot be hidden by a script that never ran. */
.product_qkonnect_banner.container-fluid .industries_aio_img img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    max-width: none;
    margin: 0;
    object-fit: cover;
    object-position: center;
    border-radius: 0;
    box-shadow: none;
    clip-path: none;
    scale: 1;
}

.product_qkonnect_banner.container-fluid .industries_aio_img::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background-image:
        linear-gradient(to right,
            #000000 0%,
            rgba(0, 0, 0, 0.94) 9%,
            rgba(0, 0, 0, 0.62) 22%,
            rgba(0, 0, 0, 0.22) 40%,
            rgba(0, 0, 0, 0) 62%),
        radial-gradient(58% 72% at 2% 50%, var(--qp-aura), transparent 72%);
}

.product_qkonnect_banner.container-fluid .industries_aio_img::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background-image: linear-gradient(to top, #000000 0%, rgba(0, 0, 0, 0) 24%);
}

@media (max-width: 991.98px) {
    .product_qkonnect_banner.container-fluid {
        grid-template-columns: minmax(0, 1fr);
        min-height: 0;
    }

    .product_qkonnect_banner.container-fluid .product_qkonnect_heading {
        padding: clamp(104px, 22vw, 128px) 5% clamp(32px, 6vw, 46px) 4vw;
        border-right: 0;
    }

    .product_qkonnect_banner.container-fluid .industries_aio_img img {
        position: static;
        height: auto;
    }

    .product_qkonnect_banner.container-fluid .industries_aio_img::before {
        background-image:
            linear-gradient(to bottom,
                #000000 0%,
                rgba(0, 0, 0, 0.45) 14%,
                rgba(0, 0, 0, 0) 42%),
            radial-gradient(80% 60% at 50% 0%, var(--qp-aura), transparent 70%);
    }

    .product_qkonnect_banner.container-fluid .industries_aio_img::after {
        background-image: linear-gradient(to top, #000000 0%, rgba(0, 0, 0, 0) 18%);
    }
}

/* --- defects in the legacy page ------------------------------------------
   Three things that are wrong before any restyling, found by measuring:

   1. The two About images are sized `height: 80%` (46% on phone) inside a
      parent with no definite height. A percentage height against an auto
      parent resolves to auto, and with the image itself at `height: 100%`
      the pair collapsed to ZERO -- both pictures were invisible on a phone.
      Letting the artwork set its own height is the fix.

   2. The "How It Works" arrows are turned edge-on with `rotateX(90deg)` at
      narrow widths, which leaves a 4px sliver rather than hiding them. The
      steps stack vertically there, so a left-to-right arrow has no job:
      taking them out of the flow is what was meant.

   3. One Features card runs taller than its row because the cards are not
      stretched to a common height.
   ------------------------------------------------------------------------ */

/* On desktop these two photographs are deliberately absolute and overlapping,
   beside the copy -- that composition is kept. The bug is only what happens
   when the section stacks: the container loses its definite height, the
   percentage heights resolve to nothing and both pictures collapse to zero.
   Putting them back in normal flow below the copy is what that layout wants.
   Position relative rather than static, so the gradient rules pinned to them
   keep their anchor. */
@media (max-width: 991.98px) {
    .qkonnect_cti_wrapper .product_qkonnect_about_section .product_qkonnect_cards_container .qkonnect_card_one_image_container,
    .qkonnect_cti_wrapper .product_qkonnect_about_section .product_qkonnect_cards_container .qkonnect_card_two_image_container {
        position: relative;
        top: auto;
        right: auto;
        bottom: auto;
        left: auto;
        width: 100%;
        height: auto;
        margin-top: 18px;
    }

    .qkonnect_cti_wrapper .product_qkonnect_about_section .product_qkonnect_cards_container .qkonnect_card_one_image_container img,
    .qkonnect_cti_wrapper .product_qkonnect_about_section .product_qkonnect_cards_container .qkonnect_card_two_image_container img {
        height: auto;
        max-width: 100%;
        border-radius: 14px;
    }
}

@media (max-width: 575.98px) {
    .qkonnect_cti_wrapper .product_qkonnect_work_section .product_qkonnect_work_cards_container .arrow_img {
        display: none;
    }
}

.qkonnect_cti_wrapper .product_qkonnect_features_section .product_qkonnect_features_card_container .product_qkonnect_features_card {
    height: 100%;
}

/* --- card surfaces -------------------------------------------------------
   The same treatment the other four pages carry: one dark surface, one
   radius, a hairline edge, an accent wash on hover and an accent texture
   bleeding out of the bottom-right corner.
   ------------------------------------------------------------------------ */

.qkonnect_cti_wrapper .product_qkonnect_why_qkonnect_section .why_qkonnect_cards_container .why_qkonnect_cards,
.qkonnect_cti_wrapper .product_qkonnect_platform_values_section .product_qkonnect_platform_cards_container .product_qkonnect_platform_card,
.qkonnect_cti_wrapper .product_qkonnect_features_section .product_qkonnect_features_card_container .product_qkonnect_features_card,
.qkonnect_cti_wrapper .product_qkonnect_work_section .product_qkonnect_work_cards_container .product_qkonnect_work_card,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_cards_container_1 .product_qkonnect_tech_enabled_cards_1,
.qkonnect_cti_wrapper .product_qkonnect_approach_section .product_qkonnect_approach_card .product_qkonnect_approach_card_one,
.qkonnect_cti_wrapper .product_qkonnect_about_section .product_qkonnect_cards_two_container .product_qkonnect_cards_two {
    position: relative;
    /* the Bootstrap .row is flex, so the COLUMNS already stretch to the
       tallest in their line -- the cards just were not filling them */
    height: 100%;
    padding: clamp(20px, 1.7vw, 26px);
    border: 1px solid var(--qp-line);
    border-radius: 16px;
    background-color: var(--qp-surface);
    background-image: none;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
    transition: transform 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
}

.qkonnect_cti_wrapper .product_qkonnect_why_qkonnect_section .why_qkonnect_cards_container .why_qkonnect_cards:hover,
.qkonnect_cti_wrapper .product_qkonnect_platform_values_section .product_qkonnect_platform_cards_container .product_qkonnect_platform_card:hover,
.qkonnect_cti_wrapper .product_qkonnect_features_section .product_qkonnect_features_card_container .product_qkonnect_features_card:hover,
.qkonnect_cti_wrapper .product_qkonnect_work_section .product_qkonnect_work_cards_container .product_qkonnect_work_card:hover,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_cards_container_1 .product_qkonnect_tech_enabled_cards_1:hover,
.qkonnect_cti_wrapper .product_qkonnect_approach_section .product_qkonnect_approach_card .product_qkonnect_approach_card_one:hover,
.qkonnect_cti_wrapper .product_qkonnect_about_section .product_qkonnect_cards_two_container .product_qkonnect_cards_two:hover {
    transform: translateY(-4px);
    border-color: var(--qp-tint);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.5), 0 0 26px var(--qp-glow);
}

.qkonnect_cti_wrapper .product_qkonnect_why_qkonnect_section .why_qkonnect_cards_container .why_qkonnect_cards::before,
.qkonnect_cti_wrapper .product_qkonnect_platform_values_section .product_qkonnect_platform_cards_container .product_qkonnect_platform_card::before,
.qkonnect_cti_wrapper .product_qkonnect_features_section .product_qkonnect_features_card_container .product_qkonnect_features_card::before,
.qkonnect_cti_wrapper .product_qkonnect_work_section .product_qkonnect_work_cards_container .product_qkonnect_work_card::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    border-radius: inherit;
    pointer-events: none;
    opacity: 0.42;
    transition: opacity 0.4s ease;
    -webkit-mask-image: radial-gradient(92% 92% at 112% 112%, #000 0%, rgba(0, 0, 0, 0.45) 42%, transparent 70%);
    mask-image: radial-gradient(92% 92% at 112% 112%, #000 0%, rgba(0, 0, 0, 0.45) 42%, transparent 70%);
    background-image: radial-gradient(circle at center, var(--qp-a2) 1.7px, transparent 2px);
    background-size: 14px 14px;
}

.qkonnect_cti_wrapper .product_qkonnect_why_qkonnect_section .why_qkonnect_cards_container .why_qkonnect_cards:hover::before,
.qkonnect_cti_wrapper .product_qkonnect_platform_values_section .product_qkonnect_platform_cards_container .product_qkonnect_platform_card:hover::before,
.qkonnect_cti_wrapper .product_qkonnect_features_section .product_qkonnect_features_card_container .product_qkonnect_features_card:hover::before,
.qkonnect_cti_wrapper .product_qkonnect_work_section .product_qkonnect_work_cards_container .product_qkonnect_work_card:hover::before {
    opacity: 0.6;
}

/* the texture varies so a nine- or fifteen-card grid does not read as one
   card repeated */
.qkonnect_cti_wrapper .product_qkonnect_platform_card:nth-of-type(4n + 2)::before,
.qkonnect_cti_wrapper .product_qkonnect_features_card:nth-of-type(4n + 2)::before,
.qkonnect_cti_wrapper .why_qkonnect_cards:nth-of-type(4n + 2)::before {
    background-image: repeating-linear-gradient(48deg, var(--qp-a2) 0 2px, transparent 2px 11px);
    background-size: auto;
}

.qkonnect_cti_wrapper .product_qkonnect_platform_card:nth-of-type(4n + 3)::before,
.qkonnect_cti_wrapper .product_qkonnect_features_card:nth-of-type(4n + 3)::before,
.qkonnect_cti_wrapper .why_qkonnect_cards:nth-of-type(4n + 3)::before {
    background-image:
        repeating-linear-gradient(135deg, var(--qp-a2) 0 2px, transparent 2px 13px),
        repeating-linear-gradient(45deg, var(--qp-a2) 0 2px, transparent 2px 13px);
    background-size: auto;
}

.qkonnect_cti_wrapper .product_qkonnect_platform_card:nth-of-type(4n)::before,
.qkonnect_cti_wrapper .product_qkonnect_features_card:nth-of-type(4n)::before,
.qkonnect_cti_wrapper .why_qkonnect_cards:nth-of-type(4n)::before {
    background-image: repeating-radial-gradient(circle at 118% 118%, var(--qp-a2) 0 2px, transparent 2px 17px);
    background-size: auto;
}

/* card content sits above the texture */
.qkonnect_cti_wrapper .why_qkonnect_cards > *,
.qkonnect_cti_wrapper .product_qkonnect_platform_card > *,
.qkonnect_cti_wrapper .product_qkonnect_features_card > *,
.qkonnect_cti_wrapper .product_qkonnect_work_card > *,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_cards_1 > * {
    position: relative;
    z-index: 1;
}

/* --- section headings ---------------------------------------------------- */


/* --- hero entrance -------------------------------------------------------
   Same contract as the other pages: inside a reduced-motion guard, animating
   the image COLUMN rather than the image, which GSAP owns.
   ------------------------------------------------------------------------ */

@media (prefers-reduced-motion: no-preference) {
    .product_qkonnect_banner.container-fluid .product_qkonnect_heading h1,
    .product_qkonnect_banner.container-fluid .product_qkonnect_heading h3,
    .product_qkonnect_banner.container-fluid .product_qkonnect_heading p,
    .product_qkonnect_banner.container-fluid .qp-hero-cta {
        animation: qp-hero-rise 0.62s cubic-bezier(0.22, 0.61, 0.36, 1) both;
    }

    .product_qkonnect_banner.container-fluid .product_qkonnect_heading h1 { animation-delay: 0.06s; }
    .product_qkonnect_banner.container-fluid .product_qkonnect_heading h3 { animation-delay: 0.13s; }
    .product_qkonnect_banner.container-fluid .product_qkonnect_heading p { animation-delay: 0.2s; }
    .product_qkonnect_banner.container-fluid .qp-hero-cta { animation-delay: 0.27s; }

    .product_qkonnect_banner.container-fluid .industries_aio_img {
        animation: qp-hero-reveal 1s cubic-bezier(0.22, 0.61, 0.36, 1) 0.1s both;
    }
}

/* --- the card families the first pass missed ------------------------------
   Auditing the page after the fact turned up three gaps of my own making:
   the About suite cards and the Approach cards took the surface but not the
   corner texture, and the AI-integrated group -- seventeen cards across three
   variants -- was left out of both, still sitting at legacy's 10px radius
   with no surface at all. Everything below closes that, so all eight families
   on the page carry the same treatment.
   ------------------------------------------------------------------------ */

.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_ai_integrated_section .product_qkonnect_tech_enabled_ai_integrated_cards_2,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_ai_integrated_section .product_qkonnect_tech_enabled_ai_integrated_cards_3,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_ai_integrated_section .product_qkonnect_tech_enabled_ai_integrated_cards_4 {
    position: relative;
    height: 100%;
    padding: clamp(20px, 1.7vw, 26px);
    border: 1px solid var(--qp-line);
    border-radius: 16px;
    background-color: var(--qp-surface);
    background-image: none;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
    transition: transform 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
}

.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_ai_integrated_section .product_qkonnect_tech_enabled_ai_integrated_cards_2:hover,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_ai_integrated_section .product_qkonnect_tech_enabled_ai_integrated_cards_3:hover,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_ai_integrated_section .product_qkonnect_tech_enabled_ai_integrated_cards_4:hover {
    transform: translateY(-4px);
    border-color: var(--qp-tint);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.5), 0 0 26px var(--qp-glow);
}

/* The corner texture, for every family that was missing it. Scoped four
   classes deep so it clears legacy, which never goes past three. */
.qkonnect_cti_wrapper .product_qkonnect_about_section .product_qkonnect_cards_two_container .product_qkonnect_cards_two::before,
.qkonnect_cti_wrapper .product_qkonnect_approach_section .product_qkonnect_approach_card .product_qkonnect_approach_card_one::before,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_ai_integrated_section .product_qkonnect_tech_enabled_ai_integrated_cards_2::before,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_ai_integrated_section .product_qkonnect_tech_enabled_ai_integrated_cards_3::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    border-radius: inherit;
    pointer-events: none;
    opacity: 0.42;
    transition: opacity 0.4s ease;
    -webkit-mask-image: radial-gradient(92% 92% at 112% 112%, #000 0%, rgba(0, 0, 0, 0.45) 42%, transparent 70%);
    mask-image: radial-gradient(92% 92% at 112% 112%, #000 0%, rgba(0, 0, 0, 0.45) 42%, transparent 70%);
    background-image: radial-gradient(circle at center, var(--qp-a2) 1.7px, transparent 2px);
    background-size: 14px 14px;
    background-repeat: repeat;
}

.qkonnect_cti_wrapper .product_qkonnect_about_section .product_qkonnect_cards_two_container .product_qkonnect_cards_two:hover::before,
.qkonnect_cti_wrapper .product_qkonnect_approach_section .product_qkonnect_approach_card .product_qkonnect_approach_card_one:hover::before,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_ai_integrated_section .product_qkonnect_tech_enabled_ai_integrated_cards_2:hover::before,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_ai_integrated_section .product_qkonnect_tech_enabled_ai_integrated_cards_3:hover::before {
    opacity: 0.6;
}

/* texture variants, so a twelve-card group does not repeat one motif */
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_2:nth-of-type(3n + 2)::before,
.qkonnect_cti_wrapper .product_qkonnect_cards_two:nth-of-type(3n + 2)::before {
    background-image: repeating-linear-gradient(48deg, var(--qp-a2) 0 2px, transparent 2px 11px);
    background-size: auto;
}

.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_2:nth-of-type(3n)::before,
.qkonnect_cti_wrapper .product_qkonnect_cards_two:nth-of-type(3n)::before {
    background-image: repeating-radial-gradient(circle at 118% 118%, var(--qp-a2) 0 2px, transparent 2px 17px);
    background-size: auto;
}

/* content above the texture on the newly covered families */
.qkonnect_cti_wrapper .product_qkonnect_cards_two > *,
.qkonnect_cti_wrapper .product_qkonnect_approach_card_one > *,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_2 > *,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_3 > *,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4 > * {
    position: relative;
    z-index: 1;
}

/* --- the two families that already own their ::before --------------------
   These draw a 5px coloured bar down the left edge, per variant, set with
   !important. Nothing new is added on top of it -- as with qbot use-case
   cards, the bar they already have simply widens on hover.
   ------------------------------------------------------------------------ */

.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_cards_1::before,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4::before {
    transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
    transform-origin: left center;
}

.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_cards_1:hover::before,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4:hover::before {
    transform: scaleX(1.8);
}

/* --- black slabs inside the cards ----------------------------------------
   Global.css line 5 sets `* { background-color: black }`, so every element
   paints opaque black unless something says otherwise. The qgold family is
   spared because legacy neutralises it there with its own
   `* { background-color: transparent }`; qkonnect never got that rule, so
   the bullet lists in the AI-integrated cards were painting a solid black
   rectangle across the middle of each card.

   Checked first: nothing inside any qkonnect card carries a deliberate
   background colour or image, so clearing the lot is safe rather than
   destructive.
   ------------------------------------------------------------------------ */

.qkonnect_cti_wrapper .product_qkonnect_cards_two *,
.qkonnect_cti_wrapper .product_qkonnect_approach_card_one *,
.qkonnect_cti_wrapper .why_qkonnect_cards *,
.qkonnect_cti_wrapper .product_qkonnect_platform_card *,
.qkonnect_cti_wrapper .product_qkonnect_features_card *,
.qkonnect_cti_wrapper .product_qkonnect_work_card *,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_cards_1 *,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_2 *,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_3 *,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4 * {
    background-color: transparent;
}

/* --- gaps between cards --------------------------------------------------
   Measured edge to edge, the grids disagreed: 24px horizontally everywhere,
   but vertically the Features grid had ZERO -- its three rows of cards were
   touching -- while others sat at 20 or 24. The cards are stretched to fill
   their Bootstrap column, so the space has to come from the row, not from a
   margin on the card itself.
   ------------------------------------------------------------------------ */

/* Only the Features grid. The other grids already carry 20-24px of vertical
   margin of their own, and adding row-gap on top of that doubled them to 44
   and 48px -- measured after the first attempt. */
.qkonnect_cti_wrapper .product_qkonnect_features_section .product_qkonnect_features_card_container .row {
    row-gap: 24px;
}

/* --- the bullet lists ----------------------------------------------------
   Now that the slab is gone the list itself can be set properly: markers in
   the product accent, and a measure that does not run to the card edge.
   ------------------------------------------------------------------------ */

.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4 ul,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_2 ul {
    margin: 12px 0 0;
    padding-left: 0;
    list-style: none;
}

.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4 ul li,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_2 ul li {
    position: relative;
    padding-left: 20px;
    margin: 0 0 8px;
    font-size: clamp(13.5px, 1.08vw, 15px);
    line-height: 1.65;
    color: var(--qp-dim);
}

.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4 ul li::before,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_2 ul li::before {
    content: "";
    position: absolute;
    top: 0.62em;
    left: 2px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background-image: linear-gradient(to bottom right, var(--qp-a1), var(--qp-a2));
}

/* ==========================================================================
   The accent-bar cards
   ==========================================================================

   Legacy gives each of these a coloured bar down the left edge -- pink,
   yellow or purple by variant class -- and then stops. Everything else about
   the three cards is identical, so the colour reads as decoration rather than
   as something the card is built around.

   Here that colour becomes the card's own: it drives the heading, the bullet
   markers, the corner texture, the bar's glow and the hover. The trio still
   reads as a set because the geometry is shared, but each card is now its own
   object rather than a recolour of its neighbour.

   The bar itself is legacy's ::before and is left in place -- its background
   is set !important per variant, so it is not ours to restyle. Only its
   geometry and glow are touched. ::after was free on both families, which is
   what the corner texture uses.
   ========================================================================== */

.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_cards_1 {
    --qk-c: var(--qp-a2);
}

.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4_pink,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_cards_1_pink {
    --qk-c: #E07394;
}

.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4_purple,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_cards_1_purple {
    --qk-c: #C878C9;
}

.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4_yellow,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_cards_1_yellow {
    --qk-c: #C78A4E;
}

/* --- the bar -------------------------------------------------------------
   Inset from the corners rather than running the full height, fully rounded,
   and lit from behind. Its colour stays legacy's.
   ------------------------------------------------------------------------ */

.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_ai_integrated_section .product_qkonnect_tech_enabled_ai_integrated_cards_4::before,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_cards_container_1 .product_qkonnect_tech_enabled_cards_1::before {
    left: 0;
    top: 14px;
    bottom: 14px;
    height: auto;
    width: 4px;
    border-radius: 0 4px 4px 0;
    /* No glow at all. A coloured box-shadow on a 4px bar reads as a halo
       bleeding onto the card rather than as light on the bar. */
    box-shadow: none;
    transition: width 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_ai_integrated_section .product_qkonnect_tech_enabled_ai_integrated_cards_4:hover::before,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_cards_container_1 .product_qkonnect_tech_enabled_cards_1:hover::before {
    width: 6px;
}

/* --- corner texture, in the card's own colour ---------------------------- */

.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4::after,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_cards_1::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    border-radius: inherit;
    pointer-events: none;
    opacity: 0.34;
    transition: opacity 0.4s ease;
    -webkit-mask-image: radial-gradient(92% 92% at 112% 112%, #000 0%, rgba(0, 0, 0, 0.45) 42%, transparent 70%);
    mask-image: radial-gradient(92% 92% at 112% 112%, #000 0%, rgba(0, 0, 0, 0.45) 42%, transparent 70%);
    background-image: radial-gradient(circle at center, var(--qk-c) 1.7px, transparent 2px);
    background-size: 14px 14px;
}

.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4_purple::after,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_cards_1_purple::after {
    background-image: repeating-linear-gradient(48deg, var(--qk-c) 0 2px, transparent 2px 11px);
    background-size: auto;
}

.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4_yellow::after,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_cards_1_yellow::after {
    background-image: repeating-radial-gradient(circle at 118% 118%, var(--qk-c) 0 2px, transparent 2px 17px);
    background-size: auto;
}

.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4:hover::after,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_cards_1:hover::after {
    opacity: 0.5;
}

/* --- heading -------------------------------------------------------------
   Tinted with the card's colour and given a short rule beneath it, so the
   colour is established at the top of the card rather than only down its
   edge.
   ------------------------------------------------------------------------ */

.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_ai_integrated_section .product_qkonnect_tech_enabled_ai_integrated_cards_4 h5,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_cards_container_1 .product_qkonnect_tech_enabled_cards_1 h5 {
    position: relative;
    z-index: 1;
    display: inline-block;
    margin: 0 0 16px;
    padding-bottom: 10px;
    font-size: clamp(16px, 1.35vw, 19px);
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--qk-c);
}

.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4 h5::after,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_cards_1 h5::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 34px;
    height: 2px;
    border-radius: 2px;
    background-color: var(--qk-c);
    opacity: 0.55;
    transition: width 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4:hover h5::after,
.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_cards_1:hover h5::after {
    width: 100%;
}

/* --- bullets, in the card's colour --------------------------------------- */

.qkonnect_cti_wrapper .product_qkonnect_tech_enabled_ai_integrated_cards_4 ul li::before {
    background-image: none;
    background-color: var(--qk-c);
}

/* --- hover, likewise ----------------------------------------------------- */

.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_ai_integrated_section .product_qkonnect_tech_enabled_ai_integrated_cards_4:hover,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_cards_container_1 .product_qkonnect_tech_enabled_cards_1:hover {
    transform: translateY(-4px);
    border-color: var(--qk-c);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55);
}

/* ==========================================================================
   The About suite cards
   ==========================================================================

   Three cards whose only distinguishing mark is the colour of their icon --
   yellow, pink, purple, the same three the accent-bar cards use. Nothing else
   about them differed, so the colour sat in the badge and stopped there while
   the texture underneath was the same pink on all three.

   There are no variant classes to hook, so the colour is assigned by column
   position, which is what the icons follow: qkonnect_icon_3 yellow first,
   _2 pink, _1 purple. Rather than introduce another custom property, each
   card simply redefines the accent properties it already inherits -- so the
   texture, the hover border and the glow all pick up its own colour with no
   further rules.
   ========================================================================== */

.qkonnect_cti_wrapper .product_qkonnect_cards_two_container > *:nth-child(1) .product_qkonnect_cards_two {
    --qk-c: #C78A4E;
    --qp-a1: #C78A4E;
    --qp-a2: #C78A4E;
    --qp-tint: rgba(199, 138, 78, 0.45);
    --qp-glow: rgba(199, 138, 78, 0.16);
}

.qkonnect_cti_wrapper .product_qkonnect_cards_two_container > *:nth-child(2) .product_qkonnect_cards_two {
    --qk-c: #E07394;
    --qp-a1: #E07394;
    --qp-a2: #E07394;
    --qp-tint: rgba(224, 115, 148, 0.45);
    --qp-glow: rgba(224, 115, 148, 0.16);
}

.qkonnect_cti_wrapper .product_qkonnect_cards_two_container > *:nth-child(3) .product_qkonnect_cards_two {
    --qk-c: #C878C9;
    --qp-a1: #C878C9;
    --qp-a2: #C878C9;
    --qp-tint: rgba(200, 120, 201, 0.45);
    --qp-glow: rgba(200, 120, 201, 0.16);
}

/* a different geometry per card, as elsewhere on the page */
.qkonnect_cti_wrapper .product_qkonnect_cards_two_container > *:nth-child(2) .product_qkonnect_cards_two::before {
    background-image: repeating-linear-gradient(48deg, var(--qk-c) 0 2px, transparent 2px 11px);
    background-size: auto;
}

.qkonnect_cti_wrapper .product_qkonnect_cards_two_container > *:nth-child(3) .product_qkonnect_cards_two::before {
    background-image: repeating-radial-gradient(circle at 118% 118%, var(--qk-c) 0 2px, transparent 2px 17px);
    background-size: auto;
}

/* --- the icon ------------------------------------------------------------
   The badge is painted into the PNG, so its shape is not ours to change. A
   ring in the card's own colour sits behind it instead, opening on hover.
   ------------------------------------------------------------------------ */

.qkonnect_cti_wrapper .product_qkonnect_about_section .product_qkonnect_cards_two_container .product_qkonnect_cards_two img {
    position: relative;
    z-index: 1;
    /* block, so the heading stays under the icon. Making the h5 an
       inline-block (which the accent rule needs, to measure the text rather
       than the column) otherwise pulls it up alongside the image. */
    display: block;
    border-radius: 50%;
    transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.4s ease;
}

.qkonnect_cti_wrapper .product_qkonnect_about_section .product_qkonnect_cards_two_container .product_qkonnect_cards_two:hover img {
    transform: scale(1.08) rotate(-3deg);
    box-shadow: 0 0 0 7px var(--qp-glow);
}

/* --- heading -------------------------------------------------------------
   Left white, because the icon above it already carries the colour. The rule
   beneath is the accent, matching the bar cards, and it runs out to full
   width on hover.
   ------------------------------------------------------------------------ */

.qkonnect_cti_wrapper .product_qkonnect_about_section .product_qkonnect_cards_two_container .product_qkonnect_cards_two h5 {
    position: relative;
    z-index: 1;
    display: inline-block;
    margin: 4px 0 14px;
    padding-bottom: 10px;
    font-size: clamp(16px, 1.35vw, 19px);
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--qp-text);
}

.qkonnect_cti_wrapper .product_qkonnect_cards_two h5::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 34px;
    height: 2px;
    border-radius: 2px;
    background-color: var(--qk-c);
    opacity: 0.7;
    transition: width 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.qkonnect_cti_wrapper .product_qkonnect_cards_two:hover h5::after {
    width: 100%;
}

.qkonnect_cti_wrapper .product_qkonnect_about_section .product_qkonnect_cards_two_container .product_qkonnect_cards_two p {
    position: relative;
    z-index: 1;
    margin: 0;
    font-size: clamp(13.5px, 1.08vw, 15px);
    line-height: 1.7;
    color: var(--qp-dim);
}

/* --- hover, in the card's own colour and without any glow ---------------- */

.qkonnect_cti_wrapper .product_qkonnect_about_section .product_qkonnect_cards_two_container .product_qkonnect_cards_two:hover {
    transform: translateY(-4px);
    border-color: var(--qk-c);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55);
}

/* ==========================================================================
   Platform value drivers
   ==========================================================================

   Nine cards whose icons carry one of the page's three colours. Sampling the
   badge fill out of each icon file gives yellow, pink, purple, purple,
   yellow, pink, pink, pink, yellow -- not a repeating cycle, so assigning by
   column position would have been guesswork that broke the first time a card
   moved.

   Each card is matched on the icon it actually contains instead. `:has()`
   reads the descendant and colours the card from it, so the mapping survives
   reordering and is legible against the markup.

   As with the suite cards, the card redefines the accent properties it
   already inherits, so the texture, the rule under the heading and the hover
   all follow without further rules. Geometry follows colour: dots for
   yellow, diagonals for pink, arcs for purple.
   ========================================================================== */

.qkonnect_cti_wrapper .product_qkonnect_platform_card:has(img[src*="platform_value1"]),
.qkonnect_cti_wrapper .product_qkonnect_platform_card:has(img[src*="platform_value5"]),
.qkonnect_cti_wrapper .product_qkonnect_platform_card:has(img[src*="qgold_icon_rv_5"]) {
    --qk-c: #C78A4E;
    --qp-a1: #C78A4E;
    --qp-a2: #C78A4E;
    --qp-tint: rgba(199, 138, 78, 0.45);
    --qp-glow: rgba(199, 138, 78, 0.16);
}

.qkonnect_cti_wrapper .product_qkonnect_platform_card:has(img[src*="platform_value2"]),
.qkonnect_cti_wrapper .product_qkonnect_platform_card:has(img[src*="platform_value6"]),
.qkonnect_cti_wrapper .product_qkonnect_platform_card:has(img[src*="platform_value7"]),
.qkonnect_cti_wrapper .product_qkonnect_platform_card:has(img[src*="strategicheadingLogo"]) {
    --qk-c: #E07394;
    --qp-a1: #E07394;
    --qp-a2: #E07394;
    --qp-tint: rgba(224, 115, 148, 0.45);
    --qp-glow: rgba(224, 115, 148, 0.16);
}

.qkonnect_cti_wrapper .product_qkonnect_platform_card:has(img[src*="platform_value3"]),
.qkonnect_cti_wrapper .product_qkonnect_platform_card:has(img[src*="platform_value4"]) {
    --qk-c: #C878C9;
    --qp-a1: #C878C9;
    --qp-a2: #C878C9;
    --qp-tint: rgba(200, 120, 201, 0.45);
    --qp-glow: rgba(200, 120, 201, 0.16);
}

/* geometry follows colour */
.qkonnect_cti_wrapper .product_qkonnect_platform_card:has(img[src*="platform_value2"])::before,
.qkonnect_cti_wrapper .product_qkonnect_platform_card:has(img[src*="platform_value6"])::before,
.qkonnect_cti_wrapper .product_qkonnect_platform_card:has(img[src*="platform_value7"])::before,
.qkonnect_cti_wrapper .product_qkonnect_platform_card:has(img[src*="strategicheadingLogo"])::before {
    background-image: repeating-linear-gradient(48deg, var(--qk-c) 0 2px, transparent 2px 11px);
    background-size: auto;
}

.qkonnect_cti_wrapper .product_qkonnect_platform_card:has(img[src*="platform_value3"])::before,
.qkonnect_cti_wrapper .product_qkonnect_platform_card:has(img[src*="platform_value4"])::before {
    background-image: repeating-radial-gradient(circle at 118% 118%, var(--qk-c) 0 2px, transparent 2px 17px);
    background-size: auto;
}

/* --- icon ---------------------------------------------------------------- */

.qkonnect_cti_wrapper .product_qkonnect_platform_values_section .product_qkonnect_platform_cards_container .product_qkonnect_platform_card img {
    position: relative;
    z-index: 1;
    display: block;
    border-radius: 50%;
    transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.4s ease;
}

.qkonnect_cti_wrapper .product_qkonnect_platform_values_section .product_qkonnect_platform_cards_container .product_qkonnect_platform_card:hover img {
    transform: scale(1.08) rotate(-3deg);
    box-shadow: 0 0 0 7px var(--qp-glow);
}

/* --- heading and copy ---------------------------------------------------- */

.qkonnect_cti_wrapper .product_qkonnect_platform_values_section .product_qkonnect_platform_cards_container .product_qkonnect_platform_card h5 {
    position: relative;
    z-index: 1;
    display: inline-block;
    margin: 14px 0 14px;
    padding-bottom: 10px;
    font-size: clamp(16px, 1.35vw, 19px);
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--qp-text);
}

.qkonnect_cti_wrapper .product_qkonnect_platform_card h5::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 34px;
    height: 2px;
    border-radius: 2px;
    background-color: var(--qk-c);
    opacity: 0.7;
    transition: width 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.qkonnect_cti_wrapper .product_qkonnect_platform_card:hover h5::after {
    width: 100%;
}

.qkonnect_cti_wrapper .product_qkonnect_platform_values_section .product_qkonnect_platform_cards_container .product_qkonnect_platform_card p {
    position: relative;
    z-index: 1;
    margin: 0;
    font-size: clamp(13.5px, 1.08vw, 15px);
    line-height: 1.7;
    color: var(--qp-dim);
}

/* --- hover, in the card's own colour, no glow ---------------------------- */

.qkonnect_cti_wrapper .product_qkonnect_platform_values_section .product_qkonnect_platform_cards_container .product_qkonnect_platform_card:hover {
    transform: translateY(-4px);
    border-color: var(--qk-c);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55);
}

/* ==========================================================================
   qkonnect section headings
   ==========================================================================

   Seven of them, all unclassed h1 elements inside a `*_heading` container,
   all left at legacy's 40px / weight 500 / no tracking. The rule beneath each
   one is set to 110% of the text, so it overhangs the last letter by a tenth
   of the heading's width -- which reads as a mistake rather than a flourish,
   and gets worse the longer the heading (the Approach heading overhangs by
   70px).

   Brought in line with the section headings on the other four product pages:
   the same responsive scale, a heavier weight, tightened tracking, and a rule
   that stops where the words do. The gradient itself is legacy's and stays.

   NOTE: an earlier pass of mine wrote these rules against
   `.product_qkonnect_section_heading`, a class that does not exist on this
   page. It matched nothing, so the headings were still entirely legacy until
   now. The containers below were read off the page rather than guessed.
   ========================================================================== */

.qkonnect_cti_wrapper .product_qkonnect_about_heading h1,
.qkonnect_cti_wrapper .product_qkonnect_approach_heading h1,
.qkonnect_cti_wrapper .product_why_qkonnect_heading h1,
.qkonnect_cti_wrapper .product_qkonnect_platform_heading h1,
.qkonnect_cti_wrapper .product_qkonnect_features_heading h1,
.qkonnect_cti_wrapper .product_qkonnect_work_heading h1,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_heading h1 {
    margin: 0;
    font-size: clamp(28px, 3.1vw, 44px);
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.02em;
    color: var(--qp-text);
}

/* the rule: the width of the words, not a tenth wider */
.qkonnect_cti_wrapper .product_qkonnect_about_heading h1::after,
.qkonnect_cti_wrapper .product_qkonnect_approach_heading h1::after,
.qkonnect_cti_wrapper .product_why_qkonnect_heading h1::after,
.qkonnect_cti_wrapper .product_qkonnect_platform_heading h1::after,
.qkonnect_cti_wrapper .product_qkonnect_features_heading h1::after,
.qkonnect_cti_wrapper .product_qkonnect_work_heading h1::after,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_heading h1::after {
    width: 100%;
    height: 3px;
    bottom: -10px;
    border-radius: 3px;
}

/* --- the secondary line --------------------------------------------------
   Some sections carry an h4 under the heading -- a sub-headline on About and
   Technology Enablers, a group label ("Calling") on Features. One treatment
   serves both: a clear second tier, well below the rule so it does not crowd
   it.
   ------------------------------------------------------------------------ */

.qkonnect_cti_wrapper .product_qkonnect_about_heading h4,
.qkonnect_cti_wrapper .product_qkonnect_approach_heading h4,
.qkonnect_cti_wrapper .product_why_qkonnect_heading h4,
.qkonnect_cti_wrapper .product_qkonnect_platform_heading h4,
.qkonnect_cti_wrapper .product_qkonnect_features_heading h4,
.qkonnect_cti_wrapper .product_qkonnect_work_heading h4,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_heading h4 {
    /* space below as well as above: the cards container follows straight
       after this block, and a Bootstrap row carries negative margins, so with
       no bottom margin the sub-headline sits flush against the first card row. */
    margin: 22px 0 20px;
    font-size: clamp(16px, 1.45vw, 21px);
    font-weight: 600;
    line-height: 1.4;
    letter-spacing: -0.01em;
    color: rgba(255, 255, 255, 0.78);
    background-color: transparent;
}

/* and any supporting paragraph in the same block */
.qkonnect_cti_wrapper .product_qkonnect_about_heading p,
.qkonnect_cti_wrapper .product_qkonnect_approach_heading p,
.qkonnect_cti_wrapper .product_why_qkonnect_heading p,
.qkonnect_cti_wrapper .product_qkonnect_platform_heading p,
.qkonnect_cti_wrapper .product_qkonnect_features_heading p,
.qkonnect_cti_wrapper .product_qkonnect_work_heading p,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_heading p {
    max-width: 74ch;
    margin: 14px 0 0;
    font-size: clamp(14px, 1.12vw, 16.5px);
    line-height: 1.7;
    color: var(--qp-dim);
    background-color: transparent;
}

/* The Features row carries a larger negative margin than the others, which
   ate half the gap below its sub-headline -- 10px against 20px elsewhere.
   This puts the two back level. */
.qkonnect_cti_wrapper .product_qkonnect_features_section .product_qkonnect_features_card_container {
    padding-top: 10px;
}

/* --- the rule draws itself in -------------------------------------------
   Matching the other four product pages: as the heading arrives, the rule
   runs out from the left rather than being there from the first frame. Gated
   on the reveal class, so with reduced motion it simply renders.
   ------------------------------------------------------------------------ */

.qp-anim .qkonnect_cti_wrapper .qp-reveal h1::after {
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform 0.75s cubic-bezier(0.22, 0.61, 0.36, 1) 0.15s;
}

.qp-anim .qkonnect_cti_wrapper .qp-reveal.is-in h1::after {
    transform: scaleX(1);
}

.qp-anim .qkonnect_cti_wrapper .qp-reveal.qp-now h1::after {
    transition: none;
}

/* ==========================================================================
   About
   ==========================================================================

   Rebuilt from the legacy page rather than from the .qfp version, on the same
   terms as the product pages: the structure legacy shipped is kept and the
   surfaces, type and motion are brought up to the system.

   The legacy structure was already sound in the way that matters -- the hero
   is text left and photograph right, and the picture cards ("What we do",
   "Why choose us") sit in their own sections, separate from the text cards
   ("Our unique value proposition"). Nothing here mixes them.

   Two card families:

     .uvp_card          text card with a coloured bar down the left edge, in
                        three colourways -- the same pattern qkonnect uses,
                        already inset in uvp.css exactly as we refined there
     .insights_card_*   picture card, title over the photograph, copy
                        revealed on hover

   The bar colours come from uvp.css and are legacy's: pink #e07394, yellow
   #C78A4E, purple #c188f0. Pink and yellow match qkonnect's exactly.
   ========================================================================== */

.rv_partners_wrapper {
    --qp-a1: #F89833;
    --qp-a2: #EA396E;
    --qp-tint: rgba(234, 57, 110, 0.38);
    --qp-glow: rgba(234, 57, 110, 0.15);
    --qp-aura: rgba(234, 57, 110, 0.18);

    --qp-surface: #141416;
    --qp-line: rgba(255, 255, 255, 0.09);
    --qp-text: #F5F5F7;
    --qp-dim: #A9A9B4;
}

/* --- hero ----------------------------------------------------------------
   A dark field with the copy on the left and the photograph held in a framed
   panel on the right, floating clear of the page rather than bleeding into
   it. Two things carry it: the field is near-black so the panel reads as lit,
   and a bloom in the brand pink sits behind the headline and again behind the
   panel, so the light in the composition has a source.

   The legacy banner paints a flat purple gradient across its whole width.
   That is what made the old hero look washed rather than dark, so it is
   replaced here -- same element, later in the cascade, no !important needed.

   The panel is deliberately independent of what is in it: a fixed aspect with
   `object-fit: cover`, so any photograph dropped into the markup fills it
   without stretching, whatever its own proportions are.

   Legacy addresses both halves of this hero one level deeper than these rules
   -- through .row -- and below 576px it zeroes the copy's padding and hides
   the photograph outright, because its own layout laid the copy over the
   picture. The phone rules at the foot match that depth to answer it.
   ------------------------------------------------------------------------ */

.rv_partners_wrapper .rv_about_us_banner {
    position: relative;
    /* edge to edge, whatever the wrapper's gutter is */
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    /* the header is fixed and this panel starts underneath it, so the
       clearance belongs here where it protects both columns */
    padding: clamp(116px, 12vh, 150px) 0 clamp(56px, 8vh, 96px);
    overflow: hidden;
    background-color: #08080B;
    background-image:
        /* the bloom behind the headline, a violet answering it, and a warm
           trace at the far side so the field is not lit from one point only */
        radial-gradient(60% 66% at 13% 0%, rgba(234, 57, 110, 0.38), transparent 62%),
        radial-gradient(42% 50% at 46% -8%, rgba(150, 86, 224, 0.22), transparent 66%),
        radial-gradient(44% 50% at 92% 8%, rgba(248, 152, 51, 0.11), transparent 68%),
        radial-gradient(72% 62% at 64% 112%, rgba(118, 74, 196, 0.14), transparent 72%);
}

/* a hairline of light along the top edge, under the header */
.rv_partners_wrapper .rv_about_us_banner::before {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    left: 0;
    z-index: 1;
    height: 1px;
    pointer-events: none;
    background-image: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.16) 22%, rgba(234, 57, 110, 0.45) 48%, rgba(255, 255, 255, 0.1) 72%, transparent);
}

/* a fade at the foot so the panel hands off to the first section */
.rv_partners_wrapper .rv_about_us_banner::after {
    content: "";
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 1;
    height: 26%;
    pointer-events: none;
    background-image: linear-gradient(to top, #000000 0%, rgba(0, 0, 0, 0) 100%);
}

/* Legacy pins this row with position:absolute at the bottom of the banner, so
   it shrinks to its content rather than filling it. Putting it back in flow is
   what lets the two columns actually split the width. */
.rv_partners_wrapper .rv_about_us_banner > .row {
    position: static;
    width: 100%;
    align-items: center;
    margin: 0;
    padding: 0;
    min-height: min(66vh, 560px);
}

.rv_partners_wrapper .rv_about_us_banner > .row > [class*="col-"] {
    padding: 0;
}

/* --- copy, on the left --------------------------------------------------- */

.rv_partners_wrapper .rv_about_us_banner .rv_about_us_banner_heading {
    position: relative;
    z-index: 3;
    display: flex;
    flex-direction: column;
    justify-content: center;
    height: 100%;
    /* left edge on the same 4% gutter the sections below use; the banner
       owns the vertical space now */
    padding: 0 clamp(20px, 2.4vw, 44px) 0 4vw;
}

.rv_partners_wrapper .rv_about_us_banner .rv_about_us_banner_heading h1 {
    margin: 0;
    font-size: clamp(38px, 5vw, 72px);
    font-weight: 800;
    line-height: 1.04;
    letter-spacing: -0.035em;
    color: #FFFFFF;
}

/* The h1 shrinks to its words, so 100% is the width of the phrase itself,
   not of the column. Legacy runs the bar to 110% and overshoots the last
   letter; this stops on it. */
.rv_partners_wrapper .rv_about_us_banner .rv_about_us_banner_heading h1::after {
    width: 100%;
    max-width: none;
    height: 3px;
    border-radius: 3px;
}

.rv_partners_wrapper .rv_about_us_banner .rv_about_us_banner_heading p {
    max-width: 56ch;
    margin: clamp(22px, 2.8vh, 34px) 0 0;
    font-size: clamp(14.5px, 1.05vw, 16.5px);
    line-height: 1.8;
    color: rgba(255, 255, 255, 0.64);
}

/* --- the framed panel, on the right -------------------------------------- */

.rv_partners_wrapper .rv_about_us_banner .rv_about_us_banner_heading_image {
    position: relative;
    z-index: 2;
    /* the same 4vw gutter the copy sits on, so the frame closes on every
       side -- bleeding it off the edge cut the right corners away */
    width: auto;
    height: clamp(300px, 33vw, 470px);
    min-height: 0;
    margin: 0 4vw 0 clamp(12px, 2vw, 40px);
    padding: 0;
    border-radius: 26px;
    box-shadow: 0 44px 96px rgba(0, 0, 0, 0.62);
}

/* the bloom the panel sits in */
.rv_partners_wrapper .rv_about_us_banner .rv_about_us_banner_heading_image::after {
    content: "";
    position: absolute;
    inset: -16% -12%;
    z-index: 0;
    pointer-events: none;
    background-image: radial-gradient(58% 58% at 46% 50%, rgba(234, 57, 110, 0.34), transparent 70%);
    filter: blur(26px);
}

.rv_partners_wrapper .rv_about_us_banner .rv_about_us_banner_heading_image img {
    position: absolute;
    inset: 0;
    z-index: 1;
    width: 100%;
    height: 100%;
    max-width: none;
    margin: 0;
    object-fit: cover;
    object-position: center;
    border-radius: inherit;
}

/* the frame: a 1px ring, masked so only the border paints */
.rv_partners_wrapper .rv_about_us_banner .rv_about_us_banner_heading_image::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    padding: 1px;
    border-radius: inherit;
    pointer-events: none;
    background-image: linear-gradient(150deg, rgba(255, 255, 255, 0.30), rgba(255, 255, 255, 0.06) 46%, rgba(234, 57, 110, 0.36) 100%);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask-composite: exclude;
}

/* The hero is above the fold, so this is a plain load-time animation with no
   observer to wait on -- the reveal script deliberately never touches the
   banner. The whole block sits inside a reduced-motion guard: when motion is
   not wanted these rules do not exist and the hero simply renders. */
@media (prefers-reduced-motion: no-preference) {
    @keyframes qp-about-panel {
        from { opacity: 0; translate: 0 24px; scale: 0.975; }
        to { opacity: 1; translate: 0 0; scale: 1; }
    }

    .rv_partners_wrapper .rv_about_us_banner .rv_about_us_banner_heading h1,
    .rv_partners_wrapper .rv_about_us_banner .rv_about_us_banner_heading p {
        animation: qp-hero-rise 0.62s cubic-bezier(0.22, 0.61, 0.36, 1) both;
    }

    .rv_partners_wrapper .rv_about_us_banner .rv_about_us_banner_heading h1 { animation-delay: 0.06s; }
    .rv_partners_wrapper .rv_about_us_banner .rv_about_us_banner_heading p { animation-delay: 0.16s; }

    .rv_partners_wrapper .rv_about_us_banner .rv_about_us_banner_heading_image {
        animation: qp-about-panel 0.85s cubic-bezier(0.22, 0.61, 0.36, 1) 0.12s both;
    }
}

/* Phones stack the two. Below 576px legacy sets the copy to padding:0 and
   hides the photograph outright, both one level deeper than the rules above,
   so these match that depth. */
@media (max-width: 767.98px) {
    .rv_partners_wrapper .rv_about_us_banner {
        /* the header is fixed, so the copy starts below it; the panel's
           own margin closes the foot, so nothing is needed there */
        padding-top: var(--qp-headerh, 92px);
        padding-bottom: 0;
    }

    .rv_partners_wrapper .rv_about_us_banner > .row {
        min-height: 0;
    }

    .rv_partners_wrapper .rv_about_us_banner .row .rv_about_us_banner_heading {
        padding: clamp(28px, 6vw, 44px) 5% clamp(26px, 5vw, 38px) 4vw;
    }

    .rv_partners_wrapper .rv_about_us_banner .row .rv_about_us_banner_heading p {
        margin-top: clamp(24px, 5vw, 34px);
    }

    .rv_partners_wrapper .rv_about_us_banner .row .rv_about_us_banner_heading_image {
        display: block;
        width: auto;
        height: clamp(210px, 52vw, 280px);
        /* a gutter each side, so the frame reads as a frame */
        margin: 0 4vw clamp(40px, 9vw, 64px);
        border-radius: 20px;
        box-shadow: 0 26px 58px rgba(0, 0, 0, 0.6);
    }
}

/* --- section headings ---------------------------------------------------- */

.rv_partners_wrapper .insights_rv_heading h1 {
    margin: 0;
    font-size: clamp(28px, 3.1vw, 44px);
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.02em;
    color: var(--qp-text);
}

.rv_partners_wrapper .insights_rv_heading h1::after {
    width: 100%;
    height: 3px;
    bottom: -10px;
    border-radius: 3px;
}

/* --- the value proposition cards ----------------------------------------
   uvp.css already draws the bar inset from the corners, which is the shape we
   arrived at on qkonnect. What it does not do is carry the colour any further
   than the bar, so all nine cards are otherwise identical. Each one now takes
   its own colour through the heading, the corner texture and the hover.
   ------------------------------------------------------------------------ */

.rv_partners_wrapper .uvp_card {
    --qk-c: var(--qp-a2);
    position: relative;
    height: 100%;
    padding: clamp(22px, 1.9vw, 28px);
    border: 1px solid var(--qp-line);
    border-radius: 16px;
    background: var(--qp-surface);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
    transition: transform 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
}

.rv_partners_wrapper .uvp_card.quality { --qk-c: #E07394; }
.rv_partners_wrapper .uvp_card.excellence { --qk-c: #C78A4E; }
.rv_partners_wrapper .uvp_card.focus { --qk-c: #C188F0; }

.rv_partners_wrapper .uvp_card:hover {
    transform: translateY(-4px);
    border-color: var(--qk-c);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55);
}

/* corner texture, in the card's own colour; ::before is legacy's bar */
.rv_partners_wrapper .uvp_card::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    border-radius: inherit;
    pointer-events: none;
    opacity: 0.4;
    transition: opacity 0.4s ease;
    -webkit-mask-image: radial-gradient(92% 92% at 112% 112%, #000 0%, rgba(0, 0, 0, 0.45) 42%, transparent 70%);
    mask-image: radial-gradient(92% 92% at 112% 112%, #000 0%, rgba(0, 0, 0, 0.45) 42%, transparent 70%);
    background-image: radial-gradient(circle at center, var(--qk-c) 1.7px, transparent 2px);
    background-size: 14px 14px;
}

.rv_partners_wrapper .uvp_card.excellence::after {
    background-image: repeating-linear-gradient(48deg, var(--qk-c) 0 2px, transparent 2px 11px);
    background-size: auto;
}

.rv_partners_wrapper .uvp_card.focus::after {
    background-image: repeating-radial-gradient(circle at 118% 118%, var(--qk-c) 0 2px, transparent 2px 17px);
    background-size: auto;
}

.rv_partners_wrapper .uvp_card:hover::after {
    opacity: 0.58;
}

.rv_partners_wrapper .uvp_card h3 {
    position: relative;
    z-index: 1;
    display: inline-block;
    margin: 0 0 14px;
    padding-bottom: 10px;
    font-size: clamp(17px, 1.45vw, 21px);
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--qk-c);
}

.rv_partners_wrapper .uvp_card h3::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 34px;
    height: 2px;
    border-radius: 2px;
    background-color: var(--qk-c);
    opacity: 0.6;
    transition: width 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.rv_partners_wrapper .uvp_card:hover h3::after {
    width: 100%;
}

.rv_partners_wrapper .uvp_card ul,
.rv_partners_wrapper .uvp_card li,
.rv_partners_wrapper .uvp_card p {
    position: relative;
    z-index: 1;
    background-color: transparent;
}

.rv_partners_wrapper .uvp_card li {
    font-size: clamp(13.5px, 1.08vw, 15px);
    line-height: 1.7;
    color: var(--qp-dim);
}



/* --- the picture cards ---------------------------------------------------
   Brought to the homepage card exactly: same proportions, same 20px radius,
   same lit edge, same travelling highlight, and the same hover -- artwork
   scales and blurs back, the title drops away, the copy rises over a black
   and pink wash.

   The homepage builds its edge from two elements, an outer .qfc-card holding
   a 1px gradient around an inner .qfc-card-in that clips. Here there is only
   the one box, so the edge is a masked ::before instead -- the same technique
   qbot's use-case cards use. The highlight, which the homepage gives its own
   .qfc-card-shine, becomes ::after; the card already clips its overflow, so
   the band is contained without extra markup. All four pseudo slots on these
   four parts were confirmed free before being used.

   Legacy already gets a good deal of this right -- the absolute title at the
   bottom, the arrow, the rise of the overlay -- and all of that is kept. Two
   of its declarations are !important and have to be answered in kind: the
   title's own scrim, which is replaced by the homepage's taller one on the
   image so every card darkens over the same distance whether its title runs
   to one line or two, and the overlay's transparent background, which is
   where the wash goes.
   ------------------------------------------------------------------------ */

.rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover {
    /* the homepage's accent and its pre-mixed tints */
    --c: #EA396E;
    --ct: rgba(234, 57, 110, 0.18);
    --cs: rgba(234, 57, 110, 0.42);

    position: relative;
    /* legacy pins this at 235px with !important, so the clamp needs one to
       reach the homepage proportion at wide viewports */
    height: clamp(230px, 17.5vw, 278px) !important;
    overflow: hidden;
    border-radius: 20px;
    box-shadow: none;
    transition: transform 0.4s ease, box-shadow 0.4s ease;
}

.rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover:hover {
    transform: translateY(-6px);
    box-shadow: 0 22px 56px rgba(0, 0, 0, 0.55), 0 0 42px var(--ct);
}

/* the lit edge: a 1px gradient ring, masked so only the border paints */
.rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 5;
    padding: 1px;
    border-radius: inherit;
    pointer-events: none;
    background-image: linear-gradient(160deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.05) 55%, rgba(255, 255, 255, 0.03) 100%);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask-composite: exclude;
    transition: background-image 0.4s ease;
}

.rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover:hover::before {
    background-image: linear-gradient(160deg, var(--cs), rgba(255, 255, 255, 0.14) 55%, rgba(255, 255, 255, 0.05) 100%);
}

/* the highlight sweeping across on hover */
.rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover::after {
    content: "";
    position: absolute;
    top: -60%;
    left: -80%;
    z-index: 6;
    width: 42%;
    height: 220%;
    pointer-events: none;
    transform: rotate(18deg) translateX(0);
    background-image: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.16) 50%, rgba(255, 255, 255, 0) 100%);
    transition: transform 0.85s ease;
}

.rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover:hover::after {
    transform: rotate(18deg) translateX(380%);
}

/* --- the photograph --- */

.rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover .insights_card_img::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background-image: linear-gradient(180deg, rgba(0, 0, 0, 0) 35%, rgba(0, 0, 0, 0.72) 100%);
}

.rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover .insights_card_img img {
    border-radius: 0;
    transition: transform 0.6s ease, filter 0.5s ease;
}

.rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover:hover .insights_card_img img {
    transform: scale(1.08);
    filter: brightness(0.4) blur(2px);
}

/* --- the title, which steps aside for the copy --- */

.rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover .insights_card_title {
    padding: 26px 96px 24px 24px;
    /* the scrim moves to the image above, so it is the same on every card */
    background-image: none !important;
}

.rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover .insights_card_title h5 {
    font-size: clamp(17px, 1.5vw, 21px);
    font-weight: 700;
    line-height: 1.3;
    text-shadow: 0 2px 12px rgba(0, 0, 0, 0.5);
}

/* --- the copy, rising on hover --- */

.rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover .insights_card_overlay {
    align-items: flex-end;
    justify-content: flex-start;
    /* the right inset keeps the copy clear of the arrow */
    padding: 24px 92px 24px 24px;
    background-image:
        linear-gradient(0deg, rgba(0, 0, 0, 0.9) 0%, rgba(0, 0, 0, 0.7) 55%, rgba(0, 0, 0, 0.3) 100%),
        linear-gradient(155deg, var(--cs), rgba(0, 0, 0, 0) 72%) !important;
}

.rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover .insights_card_overlay p {
    font-size: 13.5px;
    line-height: 1.62;
    color: #EDEDF1;
}

/* --- the arrow --- */

.rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover .insights_card_arrow {
    right: 20px;
    bottom: 20px;
    z-index: 7;
    width: 36px;
    height: 36px;
    border: 1px solid rgba(255, 255, 255, 0.3);
    background-color: rgba(12, 12, 16, 0.5);
    transition: transform 0.3s ease, background-color 0.3s ease, border-color 0.3s ease;
}

.rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover .insights_card_arrow svg {
    width: 18px;
    height: 18px;
    fill: #FFFFFF;
    transition: fill 0.3s ease;
}

.rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover:hover .insights_card_arrow {
    transform: translateX(5px);
    border-color: var(--c);
    background-color: var(--c);
}

.rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover:hover .insights_card_arrow svg {
    fill: #0C0C10;
}

/* Legacy holds three across at the md breakpoint, which leaves each card
   about 220px wide -- narrower than the hover copy can be set in, so it
   clipped on eight of the twelve. Two across through that band. */
@media (min-width: 768px) and (max-width: 991.98px) {
    .rv_partners_wrapper .insights_rv_container .insights_cards_container .row > [class*="col-"] {
        flex: 0 0 50%;
        max-width: 50%;
    }
}

/* Touch devices never get :hover, so the copy would be unreachable. Unstack
   the card there and show everything at once -- exactly as the homepage does.
   The card's own ::before and ::after are left alone: the edge is static, and
   the highlight only ever moves on a hover that cannot happen here. */
@media (hover: none) {
    .rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover {
        height: auto !important;
    }

    .rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover .insights_card_img {
        position: relative;
        aspect-ratio: 16 / 9;
    }

    .rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover .insights_card_img::after {
        display: none;
    }

    .rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover .insights_card_title {
        position: static;
        padding: 20px 20px 0;
    }

    .rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover .insights_card_overlay {
        position: static;
        /* the arrow sits below the copy here, not beside it */
        padding: 10px 20px 68px;
        background-image: none !important;
        opacity: 1;
        transform: none;
    }

    .rv_partners_wrapper .insights_rv_container .insights_cards_container .insights_card_hover .insights_card_arrow {
        top: auto;
        right: 16px;
        bottom: 16px;
    }
}

/* ==========================================================================
   Who we are  --  out-do-out-shine, csr
   ==========================================================================

   The third and fourth pages of the "Who we are" menu, after about.html. Both
   are built on the same `odos_` vocabulary and share a stylesheet section for
   that reason: every card family below appears on at least one of them, and
   the brand pillar cards appear on both.

   Scoped to .odos_wrapper. contactus.html uses that wrapper too, but it does
   not load this sheet, so nothing here can reach it.

   The heroes are deliberately NOT given about.html's framed panel. Both
   banner images are transparent cut-outs -- people on no background, a light
   bulb and seedlings on no background -- so a frame would box in a shape that
   has no edges, and `object-fit: cover` would crop the subject. What those
   heroes actually needed was the flat purple wash behind them replaced with
   the dark field the rest of the revamp uses. The cut-out stays exactly as
   legacy places it, standing on the foot of the panel.

   Card families and where they land:

     .odos_mission_cards       ×2   odos    accent card, icon + heading + copy
     .odos_brand_piller_cards  ×3   both   accent card, icon + heading + list
     .odos_principles_cards    ×6   odos    gradient-ring card, heading + copy
     .rv_csr_programes_cards   ×3   csr    picture card, photo above content

   The brand pillar icons are circular coloured badges with the colour baked
   into the artwork -- yellow, pink, purple -- and the markup names the same
   three colours inline on each heading's span. So the cards are not given a
   tile behind the icon (that would badge a badge, the qgold problem); they
   take their accent from the badge instead, and the card, its rule, its
   texture and its hover all follow that one colour.

   The principles cards already have the two-element shape the homepage card
   uses -- an outer box holding a gradient and an inner box clipping it -- so
   the ring here is the real thing rather than a masked pseudo.
   ========================================================================== */

.odos_wrapper {
    --qp-a1: #F89833;
    --qp-a2: #EA396E;
    --qp-line: rgba(255, 255, 255, 0.09);
    --qp-surface: #141416;
    --qp-text: #F5F5F7;
    --qp-dim: #A9A9B4;

    /* the three-colour family the pillar badges are drawn in */
    --ok-yellow: #C78A4E;
    --ok-pink: #E07394;
    --ok-purple: #C878C9;
}

/* --- hero ----------------------------------------------------------------
   Legacy bleeds this with `width: 108%; margin-left: -4%`, which overshoots
   and leaves the section wider than the viewport. Full-bleed properly, then
   replace the wash with the dark field and its blooms.
   ------------------------------------------------------------------------ */

.odos_wrapper .odos_banner_section {
    position: relative;
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    /* the header is fixed and this section starts underneath it */
    padding: clamp(112px, 12vh, 146px) 0 0;
    overflow: hidden;
    background-color: #08080B;
    background-image:
        radial-gradient(58% 64% at 14% 0%, rgba(234, 57, 110, 0.34), transparent 62%),
        radial-gradient(42% 50% at 48% -8%, rgba(150, 86, 224, 0.20), transparent 66%),
        radial-gradient(46% 52% at 90% 10%, rgba(248, 152, 51, 0.10), transparent 68%),
        radial-gradient(72% 62% at 66% 112%, rgba(118, 74, 196, 0.13), transparent 72%);
}

/* a hairline of light along the top edge, under the header */
.odos_wrapper .odos_banner_section::before {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    left: 0;
    z-index: 3;
    height: 1px;
    pointer-events: none;
    background-image: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.16) 22%, rgba(234, 57, 110, 0.45) 48%, rgba(255, 255, 255, 0.1) 72%, transparent);
}

/* a fade at the foot so the hero hands off to the first section */
.odos_wrapper .odos_banner_section::after {
    content: "";
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 2;
    height: 22%;
    pointer-events: none;
    background-image: linear-gradient(to top, #000000 0%, rgba(0, 0, 0, 0) 100%);
}

.odos_wrapper .odos_banner_section > .row {
    align-items: stretch;
    margin: 0;
    min-height: min(62vh, 540px);
}

.odos_wrapper .odos_banner_section > .row > [class*="col-"] {
    padding: 0;
}

/* --- hero copy --- */

.odos_wrapper .odos_banner_section .odos_heading {
    position: relative;
    z-index: 2;
    display: flex;
    flex-direction: column;
    justify-content: center;
    /* Legacy sets align-items:center here. On its row that read as vertical
       centring; as a column it centres horizontally instead, which pushed the
       odos headline off the gutter while csr -- which overrides it -- stayed
       put. Both pages start on the same edge now. */
    align-items: flex-start;
    height: 100%;
    /* left edge on the same 4% gutter the sections below use */
    padding: clamp(24px, 4vh, 48px) clamp(20px, 2.4vw, 44px) clamp(40px, 6vh, 72px) 4vw;
}

.odos_wrapper .odos_banner_section .odos_heading h1 {
    margin: 0;
    font-size: clamp(34px, 4.2vw, 60px);
    font-weight: 800;
    line-height: 1.06;
    letter-spacing: -0.032em;
    color: #FFFFFF;
}

/* The h1 already shrinks to its words, so 100% is the width of the phrase.
   Legacy runs the bar to 110% and overshoots the last letter. */
.odos_wrapper .odos_banner_section .odos_heading h1::after {
    width: 100%;
    height: 3px;
    bottom: -14px;
    border-radius: 3px;
}

.odos_wrapper .odos_banner_section .odos_heading p {
    max-width: 54ch;
    padding-top: clamp(26px, 3.2vh, 38px);
    font-size: clamp(14px, 1.02vw, 16px);
    line-height: 1.78;
    color: rgba(255, 255, 255, 0.64);
}

/* "Corporate Social Responsibility" wraps to two lines, and a shrink-to-fit
   box does not re-measure after wrapping -- it stays as wide as the space it
   was offered, so the bar ran 82px past the last letter. Capping the measure
   in em makes the box track the longest line at every size, because the text
   scales with the same font. */
.odos_wrapper .odos_banner_section .csr_heading h1 {
    max-width: 7.2em;
}

/* csr sets this to align-items:end, which fights the flex column above */
.odos_wrapper .odos_banner_section .csr_heading {
    align-items: flex-start;
    padding-bottom: clamp(40px, 6vh, 72px);
}

/* --- hero artwork: a cut-out, so it stands rather than fills -------------- */

.odos_wrapper .odos_banner_section .odos_img {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    height: 100%;
    min-height: 0;
    padding: 0 clamp(12px, 2vw, 36px) 0 0;
}

/* a bloom under the cut-out so it is lit from behind rather than pasted on */
.odos_wrapper .odos_banner_section .odos_img::before {
    content: "";
    position: absolute;
    inset: 12% 4% -6%;
    z-index: 0;
    pointer-events: none;
    background-image: radial-gradient(52% 54% at 50% 62%, rgba(234, 57, 110, 0.26), transparent 72%);
    filter: blur(30px);
}

.odos_wrapper .odos_banner_section .odos_img img {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 100%;
    height: auto;
    max-height: min(56vh, 480px);
    margin: 0;
    object-fit: contain;
    object-position: bottom center;
    border-radius: 0;
    filter: drop-shadow(0 26px 50px rgba(0, 0, 0, 0.55));
}

/* --- section headings ----------------------------------------------------
   Five places carry the same legacy heading: 44px at weight 400 with a bar at
   110%. One rule brings them all to the system's heading and stops the bar on
   the last letter.
   ------------------------------------------------------------------------ */

.odos_wrapper .purpose_section .odos_purpose_container .odos_purpose_content h2,
.odos_wrapper .purpose_section .odos_purpose_container .odos_purpose_image_container .odos_purpose_description h3,
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_heading h2,
.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_heading h2,
.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_image_container .odos_principle_image_description h2 {
    font-size: clamp(28px, 3.1vw, 44px);
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.02em;
    color: var(--qp-text);
}

.odos_wrapper .purpose_section .odos_purpose_container .odos_purpose_content h2::after,
.odos_wrapper .purpose_section .odos_purpose_container .odos_purpose_image_container .odos_purpose_description h3::after,
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_heading h2::after,
.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_heading h2::after,
.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_image_container .odos_principle_image_description h2::after {
    width: 100%;
    height: 3px;
    bottom: -12px;
    border-radius: 3px;
}

.odos_wrapper .purpose_section .odos_purpose_container .odos_purpose_content p,
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_heading p,
.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_heading p {
    max-width: 92ch;
    padding-top: 26px;
    font-size: clamp(14px, 1.02vw, 16px);
    line-height: 1.8;
    color: var(--qp-dim);
}

/* --- the accent card -----------------------------------------------------
   Mission cards and brand pillar cards are the same object with a different
   payload, so they take the same treatment and differ only in accent.
   ------------------------------------------------------------------------ */

.odos_wrapper .purpose_section .odos_purpose_container .odos_mission_cards_container .odos_mission_cards,
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards {
    --ok-c: var(--qp-a2);
    position: relative;
    padding: clamp(22px, 1.9vw, 28px);
    border: 1px solid var(--qp-line);
    border-radius: 16px;
    background: var(--qp-surface);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
    transition: transform 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
}

/* the badges are drawn in these three colours, in this order, on both pages */
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .col-lg-4:nth-child(1) .odos_brand_piller_cards { --ok-c: var(--ok-yellow); }
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .col-lg-4:nth-child(2) .odos_brand_piller_cards { --ok-c: var(--ok-pink); }
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .col-lg-4:nth-child(3) .odos_brand_piller_cards { --ok-c: var(--ok-purple); }

.odos_wrapper .purpose_section .odos_purpose_container .odos_mission_cards_container .col-lg-6:nth-child(1) .odos_mission_cards { --ok-c: var(--ok-pink); }
.odos_wrapper .purpose_section .odos_purpose_container .odos_mission_cards_container .col-lg-6:nth-child(2) .odos_mission_cards { --ok-c: var(--ok-purple); }

.odos_wrapper .purpose_section .odos_purpose_container .odos_mission_cards_container .odos_mission_cards:hover,
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards:hover {
    transform: translateY(-4px);
    border-color: var(--ok-c);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55);
}

/* corner texture in the card's own colour */
.odos_wrapper .purpose_section .odos_purpose_container .odos_mission_cards_container .odos_mission_cards::after,
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    border-radius: inherit;
    pointer-events: none;
    opacity: 0.4;
    transition: opacity 0.4s ease;
    -webkit-mask-image: radial-gradient(92% 92% at 112% 112%, #000 0%, rgba(0, 0, 0, 0.45) 42%, transparent 70%);
    mask-image: radial-gradient(92% 92% at 112% 112%, #000 0%, rgba(0, 0, 0, 0.45) 42%, transparent 70%);
    background-image: radial-gradient(circle at center, var(--ok-c) 1.7px, transparent 2px);
    background-size: 14px 14px;
}

.odos_wrapper .purpose_section .odos_purpose_container .odos_mission_cards_container .odos_mission_cards:hover::after,
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards:hover::after {
    opacity: 0.58;
}

/* The icon is already a coloured badge, so it is bounded, not tiled -- the
   card would otherwise put a second badge behind the first. */
.odos_wrapper .purpose_section .odos_purpose_container .odos_mission_cards_container .odos_mission_cards img,
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards img {
    position: relative;
    z-index: 1;
    display: block;
    width: auto;
    height: auto;
    max-width: 56px;
    max-height: 56px;
    object-fit: contain;
    border-radius: 0;
}

.odos_wrapper .purpose_section .odos_purpose_container .odos_mission_cards_container .odos_mission_cards h5,
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards h3 {
    position: relative;
    z-index: 1;
    display: inline-block;
    margin: 18px 0 0;
    padding: 0 0 10px;
    font-size: clamp(17px, 1.45vw, 21px);
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--ok-c);
}

.odos_wrapper .purpose_section .odos_purpose_container .odos_mission_cards_container .odos_mission_cards h5::after,
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards h3::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 34px;
    height: 2px;
    border-radius: 2px;
    background-color: var(--ok-c);
    opacity: 0.6;
    transition: width 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.odos_wrapper .purpose_section .odos_purpose_container .odos_mission_cards_container .odos_mission_cards:hover h5::after,
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards:hover h3::after {
    width: 100%;
}

/* the markup colours the second half of each pillar heading inline; the whole
   heading is already the card's colour, so the span stops fighting it */
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards h3 span {
    color: inherit;
}

.odos_wrapper .purpose_section .odos_purpose_container .odos_mission_cards_container .odos_mission_cards p,
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards p,
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards ul,
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards ul li {
    position: relative;
    z-index: 1;
    font-size: clamp(13.5px, 1.08vw, 15px);
    line-height: 1.7;
    color: var(--qp-dim);
}

.odos_wrapper .purpose_section .odos_purpose_container .odos_mission_cards_container .odos_mission_cards p,
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards p {
    padding-top: 14px;
}

.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards ul {
    margin: 14px 0 0;
    padding-left: 18px;
}

.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards ul li::marker {
    color: var(--ok-c);
}

/* --- the principles cards ------------------------------------------------
   Legacy's own design, kept: a hairline ring running silver to black on a
   299.85deg diagonal, wrapped around a pure black card with white type. That
   monochrome treatment is the point of the section -- six equal principles,
   none of them shouting over the others -- so it does not take the coloured
   accent the pillar and mission cards carry.

   What it gains is depth rather than colour. The ring is the same gradient on
   the same axis, only thick enough to actually paint; a sheen inside the card
   follows that axis so the light in the ring continues across the face; and
   on hover the whole thing lifts while the ring runs up to white, as though
   the card had turned into the light.
   ------------------------------------------------------------------------ */

.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_cards_container .odos_principles_cards {
    /* legacy asks for 0.5px, which a whole-pixel display renders unevenly --
       some edges paint, some do not */
    padding: 1px;
    border-radius: 12px;
    background-image: linear-gradient(299.85deg, #ACAAAA -14.19%, #000000 109.56%);
    transition: transform 0.4s ease, box-shadow 0.4s ease, background-image 0.45s ease;
}

.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_cards_container .odos_principles_cards:hover {
    transform: translateY(-6px);
    background-image: linear-gradient(299.85deg, #FFFFFF -14.19%, #8A8A90 34%, #000000 109.56%);
    box-shadow: 0 22px 52px rgba(0, 0, 0, 0.62);
}

.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_cards_container .odos_principles_cards .odos_gradient_border_cards {
    position: relative;
    overflow: hidden;
    padding: clamp(22px, 1.9vw, 28px);
    /* one pixel inside the ring, so the corner curves stay concentric */
    border-radius: 11px;
    background: #000000;
}

/* the sheen, on the same diagonal as the ring */
.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_cards_container .odos_principles_cards .odos_gradient_border_cards::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    opacity: 0.85;
    transition: opacity 0.45s ease;
    background-image: linear-gradient(299.85deg, rgba(255, 255, 255, 0.09) -14.19%, rgba(255, 255, 255, 0.02) 38%, rgba(255, 255, 255, 0) 72%);
}

.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_cards_container .odos_principles_cards:hover .odos_gradient_border_cards::before {
    opacity: 1;
}

.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_cards_container .odos_principles_cards .odos_gradient_border_cards h4 {
    position: relative;
    z-index: 1;
    display: inline-block;
    margin: 0 0 12px;
    padding-bottom: 10px;
    font-size: clamp(17px, 1.45vw, 21px);
    font-weight: 700;
    letter-spacing: -0.01em;
    color: #FFFFFF;
}

/* a short rule in the same silver as the ring, drawn out on hover */
.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_cards_container .odos_principles_cards .odos_gradient_border_cards h4::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 34px;
    height: 2px;
    border-radius: 2px;
    background-image: linear-gradient(to right, #FFFFFF, rgba(172, 170, 170, 0));
    opacity: 0.55;
    transition: width 0.45s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.45s ease;
}

.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_cards_container .odos_principles_cards:hover .odos_gradient_border_cards h4::after {
    width: 100%;
    opacity: 0.9;
}

.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_cards_container .odos_principles_cards .odos_gradient_border_cards p {
    position: relative;
    z-index: 1;
    margin: 0;
    font-size: clamp(13.5px, 1.08vw, 15px);
    line-height: 1.7;
    /* legacy sets pure white for both heading and body; holding the body a
       little back is what separates them */
    color: rgba(255, 255, 255, 0.72);
}

/* --- the csr cards ------------------------------------------------------
   Legacy's own card, kept, on both families this page carries: the charcoal
   to black diagonal on a 288.81deg axis, legacy's radii, and white type. No
   coloured accent -- the icons are already yellow, pink and purple, and the
   page reads calmer when the cards themselves stay out of the way.

   The enhancement is the hairline ring, which runs up to white on hover,
   and the lift that goes with it. Nothing else is drawn on the card: the
   rule under the heading that the odos cards carry is deliberately absent
   here.

   Two card families:

     .rv_csr_programes_cards   a photograph above its content
     .odos_brand_piller_cards  icon, heading, copy -- shared with odos, so
                               this half is scoped to the page by :has(),
                               keyed on the 1% pledge badge, which appears
                               only here

   The programme cards keep their stacked shape. Each carries a heading and
   five bullets, so the homepage card's hover reveal would bury the substance
   of the page.

   Two notes on depth, both found by measuring rather than by reading. Legacy
   colours every `p` in the description block white at six classes plus a type
   selector, so the heading rule below has to reach through the description to
   beat it; it does the same for `ul li`, so the list rules do too.
   ------------------------------------------------------------------------ */

.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .rv_csr_programes_cards {
    position: relative;
    overflow: hidden;
    border: 0;
    /* legacy's radius and legacy's surface */
    border-radius: 12px;
    background: linear-gradient(288.81deg, rgba(49, 48, 48, 0.85) -11.69%, #000000 84.53%);
    transition: transform 0.4s ease, box-shadow 0.4s ease;
}

.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .rv_csr_programes_cards:hover {
    transform: translateY(-6px);
    box-shadow: 0 22px 52px rgba(0, 0, 0, 0.62);
}

/* the ring: a 1px gradient masked so only the border paints */
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .rv_csr_programes_cards::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 3;
    padding: 1px;
    border-radius: inherit;
    pointer-events: none;
    background-image: linear-gradient(288.81deg, rgba(172, 170, 170, 0.75) -11.69%, rgba(255, 255, 255, 0.06) 48%, rgba(0, 0, 0, 0) 84.53%);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask-composite: exclude;
    transition: background-image 0.45s ease;
}

.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .rv_csr_programes_cards:hover::before {
    background-image: linear-gradient(288.81deg, #FFFFFF -11.69%, rgba(255, 255, 255, 0.22) 48%, rgba(0, 0, 0, 0) 84.53%);
}

/* A fixed aspect, so three photographs of different shapes start their
   content on the same line. Legacy leaves the height automatic and the
   headings sit at three different heights. */
.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .rv_csr_programes_cards img {
    display: block;
    width: 100%;
    height: clamp(180px, 15.5vw, 230px);
    object-fit: cover;
    border-radius: 0;
    transition: transform 0.6s ease;
}

.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .rv_csr_programes_cards:hover img {
    transform: scale(1.06);
}

.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .rv_csr_programes_cards .rv_csr_programes_cards_description {
    position: relative;
    padding: clamp(20px, 1.7vw, 26px);
    border-radius: 0;
    /* legacy paints the same gradient here; one surface reads cleaner */
    background: transparent;
}

.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .rv_csr_programes_cards .rv_csr_programes_cards_description p.rv_csr_programs_cards_heading {
    margin: 0 0 14px;
    font-size: clamp(16px, 1.32vw, 19px);
    font-weight: 700;
    line-height: 1.35;
    letter-spacing: -0.01em;
    color: #FFFFFF;
}

.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .rv_csr_programes_cards .rv_csr_programes_cards_description ul {
    margin: 0;
    padding-left: 18px;
}

.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .rv_csr_programes_cards .rv_csr_programes_cards_description ul li {
    font-size: clamp(13.5px, 1.08vw, 15px);
    line-height: 1.7;
    /* legacy sets heading and body both to pure white; holding the body a
       little back is what separates them */
    color: rgba(255, 255, 255, 0.72);
}

.odos_wrapper .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .rv_csr_programes_cards .rv_csr_programes_cards_description ul li::marker {
    color: rgba(255, 255, 255, 0.45);
}

/* --- the company aims cards ----------------------------------------------
   The same class the odos brand pillars use, so this is scoped to the page.
   The 1% pledge badge appears only on csr, which makes it the discriminator.
   ------------------------------------------------------------------------ */

.odos_wrapper:has(.rv_csr_pledge_img) .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards {
    position: relative;
    overflow: hidden;
    padding: clamp(22px, 1.9vw, 28px);
    border: 0;
    border-radius: 10px;
    background: linear-gradient(288.81deg, rgba(49, 48, 48, 0.85) -11.69%, #000000 84.53%);
    box-shadow: none;
    transition: transform 0.4s ease, box-shadow 0.4s ease;
}

.odos_wrapper:has(.rv_csr_pledge_img) .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards:hover {
    transform: translateY(-6px);
    border-color: transparent;
    box-shadow: 0 22px 52px rgba(0, 0, 0, 0.62);
}

/* the coloured corner texture belongs to the odos pillars, not here */
.odos_wrapper:has(.rv_csr_pledge_img) .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards::after {
    display: none;
}

.odos_wrapper:has(.rv_csr_pledge_img) .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 3;
    padding: 1px;
    border-radius: inherit;
    pointer-events: none;
    background-image: linear-gradient(288.81deg, rgba(172, 170, 170, 0.75) -11.69%, rgba(255, 255, 255, 0.06) 48%, rgba(0, 0, 0, 0) 84.53%);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask-composite: exclude;
    transition: background-image 0.45s ease;
}

.odos_wrapper:has(.rv_csr_pledge_img) .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards:hover::before {
    background-image: linear-gradient(288.81deg, #FFFFFF -11.69%, rgba(255, 255, 255, 0.22) 48%, rgba(0, 0, 0, 0) 84.53%);
}

.odos_wrapper:has(.rv_csr_pledge_img) .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards h3 {
    color: #FFFFFF;
}

/* the shared accent card draws a short rule beneath its heading; these
   cards do without it */
.odos_wrapper:has(.rv_csr_pledge_img) .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards h3::after {
    display: none;
}

.odos_wrapper:has(.rv_csr_pledge_img) .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards p,
.odos_wrapper:has(.rv_csr_pledge_img) .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards ul li {
    color: rgba(255, 255, 255, 0.72);
}

.odos_wrapper:has(.rv_csr_pledge_img) .odos_brand_piller_section .odos_brand_piller_container .odos_brand_piller_cards_container .odos_brand_piller_cards ul li::marker {
    color: rgba(255, 255, 255, 0.45);
}

/* --- the feature images --------------------------------------------------
   Two blocks pair a photograph with copy. Both get the framed treatment the
   about hero uses, since these are real rectangular photographs rather than
   cut-outs.
   ------------------------------------------------------------------------ */

.odos_wrapper .purpose_section .odos_purpose_container .odos_purpose_image_container .odos_purpose_image img,
.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_image_container .odos_principle_image img {
    border-radius: 18px;
}

.odos_wrapper .purpose_section .odos_purpose_container .odos_purpose_image_container .odos_purpose_image {
    position: relative;
    border-radius: 18px;
    box-shadow: 0 30px 70px rgba(0, 0, 0, 0.55);
}

.odos_wrapper .purpose_section .odos_purpose_container .odos_purpose_image_container .odos_purpose_image::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    padding: 1px;
    border-radius: inherit;
    pointer-events: none;
    background-image: linear-gradient(150deg, rgba(255, 255, 255, 0.26), rgba(255, 255, 255, 0.05) 46%, rgba(234, 57, 110, 0.30) 100%);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask-composite: exclude;
}

.odos_wrapper .purpose_section .odos_purpose_container .odos_purpose_image_container .odos_purpose_description p {
    max-width: 62ch;
    font-size: clamp(14px, 1.02vw, 16px);
    line-height: 1.8;
    color: var(--qp-dim);
}

/* the closing block: copy sits over the photograph, so the scrim carries it */
.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_image_container .odos_principle_image {
    border-radius: 18px;
    box-shadow: 0 30px 70px rgba(0, 0, 0, 0.55);
}

.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_image_container .odos_principle_image::after {
    border-radius: 18px;
    opacity: 1;
    background:
        linear-gradient(90deg, rgba(8, 8, 11, 0.94) 0%, rgba(8, 8, 11, 0.86) 34%, rgba(8, 8, 11, 0.35) 62%, rgba(8, 8, 11, 0.12) 100%),
        radial-gradient(52% 70% at 8% 50%, rgba(234, 57, 110, 0.22), transparent 70%);
}

.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_image_container .odos_principle_image_description {
    z-index: 2;
    width: 54%;
    padding: 5% 4% 5% 5%;
}

.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_image_container .odos_principle_image_description p {
    max-width: 52ch;
    padding-top: 26px;
    font-size: clamp(14px, 1.02vw, 16px);
    line-height: 1.8;
    color: rgba(255, 255, 255, 0.72);
}

.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_image_container .odos_principle_image_description button {
    margin-top: 28px;
    padding: 13px 30px;
    border: 0;
    border-radius: 999px;
    background-image: linear-gradient(100deg, var(--qp-a1), var(--qp-a2));
    font-size: 15px;
    font-weight: 600;
    color: #FFFFFF;
    transition: transform 0.3s ease, box-shadow 0.3s ease, filter 0.3s ease;
}

.odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_image_container .odos_principle_image_description button:hover {
    transform: translateY(-2px);
    filter: brightness(1.06);
    box-shadow: 0 16px 36px rgba(234, 57, 110, 0.32);
}

/* the 1% pledge badge keeps its own proportions */
.odos_wrapper .purpose_section .odos_purpose_container .rv_csr_pledge_img img {
    width: auto;
    max-width: 100%;
    height: auto;
    object-fit: contain;
}

/* --- hero motion ---------------------------------------------------------
   Above the fold, so a load-time animation with no observer to wait on; the
   reveal script deliberately never touches a banner. Inside a reduced-motion
   guard, so when motion is not wanted these rules do not exist.
   ------------------------------------------------------------------------ */

@media (prefers-reduced-motion: no-preference) {
    @keyframes qp-odos-art {
        from { opacity: 0; translate: 0 26px; scale: 0.982; }
        to { opacity: 1; translate: 0 0; scale: 1; }
    }

    .odos_wrapper .odos_banner_section .odos_heading h1,
    .odos_wrapper .odos_banner_section .odos_heading p {
        animation: qp-hero-rise 0.62s cubic-bezier(0.22, 0.61, 0.36, 1) both;
    }

    .odos_wrapper .odos_banner_section .odos_heading h1 { animation-delay: 0.06s; }
    .odos_wrapper .odos_banner_section .odos_heading p { animation-delay: 0.16s; }

    .odos_wrapper .odos_banner_section .odos_img img {
        animation: qp-odos-art 0.85s cubic-bezier(0.22, 0.61, 0.36, 1) 0.12s both;
    }
}

/* --- narrow ---------------------------------------------------------------
   Legacy stacks these columns at 764px and below. The cut-out then sits above
   the copy, so it needs a ceiling of its own or it takes the whole screen.
   ------------------------------------------------------------------------ */

@media (max-width: 991.98px) {
    /* Legacy keeps the hero five-and-seven down to 764px, which leaves the
       copy column about 270px wide -- the headline then wraps to lines far
       shorter than its own box, and the bar under it spans the box. Stacking
       from here gives the headline its full measure back. */
    .odos_wrapper .odos_banner_section > .row {
        flex-direction: column;
        min-height: 0;
    }

    .odos_wrapper .odos_banner_section > .row > [class*="col-"] {
        flex: 0 0 100%;
        width: 100%;
        max-width: 100%;
    }

    .odos_wrapper .odos_banner_section .odos_img {
        padding: 0;
    }

    .odos_wrapper .odos_banner_section .odos_img img {
        max-height: min(40vh, 320px);
    }

    .odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_image_container .odos_principle_image_description {
        width: 68%;
    }
}

@media (max-width: 767.98px) {
    .odos_wrapper .odos_banner_section {
        padding-top: var(--qp-headerh, 92px);
    }

    .odos_wrapper .odos_banner_section .odos_heading {
        padding: clamp(28px, 6vw, 44px) 5% clamp(30px, 6vw, 44px) 4vw;
    }

    .odos_wrapper .odos_banner_section .odos_img img {
        max-height: min(34vh, 260px);
    }

    /* the closing block has no room for copy beside the photograph */
    .odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_image_container .odos_principle_image_description {
        position: static;
        width: 100%;
        padding: 24px 4vw 28px;
        transform: none;
    }

    .odos_wrapper .odos_principles_section .odos_principles_container .odos_principles_image_container .odos_principle_image::after {
        background:
            linear-gradient(180deg, rgba(8, 8, 11, 0.2) 0%, rgba(8, 8, 11, 0.55) 70%, rgba(8, 8, 11, 0.8) 100%);
    }
}

/* ==========================================================================
   Services
   ==========================================================================

   Seven pages: consulting-service, strategic-partnership-services,
   products-accelerators, product-data-engineering, cybersecurity, ai-kitchen
   and customapplicationdevelopment.

   All seven were restored from the 7 September deploy archive first. Six of
   them were carrying the earlier .qfp rebuild, whose markup mixed picture
   cards and text cards in the same sections; that version is kept beside each
   page as <name>.qfp-rebuild.bak and the legacy source as <name>.before.html.

   Six pages scope on .rv_partners_wrapper, ai-kitchen on
   .rv_ai_kitchen_wrapper. about.html also uses .rv_partners_wrapper and loads
   this sheet, but shares none of the class names below -- checked, not
   assumed -- so the two cannot reach each other.

   The card families and what each one already had:

     .rv_cards_dark_gradient        charcoal card, both pseudos free
     .rv_data_ai_services_cards     charcoal card, both pseudos free
     .rv_partners_product_suite_cards   ::after is legacy's accent bar
     .rv_gradient_border_cards      ::before is legacy's masked silver ring
     .rv_partners_partner_cards     ::before is legacy's masked silver ring
     .rv_ai_kitchen_services_cards  charcoal card, both pseudos free

   Which is a happy accident: the ring cards here are drawn exactly the way
   the odos principles cards are, down to the 299.85deg axis and the #ACAAAA
   stop, so they take that same treatment and the two modules agree.

   The icons are circular coloured badges again -- yellow, pink, purple, in
   that order -- with the colour baked into the artwork at 56x56. So no tile
   goes behind them, and each card takes its accent from its own badge.
   ========================================================================== */

.rv_partners_wrapper,
.rv_ai_kitchen_wrapper {
    --qp-a1: #F89833;
    --qp-a2: #EA396E;
    --qp-line: rgba(255, 255, 255, 0.09);
    --qp-surface: #141416;
    --qp-text: #F5F5F7;
    --qp-dim: #A9A9B4;

    --sv-yellow: #C78A4E;
    --sv-pink: #E07394;
    --sv-purple: #C878C9;
}

/* --- hero ----------------------------------------------------------------
   Legacy centres the copy over a full-bleed artwork. That composition is
   kept -- the artwork is the page's own and carries its subject -- but the
   type sat straight on a busy image with nothing behind it. A scrim and a
   bloom give it something to sit on, and the heading comes up to the size the
   rest of the revamp uses.
   ------------------------------------------------------------------------ */

.rv_partners_wrapper .rv_partners_banner,
.rv_ai_kitchen_wrapper .rv_ai_kitchen_banner {
    position: relative;
}

/* the scrim, over the artwork and under the copy */
.rv_partners_wrapper .rv_partners_banner::after,
.rv_ai_kitchen_wrapper .rv_ai_kitchen_banner::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background-image:
        linear-gradient(180deg, rgba(8, 8, 11, 0.82) 0%, rgba(8, 8, 11, 0.46) 42%, rgba(8, 8, 11, 0.86) 100%),
        radial-gradient(52% 58% at 18% 12%, rgba(234, 57, 110, 0.24), transparent 68%),
        radial-gradient(44% 52% at 84% 22%, rgba(150, 86, 224, 0.20), transparent 70%);
}

.rv_partners_wrapper .rv_partners_banner .rv_partners_banner_heading,
.rv_ai_kitchen_wrapper .rv_ai_kitchen_banner .rv_ai_kitchen_banner_heading {
    z-index: 2;
}

.rv_partners_wrapper .rv_partners_banner .rv_partners_banner_heading .rv_bpr_main_heading .heading_brp_wrapper .heading_box_bpr h1 {
    font-size: clamp(30px, 3.9vw, 56px);
    font-weight: 800;
    line-height: 1.08;
    letter-spacing: -0.03em;
    color: #FFFFFF;
    text-shadow: 0 2px 24px rgba(0, 0, 0, 0.55);
}

.rv_partners_wrapper .rv_partners_banner .rv_partners_banner_heading .rv_bpr_main_heading .heading_brp_wrapper h1::after {
    height: 3px;
    bottom: -14px;
    border-radius: 3px;
}

.rv_partners_wrapper .rv_partners_banner .rv_partners_banner_heading .rv_bpr_main_heading .heading_brp_wrapper h1 p,
.rv_partners_wrapper .rv_partners_banner .rv_partners_banner_heading h3 {
    font-size: clamp(14px, 1.15vw, 18px);
    line-height: 1.7;
    color: rgba(255, 255, 255, 0.76);
    text-shadow: 0 2px 16px rgba(0, 0, 0, 0.5);
}

/* --- section headings ----------------------------------------------------
   Legacy runs these at 43-44px in the book weight with a hairline bar. One
   rule brings every heading container on the module to the system heading.
   ------------------------------------------------------------------------ */

.rv_partners_wrapper [class*="_section"] .rv_partners_product_suite_headings h1,
.rv_partners_wrapper [class*="_section"] [class*="_container"] .rv_partners_automation_heading_container h1,
.rv_partners_wrapper [class*="_section"] .rv_partners_automation_heading_container h1,
.rv_partners_wrapper [class*="_section"] .rv_partners_about_heading h1,
.rv_ai_kitchen_wrapper [class*="_section"] .rv_ai_kitchen_services_headings h1,
.rv_ai_kitchen_wrapper [class*="_section"] [class*="_container"] .rv_ai_kitchen_automation_heading_container h1,
.rv_ai_kitchen_wrapper [class*="_section"] .rv_ai_kitchen_automation_heading_container h1 {
    font-size: clamp(28px, 3.1vw, 44px);
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.02em;
    color: var(--qp-text);
}

.rv_partners_wrapper [class*="_section"] .rv_partners_product_suite_headings h1::after,
.rv_partners_wrapper [class*="_section"] [class*="_container"] .rv_partners_automation_heading_container h1::after,
.rv_partners_wrapper [class*="_section"] .rv_partners_automation_heading_container h1::after,
.rv_partners_wrapper [class*="_section"] .rv_partners_about_heading h1::after,
.rv_ai_kitchen_wrapper [class*="_section"] .rv_ai_kitchen_services_headings h1::after,
.rv_ai_kitchen_wrapper [class*="_section"] [class*="_container"] .rv_ai_kitchen_automation_heading_container h1::after,
.rv_ai_kitchen_wrapper [class*="_section"] .rv_ai_kitchen_automation_heading_container h1::after {
    height: 3px;
    bottom: -12px;
    border-radius: 3px;
}

/* --- the accent card -----------------------------------------------------
   Three families are the same object with different payloads, so they take
   one treatment. Legacy paints the charcoal gradient with !important on the
   dark-gradient variant, which is why the surface below carries one too.
   ------------------------------------------------------------------------ */

.rv_partners_wrapper .rv_partners_product_suite_section .rv_partners_product_suite_cards_container .rv_cards_dark_gradient,
.rv_partners_wrapper .rv_partners_product_suite_section .rv_partners_product_suite_cards_container .rv_data_ai_services_cards,
.rv_partners_wrapper .rv_partners_ecosystem_section .rv_ecosystem_partners_container .rv_cards_dark_gradient,
.rv_partners_wrapper .rv_partners_ecosystem_section .rv_ecosystem_partners_container .rv_data_ai_services_cards,
.rv_ai_kitchen_wrapper .rv_ai_kitchen_services_section .rv_ai_kitchen_services_cards_container .rv_ai_kitchen_services_cards {
    --sv-c: var(--sv-pink);
    position: relative;
    overflow: hidden;
    height: 100%;
    padding: clamp(22px, 1.9vw, 28px);
    border: 1px solid var(--qp-line);
    border-radius: 16px;
    background: var(--qp-surface) !important;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
    transition: transform 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
}

/* the badges run yellow, pink, purple in that order */
.rv_partners_wrapper .rv_partners_product_suite_cards_container > .row > [class*="col-"]:nth-child(3n+1) .rv_cards_dark_gradient,
.rv_partners_wrapper .rv_partners_product_suite_cards_container > .row > [class*="col-"]:nth-child(3n+1) .rv_data_ai_services_cards,
.rv_partners_wrapper .rv_ecosystem_partners_container > .row > [class*="col-"]:nth-child(3n+1) .rv_cards_dark_gradient,
.rv_partners_wrapper .rv_ecosystem_partners_container > .row > [class*="col-"]:nth-child(3n+1) .rv_data_ai_services_cards,
.rv_ai_kitchen_wrapper .rv_ai_kitchen_services_cards_container > .row > [class*="col-"]:nth-child(3n+1) .rv_ai_kitchen_services_cards { --sv-c: var(--sv-yellow); }

.rv_partners_wrapper .rv_partners_product_suite_cards_container > .row > [class*="col-"]:nth-child(3n+2) .rv_cards_dark_gradient,
.rv_partners_wrapper .rv_partners_product_suite_cards_container > .row > [class*="col-"]:nth-child(3n+2) .rv_data_ai_services_cards,
.rv_partners_wrapper .rv_ecosystem_partners_container > .row > [class*="col-"]:nth-child(3n+2) .rv_cards_dark_gradient,
.rv_partners_wrapper .rv_ecosystem_partners_container > .row > [class*="col-"]:nth-child(3n+2) .rv_data_ai_services_cards,
.rv_ai_kitchen_wrapper .rv_ai_kitchen_services_cards_container > .row > [class*="col-"]:nth-child(3n+2) .rv_ai_kitchen_services_cards { --sv-c: var(--sv-pink); }

.rv_partners_wrapper .rv_partners_product_suite_cards_container > .row > [class*="col-"]:nth-child(3n+3) .rv_cards_dark_gradient,
.rv_partners_wrapper .rv_partners_product_suite_cards_container > .row > [class*="col-"]:nth-child(3n+3) .rv_data_ai_services_cards,
.rv_partners_wrapper .rv_ecosystem_partners_container > .row > [class*="col-"]:nth-child(3n+3) .rv_cards_dark_gradient,
.rv_partners_wrapper .rv_ecosystem_partners_container > .row > [class*="col-"]:nth-child(3n+3) .rv_data_ai_services_cards,
.rv_ai_kitchen_wrapper .rv_ai_kitchen_services_cards_container > .row > [class*="col-"]:nth-child(3n+3) .rv_ai_kitchen_services_cards { --sv-c: var(--sv-purple); }

.rv_partners_wrapper .rv_partners_product_suite_section .rv_partners_product_suite_cards_container .rv_cards_dark_gradient:hover,
.rv_partners_wrapper .rv_partners_product_suite_section .rv_partners_product_suite_cards_container .rv_data_ai_services_cards:hover,
.rv_partners_wrapper .rv_partners_ecosystem_section .rv_ecosystem_partners_container .rv_cards_dark_gradient:hover,
.rv_partners_wrapper .rv_partners_ecosystem_section .rv_ecosystem_partners_container .rv_data_ai_services_cards:hover,
.rv_ai_kitchen_wrapper .rv_ai_kitchen_services_section .rv_ai_kitchen_services_cards_container .rv_ai_kitchen_services_cards:hover {
    transform: translateY(-4px);
    border-color: var(--sv-c);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55);
}

/* corner texture in the card's own colour */
.rv_partners_wrapper .rv_partners_product_suite_section .rv_partners_product_suite_cards_container .rv_cards_dark_gradient::after,
.rv_partners_wrapper .rv_partners_product_suite_section .rv_partners_product_suite_cards_container .rv_data_ai_services_cards::after,
.rv_partners_wrapper .rv_partners_ecosystem_section .rv_ecosystem_partners_container .rv_cards_dark_gradient::after,
.rv_partners_wrapper .rv_partners_ecosystem_section .rv_ecosystem_partners_container .rv_data_ai_services_cards::after,
.rv_ai_kitchen_wrapper .rv_ai_kitchen_services_section .rv_ai_kitchen_services_cards_container .rv_ai_kitchen_services_cards::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    border-radius: inherit;
    pointer-events: none;
    opacity: 0.4;
    transition: opacity 0.4s ease;
    -webkit-mask-image: radial-gradient(92% 92% at 112% 112%, #000 0%, rgba(0, 0, 0, 0.45) 42%, transparent 70%);
    mask-image: radial-gradient(92% 92% at 112% 112%, #000 0%, rgba(0, 0, 0, 0.45) 42%, transparent 70%);
    background-image: radial-gradient(circle at center, var(--sv-c) 1.7px, transparent 2px);
    background-size: 14px 14px;
}

.rv_partners_wrapper .rv_partners_product_suite_section .rv_partners_product_suite_cards_container .rv_cards_dark_gradient:hover::after,
.rv_partners_wrapper .rv_partners_product_suite_section .rv_partners_product_suite_cards_container .rv_data_ai_services_cards:hover::after,
.rv_partners_wrapper .rv_partners_ecosystem_section .rv_ecosystem_partners_container .rv_cards_dark_gradient:hover::after,
.rv_partners_wrapper .rv_partners_ecosystem_section .rv_ecosystem_partners_container .rv_data_ai_services_cards:hover::after,
.rv_ai_kitchen_wrapper .rv_ai_kitchen_services_section .rv_ai_kitchen_services_cards_container .rv_ai_kitchen_services_cards:hover::after {
    opacity: 0.58;
}

/* the badge is already a coloured disc, so it is bounded rather than tiled */
.rv_partners_wrapper .rv_partners_product_suite_cards_container .rv_cards_dark_gradient > img,
.rv_partners_wrapper .rv_partners_product_suite_cards_container .rv_data_ai_services_cards > img,
.rv_partners_wrapper .rv_ecosystem_partners_container .rv_cards_dark_gradient > img,
.rv_partners_wrapper .rv_ecosystem_partners_container .rv_data_ai_services_cards > img,
.rv_ai_kitchen_wrapper .rv_ai_kitchen_services_cards_container .rv_ai_kitchen_services_cards > img {
    position: relative;
    z-index: 1;
    display: block;
    width: auto;
    height: auto;
    max-width: 56px;
    max-height: 56px;
    object-fit: contain;
}

.rv_partners_wrapper .rv_partners_product_suite_cards_container .rv_cards_dark_gradient h3,
.rv_partners_wrapper .rv_partners_product_suite_cards_container .rv_data_ai_services_cards h3,
.rv_partners_wrapper .rv_ecosystem_partners_container .rv_cards_dark_gradient h3,
.rv_partners_wrapper .rv_ecosystem_partners_container .rv_data_ai_services_cards h3,
.rv_ai_kitchen_wrapper .rv_ai_kitchen_services_cards_container .rv_ai_kitchen_services_cards h3 {
    position: relative;
    z-index: 1;
    display: inline-block;
    margin: 18px 0 0;
    padding-bottom: 10px;
    font-size: clamp(16px, 1.32vw, 20px);
    font-weight: 700;
    line-height: 1.35;
    letter-spacing: -0.01em;
    color: var(--sv-c);
}

.rv_partners_wrapper .rv_partners_product_suite_cards_container .rv_cards_dark_gradient h3::after,
.rv_partners_wrapper .rv_partners_product_suite_cards_container .rv_data_ai_services_cards h3::after,
.rv_partners_wrapper .rv_ecosystem_partners_container .rv_cards_dark_gradient h3::after,
.rv_partners_wrapper .rv_ecosystem_partners_container .rv_data_ai_services_cards h3::after,
.rv_ai_kitchen_wrapper .rv_ai_kitchen_services_cards_container .rv_ai_kitchen_services_cards h3::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 34px;
    height: 2px;
    border-radius: 2px;
    background-color: var(--sv-c);
    opacity: 0.6;
    transition: width 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.rv_partners_wrapper .rv_partners_product_suite_cards_container .rv_cards_dark_gradient:hover h3::after,
.rv_partners_wrapper .rv_partners_product_suite_cards_container .rv_data_ai_services_cards:hover h3::after,
.rv_partners_wrapper .rv_ecosystem_partners_container .rv_cards_dark_gradient:hover h3::after,
.rv_partners_wrapper .rv_ecosystem_partners_container .rv_data_ai_services_cards:hover h3::after,
.rv_ai_kitchen_wrapper .rv_ai_kitchen_services_cards_container .rv_ai_kitchen_services_cards:hover h3::after {
    width: 100%;
}

.rv_partners_wrapper .rv_partners_product_suite_cards_container .rv_cards_dark_gradient p,
.rv_partners_wrapper .rv_partners_product_suite_cards_container .rv_data_ai_services_cards p,
.rv_partners_wrapper .rv_ecosystem_partners_container .rv_cards_dark_gradient p,
.rv_partners_wrapper .rv_ecosystem_partners_container .rv_data_ai_services_cards p,
.rv_partners_wrapper .rv_partners_product_suite_cards_container .rv_cards_dark_gradient li,
.rv_partners_wrapper .rv_partners_product_suite_cards_container .rv_data_ai_services_cards li,
.rv_ai_kitchen_wrapper .rv_ai_kitchen_services_cards_container .rv_ai_kitchen_services_cards p,
.rv_ai_kitchen_wrapper .rv_ai_kitchen_services_cards_container .rv_ai_kitchen_services_cards li {
    position: relative;
    z-index: 1;
    margin-top: 12px;
    font-size: clamp(13.5px, 1.08vw, 15px);
    line-height: 1.7;
    color: var(--qp-dim);
}

/* --- the ring cards ------------------------------------------------------
   Legacy already draws these the way the odos principles cards are drawn: a
   masked ::before carrying the same 299.85deg silver-to-black gradient. The
   ring is therefore left alone and only lit -- it runs up to white on hover,
   and the card lifts with it.
   ------------------------------------------------------------------------ */

.rv_partners_wrapper .rv_partners_partner_cards_container .rv_gradient_border_cards,
.rv_partners_wrapper .rv_partners_partner_cards_container .rv_partners_partner_cards {
    position: relative;
    height: 100%;
    border-radius: 12px;
    transition: transform 0.4s ease, box-shadow 0.4s ease;
}

.rv_partners_wrapper .rv_partners_partner_cards_container .rv_gradient_border_cards::before,
.rv_partners_wrapper .rv_partners_partner_cards_container .rv_partners_partner_cards::before {
    transition: background 0.45s ease;
}

.rv_partners_wrapper .rv_partners_partner_cards_container .rv_gradient_border_cards:hover,
.rv_partners_wrapper .rv_partners_partner_cards_container .rv_partners_partner_cards:hover {
    transform: translateY(-6px);
    box-shadow: 0 22px 52px rgba(0, 0, 0, 0.6);
}

.rv_partners_wrapper .rv_partners_partner_cards_container .rv_gradient_border_cards:hover::before,
.rv_partners_wrapper .rv_partners_partner_cards_container .rv_partners_partner_cards:hover::before {
    background: linear-gradient(299.85deg, #FFFFFF -14.19%, #8A8A90 34%, #000000 109.56%);
}

.rv_partners_wrapper .rv_partners_partner_cards_container .rv_gradient_border_cards h3,
.rv_partners_wrapper .rv_partners_partner_cards_container .rv_partners_partner_cards h3 {
    font-size: clamp(16px, 1.3vw, 19px);
    font-weight: 700;
    letter-spacing: -0.01em;
    color: #FFFFFF;
}

.rv_partners_wrapper .rv_partners_partner_cards_container .rv_gradient_border_cards p,
.rv_partners_wrapper .rv_partners_partner_cards_container .rv_partners_partner_cards p {
    font-size: clamp(13.5px, 1.08vw, 15px);
    line-height: 1.7;
    color: rgba(255, 255, 255, 0.72);
}

/* --- the suite cards -----------------------------------------------------
   These carry a product logo and legacy's coloured accent bar on ::after,
   which is the yellow and pink the rest of the family uses. The bar stays;
   the card gains the shared surface.
   ------------------------------------------------------------------------ */

.rv_partners_wrapper .rv_partners_product_suite_cards_container .rv_partners_product_suite_cards,
.rv_partners_wrapper .rv_ecosystem_partners_container .rv_partners_product_suite_cards {
    position: relative;
    height: 100%;
    border-radius: 14px;
    transition: transform 0.35s ease, box-shadow 0.35s ease;
}

.rv_partners_wrapper .rv_partners_product_suite_cards_container .rv_partners_product_suite_cards:hover,
.rv_partners_wrapper .rv_ecosystem_partners_container .rv_partners_product_suite_cards:hover {
    transform: translateY(-4px);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55);
}

.rv_partners_wrapper .rv_partners_product_suite_cards_container .rv_partners_product_suite_cards img,
.rv_partners_wrapper .rv_ecosystem_partners_container .rv_partners_product_suite_cards img {
    width: auto;
    height: auto;
    max-width: 100%;
    object-fit: contain;
}

/* --- hero motion ---------------------------------------------------------
   Above the fold, so a load-time animation with no observer to wait on. The
   whole block sits inside a reduced-motion guard.
   ------------------------------------------------------------------------ */

@media (prefers-reduced-motion: no-preference) {
    .rv_partners_wrapper .rv_partners_banner .rv_partners_banner_heading .heading_box_bpr h1,
    .rv_partners_wrapper .rv_partners_banner .rv_partners_banner_heading h3,
    .rv_ai_kitchen_wrapper .rv_ai_kitchen_banner .rv_ai_kitchen_banner_heading h1,
    .rv_ai_kitchen_wrapper .rv_ai_kitchen_banner .rv_ai_kitchen_banner_heading h3 {
        animation: qp-hero-rise 0.62s cubic-bezier(0.22, 0.61, 0.36, 1) both;
    }

    .rv_partners_wrapper .rv_partners_banner .rv_partners_banner_heading h3,
    .rv_ai_kitchen_wrapper .rv_ai_kitchen_banner .rv_ai_kitchen_banner_heading h3 {
        animation-delay: 0.14s;
    }
}

/* ==========================================================================
   Services -- customapplicationdevelopment
   ==========================================================================

   The seventh Services page, and the only one that never carried the .qfp
   rebuild. The other six share qf-page.css and so already have the card and
   the numbered rail; this one loads only the chrome sheet, which left 21
   cards sitting on plain black.

   It is not a card grid though, so the rail would be the wrong answer: it is
   seven full-width alternating feature rows, each a photograph on one side
   and copy on the other, with a strip of technology logos beneath. What it
   needs from the pattern is the heading, the framed image, the card surface
   on the logo chips, and the same silver ring that runs up to white.

   Scoped through .rv_salesforce_slack_section and .cad_tech_logos, both of
   which belong to this page. about.html shares .rv_partners_wrapper and
   loads this sheet, so the scope has to be narrower than the wrapper.
   ========================================================================== */

/* --- section headings ---------------------------------------------------
   Legacy runs these at 44px in the book weight. Same treatment as every
   other heading on the revamp, and the bar stops on the phrase because the
   heading already shrinks to its words.
   ------------------------------------------------------------------------ */

/* the headings sit in the slack description container, not the bprf one */
.rv_partners_wrapper .rv_salesforce_slack_section .rv_salesforce_slack_container .rv_salesforce_slack_description_container h1,
.rv_partners_wrapper .rv_salesforce_slack_section .rv_salesforce_slack_container .rv_salesforce_slack_description_container h2,
.rv_partners_wrapper .rv_salesforce_slack_section .rv_partners_bprf_services_cards_description h1,
.rv_partners_wrapper .rv_salesforce_slack_section .rv_partners_bprf_services_cards_description h2 {
    font-size: clamp(26px, 2.9vw, 40px);
    font-weight: 700;
    line-height: 1.18;
    letter-spacing: -0.02em;
    color: #FFFFFF;
}

.rv_partners_wrapper .rv_salesforce_slack_section .rv_salesforce_slack_container .rv_salesforce_slack_description_container p,
.rv_partners_wrapper .rv_salesforce_slack_section .rv_salesforce_slack_container .rv_salesforce_slack_description_container li,
.rv_partners_wrapper .rv_salesforce_slack_section .rv_partners_bprf_services_cards_description p,
.rv_partners_wrapper .rv_salesforce_slack_section .rv_partners_bprf_services_cards_description li {
    font-size: clamp(14px, 1.08vw, 15.5px);
    line-height: 1.75;
    color: rgba(255, 255, 255, 0.68);
}

/* --- the feature photographs --------------------------------------------
   The card itself has both pseudo slots taken by legacy, so the frame goes
   on the image wrapper, whose slots are free.
   ------------------------------------------------------------------------ */

.rv_partners_wrapper .rv_salesforce_slack_section .rv_partners_bprf_services_cards_image {
    position: relative;
    border-radius: 16px;
    overflow: hidden;
    box-shadow: 0 26px 60px rgba(0, 0, 0, 0.5);
}

.rv_partners_wrapper .rv_salesforce_slack_section .rv_partners_bprf_services_cards_image img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: 16px;
    transition: transform 0.6s ease;
}

.rv_partners_wrapper .rv_salesforce_slack_section .rv_partners_bprf_services_cards_image:hover img {
    transform: scale(1.03);
}

/* the ring, on the same 288.81deg axis the cards use */
.rv_partners_wrapper .rv_salesforce_slack_section .rv_partners_bprf_services_cards_image::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    padding: 1px;
    border-radius: inherit;
    pointer-events: none;
    background-image: linear-gradient(288.81deg, rgba(172, 170, 170, 0.75) -11.69%, rgba(255, 255, 255, 0.06) 48%, rgba(0, 0, 0, 0) 84.53%);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask-composite: exclude;
    transition: background-image 0.45s ease;
}

.rv_partners_wrapper .rv_salesforce_slack_section .rv_partners_bprf_services_cards_image:hover::after {
    background-image: linear-gradient(288.81deg, #FFFFFF -11.69%, rgba(255, 255, 255, 0.22) 48%, rgba(0, 0, 0, 0) 84.53%);
}

/* --- the technology logo chips -------------------------------------------
   Seventeen marks that were sitting loose on the page background. They take
   the card the rest of the site uses -- legacy's charcoal diagonal, the
   silver ring, and the lift -- so they read as objects rather than as
   floating artwork.
   ------------------------------------------------------------------------ */

.rv_partners_wrapper .cad_tech_logos .cad_features_points {
    position: relative;
    align-items: center;
    justify-content: center;
    gap: 10px;
    min-height: 72px;
    padding: 12px 16px;
    border-radius: 12px;
    background: linear-gradient(288.81deg, rgba(49, 48, 48, 0.85) -11.69%, #000000 84.53%);
    transition: transform 0.4s ease, box-shadow 0.4s ease;
}

.rv_partners_wrapper .cad_tech_logos .cad_features_points:hover {
    transform: translateY(-4px);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55);
}

.rv_partners_wrapper .cad_tech_logos .cad_features_points::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    padding: 1px;
    border-radius: inherit;
    pointer-events: none;
    background-image: linear-gradient(288.81deg, rgba(172, 170, 170, 0.75) -11.69%, rgba(255, 255, 255, 0.06) 48%, rgba(0, 0, 0, 0) 84.53%);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask-composite: exclude;
    transition: background-image 0.45s ease;
}

.rv_partners_wrapper .cad_tech_logos .cad_features_points:hover::after {
    background-image: linear-gradient(288.81deg, #FFFFFF -11.69%, rgba(255, 255, 255, 0.22) 48%, rgba(0, 0, 0, 0) 84.53%);
}

/* The logos are flex items in a stretching row, so each is pulled to the
   row's height and squeezed sideways -- the first came out 23x71 from a
   near-square source. Legacy already asks for auto sizing; it is the stretch
   that overrides it. */
.rv_partners_wrapper .cad_tech_logos .cad_features_points img {
    position: relative;
    z-index: 1;
    flex: 0 0 auto;
    align-self: center;
    width: auto;
    height: auto;
    max-height: 40px;
    max-width: 100%;
    object-fit: contain;
}

/* --- hero ----------------------------------------------------------------
   Legacy paints two purple washes here with !important, which is why the
   field below has to answer in kind. The washes are replaced with the dark
   field and bloom the rest of the module uses.
   ------------------------------------------------------------------------ */

.rv_partners_wrapper .rv_bprf_banner {
    background-color: #08080B;
}

.rv_partners_wrapper .rv_bprf_banner::before {
    background:
        radial-gradient(54% 60% at 14% 6%, rgba(234, 57, 110, 0.30), transparent 66%),
        radial-gradient(42% 50% at 52% -6%, rgba(150, 86, 224, 0.22), transparent 68%) !important;
}

.rv_partners_wrapper .rv_bprf_banner::after {
    background:
        radial-gradient(46% 54% at 90% 14%, rgba(248, 152, 51, 0.12), transparent 68%),
        linear-gradient(to top, #000000 0%, rgba(0, 0, 0, 0) 26%) !important;
}

.rv_partners_wrapper .rv_bprf_banner .rv_partners_banner_heading .heading_box_bpr h1,
.rv_partners_wrapper .rv_bprf_banner h1 {
    font-size: clamp(30px, 3.9vw, 56px);
    font-weight: 800;
    line-height: 1.08;
    letter-spacing: -0.03em;
    color: #FFFFFF;
    text-shadow: 0 2px 24px rgba(0, 0, 0, 0.55);
}

/* ===============================================================
   Mobile pass - qkonnect icon strips
   The strips carry col-lg-2 col-md-2 col-sm-3, so the tablet band
   put six then four items across at ~122px. Every label was cut
   mid-word ("Call Managemen", "Conferen") and the spill pushed the
   page 11px sideways. Two across below 768, three above.
   =============================================================== */
@media (min-width: 576px) and (max-width: 767.98px) {

    .qkonnect_cti_wrapper .why_qkonnect_cards_container .row > [class*="col-"],
    .qkonnect_cti_wrapper .product_qkonnect_features_card_container .row > [class*="col-"] {
        flex: 0 0 auto;
        width: 50% !important;
        max-width: 50%;
    }
}

@media (min-width: 768px) and (max-width: 991.98px) {

    .qkonnect_cti_wrapper .why_qkonnect_cards_container .row > [class*="col-"],
    .qkonnect_cti_wrapper .product_qkonnect_features_card_container .row > [class*="col-"] {
        flex: 0 0 auto;
        width: 33.3333% !important;
        max-width: 33.3333%;
    }
}

.qkonnect_cti_wrapper .why_qkonnect_cards h5,
.qkonnect_cti_wrapper .why_qkonnect_cards p,
.qkonnect_cti_wrapper .product_qkonnect_features_card h5,
.qkonnect_cti_wrapper .product_qkonnect_features_card p {
    overflow-wrap: anywhere;
    word-break: normal;
    hyphens: none;
}

/* the decorative scroll hint sat at 10px, below the readable floor */
.qp-scroll span {
    font-size: 12px;
}

/* a finger-sized hit area for the hero link, without changing its look */
@media (hover: none) {

    .qp-hero-cta .qp-cta-link {
        min-height: 44px;
        align-items: center;
    }
}

/* On the smallest phones the two-across features card left 112px for a
   113px word. Six pixels of side padding back is enough. */
@media (max-width: 575.98px) {

    .qkonnect_cti_wrapper .product_qkonnect_features_section .product_qkonnect_features_card_container .product_qkonnect_features_card {
        padding-right: 14px;
        padding-left: 14px;
    }
}

/* Global.css pins these two accent strips to a bright yellow with
   !important; the same muted amber as the rest of the accents. */
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_cards_container_1 .product_qkonnect_tech_enabled_cards_1_yellow::before,
.qkonnect_cti_wrapper .product_qkonnect_technology_enablers_section .product_qkonnect_tech_enabled_ai_integrated_section .product_qkonnect_tech_enabled_ai_integrated_cards_4_yellow::before {
    background: #C78A4E !important;
}
