/* ============================================================================
   DESIGN SYSTEM — the single source of truth for the three UI primitives.

   Loaded LAST of the head stylesheets on every page, so it settles the
   cascade for anything the component files no longer claim. The component
   files (catalogue.css, eshop.css, cfgr.css, …) had grown a dozen
   near-copies of each primitive — same glass, slightly different radius,
   fill and padding every time. Those copies have been stripped back to
   layout-only, and the material now comes from here.

   Three references, taken from the login page and the catalogue:
     1. BUTTON  — login.html's `.submit-btn` submit pill
     2. FIELD   — login.html's email / password `.form-input`
     3. TILE    — the catalogue's `.cat-tile`

   Anything that is genuinely NOT one of these three keeps its own look and
   is listed under "Deliberate exclusions" at the bottom of this file.
   ============================================================================ */


/* ============================================================
   TOKENS
   ============================================================ */
:root {
    /* --- Button: the login submit pill --- */
    --btn-height:          44px;
    --btn-padding-x:       20px;
    --btn-radius:          40px;
    --btn-font-size:       13px;
    --btn-font-weight:     600;
    --btn-bg:              rgba(255, 255, 255, 0.14);
    --btn-bg-hover:        rgba(255, 255, 255, 0.22);
    --btn-bg-active:       rgba(255, 255, 255, 0.10);
    --btn-color:           rgba(255, 255, 255, 0.82);
    --btn-color-hover:     rgba(255, 255, 255, 0.90);
    --btn-blur:            blur(25px) saturate(50%);
    --btn-border-top:      0.5px solid rgba(255, 255, 255, 0.5);
    --btn-border-bottom:   2px solid rgba(255, 255, 255, 0.2);
    --btn-border-side:     1px solid rgba(255, 255, 255, 0.1);
    --btn-border-hover:    rgba(255, 255, 255, 0.35);
    --btn-shadow:          0 8px 24px rgba(0, 0, 0, 0.01);
    --btn-shadow-hover:    0 0 14px rgba(255, 255, 255, 0.12), 0 8px 24px rgba(0, 0, 0, 0.3);
    --btn-shadow-active:   inset 0 0 10px 1px rgba(0, 0, 0, 0.8);
    --btn-transition:      all 0.3s ease;

    /* Compact variant — same material, for dense rows (product footers,
       filter bars, table cells). Only the metrics differ. */
    --btn-height-sm:       32px;
    --btn-padding-x-sm:    14px;
    --btn-font-size-sm:    12px;

    /* --- Field: the login email / password input --- */
    --field-height:        44px;
    --field-padding-x:     12px;
    --field-radius:        10px;
    --field-font-size:     14px;
    --field-bg:            rgba(0, 0, 0, 0.35);
    --field-bg-focus:      rgba(0, 0, 0, 0.45);
    --field-border:        rgba(255, 255, 255, 0.10);
    --field-border-top:    rgba(255, 255, 255, 0.18);
    --field-color:         #FFFFFF;
    --field-placeholder:   rgba(255, 255, 255, 0.40);
    --field-blur:          blur(10px) saturate(150%);
    --field-focus-ring:    0 0 0 3px rgba(32, 210, 26, 0.18);
    --field-valid-border:  rgba(32, 210, 26, 0.45);
    --field-transition:    background 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease;

    /* Compact variant — same material, for inline controls that sit inside
       a row rather than a form: quantity steppers, filter bars, the navbar
       search, the admin console's dense grids. */
    --field-height-sm:     32px;
    --field-padding-x-sm:  10px;
    --field-font-size-sm:  13px;

    /* --- Tile: the catalogue cat-tile --- */
    --tile-radius:         14px;
    --tile-height:         140px;
    --tile-bg:             rgba(255, 255, 255, 0.05);
    --tile-shadow:         0 4px 16px rgba(0, 0, 0, 0.2);
    --tile-shadow-hover:   0 10px 28px rgba(0, 0, 0, 0.35);
    --tile-lift:           -3px;
    --tile-outline-hover:  rgba(255, 255, 255, 0.38);
    /* A stroke a tile carries at REST, not only on hover. The picture-forward
       tiles do not use it — they sit on a photograph and read as objects on
       their own — but a text-forward card needs an edge to sit in. */
    --tile-outline-rest:   rgba(255, 255, 255, 0.16);
    --tile-gap:            12px;
    --tile-transition:     transform 0.2s ease, box-shadow 0.2s ease, outline-color 0.35s ease;
    --tile-gloss:          linear-gradient(to bottom, rgba(255, 255, 255, 0.18) 0%, rgba(255, 255, 255, 0) 100%);
    --tile-sweep:          linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.25) 50%, rgba(255, 255, 255, 0) 100%);
    --tile-label-size:     16px;
    --tile-count-size:     11px;
}

