JS snippets are not working on chromium browsers [migrated]

Getting an error on stackoverflow when running any snippet on chromium browsers (tested on chrome and edge) it is working on firefox though.

(index):1  Refused to display 'https://stacksnippets.net/' in a frame because it set 'X-Frame-Options' to 'sameorigin'.

console.log("stacksnippets.net refused to connect");

PHP critical condition – jtl_paypal_commerce, JTL Shop [closed]

I have an online store based on JTL Shop where this error keeps being sent all the time:

“Info: CRITICAL: PHP critical condition found!
Possbile plugin name: jtl_paypal_commerce
2025-10-01 09:20:22.223860 [NOTICE] [986761] [T0] [80.187.122.9:22877-H3:89E3F183CCE72FEF-12#APVH www.domain.de:443] [STDERR] PHP Fatal error: Uncaught TypeError: JTLLanguageLanguageHelper::mappedGetCountryCodeByCountryName(): Argument #1 ($iso) must be of type string, null given, called in /home/bndifoms/domains/domain/public_html/includes/src/Language/LanguageHelper.php on line 180 and defined in /home/bndifoms/domains/domain/public_html/includes/src/Language/LanguageHelper.php:1105”

Has anyone ever had a similar case before? Or perhaps does anyone know a solution / could help?

Thank you in advance.

How can I get the page number within a group of pages – getAliasNumPage()?

A data set is displayed in table format over multiple pages. Based on grouping by a value of a column, my code splits the output into multiple pages – using $pdf->AddPage() when a new grouping by value is encountered.

The partial data set for a grouping by value can span multiple pages. I need to display on each page, the page number ‘within’ the partal data set. I tried the following methods. However, all of them provide the page number of the 1st page of the partial data set regardless of how many pages the partial data set needs.

  • $pdf->getPage()
  • $pdf->PageNo()
  • $pdf->getNumPages()

The $pdf->getAliasNumPage() method returns the current page number while considering every page of the partial data set. This can be used to calculate the page number within the partial data set $pdf->getAliasNumPage() - $pdf->getSectionStartPage() However, it is an ‘alias’ that do not have a value until the PDF file is generated. I think it is calculated during the execution of the writeHTML() method.

Is there anyway to print the page number and reset it at the start of each section (grouping by value)?

An example follows.

Group by value: AAA
    page: 1
        row-1
        row-2
    end of page and end of section (group by value)

Group by value: BBB
    page: 1
        row-1
        row-2
        ...
        row-14
    end of page

    page: 2         <<-- I have a problem printing this page number
        row-15
        row-16
    end of page and end of section (group by value)

Group by value: CCC
    page: 1
        row-17
        row-18
    end of page and end of section (group by value)

My code:

foreach ($report_data as $index => $data_row) :
    if ($newGroupStarts) : 
        // 1. END PREVIOUS SECTION 
        if ($prevFinID !== null) {
            echo "</tbody></table>";
            $html = ob_get_clean();
            $pdf->writeHTML($html, true, false, true, false, '');
        }
        // 2. START NEW SECTION
        $pdf->AddPage();
        ob_start();
    ?>
        <!-- table header -->
        <table cellpadding="3"> 
            <thead> 
                <tr>
                    <td>Page: <?= $pageNumber // I need help populating this page number to reflect the page number within the section ?></td>
                </tr>
                <tr>
                    <th></th>
                    <th></th>
                    <th></th>
                </tr>
            </thead>
        <tbody>
    <?php endif; ?>

    <!-- DATA ROW -->
    <tr>
        <td></td>
        <td></td>
        <td></td>
    </tr>

<?php // more code ..... ?> 
<?php endforeach; ?>
<?php // more code ..... ?> 

html part of message is ignored when sending an e-mail with attachment using mail() in cron job

I’am sending an e-mail via cron job. The attachment works and is added to the e-mail message. However the html part that is referenced with $body2 does not come through.
The code looks like follows:

$body2 = '<!DOCTYPE html><html>...</html>';
$email = '[email protected]';
$attachment = '/path/to/file/file.txt';
$content = file_get_contents($attachment);

$prefix     = "part_"; // This is an optional prefix
$boundary   = uniqid($prefix, true);

// headers
$headers    = implode("rn", [
'From: [email protected]',
'Reply-To: [email protected]',
'X-Mailer: PHP/' . PHP_VERSION,
'MIME-Version: 1.0',
// boundary parameter required, must be enclosed by quotes
'Content-Type: multipart/mixed; boundary="' . $boundary . '"',
'Content-Transfer-Encoding: BINARY',
'This is a MIME encoded message.' // message for restricted transports
 ]);

// message and attachment
$message    = implode("rn", [ 
"--" . $boundary, // header boundary delimiter line
//'MIME-Version: 1.0',
'Content-Type: text/html; charset="utf8"',
'Content-Transfer-Encoding: 8bit',
//$body2 holds the html part of the e-mail
$body2,
'--' . $boundary, // content boundary delimiter line
'Content-Type: application/octet-stream; name="file.txt"',
'Content-Transfer-Encoding: BINARY',
'Content-Disposition: attachment',
$content,
"--" . $boundary . "--" // closing boundary delimiter line
]);

mail($email, $subject, $message, $headers); // send the email

I’ve spent hours with configuring this. I also tried plain text, with the same result. The text as well as the html won’ t show up in the e-mail message. How do i have to set this up, that the html and the attachment come through? Thanks for any hint.

Revolution slider: infinity loop doesn’t apply for mobile [closed]

For some reason mobile version of revolution slider doesn’t allow infinite scroll/swipe when layout type is set to Slider, not Carousel. Carousel solves problem but then it acts as literally carousel, not animated swipes.

Please take a look: https://willajacuzzi.pl/web/apartamenty

Touch:
Mobile Swipe Enabled
Bock Scroll On
Swipe Dir Vertical
Velocity 75

Mouse:
Wheel Listener: Infinity <- this works perfectly on computers

Why does a 32px component in Figma become 34px with border in CSS?

I designed a component in Figma with a height of 32px including a 1px border.
But when the developer implements it in CSS, the final rendered height shows up as 34px (32px content + 1px top border + 1px bottom border).

Why does this difference happen between Figma and CSS?
And what’s the best way to keep the dimensions consistent between design and development?

  • Change the stroke alignment in Figma (Inside vs Center), or

  • Ask developers to use box-sizing: border-box, or

  • Follow another standard practice?

I want to make sure the design specs and implementation match without confusion.

AWS pre-signed URL needs application/octet-stream to work with AJAX

I have the following C# code to generate pre-signed URLs, and it works (client is an AmazonS3Client object):

        public static string GetPreSignedURL(string filename, string displayFilename)
        {
            GetPreSignedUrlRequest request = new();

            request.Verb = HttpVerb.PUT;
            request.BucketName = BucketName;
            request.Key = filename;
            request.Expires = DateTime.UtcNow.AddHours(24);
            request.ContentType = "application/octet-stream";       //this is needed so we can upload using AJAX

            request.ResponseHeaderOverrides.ContentDisposition = "attachment; filename=" + displayFilename;

            return client.GetPreSignedURL(request);
        }

Now I have Jquery to make the PUT request:

                    $.ajax(
                    {
                        url: response1.preSignedURL,
                        type: 'PUT',
                        data: file,
                        processData: false,
                        contentType: "application/octet-stream",
                        success: function(response)
                        {
                            console.log(JSON.stringify(response));
                        }
                    });

It works fine. However if I remove application/octet-stream from the URL generator and the AJAX code, I get a dreaded SignatureDoesNotMatch error.

It would be nice to be able to remove the Content-Type header as it seems a bit hacky.

JS snippets are not working on chromium browsers

Getting an error on stackoverflow when running any snippet on chromium browsers (tested on chrome and edge) it is working on firefox though.

(index):1  Refused to display 'https://stacksnippets.net/' in a frame because it set 'X-Frame-Options' to 'sameorigin'.

console.log("stacksnippets.net refused to connect");

How to remove weird white section behind ios26 searchbar?

I want the website to be fullscreen on iOS 26 so that there’s no background behind the search bar. I want it to be floating over the website, like the screenshot from appleparts.nl below. The other screenshot below is mine.

I want the search bar to be transparent. I tried to make the color transparent, but it didn’t work.

If I’m on the top of the page, there’s nothing, but if I scroll and the navbar goes away, it shows up.

website where the bar is under the searchbar

image where it isn't -- this is what i want

This is the code of the navbar. I thought it was the theme color, but it isn’t. I don’t know how I get the section behind.

const ruler = document.getElementById('ruler');
const indicator = document.getElementById('indicator');

// Genereer ticks zoals bij een meetlat (elke 10e langer)
const totalTicks = 150;
for (let i = 0; i < totalTicks; i++) {
    const tick = document.createElement('div');
    tick.classList.add('tick');
    if (i % 10 === 0) tick.classList.add('long');
    ruler.appendChild(tick);
}

let activeIndex = 0;

function moveTo(index) {
    const link = links[index];
    const linkRect = link.getBoundingClientRect();
    const parentRect = link.parentElement.getBoundingClientRect();

    const centerOffset = linkRect.left - parentRect.left + linkRect.width / 2;

    ruler.style.transform = `translateX(${centerOffset - ruler.offsetWidth / 2}px)`;
    indicator.style.left = `${centerOffset}px`;

    links.forEach(a => a.classList.remove('active'));
    link.classList.add('active');
}

// Hover functionaliteit
links.forEach((link, index) => {
    link.addEventListener('mouseenter', () => moveTo(index));
    link.addEventListener('click', () => {
        activeIndex = index;
        moveTo(index);
    });
});

document.querySelector('.nav-links').addEventListener('mouseleave', () => {
    moveTo(activeIndex);
});

// Init bij laden van pagina
window.addEventListener('load', () => {
    const path = window.location.pathname;

    links.forEach((link, index) => {
        const href = link.getAttribute('href');
        if (path.endsWith(href)) activeIndex = index;
    });

    moveTo(activeIndex);
});

// Hamburger & mobiel menu
const hamburger = document.getElementById('hamburger');
const mobileMenu = document.getElementById('mobileMenu');
const mobileLinks = mobileMenu.querySelectorAll('a');
const desktopLinks = document.querySelectorAll('.nav-links a');

let scrollPosition = 0;

function openMobileMenu() {
    hamburger.classList.add('opened');
    hamburger.setAttribute('aria-expanded', 'true');
    mobileMenu.classList.add('open');

    // Body scroll blokkeren
    scrollPosition = window.scrollY;
    document.body.style.position = 'fixed';
    document.body.style.top = `-${scrollPosition}px`;
    document.body.style.left = '0';
    document.body.style.right = '0';
    document.body.style.overflow = 'hidden';
}

function closeMobileMenu() {
    hamburger.classList.remove('opened');
    hamburger.setAttribute('aria-expanded', 'false');
    mobileMenu.classList.remove('open');

    // Body scroll weer toestaan
    document.body.style.position = '';
    document.body.style.top = '';
    document.body.style.left = '';
    document.body.style.right = '';
    document.body.style.overflow = '';

    // Scroll terugzetten naar vorige positie
    window.scrollTo(0, scrollPosition);
}

hamburger.addEventListener('click', () => {
    if (hamburger.classList.contains('opened')) {
        closeMobileMenu();
    } else {
        openMobileMenu();
    }
});

// Menu sluiten bij klikken op link in mobiel menu + active class bijhouden
mobileLinks.forEach((link, index) => {
    link.dataset.index = index;
    link.addEventListener('click', () => {
        closeMobileMenu();

        // Active class mobiel
        mobileLinks.forEach(l => l.classList.remove('active'));
        link.classList.add('active');

        // Active class desktop
        desktopLinks.forEach(dl => dl.classList.remove('active'));
        desktopLinks[index].classList.add('active');

        // Update activeIndex
        activeIndex = index;
        moveTo(activeIndex);
    });
});

// Bij resize: sluit mobiel menu bij desktop & zet scroll aan
window.addEventListener('resize', () => {
    if (window.innerWidth > 900) {
        closeMobileMenu();
    }
});
/* =========================
   Navbar
========================= */
.navbar {
    background: #fff;
    position: fixed;
    top: 0;
    width: 100%;
    padding: 10px 0;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
    z-index: 9999;
    transition: transform 0.3s ease-in-out;

}

.navbar .container {
    max-width: 1600px;
    padding: 0 150px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    z-index: 10500;
}

.logo-wrapper {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    z-index: 1;
}

.logo {
    height: 60px;
}

/* --- Nav links --- */
.nav-wrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
    position: relative;
}

