/*
 * LEDIO storefront — design tokens and components.
 *
 * Loaded only by templates/frontend/layout/base.html.twig, after Bootstrap, so
 * the administration (admin.css) is untouched by anything in this file.
 *
 * One file on purpose: AssetMapper serves each stylesheet as its own request,
 * and the storefront's system is small enough that splitting it into eight
 * files would buy structure at the cost of seven round trips. Sections below
 * are ordered tokens → base → chrome → sections.
 *
 * Everything is prefixed .ledio-* / --ledio-* to keep the storefront's surface
 * separate from Bootstrap's and the admin's.
 */

/* ==========================================================================
   1. Tokens
   ========================================================================== */

:root {
    /* -- Dark canvas & layered surfaces -- */
    --ledio-canvas: #090d38;
    --ledio-canvas-soft: #111748;
    --ledio-surface-dark: #171d50;
    --ledio-surface-indigo: #20275d;

    /* -- Brand / UI -- */
    --ledio-primary: #00eb88;
    /* 70ea94 */
    --ledio-primary-hover: #1f9e45;
    /*--ledio-primary: #00aeeb;*/
    /*--ledio-primary-hover: #008fc7;*/
    --ledio-primary-soft: rgba(0, 174, 235, 0.12);
    /*
     * Cyan as TEXT on light surfaces. --ledio-primary-hover only reaches
     * 3.65:1 on white, so anything that renders cyan words on a light
     * background (ghost buttons, brand lines, icon tints) uses this instead.
     */
    --ledio-primary-text: #0073a7;

    --ledio-violet: #5865f2;
    --ledio-magenta: #ec48bd;
    --ledio-green: #35ed7e;
    --ledio-yellow: #ffef00;

    /* -- Light surfaces -- */
    --ledio-bg: #f4f7fb;
    --ledio-white: #ffffff;
    --ledio-surface: #ffffff;
    --ledio-surface-muted: #eef2f7;
    --ledio-border: #dfe5ed;
    --ledio-border-strong: #cfd7e2;
    /*
     * A hairline for panels that should read as a surface rather than as a
     * framed box — the listing sidebar's two cards. Light enough that the
     * white plate, not the outline, is what separates them from the page.
     */
    --ledio-border-subtle: #e9eef4;

    /* -- Text -- */
    --ledio-text: #101828;
    /*
     * Darkened from the brief's #667085, which misses WCAG AA (4.3:1) against
     * --ledio-surface-muted, where the section leads sit. This clears 5.3:1
     * there and 5.9:1 on white.
     */
    --ledio-text-muted: #5b6478;
    --ledio-text-on-dark: #ffffff;
    /* Muted text on the indigo canvas; clears 4.5:1 (WCAG AA). */
    --ledio-text-on-dark-muted: #b9c0da;

    /* -- Brand gradient: hero atmosphere, light details, brand CTA plates -- */
    --ledio-gradient-brand: linear-gradient(125deg,
            #00aeeb 0%,
            #5865f2 42%,
            #9b4de0 68%,
            #ec48bd 100%);

    /* -- Type scale -- */
    --ledio-font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
        Arial, "Noto Sans", sans-serif;
    --ledio-font-body: 1rem;
    --ledio-font-body-lg: 1.125rem;
    --ledio-font-small: 0.875rem;
    --ledio-font-h1: clamp(2.6rem, 5vw, 5.2rem);
    --ledio-font-h2: clamp(2rem, 3.5vw, 3.6rem);
    --ledio-font-h3: clamp(1.25rem, 2vw, 1.75rem);
    --ledio-measure: 68ch;

    /* -- Layout -- */
    --ledio-container-max: 1440px;
    --ledio-container-pad: clamp(20px, 3vw, 48px);

    /*
     * The height of the STICKY part of the page chrome.
     *
     * Only .ledio-header is sticky — the utility bar above it scrolls away — so
     * this is that element's own height and nothing else's: row one
     * (.ledio-header__main, min-height 76px) plus, from 992px up, row two
     * (.ledio-nav__link min-height 48px + the 1px rule above it).
     *
     * IT IS A VARIABLE BECAUSE THREE THINGS NEED THE SAME ANSWER: anchor targets
     * must land below the header, and so must anything sticky positioned under
     * it. Those used to be a 140px literal in one place and a guess in the
     * others, which is how a sticky sidebar ends up tucked underneath the
     * navigation.
     *
     * CAVEAT WORTH KNOWING: the category row wraps onto a second line on narrow
     * desktops when there are more root categories than fit, and no CSS value
     * can follow that. Everything below adds a deliberate gap on top, so a
     * wrapped row costs some of that gap rather than hiding content.
     */
    --ledio-header-height: 76px;
    --ledio-header-offset: calc(var(--ledio-header-height) + var(--ledio-space-lg));

    /* -- Soft geometry -- */
    --ledio-radius-xs: 6px;
    --ledio-radius-sm: 6px;
    --ledio-radius-md: 10px;
    --ledio-radius-lg: 10px;
    --ledio-radius-xl: 10px;
    --ledio-radius-pill: 999px;

    /* -- Spacing (8px base) -- */
    --ledio-space-2xs: 4px;
    --ledio-space-xs: 8px;
    --ledio-space-sm: 12px;
    --ledio-space-md: 16px;
    --ledio-space-lg: 24px;
    --ledio-space-xl: 32px;
    --ledio-space-2xl: 48px;
    --ledio-space-3xl: 72px;

    /* -- Depth: colour and light first, shadows kept soft and rare -- */
    --ledio-shadow-soft: 0 3px 40px rgba(16, 24, 40, 0.08);
    --ledio-shadow-lift: 0 12px 48px rgba(16, 24, 40, 0.12);
    --ledio-shadow-glow: 0 18px 60px rgba(0, 174, 235, 0.18);

    --ledio-transition: 180ms cubic-bezier(0.2, 0, 0.2, 1);
}

/* ==========================================================================
   2. Base
   ========================================================================== */

.ledio-body {
    background-color: var(--ledio-bg);
    color: var(--ledio-text);
    font-family: var(--ledio-font);
    font-size: var(--ledio-font-body);
    line-height: 1.6;
    /*
     * Nothing on this page may create a sideways scrollbar.
     * "clip", not "hidden": hidden forces the other axis to `auto`, which turns
     * <body> into its own scroll container and breaks both viewport scrolling
     * and the sticky header. clip just clips.
     */
    overflow-x: clip;
}

.ledio-body h1,
.ledio-body h2,
.ledio-body h3 {
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.08;
    text-wrap: balance;
}

/* The one wide, responsive content column. Text blocks narrow themselves. */
.ledio-container {
    width: min(100% - 2 * var(--ledio-container-pad), var(--ledio-container-max));
    margin-inline: auto;
}

.ledio-measure {
    max-width: var(--ledio-measure);
}

/* Every interactive element gets the same visible focus ring, light and dark. */
.ledio-body :focus-visible {
    outline: 3px solid var(--ledio-primary);
    outline-offset: 2px;
    border-radius: var(--ledio-radius-xs);
}

.ledio-section {
    padding-block: clamp(3.5rem, 7vw, 6.5rem);
}

.ledio-section--dark {
    background-color: var(--ledio-canvas);
    color: var(--ledio-text-on-dark);
}

.ledio-section--muted {
    background-color: var(--ledio-surface-muted);
}

.ledio-section--surface {
    background-color: var(--ledio-white);
}

/* Decorative light washes must never intercept a click or a caret. */
.ledio-decor {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 0;
}

.ledio-skip-link {
    position: absolute;
    top: -100px;
    left: var(--ledio-space-md);
    z-index: 100;
    padding: var(--ledio-space-sm) var(--ledio-space-lg);
    background: var(--ledio-white);
    color: var(--ledio-text);
    border-radius: 0 0 var(--ledio-radius-sm) var(--ledio-radius-sm);
    font-weight: 600;
    transition: top var(--ledio-transition);
}

.ledio-skip-link:focus {
    top: 0;
}

/*
 * Anchor targets (utility-bar Kontakt/Showroom, in-page CTAs) must land below
 * the sticky two-row header, not underneath it.
 *
 * Derived from --ledio-header-height rather than written out: this was a 140px
 * literal, and a second place that needed the same number got a different one.
 */
.ledio-body [id] {
    scroll-margin-top: var(--ledio-header-offset);
}

/* ==========================================================================
   3. Section headings
   ========================================================================== */

.ledio-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: var(--ledio-space-xs);
    margin-bottom: var(--ledio-space-md);
    font-size: var(--ledio-font-small);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ledio-primary);
}

/* The small luminous dot that marks an eyebrow — the "light" brand detail. */
.ledio-eyebrow::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--ledio-primary);
    box-shadow: 0 0 0 4px var(--ledio-primary-soft);
}

.ledio-section-title {
    font-size: var(--ledio-font-h2);
    margin-bottom: var(--ledio-space-md);
}

.ledio-section-lead {
    font-size: var(--ledio-font-body-lg);
    color: var(--ledio-text-muted);
    max-width: var(--ledio-measure);
    margin-bottom: 0;
}

.ledio-section--dark .ledio-section-lead {
    color: var(--ledio-text-on-dark-muted);
}

.ledio-section-head {
    margin-bottom: clamp(2rem, 4vw, 3.5rem);
}

/* Heading row with an action on the right (e.g. "Zobraziť celý katalóg"). */
.ledio-section-head--split {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--ledio-space-lg);
    flex-wrap: wrap;
}

/* ==========================================================================
   4. Buttons
   ========================================================================== */

.ledio-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--ledio-space-xs);
    /* 44px minimum touch target. */
    min-height: 46px;
    padding: var(--ledio-space-sm) var(--ledio-space-lg);
    border: 1px solid transparent;
    border-radius: var(--ledio-radius-sm);
    font-size: var(--ledio-font-body);
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--ledio-transition), transform var(--ledio-transition),
        border-color var(--ledio-transition), color var(--ledio-transition);
}

.ledio-btn:hover {
    transform: translateY(-1px);
}

.ledio-btn:active {
    transform: translateY(0);
}

/* Primary: cyan. The everyday action colour. */
.ledio-btn--primary {
    background-color: var(--ledio-primary);
    /* Dark ink on cyan: white would fall to ~2.2:1. This is ~7.5:1. */
    color: #04121c;
}

.ledio-btn--primary:hover {
    background-color: var(--ledio-primary-hover);
    color: #04121c;
}

/* Green: reserved for the single highest-intent action (B2B registration). */
.ledio-btn--green {
    background-color: var(--ledio-green);
    color: #04210f;
}

.ledio-btn--green:hover {
    background-color: #24d76b;
    color: #04210f;
}

/* Secondary on dark: outlined, clearly below the primary in weight. */
.ledio-btn--outline-light {
    background-color: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.35);
    color: var(--ledio-text-on-dark);
}

.ledio-btn--outline-light:hover {
    background-color: rgba(255, 255, 255, 0.12);
    border-color: rgba(255, 255, 255, 0.6);
    color: var(--ledio-text-on-dark);
}

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

.ledio-btn--outline:hover {
    border-color: var(--ledio-primary);
    color: var(--ledio-primary-text);
    background-color: var(--ledio-primary-soft);
}

/* A quiet tertiary action: text + arrow, no chrome. */
.ledio-btn--ghost {
    padding-inline: var(--ledio-space-xs);
    background: none;
    color: var(--ledio-primary-text);
}

.ledio-btn--ghost:hover {
    color: var(--ledio-primary-text);
    text-decoration: underline;
}

.ledio-section--dark .ledio-btn--ghost {
    color: var(--ledio-primary);
}

.ledio-btn--lg {
    min-height: 54px;
    padding-inline: var(--ledio-space-xl);
    font-size: var(--ledio-font-body-lg);
}

.ledio-btn--block {
    width: 100%;
}

/* ==========================================================================
   5. Utility bar
   ========================================================================== */

.ledio-utility {
    background-color: #060930;
    color: var(--ledio-text-on-dark-muted);
    font-size: var(--ledio-font-small);
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.ledio-utility__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ledio-space-md);
    min-height: 44px;
    flex-wrap: wrap;
}

.ledio-utility__note {
    display: inline-flex;
    align-items: center;
    gap: var(--ledio-space-xs);
}

.ledio-utility__links {
    display: flex;
    align-items: center;
    gap: var(--ledio-space-lg);
    list-style: none;
    margin: 0;
    padding: 0;
}

.ledio-utility a {
    color: var(--ledio-text-on-dark-muted);
    text-decoration: none;
    transition: color var(--ledio-transition);
}

.ledio-utility a:hover {
    color: var(--ledio-text-on-dark);
    text-decoration: underline;
}

/* ==========================================================================
   6. Header — two-row e-commerce chrome
   ========================================================================== */

.ledio-header {
    position: sticky;
    top: 0;
    z-index: 50;
    background-color: rgba(9, 13, 56, 0.92);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    color: var(--ledio-text-on-dark);
}

/* Row 1: logo · search · account/B2B. */
.ledio-header__main {
    display: flex;
    align-items: center;
    gap: clamp(16px, 2.5vw, 40px);
    min-height: 76px;
}

.ledio-logo {
    display: inline-flex;
    align-items: center;
    /* Protective clear space around the mark. */
    padding: var(--ledio-space-xs);
    flex-shrink: 0;
}

.ledio-logo img {
    /* Height drives the size; width follows the logo's own 507:83 ratio. */
    height: 36px;
    width: auto;
    display: block;
}

/*
 * BELOW lg THE MARK HAS TO GIVE WAY, and until now it refused to.
 *
 * The search and the icon labels are both hidden at this width, so the row is
 * the wordmark plus three icon buttons — but the logo and the actions were BOTH
 * `flex-shrink: 0`, and a 36px-tall wordmark is 220px wide at this logo's
 * 507:83 ratio. On a 375px screen that is wider than what is left after the
 * buttons, so the row simply overflowed and the burger went off the edge of the
 * viewport, unreachable.
 *
 * Height stops driving the size here and width does: the mark scales with
 * whatever the row can spare, down to a phone narrower than any sold today.
 * Declared beside the rule it corrects rather than in the responsive section,
 * where it would be found only by somebody already looking for it.
 */
@media (max-width: 991.98px) {
    .ledio-logo {
        flex-shrink: 1;
        min-width: 0;
        padding-inline: 0;
    }

    .ledio-logo img {
        width: 100%;
        max-width: 160px;
        height: auto;
    }
}

/* Row 2: catalog + category navigation. */
.ledio-header__nav {
    display: none;
    border-top: 1px solid rgba(255, 255, 255, 0.07);
}

.ledio-nav {
    display: flex;
    align-items: center;
    gap: var(--ledio-space-2xs);
    margin: 0;
    padding: 0;
    list-style: none;
    flex-wrap: wrap;
}

.ledio-nav__link {
    position: relative;
    display: inline-flex;
    align-items: center;
    min-height: 48px;
    padding: 0 var(--ledio-space-md);
    color: var(--ledio-text-on-dark);
    font-size: 0.9375rem;
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
    transition: color var(--ledio-transition);
}

/* Animated underline — transform-only, so it costs nothing to run. */
.ledio-nav__link::after {
    content: "";
    position: absolute;
    inset-inline: var(--ledio-space-md);
    bottom: 8px;
    height: 2px;
    background: var(--ledio-primary);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--ledio-transition);
}

.ledio-nav__link:hover {
    color: var(--ledio-primary);
}

.ledio-nav__link:hover::after,
.ledio-nav__link[aria-current="page"]::after {
    transform: scaleX(1);
}

/* Active page: colour + underline, never colour alone. */
.ledio-nav__link[aria-current="page"] {
    color: var(--ledio-primary);
}

.ledio-nav__link--strong {
    font-weight: 700;
}

.ledio-header__actions {
    display: flex;
    align-items: center;
    gap: var(--ledio-space-sm);
    margin-left: auto;
    flex-shrink: 0;
}

/* The header CTA is a single line; it must not wrap into a two-line block. */
.ledio-header__actions .ledio-btn {
    white-space: nowrap;
    padding-inline: var(--ledio-space-md);
    font-size: 0.9375rem;
}

.ledio-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--ledio-space-xs);
    min-width: 44px;
    min-height: 44px;
    padding: 0 var(--ledio-space-sm);
    border: 1px solid transparent;
    border-radius: var(--ledio-radius-sm);
    background: none;
    color: var(--ledio-text-on-dark);
    font-size: 0.9375rem;
    font-weight: 500;
    text-decoration: none;
    transition: background-color var(--ledio-transition);
}

.ledio-icon-btn:hover {
    background-color: rgba(255, 255, 255, 0.1);
    color: var(--ledio-text-on-dark);
}

.ledio-icon-btn__label {
    display: none;
}

/* ==========================================================================
   7. Search — a first-class citizen of the header and hero
   ========================================================================== */

.ledio-search {
    position: relative;
    flex-grow: 1;
    max-width: 720px;
    display: none;
}

.ledio-search__input {
    width: 100%;
    min-height: 50px;
    padding: 0 var(--ledio-space-md) 0 52px;
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: var(--ledio-radius-pill);
    background-color: rgba(255, 255, 255, 0.07);
    color: var(--ledio-text-on-dark);
    font-size: var(--ledio-font-body);
    transition: border-color var(--ledio-transition), background-color var(--ledio-transition);
}

.ledio-search__input::placeholder {
    color: rgba(255, 255, 255, 0.55);
}

.ledio-search__input:focus {
    background-color: rgba(255, 255, 255, 0.12);
    border-color: var(--ledio-primary);
    outline: none;
}

.ledio-search__icon {
    position: absolute;
    left: var(--ledio-space-md);
    top: 50%;
    transform: translateY(-50%);
    color: rgba(255, 255, 255, 0.6);
    pointer-events: none;
}

/* ==========================================================================
   8. Hero — static, slider-ready shell
   ========================================================================== */

.homepage-hero {
    position: relative;
    background-color: var(--ledio-canvas);
    color: var(--ledio-text-on-dark);
    overflow: hidden;
}

/* One slide today; the shell is where a future slider rotates them. */
.homepage-hero__slide {
    position: relative;
    padding-block: clamp(3.5rem, 7vw, 7rem);
}

/*
 * The hero's light: an architectural composition drawn in CSS.
 * Static radial washes + two light beams + a faint technical grid.
 * No animation, no GPU churn, no image request.
 */
.homepage-hero__atmosphere {
    background:
        radial-gradient(55% 60% at 82% 10%, rgba(0, 174, 235, 0.38) 0%, transparent 60%),
        radial-gradient(45% 55% at 96% 55%, rgba(236, 72, 189, 0.2) 0%, transparent 65%),
        radial-gradient(60% 65% at 30% 100%, rgba(88, 101, 242, 0.3) 0%, transparent 62%);
}

/* Faint technical grid, fading toward the text so it never fights copy. */
.homepage-hero__grid {
    background-image:
        linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
    background-size: 72px 72px;
    -webkit-mask-image: radial-gradient(70% 90% at 75% 40%, rgba(0, 0, 0, 0.9), transparent 75%);
    mask-image: radial-gradient(70% 90% at 75% 40%, rgba(0, 0, 0, 0.9), transparent 75%);
}

/* Two beams of light cutting across the right half. */
.homepage-hero__beam {
    position: absolute;
    top: -20%;
    height: 140%;
    width: 220px;
    pointer-events: none;
    transform: rotate(24deg);
    background: linear-gradient(180deg,
            transparent 0%,
            rgba(0, 174, 235, 0.14) 30%,
            rgba(88, 101, 242, 0.1) 60%,
            transparent 100%);
    filter: blur(2px);
}

.homepage-hero__beam--1 {
    right: 16%;
}

.homepage-hero__beam--2 {
    right: 4%;
    width: 120px;
    transform: rotate(30deg);
    background: linear-gradient(180deg,
            transparent 0%,
            rgba(236, 72, 189, 0.1) 40%,
            rgba(0, 174, 235, 0.08) 70%,
            transparent 100%);
}

/* A single hairline of brand light along the top edge. */
.homepage-hero__edge {
    position: absolute;
    inset-inline: 0;
    top: 0;
    height: 1px;
    background: var(--ledio-gradient-brand);
    opacity: 0.8;
    pointer-events: none;
}

.homepage-hero__inner {
    position: relative;
    z-index: 1;
}

.homepage-hero__title {
    font-size: var(--ledio-font-h1);
    margin-bottom: var(--ledio-space-lg);
    max-width: 16ch;
}

/* The service half of the promise, picked out in brand light. */
.homepage-hero__title em {
    font-style: normal;
    background: var(--ledio-gradient-brand);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

.homepage-hero__lead {
    font-size: clamp(1.0625rem, 1.5vw, 1.3125rem);
    color: var(--ledio-text-on-dark-muted);
    max-width: 56ch;
    margin-bottom: var(--ledio-space-xl);
}

.homepage-hero__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ledio-space-md);
}

/* ==========================================================================
   9. Category tiles — the shop entrance
   ========================================================================== */

.ledio-category-grid {
    display: grid;
    gap: var(--ledio-space-md);
    grid-template-columns: repeat(2, 1fr);
}

/* Product photo tile: white plate, photo, name bar. */
.ledio-category {
    position: relative;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-white);
    color: var(--ledio-text);
    text-decoration: none;
    overflow: hidden;
    transition: transform var(--ledio-transition), border-color var(--ledio-transition),
        box-shadow var(--ledio-transition);
}

.ledio-category:hover {
    transform: translateY(-4px);
    border-color: var(--ledio-primary);
    box-shadow: var(--ledio-shadow-soft);
    color: var(--ledio-text);
}

.ledio-category__media {
    aspect-ratio: 4 / 3;
    display: flex;
    align-items: center;
    justify-content: center;
    background:
        radial-gradient(80% 80% at 70% 20%, var(--ledio-primary-soft) 0%, transparent 60%),
        linear-gradient(160deg, #ffffff 0%, #eef2f9 100%);
    overflow: hidden;
}

.ledio-category__media img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    padding: var(--ledio-space-lg);
    mix-blend-mode: multiply;
    transition: transform var(--ledio-transition);
}

.ledio-category:hover .ledio-category__media img {
    transform: scale(1.04);
}

/* Fallback for categories with no product photo yet: a lit brand plate. */
.ledio-category__placeholder {
    color: var(--ledio-primary);
    opacity: 0.75;
}

.ledio-category__body {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ledio-space-sm);
    padding: var(--ledio-space-md) var(--ledio-space-lg);
    border-top: 1px solid var(--ledio-border);
}

.ledio-category__name {
    font-size: var(--ledio-font-body-lg);
    font-weight: 600;
    margin: 0;
}

.ledio-category__arrow {
    color: var(--ledio-primary);
    flex-shrink: 0;
    transition: transform var(--ledio-transition);
}

.ledio-category:hover .ledio-category__arrow {
    transform: translateX(4px);
}

/* ==========================================================================
   10. Product cards — clean e-commerce components on white
   ========================================================================== */

.home-products {
    background: var(--ledio-white);
}

/*
 * Five to a row on a wide screen, and an explicit column count rather than an
 * auto-fill guess: the row is a curated selection, so how many are side by side
 * is a decision, not whatever happens to fit. The ladder below it is the
 * category listing's own (1 → 2 → 3 → 4), which is what keeps the same card
 * from being a different size in the two places it appears.
 */
.ledio-grid--products {
    display: grid;
    gap: var(--ledio-space-lg);
    grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 576px) {
    .ledio-grid--products {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 992px) {
    .ledio-grid--products {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (min-width: 1200px) {
    .ledio-grid--products {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

@media (min-width: 1400px) {
    .ledio-grid--products {
        gap: var(--ledio-space-md);
        grid-template-columns: repeat(5, minmax(0, 1fr));
    }
}

/* With very few published products the grid centre-weights larger cards. */
.ledio-grid--products-sparse {
    grid-template-columns: repeat(auto-fit, minmax(320px, 440px));
    justify-content: center;
}

.ledio-product {
    position: relative;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-white);
    overflow: hidden;
    height: 100%;
    transition: transform var(--ledio-transition), border-color var(--ledio-transition),
        box-shadow var(--ledio-transition);
}

.ledio-product:hover {
    transform: translateY(-3px);
    border-color: var(--ledio-border-strong);
    box-shadow: var(--ledio-shadow-soft);
}

/*
 * Pure white behind every product photo — no tint, no gradient, no divider.
 * Catalogue photography is shot on white, so anything else makes the image's
 * own backdrop read as a paler rectangle floating inside the card.
 */
.ledio-product__media {
    position: relative;
    aspect-ratio: 1 / 1;
    background-color: var(--ledio-white);
    display: flex;
    align-items: center;
    justify-content: center;
}

.ledio-product__media img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    padding: var(--ledio-space-lg);
    transition: transform var(--ledio-transition);
}

.ledio-product:hover .ledio-product__media img {
    transform: translateY(-3px);
}

.ledio-product__placeholder {
    color: var(--ledio-text-muted);
    opacity: 0.4;
}

.ledio-product__body {
    display: flex;
    flex-direction: column;
    gap: var(--ledio-space-xs);
    padding: var(--ledio-space-lg);
    flex-grow: 1;
}

.ledio-product__brand {
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ledio-primary-text);
}

.ledio-product__name {
    font-size: var(--ledio-font-body-lg);
    font-weight: 600;
    line-height: 1.35;
    margin: 0;
    /* Imported names run long; clamp to keep the grid even. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.ledio-product__name a {
    color: inherit;
    text-decoration: none;
}

.ledio-product__name a:hover {
    color: var(--ledio-primary-text);
}

.ledio-product__sku {
    font-size: var(--ledio-font-small);
    color: var(--ledio-text-muted);
}

.ledio-product__price {
    margin-top: auto;
    padding-top: var(--ledio-space-md);
    font-size: var(--ledio-font-small);
    font-weight: 600;
    color: var(--ledio-text-muted);
}

/* A catalog teaser tile that completes a sparse product row honestly. */
.ledio-product-teaser {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--ledio-space-sm);
    padding: var(--ledio-space-xl);
    border: 1px dashed var(--ledio-border-strong);
    border-radius: var(--ledio-radius-lg);
    background:
        radial-gradient(70% 70% at 80% 15%, var(--ledio-primary-soft) 0%, transparent 60%),
        var(--ledio-white);
}

.ledio-product-teaser h3 {
    font-size: var(--ledio-font-h3);
    margin: 0;
}

.ledio-product-teaser p {
    color: var(--ledio-text-muted);
    margin: 0 0 var(--ledio-space-sm);
}

/* ==========================================================================
   11. B2B benefit band — one horizontal strip, not another card grid
   ========================================================================== */

.ledio-band {
    background: var(--ledio-white);
    border-block: 1px solid var(--ledio-border);
    padding-block: clamp(2rem, 4vw, 3rem);
}

.ledio-band__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ledio-space-xl);
    flex-wrap: wrap;
}

