/*
 * insights-news.css — Styles for the Insights and News content archives and
 * their related widgets. Parallel to careers.css: dedicated to the VL-46 epic
 * (Insights / News / Content Hubs) so archive-specific selectors don't leak
 * into the careers stylesheet where they don't belong.
 *
 * Scope:
 *   - Insights Hubs widget (elementor-widgets/insights-hubs.php)
 *   - Any Insights/News-archive-specific overrides for shared widgets
 *
 * Shared widget baselines (Featured Hero, etc.) still live in
 * assets/css/style.css since they're used on the Services page and elsewhere.
 * Only add rules here that are specific to the Insights/News archive context.
 */

/* ===== Featured Hero — archive-mode overrides =====
 *
 * The Featured Hero widget is shared with the Services page (VL-52). Rules in
 * this section only fire on the archive (via `body.category` — WP adds this
 * class to every category archive) so the Services rendering stays untouched.
 */

/* Vertically center the left column (tabs / title / intro) against the
 * pinned-insight panel on the right. The grid child gets align-self: center;
 * the inner flex column stacks its content with proper alignment inside the
 * centered box. Applies only at ≥1100px where the hero grid splits into two
 * columns; below that the panel is hidden and the main column runs full width
 * from the top like normal. */
@media (min-width: 1100px) {
    body.category .vl-featured-hero__main {
        align-self: center;
        display: flex;
        flex-direction: column;
        justify-content: center;
    }
}

/* Mobile-only right padding on the archive hero intro copy. The intro sits
 * inside the hero card which has enough left padding already, but the right
 * edge was reading as touching the screen edge on small viewports — this
 * adds ~10px of breathing room per design QA. Scoped to `body.category` so
 * the Services page's Featured Hero (which uses the same widget) is
 * untouched. */
@media (max-width: 767px) {
    body.category .vl-featured-hero__intro {
        padding-right: 10px;
    }
}


/* ===== Insights Hubs — VL-46 =====
 *
 * Auto-populated carousel on the Insights archive that renders every hub-flagged
 * practice/industry term as a card. Sand-brighter section background; white cards
 * with a small "Insights Hub" pill + a taxonomy-label ("Practice" / "Industry")
 * above the term title. Header row carries the section title + blurb on the left
 * and a "current/total" counter + prev/next arrows on the right. Cards flow
 * horizontally via Swiper (slidesPerView: auto).
 */
/*
 * Widget outer bounds — sand-brighter box capped at 1299px, centered. On
 * desktop the box pulls itself up 80px so its top edge overlaps the tail of
 * the Featured Hero above. Below 1024px the overlap collapses (the hero
 * doesn't have a bottom padding to invade at those sizes).
 */
.vl-insights-hubs {
    background-color: var(--vl-sand-brighter);
    max-width: 1299px;
    margin-inline: auto;
    padding-block: 32px;
    position: relative;
    z-index: 1;
}

@media (min-width: 1024px) {
    .vl-insights-hubs {
        margin-top: -60px;
        padding-block: 60px;
    }
}

.vl-insights-hubs-header {
    align-items: flex-end;
    display: flex;
    flex-wrap: wrap;
    gap: 24px;
    grid-column: 1 / -1;
    justify-content: space-between;
    margin-bottom: 24px;
}

/* Mobile spacing: controls sit closer to the description (8px) and the whole
 * header sits 16px above the carousel (vs 32px at desktop). */
@media (max-width: 767px) {
    .vl-insights-hubs-header {
        gap: 8px;
        margin-bottom: 16px;
    }
}

.vl-insights-hubs-heading {
    flex: 1 1 auto;
    max-width: 720px;
}

.vl-insights-hubs-title {
    color: var(--vl-olive);
    margin: 0 0 8px;
}

.vl-insights-hubs-blurb {
    color: var(--vl-olive);
    margin: 0;
}

/* Controls (counter + prev/next arrows) — right side of the header row.
 * 7px gap matches the pinned-insight `.vl-featured-hero__panel-nav` spacing so
 * the two carousels feel like siblings. `margin-left: auto` keeps them pinned
 * to the right edge in both layouts: inline with the heading (justify-content:
 * space-between handles it) AND stacked on their own row on mobile (where
 * space-between doesn't help since there's only one flex item on that row). */
.vl-insights-hubs-controls {
    align-items: center;
    display: flex;
    flex: 0 0 auto;
    gap: 7px;
    margin-left: auto;
}

.vl-insights-hubs-counter {
    color: var(--vl-black);
    /* Space around the divider so 1 / 3 breathes rather than looking mashed. */
    letter-spacing: 0.02em;
}

.vl-insights-hubs-counter-divider {
    margin: 0 4px;
    opacity: 0.5;
}

/*
 * Nav buttons: 20×20 black circles with the sand-brighter arrow icon,
 * matching the pinned-insight arrows treatment on the archive hero. Parent-
 * class prefix bumps specificity to (0,2,0) so these styles beat Elementor's
 * generic button rule.
 */
.vl-insights-hubs .vl-insights-hubs-prev,
.vl-insights-hubs .vl-insights-hubs-next {
    align-items: center;
    background-color: var(--vl-black);
    border: 0;
    border-radius: 50%;
    color: var(--vl-sand-brighter);
    cursor: pointer;
    display: inline-flex;
    height: 20px;
    justify-content: center;
    padding: 0;
    transition: opacity 200ms ease;
    width: 20px;
}

.vl-insights-hubs .vl-insights-hubs-prev:hover,
.vl-insights-hubs .vl-insights-hubs-next:hover,
.vl-insights-hubs .vl-insights-hubs-prev:focus-visible,
.vl-insights-hubs .vl-insights-hubs-next:focus-visible {
    opacity: 0.7;
}

.vl-insights-hubs .vl-insights-hubs-prev.swiper-button-disabled,
.vl-insights-hubs .vl-insights-hubs-next.swiper-button-disabled {
    cursor: default;
    opacity: 0.4;
}

/* Locked (all cards fit, no scrolling) — Swiper toggles .swiper-button-lock via
 * watchOverflow: true. Hide both arrows AND the counter in that case so the
 * header doesn't show useless controls. */