/* Light theme: the dark-theme values are white washes on white text, which
   vanish on a light page and read worse over the photographic backdrop.
   Only the tokens flip — every rule below is written once. */
:root[data-theme="light"] {
    --btn-bg:              rgba(0, 0, 0, 0.10);
    --btn-bg-hover:        rgba(0, 0, 0, 0.17);
    --btn-bg-active:       rgba(0, 0, 0, 0.06);
    --btn-color:           rgba(0, 0, 0, 0.78);
    --btn-color-hover:     rgba(0, 0, 0, 0.95);
    --btn-border-top:      0.5px solid rgba(255, 255, 255, 0.65);
    --btn-border-bottom:   2px solid rgba(0, 0, 0, 0.16);
    --btn-border-side:     1px solid rgba(0, 0, 0, 0.10);
    --btn-border-hover:    rgba(0, 0, 0, 0.28);
    --btn-shadow-hover:    0 0 14px rgba(0, 0, 0, 0.08), 0 8px 24px rgba(0, 0, 0, 0.14);
    --btn-shadow-active:   inset 0 0 10px 1px rgba(0, 0, 0, 0.25);

    --field-bg:            rgba(255, 255, 255, 0.65);
    --field-bg-focus:      rgba(255, 255, 255, 0.85);
    --field-border:        rgba(0, 0, 0, 0.12);
    --field-border-top:    rgba(0, 0, 0, 0.06);
    --field-color:         #1d1d1f;
    --field-placeholder:   rgba(0, 0, 0, 0.40);

    --tile-bg:             rgba(0, 0, 0, 0.03);
    --tile-shadow:         0 4px 16px rgba(0, 0, 0, 0.10);
    --tile-shadow-hover:   0 10px 28px rgba(0, 0, 0, 0.18);
    --tile-outline-hover:  rgba(0, 0, 0, 0.22);
    --tile-outline-rest:   rgba(0, 0, 0, 0.14);
    --tile-gloss:          linear-gradient(to bottom, rgba(255, 255, 255, 0.35) 0%, rgba(255, 255, 255, 0) 100%);
    --tile-sweep:          linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.45) 50%, rgba(255, 255, 255, 0) 100%);
}

/* The underground layer — the panel that drops open under a catalogue or
   application tile — is dark in EVERY theme (see .subcat-expand-panel in
   catalogue.css, and the matching rule theme.js writes for the chips). The
   light flip above is therefore wrong inside it: light glass and near-black
   labels on a near-black panel. Pin the affected tokens back to the dark
   values from the base :root block above, scoped to the panel.

   Tokens rather than component overrides on purpose: everything the panel
   holds — the chips, the component cards, the pill at the foot of a column
   — is drawn by the same three primitives, so one scope covers them all.
   Custom properties resolve from the nearest declaring ancestor, so this
   also outranks the inline --ux-glass-bg theme.js sets on <html>. */
:root[data-theme="light"] .subcat-expand-panel {
    --ux-glass-bg:         rgba(15, 15, 15, 0.55);
    --tile-bg:             rgba(255, 255, 255, 0.05);
    --tile-shadow:         0 4px 16px rgba(0, 0, 0, 0.2);
    --tile-shadow-hover:   0 10px 28px rgba(0, 0, 0, 0.35);
    --tile-outline-hover:  rgba(255, 255, 255, 0.38);
    --tile-outline-rest:   rgba(255, 255, 255, 0.16);
    --tile-gloss:          linear-gradient(to bottom, rgba(255, 255, 255, 0.18) 0%, rgba(255, 255, 255, 0) 100%);
    --tile-sweep:          linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.25) 50%, rgba(255, 255, 255, 0) 100%);

    --btn-bg:              rgba(255, 255, 255, 0.14);
    --btn-bg-hover:        rgba(255, 255, 255, 0.22);
    --btn-bg-active:       rgba(255, 255, 255, 0.10);
    --btn-color:           rgba(255, 255, 255, 0.82);
    --btn-color-hover:     rgba(255, 255, 255, 0.90);
    --btn-border-top:      0.5px solid rgba(255, 255, 255, 0.5);
    --btn-border-bottom:   2px solid rgba(255, 255, 255, 0.2);
    --btn-border-side:     1px solid rgba(255, 255, 255, 0.1);
    --btn-border-hover:    rgba(255, 255, 255, 0.35);
    --btn-shadow-hover:    0 0 14px rgba(255, 255, 255, 0.12), 0 8px 24px rgba(0, 0, 0, 0.3);
    --btn-shadow-active:   inset 0 0 10px 1px rgba(0, 0, 0, 0.8);
}


