@layer components {

  /* ─── The mascot ───────

     The faktura.to glyph on two pixel feet, drawn off the `mascot-sprite.svg`
     sheet: one row per state — idle, walk, look, wave, dance, type — and
     exactly four 20×17-unit frames in every row, drawn here at 2px a unit. The
     stage is the strip it moves along, a dotted floor under its feet.

     A choreography is a modifier on both: `--strolling` paces the bill's
     processing placeholder, `--dancing` celebrates the plan with no limits.
     Each one's animations share a clock: a `*-frames` animation walks
     `background-position-x` left one frame at a time (in steps, never
     returning, so each stretch ends on a multiple of the sheet's width and
     `repeat-x` wraps it around), the move animation carries and flips the
     mascot, and the row comes from `background-position-y`. */

  .mascot-stage {
    --mascot-frame-inline-size: 40px;
    --mascot-frame-block-size: 34px;
    --mascot-stroll: 140px;

    block-size: var(--mascot-frame-block-size);
    border-block-end: 2px dotted var(--color-border);
    inline-size: calc(var(--mascot-stroll) + var(--mascot-frame-inline-size));
    position: relative;
  }

  .mascot {
    background-image: url("/assets/mascot-sprite-72574e40.svg");
    background-repeat: repeat-x;
    background-size: calc(var(--mascot-frame-inline-size) * 4) calc(var(--mascot-frame-block-size) * 6);
    block-size: var(--mascot-frame-block-size);
    display: block;
    inline-size: var(--mascot-frame-inline-size);
    inset-block-end: 0;
    inset-inline-start: 0;
    position: absolute;
  }

  /* ─── Strolling ───────

     While a document is read, the mascot strolls to the middle, stops, looks
     left and right, walks on to the far end, waves, and strolls back to turn
     around — a 21-second loop, timed below in sevenths of the way through.
     `states` picks the row with `background-position-y`. */

  .mascot--strolling {
    animation:
      mascot-stroll 21s linear infinite,
      mascot-frames 21s infinite,
      mascot-states 21s step-end infinite;
  }

  /* 0–3s walk right, 3–5s idle, 5–8s look, 8–11s walk right, 11–14s wave,
     14–19s walk back, 19–21s idle facing left; the loop's restart turns it. */
  @keyframes mascot-stroll {
    0%       { transform: translateX(0) scaleX(1); }
    14.2857% { transform: translateX(calc(var(--mascot-stroll) / 2)) scaleX(1); }
    38.0952% { transform: translateX(calc(var(--mascot-stroll) / 2)) scaleX(1); }
    52.381%  { transform: translateX(var(--mascot-stroll)) scaleX(1); }
    66.6667% { transform: translateX(var(--mascot-stroll)) scaleX(1); animation-timing-function: step-end; }
    66.7%    { transform: translateX(var(--mascot-stroll)) scaleX(-1); }
    90.4762% { transform: translateX(0) scaleX(-1); }
    100%     { transform: translateX(0) scaleX(-1); }
  }

  /* Walking runs at 8 frames a second, waving at 4, idling and looking at
     under 2; every stretch is a whole number of four-frame cycles. */
  @keyframes mascot-frames {
    0%       { background-position-x: 0;       animation-timing-function: steps(24, end); }
    14.2857% { background-position-x: -960px;  animation-timing-function: steps(4, end); }
    23.8095% { background-position-x: -1120px; animation-timing-function: steps(4, end); }
    38.0952% { background-position-x: -1280px; animation-timing-function: steps(24, end); }
    52.381%  { background-position-x: -2240px; animation-timing-function: steps(12, end); }
    66.6667% { background-position-x: -2720px; animation-timing-function: steps(40, end); }
    90.4762% { background-position-x: -4320px; animation-timing-function: steps(4, end); }
    100%     { background-position-x: -4480px; }
  }

  /* Rows of the sheet: 0 idle, -34px walk, -68px look, -102px wave. */
  @keyframes mascot-states {
    0%       { background-position-y: -34px; }
    14.2857% { background-position-y: 0; }
    23.8095% { background-position-y: -68px; }
    38.0952% { background-position-y: -34px; }
    52.381%  { background-position-y: -102px; }
    66.6667% { background-position-y: -34px; }
    90.4762% { background-position-y: 0; }
    100%     { background-position-y: 0; }
  }

  /* ─── Dancing ───────

     A happy jig on a shorter stage: the mascot shuffles to the far end,
     dances on the spot with a twirl, shuffles back and twirls again — an
     8-second loop in eighths, the dance row's four frames (cheer, jump,
     twist right, twist left) cycling at 4 a second the whole way. */

  .mascot-stage--dancing {
    --mascot-stroll: 80px;
  }

  .mascot--dancing {
    animation:
      mascot-dance 8s linear infinite,
      mascot-dance-frames 8s steps(32, end) infinite;
    background-position-y: -136px;
  }

  /* 0–2s shuffle right, 2–4s on the spot facing left with a half-second
     twirl, 4–6s shuffle back, 6–8s on the spot facing right, twirling once
     more; a turn is a flip held by `step-end` until the next keyframe. */
  @keyframes mascot-dance {
    0%     { transform: translateX(0) scaleX(1); }
    25%    { transform: translateX(var(--mascot-stroll)) scaleX(1); animation-timing-function: step-end; }
    25.1%  { transform: translateX(var(--mascot-stroll)) scaleX(-1); }
    37.5%  { transform: translateX(var(--mascot-stroll)) scaleX(-1); animation-timing-function: step-end; }
    37.6%  { transform: translateX(var(--mascot-stroll)) scaleX(1); animation-timing-function: step-end; }
    43.75% { transform: translateX(var(--mascot-stroll)) scaleX(-1); }
    50%    { transform: translateX(var(--mascot-stroll)) scaleX(-1); }
    75%    { transform: translateX(0) scaleX(-1); animation-timing-function: step-end; }
    75.1%  { transform: translateX(0) scaleX(1); }
    87.5%  { transform: translateX(0) scaleX(1); animation-timing-function: step-end; }
    87.6%  { transform: translateX(0) scaleX(-1); animation-timing-function: step-end; }
    93.75% { transform: translateX(0) scaleX(1); }
    100%   { transform: translateX(0) scaleX(1); }
  }

  /* 32 frames in 8 seconds: eight rounds of the row. */
  @keyframes mascot-dance-frames {
    from { background-position-x: 0; }
    to   { background-position-x: -1280px; }
  }

  /* ─── Waving ───────

     Saying hello from the corner of the page, beside the bubble that offers
     the tour: the mascot stands still on a stage its own width and waves —
     two rounds of the wave row at 4 frames a second — then rests for a
     second, blinking, before the next wave. A 3-second loop in thirds. */

  .mascot-stage--waving {
    --mascot-stroll: 0px;
  }

  .mascot--waving {
    animation:
      mascot-waving-frames 3s infinite,
      mascot-waving-states 3s step-end infinite;
  }

  /* 8 wave frames, then the idle row's 4: every stretch ends on a multiple
     of the sheet's 160px, so `repeat-x` wraps it. */
  @keyframes mascot-waving-frames {
    0%       { background-position-x: 0;      animation-timing-function: steps(8, end); }
    66.6667% { background-position-x: -320px; animation-timing-function: steps(4, end); }
    100%     { background-position-x: -480px; }
  }

  /* The wave row, then the idle one. */
  @keyframes mascot-waving-states {
    0%       { background-position-y: -102px; }
    66.6667% { background-position-y: 0; }
    100%     { background-position-y: -102px; }
  }

  /* ─── Working ───────

     Reading a document at a laptop: the mascot stands at the left end of a
     short stage with the laptop (`mascot-laptop.svg`) at its right hand,
     typing — the type row's frames, the hand dropping onto the keys, eyes on
     the screen — at 8 frames a second, and glancing up from the screen for
     the last second of a 4-second loop. */

  .mascot-stage--working {
    --mascot-stroll: 0px;
    --mascot-laptop-inline-size: 28px;
    --mascot-laptop-block-size: 20px;
    /* The laptop's left edge, where the typing hand reaches: a unit short
       of the frame's edge, so the hand lands on the keys. */
    --mascot-laptop-inset: calc(var(--mascot-frame-inline-size) - 2px);

    inline-size: calc(var(--mascot-laptop-inset) + var(--mascot-laptop-inline-size));
  }

  .mascot--working {
    animation:
      mascot-working-frames 4s steps(32, end) infinite,
      mascot-working-states 4s step-end infinite;
  }

  /* 32 frames in 4 seconds: eight rounds of the row. */
  @keyframes mascot-working-frames {
    from { background-position-x: 0; }
    to   { background-position-x: -1280px; }
  }

  /* The type row is the sheet's sixth; the glance is the look row. */
  @keyframes mascot-working-states {
    0%   { background-position-y: -170px; }
    75%  { background-position-y: -68px; }
    100% { background-position-y: -170px; }
  }

  /* The laptop stands on the floor under the mascot's hand, its cursor
     blinking on the screen. */
  .mascot-laptop {
    background-image: url("/assets/mascot-laptop-e43aac2f.svg");
    background-size: 100% 100%;
    block-size: var(--mascot-laptop-block-size);
    color: var(--color-ink);
    display: block;
    inline-size: var(--mascot-laptop-inline-size);
    inset-block-end: 0;
    inset-inline-start: var(--mascot-laptop-inset);
    position: absolute;
  }

  .mascot-laptop::after {
    animation: mascot-cursor 1s step-end infinite;
    background: var(--color-brand);
    block-size: 2px;
    content: "";
    inset-block-start: 8px;
    inset-inline-start: 8px;
    inline-size: 4px;
    position: absolute;
  }

  @keyframes mascot-cursor {
    50% { opacity: 0; }
  }
}
