﻿/* =============================================
   CSS VARIABLES — change colors here
   ============================================= */
:root {
    --color-primary:        #849B2E;
    --color-primary-bright: #62741F;   /* readable olive for text on light surfaces */
    --color-primary-dark:   #4F5F19;
    --color-primary-glow:   rgba(132, 155, 46, 0.30);
    --color-primary-tint:   rgba(132, 155, 46, 0.10);

    /* Failure states (contact-form error notice). Olive carries success, so red
       is only ever "this did not work" — deliberately the one non-brand hue. */
    --color-danger:         #b3261e;
    --color-danger-tint:    rgba(179, 38, 30, 0.08);

    --color-bg:             #ffffff;
    --color-bg-deep:        #f3f5ec;
    --color-surface:        #ffffff;
    --color-surface-2:      #fafaf8;
    --color-border:         rgba(17, 17, 17, 0.10);
    --color-border-strong:  rgba(17, 17, 17, 0.24);

    --color-text:           #161613;
    --color-muted:          rgba(22, 22, 19, 0.60);
    --color-faint:          rgba(22, 22, 19, 0.36);

    /* navbar sits on olive in both themes — light-on-olive counterparts of the text tokens */
    --color-nav-bg:         rgba(98, 116, 31, 0.93);
    --color-nav-bg-solid:   #62741F;
    --color-nav-edge:       #4F5F19;   /* darker olive edge/ink, distinct from the bar */
    --color-nav-text:       #ffffff;
    --color-nav-muted:      rgba(255, 255, 255, 0.78);
    --color-nav-faint:      rgba(255, 255, 255, 0.55);
    --color-nav-accent:     #C9DA84;   /* light olive, readable on the olive bar */
    --color-nav-topbar-bg:  #4F5F19;   /* darker than the navbar; topbar sits above it */

    --navbar-height:        68px;
    --topbar-height:        34px;
    --sticky-bar-height:    58px;

    --font-display: 'Barlow Condensed', 'Arial Narrow', sans-serif;
    --font-main:    'Inter', system-ui, -apple-system, sans-serif;

    --transition: 0.22s ease;
    --radius: 2px;

    /* theme-varying detail tokens (overridden by the dark theme) */
    --grid-line:       rgba(132, 155, 46, 0.09);   /* blueprint grid lines */
    --hero-glow:       rgba(132, 155, 46, 0.10);
    --num-ghost:       rgba(17, 17, 17, 0.15);     /* oversized card numerals */
}

/* =============================================
   DARK THEME — toggled from the navbar, light is the default.
   Token swaps first; component overrides that aren't clean
   token swaps follow.
   ============================================= */
html[data-theme="dark"] {
    color-scheme: dark;

    /* navbar + topbar stay olive in both themes, so this matches the :root value */
    --color-nav-topbar-bg:  #4F5F19;

    --color-primary-bright: #9EB83A;   /* on dark surfaces "bright" really is brighter */
    --color-primary-dark:   #62741F;
    --color-primary-glow:   rgba(132, 155, 46, 0.35);
    --color-primary-tint:   rgba(132, 155, 46, 0.12);

    /* Lifted off #b3261e: that red fails contrast against the dark-grey bg. */
    --color-danger:         #f2846c;
    --color-danger-tint:    rgba(242, 132, 108, 0.10);

    --color-bg:             #1d1d1a;
    --color-bg-deep:        #161613;
    --color-surface:        #242420;
    --color-surface-2:      #2b2b26;
    --color-border:         rgba(255, 255, 255, 0.08);
    --color-border-strong:  rgba(255, 255, 255, 0.18);

    --color-text:           #f2f2ef;
    --color-muted:          rgba(242, 242, 239, 0.55);
    --color-faint:          rgba(242, 242, 239, 0.30);

    --grid-line:       rgba(132, 155, 46, 0.04);
    --hero-glow:       rgba(132, 155, 46, 0.09);
    --num-ghost:       rgba(255, 255, 255, 0.13);
}

[data-theme="dark"] .btn--primary:hover {
    background: var(--color-primary-bright);
    color: #0b0b0b;
    box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.5);
}

[data-theme="dark"] .btn--dark {
    background: #151512;
    color: var(--color-text);
}

[data-theme="dark"] .btn--dark:hover {
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.35);
}

[data-theme="dark"] .hero-plate {
    box-shadow:
        7px 7px 0 rgba(0, 0, 0, 0.4),
        inset 0 -6px 0 rgba(0, 0, 0, 0.16);
}

[data-theme="dark"] .hero-split__fig {
    filter: drop-shadow(10px 10px 0 rgba(0, 0, 0, 0.45));
}

[data-theme="dark"] .category-card__fig svg { color: rgba(255, 255, 255, 0.32); }

[data-theme="dark"] .card__image svg { color: rgba(255, 255, 255, 0.26); }

[data-theme="dark"] .card:hover { box-shadow: 0 14px 32px rgba(0, 0, 0, 0.45); }

[data-theme="dark"] .cta-bar::before {
    background: repeating-linear-gradient(-45deg,
        var(--color-bg-deep) 0 14px, transparent 14px 28px);
}

[data-theme="dark"] .sticky-bar {
    background: rgba(36, 36, 32, 0.92);
    border-color: var(--color-border-strong);
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.45), 0 2px 6px rgba(0, 0, 0, 0.30);
}

[data-theme="dark"] .sticky-mini {
    background: rgba(36, 36, 32, 0.92);
    border-color: var(--color-border-strong);
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.45), 0 2px 6px rgba(0, 0, 0, 0.30);
}

/* =============================================
   RESET & BASE
   ============================================= */
*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html {
    scroll-behavior: smooth;
    color-scheme: light;
}

body {
    font-family: var(--font-main);
    color: var(--color-text);
    background: var(--color-bg);
    line-height: 1.6;
    padding-bottom: calc(var(--sticky-bar-height) + 36px); /* floating bar + its bottom offset */
    -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
ul { list-style: none; }

::selection {
    background: var(--color-primary);
    color: #0b0b0b;
}

/* No scrollbar styling on purpose (removed 2026-07-28, client request: "it should be
   just the browser's native bar and that's it"). The old `::-webkit-scrollbar` block
   drew an 11px custom track/thumb — Chromium-only, so the site had a hand-drawn bar in
   Chrome/Edge and the native one in Firefox, i.e. it looked like a foreign element glued
   to the page in exactly one of them. Every browser now draws its own.
   `color-scheme` on html (below) is NOT scrollbar styling: it declares which theme the
   page is in, which is what lets the browser pick the matching native bar. */

:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 3px;
}

/* =============================================
   SCROLL REVEAL (JS adds .in)
   ============================================= */
.js [data-reveal] {
    opacity: 0;
    transform: translateY(26px);
    transition:
        opacity 0.7s ease var(--d, 0ms),
        transform 0.7s cubic-bezier(0.2, 0.7, 0.3, 1) var(--d, 0ms);
}

.js [data-reveal].in {
    opacity: 1;
    transform: none;
}

/* =============================================
   BUTTONS
   ============================================= */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.8rem 1.7rem;
    border-radius: var(--radius);
    font-family: var(--font-main);
    font-size: 0.82rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    cursor: pointer;
    border: none;
    transition: background var(--transition), color var(--transition),
                border-color var(--transition), box-shadow var(--transition),
                transform var(--transition);
}

.btn:active { transform: scale(0.97); }

.btn--primary {
    background: var(--color-primary);
    color: #0b0b0b;
}

.btn--primary:hover {
    background: var(--color-primary-dark);
    color: var(--color-bg);
    box-shadow: 3px 3px 0 rgba(22, 22, 19, 0.18);
}

.btn--outline {
    background: transparent;
    color: var(--color-text);
    border: 1px solid var(--color-border-strong);
}

.btn--outline:hover {
    border-color: var(--color-primary);
    color: var(--color-primary-bright);
}

.btn--dark {
    background: #161613;
    color: #f4f4f0;
}

.btn--dark:hover {
    background: #000;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
}

.btn--sm {
    padding: 0.5rem 1.05rem;
    font-size: 0.7rem;
}

/* =============================================
   NAVBAR
   ============================================= */
.topbar {
    height: var(--topbar-height);
    background: var(--color-nav-topbar-bg);
    color: var(--color-nav-muted);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0 2rem;
    font-size: 0.78rem;
}

.topbar__contact {
    display: flex;
    align-items: center;
    gap: 1.4rem;
}

.topbar__link {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--color-nav-muted);
    transition: color var(--transition);
}

.topbar__link:hover { color: var(--color-nav-text); }

.topbar__icon {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
}

.topbar__social {
    display: flex;
    align-items: center;
    gap: 0.9rem;
}

.topbar__icon-link {
    display: inline-flex;
    color: var(--color-nav-faint);
    transition: color var(--transition);
}

.topbar__icon-link:hover { color: var(--color-nav-text); }

.topbar__icon-link svg {
    width: 15px;
    height: 15px;
}

/* Sticky, not fixed. The topbar is a normal in-flow sibling above it, so the navbar
   scrolls with the page until its own top hits 0 and then docks there — the exact
   behaviour the old `position: fixed` + per-scroll-tick `navbar.style.top` JS
   produced, but computed by the compositor instead of the main thread.
   The JS version visibly juddered on Android Firefox: its dynamic URL bar resizes
   the viewport mid-scroll, so `window.scrollY` and the painted frame disagree and
   the navbar chased the page a frame behind. Sticky cannot desync that way.
   Because the navbar is now in flow, `.topbar` no longer reserves space for it with
   `margin-bottom` — content lands at the same y as before either way. */
.navbar {
    position: sticky;
    top: 0;
    left: 0;
    right: 0;
    height: var(--navbar-height);
    background: var(--color-nav-bg);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-bottom: 2px solid var(--color-nav-edge);
    display: flex;
    align-items: center;
    padding: 0 2rem;
    z-index: 1000;
    transition: background var(--transition);
}