.vl-insights-hubs .vl-insights-hubs-prev.swiper-button-lock,
.vl-insights-hubs .vl-insights-hubs-next.swiper-button-lock {
    display: none;
}

.vl-insights-hubs-prev svg,
.vl-insights-hubs-next svg {
    height: 100%;
    width: 100%;
}

.vl-insights-hubs-prev svg {
    transform: scaleX(-1);
}

/* Track — outer container for the carousel. On mobile it carries the 20px
 * left/right gutters so the swiper is inset from the section edges without
 * fighting Swiper's own transform math (padding on the swiper itself gets
 * clipped by overflow: hidden and misaligns the slide translation). Desktop
 * drops the gutter — the 1109px max-width on the swiper + auto margin do the
 * centering. */
.vl-insights-hubs-track {
    grid-column: 1 / -1;
    padding:0 20px;
}

@media (min-width: 1149px) {
    .vl-insights-hubs-track {
        padding-inline: 0;
    }
}

.vl-insights-hubs-swiper {
    max-width: 1109px;
    margin-inline: auto;
    overflow: hidden;
}

/* Equal-height cards — Swiper's `.swiper-wrapper` is a row flex; `align-items:
 * stretch` (default, forced here for clarity) makes every slide match the
 * tallest slide's height. Slides themselves are column-flex, so the card
 * inside (with `flex: 1`) fills that height vertically. Without the
 * `flex-direction: column` on the slide, `flex: 1` on the card would only
 * grow it horizontally and heights would end up content-driven. */
.vl-insights-hubs-swiper .swiper-wrapper {
    align-items: stretch;
}

.vl-insights-hubs-slide.swiper-slide {
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    height: auto;
}

/* Selectors are prefixed with `.vl-insights-hubs` (specificity 0,2,0) so they
 * beat `.elementor-kit-9 a` / `a:hover` (0,1,1), which was otherwise dragging
 * an underline onto every text element in the card link. */
.vl-insights-hubs .vl-insights-hubs-card,
.vl-insights-hubs .vl-insights-hubs-card:hover,
.vl-insights-hubs .vl-insights-hubs-card:focus,
.vl-insights-hubs .vl-insights-hubs-card:focus-visible {
    background-color: var(--vl-white);
    color: var(--vl-black);
    text-decoration: none;
}

.vl-insights-hubs-card {
    display: block;
    flex-direction: column;
    flex: 1;
    gap: 16px;
    min-height: 148px;
    /* 16px top + sides, 24px bottom per design QA — extra room under the
     * card title for visual breathing before the card border. */
    padding: 16px 16px 24px;
    width: 100%;
}

/* Focus outline for keyboard nav — no lift/shadow on either hover or focus
 * per client request. Title-underline (defined above) is the only hover cue. */
.vl-insights-hubs-card:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 4px;
}

/* Only the term title gets a hover underline — 1px thickness, 2px offset,
 * matching the Featured Hero card treatment. Pill + tax label stay clean. */
.vl-insights-hubs .vl-insights-hubs-card:hover .vl-insights-hubs-card-title,
.vl-insights-hubs .vl-insights-hubs-card:focus-visible .vl-insights-hubs-card-title {
    color: var(--vl-brown);
    text-decoration: none;
}

/* Tag row: cream "Insights Hub" pill + plain-text taxonomy label. Stacks on
 * mobile (pill on its own line, tax label below) and goes inline at ≥768px
 * per the comp. Desktop uses align-items: center so the pill and label sit
 * on the same baseline once inline. */
.vl-insights-hubs-card-tags {
    align-items: flex-start;
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 8px;
}

@media (min-width: 768px) {
    .vl-insights-hubs-card-tags {
        align-items: center;
        flex-direction: row;
        flex-wrap: wrap;
    }
}

/* Pill: inline-flex so the leading icon aligns to the text baseline without
 * an ad-hoc line-height dance. Sub-pixel gap sits between icon and label.
 * Text + icon (stroked via currentColor) are black on the cream fill. */
.vl-insights-hubs-card-pill {
    align-items: center;
    background-color: var(--vl-cream);
    color: var(--vl-black);
    display: inline-flex;
    gap: 4px;
    padding: 4px 8px;
}

.vl-insights-hubs-card-pill-icon {
    align-items: center;
    display: inline-flex;
    height: 12px;
    justify-content: center;
    width: 12px;
}

.vl-insights-hubs-card-pill-icon svg {
    display: block;
    height: 100%;
    width: 100%;
}

.vl-insights-hubs-card-tax-label {
    color: var(--vl-black);
}

.vl-insights-hubs-card-title {
    color: var(--vl-olive);
    margin: 0;
}


/* ===== Archive body (title + filter form + results) =====
 *
 * Section-level wrappers below the Insights Hubs module. The filter form HTML
 * is emitted by Search & Filter Pro; we scope the styling to
 * `.vl-insights-news-filter` so it can't leak to any other place the plugin
 * gets used (older attorney or search filters). Class names to override look
 * like `.searchandfilter` (the outer form) and `.sf-field-*` (each filter).
 */

.vl-insights-news-archive-body {
    padding-block: 40px 96px;
}

.vl-insights-news-archive-body-inner {
    grid-column: 1 / -1;
}

.vl-insights-news-archive-title {
    color: var(--vl-black);
    margin: 0 0 32px;
}

@media (min-width: 1024px) {
    .vl-insights-news-archive-title {
        margin-bottom: 40px;
    }
}

/* ===== Search & Filter Pro filter form =====
 *
 * S&F Pro emits a <form.searchandfilter> with a <ul> of <li.sf-field-*> items.
 * Each item wraps a <label> + control (<select> for taxonomy filters, <input>
 * for the keyword field). We restyle those to match the archive comp: a
 * horizontal row of pill-shaped dropdowns + a keyword input at the right on
 * desktop, stacked with a show/hide toggle on mobile.
 *
 * The `.is-collapsed` modifier on the wrapper is added/removed by JS (mobile
 * "Show Filters" toggle) — bare CSS state below assumes the panel is open.
 */