.ledio-band__items {
    display: flex;
    gap: clamp(24px, 4vw, 64px);
    flex-wrap: wrap;
    list-style: none;
    margin: 0;
    padding: 0;
}

.ledio-band__item {
    display: flex;
    align-items: center;
    gap: var(--ledio-space-md);
}

.ledio-band__icon {
    display: grid;
    place-items: center;
    flex-shrink: 0;
    width: 48px;
    height: 48px;
    border-radius: var(--ledio-radius-md);
    background-color: var(--ledio-primary-soft);
    color: var(--ledio-primary-text);
}

.ledio-band__title {
    font-size: var(--ledio-font-body);
    font-weight: 600;
    margin: 0;
}

.ledio-band__text {
    font-size: var(--ledio-font-small);
    color: var(--ledio-text-muted);
    margin: 0;
}

/* ==========================================================================
   12. Services — one editorial split
   ========================================================================== */

.ledio-split {
    display: grid;
    gap: clamp(24px, 4vw, 64px);
    align-items: center;
}

/* The visual: an architectural interior drawn with light, not a stock photo. */
.ledio-split__visual {
    position: relative;
    min-height: 320px;
    border-radius: var(--ledio-radius-xl);
    overflow: hidden;
    background:
        radial-gradient(120% 90% at 50% -10%, rgba(0, 174, 235, 0.35) 0%, transparent 55%),
        radial-gradient(80% 60% at 85% 100%, rgba(236, 72, 189, 0.16) 0%, transparent 60%),
        linear-gradient(180deg, var(--ledio-canvas-soft) 0%, var(--ledio-canvas) 100%);
    border: 1px solid rgba(255, 255, 255, 0.1);
}

/* A ceiling of light: a row of "downlights" casting cones into the room. */
.ledio-split__visual::before {
    content: "";
    position: absolute;
    inset: 0;
    background:
        radial-gradient(6px 3px at 20% 12%, rgba(255, 255, 255, 0.95), transparent),
        radial-gradient(6px 3px at 50% 12%, rgba(255, 255, 255, 0.95), transparent),
        radial-gradient(6px 3px at 80% 12%, rgba(255, 255, 255, 0.95), transparent),
        linear-gradient(180deg, transparent 12%, rgba(0, 174, 235, 0.06) 30%, transparent 75%),
        conic-gradient(from 165deg at 20% 12%, transparent 0deg, rgba(255, 255, 255, 0.1) 14deg, transparent 30deg),
        conic-gradient(from 165deg at 50% 12%, transparent 0deg, rgba(255, 255, 255, 0.1) 14deg, transparent 30deg),
        conic-gradient(from 165deg at 80% 12%, transparent 0deg, rgba(255, 255, 255, 0.1) 14deg, transparent 30deg);
    pointer-events: none;
}

/* The floor line the light lands on. */
.ledio-split__visual::after {
    content: "";
    position: absolute;
    inset-inline: 10%;
    bottom: 18%;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.35), transparent);
    pointer-events: none;
}

.ledio-steps {
    display: grid;
    gap: var(--ledio-space-md);
    counter-reset: ledio-step;
    list-style: none;
    margin: var(--ledio-space-xl) 0 0;
    padding: 0;
}

.ledio-step {
    position: relative;
    display: flex;
    gap: var(--ledio-space-md);
    align-items: flex-start;
    padding: var(--ledio-space-md) 0;
    border-bottom: 1px solid var(--ledio-border);
    counter-increment: ledio-step;
}

.ledio-step:last-child {
    border-bottom: 0;
}

/* The step number is decorative; the heading carries the meaning. */
.ledio-step::before {
    content: counter(ledio-step);
    display: grid;
    place-items: center;
    flex-shrink: 0;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--ledio-gradient-brand);
    color: #fff;
    font-size: var(--ledio-font-small);
    font-weight: 700;
}

.ledio-step__title {
    font-size: var(--ledio-font-body-lg);
    font-weight: 600;
    margin-bottom: var(--ledio-space-2xs);
}

.ledio-step__text {
    font-size: var(--ledio-font-body);
    color: var(--ledio-text-muted);
    margin: 0;
}

/* Short proof points folded into the services section (no separate grid). */
.ledio-proof {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ledio-space-sm) var(--ledio-space-lg);
    list-style: none;
    margin: var(--ledio-space-lg) 0 0;
    padding: 0;
    font-size: var(--ledio-font-small);
    color: var(--ledio-text-muted);
}

.ledio-proof li {
    display: inline-flex;
    align-items: center;
    gap: var(--ledio-space-xs);
}

.ledio-proof svg {
    color: var(--ledio-primary);
    flex-shrink: 0;
}

/* ==========================================================================
   13. Showroom
   ========================================================================== */

.ledio-showroom {
    position: relative;
    overflow: hidden;
}

.ledio-showroom__decor {
    background:
        radial-gradient(50% 60% at 88% 12%, rgba(0, 174, 235, 0.28) 0%, transparent 62%),
        radial-gradient(45% 50% at 8% 88%, rgba(236, 72, 189, 0.16) 0%, transparent 65%);
}

.ledio-showroom__inner {
    position: relative;
    z-index: 1;
}

/* The visual stand-in until a real photo is configured: a lit display wall. */
.ledio-showroom__scene {
    position: relative;
    min-height: 280px;
    height: 100%;
    border-radius: var(--ledio-radius-xl);
    overflow: hidden;
    border: 1px solid rgba(255, 255, 255, 0.12);
    background:
        radial-gradient(40% 50% at 25% 30%, rgba(255, 239, 0, 0.08) 0%, transparent 60%),
        radial-gradient(40% 50% at 75% 30%, rgba(0, 174, 235, 0.16) 0%, transparent 60%),
        linear-gradient(180deg, var(--ledio-surface-indigo) 0%, var(--ledio-canvas-soft) 100%);
}

/* Rows of "luminaires" on the display wall. */
.ledio-showroom__scene::before {
    content: "";
    position: absolute;
    inset: 12% 14% auto;
    height: 46%;
    background-image:
        radial-gradient(14px 14px at 12% 20%, rgba(255, 255, 255, 0.85), transparent 60%),
        radial-gradient(14px 14px at 50% 20%, rgba(255, 244, 200, 0.8), transparent 60%),
        radial-gradient(14px 14px at 88% 20%, rgba(220, 242, 255, 0.85), transparent 60%),
        radial-gradient(14px 14px at 30% 75%, rgba(220, 242, 255, 0.75), transparent 60%),
        radial-gradient(14px 14px at 70% 75%, rgba(255, 244, 200, 0.75), transparent 60%);
    pointer-events: none;
}

.ledio-showroom__scene img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.ledio-showroom__panel {
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: var(--ledio-radius-lg);
    background-color: rgba(32, 39, 93, 0.6);
    padding: var(--ledio-space-xl);
}

.ledio-showroom__list {
    display: grid;
    gap: var(--ledio-space-md);
    margin: 0;
    padding: 0;
}

.ledio-showroom__list dt {
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ledio-primary);
    margin-bottom: var(--ledio-space-2xs);
}

.ledio-showroom__list dd {
    margin: 0;
    font-size: var(--ledio-font-body);
    color: var(--ledio-text-on-dark);
}

.ledio-showroom__list a {
    color: var(--ledio-text-on-dark);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.ledio-showroom__hours {
    display: flex;
    justify-content: space-between;
    gap: var(--ledio-space-md);
    padding-block: 2px;
}

.ledio-showroom__hours span:last-child {
    color: var(--ledio-text-on-dark-muted);
}

/* Shown while the showroom's contact details are not configured. */
.ledio-showroom__pending {
    padding: var(--ledio-space-md);
    border: 1px dashed rgba(255, 255, 255, 0.3);
    border-radius: var(--ledio-radius-md);
    color: var(--ledio-text-on-dark-muted);
    font-size: var(--ledio-font-body);
}

.ledio-showroom__benefits {
    display: grid;
    gap: var(--ledio-space-md);
    list-style: none;
    margin: 0 0 var(--ledio-space-xl);
    padding: 0;
    font-size: var(--ledio-font-body);
}

.ledio-showroom__benefits li {
    display: flex;
    gap: var(--ledio-space-sm);
    align-items: flex-start;
    color: var(--ledio-text-on-dark-muted);
}

.ledio-showroom__benefits svg {
    flex-shrink: 0;
    margin-top: 3px;
    color: var(--ledio-primary);
}

/* ==========================================================================
   14. Segments — large lit panels, not icon chips
   ========================================================================== */

.ledio-segment-grid {
    display: grid;
    gap: var(--ledio-space-md);
    grid-template-columns: 1fr;
}

.ledio-segment {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    gap: var(--ledio-space-2xs);
    min-height: 180px;
    padding: var(--ledio-space-lg);
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-lg);
    background: var(--ledio-white);
    overflow: hidden;
}

/* Each segment gets its own light temperature via a custom property. */
.ledio-segment::before {
    content: "";
    position: absolute;
    inset: 0;
    background:
        radial-gradient(90% 70% at 80% 0%, var(--segment-light, var(--ledio-primary-soft)) 0%, transparent 65%);
    pointer-events: none;
}

.ledio-segment__icon {
    position: relative;
    display: grid;
    place-items: center;
    width: 48px;
    height: 48px;
    margin-bottom: auto;
    border-radius: var(--ledio-radius-md);
    background-color: var(--ledio-white);
    border: 1px solid var(--ledio-border);
    color: var(--ledio-primary-text);
}

.ledio-segment__title {
    position: relative;
    font-size: var(--ledio-font-h3);
    font-weight: 600;
    margin: 0;
}

.ledio-segment__text {
    position: relative;
    font-size: var(--ledio-font-body);
    color: var(--ledio-text-muted);
    margin: 0;
    max-width: 44ch;
}

/* ==========================================================================
   15. B2B registration
   ========================================================================== */

.ledio-b2b {
    position: relative;
    overflow: hidden;
    background-color: var(--ledio-surface-dark);
}

.ledio-b2b__decor {
    background: radial-gradient(60% 70% at 15% 10%, rgba(88, 101, 242, 0.35) 0%, transparent 62%);
}

.ledio-b2b__inner {
    position: relative;
    z-index: 1;
}

.ledio-b2b__benefits {
    display: grid;
    gap: var(--ledio-space-md);
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: var(--ledio-font-body-lg);
}

.ledio-b2b__benefits li {
    display: flex;
    gap: var(--ledio-space-md);
    align-items: flex-start;
    padding: var(--ledio-space-md) var(--ledio-space-lg);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: var(--ledio-radius-md);
    background-color: rgba(255, 255, 255, 0.03);
    color: var(--ledio-text-on-dark-muted);
}

.ledio-b2b__benefits svg {
    flex-shrink: 0;
    margin-top: 4px;
    color: var(--ledio-green);
}

.ledio-b2b__note {
    display: inline-flex;
    align-items: center;
    gap: var(--ledio-space-xs);
    margin-top: var(--ledio-space-md);
    font-size: var(--ledio-font-body);
    color: var(--ledio-text-on-dark-muted);
}

/* ==========================================================================
   16. Final CTA — two large, distinct paths
   ========================================================================== */

.ledio-final {
    position: relative;
    overflow: hidden;
    background-color: var(--ledio-canvas);
}

.ledio-final__decor {
    background:
        radial-gradient(55% 60% at 20% 20%, rgba(0, 174, 235, 0.3) 0%, transparent 62%),
        radial-gradient(55% 60% at 80% 80%, rgba(236, 72, 189, 0.2) 0%, transparent 62%);
}

.ledio-final__inner {
    position: relative;
    z-index: 1;
}

.ledio-final__paths {
    display: grid;
    gap: var(--ledio-space-lg);
    grid-template-columns: 1fr;
}

.ledio-final__path {
    display: flex;
    flex-direction: column;
    gap: var(--ledio-space-md);
    padding: clamp(28px, 4vw, 56px);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: var(--ledio-radius-xl);
    background-color: rgba(32, 39, 93, 0.55);
}

/* The buying path carries the brand light — it is the primary of the two. */
.ledio-final__path--catalog {
    background:
        radial-gradient(90% 90% at 85% 0%, rgba(0, 174, 235, 0.22) 0%, transparent 60%),
        rgba(32, 39, 93, 0.55);
}

.ledio-final__path h3 {
    font-size: var(--ledio-font-h3);
    margin: 0;
    color: var(--ledio-white);
}

.ledio-final__path p {
    color: var(--ledio-text-on-dark-muted);
    font-size: var(--ledio-font-body-lg);
    margin: 0 0 var(--ledio-space-md);
    flex-grow: 1;
    max-width: 52ch;
}

/* ==========================================================================
   17. Footer
   ========================================================================== */

.ledio-footer {
    position: relative;
    background-color: #060930;
    color: var(--ledio-text-on-dark-muted);
    font-size: var(--ledio-font-body);
    padding-top: clamp(3.5rem, 6vw, 6rem);
    /*
     * The section above is near-identical in darkness, so without an
     * articulated edge the footer visually "starts" wherever the previous
     * section's content ends — reading as missing top padding. The hairline
     * makes the real boundary (and the padding above the logo) legible.
     */
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.ledio-footer__top {
    display: grid;
    gap: var(--ledio-space-2xl);
    grid-template-columns: 1fr;
    padding-bottom: var(--ledio-space-2xl);
}

.ledio-footer__brand img {
    height: 34px;
    width: auto;
    margin-bottom: var(--ledio-space-lg);
}

.ledio-footer__positioning {
    max-width: 44ch;
    margin: 0;
    line-height: 1.7;
}

.ledio-footer__cols {
    display: grid;
    gap: var(--ledio-space-xl);
    grid-template-columns: repeat(2, 1fr);
}

.ledio-footer__title {
    font-size: var(--ledio-font-small);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ledio-text-on-dark);
    margin-bottom: var(--ledio-space-md);
}

.ledio-footer__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: var(--ledio-space-sm);
}

.ledio-footer a {
    color: var(--ledio-text-on-dark-muted);
    text-decoration: none;
    transition: color var(--ledio-transition);
}

.ledio-footer a:hover {
    color: var(--ledio-primary);
    text-decoration: underline;
}

/* The categories column spans two tracks; its list flows in two columns. */
.ledio-footer__col--wide {
    grid-column: span 2;
}

.ledio-footer__list--split {
    grid-template-columns: 1fr 1fr;
    column-gap: var(--ledio-space-lg);
}

/* Stacked groups in one column (Kontakt above Showroom). */
.ledio-footer__group+.ledio-footer__group {
    margin-top: var(--ledio-space-xl);
}

.ledio-footer__bottom {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--ledio-space-md);
    padding-block: var(--ledio-space-lg);
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    font-size: var(--ledio-font-small);
}

.ledio-footer__credit {
    color: var(--ledio-text-on-dark-muted);
}

.ledio-footer__legal {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ledio-space-md);
    list-style: none;
    margin: 0;
    padding: 0;
}

/*
 * "Nastavenia cookies", which is a <button> because it opens a dialog rather
 * than going anywhere — a link that navigates nowhere is a lie told to anyone
 * on a screen reader or middle-clicking it.
 *
 * Everything below exists to undo the button, so it reads as the two links
 * beside it: the browser's chrome off, then `.ledio-footer a`'s own colour,
 * transition and hover repeated. Inheriting them is not an option — `a` and
 * `button` share no selector — and this is the whole of it.
 */
.ledio-footer__consent {
    padding: 0;
    border: 0;
    background: none;
    color: var(--ledio-text-on-dark-muted);
    font: inherit;
    cursor: pointer;
    transition: color var(--ledio-transition);
}

.ledio-footer__consent:hover {
    color: var(--ledio-primary);
    text-decoration: underline;
}

/* ==========================================================================
   18. Offcanvas (mobile navigation)
   ========================================================================== */

.ledio-offcanvas {
    background-color: var(--ledio-canvas);
    color: var(--ledio-text-on-dark);
}

.ledio-offcanvas .offcanvas-header {
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.ledio-offcanvas__nav {
    list-style: none;
    margin: 0 0 var(--ledio-space-lg);
    padding: 0;
    display: grid;
    gap: var(--ledio-space-2xs);
}

.ledio-offcanvas__link {
    display: flex;
    align-items: center;
    min-height: 48px;
    padding: 0 var(--ledio-space-md);
    border-radius: var(--ledio-radius-sm);
    color: var(--ledio-text-on-dark);
    font-size: var(--ledio-font-body);
    font-weight: 500;
    text-decoration: none;
}

.ledio-offcanvas__link:hover,
.ledio-offcanvas__link[aria-current="page"] {
    background-color: rgba(255, 255, 255, 0.08);
    color: var(--ledio-text-on-dark);
}

.ledio-offcanvas__group {
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ledio-text-on-dark-muted);
    margin: var(--ledio-space-md) var(--ledio-space-md) var(--ledio-space-xs);
}

.ledio-offcanvas__actions {
    display: grid;
    gap: var(--ledio-space-sm);
}

/* Bootstrap's default close button is dark; invert it on the indigo panel. */
.ledio-offcanvas .btn-close {
    filter: invert(1) grayscale(100%) brightness(200%);
}

/* The offcanvas search is always visible, whatever the viewport. */
.ledio-offcanvas .ledio-search {
    display: block;
}

/* ==========================================================================
   19. Responsive
   ========================================================================== */

@media (min-width: 576px) {
    .ledio-segment-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (min-width: 768px) {
    .ledio-icon-btn__label {
        display: inline;
    }

    .ledio-category-grid {
        grid-template-columns: repeat(3, 1fr);
    }

    .ledio-footer__top {
        grid-template-columns: minmax(260px, 1fr) 2.2fr;
    }

    .ledio-footer__cols {
        grid-template-columns: repeat(4, 1fr);
    }

    .ledio-final__paths {
        grid-template-columns: 1fr 1fr;
    }

    .ledio-split {
        grid-template-columns: 1fr 1fr;
    }
}

@media (min-width: 992px) {

    /*
     * The second header row appears here, so the sticky stack gets taller and
     * everything positioned under it has to follow. Declared beside the rule
     * that causes it, not somewhere it can be forgotten.
     */
    :root {
        --ledio-header-height: 125px;
    }

    .ledio-header__nav {
        display: block;
    }

    .ledio-search {
        display: block;
    }

    .ledio-category-grid {
        grid-template-columns: repeat(4, 1fr);
        gap: var(--ledio-space-lg);
    }

    /* The two categories that carry the catalogue get visual priority. */
    .ledio-category--featured {
        grid-column: span 2;
    }

    .ledio-category--featured .ledio-category__media {
        aspect-ratio: 21 / 10;
    }

    .ledio-segment-grid {
        grid-template-columns: repeat(3, 1fr);
    }
}

@media (min-width: 1200px) {
    .homepage-hero__title {
        max-width: 14ch;
    }
}

/* ==========================================================================
   20. Motion
   ========================================================================== */

/*
 * A single, cheap entrance: transform + opacity only, no layout properties.
 * Content is visible by default; nothing depends on the animation running.
 */
@media (prefers-reduced-motion: no-preference) {
    .ledio-rise {
        animation: ledio-rise 600ms cubic-bezier(0.2, 0, 0.2, 1) backwards;
    }

    .ledio-rise--2 {
        animation-delay: 80ms;
    }

    .ledio-rise--3 {
        animation-delay: 160ms;
    }
}

@keyframes ledio-rise {
    from {
        opacity: 0;
        transform: translate3d(0, 12px, 0);
    }

    to {
        opacity: 1;
        transform: translate3d(0, 0, 0);
    }
}

@media (prefers-reduced-motion: reduce) {

    .ledio-body *,
    .ledio-body *::before,
    .ledio-body *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }

    .ledio-btn:hover,
    .ledio-category:hover,
    .ledio-product:hover {
        transform: none;
    }
}

/* ============================================================
   Category listing (filters + toolbar + grid + pagination)
   ============================================================ */

/*
 * The listing hero keeps the dark category header but compresses its vertical
 * rhythm: the breadcrumb sits close to the global header and the products
 * start as high as possible.
 */
.ledio-section.ledio-listing-hero {
    padding-block: var(--ledio-space-lg) var(--ledio-space-xl);
}

.ledio-listing-hero__breadcrumb {
    margin-bottom: var(--ledio-space-md);
}

.ledio-listing-hero__title {
    font-size: clamp(1.9rem, 3vw, 2.8rem);
    margin-bottom: var(--ledio-space-xs);
}

.ledio-listing-hero__lead {
    margin-bottom: var(--ledio-space-xs);
    max-width: var(--ledio-measure);
}

/*
 * Premium breadcrumb on the dark hero: home icon, small chevron separators,
 * unlinked current item. Compact — a wayfinding line, not a component.
 */
.ledio-breadcrumb {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    row-gap: 2px;
    font-size: var(--ledio-font-small);
}

.ledio-breadcrumb__item {
    display: inline-flex;
    align-items: center;
}

.ledio-breadcrumb__sep {
    display: inline-flex;
    margin-inline: var(--ledio-space-2xs);
    color: var(--ledio-text-on-dark-muted);
    opacity: 0.7;
}

.ledio-breadcrumb__link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 4px;
    border-radius: var(--ledio-radius-xs);
    color: var(--ledio-text-on-dark-muted);
    text-decoration: none;
    transition: color var(--ledio-transition);
}

.ledio-breadcrumb__link:hover {
    color: var(--ledio-text-on-dark);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.ledio-breadcrumb__link:focus-visible {
    outline: 2px solid var(--ledio-primary);
    outline-offset: 1px;
    color: var(--ledio-text-on-dark);
}

.ledio-breadcrumb__current {
    padding: 2px 4px;
    color: var(--ledio-text-on-dark);
    font-weight: 600;
}

.ledio-section.ledio-listing-section {
    padding-block: var(--ledio-space-xl) var(--ledio-space-3xl);
}

/* Two-column shell: sidebar (categories + filters) + listing. */
.ledio-listing {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--ledio-space-xl);
    align-items: start;
}

/* The sidebar is a stack of blocks — categories, then filters — and reads as
   one column because the gap between them is the only thing separating them. */
.ledio-listing__sidebar {
    display: flex;
    flex-direction: column;
    gap: var(--ledio-space-md);
}

@media (min-width: 992px) {
    .ledio-listing {
        grid-template-columns: 264px minmax(0, 1fr);
    }

    /*
     * Pinned under the sticky header — hence --ledio-header-offset and not a
     * bare space token: with the category navigation at the top of this column,
     * anything tucked behind the header is a link nobody can click.
     *
     * NO HEIGHT CAP AND NO SCROLLBAR OF ITS OWN. A capped column scrolls
     * inside the page and puts a second scrollbar next to the first, which is
     * exactly the thing this sidebar must not look like. The column simply
     * scrolls with the page when it is taller than the screen.
     */
    .ledio-listing__sidebar {
        position: sticky;
        top: var(--ledio-header-offset);
    }
}

/*
 * ≥lg the offcanvas wrapper must flow as a plain sidebar block.
 *
 * flex-direction MATTERS: Bootstrap turns `.offcanvas-lg .offcanvas-body` into
 * `display: flex` above the breakpoint, which was harmless while the body held
 * nothing but the form and laid the "Filter" heading out BESIDE it the moment
 * a second child arrived. Stacking is the whole point of this block.
 */
@media (min-width: 992px) {
    .ledio-listing__sidebar-body {
        flex-direction: column;
        padding: 0;
        overflow: visible;
    }
}

/* ==========================================================================
   Listing sidebar — vertical category navigation
   ========================================================================== */

/*
 * Both sidebar blocks are labelled the same way: a small caps label sitting
 * ABOVE its white card, never inside one of them. "Kategórie" used to live
 * inside the navigation panel while "Filter" stood above the filter form, so
 * the two labels had different colours behind them and different insets — one
 * sidebar drawn as two unrelated components.
 */
.ledio-sidebar-title {
    margin: 0 0 var(--ledio-space-xs);
    padding-inline: 2px;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--ledio-text-muted);
}

/*
 * Same panel family as the filters, and deliberately quieter than a card: a
 * hairline outline instead of a full border, so the sidebar reads as two
 * surfaces rather than as two framed boxes.
 */
.ledio-catnav__panel {
    border: 1px solid var(--ledio-border-subtle);
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-white);
    padding: var(--ledio-space-2xs) var(--ledio-space-xs) var(--ledio-space-xs);
}

/* Below lg the panel header is a button; above it, the label does the naming. */
.ledio-catnav__toggle {
    display: flex;
    align-items: center;
    gap: var(--ledio-space-sm);
    width: 100%;
    padding: var(--ledio-space-xs);
    border: 0;
    border-radius: var(--ledio-radius-md);
    background: none;
    text-align: left;
    color: var(--ledio-text);
    cursor: pointer;
}

.ledio-catnav__toggle:focus-visible {
    outline: 2px solid var(--ledio-primary);
    outline-offset: 2px;
}

.ledio-catnav__toggle-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1 1 auto;
}

.ledio-catnav__toggle-label {
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--ledio-text-muted);
}

/* The category being viewed, so a collapsed panel still says where you are. */
.ledio-catnav__toggle-current {
    overflow: hidden;
    font-weight: 700;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ledio-catnav__toggle-chevron {
    display: inline-flex;
    flex: 0 0 auto;
    color: var(--ledio-text-muted);
    transition: transform var(--ledio-transition);
}

.ledio-catnav__toggle.collapsed .ledio-catnav__toggle-chevron {
    transform: rotate(-90deg);
}

.ledio-catnav__list {
    list-style: none;
    margin: 10px 0;
    padding: 0;
}

.ledio-catnav__item {
    /* Set per item by the template; 1 = a child of the branch root. */
    --catnav-depth: 1;
}

/*
 * A top-level row: the weight carries it. NO FILL under the pointer and no
 * coloured rule anywhere — the only line in this list is the hierarchy guide
 * on the children below, and a second vertical line next to it would make the
 * two compete instead of one explaining the other.
 *
 * line-height is set for the names that wrap ("Pohybové a automatické
 * spínače"): tight enough to stay one block, loose enough that two lines do
 * not touch.
 */
.ledio-catnav__link {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--ledio-space-xs);
    padding: 8px 10px 8px calc(12px + (var(--catnav-depth) - 1) * 16px);
    border-radius: var(--ledio-radius-sm);
    color: var(--ledio-text);
    font-size: var(--ledio-font-small);
    font-weight: 600;
    line-height: 1.45;
    text-decoration: none;
    transition: color var(--ledio-transition);
}

