/*
  Latest Updates section.
  Source: Figma node 3:555 (desktop 1440 × 512).

  Header (eyebrow + title-row), then a tablist (News / Events / Videos /
  Insights & Articles) on a 1px grey baseline with the active tab marked
  by a 2px green underline, then a single content area showing 3 cards
  for the currently-selected tab. Inactive panels are display: none;
  the active panel is animated in with a soft fade+rise via @keyframes.

  All hover/focus underlines reuse the global .cta-link wipe (defined
  in css/global.css) — the "Read More" links inside each card are
  marked up with class="cta-link".
*/

.latest-updates {
  padding-block: var(--section-padding-block);
}

.latest-updates__inner {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--space-inline);
  display: flex;
  flex-direction: column;
  gap: var(--space-10);
}

/* ---------------------------------------------------------------
   Header — eyebrow + title-row (title left, description + CTA right)
   --------------------------------------------------------------- */
.latest-updates__header {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

.latest-updates__eyebrow {
  font-family: var(--font-family-sans);
  font-size: var(--font-size-eyebrow);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--letter-spacing-wide);
  text-transform: uppercase;
  color: var(--color-text-heading);
  margin: 0;
}

.latest-updates__eyebrow-slash {
  color: var(--color-green-2);
  margin-right: 0.25em;
}

.latest-updates__heading-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-7);
  align-items: start;
}

.latest-updates__heading {
  font-family: var(--font-family-display);
  font-size: var(--font-size-h2);
  font-weight: var(--font-weight-regular);
  line-height: 1.2;
  margin: 0;
  color: var(--color-text-heading);
}

.latest-updates__heading-accent {
  color: var(--color-green-2);
  font-weight: var(--font-weight-semibold);
}

.latest-updates__intro {
  display: flex;
  flex-direction: column;
  gap: var(--space-7);
  align-items: flex-start;
}

/* When the optional CTA is omitted (empty in the CMS), reserve the space
   it would have occupied so the header height stays consistent. */
.latest-updates__intro:not(:has(.btn)) {
  padding-bottom: calc(var(--space-7) + var(--btn-height));
}

/* Header CTA label clip — loosen the line-height on the .btn__label slot
   only for this section's auto "View all <X>" button so descenders ("g"
   in "Insights") don't get clipped by the global .btn__label overflow:
   hidden + line-height: 1. Scoped via [data-latest-updates-cta] so other
   site-wide .btn instances are unchanged. Inner spans match so the
   wipe-on-hover keeps registering 100% to the slot height. */
[data-latest-updates-cta] .btn__label,
[data-latest-updates-cta] .btn__label > span {
  line-height: var(--line-height-relaxed);
}

.latest-updates__subheading {
  font-family: var(--font-family-sans);
  font-size: var(--font-size-body-lg);
  font-weight: var(--font-weight-regular);
  line-height: var(--line-height-relaxed);
  color: var(--color-text-body);
  margin: 0;
}

/* Side-by-side header at ≥900px — genuine column rearrangement. */
@media (min-width: 900px) {
  .latest-updates__heading-row {
    grid-template-columns: 706fr 585fr;
    column-gap: clamp(var(--space-7), 8vw, 150px);
  }
}

/* ---------------------------------------------------------------
   Tabs
   --------------------------------------------------------------- */
.latest-updates__tabs {
  position: relative;
  /* The 1px baseline that runs under the tab list and across the
     full content width — the active tab's 2px underline overlaps it. */
  border-bottom: 1px solid var(--color-card-border);
}

.latest-updates__tablist {
  display: flex;
  gap: var(--space-6);
  /* Allow horizontal scroll on very narrow screens rather than wrapping
     the labels onto two lines, which would mess up the baseline. */
  overflow-x: auto;
  scrollbar-width: none;
}

.latest-updates__tablist::-webkit-scrollbar {
  display: none;
}

.latest-updates__tab {
  position: relative;
  /* Reset button defaults */
  appearance: none;
  background: transparent;
  border: 0;
  margin: 0;
  /* Spacing — the bottom 8px includes the gap to the green underline */
  padding: 0 0 var(--space-2);
  font-family: var(--font-family-sans);
  font-size: var(--font-size-body);
  font-weight: var(--font-weight-regular);
  line-height: 1.5;
  color: var(--color-text-body);
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.2s ease;
}

/* The active-tab underline lives on a pseudo-element so it overlaps
   (and visually punches through) the tablist's 1px baseline. */