.vl-insights-news-filter {
    margin-bottom: 48px;
}

.vl-insights-news-filter .searchandfilter {
    display: block;
}

.vl-insights-news-filter .searchandfilter > ul {
    display: flex;
    flex-direction: column;
    gap: 12px;
    list-style: none;
    margin: 0;
    padding: 0;
}

@media (min-width: 1024px) {
    .vl-insights-news-filter .searchandfilter > ul {
        flex-direction: row;
        flex-wrap: wrap;
        gap: 16px;
    }

    .vl-insights-news-filter {
        margin-bottom: 40px;
    }
}

.vl-insights-news-filter .searchandfilter > ul > li {
    flex: 1 1 0;
    margin: 0;
    min-width: 0;
    padding: 0;
}

/* Dropdowns (taxonomy filters) — white fill, 1px #63656A border, square
 * corners. Type matches `.type-theta` on mobile (Proxima Nova 700 / 16px)
 * and steps DOWN to `.type-iota` at ≥1024 (Proxima Nova 700 / 14px) per
 * the design comps. Both classes are 700-weight so the family/weight/color
 * stay constant; only font-size and line-height swap. Inlined because the
 * S&F plugin owns the <select>'s classname and can't carry a type-* class. */
.vl-insights-news-filter .searchandfilter select {
    appearance: none;
    -webkit-appearance: none;
    background-color: var(--vl-white);
    background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%23000' stroke-width='1.2' stroke-linecap='square'/%3E%3C/svg%3E");
    background-position: right 16px center;
    background-repeat: no-repeat;
    background-size: 12px 8px;
    border: 1px solid #63656A;
    border-radius: 0;
    color: var(--vl-black);
    cursor: pointer;
    font-family: proxima-nova, sans-serif;
    font-weight: 700;
    font-size: 16px;
    line-height: 1.32;
    letter-spacing: 0;
    padding: 12px 40px 12px 16px;
    width: 100%;
}

@media (min-width: 1024px) {
    .vl-insights-news-filter .searchandfilter select {
        font-size: 14px;
        line-height: 1.2;
    }
}

/* Active-filter state — border swaps from #63656A to black when the user
 * has picked a non-default option, and an inset box-shadow doubles the
 * apparent stroke (~2px) without changing the field's flow dimensions so
 * neighboring fields don't shift. S&F Pro tags every currently-selected
 * <option> with `sf-option-active` and only re-adds that class to the
 * first (default "All Items") option when the filter is reset — so the
 * combination of `:has(option.sf-option-active:not(:first-child))` gives
 * us the "user has actually made a selection" signal. */
.vl-insights-news-filter .searchandfilter select:has(option.sf-option-active:not(:first-child)) {
    border-color: #333333;
    box-shadow: inset 0 0 0 1px #333333;
}

/* Keyword search — underlined text input with a magnifier submit button on
 * the right. S&F emits <input type="text"> + <input type="submit">; we hide
 * the submit's default styling and replace it with a small magnifier SVG. */
.vl-insights-news-filter .sf-field-search {
    position: relative;
}

/* Keyword input — text baseline follows `.type-sm-p` (Proxima Nova 500 /
 * 14px mobile → 16px at ≥768). Inlined because the S&F plugin owns the
 * <input>'s classname. */
.vl-insights-news-filter .sf-field-search input[type="text"] {
    background: transparent;
    border: 0;
    border-bottom: 1px solid var(--vl-black);
    color: var(--vl-black);
    font-family: proxima-nova, sans-serif;
    font-weight: 500;
    font-size: 14px;
    line-height: 1.2;
    letter-spacing: 0;
    padding: 12px 32px 12px 0;
    width: 100%;
}

@media (min-width: 768px) {
    .vl-insights-news-filter .sf-field-search input[type="text"] {
        font-size: 16px;
        line-height: 1.32;
    }
}

.vl-insights-news-filter .sf-field-search input[type="text"]::placeholder {
    color: var(--vl-black);
    opacity: 0.55;
}

.vl-insights-news-filter .sf-field-search input[type="submit"] {
    background: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11.7078 9.57878C12.3067 8.59528 12.6235 7.46594 12.6233 6.31443C12.6233 2.82609 9.8007 0.0013913 6.31165 0C2.82574 0.00104348 0 2.82609 0 6.31374C0 9.79826 2.82609 12.623 6.31374 12.623C7.51026 12.623 8.62504 12.2849 9.57774 11.7071L13.871 16L16 13.8699L11.7078 9.57878ZM6.31304 10.2191C4.15583 10.2139 2.41183 8.47061 2.408 6.31791C2.40947 5.28262 2.82135 4.29014 3.55334 3.55801C4.28534 2.82588 5.27775 2.41383 6.31304 2.41217C8.46922 2.41774 10.2139 4.16104 10.2184 6.31791C10.2139 8.46817 8.46852 10.2139 6.31304 10.2191Z' fill='%23000'/%3E%3C/svg%3E") no-repeat center / 16px 16px;
    border: 0;
    cursor: pointer;
    font-size: 0;
    height: 16px;
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    width: 16px;
}

/* ===== Mobile: collapsible filter panel =====
 *
 * On mobile the design shows a "Show Filters" button first; expanding it
 * reveals the filter dropdowns. `.is-collapsed` on the wrapper is added by JS
 * to hide the field list on tap. The Show/Hide toggle button is emitted by
 * the archive template alongside the shortcode (still TODO — placeholder CSS
 * is in place so wiring the button in follows naturally).
 */

/* "Show Filters" / "Close Filters" toggle. Hidden on desktop entirely (the
 * filter row is always visible there). Type mirrors `.type-theta` — Proxima
 * Nova 700 with 14px mobile / 16px desktop, matching the utility class in
 * careers.css. Inlined here rather than adding the class in PHP so the
 * button's other properties (border, gap, padding) stay in one block. */
.vl-insights-news-filter-toggle {
    align-items: center;
    background: transparent;
    border: 1px solid #63656A;
    color: var(--vl-black);
    cursor: pointer;
    display: none;
    font-family: proxima-nova, sans-serif;
    font-weight: 700;
    font-size: 14px;
    line-height: 1.32;
    letter-spacing: 0;
    gap: 8px;
    padding: 8px;
}