/* ============================================================
   1. BUTTONS — reference: login.html `.submit-btn`

   `html button` rather than bare `button`: the Livematrix chat widget
   ships a Tailwind preflight (`button { background-color: transparent }`)
   that loads from <body>, after this file. At 0,0,1 it would win the
   background off every unclassed button; the `html` prefix takes this to
   0,0,2 and settles it without !important.
   ============================================================ */
html button,
html input[type="submit"],
html input[type="button"],
html input[type="reset"],
.btn,
.btn-glass,
.submit-btn,
.card-button,
.action-btn,
.detail-btn,
.details-btn,
.toolbar-btn,
.product-btn,
.add-to-basket-btn,
.proceed-order-btn,
.drawing-link-btn,
.quantity-dialog-btn,
.read-more-btn,
.filter-btn,
.filter-reset-btn,
.expand-btn,
.comparison-more-btn,
.compare-buy-btn,
.footer-write-btn,
.footer-ctl-btn,
.outline-btn,
.cfg-btn,
.glass-cart-btn,
.basket-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    height: var(--btn-height);
    padding: 0 var(--btn-padding-x);
    background: var(--btn-bg);
    color: var(--btn-color);
    -webkit-backdrop-filter: var(--btn-blur);
    backdrop-filter: var(--btn-blur);
    font-family: inherit;
    font-size: var(--btn-font-size);
    font-weight: var(--btn-font-weight);
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
    text-align: center;
    cursor: pointer;
    border-top: var(--btn-border-top);
    border-bottom: var(--btn-border-bottom);
    border-left: var(--btn-border-side);
    border-right: var(--btn-border-side);
    border-radius: var(--btn-radius);
    box-shadow: var(--btn-shadow);
    transition: var(--btn-transition);
    box-sizing: border-box;
    -webkit-appearance: none;
    appearance: none;
}

html button:hover,
html input[type="submit"]:hover,
html input[type="button"]:hover,
html input[type="reset"]:hover,
.btn:hover,
.btn-glass:hover,
.submit-btn:hover,
.card-button:hover,
.action-btn:hover,
.detail-btn:hover,
.details-btn:hover,
.toolbar-btn:hover,
.product-btn:hover,
.add-to-basket-btn:hover,
.proceed-order-btn:hover,
.drawing-link-btn:hover,
.quantity-dialog-btn:hover,
.read-more-btn:hover,
.filter-btn:hover,
.filter-reset-btn:hover,
.expand-btn:hover,
.comparison-more-btn:hover,
.compare-buy-btn:hover,
.footer-write-btn:hover,
.footer-ctl-btn:hover,
.outline-btn:hover,
.cfg-btn:hover,
.glass-cart-btn:hover,
.basket-btn:hover {
    background: var(--btn-bg-hover);
    color: var(--btn-color-hover);
    border-color: var(--btn-border-hover);
    box-shadow: var(--btn-shadow-hover);
    transform: translateY(-0.5px);
}

