/* uc-catalog.css -- the catalogue listings. F4.5, stop `S29`.
 *
 * SOURCE OF RECORD: mockups/listing-build.py EXTRA_CSS, the F3.8 artefact the
 * owner signed off on 2026-09-08 over six cases -- category, series, vendor,
 * the brand index, the empty-result state and the empty listing. ADR 0038
 * decision 3: what the mockup draws is what ships. Every value here is that
 * file's; what changed is scoping, and the list is complete:
 *
 *   * `.uc X` -> `X`. The review shell wrapped each case in a `.uc` frame at a
 *     fixed width; the page has no such wrapper.
 *   * `.uc[data-w="1440"]` and `[data-w="1200"]` -> `@media (min-width:1200px)`,
 *     which is the chrome's one breakpoint (uc-chrome.css). The mockup switched
 *     frames by attribute because it draws four widths at once, and the 1200
 *     and 1440 rules were always identical.
 *   * `.uc[data-w="390"]` -> `@media (max-width:767.98px)`, the same boundary
 *     uc-chrome.css uses for the footer's stack.
 *   * `.ds-btn`, `.ds-btn--primary`, `.ds-btn--secondary` and the icon rule are
 *     NOT shipped. The generator declares them because a mockup has no access
 *     to the design system's stylesheet; uc-ds.css has owned that geometry
 *     since F4.1, and two copies of 44/18/8/15/600 is how they drift apart.
 *   * The review page's own furniture -- `.pg-demo`, `.case-h`, `.case-n` --
 *     is not shipped. It framed the cases and was never part of them.
 *
 * L16, and each of its five rules holds:
 *   NO TOKEN IS REDECLARED. --target, --measure, the spacing scale and the
 *     palette are uc-ds.css's. The one custom property declared here,
 *     `--cart-w`, is local geometry: the width of the pinned cart column, which
 *     nothing outside this file has an opinion about.
 *   NO PRIMITIVE'S GEOMETRY IS RESTATED -- see `.ds-btn` above.
 *   ONE BREAKPOINT, 1200px, plus the 767.98 stack. Both from uc-chrome.css.
 *   INTRINSIC SIZING, NOT A COLUMN COUNT -- `.cl-brands` fills with as many
 *     180px cards as fit, against Bootstrap's three hard breakpoints.
 *   NAMESPACE `.cl-`. `.ds-` is reserved and `.uc-` is not free: uc.css already
 *     defines `.uc-table-products`, `.uc_filter`, `.uc_popular-image` and
 *     `.filter-item-disabled`, which are the four uc.css rules these pages used
 *     and which die with Bootstrap at F4.8 (`S88`).
 *
 * The lightbox the vendor route's certificates use is uc-lightbox.css --
 * F4.4's, split out at this stop rather than written again (criterion 31).
 */

/* ADR 0046 decisions 2 and 3. This shell had NO cap -- not because anyone
   decided it should be full bleed, but because nobody wrote a rule. It takes
   the wide measure, and `--shell` is set on the shell itself so the masthead
   and the footer read 1440 on these pages and match the content between
   them. */
/* THE CAP THIS SHELL NEVER HAD. Not a new measure -- the same 1180 the chrome
   has always carried, and the same width Bootstrap's .container gave every
   page before the rewrite. Without it the content ran 1712 inside a 1180
   header at a 1792 viewport. `S116`. */
.cl-page{max-width:var(--shell);margin-inline:auto;padding:18px var(--gutter) 30px}


/* --- the breadcrumb ------------------------------------------------------ */
/* L15, in the product page's shape after its 2026-09-08 correction: the anchor
   carries the 44px because it IS the item; the separator hangs off the wrapper
   because it is the list's punctuation and not the link's text; the decoration
   is text-decoration because a border sits at the bottom of a 44px box and
   detaches from the text. */
.cl-crumb{display:flex;flex-wrap:wrap;gap:6px;align-items:center;
  font-size:12px;color:var(--mut);margin:0 0 6px}
.cl-crumb>[itemprop="itemListElement"]{display:inline-flex;align-items:center;gap:6px}
.cl-crumb>[itemprop="itemListElement"]:not(:last-child)::after{content:"\203A";
  color:var(--mut);flex:none}
.cl-crumb a{display:inline-flex;align-items:center;min-height:44px;min-width:44px;
  color:var(--sec);text-decoration:underline;text-decoration-color:var(--rule);
  text-underline-offset:3px}
.cl-crumb a:hover{text-decoration-color:var(--sec)}

.cl-h1{font-size:21px;font-weight:600;line-height:1.25;margin:0 0 6px;letter-spacing:-.01em}
.cl-lede{margin:0 0 14px;font-size:14px;line-height:1.55;color:var(--sec);max-width:88ch}

