/**
 * Prototyp e-shopu Podzimní snění – sdílené styly
 * Neutrální bílý layout; brand barvy (primary/secondary/tlačítka) se táhnou z letošní
 * palety přes role (--color-*), ať eshop koresponduje s ročníkem, ne s loňskou růžovou.
 */

/* ====== PROMĚNNÉ ======
   Overrides jsou na `body.eshop` (ne `:root`) schválně: eshop přebíjí --color-background
   a spol. neutrálními hodnotami, které patří jen ke storefront <body>, ne do globálního
   :root. Třídu `eshop` nese jen storefront <body> (templates/eshop/base.html.twig).
   Aby se navíc celý eshop stylesheet netáhl na ostatní stránky po Turbo navigaci, je
   jeho <link> značen data-turbo-track="reload" (viz eshop/base.html.twig). */
body.eshop {
    /* Neutrální základ eshopu — bílý layout, nezávislý na ročníku */
    --color-background: #ffffff;
    --color-text: #1a1a1a;
    --color-border: #e5e5e5;
    --theme-surface-color: #fafafa;

    /* Brand barvy z letošní palety (role) — dřív natvrdo loňská černá / růžová.
       secondary + tlačítka jedou na `button` (oranžová), ne na `accent` (žlutá):
       na secondary pozadí je místy bílý text a ten na žluté nemá kontrast.
       Akcentové tinty (fokus ringy, slevový kupón) se odvozují color-mixem z button. */
    --theme-primary-color: var(--color-text);
    --theme-secondary-color: var(--color-button);
    --theme-button-background: var(--color-button);
    --theme-muted-color: var(--color-text-muted);

    /* Stavové barvy — základ z PS26 palety (fallback = hex z návrhu), ať se badge/alert
       sladí s tlumenou paletou ročníku; admin je přebije swatchem sage/yellow/brick.
       Z každého základu se odvodí trojice surface/border/text (jedno místo pravdy).
       Text je záměrně tmavý (≥35 % základu s téměř černou), ať badge/countdown drží
       kontrast AA i na světle laděné šalvěji/žluté. */
    --eshop-success: var(--palette-sage, #b1c397);
    --eshop-warning: var(--palette-yellow, #f2e285);
    --eshop-error: var(--palette-brick, #b03a28);

    --eshop-success-surface: color-mix(in srgb, var(--eshop-success) 20%, #fff);
    --eshop-success-border: color-mix(in srgb, var(--eshop-success) 45%, #fff);
    --eshop-success-text: color-mix(in srgb, var(--eshop-success) 35%, #141414);
    --eshop-warning-surface: color-mix(in srgb, var(--eshop-warning) 20%, #fff);
    --eshop-warning-border: color-mix(in srgb, var(--eshop-warning) 45%, #fff);
    --eshop-warning-text: color-mix(in srgb, var(--eshop-warning) 35%, #141414);
    --eshop-error-surface: color-mix(in srgb, var(--eshop-error) 20%, #fff);
    --eshop-error-border: color-mix(in srgb, var(--eshop-error) 45%, #fff);
    --eshop-error-text: color-mix(in srgb, var(--eshop-error) 60%, #141414);

    --theme-success-color: var(--eshop-success);
    --theme-warning-color: var(--eshop-warning);
    --theme-error-color: var(--eshop-error);

    /* Typografie */
    --font-family-primary: 'GT Flexa Light', 'Inter', 'Arial', sans-serif;
    --font-family-medium: 'GT Flexa Medium', 'Inter', 'Arial', sans-serif;

    /* Spacing */
    --spacing-xs: 0.25rem;
    --spacing-sm: 0.5rem;
    --spacing-md: 1rem;
    --spacing-lg: 1.5rem;
    --spacing-xl: 2rem;
    --spacing-xxl: 3rem;

    /* Radius */
    --radius-sm: 3px;
    --radius-md: 5px;
    --radius-lg: 8px;
    --radius-xl: 12px;

    /* Shadows */
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
    --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.12);

    /* Container */
    --container-max: 1200px;

    /* Sticky geometry, stacked by everything that pins itself on a storefront page.
       The site menu is the brand's line box — 2.5rem × 1.6 — so it is stated in rem
       and follows a raised browser font size instead of sliding under the menu. The
       storefront bar below it is 44px of controls plus padding and border: 61px, but
       only while its row fits one line, which is why it sticks from 1025px up
       (measured 121px at 769–880px, 61px from 900px). */
    --eshop-nav-height: 4rem;
    --eshop-subnav-height: 61px;

    /* Transition */
    --transition-fast: 0.15s ease;
    --transition-normal: 0.25s ease;
}

/* ====== RESET ====== */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; overflow-x: hidden; }
body {
    margin: 0;
    font-family: var(--font-family-primary);
    font-size: 1rem;
    line-height: 1.6;
    color: var(--color-text);
    background: var(--color-background);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    /* Deliberately no overflow-x here: html above already clamps sideways scroll,
       and a second clamp on body makes body its own scroll container — one that
       never scrolls, which kills every position:sticky on the storefront (the
       sub-nav, the site menu, the checkout summary). */
}
img { max-width: 100%; display: block; }
button { font-family: inherit; }

/* ====== TYPOGRAFIE ======
   Velikost h1 tu schválně není — drží ji globální pravidlo v core/typography.css,
   společné pro web i storefront. Zbytek škály (h2–h6) je storefrontový. */
h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-family-medium);
    font-weight: 500;
    line-height: 1.15;
    color: var(--theme-primary-color);
    margin: 0 0 var(--spacing-md);
    text-transform: lowercase;
}
h2 { font-size: clamp(1.5rem, 3vw, 2.25rem); }
h3 { font-size: clamp(1.25rem, 2.4vw, 1.75rem); }
h4 { font-size: 1.25rem; }

p { margin: 0 0 var(--spacing-md); }
a { color: var(--theme-primary-color); text-decoration: none; transition: color var(--transition-normal); }
@media (hover: hover) {
    a:hover { color: var(--theme-secondary-color); }
}
small { font-size: 0.875rem; color: var(--theme-muted-color); }
.muted { color: var(--theme-muted-color); }
.text-center { text-align: center; }
.text-right { text-align: right; }

/* ====== LAYOUT ====== */
.container {
    width: 100%;
    max-width: var(--container-max);
    margin: 0 auto;
    padding: 0 var(--spacing-lg);
}
.section { padding: var(--spacing-xl) 0; }
.section-tight { padding: var(--spacing-lg) 0; }
.main-content { flex: 1; }

/* ====== TLAČÍTKA ====== */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.7rem 1.4rem;
    font-family: var(--font-family-medium);
    font-size: 1rem;
    font-weight: 500;
    line-height: 1.2;
    border: 2px solid transparent;
    border-radius: var(--radius-md);
    background: var(--theme-button-background);
    color: var(--theme-primary-color);
    cursor: pointer;
    text-decoration: none;
    transition: all var(--transition-normal);
    text-transform: lowercase;
}
/* Hover only where a real pointer exists: on touch, Turbo swaps <body> without
   a reload and the browser re-applies the emulated :hover to whatever sits under
   the last tap — the fixed bottom bar puts the next page's button exactly there,
   so it arrived pre-darkened. Same guard on every :hover in this file and
   components/buttons.css, plus the link hovers in core/reset.css and
   core/typography.css. */
@media (hover: hover) {
    .btn:hover {
        background: var(--theme-primary-color);
        color: var(--color-background);
        transform: translateY(-1px);
        box-shadow: var(--shadow-md);
    }
}
.btn:active { transform: translateY(0); }
.btn:disabled, .btn[disabled] {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

.btn-primary {
    background: var(--theme-primary-color);
    color: var(--color-background);
    border-color: var(--theme-primary-color);
}
@media (hover: hover) {
    .btn-primary:hover {
        background: var(--theme-secondary-color);
        color: var(--theme-primary-color);
        border-color: var(--theme-secondary-color);
    }
}

.btn-outline {
    background: transparent;
    border-color: var(--theme-primary-color);
    color: var(--theme-primary-color);
}
@media (hover: hover) {
    .btn-outline:hover {
        background: var(--theme-primary-color);
        color: var(--color-background);
    }
}

.btn-ghost {
    background: transparent;
    border-color: transparent;
    color: var(--theme-primary-color);
    padding: 0.5rem 0.75rem;
}
@media (hover: hover) {
    .btn-ghost:hover {
        background: var(--theme-surface-color);
        color: var(--theme-secondary-color);
        transform: none;
        box-shadow: none;
    }
}

.btn-sm { padding: 0.45rem 0.9rem; font-size: 0.875rem; }
.btn-lg { padding: 0.9rem 1.8rem; font-size: 1.125rem; }
.btn-block { display: flex; width: 100%; }

/* ====== KARTY ====== */
.card {
    background: var(--color-background);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    transition: box-shadow var(--transition-normal), transform var(--transition-normal);
    display: flex;
    flex-direction: column;
}
@media (hover: hover) {
    .card:hover { box-shadow: var(--shadow-md); }
}
.card-image {
    aspect-ratio: 4 / 3;
    background: linear-gradient(135deg, #f0f0f0, #e8e8e8);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--theme-muted-color);
    font-size: 0.875rem;
    overflow: hidden;
}
.card-image-tall { aspect-ratio: 3 / 4; }
.card-body {
    padding: var(--spacing-lg);
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    flex: 1;
}
.card-title { margin: 0; font-size: 1.2rem; }
.card-meta { color: var(--theme-muted-color); font-size: 0.9rem; }
.card-footer {
    padding: var(--spacing-md) var(--spacing-lg);
    border-top: 1px solid var(--color-border);
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--spacing-md);
    background: var(--theme-surface-color);
}
.card-price {
    font-family: var(--font-family-medium);
    font-size: 1.4rem;
    color: var(--theme-primary-color);
}
.card-price-old {
    color: var(--theme-muted-color);
    text-decoration: line-through;
    font-size: 0.95rem;
    margin-right: 0.4rem;
}

/* Grid karet */
.grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: var(--spacing-lg);
}
.grid-2 { grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }

/* ====== BADGES & STATUS ====== */
.badge {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.2rem 0.6rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    background: var(--theme-surface-color);
    color: var(--color-text);
    border: 1px solid var(--color-border);
}
.badge-accent {
    background: var(--theme-secondary-color);
    color: var(--theme-primary-color);
    border-color: var(--theme-secondary-color);
}
.badge-success {
    background: var(--eshop-success-surface);
    color: var(--eshop-success-text);
    border-color: var(--eshop-success-border);
}
.badge-warning {
    background: var(--eshop-warning-surface);
    color: var(--eshop-warning-text);
    border-color: var(--eshop-warning-border);
}
.badge-low {
    background: var(--eshop-error-surface);
    color: var(--eshop-error-text);
    border-color: var(--eshop-error-border);
}

/* ====== FORMULÁŘE ====== */
.form-group {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    margin-bottom: var(--spacing-md);
}
.form-label {
    font-family: var(--font-family-medium);
    font-size: 0.95rem;
    color: var(--theme-primary-color);
}
.form-required::after {
    content: ' *';
    color: var(--theme-error-color);
}
.form-control {
    width: 100%;
    padding: 0.7rem 0.9rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    font-family: var(--font-family-primary);
    font-size: 1rem;
    background: var(--color-background);
    color: var(--color-text);
    transition: border-color var(--transition-normal), box-shadow var(--transition-normal);
}
.form-control:focus {
    outline: none;
    border-color: var(--theme-secondary-color);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-button) 25%, transparent);
}
.form-help {
    font-size: 0.85rem;
    color: var(--theme-muted-color);
}
.form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--spacing-md);
}

/* ====== ALERT/INFO ====== */
.alert {
    padding: var(--spacing-md) var(--spacing-lg);
    border-radius: var(--radius-md);
    border-left: 4px solid var(--theme-secondary-color);
    background: var(--theme-surface-color);
    margin-bottom: var(--spacing-md);
}
.alert-success { border-left-color: var(--theme-success-color); background: var(--eshop-success-surface); }
.alert-warning { border-left-color: var(--theme-warning-color); background: var(--eshop-warning-surface); }
.alert-error { border-left-color: var(--theme-error-color); background: var(--eshop-error-surface); }

/* ====== HERO HLAVIČKY OBRAZOVEK ====== */
.page-header {
    padding: var(--spacing-xxl) 0 var(--spacing-xl);
    border-bottom: 1px solid var(--color-border);
}
.page-header h1 { margin-bottom: var(--spacing-sm); }
.page-header p { color: var(--theme-muted-color); max-width: 60ch; margin: 0; }

/* ====== PROTOTYP BANNER ====== */
.proto-banner {
    background: var(--theme-secondary-color);
    color: var(--theme-primary-color);
    padding: 0.5rem var(--spacing-lg);
    text-align: center;
    font-size: 0.85rem;
    font-family: var(--font-family-medium);
}
.proto-banner a {
    color: var(--theme-primary-color);
    text-decoration: underline;
}

/* ====== FOOTER ====== */
/* Background stays with layout/footer.css (--color-footer). The storefront used to
   paint it --theme-primary-color instead, which on body.eshop is #1a1a1a — near
   enough to pass as black, but the Comgate strip sits on its own #000 badge, so the
   badge showed up as a darker rectangle on předprodej pages and nowhere else.
   Only the storefront's own spacing is overridden here. */
.site-footer {
    color: #fff;
    padding: var(--spacing-xxl) 0 var(--spacing-lg);
    margin-top: var(--spacing-xxl);
}
.footer-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--spacing-xl);
}
.footer-section h4 {
    color: #fff;
    font-size: 1rem;
    margin-bottom: var(--spacing-md);
}
.footer-section a { color: rgba(255, 255, 255, 0.85); }
@media (hover: hover) {
    .footer-section a:hover { color: #fff; }
}
.footer-bottom {
    margin-top: var(--spacing-xl);
    padding-top: var(--spacing-md);
    border-top: 1px solid rgba(255, 255, 255, 0.2);
    text-align: center;
    color: rgba(255, 255, 255, 0.7);
    font-size: 0.85rem;
}

/* ====== KOŠÍK COMPONENTS ====== */
.cart-table {
    width: 100%;
    border-collapse: collapse;
}
.cart-table th, .cart-table td {
    padding: var(--spacing-md);
    text-align: left;
    border-bottom: 1px solid var(--color-border);
}
.cart-table th {
    font-family: var(--font-family-medium);
    font-weight: 500;
    color: var(--theme-muted-color);
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.cart-item-name { display: flex; gap: var(--spacing-md); align-items: center; }
.cart-item-thumb {
    width: 60px; height: 60px;
    background: var(--theme-surface-color);
    border-radius: var(--radius-md);
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
    font-size: 1.2rem;
}
.cart-item-meta { color: var(--theme-muted-color); font-size: 0.85rem; }

.qty-control {
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    overflow: hidden;
}
.qty-control button {
    width: 32px; height: 32px;
    background: var(--theme-surface-color);
    border: none;
    cursor: pointer;
    font-size: 1.1rem;
    color: var(--theme-primary-color);
}
@media (hover: hover) {
    .qty-control button:hover { background: var(--theme-secondary-color); }
}
.qty-control input {
    width: 44px;
    text-align: center;
    border: none;
    border-left: 1px solid var(--color-border);
    border-right: 1px solid var(--color-border);
    height: 32px;
    font-family: var(--font-family-medium);
}

/* ====== ODPOČET REZERVACE (chip v subnavu, nalevo od košíku) ====== */
.eshop-subnav-actions {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    /* The tab row is dropped when only one section is on sale, and space-between on
       the wrapper would then pull the cart to the left edge, where nobody looks. */
    margin-left: auto;
    flex-wrap: wrap;
}
/* The countdown chip and the cart pill sized so they wrap onto separate rows instead
   of being squeezed: below roughly 400px they cannot share a line, and flexbox shrinks
   before it wraps, which broke both of them mid-word — the timer itself was splitting
   as "--:-" / "-". min-width keeps each at its natural width so shrinking is not an
   option, and grow makes whichever wrapped fill its own row rather than sit half wide.
   No effect above: the wrapper is sized by its content there, so there is nothing to
   grow into. */
.eshop-countdown,
.eshop-cart-link {
    flex: 1 1 auto;
    min-width: max-content;
    justify-content: center;
}
.eshop-countdown {
    display: inline-flex;
    align-items: baseline;
    gap: 0.45rem;
    padding: 0.25rem 0.75rem;
    border-radius: 999px;
    background: var(--theme-surface-color);
    border: 1px solid var(--color-border);
    line-height: 1.2;
}
.eshop-countdown-label {
    color: var(--theme-muted-color);
    font-size: 0.85rem;
}
.eshop-countdown-time {
    font-family: var(--font-family-medium);
    font-size: 1.05rem;
    color: var(--theme-primary-color);
    font-variant-numeric: tabular-nums;
}
/* Low time left: warn without alarming. */
.eshop-countdown.warning {
    background: var(--eshop-warning-surface);
    border-color: var(--eshop-warning-border);
}
.eshop-countdown.warning .eshop-countdown-time { color: var(--eshop-warning-text); }

/* ====== TYP VSTUPENKY ====== */
.ticket-type {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: var(--spacing-lg);
    background: var(--color-background);
    transition: all var(--transition-normal);
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
}
@media (hover: hover) {
    .ticket-type:hover {
        border-color: var(--theme-secondary-color);
        box-shadow: var(--shadow-md);
    }
}
.ticket-type-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--spacing-md);
}
.ticket-type-name {
    font-family: var(--font-family-medium);
    font-size: 1.4rem;
    color: var(--theme-primary-color);
    margin: 0;
    text-transform: lowercase;
}
.ticket-type-day {
    font-size: 0.85rem;
    color: var(--theme-muted-color);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.ticket-wave {
    background: var(--theme-surface-color);
    border-radius: var(--radius-md);
    padding: var(--spacing-md);
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--spacing-md);
    flex-wrap: wrap;
}
.ticket-wave-info { flex: 1; min-width: 0; }
.ticket-wave-name {
    font-family: var(--font-family-medium);
    font-size: 0.95rem;
    margin-bottom: 0.2rem;
}
.ticket-wave-period {
    font-size: 0.8rem;
    color: var(--theme-muted-color);
}
.ticket-wave-price {
    font-family: var(--font-family-medium);
    font-size: 1.6rem;
    color: var(--theme-primary-color);
}

/* ====== UBYTOVÁNÍ ====== */
.area-block { margin-bottom: var(--spacing-xxl); }
/* One line per fact: the heading (with the block's status opposite it), then the
   description and each note below it. They are separate admin fields and read as
   separate sentences — crammed onto one flex row they blur into each other. */
.area-header {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    margin-bottom: var(--spacing-lg);
    padding-bottom: var(--spacing-sm);
    border-bottom: 2px solid var(--theme-primary-color);
}
.area-headline {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-md);
}
.area-header h2 { margin: 0; }
.area-header .area-meta {
    color: var(--theme-muted-color);
    font-size: 0.95rem;
    line-height: 1.4;
}

