/* ==========================================================================
   Texium Solutions — Page title banner
   Breadcrumb + heading (+ optional description) on the left, a circular
   featured image on the right. Rendered by template-parts/page-title.php
   on every non-Elementor template, so every page except Home / About us
   (which Elementor builds directly) gets one automatically.
   Consumes design tokens from theme.css only.
   ========================================================================== */

.texium-page-title {
  padding-block: var(--texium-space-3xl) var(--texium-space-2xl);
  overflow: hidden;
}

.texium-page-title__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
  align-items: center;
  gap: var(--texium-space-2xl);
}

.texium-page-title--no-image .texium-page-title__inner {
  grid-template-columns: 1fr;
}

/* ---- Dark full-width background variant ----
   Opt-in per page/post (see inc/page-title-meta.php's "Dark full-width
   background" checkbox). Replaces the side X-image column entirely: a
   single centered content column over a full-bleed cover background
   (the page's own featured image, via the --texium-page-title-bg-image
   custom property set inline on the <header>) with a dark gradient
   wash for contrast, and every text element inside switched to white/
   light variants. */

.texium-page-title--dark-bg {
  position: relative;
  background-color: #0B1220;
  isolation: isolate;
}

.texium-page-title--dark-bg::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -2;
  background-image: var(--texium-page-title-bg-image, none);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}

.texium-page-title--dark-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, rgba(11, 18, 32, 0.85) 0%, rgba(11, 18, 32, 0.78) 60%, rgba(11, 18, 32, 0.92) 100%);
}

.texium-page-title--dark-bg .texium-page-title__inner {
  grid-template-columns: 1fr;
}

.texium-page-title--dark-bg .texium-page-title__content {
  width: 70%;
}

.texium-page-title--dark-bg .texium-page-title__heading,
.texium-page-title--dark-bg .texium-page-title__subtitle,
.texium-page-title--dark-bg .texium-page-title__desc {
  color: #FFFFFF;
}

.texium-page-title--dark-bg .texium-page-title__meta {
  color: rgba(255, 255, 255, 0.7);
}

.texium-page-title--dark-bg .texium-breadcrumbs__item a {
  color: rgba(255, 255, 255, 0.7);
}

.texium-page-title--dark-bg .texium-breadcrumbs__item a:hover,
.texium-page-title--dark-bg .texium-breadcrumbs__item a:focus-visible,
.texium-page-title--dark-bg .texium-breadcrumbs__item [aria-current='page'] {
  color: #FFFFFF;
}

.texium-page-title--dark-bg .texium-breadcrumbs__sep {
  color: rgba(255, 255, 255, 0.4);
}

.texium-page-title__content {
  min-width: 0;
}

.texium-page-title__heading {
  margin: var(--texium-space-sm) 0 0;
  font-family: var(--texium-font-heading);
  font-size: var(--texium-font-size-h1);
  font-weight: var(--texium-weight-bold);
  line-height: var(--texium-leading-tight);
  color: var(--texium-heading);
}

/* Highlight: identical gradient technique/animation as the Section
   Heading widget (assets/css/widgets/section-heading.css), so a
   highlighted word here reads as the same brand treatment. */

.texium-page-title__highlight {
  background: linear-gradient(
    100deg,
    var(--texium-primary-dark),
    var(--texium-x-blue) 35%,
    var(--texium-x-cyan) 65%,
    var(--texium-x-bright)
  );
  background-size: 250% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: texium-section-heading-gradient-flow 5s ease-in-out infinite;
}

@keyframes texium-section-heading-gradient-flow {
  0%,
  100% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .texium-page-title__highlight {
    animation: none;
  }
}

.texium-page-title__meta {
  display: inline-block;
  margin: var(--texium-space-sm) 0 0;
  font-size: var(--texium-font-size-xs);
  font-weight: var(--texium-weight-semibold);
  letter-spacing: var(--texium-tracking-wide);
  text-transform: uppercase;
  color: var(--texium-text-muted);
}

.texium-page-title__subtitle {
  margin: var(--texium-space-sm) 0 0;
  max-width: 52ch;
  font-size: 24px;
  font-weight: var(--texium-weight-semibold);
  line-height: var(--texium-leading-body);
  color: #000;
}

.texium-page-title__desc {
  margin: var(--texium-space-md) 0 0;
  max-width: 52ch;
  font-size: var(--texium-font-size-md);
  line-height: var(--texium-leading-body);
  color: #000;
}

/* ---- CTA button ----
   Same tilted-arrow, no-fade swipe treatment as the header "Get in
   touch" button (assets/css/header.css), duplicated locally so this
   stylesheet works standalone on templates that don't load header.css
   animations in the same cascade layer. */

.texium-page-title__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--texium-space-sm);
  margin-top: var(--texium-space-lg);
}

.texium-page-title__cta-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 1rem;
  height: 1rem;
  overflow: hidden;
}

.texium-page-title__cta-arrow svg {
  width: 100%;
  height: 100%;
  transform: rotate(-45deg);
  transition: transform var(--texium-transition-fast);
}