/*
 * A child row: lighter in weight, quieter in colour, tighter in rhythm, and
 * the one hairline this list allows itself — drawn at the child's own indent,
 * so consecutive children form a single unbroken guide.
 */
.ledio-catnav__link--nested {
    padding-block: 5px;
    color: var(--ledio-text-muted);
    font-weight: 500;
}

.ledio-catnav__link--nested::before {
    content: "";
    position: absolute;
    left: calc((var(--catnav-depth) - 1) * 16px);
    top: 0;
    bottom: 0;
    width: 1px;
    background-color: var(--ledio-border);
}

.ledio-catnav__link:hover {
    color: var(--ledio-primary-text);
}

.ledio-catnav__link:focus-visible {
    outline: 2px solid var(--ledio-primary);
    outline-offset: -2px;
    color: var(--ledio-primary-text);
}

/* An ancestor of the current category: open, but not where you are. */
.ledio-catnav__link.is-open {
    color: var(--ledio-text);
    font-weight: 700;
}

/*
 * Where you are: weight and colour, nothing else. NO BACKGROUND ANYWHERE IN
 * THIS LIST — not under the pointer, not on the current row. The plate this
 * row used to carry was the one thing that still painted a block behind a
 * link, and under the pointer it read as a hover state.
 */
.ledio-catnav__link.is-current {
    color: var(--ledio-primary-text);
    font-weight: 700;
}

.ledio-catnav__link--nested.is-current {
    font-weight: 600;
}

.ledio-catnav__name {
    flex: 1 1 auto;
    min-width: 0;
}

/*
 * "There is more inside". Pinned to the right edge by margin, not by the
 * name's growth, so a child with subcategories lines its chevron up with the
 * top-level ones however deep it sits. Readable on a parent, quieter on a
 * child, and it points down once you are inside.
 */
.ledio-catnav__marker {
    display: inline-flex;
    flex: 0 0 auto;
    margin-left: auto;
    color: var(--ledio-text-muted);
    transition: transform var(--ledio-transition), color var(--ledio-transition);
}

.ledio-catnav__link--nested .ledio-catnav__marker {
    color: var(--ledio-border-strong);
}

.ledio-catnav__link:hover .ledio-catnav__marker {
    color: currentColor;
    transform: translateX(2px);
}

.ledio-catnav__link.is-open .ledio-catnav__marker,
.ledio-catnav__link.is-current .ledio-catnav__marker {
    color: currentColor;
    transform: rotate(90deg);
}

@media (prefers-reduced-motion: reduce) {

    .ledio-catnav__toggle-chevron,
    .ledio-catnav__marker,
    .ledio-catnav__link {
        transition: none;
    }
}

/* The product grid: exactly 4 / 3 / 2 / 1 cards per row, never shrunken.
   The gap stays moderate so the cards themselves get the width. */
.ledio-listing__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--ledio-space-md);
}

/*
 * Listing-scoped card emphasis: a resting shadow separates the card from the
 * muted background, and a tighter photo padding gives the product itself more
 * of the 1:1 canvas. Typography is untouched.
 */
.ledio-listing__grid .ledio-product {
    box-shadow: var(--ledio-shadow-soft);
}

.ledio-listing__grid .ledio-product:hover {
    box-shadow: var(--ledio-shadow-lift);
}

.ledio-listing__grid .ledio-product__media img {
    padding: var(--ledio-space-sm);
}

.ledio-listing__grid .ledio-product__body {
    padding: var(--ledio-space-md) var(--ledio-space-lg) var(--ledio-space-lg);
    gap: 6px;
}

@media (min-width: 576px) {
    .ledio-listing__grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 992px) {
    .ledio-listing__grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (min-width: 1200px) {
    .ledio-listing__grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

/*
 * One toolbar above the grid: count left, sort and filter right — a single
 * anchored row, not loose elements.
 *
 * MOBILE-FIRST, AND THE MOBILE CASE IS THE HARD ONE. On a phone this bar is
 * the only thing between the heading and the first product, so it gets exactly
 * one line: the count, the current sort order, the way into the filters. It
 * wraps (count on its own line, the two controls beneath) only below ~360px,
 * where a single line genuinely cannot hold all three.
 *
 * The ≥992px block at the end restores the desktop metrics this bar has always
 * had — the visible "Zoradiť" label, the 190px select, the roomier gaps.
 */
.ledio-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ledio-space-xs);
    padding-bottom: var(--ledio-space-xs);
    border-bottom: 1px solid var(--ledio-border);
    margin-bottom: var(--ledio-space-md);
}

.ledio-toolbar__count {
    margin: 0;
    margin-right: auto;
    color: var(--ledio-text-muted);
    font-size: 0.8125rem;
    line-height: 1.2;
}

.ledio-toolbar__count strong {
    color: var(--ledio-text);
}

/*
 * Sort and filter are ONE control with two contents. Same height, same
 * hairline, same type — equal weight is the point: sorting is not more
 * important than filtering, and neither is a primary action competing with the
 * products below. 40px keeps the touch target comfortable at this density.
 */
.ledio-toolbar__control {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 40px;
    padding-inline: 10px;
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-sm);
    background-color: var(--ledio-surface);
    color: var(--ledio-text);
    font-family: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.2;
    white-space: nowrap;
    cursor: pointer;
    transition: border-color var(--ledio-transition), color var(--ledio-transition),
        background-color var(--ledio-transition);
}

.ledio-toolbar__control:hover {
    border-color: var(--ledio-border-strong);
    background-color: var(--ledio-surface-muted);
}

.ledio-toolbar__control:focus-visible {
    outline: none;
    border-color: var(--ledio-primary);
    box-shadow: 0 0 0 3px var(--ledio-primary-soft);
}

.ledio-toolbar__control svg {
    flex: 0 0 auto;
    color: var(--ledio-text-muted);
}

/*
 * The sort control is the native <select> itself, stripped to the toolbar's
 * chrome and given its own chevron. Native on purpose: the phone's own picker
 * is better than anything a dropdown of ours would be, the selected label is
 * always the server-rendered truth, and there is no JavaScript between the
 * visitor and the sort order.
 */
.ledio-toolbar__select {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 26px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235b6478' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 8px center;
    background-size: 14px 14px;
    text-overflow: ellipsis;
}

/*
 * Sort and filter travel together. When all three items no longer fit — a long
 * sort label plus an active-filter badge on a 375px phone — it is the PAIR that
 * drops to a second line, leaving the count on the first. The alternative (the
 * button breaking away alone) costs a full 40px row for one control and looks
 * like a mistake.
 */
.ledio-toolbar__controls {
    display: flex;
    align-items: center;
    gap: var(--ledio-space-xs);
    margin-left: auto;
    min-width: 0;
}

.ledio-toolbar__filters {
    flex: 0 0 auto;
}

/* Quiet enough not to turn the trigger into a CTA, loud enough to be the one
   thing in the bar that says "something is filtered". Dark ink on cyan — white
   on this cyan falls to ~2.2:1. */
.ledio-toolbar__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding-inline: 5px;
    border-radius: var(--ledio-radius-pill);
    background-color: var(--ledio-primary);
    color: #04121c;
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1;
}

.ledio-toolbar__sort {
    display: flex;
    align-items: center;
    gap: var(--ledio-space-xs);
    min-width: 0;
}

.ledio-toolbar__sort-label {
    font-size: var(--ledio-font-small);
    color: var(--ledio-text-muted);
    white-space: nowrap;
}

/* Below lg the label is clipped rather than removed: the select keeps its
   accessible name, it just stops costing a line above the control. */
@media (max-width: 991.98px) {
    .ledio-toolbar__sort-label {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border: 0;
    }

    /*
     * The select may not out-grow its share of a phone row. Left alone a
     * <select> is as wide as its WIDEST option ("Cena od najvyššej"), so the
     * default "Názov A–Z" would reserve 60px it never uses — and that is
     * exactly the 60px that decides whether all three items share one line.
     * `field-sizing: content` makes it as wide as the option actually shown;
     * where it is unsupported the max-width still caps the damage and the bar
     * degrades to two tight rows rather than overflowing.
     */
    .ledio-toolbar__select {
        field-sizing: content;
        /* Wide enough for the longest label ("Cena od najnižšej") beside the
           filter button on a 320px screen, and no wider — the cap is only a
           last-resort guard against a horizontal scrollbar. */
        max-width: 52vw;
    }
}

/* Desktop keeps the metrics it has always had. */
@media (min-width: 992px) {
    .ledio-toolbar {
        gap: var(--ledio-space-md);
        padding-bottom: var(--ledio-space-sm);
        margin-bottom: var(--ledio-space-lg);
    }

    .ledio-toolbar__count {
        font-size: var(--ledio-font-small);
    }

    .ledio-toolbar__count strong {
        font-size: var(--ledio-font-body);
    }

    /* 36px, not the mobile 40px: this is a pointer, not a thumb, and it keeps
       the bar the exact height it has always been on desktop. */
    .ledio-toolbar__control {
        min-height: 36px;
        padding-inline: var(--ledio-space-sm);
        border-color: var(--ledio-border-strong);
        font-size: var(--ledio-font-small);
    }

    .ledio-toolbar__select {
        min-width: 190px;
        padding-right: 32px;
        background-position: right 10px center;
    }
}

/* Active filter chips. On a phone they sit directly between the toolbar and
   the first product, so they carry the toolbar's tighter rhythm. */
.ledio-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ledio-space-xs);
    margin-bottom: var(--ledio-space-md);
}

@media (min-width: 992px) {
    .ledio-chips {
        margin-bottom: var(--ledio-space-lg);
    }
}

.ledio-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    border: 1px solid var(--ledio-border-strong);
    border-radius: var(--ledio-radius-pill);
    background-color: var(--ledio-white);
    color: var(--ledio-text);
    font-size: var(--ledio-font-small);
    font-weight: 600;
    text-decoration: none;
    transition: border-color var(--ledio-transition), color var(--ledio-transition);
}

.ledio-chip:hover,
.ledio-chip:focus-visible {
    border-color: var(--ledio-primary);
    color: var(--ledio-primary-text);
}

.ledio-chip--clear {
    border-color: transparent;
    background: none;
    color: var(--ledio-primary-text);
    text-decoration: underline;
}

/*
 * Filter sidebar: one compact white panel (same border/radius family as the
 * product cards), each attribute group an accordion block.
 */
.ledio-filters {
    display: flex;
    flex-direction: column;
    /* The same hairline as the category panel above it — the two cards in the
       sidebar are one component and may not be outlined differently. */
    border: 1px solid var(--ledio-border-subtle);
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-white);
    padding: var(--ledio-space-xs) var(--ledio-space-md) var(--ledio-space-md);
}

.ledio-facet {
    margin: 0;
    padding: 0;
    border: 0;
    border-bottom: 1px solid var(--ledio-border);
}

/* The legend only hosts the toggle button; the float resets undo the
   browser's special legend layout. */
.ledio-facet__legend {
    float: none;
    display: block;
    width: 100%;
    padding: 0;
    margin: 0;
}

.ledio-facet__toggle {
    display: flex;
    align-items: center;
    gap: var(--ledio-space-xs);
    width: 100%;
    padding: var(--ledio-space-sm) 2px;
    border: 0;
    background: none;
    cursor: pointer;
    text-align: left;
    color: var(--ledio-text);
}

.ledio-facet__toggle:hover .ledio-facet__title {
    color: var(--ledio-primary-text);
}

.ledio-facet__toggle:focus-visible {
    outline: 2px solid var(--ledio-primary);
    outline-offset: 2px;
    border-radius: var(--ledio-radius-xs);
}

.ledio-facet__title {
    flex: 1 1 auto;
    font-size: var(--ledio-font-small);
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--ledio-text);
    transition: color var(--ledio-transition);
}

.ledio-facet__badge {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding-inline: 5px;
    border-radius: var(--ledio-radius-pill);
    background-color: var(--ledio-primary);
    /* Same ink as the toolbar's own "N active" badge — one badge language for
       one meaning. White on this primary falls to ~1.6:1. */
    color: #04121c;
    font-size: 0.6875rem;
    font-weight: 700;
}

.ledio-facet__chevron {
    flex: 0 0 auto;
    display: inline-flex;
    color: var(--ledio-text-muted);
    transition: transform var(--ledio-transition);
}

.ledio-facet__toggle:not(.collapsed) .ledio-facet__chevron {
    transform: rotate(180deg);
}

.ledio-facet__body {
    padding: 2px 2px var(--ledio-space-md);
}

/* The availability switch has no accordion header to open — one row IS the
   block — so it supplies the vertical rhythm the header would have given it. */
.ledio-facet--switch .ledio-facet__body {
    padding-top: var(--ledio-space-md);
}

.ledio-facet__options {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.ledio-facet__option {
    display: flex;
}

.ledio-facet__option .form-check-input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.ledio-facet__option label {
    display: flex;
    align-items: center;
    gap: var(--ledio-space-xs);
    width: 100%;
    padding: 6px 8px;
    border-radius: var(--ledio-radius-xs);
    font-size: var(--ledio-font-small);
    color: var(--ledio-text);
    cursor: pointer;
    transition: background-color var(--ledio-transition);
}

.ledio-facet__option label::before {
    content: "";
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    border: 1.5px solid var(--ledio-border-strong);
    border-radius: 5px;
    background-color: var(--ledio-white);
    background-position: center;
    background-repeat: no-repeat;
    background-size: 13px;
    transition: border-color var(--ledio-transition), background-color var(--ledio-transition);
}

.ledio-facet__option label:hover {
    background-color: var(--ledio-primary-soft);
}

.ledio-facet__option .form-check-input:checked+label::before {
    border-color: var(--ledio-primary);
    background-color: var(--ledio-primary);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
}

.ledio-facet__option .form-check-input:focus-visible+label {
    outline: 2px solid var(--ledio-primary);
    outline-offset: 2px;
}

.ledio-facet__label {
    flex: 1 1 auto;
    min-width: 0;
    overflow-wrap: anywhere;
}

.ledio-facet__count {
    flex: 0 0 auto;
    color: var(--ledio-text-muted);
    font-size: 0.75rem;
}

/* Colour swatch: always paired with the text label, never colour alone. */
.ledio-swatch {
    flex: 0 0 auto;
    width: 15px;
    height: 15px;
    border-radius: 50%;
    border: 1px solid rgba(16, 24, 40, 0.25);
}

/*
 * A colour value we cannot resolve to a hex keeps its place in the row: same
 * circle, same size, no fill. Dashed rather than merely empty, because "biela"
 * is a real value with a near-white swatch — an unfilled solid circle would be
 * indistinguishable from it, and the whole point of this state is to say "we
 * do not know what this looks like" instead of quietly claiming white.
 */
.ledio-swatch--unknown {
    background-color: transparent;
    border-style: dashed;
    border-color: rgba(16, 24, 40, 0.45);
}

.ledio-facet__more {
    margin-top: var(--ledio-space-xs);
    padding: 4px 8px;
    border: 0;
    background: none;
    color: var(--ledio-primary-text);
    font-size: var(--ledio-font-small);
    font-weight: 600;
    cursor: pointer;
    text-align: left;
}

.ledio-facet__more:hover,
.ledio-facet__more:focus-visible {
    text-decoration: underline;
}

.ledio-facet__more .ledio-facet__more-show {
    display: none;
}

.ledio-facet__more .ledio-facet__more-hide {
    display: inline;
}

.ledio-facet__more.collapsed .ledio-facet__more-show {
    display: inline;
}

.ledio-facet__more.collapsed .ledio-facet__more-hide {
    display: none;
}

/*
 * Dual price-range slider: two overlaid native range inputs on one track.
 * A JS-only affordance (revealed by .is-js) layered over the from/to number
 * inputs, which remain the real, always-functional form fields.
 */
.ledio-range {
    display: none;
    position: relative;
    height: 24px;
    margin: var(--ledio-space-2xs) 2px var(--ledio-space-sm);
}

.ledio-listing.is-js .ledio-range {
    display: block;
}

.ledio-range__track,
.ledio-range__fill {
    position: absolute;
    top: 50%;
    height: 4px;
    transform: translateY(-50%);
    border-radius: var(--ledio-radius-pill);
    pointer-events: none;
}

.ledio-range__track {
    left: 0;
    right: 0;
    background-color: var(--ledio-border);
}

.ledio-range__fill {
    background-color: var(--ledio-primary);
}

.ledio-range input[type="range"] {
    position: absolute;
    inset: 0;
    width: 100%;
    margin: 0;
    background: none;
    -webkit-appearance: none;
    appearance: none;
    /* Only the thumbs are interactive; the track belongs to both inputs. */
    pointer-events: none;
}

.ledio-range input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    pointer-events: auto;
    width: 16px;
    height: 16px;
    border: 2px solid var(--ledio-primary);
    border-radius: 50%;
    background-color: var(--ledio-white);
    box-shadow: 0 1px 3px rgba(16, 24, 40, 0.25);
    cursor: grab;
}

.ledio-range input[type="range"]::-moz-range-thumb {
    pointer-events: auto;
    width: 16px;
    height: 16px;
    border: 2px solid var(--ledio-primary);
    border-radius: 50%;
    background-color: var(--ledio-white);
    box-shadow: 0 1px 3px rgba(16, 24, 40, 0.25);
    cursor: grab;
}

.ledio-range input[type="range"]:active::-webkit-slider-thumb {
    cursor: grabbing;
}

/* Price range inputs: "od – do" input-groups with € as an in-group suffix. */
.ledio-facet__price {
    display: flex;
    align-items: flex-end;
    gap: var(--ledio-space-xs);
}

.ledio-facet__price-field {
    flex: 1 1 0;
    min-width: 0;
}

.ledio-facet__price-sep {
    padding-bottom: 8px;
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
}

.ledio-facet__price-label {
    display: block;
    margin-bottom: 2px;
    font-size: 0.75rem;
    color: var(--ledio-text-muted);
}

.ledio-facet__price .form-control {
    border-color: var(--ledio-border-strong);
    border-start-start-radius: var(--ledio-radius-sm);
    border-end-start-radius: var(--ledio-radius-sm);
    font-size: var(--ledio-font-small);
}

.ledio-facet__price .input-group-text {
    padding-inline: 8px;
    border-color: var(--ledio-border-strong);
    border-start-end-radius: var(--ledio-radius-sm);
    border-end-end-radius: var(--ledio-radius-sm);
    background-color: var(--ledio-surface-muted);
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
}

.ledio-facet__price .form-control:focus {
    border-color: var(--ledio-primary);
    box-shadow: 0 0 0 3px var(--ledio-primary-soft);
}

/* A value nothing currently matches: visible, counted, but not selectable. */
.ledio-facet__option.is-disabled label {
    cursor: not-allowed;
    opacity: 0.45;
}

.ledio-facet__option.is-disabled label:hover {
    background-color: transparent;
}

.ledio-filters__actions {
    display: flex;
    flex-direction: column;
    gap: var(--ledio-space-sm);
    align-items: stretch;
    padding-top: var(--ledio-space-md);
}

/* With JavaScript connected, filters apply themselves — the fallback goes. */
.ledio-listing.is-js .ledio-filters__submit {
    display: none;
}

/* Subtle loading state while the GET navigation is in flight. */
.ledio-listing__main.is-loading .ledio-listing__grid,
.ledio-listing__main.is-loading .ledio-pagination {
    opacity: 0.45;
    pointer-events: none;
    transition: opacity var(--ledio-transition);
}

.ledio-filters__clear {
    text-align: center;
    color: var(--ledio-primary-text);
    font-size: var(--ledio-font-small);
    font-weight: 600;
}

/* Price on the card: the net price is the dominant line. */
.ledio-product__price--visible {
    display: flex;
    align-items: baseline;
    gap: var(--ledio-space-xs);
}

.ledio-product__price-value {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--ledio-text);
}

.ledio-product__price-vat {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--ledio-text-muted);
}

/* Availability line on the card. */
.ledio-product__stock {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: var(--ledio-font-small);
    color: var(--ledio-text-muted);
}

.ledio-product__stock-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: var(--ledio-border-strong);
}

.ledio-product__stock.is-in-stock .ledio-product__stock-dot {
    background-color: var(--ledio-green);
}

.ledio-product__stock.is-in-stock {
    color: #1d7a40;
}

/* The delivery window a back-ordered card carries after "Na objednávku". It is
   a range with an en dash in it and must never break across two lines, or the
   card reads "2–" on one line and "3 týždne" on the next. */
.ledio-product__lead-time {
    white-space: nowrap;
}

/*
 * Nothing is available and nothing is coming — either every supplier dropped the
 * product or the ones that have it report none. The page stays published
 * (sitemap, search results, links), so the line has to say why there is no "Do
 * košíka" under it, and it is deliberately quieter than the in-stock green: this
 * is an absence, not a warning.
 */
.ledio-product__stock--unavailable {
    color: var(--ledio-text-muted);
}

.ledio-product__stock--unavailable .ledio-product__stock-dot {
    background-color: var(--ledio-border-strong);
    opacity: 0.6;
}

/* When product detail exists the name link stretches over the whole card. */
.ledio-product__link::after {
    content: "";
    position: absolute;
    inset: 0;
}

/* Empty states. */
.ledio-listing-empty {
    padding: var(--ledio-space-3xl) var(--ledio-space-xl);
    border: 1px dashed var(--ledio-border-strong);
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-white);
    text-align: center;
}

/*
 * An optional mark above the message, for the empty state that is somebody's
 * search coming back with nothing — the one place in the shop where an empty
 * box is the answer to a question rather than a state of the catalogue, and
 * where it has to read as a deliberate reply instead of a missing grid. The
 * category listing's own empty states pass no icon and are unchanged.
 */
.ledio-listing-empty__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 4rem;
    height: 4rem;
    margin-bottom: var(--ledio-space-md);
    border-radius: 50%;
    background-color: var(--ledio-surface-muted);
    color: var(--ledio-text-muted);
}

.ledio-listing-empty__title {
    font-size: var(--ledio-font-h3);
    margin-bottom: var(--ledio-space-sm);
}

.ledio-listing-empty__text {
    /* Centred text needs a measure of its own, or a two-line explanation
       stretches the width of the page and stops reading as one sentence. */
    max-width: var(--ledio-measure);
    margin-inline: auto;
    margin-bottom: var(--ledio-space-lg);
    color: var(--ledio-text-muted);
}

/* Pagination. */
.ledio-pagination {
    margin-top: var(--ledio-space-2xl);
}

.ledio-pagination ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--ledio-space-2xs);
}

.ledio-pagination__page,
.ledio-pagination__arrow {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 40px;
    height: 40px;
    padding-inline: 10px;
    border: 1px solid var(--ledio-border-strong);
    border-radius: var(--ledio-radius-sm);
    background-color: var(--ledio-white);
    color: var(--ledio-text);
    font-size: var(--ledio-font-small);
    font-weight: 600;
    text-decoration: none;
    transition: border-color var(--ledio-transition), color var(--ledio-transition);
}

a.ledio-pagination__page:hover,
a.ledio-pagination__page:focus-visible,
a.ledio-pagination__arrow:hover,
a.ledio-pagination__arrow:focus-visible {
    border-color: var(--ledio-primary);
    color: var(--ledio-primary-text);
}

.ledio-pagination__page.is-current {
    border-color: var(--ledio-primary);
    background-color: var(--ledio-primary);
    color: var(--ledio-white);
}

.ledio-pagination__arrow.is-disabled {
    opacity: 0.4;
    pointer-events: none;
}

.ledio-pagination__gap {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 40px;
    height: 40px;
    color: var(--ledio-text-muted);
}

/*
 * Offcanvas variant of the filters (below lg). The width belongs to the
 * offcanvas panel, NOT to the sidebar column: the column also holds the
 * category navigation, which stays in the page on a phone and must keep the
 * full width there.
 */
@media (max-width: 991.98px) {
    .ledio-listing__filters {
        max-width: 320px;
    }

    .ledio-listing__filters .offcanvas-header {
        border-bottom: 1px solid var(--ledio-border);
    }

    .ledio-listing__filters .offcanvas-title {
        font-size: var(--ledio-font-body-lg);
        font-weight: 700;
    }
}

/* ============================================================
   Product detail (PDP)
   ============================================================ */

.ledio-section.ledio-pdp-hero {
    padding-block: var(--ledio-space-lg);
}

.ledio-section.ledio-pdp-main {
    padding-block: var(--ledio-space-xl) var(--ledio-space-2xl);
}

/*
 * One flat grid: the children's DOM order IS the mobile order (gallery →
 * info → description → parameters → documents). On desktop the info panel is
 * pinned into the right column across every row (unused spanned rows
 * collapse to zero height), so all content blocks stack in the left column
 * at exactly the gallery's width and the space under the panel stays empty.
 */
.ledio-pdp {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--ledio-space-xl);
    align-items: start;
}

@media (min-width: 992px) {
    .ledio-pdp {
        grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
        gap: var(--ledio-space-xl) var(--ledio-space-2xl);
    }

    .ledio-pdp__gallery {
        grid-column: 1;
        grid-row: 1;
    }

    .ledio-pdp__block {
        grid-column: 1;
    }

    /*
     * Sticky product info. Top offset = the sticky header's height (126px)
     * plus breathing room; the max-height + overflow guard keeps a long
     * panel inside the viewport instead of cutting off its bottom.
     */
    .ledio-pdp__info {
        grid-column: 2;
        grid-row: 1 / span 9;
        align-self: start;
        position: sticky;
        top: 150px;
        max-height: calc(100vh - 150px - var(--ledio-space-lg));
        overflow-y: auto;
    }
}

/* Gallery */
.ledio-pdp__stage {
    margin: 0;
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-white);
    overflow: hidden;
    aspect-ratio: 1 / 1;
    display: flex;
    align-items: center;
    justify-content: center;
}

.ledio-pdp__stage--empty {
    color: var(--ledio-text-muted);
}

.ledio-pdp__zoom {
    display: block;
    width: 100%;
    height: 100%;
    padding: var(--ledio-space-xl);
    border: 0;
    background: none;
    cursor: zoom-in;
}

.ledio-pdp__zoom img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.ledio-pdp__thumbs {
    display: flex;
    gap: var(--ledio-space-xs);
    margin-top: var(--ledio-space-sm);
    overflow-x: auto;
    padding-bottom: 4px;
    scrollbar-width: thin;
}

.ledio-pdp__thumb {
    flex: 0 0 auto;
    width: 76px;
    height: 76px;
    padding: 6px;
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-sm);
    background-color: var(--ledio-white);
    cursor: pointer;
    transition: border-color var(--ledio-transition);
}

.ledio-pdp__thumb img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.ledio-pdp__thumb:hover {
    border-color: var(--ledio-border-strong);
}

