/* ============================================================
   Site Notice Bar — slide-down banner under the top header.
   Managed in Settings > Notifications (SuperAdmin). Standalone
   (no dependency on site.js/site.css) so it can be reused the
   same way loading-mark.css/js is.
   ============================================================ */

.site-notice-bar {
    display: flex;
    flex-direction: column;
}

/* #siteNoticeBar is always present in the DOM, empty or not — a margin declared unconditionally
   here would still apply to the empty container and quietly push every ordinary page (no active
   notices) down by 1rem forever. Scope it to only when a row actually exists, same technique as
   .content's padding-top override below. Bleeds to .content's left/right padding edges so the
   bar reads as chrome under the header, not a card in the page. */
.site-notice-bar:has(.site-notice-row) {
    margin: 0 -2rem 1rem;
}

/* .content's own padding-top reserves header-clearance *plus* ~1.5rem of breathing room meant
   for a page's title — that extra room is exactly the visible gap above the bar. Rather than
   fight the exact calc() (it mixes both terms into one value, and — historically, before both
   were reconciled to 60px — didn't even agree with the header's real height across layout.css's
   two competing .content rules), assert the correct value directly, and only while a notice is
   actually showing — :has() re-matches live as notice-bar.js injects/removes rows, so ordinary
   pages (no notices) are completely unaffected. Mobile's .content already uses a flush 60px
   !important with no added breathing room, so this is a no-op there — nothing further needed for
   that breakpoint. */
.content:has(.site-notice-row) {
    padding-top: 60px;
}

/* Resident Portal placement — the bar sits inside each Portal page's own .resident-content
   wrapper (no shared top header to clear there, unlike staff), so none of the assumptions
   above apply: .resident-content has 1rem/0.75rem side padding at every breakpoint (never the
   2rem-desktop/0-mobile split .content has), so the bleed-margin trick above would overflow if
   reused unmodified — same bug class as the staff mobile overflow fixed earlier. Zero horizontal
   bleed instead: the bar just sits flush within .resident-content's own padding. One rule covers
   every breakpoint since that padding is never 0. Specificity (0,3,0) beats the base rule's
   (0,2,0) above, so this wins regardless of source order. */
.resident-content .site-notice-bar:has(.site-notice-row) {
    margin: 0 0 1rem;
}

.site-notice-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    /* Asymmetric on purpose (user-requested 2026-08-23) — the dismiss button sits right up
       against the row's trailing edge rather than mirroring the icon's own left-side breathing
       room, which otherwise left it looking stranded mid-row on a wide screen. */
    padding: 0 0.75rem 0 1.25rem;
    border-bottom: 1px solid var(--border-color);
    border-left: 4px solid var(--notice-accent, var(--accent-primary));
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
    overflow: hidden;
    max-height: 0;
    opacity: 0;
    background: linear-gradient(var(--notice-tint), var(--notice-tint)), var(--bg-primary-sidebar);
    transition: max-height 0.32s ease, opacity 0.28s ease, padding 0.32s ease;
}

.site-notice-row.show {
    max-height: 300px;
    padding-top: 0.65rem;
    padding-bottom: 0.65rem;
    opacity: 1;
}

.site-notice-row__icon {
    font-size: 1.05rem;
    color: var(--notice-accent, var(--accent-primary));
    flex-shrink: 0;
}

.site-notice-row__message {
    flex: 1;
    font-size: 0.9rem;
    /* Always the same colour as the row's own icon (user-requested 2026-08-23: "row text should
       be same colour as icon") — Info/Success don't define --notice-text, so this falls back
       straight to --notice-accent rather than the plain body colour, same as the icon itself uses
       right above; Warning/Critical's own --notice-text is a close, same-hue neighbour of their
       accent (see the severity rules below), not a different colour, so this still reads as "the
       icon's colour" for those two as well. */
    color: var(--notice-text, var(--notice-accent, var(--text-primary)));
    line-height: 1.4;
    min-width: 0;
}

