/* ============================================================
   notifications.css
   ============================================================
   Owns the notification visualization surfaces end-to-end:
     - the navbar avatar unread halo (.avatar-has-unread::after),
       which indicates pending follows / unread state on the
       navbar avatar
     - the /notifications page chrome (pr31 cleanup): inbox-style
       redesign with header, tabs, list, rows, empty state, and
       pagination
     - the per-row announcement level dot used inline in
       notification rows (Phase 14c up5)

   The .has-halo-blue primitive consumed by notification rows
   already lives in halos.css (commit 2 of the refactor) — do
   not duplicate it here.

   Reference: markdown/design/DESIGN_DECISIONS_CSS_REFACTOR.md
   ============================================================ */

/* ============================================================
   NOTIFICATIONS
   ============================================================
   Visual treatment for the notifications surface. Built on the
   existing .has-halo pattern (see ~line 396) but with a blue
   variant for "there is something new for you" — distinct from
   the brand-purple halo used for modals.

   The blue halo earns its own meaning: "unread / unattended."
   When a notification is marked read, the halo is removed and
   the row collapses to a neutral resting state.
   ============================================================ */

.avatar-has-unread::after {
    content: "";
    position: absolute;
    top: 2px;
    right: 2px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    /* app1 — flat mint halo, re-uses --color-accent so it tracks the
       theme (mint-dark on cream, full mint on midnight). Was hardcoded
       Bootstrap blue rgb(13, 110, 253) pre-Transmission. */
    background: var(--color-accent);
    border: 2px solid var(--color-bg-surface);
    pointer-events: none;
}

.notification-bell-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 6px;
    margin-left: auto;
    border-radius: 9px;
    background: rgb(13, 110, 253);
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
}

/* ============================================================
   NOTIFICATIONS PAGE — inbox-style redesign (pr31 cleanup)
   ============================================================
   Replaces the prior card-list treatment (with its orphaned
   blue halo) with a dense inbox-row layout that matches the
   visual vocabulary of the messaging inbox and search modal.

   Anatomy:
     .notifications-page             page wrapper, max-width capped
       .notifications-header          title + count pill + mark-all btn
       .notifications-tabs            all / reactions / comments / msgs
       .notifications-list            container for rows (or empty state)
         .notification-row             one row, whole-row <a> link
           .notification-glyph-wrap     avatar + kind-glyph overlay
           .notification-body            primary line + meta
           .notification-chevron         hover-revealed nav hint
       .notifications-pagination      bootstrap pagination wrapper

   Color: dark base + violet accent. No blue halo anywhere.
   Unread state: 3px violet bar on the row's left edge.

   The .has-halo-blue, .avatar-has-unread, .notification-bell-badge,
   and .notification-roster-link rules elsewhere in this file are
   kept — they're consumed by the nav avatar unread dot, the bell
   badge, and the in-line roster link (which lives inside the
   notification body and survives the redesign).
   ============================================================ */

/* ---- Page wrapper ---- */

.notifications-page {
    max-width: 720px;
    margin: 0 auto;
    padding: var(--space-5) var(--space-3);
}

/* ---- Header row ---- */

.notifications-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
}

.notifications-title {
    font-size: 1.5rem;
    font-weight: var(--font-weight-semibold);
    margin: 0;
    letter-spacing: -0.02em;
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    flex-wrap: wrap;
}

.notifications-count-pill {
    display: inline-flex;
    align-items: baseline;
    padding: 2px 10px;
    background: color-mix(in srgb, var(--color-accent) 14%, transparent);
    color: var(--color-accent);
    border-radius: var(--radius-pill);
    font-size: 0.75rem;
    font-weight: var(--font-weight-semibold);
    font-variant-numeric: tabular-nums;
}

.notifications-mark-all-btn {
    background: transparent;
    border: 1px solid var(--color-border);
    color: var(--color-text-muted);
    padding: 6px 14px;
    border-radius: var(--radius-sm);
    font-size: 0.85rem;
    font-family: inherit;
    cursor: pointer;
    white-space: nowrap;
    transition: border-color var(--transition-fast),
                color var(--transition-fast),
                background-color var(--transition-fast);
}

.notifications-mark-all-btn:hover,
.notifications-mark-all-btn:focus-visible {
    border-color: var(--color-accent);
    color: var(--color-accent);
    outline: none;
}

.notifications-mark-all-btn:focus-visible {
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-accent) 40%, transparent);
}

.notifications-mark-all-btn:disabled {
    opacity: 0.5;
    cursor: wait;
}