@media (min-width: 1024px) {
    .vl-insights-news-filter-toggle {
        font-size: 16px;
    }
}

.vl-insights-news-filter-toggle-icon {
    align-items: center;
    display: inline-flex;
    height: 16px;
    justify-content: center;
    width: 16px;
}

.vl-insights-news-filter-toggle-icon svg {
    display: block;
    height: 100%;
    width: 100%;
}

/* Icon swap: filter glyph shows when collapsed, X shows when expanded.
 * The X is 10% smaller than the filter icon per design — 14×14 vs 16×16. */
.vl-insights-news-filter-toggle-icon--close {
    display: none;
    height: 11px;
    width: 11px;
}

.vl-insights-news-filter:not(.is-collapsed) .vl-insights-news-filter-toggle-icon--open {
    display: none;
}

.vl-insights-news-filter:not(.is-collapsed) .vl-insights-news-filter-toggle-icon--close {
    display: inline-flex;
}

@media (max-width: 1023px) {
    .vl-insights-news-filter-toggle {
        display: inline-flex;
        margin-bottom: 12px;
    }

    /* Hide every filter field EXCEPT the keyword-search when collapsed. Search
     * stays visible above the results row at all times per the mobile design.
     * `:not(.sf-field-search)` on the direct <li> children of the S&F <ul>. */
    .vl-insights-news-filter.is-collapsed .searchandfilter > ul > li:not(.sf-field-search) {
        display: none;
    }
}

/* ==========================================================================
 * Results info bar
 *
 * Sits between the filter form and the results loop. Renders inside every
 * Insights/News results template response (including AJAX re-renders), so
 * the count updates in place as filters change.
 *
 * Layout: flex row. Left group = count + divider + reset link. Right group =
 * the Sort Order dropdown DOM node moved in from the S&F filter form via JS
 * (see varnum.js → initInsightsNewsSortMover).
 * ========================================================================== */

.vl-insights-news-results-bar {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 24px;
    color: var(--vl-black);
}

.vl-insights-news-results-bar-meta {
    display: flex;
    align-items: flex-end;
    gap: 12px;
}

.vl-insights-news-results-count,
.vl-insights-news-results-reset {
    color: var(--vl-black);
}

.vl-insights-news-results-bar-divider {
    color: #63656A;
}

/* Override the elementor-kit-9 anchor rule which paints all links olive. */
.vl-insights-news-results-bar .vl-insights-news-results-reset {
    color: var(--vl-black);
    text-decoration: underline;
}

.vl-insights-news-results-bar .vl-insights-news-results-reset:hover {
    text-decoration: none;
}

/* Right slot — holds the S&F sort field after JS relocates it. Reset the
 * plugin's default UL margins/padding when it lands here. */
.vl-insights-news-results-bar-sort {
    display: flex;
    align-items: center;
    gap: 8px;
}

.vl-insights-news-results-bar-sort .sf-field-sort_order,
.vl-insights-news-results-bar-sort .sf-field-sort_order > ul,
.vl-insights-news-results-bar-sort > ul,
.vl-insights-news-results-bar-sort ul {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    align-items: center;
    gap: 8px;
}

/* Sort select — no box, native underline on the displayed text, inline
 * chevron background. Typography matches .type-xsm-p to sit level with the
 * count/reset text on the left of the bar.
 *
 * The "Sort:" prefix is baked into each sort option's label in the S&F Pro
 * admin (see docs/go-live-runbook.md), so the dropdown reads "Sort: Most
 * recent" / "Sort: Relevance" without any pseudo-element prefix on our end.
 *
 * Note: `text-decoration: underline` on a <select> renders reliably in
 * Firefox but is inconsistently drawn on the selected-value text in
 * Chromium-based browsers. If designers need the underline everywhere,
 * we can swap to a `border-bottom` on the select instead. */
.vl-insights-news-results-bar-sort select {
    background-color: transparent;
    border: 0;
    padding: 0 20px 0 0;
    text-decoration: underline;
    color: var(--vl-black);
    font-family: proxima-nova, sans-serif;
    font-weight: 500;
    font-size: 13px;
    line-height: 1.2;
    letter-spacing: 0;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' stroke='%23000' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
    background-repeat: no-repeat;
    background-position: right 4px center;
    cursor: pointer;
}

.vl-insights-news-results-bar-sort label {
    margin-bottom: 0;
}

@media (min-width: 768px) {
    .vl-insights-news-results-bar-sort select {
        font-size: 14px;
    }
}

.vl-insights-news-no-results {
    padding: 40px 0;
    text-align: center;
    color: var(--vl-black);
}

/* ==========================================================================
 * Empty state — no results
 *
 * Rendered by search-filter/results.php when the current filter combo
 * returns zero posts. Sits between the results info bar and the "Latest
 * [Insights|News]" fallback grid.
 *
 * Layout is a centered flex column: circle-X icon (54×54, gray) → heading
 * (type-eta, black) → lede (type-sm-p, mid-gray) → reset link
 * (type-xsm-p, black, underlined).
 * ========================================================================== */
.vl-insights-news-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 40px 20px 48px;
    color: var(--vl-black);
}

.vl-insights-news-empty-icon {
    display: block;
    width: 54px;
    height: 54px;
    margin-bottom: 16px;
    line-height: 0;
}

.vl-insights-news-empty-icon svg {
    display: block;
    width: 100%;
    height: 100%;
}

.vl-insights-news-empty-title {
    margin: 0 0 8px;
    color: var(--vl-black);
}

.vl-insights-news-empty-lede {
    margin: 0 0 12px;
    color: rgba(99, 101, 106, 1);
    max-width: 32em;
}

/* Parent-scoped so we beat the elementor-kit-9 anchor rule that paints all
 * links olive (same specificity dance used by .vl-insights-news-results-reset
 * higher up in this file). Hover drops the underline per design. */