/* --- L4: the filter is never above the products -------------------------- */
/* The census measured .uc_filter at 954px tall starting at y=140, so the first
   product began at y=1114 on a 700px viewport: push/pull apply at md and above,
   so below 992 the DOM order wins. 53.4% of organic sessions are mobile.
   §5.3 answers it with a bar plus the dialog the chrome already ships, rather
   than inventing a third component -- the products start immediately and the
   whole sidebar is one tap away. */
.cl-bar{display:flex;align-items:center;gap:12px;margin:0 0 16px;padding:8px 0;
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule)}
.cl-bar .ds-btn{flex:none}
.cl-bar-n{font-size:13.5px;color:var(--mut)}
.cl-bar-n b{color:var(--ink);font-variant-numeric:tabular-nums}

.cl-cols{display:grid;grid-template-columns:minmax(0,1fr);gap:0}
/* Hidden below 1200 and reached through the bar. NOT moved below the products:
   a control nobody can find is not a differentiator. */
.cl-side-w{display:none}

/* --- the sidebar --------------------------------------------------------- */
/* `overflow: visible` AND NOT `hidden`, WHICH IS WHAT MAKES THE FOOTER STICK.
   `overflow: hidden` makes an element a scroll container, and a sticky child
   pins to its nearest scrolling ancestor -- so with it the footer stuck to a
   panel that never scrolls, which looks exactly like sticky not working. The
   rule was there to clip children at the 10px radius; the only child with a
   background of its own is the footer, and it carries the matching corners
   below. */
.cl-side{border:1px solid var(--rule);border-radius:10px;overflow:visible;
  background:var(--surface)}
.cl-side-h{padding:12px 14px;font-weight:600;font-size:14px;
  border-bottom:1px solid var(--rule)}

/* §5.3 -- the panel INSIDE the dialog. The dialog already says «Подбор» in its
   own heading, and the panel's card frame inside the dialog's card frame is a
   box in a box. Added at the port because the artefact drew the dialog as a
   closed button and never showed the panel in it. */
.cl-dlg .cl-side{border:0;border-radius:0}
.cl-dlg .cl-side-foot{border-radius:0}
.cl-dlg .cl-side-h{display:none}
/* AND IT SCROLLS. `.dlg` is a flex column with `overflow: hidden` and a
   measured height cap, and the callback dialog's scroller is `.dlg-form` --
   which this dialog does not have, so nothing scrolled and the facets below the
   fold were unreachable. The owner, 2026-09-08. `min-height: 0` is what lets a
   flex child shrink below its content and actually overflow. */
.cl-dlg .dlg-body{padding:0;min-height:0;flex:1;overflow-y:auto;
  -webkit-overflow-scrolling:touch}
.cl-f{padding:12px 14px;border-bottom:1px solid var(--rule)}
.cl-f-h{font-size:11.5px;text-transform:uppercase;letter-spacing:.05em;
  color:var(--mut);margin:0 0 4px;font-weight:600}
/* L9 and ADR 0043: THE ROW IS THE TARGET. Measured on the live page, all 70
   controls in this sidebar are under 44px -- 13, 18, 23 and 34 -- on the page
   whose filter is the site's stated differentiator. A <label> is already full
   width, so unlike a table cell it needs no negative margin: it carries the
   height and the checkbox rides inside it. */
.cl-opt{display:flex;align-items:center;gap:10px;min-height:44px;
  margin:0 -14px;padding:0 14px;font-size:13.5px;cursor:pointer;color:var(--ink)}
.cl-opt:hover{background:var(--ground)}
.cl-opt input{width:17px;height:17px;flex:none;accent-color:var(--brand)}
/* L7: the marking is real, and so is this data. These are the options with
   nothing left once `type=мобильный` is set -- 294 products become 4, and 13 of
   14 vendors go. What is wrong today is not the marking but its freshness:
   init_choices is fixed at worker start, which is A10 and ADR 0042 decision 4. */
/* MARKED, AND STILL SELECTABLE -- the owner, 2026-09-08, and it is what L7
   asks for in as many words: «an unavailable choice is marked, and the marking
   is true». Marked, not disabled. Within one facet the filter is OR, so
   ticking a greyed brand WIDENS the result rather than emptying it; disabling
   it forces the visitor to clear the first brand before they can add a second,
   which is two interactions to express one thought. The grey says «this adds
   nothing to what you have narrowed to», and that is all it should say. */
.cl-opt.is-off{color:var(--mut)}
.cl-opt.is-off span{opacity:.75}
.cl-more{display:flex;align-items:center;min-height:44px;margin:0 -14px;
  padding:0 14px;border:0;background:none;color:var(--brand);font:inherit;
  font-size:13px;cursor:pointer;width:calc(100% + 28px)}