.navbar.scrolled {
    background: var(--color-nav-bg-solid);
}

.navbar :focus-visible {
    outline-color: var(--color-nav-accent);
}

.navbar__logo {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    flex-shrink: 0;
}

.navbar__logo img {
    height: 40px;
    width: auto;
}

.navbar__wordmark {
    font-family: var(--font-display);
    font-size: 1.45rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: var(--color-nav-text);
    line-height: 1;
}

.navbar__wordmark span {
    color: var(--color-nav-accent);
}

.navbar__nav {
    display: flex;
    align-items: center;
    gap: 0.2rem;
    margin-left: 2.5rem;
    flex: 1;
}

.navbar__nav a {
    position: relative;
    color: var(--color-nav-muted);
    font-size: 0.85rem;
    font-weight: 500;
    padding: 0.45rem 0.8rem;
    transition: color var(--transition);
    white-space: nowrap;
}

.navbar__nav a::after {
    content: '';
    position: absolute;
    left: 0.8rem;
    right: 0.8rem;
    bottom: 0;
    height: 2px;
    background: var(--color-nav-accent);
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform var(--transition);
}

.navbar__nav a:hover { color: var(--color-nav-text); }

.navbar__nav a.active { color: var(--color-nav-text); }

.navbar__nav a.active::after,
.navbar__nav a:hover::after { transform: scaleX(1); }

/* category dropdown on the "Dizalice" nav item (client test — task 12) */
.nav-dropdown {
    position: relative;
    display: flex;
    align-items: center;
}

/* the menu sits flush against this element (top: 100%, no gap) — a `top: calc(100% + Npx)`
   offset here would create a dead zone the pointer can leave while moving from the nav item
   down into the menu, dropping :hover before the menu is reached (reported bug: dropdown
   closes on the way down). Breathing room is added as padding *inside* the menu box instead. */

.nav-dropdown__toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    margin-left: -0.3rem;
    background: none;
    border: none;
    color: var(--color-nav-faint);
    cursor: pointer;
    transition: color var(--transition);
}

.nav-dropdown__toggle:hover,
.nav-dropdown.open .nav-dropdown__toggle { color: var(--color-nav-text); }

.nav-dropdown__chevron {
    width: 12px;
    height: 12px;
    transition: transform var(--transition);
}

.nav-dropdown.open .nav-dropdown__chevron { transform: rotate(180deg); }

.nav-dropdown__menu {
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 220px;
    background: var(--color-nav-bg-solid);
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: var(--radius);
    padding: 0.55rem 0.35rem 0.35rem;
    box-shadow: 0 14px 30px rgba(0, 0, 0, 0.35);
    z-index: 1100;
    /* opacity (not display:none) keeps menu links focusable — same reasoning as
       .lang-switcher__menu */
    opacity: 0;
    pointer-events: none;
    transform: translateY(4px);
    transition: opacity var(--transition), transform var(--transition);
}

/* `.nav-dropdown__menu:focus-within` (the menu, not the whole dropdown) reveals the menu when
   a keyboard user tabs into it — otherwise focus lands on invisible links. Scoping it to the
   menu matters: `.nav-dropdown:focus-within` would also match the toggle button, which keeps
   focus after a click and would pin the menu open, breaking the click-to-close toggle. */
.nav-dropdown.open .nav-dropdown__menu,
.nav-dropdown__menu:focus-within,
html:not(.js) .nav-dropdown:focus-within .nav-dropdown__menu {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
}

@media (hover: hover) {
    .nav-dropdown:hover .nav-dropdown__menu {
        opacity: 1;
        pointer-events: auto;
        transform: translateY(0);
    }
    .nav-dropdown:hover .nav-dropdown__chevron { transform: rotate(180deg); }
}

.nav-dropdown__menu a {
    white-space: nowrap;
    color: var(--color-nav-muted);
    font-size: 0.78rem;
    font-weight: 600;
    padding: 0.5rem 0.6rem;
    border-radius: 4px;
    transition: color var(--transition), background var(--transition);
}

.nav-dropdown__menu a::after { content: none; }

.nav-dropdown__menu a:hover {
    color: var(--color-nav-edge);
    background: var(--color-nav-accent);
}

.lang-switcher {
    position: relative;
    margin-left: auto;
    flex-shrink: 0;
}

.lang-switcher__toggle {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    height: 34px;   /* matches .navbar__theme so the two controls align */
    background: none;
    border: 1px solid rgba(255, 255, 255, 0.30);
    border-radius: var(--radius);
    padding: 0 0.6rem;
    color: var(--color-nav-faint);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    cursor: pointer;
    transition: color var(--transition), border-color var(--transition);
}

.lang-switcher__toggle:hover,
.lang-switcher.open .lang-switcher__toggle { color: var(--color-nav-text); }

.lang-switcher__chevron {
    width: 12px;
    height: 12px;
    transition: transform var(--transition);
}

.lang-switcher.open .lang-switcher__chevron { transform: rotate(180deg); }

.lang-switcher__menu {
    display: flex;
    flex-direction: column;
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    min-width: 170px;
    background: var(--color-nav-bg-solid);
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: var(--radius);
    padding: 0.35rem;
    box-shadow: 0 14px 30px rgba(0, 0, 0, 0.35);
    z-index: 1100;
    /* opacity (not display:none) keeps menu links focusable, so Tab reaches them
       and :focus-within works as a no-JS fallback */
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--transition);
}

/* :focus-within is the no-JS fallback only — unscoped it would keep the menu
   open whenever the toggle button itself has focus (mouse clicks focus it),
   defeating close-on-second-click and close-on-Escape. */
/* menu-scoped :focus-within — see the note on .nav-dropdown__menu above */
.lang-switcher.open .lang-switcher__menu,
.lang-switcher__menu:focus-within,
html:not(.js) .lang-switcher:focus-within .lang-switcher__menu {
    opacity: 1;
    pointer-events: auto;
}

.lang-switcher__menu a {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    color: var(--color-nav-muted);
    font-size: 0.78rem;
    font-weight: 600;
    padding: 0.5rem 0.6rem;
    border-radius: 4px;
    transition: color var(--transition), background var(--transition);
}

.lang-switcher__menu a:hover { color: var(--color-nav-text); }

.lang-switcher__menu a.current {
    color: var(--color-nav-edge);
    background: var(--color-nav-accent);
}

.lang-switcher .flag,
.lang-switcher__menu .flag {
    width: 18px;
    height: 12px;
    flex-shrink: 0;
    border-radius: 2px;
    /* hairline so light flag edges don't dissolve into the olive bar */
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.18);
}

/* mobile-menu copy of the switcher — hidden on desktop */
.navbar__nav-lang { display: none; }

.navbar__theme {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    margin-left: 0.6rem;
    flex-shrink: 0;
    background: none;
    border: 1px solid rgba(255, 255, 255, 0.30);
    border-radius: var(--radius);
    color: var(--color-nav-muted);
    cursor: pointer;
    transition: color var(--transition), border-color var(--transition);
}

.navbar__theme:hover {
    color: var(--color-nav-text);
    border-color: rgba(255, 255, 255, 0.55);
}

