@layer infine.components {
/* ===================================================================
   Connect autosave bar
   Sticky bottom bar across CompanyData / SingleView / Grid that
   communicates autosave status, hosts undo/redo, and surfaces the
   required-field legend in one consistent place.
   =================================================================== */

/* Make room above the fixed bar so the page's footer (the copyright row,
   rendered by Root as a sibling to the routed content) isn't tucked under
   the bar when scrolled to the bottom. The padding goes on the AppShell-root
   (the scroll container shared by routed-content + footer) and is scoped
   via `:has()` so it only applies on Connect routes that mount the bar.
   44px matches the natural footer-to-viewport-bottom gap on non-bar pages
   (the footer container's own 32px margin-bottom + 12px padding-bottom),
   so the bar reads as "the new bottom" with the same breathing room. */
.mantine-AppShell-root:has(.connect-autosave-bar) {
    padding-bottom: 44px;
}

/* Bar layout — three outer columns: status / actions / legend. The actions
   group (undo + redo + feedback text) is its own flex container with a tight
   8px gap so the feedback reads as belonging to the buttons. */
.connect-autosave-bar {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    min-height: 44px;
    display: grid;
    grid-template-columns: 260px auto 1fr;
    align-items: center;
    column-gap: 32px;
    padding: 4px var(--mantine-spacing-xl);
    background: var(--infine-blue);
    border-top: 1px solid rgba(255, 255, 255, 0.10);
    box-shadow: 0 -2px 16px rgba(0, 17, 51, 0.25);
    font-family: var(--mantine-font-family);
    font-size: var(--mantine-font-size-xs);
    color: white;
    z-index: 50;
    /* Entry: ease-out-cubic at 0.6s — sharper deceleration than quad
       so the arrival reads as decisive rather than asymptotic. */
    animation: connect-autosave-bar-in 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) both;
}
.connect-autosave-bar--hidden {
    pointer-events: none;
    /* Exit: faster slide-down — get out of the way. */
    animation: connect-autosave-bar-out 0.22s cubic-bezier(0.4, 0, 1, 1) both;
}
@keyframes connect-autosave-bar-in {
    from { transform: translateY(100%); }
    to   { transform: translateY(0);    }
}
@keyframes connect-autosave-bar-out {
    from { transform: translateY(0);    }
    to   { transform: translateY(100%); }
}

.connect-autosave-actions {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

/* Icon system — every icon renders as a span whose alpha mask is the SVG
   and whose colour is `currentColor`. Status icons inherit the status block's
   colour (gray for idle/saving/saved, red for error); button icons inherit
   the button's blue. */
.connect-autosave-icon {
    width: 14px;
    height: 14px;
    display: inline-block;
    flex-shrink: 0;
    background-color: currentColor;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: center;
            mask-position: center;
    -webkit-mask-size: contain;
            mask-size: contain;
}
.connect-autosave-icon--spinner {
    /* The source SVG's content sits inside a 700×700 viewbox with generous
       margin; bump display size so the visible spinner reads at icon scale. */
    width: 18px;
    height: 18px;
    -webkit-mask-image: url("/icons/connect-saving-spinner.svg");
            mask-image: url("/icons/connect-saving-spinner.svg");
}
.connect-autosave-icon--saved {
    -webkit-mask-image: url("/icons/connect-saved.svg");
            mask-image: url("/icons/connect-saved.svg");
}
.connect-autosave-icon--error {
    width: 16px;
    height: 16px;
    -webkit-mask-image: url("/icons/connect-error.svg");
            mask-image: url("/icons/connect-error.svg");
}
.connect-autosave-icon--undo {
    -webkit-mask-image: url("/icons/connect-undo.svg");
            mask-image: url("/icons/connect-undo.svg");
}
.connect-autosave-icon--redo {
    -webkit-mask-image: url("/icons/connect-redo.svg");
            mask-image: url("/icons/connect-redo.svg");
}

@keyframes connect-spin {
    from { transform: rotate(0deg);   }
    to   { transform: rotate(360deg); }
}
.connect-autosave-icon--spin {
    animation: connect-spin 1.6s linear infinite;
}

/* Status block — text + icon. Re-mounted on every status change (key keyed
   off status) so the entry animation plays each transition. Plain opacity
   crossfade for the everyday transitions; only :error gets the attention-
   grabbing bounce. */
@keyframes connect-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}
.connect-autosave-status {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-weight: 700;
    color: white;
    /* Symmetric ease-in-out S-curve so the opacity change is spread
       evenly across the full duration with gentle ramps at both ends.
       Front-loaded ease-out curves leave the back half as dead air; this
       one keeps the fade visible from start to finish. */
    animation: connect-fade-in 0.45s cubic-bezier(0.42, 0, 0.58, 1) both;
    line-height: 1.3;
    min-width: 0;
}
.connect-autosave-status--saving,
.connect-autosave-status--saved { color: white; }
/* Error state is an inline alert chip — red pill, white text + icon, small
   corner rounding. Bounce on entry so a save failure stops being a wall of
   muted red text and becomes an unmistakable signal. Uses `--infine-red-strong`
   (slightly muted) — `--infine-red-bright` reads too neon against the dark blue. */