.latest-updates__tab::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px; /* sit on top of the .latest-updates__tabs border */
  height: 2px;
  background-color: var(--color-green-2);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.25s ease;
}

.latest-updates__tab:hover,
.latest-updates__tab:focus-visible {
  color: var(--color-text-heading);
}

.latest-updates__tab[aria-selected="true"] {
  color: var(--color-text-heading);
  font-weight: var(--font-weight-medium);
}

.latest-updates__tab[aria-selected="true"]::after {
  transform: scaleX(1);
}

/* Chevron lives inside every tab button but is only visible on mobile
   (where the tabs render as accordion headers). Rotates 180° when the
   tab is selected to indicate "expanded". */
.latest-updates__chevron {
  display: none;
  flex-shrink: 0;
  transition: transform 0.22s ease-out;
}

.latest-updates__tab[aria-selected="true"] .latest-updates__chevron {
  transform: rotate(180deg);
}

/* ---------------------------------------------------------------
   Tab panels — one visible at a time, soft fade-in
   --------------------------------------------------------------- */
.latest-updates__panels {
  /* The container holds all 4 panels but only one is rendered
     (display: grid) at a time — see .is-active below. */
  position: relative;
}

.latest-updates__panel {
  display: none;
}

.latest-updates__panel.is-active {
  display: grid;
  /* Column count is computed per panel from the item count (see
     infleqtion_lu_columns) and passed in as --lu-cols, so the grid always
     tiles into a complete rectangle with no dead space — e.g. 6 → 3×2,
     8 → 4×2, 12 → 3×4. The mobile-accordion rule below forces a single
     column ≤1099px. */
  grid-template-columns: repeat(var(--lu-cols, 1), minmax(0, 1fr));
  gap: 1px;
  background-color: var(--color-card-border);
  border: 1px solid var(--color-card-border);
  border-radius: 8px;
  overflow: hidden;
  animation: latest-updates-panel-in 0.3s ease-out both;
}

@keyframes latest-updates-panel-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 1 or 2 cards: shrink the panel container to match the occupied columns so
   the border wraps only the real cards (not the empty grid area). The card
   width stays identical to a 3-card layout — 1/3 or 2/3 of the full panel
   width — because the container is capped to the same proportions. */
.latest-updates__panel.is-active:has(> .latest-updates__cell:nth-child(1):last-child) {
  grid-template-columns: 1fr;
  max-width: calc(100% / 3);
}

.latest-updates__panel.is-active:has(> .latest-updates__cell:nth-child(2):last-child) {
  grid-template-columns: repeat(2, 1fr);
  max-width: calc(200% / 3);
}

/* ---------------------------------------------------------------
   Cell wrapper — each grid item now wraps the card so we have a
   stacking context for the admin-only edit-link overlay. The cell
   stretches to the grid row height (default grid align: stretch)
   and the card inside fills its full height.
   --------------------------------------------------------------- */
.latest-updates__cell {
  position: relative;
  display: flex;
}

.latest-updates__cell > .latest-updates__card {
  height: 100%;
}

/* Admin-only edit-link overlay. Sibling of the card link/button (not
   nested — nested anchors are invalid HTML) so clicks reach the admin
   URL directly. Sits on top via z-index. Only rendered server-side when
   get_edit_post_link() returns a URL, i.e. the current user can edit. */
.latest-updates__edit {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 2;
  padding: 4px 8px;
  background-color: rgba(0, 0, 0, 0.78);
  color: #fff;
  font-family: var(--font-family-sans);
  font-size: 12px;
  font-weight: var(--font-weight-medium);
  line-height: 1.2;
  text-decoration: none;
  border-radius: 4px;
}

.latest-updates__edit:hover,
.latest-updates__edit:focus-visible {
  background-color: #000;
  color: #fff;
}

/* ---------------------------------------------------------------
   Cards
   --------------------------------------------------------------- */
.latest-updates__card {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  padding: var(--space-7); /* 32px */
  background-color: var(--color-background);
  width: 100%;
  /* The whole card is an <a> (or a <button> for the Videos tab, which
     opens the YouTube overlay); reset link/button chrome so descendants
     control their own colors. */
  color: inherit;
  text-decoration: none;
  transition: background-color 0.22s ease-out, color 0.22s ease-out;
}

/* Card image — white box on top of the card. Fixed height keeps every
   card's image baseline aligned across the grid. position:relative
   anchors the play-button overlay on the Videos tab. */
.latest-updates__card-image {
  position: relative;
  height: 222px;
  background-color: #fff;
  border: 1px solid var(--color-card-border);
  border-radius: 8px;
  overflow: hidden;
}

