/*
 * Realtime notification toasts (dashboard).
 *
 * Why this file exists: every dimension of the toast used to be assigned as an inline style from
 * notifications-hub.js, and the two classes that were supposed to keep it small — `min-w-0` and
 * `btn-close-sm` — are not defined anywhere in this project or in Bootstrap 5.3.2. Without a real
 * `min-width: 0` on the flex text column, `text-truncate` cannot ellipsize (a flex item defaults to
 * `min-width: auto`, so it refuses to shrink below its min-content width) and the message pushed straight
 * out of the box. That is the whole reason the toast read as oversized.
 *
 * Everything here is a class on an external stylesheet, so the component needs no inline style attribute
 * and no inline script.
 */

/* Bootstrap's own `.toast-container` handles stacking; this adds the fixed placement. `inset-inline-end`
   rather than `right` so Arabic RTL mirrors the corner without a direction-specific override. */
#notif-toast-container {
    position: fixed;
    top: 1rem;
    inset-inline-end: 1rem;
    /* Above sticky chrome and modal backdrops, below tooltips — matches Bootstrap's own toast layer. */
    z-index: 1090;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    /* Shrink to the content up to a readable maximum instead of always occupying a fixed 320px block. */
    width: max-content;
    max-width: min(22rem, calc(100vw - 2rem));
    pointer-events: none;
}

#notif-toast-container > * {
    pointer-events: auto;
}

.notif-toast {
    width: 100%;
    padding: 0.55rem 0.7rem;
    font-size: 0.86rem;
}

.notif-toast__row {
    display: flex;
    gap: 0.55rem;
    align-items: flex-start;
}

.notif-toast__icon {
    flex: 0 0 auto;
    margin-top: 0.1rem;
    font-size: 0.95rem;
    line-height: 1.2;
}

/* The fix. A flex child must be told it may shrink below its content width before any ellipsis or line
   clamp inside it can take effect. */
.notif-toast__text {
    flex: 1 1 auto;
    min-width: 0;
}

