/* ==============================================================================================
   glitch.css — styles owned by js/glitch-text.js (all classes prefixed `gt-`).
   Strict 1-bit: only currentColor / #000 / #fff. No colours are hard-coded for text, so every
   effect works inside light sections and `.invert` sections alike.
   ============================================================================================== */

/* ---------- shared: screen-reader-only copy ------------------------------------------------ */
.gt-sr {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  list-style: none;
}

/* ---------- decode -------------------------------------------------------------------------
   Visible glyphs are generated content, so the only text node inside a decoding element is the
   .gt-sr copy of the final text (el.textContent stays === final text throughout).
   .gt-word     nowrap group so lines break exactly like the final text
   .gt-sp       whitespace between words (data-g), keeps natural break opportunities
   .gt-ch       one grapheme; its real glyph (::before, data-g) stays in flow but hidden, so the
                cell has the final width/height/baseline and nothing reflows while glyphs cycle
   .gt-ch__s    scramble glyph (::before, data-s) painted on top, clipped to the cell
   .is-pop      ~1-frame solid ink block right before the glyph locks ("stamp")
   .is-done     locked: real glyph visible                                                      */
.gt-word {
  white-space: nowrap;
}

.gt-sp::before {
  content: attr(data-g);
}

.gt-ch {
  position: relative;
  display: inline-block;
  vertical-align: baseline;
}

.gt-ch::before {
  content: attr(data-g);
  visibility: hidden;
}

.gt-ch__s {
  position: absolute;
  inset: 0;
  overflow: hidden;
  text-align: center;
  white-space: pre;
  pointer-events: none;
  font-variant-ligatures: none;
}

.gt-ch__s::before {
  content: attr(data-s);
}

.gt-ch.is-pop .gt-ch__s {
  background: currentColor;
}

.gt-ch.is-done::before {
  visibility: visible;
}

.gt-ch.is-done .gt-ch__s {
  display: none;
}

/* ---------- ditherReveal overlay ----------------------------------------------------------- */
.gt-reveal {
  position: absolute;
  z-index: 20;
  display: block;
  margin: 0;
  padding: 0;
  border: 0;
  max-width: none;
  pointer-events: none;
  image-rendering: pixelated;
}

/* ---------- glitchOnce ----------------------------------------------------------------------
   250 ms, 7 hard steps (≈ 28 fps): lone shifted band → band cut out → top slice → bottom slice →
   mirrored band → whole-but-shifted → settle. Offsets & slice positions come from --gt-* custom
   properties randomised per call in JS (fallbacks keep it working if JS didn't set them).         */
.gt-glitch {
  animation: gt-glitch var(--gt-glitch-dur, 250ms) steps(1, end) 1 both;
}

.gt-glitch--ib {
  display: inline-block;
}

@keyframes gt-glitch {
  0% {
    transform: translate3d(var(--gt-x1, -6px), 0, 0);
    clip-path: inset(var(--gt-a, 22%) 0 var(--gt-b, 38%) 0);
  }
  14% {
    transform: translate3d(var(--gt-x2, 4px), 0, 0);
    clip-path: polygon(
      0 0, 100% 0, 100% var(--gt-c, 30%), 0 var(--gt-c, 30%),
      0 var(--gt-d, 62%), 100% var(--gt-d, 62%), 100% 100%, 0 100%
    );
  }
  28% {
    transform: translate3d(0, 0, 0);
    clip-path: inset(0 0 var(--gt-e, 46%) 0);
  }
  42% {
    transform: translate3d(var(--gt-x3, -2px), 0, 0);
    clip-path: inset(var(--gt-f, 40%) 0 0 0);
  }
  57% {
    transform: translate3d(calc(var(--gt-x1, -6px) * -1), 0, 0);
    clip-path: inset(var(--gt-b, 38%) 0 var(--gt-a, 22%) 0);
  }
  71% {
    transform: translate3d(var(--gt-x2, 4px), 0, 0);
    clip-path: inset(0);
  }
  85% {
    transform: translate3d(0, 0, 0);
    clip-path: polygon(
      0 0, 100% 0, 100% var(--gt-d, 62%), 0 var(--gt-d, 62%),
      0 calc(var(--gt-d, 62%) + 6%), 100% calc(var(--gt-d, 62%) + 6%), 100% 100%, 0 100%
    );
  }
  100% {
    transform: none;
    clip-path: none;
  }
}

/* ---------- createTicker ----------------------------------------------------------------------
   The shell styles the bar itself (.ticker: black, 56px, mono). These rules are structural only. */
.gt-ticker {
  position: relative;
  display: flex;
  align-items: center;
  overflow: hidden;
  white-space: nowrap;
}

.gt-ticker__track {
  display: flex;
  flex: none;
  width: max-content;
  animation: gt-marquee var(--gt-ticker-dur, 40s) linear infinite;
  will-change: transform;
}

.gt-ticker__group {
  display: flex;
  flex: none;
  align-items: center;
}

.gt-ticker__item {
  display: inline-block;
  padding: 0 1.15em;
}

.gt-ticker__name {
  font-weight: 700;
}

.gt-ticker__sep {
  display: inline-block;
  line-height: 1;
}

/* Hover-pause only where hovering exists (a tap must not freeze it on phones); the toggle button and
   keyboard focus pause it everywhere. */
@media (hover: hover) {
  .gt-ticker:hover .gt-ticker__track {
    animation-play-state: paused;
  }
}

.gt-ticker:focus-within .gt-ticker__track,
.gt-ticker.is-paused .gt-ticker__track {
  animation-play-state: paused;
}

/* Pause / play control, pinned to the right end of the bar (shell may restyle it). */
.gt-ticker__toggle {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 48px;
  padding: 0;
  border: 0;
  border-left: 2px solid currentColor;
  background: inherit;
  color: inherit;
  cursor: pointer;
}

.gt-ticker__toggle[hidden] {
  display: none;
}

.gt-ticker__toggle .gt-ticker__ico-play,
.gt-ticker__toggle[aria-pressed="true"] .gt-ticker__ico-pause {
  display: none;
}

.gt-ticker__toggle[aria-pressed="true"] .gt-ticker__ico-play {
  display: inline;
}

.gt-ticker__toggle:focus-visible {
  outline: 2px dashed currentColor;
  outline-offset: -8px;
}

/* reduced motion → static, horizontally scrollable strip */
.gt-ticker.is-static {
  overflow-x: auto;
  scrollbar-width: none;
}

.gt-ticker.is-static::-webkit-scrollbar {
  display: none;
}

.gt-ticker.is-static .gt-ticker__track {
  animation: none;
  will-change: auto;
}

@keyframes gt-marquee {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(-50%, 0, 0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .gt-ticker__track,
  .gt-glitch {
    animation: none !important;
  }
}