/* ---- Tab strip ---- */

.notifications-tabs {
    display: flex;
    gap: var(--space-1);
    border-bottom: 1px solid var(--color-border);
    /* Negative bottom margin so the active tab's bottom border can
       paint over the strip's border without a visible seam. */
    margin-bottom: -1px;
    padding-bottom: 1px;
}

.notifications-tab {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-2) var(--space-3);
    border-bottom: 2px solid transparent;
    color: var(--color-text-muted);
    font-size: 0.9rem;
    text-decoration: none;
    margin-bottom: -1px;
    transition: color var(--transition-fast),
                border-color var(--transition-fast);
}

.notifications-tab:hover {
    color: var(--color-text);
}

.notifications-tab:focus-visible {
    outline: none;
    color: var(--color-text);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-accent) 40%, transparent);
    border-radius: var(--radius-sm);
}

.notifications-tab.is-active {
    color: var(--color-accent);
    border-bottom-color: var(--color-accent);
    font-weight: var(--font-weight-medium);
}

.notifications-tab-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 6px;
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--color-accent) 20%, transparent);
    color: var(--color-accent);
    font-size: 0.7rem;
    font-weight: var(--font-weight-semibold);
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

/* Inactive tabs get a quieter badge — same shape, muted color. */
.notifications-tab:not(.is-active) .notifications-tab-badge {
    background: var(--color-bg-subtle);
    color: var(--color-text-muted);
}

/* ---- List + row ---- */

.notifications-list {
    /* Real spacing between list and tabs — the tabs section's negative
       margin trick leaves us at -1px; reset and add breathing room. */
    margin-top: var(--space-4);
    display: flex;
    flex-direction: column;
}

.notification-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-3) var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--color-border-subtle);
    position: relative;
    color: inherit;
    text-decoration: none;
    border-radius: var(--radius-md);
    transition: box-shadow var(--transition-medium),
                background-color var(--transition-fast);
}

/* When the row is an <a> it inherits link color by default. Force
   body color so the row doesn't paint accent-violet text on read
   rows or against hover background. */
a.notification-row,
a.notification-row:visited {
    color: var(--color-text);
}

/* Hover halo — reuses the three-layer violet glow pattern from
   .has-halo (compose modal, free-space modal). Tighter mid + far
   layers than the modal version so adjacent rows don't bleed into
   each other in a stacked list. The 1px inner ring sits right at
   the row edge; the mid glow softens out at ~12px; the far diffuse
   layer fades by ~32px. z-index lifts the hovered row above its
   neighbors so the halo paints over their borders, not under them. */
.notification-row:hover,
.notification-row:focus-visible {
    z-index: 1;
    box-shadow:
        0 0 0 1px rgba(var(--color-halo-rgb), 0.45),
        0 0 12px 2px rgba(var(--color-halo-rgb), 0.22),
        0 0 32px 4px rgba(var(--color-halo-rgb), 0.10);
}

a.notification-row:hover,
a.notification-row:focus-visible {
    color: var(--color-text);
    text-decoration: none;
    outline: none;
}

/* The unread bar — 3px violet line on the left edge. */
.notification-row.is-unread::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 3px;
    height: 28px;
    background: var(--color-accent);
    border-radius: 0 2px 2px 0;
    box-shadow: 0 0 8px color-mix(in srgb, var(--color-accent) 50%, transparent);
}

.notification-row.is-read {
    opacity: 0.6;
}

/* ---- Avatar + kind-glyph overlay ---- */

.notification-glyph-wrap {
    position: relative;
    flex-shrink: 0;
}

.notification-glyph {
    position: absolute;
    bottom: -4px;
    right: -4px;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    /* Match the page background so the glyph reads as floating
       above the avatar rather than sitting on a chip. Hover state
       keeps the same ring — no background swap needed since the
       row's hover halo is just a box-shadow, not a fill. */
    background: var(--color-bg-page);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    line-height: 1;
    /* A 1px ring so the glyph stays visible against the avatar edge. */
    box-shadow: 0 0 0 1.5px var(--color-bg-page),
                0 0 0 2.5px var(--color-border);
}

/* ---- Body ---- */

.notification-body {
    flex: 1 1 auto;
    min-width: 0;
    line-height: 1.4;
}

.notification-line {
    font-size: 0.95rem;
    color: var(--color-text);
}

.notification-row.is-read .notification-line {
    color: var(--color-text-muted);
}

.notification-line strong {
    font-weight: var(--font-weight-semibold);
}

