Outlook addin with office.js giving Host error with code 5000 for item.sendAsync()

I’m trying to send an email using the Outlook’s office.js API’s item.sendAsync() method which triggers on custom send button added on taskpane from a task pane add-in. However, I’m getting a Host Error with the following response:

{
  "code": 5000,
  "message": "The operation is not supported.",
  "name": "Host Error"
}

Here is the code snippet I am using

item.sendAsync((result) => {
    if (result.status === Office.AsyncResultStatus.Succeeded) {
        document.getElementById('review-message').innerHTML = 
            '<p class="ms-font-xs" style="color: green;">✅ Email sent successfully via sendAsync!</p>';
        
        // Close task pane after short delay
        setTimeout(() => {
            if (window.close) {
                window.close();
            }
        }, 2000);
    } else {
        console.error('sendAsync failed:', result.error);
        const error = result.error;
    }
});

I am using it on Outlook for Mac (version 16.102)
Also I have added below permission in mainfest.xml

  <Permissions>ReadWriteMailbox</Permissions>

I want to acheive below functionality in my addIn

  1. Display email data on taskpane also having custom send button
  2. send from custom send button available in taskpane (so above code snippet is triggered on button click)

How to trigger an event at a specific time (10 minutes later) without setTimeout, Redis, or cron?

I have an API where the status of a user changes.
After exactly 10 minutes of the status change, I need to send an email to that user.

Constraints:

I cannot use setTimeout or setInterval (not reliable, won’t survive server restarts).

I don’t want to use Redis-based schedulers (like Bull, Agenda, etc.).

I don’t want to use cron jobs.

The event must fire only once (no duplicate sends).

I want to keep server load minimal.

Example flow:

User’s status is updated at 12:00.

At 12:10, system should automatically send them an email.

What are the best alternatives for this scenario?

Should I handle this inside the database (delayed execution, scheduled events)?

Or is there a pattern for “delayed single execution” without timers/cron/Redis?

I’m using Node.js (Sequelize + MySQL) but open to general solutions.

What I tried:

First, I tried using setTimeout in Node.js to delay the email send by 10 minutes.

setTimeout(() => sendEmail(userId), 10 * 60 * 1000);

But this fails if the server restarts or scales horizontally (timers are lost).

Then I looked into node-cron and Redis-based schedulers like Bull/Agenda.
These work, but I want to avoid running extra schedulers/Redis to reduce server load and complexity

When setting pattern property from a string in JavaScript, how to preserve the backslashes?

Related to Properly simulate “pattern” attribute with javascript:
How do I set an input pattern using JavaScript?

when I try element.pattern = 'aS' (as a trivial example), then the pattern ends up in aS (with the backslash being removed).
The same happens with

element.pattern = `aS`

Of course I could double the backslash, but I’d like to create the javascript using a string constant that is used in CGI’s textfield({-pattern => PATTERN}).

A bit like this:

#...perl part to create initial HTML element...
textfield(-pattern => PERL_PATTERN, ...);

#...creating JavaScript to add or remove pattern dynamically
element = document.getElementById(...);
if (...)
    element.pattern = `${PERL_PATTERN}`;
else
    element.removeAttribute('pattern');

I’d like to avoid something ugly as

use constant PERL_PATTERN => 'aS';
use constant JAVASCRIPT_PATTERN => PERL_PATTERN =~ s/\/\\/gr;

to duplicate the pattern, but with backslashes doubled.
Is there a way to keep the backslash in JavaScript?

Web animation using gsap

I want to recreate the svg animation using gsap as shown here:

