/*
 * Wisps — the ephemeral thoughts.
 *
 * Two parts: the cloud badge, a small mark on the corner of an avatar that says "this person has
 * a thought alive right now", and the quote dialog it opens. The badge is quiet on purpose — the
 * feature's brief is "present but not annoying", so the mark is small, monochrome until hovered,
 * and only the account's own live cloud fills with colour.
 *
 * Every badge is absolutely positioned, and every badge is a *sibling* of the avatar's clickable
 * element rather than a child: an interactive element inside another is markup no browser will
 * honour, so the positioning context is the wrapper each caller provides (the header's user menu,
 * a card's author block, the profile's avatar holder).
 */

/* ---- The cloud badge -------------------------------------------------------------------------- */

.wisp-badge {
    position: absolute;
    z-index: 2;

    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;

    background-color: var(--colour-surface-raised);
    border: var(--border-width) solid var(--colour-border-strong);
    border-radius: var(--radius-full);
    box-shadow: var(--shadow-sm);
    color: var(--colour-ink-quiet);
    text-decoration: none;

    transition: color var(--duration-fast) var(--easing),
        border-color var(--duration-fast) var(--easing),
        transform var(--duration-fast) var(--easing);
}

.wisp-badge:hover,
.wisp-badge:focus-visible {
    color: var(--colour-primary);
    border-color: var(--colour-border-focus);
    transform: translateY(-1px);
}

/* A live wisp fills the cloud: the one state worth colour. */
.wisp-badge--active {
    background-color: var(--colour-primary);
    border-color: var(--colour-primary);
    color: var(--colour-primary-ink);
}

.wisp-badge--active:hover,
.wisp-badge--active:focus-visible {
    background-color: var(--colour-primary-hover);
    border-color: var(--colour-primary-hover);
    color: var(--colour-primary-ink);
}

/* The header's own cloud sits on the corner of the 40px menu avatar; the user menu is already
   the positioning context. */
.wisp-badge--own {
    top: -0.375rem;
    inset-inline-end: -0.375rem;
}

/* A card's author block wraps the author link so the cloud can hang off the avatar's corner
   without living inside the link. The wrapper takes over the link's old role in the header flex. */
.post-card__author-block {
    position: relative;
    min-width: 0;
}

.wisp-badge--card {
    top: -0.375rem;
    inset-inline-start: 1.75rem;
}

/* The profile header's large avatar: the holder becomes the context, and the cloud sits on its
   top corner, above the cover picture. */
.social-profile__avatar {
    position: relative;
}

.wisp-badge--profile {
    top: -0.25rem;
    inset-inline-end: -0.25rem;

    width: 1.75rem;
    height: 1.75rem;
}

/* ---- The viewer: a thought as a quote --------------------------------------------------------- */

.wisp-viewer {
    text-align: center;
}

.wisp-viewer__mark {
    display: flex;
    justify-content: center;
    color: var(--colour-primary);
}

.wisp-viewer__quote {
    position: relative;
    margin: var(--space-3) 0 0;
    padding: var(--space-5) var(--space-3) var(--space-2);
}

/* The oversized opening quote mark is the decoration: the words arrive in a plain <p>, filled by
   textContent, so nothing the author wrote ever passes through a markup parse. */
.wisp-viewer__quote::before {
    content: "\201C";
    position: absolute;
    top: -0.35rem;
    inset-inline-start: 50%;
    transform: translateX(-50%);

    font-size: 4.5rem;
    line-height: 1;
    color: var(--colour-primary-surface);
    pointer-events: none;
}

.wisp-viewer__quote p {
    position: relative;
    margin: 0;

    font-size: var(--text-xl);
    font-weight: var(--weight-medium);
    line-height: var(--leading-tight);
    overflow-wrap: anywhere;
}

.wisp-viewer__author {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    margin-top: var(--space-4);
}

.wisp-viewer__identity {
    display: inline-flex;
    flex-direction: column;
    text-align: start;
}

.wisp-viewer__name {
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    line-height: var(--leading-tight);
}

.wisp-viewer__handle {
    font-size: var(--text-xs);
    color: var(--colour-ink-quiet);
}

.wisp-viewer__own-label {
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    color: var(--colour-ink-quiet);
}

.wisp-viewer__expires {
    margin: var(--space-3) 0 0;
    font-size: var(--text-sm);
    color: var(--colour-ink-quiet);
}

.wisp-viewer__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    margin-top: var(--space-4);
}

/* The withdrawal is a real form so it works with the script layer blocked; inline-flex keeps it
   in the row of buttons rather than taking the block for itself. */
.wisp-viewer__delete {
    display: inline-flex;
    margin: 0;
}

/* Ripple, the share that moves nothing: shown only when the server says this viewer may ripple
   the thought — the `hidden` attribute is the script's lever, and this rule keeps the form in
   line with the other acts when it appears. */
.wisp-viewer__ripple {
    margin-top: var(--space-3);
}

.wisp-viewer__ripple-form {
    display: flex;
    justify-content: center;
    margin: 0;
}

.wisp-viewer__hint {
    margin: var(--space-4) 0 0;
    font-size: var(--text-xs);
    color: var(--colour-ink-faint);
}

/* ---- The composer ------------------------------------------------------------------------------ */

.wisp-composer__input {
    resize: vertical;
    min-height: 5rem;
}

.wisp-composer__form .modal__actions {
    margin-top: var(--space-4);
}
