diff --git a/scripts/system/notifications.js b/scripts/system/notifications.js
index 26d9a603f3..98198c8d3f 100644
--- a/scripts/system/notifications.js
+++ b/scripts/system/notifications.js
@@ -1,444 +1,272 @@
 "use strict";
-/*jslint vars:true, plusplus:true, forin:true*/
-/*global Script, Settings, Window, Controller, Overlays, SoundArray, MyAvatar, Tablet, Camera, HMD, Menu, Quat, Vec3*/
 //
 //  notifications.js
-//  Version 0.801
 //
-//  Created by Adrian McCarlie October 8th, 2014
+//  Created by Adrian McCarlie on October 8th, 2014
 //  Copyright 2014 High Fidelity, Inc.
 //  Copyright 2022 Overte e.V.
 //
-//  This script demonstrates on-screen overlay type notifications.
+//  Display notifications to the user for some specific events.
 //
 //  Distributed under the Apache License, Version 2.0.
 //  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-//
-//  ############################################################################
-//  This script generates notifications created via a number of ways, such as:
-//  keystroke:
-//
-//  CTRL/s for snapshot.
-//
-//  System generated notifications:
-//  Connection refused.
-//
-//  To add a new System notification type:
-//
-//  1. Set the Event Connector at the bottom of the script.
-//  example:
-//  Audio.mutedChanged.connect(onMuteStateChanged);
-//
-//  2. Create a new function to produce a text string, do not include new line returns.
-//  example:
-//  function onMuteStateChanged() {
-//     var muteState,
-//         muteString;
-//
-//     muteState = Audio.muted ? "muted" : "unmuted";
-//     muteString = "Microphone is now " + muteState;
-//     createNotification(muteString, NotificationType.MUTE_TOGGLE);
-//  }
-//
-//  This new function must call wordWrap(text) if the length of message is longer than 42 chars or unknown.
-//  wordWrap() will format the text to fit the notifications overlay and return it
-//  after that we will send it to createNotification(text).
-//  If the message is 42 chars or less you should bypass wordWrap() and call createNotification() directly.
 