.nav-links {
    display: flex;
    gap: 40px;
    position: relative;
    z-index: 2;
}

.nav-links a {
    text-decoration: none;
    font-size: 21px;
    color: #535353;
    position: relative;
    transition: color 0.3s ease, transform 0.3s ease;
    text-shadow: 1px 1px 2px rgba(131, 131, 131, 0.4);
}

.nav-links a:hover,
.nav-links a.active {
    transform: scale(1.05);
    color: var(--button-hover);
    opacity: 0.9;
}

/* --- Hamburger button --- */
.menu {
    background: transparent;
    border: none;
    cursor: pointer;
    display: flex;
    padding: 0;
    position: absolute;
    right: 20px;
    top: 50%;
    transform: translateY(-50%);
    z-index: 9000;
}

.menu svg {
    pointer-events: none;
}

.line {
    fill: none;
    stroke: #535353;
    stroke-width: 6;
    transition:
            stroke-dasharray 600ms cubic-bezier(0.4, 0, 0.2, 1),
            stroke-dashoffset 600ms cubic-bezier(0.4, 0, 0.2, 1);
}

.line1, .line3 {
    stroke-dasharray: 60 207;
}

.line2 {
    stroke-dasharray: 60 60;
}

.opened .line1,
.opened .line3 {
    stroke-dasharray: 90 207;
    stroke-dashoffset: -134;
}