.ledio-pdp__thumb.is-active {
    border-color: var(--ledio-primary);
    box-shadow: 0 0 0 1px var(--ledio-primary);
}

.ledio-pdp__thumb:focus-visible {
    outline: 2px solid var(--ledio-primary);
    outline-offset: 2px;
}

/* Lightbox */
/* The hidden attribute must always win, whatever the UA stylesheet does. */
.ledio-pdp-lightbox[hidden] {
    display: none;
}

.ledio-pdp-lightbox {
    position: fixed;
    inset: 0;
    z-index: 1080;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: clamp(16px, 4vw, 64px);
    background-color: rgba(9, 13, 56, 0.92);
}

.ledio-pdp-lightbox__image {
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
    object-fit: contain;
    border-radius: var(--ledio-radius-sm);
    background-color: var(--ledio-white);
}

.ledio-pdp-lightbox__close,
.ledio-pdp-lightbox__nav {
    position: absolute;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: 50%;
    background-color: rgba(255, 255, 255, 0.08);
    color: var(--ledio-text-on-dark);
    cursor: pointer;
    transition: background-color var(--ledio-transition);
}

.ledio-pdp-lightbox__close:hover,
.ledio-pdp-lightbox__nav:hover {
    background-color: rgba(255, 255, 255, 0.2);
}

.ledio-pdp-lightbox__close:focus-visible,
.ledio-pdp-lightbox__nav:focus-visible {
    outline: 2px solid var(--ledio-primary);
    outline-offset: 2px;
}

.ledio-pdp-lightbox__close {
    top: 20px;
    right: 20px;
}

.ledio-pdp-lightbox__nav--prev {
    left: 20px;
    top: 50%;
    transform: translateY(-50%);
}

.ledio-pdp-lightbox__nav--next {
    right: 20px;
    top: 50%;
    transform: translateY(-50%);
}

.ledio-pdp-lightbox__counter {
    position: absolute;
    bottom: 16px;
    left: 50%;
    transform: translateX(-50%);
    margin: 0;
    color: var(--ledio-text-on-dark-muted);
    font-size: var(--ledio-font-small);
}

/* ------------------------------------------------------------------ *
 * PRODUCT INFO CARD
 *
 * One card, four bands: who and what (header + identifiers), what it costs and
 * whether it is there (the commercial strip + the CTA), what it is (description),
 * and what it measures (parameters + documents).
 *
 * The bands are separated by HAIRLINES, not by nested panels. A card holding
 * four boxes reads as four things that happen to be near each other; a card
 * holding four bands reads as one thing with four parts, which is what a product
 * is. Everything below therefore leans on rhythm and rules rather than on
 * backgrounds — there is exactly one filled element in the whole card, and it is
 * the button.
 * ------------------------------------------------------------------ */
/*
 * NO `position` HERE. The desktop rule above makes this panel `sticky`, and this
 * block sits later in the file at the same specificity — a `position: relative`
 * added here for the bookmark's sake silently won, the panel stopped sticking,
 * and its `top: 150px` started reading as a relative offset that pushed the
 * whole card 150px below the gallery. The bookmark anchors to the header
 * instead; see .ledio-pdp__header.
 */
.ledio-pdp__info {
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-white);
    padding: var(--ledio-space-xl);
    display: flex;
    flex-direction: column;
    gap: var(--ledio-space-lg);

    /*
     * The card is its own query container, because how much fits on a line
     * inside it is a fact about the CARD, not about the window: this is a
     * full-width block on a phone and a ~430px sticky column on a 1200px
     * desktop, and a viewport breakpoint cannot tell those two apart. The strips
     * below ask the card directly.
     */
    container-type: inline-size;
}

/* The bookmark's positioning context. Deliberately the header and not the card:
   the card's own `position` belongs to the desktop sticky rule and must not be
   touched from here. */
.ledio-pdp__header {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--ledio-space-2xs);
}

/*
 * An outlined circle, never filled: it is a place held for a feature, and a
 * control that looks pressed before it works is a promise the page cannot keep.
 *
 * ABSOLUTE, so it costs the title nothing. As a flex sibling of the heading it
 * shortened every line of the product name to make room for itself; pinned into
 * the card's corner — above the content padding, level with the brand line — it
 * clears the title entirely and the name gets the card's full width on every
 * line of a wrap.
 *
 * Pinned to the header's own top-right, which puts it on the card's content
 * edge rather than out in the padding: the same right-hand axis the parameter
 * values and the strip end on, and nothing for the panel's `overflow-y: auto`
 * to clip on the way past. The card itself is left unpositioned on purpose —
 * that property is the desktop sticky rule's.
 */
.ledio-pdp__bookmark {
    position: absolute;
    /* Up into the card's padding so it ends where the title begins — the name's
       first line must not run underneath it — but flush with the content's right
       axis, because a negative `right` is what the panel's overflow would clip. */
    top: calc(-1 * var(--ledio-space-md));
    right: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border: 1px solid var(--ledio-border-strong);
    border-radius: 50%;
    color: var(--ledio-text-muted);
}

/* The one line that does share the corner with it. Short by nature — a brand is
   a word — but a feed can always surprise, so the room is reserved rather than
   assumed. */
.ledio-pdp__brand {
    padding-right: 42px;
}

/* No brand means the title's own first line is what sits beside the bookmark,
   and it is the only case where the name gives up any width at all. */
.ledio-pdp__header--no-brand .ledio-pdp__title {
    padding-right: 42px;
}

.ledio-pdp__brand {
    margin: 0;
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ledio-primary-text);
}

/*
 * The one loud thing on the card. It stays dominant at every width — the buyer
 * has usually arrived from a listing of near-identical names and the first job
 * of this page is to confirm which one they opened — but the ceiling is low
 * enough that three lines of a long feed name still leave the price above the
 * fold on a phone.
 */
.ledio-pdp__title {
    margin: 0;
    font-size: clamp(1.5rem, 2.6vw, 2.125rem);
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -0.015em;
    overflow-wrap: anywhere;
}

/*
 * Product code and barcode as two small columns with a rule between them —
 * label above value, both values on their own baseline. Written as a <dl>
 * because that is what they are; `display: contents` on the pair wrapper is what
 * lets the flex row see the dt and the dd (the wrapper exists because a <dl>
 * groups its pairs in a <div>, and because .ledio-pdp__sku still has to name one
 * whole identifier for the tests).
 */
/*
 * ONE GRID, TWO STRIPS.
 *
 * The identifiers and the prices are separate rows of the same three-column
 * grid, so the product code, the barcode, the price without VAT, the price with
 * it and the availability all begin on the same three vertical axes. Sized as
 * equal thirds rather than by their contents: columns fitted to whatever the
 * feed happened to send line up with nothing, and a card of them reads as
 * values dropped where they landed rather than as a sheet.
 *
 * A grid also cannot wrap, which is what makes the dividers safe — each is the
 * left border of a cell, and a wrapped cell would leave a vertical hairline
 * hanging under the one before it, pointing at nothing. A long code wraps INSIDE
 * its own cell instead, which is where it belongs.
 *
 * Every cell carries the same horizontal padding and the first has no left
 * padding at all, so the first column shares its axis with the title, the
 * description and the parameter names below.
 */
.ledio-pdp__ident,
.ledio-pdp__buybox {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
}

.ledio-pdp__ident>*,
.ledio-pdp__buybox>* {
    min-width: 0;
    padding-right: var(--ledio-space-md);
}

/* The divider stretches the full height of the row because the cells stretch:
   a rule that stops halfway reads as decoration, one that spans the row reads
   as a column edge. */
.ledio-pdp__ident>*+*,
.ledio-pdp__buybox>*+* {
    padding-left: var(--ledio-space-md);
    border-left: 1px solid var(--ledio-border);
}

.ledio-pdp__ident {
    margin: 0;
    font-size: var(--ledio-font-small);
}

.ledio-pdp__sku {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.ledio-pdp__ident dt {
    color: var(--ledio-text-muted);
    font-weight: 400;
}

.ledio-pdp__ident dd {
    margin: 0;
    font-weight: 600;
    color: var(--ledio-text);
    /* Thirteen digits nobody reads as a word: equal widths make a barcode
       scannable in groups instead of as a run of characters. */
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}

/*
 * THE COMMERCIAL STRIP — the two prices and the availability on one line,
 * divided by hairlines. Bounded top and bottom by rules of its own, so it reads
 * as the band of the card where the money is, without a panel around it.
 */
.ledio-pdp__buybox {
    padding: var(--ledio-space-lg) 0;
    border-block: 1px solid var(--ledio-border);
}

/*
 * A price is a label and a figure stacked, not a figure with a suffix: read top
 * to bottom, the buyer knows WHICH price before reading the digits instead of
 * after. Both readings get the same size — on a trade page they are compared,
 * and shrinking one of them only means it gets looked at twice.
 */
.ledio-pdp__price {
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: var(--ledio-space-2xs);
    min-width: 0;
}

.ledio-pdp__price-value {
    font-size: clamp(1.5rem, 2.4vw, 1.9rem);
    font-weight: 700;
    line-height: 1.1;
    color: var(--ledio-text);
    /* Equal-width lining figures and slightly tightened tracking: two prices
       side by side stay on one vertical rhythm, and large numerals stop looking
       typed rather than set. */
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.02em;
    white-space: nowrap;
}

.ledio-pdp__price-vat {
    font-size: var(--ledio-font-small);
    font-weight: 400;
    color: var(--ledio-text-muted);
    white-space: nowrap;
}

/* No price to show is a sentence, not a number: the size of a body line rather
   than of a figure, and it takes both price columns so that availability stays
   in the third one — where it is on every other card. */
.ledio-pdp__price--fallback {
    grid-column: span 2;
    font-size: var(--ledio-font-body-lg);
    font-weight: 600;
    color: var(--ledio-text-muted);
}

/*
 * Availability is the third column of the strip, and the only place in the card
 * that is allowed a colour: in stock or not is the one fact a buyer scans for
 * before anything else.
 */
/*
 * Built to the same two-line rhythm as the price cells beside it — status on the
 * label line, quantity on the figure line — so the strip reads as ONE row of
 * information rather than as two prices with something else parked next to them.
 * That is what the equal columns are for, and a third cell marching to its own
 * metrics would undo them.
 */
.ledio-pdp__availability {
    display: flex;
    flex-direction: column;
    gap: var(--ledio-space-2xs);
}

/* The shared stock line is a <p> and keeps the reboot's 1rem bottom margin,
   which in a flex column does not collapse — it was adding a whole line of air
   between the status and its quantity and pushing the cell out of step with the
   prices. The listing card wants that margin; this cell does not. */
.ledio-pdp__availability .ledio-product__stock {
    margin: 0;
    font-size: var(--ledio-font-small);
    font-weight: 600;
}

.ledio-pdp__stock-qty {
    margin: 0;
    /* Under the WORD, not under the dot. The dot is a marker for the whole cell
       — it hangs to the left of both lines the way a bullet does — so the text
       of the two keeps one axis. 8px dot + 6px gap. */
    padding-left: 14px;
    font-size: var(--ledio-font-body-lg);
    font-weight: 600;
    color: var(--ledio-text);
    font-variant-numeric: tabular-nums;
}

.ledio-pdp__lead-time {
    margin: 0;
    padding-left: 14px;
    font-size: var(--ledio-font-small);
    color: var(--ledio-text-muted);
}

/*
 * Once the CARD is too narrow for three columns, availability takes a line of
 * its own under the two prices — with a rule above it instead of beside it, so
 * a wrapped cell never leaves a vertical hairline pointing at nothing.
 *
 * The threshold is the card width at which the two prices plus the stock column
 * stop fitting, measured rather than guessed. Below it the prices keep their
 * size: on a page whose entire job is quoting, the price is the last thing that
 * should give way.
 */
@container (max-width: 439.98px) {

    /* Two columns instead of three. A third of a 380px card is 127px, and a
       thirteen-digit barcode does not fit in it — the strip would keep its grid
       and lose its content, which is the wrong way round. */
    .ledio-pdp__ident,
    .ledio-pdp__buybox {
        grid-template-columns: repeat(2, 1fr);
    }

    .ledio-pdp__price--fallback {
        grid-column: span 2;
    }

    /* Half the space around the dividers. A thirteen-digit barcode needs about
       118px and a half-column here is 142: at 16px a side it is short by a
       hair's breadth and breaks across two lines, which is the one thing a
       barcode must never do. */
    .ledio-pdp__ident>*,
    .ledio-pdp__buybox>* {
        padding-right: var(--ledio-space-xs);
    }

    .ledio-pdp__ident>*+*,
    .ledio-pdp__buybox>*+* {
        padding-left: var(--ledio-space-xs);
    }

    .ledio-pdp__availability {
        grid-column: 1 / -1;
        margin-top: var(--ledio-space-md);
        padding: var(--ledio-space-md) 0 0;
        border-left: 0;
        border-top: 1px solid var(--ledio-border);
    }
}

/* The short description: readable, and deliberately quieter than the name, the
   price and the button above it. */
.ledio-pdp__intro {
    margin: 0;
    color: var(--ledio-text-muted);
    line-height: 1.65;
}

/*
 * KEY PARAMETERS — name left, value right, a hairline between rows and nothing
 * else. No icons: a technical list is read by scanning the left column for a
 * word, and a glyph in front of every row is one more thing between the eye and
 * that word. The value carries the weight because the value is what differs
 * between two products a buyer is comparing.
 */
.ledio-pdp__key-params {
    margin: 0;
    display: flex;
    flex-direction: column;
    padding-top: var(--ledio-space-xs);
    border-top: 1px solid var(--ledio-border);
}

/* 9px rather than 12: a quarter tighter reads as a datasheet instead of a menu,
   and the row is still a comfortable 36px tall — dense, not cramped. */
.ledio-pdp__key-param {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--ledio-space-md);
    padding: 9px 0;
    border-bottom: 1px solid var(--ledio-border);
    font-size: var(--ledio-font-small);
}

.ledio-pdp__key-param:last-child {
    border-bottom: 0;
    padding-bottom: 0;
}

.ledio-pdp__key-param dt {
    color: var(--ledio-text-muted);
    font-weight: 400;
}

.ledio-pdp__key-param dd {
    margin: 0;
    font-weight: 600;
    text-align: right;
    overflow-wrap: anywhere;
    font-variant-numeric: tabular-nums;
}

/*
 * The jump down to the documents: a framed row that closes the card, echoing the
 * CTA's shape at a whisper of its weight. The chevron is the only thing on the
 * right, so the row reads as "there is more this way" rather than as a button.
 */
.ledio-pdp__files-link {
    display: flex;
    align-items: center;
    gap: var(--ledio-space-sm);
    padding: var(--ledio-space-sm) var(--ledio-space-md);
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-md);
    color: var(--ledio-primary-text);
    font-size: var(--ledio-font-small);
    font-weight: 600;
    text-decoration: none;
    transition: border-color var(--ledio-transition), background-color var(--ledio-transition);
}

.ledio-pdp__files-link-text {
    flex: 1 1 auto;
    min-width: 0;
}

.ledio-pdp__files-link-more {
    flex: 0 0 auto;
    display: inline-flex;
    color: var(--ledio-text-muted);
}

.ledio-pdp__files-link:hover,
.ledio-pdp__files-link:focus-visible {
    border-color: var(--ledio-border-strong);
    background-color: var(--ledio-surface-muted);
    text-decoration: none;
}

/* Headings of the left-column content blocks. */
.ledio-pdp-section__title {
    font-size: clamp(1.25rem, 2vw, 1.6rem);
    font-weight: 700;
    margin-bottom: var(--ledio-space-lg);
}

.ledio-pdp__description {
    max-width: 75ch;
    line-height: 1.7;
    color: var(--ledio-text);
}

/* Content blocks in the left column (description, parameters, documents). */
.ledio-pdp__block {
    min-width: 0;
}

.ledio-pdp-block-panel {
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-white);
    padding: var(--ledio-space-xl);
}

/* Order block: quantity stepper + the (visual-only) primary CTA. */
/*
 * A block, not a flex row. It used to hold a stepper AND a separate CTA side by
 * side; it now holds the one cart control, and as a flex item that control
 * shrink-wrapped to its content — so the buybox's button was ~150px wide and
 * changed width between its two states. `display: block` lets the control fill
 * the panel, which is what makes both states the same footprint.
 */
.ledio-pdp__order {
    display: block;
}

/*
 * The quantity stepper — ONE segmented control, not three inputs side by side.
 *
 * Everything about it is sized from two custom properties set by the variant
 * (see the cart section at the end of this file), and that is what guarantees
 * the promise the product card makes: the "Do košíka" button and this control
 * are the same height, so a card cannot change shape when something is put in
 * the basket.
 *
 * It is used ONLY by templates/frontend/cart/_control.html.twig — the product
 * detail's old page-local stepper is gone — so its skin is the cart's skin: a
 * cyan-tinted box that reads as "this product is already in your basket" from
 * across a grid of cards, without a second badge or a tick to say so.
 */
.ledio-qty {
    display: flex;
    align-items: stretch;
    height: var(--ledio-cart-control-height);
    border: 1px solid var(--ledio-canvas);
    border-radius: var(--ledio-radius-sm);
    /*
     * THE HEADER'S NAVY, and the choice is about hierarchy rather than
     * decoration. "Do košíka" is the shop's primary action and owns the
     * cyan; a product that is ALREADY in the basket is not an invitation,
     * it is a state — so it takes the darkest surface in the system and
     * stops competing with the buttons around it. Scanning a category, the
     * dark blocks are the answer to "what have I already picked up".
     *
     * The tint it replaced (--ledio-primary-soft) read as a disabled or
     * secondary version of the CTA, which is the opposite of what it means.
     */
    background-color: var(--ledio-canvas);
    color: var(--ledio-text-on-dark);
    /* The buttons are flush with the border; this is what clips them to it. */
    overflow: hidden;
}

.ledio-qty:focus-within {
    box-shadow: 0 0 0 3px var(--ledio-primary-soft);
}

.ledio-qty__btn {
    flex: 0 0 var(--ledio-cart-control-step);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--ledio-cart-control-step);
    padding: 0;
    border: 0;
    background-color: transparent;
    color: var(--ledio-text-on-dark);
    font-size: 1.125rem;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    transition: background-color var(--ledio-transition), color var(--ledio-transition);
}

/*
 * Lifting the surface rather than tinting the glyph: on navy, a lighter plate
 * under the pointer is legible at a glance and keeps the symbol at full
 * contrast. --ledio-surface-indigo is the same step the dark sections of the
 * storefront already use for a raised panel.
 */
.ledio-qty__btn:hover {
    background-color: var(--ledio-surface-indigo);
}

.ledio-qty__btn:active {
    background-color: var(--ledio-canvas-soft);
}

/* Inset, because an outline outside the box would be clipped by `overflow`. */
.ledio-qty__btn:focus-visible {
    outline: 2px solid var(--ledio-primary);
    outline-offset: -2px;
}

/*
 * The field takes whatever the two buttons leave, so a four-digit B2B quantity
 * is readable in a card and the control still fills its slot. `min-width: 0` is
 * what lets a number input actually shrink inside a flex row.
 */
.ledio-qty__input {
    flex: 1 1 auto;
    width: 100%;
    min-width: 0;
    padding: 0 2px;
    border: 0;
    /*
     * Barely-there hairlines. They exist so the three parts read as one
     * segmented control with seams rather than as one undifferentiated bar —
     * anything stronger and the field starts looking like a separate input
     * dropped between two buttons.
     */
    border-left: 1px solid rgba(255, 255, 255, 0.14);
    border-right: 1px solid rgba(255, 255, 255, 0.14);
    background-color: transparent;
    text-align: center;
    font-size: var(--ledio-font-body);
    font-weight: 700;
    color: var(--ledio-text-on-dark);
    /* Cyan, because a white caret on navy is nearly invisible while typing. */
    caret-color: var(--ledio-primary);
    cursor: text;
    -moz-appearance: textfield;
    appearance: textfield;
}

/*
 * Focusing the field selects what is in it (cart_item_controller.js), so the
 * selection is the first thing somebody sees when they go to type a B2B
 * quantity — it has to be legible on navy rather than the browser's default
 * pale blue on white.
 */
.ledio-qty__input::selection {
    background-color: var(--ledio-primary);
    color: #04121c;
}

/*
 * The spinners are removed on purpose: they are a third way to change the
 * number, they are a two-pixel target, and they exist beside two buttons that
 * do the same job properly.
 */
.ledio-qty__input::-webkit-outer-spin-button,
.ledio-qty__input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/*
 * A lifted plate while typing, so the editable part of the control announces
 * itself. The ring around the whole box comes from :focus-within above — one
 * ring for one component, not a second one inside it.
 */
.ledio-qty__input:focus {
    background-color: var(--ledio-surface-indigo);
    outline: none;
}

/*
   What stands in the order block's place for a customer whose registration is
   still being looked at. Quiet on purpose — it is an explanation, not a warning,
   and it occupies the same slot so the buybox does not visibly lose a row.
*/
.ledio-pdp__order-locked {
    margin: 0;
    padding: var(--ledio-space-sm) var(--ledio-space-md);
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-sm);
    background-color: var(--ledio-surface-muted);
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
}

/* Technical parameters */
.ledio-pdp-params {
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-white);
    overflow: hidden;
}

.ledio-pdp-params__table {
    width: 100%;
    margin: 0;
    border-collapse: collapse;
    font-size: var(--ledio-font-small);
}

.ledio-pdp-params__table tr:not(:last-child) th,
.ledio-pdp-params__table tr:not(:last-child) td {
    border-bottom: 1px solid var(--ledio-border);
}

.ledio-pdp-params__table th {
    width: 45%;
    padding: 10px var(--ledio-space-lg);
    font-weight: 400;
    color: var(--ledio-text-muted);
    text-align: left;
    vertical-align: top;
}

.ledio-pdp-params__table td {
    padding: 10px var(--ledio-space-lg);
    font-weight: 600;
    overflow-wrap: anywhere;
}

/* Documents & files */
.ledio-pdp-files {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--ledio-space-xs);
}

@media (min-width: 768px) {
    .ledio-pdp-files {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.ledio-pdp-files__link {
    display: flex;
    align-items: center;
    gap: var(--ledio-space-sm);
    padding: var(--ledio-space-sm) var(--ledio-space-md);
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-sm);
    background-color: var(--ledio-white);
    color: var(--ledio-text);
    text-decoration: none;
    transition: border-color var(--ledio-transition);
    min-height: 56px;
}

.ledio-pdp-files__link:hover,
.ledio-pdp-files__link:focus-visible {
    border-color: var(--ledio-primary);
}

.ledio-pdp-files__icon {
    flex: 0 0 auto;
    color: var(--ledio-primary-text);
}

.ledio-pdp-files__name {
    flex: 1 1 auto;
    min-width: 0;
    font-size: var(--ledio-font-small);
    font-weight: 600;
    overflow-wrap: anywhere;
}

.ledio-pdp-files__meta {
    flex: 0 0 auto;
    font-size: 0.75rem;
    color: var(--ledio-text-muted);
    white-space: nowrap;
}

.ledio-pdp-files__action {
    flex: 0 0 auto;
    color: var(--ledio-text-muted);
}

.ledio-pdp-video {
    margin: var(--ledio-space-lg) 0 0;
    max-width: 920px;
}

.ledio-pdp-video video {
    width: 100%;
    height: auto;
    border-radius: var(--ledio-radius-sm);
    background-color: #000;
}

.ledio-pdp-video-link a {
    display: inline-flex;
    align-items: center;
    gap: var(--ledio-space-xs);
    color: var(--ledio-primary-text);
    font-weight: 600;
    text-decoration: none;
}

.ledio-pdp-video-link a:hover {
    text-decoration: underline;
}

/* ============================================================
   Account & forms (sign-in, registration, approval notice)
   ============================================================ */

/*
 * The storefront's form skin. It styles Bootstrap's own classes rather than
 * shipping a Twig form theme, because bootstrap_5_layout is what config/
 * packages/twig.yaml renders with everywhere — a second theme would be a second
 * place for a field's markup to be decided.
 *
 * Layout is stacked, not the administration's horizontal grid: these forms are
 * filled in once, on a phone as often as not, and a label above its field is
 * the shape that survives a 360px screen without a container query.
 */

.ledio-auth {
    padding-block: var(--ledio-space-2xl) var(--ledio-space-3xl);
}

.ledio-auth__panel {
    width: min(100%, 520px);
    margin-inline: auto;
    padding: clamp(var(--ledio-space-lg), 4vw, var(--ledio-space-2xl));
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-surface);
    box-shadow: var(--ledio-shadow-soft);
}

/*
 * Registration carries five blocks of paired fields, and at 860px the pairs
 * were cramped: the phone widget had no room for its country button, and Slovak
 * city names filled a half-width input end to end. 1000px is about 16% wider —
 * enough to breathe, still far short of the width at which a label and its
 * control stop reading as one thing.
 */
.ledio-auth__panel--wide {
    width: min(100%, 1000px);
}

.ledio-auth__panel--centered {
    text-align: center;
}

.ledio-auth__title {
    margin: var(--ledio-space-2xs) 0 var(--ledio-space-md);
    font-size: var(--ledio-font-h3);
}

.ledio-auth__lead {
    max-width: var(--ledio-measure);
    margin-bottom: var(--ledio-space-xl);
    color: var(--ledio-text-muted);
}

.ledio-auth__panel--centered .ledio-auth__lead {
    margin-inline: auto;
}

.ledio-auth__aside {
    margin-top: var(--ledio-space-lg);
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
}

.ledio-auth__aside a {
    color: var(--ledio-primary-text);
    font-weight: 600;
}

.ledio-auth__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ledio-space-sm);
    justify-content: center;
    margin-top: var(--ledio-space-xl);
}

/*
 * Failure, stated once at the top of the form. Red on a tinted plate rather
 * than red text alone: colour is never the only carrier, the wording is.
 */
.ledio-auth__error {
    margin-bottom: var(--ledio-space-lg);
    padding: var(--ledio-space-sm) var(--ledio-space-md);
    border: 1px solid rgba(217, 45, 32, 0.28);
    border-radius: var(--ledio-radius-sm);
    background-color: rgba(217, 45, 32, 0.08);
    color: #912018;
    font-size: var(--ledio-font-small);
}

/* -- Fields ------------------------------------------------- */

.ledio-form .form-label {
    margin-bottom: var(--ledio-space-2xs);
    color: var(--ledio-text);
    font-size: var(--ledio-font-small);
    font-weight: 600;
}