html button:active,
html input[type="submit"]:active,
html input[type="button"]:active,
.btn:active,
.btn.active,
.btn-glass:active,
.btn-glass.active,
.submit-btn:active,
.card-button:active,
.action-btn:active,
.detail-btn:active,
.details-btn:active,
.toolbar-btn:active,
.product-btn:active,
.add-to-basket-btn:active,
.proceed-order-btn:active,
.drawing-link-btn:active,
.quantity-dialog-btn:active,
.read-more-btn:active,
.filter-btn:active,
.filter-reset-btn:active,
.expand-btn:active,
.comparison-more-btn:active,
.compare-buy-btn:active,
.footer-write-btn:active,
.footer-ctl-btn:active,
.outline-btn:active,
.cfg-btn:active,
.glass-cart-btn:active,
.basket-btn:active {
    background: var(--btn-bg-active);
    border-top: none;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    border-left: 1px solid rgba(255, 255, 255, 0.05);
    border-right: 1px solid rgba(255, 255, 255, 0.05);
    box-shadow: var(--btn-shadow-active);
    color: var(--primary-color, #20d21a);
    text-shadow: 0 0 15px rgba(32, 210, 26, 0.5);
    transform: none;
}


/* --- Livematrix preflight guard ---
   The chat widget ships a Tailwind preflight that loads from <body>, after
   this file, and resets `background-color: transparent` on
   button / [type=submit] / [type=button] / [type=reset]. An attribute
   selector scores the same 0,1,0 as a single class, so `[type=submit]` ties
   `.submit-btn` and wins on order — which renders a fully styled button with
   no fill at all. Re-assert just the fill one notch higher via the `html`
   prefix. Nothing else in the pill needs it, and accent variants that set
   their own background use a compound selector and still win. */
html button,
html input[type="submit"],
html input[type="button"],
html input[type="reset"],
html .btn,
html .btn-glass,
html .submit-btn,
html .card-button,
html .action-btn,
html .detail-btn,
html .details-btn,
html .toolbar-btn,
html .product-btn,
html .add-to-basket-btn,
html .proceed-order-btn,
html .drawing-link-btn,
html .quantity-dialog-btn,
html .read-more-btn,
html .filter-btn,
html .filter-reset-btn,
html .expand-btn,
html .comparison-more-btn,
html .compare-buy-btn,
html .footer-write-btn,
html .footer-ctl-btn,
html .outline-btn,
html .cfg-btn,
html .glass-cart-btn,
html .basket-btn {
    background: var(--btn-bg);
}

html button:hover,
html input[type="submit"]:hover,
html input[type="button"]:hover,
html input[type="reset"]:hover,
html .btn:hover,
html .btn-glass:hover,
html .submit-btn:hover,
html .card-button:hover,
html .action-btn:hover,
html .detail-btn:hover,
html .details-btn:hover,
html .toolbar-btn:hover,
html .product-btn:hover,
html .add-to-basket-btn:hover,
html .proceed-order-btn:hover,
html .drawing-link-btn:hover,
html .quantity-dialog-btn:hover,
html .read-more-btn:hover,
html .filter-btn:hover,
html .filter-reset-btn:hover,
html .expand-btn:hover,
html .comparison-more-btn:hover,
html .compare-buy-btn:hover,
html .footer-write-btn:hover,
html .footer-ctl-btn:hover,
html .outline-btn:hover,
html .cfg-btn:hover,
html .glass-cart-btn:hover,
html .basket-btn:hover {
    background: var(--btn-bg-hover);
}

html button:active,
html input[type="submit"]:active,
html input[type="button"]:active,
html input[type="reset"]:active,
html .btn:active,
html .btn-glass:active,
html .submit-btn:active,
html .card-button:active,
html .action-btn:active,
html .detail-btn:active,
html .details-btn:active,
html .toolbar-btn:active,
html .product-btn:active,
html .add-to-basket-btn:active,
html .proceed-order-btn:active,
html .drawing-link-btn:active,
html .quantity-dialog-btn:active,
html .read-more-btn:active,
html .filter-btn:active,
html .filter-reset-btn:active,
html .expand-btn:active,
html .comparison-more-btn:active,
html .compare-buy-btn:active,
html .footer-write-btn:active,
html .footer-ctl-btn:active,
html .outline-btn:active,
html .cfg-btn:active,
html .glass-cart-btn:active,
html .basket-btn:active {
    background: var(--btn-bg-active);
}

/* Disabled reads as the same pill, drained */
html button:disabled,
html input[type="submit"]:disabled,
.btn:disabled,
.submit-btn:disabled,
.product-btn:disabled,
.compare-buy-btn:disabled,
.cfg-btn:disabled,
.product-btn.disabled,
.btn.disabled {
    opacity: 0.45;
    cursor: default;
    pointer-events: none;
    box-shadow: none;
    transform: none;
}

/* --- Size variant: compact. Same material, tighter metrics.
   .detail-btn / .details-btn are here because they share a row with the
   cart pill in every product card — at the full 44px they towered over it. */
.btn-sm,
.product-btn,
.add-to-basket-btn,
.drawing-link-btn,
.compare-buy-btn,
.comparison-more-btn,
.detail-btn,
.details-btn,
.glass-cart-btn,
.action-btn,
.read-more-btn,
.footer-write-btn,
.cfg-btn-sm,
.filter-actions-sidebar .submit-btn {
    height: var(--btn-height-sm);
    padding: 0 var(--btn-padding-x-sm);
    font-size: var(--btn-font-size-sm);
}

/* --- Size variant: icon-only. Same material, square footprint. --- */
.btn-icon,
.icon-btn,
.close-btn,
.qty-btn,
.quantity-btn,
.view-toggle-btn,
.fav-btn,
.compare-buy-btn.compare-buy-icon,
.basket-item-remove-btn,
.footer-ctl-btn,
.pdp-qty-btn {
    width: var(--btn-height-sm);
    height: var(--btn-height-sm);
    padding: 0;
    gap: 0;
    border-radius: 50%;
    flex-shrink: 0;
}

/* Icon buttons whose glyph is text rather than an SVG — the footer's
   language switch is the only one so far (РУС / EN). The label has to sit
   inside the same 32px circle, so it runs smaller and tighter than the
   pill's 13px; the global `button` rule already centres it. */
.footer-lang-btn .lang-code {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.02em;
    line-height: 1;
}

/* Full-width when a submit pill stands alone in a form (footer inquiry,
   register, reset) — a row of two, like the login page's back + submit,
   opts back out via .checkout-actions in checkout.css. */
.submit-btn {
    width: 100%;
}

/* Buttons sitting directly beside each other merge into one control */
.btn-group {
    display: inline-flex;
    gap: 1px;
}
.btn-group > :not(:first-child) {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}
.btn-group > :not(:last-child) {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}


/* ============================================================
   2. TEXT FIELDS — reference: login.html `.form-input`

   One chain for every typed control on the site. The `:not()` list is
   only for controls that are not text fields at all (checkboxes, radios,
   the submit/button inputs already styled as pills above).
   ============================================================ */
html input:where(:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="range"]):not([type="color"]):not([type="file"])),
html textarea,
html select,
.form-input,
.search-input,
.qty-input,
.quantity-input,
.filter-input,
.filter-select,
.filter-select-nav,
.filter-input-nav,
.eshop-sort-select,
.calc-input,
.admin-input,
.cfg-select,
.cfg-input,
.comment-input {
    padding: 0 var(--field-padding-x);
    min-height: var(--field-height);
    font-family: inherit;
    font-size: var(--field-font-size);
    color: var(--field-color);
    background: var(--field-bg);
    border: 1px solid var(--field-border);
    border-top-color: var(--field-border-top);
    border-radius: var(--field-radius);
    -webkit-backdrop-filter: var(--field-blur);
    backdrop-filter: var(--field-blur);
    box-shadow: none;
    outline: none;
    box-sizing: border-box;
    transition: var(--field-transition);
}