.navbar__theme svg {
    width: 16px;
    height: 16px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* moon invites dark mode; sun invites light mode */
.navbar__theme .icon-sun { display: none; }
[data-theme="dark"] .navbar__theme .icon-sun { display: block; }
[data-theme="dark"] .navbar__theme .icon-moon { display: none; }

.navbar__hamburger {
    display: none;
    flex-direction: column;
    gap: 5px;
    cursor: pointer;
    margin-left: auto;
    padding: 6px;
    background: none;
    border: none;
}

.navbar__hamburger span {
    display: block;
    width: 24px;
    height: 2px;
    background: var(--color-nav-text);
    border-radius: 2px;
    transition: var(--transition);
}

/* =============================================
   HERO — real KLAAS photos (variants previewed via ?hero=1|2|3)
   ============================================= */
.hero {
    position: relative;
    min-height: min(calc(100vh - var(--topbar-height) - var(--navbar-height) - var(--sticky-bar-height)), 880px);
    background:
        radial-gradient(ellipse 62% 44% at 50% 44%, var(--hero-glow), transparent 70%),
        linear-gradient(var(--grid-line) 1px, transparent 1px),
        linear-gradient(90deg, var(--grid-line) 1px, transparent 1px),
        var(--color-bg-deep);
    background-size: auto, 56px 56px, 56px 56px, auto;
    overflow: hidden;
}

@keyframes fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* --- hero content (shared by all variants) --- */
.hero__inner {
    position: relative;
    width: 100%;
    max-width: 1100px;
    margin: 0 auto;
    padding: 88px 2rem 130px;
    text-align: center;
}

.hero__inner--left { text-align: left; }

.hero__title {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.hero__title--left { align-items: flex-start; }

.hero__title > * {
    max-width: 100%;
}

.hero-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 0.7rem;
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 0.95rem;
    letter-spacing: 0.32em;
    text-transform: uppercase;
    color: var(--color-primary-bright);
    margin-bottom: 1.2rem;
    animation: fade-up 0.6s ease 0.05s both;
}

.hero-eyebrow::before {
    content: '';
    width: 26px;
    height: 2px;
    background: var(--color-primary);
}

.hero-plate {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: clamp(3.2rem, 9vw, 6.4rem);
    line-height: 0.95;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: #0c0c0c;
    background: var(--color-primary);
    padding: 0.04em 0.22em 0.1em;
    border-radius: var(--radius);
    box-shadow:
        7px 7px 0 rgba(22, 22, 19, 0.10),
        inset 0 -6px 0 rgba(0, 0, 0, 0.16);
    animation: fade-up 0.7s ease 0.15s both;
}

.hero__rest {
    display: block;
    font-family: var(--font-display);
    font-weight: 600;
    font-size: clamp(1.05rem, 2.4vw, 1.5rem);
    letter-spacing: 0.42em;
    text-indent: 0.42em;
    text-transform: uppercase;
    color: var(--color-text);
    margin-top: 1.6rem;
    animation: fade-up 0.7s ease 0.35s both;
}

.hero__rest span { color: var(--color-primary); }

.hero__sub {
    max-width: 560px;
    margin: 1.3rem auto 2.4rem;
    color: var(--color-muted);
    font-size: 1rem;
    animation: fade-up 0.7s ease 0.5s both;
}

.hero__inner--left .hero__sub { margin-left: 0; }

.hero__actions {
    display: flex;
    gap: 1rem;
    justify-content: center;
    flex-wrap: wrap;
    animation: fade-up 0.7s ease 0.65s both;
}

.hero__inner--left .hero__actions { justify-content: flex-start; }

@keyframes fade-up {
    from { opacity: 0; transform: translateY(18px); }
    to   { opacity: 1; transform: none; }
}

/* --- full-bleed photo variants: photo + fixed dark scrim, so the text
       stays light in both themes (like the olive navbar) --- */
.hero--photo {
    display: flex;
    align-items: center;
    background: #1b1b18;
}

.hero-photo__bg {
    position: absolute;
    inset: 0;
    background-image: var(--hero-img);   /* set inline in the template */
    background-size: cover;
    background-position: var(--hero-pos, center);
    animation: hero-zoom 6s ease-out both;
}

@keyframes hero-zoom {
    from { transform: scale(1.05); }
    to   { transform: none; }
}

.hero-photo__bg::after {
    /* scrim for text legibility; direction differs per variant */
    content: '';
    position: absolute;
    inset: 0;
    background: var(--hero-scrim);
}

.hero--photo .hero-eyebrow { color: #C9DA84; }
.hero--photo .hero__rest {
    color: #f2f2ef;
    text-shadow: 0 1px 10px rgba(0, 0, 0, 0.55);
}

.hero--photo .hero__sub {
    color: rgba(255, 255, 255, 0.82);
    text-shadow: 0 1px 8px rgba(0, 0, 0, 0.6);
}
.hero--photo .hero__scroll { color: rgba(255, 255, 255, 0.5); }

.hero--photo .btn--outline {
    color: #f2f2ef;
    border-color: rgba(255, 255, 255, 0.55);
}

.hero--photo .btn--outline:hover {
    border-color: var(--color-primary);
    color: #C9DA84;
}

/* --- v1 sky treatment: golden hour in light, night in dark ----------------------
   (warm grade: client request 2026-07-16; rising orb + night theme: 2026-07-17)

   k2500-yard.jpg is a flat, cold, overcast factory yard. Everything below re-lights it
   in CSS over the untouched photo rather than baking a new asset: a burned-in sun drifts
   out of frame as background-size:cover re-crops at other viewports, and every value here
   stays tunable without re-rendering anything.

   This is the one place the hero is theme-dependent. The rest of .hero--photo is
   deliberately dark in BOTH themes (fixed scrim, light text, like the olive navbar) —
   only the sky grade and the orb swap, because a moon hanging in a sunset-orange sky
   reads as a bug rather than a mood.

   The grade is done with background-blend-mode layers on .hero-photo__bg — NOT a CSS
   filter, which would also apply to that element's ::after (the legibility scrim) and
   sepia the sun along with it. Blending happens inside the one element, so the scrim
   still paints cleanly on top and text contrast is unchanged.

   Layer order, bottom to top:
     .hero-photo__bg          photo + sky grade          (rides the existing hero-zoom)
     .hero-photo__bg::after   the existing scrim         (unchanged)
     .hero-sun / .hero-moon   orb + its ambient spill    (one per theme, cross-faded)
     .hero-mark               logo watermark
     .hero__inner             headline + buttons
   ------------------------------------------------------------------------------- */
.hero--v1 {
    /* The orb — sun in light, moon in dark — sits in the one big patch of open sky: upper
       right, opposite the left text column, right where the boom crosses it so the jib
       reads backlit. Percentages are of the hero box, not the photo, so it holds its
       place as the photo re-crops. Named orb, not sun: both bodies ride these. */
    --hero-orb-x: 78%;
    --hero-orb-y: 16%;

    /* How far below its resting place the orb starts its climb. 50% of the hero box puts
       it at 66%, and the workshop roofline sits at ~57% at this x — so it starts behind
       the buildings and climbs out of them, rather than popping in over open sky. */
    --hero-orb-travel: 50%;

    /* The disc's own box. Must stay comfortably wider than twice the widest gradient in
       it (the sun's 400px bloom), or its edge cuts the glow — see .hero-orb::after. */
    --hero-orb-size: 900px;

    --hero-scrim: linear-gradient(90deg,
        rgba(20, 20, 17, 0.90) 0%,
        rgba(20, 20, 17, 0.62) 44%,
        rgba(20, 20, 17, 0.16) 78%,
        rgba(20, 20, 17, 0.32) 100%);
}

/* The sky does the work. multiply against that big flat pale-grey sky lands hard (light
   pixels take the full tint), while the dark truck and asphalt barely move — so the scene
   warms where real evening light would warm it, and the KLAAS truck keeps its blue. A sepia
   filter strong enough to warm this sky turned the truck brown; recolouring the client's
   product to sell a mood is not a trade worth making, which is why this is a blend and not
   a filter. Blended inside .hero-photo__bg, so the ::after scrim still paints clean on top. */
/* Scoped to .hero--effects: the admin sun/moon switch (off -> class absent) drops the sky
   grade too, so the hero falls back to the plain .hero-photo__bg photo. */
.hero--v1.hero--effects .hero-photo__bg {
    background-image:
        linear-gradient(179deg,
            rgba(255, 148, 58, 0.95) 0%,
            rgba(255, 172, 88, 0.78) 24%,
            rgba(255, 206, 142, 0.44) 42%,
            rgba(255, 236, 198, 0.16) 54%,
            rgba(255, 255, 255, 0) 64%),
        var(--hero-img);
    background-size: cover;
    background-position: var(--hero-pos, center);
    background-blend-mode: multiply, normal;
    /* claw back the contrast multiply costs, and lift the saturation the overcast day lacked */
    filter: saturate(1.28) contrast(1.08) brightness(1.04);
}

/* Night, same trick in a colder key: the multiply rides the same 179deg ramp so the sky
   goes deep dusk-blue while the truck and asphalt hold. Blue over blue is the free part —
   unlike the warm grade, which had to be argued down from a sepia filter to keep the truck
   from going brown, a blue tint on a blue truck only deepens it. Overrides live here rather
   than in the dark-theme block at the top of the file: these are photographic light values,
   worth nothing except read side by side with the golden-hour stack directly above.
   Kept: saturation down (night desaturates), brightness well down (this is the only thing
   that actually sells "night" — multiply alone just tints). The filter reaches the ::after
   scrim too, which only ever darkens it, so headline contrast can only improve. */
html[data-theme="dark"] .hero--v1.hero--effects .hero-photo__bg {
    background-image:
        linear-gradient(179deg,
            rgba(38, 58, 122, 0.96) 0%,
            rgba(52, 74, 140, 0.82) 24%,
            rgba(84, 108, 165, 0.50) 42%,
            rgba(130, 152, 194, 0.20) 54%,
            rgba(255, 255, 255, 0) 64%),
        var(--hero-img);
    filter: saturate(0.90) contrast(1.06) brightness(0.72);
}

/* --- the orb: sun in light, moon in dark, both rising on load -------------------
   Both are always in the DOM and the theme cross-fades between them (client spec,
   2026-07-17): the climb is a page-load moment, so re-running 2.4s of it on every navbar
   toggle would put an animation in front of a button people click twice in a row. A
   toggle mid-climb is fine and needs no special case — the incoming orb is simply caught
   partway up.

   Three layers per orb, each one earning its place:
     .hero-sun / .hero-moon   theme opacity + the screen blend. Nothing animates here.
       ::before               ambient spill; fades in, never moves (see below)
     .hero-orb                hero-sized, rides the rise transform
       ::after                the disc, in a box sized to its gradient (see below)

   The outer element's opacity is left free ON PURPOSE, because it is what the theme swap
   uses. Put the fade on it instead and `animation-fill-mode: both` pins the animated value
   there for good — an animation beats a plain declaration in the cascade, so
   `html[data-theme="dark"] .hero-sun { opacity: 0 }` would never win and dark theme would
   show the sun and the moon at once.

   The spill fades but never travels, and that is a constraint rather than a choice: its
   gradients run edge to edge, so any box it moved in would cut them into a visible line at
   its own border (the disc learned this the hard way — see .hero-orb::after). Only things
   whose gradient dies out before the box edge can be moved.

   ABOVE the scrim: under it, the scrim's 0.62–0.90 left ramp swallowed the glow entirely.
   screen only ever adds light, so it brightens sky without lifting the blacks the headline
   sits on. Reduced motion needs nothing here — the global rule near the bottom of this file
   cuts every animation to 0.01ms, and `both` then holds each orb at its resting state. */
.hero-sun,
.hero-moon {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    mix-blend-mode: screen;
    transition: opacity 0.6s ease;
}

.hero-moon { opacity: 0; }
html[data-theme="dark"] .hero-sun  { opacity: 0; }
html[data-theme="dark"] .hero-moon { opacity: 1; }

/* The disc. Rises by transform — animating --hero-orb-y instead would repaint a
   full-bleed gradient stack every frame (and need @property to interpolate at all),
   where a transform is a compositor job. inset:0 is what makes the travel percentage
   readable: the pseudo is the size of the hero box, so translateY(50%) is half a hero. */
/* The travelling layer, and the reason the orb is two nested elements instead of one:
   it is hero-sized, so `translateY(50%)` means half a hero and the travel scales with the
   viewport. It deliberately carries no background of its own — the gradient needs a box
   that is NOT hero-sized (below), and one element cannot be both.

   Slow-start curve, not a normal ease-out: an ease-out spends its speed in the first
   fraction of a second, which here is the part still hidden behind the roofline, and
   leaves the whole back half of the duration drifting the last ~30px — the rise was over
   by 1s and the other 1.4s just hung there. Starting at zero velocity spends the time on
   the climb you can actually see: measured, ~8% up at 350ms, ~37% at 700ms, ~66% at
   1050ms, then a long settle. */
.hero-orb {
    position: absolute;
    inset: 0;
    animation: hero-orb-rise 2.6s cubic-bezier(0.33, 0, 0.2, 1) both;
}

/* The disc, in a fixed box centred on the orb point.

   A background only ever paints inside its own element's box, so a MOVING layer whose
   gradient is still opaque where the box ends drags a hard edge along with it. The disc
   first shipped on a hero-sized pseudo and did exactly that: the box's top edge sliced the
   bloom at ~38% alpha, exactly `--hero-orb-y` (104px at a 648px hero) above the sun — a
   line that rode up the whole climb and only vanished at rest, where the edge lands at the
   hero's top and hides under the navbar. Reported from the client preview, 2026-07-17.

   So the box is sized to the gradient, not to the hero: half of --hero-orb-size (450px)
   clears the sun's 400px bloom, which is fully transparent by 288px anyway. .hero has
   overflow:hidden, so the oversized box costs nothing. Centred with negative margins, NOT
   translate(-50%, -50%), which would have to be repeated in every keyframe to keep the
   transform free for the rise. */
.hero-orb::after {
    content: '';
    position: absolute;
    left: var(--hero-orb-x);
    top: var(--hero-orb-y);
    width: var(--hero-orb-size);
    height: var(--hero-orb-size);
    margin: calc(var(--hero-orb-size) / -2) 0 0 calc(var(--hero-orb-size) / -2);
}

.hero-sun .hero-orb::after {
    background:
        /* hot core — the only near-white thing in frame */
        radial-gradient(circle 58px at center,
            rgba(255, 252, 232, 0.98) 0%, rgba(255, 236, 176, 0.80) 60%, rgba(255, 214, 130, 0) 100%),
        /* bloom, wide and soft so the boom edges catch it */
        radial-gradient(circle 400px at center,
            rgba(255, 176, 84, 0.62) 0%, rgba(255, 138, 46, 0.22) 44%, rgba(255, 120, 40, 0) 72%);
}

/* The moon is not a blue sun: a small hard disc and a tight halo, where the sun is a hot
   core in a 400px bloom. Moonlight barely spills — the wide soft glow is what would make
   it read as a second sun that someone tinted. */
.hero-moon .hero-orb::after {
    background:
        /* disc — cool white, crisp edge, smaller than the sun's core */
        radial-gradient(circle 30px at center,
            rgba(248, 250, 255, 0.98) 0%, rgba(228, 238, 255, 0.90) 66%, rgba(198, 216, 248, 0) 100%),
        /* halo — tight and dim next to the sun's bloom */
        radial-gradient(circle 210px at center,
            rgba(150, 180, 238, 0.30) 0%, rgba(112, 146, 212, 0.10) 46%, rgba(96, 130, 200, 0) 74%);
}

/* Ambient spill: the light the orb throws on the scene, as opposed to the orb itself. It
   fades in over the climb rather than sitting there from frame one, so the yard lights up
   as the orb clears the roofline instead of being lit by a sun that hasn't arrived. */
.hero-sun::before,
.hero-moon::before {
    content: '';
    position: absolute;
    inset: 0;
    animation: hero-orb-spill 2.6s ease-in both;
}

.hero-sun::before {
    background:
        /* directional cast falling from the sun's corner — this is what reads as late
           afternoon rather than "someone dragged an orange filter over it" */
        linear-gradient(202deg,
            rgba(255, 150, 62, 0.34) 0%, rgba(255, 120, 40, 0.10) 46%, rgba(255, 120, 40, 0) 66%),
        /* bounce light on the yard. multiply above tints the sky but leaves the dark ground
           cold, and a golden sky over a grey yard reads as two photos stitched together —
           this warms the truck's lit side and the workshop enough to join them up */
        radial-gradient(ellipse 74% 44% at 70% 60%,
            rgba(255, 146, 58, 0.20) 0%, rgba(255, 130, 48, 0.07) 46%, rgba(255, 130, 48, 0) 74%);
}

/* Same two layers, roughly a third the strength: moonlight joins the sky to the yard the
   same way, it just does far less of it. */
.hero-moon::before {
    background:
        linear-gradient(202deg,
            rgba(146, 176, 232, 0.15) 0%, rgba(110, 142, 205, 0.05) 46%, rgba(110, 142, 205, 0) 66%),
        radial-gradient(ellipse 74% 44% at 70% 60%,
            rgba(132, 164, 220, 0.09) 0%, rgba(110, 142, 205, 0.03) 46%, rgba(110, 142, 205, 0) 74%);
}

/* Opacity is done at 30%, roughly where the disc crests the roofline, so the rest of the
   climb happens at full strength. Carry the fade any further up and it stops reading as a
   sunrise and starts reading as someone turning up a dimmer. */
@keyframes hero-orb-rise {
    from { transform: translateY(var(--hero-orb-travel, 50%)); opacity: 0; }
    30%  { opacity: 1; }
    to   { transform: translateY(0); opacity: 1; }
}

@keyframes hero-orb-spill {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Logo watermark, bleeding off the bottom-left corner so it reads as brand texture rather
   than a sticker, and balancing the sun in the opposite corner. Bottom-LEFT specifically:
   the scrim runs 0.62–0.90 there, making it the darkest ground in frame, which is the only
   place a white mark reads. (It started bottom-right and was invisible at any sane opacity —
   that corner is the workshop's white roller doors, so white-on-white.)
   Above the scrim — beneath it the mark turns to mud — but below the copy. */
.hero-mark {
    position: absolute;
    left: -5%;
    bottom: -14%;
    width: min(360px, 34vw);
    aspect-ratio: 660 / 573;
    background: url('../images/02-mono-white.png') center / contain no-repeat;
    opacity: 0.13;
    pointer-events: none;
    z-index: 2;
}

.hero--v1 .hero__inner,
.hero--v1 .hero__scroll {
    position: relative;
    z-index: 3;   /* keep copy above the orb layers and .hero-mark */
}

.hero--v3 {
    align-items: flex-end;
    --hero-pos: center 32%;
    --hero-scrim: linear-gradient(180deg,
        rgba(20, 20, 17, 0.30) 0%,
        rgba(20, 20, 17, 0.22) 34%,
        rgba(20, 20, 17, 0.68) 62%,
        rgba(20, 20, 17, 0.94) 100%);
}

.hero--v3 .hero__inner {
    padding-top: 48px;
    padding-bottom: 120px;
}

/* --- split variant: theme background + studio cutout on a white plate --- */
.hero--split {
    display: flex;
    align-items: center;
}

.hero-split {
    position: relative;
    display: grid;
    grid-template-columns: 1.05fr 1fr;
    gap: 3.5rem;
    align-items: center;
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    padding: 72px 2rem 110px;
}

.hero-split__text { text-align: left; }
.hero-split__text .hero__sub { margin-left: 0; }
.hero-split__text .hero__actions { justify-content: flex-start; }

.hero-split__fig {
    position: relative;
    margin: 0;
    background: #fff;
    /* cut top-right corner, echoes the pillar / category plates;
       shadow must be drop-shadow — box-shadow gets swallowed by the clip */
    clip-path: polygon(0 0, calc(100% - 28px) 0, 100% 28px, 100% 100%, 0 100%);
    filter: drop-shadow(10px 10px 0 rgba(22, 22, 19, 0.10));
    animation: fade-up 0.7s ease 0.35s both;
}

.hero-split__fig img {
    display: block;
    width: 100%;
    height: auto;
    padding: 1.2rem 1.2rem 0.4rem;
}

.hero-split__caption {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.55rem 1.1rem 0.65rem;
    border-top: 1px solid rgba(22, 22, 19, 0.14);
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 0.85rem;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: #3c3c36;
}

.hero__scroll {
    position: absolute;
    bottom: 7px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    color: var(--color-faint);
    font-size: 0.6rem;
    font-weight: 600;
    letter-spacing: 0.34em;
    text-indent: 0.34em;
    text-transform: uppercase;
    animation: fade-in 0.8s ease 1.3s both;
}

.hero__scroll::after {
    content: '';
    width: 2px;
    height: 24px;
    background: linear-gradient(var(--color-primary), transparent);
    animation: scroll-pulse 1.8s ease-in-out infinite;
}

@keyframes scroll-pulse {
    0%, 100% { opacity: 0.35; transform: scaleY(0.7); transform-origin: top; }
    50%      { opacity: 1; transform: scaleY(1); }
}

/* =============================================
   MARQUEE
   ============================================= */
.marquee {
    overflow: hidden;
    background: var(--color-bg-deep);
    border-top: 1px solid var(--color-border);
    border-bottom: 1px solid var(--color-border);
    padding: 0.95rem 0;
}

.marquee__track {
    display: flex;
    width: max-content;
    animation: marquee 36s linear infinite;
}

.marquee__group {
    display: flex;
    align-items: center;
}

.marquee__item {
    display: flex;
    align-items: center;
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 1.05rem;
    letter-spacing: 0.28em;
    text-transform: uppercase;
    color: var(--color-faint);
    white-space: nowrap;
}

.marquee__item::after {
    content: '';
    width: 8px;
    height: 8px;
    background: var(--color-primary);
    transform: rotate(45deg);
    margin: 0 2.6rem;
    flex-shrink: 0;
}

@keyframes marquee {
    to { transform: translateX(-50%); }
}

/* =============================================
   SECTIONS
   ============================================= */
.section {
    padding: 5.5rem 2rem;
    background: var(--color-bg);
}

.section--deep {
    background: var(--color-bg-deep);
    border-top: 1px solid var(--color-border);
    border-bottom: 1px solid var(--color-border);
}

.section__inner {
    max-width: 1160px;
    margin: 0 auto;
}

.section__header {
    text-align: center;
    margin-bottom: 3.2rem;
}

.section__label {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    color: var(--color-primary);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.35em;
    text-transform: uppercase;
    margin-bottom: 0.8rem;
}

.section__label::before,
.section__label::after {
    content: '';
    width: 26px;
    height: 2px;
    background: var(--color-primary);
    opacity: 0.6;
}

.section__title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: clamp(2rem, 3.6vw, 2.9rem);
    line-height: 1.08;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}

.section__desc {
    margin: 0.9rem auto 0;
    color: var(--color-muted);
    max-width: 580px;
    font-size: 0.95rem;
}

/* =============================================
   PILLARS
   ============================================= */
.pillars {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1.4rem;
}

.pillar {
    position: relative;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    /* cut steel-plate corner, echoes the hero load plate */
    clip-path: polygon(0 0, calc(100% - 16px) 0, 100% 16px, 100% 100%, 0 100%);
    padding: 2.2rem 1.9rem;
    transition: transform var(--transition), border-color var(--transition),
                filter var(--transition);
}

.pillar:hover {
    transform: translateY(-4px);
    border-color: rgba(132, 155, 46, 0.5);
    /* drop-shadow (not box-shadow) so the shadow follows the clipped corner */
    filter: drop-shadow(5px 5px 0 rgba(132, 155, 46, 0.28));
}

.pillar__num {
    position: absolute;
    top: 1.1rem;
    right: 1.3rem;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.05rem;
    letter-spacing: 0.12em;
    color: var(--num-ghost);
}

.pillar__icon {
    width: 52px;
    height: 52px;
    background: var(--color-primary-tint);
    border: 1px solid rgba(132, 155, 46, 0.3);
    border-radius: var(--radius);
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 1.4rem;
}

.pillar__icon svg {
    width: 26px;
    height: 26px;
    color: var(--color-primary-bright);
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.pillar__title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.5rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    margin-bottom: 0.6rem;
}

.pillar__text {
    font-size: 0.9rem;
    color: var(--color-muted);
    line-height: 1.7;
}

.pillar__link {
    display: inline-block;
    margin-top: 1.3rem;
    color: var(--color-primary-bright);
    font-size: 0.83rem;
    font-weight: 600;
    letter-spacing: 0.04em;
}

.pillar__link:hover { text-decoration: underline; }

/* =============================================
   CATEGORY CARDS (crane silhouettes)
   ============================================= */
.categories {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1.4rem;
}

.category-card {
    position: relative;
    display: flex;
    flex-direction: column;
    min-height: 265px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    /* cut steel-plate corner, echoes the hero load plate */
    clip-path: polygon(0 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 0 100%);
    padding: 1.6rem 1.8rem 1.5rem;
    overflow: hidden;
    transition: transform var(--transition), border-color var(--transition),
                filter var(--transition);
}

.category-card:hover {
    transform: translateY(-4px);
    border-color: rgba(132, 155, 46, 0.6);
    /* drop-shadow (not box-shadow) so the shadow follows the clipped corner */
    filter: drop-shadow(6px 6px 0 rgba(132, 155, 46, 0.28));
}

.category-card__num {
    position: absolute;
    top: 1.1rem;
    left: 1.5rem;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.05rem;
    letter-spacing: 0.12em;
    color: var(--num-ghost);
}

.category-card__arrow {
    position: absolute;
    top: 1.1rem;
    right: 1.2rem;
    width: 34px;
    height: 34px;
    background: var(--color-primary);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transform: translate(-6px, 6px) scale(0.85);
    transition: opacity var(--transition), transform var(--transition);
}

.category-card:hover .category-card__arrow {
    opacity: 1;
    transform: none;
}

.category-card__arrow svg {
    width: 15px;
    height: 15px;
    stroke: #0b0b0b;
    fill: none;
    stroke-width: 2.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.category-card__fig {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.4rem 0 1.1rem;
}

.category-card__fig svg {
    height: 120px;
    width: auto;
    max-width: 100%;
    color: rgba(22, 22, 19, 0.38);
    transition: color 0.3s ease;
}

.category-card:hover .category-card__fig svg {
    color: var(--color-primary-bright);
}

.category-card__title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.45rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    line-height: 1.1;
}

.category-card__sub {
    font-size: 0.82rem;
    color: var(--color-muted);
    margin-top: 0.25rem;
}

/* rating-plate spec line */
.category-card__spec {
    margin-top: 0.9rem;
    padding-top: 0.65rem;
    border-top: 1px dashed var(--color-border-strong);
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 0.88rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--color-primary-bright);
}

/* =============================================
   ABOUT STRIP
   ============================================= */
.about-strip {
    display: grid;
    grid-template-columns: 1.1fr 0.9fr;
    gap: 4rem;
    align-items: center;
}

.about-strip__title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: clamp(1.8rem, 3vw, 2.6rem);
    line-height: 1.12;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    margin: 0.4rem 0 1.1rem;
}

.about-strip__title span { color: var(--color-primary-bright); }

.about-strip__text {
    color: var(--color-muted);
    line-height: 1.75;
    margin-bottom: 1.1rem;
    font-size: 0.95rem;
}

.about-strip__stats {
    display: flex;
    gap: 3rem;
    margin-top: 2.2rem;
}

.stat__number {
    display: block;
    font-family: var(--font-display);
    font-size: 2.7rem;
    font-weight: 700;
    color: var(--color-primary-bright);
    line-height: 1;
    letter-spacing: 0.02em;
}

.stat__label {
    display: block;
    font-size: 0.78rem;
    color: var(--color-muted);
    margin-top: 0.35rem;
}

.about-panel {
    position: relative;
    min-height: 400px;
    background:
        linear-gradient(var(--grid-line) 1px, transparent 1px),
        linear-gradient(90deg, var(--grid-line) 1px, transparent 1px),
        var(--color-bg-deep);
    background-size: 44px 44px, 44px 44px, auto;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    display: grid;
    place-items: center;
}

.about-panel img {
    width: 56%;
}

.about-panel::before,
.about-panel::after {
    content: '';
    position: absolute;
    width: 28px;
    height: 28px;
}

.about-panel::before {
    top: 14px;
    left: 14px;
    border-top: 2px solid var(--color-primary);
    border-left: 2px solid var(--color-primary);
}

.about-panel::after {
    bottom: 14px;
    right: 14px;
    border-bottom: 2px solid var(--color-primary);
    border-right: 2px solid var(--color-primary);
}

/* =============================================
   CTA BAR
   ============================================= */
.cta-bar {
    position: relative;
    text-align: center;
    padding: 4.5rem 2rem;
    background:
        linear-gradient(rgba(0, 0, 0, 0.05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(0, 0, 0, 0.05) 1px, transparent 1px),
        var(--color-primary);
    background-size: 44px 44px, 44px 44px, auto;
}

/* hazard stripe along the top edge */
.cta-bar::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 8px;
    background: repeating-linear-gradient(-45deg,
        var(--color-text) 0 14px, transparent 14px 28px);
    opacity: 0.85;
}

.cta-bar__title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: clamp(1.8rem, 3.2vw, 2.7rem);
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: #0c0c0c;
    margin-bottom: 0.4rem;
}