/* ====== MERCH VARIANTY ====== */
.variant-group { margin-bottom: var(--spacing-md); }
.variant-label {
    font-family: var(--font-family-medium);
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 0.4rem;
    color: var(--theme-muted-color);
}
.variant-options {
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
}
.variant-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.5rem;
    height: 2.25rem;
    padding: 0 0.7rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-background);
    color: var(--theme-primary-color);
    cursor: pointer;
    font-family: var(--font-family-medium);
    font-size: 0.9rem;
    transition: all var(--transition-fast);
}
@media (hover: hover) {
    .variant-chip:hover { border-color: var(--theme-primary-color); }
}
.variant-chip.active {
    background: var(--theme-primary-color);
    color: var(--color-background);
    border-color: var(--theme-primary-color);
}
.variant-chip.disabled {
    opacity: 0.4;
    cursor: not-allowed;
    text-decoration: line-through;
}
.color-chip {
    width: 2rem;
    height: 2rem;
    border-radius: 999px;
    padding: 0;
    border: 2px solid var(--color-border);
    cursor: pointer;
    min-width: 2rem;
}
.color-chip.active {
    box-shadow: 0 0 0 2px var(--color-background), 0 0 0 4px var(--theme-primary-color);
}

/* ====== POKLADNA ====== */
.checkout-grid {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: var(--spacing-xl);
    align-items: start;
}
.checkout-summary {
    /* The checkout markup puts the summary first (that is the reading order once the
       grid stacks); on two columns it belongs to the right, after the form. */
    order: 1;
    position: sticky;
    /* Clears both bars above it — the site menu and the storefront sub-nav. */
    top: calc(var(--eshop-nav-height) + var(--eshop-subnav-height) + var(--spacing-md));
    background: var(--theme-surface-color);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: var(--spacing-lg);
}
.summary-row {
    display: flex;
    justify-content: space-between;
    padding: 0.4rem 0;
}
.summary-row.total {
    font-family: var(--font-family-medium);
    font-size: 1.25rem;
    border-top: 1px solid var(--color-border);
    padding-top: var(--spacing-md);
    margin-top: var(--spacing-sm);
}
.summary-row.discount {
    color: var(--theme-secondary-color);
    font-family: var(--font-family-medium);
}