/* `.form-input` is the stacked-form field (login, register, reset, the
   checkout contact step, the footer inquiry form): it owns its whole row,
   so it fills the column and carries the gap down to the next field. The
   material above moved here from main.css without these two lines, which
   left every such field at the UA's ~170px intrinsic width. Rows that do
   their own spacing (.checkout-form-row) zero the margin themselves; every
   other field class sits in a layout that sizes it — grid cell, flex row,
   fixed-width stepper — so their widths stay with those layouts. */
.form-input {
    width: 100%;
    margin-bottom: 12px;
}

/* Textareas grow instead of sitting on one line */
html textarea,
textarea.form-input,
textarea.admin-input {
    min-height: 80px;
    padding: var(--field-padding-x);
    line-height: 1.5;
    resize: vertical;
    overflow-y: auto;
}

html input::placeholder,
html textarea::placeholder,
.form-input::placeholder,
.search-input::placeholder,
.calc-input::placeholder,
.admin-input::placeholder {
    color: var(--field-placeholder);
}

html input:where(:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="range"]):not([type="color"]):not([type="file"])):focus,
html textarea:focus,
html select:focus,
.form-input:focus,
.search-input:focus,
.qty-input:focus,
.quantity-input:focus,
.filter-input:focus,
.filter-select:focus,
.filter-select-nav:focus,
.filter-input-nav:focus,
.eshop-sort-select:focus,
.calc-input:focus,
.admin-input:focus,
.cfg-select:focus,
.cfg-input:focus,
.comment-input:focus {
    outline: none;
    background: var(--field-bg-focus);
    border-color: var(--primary-color, #20d21a);
    box-shadow: var(--field-focus-ring);
}

/* Filled-and-valid: a quiet green edge, no ring */
html input:where(:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="range"]):not([type="color"]):not([type="file"])):user-valid,
html textarea:user-valid,
html select:user-valid {
    border-color: var(--field-valid-border);
    box-shadow: none;
}

html input:disabled,
html textarea:disabled,
html select:disabled {
    opacity: 0.45;
    cursor: default;
}

/* Native select needs its own arrow once the UA appearance is dropped */
html select,
.filter-select,
.filter-select-nav,
.eshop-sort-select,
.cfg-select {
    -webkit-appearance: none;
    appearance: none;
    padding-right: 30px;
    background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                      linear-gradient(135deg, currentColor 50%, transparent 50%);
    background-position: calc(100% - 16px) calc(50% + 1px), calc(100% - 11px) calc(50% + 1px);
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
    cursor: pointer;
}
/* The arrow is painted with background-image, so the fill has to ride
   along as the last layer of the same shorthand. */