/* Events tab only: inset the (contain-fitted) photo with 30px padding so
   product/event shots breathe inside the white card. Videos use cover
   and fill the cell, so they keep zero padding. Scoped via :has() on
   the events-only `.latest-updates__card-photo` child. */
.latest-updates__card-image:has(.latest-updates__card-photo) {
  padding: 30px;
}

.latest-updates__card-photo {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
}

/* Per-event opt-in (ACF "Cover Featured Image" on the event post): fill the
   card edge to edge and crop, for events whose featured image is a photo
   rather than a logo. The padding reset has to come with it — otherwise the
   image would still be inset 30px and wouldn't reach the card's edges. */
.latest-updates__card-image:has(.latest-updates__card-photo--cover) {
  padding: 0;
}

.latest-updates__card-photo--cover {
  object-fit: cover;
}

/* Default fallback image: fill the card edge to edge (same treatment as
   video thumbnails). Resets the 30px padding the :has(.card-photo) rule adds. */
.latest-updates__card-image:has(.latest-updates__card-photo--default) {
  padding: 0;
}

.latest-updates__card-photo--default {
  object-fit: cover;
}

/* Videos tab: cover the card area so the YouTube poster fills the cell
   (the static product/event photos used `contain` to avoid cropping
   product shots). */
.latest-updates__card-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* Below 1367px the grid re-columns (3→2→1), so a fixed-height video box looks
   too wide or too square depending on width. Lock it to the 1440-design card
   proportion (368:222) and let width drive height, keeping the desktop shape as
   the card scales. Scoped via :has() so event/photo cards are unaffected. */
@media (max-width: 1366px) {
  .latest-updates__card-image:has(.latest-updates__card-video) {
    height: auto;
    aspect-ratio: 368 / 222;
  }
}

/* 40% dark overlay on Videos-tab thumbnails so the white play button
   reads well against the YouTube poster. Scoped to <button> cards
   (Videos tab only) — the other tabs' images are contain-fitted inside
   a padded white card, where a full-inset tint would darken the padding
   too. The play button sits at z-index 1 so it stays crisp on top. */
button.latest-updates__card .latest-updates__card-image:has(img:not(.latest-updates__play))::after {
  content: "";
  position: absolute;
  inset: 0;
  background-color: rgba(0, 0, 0, 0.4);
  pointer-events: none;
}

/* Videos-tab play button — dead-centred over the thumbnail. Decorative;
   the wrapping <button.latest-updates__card> handles the click. */
.latest-updates__play {
  position: absolute;
  left: 50%;
  top: 50%;
  /* Sit above the 40% overlay so the icon stays crisp on darkened thumbnails. */
  z-index: 1;
  width: 48px;
  height: 48px;
  transform: translate(-50%, -50%);
  pointer-events: none;
  transition: transform 0.25s ease-out;
}

button.latest-updates__card:hover .latest-updates__play,
button.latest-updates__card:focus-visible .latest-updates__play {
  transform: translate(-50%, -50%) scale(1.06);
}

/* Button-flavored card (Videos tab → opens modal). Strip native button
   chrome so it renders identically to the <a> variant. */