.texium-page-title__cta:hover .texium-page-title__cta-arrow svg,
.texium-page-title__cta:focus-visible .texium-page-title__cta-arrow svg {
  animation: texium-page-title-cta-swipe 560ms cubic-bezier(0.5, 0, 0.35, 1) 1;
}

@keyframes texium-page-title-cta-swipe {
  0% {
    transform: translate(0, 0) rotate(-45deg);
  }

  50% {
    transform: translate(200%, -200%) rotate(-45deg);
  }

  50.01% {
    transform: translate(-200%, 200%) rotate(-45deg);
  }

  100% {
    transform: translate(0, 0) rotate(-45deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .texium-page-title__cta:hover .texium-page-title__cta-arrow svg,
  .texium-page-title__cta:focus-visible .texium-page-title__cta-arrow svg {
    animation: none;
  }
}

/* ---- Media, right side ----
   Two shapes: an X-mask for the brand illustration used on regular
   pages, and a softened rounded-rectangle for single posts, whose
   featured images are real (often landscape, text-bearing) photography
   or screenshots that the X mask would clip and distort. */

.texium-page-title__media-wrap {
  position: relative;
  width: 100%;
  margin-inline: auto;
}

.texium-page-title--media-x .texium-page-title__media-wrap {
  max-width: 640px;
}

.texium-page-title__media {
  position: relative;
  width: 100%;
  overflow: hidden;
  isolation: isolate;
}

/* Registered so the browser can smoothly interpolate the wave's radius
   between keyframes — without this, a custom property used inside a
   mask-image function jumps instantly instead of animating. */
@property --texium-wave-r {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 0%;
}

/* ---- Glowing dot wave ----
   Not a separate ring of new dots — this reuses the section's own
   background dot pattern (.texium-pattern-dots::after, defined in
   theme.css) and brightens it in an expanding ring that originates at
   the image and washes outward, fading out toward the edge of the
   section rather than toward the image. Layered on the existing ::after
   via a second radial-mask + brightness overlay, so the same dots glow
   in place instead of new dots being drawn. */

.texium-page-title--media-x {
  position: relative;
}

/* Two layers, staggered half a cycle apart, so a new ripple is always
   launching before the previous one finishes fading — continuous
   concentric waves, like a stone dropped in water, instead of one wave
   with a long dead gap before the next. */

.texium-page-title--media-x::before,
.texium-page-title--media-x::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: radial-gradient(var(--texium-x-cyan) var(--texium-dot-size), transparent var(--texium-dot-size));
  background-size: var(--texium-dot-gap) var(--texium-dot-gap);
  background-position: 0 0;
  background-repeat: repeat;
  /* A thin ring band, not a filled disc: transparent center, opaque
     band, transparent again past it. Animating the band's two radii
     outward (rather than mask-size) makes it read as a wave passing
     over the dots rather than a circle growing from nothing. Origin
     sits under the X image (right side of the banner). */
  -webkit-mask-image: radial-gradient(circle at 80% 50%, transparent calc(var(--texium-wave-r, 0%) - 14%), #000 var(--texium-wave-r, 0%), transparent calc(var(--texium-wave-r, 0%) + 14%));
  mask-image: radial-gradient(circle at 80% 50%, transparent calc(var(--texium-wave-r, 0%) - 14%), #000 var(--texium-wave-r, 0%), transparent calc(var(--texium-wave-r, 0%) + 14%));
  animation: texium-page-title-dot-wave 6s ease-in-out infinite;
}

.texium-page-title--media-x::after {
  animation-delay: 3s;
}

@keyframes texium-page-title-dot-wave {
  0% {
    --texium-wave-r: 12%;
    opacity: 0.9;
  }
  100% {
    --texium-wave-r: 75%;
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .texium-page-title--media-x::before,
  .texium-page-title--media-x::after {
    animation: none;
    display: none;
  }
}

/* ---- X-shaped mask ----
   Reusable global image treatment: a normal rectangular image (featured
   image or the Customizer default) clipped into a rounded "X" via a
   shared SVG clipPath, with a separate outline SVG tracing the exact
   same geometry so the border always lines up with the mask. The
   uploaded image file itself is never touched — only its on-screen
   presentation is X-shaped. All selectors are scoped under
   .texium-page-title-image so nothing here can leak onto other images
   on the site. */

.texium-page-title-image {
  position: relative;
  width: 100%;
  max-width: 640px;
  /* Matches the source shape's own proportions (1171 x 930 viewBox from
     xshape.svg) so the clip never stretches the X off-model. */
  aspect-ratio: 1171 / 930;
  margin-inline: auto;
}

.texium-page-title-image__mask {
  position: absolute;
  inset: 0;
  overflow: hidden;
  /* The clip path is a true constant-width inward offset of the source
     X (computed via polygon offsetting, not a CSS transform) — a scale
     transform shrinks proportionally to the center, which leaves a much
     wider gap at the shape's points than along its arms. This path is
     already smaller by the same actual distance everywhere. */
  clip-path: url(#texium-page-title-x-clip);
}

.texium-page-title-image__image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  transition: transform 700ms var(--texium-ease-out, ease);
}

@media (hover: hover) {
  .texium-page-title-image:hover .texium-page-title-image__image {
    transform: scale(1.03);
  }
}

@media (prefers-reduced-motion: reduce) {
  .texium-page-title-image__image {
    transition: none;
  }
}

.texium-page-title-image__outline {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.texium-page-title-image__outline path:not(.texium-page-title-image__outline-litup) {
  fill: none;
  /* Falls back to the flat Customizer color when the browser can't
     resolve the SVG gradient (very old browsers); the gradient
     definition itself lives inline in page-title.php, right beside
     this outline path, so it always shares the same geometry. */
  stroke: var(--texium-page-title-x-border-color, var(--texium-x-cyan));
  stroke: url(#texium-page-title-x-outline-gradient);
  stroke-width: var(--texium-page-title-x-border-width, 1.4);
  opacity: var(--texium-page-title-x-border-opacity, 0.85);
  vector-effect: non-scaling-stroke;
}

/* ---- Border color-shift as the comet passes ----
   A solid-colored copy of the border, same stroke width as the base
   outline — no blur, no extra thickness — revealed only where the
   orbit mask (a soft circle moving in lockstep with the visible comet,
   via the identical animateMotion + mpath) currently sits. The border
   itself changes color locally as the light passes over it. */

.texium-page-title-image__outline-litup {
  fill: none;
  stroke: var(--texium-x-bright);
  stroke-width: var(--texium-page-title-x-border-width, 1.4);
  vector-effect: non-scaling-stroke;
}

/* Glowing infinite gradient sweep: the gradient's own start/end points
   travel back and forth along the outline, so the color band appears
   to flow continuously around the border rather than sitting static. */

.texium-page-title-image__outline-gradient {
  animation: texium-page-title-x-gradient-sweep 14s ease-in-out infinite;
}

@keyframes texium-page-title-x-gradient-sweep {
  0% {
    x1: 0%;
    y1: 0%;
    x2: 60%;
    y2: 40%;
  }
  50% {
    x1: 40%;
    y1: 60%;
    x2: 100%;
    y2: 100%;
  }
  100% {
    x1: 0%;
    y1: 0%;
    x2: 60%;
    y2: 40%;
  }
}

.texium-page-title-image__outline-dot {
  opacity: 0.95;
}

.texium-page-title-image__outline-trail {
  opacity: 0.35;
  mix-blend-mode: screen;
}

@media (prefers-reduced-motion: reduce) {
  .texium-page-title-image__outline-gradient {
    animation: none;
  }

  /* animateMotion is SMIL, not CSS — it can't be turned off by a CSS
     animation: none rule, so the moving dot/trail/litup border are
     hidden outright instead to respect the reduced-motion preference.
     The orbit mask's own circle keeps animating regardless (masks
     aren't covered by this query), but with the litup path itself
     hidden that has no visible effect. */
  .texium-page-title-image__outline-dot,
  .texium-page-title-image__outline-trail,
  .texium-page-title-image__outline-litup {
    display: none;
  }
}

.texium-page-title--media-rounded .texium-page-title__media {
  aspect-ratio: 4 / 3;
  max-width: 560px;
  border-radius: var(--texium-radius-xl);
  box-shadow: var(--texium-shadow-lg);
}

.texium-page-title__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---- Breadcrumb ---- */

.texium-breadcrumbs {
  margin-bottom: var(--texium-space-xs);
}

.texium-breadcrumbs__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35em;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--texium-font-size-xs);
  font-weight: var(--texium-weight-semibold);
  letter-spacing: var(--texium-tracking-wide);
  text-transform: uppercase;
}

.texium-breadcrumbs__item {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
}

.texium-breadcrumbs__item a {
  color: var(--texium-text-muted);
  text-decoration: none;
  transition: color var(--texium-transition-fast);
}

.texium-breadcrumbs__item a:hover,
.texium-breadcrumbs__item a:focus-visible {
  color: var(--texium-primary);
}

.texium-breadcrumbs__item [aria-current='page'] {
  color: var(--texium-primary);
}

.texium-breadcrumbs__sep {
  color: var(--texium-border-strong);
}

/* ---- Responsive ---- */

@media (max-width: 900px) {
  .texium-page-title {
    padding-block: var(--texium-space-2xl) var(--texium-space-xl);
  }

  .texium-page-title__inner {
    grid-template-columns: 1fr;
    gap: var(--texium-space-lg);
    text-align: center;
  }

  .texium-page-title__content {
    order: 2;
  }

  .texium-breadcrumbs__list {
    justify-content: center;
  }

  .texium-page-title__desc {
    margin-inline: auto;
  }

  .texium-page-title__media-wrap {
    order: 1;
    max-width: 220px;
  }

  /* The X mask specifically needs more room than the old circle did —
     a 220px-wide X reads as a sliver, not a shape. Tablet keeps the X
     proportions, mobile caps width but keeps the silhouette readable. */
  .texium-page-title--media-x .texium-page-title__media-wrap {
    max-width: 480px;
  }
}

@media (max-width: 600px) {
  .texium-page-title--media-x .texium-page-title__media-wrap {
    max-width: 360px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .texium-breadcrumbs__item a {
    transition: none;
  }
}
