/* -- Typewriter component ---------------------------------------
   A line typed character by character behind a cursor, deleted and
   cycled through a list of strings. The authored strings stay in the DOM
   for assistive tech (visually hidden); the runtime paints an aria-hidden
   copy. Without script, the first string shows as plain text. */

@layer components {
  .typewriter {
    --_cursor: var(--typewriter-cursor-color, currentColor);
    position: relative;
    display: inline;

    /* no script (or not yet initialized): the first string, as text */
    &:not([data-init]) > :not(:first-child) { display: none; }

    /* initialized: the authored strings are read, not seen */
    & > .typewriter-source {
      position: absolute;
      width: 1px;
      height: 1px;
      margin: -1px;
      padding: 0;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }

    & > .typewriter-line { white-space: pre-wrap; }

    /* -- Cursor: a bar by default; solid while typing, blinking idle -- */
    & .typewriter-cursor {
      display: inline-block;
      width: max(2px, 0.08em);
      height: 1.1em;
      margin-inline-start: 0.06em;
      vertical-align: -0.15em;
      background: var(--_cursor);
      animation: typewriter-blink 1s steps(1) infinite;
    }
    &:is([data-phase="typing"], [data-phase="deleting"]) .typewriter-cursor { animation: none; }

    &[data-cursor="block"] .typewriter-cursor { width: 0.55em; opacity: 0.85; }
    &[data-cursor="underscore"] .typewriter-cursor {
      width: 0.6em;
      height: max(2px, 0.1em);
      vertical-align: -0.1em;
    }
    &[data-cursor="none"] .typewriter-cursor { display: none; }
    /* data-cursor-hide: "typing" = only while idle; "done" = gone at the end */
    &[data-cursor-hide="typing"]:is([data-phase="typing"], [data-phase="deleting"]) .typewriter-cursor,
    &[data-cursor-hide="done"][data-state-name="done"] .typewriter-cursor { visibility: hidden; }

    /* -- data-reserve: as wide as the longest string from the start --- */
    &[data-reserve] {
      display: inline-grid;
      justify-items: start;
      vertical-align: bottom;
      & > :is(.typewriter-line, .typewriter-ghost) { grid-area: 1 / 1; }
      & > .typewriter-ghost {
        display: grid;
        visibility: hidden;
        pointer-events: none;
        /* room for the cursor after the longest string */
        padding-inline-end: 0.2em;
        & > span { grid-area: 1 / 1; white-space: pre; }
      }
      & > .typewriter-line { white-space: pre; }
    }
    &[data-reserve][data-align="center"] { justify-items: center; }
    &[data-reserve][data-align="end"] { justify-items: end; }
  }

  @keyframes typewriter-blink {
    50% { opacity: 0; }
  }

  /* -- Accessibility -------------------------------------------- */
  @media (prefers-reduced-motion: reduce) {
    /* the runtime swaps whole strings instead of typing; the cursor stays still */
    .typewriter .typewriter-cursor { animation: none; }
  }

  @media (prefers-contrast: more) {
    .typewriter[data-cursor="block"] .typewriter-cursor { opacity: 1; }
  }

  @media (forced-colors: active) {
    .typewriter .typewriter-cursor { background: CanvasText; forced-color-adjust: none; }
  }
}