.cta-bar__sub {
    color: rgba(0, 0, 0, 0.68);
    font-size: 0.95rem;
    font-weight: 500;
    margin-bottom: 2rem;
}

/* =============================================
   FOOTER
   ============================================= */
.footer {
    background: var(--color-bg-deep);
    border-top: 1px solid var(--color-border);
    color: var(--color-muted);
    padding: 3.5rem 2rem 2rem;
    font-size: 0.875rem;
}

.footer__inner {
    max-width: 1160px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 1.3fr;
    gap: 2.5rem;
}

.footer__brand img {
    height: 44px;
    margin-bottom: 1rem;
}

.footer__brand-name {
    font-family: var(--font-display);
    font-size: 1.35rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: var(--color-text);
    margin-bottom: 0.5rem;
}

.footer__brand-name span { color: var(--color-primary); }

.footer__tagline {
    line-height: 1.7;
    max-width: 280px;
}

.footer__col-title {
    font-family: var(--font-display);
    font-size: 0.95rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.22em;
    color: var(--color-text);
    margin-bottom: 1.1rem;
}

.footer__col ul {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
}

.footer__col ul a {
    color: var(--color-muted);
    transition: color var(--transition);
}

.footer__col ul a:hover { color: var(--color-primary-bright); }

.footer__contact-item {
    display: flex;
    align-items: flex-start;
    gap: 0.65rem;
    margin-bottom: 0.7rem;
    line-height: 1.5;
}