.cl-range{display:flex;align-items:center;gap:8px}
.cl-range input{flex:1;min-width:0;min-height:44px;padding:0 10px;font:inherit;
  font-size:13.5px;border:1px solid var(--rule);border-radius:8px;
  background:var(--surface);color:var(--ink)}
.cl-range-d{color:var(--mut)}
/* PINNED, because the panel is taller than any screen it is shown on and the
   control was below the fold on five of the six busiest categories. Measured
   2026-09-08 on /c/radiatory in the dialog: the panel is 1,368px in a 752px
   viewport, «Показать» sat 498px past the bottom, and there was 1,250px
   between the first facet and it. At the 282px column width the panel is
   1,865px for Водонагреватели, 1,682 for Насосы, 1,641 for Полотенцесушители
   and 1,638 for Кондиционеры -- only Запорная арматура, at 611px, ever fitted.
   The owner's, 2026-09-08.

   IT IS ALSO WHAT MAKES THE LIVE COUNT HONEST. «Показать N» already updates as
   you tick (L6); before this the page gave you the number and then asked you
   to go and find the control that acts on it. */
.cl-side-foot{position:sticky;bottom:0;z-index:2;padding:12px 14px;
  display:grid;gap:6px;background:var(--surface);border-top:1px solid var(--rule);
  border-radius:0 0 10px 10px}
.cl-apply{width:100%}
.cl-reset-b{display:flex;align-items:center;justify-content:center;min-height:44px;
  font-size:13.5px;color:var(--mut);text-decoration:none}
/* Above the products and outside the panel -- the panel is behind a dialog
   below 1200, so this is the only place the applied filters are visible at the
   width where it matters most. The × is a 44px target like everything else. */
.cl-chips{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin:0 0 16px}
/* THE PILL IS A CONTROL, NOT A LINK, and it must not read as one -- the owner,
   2026-09-08. It is an <a href> so that removing a filter works with no
   JavaScript and a crawler can see where it goes, but what it does is reset one
   filter, so it takes no underline. `:where(a)` in uc-ds.css sets one on every
   link by default, and text-decoration propagates into the × as well. */
.cl-chip,.cl-chip:hover{text-decoration:none}
.cl-chip{display:inline-flex;align-items:center;gap:8px;min-height:44px;
  padding:0 14px;border-radius:999px;background:var(--ground);
  border:1px solid var(--rule);font:inherit;font-size:13.5px;color:var(--ink);
  cursor:pointer}
.cl-chip:hover{background:var(--surface);border-color:var(--brand)}
.cl-chip i{font-style:normal;color:var(--mut)}
.cl-chip-x{color:var(--mut);font-size:17px;line-height:1}
.cl-reset{display:inline-flex;align-items:center;min-height:44px;
  font-size:13.5px;color:var(--mut)}

/* --- the list ------------------------------------------------------------ */
/* THE SECOND LEVEL, DRAWN AS ONE. Owner, 2026-09-08: is this the right size?
   No -- the markup had it right and the styling had it backwards. The page is
   category (h1) → vendor (h2) → series (h3), and the h2 was rendering at
   11.5px uppercase against the h3's 16px, so the outer level read as a label
   on the inner one. A rule above it and 19px semibold put the three back in
   order. On the vendor route the same element carries the CATEGORY name, which
   is the same level doing the same job -- ADR 0041 decision 5. */
.cl-g{font-size:19px;font-weight:600;color:var(--ink);margin:32px 0 14px;
  padding-top:16px;border-top:2px solid var(--rule);letter-spacing:-.01em}
.cl-main>.cl-g:first-child{margin-top:0;padding-top:0;border-top:0}
.cl-s-name{font-size:15.5px;font-weight:600;margin:0 0 4px;line-height:1.3;
  color:var(--ink)}
/* ADR 0043: a link is a target, so the heading line carries the 44px rather
   than being 20px of text. inline-flex, not flex, so the box stops at the
   title instead of spanning a column of empty space to its right. */
.cl-s-name a{display:inline-flex;align-items:center;min-height:44px;
  color:var(--ink);text-decoration:underline;text-decoration-color:var(--rule);
  text-underline-offset:4px}
.cl-s-name a:hover{text-decoration-color:var(--brand)}
h1.cl-s-name{font-size:21px;letter-spacing:-.01em}
.cl-s{margin:0 0 26px}
.cl-s-h{display:flex;gap:14px;align-items:flex-start;margin:0 0 10px}
.cl-s-h img{width:100px;height:100px;object-fit:contain;flex:none;
  background:var(--ground);border-radius:8px}
.cl-noimg{width:100px;height:100px;flex:none;background:var(--ground);border-radius:8px}
.cl-s-t{min-width:0}