.ledio-form .form-control,
.ledio-form .form-select {
    min-height: 46px;
    border: 1px solid var(--ledio-border-strong);
    border-radius: var(--ledio-radius-sm);
    background-color: var(--ledio-white);
    color: var(--ledio-text);
    font-size: var(--ledio-font-body);
}

.ledio-form .form-control:focus,
.ledio-form .form-select:focus {
    border-color: var(--ledio-primary);
    box-shadow: 0 0 0 3px var(--ledio-primary-soft);
}

.ledio-form .form-text {
    margin-top: var(--ledio-space-2xs);
    color: var(--ledio-text-muted);
    font-size: 0.8125rem;
}

.ledio-form .invalid-feedback {
    font-size: 0.8125rem;
}

/* Bootstrap only reveals .invalid-feedback next to an .is-invalid control, and
   Symfony's theme prints form_errors() without one — so it is shown outright. */
.ledio-form .invalid-feedback {
    display: block;
}

.ledio-form .form-check-input:checked {
    background-color: var(--ledio-primary);
    border-color: var(--ledio-primary);
}

.ledio-form .form-check-label {
    color: var(--ledio-text);
    font-size: var(--ledio-font-small);
}

/* -- Blocks and rhythm -------------------------------------- */

/*
 * Sections of a long form.
 *
 * White space alone was not enough to orient anybody: five blocks of paired
 * fields all looked like one run. Each section now opens on a hairline rule, so
 * the boundary is visible at a glance without turning the form into five
 * separate cards — it stays one card, which is what makes it read as one task.
 *
 * The first block has no rule: there is nothing above it to be separated from.
 */
.ledio-form__block {
    margin: 0 0 var(--ledio-space-xl);
    padding: 0;
    border: 0;
}

.ledio-form__block+.ledio-form__block {
    margin-top: var(--ledio-space-xl);
    padding-top: var(--ledio-space-xl);
    border-top: 1px solid var(--ledio-border);
}

.ledio-form__block--last {
    margin-bottom: var(--ledio-space-lg);
}

.ledio-form__legend {
    /* A legend, so it is announced with the fieldset — not a heading, which
       would compete with the page's h1 in the outline. */
    float: none;
    width: auto;
    margin-bottom: var(--ledio-space-lg);
    padding: 0;
    color: var(--ledio-text);
    font-size: var(--ledio-font-body-lg);
    font-weight: 700;
    letter-spacing: -0.01em;
}

.ledio-form__legend-note {
    margin-left: var(--ledio-space-xs);
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
    font-weight: 500;
}

/*
 * A disabled company block RECEDES; it never disappears. Hiding it would change
 * the form's height on a radio click and make everything below jump — the one
 * thing customer_type_controller.js exists to prevent.
 */
.ledio-form__block.is-muted {
    opacity: 0.55;
}

.ledio-form__row {
    margin-bottom: var(--ledio-space-md);
}

/* Two fields per row where they belong together (name/surname, city/postcode),
   collapsing to one column on a phone. */
.ledio-form__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0 var(--ledio-space-md);
}

@media (min-width: 640px) {
    .ledio-form__grid {
        grid-template-columns: 1fr 1fr;
    }
}

.ledio-form__note {
    margin-bottom: var(--ledio-space-md);
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
}

.ledio-form__note a {
    color: var(--ledio-primary-text);
    font-weight: 600;
}

.ledio-form__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ledio-space-md);
    padding-top: var(--ledio-space-lg);
    border-top: 1px solid var(--ledio-border);
}

/*
 * The IČO field and its "Načítať údaje" button share one row, and the button
 * has to read as attached to the field: a borderless ghost button next to an
 * outlined input looks like a stray link, not the other half of the control.
 */
.ledio-form__lookup .ledio-btn {
    border: 1px solid var(--ledio-border-strong);
    border-left: 0;
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    background-color: var(--ledio-surface-muted);
    color: var(--ledio-text);
    font-size: var(--ledio-font-small);
    white-space: nowrap;
}

.ledio-form__lookup .ledio-btn:hover {
    background-color: var(--ledio-border);
    color: var(--ledio-text);
}

.ledio-form__lookup .form-control {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

/* -- Segmented customer-type control ------------------------ */

.ledio-segmented {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ledio-space-xs);
}

.ledio-segmented__option {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 46px;
    padding-inline: var(--ledio-space-lg);
    border: 1px solid var(--ledio-border-strong);
    border-radius: var(--ledio-radius-sm);
    background-color: var(--ledio-white);
    color: var(--ledio-text);
    font-weight: 600;
    cursor: pointer;
    transition: border-color var(--ledio-transition), background-color var(--ledio-transition);
}

.btn-check:checked+.ledio-segmented__option {
    border-color: var(--ledio-primary);
    background-color: var(--ledio-primary-soft);
    color: var(--ledio-primary-text);
}

/* Keyboard focus must be visible on the LABEL: the radio itself is off-screen. */
.btn-check:focus-visible+.ledio-segmented__option {
    outline: 2px solid var(--ledio-primary);
    outline-offset: 2px;
}

/*
 * Both hints occupy the same grid cell, so the block is always as tall as the
 * taller one and switching type moves nothing.
 */
.ledio-segmented__hints {
    display: grid;
    margin-top: var(--ledio-space-sm);
}

.ledio-segmented__hint {
    grid-area: 1 / 1;
    margin: 0;
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
    visibility: hidden;
}

.ledio-segmented__hint.is-active {
    visibility: visible;
}

/* -- Approval notice ---------------------------------------- */

/*
 * Sits between the header and <main> on every page, for a customer the shop has
 * not approved yet. Amber, not red: nothing is wrong, something is pending.
 */
.ledio-account-notice {
    background-color: #fff8e6;
    border-bottom: 1px solid #f4d58a;
    color: #7a4b00;
}

.ledio-account-notice__inner {
    display: flex;
    align-items: center;
    gap: var(--ledio-space-sm);
    padding-block: var(--ledio-space-sm);
    font-size: var(--ledio-font-small);
}

/* -- Header account state ----------------------------------- */

/* The signed-in name is a label, not a control: no hover affordance, no cursor
   change, and it keeps the icon button's metrics so the row does not reflow. */
.ledio-icon-btn--static {
    cursor: default;
}

.ledio-icon-btn--static:hover {
    background-color: transparent;
}

.ledio-offcanvas__account {
    color: var(--ledio-text-on-dark-muted);
    font-size: var(--ledio-font-small);
}

/* -- Toasts ------------------------------------------------- */

/*
 * The company lookup runs on this form too, and its outcomes are toasts fired
 * by the shared helper (assets/toast.js). It sets `app-toast`; the
 * administration themes the same class under its own body, so neither theme
 * reaches the other's pages.
 */
.ledio-body .swal2-popup.app-toast {
    font-family: var(--ledio-font);
    border-radius: var(--ledio-radius-md);
    box-shadow: var(--ledio-shadow-lift);
    color: var(--ledio-text);
}

.ledio-body .swal2-popup.app-toast .swal2-title {
    font-size: var(--ledio-font-small);
    font-weight: 500;
    color: var(--ledio-text);
}

/* -- Registration intro steps ------------------------------- */

/*
 * Three plain sentences above the form. A list, not a paragraph: somebody
 * deciding whether to start filling this in reads three lines, not a block.
 */
.ledio-auth__steps {
    margin: 0 0 var(--ledio-space-xl);
    padding-left: var(--ledio-space-lg);
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
}

.ledio-auth__steps li+li {
    margin-top: var(--ledio-space-2xs);
}

/* -- Consent checkboxes ------------------------------------- */

/*
 * The terms link lives inside the label, so it must stay visibly a link when
 * the label is not — and stay clickable without toggling the box.
 */
.ledio-form .form-check-label a {
    color: var(--ledio-primary-text);
    font-weight: 600;
}

/* -- Legal pages -------------------------------------------- */

.ledio-legal {
    padding-block: var(--ledio-space-2xl) var(--ledio-space-3xl);
}

/*
 * The panel has NO width of its own. It used to carry `width: min(100%, 760px)`
 * and centre itself; the column it sits in does both now
 * (`col-12 col-lg-9 col-xl-8` in frontend/legal/show.html.twig), which is the
 * same grid the rest of the storefront uses and one less private breakpoint to
 * keep in step with it.
 */
.ledio-legal__panel {
    padding: clamp(var(--ledio-space-lg), 4vw, var(--ledio-space-2xl));
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-surface);
    box-shadow: var(--ledio-shadow-soft);

    /*
     * The backstop for text that cannot be wrapped at a space, because there
     * is no space to wrap it at: a pasted URL, an IBAN, a 40-character
     * reference number. `max-width` does not help — a box may be narrow and
     * still have a word painted straight out of it, and out of the page, which
     * gives the WHOLE document a horizontal scrollbar.
     *
     * Inherited, so it reaches the document body and the provisional text
     * alike. It is the second line of defence, not the first: the paste that
     * actually broke this page made every space non-breaking, and that is
     * repaired in App\Frontend\Legal\LegalHtmlSanitizer, where a paragraph can
     * still be wrapped BETWEEN ITS WORDS. Breaking mid-word is what this rule
     * does, and it is the right answer only for something that has no words.
     */
    overflow-wrap: break-word;
}

.ledio-legal__title {
    margin: var(--ledio-space-2xs) 0 var(--ledio-space-lg);
    font-size: var(--ledio-font-h3);
}

.ledio-legal__panel p {
    max-width: var(--ledio-measure);
    color: var(--ledio-text-muted);
}

.ledio-legal__panel a {
    color: var(--ledio-primary-text);
    font-weight: 600;
}

/*
 * The document body — administrator-written HTML, or the provisional text,
 * which is written to look exactly like it.
 *
 * Every element the sanitizer allows is styled here, because whichever one is
 * NOT styled is the one an administrator will reach for and then find rendering
 * as browser defaults in the middle of the page. The scale is deliberately flat
 * for a reason a legal text makes obvious: the page's own <h1> is the document's
 * name, so the headings inside it start one step below and stay close together
 * — six visibly different sizes would turn a contract into a poster.
 */
.ledio-legal__content h1,
.ledio-legal__content h2 {
    margin: var(--ledio-space-xl) 0 var(--ledio-space-xs);
    font-size: var(--ledio-font-body-lg);
}

.ledio-legal__content h3,
.ledio-legal__content h4,
.ledio-legal__content h5,
.ledio-legal__content h6 {
    margin: var(--ledio-space-lg) 0 var(--ledio-space-2xs);
    font-size: var(--ledio-font-body);
}

/* The deeper levels earn their distinction from weight and colour, not size. */
.ledio-legal__content h5,
.ledio-legal__content h6 {
    color: var(--ledio-text-muted);
}

.ledio-legal__content ul,
.ledio-legal__content ol {
    max-width: var(--ledio-measure);
    margin: 0 0 var(--ledio-space-md);
    padding-left: var(--ledio-space-lg);
    color: var(--ledio-text-muted);
}

.ledio-legal__content li+li {
    margin-top: var(--ledio-space-2xs);
}

/* Amber, like the approval notice: nothing is wrong, something is provisional. */
.ledio-legal__draft {
    padding: var(--ledio-space-sm) var(--ledio-space-md);
    border: 1px solid #f4d58a;
    border-radius: var(--ledio-radius-sm);
    background-color: #fff8e6;
    color: #7a4b00;
    font-size: var(--ledio-font-small);
}

/* ============================================================
   Storefront form theme (templates/frontend/form/_theme.html.twig)
   ============================================================ */

/*
 * One vertical rhythm for every field: label, control, error, help — always the
 * same distances, so a form of twenty fields reads as one thing rather than
 * twenty. The theme guarantees the STRUCTURE; this guarantees the spacing.
 */

.ledio-field {
    margin-bottom: var(--ledio-space-md);
}

.ledio-field__label {
    display: block;
    margin-bottom: var(--ledio-space-2xs);
    color: var(--ledio-text);
    font-size: var(--ledio-font-small);
    font-weight: 600;
}

/*
 * Errors and help share one metric, so a field that gains an error does not
 * push the rest of the form down by a different amount than the next one.
 */
.ledio-field__help,
.ledio-field__errors {
    margin: var(--ledio-space-2xs) 0 0;
    font-size: 0.8125rem;
    line-height: 1.45;
}

.ledio-field__help {
    color: var(--ledio-text-muted);
}

.ledio-field__errors {
    padding-left: 0;
    list-style: none;
    color: #b42318;
    font-weight: 600;
}

/*
 * Never colour alone: the message is the carrier, and the control it belongs to
 * is marked on its own border as well.
 */
.ledio-field--invalid .form-control,
.ledio-field--invalid .form-select,
.ledio-field--invalid .iti,
/*
 * The IČO group, whose border belongs to the group rather than to the input
 * inside it — without this line the one field on the opening screen is the one
 * field that cannot show it was refused.
 */
.ledio-field--invalid .ledio-lookup {
    border-color: #d92d20;
}

/* -- Phone: the composite that has to look like one control -- */

/*
 * intl-tel-input wraps the input in .iti and puts the country button INSIDE it.
 * Left alone the wrapper is an inline-block that shrinks to its content — which
 * is why the field rendered at 79px, a fraction of every other control, and read
 * as though its label were sitting beside it.
 *
 * So the border, radius and focus ring move OFF the input and onto the wrapper,
 * and the input inside goes transparent. The country button, the dial code and
 * the number then sit inside one box that matches every other field exactly.
 */
.ledio-form .iti {
    display: block;
    width: 100%;
    min-height: 46px;
    border: 1px solid var(--ledio-border-strong);
    border-radius: var(--ledio-radius-sm);
    background-color: var(--ledio-white);
    transition: border-color var(--ledio-transition), box-shadow var(--ledio-transition);
}

.ledio-form .iti input[type="tel"] {
    width: 100%;
    min-height: 44px;
    border: 0;
    border-radius: var(--ledio-radius-sm);
    background: transparent;
    box-shadow: none;
}

.ledio-form .iti input[type="tel"]:focus {
    border: 0;
    box-shadow: none;
}

/*
 * focus-within, because the focus can land on the country button or on the
 * number and either way it is THIS control that has it. Highlighting only the
 * input would leave the country button looking unfocused while it is.
 */
.ledio-form .iti:focus-within {
    border-color: var(--ledio-primary);
    box-shadow: 0 0 0 3px var(--ledio-primary-soft);
}

/* The library's own button must not carry a second background or radius. */
.ledio-form .iti .iti__selected-country {
    border-radius: var(--ledio-radius-sm) 0 0 var(--ledio-radius-sm);
    background: transparent;
}

.ledio-form .iti .iti__selected-country:focus-visible {
    outline: 2px solid var(--ledio-primary);
    outline-offset: -2px;
}

.ledio-form .iti .iti__dropdown-content {
    border-radius: var(--ledio-radius-sm);
    font-size: var(--ledio-font-small);
}

.ledio-form .iti .iti__country-name {
    white-space: nowrap;
}

/* -- IČO and its lookup button -------------------------------- */

/*
 * ONE CONTROL, not two things on a row.
 *
 * They were a two-column grid with a gap: the button read as a stray secondary
 * action parked next to a field, and the pair had two borders, two radii and two
 * focus rings between them. The IČO and "look this company up" are one gesture,
 * so they are one bordered box.
 *
 * The border, the radius and the focus ring belong to THIS element; the input
 * and the button inside give theirs up (see below). `overflow: hidden` is what
 * makes the button's corners follow the box's radius without restating it, and
 * what stops a hover background bleeding past the outline.
 */
.ledio-lookup {
    display: flex;
    align-items: stretch;
    border: 1px solid var(--ledio-border-strong);
    border-radius: var(--ledio-radius-sm);
    background-color: var(--ledio-white);
    overflow: hidden;
}

/*
 * The focus ring is drawn around the GROUP, from the group, whichever half has
 * the focus — so tabbing from the input to the button moves the caret without
 * the outline jumping from one box to another.
 *
 * box-shadow rather than outline, and the border only changes colour: both are
 * drawn outside the layout, so nothing inside moves, resizes or reflows when the
 * focus lands. The button keeps a mark of its own further down, because "the
 * group has focus" does not say WHICH half of it does.
 */
.ledio-lookup:focus-within {
    border-color: var(--ledio-primary);
    box-shadow: 0 0 0 3px var(--ledio-primary-soft);
}

/*
 * On a wide screen the pair does not need the panel's full width: eight digits
 * and one button are not a full-width task, and left at 100% the input looked
 * like it expected an essay. Half the row, matching the paired fields under it.
 */
.ledio-lookup__field {
    margin-bottom: var(--ledio-space-md);
}

@media (min-width: 640px) {
    .ledio-lookup__field {
        /* The exact width of one column of .ledio-form__grid: half the row less
           half the 16px gutter, so the IČO group lines up with the DIČ field
           directly beneath it. */
        max-width: calc(50% - (var(--ledio-space-md) / 2));
    }
}

/*
 * The input gives up its own border, radius and ring — the group has them. It
 * keeps every other .form-control property, so it is still the same field as
 * every other one on the page.
 */
.ledio-form .ledio-lookup__input,
.ledio-form .ledio-lookup__input:focus {
    flex: 1 1 auto;
    /* Without this a flex item refuses to shrink below its content width, and
       the button gets pushed out of the box on a narrow screen. */
    min-width: 0;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background-color: transparent;
}

/*
 * AND ITS OUTLINE, which is the third thing that draws a ring and the one that
 * was missed.
 *
 * `.ledio-body :focus-visible` gives every focusable element a 3px solid
 * turquoise outline. A text input always matches :focus-visible, so the IČO
 * field got one — and an outline is painted OUTSIDE the border box, which here
 * is the seam between the two halves. `overflow: hidden` on the group clips it
 * on three sides, so the only place it could land was underneath the button, and
 * the button's opaque white plate hid it. Until the pointer arrived: hover turns
 * that plate translucent, the ring underneath showed through, and the seam
 * became a 3px turquoise bar in one state and one state only — caret in the
 * field AND pointer on the button.
 *
 * Suppressed rather than recoloured because in this layout it is invisible by
 * construction: clipped on three sides, covered on the fourth. It contributes
 * nothing but that bug. What the visitor actually sees is the ring
 * `.ledio-lookup:focus-within` draws around the whole group — which is the point
 * of the group — and that is not touched.
 *
 * SCOPED TO THE ROW LAYOUT. Below 440px the group stops being a box, the input
 * takes its own border back, and its outline is neither clipped nor covered: it
 * is the same focus ring every other field on the page has, and it stays. Keep
 * this breakpoint and the one further down in step.
 */
@media (min-width: 440px) {
    .ledio-form .ledio-lookup__input:focus-visible {
        outline: none;
    }
}

/*
 * PART OF THE CONTROL, not a call to action of its own.
 *
 * It was filled with the storefront's turquoise, on the reasoning that it is the
 * only thing to do on the opening screen. But the registration has exactly one
 * call to action — "Odoslať registráciu" — and a second block of brand colour
 * competed with it the moment the form opened. So the plate is white like the
 * input beside it, the text is the form's own dark ink, and the turquoise is
 * reduced to the magnifier: enough to say "this does something", not enough to
 * be mistaken for the thing the page is for.
 *
 * It is deliberately NOT built on .ledio-btn. That class brings its own radius,
 * border and vertical padding, all three of which have to be undone inside a
 * group whose corners and height are the box's — which is how it once ended up
 * six pixels taller than the field it stood beside.
 */
.ledio-lookup__button {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* The icon and the words are one label, and they centre together. */
    gap: var(--ledio-space-xs);
    /*
     * Wide enough for the longest of the three labels it carries — "Načítať
     * údaje", "Načítavam…", "Načítať znova". Without it the button resized twice
     * per lookup and the input jumped to fill the difference, which on a control
     * this small reads as the page glitching.
     */
    min-width: 10.5rem;
    /* No vertical padding and no height: `align-items: stretch` on the group
       makes the button exactly as tall as the box, whatever the input's height
       turns out to be. One less number to keep in two places. */
    /* The divider is a pseudo-element (below), which needs something to be
       positioned against. */
    position: relative;
    padding: 0 var(--ledio-space-md);
    border: 0;
    border-radius: 0;
    background-color: var(--ledio-white);
    color: var(--ledio-text);
    font-family: inherit;
    font-size: var(--ledio-font-small);
    /* 600, not 700: it is the secondary action on the screen and reads as one. */
    font-weight: 600;
    line-height: 1.2;
    /* Stated rather than inherited: a <button> is not a link, and nothing about
       this may ever render underlined. */
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color var(--ledio-transition), color var(--ledio-transition);
}

/*
 * The seam between the two halves — a hairline, not a rule.
 *
 * It was a full-height 1px border in --ledio-border-strong, the same weight as
 * the box's own outline, which cut the control in two and made a plain field
 * look like a piece of machinery. Drawn as a pseudo-element instead: the lighter
 * --ledio-border, and short of the full height, so it reads as a seam between
 * two parts of one thing rather than as a wall between two things.
 */
.ledio-lookup__button::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 1px;
    height: 56%;
    background-color: var(--ledio-border);
}

/*
 * The whole of the turquoise. --ledio-primary-text rather than --ledio-primary:
 * the accent sits on white, where the brand cyan reaches only 3.65:1.
 */
.ledio-lookup__button-icon {
    display: inline-flex;
    color: var(--ledio-primary-text);
}

/*
 * Hover is a wash, not a fill: the plate tints, the words and the glyph take the
 * accent. Nothing about the box changes size, so the row does not move under a
 * pointer crossing it.
 */
.ledio-lookup__button:hover,
.ledio-lookup__button:focus {
    background-color: var(--ledio-primary-soft);
    color: var(--ledio-primary-text);
    text-decoration: none;
}

.ledio-lookup__button:hover .ledio-lookup__button-icon,
.ledio-lookup__button:focus .ledio-lookup__button-icon {
    color: var(--ledio-primary-text);
}

/* Pressed: the same wash, further along, so the click is felt as well as seen. */
.ledio-lookup__button:active {
    background-color: rgba(0, 174, 235, 0.22);
}

/*
 * Which half has the focus. Inset, so it is drawn inside the group's own ring
 * rather than beside it, and so it changes nothing about the box's size.
 */
.ledio-lookup__button:focus-visible {
    outline: 2px solid var(--ledio-primary);
    outline-offset: -4px;
}

/*
 * The lookup is in flight. `aria-busy` is set on the form by the existing
 * company-lookup controller and the button is disabled by it too, so the state
 * is read from the behaviour rather than duplicated in a second place.
 *
 * There is no ellipsis bolted on here any more: the controller says
 * "Načítavam…" in the label itself, which is a word rather than a punctuation
 * mark somebody has to interpret — and, unlike CSS content, one a screen reader
 * reads.
 */
.ledio-form[aria-busy="true"] .ledio-lookup__button {
    cursor: progress;
}

.ledio-lookup__button:disabled {
    opacity: 0.75;
    cursor: not-allowed;
}

/*
 * Narrow screens: the button drops below the input at full width.
 *
 * The threshold moved down with the label. "Načítať firemné údaje" needed the
 * group to break up below 560px; "Načítať údaje" is short enough that the pair
 * still fits on one row at 440, leaving the input a comfortable 180 or so. Below
 * that the group stops being a box: the input takes its own border and radius
 * back, and the button becomes a full-width target under it. A thumb gets the
 * whole row, and neither half is squeezed.
 */
@media (max-width: 439px) {
    .ledio-lookup {
        display: block;
        border: 0;
        border-radius: 0;
        background: none;
        overflow: visible;
    }

    .ledio-lookup:focus-within {
        border-color: transparent;
        box-shadow: none;
    }

    .ledio-form .ledio-lookup__input {
        width: 100%;
        border: 1px solid var(--ledio-border-strong);
        border-radius: var(--ledio-radius-sm);
        background-color: var(--ledio-white);
    }

    .ledio-form .ledio-lookup__input:focus {
        border-color: var(--ledio-primary);
        box-shadow: 0 0 0 3px var(--ledio-primary-soft);
    }

    /*
     * Stacked, the border is the input's again, so the refusal has to be marked
     * there. Specific enough to beat the rule above it, which is the whole
     * reason this line exists rather than being left to .ledio-field--invalid.
     */
    .ledio-form .ledio-field--invalid .ledio-lookup__input {
        border-color: #d92d20;
    }

    .ledio-lookup__button {
        width: 100%;
        margin-top: var(--ledio-space-sm);
        /*
         * No longer inside a box, so it needs its own shape and its own height —
         * and its own border. A white plate with no outline read as a line of
         * text with an icon in front of it rather than as something to press.
         */
        min-height: 46px;
        border: 1px solid var(--ledio-border-strong);
        border-radius: var(--ledio-radius-sm);
    }

    /* Stacked, the two halves are already separate boxes; the seam would be a
       stray line down the inside of the button's own left edge. */
    .ledio-lookup__button::before {
        display: none;
    }

    .ledio-lookup__button:focus-visible {
        outline-offset: -4px;
    }
}

/* -- Password ------------------------------------------------- */

/*
 * ONE EYE PER BOX, inside the field it belongs to.
 *
 * A single "Zobraziť heslá" link under both boxes belonged to neither — and the
 * boxes are checked one at a time, because you look at the one you have just
 * mistyped. The wrapper exists to position the button against its own input.
 */
.ledio-password {
    position: relative;
}

/* Room for the icon, so a long password does not run underneath it. */
.ledio-form .ledio-password__input {
    padding-right: 48px;
}

/*
 * Anchored from the TOP of the wrapper, not the bottom: an error message under
 * the field makes the row taller, and a button positioned from the bottom would
 * ride down with it and end up beside the error instead of in the input.
 *
 * WHICH MEANS THE OFFSET HAS TO BE THE LABEL'S REAL HEIGHT. It was a rounded
 * 1.35rem and the eye sat five pixels above the middle of the field in both
 * boxes. It is spelled out from the tokens that actually produce that height
 * instead — the label's own font size at the body's line height, plus its
 * margin, plus the input's border — so it cannot drift again when one of them
 * is retuned.
 *
 * The height is the input's INNER height (46px less two borders), so the button
 * fills the field exactly and its icon is centred by construction rather than
 * by a second number that has to agree with the first.
 */
.ledio-password__reveal {
    position: absolute;
    top: calc(var(--ledio-font-small) * 1.6 + var(--ledio-space-2xs) + 1px);
    right: 3px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* 40 x 44 — comfortably past the 24px minimum for a target this size, and
       inset far enough that the text stops five pixels clear of the glyph. */
    width: 40px;
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: var(--ledio-radius-xs);
    background: none;
    color: var(--ledio-text-muted);
    cursor: pointer;
}

.ledio-password__reveal:hover {
    color: var(--ledio-text);
}

.ledio-form__reveal:focus-visible {
    outline: 2px solid var(--ledio-primary);
    outline-offset: -2px;
    border-radius: var(--ledio-radius-xs);
}