/* Order summary item list (checkout) */
.checkout-summary h3 {
    margin-top: 0;
    margin-bottom: var(--spacing-md);
}
.checkout-items {
    border-bottom: 1px solid var(--color-border);
    padding-bottom: var(--spacing-sm);
    margin-bottom: var(--spacing-sm);
}
.checkout-item {
    display: grid;
    grid-template-columns: auto 1fr auto;
    column-gap: 0.6rem;
    align-items: baseline;
    padding: 0.35rem 0;
}
.checkout-item-qty {
    font-family: var(--font-family-medium);
    color: var(--theme-secondary-color);
    white-space: nowrap;
}
.checkout-item-name {
    line-height: 1.35;
    word-break: break-word;
}
.checkout-summary .summary-row span:last-child,
.checkout-item-price {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* ====== DISCOUNT COUPON ====== */
.discount-coupon {
    margin-bottom: var(--spacing-md);
    padding: var(--spacing-md);
    border: 1.5px dashed var(--theme-secondary-color);
    border-radius: var(--radius-md);
    background: color-mix(in srgb, var(--color-button) 8%, transparent);
}
.discount-coupon-label {
    display: block;
    font-family: var(--font-family-medium);
    font-size: 0.95rem;
}
.discount-coupon-row {
    display: flex;
    gap: var(--spacing-sm);
    margin-top: var(--spacing-sm);
}
.discount-coupon-row input {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.65rem 0.85rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: #fff;
    font-size: 1rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.discount-coupon-row input::placeholder {
    text-transform: none;
    letter-spacing: normal;
    color: var(--theme-muted-color);
}
.discount-coupon-row input:focus {
    outline: none;
    border-color: var(--theme-secondary-color);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-button) 30%, transparent);
}
.discount-coupon-row .btn {
    flex: 0 0 auto;
}