.opened .line2 {
    stroke-dasharray: 1 60;
    stroke-dashoffset: -30;
}

/* --- Ruler styling --- */
.ruler-container {
    position: relative;
    height: 30px;
    width: 100%;
    overflow: hidden;
}

.ruler-container::before,
.ruler-container::after {
    content: "";
    position: absolute;
    top: 0;
    width: 80px;
    height: 100%;
    z-index: 3;
    pointer-events: none;
}

.ruler-container::before {
    left: 0;
    background: linear-gradient(to right, #fff 0%, rgba(255, 255, 255, 0) 100%);
}

.ruler-container::after {
    right: 0;
    background: linear-gradient(to left, #fff 0%, rgba(255, 255, 255, 0) 100%);
}

.ruler {
    display: flex;
    position: absolute;
    height: 100%;
    align-items: flex-end;
    transition: transform 0.5s ease;
}

.tick {
    width: 2px;
    height: 12px;
    background: #5a595966;
    margin-right: 6px;
    box-shadow: 0 1px 3px rgba(90, 89, 89, 0.4);
}

.tick.long {
    height: 18px;
    background: rgba(16, 16, 16, 0.4);
    box-shadow: 0 2px 6px rgba(35, 35, 35, 0.4);
}

.indicator {
    position: absolute;
    top: 5px;
    width: 4px;
    height: 24px;
    background: var(--button-color);
    transition: left 0.5s ease;
    z-index: 8000;
    box-shadow: 0 0 10px rgba(0, 119, 204, 0.5);

    /* FIX: forceer aparte layer zodat kleur niet verdwijnt */
    transform: translateZ(0);
    will-change: left, transform, background;
}

/* --- Mobiel menu --- */
.mobile-menu {
    position: fixed;
    top: 100px;
    left: 0;
    width: 100%;
    height: calc(100vh - 100px);
    background: #fff;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 30px;
    opacity: 0;
    pointer-events: none;
    transform: translateY(100%);
    transition: all 0.4s ease;
    font-size: 24px;
    font-weight: 500;
    box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);

}

.mobile-menu.open {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
    overflow: hidden
}


.mobile-menu a {
    color: var(--button-color);
    text-decoration: none;
    font-size: 30px;
    transition: color 0.3s ease;
}

.mobile-menu a:hover {
    background-color: var(--button-hover);
    transform: translateY(-2px);
    opacity: 0.9;
}

/* --- Navbar responsive --- */
@media (min-width: 1001px) {
    .logo-wrapper {
        position: static;
        transform: none;
    }
    .navbar .container {
        justify-content: space-between;
    }
    .menu {
        display: none;
    }
}

@media (max-width: 1000px) {
    .nav-links {
        display: none;
    }
    .navbar {
        padding: 50px 0;
    }
    .ruler-container {
        display: none;
    }
    .logo {
        z-index: 9000;
    }
    .navbar .container {
        padding: 0 50px;
        justify-content: center;
    }
    .logo-wrapper {
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
        z-index: 1;
    }
}
<!DOCTYPE html>
<html lang="nl">
<head>
    <meta charset="UTF-8" />

    <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
    <title>Bart Fiddelaers Bouwwerken</title>
    <meta name="theme-color" content="transparent">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <link rel="stylesheet" href="assets/index.css" />
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap" rel="stylesheet">
</head>

<body>
<button id="scrollTopBtn" title="Terug naar boven">↑</button>

<header class="navbar">
    <div class="container">
        <!-- Hamburger rechts -->
        <button class="menu" id="hamburger" aria-label="Main Menu" aria-expanded="false">
            <svg width="40" height="40" viewBox="0 0 100 100">
                <path class="line line1"
                      d="M 20,29.000046 H 80.000231 C 80.000231,29.000046 94.498839,28.817352 94.532987,66.711331
            94.543142,77.980673 90.966081,81.670246 85.259173,81.668997
            79.552261,81.667751 75.000211,74.999942 75.000211,74.999942
            L 25.000021,25.000058" />
                <path class="line line2" d="M 20,50 H 80" />
                <path class="line line3"
                      d="M 20,70.999954 H 80.000231 C 80.000231,70.999954 94.498839,71.182648 94.532987,33.288669
            94.543142,22.019327 90.966081,18.329754 85.259173,18.331003
            79.552261,18.332249 75.000211,25.000058 75.000211,25.000058
            L 25.000021,74.999942" />
            </svg>
        </button>

        <!-- Logo gecentreerd -->
        <div class="logo-wrapper">
            <img class="logo" src="assets/logobf.png" alt="Logo">
        </div>

        <!-- Desktop navigatie -->
        <div class="nav-wrapper">
            <nav class="nav-links">
                <a href="index.html" data-index="0" class="active">Home</a>
                <a href="overons.html" data-index="1">Over ons</a>
                <a href="Diensten.html" data-index="2">Diensten</a>
                <a href="realisatie.html" data-index="3">Realisaties</a>
                <a href="#contact" data-index="4">Contact</a>
            </nav>
            <div class="ruler-container">
                <div class="ruler" id="ruler"></div>
                <div class="indicator" id="indicator"></div>
            </div>
        </div>
    </div>


    <!-- Mobiel menu buiten .container -->
    <nav class="mobile-menu" id="mobileMenu">
        <a href="index.html" data-index="0" class="active">Home</a>
        <a href="overons.html" data-index="1">Over ons</a>
        <a href="Diensten.html" data-index="2">Diensten</a>
        <a href="realisatie.html" data-index="3">Realisaties</a>
        <a href="#contact" data-index="4">Contact</a>
    </nav>
</header>
</pre>

I’ve tried setting the theme color to transparent, but that didn’t work.

Why does for…in include inherited properties but Object.keys() does not in JavaScript? [closed]

I was iterating over an object in JavaScript and noticed a difference between for…in and Object.keys().

const parent = { inheritedProp: "hello" };
const child = Object.create(parent);
child.ownProp = "world";

// Using for...in
for (let key in child) {
  console.log(key);
}

// Using Object.keys
console.log(Object.keys(child));

Output:

for…in: inheritedProp, ownProp
Object.keys: ownProp

Why does for…in iterate over inherited properties, while Object.keys() only returns the object’s own properties? Is there a specific reason for this behavior in JavaScript?

Strange javascript injection [closed]

I have a problem with a client’s website. The html is served fine when the user-agent is a browser, however, the page is not passing online html validation because the server is injecting some javascript code just before the !DOCTYPE tag. If I use wget to download the page I can see the injected stuff. Here it is:

<script>console.log('[PHP] session begin ENDS - 0 ms');</script>
<script>console.log('[PHP] autologin denied ends - 0.013 ms');</script>
<script>console.log('[PHP] bot check ENDS - 0.277 ms');</script>
<script>console.log('[PHP] autologin ENDS - 0.282 ms');</script>
<script>console.log('[PHP] user id forced to be integer ENDS - 0.867 ms');</script>
<script>console.log('[PHP] suser banned ENDS - 0.98 ms');</script>
<script>console.log('[PHP] if bot assign previous session ENDS - 0.985 ms');</script>
<script>console.log('[PHP] screate new session ENDS - 1.004 ms');</script>
<script>console.log('[PHP] deal with no last page ENDS - 2.297 ms');</script>
<script>console.log('[PHP] regenerate autologin ends - 2.301 ms');</script>
<script>console.log('[PHP] refresh data ends - 431.357 ms');</script>

The client wants this removed but I have no idea where this is coming from (some Apache/php module? a hack?). Any ideas?

I tried inspecting .htaccess, but there’s nothing suspicious there.

How to inner text from a span on Playwright? [closed]

In span I have number and try to inner text for my test and I can’t do it. I need to check I have 0 or another count of staff and I don’t see result of num_basket in console

<span class="basket-count-items badge badge-primary">1</span>
const num_basket = await page.locator('.basket-count-items.badge').textContent()
 console.log(num_basket)
 if (num_basket !== 0) {await page.locator('//a[@id="dropdownBasket"]').click()
 await page.locator('.btn.btn-danger').click()}

How I can inner text?

How to add javascript color to css

Sorry, I couldn’t find a suitable title for this topic.

https://codepen.io/Koray-Gen-/pen/VYemZwG

I have a script ready and it works fine. What I want to do is add a color switcher to the site and change the background canvas color. I change the code below and add the necessary css tags, but when I click, only the color changes and the sliding canvas in the background does not appear. What am I doing wrong?

enter image description here

<h3 class="text-white">Color Switcher</h3>
<li class="purple" onclick="draw('purple')"data-bs-toggle="tooltip" data-path="css/color-purple.css"></li>

Weird white section behind ios26 searchbar i want it gone

I want the website to fullscreen on iOS 26 so there’s no background behind de search bar so it’s floating over the website like the foto from appleparts.nl the other is mine.

I want that the searchbar is transparent. I did try to make the color transparent but it didn’t work.

If I’m on the top of the page there’s nothing but if I scroll and the navbar goes away it comes

[website where the bar is under the searchbar]

image where it isnt this is what i want

this is the code of the navbar i thought it was the theme color but it inst i dont know how i get the section behind

<!DOCTYPE html>
<html lang="nl">
<head>
    <meta charset="UTF-8" />

    <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
    <title>Bart Fiddelaers Bouwwerken</title>
    <meta name="theme-color" content="transparent">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <link rel="stylesheet" href="assets/index.css" />
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap" rel="stylesheet">
</head>

<body>
<button id="scrollTopBtn" title="Terug naar boven">↑</button>

<header class="navbar">
    <div class="container">
        <!-- Hamburger rechts -->
        <button class="menu" id="hamburger" aria-label="Main Menu" aria-expanded="false">
            <svg width="40" height="40" viewBox="0 0 100 100">
                <path class="line line1"
                      d="M 20,29.000046 H 80.000231 C 80.000231,29.000046 94.498839,28.817352 94.532987,66.711331
            94.543142,77.980673 90.966081,81.670246 85.259173,81.668997
            79.552261,81.667751 75.000211,74.999942 75.000211,74.999942
            L 25.000021,25.000058" />
                <path class="line line2" d="M 20,50 H 80" />
                <path class="line line3"
                      d="M 20,70.999954 H 80.000231 C 80.000231,70.999954 94.498839,71.182648 94.532987,33.288669
            94.543142,22.019327 90.966081,18.329754 85.259173,18.331003
            79.552261,18.332249 75.000211,25.000058 75.000211,25.000058
            L 25.000021,74.999942" />
            </svg>
        </button>

        <!-- Logo gecentreerd -->
        <div class="logo-wrapper">
            <img class="logo" src="assets/logobf.png" alt="Logo">
        </div>

        <!-- Desktop navigatie -->
        <div class="nav-wrapper">
            <nav class="nav-links">
                <a href="index.html" data-index="0" class="active">Home</a>
                <a href="overons.html" data-index="1">Over ons</a>
                <a href="Diensten.html" data-index="2">Diensten</a>
                <a href="realisatie.html" data-index="3">Realisaties</a>
                <a href="#contact" data-index="4">Contact</a>
            </nav>
            <div class="ruler-container">
                <div class="ruler" id="ruler"></div>
                <div class="indicator" id="indicator"></div>
            </div>
        </div>
    </div>


    <!-- Mobiel menu buiten .container -->
    <nav class="mobile-menu" id="mobileMenu">
        <a href="index.html" data-index="0" class="active">Home</a>
        <a href="overons.html" data-index="1">Over ons</a>
        <a href="Diensten.html" data-index="2">Diensten</a>
        <a href="realisatie.html" data-index="3">Realisaties</a>
        <a href="#contact" data-index="4">Contact</a>
    </nav>
</header>
</pre>
const ruler = document.getElementById('ruler');
const indicator = document.getElementById('indicator');

// Genereer ticks zoals bij een meetlat (elke 10e langer)
const totalTicks = 150;
for (let i = 0; i < totalTicks; i++) {
    const tick = document.createElement('div');
    tick.classList.add('tick');
    if (i % 10 === 0) tick.classList.add('long');
    ruler.appendChild(tick);
}

let activeIndex = 0;

function moveTo(index) {
    const link = links[index];
    const linkRect = link.getBoundingClientRect();
    const parentRect = link.parentElement.getBoundingClientRect();

    const centerOffset = linkRect.left - parentRect.left + linkRect.width / 2;

    ruler.style.transform = `translateX(${centerOffset - ruler.offsetWidth / 2}px)`;
    indicator.style.left = `${centerOffset}px`;

    links.forEach(a => a.classList.remove('active'));
    link.classList.add('active');
}

// Hover functionaliteit
links.forEach((link, index) => {
    link.addEventListener('mouseenter', () => moveTo(index));
    link.addEventListener('click', () => {
        activeIndex = index;
        moveTo(index);
    });
});

document.querySelector('.nav-links').addEventListener('mouseleave', () => {
    moveTo(activeIndex);
});

// Init bij laden van pagina
window.addEventListener('load', () => {
    const path = window.location.pathname;

    links.forEach((link, index) => {
        const href = link.getAttribute('href');
        if (path.endsWith(href)) activeIndex = index;
    });

    moveTo(activeIndex);
});

// Hamburger & mobiel menu
const hamburger = document.getElementById('hamburger');
const mobileMenu = document.getElementById('mobileMenu');
const mobileLinks = mobileMenu.querySelectorAll('a');
const desktopLinks = document.querySelectorAll('.nav-links a');

let scrollPosition = 0;

function openMobileMenu() {
    hamburger.classList.add('opened');
    hamburger.setAttribute('aria-expanded', 'true');
    mobileMenu.classList.add('open');

    // Body scroll blokkeren
    scrollPosition = window.scrollY;
    document.body.style.position = 'fixed';
    document.body.style.top = `-${scrollPosition}px`;
    document.body.style.left = '0';
    document.body.style.right = '0';
    document.body.style.overflow = 'hidden';
}

function closeMobileMenu() {
    hamburger.classList.remove('opened');
    hamburger.setAttribute('aria-expanded', 'false');
    mobileMenu.classList.remove('open');

    // Body scroll weer toestaan
    document.body.style.position = '';
    document.body.style.top = '';
    document.body.style.left = '';
    document.body.style.right = '';
    document.body.style.overflow = '';

    // Scroll terugzetten naar vorige positie
    window.scrollTo(0, scrollPosition);
}

hamburger.addEventListener('click', () => {
    if (hamburger.classList.contains('opened')) {
        closeMobileMenu();
    } else {
        openMobileMenu();
    }
});

// Menu sluiten bij klikken op link in mobiel menu + active class bijhouden
mobileLinks.forEach((link, index) => {
    link.dataset.index = index;
    link.addEventListener('click', () => {
        closeMobileMenu();

        // Active class mobiel
        mobileLinks.forEach(l => l.classList.remove('active'));
        link.classList.add('active');

        // Active class desktop
        desktopLinks.forEach(dl => dl.classList.remove('active'));
        desktopLinks[index].classList.add('active');

        // Update activeIndex
        activeIndex = index;
        moveTo(activeIndex);
    });
});

// Bij resize: sluit mobiel menu bij desktop & zet scroll aan
window.addEventListener('resize', () => {
    if (window.innerWidth > 900) {
        closeMobileMenu();
    }
});
/* =========================
   Navbar
========================= */
.navbar {
    background: #fff;
    position: fixed;
    top: 0;
    width: 100%;
    padding: 10px 0;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
    z-index: 9999;
    transition: transform 0.3s ease-in-out;

}

.navbar .container {
    max-width: 1600px;
    padding: 0 150px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    z-index: 10500;
}

.logo-wrapper {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    z-index: 1;
}

.logo {
    height: 60px;
}

/* --- Nav links --- */
.nav-wrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
    position: relative;
}