/* ADR 0041 decision 8: short_description renders unclamped, on every route --
   the owner's decision of 2026-09-07, and its length is the manager's
   judgement rather than the template's. The measure caps the LINE and not the
   block, which is F3.7's own correction. */
/* overflow-wrap AND the paragraph reset ADDED AT THE PORT, 2026-09-08, and
   both because the mockup drew one description and the catalogue has 978.
   The field is CKEditor content: it arrives as <p> markup, and one series
   in Arbonia's radiators carries a URL as an unbroken 327 px token inside
   a 244 px column, which widened the PAGE to 457 px at a 390 px viewport.
   Measured by the listing slice of chrome-harness.py on its first run. */
.cl-s-d{margin:0 0 4px;font-size:13.5px;line-height:1.6;color:var(--sec);
  max-width:88ch;overflow-wrap:anywhere}
.cl-s-d p{margin:0 0 4px}
.cl-s-d p:last-child{margin-bottom:0}

/* The wrapper is the scroller, so a wide table never pushes the PAGE sideways
   -- criterion 12's shape, and the same rule the product page uses. */
.cl-tw{overflow-x:auto;-webkit-overflow-scrolling:touch;border:1px solid var(--rule);
  border-radius:10px;background:var(--surface)}
/* THE SKIN IS `.ptable` IN uc-ds.css NOW -- S97, F4.8b. Width, collapse, font
   size, the th and td treatment, the zebra and the model link moved there and
   are shared with the product page's variants table. What is left below is this
   surface's own: the frame, the pinned price and cart columns, the model
   column's width, and the 44px cover. */
/* ADR 0043, and the mechanism §5.1 left to this round. 12px above and below a
   20.25px line box is 45.25px, so EVERY row clears 44 whether or not it holds a
   link -- that is what stops a table being ragged. The model anchor is then
   pulled out over the cell's padding and puts it back as its own, so its border
   box IS the cell's padding box and the target is the whole cell rather than a
   44x44 square around the text. The margin and the padding are the same 12px;
   changing one without the other breaks the cover. */
/* height:1px IS NOT A HEIGHT. It makes the cell's specified height DEFINITE,
   which is the only way a percentage height on a child of a <td> resolves; the
   row still stretches the cell to whatever its tallest sibling needs. Without
   it the anchor stops at its own 44px minimum while the row goes to 68 because
   the cart cell is taller -- measured here on the first build, 44 against 68,
   and that fails ADR 0043's own criterion. The product page never showed this
   because there the model cell IS the tallest; the mechanism is per-surface,
   which is what §5.1 handed to this round. */
/* MIDDLE, NOT TOP. Owner, 2026-09-08: «add to cart text on the button is
   aligned, and then the rest of the text in a row looks odd against it». The
   button is a 44px flex box and centres its own label, so with top-aligned
   cells the two only agreed while every cell was one line -- and the model
   column wraps to two on most rows, which is exactly when it stopped agreeing.
   Top alignment is the right default for a table of prose; this is a table of
   single values beside a control, and the control sets the line. */
/* height:1px is the ONLY declaration this surface still needs on a td, and it is
   not cosmetic: it is what lets `.cl-m a`'s percentage height resolve, which is
   what makes the model link cover the whole cell. Everything else -- padding,
   vertical-align, border, white-space, colour, zebra -- is `.ptable`'s. */
.cl-t td{height:1px}
/* Capped, and allowed to break. Uncapped, a model like «ELETTO DC-Inverter
   CAS25CX1/R3-W / 1U25CX1/R3» takes 360px of a 1042px wrapper and pushes the
   table to 1144 -- so the one column that can wrap was the one making the
   table too wide. */
/* td.cl-m, NOT .cl-m: `.cl-t td` is (0,2,1) and `.cl-m` is (0,2,0), so
   the nowrap above wins on specificity and the model never wraps -- it just
   spills across the next column, which is what the first build did. */
/* `.ptable` already unwraps the first column; the widths are the listing's,
   measured at F4.5 against a 1042px wrapper. */
/* THE LISTING'S CELLS WRAP, and the shared skin's do not. `.ptable td` is
   `white-space:nowrap` and stays that way for the product page's variants
   table, which has fewer columns, no cart and fits 1180 already.

   THIS IS WHAT LETS THE PAGE HAVE ONE WIDTH. Measured 2026-09-10 on
   `/c/vodonagrevateli`, whose widest table is ACV Smart Line SLE at eight
   columns: nowrap on the cells cost 81px, `.cl-m`'s 190px floor 112px and the
   price column's 96px floor 26px. Removing all three takes the table from a
   1075px minimum to 864 -- production's Bootstrap table fits the same eight
   columns in 848, and it fits because it wraps.

   THE COST IS ROW HEIGHT: 69px becomes 106px. «525 x 845 x 525 мм» and
   «13.10 л/мин» break across lines. That is the bargain production already
   makes and the owner's decision of 2026-09-10, taken after seeing both:
   one page width is the requirement, and horizontal scroll inside the table
   is what it would otherwise cost.

   PADDING IS NOT PART OF THIS. 12px would save another 8, and it is load
   bearing: `.cl-m a` covers the cell with `margin:-12px;padding:12px` and
   ADR 0043's 44px row depends on the two being the same number. */
