/* Solutions page design layer — /solutions and its four category pages.
 *
 * The presentation layer for the `webpages` rows whose slugs are
 *
 *     solutions
 *     solutions/by-industry             8 industries
 *     solutions/by-business-size        3 sizes
 *     solutions/by-department           4 departments
 *     solutions/by-hr-maturity-model    4 stages
 *
 * Those rows hold every word on those pages and are rendered by
 * ContentPage.razor's /{*Slug} catch-all — there is no component for any of the
 * URLs and this redesign does not add one. Nothing in here is content: no text,
 * no links, no numbers. See docs/solutions-redesign.sql and
 * docs/solutions-child-pages-redesign.sql for the markup this styles, and
 * docs/solutions.page_html.backup.html plus docs/solutions-child-pages/ for
 * what it replaced.
 *
 * THE FIVE PAGES ARE ONE OBJECT, WHICH IS WHY THEY SHARE A SHEET. Each is a
 * hero with a numbered list of ways in, an Explore More rail and a closing
 * band; the only difference is how many rows the list has (4, 8, 3, 4, 4) and
 * that the maturity page adds two paragraphs of prose between them. A second
 * sheet with a second prefix would have been the same rules under other names.
 * The pages one level below — /solutions/by-industry/retail and its eighteen
 * siblings — have six more bands and get their own sheet, css/pages/
 * solution-detail.css, cut from this palette so the three levels read as one
 * journey down the tree.
 *
 * Global CSS, linked from App.razor, so the two rules every sibling page sheet
 * calls out apply here too:
 *
 * 1. Nothing confines these rules to this page, so every selector is qsol-
 *    prefixed or a descendant of one. No bare element selectors.
 * 2. @keyframes names are global as well, hence the prefix on the one declared
 *    here — it must not collide with the compiled Tailwind bundle or with the
 *    qh-, qpr-, qmod-, qab-, qp-, qct-, qco-, qcp-, qps-, qsm- and qfh-
 *    animations the other page sheets declare.
 *
 * These rules are unlayered and Tailwind v4's utilities live inside @layer, so
 * they win regardless of specificity. That is why the page can be styled entirely
 * from here rather than from utility classes in the CMS textarea: the bundle the
 * site serves is a prebuilt Next.js artefact, so it contains only the utilities
 * that build emitted, and a class invented in the textarea would not exist at
 * runtime. The page this replaces was already paying for that — its one section
 * heading carried an inline `style="color: #6366F1;"` because there was no other
 * way to colour it, and its H1 an inline `style="color: #1a1a1a;"`.
 *
 * `boxed-container` IS from the bundle and is used deliberately: it is the site's
 * own container (max-width and gutters stepping 1200 -> 1400 -> 1600px), so this
 * page's content column lines up with the header, the footer and every other
 * page. Do not replace it with a max-width of this sheet's own. The old markup
 * opened with a single `boxed-container py-8` wrapping all three bands, which is
 * why nothing on the page could ever run edge to edge; here each band is
 * full-bleed and carries its own container, so the hero and the closing band can
 * be tinted across the whole viewport.
 *
 * THE TWO BUTTON PAIRS ARE NOT STYLED HERE. The hero's and the closing band's
 * are `.qh-btn` and `.qh-btn-ghost` from css/pages/home.css, which App.razor
 * links on every page — the site's primary call-to-action pair, used exactly as
 * /products, /company/about-us and /company/contact use it. This sheet only
 * positions them and undoes the CMS wrapper's inherited line-height and the
 * bundle's link underline; restyling .qh-btn here would change the home page too.
 *
 * PALETTE. The logo ramp the products, pricing, payroll, about, CPCM, contact and
 * site-map sheets already share — #4f46e5 (indigo, primary) -> #7c3aed (violet)
 * -> #a22dea (magenta-violet), with the brand's gold #d4af37 as the one
 * secondary.
 *
 * THE ONE IDEA THIS PAGE ADDS. The page's whole argument is that there are four
 * ways in, so the four category rows are the design rather than four copies of
 * one row: each takes a different stop off the ramp, indigo -> violet ->
 * magenta -> gold, top to bottom. The old version gave all four the same
 * `bg-indigo-100` chip, so the list read as one thing repeated rather than as
 * four choices. A fifth category means a fifth modifier class in the markup and
 * one more three-line rule down at .qsol-cat--*, not a new component. The
 * eight-row list on /solutions/by-industry cycles the same four stops twice,
 * which is why the modifiers are named for hues rather than for positions.
 */

