/* ============================================
   Workspace status UI — save badges,
   unified editor page headers
   ============================================ */

/* ── Unified page header ── */
.fd-page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}

.fd-page-header__main {
    flex: 1;
    min-width: 0;
}

.fd-page-header__title {
    margin: 0;
}

.fd-page-header__subtitle {
    margin: 0;
}

.fd-page-header__toolbar {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-shrink: 0;
}

/* Keep persistent header metadata on the outer edge. The save badge is hidden
   while idle but still reserves space to prevent layout shifts. */
.fd-page-header__toolbar > .fd-save-badge {
    order: -1;
}

/* ── Auto-save status badge ── */
.fd-save-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    border-radius: var(--fd-radius-sm);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.01em;
    flex-shrink: 0;
    transition: var(--fd-transition);
    background: var(--fd-bg-secondary);
    color: var(--fd-text-secondary);
    border: 1px solid var(--fd-border);
    visibility: hidden;
}

.fd-save-badge.as-dirty,
.fd-save-badge.as-saving,
.fd-save-badge.as-saved,
.fd-save-badge.as-error {
    visibility: visible;
}

.fd-save-badge .fd-save-dot {
    /* Variable so the error banner's first-line offset below stays exact where a
       host resizes the dot (yourPage's tab bar uses 7px). */
    width: var(--fd-save-dot-size, 8px);
    height: var(--fd-save-dot-size, 8px);
    border-radius: 50%;
    flex-shrink: 0;
    background: var(--fd-text-muted);
    transition: background 0.2s ease;
}

.fd-save-badge.as-saved {
    background: var(--fd-success-bg);
    color: var(--fd-success-hover);
    border-color: rgba(16, 185, 129, 0.25);
    padding: 6px 10px;
    font-weight: 500;
}

.fd-save-badge.as-saved .fd-save-dot {
    background: var(--fd-success);
}

.fd-save-badge.as-saving {
    background: var(--fd-bg-secondary);
    color: var(--fd-text-secondary);
    border-color: var(--fd-border);
}

.fd-save-badge.as-saving .fd-save-dot {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: transparent;
    border: 2px solid var(--fd-border);
    border-top-color: var(--fd-text-secondary);
    animation: fd-save-spin 0.6s linear infinite;
}

.fd-save-badge.as-dirty {
    background: var(--fd-warning-bg);
    color: var(--fd-warning-hover);
    border-color: var(--fd-warning-light);
}

.fd-save-badge.as-dirty .fd-save-dot {
    background: var(--fd-warning);
}

.fd-save-badge.as-error {
    background: var(--fd-danger-bg);
    color: var(--fd-danger);
    border-color: var(--fd-danger-light);
}

.fd-save-badge.as-error .fd-save-dot {
    background: var(--fd-danger);
}

.fd-save-badge.as-retrying {
    background: var(--fd-warning-bg);
    color: var(--fd-warning-hover);
    border-color: var(--fd-warning-light);
    animation: fd-save-pulse 2s ease-in-out infinite;
}

.fd-save-badge.as-retrying .fd-save-dot {
    background: var(--fd-warning);
}

.fd-save-badge .as-retry-btn {
    background: none;
    border: none;
    color: inherit;
    cursor: pointer;
    font-size: inherit;
    font-weight: inherit;
    text-decoration: underline;
    padding: 0;
    margin-left: 2px;
}

@keyframes fd-save-spin {
    to { transform: rotate(360deg); }
}

@keyframes fd-save-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.6; }
}

/* ── Error banner ──
   Error copy is long — "You’re offline. Check your connection and try again. Retry"
   is ~390px, the timeout message ~475px — and cannot share a row with the title:
   on phones the pill painted over the title and ran off the left edge of the
   screen; on narrow desktops (the badge never shrinks, the title column does) it
   squeezed the title and subtitle into a sliver and wrapped them mid-save.
   In any error state the toolbar therefore becomes a full-width row ABOVE the
   title — the conventional place for a page-level alert — and the badge fills
   it, so the text wraps instead of overflowing. Everything else (Saving…, All
   changes saved, idle) keeps the inline pill and its zero-shift contract; only
   errors, which are rare and deserve the attention, pay a layout shift.
   The state is read in CSS via :has() so this layout stays in the shared sheet
   with the rest of the header (see the no-layout-on-headerClass rule below);
   browsers without :has() fall back to the inline pill. */
.fd-page-header:has(> .fd-page-header__toolbar > .fd-save-badge.as-error) > .fd-page-header__toolbar {
    order: -1;
    flex-basis: 100%;
    min-width: 0;
}

/* The banner's look, shared by both hosts. The second selector is yourPage's tab
   bar, the only place outside .fd-page-header that shows this badge; its own
   sheet undoes the pill geometry it sets and does the wrapping (yourPage.css,
   search yl-tab-save-badge.as-error). Placement is per-host below. */