.notification-meta {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-top: var(--space-1);
    font-size: 0.78rem;
    color: var(--color-text-muted);
}

.notification-meta-time {
    font-variant-numeric: tabular-nums;
}

/* The "see all reactions" trigger — a small outlined pill button
   that sits in the meta line as a peer to the timestamp. Quiet
   resting state (muted border + text), wakes up to violet on
   hover/focus. Compact enough not to crowd the timestamp but
   substantial enough to read as a real button affordance.

   data-roster-trigger is picked up by reaction_roster.js via
   delegated listener; notifications.js skips this element in
   the row-click intercept so the row's <a> navigation doesn't
   fire when the user clicks the button. */
.notification-roster-btn {
    display: inline-flex;
    align-items: center;
    padding: 2px 10px;
    background: transparent;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-pill);
    color: var(--color-text-muted);
    font-family: inherit;
    font-size: 0.75rem;
    line-height: 1.4;
    cursor: pointer;
    transition: border-color var(--transition-fast),
                color var(--transition-fast),
                background-color var(--transition-fast);
}

.notification-roster-btn:hover,
.notification-roster-btn:focus-visible {
    border-color: var(--color-accent);
    color: var(--color-accent);
    background: color-mix(in srgb, var(--color-accent) 8%, transparent);
    outline: none;
}

.notification-roster-btn:focus-visible {
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-accent) 30%, transparent);
}

.notification-line .notification-roster-link:hover {
    color: var(--color-accent-hover);
    text-decoration: underline;
}

/* ---- Chevron ---- */

.notification-chevron {
    flex-shrink: 0;
    color: var(--color-text-muted);
    opacity: 0;
    transition: opacity var(--transition-fast), transform var(--transition-fast);
}

.notification-row:hover .notification-chevron,
.notification-row:focus-visible .notification-chevron {
    opacity: 1;
    transform: translateX(2px);
}

/* ---- Empty state ---- */

.notifications-empty {
    text-align: center;
    padding: var(--space-6) var(--space-4);
    color: var(--color-text-muted);
}

.notifications-empty p {
    margin: 0;
}

/* ---- Pagination spacing ---- */

.notifications-pagination {
    margin-top: var(--space-5);
}

/* ---- Responsive ---- */

@media (max-width: 600px) {
    .notifications-page {
        padding: var(--space-3) var(--space-2);
    }

    .notifications-header {
        /* Stack vertically on narrow screens — the title + pill
           and the mark-all button both want full width. */
        flex-direction: column;
        align-items: stretch;
        gap: var(--space-2);
    }

    .notifications-mark-all-btn {
        align-self: flex-start;
    }

    .notifications-tabs {
        overflow-x: auto;
        scrollbar-width: thin;
        -webkit-overflow-scrolling: touch;
        /* Keep the active-tab seam visible during overflow scroll. */
        flex-wrap: nowrap;
    }

    .notifications-tab {
        flex-shrink: 0;
    }

    .notification-row {
        padding-left: var(--space-3);
        padding-right: var(--space-2);
    }

    /* Hide the chevron on touch — there's no hover, no benefit. */
    .notification-chevron {
        display: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .notification-row,
    .notification-chevron,
    .notifications-tab,
    .notifications-mark-all-btn,
    .notification-roster-btn {
        transition: none;
    }

    .notification-row:hover .notification-chevron,
    .notification-row:focus-visible .notification-chevron {
        transform: none;
    }
}

/* ============================================================
   Notification row: announcement level dot (Phase 14c up5)
   ============================================================
   Small 8x8 colored circle rendered inline before the actor's
   username in the notification row's primary line, when the
   notification kind is announcement_published. Mirrors the
   archive page's .update-dot color dispatch (fyi/heads_up/yikes
   → info/warning/danger) so the per-level signal is consistent
   across the banner, archive, dashboard updates column, and
   bell-icon row.

   Decorative (aria-hidden in the markup) — the per-level glyph
   inside the avatar overlay (📣/⚠️/🚨) already encodes the same
   signal visually. Screen reader users don't get a level cue in
   v1; if an a11y audit raises it, surface the level as sr-only
   text in the row's primary line.
   ============================================================ */

.notification-row-level-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    margin-right: var(--space-2);
    vertical-align: middle;
}

.notification-row-level-dot[data-level="fyi"]      { background: var(--color-info); }
.notification-row-level-dot[data-level="heads_up"] { background: var(--color-warning); }
.notification-row-level-dot[data-level="yikes"]    { background: var(--color-danger); }