.site-notice-row__link {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    flex-shrink: 0;
    font-size: 0.82rem;
    font-weight: 600;
    padding: 0.32rem 0.7rem 0.32rem 0.85rem;
    border-radius: 8px;
    /* Mixed against --bg-card, not "transparent" (user-reported 2026-08-23: looked fine in dark
       but unreadably faint in light) — blending the accent into transparent composites on top of
       whatever the row's own already-tinted background happens to be, and in light mode that
       background is itself pale enough that a second pale tint on top of it reads as almost no
       chip at all. --bg-card gives the blend a fixed, theme-correct base (near-white in light,
       near-black in dark) so the chip has its own real lightness step away from the row behind
       it in both themes, not just in the one that happened to already be dark enough to show it. */
    /* --notice-text (falls back to --notice-accent when a severity doesn't define one, e.g.
       Info/Success) rather than --notice-accent directly — matches whichever colour the message
       text right below it is already using, so the button reads as the same colour as the rest of
       the row, not a separate one. */
    background: color-mix(in srgb, var(--notice-text, var(--notice-accent, var(--accent-primary))) 12%, var(--bg-card));
    border: 1px solid color-mix(in srgb, var(--notice-text, var(--notice-accent, var(--accent-primary))) 45%, transparent);
    /* !important: layout.css's global `a { color: inherit !important; }` (an intentional
       app-wide Bootstrap-link-colour reset) otherwise always wins over this regardless of
       specificity, silently leaving the button's actual text the page's plain body colour no
       matter what this rule says — found 2026-08-23 while chasing why the button's border/fill
       clearly picked up the intended hue in every screenshot but the text itself never quite did.
       border/background aren't affected (that global rule only targets the `color` property), so
       this is the one declaration on this whole element that needs it. */
    color: var(--notice-text, var(--notice-accent, var(--accent-primary))) !important;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
    text-decoration: none;
    white-space: nowrap;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}

.site-notice-row__link i {
    font-size: 0.72rem;
    transition: transform 0.15s ease;
}

/* Hover switches from --notice-text to --notice-accent — the notice's own brighter "true" colour
   (user-requested 2026-08-23: "can the button go notification bar accent colour on hover") —
   rather than just deepening the same --notice-text tint further. Text/border/fill all move
   together so the button reads as "lighting up" with the bar's own accent, not just getting a
   darker version of its resting colour. */
.site-notice-row__link:hover {
    background: color-mix(in srgb, var(--notice-accent, var(--accent-primary)) 22%, var(--bg-card));
    border-color: var(--notice-accent, var(--accent-primary));
    color: var(--notice-accent, var(--accent-primary)) !important;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
    transform: translateY(-1px);
}

.site-notice-row__link:hover i {
    transform: translateX(2px);
}

.site-notice-row__link:active {
    transform: translateY(0);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
}

.site-notice-row__dismiss {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    background: none;
    border: none;
    color: var(--text-secondary);
    font-size: 1rem;
    line-height: 1;
    padding: 0;
    cursor: pointer;
    border-radius: 6px;
    transition: background 0.15s ease, color 0.15s ease;
}

.site-notice-row__dismiss:hover {
    background: rgba(0, 0, 0, 0.06);
    color: var(--text-primary);
}

[data-theme="dark"] .site-notice-row__dismiss:hover {
    background: rgba(255, 255, 255, 0.08);
}

/* Severity accents — self-contained tokens (not --accent-light) with explicit dark overrides.
   Info/Success stay a soft, low-key wash (routine announcements). Warning/Critical are
   deliberately louder — a much stronger tint AND a tinted, contrast-safe message colour
   (--notice-text) instead of the neutral body colour — so an urgent notice doesn't read at the
   same visual weight as a routine one.

   These same three variables now also drive the pinned ribbon's colouring (see "Pinned ribbon"
   below) — placement there is decided by Scope, not Severity, so any of the four severities can
   end up in the ribbon and each needs to look right there, not just Warning/Critical. A separate
   --notice-ribbon-bg/--notice-ribbon-tint pair was tried first and then folded back into these
   once the ribbon's own background became a light tint rather than a solid block — at that point
   the two variable sets held near-identical values anyway, so keeping both was just a second
   place to update in sync for no remaining visual difference. */