html select { background-color: var(--field-bg); }
html select:focus { background-color: var(--field-bg-focus); }

/* Number spinners are noise next to the arrow/stepper controls */
html input[type="number"]::-webkit-outer-spin-button,
html input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
html input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

/* --- Size variant: compact. Same material, tighter metrics. --- */
.field-sm,
.qty-input,
.quantity-input,
.filter-input,
.filter-select,
.filter-select-nav,
.filter-input-nav,
.eshop-sort-select,
.calc-input,
.admin-input,
.cfg-select,
.cfg-input,
.search-input,
.filter-navbar .search-input,
#nav-search-input.search-input {
    min-height: var(--field-height-sm);
    padding: 0 var(--field-padding-x-sm);
    font-size: var(--field-font-size-sm);
}
/* Steppers and unit boxes centre their value */
.qty-input,
.quantity-input { text-align: center; }


/* ============================================================
   3. TILES — reference: catalogue `.cat-tile`

   Picture-forward glass card: theme-driven fill, soft shadow, a
   transparent outline that lights up on hover, a top gloss and a
   highlight that sweeps across on hover.
   ============================================================ */
html body .cat-tile,
html body .catalog-cat-tile:not(.sub-level),
html body .subcat-tile,
html body .subcat-tile-item,
html body .app-tile,
html body .sol-comp-card,
html body .category-card {
    position: relative;
    min-width: 0;
    padding: 0;
    margin: 0;
    display: block;
    overflow: hidden;
    cursor: pointer;
    /* Fill is theme-driven (theme.js writes --ux-glass-bg); the token is
       the fallback for before the theme engine runs. */
    background-color: var(--ux-glass-bg, var(--tile-bg));
    border: none;
    border-radius: var(--tile-radius);
    box-shadow: var(--tile-shadow);
    /* The stroke rides on `outline`, not border or box-shadow: it must not
       take part in the box model, and -1px offset tucks it inside the
       rounded edge. */
    outline: 1px solid transparent;
    outline-offset: -1px;
    transition: var(--tile-transition);
    -webkit-appearance: none;
    appearance: none;
    font-family: inherit;
    text-align: left;
    text-decoration: none;
    color: inherit;
}

/* Top gloss */
html body .cat-tile::before,
html body .catalog-cat-tile:not(.sub-level)::before,
html body .subcat-tile::before,
html body .subcat-tile-item::before,
html body .app-tile::before,
html body .sol-comp-card::before,
html body .category-card::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 50%;
    background: var(--tile-gloss);
    z-index: 2;
    pointer-events: none;
}

/* Highlight that sweeps across on hover */
html body .cat-tile::after,
html body .catalog-cat-tile:not(.sub-level)::after,
html body .subcat-tile::after,
html body .subcat-tile-item::after,
html body .app-tile::after,
html body .category-card::after {
    content: '';
    position: absolute;
    top: 0;
    left: -100%;
    width: 40%;
    height: 100%;
    background: var(--tile-sweep);
    transform: skewX(-20deg);
    z-index: 2;
    transition: left 0.6s ease;
    pointer-events: none;
}

/* Hover hop: the tile springs past its resting lift, dips, then settles
   on it. The animation drives the transform while it plays and hands back
   to the resting lift below, so the tile stays raised while hovered. */
@keyframes tile-hop {
    0%   { transform: translateY(0); }
    40%  { transform: translateY(-7px); }
    68%  { transform: translateY(-1px); }
    86%  { transform: translateY(-4px); }
    100% { transform: translateY(-3px); }
}

html body .cat-tile:hover,
html body .catalog-cat-tile:not(.sub-level):hover,
html body .subcat-tile:hover,
html body .subcat-tile-item:hover,
html body .app-tile:hover,
html body .category-card:hover {
    transform: translateY(var(--tile-lift));
    box-shadow: var(--tile-shadow-hover);
    outline-color: var(--tile-outline-hover);
    animation: tile-hop 0.75s cubic-bezier(0.33, 1, 0.68, 1);
}

html body .cat-tile:hover::after,
html body .catalog-cat-tile:not(.sub-level):hover::after,
html body .subcat-tile:hover::after,
html body .subcat-tile-item:hover::after,
html body .app-tile:hover::after,
html body .category-card:hover::after {
    left: 200%;
}

/* A hop is exactly the kind of motion to drop when the OS asks for less */
@media (prefers-reduced-motion: reduce) {
    html body .cat-tile:hover,
    html body .catalog-cat-tile:not(.sub-level):hover,
    html body .subcat-tile:hover,
    html body .subcat-tile-item:hover,
    html body .app-tile:hover,
    html body .category-card:hover { animation: none; }
}