.cl-t td{white-space:normal}
.cl-t td.cl-m{max-width:250px}
/* flex and centred, not block: the cell is vertically centred now, but a block
   anchor stretched over it still puts its text at the top, so the model sat
   14px above the values beside it -- the same complaint one level in. */
/* The 44px cover is this surface's -- the variants table has no cart column
   setting the row height, so it never needed one. Colour and underline come
   from `.ptable td:first-child a`. */
.cl-m a{display:flex;align-items:center;margin:-12px;padding:12px;min-height:44px;
  height:calc(100% + 24px);box-sizing:border-box;overflow-wrap:anywhere}
.cl-m a:hover{text-decoration-color:var(--brand)}
/* THE TWO COLUMNS THAT SELL DO NOT SCROLL AWAY. Found while reviewing the
   first build: at 1010 the conditioner table is six columns wide, the wrapper
   scrolls, and what goes off the right edge is the price and the cart -- so a
   table whose job is to sell showed everything except the price. Pinning them
   to the right edge keeps both in view at every width while the specification
   columns scroll underneath, and it costs nothing where the table already fits,
   because sticky in a container that does not overflow never moves.

   The offset is a variable rather than a number in two places: the cart cell's
   width is the only thing that decides where the price stops. */
/* MEASURED, NOT CHOSEN. Below 1200 both controls are a 44px icon button in
   12px of cell padding, so 68. At 1200 and above they carry their labels and
   «В корзину» measures 128, so 156. Get this wrong and the pinned cart column
   simply covers the pinned price -- which is what the first build did. */
.cl-t{--cart-w:68px}
.cl-t th:last-child,.cl-c{position:sticky;right:0;z-index:2;
  width:var(--cart-w);min-width:var(--cart-w)}
.cl-t th:nth-last-child(2),.cl-p,.cl-p-none{position:sticky;
  right:var(--cart-w);z-index:2}
/* A sticky cell scrolls OVER its neighbours, so it needs its own ground or the
   specification values slide visibly under transparent pixels. The zebra rule
   is repeated here for the same reason, at the specificity the sticky cells
   need. */
.cl-t th:last-child,.cl-t th:nth-last-child(2){background:var(--surface)}
.cl-t tbody tr:nth-child(odd) .cl-p,.cl-t tbody tr:nth-child(odd) .cl-p-none,
.cl-t tbody tr:nth-child(odd) .cl-c{background:var(--surface)}
.cl-t tbody tr:nth-child(even) .cl-p,.cl-t tbody tr:nth-child(even) .cl-p-none,
.cl-t tbody tr:nth-child(even) .cl-c{background:var(--ground)}
.cl-p{font-variant-numeric:tabular-nums;font-weight:600;white-space:nowrap;
  box-shadow:-8px 0 8px -8px rgba(23,39,43,.18)}
.cl-p-none{box-shadow:-8px 0 8px -8px rgba(23,39,43,.18)}
/* L10: 804 of 5,238 -- 15.3% -- have no price. Today they render «0 ₽» with an
   active «В корзину» and tell a crawler price 0 and «in stock». The wording is
   F3.7's and ADR 0038 makes it one answer on both surfaces. */
.cl-p-none{font-weight:400;color:var(--mut);font-size:13px;white-space:normal}
.cl-c{padding:8px 12px;text-align:right}
/* L11: the cart column stays. product-page.md §5.9 handed this here -- on a
   product page the variants table is a postscript, on a listing the table IS
   the page. It is the one column that is not per-category, and with L10 the one
   that changes state. */
.cl-c .ds-btn{white-space:nowrap;padding:0 12px}
.cl-buy span,.cl-ask span{display:none}

.cl-pg{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin:8px 0 0}
.cl-pg a,.cl-pg-c{display:inline-flex;align-items:center;justify-content:center;
  min-width:44px;min-height:44px;padding:0 10px;border-radius:8px;font-size:14px;
  text-decoration:none}