.footer__contact-item svg {
    width: 15px;
    height: 15px;
    margin-top: 4px;
    flex-shrink: 0;
    stroke: var(--color-primary);
    fill: none;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.footer__contact-item a:hover { color: var(--color-primary-bright); }

.footer__bottom {
    max-width: 1160px;
    margin: 2.5rem auto 0;
    padding-top: 1.5rem;
    border-top: 1px solid var(--color-border);
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem 1.5rem;
    font-size: 0.78rem;
    color: var(--color-faint);
}

.footer__bottom strong { color: var(--color-muted); }

.footer__credit a {
    color: var(--color-muted);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: color 0.2s, border-color 0.2s;
}

.footer__credit a:hover {
    color: var(--color-primary-bright);
    border-bottom-color: currentColor;
}

.footer__legal {
    max-width: 1160px;
    margin: 2.5rem auto 0;
    padding-top: 1.5rem;
    border-top: 1px solid var(--color-border);
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.5rem;
    font-size: 0.78rem;
}

.footer__legal a {
    color: var(--color-faint);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: color 0.2s, border-color 0.2s;
}

.footer__legal a:hover {
    color: var(--color-primary-bright);
    border-bottom-color: currentColor;
}

/* legal row already draws the divider; the bottom row below it shouldn't repeat it */
.footer__legal + .footer__bottom {
    margin-top: 1rem;
    padding-top: 0;
    border-top: none;
}

/* =============================================
   STICKY BOTTOM BAR
   ============================================= */
.sticky-bar {
    position: fixed;
    bottom: 18px;
    left: 50%;
    transform: translateX(-50%);
    width: max-content;
    max-width: calc(100vw - 2rem);
    min-height: var(--sticky-bar-height);
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid var(--color-border);
    border-radius: 14px;
    box-shadow: 0 10px 26px rgba(22, 22, 19, 0.14), 0 2px 6px rgba(22, 22, 19, 0.08);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    z-index: 999;
    padding: 0.55rem 1.6rem;
    transition: transform 0.35s ease, opacity 0.3s ease, visibility 0s;
}

/* Mid-scroll morph, browse pages only (.sticky-mini is only rendered on
   /dizalice*, /rabljeno*, /najam* — see base.html): the pill slides away and a
   small corner badge takes over. `translate(-50%, …)` restates the `-50%`
   centering `.sticky-bar` normally gets from `translateX(-50%)`, since any
   `transform` in this rule replaces it. */
body.sticky-collapsed .sticky-bar {
    transform: translate(-50%, calc(100% + 24px));
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: transform 0.35s ease, opacity 0.3s ease, visibility 0s 0.35s;
}

/* Small KLAAS corner badge — on the browse pages (Dizalice / Rabljeno / Najam
   + /dizalice/<id>/ detail) it fades in bottom-left when the pill collapses
   mid-scroll (body.sticky-collapsed); hidden otherwise so the full pill is
   what shows at the top/bottom of these pages. */
.sticky-mini {
    position: fixed;
    left: 18px;
    bottom: 18px;
    z-index: 998;
    display: flex;
    align-items: center;
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid var(--color-border);
    border-radius: 14px;
    box-shadow: 0 10px 26px rgba(22, 22, 19, 0.14), 0 2px 6px rgba(22, 22, 19, 0.08);
    padding: 0.45rem 0.7rem;
    pointer-events: none;
    opacity: 0;
    transform: translateY(14px);
    visibility: hidden;
    transition: transform 0.35s ease, opacity 0.3s ease, visibility 0s 0.35s;
}

body.sticky-collapsed .sticky-mini {
    opacity: 0.75;
    transform: none;
    visibility: visible;
    pointer-events: auto;
    transition: transform 0.35s ease, opacity 0.3s ease, visibility 0s;
}

.sticky-mini img {
    height: 22px;
    width: auto;
    display: block;
}

.sticky-bar__text {
    font-family: var(--font-display);
    color: var(--color-muted);
    font-size: 0.92rem;
    font-weight: 600;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    white-space: nowrap;
}

.sticky-bar__logo-link {
    display: inline-flex;
    align-items: center;
    color: inherit;
    text-decoration: none;
}

.sticky-bar__logo {
    height: 26px;
    width: auto;
}

.sticky-bar__divider {
    width: 1px;
    height: 24px;
    background: var(--color-border-strong);
    margin: 0 0.4rem;
}

/* =============================================
   PAGE HERO (inner pages)
   ============================================= */
.page-hero {
    position: relative;
    background:
        linear-gradient(var(--grid-line) 1px, transparent 1px),
        linear-gradient(90deg, var(--grid-line) 1px, transparent 1px),
        var(--color-bg-deep);
    background-size: 56px 56px, 56px 56px, auto;
    border-bottom: 1px solid var(--color-border);
    padding: 4.5rem 2rem 3.5rem;
    text-align: center;
    overflow: hidden;
}

.page-hero__label {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    color: var(--color-primary);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.35em;
    text-transform: uppercase;
    margin-bottom: 0.8rem;
}

.page-hero__label::before,
.page-hero__label::after {
    content: '';
    width: 26px;
    height: 2px;
    background: var(--color-primary);
    opacity: 0.6;
}

.page-hero__title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: clamp(2.2rem, 4.6vw, 3.6rem);
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--color-text);
    line-height: 1.05;
}

