/*
 * THE EVENT LOG. Tinted nodes on a hairline spine, one row per event.
 *
 * Every ornament in the label band sits on the label's FIRST LINE, never on the
 * label BLOCK — `--lotics-timeline-first-line` is that one number and everything
 * else derives from it. Centring on the ROW instead agrees exactly until a label
 * wraps, and only the wrapped rows are then wrong.
 *
 * The node's accent is the caller's datum, so it arrives as
 * `--lotics-timeline-node-color` and the wash mixes from it here.
 */
@layer theme, base, lotics, components, utilities;
@layer lotics.tokens, lotics.reset, lotics.components;

@layer lotics.components {
  .lotics-timeline {
    /* The disc, and the rail it centres in. */
    --lotics-timeline-node: 32px;
    /* The row's vertical padding — also the press target's breathing room, and
       with one line of `sm` leading on both sides it IS the 40px touch target. */
    --lotics-timeline-row-pad: var(--lotics-space-10);
    /* The disc's own box: the air around it is what the sliver above has to make
       up, so it is derived rather than hand-copied. */
    --lotics-timeline-node-box: calc(var(--lotics-timeline-node) + var(--lotics-space-6));
    --lotics-timeline-first-line: calc(
      var(--lotics-timeline-row-pad) + var(--lotics-leading-sm) / 2
    );
    display: flex;
    flex-direction: column;
    align-items: stretch;
    min-width: 0;
  }

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

  /* Band 1 — the disc beside the label row. */
  .lotics-timeline__head {
    display: flex;
    flex-direction: row;
    align-items: stretch;
    gap: var(--lotics-space-12);
    min-width: 0;
  }

  /* Band 2 — description, error and details under the label, beside the
     continuing spine; also carries the inter-item gap. */
  .lotics-timeline__foot {
    display: flex;
    flex-direction: row;
    align-items: stretch;
    gap: var(--lotics-space-12);
    min-width: 0;
  }

  .lotics-timeline__rail {
    display: flex;
    flex-direction: column;
    align-items: center;
    align-self: stretch;
    flex-shrink: 0;
    width: var(--lotics-timeline-node);
  }

  /* The sliver is always there and paints only where the log CONTINUES: a
     conditional BOX would put the first row's disc higher than the rest. */
  .lotics-timeline__spine {
    width: 1.5px;
    border-radius: var(--lotics-radius-full);
    background-color: transparent;
  }

  .lotics-timeline__spine[data-continues] {
    background-color: var(--border);
  }

  /* A fixed sliver above the disc puts its centre on the label's first line; the
     one below flexes, so the spine still reaches the bottom of a tall row. */
  .lotics-timeline__spine[data-position="above"] {
    height: calc(var(--lotics-timeline-first-line) - var(--lotics-timeline-node-box) / 2);
  }

  .lotics-timeline__spine[data-position="below"] {
    flex: 1;
    min-width: 0;
  }

  /* Tinted disc: a low-alpha wash of the accent behind a full-colour mark. */
  .lotics-timeline__node {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: var(--lotics-timeline-node);
    height: var(--lotics-timeline-node);
    border-radius: var(--lotics-radius-full);
    margin-block: var(--lotics-space-2);
    background-color: color-mix(
      in srgb,
      var(--lotics-timeline-node-color, var(--lotics-ink-default)) 10%,
      transparent
    );
    animation: lotics-timeline-node-in var(--lotics-duration-base) var(--lotics-ease-standard);
  }

  @keyframes lotics-timeline-node-in {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }

  /* Holds the press target and `right` side by side, so the wash marks exactly
     what a press acts on. The BLEED lives here rather than on the pressable:
     owned by the child it would push `right` into the gap and slide the wash
     under it. */
  .lotics-timeline__row {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    flex: 1;
    min-width: 0;
  }

  /* WIDER than the gap inside the press target, because these are not peers: the
     chevron belongs to the row's own button, `right` does not. */
  .lotics-timeline__row[data-expandable] {
    gap: var(--lotics-space-12);
    margin-inline: calc(var(--lotics-space-8) * -1);
  }

  /* The press target for an expandable row; the horizontal padding puts the
     label back on the column's own left edge, which the bleed moved. */
  .lotics-timeline__press {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    flex: 1;
    min-width: 0;
    margin: 0;
    padding-inline: var(--lotics-space-8);
    padding-block: var(--lotics-timeline-row-pad);
    border: 0 solid var(--border);
    border-radius: var(--lotics-radius-control);
    background-color: transparent;
    font: inherit;
    color: inherit;
    text-align: start;
    appearance: none;
    cursor: default;
    transition: background-color var(--lotics-duration-fast) var(--lotics-ease-standard);
  }

  .lotics-timeline__press:hover {
    background-color: var(--lotics-wash-selected);
  }

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

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

  /* The plain row carries the same vertical rhythm without the press target. */
  .lotics-timeline__plain {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    flex: 1;
    min-width: 0;
    padding-block: var(--lotics-timeline-row-pad);
    gap: var(--lotics-space-10);
  }

  .lotics-timeline__label-row {
    display: flex;
    flex-direction: row;
    /* TOP, not centre — the whole band aligns to the first line. */
    align-items: flex-start;
    flex: 1;
    min-width: 0;
    gap: var(--lotics-space-10);
  }

  .lotics-timeline__label {
    flex: 1;
    min-width: 0;
  }

  /*
   * Centres its content on the first line — the chevron, and `right`.
   *
   * `height`, never `min-height`: a floor lets the box GROW to whatever the
   * caller passed, and a grown box centres its content on its own new middle
   * rather than on the line. A FIXED box overflows symmetrically instead.
   */
  .lotics-timeline__chevron,
  .lotics-timeline__trailing {
    display: flex;
    /* A COLUMN with stretched children: a row would centre a wide fact instead
       of letting it fill. */
    flex-direction: column;
    align-items: stretch;
    justify-content: center;
    flex-shrink: 0;
    height: var(--lotics-leading-sm);
  }

  .lotics-timeline__chevron {
    align-items: center;
    --lotics-icon-color: var(--lotics-ink-muted);
  }

  /* The same job for `right` on an EXPANDABLE row, where it sits outside the
     press target and so does not inherit that padding. */
  .lotics-timeline__row[data-expandable] .lotics-timeline__trailing {
    height: calc(var(--lotics-timeline-first-line) * 2);
  }

  .lotics-timeline__body {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    flex: 1;
    min-width: 0;
    gap: var(--lotics-space-2);
    padding-bottom: var(--lotics-space-12);
  }

  .lotics-timeline__body[data-last] {
    padding-bottom: 0;
  }

  /* NO left padding: the body shares the description line's left edge above it,
     and an indent is legitimate only when something VISIBLE occupies it. */
  .lotics-timeline__details {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    min-width: 0;
    gap: var(--lotics-space-8);
    padding-top: var(--lotics-space-8);
  }
}