/*
 * The icon follows the state the controller already publishes on the button —
 * `is-visible`, the same class it has always set. No second source of truth, and
 * no JavaScript that knows what an eye looks like.
 *
 * The icon is decorative: aria-label and aria-pressed on the button say what it
 * does and whether it is on, so nothing here carries meaning on its own.
 */
.ledio-password__eye {
    display: inline-flex;
}

.ledio-password__eye--off,
.ledio-password__reveal.is-visible .ledio-password__eye--on {
    display: none;
}

.ledio-password__reveal.is-visible .ledio-password__eye--off {
    display: inline-flex;
}

/* -- Consent checkboxes --------------------------------------- */

/*
 * The whole label is the target. These are the two smallest controls on the
 * page and the last two somebody taps on a phone, so the row is padded to a
 * comfortable hit area rather than left at the size of the box itself.
 */
.ledio-check {
    margin-bottom: var(--ledio-space-sm);
}

.ledio-check__label {
    display: flex;
    align-items: flex-start;
    gap: var(--ledio-space-sm);
    padding: var(--ledio-space-sm);
    margin-left: calc(-1 * var(--ledio-space-sm));
    border-radius: var(--ledio-radius-sm);
    cursor: pointer;
    transition: background-color var(--ledio-transition);
}

.ledio-check__label:hover {
    background-color: var(--ledio-surface-muted);
}

.ledio-check__box {
    flex: 0 0 auto;
    /* Bigger than Bootstrap's default: this one is a legal act. */
    width: 22px;
    height: 22px;
    margin: 0;
    accent-color: var(--ledio-primary);
    cursor: pointer;
}

/*
 * A consent's own note — how often the e-mails come, how to stop them.
 *
 * It sits OUTSIDE the label (the theme renders it after, so tapping it does not
 * tick the box), which left it starting at the block's edge while the words it
 * explains started 22px + a gap further in. It read as a footnote to the whole
 * section rather than to the box above it. Indented to line up with that box's
 * text: 22px of checkbox, the label's gap, and the padding the label pulls
 * itself left by.
 */
.ledio-check .ledio-field__help {
    margin-top: calc(-1 * var(--ledio-space-xs));
    padding-left: calc(22px + var(--ledio-space-sm));
}

.ledio-check__text {
    font-size: var(--ledio-font-small);
    line-height: 1.5;
    color: var(--ledio-text);
}

/* The focus ring belongs on the visible row, not on the 22px box alone. */
.ledio-check__label:has(.ledio-check__box:focus-visible) {
    outline: 2px solid var(--ledio-primary);
    outline-offset: 0;
}

/*
 * The link is distinguished by weight and colour, and underlined only on hover
 * and focus — underlining it permanently inside a sentence turns the consent
 * into a wall of rules.
 *
 * IT WRAPS. It used to carry white-space: nowrap, back when the only link in a
 * consent was the two words "obchodnými podmienkami". The required consent now
 * names a document called "Informáciou o podmienkach spracúvania osobných
 * údajov" — forty-eight characters, wider than a 375px screen — and nowrap would
 * push it straight through the side of the card.
 *
 * 600 rather than 700 for the same reason: at the length these run to, bold
 * turns half the sentence into links shouting over the consent itself. It is
 * still clearly a link, by colour and by weight, and unmistakably one on hover.
 */
.ledio-check__link {
    color: var(--ledio-primary-text);
    font-weight: 600;
    text-decoration: none;
}

/*
 * Underlined on hover AND on keyboard focus — the ring that
 * `.ledio-body :focus-visible` puts around it is the primary signal, and the
 * underline is what makes it read as a link rather than as a highlighted word.
 * No focus rule of its own: the global 3px ring is stronger than anything worth
 * writing here, and the label's `:has(.ledio-check__box:focus-visible)` styling
 * keys on the BOX, so it cannot collide with a link inside it.
 */
.ledio-check__link:hover,
.ledio-check__link:focus-visible {
    text-decoration: underline;
}

.ledio-check--invalid .ledio-check__label {
    background-color: rgba(217, 45, 32, 0.06);
}

/* -- Submit --------------------------------------------------- */

.ledio-form__submit[aria-disabled="true"],
.ledio-form__submit:disabled {
    opacity: 0.65;
    cursor: progress;
}

@media (max-width: 479px) {

    /* Full width where the screen is narrow enough that anything else looks lost. */
    .ledio-form__submit {
        width: 100%;
    }

    .ledio-form__actions {
        align-items: stretch;
        text-align: center;
    }
}

/* ============================================================
   Registration: progressive disclosure
   (assets/controllers/registration_reveal_controller.js)
   ============================================================ */

/*
 * Nothing here HIDES anything. The rest of the form is hidden by the `hidden`
 * attribute, set in JavaScript, and a stylesheet that hid it too would take the
 * form away from every browser that cannot get it back.
 *
 * What is here is the seam: the notice that says how the lookup went, and the
 * short movement that makes the appearance of twelve fields read as an opening
 * rather than a page jumping under somebody's thumb.
 */

/*
 * Text for screen readers only.
 *
 * Bootstrap has .visually-hidden, but it arrives with bootstrap.min.css, which
 * this application imports from app.js — i.e. only once JavaScript has run. The
 * words this class hides ("Splnené", "Zatiaľ nesplnené") are written by
 * JavaScript anyway, but the class is used in server-rendered markup, and a
 * utility that is only sometimes loaded is a utility that sometimes dumps its
 * contents into the middle of the page.
 */
.ledio-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/*
 * The blocks inside the revealed section keep the hairline rule that separates
 * them from what came before. `.ledio-form__block + .ledio-form__block` cannot
 * see through the wrapper, and without this the seam between the IČO block and
 * the company details is the only one in the form with no line on it.
 */
.ledio-form__details>.ledio-form__block:first-child {
    margin-top: var(--ledio-space-xl);
    padding-top: var(--ledio-space-xl);
    border-top: 1px solid var(--ledio-border);
}

/*
 * The other `details` — the one INSIDE the company section, holding what the
 * lookup fills. It is a continuation of the block it sits in, not a block of its
 * own, so it takes no rule and no heading; the only thing it needs is a little
 * air between the notice above it and the first field it reveals.
 */
.ledio-form__details--inline {
    margin-top: var(--ledio-space-lg);
}

/* -- How the lookup went -------------------------------------- */

/*
 * One plate, four states, told by the words first: the message is a whole
 * sentence, and the colour and the mark beside it only agree with what it
 * already says. Amber for a failure rather than red — nothing is broken and
 * nothing the visitor did is wrong, the register simply did not answer.
 */
.ledio-notice {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ledio-space-sm);
    margin-bottom: var(--ledio-space-md);
    padding: var(--ledio-space-sm) var(--ledio-space-md);
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-sm);
    background-color: var(--ledio-surface-muted);
    font-size: var(--ledio-font-small);
}

/*
 * NO FOCUS RING, and that is deliberate.
 *
 * The message is focused programmatically when the form opens, so that a screen
 * reader and the keyboard both land where the visitor now has to look. It is not
 * a tab stop and it is not interactive, and the blue outline that came with the
 * focus made a piece of good news look like an active control — the loudest
 * thing on a form it has no business dominating.
 *
 * :focus-visible is left alone rather than suppressed too: it cannot fire from
 * tabbing (tabindex is -1) and would only ever appear if this element genuinely
 * became keyboard-reachable, which is exactly when a ring should come back.
 */
.ledio-notice:focus {
    outline: none;
}

.ledio-notice__message {
    margin: 0;
    color: var(--ledio-text);
}

.ledio-notice__message::before {
    /* Decoration that agrees with the sentence; the sentence is the message. */
    margin-right: var(--ledio-space-xs);
    font-weight: 700;
}

.ledio-notice[data-state="loading"] .ledio-notice__message::before {
    content: "⋯";
}

.ledio-notice[data-state="success"] {
    border-color: rgba(20, 130, 74, 0.28);
    background-color: rgba(20, 130, 74, 0.08);
}

.ledio-notice[data-state="success"] .ledio-notice__message::before {
    content: "✓";
    color: #14824a;
}

.ledio-notice[data-state="error"] {
    border-color: #f4d58a;
    background-color: #fff8e6;
}

.ledio-notice[data-state="error"] .ledio-notice__message::before {
    content: "!";
    color: #7a4b00;
}

.ledio-notice__action {
    /* Never the page's dominant action: the submit is. */
    margin-left: auto;
    white-space: nowrap;
}

@media (max-width: 639px) {
    .ledio-notice__action {
        margin-left: 0;
        width: 100%;
    }
}

/* -- The opening ---------------------------------------------- */

/*
 * Short, and only ever on the way in. The form works identically without it —
 * `hidden` is what actually opens the section, this only softens the moment.
 */
@media (prefers-reduced-motion: no-preference) {
    .ledio-form__details.is-revealing {
        animation: ledio-reveal 200ms cubic-bezier(0.2, 0, 0.2, 1) both;
    }
}

@keyframes ledio-reveal {
    from {
        opacity: 0;
        transform: translateY(-6px);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

/* -- Values the register filled in ---------------------------- */

/*
 * THERE IS NO STYLE HERE, and its absence is the decision.
 *
 * A filled field carries `data-autofilled` (company_lookup_controller.js sets
 * it, and drops it the moment the visitor types) and the attribute is worth
 * keeping — but it was being drawn as a pale blue plate, and a pale plate on a
 * form is what a disabled field looks like. These fields are fully editable:
 * the lookup writes only where nothing has been typed, and the visitor may
 * correct any of it. Tinting eleven of them at once said the opposite about all
 * eleven.
 *
 * So they look like every other field, and what happened is said once, in
 * words, by .ledio-notice: "Firemné údaje sme načítali. Skontrolujte ich…".
 * One sentence beats eleven plates.
 *
 * If a rule ever comes back here it must not use opacity, a muted colour, or
 * anything else that reads as "you cannot change this" — that is what
 * RegistrationRevealControllerTest guards.
 */

/* -- Password rules ------------------------------------------- */

/*
 * The four rules, ticked off while they are typed. Presentation only: the
 * policy is RegistrationType::passwordConstraints() and the server is what
 * refuses a password.
 */
.ledio-rules {
    margin: 0 0 var(--ledio-space-md);
    padding: 0;
    list-style: none;
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--ledio-space-2xs) var(--ledio-space-md);
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
}

@media (min-width: 640px) {
    .ledio-rules {
        grid-template-columns: 1fr 1fr;
    }
}

.ledio-rules__item {
    display: flex;
    align-items: baseline;
    gap: var(--ledio-space-xs);
}

/*
 * The mark is a SHAPE, not a colour: an outlined circle for a rule not yet met
 * and a tick for one that is. Somebody who cannot tell the grey from the green
 * still sees two different characters — and the word beside them, hidden from
 * the page but read aloud, says which is which.
 */
.ledio-rules__mark::before {
    content: "○";
    font-weight: 700;
}

.ledio-rules__item[data-state="met"] {
    color: #14824a;
}

.ledio-rules__item[data-state="met"] .ledio-rules__mark::before {
    content: "✓";
}

/*
 * An unmet rule is stated, never accused: the same grey as the neutral state,
 * because nothing has gone wrong until the form is submitted — and when it is,
 * the server says so on the field itself.
 */
.ledio-rules__item[data-state="unmet"] {
    color: var(--ledio-text-muted);
}

.ledio-rules__match {
    grid-column: 1 / -1;
    margin: 0 0 var(--ledio-space-md);
    font-size: var(--ledio-font-small);
}

.ledio-rules__match:empty {
    /* No box, no gap, no reserved space until there is something to say. */
    display: none;
}

.ledio-rules__match[data-state="met"] {
    color: #14824a;
}

.ledio-rules__match[data-state="unmet"] {
    color: #912018;
}

/*
 * The same three-line list on the centred confirmation panel. `list-style-
 * position: inside` so the numbers sit with their text instead of hanging in
 * the left margin of a centred column, and the whole block is capped and
 * centred rather than stretched across the panel.
 */
.ledio-auth__steps--centered {
    width: fit-content;
    max-width: 100%;
    margin-inline: auto;
    padding-left: 0;
    list-style-position: inside;
    text-align: left;
}

/* -- Confirming the e-mail address -------------------------- */

/*
 * The notice a dead confirmation link redirects with, and the answer the resend
 * button gives a browser that ran none of our JavaScript. Neutral, not alarming:
 * nothing has gone wrong that pressing one button does not fix, and the button
 * is directly below it.
 */
.ledio-auth__notice {
    margin-bottom: var(--ledio-space-lg);
    padding: var(--ledio-space-sm) var(--ledio-space-md);
    border: 1px solid var(--ledio-border-strong);
    border-radius: var(--ledio-radius-sm);
    background-color: var(--ledio-surface-muted);
    color: var(--ledio-text);
    font-size: var(--ledio-font-small);
    text-align: left;
}

/*
 * "Didn't get it?" and the way to fix it, as ONE block with a rule above it.
 * The separation is the message: everything above is what happens next, this is
 * what to do if it does not. The button is outlined rather than filled — a
 * rescue nobody should need must not look like the step they were given.
 */
.ledio-resend {
    margin-top: var(--ledio-space-xl);
    padding-top: var(--ledio-space-lg);
    border-top: 1px solid var(--ledio-border);
}

.ledio-resend__text {
    margin-bottom: var(--ledio-space-sm);
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
}

.ledio-resend__form {
    margin: 0;
}

/*
 * A button mid-request. `aria-busy` is on the form, so the label change and the
 * dimming are driven by the same attribute a screen reader is told about,
 * instead of by a second class that could drift from it.
 */
.ledio-resend__form[aria-busy="true"] .ledio-btn {
    opacity: 0.7;
    cursor: progress;
}

.ledio-resend .ledio-btn[disabled] {
    transform: none;
    cursor: not-allowed;
}


/* ==========================================================================
   Customer zone (/ucet)
   ==========================================================================

   The B2B account area. Every value below comes from the tokens declared at the
   top of this file — there is no second palette, no second type scale and no
   second spacing rhythm here. What the zone adds is layout: a sidebar, panels,
   a table that becomes cards, and a menu.

   Bootstrap does the ordinary grid work (row / col-*, offcanvas-lg, display
   utilities); these classes only cover what Bootstrap has no opinion about.
   ========================================================================== */

.ledio-account {
    padding-block: var(--ledio-space-2xl) var(--ledio-space-3xl);
}

/*
 * Sidebar + content, mirroring .ledio-listing so the account area and the
 * catalogue have the same skeleton. Below lg the sidebar is a Bootstrap
 * offcanvas and this collapses to a single column.
 */
.ledio-account__shell {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--ledio-space-xl);
    align-items: start;
}

@media (min-width: 992px) {
    .ledio-account__shell {
        grid-template-columns: 268px minmax(0, 1fr);
    }

    /*
     * Under the header, never behind it. `top: var(--ledio-space-lg)` pinned the
     * menu 24px from the VIEWPORT, which is 100px inside a sticky header that is
     * drawn on top of it — so scrolling slid the first menu entries out of sight
     * under the navigation. The offset is the header's own height plus the same
     * 24px of air, both from one variable.
     */
    .ledio-account__sidebar {
        position: sticky;
        top: var(--ledio-header-offset);
        /* So a long menu can still be scrolled to its end on a short window. */
        max-height: calc(100vh - var(--ledio-header-offset) - var(--ledio-space-lg));
        overflow-y: auto;
    }
}

/* ≥lg the offcanvas wrapper must flow as a plain sidebar block. */
@media (min-width: 992px) {
    .ledio-account__sidebar-body {
        padding: 0;
        overflow: visible;
    }
}

/* The content column is a stack; every panel keeps the same distance. */
.ledio-account__main {
    display: flex;
    flex-direction: column;
    gap: var(--ledio-space-lg);
    /* grid children default to min-content width, which lets a wide table
       stretch the column past the viewport. */
    min-width: 0;
}

.ledio-account__menu-toggle {
    align-self: flex-start;
}

.ledio-account__header {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--ledio-space-md);
}

.ledio-account__title {
    margin: var(--ledio-space-2xs) 0 0;
    font-size: var(--ledio-font-h3);
}

.ledio-account__lead {
    max-width: var(--ledio-measure);
    margin-top: var(--ledio-space-xs);
    color: var(--ledio-text-muted);
}

.ledio-account__header-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ledio-space-sm);
}

/* -- Menu --------------------------------------------------- */

.ledio-account-nav__list {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.ledio-account-nav__item form {
    margin: 0;
}

/*
 * One rule for links, the sign-out button and the unavailable entries alike, so
 * the eight rows are one column of identical shapes whatever element each is
 * built from. The button resets its own chrome rather than being styled
 * separately — a button that looks 1px different from the links above it is the
 * kind of detail that makes a menu look assembled rather than designed.
 */
.ledio-account-nav__link {
    display: flex;
    align-items: center;
    gap: var(--ledio-space-sm);
    width: 100%;
    padding: var(--ledio-space-sm) var(--ledio-space-md);
    border: 0;
    border-radius: var(--ledio-radius-sm);
    background: transparent;
    color: var(--ledio-text);
    font-size: var(--ledio-font-small);
    font-weight: 600;
    text-align: left;
    text-decoration: none;
    transition: background-color var(--ledio-transition), color var(--ledio-transition);
}

.ledio-account-nav__link:hover {
    background-color: var(--ledio-surface-muted);
    color: var(--ledio-text);
}

.ledio-account-nav__link.is-current {
    background-color: var(--ledio-primary-soft);
    color: var(--ledio-primary-text);
}

.ledio-account-nav__icon {
    display: inline-flex;
    flex: none;
    color: var(--ledio-text-muted);
}

.ledio-account-nav__link.is-current .ledio-account-nav__icon {
    color: var(--ledio-primary-text);
}

.ledio-account-nav__label {
    flex: 1 1 auto;
}

/*
 * An announced-but-unbuilt entry. It recedes; it never disappears — the menu
 * states the whole shape of the zone on purpose. `cursor: default` because
 * there is nothing to click, and it is not focusable (it is a <span>), so
 * nothing promises otherwise.
 */
.ledio-account-nav__link.is-unavailable {
    color: var(--ledio-text-muted);
    font-weight: 500;
    cursor: default;
}

.ledio-account-nav__link.is-unavailable:hover {
    background: transparent;
}

/* Sign-out sits apart: it is the one entry that does something rather than
   going somewhere. */
.ledio-account-nav__item:last-child {
    margin-top: var(--ledio-space-sm);
    padding-top: var(--ledio-space-sm);
    border-top: 1px solid var(--ledio-border);
}

.ledio-account-nav__link--action {
    color: var(--ledio-text-muted);
    cursor: pointer;
}

/* -- Panels ------------------------------------------------- */

/*
 * The zone's one container. Same card as .ledio-auth__panel — white, hairline
 * border, soft shadow, large radius — because they are the same object seen on
 * two pages, and a customer moving from the sign-in form into their account
 * should not cross a visual seam.
 */
.ledio-account-panel {
    padding: clamp(var(--ledio-space-lg), 3vw, var(--ledio-space-xl));
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-surface);
    box-shadow: var(--ledio-shadow-soft);
}

.ledio-account-panel__head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--ledio-space-sm);
    margin-bottom: var(--ledio-space-lg);
}

.ledio-account-panel__title {
    margin: 0;
    font-size: var(--ledio-font-body-lg);
    font-weight: 700;
    letter-spacing: -0.01em;
}

.ledio-account-panel__action {
    color: var(--ledio-primary-text);
    font-size: var(--ledio-font-small);
    font-weight: 600;
    text-decoration: none;
}

.ledio-account-panel__action:hover {
    text-decoration: underline;
}

.ledio-account-panel__meta,
.ledio-account-panel__empty {
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
}

.ledio-account-panel__empty a,
.ledio-account-panel__meta a {
    color: var(--ledio-primary-text);
    font-weight: 600;
}

.ledio-account-panel__aside {
    margin-top: var(--ledio-space-lg);
    padding-top: var(--ledio-space-lg);
    border-top: 1px solid var(--ledio-border);
}

.ledio-account-panel__aside-title {
    margin-bottom: var(--ledio-space-2xs);
    color: var(--ledio-text-muted);
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* A section heading above a group of panels (the security page's two halves). */
.ledio-account-section-title {
    margin: var(--ledio-space-lg) 0 0;
    font-size: var(--ledio-font-body-lg);
    font-weight: 700;
    letter-spacing: -0.01em;
}

.ledio-account-section-title:first-of-type {
    margin-top: 0;
}

.ledio-account-empty__title {
    margin-bottom: var(--ledio-space-xs);
    font-size: var(--ledio-font-body-lg);
    font-weight: 700;
}

/* -- Identity strip ----------------------------------------- */

/*
 * Who is signed in, as what, on what terms — the facts somebody opens the
 * overview to confirm, on the indigo canvas so they read as the page's subject
 * rather than as one panel among several.
 */
.ledio-account-identity {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--ledio-space-lg);
    padding: clamp(var(--ledio-space-lg), 3vw, var(--ledio-space-xl));
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-canvas);
    color: var(--ledio-text-on-dark);
}

.ledio-account-identity__eyebrow {
    color: var(--ledio-text-on-dark-muted);
    font-size: var(--ledio-font-small);
}

.ledio-account-identity__name {
    font-size: var(--ledio-font-h3);
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.15;
}

.ledio-account-identity__facts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ledio-space-xl);
    margin: 0;
}

.ledio-account-identity__facts dt {
    margin-bottom: var(--ledio-space-2xs);
    color: var(--ledio-text-on-dark-muted);
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.ledio-account-identity__facts dd {
    margin: 0;
    font-size: var(--ledio-font-body-lg);
}

.ledio-account-identity__hint {
    display: block;
    margin-top: 2px;
    color: var(--ledio-text-on-dark-muted);
    font-size: var(--ledio-font-small);
    font-weight: 400;
}

/* -- Definition lists and addresses -------------------------- */

.ledio-account-list {
    display: grid;
    gap: var(--ledio-space-sm);
    margin: 0;
}

.ledio-account-list>div {
    display: grid;
    grid-template-columns: 1fr;
    gap: 2px;
}

/*
 * Label beside value from 480px up. Below that they stack: a Slovak label and a
 * long business name in two columns on a 360px screen leaves neither readable.
 */
@media (min-width: 480px) {
    .ledio-account-list>div {
        grid-template-columns: minmax(120px, 34%) minmax(0, 1fr);
        gap: var(--ledio-space-md);
        align-items: baseline;
    }
}

.ledio-account-list dt {
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
    font-weight: 600;
}

.ledio-account-list dd {
    margin: 0;
    /* Long values (an IČ DPH, an e-mail) must wrap rather than widen the
       column past the panel. */
    overflow-wrap: anywhere;
}

/*
 * Facts laid out in COLUMNS, label above value — the shape for a handful of
 * short, read-only values (the locked company identifiers) where
 * .ledio-account-list's label-beside-value rows would turn four glanceable
 * facts into four full-width lines to scroll past.
 *
 * The columns themselves are Bootstrap's; this only supplies the typography and
 * the vertical rhythm inside each one.
 */
.ledio-account-facts {
    margin: 0;
}

.ledio-account-facts dt {
    margin-bottom: 2px;
    color: var(--ledio-text-muted);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.ledio-account-facts dd {
    margin: 0;
    font-weight: 600;
    overflow-wrap: anywhere;
}

.ledio-account-locked-note {
    display: flex;
    gap: var(--ledio-space-sm);
    margin-top: var(--ledio-space-md);
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
}

.ledio-account-locked-note__icon {
    flex: none;
    color: var(--ledio-primary-text);
}

.ledio-account-locked-note a {
    color: var(--ledio-primary-text);
    font-weight: 600;
}

.ledio-account-address {
    margin-bottom: 0;
    font-style: normal;
    line-height: 1.7;
}

/* -- Flashes ------------------------------------------------- */

/*
 * Not a toast. The administration uses toasts because the confirmation there is
 * incidental to a list somebody is working through; here it is the answer to
 * the one thing the customer came to do, and a message that fades in four
 * seconds is one they will miss.
 */
.ledio-account-flash {
    display: flex;
    align-items: flex-start;
    gap: var(--ledio-space-sm);
    margin: 0;
    padding: var(--ledio-space-sm) var(--ledio-space-md);
    border: 1px solid transparent;
    border-radius: var(--ledio-radius-sm);
    font-size: var(--ledio-font-small);
}

.ledio-account-flash__icon {
    flex: none;
    display: inline-flex;
}

.ledio-account-flash--success {
    border-color: rgba(5, 150, 105, 0.28);
    background-color: rgba(5, 150, 105, 0.08);
    /* 5.9:1 on the tint above — the wording carries the meaning, the colour
       only reinforces it. */
    color: #065f46;
}

.ledio-account-flash--error {
    border-color: rgba(217, 45, 32, 0.28);
    background-color: rgba(217, 45, 32, 0.08);
    color: #912018;
}

/* -- Badges -------------------------------------------------- */

/*
 * A status. The label is ALWAYS printed inside, so colour is never the only
 * carrier — these variants reinforce a word that is already there.
 */
.ledio-badge {
    display: inline-flex;
    align-items: center;
    padding: 2px var(--ledio-space-sm);
    border: 1px solid transparent;
    border-radius: var(--ledio-radius-pill);
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
}

.ledio-badge--success {
    border-color: rgba(5, 150, 105, 0.3);
    background-color: rgba(5, 150, 105, 0.1);
    color: #065f46;
}

.ledio-badge--warning {
    border-color: rgba(180, 83, 9, 0.3);
    background-color: rgba(180, 83, 9, 0.1);
    color: #92400e;
}

.ledio-badge--danger {
    border-color: rgba(217, 45, 32, 0.3);
    background-color: rgba(217, 45, 32, 0.1);
    color: #912018;
}

.ledio-badge--info {
    border-color: rgba(0, 174, 235, 0.35);
    background-color: var(--ledio-primary-soft);
    color: var(--ledio-primary-text);
}

.ledio-badge--muted {
    border-color: var(--ledio-border-strong);
    background-color: var(--ledio-surface-muted);
    color: var(--ledio-text-muted);
}

/* The identity strip is dark; the badges on it need their own contrast. */
.ledio-account-identity .ledio-badge {
    border-color: rgba(255, 255, 255, 0.28);
    background-color: rgba(255, 255, 255, 0.12);
    color: var(--ledio-text-on-dark);
}

/* -- Waiting-for-approval panel ------------------------------ */

/*
 * INFORMATION, NOT A WARNING. Nothing has gone wrong — they registered,
 * confirmed their address, and a person at the shop has not got to them yet. So
 * it is the brand's own colour on a soft plate, never the red or amber that
 * would tell them to do something about it.
 */
.ledio-account-pending {
    display: flex;
    gap: var(--ledio-space-md);
    padding: clamp(var(--ledio-space-lg), 3vw, var(--ledio-space-xl));
    border: 1px solid rgba(0, 174, 235, 0.35);
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-primary-soft);
}

.ledio-account-pending__icon {
    flex: none;
    color: var(--ledio-primary-text);
}

.ledio-account-pending__body {
    min-width: 0;
}

.ledio-account-pending__title {
    margin: 0 0 var(--ledio-space-2xs);
    font-size: var(--ledio-font-body);
    font-weight: 700;
}

/*
 * Two lines of explanation and nothing else. The checklist that used to be here
 * implied steps the reader was expected to take, and there are none — every
 * remaining step is the shop's.
 */
.ledio-account-pending__text {
    color: var(--ledio-text);
    font-size: var(--ledio-font-small);
}

/* -- Tables and their card counterpart ----------------------- */

/*
 * Wide content scrolls INSIDE its own container; the page body never scrolls
 * sideways. From md up this is the shape the order data actually is.
 */
.ledio-account-table-wrap {
    overflow-x: auto;
}

.ledio-account-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--ledio-font-small);
}

