/* CM001 kit — timeline.css
 *
 * The visual history of a work order, its job orders, or a request: a lane map of what happened, over
 * a chronological feed of every event behind it.
 *
 * 🔴 WHY .cm-tl-* AND NOT A FRIENDLIER NAME. A component that reuses an existing kit class name is at
 * the mercy of the cascade between the legacy sheet and the kit layers, and the note about that in
 * assets/css/cm/base.css is itself out of date (assets/css/base.css does open @layer cm.components, so
 * the real consequence is that cm.components is registered first and therefore sits LOWEST, not that
 * the legacy sheet is unlayered and wins). A fresh namespace makes the question moot instead of
 * requiring anyone to be right about it.
 *
 * 🔴 COLOUR. Only colour is tokenised on this platform; spacing, radii and type are hard-coded per kit
 * convention. Semantic ink follows the formula base.css arrived at after measuring real contrast
 * failures: fill and border keep the raw hue, but INK is the hue pulled part-way toward var(--text),
 * which is dark in light themes and light in dark ones. That is self-correcting for any palette a root
 * user configures. --surface-2 is deliberately NOT used to mean anything semantic: it is darker than
 * --surface in light themes and lighter in dark ones, so a "not applicable" wash painted with it would
 * flip meaning between themes.
 */
@layer cm.components {

  .cm-tl { display: grid; gap: 14px; }

  /* ---- the figures ------------------------------------------------------ */
  .cm-tl__facts {
    display: grid; gap: 10px;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  }
  .cm-tl-fact {
    padding: 11px 13px; border: 1px solid var(--line); border-radius: var(--radius-md, 10px);
    background: var(--surface); display: grid; gap: 2px; align-content: start;
  }
  .cm-tl-fact__k {
    font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
    color: var(--text-3); font-weight: 700; display: flex; align-items: center; gap: 5px;
  }
  .cm-tl-fact__v { font-size: 22px; font-weight: 700; color: var(--text); line-height: 1.15; }
  .cm-tl-fact__s { font-size: 11.5px; color: var(--text-3); }
  /* A figure with no basis says so, in words, at the same size as a real one. It is not dressed as a
   * zero — "0%" and "we cannot tell" are different claims and only one of them is true. */
  .cm-tl-fact--none .cm-tl-fact__v { font-size: 13px; font-weight: 600; color: var(--text-3); padding-block: 4px; }

  /* ---- the lane map ----------------------------------------------------- */
  /* The map scrolls inside ITSELF. The page body must never scroll horizontally. */
  .cm-tl__map {
    border: 1px solid var(--line); border-radius: var(--radius-md, 10px);
    background: var(--surface); padding: 4px 0 2px;
    overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
  }
  .cm-tl-lanes { display: grid; gap: 2px; min-width: max-content; padding: 8px 12px 4px; }

  .cm-tl-lane { display: grid; gap: 4px; padding: 7px 0 9px; }
  .cm-tl-lane + .cm-tl-lane { border-top: 1px dashed var(--line); }
  .cm-tl-lane__id {
    display: flex; align-items: baseline; gap: 7px; font-size: 12px; min-width: 0;
    position: sticky; inset-inline-start: 0;
  }
  .cm-tl-lane__ref { font-weight: 700; color: var(--text); white-space: nowrap; }
  .cm-tl-lane__name {
    color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 46ch;
  }
  /* a job order sits under its work order, indented and quieter */
  .cm-tl-lane--child { padding-inline-start: 18px; }
  .cm-tl-lane--child .cm-tl-lane__ref { font-weight: 600; color: var(--text-2); }

  .cm-tl-lane__rail {
    display: grid; grid-auto-flow: column; grid-auto-columns: minmax(96px, 1fr);
    align-items: start; position: relative; padding-top: 15px;
  }
  /* the rail line itself, drawn behind the dots */
  .cm-tl-lane__rail::before {
    content: ""; position: absolute; inset-inline: 10px; top: 20px; height: 2px;
    background: var(--line-2, var(--line)); border-radius: 2px;
  }

  /* ---- one moment on a rail --------------------------------------------- */
  .cm-tl-step {
    position: relative; display: grid; justify-items: center; gap: 5px;
    padding-inline: 4px; min-width: 0; background: none; border: 0; font: inherit;
    color: inherit; cursor: default; text-align: center;
  }
  .cm-tl-step__dot {
    inline-size: 11px; block-size: 11px; border-radius: 50%;
    background: var(--surface); border: 2px solid var(--line-2, var(--line));
    position: relative; z-index: 1; flex: none;
  }
  .cm-tl-step__cap {
    font-size: 11px; line-height: 1.25; color: var(--text-2); max-width: 13ch;
    overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  }
  .cm-tl-step__at { font-size: 10px; color: var(--text-3); white-space: nowrap; }
  /* how many events collapsed into this one moment — 19 events sharing a timestamp is real data */
  /* hugs its own dot rather than the cell edge — at the cell edge it reads as if it belonged to the
   * gap between two dots, which is the one thing it does not mean */
  .cm-tl-step__n {
    position: absolute; top: -3px; inset-inline-end: calc(50% - 19px);
    font-size: 9.5px; font-weight: 700; line-height: 1;
    padding: 2px 4px; border-radius: 999px;
    background: var(--surface); border: 1px solid var(--line);
    color: var(--text-3);
  }

  /* semantic dots — fill and border keep the raw hue, ink blends toward --text */
  .cm-tl-step--ok     .cm-tl-step__dot { background: color-mix(in srgb, var(--ok) 55%, var(--surface));     border-color: color-mix(in srgb, var(--ok) 70%, transparent); }
  .cm-tl-step--warn   .cm-tl-step__dot { background: color-mix(in srgb, var(--warn) 55%, var(--surface));   border-color: color-mix(in srgb, var(--warn) 70%, transparent); }
  .cm-tl-step--danger .cm-tl-step__dot { background: color-mix(in srgb, var(--danger) 55%, var(--surface)); border-color: color-mix(in srgb, var(--danger) 70%, transparent); }
  .cm-tl-step--brand  .cm-tl-step__dot { background: color-mix(in srgb, var(--brand) 55%, var(--surface));  border-color: color-mix(in srgb, var(--brand) 70%, transparent); }
  .cm-tl-step--ok     .cm-tl-step__cap { color: color-mix(in srgb, var(--ok) 62%, var(--text)); }
  .cm-tl-step--warn   .cm-tl-step__cap { color: color-mix(in srgb, var(--warn) 62%, var(--text)); }
  .cm-tl-step--danger .cm-tl-step__cap { color: color-mix(in srgb, var(--danger) 62%, var(--text)); }
  .cm-tl-step--brand  .cm-tl-step__cap { color: color-mix(in srgb, var(--brand) 62%, var(--text)); }
  /* 🔑 colour is never the only carrier: the current moment also gets a ring, and every dot keeps its
   * text label underneath it. */
  .cm-tl-step--now .cm-tl-step__dot { box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 22%, transparent); }

  .cm-tl-step[aria-expanded] { cursor: pointer; }
  .cm-tl-step:focus-visible { outline: 2px solid var(--focus-ring, var(--brand)); outline-offset: 3px; border-radius: 6px; }

  /* ---- the feed --------------------------------------------------------- */
  .cm-tl__feed { display: grid; gap: 0; }
  .cm-tl-ev {
    display: grid; grid-template-columns: auto 1fr; gap: 2px 10px;
    padding: 9px 0; border-top: 1px solid var(--line); align-items: start;
  }
  .cm-tl-ev:first-child { border-top: 0; }
  .cm-tl-ev__mark {
    inline-size: 9px; block-size: 9px; border-radius: 50%; margin-top: 5px;
    background: var(--line-2, var(--line)); grid-row: 1 / span 2; flex: none;
  }
  .cm-tl-ev--ok     .cm-tl-ev__mark { background: var(--ok); }
  .cm-tl-ev--warn   .cm-tl-ev__mark { background: var(--warn); }
  .cm-tl-ev--danger .cm-tl-ev__mark { background: var(--danger); }
  .cm-tl-ev--brand  .cm-tl-ev__mark { background: var(--brand); }
  .cm-tl-ev__meta { font-size: 11.5px; color: var(--text-3); display: flex; flex-wrap: wrap; gap: 4px 8px; }
  .cm-tl-ev__who { font-weight: 600; color: var(--text-2); }
  .cm-tl-ev__src { font-weight: 600; }
  .cm-tl-ev__body { font-size: 13px; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
  /* an internal note is staff-only; it carries the platform's existing --internal wash */
  .cm-tl-ev--internal { background: color-mix(in srgb, var(--internal, var(--warn)) 8%, transparent); }
  .cm-tl-ev--internal .cm-tl-ev__body { color: var(--text-2); }

  /* ---- collapsed noise -------------------------------------------------- */
  /* Automated chasing and permit re-emission are 90% of some records. They are kept — the record must
   * be complete — but folded, so the eight events that are state transitions are readable. */
  .cm-tl-fold { border-top: 1px solid var(--line); }
  .cm-tl-fold > summary {
    cursor: pointer; padding: 9px 0; font-size: 12px; color: var(--text-3);
    display: flex; align-items: center; gap: 7px; list-style: none;
  }
  .cm-tl-fold > summary::-webkit-details-marker { display: none; }
  .cm-tl-fold > summary::after {
    content: ""; inline-size: 7px; block-size: 7px; margin-inline-start: 2px;
    border-inline-end: 2px solid currentColor; border-block-end: 2px solid currentColor;
    transform: rotate(45deg) translate(-2px, -2px); transition: transform .15s ease;
  }
  .cm-tl-fold[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
  .cm-tl-fold > summary:focus-visible { outline: 2px solid var(--focus-ring, var(--brand)); outline-offset: 2px; border-radius: 6px; }
  .cm-tl-fold__body { padding-inline-start: 19px; }

  .cm-tl__empty { padding: 6px 0; }

  /* ---- narrow screens ---------------------------------------------------- */
  /* A horizontal rail on a 375px phone is unreadable, and this is a PWA used in the field. Below 640px
   * every lane turns vertical: the rail becomes a spine running down the start edge with the moments
   * stacked against it. Same markup, same order, no horizontal scroll at all. */
  @media (max-width: 640px) {
    .cm-tl__map { overflow-x: visible; }
    .cm-tl-lanes { min-width: 0; padding-inline: 12px; }
    .cm-tl-lane__rail {
      grid-auto-flow: row; grid-auto-columns: auto; padding-top: 6px;
      padding-inline-start: 14px; gap: 11px;
    }
    .cm-tl-lane__rail::before {
      inset-inline: auto; inset-inline-start: 4px; top: 12px; bottom: 8px;
      height: auto; width: 2px;
    }
    .cm-tl-step {
      grid-template-columns: auto 1fr; justify-items: start; align-items: baseline;
      gap: 2px 9px; padding-inline: 0; text-align: start;
      margin-inline-start: -14px;
    }
    .cm-tl-step__dot { grid-row: 1 / span 3; margin-top: 3px; }
    .cm-tl-step__cap { max-width: none; -webkit-line-clamp: 3; }
    /* In the vertical layout the badge must stay in the TEXT column. Left in the spine column it lands
     * under the dot and reads as if it belonged to the gap below, which is the one thing it never
     * means — it counts the entries at the moment ABOVE it. */
    .cm-tl-step__n { position: static; grid-column: 2; justify-self: start; margin-top: 1px; }
    .cm-tl-lane__name { max-width: 24ch; }
  }

  @media (prefers-reduced-motion: reduce) {
    .cm-tl-fold > summary::after { transition: none; }
  }

  /* ---- print ------------------------------------------------------------- */
  /* A timeline is what gets attached to a dispute. Printed, everything is open and nothing scrolls. */
  @media print {
    /* The one literal colour in this file, and deliberate: paper has no theme. var(--line) under a dark
     * theme resolves to a near-white rule that disappears on a white page, so the printed border is
     * stated outright rather than inherited from a palette that does not apply. */
    .cm-tl__map { overflow: visible; border-color: #999; }
    .cm-tl-lanes { min-width: 0; }
    .cm-tl-fold > summary { display: none; }
    .cm-tl-fold__body { padding-inline-start: 0; }
    .cm-tl-fold > .cm-tl-fold__body { display: block !important; }
  }
}

/* ---- the jump mark (timeline.js) ------------------------------------------
 * Set for 1.6s when a moment is clicked, so the reader can see WHICH feed rows that dot stood for.
 * Colour is not the only signal: the row also gets an inset rule on its start edge. */
@layer cm.components {
  .cm-tl-ev.is-marked {
    background: color-mix(in srgb, var(--brand) 10%, transparent);
    box-shadow: inset 3px 0 0 0 var(--brand);
  }
  .cm-tl-step.is-active .cm-tl-step__dot { box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 30%, transparent); }
  @media (prefers-reduced-motion: no-preference) {
    .cm-tl-ev { transition: background-color .2s ease, box-shadow .2s ease; }
  }
}