.cl-pg a{color:var(--sec);border:1px solid var(--rule)}
.cl-pg-c{background:var(--brand);color:#fff;font-weight:600}
.cl-pg-e{font-size:19px;line-height:1}
/* Disabled rather than absent, so the row does not shift when you reach an
   end -- and not a target either, because it goes nowhere. */
.cl-pg-e.is-off{color:var(--rule);border:1px solid var(--rule);
  display:inline-flex;align-items:center;justify-content:center;
  min-width:44px;min-height:44px;border-radius:8px}
.cl-pg-g{display:inline-flex;align-items:flex-end;justify-content:center;
  min-width:24px;min-height:44px;color:var(--mut)}
.cl-pg-t{margin-left:auto;font-size:12.5px;color:var(--mut);
  font-variant-numeric:tabular-nums}

/* §5.5 -- the state a filter combination produces when it matches nothing. Not
   the empty catalogue page: that one has no stock at all and is noindex; this
   is a live category narrowed to zero, and the way out is a filter, not a
   phone call. The pills above are the fix, so the buttons here name them. */
.cl-zero{max-width:56ch;padding:22px;border:1px solid var(--rule);
  border-radius:10px;background:var(--surface)}
.cl-zero-t{font-size:16px;font-weight:600;margin:0 0 8px;color:var(--ink)}
.cl-zero p{margin:0 0 14px;font-size:14px;line-height:1.6;color:var(--sec)}
.cl-zero-a{display:flex;flex-wrap:wrap;gap:10px;margin:0 0 14px}
.cl-zero-n{font-size:12.5px;color:var(--mut)}
.cl-apply[disabled]{opacity:.45;cursor:default}

.cl-jump{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 18px}
.cl-jump a{display:inline-flex;align-items:center;min-height:44px;padding:0 14px;
  border:1px solid var(--rule);border-radius:999px;font-size:13.5px;color:var(--sec);
  text-decoration:none}
.cl-also{margin:26px 0 0;padding-top:18px;border-top:1px solid var(--rule)}
.cl-also h2{font-size:15px;font-weight:600;margin:0 0 4px;color:var(--ink)}
.cl-also ul{list-style:none;margin:0;padding:0}
.cl-also li a{display:flex;align-items:center;min-height:44px;font-size:13.5px;
  color:var(--brand)}

/* --- the vendor's own half of the page ---------------------------------- */
/* Shaped like the series block: image left, name and prose right. It looked
   different in the first build for no reason other than that it was not drawn
   at all. */
.cl-v-head{display:flex;gap:18px;align-items:flex-start;margin:0 0 18px}
.cl-v-logo{flex:none;width:150px;height:80px;display:flex;align-items:center;
  justify-content:center;border:1px solid var(--rule);border-radius:10px;
  background:var(--surface);padding:10px}
.cl-v-logo img{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain}
.cl-v-body{min-width:0}
.cl-v-n{margin:0 0 8px;font-size:13px;color:var(--mut)}
.cl-v-d{margin:0 0 10px;font-size:14px;line-height:1.6;color:var(--sec);max-width:88ch}
.cl-v-site{display:inline-flex;align-items:center;min-height:44px;font-size:13.5px;
  color:var(--brand)}
/* L13 and criterion 28: this block survives, and its lightbox is F4.4's vanilla
   one. vendor.html:71 is the LAST $(...).fancybox() caller on the site, so this
   is where that library finally goes. Seven vendors have a certificate. */
.cl-v-certs{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:6px 0 0}
.cl-v-cl{font-size:11.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--mut)}
.cl-v-cert{display:block;border:1px solid var(--rule);border-radius:8px;padding:4px;
  background:var(--surface);min-height:44px}
.cl-v-cert img{display:block;max-height:76px;width:auto;height:auto}

/* The brand index. Intrinsic sizing, not a column count -- L16: the grid fills
   with as many 180px cards as fit, so 390, 1010 and 1440 need no separate
   rules. Today this is Bootstrap's col-xs-12 col-sm-6 col-lg-3, which is three
   hard breakpoints for a wall of tiles. */
.cl-brands{display:grid;gap:12px;
  grid-template-columns:repeat(auto-fill,minmax(180px,1fr))}
/* THE CARD IS THE TARGET -- ADR 0043, and here it is the natural shape: today
   the logo and the name are two separate links to the same address, one of
   them an image with no minimum and the other a 16.5px line of text. */
.cl-b{display:flex;flex-direction:column;align-items:center;gap:6px;
  min-height:150px;padding:14px 12px;border:1px solid var(--rule);border-radius:10px;
  background:var(--surface);text-decoration:none;color:var(--ink);text-align:center}