[Before]
(https://i.sstatic.net/7oXflNxe.png)

on hover

you can check out orginal animation on their official website : https://www.rejouice.com/ below there is marque container you can pan left or right till you see the clock card

Can anyone tell me exactly how to create this animation using gsap I am pretty confused right now.

I dont know how to animate svg components just want to learn it

Turning certain google ad keywords on/off every hour

I am trying to write a google ads script where for two specific keywords, I turn them both ON and then both OFF in alternating hours for six weeks in a specific country. All users should be able to see these ads when the keywords are on, and no users should be able to see them when they are off. So the rhythm should be:

Monday
00:00 – 00:59 Keywords ON
01:00 – 01:59 Keywords OFF
02:00 – 02:59 Keywords ON

Tuesday
00:00 – 00:59 Keywords OFF
01:00 – 01:59 Keywords ON
02:00 – 02:59 Keywords OFF

And so on. If this routine is followed, Monday on week 2 should start with keywords OFF from 00:00 – 00:59 and so on.

I only have some javascript experience and am totally new to google ads specifically, so I’m a bit afraid of just implementing my script without prior consulting someone else. It also feels needlessly complicated as of right now. Here’s what I have so far:

function main() {
  var account = AdsApp.currentAccount();
  var tz = account.getTimeZone();

  // only run for austria accounts
  if (tz !== "Europe/Vienna") {
    Logger.log("Not Austria (" + tz + "), exiting.");
    return;
  }

  // define start date
  var startDate = new Date(2025, 0, 1); // Example: Jan 1, 2025
  var today = new Date();
  
  // get "today" in account time zone
  var todayStr = Utilities.formatDate(today, tz, "yyyy-MM-dd");
  var todayLocal = new Date(todayStr); // midnight local

  // days since start
  var msPerDay = 1000 * 60 * 60 * 24;
  var daysSinceStart = Math.floor((todayLocal - startDate) / msPerDay) + 1;

  // odd days start ON, even days start OFF
  var startingOn = (daysSinceStart % 2 === 1);

  // current hour in AT
  var hour = parseInt(Utilities.formatDate(today, tz, "H"), 10);

  // flip every hour
  var isOn = (hour % 2 === 0) ? startingOn : !startingOn;

  Logger.log("Day " + daysSinceStart + " (startingOn=" + startingOn + 
             "), hour " + hour + " → " + (isOn ? "ON" : "OFF"));

  // select keywords by label
  var selector = AdsApp.keywords()
    .withCondition("LabelNames CONTAINS 'EXPLabel'");

  var keywords = selector.get();
  while (keywords.hasNext()) {
    var kw = keywords.next();
    if (isOn && kw.isPaused()) {
      kw.enable();
      Logger.log("Enabled: " + kw.getText());
    } else if (!isOn && !kw.isPaused()) {
      kw.pause();
      Logger.log("Paused: " + kw.getText());
    }
  }
}

Is it possible to get warnings with event listeners? [closed]

I’ve implemented a temporary debug dialog for a web page which displays any error messages using an event listener:

window.addEventListener("error", function (event) {
        $('#debugDialogModalBody').append('<h5>' + event.error + '</h5>');
        $('#debugDialogModalBody').append('<p>' + event.error.stack.replace(/n/g, '<br/>') + '</p>');
});

I am now trying to catch any warning messages to append to the dialog, but it appears that there are no event types which correspond to warnings. Is it possible to get any warnings through event listeners, or do I need to find these using any other method?

I am converting a XYFlow component from JavaScript to typescript but getting a type error

I am trying to add a context menu component to my React flow app so when you right click on a node a context menu shows up next to it. I am using React Flow and have been trying to convert the
example they give in JavaScript to typescript.

the context component works with no errors, but after I add this logic for positioning the menu, I am getting this error message Type 'void' is not assignable to type 'string | number | undefined'. The expected type comes from this index signature.

this is my App.tsx

import { ReactFlow, type Node,  useNodesState, addEdge, useEdgesState,  type Edge } from '@xyflow/react';
import {Controls, Background, BackgroundVariant} from '@xyflow/react'
import ContextMenu, { type Menu } from './ContextMenu';
import React from 'react'
import { useCallback, useRef, useState} from 'react';
import ExtendableNode from './extendable-node'


 const nodeTypes = {
  extendableNode: ExtendableNode 

};
 
const initialNodes: Node[] = [
  {
    id: '1',
    position: {x: 10, y: 10},
    data: {label: "default label"
    },
    type: 'extendableNode',

  }
  
];
 
const initialEdges: Edge[] = []
//const NewNodeId = () => `randomnode_${new Date()}`


function Flow() {

  const [nodes, setNodes , onNodesChange] = useNodesState(initialNodes);
  const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
  const [menu,  setMenu] = useState<Menu | null>(null);
  const ref = useRef<HTMLDivElement | null>(null);



  const onNodeContextMenu = useCallback(
    (event: React.MouseEvent, node: { id: string }) => {
      // Prevent native context menu from showing
      event.preventDefault();

      // Calculate position of the context menu so it doesn't get rendered off screen

      const pane = ref.current?.getBoundingClientRect();
      if (pane) {
        setMenu({
          id: node.id,
          top: event.clientY < pane.height - 200 ? event.clientY : false,
          left: event.clientX < pane.width - 200 ? event.clientX : false,
          right: event.clientX >= pane.width - 200 ? pane.width - event.clientX : false,
          bottom: event.clientY >= pane.height - 200 ? pane.height - event.clientY : false,
        });
      }
    },
    [setMenu],
  );

  // Close the context menu if it's open whenever the window is clicked.
  const onPaneClick = useCallback(() => setMenu(null), [setMenu]);

  return (
    <div className="h-screen w-screen p-8 bg-gray-50 rounded-xl">
      <ReactFlow
        nodes={nodes}
        nodeTypes={nodeTypes}
        onNodesChange={onNodesChange}
       onPaneClick={onPaneClick}
       onNodeContextMenu={onNodeContextMenu}
  
        fitView>
           {menu && <ContextMenu onClick={onPaneClick} {...menu} />}
        <Background color="#ccc" variant={BackgroundVariant.Cross} />
       
      
        <Controls/>
        </ReactFlow>
      
    
      
    </div>
  );
}
export function App() {
  return <Flow />;
}


This is the interface


import  {type FC, useCallback } from 'react';
import { useReactFlow, type Node } from '@xyflow/react';


interface ContextMenuProps  {
    id: string;
    top: number;
    left: number;
    right: number;
    bottom: number;
    [key: string]:  string | number | undefined ;

}


const ContextMenu: FC<ContextMenuProps> =  ({
        id,
        top,
        left,
        right,
        bottom,
        ...props

}) =>

{
  const { getNode, setNodes, addNodes, setEdges } = useReactFlow();
  const duplicateNode = useCallback(() => {
    const node: Node | undefined  = getNode(id)!;
    if(node) {
    const position = {
      x: node.position.x + 50,
      y: node.position.y + 50,
   
 };
    addNodes({
      ...node,
      selected: false,
      dragging: false,
      id: `${node.id}-copy`,
      position,
    });
    }
  }, [id, getNode, addNodes]);

  const deleteNode = useCallback(() => {
    setNodes((nodes) => nodes.filter((node) => node.id !== id));
    setEdges((edges) => edges.filter((edge) => edge.source !== id));
  }, [id, setNodes, setEdges]);



  return (
    <div
      style={{ top, left, right, bottom }}
      className="context-menu"
      {...props}
    >
      <p style={{ margin: '0.5em' }}>
        <small>node: {id}</small>
      </p>
      <button onClick={duplicateNode}>duplicate</button>
      <button onClick={deleteNode}>delete</button>
    </div>
  );    
}
export default ContextMenu;
export type Menu = {
  id: string;
  top: number | boolean;
  left: number | boolean;
  right: number | boolean;
  bottom: number | boolean;


};

I know typescript has strict expectations around being explicit with return types so I tried to add the onclick to the index signature.

interface ContextMenuProps  {
    id: string;
    top: number;
    left: number;
    right: number;
    bottom: number;
    onClick: ()=> void;
    [key: string]:  string | number | undefined | (()=>void);

}

that then lead to another error type '() => void'.The expected type comes from property 'onClick' which is declared here on type 'IntrinsicAttributes & ContextMenuProps'*

I feel I must have made a glaring mistake that I am missing.

How to add transparent as a shield to prevent click on a video [closed]

Please how can i place a transparent element over a video on the page where it’s embedded. I want the transparent to act as a shield element to intercept the clicks. This prevents the clicks from having an effect on the video. The video is hosted on wistia.

I have zero knowledge on coding, and i am using free Elementor version. please i need help.
Here is the page i want to edit
https://www.bloghoursstudio.com/demo-class/

I found some codes:

.yourDiv {pointer-events: none;} but i dont know how to use it correctly

Have problem in transform from EPSG:3857 to EPSG:3395

const transformCoord = function (_, z, x, y) {
  const zoomStr = "L" + (z - 2).toString().padStart(2, "0");
  const { lng, lat } = this.map.unproject({ x, y });
  const convertLnglat = proj4("EPSG:3857", "EPSG:3395", [lng, lat]);
  const convertedObj = this.map.project(convertLnglat);
  const xStr =
    "C" + Number(Math.round(convertedObj.x)).toString(16).padStart(8, "0");
  const yStr =
    "R" + Number(Math.round(convertedObj.y)).toString(16).padStart(8, "0");
  return `/${zoomStr}/${yStr}/${xStr}`;
};

I’m using maplibre-gl map engine. i can’t get the right tile when switch from EPSG:3857 to EPSG:3395. it looks the the only difference is the y value.

any help is appreciat

i am creating a ecom website using vite react [closed]

i have various product cards and when i add an item to cart , i want the text and icon of add to cart should change to go to cart by checking if that item is in the cart or not,but the function is returning false everytime even the item has been added to the cart, when i am creating a custom cart it is working properly

findProductInCart code below

export const findProductInCart = (cart, id) => {
    const result = cart?.length > 0 && cart.some((product) => product.id === id);

    return result;
};

button text logic

<button onClick={() => onCartClick(product)}>
    {isProductInCart ? (
         <>
             <ShoppingCartCheckoutOutlinedIcon />
             Go to Cart
         </>
     ) : (
         <>
             <ShoppingCartOutlinedIcon />
             Add to Cart
         </>
     )}
</button>

Add to cart Logic

const { cart, cartDispatch } = useCart();
  const navigate = useNavigate();
  const isProductInCart = findProductInCart(cart, product.id);

  const onCartClick = (product) => {
    !isProductInCart
      ? cartDispatch({
          type: "ADD_TO_CART",
          payload: { product },
        })
      : navigate("/cart");
  };

Issue with setThemingColor on groups

We’re working with Forge Viewer v7 and trying to color objects based on their ID. The idea is simple: when we provide an ID, the viewer should color the corresponding objects and sub-objects.

We’ve used viewer.setThemingColor(dbId, colorCode, null, true) hoping it would apply the color recursively:

dbIds.forEach(dbId => {
  let color = new THREE.Color(colour);
  let colorCode = new THREE.Vector4(color.r, color.g, color.b, 1);
  vm.viewer.setThemingColor(dbId, colorCode, null, true);
});

It works fine when the ID matches a geometry node directly (like a mesh), but when the node corresponds to a group, the sub-object inside that group are not colored. It seems the recursive flag doesn’t traverse into the group structure as expected.

Has anyone run into this issue before or found a reliable way to color all sub-objects belonging to an ID node? Any advice or ideas would be greatly appreciated.

fetch API GET error “TypeError: Failed to fetch” – ASP NET Core 8 Razor Pages

Summary:

ASP.NET Core 8 Razor Pages application –
Trying to GET some data from backend using fetch-API. The Request hits the GET Handler. The handler does the work and returns Content("0"). Back in JavaScript I get "TypeError: Failed to fetch". No Response is sent.

Setup:

The Login page is the default page, setup like below in Program.cs:

builder.Services.AddRazorPages(options =>
{
    options.Conventions.AddPageRoute("/Auth/Login", "/");
})

Use Case – Forgot Password

User fills-in the ID and clicks on the Button. Button click is handled in JavaScript. It makes a fetch api GET call to the GET Handler in Login.cshtml.cs file.

JavaScript Code:

try {
 const showResult = async () => {
    const resp = await fetch(`/?handler=ForgotPwd&UserName=${usrname}`, {method:'GET'});
    if (resp.ok) {
        return resp.text();
    }
    else alert(resp.status);
 };
 showResult()
 .then(ret => {
     alert(ret);
 });
}
catch (ex) {
    alert(ex);
}

GET Handler Code:

public async Task<IActionResult> OnGetForgotPwdAsync(string UserName)
{
//Processing...
return Content("0");    //SUCCESS
}

FetchAPIError

As you can see above the Response is blank. Alert shows the TypeError.

If I try any other URL (e.g. /Auth/Login?handler…), I get 404 status code, which means the above URL is correct. Also, the breakpoint on the GET Handler gets hit.

Placeholder(popup) flickering on dragging card in react-grid-layout library

I’m using the react-grid-layout library for drag-and-drop functionality. The requirement is to drag filters and drop them into the available boxes. However, when I drag a filter, the popup of the dragged item (the placeholder) starts flickering.

I observed this issue on Chrome and Edge, but on another laptop, it seems to work fine on Edge.

Initially, I thought the issue was related to component re-rendering, so I suspected the onDrag function might be causing it. However, even after commenting out the function, the issue still persists. It might be related to CSS.

Engine.update not advancing simulation ( having trouble with deltaTime )

so i am trying to run a matter instance in a worker thread.
Im running it with my own loop as shown below. However I’m experiencing trouble with game pacing. Before getting to the explanation here is my code below:

function gameLoop(currentTime) {
  const elapsed = currentTime - state.lastTime;
  state.lastTime = currentTime;
  state.accumulator += elapsed;

  while (state.accumulator >= state.physicsDelta) {
    Engine.update(state.engine, state.physicsDelta);
    state.accumulator -= state.physicsDelta;
  }

  requestAnimationFrame(workerGameLoop);
}

requestAnimationFrame(workerGameLoop)

state.lastTime is initialized to performance.now
and currentTime is handled by requestAnimationFrame.

state.physicsDelta is set to a value of 1000/60 or 16.666 …

If the game is to run at say 30fps then we would expect to see the Engine.update method be called twice to maintain pace.
However after testing, Calling Engine.update isnt really “progressing” the simulation more, calling it 100 times within the same loop doesn’t seem to advance it any further either. Am i missing something?

The reason I have matter on a worker thread is so I can decouple the rendering/physics which will be useful down the line for network games.

this snippet below also runs in the gameLoop function once per animation frame. It pings the main thread with physics data

  // Add all dynamic bodies
  for (const [id, body] of state.dynamicBodies.entries()) {
    bodiesData.push({
      id,
      x: body.position.x,
      y: body.position.y,
      offset: body.offset,
      angle: body.angle,
      velocity: body.velocity,
    });
    updatedIds.add(id);
  }


  if (bodiesData.length > 0) {
    postMessage({ type: "update", payload: bodiesData });
  }

I do have a working html demo you can test where I use the same principle for maintaining physics pace, but only here its running on the main thread.

Feel free to check it out! test the physics pacing by changing your display to a lower frequency, or letting your browser switch to power saving.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Matter.js Top-Down Player Demo</title>
    <style>
      /* Basic styling to center the canvas and remove scrollbars */
      body {
        margin: 0;
        overflow: hidden;
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        background-color: #1a1a1a;
      }
      canvas {
        display: block;
        background-color: #2c2c2c;
      }
      .instructions {
        position: absolute;
        top: 20px;
        left: 50%;
        transform: translateX(-50%);
        color: #fff;
        font-family: Arial, sans-serif;
        font-size: 16px;
        background-color: rgba(0, 0, 0, 0.5);
        padding: 10px 20px;
        border-radius: 10px;
        pointer-events: none; /* Make it non-interactive */
      }
    </style>
  </head>
  <body>
    <div class="instructions">Use WASD to move</div>
    <!-- The Matter.js library is loaded from a CDN -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"></script>

    <script>
      function createRectWithOrigin(
        x,
        y,
        width,
        height,
        origin = { x: 0.5, y: 0.5 },
        options = {}
      ) {
        // Calculate the center offset from the desired origin
        const offsetX = (0.5 - origin.x) * width;
        const offsetY = (0.5 - origin.y) * height;

        // Create the rectangle at the world position plus the offset
        const rect = Bodies.rectangle(
          x + offsetX,
          y + offsetY,
          width,
          height,
          options
        );

        // Shift vertices so the physics center aligns with the origin
        //Body.translate(rect, Vector.create(-offsetX, -offsetY));

        return rect;
      }

      /**
       * Create thin rectangles along a line path to approximate a line for collisions.
       * @param {Vector[]} points - Array of points [{x, y}, ...] defining the line path
       * @param {number} thickness - The thickness of the rectangles
       * @param {object} options - Optional Matter.js body options
       * @param {World} world - Matter.World to add the rectangles to
       * @returns {Body[]} - Array of rectangle bodies created
       */
      function createLineBodies(
        x,
        y,
        points,
        thickness = 2,
        options = {},
        world
      ) {
        const bodies = [];

        for (let i = 0; i < points.length - 1; i++) {
          const p1 = points[i];
          const p2 = points[i + 1];

          // Compute segment vector
          const delta = Vector.sub(p2, p1);
          const length = Vector.magnitude(delta);

          // Compute angle
          const angle = Math.atan2(delta.y, delta.x);
          const wallOptions = {
            ...options,
            isStatic: true,
            friction: 0.01, // Low friction to encourage sliding
            render: {
              fillStyle: "#a1a1a1",
            },
          };
          // Create thin rectangle for this segment
          const rect = Bodies.rectangle(
            x + (p1.x + p2.x) / 2,
            y + (p1.y + p2.y) / 2,
            length,
            thickness,
            Object.assign({}, wallOptions, { angle })
          );

          bodies.push(rect);
          if (world) World.add(world, rect);
        }

        return bodies;
      }

      /**
       * Create a compound Matter.js body from pre-decomposed convex polygons
       * @param {number} x - world x position of the origin
       * @param {number} y - world y position of the origin
       * @param {Array[]} convexParts - array of convex vertex sets, e.g. [[{x,y},...], ...]
       * @param {object} options - Matter.js body options applied to all parts
       * @param {Vector} origin - optional offset vector to shift origin (default {x:0,y:0})
       * @param {World} world - optional Matter.World to add the body to
       * @returns {Body} compound Matter.js body
       */
      function createCompoundBody(
        x,
        y,
        convexParts,
        options = {},
        origin = { x: 0, y: 0 },
        world
      ) {
        const parts = convexParts.map((vertices) => {
          // Create each convex body at origin; options can include render or physics settings
          return Bodies.fromVertices(x, y, [vertices], options, true);
        });

        // Combine all parts into a single compound body
        const compound = Body.create({
          parts: parts,
          ...options,
        });

        // Adjust origin if requested
        if (origin.x !== 0 || origin.y !== 0) {
          Body.translate(compound, { x: -origin.x, y: -origin.y });
        }

        return compound;
      }

      // --- MODULE ALIASES ---
      // These aliases make the code easier to read
      const { Engine, Render, Runner, World, Bodies, Body, Events, Vector } =
        Matter;

      // --- SCENE SETUP ---
      const sceneWidth = 800;
      const sceneHeight = 600;

      // 1. Create the physics engine
      const engine = Engine.create();

      // Disable gravity for a top-down view
      engine.world.gravity.y = 0;

      // 2. Create the renderer
      const render = Render.create({
        element: document.body,
        engine: engine,
        options: {
          width: sceneWidth,
          height: sceneHeight,
          wireframes: false, // Set to false for solid colors
          background: "#333",
          showPerformance: true,
        },
      });

      // 3. Create a runner to step the engine forward

      // --- PLAYER SETUP ---
      const playerRadius = 15;
      const player = Bodies.circle(
        sceneWidth / 2,
        sceneHeight / 2,
        playerRadius,
        {
          label: "player",
          // Physics properties for a "slidey" feel with acceleration
          frictionAir: 0.08, // Increased air friction for a smoother stop
          friction: 0.0, // Very low friction against other bodies
          restitution: 0.0, // A little bounciness
          inertia: Infinity, // Prevents the player from rotating on collision
          render: {
            fillStyle: "#4287f5", // Player color
          },
        }
      );

      // --- CHASER SETUP ---
      const chasers = [];
      const chaserCount = 0;
      const chaserRadius = 14;
      const chaserForce = 0.000511;
      const chaserOptions = {
        label: "chaser",
        frictionAir: 0.07,
        friction: 0.0,
        density: 0.00051,
        restitution: 0.0, // Make them a bit bouncy
        render: {
          fillStyle: "#f55a42", // Chaser color
        },
      };

      for (let i = 0; i < chaserCount; i++) {
        // Spawn them in random locations away from the center
        const x = Math.random() * sceneWidth;
        const y = Math.random() * sceneHeight;
        const chaser = Bodies.circle(x, y, chaserRadius, chaserOptions);
        chasers.push(chaser);
      }

      // --- WALLS & OBSTACLES ---
      // The walls are static, meaning they don't move
      const wallOptions = {
        isStatic: true,
        friction: 0.01, // Low friction to encourage sliding
        render: {
          fillStyle: "#a1a1a1",
        },
      };

      const wallThickness = 50;

      const walls = [
        ...createLineBodies(200, 100, [
          { x: 0, y: 0 },
          { x: 500, y: 5 },
          { x: 500, y: 30 },
          { x: 0, y: 35 },
          { x: 0, y: 200 },
          { x: 100, y: 200 },
          { x: 400, y: 210 },
        ]), // Top
        Bodies.rectangle(sceneWidth / 2, 0, sceneWidth, wallThickness, {
          ...wallOptions,
        }), // Top
        // Outer boundaries
        Bodies.rectangle(
          sceneWidth / 2,
          sceneHeight,
          sceneWidth,
          wallThickness,
          { ...wallOptions }
        ), // Bottom
        Bodies.rectangle(0, sceneHeight / 2, wallThickness, sceneHeight, {
          ...wallOptions,
        }), // Left
        Bodies.rectangle(
          sceneWidth,
          sceneHeight / 2,
          wallThickness,
          sceneHeight,
          { ...wallOptions }
        ), // Right
      ];

      // --- CORNER OBSTACLES ---
      // These are made of two static rectangles to test multi-body collisions
      const cornerSize = 150;
      const cornerThickness = 20;

      // Top-left corner
      const topLeftCorner = [
        createRectWithOrigin(
          100,
          wallThickness / 2,
          10,
          500,
          { x: 0.5, y: 0 },
          {
            ...wallOptions,
            render: {
              fillStyle: "#9217f5",
            },
          }
        ),
      ];

      // Bottom-right corner
      const bottomRightCorner = [
        Bodies.rectangle(
          sceneWidth - cornerSize / 2,
          sceneHeight - 100 - cornerThickness / 2,
          cornerSize,
          cornerThickness,
          { ...wallOptions }
        ),
        Bodies.rectangle(
          sceneWidth - cornerSize + cornerThickness / 2,
          sceneHeight - 100 - cornerSize / 2,
          cornerThickness,
          cornerSize,
          { ...wallOptions }
        ),
      ];

      World.add(engine.world, [
        player,
        ...walls,
        ...topLeftCorner,
        ...bottomRightCorner,
        ...chasers, // Add this line
      ]);

      const keys = {};
      const playerForce = 0.0015; // A small force value for gradual acceleration

      window.addEventListener("keydown", (event) => {
        keys[event.code] = true;
      });

      window.addEventListener("keyup", (event) => {
        keys[event.code] = false;
      });

      // This event runs just before the engine updates each frame
      Events.on(engine, "beforeUpdate", (event) => {
        const force = Vector.create(0, 0);

        if (keys["KeyW"]) {
          force.y -= playerForce;
        }
        if (keys["KeyS"]) {
          force.y += playerForce;
        }
        if (keys["KeyA"]) {
          force.x -= playerForce;
        }
        if (keys["KeyD"]) {
          force.x += playerForce;
        }

        // Apply the calculated force to the player's center
        Body.applyForce(player, player.position, force);

        chasers.forEach((chaser) => {
          // Calculate vector from chaser to player
          const direction = Vector.sub(player.position, chaser.position);

          // Normalize the vector (get a unit vector)
          const normalizedDirection = Vector.normalise(direction);

          // Create a force vector and apply it to the chaser
          const force = Vector.mult(normalizedDirection, chaserForce);
          Body.applyForce(chaser, chaser.position, force);
        });
      });

      const physicsDelta = 1000 / 600;

      let lastTime = performance.now();
      let accumulator = 0;

      // This function will be our main game loop.
      function gameLoop(currentTime) {
        debugger;
        // Calculate how much time has passed since the last frame.
        const elapsed = currentTime - lastTime;
        lastTime = currentTime;

        // Add the elapsed time to an accumulator.
        accumulator += elapsed;

        // Trigger the 'beforeUpdate' event where all your movement logic lives.
        // The default runner does this automatically, so we must do it manually here.
        Events.trigger(engine, "beforeUpdate", {
          timestamp: engine.timing.timestamp,
        });

        // While the accumulator has enough time for one or more physics steps,
        // update the engine. This loop ensures the physics simulation "catches up"
        // if rendering falls behind, maintaining a consistent simulation speed.
        while (accumulator >= physicsDelta) {
          // Update the engine by a fixed amount.
          Engine.update(engine, physicsDelta);
          accumulator -= physicsDelta;
        }

        // Render the current state of the world.
        // This is done once per frame, regardless of how many physics steps were taken.
        Render.world(render);

        // Request the next animation frame from the browser to continue the loop.
        requestAnimationFrame(gameLoop);
      }

      // Start the custom game loop!
      requestAnimationFrame(gameLoop);
    </script>
  </body>
</html>

Low conversion rate after launch — need step-by-step digital marketing fix for new e-commerce clothing store [closed]

I launched a new e-commerce clothing store 3 months ago targeting urban 18–34 customers. Traffic sources are a mix of Google Ads (Search + Shopping), Facebook/Instagram paid campaigns, organic search, and a few influencer posts. Current monthly averages: ~10,000 sessions, 0.7% conversion rate (~70 orders), bounce rate ~65%, average order value ₹1,200, ad spend ₹60,000/month with CPA ≈ ₹857 and ROAS ~1.2. Users add to cart but drop off at checkout or during payment selection. Organic visibility is low for primary product keywords.your text

Launched Search + Shopping campaigns and several FB/IG creatives (carousel + short video).

Set up basic remarketing (FB pixel + Google remarketing tag).

Added 10% first-order discount, free shipping on orders over ₹1,000.

Reduced checkout steps from 5 to 3 and added trust badges.

Created blog posts and social content but with low posting cadence.

Ran one A/B test on CTA text and swapped product thumbnails.

Enabled dynamic product ads for cart abandoners.
Results: traffic increased slightly, CTR on ads is OK, but conversion rate and CPA barely moved.

Conversion rate to rise to 2–3% within 6–8 weeks.

CPA to fall to ₹200–₹350 and ROAS to reach 2.5–3x.

Reduced checkout abandonment and higher repeat purchase rate from remarketing flows.