.nav-links {
    display: flex;
    gap: 40px;
    position: relative;
    z-index: 2;
}

.nav-links a {
    text-decoration: none;
    font-size: 21px;
    color: #535353;
    position: relative;
    transition: color 0.3s ease, transform 0.3s ease;
    text-shadow: 1px 1px 2px rgba(131, 131, 131, 0.4);
}

.nav-links a:hover,
.nav-links a.active {
    transform: scale(1.05);
    color: var(--button-hover);
    opacity: 0.9;
}

/* --- Hamburger button --- */
.menu {
    background: transparent;
    border: none;
    cursor: pointer;
    display: flex;
    padding: 0;
    position: absolute;
    right: 20px;
    top: 50%;
    transform: translateY(-50%);
    z-index: 9000;
}

.menu svg {
    pointer-events: none;
}

.line {
    fill: none;
    stroke: #535353;
    stroke-width: 6;
    transition:
            stroke-dasharray 600ms cubic-bezier(0.4, 0, 0.2, 1),
            stroke-dashoffset 600ms cubic-bezier(0.4, 0, 0.2, 1);
}

.line1, .line3 {
    stroke-dasharray: 60 207;
}

.line2 {
    stroke-dasharray: 60 60;
}

.opened .line1,
.opened .line3 {
    stroke-dasharray: 90 207;
    stroke-dashoffset: -134;
}