button.latest-updates__card {
  border: 0;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

/* Hover: the whole card flips white → navy (same treatment as
   research-breakthroughs / products). Title + description go white; the green
   date stays green (reads fine on navy) and the "Read More" cta-link keeps its
   teal underline-wipe + arrow. The image area is already navy, so on hover
   it visually merges into the now-navy card background. */
a.latest-updates__card:hover,
a.latest-updates__card:focus-visible,
button.latest-updates__card:hover,
button.latest-updates__card:focus-visible {
  background-color: var(--color-navy-blue);
  color: var(--color-text-on-dark);
}

a.latest-updates__card:hover .latest-updates__card-title,
a.latest-updates__card:focus-visible .latest-updates__card-title,
a.latest-updates__card:hover .latest-updates__card-description,
a.latest-updates__card:focus-visible .latest-updates__card-description,
button.latest-updates__card:hover .latest-updates__card-title,
button.latest-updates__card:focus-visible .latest-updates__card-title,
button.latest-updates__card:hover .latest-updates__card-description,
button.latest-updates__card:focus-visible .latest-updates__card-description {
  color: var(--color-text-on-dark);
}

/* Videos tab cards (button) — replay the same cta-link hover treatment
   the global rule applies to <a> ancestors (color → accent, underline
   wipes via scaleX(0), arrow slides in after the wipe). The global
   selectors only target anchors, so a <button> card needs its own
   matching rules so "Watch" behaves identically to "Read More" etc. */
button.latest-updates__card:hover .cta-link,
button.latest-updates__card:focus-visible .cta-link {
  color: var(--color-accent);
}

button.latest-updates__card:hover .cta-link::after,
button.latest-updates__card:focus-visible .cta-link::after {
  transform: scaleX(0);
}

button.latest-updates__card:hover .cta-link::before,
button.latest-updates__card:focus-visible .cta-link::before {
  opacity: 1;
  transform: translate(0, 50%);
  transition-delay: 0.35s;
}

.latest-updates__card-content {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Push the "Read More" cta-link to the bottom of the card so all cards
   in a row align their CTAs, regardless of description length. The grid
   already stretches every card to the same height — `margin-top: auto`
   on the last child eats the extra space below the content block. */
.latest-updates__card > .cta-link {
  margin-top: auto;
}

.latest-updates__card-date {
  font-family: var(--font-family-sans);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-green-2);
  margin: 0;
}

/* Tag chips row — sits above the date. Wraps to a second line when a card
   has too many tags to fit. Figma spec: 16px gap, pill chips with a 1px
   green outline. Rendered by latest-updates-dynamic.php from the tab's
   mapped taxonomy (news_tag / video_tag / post_tag); Events skips the
   row entirely. */
.latest-updates__card-tags {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4_5);
}

.latest-updates__card-tag {
  display: inline-flex;
  align-items: center;
  padding: 5px var(--space-2);
  border: 1px solid var(--color-green-2);
  border-radius: 200px;
  font-family: var(--font-family-sans);
  font-size: var(--font-size-eyebrow);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--letter-spacing-wide);
  text-transform: uppercase;
  color: var(--color-navy-blue);
  white-space: nowrap;
  transition: color 0.22s ease-out;
}

/* Card flips to navy on hover — flip chip text to white so it stays
   readable. Border stays green (visible on both light and dark).
   Covers both card variants: <a> (News / Events / Insights) and
   <button> (Videos tab, which opens the video modal). */
a.latest-updates__card:hover .latest-updates__card-tag,
a.latest-updates__card:focus-visible .latest-updates__card-tag,
button.latest-updates__card:hover .latest-updates__card-tag,
button.latest-updates__card:focus-visible .latest-updates__card-tag {
  color: var(--color-text-on-dark);
}

.latest-updates__card-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.latest-updates__card-title {
  font-family: var(--font-family-display);
  font-size: var(--font-size-h4);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-card-title);
  margin: 0;
  color: #171717;
  transition: color 0.22s ease-out;
}

.latest-updates__card-description {
  font-family: var(--font-family-sans);
  font-size: var(--font-size-body);
  font-weight: var(--font-weight-regular);
  line-height: 1.5;
  margin: 0;
  color: var(--color-text-body);
  transition: color 0.22s ease-out;
}

/* ---------------------------------------------------------------
   Mobile: tabs collapse into a vertical accordion.

   The DOM doesn't change. Instead .latest-updates__tabs / __tablist /
   __panels are flattened with `display: contents` so each tab and each
   panel becomes a direct child of .latest-updates__inner — then the
   `order` property interleaves them (tab → its panel → next tab → its
   panel …). The existing JS still toggles the same .is-active class
   on the panel and aria-selected on the tab; on mobile that .is-active
   class is what shows the panel and what rotates the chevron.
   --------------------------------------------------------------- */
