/* ==========================================================================
   WizeTek content — posts, roles, article bodies, sidebars, trust bar, map
   Depends on tokens.css, base.css and components.css.
   ========================================================================== */

/* ==========================================================================
   Trust bar
   ========================================================================== */

.wz-trustbar {
    padding-block: var(--wz-s-7);
    background: var(--wz-ground);
    border-block: 1px solid var(--wz-rule);
}

.wz-trustbar__label {
    text-align: center;
    font-size: var(--wz-fs-label);
    font-weight: 600;
    letter-spacing: var(--wz-tracking-label);
    text-transform: uppercase;
    color: var(--wz-ink-faint);
    margin: 0 0 var(--wz-s-5);
}

/* The wall scrolls at roughly the pace the mesh nodes drift, so the two read as
   one movement rather than two competing ones. It fades at both edges instead of
   cutting off, and pauses on hover so a logo can actually be looked at. */
.wz-logowall {
    display: flex;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(
        90deg,
        transparent 0%,
        #000 7%,
        #000 93%,
        transparent 100%
    );
    mask-image: linear-gradient(
        90deg,
        transparent 0%,
        #000 7%,
        #000 93%,
        transparent 100%
    );
}

.wz-logowall__track {
    display: flex;
    flex: none;
    align-items: center;
    gap: var(--wz-s-8);
    margin: 0;
    /* Inline: half a gap each side, so the two halves meet across the seam and
       read as one full gap, and each track is exactly as wide as the distance it
       travels. Block: headroom for the hover scale - the wall clips its
       overflow, so without it a raised mark is cut off top and bottom. Block
       padding does not affect track width, so the seam maths still holds. */
    padding: var(--wz-s-2) calc(var(--wz-s-8) / 2);
    list-style: none;
    animation: wz-marquee var(--wz-marquee-duration, 34s) linear infinite;
}

.wz-logowall:hover .wz-logowall__track,
.wz-logowall:focus-within .wz-logowall__track {
    animation-play-state: paused;
}

@keyframes wz-marquee {
    to {
        transform: translateX(-100%);
    }
}

/* A 56px gap and a 34px mark are sized for a 1440px band; on a phone that is
   two logos per screen with holes between them. Gap and padding move together -
   the padding is half the gap, and that is what keeps the loop seamless. */
@media (max-width: 640px) {
    .wz-logowall__track {
        gap: var(--wz-s-6);
        padding-inline: calc(var(--wz-s-6) / 2);
    }

    .wz-logowall img,
    .wz-logowall__name {
        width: 104px;
        height: 36px;
    }

    .wz-logowall__name {
        font-size: 0.8rem;
    }

    .wz-logowall {
        -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 12%, #000 88%, transparent 100%);
        mask-image: linear-gradient(90deg, transparent 0%, #000 12%, #000 88%, transparent 100%);
    }
}

/* No movement, and no duplicate: back to a plain centred row. */
@media (prefers-reduced-motion: reduce) {
    .wz-logowall {
        justify-content: center;
        mask-image: none;
        -webkit-mask-image: none;
    }

    .wz-logowall__track {
        /* flex: none is what keeps the track at full width while it scrolls.
           With the scroll off it has to shrink to the container instead, or it
           stays one long row and overflow: hidden clips half the logos away. */
        flex: 1 1 auto;
        min-width: 0;
        flex-wrap: wrap;
        justify-content: center;
        gap: var(--wz-s-5) var(--wz-s-8);
        animation: none;
        padding: 0;
    }

    .wz-logowall__track[aria-hidden="true"] {
        display: none;
    }
}

/* Every mark gets the same box.

   Client artwork arrives at every proportion - a 5:1 wordmark, a stacked
   lockup, a square crest. Sizing on height alone gave them the same height and
   wildly different widths: LTIMindtree came out 178px across and the Porsche
   crest 34px, which reads as one client shouting and another whispering.

   A fixed box with object-fit: contain evens that out. Wide marks fill the
   width, tall ones the height, and each takes the same footprint on the bar. */
.wz-logowall img,
.wz-logowall__name {
    width: 140px;
    /* 44 rather than 48: contain scales a mark *up* to fill the box, and six of
       these came from the old theme at display resolution. A taller box would
       upscale the smallest of them past the point where it stays sharp. */
    height: 44px;
    flex: none;
}

.wz-logowall img {
    object-fit: contain;
    object-position: center;
}

/* Clients who have not sent artwork yet. A set wordmark is honest and reads as
   deliberate, where a broken image or an empty gap reads as unfinished. It takes
   the same box as a real mark, so the rhythm of the bar does not break. */
.wz-logowall__name {
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    font-family: var(--wz-font-display);
    font-size: 0.95rem;
    font-weight: 700;
    letter-spacing: 0.005em;
    line-height: 1.2;
    text-wrap: balance;
    color: var(--wz-ink-muted);
}

/* Every mark was greyed to 62% before. A client who has agreed to be named
   should appear as themselves, so the mute is gone and hover does the work
   instead: the marquee is already paused by then, so the one under the cursor
   simply steps forward. */
.wz-logowall li {
    flex: none;
    transition: transform var(--wz-dur) var(--wz-ease);
}

.wz-logowall li:hover,
.wz-logowall li:focus-within {
    transform: scale(1.14);
}

.wz-logowall li:hover .wz-logowall__name,
.wz-logowall li:focus-within .wz-logowall__name {
    color: var(--wz-blue);
}

/* ==========================================================================
   Post cards — Insights list and the homepage strip
   ========================================================================== */

.wz-post {
    display: flex;
    flex-direction: column;
    background: var(--wz-white);
    border: 1px solid var(--wz-rule);
    border-radius: var(--wz-r);
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    transition:
        border-color var(--wz-dur) var(--wz-ease),
        box-shadow var(--wz-dur) var(--wz-ease),
        transform var(--wz-dur) var(--wz-ease);
}

.wz-post:hover {
    border-color: var(--wz-azure);
    box-shadow: var(--wz-shadow);
    transform: translateY(-2px);
}

.wz-post__media {
    aspect-ratio: 16 / 9;
    background: var(--wz-ground-2);
    overflow: hidden;
}

.wz-post__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.wz-post__body {
    display: flex;
    flex-direction: column;
    gap: var(--wz-s-3);
    padding: var(--wz-s-5);
    flex: 1;
}

.wz-post__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--wz-s-2) var(--wz-s-4);
    font-size: var(--wz-fs-xs);
    color: var(--wz-ink-faint);
}