.connect-autosave-status--error  {
    background: var(--infine-red-strong);
    color: white;
    padding: 4px 10px;
    border-radius: 4px;
    align-items: center;
    animation: bounceIn 0.55s cubic-bezier(0.215,0.61,0.355,1) both;
}
/* Refused-input notice. Amber, not the error pill's red: red says "we failed to
   save", which sends the user looking for a retry — this says "we did save, but
   that text wasn't a value the field accepts", whose remedy is theirs. Shares the
   error pill's geometry and entry bounce so it reads as the same class of signal
   at the same weight. Collapsed to zero width when empty so it costs no layout. */
.connect-autosave-notice {
    display: inline-flex;
    align-items: center;
    max-width: 0;
    padding: 0;
    overflow: hidden;
    opacity: 0;
    white-space: nowrap;
    font-size: var(--mantine-font-size-xs);
    font-weight: 600;
    line-height: 1.3;
    border-radius: 4px;
    background: var(--infine-yellow-strong);
    color: #1a1a1a;
    transition: opacity 0.25s ease;
}
.connect-autosave-notice--shown {
    /* The ceiling here is the legend, not the text: wider than this and the legend wraps to a
       second line at 1280px, doubling the bar past the 44px the page reserves for it. Notices
       are kept short at the source to fit, rather than widened here — see quote-sample. */
    max-width: 54ch;
    padding: 4px 10px;
    opacity: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    animation: bounceIn 0.55s cubic-bezier(0.215,0.61,0.355,1) both;
}

.connect-autosave-status .connect-autosave-status-text {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Undo / redo buttons. Always rendered so their layout slots stay fixed;
   `--hidden` zeroes their visibility and disables interaction without
   collapsing the slot. */
.connect-autosave-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.30);
    border-radius: 6px;
    padding: 3px 10px;
    min-width: 88px;
    font-family: inherit;
    font-size: var(--mantine-font-size-xs);
    font-weight: 600;
    color: white;
    cursor: pointer;
    transition: opacity 0.15s ease,
                background-color 0.15s ease,
                border-color 0.15s ease,
                color 0.15s ease;
}
.connect-autosave-btn:hover {
    background: rgba(255, 255, 255, 0.10);
    border-color: rgba(255, 255, 255, 0.55);
    color: white;
}
.connect-autosave-btn:active {
    transform: translateY(1px);
}
.connect-autosave-btn--hidden {
    opacity: 0;
    pointer-events: none;
    cursor: default;
}

/* Transient confirmation/error message slot that follows the buttons. The
   slot is permanently in the layout (1fr column); the text fades in/out
   only when there's something to say so the buttons stay anchored. */
.connect-autosave-undo-msg {
    display: inline-block;
    font-size: var(--mantine-font-size-xs);
    color: rgba(255, 255, 255, 0.80);
    font-style: italic;
    opacity: 0;
    transition: opacity 0.18s ease;
    line-height: 1.3;
}
.connect-autosave-undo-msg--ok,
.connect-autosave-undo-msg--error {
    opacity: 1;
}
.connect-autosave-undo-msg--error {
    color: var(--infine-red-fade);
    font-style: normal;
    font-weight: 700;
}

/* Right side — required-field legend. Reuses the existing
   .connect-grid-legend-item / .connect-grid-legend-marker classes from the
   old grid-bottom legend so the visual treatment stays identical. */
.connect-autosave-legend {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 4px 18px;
    flex-wrap: wrap;
    flex-shrink: 0;
    font-size: 11px;
    color: rgba(255, 255, 255, 0.85);
}

/* When the bar gets too narrow to fit the full grid legend in one row, drop
   the conditionally-required rows (variants 1/2/3) and keep just the
   always-required marker — saving status and undo are the load-bearing
   pieces. The full set fits comfortably above ~1200px. */
@media (max-width: 1180px) {
    .connect-autosave-legend .connect-grid-legend-item:not(:first-child) {
        display: none;
    }
}
@media (max-width: 700px) {
    .connect-autosave-legend { display: none; }
}

/* Lift the HubSpot chat bubble clear of the fixed autosave bar so it doesn't
   cover the bar's legend/status text. HubSpot injects the container with
   inline `bottom`, so `!important` is required to override it. */
#hubspot-messages-iframe-container {
    bottom: 17px !important;
}

}