@media (max-width: 1099px) {
  .latest-updates__tabs,
  .latest-updates__tablist,
  .latest-updates__panels {
    display: contents;
  }

  /* Flex `order` re-sequences the now-flat list of children so each
     tab is followed by its own panel. Keyed off source position
     (nth-child within the tablist / panels container), NOT specific IDs,
     so it works for both the static markup and the dynamic CPT-driven
     part whose tab/panel IDs differ (lud…-tab-0 etc.). */
  .latest-updates__header              { order: 0; }
  .latest-updates__tab:nth-child(1)    { order: 1; }
  .latest-updates__panel:nth-child(1)  { order: 2; }
  .latest-updates__tab:nth-child(2)    { order: 3; }
  .latest-updates__panel:nth-child(2)  { order: 4; }
  .latest-updates__tab:nth-child(3)    { order: 5; }
  .latest-updates__panel:nth-child(3)  { order: 6; }
  .latest-updates__tab:nth-child(4)    { order: 7; }
  .latest-updates__panel:nth-child(4)  { order: 8; }

  /* Tab becomes a full-width accordion header. */
  .latest-updates__tab {
    width: 100%;
    padding: var(--space-4) 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    border-top: 1px solid var(--color-card-border);
    font-size: var(--font-size-body);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-heading);
  }

  /* The chevron is the active-state indicator on mobile, not the green
     underline — hide the desktop ::after bar entirely. */
  .latest-updates__tab::after {
    display: none;
  }

  .latest-updates__chevron {
    display: block;
    color: var(--color-text-body);
  }

  /* Bottom border on the last accordion item closes the stack. */
  .latest-updates__tab:last-child {
    border-bottom: 1px solid var(--color-card-border);
  }
  /* …unless the last panel is expanded — then the bottom border lives
     on the panel-card grid instead and we don't want a double line. */
  .latest-updates__tab:last-child[aria-selected="true"] {
    border-bottom: 0;
  }

  /* No flex gap between tabs/panels — the tabs already provide their
     own visual rhythm via padding + border-top. The header keeps a
     bottom margin so it doesn't collapse against the first tab. */
  .latest-updates__inner {
    gap: 0;
  }

  .latest-updates__header {
    margin-bottom: var(--space-6);
  }

  /* Cards inside the active accordion panel tile as a 2×2 grid down to
     696px, then collapse to a single column on phones. Overrides the
     --lu-cols desktop count so phones/tablets don't get the 3- or
     4-wide layout that's only legible at full width.
     margin-bottom (not padding-bottom) creates empty space between
     the panel's outer border and the next tab's border-top; padding
     would have shown the grid container's gray bg color as a strip
     below the last card. */
  .latest-updates__panel.is-active {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin-bottom: var(--space-6);
  }
}

/* Single-column phones: drop the 2×2 down to a stack. */
@media (max-width: 695px) {
  .latest-updates__panel.is-active {
    grid-template-columns: 1fr;
  }
}

/* ---------------------------------------------------------------
   Scroll-driven reveal stagger
   Header → tabs → panels cascade in as the section enters viewport.
   The .is-active panel's own latest-updates-panel-in keyframe still
   handles tab switches (unchanged).
   --------------------------------------------------------------- */
.latest-updates__tabs   { --reveal-delay: 0.1s; }
.latest-updates__panels { --reveal-delay: 0.2s; }

/* Empty-state message for a dynamic panel with no posts yet. Spans the
   full panel width inside the card grid. */
.latest-updates__empty {
  grid-column: 1 / -1;
  margin: 0;
  padding: var(--space-7_5);
  background-color: var(--color-background);
  font-family: var(--font-family-sans);
  font-size: var(--font-size-body);
  color: var(--color-text-body);
}

/* ---------------------------------------------------------------
   Newsletter filler — fills the trailing cell when a tab has an odd
   number of cards (appended in PHP). Dark navy, modeled on the
   research-breakthroughs stat card; sits as a normal grid cell.
   --------------------------------------------------------------- */
.latest-updates__filler {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--space-6);
  padding: var(--space-7);
  min-height: 263px;
  background-color: var(--color-navy-blue);
  color: var(--color-text-on-dark);
}

.latest-updates__filler-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.latest-updates__filler-heading {
  font-family: var(--font-family-display);
  font-size: var(--font-size-h4);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-card-title);
  margin: 0;
}

.latest-updates__filler-text {
  font-family: var(--font-family-sans);
  font-size: var(--font-size-body);
  line-height: 1.5;
  margin: 0;
  color: rgb(255 255 255 / 0.75);
}

.latest-updates__filler-form {
  position: relative;
}

.latest-updates__filler-input {
  width: 100%;
  padding: var(--space-4) 56px var(--space-4) var(--space-5);
  border-radius: var(--radius-pill);
  border: 1px solid rgb(255 255 255 / 0.3);
  background-color: transparent;
  color: var(--color-text-on-dark);
  font-family: var(--font-family-sans);
  font-size: var(--font-size-sm);
}

.latest-updates__filler-input::placeholder {
  color: rgb(255 255 255 / 0.5);
}

.latest-updates__filler-submit {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 50%;
  background-color: var(--color-accent);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background-color 0.2s ease;
}

.latest-updates__filler-submit:hover,
.latest-updates__filler-submit:focus-visible {
  background-color: #fff;
}

.latest-updates__filler-submit svg {
  width: 20px;
  height: auto;
  fill: var(--color-navy-blue);
}