.wz-post__meta span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.wz-post__meta svg {
    width: 14px;
    height: 14px;
}

.wz-post__title {
    margin: 0;
}

.wz-post__excerpt {
    margin: 0;
    font-size: var(--wz-fs-sm);
    color: var(--wz-ink-muted);
}

.wz-post__more {
    margin-top: auto;
    padding-top: var(--wz-s-3);
    display: inline-flex;
    align-items: center;
    gap: var(--wz-s-2);
    font-size: var(--wz-fs-sm);
    font-weight: 600;
    color: var(--wz-blue);
}

/* ==========================================================================
   Article body
   ========================================================================== */

.wz-article {
    display: flex;
    flex-direction: column;
    gap: var(--wz-s-5);
}

.wz-article__cover {
    border-radius: var(--wz-r);
    overflow: hidden;
    background: var(--wz-ground-2);
}

.wz-article__cover img {
    width: 100%;
    height: auto;
}

.wz-article__body {
    max-width: var(--wz-measure);
    font-size: var(--wz-fs-body);
}

.wz-article__body p {
    margin-bottom: var(--wz-s-4);
}

.wz-article__body h2,
.wz-article__body h3 {
    margin-top: var(--wz-s-6);
    margin-bottom: var(--wz-s-3);
}

.wz-article__body ul,
.wz-article__body ol {
    margin-bottom: var(--wz-s-4);
}

.wz-article__body li {
    margin-bottom: var(--wz-s-2);
}

/* Article page and sidebar side by side. */
.wz-with-aside {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: var(--wz-s-8);
    align-items: start;
}

@media (max-width: 960px) {
    .wz-with-aside {
        grid-template-columns: 1fr;
        gap: var(--wz-s-7);
    }
}

/* ==========================================================================
   Sidebar widgets
   ========================================================================== */

.wz-widget {
    display: flex;
    flex-direction: column;
    gap: var(--wz-s-4);
    padding: var(--wz-s-5);
    border: 1px solid var(--wz-rule);
    border-radius: var(--wz-r);
    background: var(--wz-ground);
}

.wz-widget__title {
    margin: 0;
    font-family: var(--wz-font-body);
    font-size: var(--wz-fs-label);
    font-weight: 600;
    letter-spacing: var(--wz-tracking-label);
    text-transform: uppercase;
    color: var(--wz-ink-faint);
}

.wz-widget__list {
    display: flex;
    flex-direction: column;
    gap: var(--wz-s-4);
    margin: 0;
    padding: 0;
    list-style: none;
}

.wz-minipost {
    display: grid;
    grid-template-columns: 72px 1fr;
    gap: var(--wz-s-3);
    align-items: start;
    text-decoration: none;
    color: inherit;
}