/* Applied state */
.discount-chip {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-md);
    padding: 0.7rem var(--spacing-md);
    border: 1px solid color-mix(in srgb, var(--color-button) 45%, transparent);
    border-radius: var(--radius-md);
    background: color-mix(in srgb, var(--color-button) 14%, transparent);
}
.discount-chip-check {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 50%;
    background: var(--theme-secondary-color);
    color: #fff;
    font-size: 0.85rem;
}
.discount-chip-text {
    display: flex;
    flex: 1 1 auto;
    min-width: 0;
    flex-direction: column;
    line-height: 1.25;
}
.discount-chip-text strong {
    font-family: var(--font-family-medium);
    letter-spacing: 0.04em;
}
.discount-chip-text span {
    font-size: 0.85rem;
    color: var(--theme-muted-color);
}
.discount-chip-remove {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.75rem;
    height: 2.75rem;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: var(--theme-muted-color);
    font-size: 0.95rem;
    cursor: pointer;
    transition: background var(--transition-fast), color var(--transition-fast);
}
@media (hover: hover) {
    .discount-chip-remove:hover {
        background: color-mix(in srgb, var(--color-button) 22%, transparent);
        color: var(--color-text);
    }
}

@media (max-width: 576px) {
    .discount-coupon-row {
        flex-direction: column;
    }
    .discount-coupon-row .btn {
        width: 100%;
    }
}

/* ====== STEPPER ====== */
.stepper {
    display: flex;
    gap: var(--spacing-md);
    margin-bottom: var(--spacing-xl);
}
.step {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    padding-bottom: var(--spacing-sm);
    border-bottom: 3px solid var(--color-border);
    color: var(--theme-muted-color);
    font-family: var(--font-family-medium);
    font-size: 0.9rem;
    text-align: center;
}
.step.active { border-bottom-color: var(--theme-secondary-color); color: var(--theme-primary-color); }
.step.done { border-bottom-color: var(--theme-primary-color); color: var(--theme-primary-color); }
.step-number {
    width: 2rem; height: 2rem;
    border-radius: 999px;
    border: 2px solid currentColor;
    display: flex;
    align-items: center;
    justify-content: center;
}
.step.done .step-number {
    background: var(--theme-primary-color);
    color: var(--color-background);
    border-color: var(--theme-primary-color);
}