.cl-b:hover{border-color:var(--brand)}
/* THE SAME PICTURE TREATMENT AS `.card-pic` -- S98, the owner's decision of
   2026-09-09, on the question of why one surface framed the logo and the other
   did not. Measured that day across all 102 enabled vendors' logo files:
   56 have a WHITE background (55%), 36 are genuinely transparent (35%), and 10
   are opaque with a non-white one. So the common case is a white rectangle, not
   an alpha channel.

   `mix-blend-mode: multiply` is what makes that work on a tinted panel: white
   multiplies to the backdrop, so the logo's white rectangle becomes the panel
   and only the mark is left. Without it, 56 of 102 logos would sit in a white
   box inside a grey box. The index had no panel at all, which is why it also
   looked right -- white on white is invisible for the same reason -- but it
   left the 36 transparent logos with no defined edge.

   THE HEIGHT IS 170px AND MATCHES `.card-pic` -- the owner's, 2026-09-09, and
   the chain is theirs: the front page's vendor panel matches the series panels
   in «Сейчас популярно», and this matches the front page. Measured before the
   decision, both front-page rails are 170 already, so nothing moves there and
   only this file changes.

   ~~64px~~ was this page's own and is what the `S98` row defended on page
   length. The cost is real and was measured rather than estimated: at eight
   columns the page goes 2,981 -> 4,355 px, and at four columns the grid goes
   4,788 -> 7,756. The owner has it.

   WHAT 170 DOES NOT DO IS ENLARGE A LOGO. Every file is generated by
   easy-thumbnails at `height100`, so no logo is taller than 100px -- max 100,
   median 100, p25 87, min 26 across all 102. At the old 64px cap **82 of the
   102 were being scaled down**, and that is the visible gain here. Above 100
   the box only adds air: `max-height` never upscales, so a 100px logo sits in
   a 170px panel with 70px of empty ground under it, on this page and on the
   front page equally. That is stated so nobody reads 170 as a logo size. */
.cl-b-art{display:flex;align-items:center;justify-content:center;
  height:170px;width:100%;background:var(--ground);border-radius:var(--r-sm)}
.cl-b-art img{max-height:170px;max-width:100%;width:auto;height:auto;
  object-fit:contain;mix-blend-mode:multiply}
/* Seven brands have no logo. A named box beats an empty one, and F3.2 already
   falls back this way for Stiebel Eltron. */
.cl-b-type{font-size:17px;font-weight:600;color:var(--sec);letter-spacing:-.01em}
.cl-b-n{font-size:13.5px;font-weight:600;line-height:1.3}
.cl-b-m{font-size:12px;color:var(--mut);font-variant-numeric:tabular-nums}
/* The 20 brands with nothing in stock. Their pages stay live and noindex --
   S16, L12 -- so the card stays too, and says which it is. */
/* AN EMPTY BRAND CARD IS AN ORDINARY CARD WITH ONE LINE OF RED -- the owner's,
   2026-09-09. It used to carry three signals: a `--ground` card, a logo dimmed
   to 55% and the coloured count line. The first two are gone; the sentence is
   the signal.

   THE TRADE, STATED. The grey was added because the 20 brands with nothing in
   stock looked identical to the 89 that do, and dropping it gives back some of
   that -- the difference is now one line of text rather than the whole tile.
   It also removes a collision the panel introduced earlier the same day: with
   the card at `--ground` and `.cl-b-art` at `--ground` too, the logo panel was
   invisible on exactly these 20 cards.

   `var(--warn, …)` IS WHY THE COLOUR NEVER MOVED: `--warn` is not defined
   anywhere in uc-ds.css and never has been, so this has always rendered the
   fallback. Named honestly now. The value is unchanged -- it is `--accent`,
   F3.1's orange, which reads as red at 12px; whether a stock warning should be
   the accent or one of the `--danger-*` reds is a question for whoever settles
   `S116`'s measure work, and changing it here would move a colour the owner
   has just looked at and kept. */
.cl-b.is-empty .cl-b-m{color:var(--accent)}

.cl-empty{max-width:62ch}
.cl-empty-t{font-size:16px;font-weight:600;margin:0 0 8px;color:var(--ink)}
.cl-empty p{margin:0 0 14px;font-size:14px;line-height:1.6;color:var(--sec)}
.cl-empty-a{display:flex;flex-wrap:wrap;gap:10px;margin:0 0 16px}
.cl-empty-n{font-size:12.5px;color:var(--mut)}



/* --- 1200 and up: the sidebar is a column, not a dialog --------------- */
@media (min-width: 1200px) {
  /* 24 and not 40 -- the owner's, 2026-09-10, to give the widest table back
     32px of the 80 it is short at a 1180 page. Production's Bootstrap gutter
     was 15px each side, so 24 is still the more generous of the two. */
  .cl-page{padding:24px var(--gutter) 44px}
  .cl-h1{font-size:26px}
  .cl-bar{display:none}
  .cl-cols{
    /* gap 20, not 32 -- the same decision and the same reason: 12px more for
       the table. The sidebar's own width is UNCHANGED at 282, the owner's:
       narrowing the filter to win table width trades one thing the site is
       for another. */
    grid-template-columns:minmax(240px,282px) minmax(0,1fr);gap:20px;align-items:start}
  .cl-side-w{display:block}
  h1.cl-s-name{font-size:26px}
  .cl-t{--cart-w:156px}
  .cl-buy span,.cl-ask span{display:inline}
}