/* ── page shell ─────────────────────────────────────────────────────────
 *
 * ContentPage wraps every stored page in a div carrying
 * `style="color:#1a1a1a;line-height:1.8"` inline. Every CMS page depends on that
 * pair and it would otherwise cascade into every heading, badge and card here —
 * 1.8 silently inflates anything that sets no line-height of its own. Both are
 * re-declared on .qsol-page so this page's type inherits from the page root down
 * rather than from the wrapper. Do not remove them. */
.qsol-page {
    color: #14103a;
    line-height: 1.6;
    background: #fff;
}

/* The JSON-LD block is the first child of .qsol-page. It renders as nothing, but
 * a stray `display` from elsewhere would give it a box. */
.qsol-page > script {
    display: none;
}

/* ── shared section furniture ───────────────────────────────────────────
 *
 * One rule rather than a per-section heading size, which is what the page had:
 * `text-3xl` with a hand-written hex colour beside it, and section spacing set by
 * `mb-12` on two sections and `py-12 md:py-16` on the hero, so the gaps changed
 * down the page for no reason a reader could see. */
.qsol-section {
    position: relative;
    padding: 82px 0;
}

/* The page has one of these — Explore More — sitting between the pale hero and
 * the dark closing band, so it takes the tint rather than white: three bands in
 * a row of light, light, dark would leave the middle one with no edge of its
 * own. A second section added later that should be white needs no class, only
 * the absence of this one; .qsol-section already inherits the white .qsol-page
 * sets. */
.qsol-section--tint {
    background:
        radial-gradient(760px 460px at 6% 0%, rgba(79, 70, 229, .07), transparent 62%),
        radial-gradient(700px 440px at 94% 100%, rgba(162, 45, 234, .06), transparent 60%),
        #f8f7fe;
}

.qsol-head {
    max-width: 760px;
    margin: 0 auto 46px;
    text-align: center;
}

.qsol-title {
    margin: 0;
    font-size: clamp(26px, 2.9vw, 39px);
    font-weight: 800;
    line-height: 1.15;
    letter-spacing: -.022em;
    color: #14103a;
}

/* A short brand rule under the section heading. On /solutions the two section
 * headings were the only things on the page carrying a hand-written hex in a
 * style attribute, for want of any other way to colour them; this replaces the
 * colour with a mark, which does the same job without tinting the words. */
.qsol-title::after {
    content: "";
    display: block;
    width: 54px;
    height: 3px;
    margin: 14px auto 0;
    border-radius: 3px;
    background: linear-gradient(90deg, #4f46e5, #a22dea);
}

/* ── prose band ─────────────────────────────────────────────────────────
 *
 * Two paragraphs of explanation, which only /solutions/by-hr-maturity-model
 * has — its "How It Works". Centred on the same 760px measure as the section
 * head above it so the band reads as one column rather than as a heading with
 * a wider body under it. */
.qsol-prose {
    max-width: 760px;
    margin: 0 auto;
    text-align: center;
}

.qsol-prose p {
    margin: 0 0 18px;
    font-size: clamp(15.5px, 1.15vw, 17px);
    line-height: 1.75;
    color: #5b5673;
}

.qsol-prose p:last-child {
    margin-bottom: 0;
}

/* ── hero ───────────────────────────────────────────────────────────────
 *
 * Copy on the left, the category panel on the right — the arrangement the page
 * already had. What changes is that the panel is now a raised white card on a
 * tinted band rather than a grey box on white, so the first screen has a focal
 * point instead of two equally flat halves. */
.qsol-hero {
    position: relative;
    overflow: hidden;
    padding: clamp(56px, 7vw, 92px) 0 clamp(60px, 7vw, 96px);
    background:
        radial-gradient(900px 520px at 12% -10%, rgba(79, 70, 229, .13), transparent 60%),
        radial-gradient(760px 520px at 88% 8%, rgba(162, 45, 234, .11), transparent 58%),
        #fbfaff;
}

/* A hairline of the ramp closing the band off from the section below it. */
.qsol-hero::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(124, 58, 237, .28) 30%, rgba(162, 45, 234, .28) 70%, transparent);
}

/* Two soft blooms, purely atmospheric, behind the content. */
.qsol-hero__orb {
    position: absolute;
    border-radius: 999px;
    filter: blur(70px);
    pointer-events: none;
}

.qsol-hero__orb--a {
    top: -120px;
    left: -80px;
    width: 380px;
    height: 380px;
    background: rgba(79, 70, 229, .18);
}