/* ====== POTVRZENÍ / QR ====== */
.confirmation-card {
    text-align: center;
    padding: var(--spacing-xxl);
    background: var(--theme-surface-color);
    border-radius: var(--radius-lg);
    border: 1px solid var(--color-border);
}
.confirmation-icon {
    width: 4rem;
    height: 4rem;
    border-radius: 999px;
    background: var(--theme-secondary-color);
    color: var(--theme-primary-color);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 2rem;
    margin-bottom: var(--spacing-md);
}
.qr-card {
    display: flex;
    gap: var(--spacing-lg);
    align-items: center;
    background: var(--color-background);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: var(--spacing-lg);
}
.qr-image {
    width: 120px;
    height: 120px;
    background: repeating-conic-gradient(#000 0 25%, #fff 0 50%) 50% / 12px 12px;
    border: 4px solid #fff;
    box-shadow: 0 0 0 1px var(--color-border);
    flex-shrink: 0;
    border-radius: var(--radius-sm);
}
.qr-content { flex: 1; min-width: 0; }
.qr-title { font-family: var(--font-family-medium); margin: 0 0 0.3rem; }

/* ====== TOAST ====== */
.proto-toast {
    position: fixed;
    bottom: var(--spacing-xl);
    left: 50%;
    transform: translateX(-50%) translateY(20px);
    background: var(--theme-primary-color);
    color: var(--color-background);
    padding: 0.8rem 1.4rem;
    border-radius: var(--radius-md);
    font-family: var(--font-family-medium);
    box-shadow: var(--shadow-lg);
    opacity: 0;
    pointer-events: none;
    transition: all var(--transition-normal);
    z-index: 100;
    max-width: 90vw;
}
.proto-toast.visible {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* ====== UTILITY ====== */
.flex { display: flex; }
.flex-col { display: flex; flex-direction: column; }
.gap-sm { gap: var(--spacing-sm); }
.gap-md { gap: var(--spacing-md); }
.gap-lg { gap: var(--spacing-lg); }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.flex-wrap { flex-wrap: wrap; }
.flex-1 { flex: 1; }
.mt-md { margin-top: var(--spacing-md); }
.mt-lg { margin-top: var(--spacing-lg); }
.mb-md { margin-bottom: var(--spacing-md); }
.mb-lg { margin-bottom: var(--spacing-lg); }

/* ====== RESPONZIVITA – TABLET ≤1024px ====== */
@media (max-width: 1024px) {
    .checkout-grid { grid-template-columns: 1fr; }
    /* Stacked, the summary keeps its markup position above the form: shoppers reported
       reaching the pay button before seeing what they were paying for. */
    .checkout-summary { position: static; order: 0; }
    .footer-grid { grid-template-columns: repeat(2, 1fr); }
    .grid { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
}

/* ====== RESPONZIVITA – MOBIL ≤768px ====== */
@media (max-width: 768px) {
    .container { padding: 0 var(--spacing-md); }

    .grid, .grid-2 { grid-template-columns: 1fr; }
    .form-row { grid-template-columns: 1fr; }
    .footer-grid { grid-template-columns: 1fr; gap: var(--spacing-lg); text-align: center; }

    /* Each line becomes a card rather than a column of labelled blocks: the name across
       the top, the two amounts facing each other, and the quantity control opposite the
       remove button. The old stack put five uppercase labels under one another and left
       the ✕ floating on a row of its own. */
    .cart-table thead { display: none; }
    .cart-table, .cart-table tbody { display: block; width: 100%; }
    .cart-table tr {
        display: grid;
        grid-template-columns: 1fr auto;
        align-items: center;
        column-gap: var(--spacing-md);
        row-gap: var(--spacing-sm);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-lg);
        margin-bottom: var(--spacing-md);
        padding: var(--spacing-md);
        box-shadow: var(--shadow-sm);
    }
    .cart-table td { display: block; border: none; padding: 0; }
    .cart-table td::before {
        content: attr(data-label);
        display: block;
        font-size: 0.75rem;
        text-transform: uppercase;
        color: var(--theme-muted-color);
        letter-spacing: 0.5px;
        margin-bottom: 0.2rem;
    }
    /* The name and the stepper say what they are; a label over them is noise. The remove
       cell has no data-label at all, but the rule above still gives it an empty block
       with a margin, which pushed the button off the stepper it faces. */
    .cart-table td.cart-item-cell::before,
    .cart-table .cart-cell-name::before,
    .cart-table .cart-cell-qty::before,
    .cart-table .cart-cell-remove::before { display: none; }

    .cart-cell-name {
        grid-column: 1 / -1;
        font-family: var(--font-family-medium);
    }
    .cart-cell-unit { grid-column: 1; grid-row: 2; }
    .cart-cell-total {
        grid-column: 2;
        grid-row: 2;
        text-align: right;
        font-family: var(--font-family-medium);
    }
    .cart-cell-qty { grid-column: 1; grid-row: 3; }
    .cart-cell-remove { grid-column: 2; grid-row: 3; justify-self: end; }

    /* On narrow screens the actions group wraps below the tabs and takes the full width;
       the countdown chip and the cart link then share that row, or take one each when
       they no longer fit (see their flex sizing above). */
    .eshop-subnav-actions { width: 100%; }
    .stepper { gap: var(--spacing-xs); }
    .step { font-size: 0.75rem; }
    .step-label { display: none; }
    .qr-card { flex-direction: column; text-align: center; }
    .ticket-type-header { flex-direction: column; }
    .area-header { flex-direction: column; align-items: flex-start; gap: var(--spacing-xs); }
    .ticket-wave { flex-direction: column; align-items: stretch; gap: var(--spacing-sm); }
    .ticket-wave-price { font-size: 1.4rem; text-align: right; }
}

/* ====== RESPONZIVITA – MALÝ MOBIL ≤480px ====== */
@media (max-width: 480px) {
    .page-header { padding: var(--spacing-xl) 0 var(--spacing-lg); }
    .btn { padding: 0.65rem 1.1rem; font-size: 0.95rem; }
    .ticket-wave { flex-direction: column; align-items: stretch; }
    .ticket-wave-price { font-size: 1.4rem; }
    .confirmation-card { padding: var(--spacing-xl) var(--spacing-md); }
}

/* ====== EShop: nedostupné položky (vyprodáno / mimo okno prodeje) ====== */
.ticket-type.is-unavailable,
.card.is-unavailable {
    opacity: 0.55;
    filter: grayscale(0.4);
}

/* ====== EShop: lightbox (zvětšení fotek merche) ====== */
.lightbox-overlay {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 9999;
    background: rgba(0, 0, 0, 0.85);
    align-items: center;
    justify-content: center;
    padding: var(--spacing-lg);
    cursor: zoom-out;
}
.lightbox-overlay.is-open { display: flex; }
.lightbox-image {
    max-width: 90vw;
    max-height: 90vh;
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    cursor: default;
}
.lightbox-nav {
    flex: 0 0 auto;
    width: 48px;
    height: 48px;
    margin: 0 var(--spacing-sm);
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.15);
    color: #fff;
    font-size: 2rem;
    line-height: 1;
    cursor: pointer;
}
@media (hover: hover) {
    .lightbox-nav:hover { background: rgba(255, 255, 255, 0.3); }
}

/* ====== EShop: galerie merche (náhledy + výběr varianty) ====== */
.merch-detail-thumb {
    width: 80px;
    height: 80px;
    object-fit: cover;
    border-radius: var(--radius-md);
    cursor: pointer;
    border: 2px solid transparent;
}
@media (hover: hover) {
    .merch-detail-thumb:hover { border-color: var(--theme-secondary-color); }
}
.merch-variant-label {
    display: block;
    margin-bottom: var(--spacing-xs);
    font-family: var(--font-family-medium);
}
.merch-variant-select {
    width: 100%;
    max-width: 22rem;
    padding: var(--spacing-sm) var(--spacing-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--theme-surface-color);
    color: var(--theme-primary-color);
    font-size: 1rem;
}

/* ====== EShop: hláška o vypršení rezervace ====== */
.cart-expiry {
    position: fixed;
    inset: 0;
    z-index: 9998;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--spacing-lg);
    background: rgba(0, 0, 0, 0.6);
}
/* The class sets display:flex, which would otherwise beat the UA [hidden] rule
   (equal specificity, later in the cascade) and show the modal permanently. */
.cart-expiry[hidden] {
    display: none;
}
.cart-expiry-card {
    max-width: 28rem;
    width: 100%;
    padding: var(--spacing-xl);
    border-radius: var(--radius-lg);
    background: var(--theme-surface-color);
    box-shadow: var(--shadow-lg);
    text-align: center;
}
.cart-expiry-card h3 { margin-top: 0; }
.cart-expiry-actions {
    display: flex;
    gap: var(--spacing-md);
    justify-content: center;
    flex-wrap: wrap;
    margin-top: var(--spacing-lg);
}
.cart-expiry-actions form { margin: 0; }

