/* ============================================================
   Binary Thinkers — base stylesheet (design system foundation)
   Custom design from scratch; no CSS framework.
   ============================================================ */

:root {
    /* User-themeable from the Settings page / admin colour modes:
       --bt-bg          page background
       --bt-text        site text colour (also unselected button text)
       --bt-item        unselected button colour
       --bt-hover       selected button colour
       --bt-hover-text  selected button text colour */
    /* Theme SELECTION lives here in the stable stylesheet (a <link>, which survives
       Blazor enhanced navigation reliably — inline <style> in the head does not).
       The active --bt-* pull from the per-theme colour vars App.razor injects
       (--bt-moon-* / --bt-ml-*); if that inline data is ever missing, the hard-coded
       fallbacks keep the right dark/light look. Default (+ OS unknown) = Moon (dark). */
    --bt-bg: var(--bt-moon-bg, #1f1f1f);
    --bt-text: var(--bt-moon-text, #ffffff);
    --bt-item: var(--bt-moon-item, #333333);
    --bt-hover: var(--bt-moon-hover, #cccc33);
    --bt-hover-text: var(--bt-moon-htext, #1f1f1f);

    /* Typography */
    --bt-font-sans: ui-sans-serif, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --bt-font-mono: ui-monospace, "Cascadia Code", "Segoe UI Mono", Menlo, monospace;

    /* Motion */
    --bt-ease: cubic-bezier(0.22, 1, 0.36, 1);
    --bt-dur: 400ms;
}

/* Light OS scheme -> MoonLight. A pre-JS fallback: site.js also sets data-bt-theme
   from the OS (or the session override) so this only matters before scripts run. */
@media (prefers-color-scheme: light) {
    :root {
        --bt-bg: var(--bt-ml-bg, #e6e6e6);
        --bt-text: var(--bt-ml-text, #1f2937);
        --bt-item: var(--bt-ml-item, #ffffff);
        --bt-hover: var(--bt-ml-hover, #cccc33);
        --bt-hover-text: var(--bt-ml-htext, #1f2937);
    }
}
/* The resolved theme JS sets on <html> (session override, else the OS scheme). Higher
   specificity than :root above, so the manual override always wins; and because this
   lives in the stable stylesheet it can't be lost to an enhanced-navigation head morph. */
html[data-bt-theme="moon"] {
    --bt-bg: var(--bt-moon-bg, #1f1f1f);
    --bt-text: var(--bt-moon-text, #ffffff);
    --bt-item: var(--bt-moon-item, #333333);
    --bt-hover: var(--bt-moon-hover, #cccc33);
    --bt-hover-text: var(--bt-moon-htext, #1f1f1f);
}
html[data-bt-theme="moonlight"] {
    --bt-bg: var(--bt-ml-bg, #e6e6e6);
    --bt-text: var(--bt-ml-text, #1f2937);
    --bt-item: var(--bt-ml-item, #ffffff);
    --bt-hover: var(--bt-ml-hover, #cccc33);
    --bt-hover-text: var(--bt-ml-htext, #1f2937);
}

*,
*::before,
*::after {
    box-sizing: border-box;
    /* disables iOS double-tap-to-zoom (which raced the laser gesture);
       scrolling and pinch zoom remain untouched */
    touch-action: manipulation;
}

/* Discourage copying site content: no text selection on the public site.
   The admin area (/sitesettings) and form fields keep normal selection. */
body {
    -webkit-user-select: none;
    -moz-user-select: none;
    user-select: none;
}
.bt-admin,
.bt-admin *,
input,
textarea,
select,
[contenteditable="true"] {
    -webkit-user-select: text;
    -moz-user-select: text;
    user-select: text;
}

html {
    scroll-behavior: smooth;
}

body {
    margin: 0;
    font-family: var(--bt-font-sans);
    background: var(--bt-bg);
    color: var(--bt-text);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

img, video, canvas {
    max-width: 100%;
    height: auto;
}

/* Anchored footer: removed from the scrolling grid and pinned to the bottom of
   the shell. Spans from the aside (left: 49px) to the quick-actions area
   (right: 48px); the right border continues the C3 vertical guide line, and the
   left edge sits flush against the aside's existing right border. */
.bt-footer {
    position: absolute;
    left: 49px;
    /* The single vertical guide line for this boundary sits 47px from the right
       edge (the compact-view grid draws its background guide line at exactly
       `right: 47px`, and the wide-screen .bt-line-c3-right lands there too).
       The footer extends to that same 47px line and paints its OWN 1px darkgray
       border-right directly on top of it: one solid, uniform line covering the
       guide line — instead of the footer's edge merely grazing it, which let the
       black strip bleed dark onto the line in some spots (uneven colour) and the
       earlier separate border sit a pixel beside it (uneven ~2px width). */
    right: 47px;
    /* Black: the footer overlays the bottom two of the grid's last three rows,
       which use a black C3/C4 boundary line. */
    border-right: 1px solid black;
    bottom: 0;
    z-index: 45;
    display: flex;
    flex-direction: column;
}

.bt-footer-strip {
    height: 12px;
    background: black;
}

/* Cookie-consent banner (EU/UK/EEA only; shown by the GA script in App.razor).
   Reject and Accept are equally prominent (no dark pattern). */
.bt-consent {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 9990;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 10px 18px;
    padding: 14px 20px;
    background: var(--bt-item);
    color: var(--bt-text);
    border-top: 1px solid darkgray;
    box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.18);
    font-size: 14px;
}
.bt-consent[hidden] { display: none; }   /* beat the flex display when hidden */
.bt-consent-text { margin: 0; max-width: 64ch; line-height: 1.5; }
.bt-consent-text a { color: var(--bt-text); text-decoration: underline; }
.bt-consent-actions { display: flex; gap: 10px; flex: 0 0 auto; }
.bt-consent-btn {
    padding: 8px 20px;
    border: 1px solid darkgray;
    background: var(--bt-item);
    color: var(--bt-text);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-size: 0.75rem;
    cursor: pointer;
    transition: background-color 150ms ease, color 150ms ease;
}
.bt-consent-btn:hover { background: var(--bt-hover); color: var(--bt-hover-text); }

/* Footer links row — centered, uppercase, no underline. Global on purpose:
   bypasses scoped-CSS bundling so centering can't be lost to a stale bundle. */
.footer-links {
    display: flex;
    align-items: center; /* vertical centering in the row */
    justify-content: center;
    width: 100%;
    height: 48px;
    text-align: center;
    background: var(--bt-item);
    transition: background-color 200ms ease;
}

/* Hover flip only on devices with a real pointer — touch taps on iOS
   otherwise smear :hover onto the row from unrelated touches */
@media (hover: hover) {
    .footer-links:hover {
        background: var(--bt-hover);
    }

    .footer-links:hover a {
        color: var(--bt-hover-text);
    }
}

/* Phones/compact: the links block sits at the bottom of the page and
   gets extra height so bottom browser bars don't cover the text.
   Other rows are unaffected. */
@media (max-width: 960px) {
    .footer-links {
        height: 48px;
        order: 999; /* last, right below the black strip (which carries margin-top: auto) */
        border-top: 1px solid darkgray; /* visible row line above the footer */
    }
}

.footer-links a {
    display: inline-block;
    flex: 0 0 auto; /* never grow or shrink — keeps links tight together */
    margin: 0 8px; /* 16px between links */
    white-space: nowrap; /* never wrap "© 2026" / "PRIVACY POLICY" */
    color: var(--bt-text); /* unselected button text = site text colour */
    transition: color 200ms ease;
    text-transform: uppercase;
    text-decoration: none;
    font-size: 0.85rem;
    letter-spacing: 0.06em;
}

.footer-links a:hover {
    text-decoration: none;
}

/* ===== Linked hover: the header logo section and the aside's top-left
   corner act as a single area — hovering either activates both ===== */

.bt-shell:has(.bt-logo:hover) .bt-aside-corner {
    background: var(--bt-hover);
}

.bt-shell:has(.bt-aside-corner:hover) .bt-logo {
    background: var(--bt-hover);
}

.bt-shell:has(.bt-aside-corner:hover) .bt-logo .bt-logo-color {
    display: none;
}

.bt-shell:has(.bt-aside-corner:hover) .bt-logo .bt-logo-gray {
    display: block;
}

/* R2's and R5's dotted bottom row lines (2px dots, 6px gaps) — same
   rendering in desktop and mobile. Longhand properties, global file:
   immune to scoped-CSS bundling/specificity issues. */
.bt-grid > .bt-r2-spacer,
.bt-grid > .bt-r5-spacer,
.bt-grid > .bt-r7-spacer,
.bt-grid > .bt-r14-spacer {
    background-image: repeating-linear-gradient(to right, darkgray 0 2px, transparent 2px 8px);
    background-repeat: no-repeat;
    background-position: left bottom;
    background-size: 100% 1px;
}

/* Home-only decorative accent cells (placed via inline grid-row/column in the
   page). Hidden on mobile, like the layout's other cell accents. */
.bt-r1c3-accent {
    background: black;
}

.bt-r3c2-accent {
    background: #CCCC33; /* same green as row 1 / C1 (.bt-r1c1-accent) */
}
/* Games page: row 3 / cell 2 accent is darkgray instead of green. */
.bt-grid:has(.bt-games-links) > .bt-r3c2-accent { background: darkgray; }
/* Apps page: brand-green fill in row 3 / cell 3 (desktop/burger only; hidden on mobile) */
.bt-r3c3-green { background: #cccc33; }
@media (max-width: 960px) { .bt-r3c3-green { display: none; } }
/* Apps page: white fill in row 9 / cell 3 (desktop/burger only; hidden on mobile) */
.bt-r9c3-white { background: #ffffff; }
@media (max-width: 960px) { .bt-r9c3-white { display: none; } }
/* Apps page: App001 (rows 5–6) and App002 (row 8) shown in cell 3 as VIEWPORT-FIXED
   backgrounds (background-attachment: fixed) — each stays anchored in the middle of
   the screen while the page scrolls over its row band (the window). Left edge at the
   cell-3 start (page centre), 400×400, vertically centred. Hidden once the page
   narrows enough for the left-hand body text to reach them. */
.bt-app-shot {
    background-repeat: no-repeat;
    background-attachment: fixed;
    background-position: calc(50vw + 24px) center;   /* left edge ≈ cell-3 start; vertically centred */
    background-size: 400px 400px;
    pointer-events: none;
    z-index: 2;
}
.bt-app-shot1 { background-image: url('assets/images/App001.png'); }
.bt-app-shot2 { background-image: url('assets/images/App002.png'); }
/* Disappear ~24px before the image would touch the left-hand body text (the side
   it reaches first as the window narrows). */
@media (max-width: 1505px) { .bt-app-shot { display: none; } }

/* Web page: web.png in the lower-right corner of row 6 / cell 3 — 600px wide,
   height proportional (kept undistorted). Desktop only. */
.bt-web-shot {
    justify-self: end;
    align-self: end;
    width: 600px; height: auto;
    filter: grayscale(1);        /* always grayscale */
    pointer-events: none;
    z-index: 0;                  /* behind the robo-spider (z-index: 2) */
}
@media (max-width: 1199px) { .bt-web-shot { display: none; } }

/* Web page: a glossy top-down beetle that random-walks rows 5–8 over everything,
   steering clear of the swinging spider. Engine in wwwroot/js/site.js. */
.bt-beetle-zone {
    position: relative;          /* roaming area; the beetle is absolute within it */
    pointer-events: none;
    overflow: visible;
    z-index: 40;                 /* above the page content (spider is z-index 2) */
}
.bt-beetle {
    position: absolute;
    top: 0; left: 0;
    width: 52px; height: 65.3px;        /* smaller again */
    margin: -32.65px 0 0 -26px;         /* so translate(x,y) puts the beetle's centre at (x,y) */
    transform-origin: 50% 61%;          /* spin around the body centre, not the box centre */
    will-change: transform;
    pointer-events: none;
}
.bt-beetle-svg { width: 100%; height: 100%; display: block; filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.4)); }
/* Alternating-tripod gait: the two diagonal leg sets step in opposite phase.
   --btl-gait (set per-frame by site.js) keeps the stride period in lock-step
   with how fast the body is actually moving, so the legs never skate. */
.btl-legs-a { transform-box: view-box; transform-origin: 60px 95px; animation: btl-step-a var(--btl-gait, 0.34s) ease-in-out infinite; }
.btl-legs-b { transform-box: view-box; transform-origin: 60px 95px; animation: btl-step-b var(--btl-gait, 0.34s) ease-in-out infinite; }
@keyframes btl-step-a { 0%, 100% { transform: rotate(-5deg); } 50% { transform: rotate(5deg); } }
@keyframes btl-step-b { 0%, 100% { transform: rotate(5deg); } 50% { transform: rotate(-5deg); } }
/* Stopped/talking beetles keep their legs still. */
.bt-beetle.is-still .btl-legs-a, .bt-beetle.is-still .btl-legs-b { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .btl-legs-a, .btl-legs-b { animation: none; } }
@media (max-width: 1199px) { .bt-beetle-zone { display: none; } }

/* AI page: white background for row 1 / cell 2 (desktop only). */
.bt-r1c2-white { background: #ffffff; }
@media (max-width: 960px) { .bt-r1c2-white { display: none; } }
/* AI page: brand-green fill in row 9 / cell 3 (desktop/burger only; hidden on mobile) */
.bt-r9c3-green { background: #cccc33; }
@media (max-width: 960px) { .bt-r9c3-green { display: none; } }
/* Games page: darkgray fill in row 9 / cell 3 (desktop/burger only; hidden on mobile) */
.bt-r9c3-gray { background: darkgray; }
@media (max-width: 960px) { .bt-r9c3-gray { display: none; } }

/* ===== Row 9 / cell 3: "READ MORE" articles CTA =====
   A black square button (no border) with a white two-line label, and a brand-green
   glow on hover. Same on every page, left-aligned in the cell with a margin.
   Desktop only — hidden in mobile / one-column / burger-visible view (≤1199px). */
.bt-cta {
    position: relative;           /* anchor for the ARTICLES reveal */
    justify-self: start;          /* left-aligned in the cell */
    align-self: center;           /* equal gap top & bottom (row is 96px) */
    z-index: 2;                   /* above the r9c3 accent fill */
    margin-left: 16px;            /* equal to the top/bottom gap → equal margin on all three sides */
    display: flex;
    flex-direction: column;       /* "READ" over "MORE" — two lines */
    align-items: center;
    justify-content: center;
    width: 64px;
    height: 64px;
    background: #000;             /* black, no border */
    color: #fff;                 /* white text */
    text-decoration: none;
    font-weight: 400;            /* thinner */
    font-size: 12px;
    letter-spacing: 0.08em;
    line-height: 1.25;
    text-align: center;
    text-transform: uppercase;   /* capital text */
    cursor: pointer;
}
/* (No hover glow — the only hover effect is the sliding ARTICLES reveal below.) */
/* Brand-green label instead of white, for cells with a white (Apps) or darkgray
   (Games) background. */
.bt-cta-greentext { color: #cccc33; }

/* The button's own label — "READ" over "MORE", force-justified (letters spread
   edge to edge) with an equal 16px margin on every side (matching the button's
   left margin in the cell). */
.bt-cta-txt {
    position: absolute;
    inset: 0;
    padding: 16px;                    /* equal margin on all sides */
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    justify-content: space-between;   /* READ pinned top, MORE pinned bottom */
    font-size: 10px;
    line-height: 1;
    letter-spacing: normal;
}
.bt-cta-line {
    display: flex;
    justify-content: space-between;   /* letters spread to both edges (force-justified) */
    width: 100%;
}

/* Hover: the whole word "ARTICLES" slides out to the right from behind the button
   (like a drawer) and slides back smoothly on leave. Drawn as SVG text so its caps
   fill the button's height exactly (tops and bottoms line up) — CSS text metrics
   can't be pinned reliably. Condensed face keeps the tall word compact; black (the
   button's colour). The wrapper clips + sits behind the button. */
.bt-cta-reveal {
    position: absolute;
    top: 0;
    left: 100%;                  /* drawer opens at the button's right edge */
    height: 100%;                /* = button height */
    width: 380px;                /* drawer length (fits the word) */
    overflow: hidden;            /* the word emerges from behind the button */
    pointer-events: none;
    z-index: -1;                 /* behind the button, so the seam is hidden */
}
.bt-cta-reveal > svg {
    display: block;
    height: 100%;                /* caps fill the button height via the viewBox */
    width: auto;
    transform: translateX(-100%);   /* tucked behind the button */
    transition: transform 0.45s ease;
}
.bt-cta:hover .bt-cta-reveal > svg { transform: translateX(0); }
@media (prefers-reduced-motion: reduce) { .bt-cta-reveal > svg { transition: none; } }
@media (prefers-reduced-motion: reduce) { .bt-cta { transition: none; } }
@media (max-width: 1199px) { .bt-cta { display: none; } }

/* Web page: black background for row 3 / cell 1 (desktop only). */
.bt-r3c1-black { background: #000000; }
@media (max-width: 960px) { .bt-r3c1-black { display: none; } }

/* Apps page: white background for row 3 / cell 2 (over the green accent; desktop only). */
.bt-r3c2-white { background: #ffffff; }
@media (max-width: 960px) { .bt-r3c2-white { display: none; } }

/* ===== Apps + Web pages: looping video in row 4 / cell 3 ===== */
.bt-window-video { background: #000; filter: grayscale(1); transition: filter 450ms ease; }
.bt-window-video:hover { filter: grayscale(0); }   /* full colour on hover/tap */
/* Web page: per-loop fade. The opacity keyframes loop forever; site.js matches
   their period to the clip length and phase-aligns them so the fade-out lands on
   the loop seam. The black .bt-window-video background means it fades to/from black. */
.bt-video-fade { opacity: 1; }   /* visible until site.js starts the synced fade */
@keyframes bt-video-fade {
    0% { opacity: 0; }
    8% { opacity: 1; }
    92% { opacity: 1; }
    100% { opacity: 0; }
}
.bt-window-video-el {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: right bottom;   /* keep the bottom-right (text) always visible */
    display: block;
}

/* Web page: robo-spider (2x size) hanging by a silk thread from the row-5
   ceiling, walking up and down the right wall of cell 3 (desktop only). The
   thread and the spider's position animate in sync; legs alternate. */
.bt-spider-track {
    grid-row: 5 / 7;
    justify-self: end;
    align-self: stretch;
    width: 100px;
    margin-right: 24px;          /* before the last vertical line */
    transform: translateX(-150px);  /* move the whole rig left so the swing has room */
    position: relative;
    z-index: 2;
    pointer-events: none;
}
/* the hanging unit (thread + spider) swings like a pendulum around the ceiling
   anchor (track top centre) */
.bt-spider-hang {
    position: absolute;
    top: 0;
    left: 50%;
    width: 0;
    height: 100%;
    transform-origin: top center;
    animation: spider-swing 7s ease-in-out infinite;
}
@keyframes spider-swing {
    0%, 100% { transform: rotate(-28deg); }
    50%      { transform: rotate(28deg); }
}
/* silk thread anchored at the ceiling; grows as the spider descends */
.bt-spider-thread {
    position: absolute;
    top: 0;
    left: 0;
    width: 1.5px;
    transform: translateX(-50%);
    background: linear-gradient(#cfd5dd, #aab1bb);
    animation: spider-thread 12s ease-in-out infinite;
}
@keyframes spider-thread {
    0%, 100% { height: 65px; }
    50%      { height: calc(100% - 91px); }
}
.bt-spider-svg {
    position: absolute;
    left: 0;
    transform: translateX(-50%);
    width: 96px;
    height: 96px;
    top: 36px;
    animation: spider-climb 12s ease-in-out infinite;
}
@keyframes spider-climb {
    0%, 100% { top: 36px; }
    50%      { top: calc(100% - 120px); }   /* 96px tall + 24px bottom margin */
}
/* alternating leg gait, rotating each set around the body centre */
.bt-spider-legs { transform-box: view-box; transform-origin: 24px 24px; }
.sp-legs-a { animation: spider-step 0.9s ease-in-out infinite alternate; }
.sp-legs-b { animation: spider-step 0.9s ease-in-out infinite alternate-reverse; }
@keyframes spider-step { from { transform: rotate(-2.5deg); } to { transform: rotate(2.5deg); } }
/* eyes glow up at random-ish moments */
.bt-spider-eye { animation: spider-eye 7.3s ease-in-out infinite; }
@keyframes spider-eye {
    0%, 24%, 30%, 60%, 66%, 100% { fill: #50545a; filter: none; }
    27% { fill: #7fe6ff; filter: drop-shadow(0 0 3px #7fe6ff); }
    63% { fill: #7fe6ff; filter: drop-shadow(0 0 3px #7fe6ff); }
}
@media (max-width: 1199px) { .bt-spider-track { display: none; } }
@media (prefers-reduced-motion: reduce) {
    .bt-spider-svg, .bt-spider-thread, .bt-spider-hang, .sp-legs-a, .sp-legs-b, .bt-spider-eye { animation: none; }
}
@media (max-width: 960px) {
    .bt-window-web { display: none; }
}

/* Row-1 breadcrumb (cell 1). A self-contained green strip (same green as
   .bt-r1c1-accent) with text in the aside "PAST" tab style; equal 12px top,
   left and bottom margins. */
.bt-crumbs {
    position: relative;
    z-index: 4;
    display: flex;
    align-items: center;        /* vertical centre → equal top/bottom margin in the 36px row */
    gap: 6px;
    padding-left: 12px;         /* equal left margin */
    overflow: hidden;
    white-space: nowrap;
    background: #cccc33;        /* green strip — same as row 1 / C1 */
    color: var(--bt-text);
    font-size: 0.75rem;         /* matches .bt-era-tab */
    letter-spacing: 0.08em;
    line-height: 1;
    text-transform: uppercase;
}
.bt-crumbs a {
    color: var(--bt-text);
    text-decoration: none;
}
.bt-crumbs a:hover { text-decoration: underline; }
/* separator scaled up to about the cap height of the breadcrumb text */
.bt-crumb-sep { font-size: 1.5em; opacity: 0.6; }

@media (max-width: 960px) {
    /* Becomes the 36px top strip (matching desktop row 1); the plain 12px green
       accent is hidden so there is a single green bar that doesn't roll out. */
    .bt-crumbs {
        order: -2;
        flex: 0 0 36px;
        height: 36px;
        /* cancel the generic mobile content padding-bottom so the text stays
           vertically centred in the 36px bar */
        padding: 0 0 0 12px !important;
    }
    .bt-grid:has(.bt-r3c2-accent) > .bt-r1c1-accent { display: none; }
}

.bt-r9c12-accent {
    background: black;   /* row 9, cells 1–2 */
}

.bt-r16c3-accent {
    background: darkgray;   /* row 16, cell 3 */
}

.bt-r17c3-accent {
    background: white;   /* row 17, cell 3 */
}

/* Branding card inside row 17 / cell 3: logo across the top, tagline along the
   bottom, with 48px insets (matching the FAQ's left padding). */
.bt-brandcard {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 24px;
    padding: 48px;
    box-sizing: border-box;
    /* The card's white background sits over the C3/C4 guide line, so the card
       draws that boundary itself — 1px black, matching the footer's right line
       (this is the bottom of the grid's "last three rows"). */
    border-right: 1px solid black;
}

.bt-brandcard-logo {
    display: block;
    width: 100%;
    height: auto;
}

/* Row 17 walking-icon scene (stairs in cell 1, door in cell 2) */
.bt-stairs-scene {
    position: relative;
    overflow: visible;   /* don't clip the jumping icon; .bt-main still clips the wall exit */
}

.bt-stairs {
    position: absolute;
    left: 0;
    bottom: 0;
    width: min(326px, 80%);  /* 80% of cell 1 on desktop; scales to the scene on mobile */
    height: 60%;             /* 40% top margin */
}

.bt-door {                   /* squarish door; the panel opens to show the dark interior */
    position: absolute;
    right: 20px;
    bottom: 0;
    width: 62px;
    height: 126px;           /* 1.5x taller */
    background: #2a2a2a;      /* dark interior, seen while the door is open */
    border: 3px solid darkgray;
    border-bottom: none;
    border-radius: 6px 6px 0 0;
    overflow: hidden;
    perspective: 340px;
}
.bt-door-panel {             /* the swinging door slab */
    position: absolute;
    inset: 0;
    background: darkgray;
    border-radius: 4px 4px 0 0;
    transform-origin: left center;
    transition: transform 0.7s ease;
    backface-visibility: hidden;
}
.bt-door.open .bt-door-panel {
    transform: rotateY(-118deg);
}
.bt-door-panel::after {      /* knob */
    content: "";
    position: absolute;
    right: 7px;
    top: 50%;
    width: 6px;
    height: 6px;
    margin-top: -3px;
    border-radius: 50%;
    background: #2a2a2a;
}
/* door is shown only while the burger menu is hidden (same breakpoint) */
@media (max-width: 1199px) {
    .bt-door { display: none; }
}

.bt-walker {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 52px;
    height: 52px;
    opacity: 0;              /* hidden between journeys; the script fades it in */
    cursor: pointer;
    pointer-events: none;    /* clickable only while visible (toggled in script) */
    will-change: transform, opacity;
}
.bt-walker-ico {
    display: block;
    width: 100%;
    height: 100%;
}
.bt-walker-ico.bt-walking {
    animation: bt-walk-bob 0.36s ease-in-out infinite;
}
.bt-walker-ico.bt-arrive {
    animation: bt-arrive 2s ease;       /* small dance */
}
@keyframes bt-walk-bob {
    0%, 100% { transform: translateY(0) rotate(-3deg); }
    50%      { transform: translateY(-4px) rotate(3deg); }
}
@keyframes bt-arrive {
    0%   { transform: translateY(0) rotate(0); }
    15%  { transform: translateY(-8px) rotate(-8deg); }
    30%  { transform: translateY(0) rotate(0); }
    45%  { transform: translateY(-8px) rotate(8deg); }
    60%  { transform: translateY(0) rotate(0); }
    75%  { transform: translateY(-6px) rotate(-6deg); }
    90%  { transform: translateY(0) rotate(6deg); }
    100% { transform: translateY(0) rotate(0); }
}

/* Speech bubble: top-right of cell 1 (6px margin), shown while the icon waits */
.bt-bubble {                       /* positioned container; the oval child paints over the
                                      tail so the border never shows inside the oval */
    position: absolute;
    top: 18px;                     /* moved up 6px */
    right: max(6px, 100% - 384px); /* 24px inside cell 1 on desktop; stays on-screen on mobile */
    width: 244px;                  /* <= 3 stair tiles wide (3 x 81.5px) */
    height: 160px;
    opacity: 0;
    /* The script sets --bt-bubble-scale per journey so the balloon (text
       included) shrinks to keep its top edge ~6-12px below the scene top and
       fits the available width. Using the independent `scale` property (rather
       than a var() inside a keyframe transform, which is unreliable) guarantees
       it always applies; it pivots around the tail tip (transform-origin). */
    scale: var(--bt-bubble-scale, 1);
    transform-origin: 18px 122px;  /* pivot at the tail tip (lower endpoint) */
    transition: opacity 0.35s ease;
    pointer-events: none;
    cursor: pointer;
    z-index: 3;
}
.bt-bubble.show {
    opacity: 1;
    pointer-events: auto;          /* clickable while shown */
    animation: bt-bubble-sway 3.2s ease-in-out infinite;   /* gentle right/left sway */
}
@keyframes bt-bubble-sway {
    /* rotate-only sway (pivot = tail tip) so the tip stays pinned to the icon;
       the `scale` property is untouched, so the size stays as the script set it */
    0%, 100% { rotate: -2.5deg; }
    50%      { rotate: 2.5deg; }
}
@media (prefers-reduced-motion: reduce) {
    .bt-bubble.show { animation: none; transform: none; }
}
.bt-bubble-shape {                 /* single SVG: oval + down-left tail, white fill, black border */
    position: absolute;
    left: 0;
    top: 0;
    width: 244px;
    height: 160px;
    overflow: visible;
    filter: drop-shadow(0 6px 12px rgba(0, 0, 0, 0.18));
}
.bt-bubble-oval {                  /* message text, centred over the oval */
    position: absolute;
    left: 26px;
    top: 6px;
    width: 192px;
    height: 86px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    color: #4c4c4c;                /* darkgray, as the "binary" in the logo */
    font-size: 15px;
    font-weight: 900;              /* heavy */
    line-height: 1.3;
    z-index: 1;
}

/* Idle attention callout: shown whenever no character is on screen */
.bt-contact {                      /* curved label behind an arrow; always visible */
    position: absolute;
    left: 0;
    bottom: 0;
    width: 240px;
    height: 150px;
    pointer-events: auto;
    cursor: pointer;
    animation: bt-contact-dance 2.2s ease-in-out infinite;   /* subtle nudge toward the corner */
    transition: opacity 0.3s ease;
    z-index: 4;
}
/* hide the contact callout while the character's speech bubble is showing */
.bt-bubble.show ~ .bt-contact {
    opacity: 0;
    pointer-events: none;
}
@keyframes bt-contact-dance {
    0%, 100% { transform: translate(0, 0); }
    50%      { transform: translate(-4px, 4px); }
}
.bt-contact-text {                 /* curved SVG label, tilted right, behind the arrow */
    position: absolute;
    left: -18px;                   /* 30px left of the arrow */
    bottom: 120px;                 /* up 24px more */
    width: 185px;
    height: 90px;
    overflow: visible;
    transform: rotate(50deg);
    transform-origin: bottom left;
    z-index: 1;
}
.bt-contact-text text {
    font-family: "Arial Rounded MT Bold", "Trebuchet MS", var(--bt-font-sans);
}
.bt-contact-arrow {                /* white arrow with black border, points lower-left */
    position: absolute;
    left: 18px;
    bottom: 12px;
    width: 52px;
    height: 68px;
    overflow: visible;
    transform: rotate(45deg);
    z-index: 2;
}
@media (prefers-reduced-motion: reduce) {
    .bt-contact { animation: none; }
}

.bt-brandcard-tag {
    margin: 0;
    padding-left: 0.7em;     /* offset the trailing letter-spacing so it reads centred */
    text-align: center;
    color: #4C4C4C;          /* darkgray, as the "binary" in the logo */
    font-weight: 300;
    font-size: 22px;
    letter-spacing: 0.7em;
    font-family: var(--bt-font-sans);
}

/* ===== Home "window" scenes =====
   A 3D/animation scene is drawn to a fixed, full-viewport canvas and revealed
   only through one of these grid cells. The canvas clip tracks the cell each
   frame, so the scene stays still while the page scrolls over it. */
.bt-window {
    background: #000;          /* fallback before WebGL paints / if unavailable */
    position: relative;
    overflow: hidden;
}

.bt-scene-canvas {
    position: fixed;
    inset: 0;
    width: 100vw;
    height: 100vh;
    z-index: 6;                /* always clipped to a window, so it never covers UI */
    pointer-events: none;
    display: block;
}

/* ===== Games page: "Invader Defense" canvas mini-game (row 4 / cell 3) =====
   Retro-modern: neon-on-near-black, glowing sprites, a HUD, an overlay for
   start/over/paused, and a 3-button control pad below the play area. */
.bt-window-game { background: #05060f; display: flex; flex-direction: column; }
.bt-game-stage { position: relative; flex: 1 1 auto; min-height: 0; }
.bt-game-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.bt-game-hud {
    position: absolute; top: 6px; left: 8px; right: 8px;
    display: flex; justify-content: flex-start; gap: 12px; padding-right: 62px;
    font: 700 11px/1 ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
    letter-spacing: 0.08em; color: #9ef7e6; text-shadow: 0 0 6px rgba(80, 230, 255, 0.5);
    pointer-events: none;
}
.bt-game-hud .bt-game-lives { color: #ff6b6b; text-shadow: 0 0 6px rgba(255, 80, 80, 0.5); }
.bt-game-overlay {
    position: absolute; inset: 0; z-index: 3;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
    text-align: center; padding: 12px; background: rgba(5, 6, 15, 0.72);
}
.bt-game-overlay[hidden] { display: none; }
.bt-game-otitle {
    /* Doom-style display face; falls back to a heavy system font if it can't load */
    font: 400 clamp(20px, 5.6vw, 34px)/1 "Black Ops One", Impact, "Arial Black", sans-serif;
    text-transform: uppercase;
    letter-spacing: 0.06em; color: #cccc33; text-shadow: 0 0 14px rgba(204, 204, 51, 0.7);
}
.bt-game-omsg { font: 600 12px/1.4 ui-monospace, Menlo, Consolas, monospace; color: #cfe9ff; opacity: 0.9; max-width: 90%; }
.bt-game-cta {
    margin-top: 4px; font: 800 14px/1 ui-monospace, Menlo, Consolas, monospace; letter-spacing: 0.1em;
    color: #06121a; background: linear-gradient(#e2e24f, #cccc33); border: none; border-radius: 9px;
    padding: 11px 24px; cursor: pointer; box-shadow: 0 0 18px rgba(204, 204, 51, 0.55);
}
.bt-game-cta:hover { filter: brightness(1.08); }
.bt-game-pad {
    flex: 0 0 auto; display: flex; gap: 8px; padding: 8px;
    background: #0a0c1a; border-top: 1px solid #1b2440;
}
.bt-game-btn {
    flex: 1 1 0; min-height: 42px; font-size: 18px; color: #cfe9ff;
    background: linear-gradient(#16203c, #0d1429); border: 1px solid #2a3a66; border-radius: 9px;
    cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent; touch-action: manipulation;
    transition: filter 0.1s ease, transform 0.05s ease;
}
.bt-game-btn:active { transform: translateY(1px); filter: brightness(1.6); }
.bt-game-btn-fire { flex: 1.4 1 0; color: #ffd34d; border-color: #6b5a1f; background: linear-gradient(#2a2410, #171204); }
/* small utility buttons (top-right): full-screen / revert toggle + exit */
.bt-game-tools { position: absolute; top: 5px; right: 6px; z-index: 4; display: flex; gap: 6px; }
.bt-game-tool {
    width: 27px; height: 24px; padding: 0; font-size: 13px; line-height: 1;
    color: #cfe9ff; background: rgba(12, 18, 38, 0.72); border: 1px solid #2a3a66; border-radius: 6px;
    cursor: pointer; -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.bt-game-tool:hover { filter: brightness(1.35); }

/* Games page: tall game-agent character down the right of row 6 / cell 3.
   Fills the cell top-to-bottom with 24px top/right/bottom margins (the right
   margin sits just inside the last C3 vertical line). Desktop only. */
.bt-games-agent {
    position: relative;          /* containing block for the absolute image */
    align-self: stretch;
    justify-self: stretch;       /* matches the cell; the image is absolute so it never grows the row */
    z-index: 2;
    pointer-events: none;
}
/* the link wraps the image but takes no layout box, so the image keeps its own
   absolute positioning (and the centering script keeps working) */
.bt-games-agent a { display: contents; }
.bt-games-agent img {
    position: absolute;
    top: 24px;                   /* 24px insets = same top/bottom as the caption text */
    bottom: 24px;
    right: 30px;                 /* 30px before the last vertical line (JS re-centres it) */
    height: calc(100% - 48px);   /* taller — spans the same extent as the caption text */
    width: auto;
    object-fit: contain;
    object-position: bottom right;
    display: block;
    pointer-events: auto;        /* clickable (its container is pointer-events:none) */
    cursor: pointer;
    filter: drop-shadow(-2px 3px 3px rgba(0, 0, 0, 0.25));  /* small, subtle shadow */
    transition: transform 0.15s ease, filter 0.15s ease;
}
/* same hover as the game icons: scale up + a soft drop-shadow */
.bt-games-agent img:hover {
    transform: scale(1.07);
    filter: drop-shadow(0 5px 12px rgba(0, 0, 0, 0.45));
}
@media (max-width: 1199px) { .bt-games-agent { display: none; } }

/* Promo stat to the LEFT of the trophy (row 6 / cell 3). Five short lines,
   left-aligned, medium weight; its block stays within 325px of the last
   vertical line (right edge 140px in + 185px wide = left edge at 325px). */
.bt-games-stat {
    justify-self: end;
    align-self: center;
    margin-right: 116px;          /* moved 24px right (still within 325px of the line) */
    width: max-content;
    max-width: 209px;
    white-space: nowrap;
    text-align: left;
    font-family: "Segoe Script", "Bradley Hand", "Comic Sans MS", "Brush Script MT", cursive;
    font-size: 1.85rem;           /* bigger, handwritten */
    font-weight: 700;
    line-height: 1.18;
    color: #000;                  /* black by default */
    transform: rotate(-5deg);     /* tilted 5° to the left */
    transform-origin: center;
    z-index: 2;
    pointer-events: auto;         /* hoverable */
    cursor: default;
}
/* hover: switch to the flashy red "liquid" gradient text + glow pulse */
.bt-games-stat:hover {
    color: transparent;
    -webkit-text-fill-color: transparent;
    background: linear-gradient(100deg, #ff3b3b, #ff8a8a, #c30000, #ff5252, #ff1a1a, #ff8a8a, #ff3b3b);
    background-size: 300% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    animation: bt-stat-liquid 5s linear infinite, bt-stat-flash 1.6s ease-in-out infinite;
}
@keyframes bt-stat-liquid { to { background-position: 300% 0; } }
@keyframes bt-stat-flash {
    0%, 100% { filter: drop-shadow(0 0 4px rgba(255, 40, 40, 0.55)); }
    50% { filter: drop-shadow(0 0 16px rgba(255, 60, 60, 0.95)); }
}
@media (prefers-reduced-motion: reduce) { .bt-games-stat:hover { animation: none; } }
@media (max-width: 1199px) { .bt-games-stat { display: none; } }

/* Row 8 / cell 3: three game icons stacked vertically at equal spacing, their
   column 300px in from the last vertical line; each links to a YouTube video. */
.bt-games-links {
    justify-self: end;
    align-self: center;          /* centered like the caption; JS sets its height
                                    to the caption's so the two stay aligned */
    margin-right: 96px;          /* icon group position (moved 12px right) */
    padding: 24px 0;             /* same top/bottom inset as the unity caption */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;  /* spread the 3 games top → bottom so the
                                        group's top/bottom align with the caption */
    z-index: 2;
}
.bt-games-links a {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    text-decoration: none;
    pointer-events: auto;
    transition: transform 0.15s ease, filter 0.15s ease;
}
.bt-games-links a:hover { transform: scale(1.07); filter: drop-shadow(0 5px 12px rgba(0, 0, 0, 0.45)); }
.bt-games-links img { width: 128px; height: 128px; display: block; border-radius: 14px; }
.bt-games-link-name { font-size: 0.95rem; font-weight: 600; letter-spacing: 0.01em; color: var(--bt-text); white-space: nowrap; }
.bt-games-links a:hover .bt-games-link-name { text-decoration: underline; }
/* Game-video icons stay visible on tablet/desktop (so the popup player works
   there); hidden on the single-column mobile layout (no mobile YouTube needed). */
@media (max-width: 960px) { .bt-games-links { display: none; } }

/* Games page: in-page YouTube popup. Clicking a game icon opens the video here
   (engine in site.js) instead of leaving for YouTube. The player keeps a 10%
   margin on the left and right (width 80%), capped so it always fits the height. */
.bt-ytmodal {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.86);
    opacity: 0;
    pointer-events: none;
    transition: opacity 200ms ease;
}
.bt-ytmodal.is-open { opacity: 1; pointer-events: auto; }
.bt-ytmodal-frame {
    position: relative;
    width: min(80%, calc(85vh * 16 / 9));   /* 10% margins; never taller than 85vh */
    aspect-ratio: 16 / 9;
    background: #000;
    box-shadow: 0 16px 70px rgba(0, 0, 0, 0.6);
    transform: scale(0.96);
    transition: transform 200ms ease;
}
.bt-ytmodal.is-open .bt-ytmodal-frame { transform: scale(1); }
.bt-ytmodal-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; }
.bt-ytmodal-close {
    position: absolute;
    /* Sit entirely OUTSIDE the iframe's rectangle (in the 10% right margin). A video
       iframe is composited and repaints over any overlapping sibling — e.g. after a
       tab switch — regardless of z-index, so the only reliable fix is no overlap. */
    top: 0;
    right: -50px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: #fff;
    color: #111;
    border: none;
    cursor: pointer;
    font-size: 24px;
    line-height: 38px;
    text-align: center;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
    transition: background-color 150ms ease, color 150ms ease;
    z-index: 2;
}
.bt-ytmodal-close:hover { background: #cccc33; }

/* Games page: real IBM PC-XT photo, bottom-left of row 8 / cell 3, ~3× the 128px
   game icons wide. The green Pong canvas is overlaid on the monitor's screen.
   Hidden ≤1400px — earlier than the game icons (≤1199px) — before it crowds the
   row's left-hand text / right-hand icons. */
.bt-retropc {
    position: relative;          /* anchors the screen overlay */
    justify-self: start;
    align-self: end;             /* sit on the cell's bottom border */
    margin-left: 42px;           /* 24px guide-line inset + 24px right nudge − 6px left */
    width: min(768px, calc(100% - 282px));   /* shifted 24px right of its prior spot; capped so it's never cut */
    line-height: 0;
    pointer-events: none;        /* the photo never blocks; only the screen is interactive */
    z-index: 1;                  /* behind the link icons if they ever meet */
}
.bt-retropc-img { width: 100%; height: auto; display: block; }
/* Screen overlay — measured from game-pc.png (677×369). Nudge by a px if needed.
   The screen is the playable zone: focusable, Enter to start, arrows to play. */
.bt-retropc-canvas {
    position: absolute;
    left: 22.5%; top: 7.8%;       /* aligned to the CRT glass (as % so it scales with the PC) */
    width: 36%; height: 36.9%;
    display: block;
    border-radius: 7px;
    overflow: hidden;
    pointer-events: auto;
    cursor: pointer;
    outline: none;               /* no focus ring */
}
@media (max-width: 1400px) { .bt-retropc { display: none; } }

/* Vertical captions, 24px from the last vertical line: row 8's "Unity Supports
   20+ Platforms" and the row-6 "Million+ Download & Views Crossed!" — same
   character height (38px) and right margin. */
.bt-games-unity,
.bt-games-views {
    justify-self: end;
    align-self: center;
    margin-right: 24px;          /* 24px from the last vertical line */
    padding: 24px 0;             /* 24px top/bottom margin — equal to the right margin */
    display: flex;
    align-items: center;
    justify-content: center;
    writing-mode: vertical-rl;
    text-orientation: sideways;  /* each character rotated 90° (like MAUI) */
    white-space: nowrap;
    line-height: 1;
    font-size: 38px;
    font-weight: 800;
    letter-spacing: 2px;
    color: var(--bt-text);
    transition: color 0.15s ease;
    z-index: 1;
    pointer-events: auto;        /* allow hover (nothing clickable sits behind it) */
    user-select: none;
}
.bt-games-unity:hover,
.bt-games-views:hover {
    color: #CCCC33;                  /* brand green fill */
    -webkit-text-stroke: 3px #000;   /* thick black outline behind the text */
    paint-order: stroke fill;        /* stroke drawn first (behind), green fill on top */
}
@media (max-width: 1199px) { .bt-games-unity, .bt-games-views { display: none; } }

/* ===== Games-page cursor companion (script in App.razor) =====
   A yellow smiley that chases the cursor, winks once when it stops, then sleeps
   (Zzz) after 1s. Double-click swaps it to a gray ghost (and back). */
.bt-pac {
    position: fixed; left: 0; top: 0; width: 46px; height: 46px;
    pointer-events: none; z-index: 9998; will-change: transform;
    filter: drop-shadow(0 3px 3px rgba(0, 0, 0, 0.3));
}
.bt-pac svg { display: block; overflow: visible; }
/* eye states */
.eye-wink, .eye-sleep { display: none; }
.bt-pac--wink .eye-open { display: none; }
.bt-pac--wink .eye-wink { display: block; }
.bt-pac--sleep .eye-open { display: none; }
.bt-pac--sleep .eye-sleep { display: block; }
/* laugh (a giggle wobble) while winking */
.bt-pac--wink svg { animation: bt-pac-laugh 0.32s ease-in-out infinite; }
@keyframes bt-pac-laugh { 0%, 100% { transform: translateY(0) rotate(-5deg); } 50% { transform: translateY(-3px) rotate(5deg); } }
/* gentle breathing + floating Zzz while asleep */
.bt-pac--sleep svg { animation: bt-pac-breathe 3.4s ease-in-out infinite; }
@keyframes bt-pac-breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.04); } }
.bt-pac-z { opacity: 0; }
.bt-pac--sleep .bt-pac-z1 { animation: bt-pac-z 2.4s ease-in-out infinite; }
.bt-pac--sleep .bt-pac-z2 { animation: bt-pac-z 2.4s ease-in-out 0.55s infinite; }
.bt-pac--sleep .bt-pac-z3 { animation: bt-pac-z 2.4s ease-in-out 1.1s infinite; }
@keyframes bt-pac-z { 0% { opacity: 0; transform: translate(0, 0); } 25% { opacity: 0.95; } 100% { opacity: 0; transform: translate(4px, -9px); } }

/* ===== Home hero cursor trail (script in App.razor) =====
   Key Phrase 1 letters dropped behind the cursor in the rows 1–4 band. Each
   glyph inflates like a balloon, drifts up with a little sway (--dx, --rise,
   --rot) and fades within 2s, so the trail clears itself character-by-character. */
.bt-kptrail {
    position: fixed; left: 0; top: 0; z-index: 9997;
    pointer-events: none; user-select: none; white-space: pre;
    /* thin, ~2× the previous size; row 1 / cell 1 background green */
    font: 200 clamp(30px, 3vw, 44px)/1 var(--bt-font-sans);
    color: #CCCC33;
    will-change: transform, opacity;
    transform: translate(-50%, -50%) scale(0.4) rotate(var(--baseRot, 0deg));
    /* slow steady rise over 5s */
    animation: bt-kptrail-float 5s linear forwards;
}
/* --baseRot aligns the glyph to the direction the mouse was travelling (so a
   round/curved gesture sweeps the letters' angle); --rot adds a tiny drift. */
@keyframes bt-kptrail-float {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.4) rotate(var(--baseRot, 0deg)); }
    8%   { opacity: 1; transform: translate(-50%, -53%) scale(var(--scl, 1)) rotate(var(--baseRot, 0deg)); }
    72%  { opacity: 1; }
    100% { opacity: 0; transform: translate(calc(-50% + var(--dx, 0px)), calc(-50% + var(--rise, -150px))) scale(var(--scl, 1)) rotate(calc(var(--baseRot, 0deg) + var(--rot, 0deg))); }
}

/* Games page: cursor icon trail over row 6 only. Each game icon STAYS where it
   spawns (no float), appears at a random angle and random size (up to the row-8
   icon size, 128px), front-facing (2-D rotation — never flipped/mirrored), and
   shrinks a little as it fades out. */
.bt-gicon {
    position: absolute; left: 0; top: 0; z-index: 9997;   /* anchored inside .bt-main — scrolls with the page content */
    width: var(--size, 128px); height: auto;
    border-radius: 14px;                 /* match the row-8 icons' rounding */
    pointer-events: none; user-select: none;
    will-change: transform, opacity;
    transform: translate(-50%, -50%) rotate(var(--rot, 0deg)) scale(0.7);
    animation: bt-gicon-pop 5s ease-out forwards;
}
@keyframes bt-gicon-pop {
    0%   { opacity: 0; transform: translate(-50%, -50%) rotate(var(--rot, 0deg)) scale(0.6); }
    12%  { opacity: 1; transform: translate(-50%, -50%) rotate(var(--rot, 0deg)) scale(1); }
    70%  { opacity: 1; transform: translate(-50%, -50%) rotate(var(--rot, 0deg)) scale(1); }
    100% { opacity: 0; transform: translate(-50%, -50%) rotate(var(--rot, 0deg)) scale(0.82); }
}

@media (max-width: 960px) {
    /* order -1 pulls these into the content flow (space window above the
       keyphrase-2 heading, board window just after the FAQ) instead of
       dropping to the bottom with the spacer rows */
    .bt-window-space {
        order: 45;               /* anim1: just below the row-4 writeup (order 40) */
        min-height: 220px;
    }

    /* The AI data-centre scene holds an IN-FLOW <svg>, so it needs a DEFINITE
       height for the svg's height:100% to resolve. With only min-height the
       window kept extra height and its black background showed below the art. */
    .bt-window-dc,
    .bt-window-web,
    .bt-window-video {
        order: 45;
        flex: 0 0 200px;
        height: 200px;
        min-height: 200px;
        margin-top: -24px;
    }

    /* the Games mini-game needs more room for the canvas + control buttons */
    .bt-window-game {
        order: 45;
        flex: 0 0 380px;
        height: 380px;
        min-height: 380px;
        margin-top: -24px;
    }

    /* anim3 (board): just below the FAQ, at its desktop height (196px),
       flush (cancel the flex gap) with a darkgray row line beneath it */
    .bt-window-board {
        order: 150;
        flex: 0 0 196px;
        height: 196px;
        min-height: 196px;
        margin-top: -24px;
        padding-bottom: 0 !important;
        border-bottom: 1px solid darkgray;
    }

    /* cancel the 24px column gap above anim1 / anim2 so they sit flush with the
       element above, as they do on desktop */
    .bt-window-space,
    .bt-window-matrix {
        margin-top: -24px;
    }
}

/* ===== AI page: "AI agents working in a data centre" scene (row 4 / cell 3).
   Self-contained SVG + CSS (no WebGL). Sci-fi neon on deep navy. ===== */
.bt-window-dc { background: #03050e; }
/* Absolutely fill the window so the scene always covers it, regardless of how
   the height resolves (grid cell on desktop, flex item on mobile). This removes
   the black strip that showed below the art in compact / mobile layouts. */
.dc-scene { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }

/* Grayscale at rest, full sci-fi colour on hover (pointer devices only —
   touch devices, which can't hover, keep it in colour). */
@media (hover: hover) {
    .bt-window-dc { filter: grayscale(1); transition: filter 450ms ease; }
    .bt-window-dc:hover { filter: grayscale(0); }
}

/* ===== Web page: spider-web scene (row 4 / cell 3) ===== */
.bt-window-web { background: #05090b; }
.web-scene { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }

/* web strands gently shimmer */
.web-strands { animation: web-shimmer 5s ease-in-out infinite; }
@keyframes web-shimmer { 0%, 100% { opacity: 0.42; } 50% { opacity: 0.62; } }

/* spiders bob up/down in their own columns, drifting in and out of line so they
   spell WEB when level. Different periods keep the motion looking random. */
.web-bob-1 { animation: web-bob-1 4.6s ease-in-out infinite; }
.web-bob-2 { animation: web-bob-2 5.5s ease-in-out infinite; }
.web-bob-3 { animation: web-bob-3 3.9s ease-in-out infinite; }
@keyframes web-bob-1 { 0%, 100% { transform: translateY(-20px); } 50% { transform: translateY(18px); } }
@keyframes web-bob-2 { 0%, 100% { transform: translateY(16px); } 50% { transform: translateY(-22px); } }
@keyframes web-bob-3 { 0% { transform: translateY(-14px); } 30% { transform: translateY(20px); } 65% { transform: translateY(-18px); } 100% { transform: translateY(-14px); } }

/* subtle leg twitch */
.web-legs { transform-box: fill-box; transform-origin: center; animation: web-legs 0.5s ease-in-out infinite alternate; }
@keyframes web-legs { from { transform: scaleX(1); } to { transform: scaleX(1.06); } }

/* comic bugs cross the web at intervals (different directions / timings) */
.web-bug-1 { animation: web-bug-cross 9s linear infinite; }
.web-bug-2 { animation: web-bug-cross-2 12s linear infinite; animation-delay: 4s; }
@keyframes web-bug-cross {
    0%   { transform: translate(-34px, 104px); opacity: 0; }
    7%   { opacity: 1; }
    93%  { opacity: 1; }
    100% { transform: translate(400px, 80px); opacity: 0; }
}
@keyframes web-bug-cross-2 {
    0%   { transform: translate(400px, 52px); opacity: 0; }
    7%   { opacity: 1; }
    93%  { opacity: 1; }
    100% { transform: translate(-34px, 168px); opacity: 0; }
}
.web-bug-wob { animation: web-bug-wob 0.5s ease-in-out infinite alternate; }
@keyframes web-bug-wob { from { transform: translateY(-2px); } to { transform: translateY(3px); } }

@media (prefers-reduced-motion: reduce) {
    .web-strands, .web-bob-1, .web-bob-2, .web-bob-3, .web-legs,
    .web-bug-1, .web-bug-2, .web-bug-wob {
        animation: none;
    }
}

/* AI page sticky note (row 6 / cell 3): 240x240 yellow paper note, pinned at the
   upper-left, parked at the middle-right of the cell, 24px before the C3 line.
   Desktop only. */
.bt-stickynote {
    position: relative;
    z-index: 3;
    justify-self: end;          /* right side of cell C3 */
    align-self: start;          /* upper side of the row */
    margin-right: 36px;
    margin-top: 36px;
    box-sizing: border-box;
    width: 240px;
    height: 240px;
    padding: 22px 18px 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    /* hand-written look — blue ballpen ink on the paper */
    color: #1b3a8f;
    font-family: "Segoe Script", "Bradley Hand", "Comic Sans MS", "Brush Script MT", cursive;
    font-size: 16px;
    line-height: 1.4;
    font-weight: 600;
    border-radius: 2px;
    box-shadow: 3px 5px 12px rgba(0, 0, 0, 0.28);
    transform: rotate(3deg);    /* tilt toward the right */
    transform-origin: 18px 4px; /* swing from the pushpin head (top-left) */
    transition: transform 0.55s var(--bt-ease);   /* smooth swing back on hover-out */
    /* paper texture: soft light sheen + faint crosshatch fibres over a gently
       shaded yellow base */
    background-color: #fff3a6;
    background-image:
        radial-gradient(115% 120% at 22% 12%, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0) 55%),
        repeating-linear-gradient(0deg, rgba(90, 70, 0, 0.045) 0 1px, transparent 1px 4px),
        repeating-linear-gradient(90deg, rgba(90, 70, 0, 0.035) 0 1px, transparent 1px 5px),
        linear-gradient(180deg, #fff8b8, #ffef88);
}
/* pushpin needle (behind the head) */
.bt-stickynote::before {
    content: "";
    position: absolute;
    top: 12px;
    left: 17px;
    width: 3px;
    height: 12px;
    border-radius: 0 0 2px 2px;
    background: linear-gradient(#ececec, #8c8c8c 60%, #555);
    box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.25);
    transform: rotate(10deg);
    transform-origin: top center;
}
/* pushpin head (glossy red dome, upper-left corner, on top) */
.bt-stickynote::after {
    content: "";
    position: absolute;
    top: -8px;
    left: 6px;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: radial-gradient(circle at 34% 30%, #ffb3b3 0 14%, #ef4444 46%, #a11a1a 100%);
    box-shadow:
        0 4px 6px rgba(0, 0, 0, 0.4),
        inset -2px -2px 3px rgba(0, 0, 0, 0.35),
        inset 2px 2px 4px rgba(255, 255, 255, 0.55);
}
/* Light-blue paper variant (Apps page) — same note/texture, blue tones. */
.bt-stickynote-blue {
    background-color: #d6ecff;
    background-image:
        radial-gradient(115% 120% at 22% 12%, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0) 55%),
        repeating-linear-gradient(0deg, rgba(20, 50, 95, 0.05) 0 1px, transparent 1px 4px),
        repeating-linear-gradient(90deg, rgba(20, 50, 95, 0.04) 0 1px, transparent 1px 5px),
        linear-gradient(180deg, #e2f2ff, #bfe0fb);
}

/* Apps page: device line-up (row 8 / cell 3) — 300x600 column on the right,
   24px before the last vertical line, desktop only. */
.bt-devices {
    justify-self: end;
    align-self: center;          /* vertically centred — equal top/bottom margins */
    /* Box right edge sits 210px from the line, keeping a ~36px gap to the now
       wider MAUI block (MAUI right margin 36 + glyph block ~138 visible + 36
       gap). Width hugs the content (widest = the "Android Phone" label) so the
       group's rightmost point is ~36px from MAUI's leftmost point. */
    margin-right: 196px;
    width: max-content;
    height: 600px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: center;
    z-index: 2;
    pointer-events: none;
}
.bt-dev-defs { position: absolute; width: 0; height: 0; }
.bt-device { display: flex; flex-direction: column; align-items: center; gap: 5px; pointer-events: auto; }
.bt-dev-ico { height: 62px; width: auto; display: block; filter: drop-shadow(0 3px 4px rgba(0, 0, 0, 0.22)); }
.bt-dev-name { font-size: 12px; font-weight: 600; letter-spacing: 0.02em; color: var(--bt-text); white-space: nowrap; }
/* "MAUI" appears centred on a device's screen while it's hovered */
.bt-dev-maui { opacity: 0; transition: opacity 0.25s ease; }
.bt-device:hover .bt-dev-maui { opacity: 1; }
/* Purple tick centred on every device screen while the MAUI block is hovered */
.bt-dev-check { opacity: 0; transition: opacity 0.25s ease; }
.bt-grid:has(.bt-maui-label:hover) .bt-dev-check,
.bt-grid:has(.bt-blazor-label:hover, .bt-pwa-svg:hover) .bt-dev-check { opacity: 1; }

/* Big vertical MAUI block between the device group and the last vertical line.
   Vertical span matches the device group (top of first device → last device's
   name). Right margin (to the line) and left gap (to the device group) are both
   36px — meant to equal the gap above the first device. The 4 sideways letters
   are sized up to fill the ~600px height, spaced ~one cap-height ("I") apart. */
.bt-maui-label {
    justify-self: end;
    align-self: center;
    margin-right: 36px;          /* right margin from the vertical line */
    transform: translate(20px, 18px); /* nudged 20px right, 18px below centre */
    width: 144px;                /* glyph block width (line-height x font-size) */
    height: 600px;               /* = device group height */
    display: flex;
    align-items: flex-start;     /* anchor M to the top; I reaches the bottom */
    justify-content: center;
    writing-mode: vertical-rl;
    text-orientation: sideways;  /* each character rotated 90° */
    line-height: 0.78;           /* tighten cross-axis toward the cap height */
    font-size: 184px;            /* enlarged so the 4 letters fill the height with small gaps */
    font-weight: 800;
    letter-spacing: 36px;        /* ~36px gap between the letters */
    color: var(--bt-text);       /* page text colour */
    z-index: 1;
    pointer-events: auto;        /* hoverable: turns all letters MAUI-purple */
    user-select: none;
}
/* hover any letter → all four turn MAUI brand purple */
.bt-maui-label:hover { color: #512BD4; }

/* Web page: same device line-up, but a narrower BLAZOR label (6 letters). The
   device group sits 150px from the line to keep a ~36px gap to the label. */
.bt-devices.bt-web-devices { margin-right: 150px; }
.bt-blazor-label {
    justify-self: end;
    align-self: center;
    transform: translate(6px, 18px); /* whole group nudged 6px right, 18px down */
    margin-right: 36px;          /* right margin from the vertical line */
    width: 80px;                 /* glyph block width (line-height x font-size) */
    height: 600px;               /* = device group height */
    display: flex;
    align-items: flex-end;       /* anchor the letters to the LEFT of the box */
    justify-content: center;
    writing-mode: vertical-rl;
    text-orientation: sideways;  /* each character rotated 90° */
    line-height: 0.72;
    font-size: 112px;            /* enlarged to fill the column → right edge matches PWA */
    font-weight: 800;
    letter-spacing: 36px;        /* ~36px gap between the letters */
    color: var(--bt-text);
    z-index: 1;
    pointer-events: auto;        /* hoverable: turns all letters Blazor-purple */
    user-select: none;
}
/* BLAZOR + PWA act as one hover group: hovering either turns both purple */
.bt-grid:has(.bt-blazor-label:hover, .bt-pwa-svg:hover) .bt-blazor-label { color: #512BD4; }
.bt-grid:has(.bt-blazor-label:hover, .bt-pwa-svg:hover) .bt-pwa-svg text { fill: #512BD4; }

/* "PWA" written horizontally below BLAZOR — same width as the BLAZOR group,
   height proportional, bottom anchored to the device group's bottom. */
.bt-pwa-label {
    justify-self: end;
    align-self: center;
    transform: translateX(-2px); /* nudged 2px left */
    margin-right: 36px;          /* same column as BLAZOR */
    width: 80px;                 /* = BLAZOR group width */
    height: 600px;               /* = device group height */
    display: flex;
    align-items: flex-end;       /* PWA sits at the bottom (device group bottom) */
    justify-content: center;
    z-index: 1;
    pointer-events: none;
}
.bt-pwa-svg { width: 80px; height: auto; display: block; pointer-events: auto; }
.bt-pwa-svg text { fill: var(--bt-text); font-family: Arial, sans-serif; font-weight: 800; }
@media (max-width: 1199px) { .bt-devices, .bt-maui-label, .bt-blazor-label, .bt-pwa-label { display: none; } }

/* Hide as soon as the burger menu appears (≤1199px); visible only on the full
   desktop layout where the inline header menu is shown. */
@media (max-width: 1199px) {
    .bt-stickynote { display: none; }
}

/* ===== AI page agent photo (cell 3, standing below the sticky note) =====
   Visibility matches the sticky note: desktop only. Drop the photo at
   wwwroot/assets/images/ai-agent.png (transparent PNG/WebP recommended). */
.bt-bot-photo {
    align-self: end;            /* stand on the floor (bottom of the cell) */
    justify-self: end;          /* hug the right side of cell 3 */
    margin-right: 8px;          /* small inset from the C3 vertical line */
    height: 400px;
    width: auto;
    max-width: 100%;
    object-fit: contain;
    object-position: bottom right;
    z-index: 2;                 /* sits in front of the data-centre scene */
    pointer-events: auto;       /* hoverable, so it can nudge the sticky note */
    filter: drop-shadow(0 8px 10px rgba(0, 0, 0, 0.30));   /* grounded depth */
}
/* Hovering the agent character swings the sticky note on its pushpin, then it
   eases back to rest when the pointer leaves. */
.bt-grid:has(.bt-bot-photo:hover) .bt-stickynote {
    transform: rotate(8deg);
}
/* Apps page: swing the opposite way (counter-clockwise). */
.bt-grid:has(.bt-bot-photo:hover) .bt-stickynote-blue {
    transform: rotate(-2deg);
}
@media (max-width: 1199px) {
    .bt-bot-photo { display: none; }   /* desktop only, like the sticky note */
}

/* ===== Web page: grayscale mini-logo watermark (row 6 / cell 3) =====
   Anchored to the left of cell 3 and vertically centred, scaled proportionally
   (contain) with >=48px top/bottom margins. Sits behind the writeup text; hidden
   on narrower widths (burger/stacked) where it would crowd the cell 1–2 text. */
.bt-pool {
    justify-self: stretch;      /* spans the whole row (cells 1-3); logo sits in cell 3 */
    align-self: stretch;        /* fill the row height */
    width: 100%;
    pointer-events: none;       /* never blocks text; ripples driven via window mousemove */
    position: relative;
    /* Fallback when WebGL is unavailable: the static grayscale logo, kept in the
       cell-3 area (~75% across) with >=48px top/bottom margin. Hidden once the GL
       pool takes over. */
    background-image: url('assets/images/binarythinkers-logo-grayscale-mini-with-transparent-background.svg');
    background-repeat: no-repeat;
    background-position: 75% center;
    background-size: contain;
    background-origin: content-box;
    padding: 48px 0;
}
.bt-pool.gl-ready { background-image: none; padding: 0; }   /* canvas takes over */
.bt-pool-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
@media (max-width: 1199px) {
    .bt-pool { display: none; }   /* desktop only, like the other cell-3 chrome */
}

/* server-rack neon edge + blinking status LEDs */
.dc-rack-edge { filter: drop-shadow(0 0 3px rgba(210, 218, 230, 0.65)); }
.dc-led {
    fill: #d9e0ea;
    filter: drop-shadow(0 0 2px rgba(210, 218, 230, 0.85));
    animation: dc-led-blink 2.4s ease-in-out infinite;
}
.dc-led-g { fill: #cccc33; filter: drop-shadow(0 0 2px rgba(204, 204, 51, 0.85)); }
.dc-led-m { fill: #f4c542; filter: drop-shadow(0 0 2px rgba(244, 197, 66, 0.85)); }
@keyframes dc-led-blink { 0%, 100% { opacity: 0.25; } 50% { opacity: 1; } }

/* a bright scan line sweeping down each rack */
.dc-rack-scan { animation: dc-rack-scan 3.2s linear infinite; }
@keyframes dc-rack-scan {
    0%   { transform: translateY(0);    opacity: 0; }
    12%  { opacity: 0.85; }
    88%  { opacity: 0.85; }
    100% { transform: translateY(96px); opacity: 0; }
}

/* perspective floor grid — gentle pulse */
.dc-floor { animation: dc-floor-pulse 4s ease-in-out infinite; }
@keyframes dc-floor-pulse { 0%, 100% { opacity: 0.7; } 50% { opacity: 1; } }

/* data streams flowing toward the holo panel */
.dc-flow {
    stroke: #d9e0ea;
    stroke-width: 1.4;
    stroke-dasharray: 6 10;
    filter: drop-shadow(0 0 2px rgba(210, 218, 230, 0.85));
    animation: dc-flow 1.4s linear infinite;
}
.dc-flow-m { stroke: #f4c542; filter: drop-shadow(0 0 2px rgba(244, 197, 66, 0.85)); }
@keyframes dc-flow { to { stroke-dashoffset: -32; } }

/* hovering AI-agent drones */
.dc-bob1 { animation: dc-bob 4s ease-in-out infinite; }
.dc-bob2 { animation: dc-bob 5.2s ease-in-out infinite; }
.dc-drift { animation: dc-drift 15s ease-in-out infinite; }
@keyframes dc-bob { 0%, 100% { transform: translateY(-4px); } 50% { transform: translateY(5px); } }
@keyframes dc-drift { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(104px); } }

/* robot-head agents */
.dc-head { filter: drop-shadow(0 0 4px rgba(210, 218, 230, 0.55)); }
.dc-head-m { filter: drop-shadow(0 0 4px rgba(244, 197, 66, 0.55)); }
.dc-pupil { filter: drop-shadow(0 0 3px rgba(244, 247, 251, 0.95)); transition: transform 90ms linear; }
.dc-pupil-m { filter: drop-shadow(0 0 3px rgba(255, 220, 120, 0.95)); }
.dc-ant { animation: dc-led-blink 1.6s ease-in-out infinite; }

.dc-ring, .dc-ring-r { transform-box: fill-box; transform-origin: center; }
.dc-ring { animation: dc-spin 6s linear infinite; }
.dc-ring-r { animation: dc-spin 4.5s linear infinite reverse; }
@keyframes dc-spin { to { transform: rotate(360deg); } }

/* downward scanning beam, sweeping left↔right around its apex */
.dc-beam { transform-box: fill-box; transform-origin: center top; animation: dc-beam-sweep 3.6s ease-in-out infinite; }
@keyframes dc-beam-sweep {
    0%, 100% { transform: rotate(-16deg); opacity: 0.5; }
    50%      { transform: rotate(16deg);  opacity: 0.85; }
}

/* holographic status panel */
.dc-holo { animation: dc-holo-flicker 5s steps(1, end) infinite; }
@keyframes dc-holo-flicker {
    0%, 46% { opacity: 0.95; }
    47% { opacity: 0.55; } 48% { opacity: 0.95; }
    92% { opacity: 0.95; } 93% { opacity: 0.6; } 94%, 100% { opacity: 0.95; }
}
.dc-bar { transform-box: fill-box; transform-origin: center bottom; animation: dc-bar 1.8s ease-in-out infinite; }
@keyframes dc-bar { 0%, 100% { transform: scaleY(0.3); } 50% { transform: scaleY(1); } }

/* drifting data motes */
.dc-dust circle { animation: dc-dust-rise 6s linear infinite; }
@keyframes dc-dust-rise {
    0%   { transform: translateY(0);     opacity: 0; }
    10%  { opacity: 0.9; }
    90%  { opacity: 0.45; }
    100% { transform: translateY(-64px); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .dc-led, .dc-ant, .dc-rack-scan, .dc-floor, .dc-flow,
    .dc-bob1, .dc-bob2, .dc-drift, .dc-ring, .dc-ring-r,
    .dc-beam, .dc-holo, .dc-bar, .dc-dust circle {
        animation: none;
    }
}

/* Home row 7: the keyphrase-1 heading spans cells 2–3, so carry the cell-3
   darkgray accent colour across the whole heading (desktop and mobile). */
.bt-grid:has(.bt-r3c2-accent) > .bt-kp2[style*="grid-row: 7;"] {
    background: darkgray;
}
/* Games page: that row-7 heading band ("Hire Unity Developer") is brand green. */
.bt-grid:has(.bt-games-links) > .bt-kp2[style*="grid-row: 7;"] {
    background: #cccc33;
}
/* Apps page: the row-7 heading text ("Hire MAUI Developer") is brand green. */
.bt-grid:has(.bt-maui-label) > .bt-kp2[style*="grid-row: 7;"] {
    color: #cccc33;
}
/* Web page: the row-7 heading ("Hire Blazor Developer") — black band, brand-green text. */
.bt-grid:has(.bt-blazor-label) > .bt-kp2[style*="grid-row: 7;"] {
    background: black;
    color: #cccc33;
}

/* Row 7 / cell 3 (home): Windows-style window controls, right-anchored over the
   darkgray title-bar row. Decorative; desktop only (hidden < 960px below). */
.bt-winctrls {
    display: flex;
    align-items: stretch;
    justify-content: flex-end;   /* anchor the trio to the right of cell 3 */
    z-index: 2;                  /* above the heading background */
    pointer-events: none;        /* only the buttons react to hover */
}
.bt-winbtn {
    position: relative;
    width: 46px;
    pointer-events: auto;
    transition: background-color 150ms ease;
}
.bt-winbtn::before,
.bt-winbtn::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    background: #2b2b2b;         /* dark glyph on the medium-gray bar */
}
.bt-winbtn-min::before {         /* minimize: one horizontal bar */
    width: 12px;
    height: 1px;
    transform: translate(-50%, -50%);
}
.bt-winbtn-max::before {         /* maximize: a square outline */
    width: 11px;
    height: 11px;
    background: transparent;
    border: 1px solid #2b2b2b;
    transform: translate(-50%, -50%);
}
.bt-winbtn-close::before,        /* close: two crossed bars */
.bt-winbtn-close::after {
    width: 14px;
    height: 1px;
}
.bt-winbtn-close::before { transform: translate(-50%, -50%) rotate(45deg); }
.bt-winbtn-close::after { transform: translate(-50%, -50%) rotate(-45deg); }
.bt-winbtn-min:hover,
.bt-winbtn-max:hover { background-color: #fff; }   /* white background on hover */
.bt-winbtn-close:hover { background-color: #e81123; }   /* Windows close red */
.bt-winbtn-close:hover::before,
.bt-winbtn-close:hover::after { background: #fff; }

/* Row 9 / cell 1: macOS-style traffic-light buttons overlaid on the matrix,
   top-left like a window. The dark glyphs appear when the cluster is hovered. */
.bt-macbtns-row {
    position: absolute;
    top: 14px;
    left: 16px;
    z-index: 8;                  /* above the matrix scene canvas (z-index 6) */
    display: inline-flex;
    gap: 8px;
    pointer-events: auto;        /* only the small cluster is interactive */
}
.bt-macbtn {
    position: relative;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    box-shadow: inset 0 0 0 0.5px rgba(0, 0, 0, 0.25);  /* subtle rim */
}
.bt-macbtn-close { background: #ff5f57; }   /* red */
.bt-macbtn-min { background: #febc2e; }     /* yellow */
.bt-macbtn-zoom { background: #28c840; }    /* green */
.bt-macbtn::before,
.bt-macbtn::after {
    content: "";
    position: absolute;
    opacity: 0;                  /* symbols hidden until the cluster is hovered */
    transition: opacity 120ms ease;
}
.bt-macbtns-row:hover .bt-macbtn::before,
.bt-macbtns-row:hover .bt-macbtn::after { opacity: 1; }
/* close: an x */
.bt-macbtn-close::before,
.bt-macbtn-close::after {
    left: 50%;
    top: 50%;
    width: 7px;
    height: 1.3px;
    background: #4d0000;
}
.bt-macbtn-close::before { transform: translate(-50%, -50%) rotate(45deg); }
.bt-macbtn-close::after { transform: translate(-50%, -50%) rotate(-45deg); }
/* minimize: a single bar */
.bt-macbtn-min::before {
    left: 50%;
    top: 50%;
    width: 7px;
    height: 1.3px;
    background: #5c3d00;
    transform: translate(-50%, -50%);
}
/* zoom: two fullscreen triangles (top-left + bottom-right) */
.bt-macbtn-zoom::before,
.bt-macbtn-zoom::after {
    width: 4px;
    height: 4px;
    background: #003d00;
}
.bt-macbtn-zoom::before {
    top: 2.5px;
    left: 2.5px;
    clip-path: polygon(0 0, 100% 0, 0 100%);          /* points to the top-left */
}
.bt-macbtn-zoom::after {
    bottom: 2.5px;
    right: 2.5px;
    clip-path: polygon(100% 0, 100% 100%, 0 100%);    /* points to the bottom-right */
}

/* Row 15: Android-style navigation bar (back / home / recents) overlaid on the
   board ("AI chip") scene, centered 6px above the bottom edge. */
.bt-navbtns {
    position: absolute;
    left: 50%;
    bottom: 6px;
    transform: translateX(-50%);
    z-index: 8;                  /* above the board scene canvas (z-index 6) */
    display: flex;
    align-items: center;
    gap: 52px;                   /* spread apart like an Android nav bar */
    pointer-events: none;        /* decorative */
}
.bt-navbtn-back {                /* back: left-pointing triangle */
    width: 0;
    height: 0;
    border-top: 6px solid transparent;
    border-bottom: 6px solid transparent;
    border-right: 11px solid #d4d4d4;
}
.bt-navbtn-home {                /* home: circle */
    width: 13px;
    height: 13px;
    border: 1.5px solid #d4d4d4;
    border-radius: 50%;
}
.bt-navbtn-recent {              /* recents: rounded square */
    width: 12px;
    height: 12px;
    border: 1.5px solid #d4d4d4;
    border-radius: 2px;
}

/* Glow cyan on hover. The container is pointer-events:none (decorative), so
   re-enable hit-testing on the buttons themselves. drop-shadow follows each
   shape (incl. the triangle), giving a neon glow. */
.bt-navbtn-back,
.bt-navbtn-home,
.bt-navbtn-recent {
    pointer-events: auto;
    transition: filter 150ms ease, border-color 150ms ease;
}
.bt-navbtn-home:hover,
.bt-navbtn-recent:hover {
    border-color: #00e5ff;
    filter: drop-shadow(0 0 5px #00e5ff) drop-shadow(0 0 9px #00e5ff);
}
.bt-navbtn-back:hover {
    border-right-color: #00e5ff;
    filter: drop-shadow(0 0 5px #00e5ff) drop-shadow(0 0 9px #00e5ff);
}

/* Easter egg: a laughing-cat emoji pops over a clicked (decorative) window
   button — Android nav, the row-7 Windows controls or the row-9 macOS dots —
   24x24, wiggles like a laugh, then fades away after 2s (script in App.razor). */
.bt-cat-pop {
    position: fixed;
    width: 24px;
    height: 24px;
    font-size: 24px;
    line-height: 24px;
    text-align: center;
    transform: translate(-50%, -50%);
    pointer-events: none;
    z-index: 9999;
    animation: bt-cat-pop 2s ease forwards;
    will-change: transform, opacity;
}
@keyframes bt-cat-pop {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.4) rotate(0deg); }
    12%  { opacity: 1; transform: translate(-50%, -56%) scale(1.2) rotate(-14deg); }
    28%  {              transform: translate(-50%, -56%) scale(1) rotate(14deg); }
    44%  {              transform: translate(-50%, -58%) scale(1.06) rotate(-10deg); }
    60%  {              transform: translate(-50%, -56%) scale(1) rotate(10deg); }
    75%  { opacity: 1;  transform: translate(-50%, -56%) scale(1) rotate(-6deg); }
    100% { opacity: 0;  transform: translate(-50%, -74%) scale(0.95) rotate(0deg); }
}

@media (max-width: 960px) {
    .bt-r1c3-accent,
    .bt-r3c2-accent,
    .bt-r16c3-accent,
    .bt-r17c3-accent,
    .bt-winctrls {
        display: none;
    }

    /* Row 3: show the green present-era strip on mobile too, between the marquee
       (order 20) and the row-4 writeup (order 40). Overrides the hide above. */
    .bt-grid:has(.bt-r3c2-accent) > .bt-r3c2-accent {
        display: block;
        order: 30;
        flex: 0 0 12px;
        height: 12px;
        min-height: 12px !important;
        margin-top: -24px;
        padding: 0 !important;
        box-sizing: border-box;
        border-bottom: 1px solid darkgray;
    }

    /* the cell-1 scene (stairs + walking icon + Contact) shows after anim3 and
       the row-16 divider strip, at its desktop height (row 17 = 300px). A
       definite height is required so the stairs' percentage height resolves
       (min-height alone leaves the staircase at zero on mobile). */
    .bt-stairs-scene {
        order: 170;
        flex: 0 0 300px;
        height: 300px;
        min-height: 300px;
        margin-top: -24px;
        padding-bottom: 0 !important;   /* beat the mobile content padding so the stairs sit on the bottom */
        border-bottom: 1px solid darkgray;
    }

    /* Home mobile bottom: keep only anim3 -> row-16 strip -> scene below the
       FAQ. Hide the desktop scaffolding spacer bands that otherwise pile up
       after the content (scoped to home via the C2 green accent marker). */
    .bt-grid:has(.bt-r3c2-accent) .bt-r2-spacer,
    .bt-grid:has(.bt-r3c2-accent) .bt-r3-spacer,
    .bt-grid:has(.bt-r3c2-accent) .bt-r4-spacer,
    .bt-grid:has(.bt-r3c2-accent) .bt-r5-spacer,
    .bt-grid:has(.bt-r3c2-accent) .bt-r6-spacer,
    .bt-grid:has(.bt-r3c2-accent) .bt-r7-spacer,
    .bt-grid:has(.bt-r3c2-accent) .bt-r8-spacer,
    .bt-grid:has(.bt-r3c2-accent) .bt-rfill-spacer,
    .bt-grid:has(.bt-r3c2-accent) .bt-r13-spacer,
    .bt-grid:has(.bt-r3c2-accent) .bt-r14-spacer,
    .bt-grid:has(.bt-r3c2-accent) .bt-r15-spacer,
    .bt-grid:has(.bt-r3c2-accent) .bt-r16-spacer {
        display: none;
    }

    /* Cell 2 of row 16: the 12px white divider strip shown between anim3 and
       the scene, at its desktop height. */
    .bt-grid:has(.bt-r3c2-accent) .bt-r15c2-accent {
        display: block;
        order: 160;
        flex: 0 0 12px;
        height: 12px;
        /* !important beats the grid-row:16 utility (min-height:288px) and the
           mobile content padding (padding-bottom:24px), both higher specificity */
        min-height: 12px !important;
        margin-top: -24px;
        padding-bottom: 0 !important;
        box-sizing: border-box;
        border-bottom: 1px solid darkgray;
    }

    /* row-9 black band stays visible on mobile, as a full-width 96px band,
       sitting between the keyphrase-3 writeup and the FAQ */
    .bt-r9c12-accent {
        order: 90;               /* anim2: just below the row-8 writeup (order 80) */
        flex: 0 0 96px;
    }

    /* Marquee pages (home + AI/Web/Apps/Games): explicit mobile stacking order so
       the column follows the desktop top-to-bottom flow. The chrome is rendered
       by a shared component near the top of the page, so source order can't be
       relied on. anim1 (space, order 45) lands below the row-4 writeup; anim2
       (matrix, order 90) below the row-8 writeup. Scoped via the C2 marker, so
       Future/Past and other pages are unaffected. */
    .bt-grid:has(.bt-r3c2-accent) > [style*="grid-row: 2;"]:not([class*="-spacer"]):not([class*="-accent"]) { order: 20; }
    .bt-grid:has(.bt-r3c2-accent) > .bt-writeup[style*="grid-row: 4;"] { order: 40; }
    .bt-grid:has(.bt-r3c2-accent) > .bt-kp2[style*="grid-row: 5;"] { order: 50; }
    .bt-grid:has(.bt-r3c2-accent) > .bt-writeup[style*="grid-row: 6;"] { order: 60; }
    .bt-grid:has(.bt-r3c2-accent) > .bt-kp2[style*="grid-row: 7;"] { order: 70; }
    .bt-grid:has(.bt-r3c2-accent) > .bt-writeup[style*="grid-row: 8;"] { order: 80; }
    .bt-grid:has(.bt-r3c2-accent) > .bt-faq { order: 100; }

    /* On mobile keep only the FAQ's bottom line; the right-edge line is
       desktop-only. */
    .bt-faq {
        border-right: none;
    }

    /* Home page: keep the row-5 (white) and row-7 (darkgray) heading
       backgrounds in mobile too, matching the desktop accent cells that
       mobile otherwise drops. Scoped to home via its unique .bt-r3c2-accent. */
    .bt-grid:has(.bt-r3c2-accent) > .bt-kp2[style*="grid-row: 5;"],
    .bt-grid:has(.bt-r3c2-accent) > .bt-kp2[style*="grid-row: 7;"] {
        /* Band that vertically centres the heading. Allow the heading to WRAP on
           narrow screens — with nowrap a long keyphrase overflowed the column to
           the right, under the burger / quick-action icons. min-height keeps the
           48px band for short headings; it grows for wrapped ones. */
        display: flex;
        align-items: center;
        min-height: 48px;
        white-space: normal;
        overflow: hidden;
        line-height: 1.15;
        margin-top: -24px;
        margin-bottom: -24px;
        /* cancel the generic mobile content padding-bottom:24px so the text is
           truly vertically centred (equal top/bottom) */
        padding: 6px 24px !important;
    }

    .bt-grid:has(.bt-r3c2-accent) > .bt-kp2[style*="grid-row: 5;"] {
        background: white;
    }

    .bt-grid:has(.bt-r3c2-accent) > .bt-kp2[style*="grid-row: 7;"] {
        background: darkgray;
    }

    /* Games page: that row-7 heading band ("Hire Unity Developer") stays brand green on mobile too. */
    .bt-grid:has(.bt-games-links) > .bt-kp2[style*="grid-row: 7;"] {
        background: #cccc33;
    }

    /* Web page: that row-7 band stays black (brand-green text) on mobile too. */
    .bt-grid:has(.bt-blazor-label) > .bt-kp2[style*="grid-row: 7;"] {
        background: black;
    }
}

/* ===== Menu robo-icons =====
   36×36, art centered, transparent background. Each icon takes a
   2-second turn on a shared 32s clock, turns passing every 8s, one icon
   at a time. Hovering the menu pauses everything; on leave, the cycle
   resumes where it was. */
.bt-ico {
    flex: 0 0 60px;
    width: 60px;
    height: 60px;
    /* Very light logo-green glow behind every menu icon */
    filter: drop-shadow(0 1px 4px rgba(204, 204, 51, 0.55));
}

/* On the page you're currently in (AI / Web / Apps / Games) that item's
   icon gets a black shadow instead, marking where you are */
.bt-menu a.active .bt-ico {
    filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.5));
}

/* Menu labels grow to 2× during their icon's turn; anchored on their
   right edge so the distance to the icon never changes */
.bt-label {
    display: inline-block;
    transform-origin: right center;
}

.bt-menu a:nth-child(1) .bt-label { animation: bt-turn-label 32s linear 8s  infinite; }
.bt-menu a:nth-child(2) .bt-label { animation: bt-turn-label 32s linear 16s infinite; }
.bt-menu a:nth-child(3) .bt-label { animation: bt-turn-label 32s linear 24s infinite; }
.bt-menu a:nth-child(4) .bt-label { animation: bt-turn-label 32s linear 32s infinite; }

.bt-ico-ai    { animation: bt-turn-bounce  32s linear 8s  infinite; }
.bt-ico-web   { animation: bt-turn-scuttle 32s linear 16s infinite; }
.bt-ico-apps  { animation: bt-turn-vibrate 32s linear 24s infinite; }

/* Robo-ghost: the body floats and lunges toward the pellets (the ground
   shadow stays put), and the pellets get eaten */
.bt-ico-games .gm-body {
    animation: bt-turn-ghost 32s linear 32s infinite;
}

.gm-dots {
    animation: bt-turn-dots 32s linear 32s infinite;
}

/* Eyes light up in the logo green during each robot's turn */
.bt-ico-ai .bt-eye    { animation: bt-turn-eyes 32s linear 8s  infinite; }
.bt-ico-web .bt-eye   { animation: bt-turn-eyes 32s linear 16s infinite; }
.bt-ico-apps .bt-eye  { animation: bt-turn-eyes 32s linear 24s infinite; }
.bt-ico-games .bt-eye { animation: bt-turn-eyes 32s linear 32s infinite; }

/* Hovering the menu stops the show smoothly: animations are removed and
   1s transitions ease every part back to its resting state */
.bt-ico,
.bt-eye,
.gm-dots,
.gm-body,
.bt-label {
    transition: transform 1s ease, fill 1s ease, opacity 1s ease, filter 0.6s ease;
}

.bt-menu:hover .bt-ico,
.bt-menu:hover .gm-dots,
.bt-menu:hover .bt-ico-games .gm-body,
.bt-menu:hover .bt-eye,
.bt-menu:hover a:nth-child(n) .bt-label {
    animation: none;
}

/* ===== Hover particle burst around a menu item =====
   Tiny green/silver sparks drift up and fade, staggered, while hovered */
.bt-fx {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: visible;
    /* the vortex leans toward the cursor (vars set by a tiny script) */
    transform: translate(var(--mx, 0px), var(--my, 0px));
    transition: transform 0.3s ease;
}

.bt-fx i {
    position: absolute;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: #CCCC33;
    opacity: 0;
}

.bt-fx i:nth-child(even) {
    width: 4px;
    height: 4px;
    background: #9aa0a8;
}

/* Tornado vortex: each particle orbits the group's center on its own
   ring — wide and slow at the top, tight and fast at the bottom — with
   opacity/scale dipping on the "far side" for depth. Negative delays
   spread them around the funnel. */
.bt-fx i { left: 50%; margin-left: -2px; }

.bt-fx i:nth-child(1) { top: 12%; --r: 64px; --t: 1.6s; }
.bt-fx i:nth-child(2) { top: 22%; --r: 56px; --t: 1.5s; animation-delay: -0.4s !important; }
.bt-fx i:nth-child(3) { top: 34%; --r: 48px; --t: 1.4s; animation-delay: -0.8s !important; }
.bt-fx i:nth-child(4) { top: 46%; --r: 42px; --t: 1.3s; animation-delay: -1.1s !important; }
.bt-fx i:nth-child(5) { top: 58%; --r: 36px; --t: 1.2s; animation-delay: -0.5s !important; }
.bt-fx i:nth-child(6) { top: 70%; --r: 30px; --t: 1.1s; animation-delay: -0.9s !important; }
.bt-fx i:nth-child(7) { top: 82%; --r: 24px; --t: 1.0s; animation-delay: -0.2s !important; }
.bt-fx i:nth-child(8) { top: 92%; --r: 18px; --t: 0.9s; animation-delay: -0.6s !important; }
.bt-fx i:nth-child(9)  { top: 18%; --r: 70px; --t: 1.7s;  animation-delay: -1.3s !important; }
.bt-fx i:nth-child(10) { top: 28%; --r: 60px; --t: 1.55s; animation-delay: -0.7s !important; }
.bt-fx i:nth-child(11) { top: 40%; --r: 52px; --t: 1.45s; animation-delay: -1.0s !important; }
.bt-fx i:nth-child(12) { top: 52%; --r: 44px; --t: 1.35s; animation-delay: -0.3s !important; }
.bt-fx i:nth-child(13) { top: 64%; --r: 38px; --t: 1.25s; animation-delay: -1.2s !important; }
.bt-fx i:nth-child(14) { top: 78%; --r: 28px; --t: 1.05s; animation-delay: -0.45s !important; }

@media (hover: hover) {
    .bt-menu a:hover .bt-fx i {
        animation: bt-tornado var(--t, 1.2s) linear infinite;
    }
}

@keyframes bt-tornado {
    0%   { transform: rotate(0deg)   translateX(var(--r, 40px)) scale(1);   opacity: 0.95; }
    50%  { transform: rotate(180deg) translateX(var(--r, 40px)) scale(0.6); opacity: 0.3; }
    100% { transform: rotate(360deg) translateX(var(--r, 40px)) scale(1);   opacity: 0.95; }
}

/* ===== Hovered item keeps performing while the others rest =====
   These outrank the .bt-menu:hover stop rules, so only the hovered
   group's show continues — in a tight continuous loop. */
@media (hover: hover) {
    .bt-menu a:hover .bt-ico-ai {
        animation: bt-hover-bounce 1.2s ease-in-out infinite;
    }

    .bt-menu a:hover .bt-ico-web {
        animation: bt-hover-scuttle 1s ease-in-out infinite;
    }

    .bt-menu a:hover .bt-ico-apps {
        animation: bt-hover-vibrate 0.9s ease-in-out infinite;
    }

    .bt-menu a:hover .bt-ico-games .gm-body {
        animation: bt-hover-ghost 1.3s ease-in-out infinite;
    }

    .bt-menu a:hover .gm-dots {
        animation: bt-hover-dots 1.3s linear infinite;
    }

    .bt-menu a:hover .bt-eye {
        fill: #CCCC33; /* steady green while its robot performs */
    }

    .bt-menu a:nth-child(n):hover .bt-label {
        animation: bt-label-pulse 2s ease-in-out infinite;
    }
}

@keyframes bt-hover-bounce {
    0%, 100% { transform: translateY(0) rotate(0deg); }
    25%  { transform: translateY(-5px) rotate(-7deg); }
    50%  { transform: translateY(0) rotate(5deg); }
    75%  { transform: translateY(-4px) rotate(-3deg); }
}

@keyframes bt-hover-scuttle {
    0%, 100% { transform: translateX(0) rotate(0deg); }
    25%  { transform: translateX(-4px) rotate(-6deg); }
    75%  { transform: translateX(4px) rotate(6deg); }
}

@keyframes bt-hover-vibrate {
    0%, 100% { transform: rotate(0deg); }
    20%  { transform: rotate(8deg); }
    40%  { transform: rotate(-8deg); }
    60%  { transform: rotate(6deg); }
    80%  { transform: rotate(-6deg); }
}

@keyframes bt-hover-ghost {
    0%, 100% { transform: translate(0, 0); }
    30%  { transform: translate(3px, -4px); }
    60%  { transform: translate(5px, 0); }
    80%  { transform: translate(2px, -3px); }
}

@keyframes bt-hover-dots {
    0%   { transform: translateX(0); opacity: 1; }
    60%  { transform: translateX(-6px); opacity: 0.4; }
    80%  { transform: translateX(-9px); opacity: 0; }
    81%  { transform: translateX(0); opacity: 0; }
    100% { transform: translateX(0); opacity: 1; }
}

@keyframes bt-label-pulse {
    0%, 100% { transform: scale(1); }
    50%  { transform: scale(2); }
}

@keyframes bt-dance {
    0%   { transform: translateY(0) rotate(-6deg); }
    25%  { transform: translateY(-5px) rotate(0deg); }
    50%  { transform: translateY(0) rotate(6deg); }
    75%  { transform: translateY(-5px) rotate(0deg); }
    100% { transform: translateY(0) rotate(-6deg); }
}

/* AI robot: happy bounce with a head tilt (2s of the 32s clock = 6.25%) */
@keyframes bt-turn-bounce {
    0%, 6.25%, 100% { transform: translateY(0) rotate(0deg); }
    1%    { transform: translateY(-5px) rotate(-8deg); }
    2%    { transform: translateY(0) rotate(6deg); }
    3.1%  { transform: translateY(-4px) rotate(-5deg); }
    4.2%  { transform: translateY(0) rotate(3deg); }
    5.2%  { transform: translateY(-2px) rotate(0deg); }
}

/* Spider: skittish side-to-side scuttle */
@keyframes bt-turn-scuttle {
    0%, 6.25%, 100% { transform: translateX(0) rotate(0deg); }
    0.8%  { transform: translateX(-4px) rotate(-6deg); }
    1.7%  { transform: translateX(4px) rotate(6deg); }
    2.6%  { transform: translateX(-4px) rotate(-6deg); }
    3.5%  { transform: translateX(4px) rotate(6deg); }
    4.4%  { transform: translateX(-2px) rotate(-3deg); }
    5.3%  { transform: translateX(0) rotate(0deg); }
}

/* Phone robot: incoming-call vibration, easing out */
@keyframes bt-turn-vibrate {
    0%, 6.25%, 100% { transform: rotate(0deg); }
    0.4%  { transform: rotate(10deg); }
    0.9%  { transform: rotate(-10deg); }
    1.4%  { transform: rotate(10deg); }
    1.9%  { transform: rotate(-10deg); }
    2.4%  { transform: rotate(8deg); }
    2.9%  { transform: rotate(-8deg); }
    3.4%  { transform: rotate(6deg); }
    3.9%  { transform: rotate(-6deg); }
    4.4%  { transform: rotate(4deg); }
    4.9%  { transform: rotate(-2deg); }
    5.4%  { transform: rotate(0deg); }
}

/* Robo-ghost: spooky float, lunging toward the pellets */
@keyframes bt-turn-ghost {
    0%, 6.25%, 100% { transform: translate(0, 0); }
    1%    { transform: translate(2px, -3px); }
    2%    { transform: translate(4px, 0); }
    3%    { transform: translate(2px, -3px); }
    4%    { transform: translate(5px, 0); }
    5%    { transform: translate(2px, -2px); }
}

/* Menu label: grows to 2×, holds, shrinks back */
@keyframes bt-turn-label {
    0%, 6.25%, 100% { transform: scale(1); }
    1.9%  { transform: scale(2); }
    4.4%  { transform: scale(2); }
}

/* ...and the energy pellets get eaten, then respawn */
@keyframes bt-turn-dots {
    0%, 100% { transform: translateX(0); opacity: 1; }
    3%    { transform: translateX(-5px); opacity: 1; }
    5.5%  { transform: translateX(-9px); opacity: 0; }
    6.25% { transform: translateX(0); opacity: 1; }
}

/* Eye glow: gray lens → logo green and back, within the turn window */
@keyframes bt-turn-eyes {
    0%, 6.25%, 100% { fill: #50545a; }
    0.8%, 5.2% { fill: #CCCC33; }
}

@media (prefers-reduced-motion: reduce) {
    .bt-ico,
    .gm-dots,
    .gm-body,
    .bt-eye,
    .bt-label,
    .bt-drawer svg,
    .bt-burger span,
    .bt-main.bt-page-in {
        animation: none;
    }

    .bt-main {
        transition: none;
    }
}

/* Grid items may shrink below their content's natural width (prevents
   text/images from overflowing narrowed columns) */
.bt-grid > :not(.bt-line) {
    min-width: 0;
    min-height: 0;
}

/* Below 960px: every object stacks into the single content column,
   in source order, regardless of its inline grid placement. Guide-line
   elements (.bt-line) are exempt — they're handled by the layout CSS.
   (Global file on purpose — page content isn't reachable from scoped CSS.) */
@media (max-width: 960px) {
    .bt-grid > :not(.bt-line) {
        grid-row: auto !important;
        grid-column: 1 !important;
    }

    /* Horizontal line below each stacked block (mirrors the desktop row lines) */
    .bt-grid > :not(.bt-line):not(.bt-r1c1-accent):not(.bt-r2-spacer):not(.bt-r5-spacer):not(.bt-r7-spacer):not(.bt-r14-spacer):not(:last-child) {
        border-bottom: 1px solid darkgray;
    }

    /* Row line under the green strip — border only, no extra padding,
       so the strip stays exactly 12px like on desktop */
    .bt-grid > .bt-r1c1-accent {
        border-bottom: 1px solid darkgray;
    }

    /* Objects placed in rows 2 or 14 keep the 120px height in mobile too */
    .bt-grid > [style*="grid-row: 2;"],
    .bt-grid > [style*="grid-row: 14;"]:not(.bt-r14-spacer) {
        min-height: 120px;
    }

    /* R2 page content (the headline marquee) renders after the layout's
       spacer bands in source order; pull it just below the green strip
       (order -2) so it isn't buried far down on narrow screens */
    .bt-grid > [style*="grid-row: 2;"]:not([class*="-spacer"]):not([class*="-accent"]) {
        order: -1;
    }

    /* Objects placed in rows 4, 6, 8 or 13 keep the 288px minimum in mobile too */
    .bt-grid > [style*="grid-row: 4;"]:not(.bt-r4-spacer),
    .bt-grid > [style*="grid-row: 6;"]:not(.bt-r6-spacer),
    .bt-grid > [style*="grid-row: 8;"]:not(.bt-r8-spacer),
    .bt-grid > [style*="grid-row: 13;"]:not(.bt-r13-spacer),
    .bt-grid > [style*="grid-row: 16;"]:not(.bt-r16-spacer) {
        min-height: 288px;
    }

    /* Text-type blocks keep equal spacing above their separator;
       images stay flush (no margin) against theirs */
    .bt-grid > :not(.bt-line):not(.bt-r1c1-accent):not(.bt-r17-accent):not(.bt-r2-spacer):not(.bt-r3-spacer):not(.bt-r4-spacer):not(.bt-r5-spacer):not(.bt-r6-spacer):not(.bt-r7-spacer):not(.bt-r8-spacer):not(.bt-rfill-spacer):not(.bt-r13-spacer):not(.bt-r14-spacer):not(.bt-r15-spacer):not(.bt-r16-spacer):not(:last-child):not(.demo-img):not(.demo-img-span):not(.bt-writeup) {
        padding-bottom: 24px;
    }

    /* Keep the keyphrase-2 heading + writeup with the headline near the top
       (same order as the marquee), instead of after the empty spacer bands */
    .bt-grid > .bt-kp2,
    .bt-grid > .bt-writeup,
    .bt-grid > .bt-faq {
        order: -1;
    }

    /* equalize the writeup's top and left margins (both 24px) on mobile.
       margin-top cancels the 24px flex-column gap above it, which otherwise
       stacked on top of the padding and made the top inset far bigger than the left. */
    .bt-grid > .bt-writeup { padding-top: 24px; padding-right: 24px; padding-left: 24px; margin-top: -24px; }

    /* Rows 6 & 8 follow a kp2 heading whose margin-bottom:-24px already cancels the
       gap below it — subtracting it again pulled the body text up against the
       heading. Keep their natural top gap instead. */
    .bt-grid:has(.bt-r3c2-accent) > .bt-writeup[style*="grid-row: 6;"],
    .bt-grid:has(.bt-r3c2-accent) > .bt-writeup[style*="grid-row: 8;"] { margin-top: 0; }
}

/* ===== Burger + slide-down drawer menu =====
   The burger lives in the rightmost 48px header strip (after the last
   vertical line) and only exists while the header menu is hidden.
   The drawer slides out from under the header: above the grid (z 40),
   below the header (z 50). A full-screen backdrop closes it on any
   outside click; the checkbox carries the open state without JS. */

.bt-burger-check {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.bt-burger {
    display: none; /* shown only when the header menu can't fit */
    position: absolute;
    right: 0;
    top: 0;
    height: 100%;
    width: 48px;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    cursor: pointer;
}

.bt-burger span {
    width: 22px;
    height: 2px;
    background: var(--bt-text);
    transition: transform 0.3s ease, opacity 0.3s ease, width 0.3s ease;
}

/* idle nudge: middle bar gently pulses to invite a click */
.bt-burger span:nth-child(2) {
    animation: bt-burger-pulse 2.4s ease-in-out infinite;
}

@keyframes bt-burger-pulse {
    0%, 100% { width: 22px; }
    50% { width: 14px; }
}

.bt-burger:hover span {
    width: 26px;
}

/* open state: morph into an X */
.bt-burger-check:checked ~ .bt-header .bt-burger span:nth-child(1) {
    transform: translateY(7px) rotate(45deg);
}

.bt-burger-check:checked ~ .bt-header .bt-burger span:nth-child(2) {
    opacity: 0;
    animation: none;
}

.bt-burger-check:checked ~ .bt-header .bt-burger span:nth-child(3) {
    transform: translateY(-7px) rotate(-45deg);
}

.bt-drawer {
    position: absolute;
    top: 96px; /* just below the header */
    left: 49px; /* starts where the aside (48px + 1px divider) ends */
    right: 48px; /* ends at the burger column's left edge */
    border-right: 1px solid darkgrey;
    z-index: 40;
    background: var(--bt-bg);
    border-bottom: 1px solid darkgray;
    transform: translateY(-110%);
    transition: transform 0.35s ease;
}

.bt-burger-check:checked ~ .bt-drawer {
    transform: translateY(0);
}

.bt-drawer a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 72px;
    padding: 0 24px;
    color: var(--bt-text);
    text-transform: uppercase;
    text-decoration: none;
    font-size: 0.95rem;
    letter-spacing: 0.06em;
    border-bottom: 1px solid darkgray;
}

.bt-drawer a:last-child {
    border-bottom: none;
}

/* Drawer label grows to 2× on hover (like the header labels during
   their turn), anchored left so it expands toward the middle */
.bt-drawer .bt-label {
    transform-origin: left center;
}

.bt-drawer a:hover .bt-label {
    transform: scale(2);
}

/* Smooth hand-over between rows: when the mouse leaves a row, its dance
   animation is dropped and these transitions ease everything back */
.bt-drawer svg,
.bt-drawer .gm-body {
    transition: transform 1s ease;
}

/* Hovering a drawer row: its robot dances with green eyes until the
   mouse leaves (ghost: body only, so its shadow stays grounded) */
.bt-drawer a:hover svg {
    animation: bt-dance 1.2s ease-in-out infinite;
}

.bt-drawer a:last-child:hover svg {
    animation: none;
}

.bt-drawer a:last-child:hover .gm-body {
    animation: bt-dance 1.2s ease-in-out infinite;
}

.bt-drawer a:hover .bt-eye {
    fill: #CCCC33;
}

.bt-drawer-backdrop {
    display: none;
    position: absolute;
    inset: 0;
    z-index: 30; /* under drawer and header, over everything else */
}

.bt-burger-check:checked ~ .bt-drawer-backdrop {
    display: block;
}

/* Burger/drawer exist only while the header menu is hidden */
@media (max-width: 1199px) {
    .bt-burger {
        display: flex;
    }
}

@media (min-width: 1200px) {
    .bt-drawer,
    .bt-drawer-backdrop {
        display: none;
    }
}

/* ===== CCTV camera (top-right, below the burger zone) =====
   Same 3D plastic/silver look as the menu robots; the head swivels to
   follow the cursor and the LED blinks — frantically during the siren. */
.bt-cctv {
    position: absolute;
    right: 6px;
    top: 118px; /* clear of the header so the swivel never crosses into it */
    z-index: 45;
    pointer-events: none;
}

.cc-head {
    transform-origin: 32px 15px;
    transition: transform 0.25s ease-out;
}

.cc-led {
    animation: cc-blink 1.6s ease-in-out infinite;
}

@keyframes cc-blink {
    0%, 55%  { opacity: 1; }
    65%, 90% { opacity: 0.15; }
    100%     { opacity: 1; }
}

.bt-siren .cc-led {
    animation: cc-blink 0.2s linear infinite;
    fill: #e0483e; /* alarm red while the siren buzzes */
}

/* ===== CCTV laser strike: beam flash → spark → rising smoke ===== */
.bt-laser {
    position: fixed;
    height: 1px;
    background: linear-gradient(to right, rgba(140, 22, 14, 0), #8c160e 30%, #b3261e);
    box-shadow: 0 0 4px 0 rgba(140, 22, 14, 0.7);
    transform-origin: 0 50%;
    z-index: 9998;
    pointer-events: none;
    animation: bt-laser-flash 0.18s ease-out forwards;
}

@keyframes bt-laser-flash {
    0%   { opacity: 0; }
    15%  { opacity: 1; }
    100% { opacity: 0; }
}

.bt-spark {
    position: fixed;
    width: 10px;
    height: 10px;
    margin: -5px;
    border-radius: 50%;
    background: radial-gradient(circle, #ffffff 0 25%, #ffd54d 45%, rgba(224, 72, 62, 0.9) 70%, transparent 75%);
    z-index: 9998;
    pointer-events: none;
    animation: bt-spark-pop 0.22s ease-out forwards;
}

@keyframes bt-spark-pop {
    0%   { transform: scale(0.3); opacity: 1; }
    60%  { transform: scale(1.6); opacity: 1; }
    100% { transform: scale(2.1); opacity: 0; }
}

.bt-smoke {
    position: fixed;
    width: 22px;
    height: 22px;
    margin: -11px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(120, 124, 130, 0.55), rgba(120, 124, 130, 0));
    opacity: 0;
    z-index: 9997;
    pointer-events: none;
    animation: bt-smoke-rise 1.2s ease-out forwards;
}

@keyframes bt-smoke-rise {
    0%   { transform: translateY(0) scale(0.6); opacity: 0.85; }
    100% { transform: translateY(-44px) scale(2.6); opacity: 0; }
}

/* ===== Quick actions (lower-right, mirroring the aside socials) =====
   Bottom→top: Settings, Volume on/off, Share. Plain darkgray glyphs
   (the logo's "binary" gray), transparent background. */
.bt-quick {
    position: absolute;
    right: 6px;
    bottom: 6px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    z-index: 45;
}

.bt-qa {
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    padding: 0;
    cursor: pointer;
    color: #4C4C4C;
    transition: color 150ms ease, transform 150ms ease;
}

.bt-qa:hover {
    color: #1f2937;
    transform: scale(1.15);
}

.bt-qa svg {
    width: 26px;
    height: 26px;
}

/* volume button swaps glyphs with the html.bt-muted state */
.bt-qa-volume .qa-voff { display: none; }
.bt-muted .bt-qa-volume .qa-von { display: none; }
.bt-muted .bt-qa-volume .qa-voff { display: block; }

/* ===== Row-2 library shelf (decorative books, far right of cell 3) =====
   A little bookshelf in row 2 / cell 3: two or three grayscale spines, each with
   a different lean, sitting flush to the bottom and to the far-right vertical line
   (the rightmost leans least and meets the line; the others rest against their
   neighbour). They stand on a dotted base line (no solid shelf). Titles are
   subject-themed, for show only, and auto-sized by site.js to fill each spine.
   Purely decorative — no mouse interaction. Desktop only (hidden ≤1199px). */
.bt-books {
    display: flex;
    align-items: flex-end;
    justify-content: flex-end;      /* hug the far-right; rightmost book meets the cell's right line */
    padding: 0 4px 0 0;             /* flush to the bottom; tiny right inset so the leaning rightmost book meets but never crosses the line */
    pointer-events: none;           /* purely decorative — nothing happens on mouse move */
}
.bt-books-shelf {
    display: flex;
    align-items: flex-end;          /* every book sits on the base, touching the bottom */
    gap: 0;                         /* books stand adjacent so they touch; the random lean makes them rest against each other */
    border-bottom: 2px dotted #8a8a8a;   /* the base line the books stand on (no solid shelf) */
}
.bt-book {
    position: relative;
    width: 25px;
    border-radius: 2px 3px 3px 2px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #f0f0f0;
    background: linear-gradient(90deg, #3f3f3f, #565656 45%, #3f3f3f);   /* fallback; site.js sets a random grayscale shade per book */
    transform-origin: bottom center;     /* lean in place; site.js sets each book's random angle */
    box-shadow:
        inset -3px 0 5px rgba(0, 0, 0, 0.4),
        inset 4px 0 4px rgba(255, 255, 255, 0.12),
        0 2px 3px rgba(0, 0, 0, 0.25);
}
.bt-book-title {
    writing-mode: vertical-rl;
    text-orientation: mixed;        /* letters read down the spine, as on real books */
    font: 700 11px/1 "Segoe UI", system-ui, sans-serif;   /* site.js resizes to fit each spine */
    letter-spacing: 0.02em;
    white-space: nowrap;   /* case shown exactly as typed in the admin (case-sensitive) */
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.45);
}

/* Varied spine heights for a natural, lived-in row. The lean angle, grayscale
   shade and title font are all set per book (randomly, but stably) by site.js so
   the row looks hand-placed; the rightmost book is kept gentle so it never
   crosses the line. */
.bt-book-0 { height: 100px; }
.bt-book-1 { height: 94px; }
.bt-book-2 { height: 88px; }
.bt-book-3 { height: 98px; }
.bt-book-4 { height: 92px; }

/* Desktop only — hide in mobile / one-column / burger-visible view (≤1199px). */
@media (max-width: 1199px) { .bt-books { display: none; } }

/* ===== Row-2 headline marquee (shared across all pages) ===== */
.bt-marquee {
    overflow: hidden;
    display: flex;
    align-items: center;
    height: 100%;
    min-width: 0;
    /* own stable compositor layer: keeps the scroll running even when the
       fire sequence spawns several animated overlay layers */
    contain: paint;
    isolation: isolate;
    /* behave like a drawn graphic: no text selection, no drag-image,
       no long-press callout — but clicks still bubble to the CCTV handler */
    user-select: none;
    -webkit-user-select: none;
    -webkit-user-drag: none;
    -webkit-touch-callout: none;
    cursor: default;
}

/* The row-2 headline marquee is a decorative heading and .bt-main is only a
   scroll container — neither is an interactive control. Suppress every focus
   outline and selection highlight so the marquee never looks "selected" with a
   black border (incl. when the browser restores a selection/focus on a hard
   refresh). !important beats the UA focus ring. */
.bt-main,
.bt-main:focus,
.bt-main:focus-visible,
.bt-marquee,
.bt-marquee *,
.bt-marquee :focus,
.bt-marquee :focus-visible { outline: none !important; }
.bt-marquee::selection,
.bt-marquee ::selection { background: transparent !important; }
.bt-marquee::-moz-selection,
.bt-marquee ::-moz-selection { background: transparent !important; }

.bt-marquee-track {
    display: flex;
    flex: none;
    white-space: nowrap;
    /* This is the scrolling compositor layer. It TRANSLATES only (offset set by
       the script in App.razor). The 0.78 horizontal condense lives on the <h1>
       below — NOT here — because scaling a GPU layer resamples its texture and
       leaves a faint seam at the layer's edges, which showed as thin vertical
       lines just before / after the headline (and a line below it). With the
       layer only translated by whole pixels, its edges stay perfectly aligned. */
    will-change: transform;
}

.bt-marquee-track h1,
.bt-marquee-track span {
    margin: 0;
    font-size: 120px;
    line-height: 120px;
    font-weight: 800;
    font-family: "Arial Narrow", "Helvetica Neue Condensed", "Roboto Condensed", "Liberation Sans Narrow", var(--bt-font-sans);
    font-stretch: condensed;
    letter-spacing: -0.01em;
    color: var(--bt-text);
}

/* Horizontal condense applied to the headline itself (direct child of the
   track), so the scrolling layer above is never scaled. Also the static
   fallback when motion is reduced. Origin must stay left. */
.bt-marquee-track > h1,
.bt-marquee-track > span {
    transform: scaleX(0.78);
    transform-origin: left center;
}

/* Home marquee rolling gear: sits at the right of cell 1, height = 2× its
   right margin. The scrolling characters hop as they roll over it (App.razor). */
.bt-gear-marquee {
    position: relative;
}

.bt-gear {
    position: absolute;
    bottom: 0;        /* touch the bottom of the row */
    left: 12px;       /* far left of cell 1, meeting the short handle */
    width: 30px;
    height: 30px;
    z-index: 2;
    pointer-events: none;
    animation: bt-gear-spin 2.4s linear infinite;
}

/* Thin metal arm bracing the gear from the left wall (flat colours, hard border). */
.bt-gear-handle {
    position: absolute;
    left: 0;
    bottom: 12.5px;   /* centred on the gear's axle (~15px from the bottom) */
    width: 27px;      /* left wall → gear centre (half the previous length) */
    height: 5px;
    background: #9a9a9a;
    border: 1px solid #4a4a4a;
    border-radius: 0 3px 3px 0;
    z-index: 1;
    pointer-events: none;
}

@keyframes bt-gear-spin {
    to { transform: rotate(-360deg); }   /* counter-clockwise */
}

.bt-gear-ch {
    display: inline-block;
    /* no per-character will-change: a persistent layer per glyph anti-aliases at
       its edges and leaves faint seams around the letters as they hop. */
}

@media (prefers-reduced-motion: reduce) {
    .bt-gear { animation: none; }
}

@media (prefers-reduced-motion: reduce) {
    .bt-marquee-track {
        animation: none;
    }
}

@media (max-width: 960px) {
    .bt-marquee {
        height: 120px;
        flex: 0 0 120px;
        /* cancel the generic mobile content padding-bottom:24px, which otherwise
           shrinks the text area and lifts the letters off the gear */
        padding-bottom: 0 !important;
        /* sit flush under the row above (cancel the 24px flex-column gap), so the
           jumping letters reach the top edge like on desktop instead of leaving a gap */
        margin-top: -24px;
    }

    .bt-marquee-track h1,
    .bt-marquee-track span {
        font-size: 120px;       /* match desktop so letters fill the row and roll over the gear */
        line-height: 120px;
    }
}

/* ===== Keyphrase-2 block (3-keyphrase pages) =====
   .bt-kp2  : secondary heading in row 5, cells C1–C2 (on the white accent band)
   .bt-writeup : SEO body copy in row 6, cells C1–C3 (on the page background).
   Grid placement is set inline on each element; these rules are visual only. */
.bt-kp2 {
    margin: 0;
    display: flex;
    align-items: center;
    padding: 0 24px;
    white-space: nowrap;
    color: var(--bt-text);
    font-family: "Arial Narrow", "Helvetica Neue Condensed", "Roboto Condensed", "Liberation Sans Narrow", var(--bt-font-sans);
    font-weight: 800;
    font-stretch: condensed;
    font-size: 32px;
    line-height: 1;
    letter-spacing: -0.01em;
    text-transform: uppercase;
}

.bt-writeup {
    margin: 0;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;    /* top-align so the 16px top padding is the real top margin */
    padding: 16px 24px 16px 24px;   /* top/bottom 16; left/right 24 (equal) */
    color: var(--bt-text);
}

.bt-writeup p {
    margin: 0;
    /* Fixed measure (~ the Windows Chrome rendering of the old 72ch). px instead
       of the font-dependent ch keeps line length, right margin and line count
       identical across OSes/fonts, so the cell-3 robot + sticky note never
       collide and the body text stays within cells 1-2. */
    max-width: 680px;
    font-size: 19px;
    /* slightly more than double: grows the row 4/6/8 cell-1 text a touch so the
       cell-3 graphics/animations get a little extra bottom clearance */
    line-height: 2.15;
    text-align: justify;
}

/* Burger + mobile (<=1199px): make the writeup's visible TOP inset match the
   LEFT (24px). The top padding is 24px, but line-height:2 adds ~12px of leading
   above the first line — so we pull the first line up by that amount so the
   text top sits at the 24px padding edge, equal to the left. */
@media (max-width: 1199px) {
    .bt-grid > .bt-writeup { padding-top: 24px; padding-right: 24px; }
    .bt-grid > .bt-writeup > :first-child { margin-top: -12px; }
}

/* Marquee pages (home/ai/web/apps/games): drop the C1/C2 vertical line in the
   writeup rows (4, 6, 8). The single full-height line is hidden and PageChrome
   redraws it as segments that skip those rows. */
.bt-grid:has(.bt-r3c2-accent) > .bt-line-v1 { display: none; }
.bt-c1-seg {
    grid-column: 2;
    justify-self: start;
    width: 1px;
    height: 100%;
    background: darkgray;
}
@media (max-width: 960px) { .bt-c1-seg { display: none; } }

/* Same for the C2/C3 line, skipping only rows 6 and 8. */
.bt-grid:has(.bt-r3c2-accent) > .bt-line-v2 { display: none; }
.bt-c2-seg {
    grid-column: 3;
    justify-self: start;
    width: 1px;
    height: 100%;
    background: darkgray;
}
@media (max-width: 960px) { .bt-c2-seg { display: none; } }

/* ===== FAQ accordions (3-keyphrase pages) =====
   Pure-CSS <details>/<summary> — no JS, works under static SSR. The section
   has an opaque background so it covers the decorative accent cells behind it. */
.bt-faq {
    align-self: stretch;      /* fill the row span so the bottom border is flush */
    background: var(--bt-bg);
    display: flex;
    flex-direction: column;
    padding: 24px 48px;
    z-index: 1;
    border-right: 1px solid darkgray;   /* frame: right edge lands on cell-3's right */
    border-bottom: 1px solid darkgray;  /* frame: bottom edge */
}

.bt-faq-title {
    margin: 0 0 10px;
    color: var(--bt-text);
    font-family: "Arial Narrow", "Helvetica Neue Condensed", "Roboto Condensed", "Liberation Sans Narrow", var(--bt-font-sans);
    font-weight: 800;
    font-stretch: condensed;
    font-size: 32px;
    line-height: 1;
    letter-spacing: -0.01em;
    text-transform: uppercase;
}

.bt-faq-item {
    border-bottom: 1px solid darkgray;
}

.bt-faq-item summary {
    list-style: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 16px 0;
    color: var(--bt-text);
    font-weight: 600;
    font-size: 20px;
}

.bt-faq-item summary::-webkit-details-marker { display: none; }

/* Triangle toggle: points down when closed, flips up when open */
.bt-faq-arrow {
    flex: none;
    width: 0;
    height: 0;
    border-left: 7px solid transparent;
    border-right: 7px solid transparent;
    border-top: 9px solid var(--bt-text);
    transition: transform 200ms var(--bt-ease);
}

.bt-faq-item[open] .bt-faq-arrow {
    transform: rotate(180deg);
}

.bt-faq-answer {
    overflow: hidden;
    padding-bottom: 18px;
}

.bt-faq-item[open] .bt-faq-answer {
    animation: bt-faq-open 240ms var(--bt-ease);
}

@keyframes bt-faq-open {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: none; }
}

.bt-faq-answer p {
    margin: 0;
    max-width: 72ch;
    font-size: 18px;
    line-height: 2;
    text-align: justify;
    color: var(--bt-text);
}

/* Home: remove row 14 (the empty row between the FAQ and the row-15 board
   window) by collapsing it to 0. Higher specificity beats the scoped base. */
.bt-main .bt-grid:has(.bt-r3c2-accent) {
    /* row 1 = 36px (matches the aside Past button's width) to seat the breadcrumb */
    grid-template-rows: 36px 120px 12px minmax(288px, auto) 48px minmax(288px, auto) 48px minmax(288px, auto) 96px minmax(48px, 1fr) minmax(48px, 1fr) minmax(48px, 1fr) minmax(48px, 1fr) 0 196px 12px minmax(300px, auto) 12px 48px;
}

/* ===== Legal / policy pages (Terms, Privacy) =====
   The .bt-legal block renders the legal copy AND collapses the shared layout
   to just the top 4 and bottom 2 grid rows (rows 5–16 removed). The high
   specificity beats the scoped .bt-grid grid-template-rows from the layout. */
.bt-main .bt-grid:has(.bt-legal) {
    grid-template-rows: 0 0 0 minmax(288px, auto) 0 0 0 0 0 0 0 0 0 0 0 0 0 12px 48px;
}

/* hide the decorative spacers, accents and guide lines in rows 1–3 and 5–16,
   plus the row-4 black accent cell (so column 3 stays clean behind the text) and
   the empty row-4 spacer (which surfaces as a blank band at the top on mobile) —
   but NOT the vertical guide lines, which should remain visible like on home */
.bt-grid:has(.bt-legal) > .bt-r4-spacer,
.bt-grid:has(.bt-legal) > .bt-r4c3-accent,
.bt-grid:has(.bt-legal) > .bt-r1c1-accent,
.bt-grid:has(.bt-legal) > [style*="grid-row: 1;"],
.bt-grid:has(.bt-legal) > [style*="grid-row: 2;"],
.bt-grid:has(.bt-legal) > [style*="grid-row: 3;"],
.bt-grid:has(.bt-legal) > [style*="grid-row: 5;"],
.bt-grid:has(.bt-legal) > [style*="grid-row: 6;"],
.bt-grid:has(.bt-legal) > [style*="grid-row: 7;"],
.bt-grid:has(.bt-legal) > [style*="grid-row: 8;"],
.bt-grid:has(.bt-legal) > [style*="grid-row: 9;"],
.bt-grid:has(.bt-legal) > [style*="grid-row: 10;"],
.bt-grid:has(.bt-legal) > [style*="grid-row: 11;"],
.bt-grid:has(.bt-legal) > [style*="grid-row: 12;"],
.bt-grid:has(.bt-legal) > [style*="grid-row: 13;"],
.bt-grid:has(.bt-legal) > [style*="grid-row: 14;"],
.bt-grid:has(.bt-legal) > [style*="grid-row: 15;"],
.bt-grid:has(.bt-legal) > [style*="grid-row: 16;"],
.bt-grid:has(.bt-legal) > [style*="grid-row: 17;"] {
    display: none;
}

/* ===== Article pages (/articles/{slug}) =====
   Articles use the clean .bt-legal layout (no laser/CCTV) but also carry the
   .bt-article marker, which keeps the home-style row-17 contact scene + brand
   card visible below the article. These rules come AFTER the legal collapse so
   they win on equal specificity. */
.bt-grid:has(.bt-article) > .bt-stairs-scene {
    display: block;   /* un-hide the contact scene on every viewport */
}
@media (min-width: 961px) {
    .bt-main .bt-grid:has(.bt-article) {
        grid-template-rows: 0 0 0 minmax(288px, auto) 0 0 0 0 0 0 0 0 0 0 0 0 minmax(300px, auto) 12px 48px;
    }
    /* brand card stays in column 3 on desktop (it is hidden on mobile, like home) */
    .bt-grid:has(.bt-article) > .bt-r17c3-accent {
        display: flex;
    }
}

.bt-legal {
    align-self: start;
    /* transparent (like the home-page writeups) so the grid's vertical
       darkgrey guide lines show through, matching the home look */
    padding: 32px 48px;
    color: var(--bt-text);
}

.bt-legal h1 {
    margin: 0 0 4px;
    font-family: "Arial Narrow", "Helvetica Neue Condensed", "Roboto Condensed", "Liberation Sans Narrow", var(--bt-font-sans);
    font-weight: 800;
    font-stretch: condensed;
    font-size: 30px;
    letter-spacing: -0.01em;
    text-transform: uppercase;
}

/* Articles index (/articles): list of published articles, newest first. */
.bt-artindex .bt-artlist {
    list-style: none;
    margin: 22px 0 0;
    padding: 0;
}
.bt-artlist-item { border-top: 1px solid rgba(128, 128, 128, 0.35); }
.bt-artlist-item:last-child { border-bottom: 1px solid rgba(128, 128, 128, 0.35); }
.bt-artlist-link {
    display: block;
    padding: 18px 4px;
    text-decoration: none;
    color: var(--bt-text);
    transition: padding-left 0.18s ease;
}
.bt-artlist-link:hover { padding-left: 12px; }
.bt-artlist-title { margin: 0; font-size: 22px; font-weight: 800; line-height: 1.2; }
.bt-artlist-link:hover .bt-artlist-title { color: var(--bt-hover); }
.bt-artlist-date { display: block; margin: 4px 0 0; font-size: 13px; opacity: 0.65; }
.bt-artlist-desc { margin: 8px 0 0; font-size: 15px; line-height: 1.55; max-width: 70ch; }
.bt-artlist-more {
    display: inline-block;
    margin-top: 8px;
    font-size: 13px;
    font-weight: 700;
    color: var(--bt-hover);
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity 0.18s ease, transform 0.18s ease;
}
.bt-artlist-link:hover .bt-artlist-more { opacity: 1; transform: translateX(0); }
@media (prefers-reduced-motion: reduce) {
    .bt-artlist-link, .bt-artlist-more { transition: none; }
}

/* Future / Past / Settings: full (non-condensed) bold key-phrase-1 title, and
   no C1/C2 or C2/C3 vertical guide lines (scoped via .bt-kp1page). */
.bt-legal.bt-kp1page h1 {
    font-family: var(--bt-font-sans);
    font-stretch: normal;
    font-weight: 800;
}
/* Future / Past / Settings: all four insets = 24px, matching the home page's
   row-4 cell-1 writeup left margin. */
.bt-legal.bt-kp1page {
    padding: 24px;
}
.bt-grid:has(.bt-kp1page) > .bt-line-v1,
.bt-grid:has(.bt-kp1page) > .bt-line-v2 { display: none; }

/* Article & admin pages: remove the C1/C2 and C2/C3 vertical guide lines entirely
   (same as the Future/Past/Settings pages), for a clean single-column reading view. */
.bt-grid:has(.bt-article) > .bt-line-v1,
.bt-grid:has(.bt-article) > .bt-line-v2,
.bt-grid:has(.bt-admin) > .bt-line-v1,
.bt-grid:has(.bt-admin) > .bt-line-v2 { display: none; }

/* ===== Error / utility pages (404, 403, 500, offline) =====
   Built on the clean .bt-article layout: a centred "lost ladybug", the big status
   code, a clear message and a single Home button. */
.bt-errorpage { padding: 48px; }
.bt-err {
    min-height: 360px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: 6px;
}
/* Code + bug sit together; the bug overlaps the right of the numerals a little. */
.bt-err-art {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    flex-wrap: wrap;
}
.bt-err-code {
    font-family: "Arial Narrow", "Helvetica Neue Condensed", "Roboto Condensed", "Liberation Sans Narrow", var(--bt-font-sans);
    font-weight: 800;
    font-stretch: condensed;
    font-size: clamp(96px, 18vw, 168px);
    line-height: 0.9;
    letter-spacing: -0.02em;
    color: var(--bt-text);
}
.bt-err-bug { width: clamp(150px, 26vw, 232px); height: auto; display: block; }
.bt-errorpage h1 {
    margin: 14px 0 0;
    font-size: clamp(22px, 3vw, 30px);
}
.bt-err-msg {
    margin: 8px 0 0;
    max-width: 520px;
    font-size: 17px;
    line-height: 1.6;
    color: var(--bt-text);
    opacity: 0.85;
}
.bt-err-home {
    margin-top: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 13px 30px;
    background: var(--bt-text);
    color: var(--bt-bg);
    border: 1px solid var(--bt-text);
    border-radius: 2px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    font-size: 0.85rem;
    text-decoration: none;
    transition: background-color 160ms ease, color 160ms ease;
}
.bt-err-home:hover { background: var(--bt-hover); color: var(--bt-hover-text); border-color: var(--bt-hover); text-decoration: none; }
.bt-err-reqid { margin-top: 18px; font-size: 12px; opacity: 0.55; }
.bt-err-reqid code { font-family: var(--bt-font-mono, monospace); }

/* The ladybug idles: a gentle wobble + scuttling legs + a fading "lost?" mark. */
.bt-err-ladybug { transform-box: fill-box; transform-origin: 50% 60%; animation: bt-err-wobble 2.8s ease-in-out infinite; }
.bt-err-legs { animation: bt-err-scuttle 0.5s ease-in-out infinite; transform-box: fill-box; transform-origin: 50% 50%; }
.bt-err-q { animation: bt-err-qpulse 2.8s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
.bt-err-trail { stroke-dashoffset: 0; animation: bt-err-trail 7s linear infinite; }
@keyframes bt-err-wobble { 0%, 100% { transform: rotate(-3deg); } 50% { transform: rotate(3deg); } }
@keyframes bt-err-scuttle { 0%, 100% { transform: rotate(-2deg); } 50% { transform: rotate(2deg); } }
@keyframes bt-err-qpulse { 0%, 100% { opacity: 0.35; transform: translateY(0); } 50% { opacity: 1; transform: translateY(-3px); } }
@keyframes bt-err-trail { to { stroke-dashoffset: -140; } }
@media (prefers-reduced-motion: reduce) {
    .bt-err-ladybug, .bt-err-legs, .bt-err-q, .bt-err-trail { animation: none; }
}
/* Compact view: stack the code above the bug, keep it tidy. */
@media (max-width: 600px) {
    .bt-err-art { flex-direction: column; }
}

.bt-legal h3 {
    margin: 22px 0 6px;
    font-size: 18px;
    font-weight: 700;
}

.bt-legal p {
    margin: 0;
    max-width: 80ch;
    font-size: 16px;
    line-height: 1.7;
    text-align: justify;
}

.bt-legal ul {
    margin: 8px 0 0;
    padding-left: 22px;
    max-width: 80ch;
}

.bt-legal li {
    font-size: 16px;
    line-height: 1.7;
    margin: 2px 0;
}

/* ===== Admin panel (/sitesettings) ===== */
.bt-admin .bt-admin-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}
.bt-admin .bt-admin-sub {
    margin: 0 0 14px;
    color: #6a6a6a;
}
.bt-admin form.bt-admin-login,
.bt-admin .bt-admin-form {
    display: flex;
    flex-direction: column;
    gap: 14px;
    max-width: 780px;
    margin-top: 12px;
}
.bt-admin label {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-weight: 700;
    font-size: 14px;
    color: #000;   /* fixed black — readable on the light admin form, theme-independent */
}
.bt-admin label span {
    font-weight: 400;
    font-size: 12px;
    color: #000;   /* hint text (e.g. "Settings page H1", rich-text hint) in black */
}
.bt-admin input,
.bt-admin textarea {
    font: inherit;
    font-weight: 400;
    font-size: 15px;
    padding: 8px 10px;
    border: 1px solid #b9b9b9;
    border-radius: 4px;
    background: #fff;
    color: var(--bt-text);
    width: 100%;
    box-sizing: border-box;
}
.bt-admin textarea {
    resize: vertical;
    line-height: 1.55;
}
/* Library-shelf book-name inputs: a compact two-column grid inside the fieldset. */
.bt-admin .bt-admin-books {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px 14px;
}
@media (max-width: 620px) { .bt-admin .bt-admin-books { grid-template-columns: 1fr; } }
.bt-admin button {
    align-self: flex-start;
    font: inherit;
    font-weight: 700;
    padding: 9px 22px;
    border: 1px solid var(--bt-text);
    border-radius: 4px;
    background: var(--bt-text);
    color: #fff;
    cursor: pointer;
}
.bt-admin button:hover { opacity: 0.9; }
.bt-admin .bt-admin-logout { margin: 0; }
.bt-admin .bt-admin-logout button {
    padding: 6px 14px;
    background: transparent;
    color: var(--bt-text);
}
.bt-admin .bt-admin-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 14px 0;
}
.bt-admin .bt-admin-tabs a {
    text-transform: uppercase;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.04em;
    padding: 6px 12px;
    border: 1px solid #b9b9b9;
    border-radius: 4px;
    text-decoration: none;
    color: var(--bt-text);
}
.bt-admin .bt-admin-tabs a.active {
    background: var(--bt-text);
    color: #fff;
    border-color: var(--bt-text);
}
.bt-admin .bt-admin-msg {
    padding: 8px 12px;
    border-radius: 4px;
    font-weight: 700;
    font-size: 14px;
    max-width: 780px;
}
.bt-admin .bt-admin-ok { background: #e6f5e6; color: #1c6b1c; }
.bt-admin .bt-admin-err { background: #fbe6e6; color: #9b1c1c; }
.bt-admin .bt-admin-note {
    font-size: 13px;
    color: #000;   /* help notes (e.g. the Articles publish note) in black */
    max-width: 780px;
}
.bt-admin .bt-admin-note code { font-family: monospace; }
.bt-admin .bt-admin-fs {
    display: flex;
    flex-direction: column;
    gap: 14px;
    border: 1px solid #d0d0d0;
    border-radius: 6px;
    padding: 14px 16px 16px;
    margin: 2px 0;
}
.bt-admin .bt-admin-fs legend {
    font-weight: 700;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #000;   /* section titles (Moon / MoonLight / Social cards / FAQ) in black */
    padding: 0 6px;
}
.bt-admin .bt-admin-tabsep {
    flex: 0 0 1px;
    align-self: stretch;
    background: #d0d0d0;
    margin: 0 4px;
}

/* ----- Articles admin grid ----- */
.bt-admin .bt-articles-grid {
    width: 100%;
    border-collapse: collapse;
    margin: 8px 0 20px;
    font-size: 14px;
}
.bt-admin .bt-articles-grid th,
.bt-admin .bt-articles-grid td {
    text-align: left;
    padding: 10px 12px;
    border-bottom: 1px solid #e2e2e2;
    vertical-align: middle;
}
.bt-admin .bt-articles-grid th {
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #6a6a6a;
}
.bt-admin .bt-articles-grid tr.is-hidden td {
    color: #9a9a9a;
}
.bt-admin .bt-articles-grid tr.is-hidden a {
    color: #9a9a9a;
}
.bt-admin .bt-articles-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
}
.bt-admin .bt-articles-actions form {
    margin: 0;
    display: inline;
}
.bt-admin .bt-articles-actions button {
    font-size: 13px;
    padding: 5px 12px;
    cursor: pointer;
}
.bt-admin .bt-articles-actions .bt-danger {
    background: #b3261e;
    color: #fff;
    border-color: #b3261e;
}
.bt-admin .bt-admin-linkbtn {
    display: inline-block;
    font-size: 13px;
    padding: 5px 12px;
    border: 1px solid #c4c4c4;
    border-radius: 6px;
    text-decoration: none;
    color: inherit;
}
.bt-admin .bt-admin-h2 {
    font-size: 18px;
    font-weight: 800;
    margin: 8px 0 4px;
}
.bt-admin .bt-articles-formbtns {
    display: flex;
    gap: 10px;
    align-items: center;
}

/* ===== Rich-text content (content pages) + admin editor ===== */
/* Responsive media — images, video and YouTube fit mobile and desktop. */
.bt-richtext img,
.bt-richtext video {
    max-width: 100%;
    height: auto;
    border-radius: 6px;
}
.bt-richtext .bt-embed {
    position: relative;
    width: 100%;
    max-width: 820px;
    aspect-ratio: 16 / 9;
    margin: 18px 0;
}
.bt-richtext .bt-embed iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
    border-radius: 6px;
}
.bt-richtext iframe { max-width: 100%; }

.bt-rte {
    border: 1px solid #b9b9b9;
    border-radius: 6px;
    overflow: hidden;
    background: #fff;
}
.bt-rte-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    padding: 6px;
    background: #f2f2f2;
    border-bottom: 1px solid #d6d6d6;
}
.bt-admin .bt-rte-toolbar button {
    align-self: auto;
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    padding: 4px 9px;
    background: #fff;
    color: var(--bt-text);
    border: 1px solid #c4c4c4;
    border-radius: 4px;
    cursor: pointer;
}
.bt-admin .bt-rte-toolbar button:hover { background: #e8e8e8; }
.bt-rte-area {
    min-height: 260px;
    padding: 14px 16px;
    color: var(--bt-text);
    outline: none;
    font-size: 15px;
    line-height: 1.6;
}
.bt-rte-area:focus { box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.06); }
.bt-rte-area h3 { margin: 16px 0 6px; }
.bt-rte-area p { margin: 0 0 10px; }
.bt-rte-mark { background: #fff176; padding: 0 3px; border-radius: 2px; }
.bt-rte-fc { border-bottom: 3px solid #d33; line-height: 1; }
/* hidden native colour picker (opened by the text-colour button) */
.bt-rte-color { width: 0; height: 0; padding: 0; margin: 0; border: 0; opacity: 0; flex: 0 0 0; }

/* Styled prompt popup for the rich-text editor (replaces window.prompt) */
.bt-modal {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.45);
}
.bt-modal[hidden] { display: none; }
.bt-modal-box {
    width: min(92vw, 460px);
    background: #fff;
    color: #222;
    border-radius: 10px;
    padding: 20px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.bt-modal-label { font-weight: 700; font-size: 15px; color: #222; }
.bt-modal-input,
.bt-modal-textarea {
    font: inherit;
    font-size: 15px;
    padding: 9px 11px;
    border: 1px solid #b9b9b9;
    border-radius: 6px;
    width: 100%;
    box-sizing: border-box;
    background: #fff;
    color: #222;
}
.bt-modal-textarea { min-height: 170px; resize: vertical; font-family: monospace; line-height: 1.5; }
.bt-modal-actions { display: flex; gap: 10px; justify-content: flex-end; }
.bt-modal-actions .bt-btn {
    font: inherit;
    font-weight: 700;
    padding: 8px 18px;
    border: 1px solid #888;
    border-radius: 6px;
    background: #fff;
    color: #222;
    cursor: pointer;
}
.bt-modal-actions .bt-btn-primary { background: #222; color: #fff; border-color: #222; }

/* Admin colour-mode inputs */
.bt-admin .bt-admin-colors {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
}
.bt-admin .bt-admin-colors label {
    flex: 0 0 auto;
    font-size: 13px;
    align-items: center;
}
.bt-admin .bt-admin-colors input[type="color"] {
    width: 52px;
    height: 32px;
    padding: 0;
    border: 1px solid #b9b9b9;
    border-radius: 4px;
    background: #fff;
    cursor: pointer;
}

/* Settings page layout. max-width 336px = 408px (C1/C2 boundary, under the
   header's logo line) − 48px section padding − 24px right gap, so the theme
   buttons end 24px left of that line and read well on mobile. */
.bt-settings {
    display: flex;
    flex-direction: column;
    gap: 16px;
    margin-top: 22px;
    max-width: 336px;
}

/* ===== Theme picker (Settings page) — click a theme to apply it instantly ===== */
.bt-mode-heading { margin: 0; font-size: 16px; font-weight: 700; letter-spacing: 0.02em; color: var(--bt-text); }
.bt-theme-grid { display: flex; flex-direction: column; gap: 8px; }
.bt-theme-opt {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 9px 12px;
    background: var(--bt-item);
    color: var(--bt-text);
    border: 1px solid darkgrey;   /* square, matches the era-tab / admin styling */
    border-radius: 0;
    cursor: pointer;
    font: inherit;
    font-size: 15px;
    text-align: left;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.bt-theme-opt:hover { background: var(--bt-hover); color: var(--bt-hover-text); }
.bt-theme-opt.is-active {
    background: var(--bt-hover);
    color: var(--bt-hover-text);
    border-color: var(--bt-text);
    font-weight: 700;
}
/* mini preview of each theme: its background, an accent dot (hover) + a button bar (item) */
.bt-theme-prev { flex: none; width: 40px; height: 24px; position: relative; border: 1px solid rgba(0, 0, 0, 0.3); overflow: hidden; }
.bt-theme-prev i, .bt-theme-prev b { position: absolute; display: block; }
.bt-theme-prev i { width: 11px; height: 11px; border-radius: 50%; right: 4px; top: 50%; transform: translateY(-50%); }
.bt-theme-prev b { left: 4px; bottom: 4px; width: 14px; height: 5px; }
.bt-theme-name { white-space: nowrap; }

.bt-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 8px;
}

.bt-btn {
    padding: 10px 18px;
    border: 1px solid var(--bt-text);
    border-radius: 6px;
    background: transparent;
    color: var(--bt-text);
    font-size: 15px;
    cursor: pointer;
    transition: background-color 200ms ease, color 200ms ease;
}

.bt-btn:hover {
    background: var(--bt-hover);
    color: white;
}

.bt-btn-primary {
    background: var(--bt-text);
    color: white;
}

.bt-btn-primary:hover {
    background: var(--bt-hover);
}

/* Settings page Save / Cancel / Reset: same look & hover behaviour as the
   aside era tabs (FUTURE / PRESENT / PAST) — an item-filled, 1px darkgrey
   bordered, square box with uppercase letter-spaced text that fills with the
   hover colour on hover. */
.bt-settings-page .bt-actions .bt-btn {
    background: var(--bt-item);
    border: 1px solid darkgrey;
    border-radius: 0;
    color: var(--bt-text);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 0.75rem;
    transition: background-color 150ms ease, color 150ms ease;
}

.bt-settings-page .bt-actions .bt-btn:hover {
    background: var(--bt-hover);
    color: var(--bt-hover-text);
}

.bt-legal .bt-legal-meta {
    color: #5b6470;
    font-size: 14px;
    text-align: left;
}

/* The Terms page hides the CCTV camera; its laser/siren firing is also
   disabled on this page in App.razor's strike handler. */
.bt-shell:has(.bt-legal) .bt-cctv,
.bt-shell:has(.bt-no-fx) .bt-cctv {
    display: none;
}

/* On mobile the legal/policy pages have no filler rows to absorb leftover
   height, so short pages (e.g. Settings) would float the footer up. Let the
   content block grow to fill the viewport, keeping the footer at the bottom. */
@media (max-width: 960px) {
    .bt-grid > .bt-legal {
        flex: 1 0 auto;
    }
}

/* ===== Page transitions =====
   Only the main area animates; header/aside stay put like an app shell.
   Exit: quick fade/lift on link click. Enter: fade/rise when the new
   page's content arrives via enhanced navigation. */
.bt-main.bt-page-out {
    /* hide instantly on click so the main is already blank when the new page is
       morphed in; otherwise a half-finished fade snaps back to 0 and flickers */
    opacity: 0;
}

.bt-main.bt-page-in {
    animation: bt-page-in 300ms var(--bt-ease);
}

/* Opacity-only crossfade: no translate, so nothing shifts position during the
   transition. A vertical slide here made row 1 jump down then ride back up to
   the top after enhanced navigation, and the transform also broke the
   position:fixed scene layers. */
@keyframes bt-page-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Respect users who opt out of motion */
@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }

    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}