/* --- below 768: the stack --------------------------------------------- */
@media (max-width: 767.98px) {
  .cl-g{font-size:17px;margin:26px 0 12px}
  .cl-pg-t{margin-left:0;width:100%;margin-top:4px}
  .cl-v-head{flex-direction:column;gap:12px}
  .cl-brands{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px}
}


/* ======================================================================== */
/* THE SEARCH RESULTS PAGE. Phase F stop F4.6, `S30`'s search half.         */
/* ======================================================================== */

/* THE SPECIFICATION IS docs/phase-f/search.md and the markup is the F3.10
   artefact the owner signed off on 2026-09-08 (mockups/search-build.py).

   WHY IT IS IN THIS FILE AND NOT A SIXTH STYLESHEET. `Q13` says the search page
   declares nothing the design system already has, and after `Q3` (the card is
   the front page's, now in uc-ds.css) and `Q7` (the pager is F4.5's `.cl-pg`)
   what is left is five rules. The page needs `.cl-page`, `.cl-h1`, `.cl-pg`,
   `.cl-empty` and `.cl-jump` from this file anyway, so it loads this file and
   adds its five here. A uc-search.css would either be a copy of the pager and
   the empty state -- `S97`'s and `S98`'s defect for the third time -- or a file
   that cannot be loaded on its own.

   THE COST, STATED: /search/ loads 26 KB of catalogue stylesheet to use about a
   sixth of it. That is the price of one component rather than two, and it is
   the same trade F4.5 took when three routes became one file.

   WHAT IS NOT HERE, AND THAT IS THE POINT.
     .card and its children   uc-ds.css, moved there at this stop -- `Q3`
     the pager                .cl-pg above, unchanged and not re-declared
     the empty state          .cl-empty and .cl-jump above, ditto
     the page padding         .cl-page. The mockup called it `.se-page` and
                              declared the identical padding at both widths
     the heading step         .cl-h1. The mockup's `.se-h1` was 22px against
                              this file's 21px; a second type step for one page
                              is exactly what `Q13` forbids, so the search
                              heading is the catalogue's heading */

/* A query is a string a visitor typed and can be one 90-character token with no
   space in it. Without this the heading pushes the document sideways. */
.se-h1{overflow-wrap:anywhere}

/* Q6. The count, and the one word that says the list was cut. 53 of the 179
   queries that return anything hit MAX_MATCHES and take 28.6% of the weighted
   demand; today they show 17 pages with nothing to tell them apart from a query
   that genuinely matched 200. It is the count line and not a notice beside it --
   the owner's, 2026-09-08: a capped set is not an error state and a box around
   it says it is. */
.se-n{margin:0 0 14px;font-size:13.5px;color:var(--mut);
  font-variant-numeric:tabular-nums}

/* The grid the cards sit in. It is the search page's and not the front page's:
   `.fp .rail` is six across at its widest because six is what that block IS,
   and this is four.

   THE THREE BANDS ARE THE ARTEFACT'S FOUR FRAMES. F3.10 draws 390, 1010, 1200
   and 1440; the floor is 150px rather than the rail's 160px because a search
   card carries a category eyebrow the rail's cards do not, and 160 clipped it
   at 390. */
.se-grid{display:grid;gap:var(--s-3);
  grid-template-columns:repeat(auto-fill,minmax(150px,1fr))}

/* Q5, and the third surface to use one answer. `product-page.md` §5.5 and `L10`
   already fixed the wording; 142 of the 844 products that reach a first page --
   16.8% -- render «0 ₽» beside a working «В корзину» today. There is no cart
   control on a search card at all, priced or not, so unlike the listing this
   state replaces the price and nothing else. */
/* S97, F4.8b. The listing's quiet rendering, not 13.5px/600 -- three surfaces
   STATE this fact and they now state it the same way: the listing's
   `.cl-p-none`, the cart's `.ct-nostock` and this. 600 is the weight prices
   are set at, so a card with no price was emphasising its absence. The
   product page's `.pg-ask` is NOT part of this and is deliberately different:
   it is 20px in full ink with a subtitle and an «Оставить заявку» button,
   which is an offer rather than a label, and F3.7 decided it that way. */
.se-nostock{font-size:13px;font-weight:400;color:var(--mut)}

@media (min-width: 768px) {
  .se-grid{grid-template-columns:repeat(3,1fr)}
}
@media (min-width: 1200px) {
  .se-grid{grid-template-columns:repeat(4,1fr)}
}