.page-hero__sub {
    max-width: 620px;
    margin: 0.9rem auto 0;
    color: var(--color-muted);
    font-size: 0.95rem;
}

/* =============================================
   CONTENT CARDS (machines, used, rent)
   ============================================= */
.cards-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1.4rem;
}

.card {
    display: flex;
    flex-direction: column;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    overflow: hidden;
    transition: transform var(--transition), border-color var(--transition),
                box-shadow var(--transition);
}

.card:hover {
    transform: translateY(-4px);
    border-color: rgba(132, 155, 46, 0.4);
    box-shadow: 0 14px 32px rgba(0, 0, 0, 0.12);
}

.card__image {
    aspect-ratio: 16 / 10;
    background:
        linear-gradient(var(--grid-line) 1px, transparent 1px),
        linear-gradient(90deg, var(--grid-line) 1px, transparent 1px),
        var(--color-bg-deep);
    background-size: 34px 34px, 34px 34px, auto;
    border-bottom: 1px solid var(--color-border);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.card__image svg {
    height: 72%;
    width: auto;
    color: rgba(22, 22, 19, 0.32);
    transition: color 0.3s ease;
}

.card:hover .card__image svg {
    color: var(--color-primary-bright);
}

.card__image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.card__body {
    padding: 1.25rem;
    flex: 1;
}

.card__title {
    display: block;
    font-family: var(--font-display);
    font-size: 1.3rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    margin-bottom: 0.35rem;
}

.card__tag {
    display: inline-block;
    color: var(--color-primary-bright);
    border: 1px solid rgba(132, 155, 46, 0.4);
    background: var(--color-primary-tint);
    font-size: 0.68rem;
    font-weight: 700;
    padding: 0.18rem 0.6rem;
    border-radius: 3px;
    margin-bottom: 0.5rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

.card__desc {
    font-size: 0.85rem;
    color: var(--color-muted);
    line-height: 1.6;
}

.card__text {
    font-size: 0.85rem;
    color: var(--color-faint);
    line-height: 1.55;
    margin-top: 0.5rem;
}

.card__footer {
    padding: 0.85rem 1.25rem;
    border-top: 1px solid var(--color-border);
    display: flex;
    justify-content: flex-end;
    gap: 0.6rem;
}

/* =============================================
   MACHINE DETAIL
   ============================================= */
.page-hero__back {
    /* own line, centered, tight click target — kept off the same line as the
       category chip / title (which are inline-level and would otherwise share it) */
    display: block;
    width: fit-content;
    margin: 0 auto 1.6rem;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--color-muted);
}

.page-hero__back:hover { color: var(--color-primary-bright); }

.detail-layout {
    display: grid;
    grid-template-columns: 1.1fr 1fr;
    gap: 2.4rem;
    align-items: start;
}

/* Event detail is an article, not a product page: the gallery leads full-width and the prose
   runs underneath at a readable measure. (The side-by-side .detail-layout above is for
   machine detail, where the spec plate genuinely belongs next to the photo.) */
/* the dot indicators are the last thing in the wrapper, so this gap is measured from them —
   it needs to be wider than it looks on paper to read as separation from the body copy */
.article-layout__gallery {
    margin-bottom: 3.8rem;
}

.article-layout__body {
    max-width: 720px;
    margin: 0 auto;
}

/* --- Legal pages (privacy / cookies / impressum / terms): long-form prose --- */
.legal {
    max-width: 760px;
    margin: 0 auto;
}
.legal h2 {
    font-family: var(--font-display);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    font-size: 1.4rem;
    color: var(--color-text);
    margin: 2.6rem 0 0.9rem;
}
.legal h2:first-child { margin-top: 0; }
.legal h3 {
    font-family: var(--font-display);
    text-transform: uppercase;
    font-size: 1.08rem;
    color: var(--color-text);
    margin: 1.7rem 0 0.6rem;
}
.legal p,
.legal li {
    color: var(--color-muted);
    line-height: 1.75;
}
.legal p { margin: 0 0 1rem; }
.legal ul { margin: 0 0 1rem; padding-left: 1.25rem; }
.legal li { margin-bottom: 0.4rem; }
.legal a {
    color: var(--color-primary-bright);
    text-decoration: underline;
    text-underline-offset: 2px;
}
.legal strong { color: var(--color-text); }
.legal__meta {
    list-style: none;
    padding: 0.2rem 0 0.2rem 1.1rem;
    margin: 0 0 1rem;
    border-left: 3px solid var(--color-primary);
}
.legal__meta li { margin-bottom: 0.55rem; }
.legal__updated {
    margin-top: 2.8rem;
    font-size: 0.86rem;
    color: var(--color-faint);
}

.detail-gallery__main {
    aspect-ratio: 4 / 3;
    background:
        linear-gradient(var(--grid-line) 1px, transparent 1px),
        linear-gradient(90deg, var(--grid-line) 1px, transparent 1px),
        var(--color-bg-deep);
    background-size: 34px 34px, 34px 34px, auto;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.detail-gallery__main svg {
    height: 72%;
    width: auto;
    color: rgba(22, 22, 19, 0.32);
}

[data-theme="dark"] .detail-gallery__main svg { color: rgba(255, 255, 255, 0.26); }

.detail-gallery__main img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.detail-gallery__thumbs {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin-top: 0.8rem;
}

.detail-gallery__thumb {
    width: 74px;
    height: 56px;
    padding: 0;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    overflow: hidden;
    cursor: pointer;
    background: var(--color-bg-deep);
    opacity: 0.65;
    transition: opacity var(--transition), border-color var(--transition);
}

.detail-gallery__thumb img { width: 100%; height: 100%; object-fit: cover; }

.detail-gallery__thumb:hover { opacity: 0.9; }

.detail-gallery__thumb.active {
    opacity: 1;
    border-color: var(--color-primary);
}

.detail-desc {
    color: var(--color-muted);
    font-size: 0.95rem;
    line-height: 1.7;
    margin-bottom: 1.6rem;
}

.detail-desc p + p { margin-top: 0.9rem; }

.detail-desc h2,
.detail-desc h3 {
    font-family: var(--font-display);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--color-text);
    margin: 1.4rem 0 0.6rem;
}

.detail-desc h2 { font-size: 1.4rem; }
.detail-desc h3 { font-size: 1.15rem; }

.detail-desc ul,
.detail-desc ol {
    margin: 0.9rem 0;
    padding-left: 1.2rem;
}

.detail-desc li + li { margin-top: 0.4rem; }

.detail-desc a {
    color: var(--color-primary-bright);
    text-decoration: underline;
}

.detail-desc blockquote {
    border-left: 2px solid var(--color-border-strong);
    padding-left: 1rem;
    margin: 0.9rem 0;
    color: var(--color-faint);
}

.spec-plate {
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius);
    padding: 1.1rem 1.3rem;
    background: var(--color-surface);
    margin-bottom: 1.6rem;
}