.vl-insights-news-empty .vl-insights-news-empty-reset {
    color: var(--vl-black);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.vl-insights-news-empty .vl-insights-news-empty-reset:hover,
.vl-insights-news-empty .vl-insights-news-empty-reset:focus-visible {
    color: var(--vl-black);
    text-decoration: none;
}

/* ==========================================================================
 * Latest [Insights|News] — fallback grid on empty state
 *
 * A 4-up grid of the newest posts in the current archive context, shown
 * below the empty state so the page still has something useful. Divider
 * above the heading mirrors the design comp. Reuses the shared
 * .vl-loop-insight-container grid so cards match the standard results.
 * ========================================================================== */
.vl-insights-news-latest {
    margin-top: 8px;
    padding-top: 40px;
    border-top: 1px solid rgba(99, 101, 106, 0.25);
}

.vl-insights-news-latest-heading {
    margin: 0 0 32px;
    text-align: center;
    color: var(--vl-black);
}

@media (min-width: 768px) {
    .vl-insights-news-latest {
        padding-top: 56px;
    }

    .vl-insights-news-latest-heading {
        margin-bottom: 40px;
    }
}

/* ==========================================================================
 * Insights/News result card
 *
 * Rendered by template-parts/loop-insight.php inside the results container
 * .vl-loop-insight-container (in search-filter/results.php). Layouts:
 *
 *   Mobile (<768):  flex row inside .vl-insight-card-header — media on the
 *                   left (fixed 120px square), meta stacked on the right
 *                   (tag pill, title, date). Excerpt and pills fall
 *                   full-width below the header.
 *   Desktop (≥768): media stacks on top of meta as blocks. Tag is
 *                   position:absolute inside the header, overlaid on the
 *                   media at top-left.
 *
 * DOM is static; the swap is CSS-only.
 * ========================================================================== */

/* Container — nested 12-col grid sitting inside the archive's outer .vl-grid.
 * Mobile is 1-up; desktop bumps to 12 cols with each card spanning 3 (= 4-up).
 *
 * Row/column gaps per design: mobile row-gap 16px; desktop row-gap 24px,
 * column-gap 20px. */
.vl-loop-insight-container {
    display: grid;
    grid-template-columns: 1fr;
    row-gap: 16px;
}

@media (min-width: 768px) {
    .vl-loop-insight-container {
        grid-template-columns: repeat(2, 1fr);
        column-gap: 20px;
        row-gap: 24px;
    }
}

@media (min-width: 1024px) {
    .vl-loop-insight-container {
        grid-template-columns: repeat(12, 1fr);
    }
}

/* Card outer — border + padding + position context for the desktop overlay
 * tag pill. Mobile applies 16px padding to the whole card (image inside).
 * Desktop applies 20px padding and bleeds the image to the card edges via
 * negative margin on .vl-insight-card-media. */
.vl-insight-card {
    position: relative;
    border: 1px solid #D5D5D5;
    padding: 16px;
    background: var(--vl-white, #ffffff);
    transition: box-shadow 150ms ease;
}

/* Subtle drop shadow on hover — same treatment fires whether the user is
 * over the image, title, excerpt, or empty card space (all trigger the
 * card's :hover). Focus-within covers keyboard nav so the shadow appears
 * when tabbing to the title link too. */
.vl-insight-card:hover,
.vl-insight-card:focus-within {
    box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.08);
}

@media (min-width: 768px) {
    .vl-insight-card {
        padding: 16px;
    }
}

@media (min-width: 1024px) {
    .vl-insight-card {
        /* Desktop: 3 of 12 → 4-up. */
        grid-column: span 3;
    }
}

/* Primary card link — anchors on the title text. A ::after pseudo-element
 * expands over the whole card so clicks on card whitespace still navigate to
 * the post. Pill links get `position: relative` + `z-index: 1` further down
 * so they sit above this pseudo and remain independently clickable.
 *
 * Specificity (0,2,0) beats elementor-kit-9's `a { color: <olive> }` rule
 * (0,1,1). */
.vl-loop-insight-container .vl-insight-card-link {
    color: var(--vl-black);
    text-decoration: none;
}

.vl-loop-insight-container .vl-insight-card-link:hover,
.vl-loop-insight-container .vl-insight-card-link:focus {
    /* Recolor to brown on hover — the ::after pseudo makes the whole card
     * a hit target, but the color change paints on the title element
     * itself, so pill / image / excerpt hover areas fire the link :hover
     * without any visual change beyond the title text turning brown. No
     * underline. */
    color: var(--vl-brown);
    text-decoration: none;
}

.vl-insight-card-link::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
}

/* Header —
 *   Mobile: 2-col grid. Media takes col 1 across all 3 rows (aspect 100:111
 *           locked via align-self: start). Tag / title / date stack in col 2.
 *   Desktop: display: block. Media bleeds to card edges; tag becomes
 *            absolutely-positioned on top of the media (positioned relative
 *            to .vl-insight-card, which has position: relative). */
.vl-insight-card-header {
    display: grid;
    grid-template-columns: 100px 1fr;
    /* 4 rows: three auto-sized rows for tag/title/date, then a 1fr row that
     * absorbs any excess height left over after the media spans all four
     * rows. Without the trailing 1fr row, grid stretches rows 1-3 to fit
     * the media's 111px total height, and each text element ends up
     * vertically centered in its enlarged row — visually reads as
     * center-aligned copy against the image. The 1fr row keeps rows 1-3
     * at their natural content heights (stack from the top), and the
     * fourth row is left visually empty because the media occupies col 1
     * across all rows and col 2 has no content for that row. */
    grid-template-rows: auto auto auto 1fr;
    grid-template-areas:
        "media tag"
        "media title"
        "media date"
        "media .";
    column-gap: 12px;
    row-gap: 4px;
}

.vl-insight-card-media {
    grid-area: media;
    align-self: start;
    aspect-ratio: 100 / 111;
    overflow: hidden;
    background: var(--vl-sand);
}

