/* --- Full-screen, 3D-tilt card sections (services list + benefits grids) ---
   Scoped entirely to new classes/attributes rather than touching the shared
   .card/.grid rules those live in components.css/layout.css — .card is used
   site-wide (home, about, portfolio), so a global change there would leak
   into pages that never asked for a 3D-tilt or full-screen treatment. Used
   by both the services index page (service list + "Why Choose Konstent")
   and every service detail page (capabilities + "Why Konstent for X"). */

.services-fullscreen-section {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  padding-block: var(--space-2xl);
  /* Deliberately NOT clipped. card-fan-scroll.js's "bunch" converges on the
     centre of the VIEWPORT (a fixed screen position) — horizontally that's
     always safely between a card's own natural left/right position (both
     already within the viewport), so it can't push a card past the left/
     right edge; only vertically can the bunch sit outside THIS section's
     own current box while the section is still scrolling into place, and
     clipping the section to contain that visually cut cards off mid-bunch
     (the section's box doesn't yet span the viewport at that point — the
     clip boundary and the "is the viewport-centre point actually inside
     this section" boundary don't line up). Letting the page scroll a
     little taller during the transient bunch state is a fine trade for not
     slicing a card in half. */
}

.services-fullscreen-section .container {
  width: 100%;
}

/* IMPORTANT: .container--full itself must NOT clip when it's nested inside
   a .services-fullscreen-section (capabilities/benefits/services-list/why-
   choose) — that inner div is sized to fit just its own heading+grid
   content, much smaller than the full-screen section around it. The
   card-fan "bunch" converges on the centre of the VIEWPORT, a point that
   can fall outside this narrower div's own box even while comfortably
   inside the section's — clipping HERE as well cut cards off mid-bunch.
   Containment for that case comes from the outer section's own
   overflow:clip above; nesting a second clip here just re-introduces the
   cutting.
   Related Services/FAQ/CTA (a plain .section, not .services-fullscreen-
   section) still need this, for the older card-reveal-wrap translateX(70px)
   slide-in — bounded, and safely smaller than that section's own natural
   size, so clipping there doesn't cut anything real off.
   `overflow: clip` (both axes), not `overflow-x` alone: per the CSS
   overflow spec, ANY non-visible value on one axis — even `clip` — forces
   the UA to convert the other axis's "visible" to "auto", including its
   own *default* value, not just an explicit declaration. An overflow-x-only
   rule was silently turning the element into its own scrollable-Y
   container the moment there was even a few px of incidental vertical
   overflow (a shadow, a border, sub-pixel rounding) — exactly what
   produced a second, unwanted scrollbar the first time this was written.
   `clip` on both axes never establishes a scroll container at all, so
   that mismatch can't happen. */
.section:not(.services-fullscreen-section) .container--full {
  overflow: clip;
}

/* Product pages (VULNKON/ENTERKON/BUSSKON) reuse .services-fullscreen-section
   for full-height layout on grids that never adopted the card-fan "bunch"
   system — those still use the plain translateX(70px) slide-in, so they
   need the same clipping as a plain .section above. Scoped with :has() to
   skip only sections that DO still contain a live fan grid (today, that's
   every services-page usage), so this can't reintroduce the mid-bunch
   cutting the outer rule above was written to avoid. */
.services-fullscreen-section .container--full:not(:has([data-card-fan])) {
  overflow: clip;
}

/* FAQ: the section itself goes full width like every other section on the
   page (consistent edge-to-edge rhythm), but the actual question list
   stays at a comfortable reading width nested inside — a "container
   container--narrow" nested inside the outer "container container--full"
   would otherwise double up on side padding, so it's zeroed here. */
.faq-list-wrap {
  padding-inline: 0;
}

/* .section-head's h2 has no font-size of its own site-wide (falls back to
   the browser's unstyled default, ~1.5em) — fine for a plain text section,
   but once the cards below it got noticeably bigger, that left the
   section's own heading reading SMALLER than the cards under it, an
   inverted hierarchy. Scoped to .services-fullscreen-section specifically
   (not a change to .section-head globally) so it doesn't affect the many
   other .section-head usages site-wide. */
.services-fullscreen-section .section-head h2,
.container--full .section-head h2 {
  font-size: var(--fs-2xl);
}

/* Perspective lives on the grid so every card tilts relative to the same
   vanishing point, rather than each card getting its own detached one. */
.card-tilt-grid {
  perspective: 1600px;
}

/* [data-reveal]'s own fade/rise (components.css) sets `transform:
   translateY(...)` with !important — putting the 3D tilt transform on that
   SAME element would have one silently clobber the other every time. So
   [data-reveal] stays on this plain wrapper (the translateY fade), and the
   tilt transform applies only to the .card inside it; the wrapper just
   needs to stretch to the grid cell so the card still fills it exactly
   like it did before this wrapper existed. */
.card-reveal-wrap {
  display: flex;
  height: 100%;
}

/* Cards slide in horizontally as the grid scrolls into view, staggered
   left-to-right/row-by-row, and settle into the exact same grid you see at
   rest — a scroll-driven "cards arrive in sequence" entrance rather than
   the site's default straight-up fade. Overrides base.css's
   [data-reveal]/.is-visible translateY with a translateX here instead;
   .card-tilt-grid .card-reveal-wrap.is-visible is more specific than the
   base [data-reveal].is-visible rule so it wins even though both use
   !important. Only for grids WITHOUT the fan-deck treatment below — those
   own opacity/transform entirely via card-fan-scroll.js instead. */
.card-tilt-grid:not([data-card-fan]) .card-reveal-wrap {
  opacity: 0;
  transform: translateX(70px);
  transition: opacity 0.7s var(--ease-out), transform 0.7s var(--ease-out);
}