.notif-toast__title {
    display: block;
    overflow: hidden;
    font-size: 0.88rem;
    font-weight: 650;
    line-height: 1.3;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Two lines is the ceiling: a toast points at the notification centre, it does not reproduce it. */
.notif-toast__body {
    display: -webkit-box;
    overflow: hidden;
    margin-top: 0.1rem;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    font-size: 0.8rem;
    line-height: 1.35;
    opacity: 0.85;
    overflow-wrap: anywhere;
}

.notif-toast__close {
    flex: 0 0 auto;
    margin-top: 0.15rem;
    /* Bootstrap has no `.btn-close-sm`; the smaller target is set here instead of with a class that does
       not exist. Kept at 1.5rem so it still meets a comfortable pointer target once padding is counted. */
    width: 0.65rem;
    height: 0.65rem;
    padding: 0.4rem;
    background-size: 0.65rem;
}

/* Severity is carried by a left-hand glyph and the title, never by colour alone.
   The glyph colour is a token so the dark block below can lift it off a dark surface without this
   component being written twice. */
.notif-toast--info .notif-toast__icon {
    color: var(--toast-icon-info, #1d4ed8);
}

.notif-toast--success .notif-toast__icon {
    color: var(--toast-icon-success, #047857);
}

.notif-toast--warning .notif-toast__icon {
    color: var(--toast-icon-warning, #b45309);
}

.notif-toast--error .notif-toast__icon {
    color: var(--toast-icon-error, #b91c1c);
}

@media (max-width: 575.98px) {
    /* On a phone the corner box becomes a full-width strip pinned to the top, which is the one placement
       that does not cover the content the notification refers to. */
    #notif-toast-container {
        top: 0.5rem;
        inset-inline: 0.5rem;
        width: auto;
        max-width: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .notif-toast {
        transition: none;
    }
}

/* ============================================================================================
   Shared-component additions
   ============================================================================================

   This file began as the dashboard's realtime-notification stylesheet and is now the presentation for
   the shared toast (shared/js/custom/toast.js) on both shells, so it also has to carry the surface
   treatment the Website redesign asked for: a defined edge, a soft shadow, a severity rail, and an
   optional compact call to action.

   ONE component, two shells, two themes.

   The Website declares --border / --text / --text-dim / --primary in home-static-port.css. The dashboard
   declares none of those, but it does declare its own theme-flipped set in the Sash theme, twice: once on
   bare :root for light and again under [data-theme-mode=dark]. Writing a single literal fallback (which is
   what this file used to do) therefore pinned the toast to the light palette on the dashboard, so in dark
   mode it rendered as an opaque white panel with near-black text.

   Chaining the two token sets fixes both shells at once without duplicating the component:

       var(--website-token, var(--dashboard-token, <light literal>))

   On the Website the first name resolves and the palette is bit-for-bit what it was. On the dashboard the
   first name is undefined, so the dashboard's own token wins - and because that token is already
   theme-flipped by the vendor stylesheet, the toast follows light/dark with no JS and no second ruleset.
   The literal only survives where neither shell declares anything.
*/

.notif-toast {
    --toast-surface: var(--custom-white, #FFFFFF);
    --toast-border: var(--border, var(--default-border, #E2E8F0));
    --toast-title-color: var(--text, var(--default-text-color, #0F172A));
    --toast-body-color: var(--text-dim, var(--text-muted, #475569));
    --toast-accent: var(--primary, rgb(var(--primary-rgb, 37, 99, 235)));
    --toast-shadow: rgba(15, 23, 42, 0.30);
    --toast-shadow-soft: rgba(15, 23, 42, 0.05);

    border: 1px solid var(--toast-border);
    border-radius: var(--r-md, 12px);
    background: var(--toast-surface);
    box-shadow: 0 14px 34px -14px var(--toast-shadow), 0 3px 8px var(--toast-shadow-soft);
}

/* A 3px severity rail on the leading edge. Drawn with an inset shadow rather than a border so it
   follows the writing direction and does not shift the box by a pixel. */
.notif-toast--info    { box-shadow: inset 3px 0 0 0 #2563EB, 0 14px 34px -14px var(--toast-shadow); }
.notif-toast--success { box-shadow: inset 3px 0 0 0 #10B981, 0 14px 34px -14px var(--toast-shadow); }
.notif-toast--warning { box-shadow: inset 3px 0 0 0 #F59E0B, 0 14px 34px -14px var(--toast-shadow); }
.notif-toast--error   { box-shadow: inset 3px 0 0 0 #BA1A1A, 0 14px 34px -14px var(--toast-shadow); }

[dir="rtl"] .notif-toast--info    { box-shadow: inset -3px 0 0 0 #2563EB, 0 14px 34px -14px var(--toast-shadow); }
[dir="rtl"] .notif-toast--success { box-shadow: inset -3px 0 0 0 #10B981, 0 14px 34px -14px var(--toast-shadow); }
[dir="rtl"] .notif-toast--warning { box-shadow: inset -3px 0 0 0 #F59E0B, 0 14px 34px -14px var(--toast-shadow); }
[dir="rtl"] .notif-toast--error   { box-shadow: inset -3px 0 0 0 #BA1A1A, 0 14px 34px -14px var(--toast-shadow); }

/* The rail sits inside the padding box, so the content needs to clear it. */
.notif-toast__row {
    padding-inline-start: 0.2rem;
}

.notif-toast__title {
    color: var(--toast-title-color);
}

.notif-toast__body {
    color: var(--toast-body-color);
    /* The title above already carries the emphasis; dimming by colour rather than opacity keeps the
       text at full contrast against the surface in either theme. */
    opacity: 1;
}

/* Optional pointer to the record the toast is about. Kept to one short line so the toast stays a
   glance, not a panel. */
.notif-toast__action {
    display: inline-block;
    margin-top: 0.35rem;
    color: var(--toast-accent);
    font-size: 0.79rem;
    font-weight: 650;
    text-decoration: none;
}

.notif-toast__action:hover {
    text-decoration: underline;
}

.notif-toast__action:focus-visible {
    outline: 2px solid var(--toast-accent);
    outline-offset: 2px;
    border-radius: 3px;
}

/* ---------------------------------------------------------------------------- shared-shell fixes
 *
 * Two things only showed up once this component started carrying the Website's flash messages.
 */

/* 1. The title was `white-space: nowrap` with an ellipsis, which suits the dashboard's realtime
 *    notifications — a short subject line above a body. A flash message has no separate body: the whole
 *    sentence IS the title, so truncating it to one line threw the message away and left
 *    "This plan is not available to order onl…". It now wraps to at most two lines, which keeps the
 *    toast compact without losing what it says. The body below still clamps to two lines of its own. */
.notif-toast__title {
    display: -webkit-box;
    overflow: hidden;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    white-space: normal;
    text-overflow: clip;
}

/* 2. The Website has a sticky full-width header; a toast pinned 1rem from the top landed on top of it,
 *    covering the language switcher. Only the Website shell needs the offset — the dashboard's own
 *    chrome sits elsewhere — so this is scoped rather than changed for both. */
.website-shell #notif-toast-container {
    top: 5.25rem;
}

@media (max-width: 575.98px) {
    .website-shell #notif-toast-container {
        top: 4.5rem;
    }
}

/* 3. The dashboard needed the same treatment as the Website, for the same reason and for a worse
 *    consequence. Its .app-header is sticky and occupies the top-right corner the toast is pinned to,
 *    so a toast covered the theme toggle and the notification bell. Because warning and error toasts
 *    deliberately persist until dismissed, they blocked those controls indefinitely rather than for a
 *    few seconds - measured here as container top 8px against a header bottom of 85px.
 *    data-nav-layout is written only by the dashboard layout (_MainLayout.cshtml:70), so this offset
 *    cannot reach the Website shell, which carries its own above.
 *
 *    One value covers both widths on purpose: the dashboard header measures 85px at 1440px and at
 *    375px alike, and this selector already outranks the generic phone rule above on specificity, so a
 *    separate mobile offset would only be a second number to keep in sync. The phone rule's
 *    inset-inline/width parts still apply. */
[data-nav-layout] #notif-toast-container {
    top: 5.5rem;
}

/* ---------------------------------------------------------------------------- dashboard dark mode
 *
 * Everything above already follows the theme, because the surface, border and text colours resolve to
 * the dashboard's own theme-flipped tokens. Three things cannot be expressed that way and are set here.
 *
 * The selector is the attribute the dashboard layout writes on <html> (_MainLayout.cshtml:71) and that
 * dashboard-theme.js rewrites live on toggle, so a toast raised after a theme switch is correct without
 * a reload. The Website shell never sets the attribute, so none of this reaches it.
 */
[data-theme-mode="dark"] .notif-toast {
    /* 1. Severity glyphs. The light values are deep shades picked to carry on white; on the dark
     *    surface they read as near-black smudges. These are the same four hues lifted in luminance,
     *    not different colours, so severity still maps to the palette the rest of the shell uses. */
    --toast-icon-info: #93B4FD;
    --toast-icon-success: #6EE7B7;
    --toast-icon-warning: #FCD34D;
    --toast-icon-error: #FCA5A5;

    /* 2. A slate-tinted shadow is invisible against a dark ground; elevation has to come from real
     *    black, and a touch more of it, or the toast looks pasted onto the page. */
    --toast-shadow: rgba(0, 0, 0, 0.55);
    --toast-shadow-soft: rgba(0, 0, 0, 0.35);

    /* 3. The action link. rgb(37,99,235) is the un-flipped brand blue and fails contrast on the dark
     *    surface, so the link gets the lighter tint the dark palette uses elsewhere. */
    --toast-accent: #93B4FD;
}

/* Bootstrap's .btn-close is a dark SVG data-URI, which disappears on the dark surface. Bootstrap 5.3
 * exposes .btn-close-white for this, but the markup is produced by shared/js/custom/toast.js for both
 * shells, so the class is not conditionally added; inverting the existing glyph keeps the component's
 * markup identical everywhere. */
[data-theme-mode="dark"] .notif-toast .notif-toast__close {
    filter: invert(1) grayscale(100%) brightness(200%);
}
