/* Kinetic Headline — block styles */

.kinetic-headline {
  position: relative;
  /* Full-bleed at first paint. The JS below re-measures and corrects for
     asymmetric containers, but in a centred one (Dawn's page-width wrapper)
     this already matches what the JS computes, so nothing shifts. Leaving it
     at width:100% meant every block rendered inset until its script finished
     downloading — a visible gap on every load. */
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--kh-padding-y, 40px) 1.5rem;
  background-color: var(--kh-bg-color, #333333);
  color: var(--kh-heading-color, #fff);
  overflow: hidden;
  isolation: isolate;
  /* Every other block sets this; Kinetic Headline was the one that didn't.
     Without it the 1.5rem side padding is added OUTSIDE the width, so the
     full-bleed width of one viewport became viewport + 48px and the page
     picked up a horizontal scrollbar. */
  box-sizing: border-box;
}

.kinetic-headline--bg-image .kinetic-headline__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.kinetic-headline__bg-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.kinetic-headline__overlay {
  /* Dawn ships a rule that collapses empty leaf div elements — same
     bug we hit on Counter Scroll and Flip Cards overlays. !important
     is the reliable override so the merchant's Image overlay opacity
     slider actually paints on Dawn (already worked on Horizon). */
  display: block !important;
  position: absolute;
  inset: 0;
  background-color: rgba(0, 0, 0, var(--kh-overlay-alpha, 0.35));
  pointer-events: none;
}

.kinetic-headline__content {
  position: relative;
  z-index: 1;
  max-width: 1100px;
  width: 100%;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.75rem;
}

/* Headline + size variants */
.kinetic-headline__heading {
  margin: 0;
  font-family: var(--kh-font-family, "Helvetica Neue", Arial, sans-serif);
  font-style: var(--kh-font-style, normal);
  font-weight: var(--kh-font-weight, 800);
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--kh-heading-color, #fff);
  word-break: break-word;
}

.kinetic-headline--size-md .kinetic-headline__heading { font-size: clamp(1.75rem, 4vw, 2.75rem); }
.kinetic-headline--size-lg .kinetic-headline__heading { font-size: clamp(2.25rem, 6vw, 4.5rem); }
.kinetic-headline--size-xl .kinetic-headline__heading { font-size: clamp(3rem,   8vw, 6.5rem); }

.kinetic-headline__static {
  display: inline;
}

/* Rotating word slot.
   The width is pinned by JS to the widest rotating word so prefix/suffix
   wrap positions stay stable across rotations — nothing shifts around it.
   Text-align centers the shorter words inside that fixed-width slot. */
.kinetic-headline__word {
  position: relative;
  display: inline-block;
  color: var(--kh-accent-color, #ff8820);
  /* Wraps rather than running off. This was `nowrap`, which combined with the
     JS-pinned pixel width meant a long word simply extended past the block
     and got cut off at both ends by overflow:hidden. The pinning still keeps
     the slot a fixed size; it just wraps inside it now. */
  white-space: normal;
  overflow-wrap: break-word;
  /* Safety net for first paint, before the JS has measured. */
  max-width: 100%;
  min-width: 0.5em;
  margin-inline: 0.25em;
  vertical-align: baseline;
  text-align: center;
  will-change: transform, opacity, filter;
  transform-origin: center;
}

/* Caret used by typewriter mode */
.kinetic-headline__word--typewriter::after {
  content: '';
  display: inline-block;
  width: 0.06em;
  height: 0.95em;
  margin-left: 0.06em;
  vertical-align: -0.05em;
  background-color: currentColor;
  animation: khCaretBlink 0.9s steps(2, end) infinite;
}

@keyframes khCaretBlink {
  0%, 50%   { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}

/* ===== Button =====
   Outlined CTA whose text + border are driven by --kh-cta-color. Same
   treatment as Flip Cards' back-of-card button so behavior stays
   consistent across blocks and themes. */
.kinetic-headline__actions {
  display: flex;
  align-items: center;
  justify-content: center;
}
.kinetic-headline__button.button,
.kinetic-headline__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--kh-cta-color, #FF8820);
  border: 1px solid var(--kh-cta-color, #FF8820);
  text-decoration: none;
  /* Only box-shadow transitions — used to thicken the outline on hover. */
  transition: box-shadow 0.15s ease;
}
/* Dawn (and some other OS 2.0 themes) draw a second "shadow border" on
   .button via ::before/::after pseudo-elements. Kill both so only our
   controlled 1px border shows. */
.kinetic-headline__button.button::before,
.kinetic-headline__button.button::after {
  content: none !important;
  display: none !important;
}
/* Hover: bg stays transparent, text color unchanged, outline thickens
   via inset box-shadow (no layout shift). */
.kinetic-headline__button:hover,
.kinetic-headline__button:focus-visible {
  background-color: transparent;
  color: var(--kh-cta-color, #FF8820);
  box-shadow: inset 0 0 0 2px var(--kh-cta-color, #FF8820);
}
/* Disabled variant: merchant set a label but no link. Rendered as a
   non-anchor span so it's non-clickable + non-focusable by default;
   dimmed opacity + not-allowed cursor communicate the state visually. */
.kinetic-headline__button--disabled {
  opacity: 0.55;
  pointer-events: none;
  cursor: not-allowed;
  user-select: none;
}
.kinetic-headline__button--disabled:hover,
.kinetic-headline__button--disabled:focus-visible {
  background-color: transparent;
  color: var(--kh-cta-color, #FF8820);
  box-shadow: none;
}

/* ===== Animations =====
   Each animation has an "enter" keyframe applied when the new word arrives.
   The JS swaps text content during the brief moment the old word is leaving
   (or for typewriter/type-in, drives the reveal directly). */

/* slide-up */
@keyframes khSlideUp {
  from { opacity: 0; transform: translateY(100%); }
  to   { opacity: 1; transform: translateY(0); }
}
.kinetic-headline--anim-slide-up .kinetic-headline__word.kh-enter {
  animation: khSlideUp 0.5s cubic-bezier(0.16, 0.84, 0.32, 1) both;
}

/* slide-down */
@keyframes khSlideDown {
  from { opacity: 0; transform: translateY(-100%); }
  to   { opacity: 1; transform: translateY(0); }
}
.kinetic-headline--anim-slide-down .kinetic-headline__word.kh-enter {
  animation: khSlideDown 0.5s cubic-bezier(0.16, 0.84, 0.32, 1) both;
}

/* flip-vertical */
@keyframes khFlipVertical {
  from { opacity: 0; transform: rotateX(-90deg); }
  to   { opacity: 1; transform: rotateX(0); }
}
.kinetic-headline--anim-flip-vertical .kinetic-headline__word.kh-enter {
  animation: khFlipVertical 0.6s cubic-bezier(0.2, 0.6, 0.2, 1) both;
  transform-origin: center bottom;
  perspective: 600px;
}

/* scale-in */
@keyframes khScaleIn {
  from { opacity: 0; transform: scale(0.5); }
  to   { opacity: 1; transform: scale(1); }
}
.kinetic-headline--anim-scale-in .kinetic-headline__word.kh-enter {
  animation: khScaleIn 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

/* blur-in */
@keyframes khBlurIn {
  from { opacity: 0; filter: blur(14px); }
  to   { opacity: 1; filter: blur(0); }
}
.kinetic-headline--anim-blur-in .kinetic-headline__word.kh-enter {
  animation: khBlurIn 0.55s ease-out both;
}

/* type-in (letter-by-letter fade — driven by JS adding <span class="kh-char"> with stagger) */
@keyframes khCharIn {
  from { opacity: 0; transform: translateY(0.1em); }
  to   { opacity: 1; transform: translateY(0); }
}
.kinetic-headline--anim-type-in .kinetic-headline__word .kh-char {
  display: inline-block;
  opacity: 0;
  animation: khCharIn 0.25s ease forwards;
}

/* Keeps a word's characters together. Each .kh-char is inline-block, and
   browsers allow a line break between adjacent inline-blocks — so without
   this, Type in could break a line at any character ("summersalepic" /
   "ks"). Breaks now fall only on the real spaces between groups. JS drops
   the grouping if a single token is wider than the slot, since nowrap would
   otherwise stop it breaking at all and it would overflow. */
.kinetic-headline__word .kh-word {
  white-space: nowrap;
}

/* typewriter visuals handled via the caret class above; the typing itself is JS-driven. */

/* Reduced motion: snap to final state, no anim loops */
@media (prefers-reduced-motion: reduce) {
  .kinetic-headline__word,
  .kinetic-headline__word .kh-char {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
  }
  .kinetic-headline__word--typewriter::after {
    animation: none;
  }
}

/* Mobile tweaks */
@media (max-width: 600px) {
  .kinetic-headline { padding: var(--kh-padding-y, 40px) 1rem; }
  .kinetic-headline__content { gap: 1.25rem; }
}