/* ====== EShop: odpověď na přidání do košíku ======
   A <dialog> rendered open, not showModal()'d, so it stays in the normal stacking
   order — below .cart-expiry (9998), which must be able to interrupt it. That also
   means overriding the UA's absolute positioning, border and width. */
.cart-added {
    position: fixed;
    inset: 0;
    z-index: var(--z-modal);
    display: flex;
    /* flex-start + auto margins, not align-items:center: a card centred on the cross
       axis overflows in both directions on a short viewport (a phone held sideways),
       and the part above the top edge — the close button among it — cannot be
       scrolled to. */
    align-items: flex-start;
    justify-content: center;
    /* The UA gives dialog width/height: fit-content, and a fit-content height beats
       inset:0 (top and bottom over-constrain, so bottom is dropped). Without this the
       box ends where its content does: the dark layer covered only the top of the
       screen and the card centred itself inside that stub instead of the viewport. */
    width: 100%;
    height: 100%;
    max-width: none;
    max-height: none;
    padding: var(--spacing-lg);
    border: 0;
    background: rgba(0, 0, 0, 0.6);
    overflow-y: auto;
}
.cart-added:not([open]) {
    display: none;
}
.cart-added-card {
    position: relative;
    margin: auto;
    width: 100%;
    /* Wide enough for the longest heading — "položku se nepodařilo přidat" — to hold one
       line next to the padding that keeps it clear of the close button. Narrow screens
       are unaffected: there the card is capped by the viewport, not by this. */
    max-width: 34rem;
    padding: var(--spacing-xl);
    border-radius: var(--radius-lg);
    background: var(--theme-surface-color);
    box-shadow: var(--shadow-lg);
    text-align: center;
}
.cart-added-card h3 {
    margin-top: 0;
    /* Symmetric, so the heading stays centred while keeping clear of the close button
       in the corner — the error heading is long enough to run under it otherwise. */
    padding: 0 2.5rem;
    /* Focused on open so screen readers announce the answer; the ring would only
       tell sighted users they pressed something they did not. */
    outline: none;
}
.cart-added-dismiss {
    position: absolute;
    top: var(--spacing-sm);
    right: var(--spacing-sm);
    margin: 0;
}
.cart-added-x {
    min-width: 44px;
    min-height: 44px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--theme-primary-color);
    font-size: 1.75rem;
    line-height: 1;
    cursor: pointer;
}
.cart-added-item {
    margin-bottom: var(--spacing-sm);
    font-family: var(--font-family-medium);
}

/* A refusal used to be told apart from a confirmation by its wording alone, on an
   otherwise identical card. The error colour runs along the top edge and through the
   heading, and the reason sits in the same red-bordered block the flash strip uses. */
.cart-added-card.is-error {
    border-top: 4px solid var(--theme-error-color);
}
.cart-added-card.is-error h3 {
    color: var(--theme-error-color);
}
.cart-added-reason {
    margin-bottom: 0;
    padding: var(--spacing-md) var(--spacing-lg);
    border-left: 4px solid var(--theme-error-color);
    border-radius: var(--radius-md);
    background: var(--eshop-error-surface);
    text-align: left;
}
.cart-added-note,
.cart-added-total {
    font-size: 0.9rem;
    opacity: 0.75;
}
.cart-added-total {
    margin-bottom: 0;
}
.cart-added-actions {
    display: flex;
    gap: var(--spacing-md);
    justify-content: center;
    flex-wrap: wrap;
    margin: var(--spacing-lg) 0;
}
.cart-added-actions form { margin: 0; }
.cart-added-sections {
    display: flex;
    gap: var(--spacing-sm);
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    padding-top: var(--spacing-md);
    border-top: 1px solid var(--color-border);
}
.cart-added-sections-label {
    font-size: 0.85rem;
    opacity: 0.75;
}

/* ====== EShop: sekční taby (předprodej) ======
   Pill buttons instead of quiet text links: shoppers kept missing the section
   menu. Inactive pills are outlined, the active one is filled; a short staggered
   slide-in on load draws the eye without getting in the way. 44px min height
   keeps the mobile touch-target rule from the a11y pass. */
.eshop-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
}
.eshop-tab {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 1.25rem;
    font-family: var(--font-family-medium);
    color: var(--theme-primary-color);
    background: var(--color-background);
    border: 1px solid var(--color-border);
    border-radius: 999px;
    text-transform: lowercase;
    transition: background var(--transition-normal), border-color var(--transition-normal), color var(--transition-normal);
}
/* The intro class is added by subnav_controller.js when the shopper enters the
   storefront from outside it — a bare animation would replay on every Turbo
   body swap, i.e. on each click between the tabs. */
.eshop-tabs--intro .eshop-tab { animation: eshop-tab-in 0.35s ease-out backwards; }
.eshop-tabs--intro .eshop-tab:nth-child(2) { animation-delay: 0.08s; }
.eshop-tabs--intro .eshop-tab:nth-child(3) { animation-delay: 0.16s; }
/* Pin the text colour on hover, or the global a:hover would turn it lavender
   (~2.3:1 on the white pill). */
@media (hover: hover) {
    .eshop-tab:hover {
        border-color: var(--theme-secondary-color);
        color: var(--theme-primary-color);
    }
}
.eshop-tab.active {
    background: var(--theme-primary-color);
    border-color: var(--theme-primary-color);
    color: var(--color-background);
}

@keyframes eshop-tab-in {
    from { opacity: 0; transform: translateX(-0.75rem); }
    to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .eshop-tabs--intro .eshop-tab { animation: none; }
}

/* ====== EShop: přilepená spodní lišta (telefon + tablet) ======
   Na širokém displeji drží subnav přilepený nahoře, níž odscrolluje pryč — lišta
   proto nese průběžnou částku a odkazy na ostatní sekce. Hranice je 1024 px, ne
   768: mezi tím se řádek subnavu láme na dva a přilepený by ukrojil ~185 px výšky,
   takže tam raději jede lišta (a tablet na dotyk ji ocení stejně jako telefon).
   Breakpoint je schválně tady u komponenty, ne ve sdíleném mobilním bloku výš: ten
   je v souboru dřív, takže by ho tenhle default se stejnou specificitou přebil a
   lišta by nevyjela nikdy. */
.eshop-bottombar { display: none; }