html body .cat-tile.active,
html body .catalog-cat-tile:not(.sub-level).active,
html body .subcat-tile.active,
html body .subcat-tile-item.active,
html body .app-tile.active,
html body .sol-comp-card.active,
html body .category-card.active {
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
    outline-color: var(--primary-color, #20d21a);
}

/* Picture fills the whole tile and eases in on hover */
.cat-tile-img,
.subcat-tile-img img,
.app-tile-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    z-index: 0;
    transition: transform 0.3s ease;
}
.cat-tile:hover .cat-tile-img,
.subcat-tile:hover .subcat-tile-img img,
.app-tile:hover .app-tile-img { transform: scale(1.05); }

/* Caption block, pinned to the top and sitting on the picture */
.cat-tile-overlay,
.subcat-tile-overlay,
.app-tile-overlay {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    z-index: 1;
    padding: 10px 14px 40px;
    background: linear-gradient(to bottom, rgba(0, 0, 0, 0.25) 0%, transparent 60%);
}
.cat-tile-label,
.subcat-tile-label,
.app-tile-label,
.catalog-cat-tile:not(.sub-level) span,
.category-card h4 {
    position: relative;
    z-index: 3;
    margin: 0;
    font-size: var(--tile-label-size);
    font-weight: 400;
    color: #fff;
    line-height: 1.25;
    /* No right padding: the arrow is pinned to the BOTTOM right, so the
       label never collides with it. */
    padding-right: 2px;
    /* Wrap rather than run off the tile — the longer Russian category
       names are wider than a column. break-word is a backstop for a
       single word longer than the tile; hyphens stay off here, since the
       markup says lang="en" until navbar.js sets the real language. The
       home-page grids opt in (catalogue.css), where 6-up tiles are too
       narrow for «Гидрораспределители». */
    white-space: normal;
    overflow-wrap: break-word;
    hyphens: manual;
    text-shadow: var(--tile-caption-shadow);
}
.cat-tile-count,
.category-card .card-type {
    font-size: var(--tile-count-size);
    color: rgba(255, 255, 255, 0.72);
    margin-top: 2px;
    text-shadow: var(--tile-caption-shadow);
}
.cat-tile-arrow,
.app-tile-arrow {
    position: absolute;
    bottom: 10px;
    right: 12px;
    width: 16px;
    height: 16px;
    z-index: 2;
    color: rgba(255, 255, 255, 0.75);
    transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1), color 0.3s ease;
}
.cat-tile.active .cat-tile-arrow,
.app-tile.active .app-tile-arrow {
    transform: rotate(180deg);
    color: var(--primary-color, #20d21a);
}

/* Filler tiles that pad a short row out to the full column set.
   Decorative only: same material and geometry, but empty, inert, and
   without the hover lift or the sweep. */
html body .cat-tile.blank-tile,
html body .app-tile.blank-tile {
    background-color: var(--tile-bg);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.05);
    cursor: default;
    pointer-events: none;
}
html body .cat-tile.blank-tile::after,
html body .app-tile.blank-tile::after { display: none; }
:root[data-theme="light"] html body .cat-tile.blank-tile,
:root[data-theme="light"] html body .app-tile.blank-tile {
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.05);
}

/* An application tile with nothing to open yet: still a picture on the wall,
   but it does not answer a click, so it drops the chevron and every hover
   affordance. solutions.js removes the class from any tile the CRM has
   filled a components menu in for. Beats the :hover rules above at (0,3,2)
   — restating them one class higher rather than reaching for !important. */
html body .cat-tile.is-inert { cursor: default; }
html body .cat-tile.is-inert .cat-tile-arrow { display: none; }
html body .cat-tile.is-inert:hover {
    transform: none;
    box-shadow: var(--tile-shadow);
    outline-color: transparent;
    animation: none;
}
html body .cat-tile.is-inert:hover::after { left: -100%; }

/* --- Geometry variants: same material, different footprint --- */
html body .cat-tile,
html body .catalog-cat-tile:not(.sub-level),
html body .subcat-tile,
html body .app-tile {
    height: var(--tile-height);
}
/* Sublevel chips: a short, centred tile rather than a picture-forward one */
html body .subcat-tile-item {
    height: 70px;
    flex: 1 0 160px;
    max-width: 240px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 10px 14px;
    text-align: center;
}
html body .category-card {
    min-height: 120px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 20px;
}
/* Solution component columns: a tall reading card, not a control. It takes
   the tile material and the gloss but deliberately sits out the hover hop
   and the sweep above — the card itself does nothing when clicked; the pill
   at its foot is what is clickable, and a card that springs under the
   cursor promises otherwise. Width and stacking are layout, and live with
   the rest of the grid in catalogue.css. */