.vl-insight-card-media img,
.vl-insight-card-image {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.vl-insight-card-tag {
    grid-area: tag;
    align-self: start;
    justify-self: start;
}

/* News-modifier — overrides the base `.hc-tag` olive+light-gray treatment
 * with black bg + white text per design QA. `.hc-tag` fill lives at
 * (0,1,0); this two-class selector (0,2,0) beats it without !important. */
.vl-insight-card-tag.vl-insight-card-tag--news {
    background: var(--vl-black);
    color: var(--vl-white, #ffffff);
}

.vl-insight-card-title {
    grid-area: title;
    margin: 0;
    color: var(--vl-black);
    /* Mobile-only: cap the title at 3 lines and add an ellipsis for
     * anything longer. The desktop override below (in the ≥768px block)
     * resets `-webkit-line-clamp` back to unset so full titles show on
     * larger viewports. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.vl-insight-card-date {
    grid-area: date;
    margin: 0;
    color: var(--vl-black);
}

@media (min-width: 768px) {
    .vl-insight-card-header {
        display: block;
    }

    .vl-insight-card-media {
        /* Full-bleed image on desktop — negative margins negate the card's
         * 16px padding on top and both sides. Bottom margin gives 16px of
         * breathing room above the title. */
        width: calc(100% + 32px);
        aspect-ratio: 263 / 148;
        margin: -16px -16px 16px;
    }

    .vl-insight-card-tag {
        position: absolute;
        top: 12px;
        left: 12px;
        z-index: 1;
    }

    .vl-insight-card-title {
        margin: 0 0 4px;
        /* Desktop: reset the mobile line-clamp so long titles display in
         * full — the desktop card gives titles more horizontal room, so
         * three-line wrapping isn't a design concern here. */
        display: block;
        -webkit-line-clamp: unset;
        overflow: visible;
    }
}

/* Excerpt — falls below the header on all breakpoints. */
.vl-insight-card-excerpt {
    margin: 12px 0 0;
    color: var(--vl-black);
}

/* Taxonomy pills — practices + industries, stacked vertically (one per row).
 * Border #D5D5D5 matches the card border. Typography = .type-kappa (utility
 * applied in PHP). Each pill is an independent link to the filtered archive
 * view. The `position: relative; z-index: 1` on the <ul> pulls the pill
 * links above the title-link ::after pseudo-element so they receive their
 * own click events. */
.vl-insight-card-pills {
    display: flex;
    /* Mobile: pills flow inline and wrap to the next line when they run
     * out of space. Desktop override below flips back to a vertical
     * column stack — matches the design at ≥768px where each card is
     * narrower and single-per-line reads cleaner. */
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 8px;
    list-style: none;
    padding: 0;
    margin: 12px 0 0;
    position: relative;
    z-index: 1;
    max-width: 100%;
}

@media (min-width: 768px) {
    .vl-insight-card-pills {
        flex-direction: column;
        flex-wrap: nowrap;
    }
}

.vl-insight-card-pills li {
    max-width: 100%;
    min-width: 0;
    display: block;
}

.vl-loop-insight-container .vl-insight-card-pill {
    display: inline-block;
    max-width: 100%;
    box-sizing: border-box;
    padding: 4px 12px;
    border: 1px solid #D5D5D5;
    border-radius: 999px;
    color: var(--vl-black);
    background: transparent;
    text-decoration: none;
    transition: background-color 0.15s ease;
    vertical-align: bottom;
    /* NOTE: no `overflow: hidden` on the pill anchor itself — that would
     * clip the tooltip ::before as well. Truncation lives on the inner
     * .vl-insight-card-pill-label span below. */
}

/* Inner text wrapper carries the actual ellipsis truncation so the pill
 * anchor stays `overflow: visible` and lets the tooltip pseudo escape. */
.vl-insight-card-pill-label {
    display: block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.vl-loop-insight-container .vl-insight-card-pill:hover,
.vl-loop-insight-container .vl-insight-card-pill:focus {
    background: #D5D5D5;
    color: var(--vl-black);
    text-decoration: none;
}

/* Tooltip on hover for truncated pills only.
 *
 * The `.is-truncated` class is added by JS (assets/js/varnum.js →
 * initInsightCardPillTruncation) when the pill's scrollWidth exceeds its
 * clientWidth. Pills whose text fits their card width never receive the
 * class, so the tooltip only appears where it adds information.
 *
 * `data-vl-tooltip` on the pill anchor holds the full term name (set in
 * template-parts/loop-insight.php) and is used as the pseudo's content
 * via attr(). z-index: 10 pulls the pseudo above the card content and
 * neighboring cards' overlays. */
.vl-loop-insight-container .vl-insight-card-pill.is-truncated {
    position: relative;
}

.vl-loop-insight-container .vl-insight-card-pill.is-truncated::before {
    content: attr(data-vl-tooltip);
    position: absolute;
    bottom: calc(100% + 6px);
    left: 0;
    max-width: 240px;
    padding: 8px 12px;
    background: var(--vl-white, #ffffff);
    border: 1px solid #D5D5D5;
    color: var(--vl-black);
    white-space: normal;
    text-align: left;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    pointer-events: none;
    opacity: 0;
    visibility: hidden;
    z-index: 10;
    transition: opacity 0.12s ease, visibility 0.12s ease;
}

.vl-loop-insight-container .vl-insight-card-pill.is-truncated:hover::before,
.vl-loop-insight-container .vl-insight-card-pill.is-truncated:focus::before {
    opacity: 1;
    visibility: visible;
}

/* ==========================================================================
 * Pill overflow — +N button + click-to-open popover
 *
 * Cards can carry many taxonomy terms (Best Law Firms rankings, for one,
 * routinely have 20+ practice terms). Visible pills are capped at 3 in
 * template-parts/loop-insight.php; the remaining terms live inside a
 * click-triggered popover so the card body doesn't grow tall.
 *
 * The +N element is a <button> that reuses .vl-insight-card-pill styling
 * (same shape and border). The popover positions absolutely off the button
 * so it can extend beyond the card boundary — the card and container both
 * keep overflow: visible so the popover isn't clipped.
 * ========================================================================== */

.vl-insight-card-pill-more-wrap {
    position: relative;
    max-width: 100%;
    /* Inherits `<li>` block behavior from earlier rules — the wrapper is
     * the flex item; the button and popover live inside it. */
}

/* Raise the whole card in the grid stacking order while its popover is
 * open. Popover renders inside .vl-insight-card-pills' local stacking
 * context (the UL has position: relative; z-index: 1) — without this
 * promotion, later cards' own tag pills (also z-index: 1) paint on top
 * because siblings tie on z-index and source order wins. JS toggles
 * `.has-popover-open` on the card element. */
.vl-insight-card.has-popover-open {
    z-index: 10;
}

/* Button reset — pill visual comes from the .vl-insight-card-pill class
 * also applied to the button. Do NOT set `font: inherit` here — that
 * shorthand would clobber the font-size/family that .type-kappa applies
 * (same specificity, later cascade wins), making the "+N" text render at
 * the inherited archive font size (~16px) instead of the tiny kappa size. */
.vl-loop-insight-container .vl-insight-card-pill-more {
    cursor: pointer;
}

.vl-insight-card-pill-more-popover {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 5;
    min-width: 200px;
    max-width: 280px;
    padding: 8px;
    background: var(--vl-white, #ffffff);
    border: 1px solid #D5D5D5;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.vl-insight-card-pill-more-popover[hidden] {
    display: none;
}

.vl-insight-card-pill-more-popover ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
}

/* Popover pills wrap freely — no ellipsis, since the whole point of the
 * popover is to show what's normally clipped. */
.vl-insight-card-pill-more-popover .vl-insight-card-pill {
    max-width: 100%;
    white-space: normal;
}

.vl-insight-card-pill-more-popover .vl-insight-card-pill-label {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
}

/* ==========================================================================
 * Pagination — Insights/News archive
 *
 * WP-PageNavi output structure:
 *   .wp-pagenavi
 *     .pages           "Page X of Y" label
 *     .previouspostslink   « prev
 *     .first               First «
 *     .page                (number link)
 *     .current             (current page number, not a link)
 *     .extend              …
 *     .nextpostslink       next »
 *     .last                Last »
 *
 * Overrides the generic .pagination .wp-pagenavi rules in style.css by
 * scoping under .vl-insights-news-pagination (0,2,0 vs the older 0,2,0
 * — same specificity but this stylesheet loads AFTER style.css, so it wins
 * on cascade). Each number is a 40x40 square, gap 6px between items,
 * hover/current fills #D5D5D5 with no border or radius.
 * ========================================================================== */
.vl-insights-news-pagination .wp-pagenavi {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 6px;
    padding: 0;
}

.vl-insights-news-pagination .wp-pagenavi span,
.vl-insights-news-pagination .wp-pagenavi a {
    /* Each cell: 40x40 square, no fill, no border, no radius. Typography
     * mirrors .type-theta (Proxima Nova 700 / 16px). Restated inline since
     * .type-theta is defined only at ≥1024 in careers.css — the pagination
     * needs the same look at every viewport. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: none;
    border-radius: 0;
    background: transparent;
    color: var(--vl-black);
    text-decoration: none;
    font-family: proxima-nova, sans-serif;
    font-weight: 700;
    font-size: 16px;
    line-height: 1.32;
    letter-spacing: 0;
    transition: background-color 0.15s ease;
}

/* Hover on links + current-page indicator get the #D5D5D5 fill. */
.vl-insights-news-pagination .wp-pagenavi a:hover,
.vl-insights-news-pagination .wp-pagenavi a:focus,
.vl-insights-news-pagination .wp-pagenavi .current {
    background: #D5D5D5;
    color: var(--vl-black);
    text-decoration: none;
    border: none;
    border-radius: 0;
}

/* Hide the "Page X of Y" text — design doesn't include it. */
.vl-insights-news-pagination .wp-pagenavi .pages {
    display: none;
}

/* First / Last text links can exceed 40px width because they carry text
 * labels ("First «" / "Last »"). Let them size to content while keeping
 * the same height and hover treatment. */
.vl-insights-news-pagination .wp-pagenavi .first,
.vl-insights-news-pagination .wp-pagenavi .last {
    width: auto;
    padding: 0 12px;
}

/* ==========================================================================
 * Content Hub card
 *
 * Rendered by template-parts/loop-hub-card.php inside the results grid when
 * the current filter targets a hub-flagged practice or industry (helper in
 * functions.php → vl_get_filtered_hub_terms()). Sits in the normal
 * .vl-loop-insight-container grid slot (same span as .vl-insight-card).
 *
 * Visual: sand-brighter card background with a subtle cream triangle
 * emanating from the top-left, "Insights Hub" pill + taxonomy label at the
 * top, serif title, short description, brown CTA button pinned to the
 * bottom. Whole card is one <a> — the CTA is a styled span, not a nested
 * link.
 * ========================================================================== */
.vl-hub-card {
    position: relative;
    background: var(--vl-sand-brighter);
    color: var(--vl-black);
    overflow: hidden;
    box-sizing: border-box;
}

@media (min-width: 1024px) {
    .vl-hub-card {
        /* Same 3-of-12 slot as .vl-insight-card at desktop. */
        grid-column: span 3;
    }
}

/* Decorative triangle behind the content. clip-path draws a right triangle
 * anchored at the top-left corner with legs extending 65% along the top and
 * left edges. Tweak the two 65% stops together to grow or shrink the shape. */
.vl-hub-card::before {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--vl-sand);
    clip-path: polygon(51% 100%, 0 0, 100% 0);
    pointer-events: none;
    height: calc(100% - s24px);
    z-index: 0;
}

@media (min-width: 768px) {
    .vl-hub-card::before {
        min-height: 270px;
        height: 50%;
    }
}

/* Link wrapper carries the padding + flex column so the CTA can be pushed
 * to the bottom of the card via margin-top: auto. Sits above the triangle
 * via z-index. Defeats elementor-kit-9's global anchor color rule (0,1,1)
 * via the container-scoped selector further down. */
.vl-hub-card-link {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: 24px 16px;
    color: var(--vl-black);
    text-decoration: none;
    box-sizing: border-box;
}

@media (min-width: 768px) {
    .vl-hub-card-link {
        justify-content: space-between;
    }
}

.vl-loop-insight-container .vl-hub-card-link {
    color: var(--vl-black);
    text-decoration: none;
}

.vl-loop-insight-container .vl-hub-card-link:hover,
.vl-loop-insight-container .vl-hub-card-link:focus {
    color: var(--vl-black);
    text-decoration: none;
}

.vl-hub-card-tags {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 8px;
}

/* "Insights Hub" pill — cream fill on the sand card, small type. Icon +
 * label sit inline. */
.vl-hub-card-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    background: var(--vl-cream);
    color: var(--vl-black);
    border-radius: 3px;
}

.vl-hub-card-pill-icon {
    display: inline-flex;
}

.vl-hub-card-pill-icon svg {
    display: block;
}

.vl-hub-card-tax-label {
    color: var(--vl-black);
}

.vl-hub-card-title {
    margin: 0 0 4px;
    color: var(--vl-black);
}

.vl-hub-card-description {
    margin: 0 0 24px;
    color: var(--vl-black);
}

/* CTA — styled span, mirrors .type-button-brown's visual treatment. The
 * whole card is already an anchor, so this span doesn't need to be a link
 * itself; margin-top: auto pins it to the bottom of the flex column. */
.vl-hub-card-cta {
    align-self: flex-start;
    background: var(--vl-brown-dark);
    color: var(--vl-cream);
    padding: 12px 24px;
    font-family: Georgia, "Times New Roman", serif;
    font-weight: 400;
    font-size: 15px;
    line-height: 1.32;
    letter-spacing: 0.02em;
    transition: opacity 200ms ease;
}

.vl-hub-card-link:hover .vl-hub-card-cta,
.vl-hub-card-link:focus .vl-hub-card-cta {
    opacity: 0.85;
}


/* ==========================================================================
 * Content Hub hero (template-hub.php)
 *
 * Overrides the Featured Hero widget's default full-cover treatment on hub
 * pages. Structure:
 *   .vl-hub-hero-wrap                     ← background image strip (narrow)
 *     .vl-featured-hero                   ← olive card, max 1532px, centered
 *
 * The wrap holds the hub background image as a strip at the top (120px
 * mobile, 360px desktop). Padding-top on the wrap pushes the olive card
 * downward: on mobile the card sits directly below the image (no overlap);
 * on desktop the card starts 230px into the image, overlapping the bottom
 * 130px of the strip.
 *
 * The hub image URL is passed inline via a `--vl-hub-hero-bg` custom
 * property on the wrap so the CSS stays static and each hub can supply its
 * own image without a stylesheet change.
 * ========================================================================== */
.vl-hub-hero-wrap {
    position: relative;
    padding-top: 120px;
}

/* Image lives on a fixed-height pseudo-element so `background-size: cover`
 * can crop/scale the image to fill exactly the strip area rather than
 * stretching to a hardcoded 100% × Xpx (which distorted images with the
 * wrong aspect ratio). The wrap's padding-top reserves the same space above
 * the child content — desktop bumps the reservation to 230px so the olive
 * card overlaps the bottom of the 360px strip. */
.vl-hub-hero-wrap::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 120px;
    background-image: var(--vl-hub-hero-bg);
    background-repeat: no-repeat;
    background-position: center;
    background-size: cover;
}

@media (min-width: 1024px) {
    .vl-hub-hero-wrap {
        padding-top: 230px;
    }

    .vl-hub-hero-wrap::before {
        height: 360px;
    }
}

/* Constrain the olive card to 1532px and drop the archive's tall
 * min-height so the card sizes to its content on hub pages. */
.vl-hub-hero-wrap .vl-featured-hero {
    max-width: 1532px;
    margin-inline: auto;
    min-height: 0;
    position: relative; /* keeps the card above the ::before image strip */
}

/* Text color inside the olive card — sand-brighter for the eyebrow, title,
 * and intro description. Overrides the widget's default (which inherits the
 * page's black on light background) since here we're on the olive fill. */
.vl-hub-hero-wrap .vl-featured-hero__eyebrow,
.vl-hub-hero-wrap .vl-featured-hero__title,
.vl-hub-hero-wrap .vl-featured-hero__intro,
.vl-hub-hero-wrap .vl-featured-hero__intro p {
    color: var(--vl-sand-brighter);
}

/* Keep the hub-hero eyebrow in its natural case. The base
 * `.vl-featured-hero__eyebrow` rule in style.css sets
 * `text-transform: uppercase` for the archive hero; overriding here so
 * the hub reads "Insights Hub" as-typed, matching the design comp. */
.vl-hub-hero-wrap .vl-featured-hero__eyebrow {
    text-transform: none;
}

/* Show the pinned panel on mobile inside the hub hero. The base widget CSS
 * hides `.vl-featured-hero__panel` below 1100px (archive design tucks the
 * panel away on small screens), but the hub design keeps it visible and
 * stacks it below the main content column. At ≥1100px the widget's own
 * grid takes over and places the panel to the right of the main column
 * as usual — no override needed there. */
.vl-hub-hero-wrap .vl-featured-hero__panel {
    display: block;
}

/* Mobile-only hub hero adjustments (below the widget's own 1100px
 * two-column breakpoint):
 *   - The main-content bottom padding is removed so the CTA button sits
 *     immediately above the pinned panel, with the CTA's own 40px
 *     margin-bottom providing the gap.
 *   - The pinned panel breaks out of the olive card's max-width using the
 *     100vw / calc trick, so its sand-brighter background reaches the
 *     viewport edges edge-to-edge.
 *   - The panel gets 40px vertical padding and a 20px gutter so the inner
 *     content isn't flush with the viewport edges. */
@media (max-width: 1099px) {
    .vl-hub-hero-wrap .vl-featured-hero__inner {
        padding-bottom: 0;
    }

    .vl-hub-hero-wrap .vl-featured-hero__cta {
        margin-bottom: 40px;
    }

    .vl-hub-hero-wrap .vl-featured-hero__panel {
        width: 100vw;
        margin-left: calc(-50vw + 50%);
        margin-right: calc(-50vw + 50%);
        padding: 40px 20px;
    }
}