@media (max-width: 1024px) {
    .eshop-bottombar {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 90;
        display: flex;
        align-items: center;
        gap: var(--spacing-md);
        padding: var(--spacing-sm) var(--spacing-md);
        /* viewport-fit=cover is on (base.html.twig), so clear the home indicator. */
        padding-bottom: calc(var(--spacing-sm) + env(safe-area-inset-bottom));
        background: var(--color-background);
        border-top: 1px solid var(--color-border);
        box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.1);
    }
    .eshop-bottombar-cart {
        display: flex;
        flex-direction: column;
        justify-content: center;
        /* Shrinkable: the count line would otherwise push the section links off a
           320px screen instead of letting them scroll. */
        flex: 0 1 auto;
        min-width: 0;
        min-height: 44px;
        line-height: 1.25;
    }
    .eshop-bottombar-count {
        font-size: 0.8rem;
        color: var(--theme-muted-color);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    .eshop-bottombar-total {
        font-family: var(--font-family-medium);
        font-size: 1.15rem;
        font-variant-numeric: tabular-nums;
        white-space: nowrap;
    }
    .eshop-bottombar-note {
        font-family: var(--font-family-primary);
        font-size: 0.75rem;
        color: var(--theme-muted-color);
    }
    /* The section links scroll sideways rather than wrap: three of them plus the
       cart block do not fit a 320px screen. margin-left rather than
       justify-content: flex-end — with the links right-aligned, an overflowing row
       would start scrolled past the first of them. */
    .eshop-bottombar-links {
        display: flex;
        gap: var(--spacing-sm);
        margin-left: auto;
        min-width: 0;
        overflow-x: auto;
        scrollbar-width: none;
        padding: 2px;
    }
    .eshop-bottombar-links::-webkit-scrollbar { display: none; }
    .eshop-bottombar-links .btn {
        flex: 0 0 auto;
        min-height: 44px;
    }
    /* Keep the page's own end (and the footer) clear of the fixed bar — only on the
       pages that actually render it. The inset is added, not absorbed: the bar pads
       itself by the same amount, so a home indicator makes it that much taller. */
    body.eshop:has(.eshop-bottombar) { padding-bottom: calc(5.5rem + env(safe-area-inset-bottom)); }
}

/* ====== EShop: košík právě povyrostl ======
   Přidání do košíku se překreslí na tutéž stránku a mění jen číslo v liště/subnavu.
   Pulz na něj upozorní (viz assets/controllers/cart_change_controller.js). */
.cart-bumped {
    animation: cart-bump 0.6s ease-out;
}
@keyframes cart-bump {
    0% { transform: none; }
    25% { transform: scale(1.12); }
    60% { transform: scale(0.98); }
    100% { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .cart-bumped { animation: none; }
}

/* ====== EShop: flash zprávy (sdílený blok pod subnav) ====== */
.eshop-flashes { margin-top: var(--spacing-lg); }
.eshop-flashes .alert { margin-bottom: 0; }
.eshop-flashes .alert + .alert { margin-top: var(--spacing-sm); }

/* ====== EShop: subnav pruh pod hlavním menu (taby + košík) ====== */
.eshop-subnav {
    background: var(--theme-surface-color);
    border-bottom: 1px solid var(--color-border);
}
.eshop-subnav-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-md);
    flex-wrap: wrap;
    padding-top: var(--spacing-sm);
    padding-bottom: var(--spacing-sm);
}

/* The storefront bar used to scroll away on the first flick, leaving shoppers with
   the site menu — which says nothing about předprodej — and that is why they
   reported missing the sections. It now sticks under the site menu, but only from
   1025px: below that its row wraps to two lines, and a pinned 121px strip on top of
   the 64px site menu would freeze a third of a tablet's viewport. Narrower screens
   get the bottom bar instead. */
@media (min-width: 1025px) {
    .eshop-subnav {
        position: sticky;
        top: var(--eshop-nav-height);
        /* Below the site nav's own layer (--z-sticky), so its dropdowns still open
           over the storefront bar rather than behind it. */
        z-index: calc(var(--z-sticky) - 1);
        box-shadow: var(--shadow-sm);
    }
}
/* An outlined button, not a text link: the storefront navigation was being missed
   entirely, and this is the control shoppers look for. It carries the running total
   so the amount is not a surprise waiting in the cart. */
.eshop-cart-link {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    min-height: 44px;
    padding: var(--spacing-sm) var(--spacing-md);
    font-family: var(--font-family-medium);
    color: var(--theme-primary-color);
    border: 1px solid var(--theme-primary-color);
    border-radius: 999px;
    background: var(--color-background);
    transition: background var(--transition-normal), color var(--transition-normal);
}
@media (hover: hover) {
    .eshop-cart-link:hover {
        background: var(--theme-primary-color);
        color: var(--color-background);
    }
}
.eshop-cart-link.active {
    background: var(--theme-primary-color);
    color: var(--color-background);
}
.eshop-cart-total {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.eshop-cart-total::before {
    content: '·';
    margin-right: 0.4rem;
    opacity: 0.5;
}
.eshop-cart-total-note {
    font-family: var(--font-family-primary);
    font-size: 0.75rem;
    opacity: 0.75;
}

/* ====== EShop: položky jako řádky (desktop), karty (mobil) ====== */
.eshop-list { display: flex; flex-direction: column; }
.eshop-item {
    display: flex;
    align-items: center;
    gap: var(--spacing-lg);
    padding: var(--spacing-md) var(--spacing-sm);
    border-bottom: 1px solid var(--color-border);
}
.eshop-item-media { flex: 0 0 auto; width: 72px; height: 72px; }
.eshop-item-media img { width: 72px; height: 72px; object-fit: cover; border-radius: var(--radius-md); }
.eshop-item-media-placeholder { font-size: 2.5rem; line-height: 72px; }
.eshop-item-main { flex: 1 1 auto; min-width: 0; }
.eshop-item-title { margin: 0 0 0.15rem; font-size: 1.15rem; }
.eshop-item-meta { color: var(--theme-muted-color); font-size: 0.9rem; line-height: 1.4; }
/* Sits above the list, once per page — see templates/eshop/_soldout_note.html.twig
   for why it is not attached to the individual sold-out item. */
.eshop-soldout-note {
    margin: 0 0 var(--spacing-md);
    color: var(--theme-muted-color);
    font-size: 0.9rem;
    line-height: 1.4;
    font-style: italic;
}
.eshop-item-status { flex: 0 0 auto; width: 9rem; }
.eshop-item-price {
    flex: 0 0 auto;
    min-width: 7rem;
    text-align: right;
    font-family: var(--font-family-medium);
    font-size: 1.15rem;
}
.eshop-item-action { flex: 0 0 auto; width: 12rem; text-align: right; }

/* Vstupenky: typ je blok jako oblast ubytování a jeho kategorie jsou řádky, které
   sdílejí JEDEN počet kusů — proto je dostupnost jednou v hlavičce bloku, ne u
   každé ceny zvlášť. */
.eshop-ticket-note {
    margin: 0;
    padding: var(--spacing-md) var(--spacing-sm);
    color: var(--theme-muted-color);
    font-size: 0.9rem;
}
.eshop-item-action form { margin: 0; }
.eshop-add { display: flex; gap: var(--spacing-xs); }
.eshop-add .btn { flex: 1 1 auto; }
.eshop-qty {
    flex: 0 0 auto;
    width: 3.5rem;
    padding: var(--spacing-xs);
    text-align: center;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--theme-surface-color);
    color: var(--theme-primary-color);
}