-//  To add a keypress driven notification:
-//
-//  1. Add a key to the keyPressEvent(key).
-//  2. Declare a text string.
-//  3. Call createNotifications(text, NotificationType) parsing the text.
-//  example:
-//  if (key.text === "o") {
-//      if (ctrlIsPressed === true) {
-//          noteString = "Open script";
-//          createNotification(noteString, NotificationType.OPEN_SCRIPT);
-//      }
-//  }
-
-
-(function () { // BEGIN LOCAL_SCOPE
-
-    Script.include("./libraries/soundArray.js");
-
-    var width = 340.0; //width of notification overlay
-    var windowDimensions = Controller.getViewportDimensions(); // get the size of the interface window
-    var overlayLocationX = (windowDimensions.x - (width + 20.0)); // positions window 20px from the right of the interface window
-    var buttonLocationX = overlayLocationX + (width - 28.0);
-    var locationY = 20.0; // position down from top of interface window
-    var topMargin = 13.0;
-    var leftMargin = 10.0;
-    var textColor =  { red: 228, green: 228, blue: 228}; // text color
-    var backColor =  { red: 2, green: 2, blue: 2}; // background color was 38,38,38
-    var backgroundAlpha = 0;
-    var fontSize = 12.0;
-    var PERSIST_TIME_2D = 10.0;  // Time in seconds before notification fades
-    var PERSIST_TIME_3D = 12.0;
-    var persistTime = PERSIST_TIME_2D;
-    var frame = 0;
-    var ctrlIsPressed = false;
-    var ready = true;
-    var NOTIFICATION_MENU_ITEM_POST = " Notifications";
+(function () {
+    Script.include([
+        "create/audioFeedback/audioFeedback.js"
+    ]);
+    
     var NOTIFICATIONS_MESSAGE_CHANNEL = "Hifi-Notifications";
-    var NOTIFICATION_ALPHA = 9.0; // On a scale of 10.
-
-    var NotificationType = {
-        UNKNOWN: 0,
-        SNAPSHOT: 1,
-        CONNECTION_REFUSED: 2,
-        EDIT_ERROR: 3,
-        TABLET: 4,
-        CONNECTION: 5,
-        WALLET: 6,
-        properties: [
-            { text: "Snapshot" },
-            { text: "Connection Refused" },
-            { text: "Edit error" },
-            { text: "Tablet" },
-            { text: "Connection" },
-            { text: "Wallet" }
-        ],
-        getTypeFromMenuItem: function (menuItemName) {
-            var type;
-            if (menuItemName.substr(menuItemName.length - NOTIFICATION_MENU_ITEM_POST.length) !== NOTIFICATION_MENU_ITEM_POST) {
-                return NotificationType.UNKNOWN;
-            }
-            var preMenuItemName = menuItemName.substr(0, menuItemName.length - NOTIFICATION_MENU_ITEM_POST.length);
-            for (type in this.properties) {
-                if (this.properties[type].text === preMenuItemName) {
-                    return parseInt(type, 10) + 1;
-                }
-            }
-            return NotificationType.UNKNOWN;
-        },
-        getMenuString: function (type) {
-            return this.properties[type - 1].text + NOTIFICATION_MENU_ITEM_POST;
-        }
-    };
-
-    var randomSounds = new SoundArray({ localOnly: true }, true);
-    var numberOfSounds = 2;
-    var soundIndex;
-    for (soundIndex = 1; soundIndex <= numberOfSounds; soundIndex++) {
-        randomSounds.addSound(Script.resolvePath("assets/sounds/notification-general" + soundIndex + ".raw"));
-    }
-
+    var SETTING_ACTIVATION_SNAPSHOT_NOTIFICATIONS = "snapshotNotifications";
+    var NOTIFICATION_LIFE_DURATION = 10000; //10 seconds (in millisecond) before expiration.
+    var FADE_OUT_DURATION = 1000; //1 seconds (in millisecond) to fade out.
+    var NOTIFICATION_ALPHA = 0.9; // a value between: 0.0 (transparent) and 1.0 (fully opaque).
+    var MAX_LINE_LENGTH = 42;
     var notifications = [];
-    var buttons = [];
-    var times = [];
-    var heights = [];
-    var myAlpha = [];
-    var arrays = [];
+    var newEventDetected = false;
+    var isOnHMD = HMD.active;
 
-    var isOnHMD = false,
-        NOTIFICATIONS_3D_DIRECTION = -45.0,  // Degrees from avatar orientation.
-        NOTIFICATIONS_3D_DISTANCE = 1.2,  // Horizontal distance from avatar position.
-        NOTIFICATIONS_3D_ELEVATION = 0.5,  // Height of top middle of top notification relative to avatar eyes.
-        NOTIFICATIONS_3D_YAW = 10.0,  // Degrees relative to notifications direction.
-        NOTIFICATIONS_3D_PITCH = 0.0,  // Degrees from vertical.
-        NOTIFICATION_3D_SCALE = 0.0025,  // Multiplier that converts 2D overlay dimensions to 3D overlay dimensions.
-        NOTIFICATION_3D_BUTTON_WIDTH = 40 * NOTIFICATION_3D_SCALE,  // Need a little more room for button in 3D.
-        overlay3DDetails = [];
+    var textColor =  { "red": 228, "green": 228, "blue": 228};
+    var backColor =  { "red": 2, "green": 2, "blue": 2}; 
 
-    //  push data from above to the 2 dimensional array
-    function createArrays(notice, button, createTime, height, myAlpha) {
-        arrays.push([notice, button, createTime, height, myAlpha]);
-    }
+    //DESKTOP OVERLAY PROPERTIES
+    var overlayWidth = 340.0; //width in pixel of notification overlay in desktop
+    var windowDimensions = Controller.getViewportDimensions(); // get the size of the interface window
+    var overlayLocationX = (windowDimensions.x - (overlayWidth + 20.0)); // positions window 20px from the right of the interface window
+    var overlayLocationY = 20.0; // position down from top of interface window
+    var overlayTopMargin = 13.0;
+    var overlayLeftMargin = 10.0;
+    var overlayFontSize = 12.0;
+    var TEXT_OVERLAY_FONT_SIZE_IN_PIXELS = 18.0; // taken from TextOverlay::textSize
+    var DESKTOP_INTER_SPACE_NOTIFICATION = 5; //5 px
+    
+    //HMD NOTIFICATION PANEL PROPERTIES
+    var HMD_UI_SCALE_FACTOR = 1.0; //This define the size of all the notification system in HMD.
+    var hmdPanelLocalPosition = {"x": 1.2, "y": 2, "z": -1.0};
+    var hmdPanelLocalRotation = Quat.fromVec3Degrees({"x": 0, "y": -15, "z": 0});
+    var mainHMDnotificationContainerID = Uuid.NULL;
+    
+    //HMD LOCAL ENTITY PROPERTIES
+    var entityWidth = 0.8; //in meter
+    var HMD_LINE_HEIGHT = 0.03;
+    var entityTopMargin = 0.02;
+    var entityLeftMargin = 0.02;
+    var HMD_INTER_SPACE_NOTIFICATION = 0.05;
 
-    //  This handles the final dismissal of a notification after fading
-    function dismiss(firstNoteOut, firstButOut, firstOut) {
-        Overlays.deleteOverlay(firstNoteOut);
-        Overlays.deleteOverlay(firstButOut);
-        notifications.splice(firstOut, 1);
-        buttons.splice(firstOut, 1);
-        times.splice(firstOut, 1);
-        heights.splice(firstOut, 1);
-        myAlpha.splice(firstOut, 1);
-        overlay3DDetails.splice(firstOut, 1);
-    }
-
-    function fadeIn(noticeIn, buttonIn) {
-        var q = 0,
-            qFade,
-            pauseTimer = null;
-
-        pauseTimer = Script.setInterval(function () {
-            q += 1;
-            qFade = q / 10.0;
-            Overlays.editOverlay(noticeIn, { "alpha": qFade, "backgroundAlpha": qFade, "textAlpha": qFade });
-            Overlays.editOverlay(buttonIn, { "alpha": qFade });
-            if (q >= NOTIFICATION_ALPHA) {
-                Script.clearInterval(pauseTimer);
-            }
-        }, 10);
-    }
-
-    //  this fades the notification ready for dismissal, and removes it from the arrays
-    function fadeOut(noticeOut, buttonOut, arraysOut) {
-        var r = NOTIFICATION_ALPHA,
-            rFade,
-            pauseTimer = null;
-
-        pauseTimer = Script.setInterval(function () {
-            r -= 1;
-            rFade = Math.max(0.0, r / 10.0);
-            Overlays.editOverlay(noticeOut, { "alpha": rFade, "backgroundAlpha": rFade, "textAlpha": rFade });
-            Overlays.editOverlay(buttonOut, { "alpha": rFade });
-            if (r <= 0) {
-                dismiss(noticeOut, buttonOut, arraysOut);
-                arrays.splice(arraysOut, 1);
-                ready = true;
-                Script.clearInterval(pauseTimer);
-            }
-        }, 20);
-    }
-
-    function calculate3DOverlayPositions(noticeWidth, noticeHeight, y) {
-        // Calculates overlay positions and orientations in avatar coordinates.
-        var noticeY,
-            originOffset,
-            notificationOrientation,
-            notificationPosition,
-            buttonPosition;
-        var sensorScaleFactor = isOnHMD ? MyAvatar.sensorToWorldScale : 1.0;
-        // Notification plane positions
-        noticeY = -sensorScaleFactor * (y * NOTIFICATION_3D_SCALE + 0.5 * noticeHeight);
-        notificationPosition = { x: 0, y: noticeY, z: 0 };
-        buttonPosition = { x: sensorScaleFactor * (noticeWidth - NOTIFICATION_3D_BUTTON_WIDTH), y: noticeY, z: 0.001 };
-
-        // Rotate plane
-        notificationOrientation = Quat.fromPitchYawRollDegrees(NOTIFICATIONS_3D_PITCH, NOTIFICATIONS_3D_DIRECTION + NOTIFICATIONS_3D_YAW, 0);
-        notificationPosition = Vec3.multiplyQbyV(notificationOrientation, notificationPosition);
-        buttonPosition = Vec3.multiplyQbyV(notificationOrientation, buttonPosition);
-
-        // Translate plane
-        originOffset = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, NOTIFICATIONS_3D_DIRECTION, 0), { x: 0, y: 0, z: -NOTIFICATIONS_3D_DISTANCE * sensorScaleFactor});
-        originOffset.y += NOTIFICATIONS_3D_ELEVATION * sensorScaleFactor;
-        notificationPosition = Vec3.sum(originOffset, notificationPosition);
-        buttonPosition = Vec3.sum(originOffset, buttonPosition);
-
-        return {
-            notificationOrientation: notificationOrientation,
-            notificationPosition: notificationPosition,
-            buttonPosition: buttonPosition
-        };
-    }
-
-    //  Pushes data to each array and sets up data for 2nd dimension array
-    //  to handle auxiliary data not carried by the overlay class
-    //  specifically notification "heights", "times" of creation, and .
-    function notify(notice, button, height, imageProperties, image) {
-        var notificationText,
-            noticeWidth,
-            noticeHeight,
-            positions,
-            last;
-        var sensorScaleFactor = isOnHMD ? MyAvatar.sensorToWorldScale : 1.0;
-        if (isOnHMD) {
-            // Calculate 3D values from 2D overlay properties.
-
-            noticeWidth = notice.width * NOTIFICATION_3D_SCALE + NOTIFICATION_3D_BUTTON_WIDTH;
-            noticeHeight = notice.height * NOTIFICATION_3D_SCALE;
-
-            notice.dimensions = { "x": noticeWidth * sensorScaleFactor, "y": noticeHeight * sensorScaleFactor, "z": 0.01 };
-
-            positions = calculate3DOverlayPositions(noticeWidth, noticeHeight, notice.y);   
-            notice.parentID = MyAvatar.sessionUUID;
-            notice.parentJointIndex = -2;
-            notice.isVisibleInSecondaryCamera = false;
-            
-            if (!image) {
-                notice.topMargin = 0.75 * notice.topMargin * NOTIFICATION_3D_SCALE * sensorScaleFactor;
-                notice.leftMargin = 2 * notice.leftMargin * NOTIFICATION_3D_SCALE * sensorScaleFactor;
-                notice.bottomMargin = 0;
-                notice.rightMargin = 0;
-                notice.lineHeight = 10.0 * (fontSize * sensorScaleFactor / 12.0) * NOTIFICATION_3D_SCALE;
-                notice.billboardMode = "none";
-                notice.type = "Text";
-                notice.unlit = true;
-                
-                notificationText = Entities.addEntity(notice, "local");
-                notifications.push(notificationText);
-            } else {
-                notice.type = "Image";
-                notice.emissive = true;
-                
-                notifications.push(Entities.addEntity(notice, "local"));
-            }
-
-            button.url = button.imageURL;
-            button.scale = button.width * NOTIFICATION_3D_SCALE;
-            button.isFacingAvatar = false;
-            button.parentID = MyAvatar.sessionUUID;
-            button.parentJointIndex = -2;
-            button.visible = false;
-            button.type = "Image";
-            button.emissive = true;
-            button.isVisibleInSecondaryCamera = false;
-
-            buttons.push(Entities.addEntity(button, "local"));
-            overlay3DDetails.push({
-                "notificationOrientation": positions.notificationOrientation,
-                "notificationPosition": positions.notificationPosition,
-                "buttonPosition": positions.buttonPosition,
-                "width": noticeWidth * sensorScaleFactor,
-                "height": noticeHeight * sensorScaleFactor
-            });
-
-
-            var defaultEyePosition,
-                avatarOrientation,
-                notificationPosition,
-                buttonPosition,
-                notificationIndex;
-
-            if (isOnHMD && notifications.length > 0) {
-                // Update 3D overlays to maintain positions relative to avatar
-                defaultEyePosition = MyAvatar.getDefaultEyePosition();
-                avatarOrientation = MyAvatar.orientation;
-
-                for (notificationIndex = 0; notificationIndex < notifications.length; notificationIndex += 1) {
-                    notificationPosition = Vec3.sum(defaultEyePosition, Vec3.multiplyQbyV(avatarOrientation, overlay3DDetails[notificationIndex].notificationPosition));
-                    buttonPosition = Vec3.sum(defaultEyePosition, Vec3.multiplyQbyV(avatarOrientation, overlay3DDetails[notificationIndex].buttonPosition));
-
-                    Overlays.editOverlay(notifications[notificationIndex], { "position": notificationPosition, "localRotation": overlay3DDetails[notificationIndex].notificationOrientation, "velocity": Vec3.ZERO });
-
-                    Overlays.editOverlay(buttons[notificationIndex], { "position": buttonPosition, "localRotation": overlay3DDetails[notificationIndex].notificationOrientation });
+    //ACTIONS
+    // handles clicks on notifications overlays to delete notifications. (DESKTOP only)
+    function mousePressEvent(event) {
+        if (!isOnHMD) {
+            var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
+            for (var i = 0; i < notifications.length; i += 1) {
+                if (clickedOverlay === notifications[i].overlayID || clickedOverlay === notifications[i].imageOverlayID) {
+                    deleteSpecificNotification(i);
+                    notifications.splice(i, 1);
+                    newEventDetected = true;
                 }
             }
-
-        } else {
-            if (!image) {
-                notificationText = Overlays.addOverlay("text", notice);
-                notifications.push(notificationText);
-            } else {
-                notifications.push(Overlays.addOverlay("image", notice));
-            }
-            buttons.push(Overlays.addOverlay("image", button));
         }
-        
-        if (isOnHMD) {
-            height = height + 6.0;
-        } else {
-            height = height + 1.0;
-        }
-        heights.push(height);
-        times.push(new Date().getTime() / 1000);
-        last = notifications.length - 1;
-        myAlpha.push(notifications[last].alpha);
-        createArrays(notifications[last], buttons[last], times[last], heights[last], myAlpha[last]);
-        fadeIn(notifications[last], buttons[last]);
+    }
 
-        if (imageProperties && !image) {
-            var imageHeight = notice.width / imageProperties.aspectRatio;
-            if (isOnHMD) {
-                imageHeight = (notice.width + (NOTIFICATION_3D_BUTTON_WIDTH / NOTIFICATION_3D_SCALE)) / imageProperties.aspectRatio;
+    function checkHands() {
+        var myLeftHand = Controller.getPoseValue(Controller.Standard.LeftHand);
+        var myRightHand = Controller.getPoseValue(Controller.Standard.RightHand);
+        var eyesPosition = MyAvatar.getEyePosition();
+        var hipsPosition = MyAvatar.getJointPosition("Hips");
+        var eyesRelativeHeight = eyesPosition.y - hipsPosition.y;
+        if (myLeftHand.translation.y > eyesRelativeHeight || myRightHand.translation.y > eyesRelativeHeight) {
+            audioFeedback.action();
+            deleteAllExistingNotificationsDisplayed();
+            notifications = [];
+        }
+    }
+
+    //DISPLAY
+    function renderNotifications(remainingTime) {
+        var alpha = NOTIFICATION_ALPHA;
+        if (remainingTime < FADE_OUT_DURATION) {
+            alpha = NOTIFICATION_ALPHA * (remainingTime/FADE_OUT_DURATION);
+        }
+        var properties, count, extraline, breaks, height;
+        var breakPoint = MAX_LINE_LENGTH + 1;
+        var level = overlayLocationY;
+        var entityLevel = 0;
+        if (notifications.length > 0) {
+            for (var i = 0; i < notifications.length; i++) {
+                count = (notifications[i].dataText.match(/\n/g) || []).length,
+                extraLine = 0;
+                breaks = 0;
+                if (notifications[i].dataText.length >= breakPoint) {
+                    breaks = count;
+                }                
+                if (isOnHMD) {
+                    //use HMD local entities
+                    var sensorScaleFactor = MyAvatar.sensorToWorldScale * HMD_UI_SCALE_FACTOR;
+                    var lineHeight = HMD_LINE_HEIGHT;
+                    height = lineHeight + (2 * entityTopMargin);
+                    extraLine = breaks * lineHeight;
+                    height = (height + extraLine) * HMD_UI_SCALE_FACTOR;
+                    entityLevel = entityLevel - (height/2);
+                    properties = {
+                        "type": "Text",
+                        "parentID": mainHMDnotificationContainerID,
+                        "localPosition": {"x": 0, "y": entityLevel, "z": 0},
+                        "dimensions": {"x": (entityWidth * HMD_UI_SCALE_FACTOR), "y": height, "z": 0.01},
+                        "isVisibleInSecondaryCamera": false,
+                        "lineHeight": lineHeight * sensorScaleFactor,
+                        "textColor": textColor,
+                        "textAlpha": alpha,
+                        "backgroundColor": backColor,
+                        "backgroundAlpha": alpha,
+                        "leftMargin": entityLeftMargin * sensorScaleFactor,
+                        "topMargin": entityTopMargin * sensorScaleFactor,
+                        "unlit": true,
+                        "renderLayer": "hud"
+                    };
+                    if (notifications[i].entityID === Uuid.NULL){
+                        properties.text =  notifications[i].dataText;
+                        notifications[i].entityID = Entities.addEntity(properties, "local");
+                    } else {
+                        Entities.editEntity(notifications[i].entityID, properties);
+                    }
+                    if (notifications[i].dataImage !== null) {
+                        entityLevel = entityLevel - (height/2);
+                        height = (entityWidth / notifications[i].dataImage.aspectRatio) * HMD_UI_SCALE_FACTOR;
+                        entityLevel = entityLevel - (height/2);
+                        properties = {
+                            "type": "Image",
+                            "parentID": mainHMDnotificationContainerID,
+                            "localPosition": {"x": 0, "y": entityLevel, "z": 0},
+                            "dimensions":  {"x": (entityWidth * HMD_UI_SCALE_FACTOR), "y": height, "z": 0.01},
+                            "isVisibleInSecondaryCamera": false,
+                            "emissive": true,
+                            "visible": true,
+                            "alpha": alpha,
+                            "renderLayer": "hud"
+                        };                        
+                        if (notifications[i].imageEntityID === Uuid.NULL){
+                            properties.imageURL = notifications[i].dataImage.path;
+                            notifications[i].imageEntityID = Entities.addEntity(properties, "local");
+                        } else {
+                            Entities.editEntity(notifications[i].imageEntityID, properties);
+                        }
+                    }
+                    entityLevel = entityLevel - (height/2) - (HMD_INTER_SPACE_NOTIFICATION * HMD_UI_SCALE_FACTOR);
+                } else {
+                    //use Desktop overlays
+                    height = 40.0;
+                    extraLine = breaks * TEXT_OVERLAY_FONT_SIZE_IN_PIXELS;
+                    height = height + extraLine;
+                    properties = {
+                        "x": overlayLocationX,
+                        "y": level,
+                        "width": overlayWidth,
+                        "height": height,
+                        "color": textColor,
+                        "backgroundColor": backColor,
+                        "alpha": alpha,
+                        "topMargin": overlayTopMargin,
+                        "leftMargin": overlayLeftMargin,
+                        "font": {"size": overlayFontSize}
+                    };
+                    if (notifications[i].overlayID === Uuid.NULL){
+                        properties.text =  notifications[i].dataText;
+                        notifications[i].overlayID = Overlays.addOverlay("text", properties);
+                    } else {
+                        Overlays.editOverlay(notifications[i].overlayID, properties);
+                    }
+                    if (notifications[i].dataImage !== null) {
+                        level = level + height;
+                        height = overlayWidth / notifications[i].dataImage.aspectRatio;
+                        properties = {
+                            "x": overlayLocationX,
+                            "y": level,
+                            "width": overlayWidth,
+                            "height": height,
+                            "subImage": { "x": 0, "y": 0 },
+                            "visible": true,
+                            "alpha": alpha
+                        };                        
+                        if (notifications[i].imageOverlayID === Uuid.NULL){
+                            properties.imageURL = notifications[i].dataImage.path;
+                            notifications[i].imageOverlayID = Overlays.addOverlay("image", properties);
+                        } else {
+                            Overlays.editOverlay(notifications[i].imageOverlayID, properties);
+                        }
+                    }
+                    level = level + height + DESKTOP_INTER_SPACE_NOTIFICATION;
+                }
             }
-            notice = {
-                "x": notice.x,
-                "y": notice.y + height,
-                "width": notice.width,
-                "height": imageHeight,
-                "subImage": { "x": 0, "y": 0 },
-                "color": { "red": 255, "green": 255, "blue": 255},
-                "visible": true,
-                "imageURL": imageProperties.path,
-                "alpha": backgroundAlpha
+        }
+    }
+
+    function deleteAllExistingNotificationsDisplayed() {
+        if (notifications.length > 0) {
+            for (var i = 0; i < notifications.length; i++) {
+                deleteSpecificNotification(i);
+            }
+        }
+    }
+    
+    function deleteSpecificNotification(indexNotification) {
+        if (notifications[indexNotification].entityID !== Uuid.NULL){
+            Entities.deleteEntity(notifications[indexNotification].entityID);
+            notifications[indexNotification].entityID = Uuid.NULL;
+        }
+        if (notifications[indexNotification].overlayID !== Uuid.NULL){
+            Overlays.deleteOverlay(notifications[indexNotification].overlayID);
+            notifications[indexNotification].overlayID = Uuid.NULL;
+        }
+        if (notifications[indexNotification].imageEntityID !== Uuid.NULL){
+            Entities.deleteEntity(notifications[indexNotification].imageEntityID);
+            notifications[indexNotification].imageEntityID = Uuid.NULL;
+        }
+        if (notifications[indexNotification].imageOverlayID !== Uuid.NULL){
+            Overlays.deleteOverlay(notifications[indexNotification].imageOverlayID);
+            notifications[indexNotification].imageOverlayID = Uuid.NULL;
+        }
+    }
+    
+    function createMainHMDnotificationContainer() {
+        if (mainHMDnotificationContainerID === Uuid.NULL) {
+            var properties = {
+                "type": "Shape",
+                "shape": "Cube",
+                "visible": false,
+                "dimensions": {"x": 0.1, "y": 0.1, "z":0.1},
+                "parentID": MyAvatar.sessionUUID,
+                "parentJointIndex": -2,
+                "localPosition": hmdPanelLocalPosition,
+                "localRotation": hmdPanelLocalRotation
             };
-            notify(notice, button, imageHeight, imageProperties, true);
+            mainHMDnotificationContainerID = Entities.addEntity(properties, "local");
         }
-
-        return notificationText;
     }
-
-    var CLOSE_NOTIFICATION_ICON = Script.resolvePath("assets/images/close-small-light.svg");
-    var TEXT_OVERLAY_FONT_SIZE_IN_PIXELS = 18.0; // taken from TextOverlay::textSize
-
-    //  This function creates and sizes the overlays
-    function createNotification(text, notificationType, imageProperties) {
-        var count = (text.match(/\n/g) || []).length,
-            breakPoint = 43.0, // length when new line is added
-            extraLine = 0,
-            breaks = 0,
-            height = 40.0,
-            stack = 0,
-            level,
-            noticeProperties,
-            bLevel,
-            buttonProperties,
-            i;
-
-        var sensorScaleFactor = isOnHMD ? MyAvatar.sensorToWorldScale : 1.0;
-        if (text.length >= breakPoint) {
-            breaks = count;
-        }
-        extraLine = breaks * TEXT_OVERLAY_FONT_SIZE_IN_PIXELS;
-        for (i = 0; i < heights.length; i += 1) {
-            stack = stack + heights[i];
+    
+    function deleteMainHMDnotificationContainer() {
+        if (mainHMDnotificationContainerID !== Uuid.NULL) {
+            Entities.deleteEntity(mainHMDnotificationContainerID);
+            mainHMDnotificationContainerID = Uuid.NULL;
         }
+    }    
+    //UTILITY FUNCTIONS
 
-        level = (stack + 20.0);
-        height = height + extraLine;
+    // Trims extra whitespace and breaks into lines of length no more 
+    // than MAX_LINE_LENGTH, breaking at spaces. Trims extra whitespace.
 
-        noticeProperties = {
-            "x": overlayLocationX,
-            "y": level,
-            "width": width,
-            "height": height,
-            "color": textColor,
-            "backgroundColor": backColor,
-            "alpha": backgroundAlpha,
-            "backgroundAlpha": backgroundAlpha,
-            "textAlpha": backgroundAlpha,
-            "topMargin": topMargin,
-            "leftMargin": leftMargin,
-            "font": {"size": fontSize * sensorScaleFactor},
-            "text": text
-        };
-
-        bLevel = level + 12.0;
-        buttonProperties = {
-            "x": buttonLocationX,
-            "y": bLevel,
-            "width": 10.0,
-            "height": 10.0,
-            "subImage": { "x": 0, "y": 0, "width": 10, "height": 10 },
-            "imageURL": CLOSE_NOTIFICATION_ICON,
-            "color": { "red": 255, "green": 255, "blue": 255},
-            "visible": true,
-            "alpha": backgroundAlpha
-        };
-
-        return notify(noticeProperties, buttonProperties, height, imageProperties);
-    }
-
-    function deleteNotification(index) {
-        var notificationTextID = notifications[index];
-        Overlays.deleteOverlay(notificationTextID);
-        Overlays.deleteOverlay(buttons[index]);
-        notifications.splice(index, 1);
-        buttons.splice(index, 1);
-        times.splice(index, 1);
-        heights.splice(index, 1);
-        myAlpha.splice(index, 1);
-        overlay3DDetails.splice(index, 1);
-        arrays.splice(index, 1);
-    }
-
-
-    // Trims extra whitespace and breaks into lines of length no more than MAX_LENGTH, breaking at spaces. Trims extra whitespace.
-    var MAX_LENGTH = 42;
     function wordWrap(string) {
         var finishedLines = [], currentLine = '';
         string.split(/\s/).forEach(function (word) {
             var tail = currentLine ? ' ' + word : word;
-            if ((currentLine.length + tail.length) <= MAX_LENGTH) {
+            if ((currentLine.length + tail.length) <= MAX_LINE_LENGTH) {
                 currentLine += tail;
             } else {
                 finishedLines.push(currentLine);
                 currentLine = word;
+                if (currentLine.length > MAX_LINE_LENGTH) {
+                    finishedLines.push(currentLine.substring(0,MAX_LINE_LENGTH));
+                    currentLine = currentLine.substring(MAX_LINE_LENGTH, currentLine.length);
+                }
             }
         });
         if (currentLine) {
@@ -447,200 +275,146 @@
         return finishedLines.join('\n');
     }
 
-    function updateNotificationsTexts() {
-        var sensorScaleFactor = isOnHMD ? MyAvatar.sensorToWorldScale : 1.0;
-        for (var i = 0; i < notifications.length; i++) {
-            var overlayType = Overlays.getOverlayType(notifications[i]);
-            if (overlayType === "text3d") {
-                var props = {
-                    "lineHeight": 10.0 * (fontSize * sensorScaleFactor / 12.0) * NOTIFICATION_3D_SCALE
-                };
-                Overlays.editOverlay(notifications[i], props);
-            }
+    //NOTIFICATION STACK MANAGEMENT
+    
+    function addNotification (dataText, dataImage) {
+        var d = new Date();
+        var notification = {
+            "dataText": dataText,
+            "dataImage": dataImage,
+            "timestamp": d.getTime(),
+            "entityID": Uuid.NULL,
+            "imageEntityID": Uuid.NULL,
+            "overlayID": Uuid.NULL,
+            "imageOverlayID": Uuid.NULL
+        };
+        notifications.push(notification);
+        newEventDetected = true;
+        
+        if (notifications.length === 1) {
+            createMainHMDnotificationContainer();
+            Script.update.connect(update);
+            Controller.mousePressEvent.connect(mousePressEvent);
         }
+        
     }
 
-    function update() {
-        updateNotificationsTexts();
-        var noticeOut,
-            buttonOut,
-            arraysOut,
-            positions,
-            i,
-            j,
-            k;
-
-        if (isOnHMD !== HMD.active) {
-            while (arrays.length > 0) {
-                deleteNotification(0);
-            }
-            isOnHMD = !isOnHMD;
-            persistTime = isOnHMD ? PERSIST_TIME_3D : PERSIST_TIME_2D;
-            return;
-        }
-
-        frame += 1;
-        if ((frame % 60.0) === 0) { // only update once a second
-            locationY = 20.0;
-            for (i = 0; i < arrays.length; i += 1) { //repositions overlays as others fade
-                if (isOnHMD) {
-                    positions = calculate3DOverlayPositions(overlay3DDetails[i].width, overlay3DDetails[i].height, locationY);
-                    overlay3DDetails[i].notificationOrientation = positions.notificationOrientation;
-                    overlay3DDetails[i].notificationPosition = positions.notificationPosition;
-                    overlay3DDetails[i].buttonPosition = positions.buttonPosition;
-                    //We don't reposition in HMD, because it is very annoying.
+    function update(deltaTime) {
+        if (notifications.length === 0 && !newEventDetected) {
+            Script.update.disconnect(update);
+            Controller.mousePressEvent.disconnect(mousePressEvent);
+            deleteMainHMDnotificationContainer();
+        } else {
+            if (isOnHMD !== HMD.active) {
+                deleteAllExistingNotificationsDisplayed();
+                isOnHMD = HMD.active;
+            }            
+            var d = new Date();
+            var immediatly = d.getTime();
+            var mostRecentRemainingTime = NOTIFICATION_LIFE_DURATION;
+            var expirationDetected = false;
+            for (var i = 0; i < notifications.length; i++) {
+                if ((immediatly - notifications[i].timestamp) > NOTIFICATION_LIFE_DURATION){
+                    deleteSpecificNotification(i);
+                    notifications.splice(i, 1);
+                    expirationDetected = true;
                 } else {
-                    Overlays.editOverlay(notifications[i], { x: overlayLocationX, y: locationY });
-                    Overlays.editOverlay(buttons[i], { x: buttonLocationX, y: locationY + 12.0 });
-                }
-                locationY = locationY + arrays[i][3];
-            }
-        }
-
-        //  This checks the age of the notification and prepares to fade it after 9.0 seconds (var persistTime - 1)
-        for (i = 0; i < arrays.length; i += 1) {
-            if (ready) {
-                j = arrays[i][2];
-                k = j + persistTime;
-                if (k < (new Date().getTime() / 1000)) {
-                    ready = false;
-                    noticeOut = arrays[i][0];
-                    buttonOut = arrays[i][1];
-                    arraysOut = i;
-                    fadeOut(noticeOut, buttonOut, arraysOut);
+                    mostRecentRemainingTime = NOTIFICATION_LIFE_DURATION - (immediatly - notifications[i].timestamp);
                 }
             }
-        }
-    }
-
-    var STARTUP_TIMEOUT = 500,  // ms
-        startingUp = true,
-        startupTimer = null;
-
-    function finishStartup() {
-        startingUp = false;
-        Script.clearTimeout(startupTimer);
-    }
-
-    function isStartingUp() {
-        // Is starting up until get no checks that it is starting up for STARTUP_TIMEOUT
-        if (startingUp) {
-            if (startupTimer) {
-                Script.clearTimeout(startupTimer);
+            if (newEventDetected || expirationDetected || mostRecentRemainingTime < FADE_OUT_DURATION) {
+                renderNotifications(mostRecentRemainingTime);
+                newEventDetected = false;
             }
-            startupTimer = Script.setTimeout(finishStartup, STARTUP_TIMEOUT);
         }
-        return startingUp;
+        if (isOnHMD) {
+            checkHands();
+        }
     }
 
+    //NOTIFICATION EVENTS FUNCTIONS
     function onDomainConnectionRefused(reason, reasonCode) {
         // the "login error" reason means that the DS couldn't decrypt the username signature
         // since this eventually resolves itself for good actors we don't need to show a notification for it
-        var LOGIN_ERROR_REASON_CODE = 2;
-
-        if (reasonCode != LOGIN_ERROR_REASON_CODE) {
-            createNotification("Connection refused: " + reason, NotificationType.CONNECTION_REFUSED);
+        var LoginErrorMetaverse_REASON_CODE = 2;
+        if (reasonCode !== LoginErrorMetaverse_REASON_CODE) {
+            addNotification("Connection refused: " + reason, null);
         }
     }
 
     function onEditError(msg) {
-        createNotification(wordWrap(msg), NotificationType.EDIT_ERROR);
+        addNotification(wordWrap(msg), null);
     }
 
     function onNotify(msg) {
-        createNotification(wordWrap(msg), NotificationType.UNKNOWN); // Needs a generic notification system for user feedback, thus using this
+         // Generic notification system for user feedback, thus using this
+        addNotification(wordWrap(msg), null);
     }
 
     function onMessageReceived(channel, message) {
         if (channel === NOTIFICATIONS_MESSAGE_CHANNEL) {
             message = JSON.parse(message);
-            createNotification(wordWrap(message.message), message.notificationType);
+            addNotification(wordWrap(message.message), null);
         }
     }
 
     function onSnapshotTaken(pathStillSnapshot, notify) {
-        if (Settings.getValue("snapshotNotifications", true)) {
+        if (Settings.getValue(SETTING_ACTIVATION_SNAPSHOT_NOTIFICATIONS, true)) {
             if (notify) {
                 var imageProperties = {
-                    path: "file:///" + pathStillSnapshot,
-                    aspectRatio: Window.innerWidth / Window.innerHeight
+                    "path": "file:///" + pathStillSnapshot,
+                    "aspectRatio": Window.innerWidth / Window.innerHeight
                 };
-                createNotification(wordWrap("Snapshot saved to " + pathStillSnapshot), NotificationType.SNAPSHOT, imageProperties);
+                addNotification(wordWrap("Snapshot saved to " + pathStillSnapshot), imageProperties);
             }
         }
     }
 
     function tabletNotification() {
-        createNotification("Tablet needs your attention", NotificationType.TABLET);
+        addNotification("Tablet needs your attention", null);
     }
 
     function processingGif() {
-        if (Settings.getValue("snapshotNotifications", true)) {
-            createNotification("Processing GIF snapshot...", NotificationType.SNAPSHOT);
+        if (Settings.getValue(SETTING_ACTIVATION_SNAPSHOT_NOTIFICATIONS, true)) {
+            addNotification("Processing GIF snapshot...", null);
         }
     }
 
-    function walletNotSetup() {
-        createNotification("Your wallet isn't activated yet. Open the WALLET app.", NotificationType.WALLET);
-    }
-
     function connectionAdded(connectionName) {
-        createNotification(connectionName, NotificationType.CONNECTION);
+        addNotification(connectionName, null);
     }
 
     function connectionError(error) {
-        createNotification(wordWrap("Error trying to make connection: " + error), NotificationType.CONNECTION);
+        addNotification(wordWrap("Error trying to make connection: " + error), null);
     }
 
-    //  handles mouse clicks on buttons
-    function mousePressEvent(event) {
-        var pickRay,
-            clickedOverlay,
-            i;
-
-        if (isOnHMD) {
-            pickRay = Camera.computePickRay(event.x, event.y);
-            clickedOverlay = Overlays.findRayIntersection(pickRay).overlayID;
-        } else {
-            clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
-        }
-
-        for (i = 0; i < buttons.length; i += 1) {
-            if (clickedOverlay === buttons[i]) {
-                deleteNotification(i);
-            }
-        }
-    }
-
-    //  Control key remains active only while key is held down
-    function keyReleaseEvent(key) {
-        if (key.key === 16777249) {
-            ctrlIsPressed = false;
-        }
-    }
-
-    //  Triggers notification on specific key driven events
-    function keyPressEvent(key) {
-        if (key.key === 16777249) {
-            ctrlIsPressed = true;
-        }
-    }
-
-    //  When our script shuts down, we should clean up all of our overlays
+    //STARTING AND ENDING
+    
     function scriptEnding() {
-        var notificationIndex;
-        for (notificationIndex = 0; notificationIndex < notifications.length; notificationIndex++) {
-            Overlays.deleteOverlay(notifications[notificationIndex]);
-            Overlays.deleteOverlay(buttons[notificationIndex]);
+        //cleanup
+        deleteAllExistingNotificationsDisplayed();
+        
+        //disconnecting
+        if (notifications.length > 0) {
+            Script.update.disconnect(update);
+            Controller.mousePressEvent.disconnect(mousePressEvent);
         }
+        Script.scriptEnding.disconnect(scriptEnding);        
         Messages.unsubscribe(NOTIFICATIONS_MESSAGE_CHANNEL);
+        Window.domainConnectionRefused.disconnect(onDomainConnectionRefused);
+        Window.stillSnapshotTaken.disconnect(onSnapshotTaken);
+        Window.snapshot360Taken.disconnect(onSnapshotTaken);
+        Window.processingGifStarted.disconnect(processingGif);
+        Window.connectionAdded.disconnect(connectionAdded);
+        Window.connectionError.disconnect(connectionError);
+        Window.announcement.disconnect(onNotify);
+        Tablet.tabletNotification.disconnect(tabletNotification);
+        Messages.messageReceived.disconnect(onMessageReceived);
     }
 
-    Controller.keyPressEvent.connect(keyPressEvent);
-    Controller.mousePressEvent.connect(mousePressEvent);
-    Controller.keyReleaseEvent.connect(keyReleaseEvent);
-    Script.update.connect(update);
     Script.scriptEnding.connect(scriptEnding);
+    
+    //EVENTS TO NOTIFY
     Window.domainConnectionRefused.connect(onDomainConnectionRefused);
     Window.stillSnapshotTaken.connect(onSnapshotTaken);
     Window.snapshot360Taken.connect(onSnapshotTaken);
@@ -651,8 +425,6 @@
     Window.notifyEditError = onEditError;
     Window.notify = onNotify;
     Tablet.tabletNotification.connect(tabletNotification);
-    WalletScriptingInterface.walletNotSetup.connect(walletNotSetup);
-
     Messages.subscribe(NOTIFICATIONS_MESSAGE_CHANNEL);
     Messages.messageReceived.connect(onMessageReceived);
-}()); // END LOCAL_SCOPE
+}());