.ledio-account-table th,
.ledio-account-table td {
    padding: var(--ledio-space-sm) var(--ledio-space-md);
    text-align: left;
    vertical-align: middle;
}

.ledio-account-table thead th {
    border-bottom: 1px solid var(--ledio-border);
    color: var(--ledio-text-muted);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    white-space: nowrap;
}

.ledio-account-table tbody tr+tr {
    border-top: 1px solid var(--ledio-border);
}

.ledio-account-table tbody tr:hover {
    background-color: var(--ledio-surface-muted);
}

.ledio-account-table th[scope="row"] {
    font-weight: 700;
}

.ledio-account-table__number,
.ledio-account-table__money {
    white-space: nowrap;
}

/* Tabular figures so the decimal points line up down the column. */
.ledio-account-table__money {
    font-variant-numeric: tabular-nums;
}

.ledio-account-table__money--total {
    font-weight: 700;
}

.ledio-account-table__product {
    min-width: 200px;
}

.ledio-account-table__link {
    color: var(--ledio-primary-text);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}

.ledio-account-table__link:hover {
    text-decoration: underline;
}

/* The same rows below md, where six columns cannot be read. */
.ledio-account-cards {
    display: grid;
    gap: var(--ledio-space-md);
    margin: 0;
    padding: 0;
    list-style: none;
}

.ledio-account-card {
    padding: var(--ledio-space-md);
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-md);
    background-color: var(--ledio-surface);
}

.ledio-account-card__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--ledio-space-xs);
    margin-bottom: var(--ledio-space-sm);
}

.ledio-account-card__number {
    font-weight: 700;
}

.ledio-account-card__facts {
    display: grid;
    gap: var(--ledio-space-2xs);
    margin: 0 0 var(--ledio-space-md);
    font-size: var(--ledio-font-small);
}

.ledio-account-card__facts>div {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--ledio-space-md);
}

.ledio-account-card__facts dt {
    color: var(--ledio-text-muted);
    font-weight: 600;
}

.ledio-account-card__facts dd {
    margin: 0;
    font-variant-numeric: tabular-nums;
    text-align: right;
}

/* -- Order totals -------------------------------------------- */

.ledio-account-totals {
    display: grid;
    gap: var(--ledio-space-xs);
    margin: var(--ledio-space-lg) 0 0;
    margin-left: auto;
    padding-top: var(--ledio-space-md);
    border-top: 1px solid var(--ledio-border);
    /* Right-aligned block, capped so the labels stay beside their figures
       instead of drifting to the far side of a wide panel. */
    width: min(100%, 340px);
    font-size: var(--ledio-font-small);
}

.ledio-account-totals>div {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--ledio-space-md);
}

.ledio-account-totals dt {
    color: var(--ledio-text-muted);
}

.ledio-account-totals dd {
    margin: 0;
    font-variant-numeric: tabular-nums;
}

.ledio-account-totals__total {
    padding-top: var(--ledio-space-xs);
    border-top: 1px solid var(--ledio-border);
    font-size: var(--ledio-font-body-lg);
    font-weight: 700;
}

.ledio-account-totals__total dt {
    color: var(--ledio-text);
}

/* -- Delivery addresses -------------------------------------- */

/* -- Delivery addresses: a list of rows -------------------- */

/*
 * A LIST, NOT A GRID OF CARDS, and not an admin table either.
 *
 * The card grid was wrong for the case that actually happens: almost every B2B
 * customer here has ONE delivery address, and one card in a three-column grid is
 * a lonely box with two thirds of the row empty beside it. A row fills its width
 * honestly whether there is one or six of them.
 *
 * Bootstrap's grid places the four things inside a row; everything here is the
 * divider, the typography and the alignment. There are no column rules and no
 * header row — the shapes are a name, an address, a phone number and two
 * actions, separated by a hairline.
 */
.ledio-address-list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.ledio-address-row {
    padding: var(--ledio-space-md) clamp(var(--ledio-space-lg), 3vw, var(--ledio-space-xl));
}

/* Between rows only: a rule under the last one would be a line to nowhere. */
.ledio-address-row+.ledio-address-row {
    border-top: 1px solid var(--ledio-border);
}

.ledio-address-row__name {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ledio-space-xs);
    font-weight: 700;
}

.ledio-address-row__company,
.ledio-address-row__address,
.ledio-address-row__phone {
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
}

.ledio-address-row__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ledio-space-lg);
}

/* Two short verbs belong on one line; wrapped, they read as a stack of
   unrelated controls rather than as this row's actions. */
.ledio-address-row__action {
    white-space: nowrap;
}

.ledio-address-row__actions form {
    margin: 0;
}

/*
 * QUIET ACTIONS. Two filled buttons per row would make a list somebody reads
 * look like a list somebody is being asked to act on. They are text, sized and
 * weighted like the links elsewhere in this zone — and the delete is a real
 * <button> stripped of its chrome, because it has to stay a form submit.
 */
.ledio-address-row__action {
    padding: 0;
    border: 0;
    background: none;
    color: var(--ledio-primary-text);
    font-size: var(--ledio-font-small);
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
}

.ledio-address-row__action:hover {
    text-decoration: underline;
}

.ledio-address-row__action--danger {
    color: var(--ledio-text-muted);
}

.ledio-address-row__action--danger:hover {
    color: #912018;
}

/* From lg the row is columns, so the actions sit at its right-hand end. */
@media (min-width: 992px) {
    .ledio-address-row__actions {
        justify-content: flex-end;
    }
}

/*
 * A panel whose content supplies its own padding — the address rows do, so that
 * each divider can run the full width of the card instead of stopping short of
 * it on both sides.
 */
.ledio-account-panel--flush {
    padding: 0;
    overflow: hidden;
}

/* -- Forms inside the zone ----------------------------------- */

/*
 * The account's forms are the storefront's forms — .ledio-form does the work
 * (see the auth section). What is added here is the rhythm between the panels a
 * long form is split across, and the quiet way out beside the submit.
 */
.ledio-account-form {
    display: flex;
    flex-direction: column;
    gap: var(--ledio-space-lg);
}

.ledio-account-form .ledio-form__actions {
    margin: 0;
}

.ledio-account-form__cancel {
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
    font-weight: 600;
}

/*
 * Two links, on one line, outside any panel. They had a card of their own with a
 * heading and a paragraph, which gave two hrefs the same weight as the forms
 * above them — these are documents somebody occasionally opens, not a section of
 * the page.
 */
/*
 * A stated current value above the form that changes it — "Aktuálny e-mail",
 * the address, and whether it has been proved. Small, quiet, and above the
 * fields rather than inside them: it is a fact, not an input.
 */
.ledio-account-current {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ledio-space-xs);
    margin-bottom: var(--ledio-space-lg);
    padding-bottom: var(--ledio-space-md);
    border-bottom: 1px solid var(--ledio-border);
}

.ledio-account-current__label {
    width: 100%;
    color: var(--ledio-text-muted);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.ledio-account-current__value {
    font-weight: 600;
    overflow-wrap: anywhere;
}

/*
 * The last decision on a form, set off by a hairline instead of by a heading of
 * its own. "Predvolená adresa" is one tick and had a whole panel; a rule above
 * it says the same thing at the weight it deserves.
 */
.ledio-account-form__tail {
    margin-top: var(--ledio-space-xs);
    padding-top: var(--ledio-space-md);
    border-top: 1px solid var(--ledio-border);
}

.ledio-account-doc-links {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ledio-space-md) var(--ledio-space-xl);
    /* A sibling of the panels, so it lines up with their outer edge rather than
       with the text inside them. */
    margin: 0;
    padding: 0;
    font-size: var(--ledio-font-small);
}

.ledio-account-doc-links a {
    display: inline-flex;
    align-items: center;
    gap: var(--ledio-space-xs);
    color: var(--ledio-primary-text);
    font-weight: 600;
    text-decoration: none;
}

.ledio-account-doc-links a:hover {
    text-decoration: underline;
}

/*
 * The delete confirmation. confirm_controller.js is shared with the
 * administration and asks SweetAlert2 for `.admin-swal`, whose styling lives in
 * admin.css and is not loaded here — so the popup is given the storefront's own
 * surface under the same class rather than the controller being forked for one
 * dialog.
 */
.ledio-body .swal2-popup.admin-swal {
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-surface);
    box-shadow: var(--ledio-shadow-lift);
    color: var(--ledio-text);
    font-family: var(--ledio-font);
}

.ledio-body .swal2-popup.admin-swal .swal2-title {
    color: var(--ledio-text);
    font-size: var(--ledio-font-body-lg);
    font-weight: 700;
}

.ledio-body .swal2-popup.admin-swal .admin-swal-actions {
    gap: var(--ledio-space-xs);
}

/* ==========================================================================
   21. Cart — trigger, control, offcanvas panel
   --------------------------------------------------------------------------
   Storefront only, like everything else in this file: frontend.css is loaded
   by templates/frontend/layout/base.html.twig and by nothing else, so none of
   this can reach /admin. Nothing global is redefined here — every selector is
   a .ledio-cart-* class of its own (plus .ledio-qty, which the cart is now the
   only consumer of).
   ========================================================================== */

/* -- Header trigger ------------------------------------------------------- */

/*
 * The badge sits on the icon, so it needs a positioned parent. `.ledio-icon-btn`
 * is shared with the account link, hence the modifier rather than a change
 * to the base class.
 */
.ledio-cart-btn {
    position: relative;
}

.ledio-cart-btn__badge {
    position: absolute;
    top: -2px;
    left: 14px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 19px;
    height: 19px;
    padding: 0 5px;
    border-radius: var(--ledio-radius-pill);
    background-color: var(--ledio-primary);
    /* Dark ink on cyan, for the same reason as .ledio-btn--primary. */
    color: #04121c;
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1;
}

/*
 * An empty basket renders an EMPTY badge, not a missing one — the element
 * stays in the DOM so the browser has something to write into, and this is
 * what keeps it invisible until there is a number.
 */
.ledio-cart-btn__badge:empty {
    display: none;
}

/* -- The shared add / stepper control ------------------------------------- */

/*
 * TWO NUMBERS DECIDE THE WHOLE COMPONENT, and both halves read them: the CTA's
 * height and the stepper's height are the same declaration, so "Do košíka" and
 * "− 2 +" occupy exactly the same box. That is the promise the product card
 * makes — nothing below the price moves when something is added — and it is
 * kept here rather than by two numbers that happen to match today.
 *
 * The step buttons stay square-ish at every size, which is what keeps them
 * reading as buttons rather than as slivers beside a long field.
 */
.ledio-cart-control {
    --ledio-cart-control-height: 46px;
    --ledio-cart-control-step: 44px;
}

/*
 * The detail page's control is the biggest one anywhere, and on purpose: it is
 * the single action of the whole card, it spans the card's full width, and it is
 * the one filled element among a page of hairlines. Everything else on the card
 * earns attention by position; this earns it by weight.
 */
.ledio-cart-control--detail {
    --ledio-cart-control-height: 56px;
    --ledio-cart-control-step: 56px;
}

.ledio-cart-control--detail .ledio-cart-control__add {
    font-size: var(--ledio-font-body-lg);
}

.ledio-cart-control--panel {
    --ledio-cart-control-height: 40px;
    --ledio-cart-control-step: 38px;
}

/*
 * The cart page's rows. Bigger than the offcanvas panel's at every width and
 * that is the whole difference: the panel is a glance inside a 400px drawer,
 * this is the page somebody sits on to fix the quantities of a twenty-line
 * order. It WEARS THE PANEL'S SKIN — outlined navy, not filled — because it is
 * saying the same thing the panel says: every row here is already in the basket,
 * so there is nothing to pick out. See the skin rules further down, whose
 * selectors name both variants.
 */
.ledio-cart-control--page {
    --ledio-cart-control-height: 44px;
    --ledio-cart-control-step: 42px;
}

/* Under a thumb the panel's controls get the full touch target back. */
@media (max-width: 575.98px) {
    .ledio-cart-control--panel {
        --ledio-cart-control-height: 44px;
        --ledio-cart-control-step: 44px;
    }
}

.ledio-cart-control__form {
    display: flex;
    align-items: center;
    gap: var(--ledio-space-xs);
}

/*
 * A wider gap before the bin than inside the stepper, so the segmented control
 * reads as one thing and the bin reads as something else. At 8px the bin looked
 * like a fourth segment of a control that has three.
 */
.ledio-cart-control--panel .ledio-cart-control__form,
.ledio-cart-control--page .ledio-cart-control__form {
    gap: var(--ledio-space-sm);
}

/*
 * The two halves are <fieldset>s, which arrive with a border, padding, a margin
 * and a min-width of min-content. The disabled/hidden pair is doing real work
 * here (see the template) and must cost nothing visually.
 *
 * THE BORDER IS RESET ON THE CTA'S FIELDSET ONLY, and that is not tidiness:
 * this rule sits after .ledio-qty in the file, so a blanket `border: 0` here
 * silently won over the stepper's own border. It went unnoticed while the
 * stepper was filled — its border colour equalled its background — and showed
 * up the moment the panel's variant asked for an outline and got nothing.
 */
.ledio-cart-control fieldset {
    min-width: 0;
    margin: 0;
    padding: 0;
}

.ledio-cart-control__add {
    display: flex;
    flex: 1 1 auto;
    border: 0;
}

/*
 * `height` as well as `min-height`: .ledio-btn brings its own min-height, and a
 * button that is 46px in one state and 44px in the other is exactly the shift
 * this component exists to avoid.
 */
.ledio-cart-control__cta {
    flex: 1 1 auto;
    height: var(--ledio-cart-control-height);
    min-height: var(--ledio-cart-control-height);
    white-space: nowrap;
}

/* While a change is in flight: legible, not disabled — see cart_item_controller.js. */
.ledio-cart-control.is-busy {
    opacity: 0.65;
}

/* On a card the control fills its row: the field takes what the buttons leave. */
.ledio-cart-control--card .ledio-cart-control__form,
.ledio-cart-control--card .ledio-qty {
    width: 100%;
}

/*
 * In the panel the STEPPER is what has a fixed width, not the control: the bin
 * is a sibling of it inside the same form, so fixing the control's width made
 * the two share it and collapsed the field to a few pixels.
 *
 * Fixed rather than flexible because the line total beside it varies —
 * "1 225,00 €" against "39,90 €" — and a column of steppers that are each a
 * different width reads as three unrelated inputs rather than as one component
 * repeated down the list. The total takes the remainder (margin-left: auto).
 */
.ledio-cart-control--panel .ledio-qty,
.ledio-cart-control--page .ledio-qty {
    flex: 0 0 auto;
    width: calc(var(--ledio-cart-control-step) * 2 + 60px);
}

/*
 * THE PANEL'S STEPPER IS OUTLINED, NOT FILLED, and the reason is that it is
 * saying something different from the one in the grid.
 *
 * In a category, a solid navy block answers "which of these have I already
 * picked up" across a wall of white cards — it has to win at a glance. In the
 * panel every row is in the basket already, so there is nothing to pick out:
 * four solid navy blocks down a white list would just be four heavy shapes
 * competing with the prices and the names beside them. Same component, same
 * geometry, quieter skin.
 *
 * Scoped to the panel variant alone, so the listing and the product detail keep
 * the filled treatment untouched.
 */
.ledio-cart-control--panel .ledio-qty,
.ledio-cart-control--page .ledio-qty {
    /*border-color: var(--ledio-canvas);*/
    border-color: #4aa1e1;
    background-color: var(--ledio-white);
    color: var(--ledio-canvas);
}

.ledio-cart-control--panel .ledio-qty__btn,
.ledio-cart-control--page .ledio-qty__btn {
    color: var(--ledio-canvas);
}

/* Light, because there is no dark plate left to lift — see the block above. */
.ledio-cart-control--panel .ledio-qty__btn:hover,
.ledio-cart-control--page .ledio-qty__btn:hover {
    background-color: var(--ledio-surface-muted);
}

.ledio-cart-control--panel .ledio-qty__btn:active,
.ledio-cart-control--page .ledio-qty__btn:active {
    background-color: rgba(9, 13, 56, 0.1);
}

/* The seams keep their weight relative to the surface: navy at low alpha here,
   white at low alpha on the filled variant. */
.ledio-cart-control--panel .ledio-qty__input,
.ledio-cart-control--page .ledio-qty__input {
    border-left-color: rgba(9, 13, 56, 0.14);
    border-right-color: rgba(9, 13, 56, 0.14);
    color: var(--ledio-canvas);
    caret-color: var(--ledio-canvas);
}

.ledio-cart-control--panel .ledio-qty__input:focus,
.ledio-cart-control--page .ledio-qty__input:focus {
    background-color: var(--ledio-surface-muted);
}

.ledio-cart-control--card .ledio-qty__input,
.ledio-cart-control--panel .ledio-qty__input,
.ledio-cart-control--page .ledio-qty__input {
    font-size: var(--ledio-font-small);
}

/*
 * The detail page's control fills its row in BOTH states, like the card's. A
 * full-width "Do košíka" that becomes a 180px stepper has the same height and a
 * different footprint, and the buybox visibly narrows the moment something is
 * added. It also gives the field the most room of the three variants, which is
 * right: this is the page somebody types 250 into.
 */
.ledio-cart-control--detail .ledio-cart-control__form,
.ledio-cart-control--detail .ledio-qty {
    width: 100%;
}

.ledio-cart-control--detail .ledio-qty__input {
    font-size: var(--ledio-font-body-lg);
}

@media (max-width: 575.98px) {
    .ledio-cart-control--detail .ledio-cart-control__form {
        flex-wrap: wrap;
    }

    .ledio-cart-control--detail .ledio-cart-control__add,
    .ledio-cart-control--detail .ledio-qty {
        flex-basis: 100%;
    }
}

/*
 * Removing a line. The ICON is small and the TARGET is not — the button is as
 * tall as the stepper beside it and at least as wide as a fingertip, so it is
 * comfortable on a phone without a destructive action shouting from the row.
 */
.ledio-cart-control__remove {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--ledio-cart-control-height);
    height: var(--ledio-cart-control-height);
    padding: 0;
    border: 0;
    border-radius: var(--ledio-radius-sm);
    background-color: transparent;
    color: var(--ledio-text-muted);
    cursor: pointer;
    transition: color var(--ledio-transition), background-color var(--ledio-transition);
}

.ledio-cart-control__remove:hover {
    background-color: var(--ledio-surface-muted);
    color: #b42318;
}

.ledio-cart-control__remove:focus-visible {
    outline: 2px solid var(--ledio-primary);
    outline-offset: 2px;
}

/*
 * The card's cart slot. The product name's link is stretched over the entire
 * card (.ledio-product__link::after), so without lifting this above it the
 * first press of "+" would open the product instead.
 */
.ledio-product__cart {
    position: relative;
    z-index: 1;
    margin-top: var(--ledio-space-sm);
}

/* -- The offcanvas panel -------------------------------------------------- */

/*
 * The width is set through Bootstrap's own custom property rather than with a
 * `width` of our own: `.offcanvas-end` reads --bs-offcanvas-width, and a
 * competing declaration at the same specificity is a coin toss that this one
 * lost. Wider than the 400px default because a cart row carries a thumbnail, a
 * two-line name, a stepper, a bin AND a line total.
 *
 * Position and animation are Bootstrap's own, untouched: the panel is a plain
 * `.offcanvas-end`, full height, over the header rather than offset beneath it.
 * There is no reason to teach it about the header's height, and doing so is how
 * a panel ends up mispositioned the day the header wraps to two rows.
 */
.ledio-cart-offcanvas {
    --bs-offcanvas-width: min(440px, 100vw);
    background-color: var(--ledio-surface);
    color: var(--ledio-text);
}

.ledio-cart-offcanvas .offcanvas-header {
    padding: var(--ledio-space-md) var(--ledio-space-lg);
    border-bottom: 1px solid var(--ledio-border);
}

/*
 * THE CLOSE BUTTON IS A WAY OUT, NOT THE HEADLINE.
 *
 * Bootstrap's `.btn-close` arrives at full opacity with a 4px focus ring drawn
 * on plain `:focus` — and `:focus` is what a mouse click leaves behind, so the
 * panel opened and the loudest thing in it was the × next to "Váš košík". The
 * glyph is quietened to sit below the title, and the ring moves to
 * `:focus-visible`, which is the browser's own answer to "did this person
 * actually navigate here with a keyboard".
 *
 * THE TARGET GROWS WHILE THE MARK SHRINKS: explicit box, small background-size.
 * 44px under a thumb, an 11px × on screen. Scoped to the cart panel — the dark
 * navigation offcanvas keeps its own inverted treatment untouched, and none of
 * this is in admin.css.
 */
.ledio-cart-offcanvas .btn-close {
    width: 44px;
    height: 44px;
    margin: 0;
    padding: 0;
    background-size: 11px;
    border-radius: var(--ledio-radius-sm);
    opacity: 0.5;
    transition: opacity var(--ledio-transition), background-color var(--ledio-transition);
}

.ledio-cart-offcanvas .btn-close:hover {
    background-color: var(--ledio-surface-muted);
    opacity: 0.85;
}

/* Bootstrap draws this on :focus; taken back so a mouse click leaves nothing. */
.ledio-cart-offcanvas .btn-close:focus {
    box-shadow: none;
    opacity: 0.85;
}

.ledio-cart-offcanvas .btn-close:focus-visible {
    outline: 3px solid var(--ledio-primary);
    outline-offset: 2px;
    opacity: 1;
}

/*
 * The body is the swap target and owns the scrolling, so the summary can be
 * pinned to the bottom of it while the lines scroll behind.
 */
.ledio-cart-offcanvas__body {
    display: flex;
    flex-direction: column;
    padding: 0;
    overflow: hidden;
}

.ledio-cart-offcanvas__body:focus-visible {
    outline: none;
}

/*
 * A LIST, NOT A DECK OF CARDS. Rows sit on the panel's own surface and are
 * separated by a hairline — the bordered white card inside a tinted panel that
 * used to be here spent a third of the width on chrome and let four items fill
 * the screen. Ten items now read as a list.
 */
.ledio-cart-lines {
    flex: 1 1 auto;
    overflow-y: auto;
    /* The rows never scroll sideways; they wrap (see __actions below). */
    overflow-x: hidden;
    list-style: none;
    margin: 0;
    padding: 0;
}

.ledio-cart-line {
    display: flex;
    gap: var(--ledio-space-sm);
    padding: var(--ledio-space-sm) var(--ledio-space-lg);
    border-bottom: 1px solid var(--ledio-border);
}

.ledio-cart-line:last-child {
    border-bottom: 0;
}

.ledio-cart-line__media {
    flex: 0 0 56px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: var(--ledio-radius-xs);
    background-color: var(--ledio-surface-muted);
    overflow: hidden;
}

.ledio-cart-line__media img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.ledio-cart-line__placeholder {
    color: var(--ledio-text-muted);
}

/*
 * `align-content: start` is not cosmetic: without it the grid stretches its
 * rows to fill whatever height the row has, and every line grew to roughly
 * twice the height it needs.
 */
.ledio-cart-line__body {
    flex: 1 1 auto;
    min-width: 0;
    display: grid;
    align-content: start;
    gap: 2px;
}

.ledio-cart-line__name {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    color: var(--ledio-text);
    font-size: var(--ledio-font-small);
    font-weight: 600;
    line-height: 1.3;
    text-decoration: none;
}

.ledio-cart-line__name:hover {
    color: var(--ledio-primary-text);
}

/* Code and unit price on one line: the two things somebody scans to confirm
   they picked the right item. Two rows of grey for them is what made the panel
   feel heavy. */
.ledio-cart-line__meta {
    color: var(--ledio-text-muted);
    font-size: 0.75rem;
    line-height: 1.4;
}

.ledio-cart-line__dot {
    margin: 0 4px;
}

.ledio-cart-line__unit {
    white-space: nowrap;
}

/*
 * Stepper, bin and line total on one row — and onto two when a narrow phone
 * cannot hold them, rather than pushing the panel into a sideways scroll. The
 * control keeps a sane minimum so the field never collapses to nothing.
 */
.ledio-cart-line__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ledio-space-xs);
    margin-top: var(--ledio-space-2xs);
}

.ledio-cart-line__actions .ledio-cart-control {
    flex: 0 0 auto;
}

.ledio-cart-line__total {
    margin-left: auto;
    font-size: var(--ledio-font-body);
    font-weight: 700;
    white-space: nowrap;
}

/* The summary is pinned; the lines above it scroll. */
.ledio-cart-summary {
    flex: 0 0 auto;
    padding: var(--ledio-space-md) var(--ledio-space-lg) var(--ledio-space-lg);
    border-top: 1px solid var(--ledio-border);
    background-color: var(--ledio-surface-muted);
}

.ledio-cart-summary__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--ledio-space-sm);
}

.ledio-cart-summary__label {
    display: flex;
    flex-direction: column;
    font-size: var(--ledio-font-small);
    font-weight: 600;
}

.ledio-cart-summary__count {
    color: var(--ledio-text-muted);
    font-size: 0.75rem;
    font-weight: 500;
}

.ledio-cart-summary__value {
    font-size: 1.375rem;
    font-weight: 700;
    white-space: nowrap;
}

.ledio-cart-summary__note {
    margin-top: var(--ledio-space-xs);
    color: var(--ledio-text-muted);
    font-size: 0.75rem;
}

.ledio-cart-summary__cta {
    margin-top: var(--ledio-space-md);
}