/* ====== EShop: merch jako dlaždice (vstupenky a ubytování zůstávají v řádcích) ====== */
.eshop-list--grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: var(--spacing-lg);
}
.eshop-list--grid .eshop-item {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: 0;
    overflow: hidden;
    box-shadow: var(--shadow-sm);
}

/* Edge-to-edge portrait photo (clothing-eshop pattern) with a slow zoom on
   hover. The long transform duration is deliberate — the zoom should still be
   drifting when the visitor clicks through. */
.eshop-list--grid .eshop-item-media {
    position: relative;
    width: 100%;
    /* height:auto is load-bearing: it overrides the 72px row-thumbnail height
       from the base .eshop-item-media rule, or aspect-ratio would be ignored
       and the photo collapses to a 72px strip. */
    height: auto;
    aspect-ratio: 4 / 5;
    background: var(--theme-surface-color);
    overflow: hidden;
}
/* width/height beat the shared mobile rule (.eshop-item-media img gets a fixed
   200px height under 768px) — inset alone would lose to it on the img. */
.eshop-list--grid .eshop-item-photo {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 0;
    transition: transform 2.5s ease;
}
@media (hover: hover) {
    .eshop-list--grid .eshop-item:not(.is-unavailable):hover .eshop-item-photo { transform: scale(1.04); }
}
.eshop-list--grid .eshop-item-media-placeholder {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 3rem;
    line-height: 1;
}
.eshop-list--grid .eshop-item-stock {
    position: absolute;
    top: var(--spacing-sm);
    left: var(--spacing-sm);
}
/* Sold out: the photo goes grey with a sticker across it. Grayscale only the
   photo, not the whole media box — the sticker must stay high-contrast. */
.eshop-list--grid .is-unavailable .eshop-item-photo,
.eshop-list--grid .is-unavailable .eshop-item-media-placeholder { filter: grayscale(1); opacity: 0.7; }
.eshop-item-soldout {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) rotate(-8deg);
    background: var(--theme-primary-color);
    color: var(--color-background);
    font-family: var(--font-family-medium);
    padding: 0.3rem 1.1rem;
    letter-spacing: 0.03em;
    text-transform: lowercase;
}

.eshop-list--grid .eshop-item-main {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    padding: var(--spacing-md);
}
.eshop-list--grid .eshop-item-header {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--spacing-md);
}
.eshop-list--grid .eshop-item-title { margin: 0; font-size: 1.05rem; }
/* width/text-align guard the shared mobile rule (max-width: 768px sets
   .eshop-item-price to width: 100%), which would blow the price up to the full
   header row and squeeze the title out. */
.eshop-list--grid .eshop-item-price {
    width: auto;
    min-width: 0;
    font-size: 1.05rem;
    white-space: nowrap;
    text-align: right;
}
.eshop-item-sizes {
    color: var(--theme-muted-color);
    font-size: 0.82rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
/* The description shows only on sizeless products (enamel mug) — clamp it to two
   lines so cards in a grid row stay level. */
.eshop-list--grid .eshop-item-meta {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.eshop-item-swatches { display: flex; gap: 0.35rem; margin-top: 0.15rem; }
.eshop-item-swatch {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    border: 1px solid var(--color-border);
}

/* Stretched link: the product-name link covers the whole card, so the photo is
   clickable too. Safe only on cards without other interactive elements (merch
   grid); the ::after would sit above buttons elsewhere. */
.eshop-item { position: relative; }
.eshop-item-link::after {
    content: '';
    position: absolute;
    inset: 0;
}
.eshop-list--grid .eshop-item:has(.eshop-item-link) {
    transition: box-shadow var(--transition-normal), transform var(--transition-normal);
}
/* No lift on sold-out cards — the shadow would read as "available". The link
   itself stays live: the detail page still exists. */
@media (hover: hover) {
    .eshop-list--grid .eshop-item:has(.eshop-item-link):not(.is-unavailable):hover {
        box-shadow: var(--shadow-lg);
        transform: translateY(-3px);
    }
}

@media (prefers-reduced-motion: reduce) {
    .eshop-list--grid .eshop-item { transition: none; }
    .eshop-list--grid .eshop-item:not(.is-unavailable):hover .eshop-item-photo { transform: none; }
    .eshop-list--grid .eshop-item:has(.eshop-item-link):not(.is-unavailable):hover { transform: none; }
}

/* ====== EShop: zarovnání množství v košíku ====== */
.cart-table td { vertical-align: middle; }
/* One joined control, not two loose squares with a number floating between them —
   on a phone card that read as three unrelated boxes. */
.cart-qty {
    display: inline-flex;
    align-items: stretch;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    background: var(--theme-surface-color);
    overflow: hidden;
}
.cart-qty form { margin: 0; display: inline-flex; }
.cart-qty-btn {
    width: 44px; height: 44px;
    display: inline-flex; align-items: center; justify-content: center;
    border: none;
    background: none;
    color: var(--theme-primary-color);
    cursor: pointer;
    font-size: 1.2rem; line-height: 1;
}
@media (hover: hover) {
    .cart-qty-btn:hover { background: var(--theme-secondary-color); }
}
.cart-qty-value {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 3ch;
    padding: 0 0.25rem;
    border-left: 1px solid var(--color-border);
    border-right: 1px solid var(--color-border);
    background: var(--color-background);
    font-family: var(--font-family-medium);
    font-variant-numeric: tabular-nums;
}
/* An outlined pill, matching the quantity control it sits next to — as bare text it
   read as a stray label rather than something you press. Quiet until touched, then it
   turns the colour of the thing it is about to do. */
.cart-remove {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    min-height: 44px;
    padding: 0 var(--spacing-md);
    border: 1px solid var(--color-border);
    border-radius: 999px;
    background: var(--color-background);
    color: var(--theme-muted-color);
    font-family: inherit;
    font-size: 0.9rem;
    line-height: 1;
    cursor: pointer;
    transition: color var(--transition-normal), border-color var(--transition-normal), background var(--transition-normal);
}
.cart-remove-x {
    font-size: 1.05rem;
    line-height: 1;
}
@media (hover: hover) {
    .cart-remove:hover {
        border-color: var(--theme-error-color);
        background: var(--eshop-error-surface);
        color: var(--theme-error-color);
    }
}

@media (max-width: 768px) {
    .eshop-list { gap: var(--spacing-md); }
    .eshop-item {
        flex-direction: column;
        align-items: stretch;
        gap: var(--spacing-sm);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-lg);
        padding: var(--spacing-md);
        box-shadow: var(--shadow-sm);
    }
    .eshop-item-media,
    .eshop-item-status,
    .eshop-item-price,
    .eshop-item-action { width: 100%; min-width: 0; text-align: left; }
    .eshop-item-media img { width: 100%; height: 200px; }
    .eshop-item-media-placeholder { line-height: normal; }
}