html body .sol-comp-card {
    height: auto;
    display: flex;
    flex-direction: column;
    cursor: default;
    /* Padding lives HERE, not in catalogue.css: the shared tile rule above
       sets `padding: 0` at (0,2,1) and beat the component file's plain
       `.sol-comp-card` (0,1,0), so the card rendered edge-to-edge however
       much padding that file asked for. Same reason as every other geometry
       variant in this section. */
    padding: 18px;
    /* Unlike the picture-forward tiles this one is mostly text on the
       panel's own dark ground, so it carries its stroke at rest and only
       brightens it on hover. The outline property is already in the shared
       rule — this variant just gives it a resting colour. */
    outline-color: var(--tile-outline-rest);
}
/* Caption block of a subcat tile: scrim + label in one element */
html body .subcat-tile .subcat-tile-name {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1;
    padding: 10px 14px 40px;
    background: linear-gradient(to bottom, rgba(0, 0, 0, 0.25) 0%, transparent 60%);
    font-size: var(--tile-label-size);
    font-weight: 400;
    line-height: 1.25;
    color: #fff;
    text-align: left;
    white-space: normal;
    overflow-wrap: break-word;
    text-shadow: var(--tile-caption-shadow);
    box-sizing: border-box;
}
html body .subcat-tile .subcat-tile-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 0;
}

/* Tile grids share one gap so rows line up across the page */
.cat-tile-grid,
.subcat-tile-grid,
.subcat-grid,
.category-grid { gap: var(--tile-gap); }


/* --- Light theme: the caption sits on a light scrim, not a dark one --- */
:root[data-theme="light"] .cat-tile-overlay,
:root[data-theme="light"] .subcat-tile-overlay,
:root[data-theme="light"] .app-tile-overlay,
:root[data-theme="light"] html body .subcat-tile .subcat-tile-name {
    background: linear-gradient(to bottom, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.6) 60%, transparent 100%);
}
/* .subcat-tile-label is deliberately absent: it only ever labels a
   .subcat-tile-item, which lives in the underground layer and keeps its dark
   glass in this theme, so its label stays white. */
:root[data-theme="light"] .cat-tile-label,
:root[data-theme="light"] .app-tile-label,
:root[data-theme="light"] .catalog-cat-tile:not(.sub-level) span,
:root[data-theme="light"] .category-card h4,
:root[data-theme="light"] html body .subcat-tile .subcat-tile-name {
    color: #1d1d1f;
}
:root[data-theme="light"] .cat-tile-count,
:root[data-theme="light"] .category-card .card-type { color: rgba(0, 0, 0, 0.55); }
:root[data-theme="light"] .cat-tile-arrow,
:root[data-theme="light"] .app-tile-arrow { color: rgba(0, 0, 0, 0.25); }

/* --- Narrow screens: tiles shrink, fillers drop out --- */
@media (max-width: 768px) {
    html body .cat-tile,
    html body .catalog-cat-tile:not(.sub-level),
    html body .app-tile {
        height: 110px;
        padding: 0;
    }
    /* The grids reflow to auto-fill here, so the fillers no longer complete
       a row — they would just add an empty one. */
    html body .cat-tile.blank-tile,
    html body .app-tile.blank-tile { display: none; }
    html body .subcat-tile {
        width: 100%;
        height: auto;
        aspect-ratio: 1 / 1;
    }
    html body .subcat-tile-item { height: 56px; }
    html body .sol-comp-card { padding: 16px; }
    .cat-tile-label,
    .subcat-tile-label,
    .app-tile-label,
    html body .subcat-tile .subcat-tile-name { font-size: 12px; }
}


/* ============================================================
   DELIBERATE EXCLUSIONS

   These are buttons in markup but not buttons in the design — they own a
   surface of their own, and pulling them into the pill above would repaint
   the navigation. They keep their own rules in main.css / eshop.css /
   catalogue.css:

     .nav-tab, .icon-btn, .menu-toggle-btn   navbar segments
     .sidebar-nav-btn, .sidebar-submenu-btn  catalogue sidebar rows
     .catalog-cat-tile:not(.sub-level).sub-level             breadcrumb chips
     .qty-action                             inline steppers inside a cart pill
     .calc-tab, .cfg-pill, .cfg-opt          segmented pickers in the
                                             converter and configurator
     .toggle-switch, .cfg-switch, .rocker    switches, not buttons
     .contact-toggle-option                  segmented control (footer.css)
     .product-card                           expandable list row, not a tile
   ============================================================ */
