/* ==========================================================
   zxacc — Site-wide "typewriter on scroll" text reveal
   Applies to section headings (.section-title / .ps-title) and
   product-card titles (.ps-card-name) across the whole site.
   See theme-typewriter.js for the reveal engine.

   How it avoids layout shift / flashing: the JS wraps each
   character of the *existing* text in a <span class="tw-char">
   at runtime (never removes or replaces the text itself), so the
   element's full width/height is reserved from the very first
   paint — only per-character opacity is animated, nothing moves.
   If JS never runs (blocked, unsupported browser), no .tw-char
   spans are ever created, so this stylesheet has nothing to
   select and the heading/title just renders normally, fully
   visible — there is no CSS-only way to end up with hidden text.

   Purely additive: new selectors only, does not touch any other
   theme CSS. Loaded last, right after theme-faq-path.css.
   ========================================================== */

.tw-char {
    opacity: 0;
    transition: opacity .12s linear;
}
.tw-char.is-shown { opacity: 1; }

/* Blinking caret shown at the end of the text while it is actively
   typing; removed once the element finishes. */
.tw-typing::after {
    content: '';
    display: inline-block;
    width: 2px;
    height: .95em;
    margin-inline-start: 2px;
    vertical-align: -0.12em;
    background: currentColor;
    opacity: .75;
    animation: tw-caret-blink .85s step-end infinite;
}
@keyframes tw-caret-blink {
    0%, 100% { opacity: .75; }
    50% { opacity: 0; }
}

/* Respect reduced-motion: the JS itself skips the animated reveal
   and shows all characters immediately in that case (see .js), so
   this rule only needs to make sure no caret is drawn either. */
@media (prefers-reduced-motion: reduce) {
    .tw-typing::after { display: none; }
}