.card-tilt-grid:not([data-card-fan]) .card-reveal-wrap.is-visible {
  opacity: 1 !important;
  transform: translateX(0) !important;
}

.card-tilt-grid:not([data-card-fan]) .card-reveal-wrap:nth-child(1) { transition-delay: 0s; }
.card-tilt-grid:not([data-card-fan]) .card-reveal-wrap:nth-child(2) { transition-delay: 0.09s; }
.card-tilt-grid:not([data-card-fan]) .card-reveal-wrap:nth-child(3) { transition-delay: 0.18s; }
.card-tilt-grid:not([data-card-fan]) .card-reveal-wrap:nth-child(4) { transition-delay: 0.27s; }
.card-tilt-grid:not([data-card-fan]) .card-reveal-wrap:nth-child(5) { transition-delay: 0.36s; }
.card-tilt-grid:not([data-card-fan]) .card-reveal-wrap:nth-child(6) { transition-delay: 0.45s; }
.card-tilt-grid:not([data-card-fan]) .card-reveal-wrap:nth-child(n+7) { transition-delay: 0.5s; }

@media (prefers-reduced-motion: reduce) {
  .card-tilt-grid:not([data-card-fan]) .card-reveal-wrap {
    transition: none;
    transition-delay: 0s;
  }
}

/* --- Fan-deck scroll effect (card-fan-scroll.js) ---
   card-fan-scroll.js sets opacity/transform/z-index on these directly via
   inline style, continuously, driven by scroll position — deliberately no
   !important anywhere here (an !important rule beats an inline style
   regardless of specificity, which silently cancelled every frame of the
   JS-driven transform the first time this was written). The [data-reveal]
   attribute is also removed from these specific wraps in the markup so
   reveal.js's own IntersectionObserver never adds its
   opacity/translateY(!important) .is-visible state to them either — two
   different systems otherwise fighting over the same properties. */
[data-card-fan] .card-reveal-wrap {
  position: relative;
  transition: none;
}

.card-tilt-grid .card {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: var(--space-2xl);
  min-height: 16rem;
  /* A resting elevation shadow — visible even before any hover — so the
     card reads as a lifted 3D object sitting on the page, not a flat
     rectangle that only becomes "3D" while the pointer happens to be over
     it (which a static view, or a screenshot, would never show). */
  box-shadow: 0 1.5rem 2.5rem -1.25rem rgba(0, 0, 0, 0.35), 0 0.5rem 1rem -0.5rem rgba(0, 0, 0, 0.22);
  transform: perspective(1600px) rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg)) translateZ(var(--tilt-z, 0px));
  transform-style: preserve-3d;
  transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1), border-color var(--duration-base) var(--ease-out), box-shadow var(--duration-base) var(--ease-out);
  will-change: transform;
}

.card-tilt-grid .card.is-tilting {
  transition: transform 0.08s linear, border-color var(--duration-base) var(--ease-out), box-shadow var(--duration-base) var(--ease-out);
  box-shadow: 0 2.5rem 4rem -1.5rem rgba(0, 0, 0, 0.45), 0 1rem 1.5rem -0.5rem rgba(0, 0, 0, 0.3);
  border-color: var(--color-border-strong);
}

/* Per-card animated vector icon (card_icon() in helpers.php) — picked by
   keyword match against the card's own title/body, so each card gets an
   icon that fits what it actually says. .card__icon's box/color already
   exist site-wide (components.css); sizing bumped up here to match these
   bigger cards. */
.card-tilt-grid .card__icon {
  width: 3.25rem;
  height: 3.25rem;
  margin-bottom: var(--space-md);
}

.card-tilt-grid .card-icon__svg {
  width: 100%;
  height: 100%;
  overflow: visible;
}

.card-icon-draw {
  stroke-dasharray: 90;
  stroke-dashoffset: 90;
  animation: card-icon-draw-in 1.8s var(--ease-out) infinite alternate;
}

@keyframes card-icon-draw-in {
  0% { stroke-dashoffset: 90; }
  60%, 100% { stroke-dashoffset: 0; }
}

.card-icon-pulse {
  transform-box: fill-box;
  transform-origin: center;
  animation: card-icon-pulse 2.4s ease-in-out infinite;
}

@keyframes card-icon-pulse {
  0%, 100% { opacity: 0.55; transform: scale(0.92); }
  50% { opacity: 1; transform: scale(1); }
}

.card-icon-float {
  animation: card-icon-float 2.6s ease-in-out infinite;
}

@keyframes card-icon-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-2px); }
}

.card-icon-spin {
  transform-box: fill-box;
  transform-origin: center;
  animation: card-icon-spin 6s linear infinite;
}

@keyframes card-icon-spin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .card-icon-draw,
  .card-icon-pulse,
  .card-icon-float,
  .card-icon-spin {
    animation: none;
  }
}

.card-tilt-grid .card__title {
  font-size: var(--fs-lg);
  margin-bottom: var(--space-sm);
}

.card-tilt-grid .card__body {
  font-size: var(--fs-md);
  line-height: 1.6;
}

.card-tilt-grid .card__link {
  font-size: var(--fs-md);
  margin-top: auto;
  padding-top: var(--space-md);
}

/* A subtle "lift" layer for the card's own content so the 3D depth reads
   as more than just a flat plane rotating. */
.card-tilt-grid .card > * {
  transform: translateZ(var(--tilt-content-z, 0px));
}

@media (prefers-reduced-motion: reduce) {
  .card-tilt-grid .card {
    transition: none;
    transform: none !important;
  }
}