.fd-page-header:has(> .fd-page-header__toolbar > .fd-save-badge.as-error) .fd-save-badge,
.yl-tab-bar:has(> .fd-save-badge.as-error) .fd-save-badge {
    width: 100%;
    /* Multi-line message: pin the dot to the first line rather than the block’s
       middle. */
    align-items: flex-start;
}

/* (line box − dot) / 2. The badge’s line-height is `normal`, 16.5px for Outfit
   at 13px; the lh unit tracks that if the font or size ever changes, the static
   value is the fallback for browsers without it. */
.fd-page-header:has(> .fd-page-header__toolbar > .fd-save-badge.as-error) .fd-save-badge .fd-save-dot,
.yl-tab-bar:has(> .fd-save-badge.as-error) .fd-save-badge .fd-save-dot {
    margin-top: 4.25px;
    margin-top: calc((1lh - var(--fd-save-dot-size, 8px)) / 2);
}

/* ── Responsive ── */
@media (max-width: 768px) {
    /* The header used to stack into a column at this width, which gave the toolbar a
       row of its own. Since the save badge reserves its space while idle (see its
       visibility rule above), that row rendered as a permanent empty band between
       the subtitle and the first card on every editor page.
       Grid keeps the reservation without the band: the badge shares the title's row,
       which already has the height to hold it, and the subtitle spans the full width
       underneath rather than being squeezed by an element nobody can see.
       Vertically nothing shifts — min-height below pins the row. The badge's column
       is content-sized, though, so it does widen when the badge gains its text: on
       the narrowest phones that can re-wrap a long title mid-save (Services &
       Pricing does at 375px, but not at 390px and up). Reserving the widest state
       instead would wrap those titles permanently, which is the worse trade.
       Error states leave this row altogether — see the error-banner rules above
       and their grid placement at the end of this block. */
    .fd-page-header {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        column-gap: 16px;
        row-gap: var(--fd-page-header-gap, 8px);
    }

    /* Promotes the title and subtitle to grid items so they can take separate rows.
       This wrapper only ever carried flex sizing — no page paints a background,
       border, or padding on it — so dropping its box costs nothing. */
    .fd-page-header__main {
        display: contents;
    }

    /* The title→subtitle gap is the title's own bottom margin, declared by each
       page. Left there it sits INSIDE row 1, so the row is taller than the title
       and centring the badge against the row dropped it half a margin below the
       title's text. The gap moves to row-gap above — pages whose margin is not
       8px declare --fd-page-header-gap to match — leaving row 1 as the title box
       and the badge alone, which centre on each other exactly.
       align-self is needed because the row is floored at the badge's 34px: without
       it the title stretches and its text sits at the top of that taller row.
       The selector must out-specify the page's own title class, which is where
       the margin lives and whose sheet loads after this one. */
    .fd-page-header .fd-page-header__title {
        grid-column: 1;
        grid-row: 1;
        align-self: center;
        margin-bottom: 0;
    }

    .fd-page-header__subtitle {
        grid-column: 1 / -1;
        grid-row: 2;
    }

    /* align-self rather than the container's align-items: it centres the badge
       against the title on every page, including the two that set align-items
       themselves.
       min-height is the badge's height in its active states — idle it is 8px
       shorter, having no text, and without a floor the row (and everything below
       it) would grow the moment a save starts. */
    .fd-page-header__toolbar {
        grid-column: 2;
        grid-row: 1;
        align-self: center;
        justify-content: flex-end;
        min-height: 34px;
    }
    /* Error banner in the grid: the toolbar takes a full-width first row, the
       title and subtitle move down one row each. The title spans both columns
       too — with column 2 empty it would otherwise still lose the 16px column
       gap. The extra bottom margin lifts the banner→title gap to 16px on every
       page regardless of its --fd-page-header-gap. */
    .fd-page-header:has(> .fd-page-header__toolbar > .fd-save-badge.as-error) > .fd-page-header__toolbar {
        grid-column: 1 / -1;
        grid-row: 1;
        margin-bottom: calc(16px - var(--fd-page-header-gap, 8px));
    }

    .fd-page-header:has(> .fd-page-header__toolbar > .fd-save-badge.as-error) .fd-page-header__title {
        grid-column: 1 / -1;
        grid-row: 2;
    }

    .fd-page-header:has(> .fd-page-header__toolbar > .fd-save-badge.as-error) .fd-page-header__subtitle {
        grid-row: 3;
    }
}

@media (max-width: 480px) {
    .fd-save-badge.as-saved .fd-save-text {
        font-size: 0;
    }

    .fd-save-badge.as-saved .fd-save-text::after {
        content: 'Saved';
        font-size: 13px;
    }
}
