/* ONE ANATOMY, TWO AXES: a gutter (marker between two spine segments) beside the content;
   `data-orientation` turns the run rather than forking it. Two segments per step because the marker
   centres on the content's first row, so the upper segment keeps the line continuous.
   `--lotics-stepper-node`, `Checkbox`'s own box, drives the geometry. `--lotics-stepper-color` is the
   run's ink; `--lotics-stepper-node-color` one node's — the run's by default, danger on `fail`, and an
   inline own colour beating both. */
@layer theme, base, lotics, components, utilities;
@layer lotics.tokens, lotics.reset, lotics.components;

@layer lotics.components {
  .lotics-stepper,
  .lotics-stepper__marker {
    --lotics-stepper-node: 24px;
  }

  .lotics-stepper {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    min-width: 0;
    list-style: none;
  }

  .lotics-stepper[data-orientation="horizontal"] {
    flex-direction: row;
  }

  .lotics-stepper__step {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    min-width: 0;
  }

  .lotics-stepper__step[data-orientation="horizontal"] {
    flex: 1;
  }

  .lotics-stepper__item {
    display: flex;
    flex-direction: row;
    align-items: stretch;
    /* The kit's one mark-to-label gap (`--lotics-lead-gap`, `STEP_MARKER_GAP`), since the node is a round
       mark. */
    gap: var(--lotics-lead-gap);
    min-width: 0;
  }

  /* Steps rise and fade in on mount, so a streamed feed reads as steps appearing. */
  .lotics-stepper__step[data-orientation="vertical"] .lotics-stepper__item {
    animation: lotics-stepper-step-in var(--lotics-duration-slow) var(--lotics-ease-standard);
  }

  @keyframes lotics-stepper-step-in {
    from {
      opacity: 0;
      transform: translateY(6px);
    }
    to {
      opacity: 1;
      transform: none;
    }
  }

  .lotics-stepper__step[data-orientation="horizontal"] .lotics-stepper__item {
    flex-direction: column;
    align-items: center;
    gap: var(--lotics-space-8);
    width: 100%;
  }

  .lotics-stepper__gutter {
    display: flex;
    flex-direction: column;
    align-items: center;
    flex-shrink: 0;
    width: var(--lotics-stepper-node);
  }

  .lotics-stepper__step[data-orientation="horizontal"] .lotics-stepper__gutter {
    flex-direction: row;
    width: 100%;
  }

  .lotics-stepper__spine {
    flex-shrink: 0;
    background: transparent;
  }

  .lotics-stepper__spine[data-line] {
    background: var(--border);
  }

  .lotics-stepper__step[data-orientation="vertical"] .lotics-stepper__spine {
    width: 1.5px;
    border-radius: var(--lotics-radius-full);
  }

  /* As tall as the offset that centres the marker on the first row. */
  .lotics-stepper__step[data-orientation="vertical"] .lotics-stepper__spine[data-before] {
    height: var(--lotics-stepper-marker-offset);
  }

  /* A mark's node centres on its row's lead: the row's sliver (`STEP_ROW_PAD`) plus half the lead's rung
     less half the node, derived from the stated rung, floored at zero like `markerTopOffset`. With no
     lead, one `sm` line. */
  .lotics-stepper__gutter[data-status="mark"] {
    --lotics-stepper-marker-offset: max(
      0px,
      calc(var(--lotics-space-2) + var(--lotics-stepper-lead, var(--lotics-leading-sm)) / 2 - var(--lotics-stepper-node) / 2)
    );
  }

  /* The segment starts at the marker, or the line detaches. */
  .lotics-stepper__step[data-orientation="vertical"] .lotics-stepper__spine:not([data-before]) {
    flex: 1;
    min-height: 14px;
  }

  .lotics-stepper__step[data-orientation="vertical"] .lotics-stepper__spine[data-line][data-filled] {
    background: var(--lotics-wash-control-press);
  }

  .lotics-stepper__step[data-orientation="horizontal"] .lotics-stepper__spine {
    flex: 1;
    height: 2px;
  }

  .lotics-stepper__step[data-orientation="horizontal"] .lotics-stepper__spine[data-filled] {
    background: var(--lotics-stepper-color, var(--primary));
  }

  .lotics-stepper__marker {
    --lotics-stepper-node-color: var(--lotics-stepper-color, var(--primary));
    position: relative;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: var(--lotics-stepper-node);
    height: var(--lotics-stepper-node);
    border: 0 solid transparent;
    border-radius: var(--lotics-radius-full);
    background: var(--card);
    color: var(--lotics-white);
  }

  .lotics-stepper__marker[data-status="upcoming"] {
    border-width: 1.5px;
    border-color: var(--input);
  }

  /* A ring in the run's ink, thicker than those ahead and the only full-contrast mark; not a solid disc,
     or the eye finds the current stage by its missing check. */
  .lotics-stepper__marker[data-status="current"] {
    border-width: 2.5px;
    border-color: var(--lotics-stepper-node-color);
  }

  /* The checked box's filled disc; the disc is an ink that lightens in dark themes, so its tick takes the
     inverse ground's ink, not white. */
  .lotics-stepper__marker[data-status="done"] {
    background: var(--lotics-stepper-node-color);
    color: var(--lotics-ink-on-inverse);
  }

  /* The disc unreported, in the thing's own colour with no glyph: the tick is exactly the claim it must
     not make. */
  .lotics-stepper__marker[data-status="mark"] {
    background: var(--lotics-stepper-node-color);
  }

  /* No node and an unbroken line: the box collapses on both axes so the segments meet; a transparent
     full-size box opened a one-node gap that read as a break. */
  .lotics-stepper__marker[data-status="through"] {
    width: 0;
    height: 0;
    border-width: 0;
    background: transparent;
  }

  /* A ring spending its ink on the check, also the terminal "Done", so a reported history does not
     outweigh the current stage. */
  .lotics-stepper__marker[data-status="complete"] {
    border-width: 2px;
    border-color: var(--primary);
    color: var(--lotics-ink-default);
  }

  .lotics-stepper__marker[data-status="warning"] {
    background: var(--lotics-tone-amber-solid);
  }

  /* The done disc in danger, so only colour says which way it went — or the node's own colour where it has
     one. */
  .lotics-stepper__marker[data-status="fail"] {
    --lotics-stepper-node-color: var(--lotics-tone-red-solid);
    background: var(--lotics-stepper-node-color);
  }

  /* A real `Checkbox` draws its own face; the node keeps only the box. */
  .lotics-stepper__marker[data-control] {
    border-width: 0;
    background: transparent;
  }

  .lotics-stepper__pulse {
    position: absolute;
    width: var(--lotics-stepper-node);
    height: var(--lotics-stepper-node);
    border: 2px solid var(--lotics-stepper-node-color);
    border-radius: var(--lotics-radius-full);
    pointer-events: none;
    animation-name: lotics-stepper-pulse;
    /* 1500ms — 6.25 slow durations, so the rhythm follows the token. */
    animation-duration: calc(var(--lotics-duration-slow) * 6.25);
    animation-timing-function: linear;
    animation-iteration-count: infinite;
  }

  /* The duration tokens cannot retime an infinite animation: at 1ms the halo strobes (docs/theming.md
     §2.3). */
  @media (prefers-reduced-motion: reduce) {
    .lotics-stepper__pulse {
      animation: none;
    }
  }

  @keyframes lotics-stepper-pulse {
    from {
      transform: scale(1);
      opacity: 0.35;
    }
    to {
      transform: scale(2.2);
      opacity: 0;
    }
  }

  /* `xs` is the only body rung whose line box (18) fits the 24 disc; `sm` clipped and off-centred the
     digit (as `count.css`). Two digits fit, so the node never widens and text stays put at stop ten. */
  .lotics-stepper__ordinal {
    font-family: var(--font-sans);
    font-size: var(--lotics-text-xs);
    line-height: var(--lotics-leading-xs);
    letter-spacing: var(--lotics-tracking-xs);
    font-weight: var(--lotics-weight-medium);
    font-variant-numeric: var(--lotics-font-numeric);
    font-feature-settings: var(--lotics-font-features);
    color: currentColor;
    user-select: none;
  }

  .lotics-stepper__bar {
    width: 8px;
    height: 2px;
    border-radius: var(--lotics-radius-full);
    background: currentColor;
  }

  .lotics-stepper__content {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    flex: 1;
    min-width: 0;
    /* Overridable by `Stepper`'s `gap`; it must beat the in-step spacing or groups stop reading as groups. */
    --lotics-stepper-gap: var(--lotics-space-16);
  }

  .lotics-stepper__step[data-orientation="vertical"]:not([data-last]) .lotics-stepper__content {
    padding-bottom: var(--lotics-stepper-gap);
  }

  .lotics-stepper__step[data-orientation="horizontal"] .lotics-stepper__content {
    align-items: center;
    flex: 0 0 auto;
  }

  /* The one box that presses, washes and rings owns the bleed (inset plus equal negative margin, as
     `pressable_row.css`); split across two boxes the wash outgrew the button and the ring landed inside
     the highlight. */
  .lotics-stepper__press {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    min-width: 0;
    border: 0 solid transparent;
    border-radius: calc(var(--lotics-radius-control) - var(--lotics-space-2));
    /* 10 — `STEP_ROW_BLEED`. The sliver above the first line stays on the row every step has, since the
       marker's offset is measured against it. */
    padding-inline: var(--lotics-space-10);
    margin-inline: calc(var(--lotics-space-10) * -1);
    background: transparent;
    background-image: none;
    appearance: none;
    color: var(--lotics-ink-default);
    font-family: var(--font-sans);
    font-size: var(--lotics-text-sm);
    line-height: var(--lotics-leading-sm);
    letter-spacing: var(--lotics-tracking-sm);
    font-weight: var(--lotics-weight-regular);
    font-feature-settings: var(--lotics-font-features);
    text-align: start;
    /* The arrow: a step is a button around data whose text is read. */
    cursor: auto;
    touch-action: manipulation;
    transition: background-color var(--lotics-duration-fast) var(--lotics-ease-standard);
  }

  /* One box washes in every state on both axes; `data-active` rides every part and washes are translucent,
     so nested boxes would double. */
  .lotics-stepper__press:not([data-active]):hover {
    background: var(--lotics-wash-hover);
  }

  .lotics-stepper__press[data-active] {
    background: var(--lotics-wash-selected);
  }

  .lotics-stepper__press:active {
    background: var(--lotics-wash-press);
  }

  .lotics-stepper__press:focus-visible {
    outline: var(--lotics-ring-width) solid var(--ring);
    outline-offset: 0;
  }

  /* Horizontally the press wraps the whole step, so the vertical bleed would push the end nodes off the
     band. */
  .lotics-stepper__step[data-orientation="horizontal"] .lotics-stepper__press {
    width: 100%;
    padding-inline: 0;
    margin-inline: 0;
    padding-block: var(--lotics-space-4);
  }

  /* No ground, corner or bleed, so steps with and without a destination start text on one x; only the
     sliver the marker offset measures against. */
  .lotics-stepper__row {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    min-width: 0;
    /* 2 — `STEP_ROW_PAD`. */
    padding-block: var(--lotics-space-2);
  }

  .lotics-stepper__step[data-orientation="horizontal"] .lotics-stepper__row {
    padding: 0;
  }
}