.opened .line2 {
    stroke-dasharray: 1 60;
    stroke-dashoffset: -30;
}

/* --- Ruler styling --- */
.ruler-container {
    position: relative;
    height: 30px;
    width: 100%;
    overflow: hidden;
}

.ruler-container::before,
.ruler-container::after {
    content: "";
    position: absolute;
    top: 0;
    width: 80px;
    height: 100%;
    z-index: 3;
    pointer-events: none;
}

.ruler-container::before {
    left: 0;
    background: linear-gradient(to right, #fff 0%, rgba(255, 255, 255, 0) 100%);
}

.ruler-container::after {
    right: 0;
    background: linear-gradient(to left, #fff 0%, rgba(255, 255, 255, 0) 100%);
}

.ruler {
    display: flex;
    position: absolute;
    height: 100%;
    align-items: flex-end;
    transition: transform 0.5s ease;
}

.tick {
    width: 2px;
    height: 12px;
    background: #5a595966;
    margin-right: 6px;
    box-shadow: 0 1px 3px rgba(90, 89, 89, 0.4);
}

.tick.long {
    height: 18px;
    background: rgba(16, 16, 16, 0.4);
    box-shadow: 0 2px 6px rgba(35, 35, 35, 0.4);
}

.indicator {
    position: absolute;
    top: 5px;
    width: 4px;
    height: 24px;
    background: var(--button-color);
    transition: left 0.5s ease;
    z-index: 8000;
    box-shadow: 0 0 10px rgba(0, 119, 204, 0.5);

    /* FIX: forceer aparte layer zodat kleur niet verdwijnt */
    transform: translateZ(0);
    will-change: left, transform, background;
}

/* --- Mobiel menu --- */
.mobile-menu {
    position: fixed;
    top: 100px;
    left: 0;
    width: 100%;
    height: calc(100vh - 100px);
    background: #fff;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 30px;
    opacity: 0;
    pointer-events: none;
    transform: translateY(100%);
    transition: all 0.4s ease;
    font-size: 24px;
    font-weight: 500;
    box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);

}

.mobile-menu.open {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
    overflow: hidden
}


.mobile-menu a {
    color: var(--button-color);
    text-decoration: none;
    font-size: 30px;
    transition: color 0.3s ease;
}

.mobile-menu a:hover {
    background-color: var(--button-hover);
    transform: translateY(-2px);
    opacity: 0.9;
}

/* --- Navbar responsive --- */
@media (min-width: 1001px) {
    .logo-wrapper {
        position: static;
        transform: none;
    }
    .navbar .container {
        justify-content: space-between;
    }
    .menu {
        display: none;
    }
}

@media (max-width: 1000px) {
    .nav-links {
        display: none;
    }
    .navbar {
        padding: 50px 0;
    }
    .ruler-container {
        display: none;
    }
    .logo {
        z-index: 9000;
    }
    .navbar .container {
        padding: 0 50px;
        justify-content: center;
    }
    .logo-wrapper {
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
        z-index: 1;
    }
}

if tried theme color to transparent but it didnt work i want the weird bar onder the searchbar gone