/*
 * What is still ahead of this visitor (App\Cart\CartNotice). Quiet on purpose:
 * it is a note about what happens next, not a warning, and the panel's job is
 * to show what is in the basket.
 */
.ledio-cart-hint {
    margin-top: var(--ledio-space-sm);
    padding-top: var(--ledio-space-sm);
    border-top: 1px solid var(--ledio-border);
}

.ledio-cart-hint__text {
    color: var(--ledio-text-muted);
    font-size: 0.75rem;
    line-height: 1.5;
}

.ledio-cart-hint__actions {
    display: flex;
    gap: var(--ledio-space-xs);
    margin-top: var(--ledio-space-xs);
}

.ledio-cart-hint__action {
    flex: 1 1 0;
    min-height: 40px;
    padding: var(--ledio-space-xs) var(--ledio-space-sm);
    font-size: var(--ledio-font-small);
}

.ledio-cart-empty {
    margin: auto;
    padding: var(--ledio-space-2xl) var(--ledio-space-lg);
    text-align: center;
}

.ledio-cart-empty__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 64px;
    height: 64px;
    margin-bottom: var(--ledio-space-md);
    border-radius: var(--ledio-radius-pill);
    background-color: var(--ledio-surface-muted);
    color: var(--ledio-text-muted);
}

.ledio-cart-empty__title {
    margin-bottom: var(--ledio-space-2xs);
    font-size: var(--ledio-font-body-lg);
    font-weight: 700;
}

.ledio-cart-empty__text {
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
}

.ledio-cart-empty__cta {
    margin-top: var(--ledio-space-sm);
}

/* ==========================================================================
   22. Cart page (/kosik)
   --------------------------------------------------------------------------
   Storefront only, like everything else in this file: frontend.css is loaded
   by templates/frontend/layout/base.html.twig and by nothing else, so none of
   this can reach /admin. Every selector is a class of its own; Bootstrap's grid
   does the placement and nothing global is redefined.

   THE PAGE IS ONE COLUMN ON A PHONE, in the order the decisions are made —
   items, who is shopping, where it goes, what it costs. From lg up the last of
   those moves into a sticky column beside the rest, because a total that
   scrolls away is a total somebody scrolls back to.
   ========================================================================== */

/*
 * The dark page header, in the shape every other storefront page uses. Only the
 * vertical rhythm is its own — the band, the breadcrumb and the title all come
 * from `.ledio-section--dark`, `.ledio-breadcrumb` and `.ledio-section-title`,
 * exactly as on the catalogue and the product detail (each of which likewise
 * has one class of its own for this and nothing more).
 */
.ledio-section.ledio-cart-hero {
    padding-block: var(--ledio-space-lg) var(--ledio-space-xl);
}

.ledio-cart-hero__breadcrumb {
    margin-bottom: var(--ledio-space-md);
}

/* Title left, the way back out right — one row, wrapping on a narrow screen. */
.ledio-cart-hero__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    /*
     * Only a floor: `space-between` sets the real distance while the two sit on
     * one line. It matters when they DO NOT — at a narrow tablet width the link
     * drops under the title, and 12px there put it adrift of the heading it
     * belongs to. (On a phone there is no link at all; see `__back` below.)
     */
    gap: var(--ledio-space-2xs);
}

.ledio-cart-hero__title {
    margin-bottom: 0;
    font-size: clamp(1.9rem, 3vw, 2.8rem);
}

/*
 * The way back out, as the storefront's quiet-button pattern rather than as a
 * bare link — it was an underlined caption that landed above the summary column
 * and read as a label on it. `.ledio-section--dark .ledio-btn--ghost` already
 * gives it the right colour on this band.
 *
 * NO INLINE PADDING, so the text edge is the container's edge. `--ghost` pads
 * itself by 8px, which is invisible while the button sits at the right of its
 * row and obvious the moment it wraps underneath the title: the label lands
 * indented against a heading that starts flush, and the two stop looking
 * related. The 46px touch target is the button's height and is untouched.
 *
 * NOT ON A PHONE AT ALL. Below md there is no room beside the title, so it
 * wraps under the h1 and turns the header into a two-line block whose second
 * line is the least important thing on the page. A phone already has ways back
 * — the breadcrumb's home icon, the header menu — and an empty cart keeps its
 * own "Prejsť do katalógu" button in the body, so nothing is lost by hiding it.
 */
.ledio-cart-hero__back {
    display: none;
    padding-inline: 0;
    font-size: var(--ledio-font-small);
}

@media (min-width: 768px) {
    .ledio-cart-hero__back {
        display: inline-flex;
    }
}

/*
 * One sentence, above everything, in one of two weights. The storefront had no
 * flash region at all before this page: the cart endpoints' no-JavaScript
 * refusals were written to `cart_notice` and rendered nowhere.
 */
.ledio-cart-page__flash {
    margin-bottom: var(--ledio-space-md);
    padding: var(--ledio-space-sm) var(--ledio-space-md);
    border-radius: var(--ledio-radius-sm);
    font-size: var(--ledio-font-small);
}

.ledio-cart-page__flash--info {
    background-color: var(--ledio-primary-soft);
    color: var(--ledio-primary-text);
}

.ledio-cart-page__flash--warning {
    background-color: #fdf3e3;
    color: #8a5a00;
}

/*
 * THE EMPTY CART IS A CLASS, NOT A SECOND LAYOUT. The server renders `is-empty`
 * and cart_page_controller.js toggles the identical class when the last line
 * goes, so both paths produce one DOM. Hiding the summary COLUMN (not just its
 * contents) is what stops an empty third of the row from squeezing the empty
 * state into the remainder.
 */
.ledio-cart-page.is-empty .ledio-cart-page__aside,
.ledio-cart-page.is-empty .ledio-cart-page__summary-col {
    display: none;
}

@media (min-width: 992px) {
    .ledio-cart-page.is-empty .ledio-cart-page__main {
        flex: 0 0 100%;
        max-width: 100%;
    }
}

/*
 * Offset from the header, derived rather than guessed: the same custom property
 * the account sidebar uses. A hard-coded number here is how a sticky panel ends
 * up under the header the next time the header changes height.
 */
@media (min-width: 992px) {
    .ledio-cart-page__sticky {
        position: sticky;
        top: var(--ledio-header-offset);
    }
}

.ledio-cart-page__aside {
    display: flex;
    flex-direction: column;
    gap: var(--ledio-space-md);
    margin-top: var(--ledio-space-lg);
}

.ledio-cart-page__empty {
    padding: var(--ledio-space-2xl) var(--ledio-space-lg);
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-surface);
    text-align: center;
}

/* -- Rows ----------------------------------------------------------------- */

/*
 * A LIST ON ONE SURFACE, not a deck of cards. The offcanvas panel learnt this
 * the hard way: bordered boxes inside a bordered box spend a third of the width
 * on chrome and let four items fill the screen. A hairline between rows scales
 * from one line to twenty.
 */
.ledio-cart-rows {
    margin: 0;
    padding: 0 var(--ledio-space-lg);
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-surface);
    list-style: none;
}

/*
 * ROOM TO BREATHE, WITHOUT BECOMING A PRODUCT CARD. The row was tight enough to
 * read as an admin table: a 64px thumbnail, everything at 0.75–0.875rem, and
 * 16px of air. It now gets a larger picture and a proper type scale — and
 * nothing else. No border, no radius, no shadow, no hover lift: it is still a
 * row in a list, and twenty of them still scan as one.
 */
.ledio-cart-row {
    /* Positioned for the remove button, which is painted rather than laid out. */
    position: relative;
    padding: var(--ledio-space-lg) 0;
    border-bottom: 1px solid var(--ledio-border);
}

.ledio-cart-row:last-child {
    border-bottom: 0;
}

.ledio-cart-row__product {
    display: flex;
    align-items: center;
    gap: var(--ledio-space-md);
    min-width: 0;
}

/*
 * Big enough to recognise a luminaire by, which is the whole job: at 64px a
 * downlight and a spot are the same grey circle. Square, so a portrait and a
 * landscape photo occupy the same box and the rows stay level.
 */
.ledio-cart-row__media {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 72px;
    height: 72px;
    overflow: hidden;
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-sm);
    background-color: var(--ledio-white);
}

@media (min-width: 992px) {
    .ledio-cart-row__media {
        width: 88px;
        height: 88px;
    }
}

.ledio-cart-row__media img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.ledio-cart-row__placeholder {
    color: var(--ledio-text-muted);
}

.ledio-cart-row__body {
    min-width: 0;
}

/*
 * Clamped to two lines with the full text on the title attribute — the same way
 * the listing card handles long product names, which here are routinely longer
 * than the column.
 *
 * ONE SIZE AT EVERY WIDTH, and it is the small one. At 1rem on desktop the name
 * was the loudest thing on a page whose subject is a total: a cart is read for
 * its numbers, and the name is there to confirm the row, not to sell it again.
 */
.ledio-cart-row__name {
    display: -webkit-box;
    overflow: hidden;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    color: var(--ledio-text);
    font-size: var(--ledio-font-small);
    font-weight: 600;
    line-height: 1.4;
    text-decoration: none;
}

.ledio-cart-row__name:hover {
    color: var(--ledio-primary-text);
}

.ledio-cart-row__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--ledio-space-2xs);
    margin-top: var(--ledio-space-2xs);
    font-size: 0.8125rem;
}

/* The code identifies the row; it is not something anybody reads for pleasure. */
.ledio-cart-row__sku {
    color: var(--ledio-text-muted);
}

.ledio-cart-row__dot {
    color: var(--ledio-border-strong);
}

/*
 * The unit price is where the line total comes from, so it carries more weight
 * than the code beside it and less than the total at the end of the row. That
 * is the whole hierarchy: name, price-per-piece, line total.
 */
.ledio-cart-row__unit {
    color: var(--ledio-text);
    font-weight: 600;
    white-space: nowrap;
}

/*
 * The amount always closes the row, at every width — no order utilities, the
 * DOM is already in reading order (what it is, how many, what it costs). The
 * strip on the right is where the remove button is painted; see below.
 */
.ledio-cart-row__total {
    padding-right: 44px;
    text-align: right;
}

.ledio-cart-row__amount {
    font-size: var(--ledio-font-body-lg);
    font-weight: 700;
    white-space: nowrap;
}

.ledio-cart-row__amount--quiet {
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-body);
    font-weight: 500;
}

/*
 * PUSHED TO THE RIGHT OF ITS COLUMN, so the stepper ends where the amount
 * begins. "This many, therefore this much" is one thought and it should occupy
 * one place; the stepper used to be centred in its column with a gap on either
 * side, which read as a third unrelated element between the name and the price.
 */
.ledio-cart-row__actions {
    display: flex;
    justify-content: flex-start;
}

@media (min-width: 992px) {
    .ledio-cart-row__actions {
        justify-content: flex-end;
    }
}

/*
 * REMOVING A LINE IS A ROW ACTION, so it sits at the row's edge — out of the
 * quantity-to-amount flow it used to interrupt from a column of its own.
 *
 * IT IS PAINTED THERE, NOT LAID OUT THERE, and that is deliberate. The button
 * has to stay inside the control's <form> and AFTER the number field: both are
 * named `quantity`, the value that arrives last is the one PHP keeps, and that
 * ordering is what makes the bin beat whatever the field holds (see
 * frontend/cart/_control.html.twig). Moving it in the DOM would quietly break
 * removal for anybody whose JavaScript did not run; moving it in CSS cannot.
 *
 * WHICH EDGE DEPENDS ON THE SHAPE OF THE ROW, and space is reserved for it in
 * whichever element it lands beside — never by padding the whole row, which is
 * what cost the product name its second line on a phone.
 *
 * On a phone the row is two lines and the bin closes the second one, past the
 * amount: reserving a strip on the FIRST line would take 44px from the only
 * thing on the page that is genuinely long.
 */
.ledio-cart-row .ledio-cart-control__remove {
    position: absolute;
    right: 0;
    bottom: var(--ledio-space-lg);
}

/* From lg the row is one line, so the bin closes it, centred against the rest. */
@media (min-width: 992px) {
    .ledio-cart-row {
        padding-right: 44px;
    }

    .ledio-cart-row__total {
        padding-right: 0;
    }

    .ledio-cart-row .ledio-cart-control__remove {
        top: 50%;
        bottom: auto;
        transform: translateY(-50%);
    }
}

/* -- Recapitulation ------------------------------------------------------- */

.ledio-cart-recap {
    padding: var(--ledio-space-lg);
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-surface);
}

.ledio-cart-recap__title {
    margin-bottom: var(--ledio-space-md);
    font-size: var(--ledio-font-body-lg);
    font-weight: 700;
}

.ledio-cart-recap__rows {
    display: flex;
    flex-direction: column;
    gap: var(--ledio-space-xs);
}

.ledio-cart-recap__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--ledio-space-sm);
}

/*
 * One line per figure. It used to be a flex column because the piece count sat
 * under the net label — a fact about a different thing, in a column of money.
 * With that gone a term is a term.
 */
.ledio-cart-recap__row dt {
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
    font-weight: 500;
}

.ledio-cart-recap__row dd {
    margin: 0;
    font-weight: 600;
    white-space: nowrap;
}

/* The one number the customer came for, set apart by a rule rather than a box. */
.ledio-cart-recap__row--total {
    margin-top: var(--ledio-space-xs);
    padding-top: var(--ledio-space-sm);
    border-top: 1px solid var(--ledio-border);
}

.ledio-cart-recap__row--total dt {
    color: var(--ledio-text);
    font-size: var(--ledio-font-body);
    font-weight: 700;
}

.ledio-cart-recap__row--total dd {
    font-size: 1.375rem;
    font-weight: 700;
}

.ledio-cart-recap__note {
    margin-top: var(--ledio-space-sm);
    color: var(--ledio-text-muted);
    font-size: 0.75rem;
}

/*
 * THE PAGE'S ONE CTA, AND IT TAKES THE WHOLE COLUMN.
 *
 * Everything else in this panel is a figure; the button is the only thing that
 * does anything, so it is the only full-width element and it sits directly
 * under the total it acts on. Its height matches the cart control's 46px touch
 * target — the same number, taken from the same variable, so the summary column
 * and the rows beside it are built to one rhythm.
 */
.ledio-cart-recap__submit {
    margin-top: var(--ledio-space-md);
}

.ledio-cart-recap__cta {
    justify-content: center;
    width: 100%;
    min-height: var(--ledio-cart-control-height, 46px);
}

/* A locked button still reads as the primary action, just not as a live one. */
.ledio-cart-recap__cta[disabled] {
    cursor: progress;
    opacity: 0.72;
}

/* -- Who is shopping, and where it goes ----------------------------------- */

/*
 * ONE PANEL PER DECISION, and no card inside a card. These sit in the same
 * column as the rows and share their surface treatment, so the page reads as
 * four blocks of one kind rather than as boxes nested in boxes.
 */
.ledio-cart-block {
    padding: var(--ledio-space-lg);
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-lg);
    background-color: var(--ledio-surface);
}

/* Waiting for approval is information, not an error — a tint, not a red rule. */
.ledio-cart-block--waiting {
    border-color: var(--ledio-border-strong);
    background-color: var(--ledio-surface-muted);
}

.ledio-cart-block__title {
    margin-bottom: var(--ledio-space-2xs);
    font-size: var(--ledio-font-body);
    font-weight: 700;
}

.ledio-cart-block__text {
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
    line-height: 1.55;
}

.ledio-cart-block__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ledio-space-xs);
    margin-top: var(--ledio-space-md);
}

/*
 * SELECTABLE ROWS, NOT A DROPDOWN AND NOT CARDS.
 *
 * Not a dropdown, because almost every customer here has one or two
 * destinations and a select hides a two-item list behind a click while showing
 * none of what is in it — the point of this control is that the address is READ
 * before it is chosen.
 *
 * Not cards, and that is the correction: these were bordered, rounded boxes
 * inside a bordered, rounded panel. A card in a card spends twice the chrome on
 * one decision and turns two addresses into a gallery. They are rows now,
 * separated by a hairline that runs the FULL WIDTH of the block — hence the
 * negative inline margin, which is how a list bleeds to the edges of a padded
 * panel without either of them being given a fixed width.
 */
.ledio-address-choices {
    display: flex;
    flex-direction: column;
    margin: var(--ledio-space-sm) calc(var(--ledio-space-lg) * -1) 0;
    padding: 0;
    border: 0;
    border-top: 1px solid var(--ledio-border);
}

.ledio-address-choice {
    display: flex;
    align-items: flex-start;
    gap: var(--ledio-space-sm);
    padding: var(--ledio-space-sm) var(--ledio-space-lg);
    border-bottom: 1px solid var(--ledio-border);
    cursor: pointer;
    transition: background-color var(--ledio-transition);
}

.ledio-address-choice:hover {
    background-color: var(--ledio-surface-muted);
}

/*
 * WHICH ONE IS PICKED IS SAID BY THE RADIO and the row follows from it here. A
 * second `is-selected` class kept in step by JavaScript would be a second answer
 * to the same question — and the one that is wrong between the click and the
 * server's reply.
 *
 * A TINT AND A LEFT EDGE, nothing more. The chosen destination has to be
 * unmistakable at a glance; it does not have to be a component.
 */
.ledio-address-choice:has(.ledio-address-choice__input:checked) {
    box-shadow: inset 3px 0 0 var(--ledio-primary);
    background-color: var(--ledio-primary-soft);
}

.ledio-address-choice__input {
    flex: 0 0 auto;
    margin-top: 2px;
}

.ledio-address-choice__body {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}

.ledio-address-choice__label {
    font-size: var(--ledio-font-small);
    font-weight: 600;
}

.ledio-address-choice__address {
    color: var(--ledio-text-muted);
    font-size: 0.8125rem;
}

/* Hidden by cart_address_controller.js, never here — see that file. */
.ledio-address-choices__submit {
    margin-top: var(--ledio-space-md);
}

.ledio-address-choices.is-busy {
    opacity: 0.65;
}

/*
 * The toggle sits below the list and is .ledio-btn--ghost, so its own padding
 * and 46px target come from the shared button. Pulled back to the block's text
 * edge because that button pads itself horizontally.
 */
.ledio-cart-address-toggle {
    margin: var(--ledio-space-sm) 0 0 calc(var(--ledio-space-xs) * -1);
}

.ledio-cart-address-toggle__link {
    font-size: var(--ledio-font-small);
}

.ledio-cart-address-form {
    margin-top: var(--ledio-space-md);
    padding-top: var(--ledio-space-md);
    border-top: 1px solid var(--ledio-border);
}

/* The last decision on the form, set off by a hairline rather than a heading. */
.ledio-cart-address-form__tail {
    margin-top: var(--ledio-space-sm);
    padding-top: var(--ledio-space-sm);
    border-top: 1px solid var(--ledio-border);
}

/* =========================================================================
   Order confirmation (/objednavka/{id}/dakujeme)
   =========================================================================

   NO NEW LAYOUT LANGUAGE. The page reuses the cart's hero and the cart's own
   `.ledio-cart-block`; what is below is the little that is genuinely its own —
   the confirmation's two facts and the payment slip. Everything sits on the
   Bootstrap grid, exactly as /kosik does.

   Frontend only: nothing here is reachable from admin.css.
   ========================================================================= */

.ledio-order-done__lede {
    margin-bottom: var(--ledio-space-md);
    font-size: var(--ledio-font-body-lg);
    line-height: 1.6;
}

/*
 * The number and the amount, side by side. Two facts is a row on any screen
 * that fits two short values; it wraps rather than being given a breakpoint of
 * its own.
 */
.ledio-order-done__facts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ledio-space-lg);
    margin: 0 0 var(--ledio-space-md);
    padding: var(--ledio-space-md) 0;
    border-top: 1px solid var(--ledio-border);
    border-bottom: 1px solid var(--ledio-border);
}

.ledio-order-done__facts dt {
    margin-bottom: var(--ledio-space-2xs);
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
    font-weight: 500;
}

.ledio-order-done__facts dd {
    margin: 0;
    font-size: 1.25rem;
    font-weight: 700;
}

.ledio-order-done__note {
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
    line-height: 1.55;
}

.ledio-order-done__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ledio-space-xs);
    margin-top: var(--ledio-space-md);
}

/* -- The payment slip ----------------------------------------------------- */

.ledio-order-pay__rows {
    display: flex;
    flex-direction: column;
    gap: var(--ledio-space-xs);
    margin: var(--ledio-space-md) 0 0;
}

.ledio-order-pay__row {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--ledio-space-sm);
}

.ledio-order-pay__row dt {
    color: var(--ledio-text-muted);
    font-size: var(--ledio-font-small);
    font-weight: 500;
}

.ledio-order-pay__row dd {
    margin: 0;
    font-weight: 600;
    text-align: right;
}

/*
 * The IBAN is the one value here that gets copied by hand, so it is set in a
 * monospaced face: grouped digits that a reader has to check character by
 * character are exactly what proportional figures make hard. It is allowed to
 * wrap — a 29-character value must not push the panel wider than the phone.
 */
.ledio-order-pay__iban {
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-size: var(--ledio-font-small);
    letter-spacing: 0.02em;
    overflow-wrap: anywhere;
}

/*
 * On a phone the account takes its own line rather than sharing one with its
 * label. Measured at 375px: beside the label it broke after "1234" and left
 * "5678" hanging on a second, right-aligned line — four digits of an account
 * number, in the one place a customer copies character by character.
 */
@media (max-width: 575.98px) {
    .ledio-order-pay__iban {
        flex: 1 0 100%;
        text-align: left;
    }
}

.ledio-order-pay__qr {
    margin: var(--ledio-space-md) 0 0;
    text-align: center;
}

.ledio-order-pay__qr img {
    width: 220px;
    max-width: 100%;
    height: auto;
    padding: var(--ledio-space-sm);
    border: 1px solid var(--ledio-border);
    border-radius: var(--ledio-radius-md);
    background-color: #ffffff;
}

.ledio-order-pay__qr figcaption {
    margin-top: var(--ledio-space-xs);
    color: var(--ledio-text-muted);
    font-size: 0.75rem;
}

/* =========================================================================
   Cookie consent (CookieConsent v3)
   =========================================================================

   A VARIABLE MAP, NOT A THEME. The library draws its own banner and dialog and
   exposes every colour, radius and font as a --cc-* custom property; this block
   points those at the tokens at the top of this file and stops. There is no
   layout here, no overridden component and nothing that has to be revisited
   when the library is updated — a new version that renames an internal class
   keeps working, because nothing below names one.

   Declared on #cc-main rather than :root ON PURPOSE. cookieconsent.css is
   imported by assets/cookie-consent.js, so the browser appends it AFTER this
   file and its own :root block would win on source order. The id is a heavier
   selector than :root, so these hold whichever way round the two sheets land.

   Storefront only, like the rest of this file: admin.css contains none of it
   and the administration never loads the library.
   ========================================================================= */

#cc-main {
    --cc-font-family: var(--ledio-font);

    /* The dialog is a card, and the shop's cards are --ledio-radius-lg. */
    --cc-modal-border-radius: var(--ledio-radius-lg);
    --cc-btn-border-radius: var(--ledio-radius-sm);
    --cc-pm-toggle-border-radius: var(--ledio-radius-pill);

    /* Light surface, dark ink — the storefront's content surfaces. */
    --cc-bg: var(--ledio-surface);
    --cc-primary-color: var(--ledio-text);
    --cc-secondary-color: var(--ledio-text-muted);
    --cc-link-color: var(--ledio-primary-text);
    --cc-separator-border-color: var(--ledio-border);
    --cc-overlay-bg: rgba(9, 13, 56, 0.6);

    /*
     * Accept and refuse share these variables — `equalWeightButtons` in the
     * configuration gives both the primary treatment, so the refusal is the
     * same size, colour and weight as the acceptance rather than a grey
     * afterthought beside it. Cyan with dark ink, exactly as .ledio-btn--primary
     * and for the same contrast reason: white on cyan falls to ~2.2:1.
     */
    --cc-btn-primary-bg: var(--ledio-primary);
    --cc-btn-primary-color: #04121c;
    --cc-btn-primary-border-color: var(--ledio-primary);
    --cc-btn-primary-hover-bg: var(--ledio-primary-hover);
    --cc-btn-primary-hover-color: #04121c;
    --cc-btn-primary-hover-border-color: var(--ledio-primary-hover);

    /* "Nastavenia cookies" — the quiet third option, as .ledio-btn--outline. */
    --cc-btn-secondary-bg: transparent;
    --cc-btn-secondary-color: var(--ledio-text);
    --cc-btn-secondary-border-color: var(--ledio-border-strong);
    --cc-btn-secondary-hover-bg: var(--ledio-primary-soft);
    --cc-btn-secondary-hover-color: var(--ledio-text);
    --cc-btn-secondary-hover-border-color: var(--ledio-primary);

    /* Category rows in the preferences dialog. */
    --cc-cookie-category-block-bg: var(--ledio-surface-muted);
    --cc-cookie-category-block-border: var(--ledio-border);
    --cc-cookie-category-block-hover-bg: var(--ledio-border);
    --cc-cookie-category-block-hover-border: var(--ledio-border-strong);
    --cc-cookie-category-expanded-block-bg: transparent;
    --cc-cookie-category-expanded-block-hover-bg: var(--ledio-border);
    --cc-section-category-border: var(--ledio-border);

    /* An "on" switch is the primary colour everywhere else in the shop. */
    --cc-toggle-on-bg: var(--ledio-primary-hover);
    --cc-toggle-off-bg: var(--ledio-text-muted);

    /*
     * The locked switch on "Nevyhnutné cookies" — grey rather than green,
     * because it cannot be moved, but its tick has to be READABLE. It is the
     * only thing on the row saying the category is on, and the row sits beside
     * two green switches; a tick nobody can see turns "always on" into what
     * looks like the one category that is off.
     *
     * --ledio-surface-muted was the obvious token here and is the wrong one:
     * #eef2f7 on the white knob is about 1.1:1. The muted text colour clears
     * 5.9:1 on the same knob.
     */
    --cc-toggle-readonly-bg: var(--ledio-border-strong);
    --cc-toggle-readonly-knob-bg: var(--ledio-white);
    --cc-toggle-readonly-knob-icon-color: var(--ledio-text-muted);

    --cc-footer-bg: var(--ledio-surface-muted);
    --cc-footer-color: var(--ledio-text-muted);
    --cc-footer-border-color: var(--ledio-border);

    /*
     * Under the sticky header, over everything else. The library defaults to
     * the maximum 32-bit integer, which also puts it over the browser's own
     * autofill and password dialogs on some platforms.
     */
    --cc-z-index: 1080;
}