.site-notice-row--info     { --notice-accent: #0078d4; --notice-tint: rgba(0, 120, 212, 0.07); }
.site-notice-row--success  { --notice-accent: #1a9c5c; --notice-tint: rgba(26, 156, 92, 0.08); }
/* Light-mode warning — several rounds of user feedback 2026-08-23, settled on matching Critical's
   own pattern ("Like critical"): accent (icon/border-left) and --notice-text (message + button)
   are close, same-hue neighbours, not a bright-chrome/dark-text split — an earlier attempt made
   --notice-accent a much brighter, more saturated yellow than --notice-text specifically so the
   icon could be vivid without dragging the (necessarily darker, for contrast) message/button down
   with it, but that read as two different colours on one row rather than "yellow" as a single,
   recognizable identity. #a8850a/#8a6c00 are both hue ~47° (true yellow, not the original
   #b45309's ~30° orange) and close enough in lightness to read as one colour, the same way
   Critical's own #b91c1c accent / #8a1414 text already do. --notice-tint follows the accent's hue
   at a moderate alpha, same relationship Critical's own tint has to its accent. */
.site-notice-row--warning  { --notice-accent: #a8850a; --notice-tint: rgba(168, 133, 10, 0.11); --notice-text: #8a6c00; }
.site-notice-row--critical { --notice-accent: #b91c1c; --notice-tint: rgba(185, 28, 28, 0.10); --notice-text: #8a1414; }

/* Dark mode also needs its own --notice-tint, not just a re-hued --notice-accent (fixed
   2026-08-23, user-reported: "can't see the colours of the notification bar in dark") — the
   tint is alpha-composited over a near-black base (--bg-primary-sidebar/--bg-header are both
   ~#252423 in dark), and the same low alpha that reads as a clear pale wash over a near-white
   light background (see above) is nearly imperceptible over near-black — alpha compositing
   doesn't preserve perceived contrast across such different base luminances. Roughly
   doubled/tripled here, using each severity's own dark accent hue, to restore the same "yes,
   this row is visibly tinted" read light mode already had. */
[data-theme="dark"] .site-notice-row--info     { --notice-accent: #4fb2f5; --notice-tint: rgba(79, 178, 245, 0.16); }
[data-theme="dark"] .site-notice-row--success  { --notice-accent: #4ad392; --notice-tint: rgba(74, 211, 146, 0.16); }
/* --notice-text set equal to --notice-accent here (not a separate lighter pastel, as it was
   before 2026-08-23) — unlike light mode, the dark accent alone already has plenty of contrast as
   text against the near-black background (~8:1 for warning, ~4.6:1 for critical), so there's no
   legibility reason to diverge from it, and matching exactly gives the cleanest, most literal
   "same colour as the icon" read the light-mode neighbours above only approximate. */
[data-theme="dark"] .site-notice-row--warning  { --notice-accent: #f0b429; --notice-text: #f0b429; --notice-tint: rgba(240, 180, 41, 0.20); }
[data-theme="dark"] .site-notice-row--critical { --notice-accent: #ef5c5c; --notice-text: #ef5c5c; --notice-tint: rgba(239, 92, 92, 0.20); }

/* Preview variant — used inside the Settings > Notifications "New/Edit Notice" modal so admins
   see exactly what they're about to publish. Static (no fixed positioning, no live dismiss). */
.site-notice-row--preview {
    position: static;
    max-height: none;
    opacity: 1;
    padding: 0.65rem 1rem;
    border-radius: 8px;
    box-shadow: none;
}

@media (max-width: 768px) {
    /* .content drops its own 2rem side padding on mobile (layout.css) — nothing left to
       bleed past, so cancel the negative margin or the bar would overflow the viewport.
       Must match the :has() selector's specificity (not just .site-notice-bar) — the base
       rule above is .site-notice-bar:has(.site-notice-row), which otherwise keeps winning
       the cascade over a plain .site-notice-bar here regardless of media-query order. */
    .site-notice-bar:has(.site-notice-row) {
        margin-left: 0;
        margin-right: 0;
    }

    .site-notice-row {
        padding-left: 1rem;
        padding-right: 1rem;
        flex-wrap: wrap;
        gap: 0.5rem;
    }

    .site-notice-row__message {
        font-size: 0.85rem;
        flex-basis: 100%;
        order: 2;
    }

    .site-notice-row__icon { order: 1; }
    .site-notice-row__dismiss { order: 1; margin-left: auto; }
    .site-notice-row__link { order: 3; }
}

/* ============================================================
   Pinned ribbon — placement is by Scope, not Severity (see isRibbonNotice in notice-bar.js):
   anything except a Communities-scoped notice renders here rather than the routine in-content
   bar, so any of the four severities can appear — Info/Success included (e.g. the synthesized
   "free trial ends" notice, Domain-scoped and often Info until its final window).
   Fixed above everything, including the header, so a notice here can't be scrolled past the way
   the routine bar can. #siteNoticeRibbon lives outside .layout-wrapper in _Layout.cshtml
   specifically so it's a true viewport-fixed element, not scoped to .content the way the routine
   bar deliberately is.

   Deliberately placed after every base .site-notice-row rule above, not just alongside them —
   .site-notice-row--ribbon shares the same (0,1,0) specificity as the base .site-notice-row it's
   overriding (border-left, box-shadow, etc.), and an equal-specificity tie goes to whichever rule
   is later in the cascade. Defining it earlier in the file (as a first pass did) meant several of
   its own declarations were silently dead, overridden by the base rule that came after them.
   ============================================================ */

.site-notice-ribbon {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    /* Above .header (1003) and .mobile-search-bar (1002) — layout.css — so it's never the thing
       that gets covered. */
    z-index: 1010;
    display: flex;
    flex-direction: column;
}

/* Same --notice-accent/--notice-tint/--notice-text tokens the routine bar uses (defined for all
   four severities above), not a separate ribbon-only colour set — a full-strength solid block
   with forced white text was tried first and read as too heavy/loud once actually seen live
   (especially two stacked), and a dedicated ribbon-only tint/bg pair duplicated the routine bar's
   own colours once this settled on a light-wash-plus-dark-text look anyway. Composited over
   --bg-header (fixed 2026-08-23 — was a hardcoded #fff, which read as a bright white strip
   pinned above an otherwise dark UI in dark mode; --bg-header already matches the header
   directly beneath it in both themes, light and dark, so the ribbon reads as chrome continuing
   above the header rather than a stray light-mode-only panel). */
.site-notice-row--ribbon {
    /* border-left restored 2026-08-23 (was explicitly `none` in the original pinned-ribbon pass
       below) — user preferred the routine bar's own left accent stripe once several stacked
       severities were compared side by side live: with no per-row accent, multiple stacked
       ribbon rows (e.g. Critical + Warning + Success at once) read as a flat stack of
       same-shaped bars distinguishable only by their (fairly close) background tint, whereas the
       routine bar's left stripe gives each row an immediate, unambiguous severity cue even at a
       glance. Just inherits the base .site-notice-row rule now — no override needed. */
    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.10);
    background: linear-gradient(var(--notice-tint), var(--notice-tint)), var(--bg-header, #fff);
}
.site-notice-row--ribbon.show {
    padding-top: 0.45rem;
    padding-bottom: 0.45rem;
}

.site-notice-row--ribbon .site-notice-row__icon {
    color: var(--notice-accent);
}
.site-notice-row--ribbon .site-notice-row__message {
    /* Same colour as the routine bar's own message (var(--notice-text, var(--notice-accent, ...)))
       — kept as its own ribbon-scoped rule rather than folded into the base .site-notice-row__
       message selector purely so this file's ribbon section stays self-contained/searchable. */
    color: var(--notice-text, var(--notice-accent, var(--text-primary)));
}
.site-notice-row--ribbon .site-notice-row__dismiss {
    color: var(--text-secondary);
}
/* No ribbon-specific .site-notice-row__link override — it used to redeclare the same
   border-color/color the base rule already resolves to, which meant its own (higher-specificity)
   :hover block silently shadowed the base rule's newer box-shadow/lift/arrow-shift (see the
   2026-08-23 "smart and professional" pass above) without adding anything itself. Removed so the
   ribbon's button matches the routine bar's exactly, from one rule. No ribbon-specific
   .site-notice-row__dismiss:hover override either, same reasoning — now that the ribbon's own
   resting dismiss colour is the plain neutral var(--text-secondary) above (not severity-tinted),
   its hover state is identical to the base rule's too, so this row just inherits that. */
/* A black tint is invisible against the ribbon's own dark background in dark mode (see --bg-header
   fix above) — this dark-only override just swaps that one value; specificity is (0,2,0), the same
   as [data-theme="dark"] .site-notice-row__dismiss:hover earlier in the file, so it wins the tie
   on source order (later wins) rather than needing a higher-specificity selector. */
[data-theme="dark"] .site-notice-row--ribbon .site-notice-row__dismiss:hover {
    background: rgba(255, 255, 255, 0.08);
}

/* Header/sidebars/content push down by exactly the ribbon's real rendered height — kept in sync
   live by notice-bar.js's ResizeObserver (observeRibbonHeight), so this tracks correctly through
   the slide-open/close transition and however many Warning/Critical notices are stacked, rather
   than assuming a single fixed row height. :has() re-matches live as rows are added/removed, so
   every rule here is automatically a no-op on a page with no active ribbon notice. Same "assert
   the correct value directly rather than fight the base rule's own calc()" approach as
   .content:has(.site-notice-row) above — layout.css's .header/.primary-sidebar/.secondary-sidebar
   are otherwise hardcoded to a bare top:0/60px with no ribbon-height term to extend. */
body:has(#siteNoticeRibbon .site-notice-row) .header {
    top: var(--notice-ribbon-height, 0px);
    transition: top 0.28s ease;
}
body:has(#siteNoticeRibbon .site-notice-row) .primary-sidebar,
body:has(#siteNoticeRibbon .site-notice-row) .secondary-sidebar {
    top: calc(60px + var(--notice-ribbon-height, 0px));
    transition: top 0.28s ease;
}
body:has(#siteNoticeRibbon .site-notice-row) .content {
    /* 1.5rem, not 2rem — kept in sync with layout.css's own .content padding-top (top/bottom
       breathing-room symmetry, user-requested). */
    padding-top: calc(60px + 1.5rem + var(--notice-ribbon-height, 0px));
    transition: padding-top 0.28s ease;
}
body:has(#siteNoticeRibbon .site-notice-row) .mobile-search-bar {
    top: calc(60px + var(--notice-ribbon-height, 0px));
}

/* Mobile's own .content rule (layout.css, end of file) asserts a flush `padding-top: 60px
   !important` with no added breathing room — !important always wins over the unqualified rule
   above regardless of specificity, so it needs its own matching override here to actually take
   effect on small screens. */
@media (max-width: 768px) {
    body:has(#siteNoticeRibbon .site-notice-row) .content {
        padding-top: calc(60px + var(--notice-ribbon-height, 0px)) !important;
    }
}