.wz-minipost__media {
    aspect-ratio: 1;
    border-radius: var(--wz-r-sm);
    overflow: hidden;
    background: var(--wz-ground-2);
}

.wz-minipost__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.wz-minipost__title {
    margin: 0 0 4px;
    font-family: var(--wz-font-display);
    font-size: var(--wz-fs-sm);
    font-weight: 600;
    line-height: 1.35;
}

.wz-minipost:hover .wz-minipost__title {
    color: var(--wz-blue);
}

.wz-minipost__date {
    font-size: var(--wz-fs-xs);
    color: var(--wz-ink-faint);
}

/* ==========================================================================
   Role cards — Careers
   ========================================================================== */

.wz-role {
    display: flex;
    flex-direction: column;
    gap: var(--wz-s-4);
    padding: var(--wz-s-6);
    border: 1px solid var(--wz-rule);
    border-radius: var(--wz-r);
    background: var(--wz-white);
    text-decoration: none;
    color: inherit;
    transition:
        border-color var(--wz-dur) var(--wz-ease),
        box-shadow var(--wz-dur) var(--wz-ease),
        transform var(--wz-dur) var(--wz-ease);
}

.wz-role:hover {
    border-color: var(--wz-azure);
    box-shadow: var(--wz-shadow);
    transform: translateY(-2px);
}

.wz-role__title {
    margin: 0;
}

.wz-role__text {
    margin: 0;
    font-size: var(--wz-fs-sm);
    color: var(--wz-ink-muted);
}

.wz-role__facts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--wz-s-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.wz-role__more {
    margin-top: auto;
    padding-top: var(--wz-s-2);
    display: inline-flex;
    align-items: center;
    gap: var(--wz-s-2);
    font-size: var(--wz-fs-sm);
    font-weight: 600;
    color: var(--wz-blue);
}

.wz-meta-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--wz-s-3) var(--wz-s-5);
    font-size: var(--wz-fs-sm);
    color: var(--wz-ink-muted);
}

.wz-meta-row span {
    display: inline-flex;
    align-items: center;
    gap: var(--wz-s-2);
}

.wz-meta-row svg {
    width: 16px;
    height: 16px;
    color: var(--wz-ink-faint);
}

/* ==========================================================================
   Contact details and map
   ========================================================================== */

.wz-contact-cards {
    display: grid;
    gap: var(--wz-s-4);
}

.wz-contact-card {
    display: grid;
    grid-template-columns: 44px 1fr;
    gap: var(--wz-s-4);
    align-items: start;
    padding: var(--wz-s-5);
    border: 1px solid var(--wz-rule);
    border-radius: var(--wz-r);
    background: var(--wz-white);
}

.wz-contact-card__icon {
    display: grid;
    place-items: center;
    width: 42px;
    height: 42px;
    border-radius: var(--wz-r-sm);
    background: rgba(22, 87, 199, 0.08);
    color: var(--wz-blue);
}

.wz-contact-card__icon svg {
    width: 20px;
    height: 20px;
}

.wz-contact-card__label {
    font-size: var(--wz-fs-label);
    font-weight: 600;
    letter-spacing: var(--wz-tracking-label);
    text-transform: uppercase;
    color: var(--wz-ink-faint);
    margin: 0 0 4px;
}

.wz-contact-card__value {
    margin: 0;
    font-size: var(--wz-fs-sm);
    color: var(--wz-ink);
}

.wz-contact-card__value a {
    color: inherit;
    text-decoration: none;
}

.wz-contact-card__value a:hover {
    color: var(--wz-blue);
    text-decoration: underline;
}

/* Placeholder until a real embed is wired up - see the launch checklist. */
.wz-map {
    position: relative;
    display: grid;
    place-items: center;
    min-height: 340px;
    border: 1px dashed var(--wz-rule-strong);
    border-radius: var(--wz-r);
    background:
        repeating-linear-gradient(
            45deg,
            var(--wz-ground) 0 12px,
            var(--wz-ground-2) 12px 24px
        );
    text-align: center;
    padding: var(--wz-s-6);
}

.wz-map__inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--wz-s-3);
    color: var(--wz-ink-muted);
    font-size: var(--wz-fs-sm);
}

.wz-map__inner svg {
    width: 30px;
    height: 30px;
    color: var(--wz-blue);
}

.wz-map iframe {
    width: 100%;
    height: 100%;
    min-height: 340px;
    border: 0;
    border-radius: var(--wz-r);
}

/* ==========================================================================
   Empty states
   ========================================================================== */