.qsol-hero__orb--b {
    right: -110px;
    bottom: -150px;
    width: 420px;
    height: 420px;
    background: rgba(162, 45, 234, .14);
}

.qsol-hero .boxed-container {
    position: relative;
    z-index: 1;
}

.qsol-hero__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 44px;
    align-items: center;
}

/* A grid child's default `min-width: auto` refuses to shrink below its content,
 * so one long unbroken string in the copy — a URL an editor pastes in — would
 * push the panel off the side of the band rather than wrapping. */
.qsol-hero__copy {
    min-width: 0;
}

.qsol-badge {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 8px 16px;
    border-radius: 999px;
    background: #fff;
    border: 1px solid #e7e4fb;
    box-shadow: 0 10px 26px -20px rgba(79, 70, 229, .55);
    font-size: 13px;
    font-weight: 650;
    letter-spacing: .01em;
    line-height: 1;
    color: #4f46e5;
}

.qsol-badge__dot {
    width: 7px;
    height: 7px;
    border-radius: 999px;
    flex: 0 0 auto;
    background: linear-gradient(135deg, #4f46e5, #a22dea);
    animation: qsol-pulse 2.4s ease-in-out infinite;
}

@keyframes qsol-pulse {
    0%, 100% { opacity: 1;   transform: scale(1); }
    50%      { opacity: .45; transform: scale(.82); }
}

.qsol-hero__title {
    margin: 20px 0 0;
    font-size: clamp(32px, 4.1vw, 54px);
    font-weight: 800;
    line-height: 1.08;
    letter-spacing: -.028em;
    color: #14103a;
}

.qsol-hero__lede {
    margin: 20px 0 0;
    max-width: 560px;
    font-size: clamp(15.5px, 1.15vw, 17.5px);
    line-height: 1.72;
    color: #5b5673;
}

/* .qh-hero__actions comes from home.css and already spaces the pair. The CMS
 * wrapper's line-height and the bundle's link underline are what need undoing. */
.qsol-page .qh-hero__actions {
    line-height: 1.2;
}

.qsol-page .qh-btn,
.qsol-page .qh-btn-ghost {
    text-decoration: none;
}

/* ── browse by category ─────────────────────────────────────────────────
 *
 * Four rows, each a numbered chip and a name/description pair, in the panel that
 * sat opposite the hero copy before and still does.
 *
 * THE CLICK TARGET IS UNCHANGED AND THAT IS DELIBERATE. In the stored markup the
 * anchor wraps the category name only; the description is a sibling paragraph
 * outside it. Growing the anchor to swallow the whole row would be a nicer
 * target, but it is a behaviour change, and the brief for this work was the
 * design. So the row lifts and tints on hover — including when the pointer is
 * over the description — while the thing that is actually clickable is still the
 * name. The chevron is drawn by this sheet on the anchor, so it moves with the
 * link rather than promising a click the row does not accept. */
.qsol-browse {
    position: relative;
    padding: 30px;
    border-radius: 22px;
    background: #fff;
    border: 1px solid #eceafb;
    box-shadow: 0 34px 70px -44px rgba(28, 20, 84, .55), 0 2px 6px -2px rgba(28, 20, 84, .07);
}

/* The ramp as a top edge, so the card belongs to the brand without being tinted
 * by it. */
.qsol-browse::before {
    content: "";
    position: absolute;
    top: 0;
    left: 26px;
    right: 26px;
    height: 3px;
    border-radius: 0 0 3px 3px;
    background: linear-gradient(90deg, #4f46e5, #7c3aed 50%, #a22dea);
}

.qsol-browse__label {
    margin: 0 0 18px;
    font-size: 12.5px;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: #4f46e5;
}

.qsol-browse__list {
    margin: 0;
    padding: 0;
    list-style: none;
}

/* The row. `--qsol-cat-*` are set by the four modifiers below; every rule in
 * here reads them rather than naming a hue, so the ramp is declared once. */
.qsol-cat {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 14px 14px 14px 12px;
    border-radius: 14px;
    border: 1px solid transparent;
    transition: background .25s, border-color .25s, transform .25s cubic-bezier(.2, .8, .2, 1);
}

.qsol-cat + .qsol-cat {
    margin-top: 6px;
}

.qsol-cat:hover {
    transform: translateX(3px);
    background: var(--qsol-cat-wash);
    border-color: var(--qsol-cat-edge);
}

.qsol-cat__num {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    border-radius: 11px;
    font-size: 13px;
    font-weight: 750;
    line-height: 1;
    color: #fff;
    background: var(--qsol-cat-fill);
    box-shadow: 0 10px 20px -12px var(--qsol-cat-glow);
    transition: transform .25s cubic-bezier(.2, .8, .2, 1);
}

.qsol-cat:hover .qsol-cat__num {
    transform: scale(1.06);
}

.qsol-cat__body {
    min-width: 0;
}

/* The anchor. Inline-flex so the chevron sits on the baseline of the name and
 * inside the link's own box — hovering the description must not move it. */
.qsol-cat__link {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: 15.5px;
    font-weight: 700;
    line-height: 1.35;
    color: #14103a;
    text-decoration: none;
    transition: color .2s;
}

.qsol-cat__link:hover,
.qsol-cat__link:focus-visible {
    color: var(--qsol-cat-ink);
    text-decoration: none;
}

/* Half a square rotated 45°, which needs no second element and no icon file. */
.qsol-cat__link::after {
    content: "";
    width: 6px;
    height: 6px;
    border-top: 1.7px solid currentColor;
    border-right: 1.7px solid currentColor;
    border-radius: 1px;
    transform: rotate(45deg);
    opacity: .45;
    transition: opacity .25s, transform .25s;
}

.qsol-cat:hover .qsol-cat__link::after {
    opacity: 1;
    transform: rotate(45deg) translate(2px, -2px);
}

.qsol-cat__desc {
    margin: 4px 0 0;
    font-size: 13.5px;
    line-height: 1.55;
    color: #6b6785;
}

/* The four stops. Indigo -> violet -> magenta -> gold, in the order the
 * categories are listed. */
.qsol-cat--indigo {
    --qsol-cat-fill: linear-gradient(135deg, #4f46e5, #6366f1);
    --qsol-cat-glow: rgba(79, 70, 229, .9);
    --qsol-cat-wash: #f4f2ff;
    --qsol-cat-edge: #ddd8fb;
    --qsol-cat-ink: #4f46e5;
}

.qsol-cat--violet {
    --qsol-cat-fill: linear-gradient(135deg, #7c3aed, #8b5cf6);
    --qsol-cat-glow: rgba(124, 58, 237, .9);
    --qsol-cat-wash: #f7f2ff;
    --qsol-cat-edge: #e2d5fb;
    --qsol-cat-ink: #7c3aed;
}

.qsol-cat--magenta {
    --qsol-cat-fill: linear-gradient(135deg, #a22dea, #b44df0);
    --qsol-cat-glow: rgba(162, 45, 234, .9);
    --qsol-cat-wash: #fbf2ff;
    --qsol-cat-edge: #ecd3fa;
    --qsol-cat-ink: #a22dea;
}

/* Gold is the brand's one secondary, and it is darkened to #9a7b12 for the link
 * hover: #d4af37 on white is 2.1:1, which is not readable body text. The chip
 * keeps the bright gold because its text is white on top of it. */
.qsol-cat--gold {
    --qsol-cat-fill: linear-gradient(135deg, #c19b1f, #d4af37);
    --qsol-cat-glow: rgba(196, 155, 31, .9);
    --qsol-cat-wash: #fdf8ec;
    --qsol-cat-edge: #eddfb4;
    --qsol-cat-ink: #9a7b12;
}

/* ── explore more ───────────────────────────────────────────────────────
 *
 * Nine navigation cards, each an icon tile and a name/description pair. Closest
 * to what the page already had, and kept that way: this row was the one part of
 * the old design that was not competing for attention. Same object as
 * .qpr-link on /products, because it is the same nine links. */
.qsol-explore {
    display: grid;
    grid-template-columns: 1fr;
    gap: 16px;
}

.qsol-link {
    display: flex;
    align-items: flex-start;
    gap: 15px;
    padding: 19px 20px;
    border-radius: 16px;
    background: #fff;
    border: 1px solid #e9e7f5;
    box-shadow: 0 18px 36px -38px rgba(28, 20, 84, .6);
    text-decoration: none;
    transition: transform .25s cubic-bezier(.2, .8, .2, 1), box-shadow .25s, border-color .25s;
}

.qsol-link:hover {
    transform: translateY(-3px);
    border-color: #cfc9f7;
    box-shadow: 0 26px 48px -30px rgba(79, 70, 229, .45);
    text-decoration: none;
}

.qsol-link__icon {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 42px;
    height: 42px;
    border-radius: 13px;
    color: #4f46e5;
    background: #f1effe;
    transition: color .25s, background .25s;
}

/* The nine SVGs carried `class="w-6 h-6"` in the old markup and nothing else
 * sized them. They are sized here so the CMS body holds no utility classes. */
.qsol-link__icon svg {
    width: 21px;
    height: 21px;
}

.qsol-link:hover .qsol-link__icon {
    color: #fff;
    background: linear-gradient(135deg, #4f46e5, #7c3aed);
}

.qsol-link__body {
    display: block;
    min-width: 0;
}

.qsol-link__name {
    display: block;
    font-size: 15px;
    font-weight: 700;
    line-height: 1.4;
    color: #14103a;
    transition: color .2s;
}

.qsol-link:hover .qsol-link__name {
    color: #4f46e5;
}

.qsol-link__desc {
    display: block;
    margin-top: 3px;
    font-size: 13px;
    line-height: 1.5;
    color: #7a7593;
}

/* ── closing band ───────────────────────────────────────────────────────
 *
 * The page's one dark surface, and its last. The old one was a flat
 * indigo-to-purple gradient with two pill buttons of its own invention; the
 * gradient stays, deepened, and the buttons are the site's own pair. */
.qsol-cta {
    position: relative;
    overflow: hidden;
    padding: clamp(64px, 7vw, 96px) 0;
    color: #f4f2ff;
    background:
        radial-gradient(720px 420px at 14% 0%, rgba(124, 58, 237, .55), transparent 62%),
        radial-gradient(680px 420px at 88% 100%, rgba(162, 45, 234, .45), transparent 60%),
        linear-gradient(120deg, #241a5c, #17123a);
}

.qsol-cta__orb {
    position: absolute;
    border-radius: 999px;
    filter: blur(80px);
    pointer-events: none;
}

.qsol-cta__orb--a {
    top: -160px;
    left: -90px;
    width: 400px;
    height: 400px;
    background: rgba(79, 70, 229, .35);
}

.qsol-cta__orb--b {
    right: -120px;
    bottom: -170px;
    width: 440px;
    height: 440px;
    background: rgba(162, 45, 234, .28);
}

.qsol-cta .boxed-container {
    position: relative;
    z-index: 1;
}

.qsol-cta__inner {
    max-width: 780px;
    margin: 0 auto;
    text-align: center;
}

.qsol-cta__title {
    margin: 0;
    font-size: clamp(26px, 3vw, 40px);
    font-weight: 800;
    line-height: 1.15;
    letter-spacing: -.024em;
    color: #fff;
}

.qsol-cta__lede {
    margin: 16px 0 0;
    font-size: clamp(15.5px, 1.2vw, 17.5px);
    line-height: 1.7;
    color: #cac4e8;
}

.qsol-cta .qh-hero__actions {
    justify-content: center;
}

/* On the dark band the ghost button's white fill is the contrast it needs; only
 * its resting border is too bright against it. */
.qsol-cta .qh-btn-ghost {
    border-color: transparent;
}

/* ── breakpoints ────────────────────────────────────────────────────────
 *
 * Mobile-first: every grid above is one column, and each step below adds
 * columns. Ordered narrow to wide so later rules win. */
@media (min-width: 760px) {
    .qsol-explore {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 1024px) {
    .qsol-hero__grid {
        grid-template-columns: minmax(0, 1.06fr) minmax(0, .94fr);
        gap: 60px;
    }

    .qsol-browse {
        padding: 34px;
    }

    .qsol-explore {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

/* ── motion and focus ───────────────────────────────────────────────────
 *
 * None of the transforms above is load-bearing, so they all go when the visitor
 * has asked for less motion. */
@media (prefers-reduced-motion: reduce) {
    .qsol-badge__dot {
        animation: none;
    }

    .qsol-cat,
    .qsol-cat__num,
    .qsol-cat__link::after,
    .qsol-link {
        transition: none;
    }

    .qsol-cat:hover,
    .qsol-cat:hover .qsol-cat__num,
    .qsol-link:hover {
        transform: none;
    }

    /* The chevron's rotate is what makes it a chevron rather than a corner of a
     * square, so only the 2px nudge goes. */
    .qsol-cat:hover .qsol-cat__link::after {
        transform: rotate(45deg);
    }
}

/* Keyboard users get the same affordance a mouse gets, plus a ring. The bundle
 * strips outlines from links site-wide, so this has to be explicit. */
.qsol-cat__link:focus-visible,
.qsol-link:focus-visible {
    outline: 3px solid rgba(79, 70, 229, .45);
    outline-offset: 3px;
    border-radius: 8px;
}