.spec-plate__title {
    display: block;
    font-family: var(--font-display);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-size: 0.85rem;
    color: var(--color-primary-bright);
    margin-bottom: 0.7rem;
}

.spec-plate__list { display: flex; flex-direction: column; gap: 0.5rem; }

.spec-plate__row {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--color-border);
    font-size: 0.88rem;
}

.spec-plate__row:last-child { border-bottom: none; padding-bottom: 0; }

.spec-plate__row dt { color: var(--color-muted); }
.spec-plate__row dd { font-weight: 600; color: var(--color-text); }

.detail-links {
    display: flex;
    flex-wrap: wrap;
    gap: 0.7rem;
}

.table-figs {
    margin-top: 3rem;
    padding-top: 2.4rem;
    border-top: 1px solid var(--color-border);
}

.table-figs__grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1.6rem;
    margin-top: 1rem;
}

.table-figs__fig {
    margin: 0;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 0.9rem;
    background: var(--color-surface);
}

.table-figs__fig figcaption {
    font-family: var(--font-display);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-size: 0.8rem;
    color: var(--color-muted);
    margin-bottom: 0.6rem;
}

.table-figs__fig img {
    width: 100%;
    max-width: 100%;
    height: auto;
    display: block;
    border: 1px solid var(--color-border);
    /* KLAAS load/capacity diagrams are transparent line art drawn for a light
       background; keep a fixed white matte so they stay legible in dark mode too
       (a theme-following surface would swallow the dark axis lines and labels) */
    background: #fff;
    border-radius: var(--radius);
}

.detail-source {
    margin-top: 2.4rem;
    padding-top: 1.2rem;
    border-top: 1px solid var(--color-border);
    font-size: 0.85rem;
    color: var(--color-muted);
}

.detail-source a {
    color: var(--color-primary-bright);
    word-break: break-all;
}

@media (max-width: 860px) {
    .detail-layout { grid-template-columns: 1fr; }
    .table-figs__grid { grid-template-columns: 1fr; }
}

/* =============================================
   CATEGORY SECTION NAV (scroll arrows on /dizalice/)
   ============================================= */
/* anchor jumps (#autodizalice etc.) must clear the fixed navbar */
[data-category-section] {
    scroll-margin-top: calc(var(--navbar-height) + 12px);
}

.section-nav {
    position: fixed;
    top: 50%;
    right: 18px;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    z-index: 900;
}

.section-nav__btn {
    width: 48px;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-surface);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius);
    color: var(--color-text);
    box-shadow: 3px 3px 0 var(--color-border-strong);
    cursor: pointer;
    transition: color var(--transition), border-color var(--transition), transform var(--transition);
}

.section-nav__btn svg {
    width: 20px;
    height: 20px;
}

.section-nav__btn:hover:not(:disabled) {
    color: var(--color-primary-bright);
    border-color: var(--color-primary);
    transform: translateX(-2px);
}

.section-nav__btn:disabled {
    opacity: 0.35;
    cursor: default;
}

/* =============================================
   CAROUSEL (event detail + /servis/ galleries)
   ============================================= */
/* --per-view is the single source of truth for how many slides are visible: CSS owns the
   breakpoints, main.js only reads the value back. Slides advance one at a time regardless. */
.carousel {
    position: relative;
    --per-view: 3;
    --carousel-gap: 0.9rem;
}

@media (max-width: 900px) {
    .carousel { --per-view: 2; }
}

@media (max-width: 600px) {
    .carousel { --per-view: 1; }
}

.carousel__viewport {
    overflow: hidden;
    touch-action: pan-y;
}

.carousel__track {
    display: flex;
    gap: var(--carousel-gap);
    /* positioned so a slide's offsetLeft is measured against the track — that offset is what
       main.js translates by, which keeps the gap maths out of JS entirely */
    position: relative;
    transition: transform 0.35s ease;
}

.carousel__slide {
    flex: 0 0 calc((100% - (var(--per-view) - 1) * var(--carousel-gap)) / var(--per-view));
    min-width: 0;
    margin: 0;
}

/* every slide already fits — nothing to scroll to */
.carousel--static .carousel__btn,
.carousel--static .carousel__dots { display: none; }

/* centered wrapper for a standalone carousel (/servis/, event detail) */
.carousel-wrap {
    max-width: 860px;
    /* margin-inline, not `margin: 0 auto` — this class is combined with others that set a
       bottom margin (.article-layout__gallery), and the shorthand would silently zero it */
    margin-inline: auto;
}

/* wraps each slide image so the lightbox has a real, focusable trigger */
.carousel__zoom {
    display: block;
    width: 100%;
    padding: 0;
    border: none;
    background: none;
    cursor: zoom-in;
}

.carousel__zoom:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 3px;
}

/* cover, not contain: these are thumbnails in a strip now, so a uniform tile beats a
   letterboxed panel — the uncropped photo is one click away in the lightbox */
.carousel__slide img {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    background: var(--color-surface-2);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
}

.carousel__caption {
    padding: 0.6rem 0.2rem 0;
    font-size: 0.82rem;
    color: var(--color-muted);
}

.carousel__btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 48px;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-surface);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius);
    color: var(--color-text);
    box-shadow: 3px 3px 0 var(--color-border-strong);
    cursor: pointer;
    transition: color var(--transition), border-color var(--transition), transform var(--transition);
}

.carousel__btn svg { width: 20px; height: 20px; }

.carousel__btn--prev { left: 10px; }
.carousel__btn--next { right: 10px; }

.carousel__btn:hover:not(:disabled) {
    color: var(--color-primary-bright);
    border-color: var(--color-primary);
}

.carousel__btn:disabled {
    opacity: 0.35;
    cursor: default;
}

.carousel__dots {
    display: flex;
    justify-content: center;
    gap: 0.5rem;
    margin-top: 0.8rem;
}

.carousel__dot {
    width: 10px;
    height: 10px;
    padding: 0;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius);
    background: transparent;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition);
}

.carousel__dot.active {
    background: var(--color-primary);
    border-color: var(--color-primary);
}

html:not(.js) .carousel__viewport {
    overflow-x: auto;
}

html:not(.js) .carousel__track {
    transition: none;
}

html:not(.js) .carousel__btn,
html:not(.js) .carousel__dots {
    display: none;
}

/* --- lightbox (opened by clicking a carousel slide) --- */
.lightbox {
    position: fixed;
    inset: 0;
    z-index: 1200;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.94);
}

/* Edge-to-edge: width/height rather than max-* so the photo scales UP to fill the window
   instead of sitting at natural size in the middle of a black field (the uploads are only
   ~620px wide). `contain` keeps the aspect ratio and never crops. */
.lightbox__img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* the photo now runs edge-to-edge underneath these, so they carry their own backdrop
   instead of relying on the scrim showing through */
.lightbox__close {
    position: absolute;
    top: 18px;
    right: 18px;
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border: 1px solid rgba(255, 255, 255, 0.4);
    border-radius: var(--radius);
    color: #fff;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition);
}

.lightbox__close:hover,
.lightbox__btn:hover:not(:disabled) {
    background: rgba(0, 0, 0, 0.8);
    border-color: #fff;
}

.lightbox__close svg { width: 20px; height: 20px; }

.lightbox__btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 48px;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border: 1px solid rgba(255, 255, 255, 0.4);
    border-radius: var(--radius);
    color: #fff;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition);
}

.lightbox__btn svg { width: 20px; height: 20px; }

.lightbox__btn--prev { left: 18px; }
.lightbox__btn--next { right: 18px; }

.lightbox__btn:disabled {
    opacity: 0.3;
    cursor: default;
}

/* =============================================
   CONTACT
   ============================================= */
.contact-grid {
    display: grid;
    grid-template-columns: 1fr 1.5fr;
    gap: 4rem;
    align-items: start;
}

.contact-grid h2 {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.7rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    margin-bottom: 1.8rem;
}

.contact-info__item {
    display: flex;
    gap: 1rem;
    margin-bottom: 1.4rem;
}