/* An empty state is the emptiest thing on the site by definition - on Vacancy it
   is the whole section. The lattice gives it a floor to sit on, so the dashed box
   reads as a considered placeholder rather than a gap in the page. */
.wz-empty {
    position: relative;
    isolation: isolate;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--wz-s-4);
    padding: var(--wz-s-9) var(--wz-s-5);
    border: 1px dashed var(--wz-rule-strong);
    border-radius: var(--wz-r);
    background: var(--wz-ground);
    text-align: center;
    color: var(--wz-ink-muted);
}
.wz-empty::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
    background-image: radial-gradient(
        circle at 1px 1px,
        var(--wz-deco-node) 1.5px,
        transparent 1.5px
    );
    background-size: 24px 24px;
    -webkit-mask-image: radial-gradient(70% 70% at 50% 50%, #000 0%, transparent 72%);
    mask-image: radial-gradient(70% 70% at 50% 50%, #000 0%, transparent 72%);
}


/* ==========================================================================
   Error pages
   ========================================================================== */

.wz-errorpage {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--wz-s-5);
    text-align: center;
    max-width: 52ch;
    margin-inline: auto;
}

.wz-errorpage__code {
    font-family: var(--wz-font-display);
    font-size: clamp(4.5rem, 3rem + 7vw, 8rem);
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.04em;
    color: var(--wz-sky);
    font-variant-numeric: tabular-nums;
}

.wz-errorpage__text {
    margin: 0;
    color: var(--wz-on-dark-muted);
    font-size: var(--wz-fs-lead);
}

/* ==========================================================================
   Testimonials
   ========================================================================== */

/* ---- testimonial marquee -------------------------------------------------
   Built like the logo wall: two tracks, each holding the set twice, each
   sliding exactly its own width so the second lands where the first began. No
   JavaScript, nothing measured, and the loop closes seamlessly.

   Quotes are meant to be read, so this runs slower than the logo wall and stops
   the moment a pointer or the keyboard enters it. */
.wz-quotewall {
    display: flex;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(
        90deg,
        transparent 0%,
        #000 4%,
        #000 96%,
        transparent 100%
    );
    mask-image: linear-gradient(
        90deg,
        transparent 0%,
        #000 4%,
        #000 96%,
        transparent 100%
    );
}

.wz-quotewall__track {
    display: flex;
    flex: none;
    align-items: stretch;
    gap: var(--wz-s-5);
    /* Half a gap each side: the halves meet across the seam and read as one. */
    padding: 4px calc(var(--wz-s-5) / 2) 14px;
    margin: 0;
    list-style: none;
    animation: wz-quotemarquee var(--wz-quotewall-duration, 80s) linear infinite;
}

.wz-quotewall:hover .wz-quotewall__track,
.wz-quotewall:focus-within .wz-quotewall__track {
    animation-play-state: paused;
}

@keyframes wz-quotemarquee {
    to {
        transform: translateX(-100%);
    }
}

.wz-quotewall__slide {
    display: flex;
    flex: none;
    width: min(380px, 82vw);
}

.wz-quotewall__slide > .wz-quote {
    width: 100%;
}

/* No movement, and no duplicate: back to a plain wrapped row. */
@media (prefers-reduced-motion: reduce) {
    .wz-quotewall {
        mask-image: none;
        -webkit-mask-image: none;
    }

    .wz-quotewall__track {
        /* flex: none keeps the track at full width while it scrolls. With the
           scroll off it has to shrink to the container instead, or it stays one
           long row and overflow: hidden clips most of it away. */
        flex: 1 1 auto;
        min-width: 0;
        flex-wrap: wrap;
        justify-content: center;
        animation: none;
        padding-inline: 0;
    }

    .wz-quotewall__track[aria-hidden="true"] {
        display: none;
    }
}

.wz-quote {
    position: relative;
    display: flex;
    /* Quotes vary in length and that is fine - each card ends where its own
       content ends rather than stretching to match the tallest beside it. */
    align-self: flex-start;
    flex-direction: column;
    gap: var(--wz-s-4);
    padding: var(--wz-s-6);
    border: 1px solid var(--wz-rule);
    /* A blue edge ties the card to the rest of the site. Left rather than top:
       the pillar cards already own the top accent. */
    border-left: 3px solid var(--wz-blue);
    border-radius: var(--wz-r);
    background: var(--wz-white);
    transition:
        border-color var(--wz-dur) var(--wz-ease),
        box-shadow var(--wz-dur) var(--wz-ease),
        transform var(--wz-dur) var(--wz-ease);
}

