@layer infine.components {
/* Section-header completeness label. Borderless, fill-less — reads as a
   typographic annotation next to the section title rather than as a UI
   chip. The state colour comes from the modifier classes below; one shape,
   three states. Less assertive than the earlier outlined pill so the
   header's main job — naming the section — leads. */
.connect-group-completeness {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: auto;
    margin-right: 16px;
    padding: 0 2px;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.02em;
    background: transparent;
    color: var(--infine-blue);
    border: 0;
    transition: color 240ms ease;
}

.connect-group-completeness--complete {
    color: var(--infine-green-bright);
}
/* Optional-complete drops to a neutral grey — there's no value in
   colour-coding "all optional fields filled" (it's not a requirement),
   and the lighter green was reading as a muddier sibling of the
   required-complete green rather than a distinct state. The kind class
   (`--optional`) is stamped by the optional-pill component. */
.connect-group-completeness--optional.connect-group-completeness--complete {
    color: var(--mantine-color-gray-6);
}
/* One-shot pop only on the real "section just reached complete" transition,
   gated by cljs via `data-just-completed`. Without this gate the animation
   replays on every accordion re-open, since Mantine collapse remounts the
   inner DOM and re-applies the --complete class fresh.

   Required-complete pops; optional-complete does not. Filling every optional
   isn't a milestone worth celebrating (it's not a requirement), and the
   green ring on a now-grey pill would clash. */
.connect-group-completeness--complete[data-just-completed="true"]:not(.connect-group-completeness--optional) {
    animation: connect-pill-pop 480ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
.connect-group-completeness--partial  {
    color: var(--infine-yellow-bright);
    border-color: var(--infine-yellow-bright);
}
.connect-group-completeness--errors {
    color: var(--infine-red-bright);
    border-color: var(--infine-red-bright);
}

/* Error pill: only renders when the segment has errors or has just cleared
   them. The mount animation (`pill-fly-in`) gives a small entrance pop so it
   reads as something that just appeared. On clearing, the pill keeps the red
   colour — the resolution is communicated by the 'RESOLVED' label + tick,
   not by a colour flip — and stays in place long enough for the user to read
   it after the field-block shake has played out. No celebratory pop here,
   intentionally: it would compete with the field-shake for attention. */
.connect-group-completeness--error-pill {
    animation: connect-pill-fly-in 260ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* Fade-out tail: starts after ~2000 ms of full visibility so the user has
   time to read the resolved label, then ~500 ms fade-out before the parent
   unmounts the pill at 2500 ms. */
.connect-group-completeness--error-pill.connect-group-completeness--fading {
    animation: connect-pill-fade-out 500ms ease 2000ms forwards;
}

@keyframes connect-pill-pop {
    0%   { transform: scale(1);    box-shadow: 0 0 0 0  rgb(from var(--infine-green-bright) r g b / 0.35); }
    50%  { transform: scale(1.08); box-shadow: 0 0 0 6px rgb(from var(--infine-green-bright) r g b / 0); }
    100% { transform: scale(1);    box-shadow: 0 0 0 0  rgb(from var(--infine-green-bright) r g b / 0); }
}

@keyframes connect-pill-fly-in {
    0%   { transform: scale(0.6); opacity: 0; }
    100% { transform: scale(1);   opacity: 1; }
}

@keyframes connect-pill-fade-out {
    0%   { opacity: 1; transform: scale(1); }
    100% { opacity: 0; transform: scale(0.92); }
}

/* Inline tick rendered alongside the count when complete. The svg scales in
   with a bouncy ease so it lands with a small "click". The pill text swap
   ("REQUIRED: 7/7" → "REQUIRED ✓") is handled in cljs. */
.connect-group-completeness .pill-check {
    width: 12px;
    height: 12px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: currentColor;
}
/* Tick scales in only on the real completion event, not on every re-mount. */
.connect-group-completeness[data-just-completed="true"] .pill-check {
    animation: connect-pill-check-in 380ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
.connect-group-completeness .pill-check svg {
    width: 100%;
    height: 100%;
    display: block;
}
@keyframes connect-pill-check-in {
    0%   { transform: scale(0)   rotate(-20deg); opacity: 0; }
    100% { transform: scale(1)   rotate(0deg);   opacity: 1; }
}

/* Neutral (uncoloured) variant — used for the Optional pill so the eye is
   drawn to the colour-coded Required pill next to it. */
.connect-group-completeness--neutral {
    color: var(--mantine-color-gray-6);
}
}