.contact-info__icon {
    width: 42px;
    height: 42px;
    background: var(--color-primary-tint);
    border: 1px solid rgba(132, 155, 46, 0.3);
    border-radius: var(--radius);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.contact-info__icon svg {
    width: 18px;
    height: 18px;
    stroke: var(--color-primary-bright);
    fill: none;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.contact-info__label {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: var(--color-faint);
    margin-bottom: 0.15rem;
}

.contact-info__value {
    font-weight: 600;
    color: var(--color-text);
}

.contact-info__value a:hover { color: var(--color-primary-bright); }

.form-group { margin-bottom: 1.2rem; }

.form-group label {
    display: block;
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    margin-bottom: 0.4rem;
    color: var(--color-muted);
}

.form-group input,
.form-group select,
.form-group textarea {
    width: 100%;
    padding: 0.75rem 0.95rem;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius);
    font-family: var(--font-main);
    font-size: 0.9rem;
    color: var(--color-text);
    background: var(--color-bg-deep);
    transition: border-color var(--transition), box-shadow var(--transition);
}

.form-group input::placeholder,
.form-group textarea::placeholder {
    color: var(--color-faint);
}

.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
    outline: none;
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px var(--color-primary-tint);
}

.form-group textarea {
    resize: vertical;
    min-height: 130px;
}

.form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
}

/* Contact-form flash. Hard left rule instead of a filled panel, matching the
   .adm-flash treatment in the admin. */
.form-notice {
    border: 1px solid var(--color-border-strong);
    border-left: 4px solid var(--color-primary);
    background: var(--color-primary-tint);
    padding: 0.8rem 1rem;
    margin-bottom: 1.4rem;
    font-size: 0.88rem;
    line-height: 1.5;
}

.form-notice--error {
    border-left-color: var(--color-danger);
    background: var(--color-danger-tint);
}

/* Honeypot: off-screen rather than display:none / hidden — bots skip fields they
   can tell are unrenderable, and this one only works if it looks fillable. */
.form-honeypot {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* =============================================
   RESPONSIVE
   ============================================= */
@media (max-width: 1024px) {
    .footer__inner { grid-template-columns: 1fr 1fr; }

    .about-strip {
        grid-template-columns: 1fr;
        gap: 2.5rem;
    }

    .about-panel { min-height: 300px; }

    .cards-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 900px) {
    .hero-split {
        grid-template-columns: 1fr;
        gap: 2.4rem;
        padding-top: 56px;
    }

    .hero-split__fig {
        max-width: 520px;
    }

    .hero__inner { padding-top: 64px; }
}

@media (max-width: 768px) {
    .topbar__text { display: none; }

    .topbar { padding: 0 1rem; }

    .section-nav { right: 10px; gap: 0.4rem; }

    .section-nav__btn { width: 40px; height: 40px; }

    .section-nav__btn svg { width: 17px; height: 17px; }

    .navbar__nav {
        display: none;
        /* anchor to the navbar's own bottom edge so the dropdown stays flush as
           the navbar docks upward on scroll; a static viewport `top` left a gap
           once the topbar scrolled out (page showed through). Use the fixed navbar
           height, not `top: 100%` — the percentage misresolves against the
           positioned navbar and reintroduces the gap. */
        position: absolute;
        top: var(--navbar-height);
        left: 0;
        right: 0;
        background: var(--color-nav-bg-solid);
        flex-direction: column;
        align-items: stretch;
        padding: 0.8rem 1rem 1rem;
        gap: 0.15rem;
        margin-left: 0;
        border-bottom: 2px solid var(--color-primary-dark);
        /* never let the dropdown run off a short screen — scroll it instead */
        max-height: calc(100vh - var(--topbar-height) - var(--navbar-height));
        max-height: calc(100dvh - var(--topbar-height) - var(--navbar-height));
        overflow-y: auto;
    }

    .navbar__nav.open { display: flex; }

    .navbar__nav a { padding: 0.7rem 0.75rem; }

    .navbar__nav a::after { display: none; }

    .navbar__nav a.active { color: var(--color-nav-accent); }

    /* category dropdown collapses to an indented, tap-to-expand list (task 12) */
    .nav-dropdown { flex-wrap: wrap; }

    .nav-dropdown__menu {
        position: static;
        flex: 0 0 100%;
        width: 100%;
        background: none;
        border: none;
        box-shadow: none;
        padding: 0 0 0 1rem;
        margin-top: 0.2rem;
        opacity: 1;
        pointer-events: auto;
        transform: none;
        max-height: 0;
        overflow: hidden;
        transition: max-height var(--transition);
    }

    /* focus-within so tabbing into the collapsed list expands it instead of leaving focus
       stranded in a max-height:0 box */
    .nav-dropdown.open .nav-dropdown__menu,
    .nav-dropdown__menu:focus-within {
        max-height: 400px;
    }

    .nav-dropdown__menu a { padding: 0.55rem 0.6rem; }

    .navbar > .lang-switcher { display: none; }

    .navbar__nav-lang {
        display: block;
        margin-top: 0.5rem;
        padding: 0.9rem 0.75rem 0.3rem;
        border-top: 1px solid rgba(255, 255, 255, 0.18);
    }

    .navbar__nav-lang .lang-switcher {
        margin-left: 0;
    }

    .navbar__nav-lang .lang-switcher__toggle { display: none; }

    .navbar__nav-lang .lang-switcher__menu {
        /* 2-col grid wraps the four languages within the screen; the old
           `width: max-content` forced one row that overflowed the right edge */
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 0.2rem;
        position: static;
        width: 100%;
        background: none;
        border: none;
        box-shadow: none;
        padding: 0;
        opacity: 1;
        pointer-events: auto;
    }

    /* lang selector is hidden here, so the theme button takes over the auto margin */
    .navbar__theme { margin-left: auto; }

    .navbar__hamburger {
        display: flex;
        margin-left: 0.6rem;
    }

    .hero__inner { padding-bottom: 110px; }

    .pillars { grid-template-columns: 1fr; }

    .categories { grid-template-columns: 1fr; }

    .category-card { min-height: 230px; }

    .contact-grid {
        grid-template-columns: 1fr;
        gap: 2.5rem;
    }

    .footer__inner {
        grid-template-columns: 1fr;
        gap: 2rem;
    }

    .footer__bottom {
        flex-direction: column;
        text-align: center;
    }

    .cards-grid { grid-template-columns: 1fr; }

    .form-row { grid-template-columns: 1fr; }

    .about-strip__stats {
        gap: 1.6rem;
        flex-wrap: wrap;
    }

    .sticky-bar {
        gap: 0.6rem;
        flex-wrap: wrap;      /* button drops to a second row instead of overflowing the pill */
        row-gap: 0.45rem;
    }

    .sticky-bar__text {
        font-size: 0.68rem;
        letter-spacing: 0.14em;
    }

    /* Client decision 2026-07-24: KLAAS banners keep the logo on mobile but stop
       linking anywhere (both the pill's logo link and the browse-page corner
       badge) — desktop is unchanged. pointer-events:none blocks mouse/touch
       activation without touching the markup or the desktop behaviour. The
       `body.sticky-collapsed .sticky-mini` selector is repeated (not just
       `.sticky-mini`) to match that rule's specificity — it resets
       pointer-events to auto for the collapsed/visible badge, and being
       earlier in the file it would otherwise win the specificity tie and
       leave the mobile badge clickable while collapsed. */
    .sticky-bar__logo-link,
    .sticky-mini,
    body.sticky-collapsed .sticky-mini {
        pointer-events: none;
    }
}

@media (max-width: 600px) {
    /* below ~600px the bar wraps to two rows; a trailing divider looks stray */
    .sticky-bar__divider { display: none; }
}

@media (max-width: 480px) {
    .section { padding: 3.6rem 1.25rem; }

    .hero__inner {
        padding-left: 1.25rem;
        padding-right: 1.25rem;
    }

    .hero__rest {
        font-size: 0.95rem;
        letter-spacing: 0.2em;
        text-indent: 0.2em;
    }

    .sticky-bar {
        gap: 0.45rem;
        row-gap: 0.4rem;
        padding: 0.55rem 0.9rem;
        bottom: 10px;
        max-width: calc(100vw - 1.2rem);
    }

    .sticky-bar__text { font-size: 0.6rem; }

    .sticky-bar__logo { height: 20px; }
}

/* =============================================
   MAINTENANCE MODE
   Standalone page — no navbar/topbar/footer/sticky-bar. Rendered by app.py's
   _maintenance_mode before_request in place of every public page when the
   admin toggle is on (see CLAUDE.md "Maintenance mode"). maintenance.html
   does not extend base.html, so this is a self-contained centered layout,
   not a variant of .page-hero/.section.
   ============================================= */
body.maintenance-body {
    padding-bottom: 0;      /* no sticky bar here to clear, unlike the global body rule */
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
}

.maintenance-page {
    max-width: 480px;
    padding: 2rem;
    text-align: center;
}

.maintenance-page__brand {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.7rem;
    margin-bottom: 2.5rem;
}

.maintenance-page__logo {
    height: 44px;
    width: auto;
}

.maintenance-page__wordmark {
    font-family: var(--font-display);
    font-size: 1.7rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: var(--color-text);
    line-height: 1;
}

.maintenance-page__wordmark span {
    color: var(--color-primary-bright);
}

.maintenance-page__title {
    font-family: var(--font-display);
    font-size: clamp(1.6rem, 4vw, 2.2rem);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    line-height: 1.1;
    color: var(--color-text);
    margin-bottom: 0.75rem;
}

.maintenance-page__text {
    color: var(--color-muted);
    font-size: 1rem;
}

/* =============================================
   REDUCED 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;
    }

    .marquee__track { animation: none; }

    .js [data-reveal] {
        opacity: 1;
        transform: none;
    }
}