.wz-quote:hover {
    border-inline-end-color: var(--wz-rule-strong);
    border-block-color: var(--wz-rule-strong);
    box-shadow: var(--wz-shadow);
    transform: translateY(-3px);
}

/* Tucked into the corner at low opacity, behind the text: it should frame the
   quote, not announce it. Out of flow so it costs the card no height. */
.wz-quote__mark {
    position: absolute;
    top: 6px;
    left: 14px;
    z-index: 0;
    font-family: var(--wz-font-display);
    font-size: 3.2rem;
    line-height: 1;
    color: var(--wz-sky);
    opacity: 0.28;
    pointer-events: none;
}

.wz-quote__tag {
    align-self: flex-start;
    position: relative;
    z-index: 1;
    font-size: var(--wz-fs-xs);
    font-weight: 600;
    letter-spacing: var(--wz-tracking-label);
    text-transform: uppercase;
    color: var(--wz-blue);
    background: rgba(22, 87, 199, 0.09);
    border-radius: var(--wz-r-pill);
    padding: 3px 10px;
}

.wz-quote__text {
    position: relative;
    z-index: 1;
    margin: 0;
    /* ~45-55 characters: past that a quote stops reading as speech. */
    max-width: 52ch;
    font-size: var(--wz-fs-body);
    line-height: 1.6;
    color: var(--wz-ink);
}

.wz-quote__rating {
    display: flex;
    gap: 2px;
    color: var(--wz-azure);
}

.wz-quote__rating svg {
    width: 16px;
    height: 16px;
}

.wz-quote__author {
    display: grid;
    grid-template-columns: 40px 1fr;
    gap: var(--wz-s-3);
    align-items: center;
    margin-top: auto;
    padding-top: var(--wz-s-4);
    border-top: 1px solid var(--wz-rule);
}

/* Name over role in one left column. Both were inline spans, so they ran
   together on a single line. */
.wz-quote__who {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.wz-quote__avatar {
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    overflow: hidden;
    background: rgba(22, 87, 199, 0.1);
    color: var(--wz-blue);
    font-family: var(--wz-font-display);
    font-size: var(--wz-fs-sm);
    font-weight: 700;
}

.wz-quote__avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Stands in when a quote is attributed to a role rather than a person, so there
   are no initials to set. */
.wz-quote__avatar-icon {
    width: 19px;
    height: 19px;
}

.wz-quote__name {
    font-family: var(--wz-font-display);
    font-weight: 600;
    font-size: var(--wz-fs-sm);
    color: var(--wz-ink);
}

.wz-quote__role {
    font-size: var(--wz-fs-xs);
    color: var(--wz-ink-muted);
}

.wz-quote__video {
    display: inline-flex;
    align-items: center;
    gap: var(--wz-s-2);
    font-size: var(--wz-fs-sm);
    font-weight: 600;
    color: var(--wz-blue);
}

/* On dark bands the card needs the translucent treatment the rest use. */
.wz-on-dark .wz-quote {
    background: var(--wz-on-dark-panel);
    border-color: var(--wz-on-dark-rule);
}

.wz-on-dark .wz-quote__text {
    color: var(--wz-on-dark);
}

.wz-on-dark .wz-quote__author {
    border-top-color: var(--wz-on-dark-rule);
}

.wz-on-dark .wz-quote__avatar {
    background: rgba(90, 182, 255, 0.14);
    color: var(--wz-sky);
}

.wz-on-dark .wz-quote__role {
    color: var(--wz-on-dark-muted);
}

.wz-on-dark .wz-quote__name {
    color: var(--wz-white);
}

.wz-on-dark .wz-quote__tag {
    color: var(--wz-sky);
    background: rgba(90, 182, 255, 0.14);
}

.wz-on-dark .wz-quote:hover {
    border-inline-end-color: var(--wz-on-dark-rule-strong, var(--wz-sky));
    border-block-color: var(--wz-on-dark-rule-strong, var(--wz-sky));
}

.wz-on-dark .wz-quote__video {
    color: var(--wz-sky);
}

/* Project cards have no cover until one is uploaded; this keeps the card's
   proportions instead of collapsing the media band to nothing. */
.wz-post__placeholder {
    display: grid;
    place-items: center;
    width: 100%;
    height: 100%;
    background:
        url("../img/mesh/mesh-panel.996bd3c8cf8a.svg") center / cover no-repeat,
        linear-gradient(160deg, var(--wz-navy) 0%, var(--wz-navy-900) 100%);
    color: var(--wz-sky);
}

.wz-post__placeholder svg {
    width: 42px;
    height: 42px;
    opacity: 0.7;
}
