/* =============================================================================
   LONDON SPOT: layout.css
   The shared shell: topbar, header, search, catalog bar, category rail +
   mega-panel, mobile drawer, footer, mobile bottom bar.     [FOUNDATION owns]
   -----------------------------------------------------------------------------
   Load order, as every page actually links it:
       base.css → layout.css → components.css → <page>.css
   That is not the order this comment used to claim, and it matters: this
   sheet loads BEFORE components.css, so a single-class rule here loses to a
   single-class rule there. Where this file has to overrule a component
   (`.iconbtn`, `.btn`), it says so and uses a selector that wins on
   specificity rather than on order.
   Reuses every token, .icon, .dot, .mark, .linebar, .btn, .chip, .crumbs,
   .skeleton from base.css / components.css. Nothing is redefined.
   Mobile-first: every desktop rule is a min-width query.

      0  Shell contract (the chrome contract: scroll padding, body padding)
      1  Topbar            (≥768px)
      2  Main header       (brand only <768px, sticky from 768px)
      3  Search: inline dropdown, suggestions, mobile full-screen layer
      4  Catalog bar       (≥1024px)
      5  Category rail + mega-panel (the signature interaction, ≥1024px)
      6  Drawer: two-level push navigation (<1024px)
      7  Scrim
      8  Footer
      9  Mobile bottom bar (<768px)
     10  Breadcrumb bar, focus rings in clipping scrollers, press states,
         the status page (404.html)
     11  Reduced motion
   ========================================================================== */


/* ── 0. SHELL CONTRACT ─────────────────────────────────────────────────────
   Layers: the whole ladder is in base.css (design.md §4 "Layers"); this
   sheet only uses its rungs. A page stylesheet may use --z-pop, --z-sticky,
   --z-bar and --z-modal and nothing above them.

   THE CHROME CONTRACT (design.md §4 "Pinned bars", §14.13), for every page
   ------------------------------------------------------------------------
   Every band pinned to the top or the bottom of the window has its height
   in base.css (--bar-*), and the page pays for all of them once, here:
     · html's scroll padding keeps a focused control or an anchored heading
       --s-3 clear of the pinned chrome at both ends (WCAG 2.4.11);
     · body's bottom padding pays for the bottom band, so the page end is
       never under it. A page adds no padding of its own for a bar.
   --chrome-top is the pinned header (--hdr-h, published on <html> by
   layout.js: 0px below 768px, where the header scrolls away) plus the
   page's own sticky toolbar; --chrome-bottom is the bottom band plus the
   safe area. A page registers its own band ON :root, nowhere else, because
   the sums resolve on <html>:
       :root:has(.cx-tools){ --pin-top:var(--bar-tool) }           catalog
       :root:has(body.buybar-on){ --pin-bottom:var(--bar-call) }   product
   Fixed furniture a page pins to the bottom edge sits on the live nav band:
       bottom: calc(var(--bottombar) + env(safe-area-inset-bottom));
   and a sticky page toolbar sits under the header: top: var(--hdr-h).
   While the product call bar is on, the bottom bar leaves and --bottombar
   drops to 0px (§9), so the call bar lands in its place by that same rule.
   ---------------------------------------------------------------------- */
/* Measured values the scripts write, with their resting value. The two
   column widths the shell and the catalog stand on, --rail-w and
   --facet-w, are tokens in base.css (verify S-11). */
:root{
  --hdr-h:0px;             /* overwritten by layout.js (ResizeObserver)  */
  --sbw:0px;               /* scrollbar width, measured on scroll lock   */
}

html{
  scroll-padding-block:calc(var(--chrome-top) + var(--s-3))
                       calc(var(--chrome-bottom) + var(--s-3));
}
body{ padding-bottom:var(--chrome-bottom) }

/* Every tappable surface the shell owns. `manipulation` drops the 300ms
   double-tap-zoom wait; the tap highlight is turned off deliberately and
   only here, where each of these already answers a press with its own
   :active fill, so the feedback is the design's and not the platform's. */
.act, .bbi, .crow__a, .drow__a, .dback, .dsec__a, .sg__opt, .sg__rm, .sg__all,
.fcol__a, .topbar__a, .topbar__tel, .hdr__tel, .drawer__tel, .fphone__n,
.catbar__q, .fsocial__a, .hdr__brand, .fbrand__logo, .mega__all, .mega__sa,
.mega__ca, .mega__ba, .rail-more, .pmini, .lang a.seg__b{
  touch-action:manipulation;
  -webkit-tap-highlight-color:transparent;
}

/* The mount point must not box the header in. A sticky element can only
   travel inside its parent, and #ls-header is exactly as tall as the header
   it holds, so without this the sticky header scrolls away with the page.
   display:contents removes the wrapper's box; <body> becomes the containing
   block and the header pins to the viewport as intended.                  */
#ls-header{ display:contents }
/* The banner landmark inside it (layout.js tplHeader) holds the topbar, the
   header row and the catalog bar, and draws no box for the same reason:
   a box round all three would hold the sticky header row inside it. The
   element keeps its landmark with `display:contents`. */
.banner{ display:contents }

/* ...but an empty mount has to hold the header's place first. layout.js
   builds the header into #ls-header after the first paint, so until it lands
   the mount is an empty box of no height and everything below it starts at
   the top of the viewport, then drops by the whole header when the script
   runs. That is the same shift on every page, and it is the largest one left.
   `:empty` reserves the height and stops applying the moment layout.js fills
   the mount, so the reservation cannot outlive or fight the header it stands
   in for; `display:block` is what gives it a box to be tall, against the
   `display:contents` above.
   The reservation is the sum of the bands, from their tokens: the header
   row and its hairline everywhere; from 768px the topbar row and its 3px
   .linebar seam above it; and from 1024px on an inner page the catalog bar
   and its hairline under it (the home page draws no catalog bar: its rail
   host, #homeRail, is how both this rule and layout.js isHomePage() know
   it). Without that last term main dropped 53px when the bar landed (B16).
   While the test-mode notice is up, --bar-note stands for the seam from
   768px and adds the band below it (§ THE TEST-MODE NOTICE, below). */
#ls-header:empty{ display:block; height:calc(var(--bar-note) + var(--bar-hdr) + var(--bw-1)) }
@media (min-width:768px){
  #ls-header:empty{
    height:calc(var(--bar-topbar) + var(--bar-note) + var(--bar-hdr) + var(--bw-1));
  }
}
@media (min-width:1024px){
  :root:not(:has(#homeRail)) #ls-header:empty{
    height:calc(var(--bar-topbar) + var(--bar-note) + var(--bar-hdr) + var(--bw-1) +
                var(--bar-catbar) + var(--bw-1));
  }
}

/* The counted scroll lock of the overlay primitive (LS.lock, core.js):
   `overflow:hidden` on <html> (not <body>) keeps body{overflow-x:clip} and
   position:sticky intact, and the scrollbar's width is paid as --sbw. */
html.ls-lock{ overflow:hidden }
html.ls-lock body{ padding-right:var(--sbw) }

/* Shared surface for every panel that floats over the page: the card
   surface and the elevation, and no hairline. design.md §7 specifies the
   mega panel as --paper plus --sh-3; a 1px border under a 60px shadow drew
   the edge twice (audit B43). */
.pop-surface{
  background:var(--paper);
  border-radius:var(--r);
  box-shadow:var(--sh-3);
}


/* ── THE TEST-MODE NOTICE: written in the red line, and it stays ─────────
   While the site is in test mode (owner, 2026-09-30, DECISIONS.md) the red
   line carries the notice, white on --red (4.63:1, design.md §2). From
   768px it is the seam under the topbar, grown to one 32px line (--s-8);
   below 768px, where there is no topbar, it opens the page, 56px like the
   phone's header row and bottom bar, and each sentence takes a line of its
   own there, which keeps the height known. A short window from 568px wide
   (a phone on its side; the Georgian line and its sign are 524px, with the
   gutters 556) gets the one 32px line, so the pinned line costs it little.
   Whole pixels everywhere, so a band pinned under it (--hdr-h is rounded)
   leaves no sliver of the page showing between the two.
   It does not scroll away (owner): it pins at the top edge at every width.
   From 768px the header row pins under it; below 768px the header row
   still scrolls and the line is the one band at the top. That makes it the
   one exception to "a phone and a short window pin nothing at the top"
   (§14.13). layout.js counts it in --hdr-h, so html's scroll padding, the
   catalog's toolbar and every other pinned offset clear it.
   One sign opens it (owner): the outline alert, white strokes on the red,
   as tall as the text beside it. On a phone that is both lines: in a 40px
   box at the §5 tier for sizes over 32 (stroke 1.5) its triangle runs from
   the top of the first line's letters (4.2px into the text) to the second
   line's baseline (35.5px), measured on Google Sans. Below 360px it drops
   to 28px, because the second Georgian sentence is 251px and a 40px sign
   leaves it 240 at 320. On one line it is 20px (stroke 2). It stands on the
   container's edge, in line with the logo, and a second line of text starts
   under the first, not under the sign. The first sentence says what is
   going on (600), the second what it means for a shopper (400).
   The reservation above counts the line as --bar-note, so nothing moves when
   the header lands. To take it down: TEST_NOTE in layout.js to false, and
   --bar-note to 0px below 768px and 3px from 768px (the seam's own height).
   ---------------------------------------------------------------------- */
:root{ --bar-note:calc(var(--s-12) + var(--s-2)) }
@media (min-width:768px), (min-width:568px) and (max-height:500px){
  :root{ --bar-note:var(--s-8) }
}
.notebar{
  position:sticky; top:0; z-index:var(--z-hdr);
  background:var(--red); color:var(--on-fill);
  font-size:var(--t-small-ka); line-height:var(--lh-small-ka);
}
.notebar__in{
  display:flex; align-items:center; column-gap:var(--s-3);
  min-height:var(--bar-note);
}
.notebar__ic{ width:40px; height:40px; --sw:1.5 }
.notebar__t{ flex:1 1 0; min-width:0 }
.notebar__h{ display:block; font-weight:600 }
.notebar__d{ display:block; font-weight:400 }
@media (max-width:359.98px){
  .notebar__in{ column-gap:var(--s-1) }
  .notebar__ic{ width:28px; height:28px; --sw:1.75 }
}
@media (min-width:768px), (min-width:568px) and (max-height:500px){
  .notebar__in{ column-gap:var(--s-2) }
  .notebar__ic{ width:20px; height:20px; --sw:2 }
  .notebar__h, .notebar__d{ display:inline }
}
@media (min-width:768px){
  .notebar ~ .hdrwrap{ top:var(--bar-note) }
}


/* ── 1. TOPBAR: light surface, ≥768px only ────────────────────────────────
   Bottom edge is the .linebar: the site's one red hairline. That hairline is
   why the bar is light. --red on the dark surface is 2.38:1 and the 3px seam
   all but disappears; on --page-2 it is 4.08:1 and actually reads. A light
   strip above a --paper header also lifts the top of every page.
   ---------------------------------------------------------------------- */
.topbar{ display:none }

/* Between 768 and 1024 the delivery line, three links and the language
   toggle do not fit on one 44px row and the bar wraps to two. The links
   already live in the drawer at those widths, so they only appear at
   1024px, where there is room for all of it on one line, and the
   separator between them goes with them. The one inside the shop line,
   between the number and „მაღაზია:", stays from 768px: without it the two
   facts ran together with only the 8px gap between them (review S9). */
.topbar__a,
.topbar__nav .topbar__sep{ display:none }

@media (min-width:768px){
  .topbar{
    display:block;
    background:var(--page-2); color:var(--ink-2);
    font-size:var(--t-sm); line-height:var(--lh-sm);
  }
  /* 52, not 44. The language toggle in this row is a 44px control, so at a
     44px row it filled the bar edge to edge: the dark half of the pill ran
     from the top of the strip to the 3px red seam at the bottom of it with
     nothing between, which is what made a small utility control read as the
     heaviest thing on the page. Four pixels above and below it is all the
     row needed. The header reserve above matches. */
  .topbar__in{
    display:flex; align-items:center; justify-content:space-between;
    gap:var(--s-4); min-height:var(--bar-topbar); flex-wrap:wrap;
  }
  .topbar__ship{
    display:inline-flex; align-items:center; gap:var(--s-2);
    min-width:0; color:var(--ink); font-weight:500;
  }
  .topbar__ship .icon{ color:var(--ink-2) }
  /* The shop's number is a 44px target inside the 52px row (audit B17: it
     was the 22px line box). Its padding is cancelled by the margin so the
     number stays where the sentence puts it (design.md §14.2, optical). */
  .topbar__tel{
    display:inline-flex; align-items:center;
    min-height:44px; padding-inline:var(--s-1);
    margin-inline:calc(var(--s-1) * -1);
    border-radius:var(--r-xs);
    color:var(--ink);
    transition:background-color var(--d-hover) var(--ease);
  }
  .topbar__nav{ display:flex; align-items:center; gap:var(--s-1); flex-wrap:wrap }
  .topbar__sep{
    display:block;
    width:var(--bw-1); height:14px; flex:none;
    background:var(--bd-2);
  }
}

@media (min-width:1024px){
  .topbar__a{
    display:inline-flex; align-items:center;
    min-height:44px; padding-inline:var(--s-3);
    border-radius:var(--r-xs);
    color:var(--ink-2);
    transition:color var(--d-hover) var(--ease),
               background-color var(--d-hover) var(--ease);
  }
  .topbar__a[aria-current="page"]{ color:var(--ink); font-weight:600 }
  .topbar__nav .topbar__sep{ display:block }
}
/* Nav links on --page-2 (design.md §2 state table): hover is the ink and an
   underline, press a --bd fill. */
@media (hover:hover){
  .topbar__a:hover,
  .topbar__tel:hover{ color:var(--ink); text-decoration:underline; text-underline-offset:3px }
}
.topbar__a:active,
.topbar__tel:active{ background:var(--bd) }

/* ka / en: the language pair is the segmented control (.seg, components.css
   §15, design.md §6): the page's own language the pressed half, the other a
   link to this page in it, and until English is live the ENG half of a
   Georgian page a disabled half with its reason kept (layout.js tplLang).
   Only its place is set here: a 44px control in the 52px row, so there is
   air above the red seam (40px under a fine pointer from 1024px). */
.lang{ margin-inline-start:var(--s-3) }


/* ── 2. MAIN HEADER ────────────────────────────────────────────────────────
   Below 768px the header is ONE 56px row holding the brand, and it scrolls
   away with the page. Everything else that used to be in it lives in the
   bottom bar: search, cart, account. It used to be two rows, 109px tall,
   with a 53px sticky remainder, and it printed the search field, the
   wishlist heart and the cart badge a second time twenty pixels above the
   bar that already carried all three (AUDIT-visual §9.17). A phone now
   spends 56px of chrome on navigation, not 109px on two of everything.

   Not sticky, and that is the point. A fixed 56px bar at the top plus a
   fixed 56px bar at the bottom is 20 percent of a 568px screen gone before
   any content. The bottom bar is the one that stays, because it is the one
   with the destinations in it; a brand plate does not need to follow you
   down the page. There is no hide-on-scroll, because there is nothing to
   hide: the header simply scrolls, which costs no JS, no timing and no
   reduced-motion branch.

   ≥768px: one row, search inline, burger and actions back. ≥1024px: the
   catalog bar rides along and the burger goes (the rail takes over).
   ---------------------------------------------------------------------- */
.hdrwrap{
  --r1:var(--bar-hdr);          /* 56px, 72px from 768 (base.css)          */
  position:static;
  z-index:var(--z-hdr);
  background:var(--paper);
  border-bottom:var(--bw-1) solid var(--bd);
  transition:box-shadow var(--d-hover) var(--ease);
}
@media (min-width:768px){
  .hdrwrap{ position:sticky; top:0 }
  .hdrwrap.is-stuck{ box-shadow:var(--sh-1) }
}
/* A short window pins nothing at the top (design.md §14.13): a phone on its
   side spent 31 to 38% of its height on bars (audit M20). The header scrolls
   with the page there, and layout.js then publishes --hdr-h as 0px. */
@media (min-width:768px) and (max-height:500px){
  .hdrwrap{ position:static }
}

/* Below 768px: the brand, the other language and the shop's number (review
   S1). The language link stands at the end of the middle track, beside the
   number, and the track's free width is the air after the brand: 6.9px at
   320 (the three need 77.1 + 44 + 160 of 288), 46.9px at 360 and more
   above. No column gap, then: a 4px one would squeeze the link under its
   44px at 320. The number's own 8px padding is the air between the two. */
.hdr__in{
  display:grid; align-items:center;
  grid-template-columns:auto minmax(0,1fr) auto;
  grid-template-areas:"brand lang note";
  column-gap:0;
  min-height:var(--r1);
}
/* The link half of the language pair, alone (layout.js tplHdrLang): the
   pair's look and states (components.css §15), its halves compact as in the
   drawer's head, a 44px target. Hidden from 768px, where the topbar holds
   the whole pair. */
.hdr__in > .lang--hdr{
  grid-area:lang; justify-self:end;
  margin-inline-start:0;
}
.lang--hdr .seg__b{ padding-inline:var(--s-2) }

/* The phone's one line of the topbar: the shop's number, the only way to
   buy, in the space the header's controls left behind. From 768px the
   topbar carries it in full. The link is the icon and the number together,
   a 44px target inside the 56px band (audit M23: it was 22px tall). */
.hdr__note{
  grid-area:note; justify-self:end;
  display:flex; align-items:center; min-width:0;
  font-size:var(--t-sm); line-height:var(--lh-ui);
}
.hdr__tel{
  display:inline-flex; align-items:center; gap:var(--s-2);
  min-height:44px; min-width:0;
  padding-inline:var(--s-2); margin-inline-end:calc(var(--s-2) * -1);
  border-radius:var(--r-sm);
  color:var(--ink-2); white-space:nowrap;
  transition:background-color var(--d-hover) var(--ease), color var(--d-hover) var(--ease);
}
.hdr__tel .icon{ flex:none }
@media (hover:hover){ .hdr__tel:hover{ background:var(--page-2); color:var(--ink) } }
.hdr__tel:active{ background:var(--bd) }

/* The ≥768px controls: one rule, so there is one place to check what a
   phone does and does not show. The child combinator is not decoration:
   this sheet loads BEFORE components.css (index.html), so a bare
   .hdr__burger loses to .iconbtn's own display and the burger comes back.
   Every rule that switches these three carries the same shape.           */
.hdr__in > .hdr__burger,
.hdr__in > .hdr__acts,
.hdr__in > .hsearch--hdr{ display:none }

.hdr__burger{ grid-area:burger; margin-inline-start:calc(var(--s-2) * -1) }

/* The logo's box is its 44px target, centred in the row, not the row's
   whole height: below 768px the row starts at the top of the screen (and
   from 768px it pins there), and the ring round a box as tall as the row
   lost its top side off the screen (final accessibility check, 5). Now the
   ring stands whole outside the box, clear of the logo, whose wordmark
   runs to the image's edge. */
.hdr__brand{
  grid-area:brand;
  display:inline-flex; align-items:center;
  min-height:44px; min-width:0;
  border-radius:var(--r-xs);
  transition:transform var(--d-press) var(--ease-press);
}
.hdr__brand img{ height:30px; width:auto; max-width:100%; }
/* The press is the answer on touch (the platform's tap highlight is off in
   §0); the mark has no hover of its own, the pointer is the cue. */
.hdr__brand:active{ transform:scale(.97) }

.hdr__acts{
  grid-area:acts;
  align-items:center; gap:var(--s-1);
  justify-self:end; min-width:0;
  margin-inline-end:calc(var(--s-2) * -1);
}

/* one header action: icon + live count badge + (≥1280px) a label.
   design.md §2, the quiet button row: --ink-2 at rest, a --page-2 wash and
   --ink on hover, a --bd fill and the press scale under the thumb. */
.act{
  position:relative;
  display:inline-flex; flex-direction:column; align-items:center; justify-content:center;
  gap:var(--s-1); flex:none;
  min-width:44px; min-height:44px; padding-inline:var(--s-1);
  border-radius:var(--r-sm);
  color:var(--ink-2);
  transition:background-color var(--d-hover) var(--ease), color var(--d-hover) var(--ease),
             transform var(--d-press) var(--ease-press);
}
@media (hover:hover){ .act:hover{ background:var(--page-2); color:var(--ink) } }
.act:active{ background:var(--bd); transform:scale(.97) }
.act[aria-current="page"]{ color:var(--ink-strong) }
/* A count badge that lives inside a control which already names itself is
   drawn from its own attribute rather than from a text node: as text its
   digits would sit in front of the label and break WCAG 2.5.3, Label in
   Name (core.js §6, setCounter). One rule covers the header action, the
   bottom bar item and the drawer's wishlist row. */
[data-count-glyph]::after{ content:attr(data-n) }

/* the icon is the count badge's host (.count--icon, components.css) */
.act__ic{ position:relative; display:grid; place-items:center }
.act__l{ display:none; font-size:var(--t-small-ka); line-height:var(--lh-ui); font-weight:500 }
@media (min-width:1280px){
  .act{ flex-direction:row; gap:var(--s-2); padding-inline:var(--s-3) }
  .act__l{ display:inline }
}

@media (min-width:768px){
  .hdr__in > .hdr__burger{ display:inline-grid }
  .hdr__in > .hdr__acts{ display:flex }
  .hdr__in > .hsearch--hdr{ display:block }
  .hdr__in > .hdr__note,
  .hdr__in > .lang--hdr{ display:none }
  .hdr__in{
    grid-template-columns:auto auto minmax(0,1fr) auto;
    grid-template-areas:"burger brand search acts";
    column-gap:var(--s-4);
  }
  .hdr__brand img{ height:38px }
}
@media (min-width:1024px){
  /* the drawer is a phone/tablet affordance, the rail takes over here */
  .hdr__in > .hdr__burger{ display:none }
  /* The search is the dominant element: 45% of the header width, and it sits
     in the middle of it. Equal 1fr side columns are what centre it. With an
     `auto` brand column the field starts at the logo and the whole band reads
     as pushed left. Brand and actions then anchor to their own outer edges. */
  .hdr__in{
    grid-template-columns:minmax(0,1fr) minmax(280px,45%) minmax(0,1fr);
    grid-template-areas:"brand search acts";
    column-gap:var(--s-6);
  }
  .hdr__brand{ justify-self:start }
  .hdr__brand img{ height:42px }
  .hdr__acts{ gap:var(--s-1) }
}


/* ── 3. SEARCH ─────────────────────────────────────────────────────────────
   One controller, two hosts: the inline field (≥768px) and the full-screen
   layer, which below 768px is the only way to search and is opened from the
   bottom bar (FLOWS §2: "the header does not carry a second one"). Both
   render the same .sg listbox.
   ---------------------------------------------------------------------- */
.hsearch{
  grid-area:search;
  position:relative; min-width:0;
}

/* design.md §6 "Input / select": the one large field. The --bd-3 edge is
   3.37:1 on --paper, the 3:1 a control boundary needs (the --bd-2 edge was
   1.44:1, audit TC5). One magnifier, and it is the submit: a quiet icon
   button at the inline end; the clear × stands before it while there is
   text. The red „ძებნა" button, a second primary on every page, is gone
   (audit C20). */
.hsearch__box{
  display:flex; align-items:center; min-width:0;
  height:48px;
  background:var(--paper);
  border:var(--bw-1) solid var(--bd-3);
  border-radius:var(--r-sm);
  transition:border-color var(--d-hover) var(--ease);
}
@media (hover:hover){ .hsearch__box:hover{ border-color:var(--ink-3) } }
.hsearch__box:focus-within{ border-color:var(--focus) }
/* A text field shows the ring on any focus, a tap included: Chrome matches
   :focus-visible on a text input for every focus, and the system takes the
   platform's behaviour (design.md §6). The ring belongs to the box. */
.hsearch__box:has(.hsearch__in:focus-visible){
  outline:var(--ring) solid var(--focus); outline-offset:var(--ring-off);
}
.hsearch__in{
  flex:1 1 auto; min-width:0;
  height:100%; padding-block:0; padding-inline:var(--s-4) var(--s-2);
  border:0; background:transparent; outline:none;
  font-family:var(--f-ui); font-size:var(--t-body); color:var(--ink);
  appearance:none; -webkit-appearance:none;
  /* An input clips its placeholder mid-glyph; layout.js measures the field
     and picks the long or the short placeholder, this is the last resort. */
  text-overflow:ellipsis;
}
.hsearch__in::placeholder{ color:var(--ink-3); opacity:1 }
.hsearch__in::-webkit-search-cancel-button{ -webkit-appearance:none }
.hsearch__in:focus-visible{ outline:none }
/* The clear × and the submit are .iconbtn (components.css), 44px squares in
   the 46px inside of the box. CONCENTRIC CORNERS: the box is --r-sm (10px)
   over a 1px edge and a 1px gap, so an inner corner wants 8px; --r-xs is the
   rung below, and going over is the one wrong direction. Two classes deep,
   because components.css loads after this sheet. */
.hsearch__box > .iconbtn{ flex:none; border-radius:var(--r-xs) }
.hsearch__box > .iconbtn:last-child{ margin-inline-end:var(--bw-1) }

/* The layer submits with the keyboard's search key and with the
   „ყველა შედეგი" row, so it carries no submit (design.md §6).             */
.hsearch--layer .hsearch__go{ display:none }

/* inline suggestion dropdown ------------------------------------------- */
/* --sh-2, not the --sh-3 .pop-surface brings: this panel opens on a focus,
   dozens of times a session, and sits 4px under the field it belongs to. A
   mega-panel's shadow reads as "a layer arrived"; on a typeahead it reads as
   weather. The later rule wins on order, both being one class deep.       */
.hsearch__pop{
  position:absolute; z-index:var(--z-pop);
  top:calc(100% + var(--s-1)); inset-inline:0;
  max-height:min(70dvh, 560px); overflow:auto; overscroll-behavior:contain;
  padding:var(--s-2);
  box-shadow:var(--sh-2);
  /* The list is the answer to a keystroke, so it is on screen in the same
     frame; the fade only takes the hard edge off its arrival. Under reduced
     motion the duration tokens are 0s and it is simply there.            */
  animation:sg-in var(--d-press) var(--ease-out);
}
@keyframes sg-in{ from{ opacity:0 } to{ opacity:1 } }
.hsearch__pop[hidden]{ display:none }

/* the listbox itself: shared by the dropdown and the mobile layer.
   design.md §6 "List rows". */
.sg{ display:flex; flex-direction:column; min-width:0 }
/* a group label: the label role in --ink-2 at 600 (design.md §3) */
.sg__grp{
  display:flex; align-items:center; gap:var(--s-2);
  padding:var(--s-3) var(--s-3) var(--s-2);
  font-size:var(--t-small-ka); line-height:var(--lh-ui); font-weight:600; color:var(--ink-2);
}
.sg__grp + .sg__opt{ margin-top:0 }
/* A quiet line, not an option: the catalogue is still in flight, or it did
   not arrive. It is not selectable and ↓ does not stop on it.             */
.sg__note{
  padding:var(--s-3); color:var(--ink-2);
  font-size:var(--t-sm); line-height:var(--lh-sm);
}
.sg__opt{
  position:relative;
  display:flex; align-items:center; gap:var(--s-3);
  min-height:44px; padding:var(--s-2) var(--s-3) var(--s-2) var(--s-5);
  border-radius:var(--r-sm);
  cursor:pointer; min-width:0;
  transition:background-color var(--d-press) var(--ease-out);
}
.sg__row{ position:relative }
/* The hairline between two rows is straight: it is its own 1px box across
   the row, not an inset shadow on a rounded one, which bent it up at both
   ends (audit C9). The highlight keeps its --r-sm corners under it. Never
   above the first row of a group: the group label is the separator there. */
.sg__opt + .sg__opt::before,
.sg__row + .sg__row::before,
.sg__opt + .sg__row::before,
.sg__row + .sg__opt::before{
  content:""; position:absolute; inset-inline:0; top:0;
  height:var(--bw-1); background:var(--bd);
}
@media (hover:hover){ .sg__opt:hover{ background:var(--page-2) } }

/* The active row: a --page-2 fill and a dot at the leading edge. The dot is
   in the flow with a transparent resting state, so moving the highlight
   never shifts a single glyph, and it is 6px of shape rather than a
   coloured side stripe (impeccable bans those above 1px).                 */
.sg__dot{
  position:absolute; inset-inline-start:calc((var(--s-5) - var(--dot)) / 2); top:50%;
  width:var(--dot); height:var(--dot); margin-top:calc(var(--dot) / -2); border-radius:50%;
  background:transparent;
  transition:background-color var(--d-press) var(--ease-out);
}
.sg__opt.is-on{ background:var(--page-2) }
.is-on > .sg__dot{ background:var(--slate-800) }
/* Where the query landed, marked by weight. Colour alone is never the mark:
   it carries nothing for a shopper who cannot see it, and the one accent
   this design has belongs to the primary action, not to a substring.      */
.sg__hit{ font-weight:700; color:inherit }

/* a recent search: the option, plus a × that is deliberately not focusable.
   An option may not own an interactive element, so the keyboard path to the
   same action is the Delete key (layout.js §3) and the row says so in its
   accessible name. The hit area is still 44px for the thumb.              */
.sg__row{ display:flex; align-items:center; gap:var(--s-1); min-width:0 }
.sg__row .sg__opt{ flex:1 1 auto; min-width:0 }
@media (hover:hover){ .sg__row:hover .sg__opt{ background:var(--page-2) } }
.sg__rm{
  flex:none; display:grid; place-items:center;
  width:44px; height:44px;
  border-radius:var(--r-sm); color:var(--ink-2); cursor:pointer;
  transition:color var(--d-hover) var(--ease), background-color var(--d-hover) var(--ease);
}
@media (hover:hover){ .sg__rm:hover{ background:var(--bd); color:var(--ink) } }
.sg__rm:active{ background:var(--bd) }
.sg__opt--recent .sg__chip{ color:var(--ink-2) }
/* a product's photograph on the white well, contained, never cropped
   (design.md §15.2); the slot is 44px, 40px under a fine pointer */
.sg__im{
  flex:none; display:grid; place-items:center;
  width:44px; height:44px; padding:var(--s-1);
  background:var(--paper); border:var(--bw-1) solid var(--bd); border-radius:var(--r-xs);
  overflow:hidden;
}
.sg__im img{ width:100%; height:100%; object-fit:contain }
/* on its way: the plain --page-2 well, no glyph (design.md §15.3); no
   photograph at all: the device's glyph alone on the same fill */
.sg__im:has(img[data-img]),
.sg__im:has(.nophoto){ background:var(--page-2) }
.sg__chip{
  flex:none; display:grid; place-items:center;
  width:44px; height:44px; border-radius:var(--r-xs);
  background:var(--page-2); color:var(--ink-2);
}
.sg__b{ display:flex; flex-direction:column; gap:var(--s-1); min-width:0; flex:1 1 auto }
/* A name takes two lines in the phone layer (design.md §6 "List rows"):
   four product rows read „ECOVACS WI…" at 320px (audit M22), and the
   longest category lost 79px to the ellipsis. One line in the header
   dropdown from 768px, where the row is wide. */
.sg__t{
  display:-webkit-box; -webkit-box-orient:vertical;
  -webkit-line-clamp:2; line-clamp:2;
  overflow:hidden; overflow-wrap:break-word;
  font-size:var(--t-body); line-height:var(--lh-name); color:var(--ink);
}
@media (min-width:768px){
  .sg__t{
    display:block; -webkit-line-clamp:none; line-clamp:none;
    line-height:var(--lh-ui);
    text-overflow:ellipsis; white-space:nowrap;
  }
}
.sg__m{
  font-size:var(--t-sm); line-height:var(--lh-ui); color:var(--ink-3); min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
/* The second line of a PRODUCT row is not secondary information, it is the
   row's identity: the Georgian half of a product name is a generic noun, so
   a search for "ჩაიდანი" returns six rows all titled ჩაიდანი and only the
   supplier half tells them apart. On a category or brand row the second line
   really is meta ("64 პროდუქტი") and stays in the muted tier; here it steps
   up to --ink-2, 7.17:1 on --paper, 6.70:1 on --page.                     */
.sg__m--id{ color:var(--ink-2) }
.sg__p{ flex:none; font-size:var(--t-body) }
/* "see all results" is the row users reach for most: it stays pinned to the
   bottom of the scroller instead of hiding below six product suggestions */
.sg__all{
  position:sticky; bottom:0; z-index:1;
  display:flex; align-items:center; justify-content:space-between; gap:var(--s-3);
  min-height:48px; margin-top:var(--s-2);
  padding:var(--s-2) var(--s-3) var(--s-2) var(--s-5);
  background:var(--paper);
  border-top:var(--bw-1) solid var(--bd);
  font-size:var(--t-body); line-height:var(--lh-ui); font-weight:600; color:var(--ink-strong);
  cursor:pointer;
}
/* red as TEXT on a light surface is always --red-700 (5.44:1 on the wash) */
@media (hover:hover){ .sg__all:hover{ color:var(--red-700); background:var(--page-2) } }
.sg__all:active{ background:var(--bd) }
.sg__all.is-on{ background:var(--page-2) }
/* Nothing matched: the one empty state (components.css §12, LS.empty) with
   the search mark and a way out, never a box that just goes blank. Inside
   the list it keeps the list's inner edge and no margin above it; the
   popular rows under it are the way on. */
.sg__empty.empty{ margin-top:0; padding:var(--s-4) var(--s-3) var(--s-2) }

/* Pointer density. The dropdown from 768px is driven by a pointer and by
   ↑↓, where six 60px rows push the last one past the fold: rows step down to
   40px and the thumbnails with them (design.md §6 "List rows"). Only under a
   fine pointer: a 768px tablet is a touch device and keeps 44px. Georgian
   never drops below 14px in either. */
@media (min-width:768px){
  .sg__grp{ padding:var(--s-2) var(--s-3) var(--s-1) }
}
@media (min-width:768px) and (hover:hover) and (pointer:fine){
  .sg__opt{ min-height:40px; padding-block:var(--s-1) }
  .sg__im, .sg__chip{ width:40px; height:40px }
  .sg__rm{ width:40px; height:40px }
}

/* full-screen mobile search layer -------------------------------------- */
/* dvh, not vh: on a phone the URL bar is part of the viewport arithmetic and
   a 100vh layer puts its own field under the browser chrome (design.md §11). */
.slayer{
  position:fixed; inset:0; z-index:var(--z-search);
  height:100dvh; max-height:100dvh;
  display:flex; flex-direction:column;
  background:var(--page);
}
.slayer[hidden]{ display:none }
.slayer__bar{
  display:flex; align-items:center; gap:var(--s-2);
  padding:var(--s-2) var(--gut);
  padding-top:calc(var(--s-2) + env(safe-area-inset-top));
  background:var(--paper); border-bottom:var(--bw-1) solid var(--bd);
}
/* the back control is optically on the gutter, as the burger is */
.slayer__bar > .iconbtn{ margin-inline-start:calc(var(--s-2) * -1) }
.slayer__bar > .hsearch{ flex:1 1 auto }
/* every inner edge on --gut, like the page under it (design.md §14.2; the
   body sat at 12px, audit L28) */
.slayer__body{
  flex:1 1 auto; min-height:0;
  overflow:auto; overscroll-behavior:contain;
  padding:var(--s-2) var(--gut) calc(var(--s-8) + env(safe-area-inset-bottom));
}
/* In the layer the listbox is a block in the flow, not a floating dropdown:
   same --paper list and same hairlines as the desktop dropdown, so a row
   reads identically in both hosts, but no shadow. A shadow says "this
   arrived over something"; here it is the screen, and there is nothing
   underneath it to lift away from.                                        */
.slayer .hsearch__pop{
  position:static; max-height:none; overflow:visible;
  padding:var(--s-2);
  background:var(--paper);
  border:var(--bw-1) solid var(--bd); border-radius:var(--r);
  box-shadow:none;
}
/* In the layer the „ყველა შედეგი" row ends the list instead of sticking to
   the bottom of the screen: with names on two lines the list outgrows a
   320px screen, and a pinned row stood over the last product and took its
   target (the dropdown from 768px keeps it pinned). */
.slayer .sg__all{ position:static }


/* ── 4. CATALOG BAR: ≥1024px ──────────────────────────────────────────────
   Below the sticky header, not inside it: pinning this row as well put 125px
   of chrome over every inner page (layout.js, tplHeader). It scrolls away
   and the header band stays, so --hdr-h is 73px at desktop.
   The stacking sits one step under the header on purpose. The row opens the
   rail popover and the mega-panel out of its own box, and those have to
   clear the page (--z-bar is 300, the ceiling a page may use) while still
   passing under the header that scrolls over this row on the way up.
   ---------------------------------------------------------------------- */
.catbar{ display:none }
@media (min-width:1024px){
  .catbar{
    display:block;
    position:relative; z-index:calc(var(--z-hdr) - 1);
    background:var(--paper);
    /* the header above already draws its own bottom hairline; this row draws
       the one under itself, so the seam stays one pixel and not two */
    border-bottom:var(--bw-1) solid var(--bd);
  }
  .catbar__in{
    position:relative;
    display:flex; align-items:center; gap:var(--s-4);
    min-height:var(--bar-catbar);
  }
  .catbar__quick{
    display:flex; align-items:center; gap:var(--s-1);
    min-width:0;
  }
  /* A nav row (design.md §2): --ink-2, a --page-2 wash and --ink-strong on
     hover, a --bd fill on press; the current quick link is --ink-strong at
     600 with the red underline, one of the two place markers red is spent
     on (§2 "Where red is allowed", audit D33). */
  .catbar__q{
    position:relative;
    display:inline-flex; align-items:center; gap:var(--s-2);
    min-height:44px; padding-inline:var(--s-3);
    border-radius:var(--r-sm);
    font-size:var(--t-small-ka); line-height:var(--lh-ui); font-weight:500; color:var(--ink-2);
    white-space:nowrap;
    transition:color var(--d-hover) var(--ease), background-color var(--d-hover) var(--ease);
  }
  /* the marker is its own 3px bar under the label, the bottom bar's marker
     turned on its side: a text underline would be clipped by the label's
     ellipsis box below */
  .catbar__q::after{
    content:""; position:absolute;
    inset-inline:var(--s-3); bottom:var(--s-1); height:3px;
    border-radius:var(--r-pill);
    background:transparent;
  }
  /* Safety net only. The five biggest aisles fit whole at the counts the
     band shows (3, 4 and 5 below); a name longer than any on the shelf
     today is ellipsised rather than pushing the row over. */
  .catbar__q > span:last-child{
    max-width:20.6em; overflow:hidden; text-overflow:ellipsis;   /* 32ch of Google Sans */
  }
  .catbar__q:nth-child(n+4){ display:none }
  .catbar__q:active{ background:var(--bd) }
  .catbar__q[aria-current="page"]{ color:var(--ink-strong); font-weight:600 }
  .catbar__q[aria-current="page"]::after{ background:var(--red) }
}
@media (min-width:1024px) and (hover:hover){
  .catbar__q:hover{ color:var(--ink-strong); background:var(--page-2) }
}
@media (min-width:1280px){
  .catbar__q:nth-child(4){ display:inline-flex }
}
@media (min-width:1440px){
  .catbar__q:nth-child(5){ display:inline-flex }
}
.catbtn{ flex:none }
.catbtn .icon:last-child{ transition:transform var(--d-ui) var(--ease-out) }
.catbtn[aria-expanded="true"] .icon:last-child{ transform:rotate(180deg) }

/* The rail as a popover under the catalog-bar button. The containing block
   is .catbar__in's PADDING box, so `start:0` would sit flush against the
   viewport edge; --gut lines it up with the button above it.             */
.railpop{
  position:absolute; z-index:var(--z-pop);
  top:calc(100% + var(--s-2)); inset-inline-start:var(--gut);
  padding:var(--s-2);
}
.railpop[hidden]{ display:none }


/* ── 5. CATEGORY RAIL + MEGA-PANEL: the signature interaction ────────────
   ≥1024px. The rail is as wide as its longest name set on one line
   (--rail-w, :root above); hover or focus slides the panel out to the
   right in 220ms, design.md §10 calls this the site's one signature motion.
   On the home page the rail FOLDS: ten rows and a fold row at rest, the
   whole list over the page on a resting pointer, on focus or on the fold
   row, and the panel flush beside it as one surface (after zoommer.ge,
   owner 2026-09-29).
   Below 1024px the rail host renders nothing; the drawer takes over.
   ---------------------------------------------------------------------- */
.railhost{ display:none }
@media (min-width:1024px){
  .railhost{
    position:relative; display:block;
    width:var(--rail-w); flex:none;
  }
}
.railpop .railhost{ display:block }

/* One row, one line, one height: every name fits the rail's measure, so a
   list of N rows is N times this height, which is what lets the fold
   reserve its box in CSS. 44px is the touch floor; a fine pointer gets
   40px, the step .chip--filter takes too. */
.railhost{ --rail-row:44px }
@media (hover:hover) and (pointer:fine){ .railhost{ --rail-row:40px } }

.rail-nav-list{
  width:var(--rail-w);
  background:var(--paper);
  border:var(--bw-1) solid var(--bd); border-radius:var(--r-lg);
  overflow:hidden;
}
.railpop .rail-nav-list{ border:0; border-radius:var(--r-sm) }

.rail-nav-list__h{
  display:flex; align-items:center; gap:var(--s-2);
  min-height:48px; padding-inline:var(--s-4);
  border-bottom:var(--bw-1) solid var(--bd);
  color:var(--ink);
  font-size:var(--t-body); line-height:var(--lh-ui); font-weight:600;
}
.railpop .rail-nav-list__h{ display:none }

/* A row is an icon and a name. It used to carry a colour rail, a tinted
   chip, a count and a chevron as well; four signals for one link.
   The list is ONE Tab stop (roving tabindex, layout.js §5): the arrow keys
   walk the rows (audit H23: the opening's button was Tab stop 34). */
.crow + .crow{ border-top:var(--bw-1) solid var(--bd) }
.crow__a{
  position:relative;
  display:flex; align-items:center; gap:var(--s-3);
  min-height:var(--rail-row, 44px); padding-inline:var(--s-4);
  color:var(--ink); min-width:0;
  transition:background-color var(--d-hover) var(--ease),
             color var(--d-hover) var(--ease);
}
@media (hover:hover){ .crow__a:hover{ background:var(--page-2) } }
.crow.is-open > .crow__a{ background:var(--page-2) }
.crow__a:active{ background:var(--bd) }
.crow__chip{
  flex:none; display:grid; place-items:center;
  width:20px; height:20px;
  color:var(--ink);
  transition:color var(--d-hover) var(--ease);
}
/* the chip is an icon on the --page-2 hover wash: --red is 4.1:1 there,
   --red-700 is 5.4:1 (design.md §2: the hovered rail icon is red's) */
@media (hover:hover){ .crow__a:hover .crow__chip{ color:var(--red-700) } }
.crow.is-open .crow__chip{ color:var(--red-700) }
/* One line, never two (owner, 2026-09-29). The rail is as wide as the
   longest name in either language (--rail-w, §0); build.mjs fails a name
   that outgrows it, so the ellipsis is only the last fallback. */
.crow__n{
  flex:1 1 auto; min-width:0;
  font-size:var(--t-sm); line-height:var(--lh-ui); font-weight:500;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
@media (min-width:1280px){ .crow__n{ font-size:var(--t-body) } }

/* The fold. The host keeps the folded height in the page, reserved by this
   rule before layout.js has drawn a row: the home rail used to grow from
   nothing to 1 053px as the tree arrived, a layout shift of 0.48 to 0.64.
   The card is lifted out of the flow inside the host, so unfolding covers
   the page below instead of pushing it: ten rows and the fold row become
   the whole list. --rail-full, written by layout.js, is the height of the
   whole list. The height is the one animated box on the rail: the list is
   out of the flow, so nothing around it reflows while it unfolds, and the
   rows inside keep their fixed height. It stays a height (verify S-10): a
   clip-path would cut the unfolded card's --sh-2 and leave the sticky fold
   row at the foot of the whole list instead of the visible edge, and a
   grid-template-rows track is the same layout work under another name.
   The host sits on --z-pop, a panel opened from inside a band (§4 Layers). */
@media (min-width:1024px){
  .railhost.railhost--fold{ z-index:var(--z-pop) }
  .railhost--fold{
    --rail-rows:10;
    --rail-rest:calc((var(--rail-rows) + 1) * var(--rail-row) +
                     var(--rail-rows) * var(--bw-1) + 2 * var(--bw-1));
    height:var(--rail-rest);
  }
  .railhost--fold > .rail-nav-list{
    position:absolute; inset-block-start:0; inset-inline-start:0; z-index:1;
    height:var(--rail-rest);
    transition:height var(--d-panel) var(--ease),
               box-shadow var(--d-panel) var(--ease);
  }
  .railhost--fold .rail-nav-list__h{ display:none }
  .railhost--fold.is-unfolded > .rail-nav-list{
    height:var(--rail-full, var(--rail-rest));
    box-shadow:var(--sh-2);
  }
  /* panel open: the rail and the panel are one card, square at the join.
     The panel is as tall as its own content (§5 below), so the list's lower
     corner is square only when the panel runs past it. */
  .railhost--fold.has-panel > .rail-nav-list{ border-start-end-radius:0 }
  .railhost--fold.has-panel.panel-taller > .rail-nav-list{ border-end-end-radius:0 }
}

/* The fold row, the card's last line at rest. It is sticky to the card's
   bottom edge, so it stands over the first folded row rather than after
   the last one; unfolded, it has nothing left to reveal and goes. */
.rail-more{
  position:sticky; inset-block-end:0;
  display:flex; align-items:center; gap:var(--s-3);
  width:100%; min-height:var(--rail-row, 44px); padding-inline:var(--s-4);
  background:var(--paper); border-top:var(--bw-1) solid var(--bd);
  color:var(--ink-2); font-size:var(--t-small-ka); line-height:var(--lh-ui);
  font-weight:600; text-align:start;
  cursor:pointer;
  transition:background-color var(--d-hover) var(--ease);
}
.rail-more__t{ flex:1 1 auto; min-width:0; white-space:nowrap }
.rail-more__c{ flex:none; color:var(--ink-3) }
.rail-more__i{ flex:none }
@media (hover:hover){ .rail-more:hover{ background:var(--page-2) } }
.rail-more:active{ background:var(--bd) }
.railhost--fold.is-unfolded .rail-more{ display:none }

/* The last row of the rail, „ყველა კატეგორია": the one row that carries a
   count, because the count is what it says, that there are this many
   categories in all and the ten above are not all of them.
   The display face and the tabular figures come from `num` in the markup
   (base.css §4), so only the box and the type tier are set here. */
.crow--all .crow__n{ font-weight:600 }
.crow__c{ flex:none; font-size:var(--t-sm); color:var(--ink-3) }

/* the mega-panel ------------------------------------------------------- */
/* Width: 760px was two columns of names plus a 232px aside of promoted
   products and the hotline. The aside is gone, and up to ten names the list
   is one column, so the cap comes down with it: at 760px a single column
   of ten short links reads as a half-empty sheet. Past ten the panel takes
   the 760px back (.mega--wide below) and puts two columns in it.
   520px leaves ~400px of text per row, which the longest subcategory here
   ("ცხელი წყლის დისპენსერი") clears on one line with its count still
   pinned right.
   The vw term keeps the panel inside the container between 1024 and 1280.
   The 20px is a scrollbar allowance: 100vw includes the scrollbar and the
   container does not. body{overflow-x:clip} means an error here clips
   rather than scrolls, so the formula is deliberately conservative.
   Height: the longest list here is 25 entries, which is thirteen rows of
   two columns, and thirteen rows plus the head and the foot measure 619px.
   680px clears that, so the panel that used to scroll no longer does from
   776px of viewport height up. Under that the 80vh term binds instead and
   the body keeps its scroller, which is all that is left: the panel opens
   160px down the page, so 768px of viewport leaves 608px of screen below
   its top for 619px of panel.                                              */
.mega{
  position:absolute; z-index:calc(var(--z-pop) + 1);
  top:0; inset-inline-start:calc(100% + var(--s-3));
  width:min(520px, calc(100vw - var(--rail-w) - var(--gut) * 2 - var(--s-3) - 20px));
  max-height:min(80dvh, 680px);
  display:flex; flex-direction:column;
  overflow:hidden;
  opacity:0; transform:translateX(-16px); pointer-events:none;
  transition:opacity var(--d-panel) var(--ease),
             transform var(--d-panel) var(--ease),
             visibility 0s linear var(--d-panel);
  visibility:hidden;
}
.mega.is-open{
  opacity:1; transform:none; pointer-events:auto; visibility:visible;
  transition:opacity var(--d-panel) var(--ease),
             transform var(--d-panel) var(--ease),
             visibility 0s;
}
.mega__head{
  display:flex; align-items:center; gap:var(--s-3);
  padding:var(--s-4) var(--s-5);
  border-bottom:var(--bw-1) solid var(--bd);
}
/* the panel title role (design.md §3) */
.mega__t{
  min-width:0; flex:1 1 auto;
  font-size:var(--t-h3); line-height:var(--lh-h3); font-weight:700;
  letter-spacing:var(--ls-heading);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.mega__n{ flex:none; font-family:var(--f-disp); font-size:var(--t-sm); color:var(--ink-3);
           font-variant-numeric:tabular-nums }

/* "see all" is the last line of the panel, not a control tucked into the
   header beside the title. It reads as the end of the list it belongs to,
   and as a full-width strip its hover covers the whole row rather than a
   label-sized patch. flex:none keeps it off the scrolling body above it.
   The see-all link of design.md §2: hover --red-700 on a --page-2 wash with
   the arrow moving --s-1, press --red-800. */
.mega__foot{
  flex:none;
  padding:var(--s-2) var(--s-3);
  border-top:var(--bw-1) solid var(--bd);
}
.mega__all{
  display:flex; align-items:center; justify-content:space-between; gap:var(--s-2);
  width:100%; min-height:44px; padding-inline:var(--s-3);
  border-radius:var(--r-sm);
  font-size:var(--t-small-ka); line-height:var(--lh-ui); font-weight:600; color:var(--ink-strong);
  transition:color var(--d-hover) var(--ease), background-color var(--d-hover) var(--ease);
}
.mega__all .icon{ transition:transform var(--d-hover) var(--ease) }
@media (hover:hover){
  .mega__all:hover{ color:var(--red-700); background:var(--page-2) }  /* 5.44:1 */
  .mega__all:hover .icon{ transform:translateX(var(--s-1)) }
}
.mega__all:active{ color:var(--red-800); background:var(--page-2) }

.mega__body{
  display:grid; grid-template-columns:minmax(0,1fr);
  gap:var(--s-5);
  padding:var(--s-4) var(--s-5);
  overflow:auto; overscroll-behavior:contain;
}
/* One column up to ten entries, two above that. Two columns of the 520px
   panel are ~230px per name, which is where a Georgian subcategory starts
   breaking over two and three lines ("ცხელი წყლის დისპენსერი",
   "მტვერსასუტი/აქსესუარები"), so up to ten names the single column is worth
   the height it costs. Past ten it is not: the largest category here has 25
   and made a 968px column inside a 440px scroller. Past ten the panel widens
   to the 760px of .mega--wide, where the two columns are ~340px each and
   every subcategory name clears one line or wraps once at a space.
   columns has no effect on a flex container, so the two-column variant is a
   block container instead; .mega__sa stacks the same either way.           */
.mega__subs{ display:flex; flex-direction:column; min-width:0 }
.mega__subs--cols{ display:block; columns:2; column-gap:var(--s-5) }
/* A list row of the panel (design.md §6 "List rows"): 44px, 40px under a
   fine pointer. The name is inline text and its count follows its last word
   (audits C32, D45): a name that wraps keeps its count beside it instead of
   leaving it at the top of the row or 300px away at the column's far edge. */
.mega__sa{
  display:block;
  min-height:44px; padding:var(--s-3) var(--s-2);
  margin-inline-start:calc(var(--s-2) * -1);
  border-radius:var(--r-xs);
  font-size:var(--t-sm); line-height:var(--lh-ui); color:var(--ink-2);
  break-inside:avoid;    /* a two-line name is never split across the columns */
  transition:color var(--d-hover) var(--ease), background-color var(--d-hover) var(--ease);
}
/* a fine pointer takes the row at its natural 42px: one line on --lh-ui
   between two --s-3 */
@media (hover:hover) and (pointer:fine){ .mega__sa{ min-height:0 } }
@media (hover:hover){ .mega__sa:hover{ color:var(--ink-strong); background:var(--page-2) } }
/* break-word, not anywhere: a long Georgian word wraps to the next line
   instead of being split mid-word with one orphan letter below it. */
.mega__st{ overflow-wrap:break-word }
/* the count role beside a name: --t-sm, tabular, --ink-3 (design.md §3) */
.mega__sc{
  margin-inline-start:var(--s-2); white-space:nowrap;
  font-family:var(--f-disp); font-size:var(--t-sm); color:var(--ink-3);
  font-variant-numeric:tabular-nums;
}

/* Two-column panels: the all-categories map, and a category with more than
   ten subcategories in stock. 760px is two columns of about 340px, which
   the longest subcategory here clears on one line. The vw term is the same
   guard the 520px panel carries. */
.mega--wide{
  width:min(760px, calc(100vw - var(--rail-w) - var(--gut) * 2 - var(--s-3) - 20px));
}
.mega__cats{ columns:2; column-gap:var(--s-5); min-width:0 }
.mega__ca{
  display:flex; align-items:center; gap:var(--s-2);
  min-height:44px; padding:var(--s-1) var(--s-2);
  margin-inline-start:calc(var(--s-2) * -1);
  border-radius:var(--r-xs);
  font-size:var(--t-sm); line-height:var(--lh-ui); color:var(--ink-2);
  break-inside:avoid;
  transition:color var(--d-hover) var(--ease), background-color var(--d-hover) var(--ease);
}
@media (hover:hover) and (pointer:fine){ .mega__ca{ min-height:40px } }
.mega__ca .mega__st{ flex:0 1 auto; min-width:0 }
.mega__ca .mega__sc{ flex:none; margin-inline-start:0 }
.mega__ci{ flex:none; display:grid; place-items:center; width:20px; height:20px; color:var(--ink);
           transition:color var(--d-hover) var(--ease) }
@media (hover:hover){
  .mega__ca:hover{ color:var(--ink-strong); background:var(--page-2) }
  .mega__ca:hover .mega__ci{ color:var(--red-700) }   /* 5.44:1 on --page-2, as the rail chip */
}

.mega__col{ display:flex; flex-direction:column; gap:var(--s-3); min-width:0 }
/* The "popular" minis are the one thing in this panel that needs a product,
   so they are the one thing that arrives late (layout.js §1b). The list is a
   column inside a column: it starts empty at zero height and grows downward
   inside a panel that already has its max-height, so nothing above it moves
   when the catalogue lands. */
.mega__minis{ display:flex; flex-direction:column; gap:var(--s-2); min-width:0 }
/* a group label: the label role in --ink-2 at 600 (design.md §3) */
.mega__lab{ font-size:var(--t-small-ka); line-height:var(--lh-ui); font-weight:600; color:var(--ink-2) }

/* product mini: a real product, never a decorative promo card */
.pmini{
  display:flex; align-items:center; gap:var(--s-3);
  padding:var(--s-2); min-width:0;
  border:var(--bw-1) solid var(--bd); border-radius:var(--r-sm);
  background:var(--paper);
  transition:border-color var(--d-hover) var(--ease), background-color var(--d-hover) var(--ease);
}
@media (hover:hover){ .pmini:hover{ border-color:var(--bd-2); background:var(--paper-2) } }
.pmini__im{
  flex:none; display:grid; place-items:center;
  width:52px; height:52px; padding:var(--s-1);
  background:var(--paper); border-radius:var(--r-xs); overflow:hidden;
}
.pmini__im img{ width:100%; height:100%; object-fit:contain }
.pmini__b{ display:flex; flex-direction:column; gap:var(--s-1); min-width:0 }
.pmini__t{ font-size:var(--t-sm); line-height:var(--lh-name); color:var(--ink) }
/* a price is a numeral step, never a text one (design.md §3) */
.pmini .price{ font-size:var(--t-num-sm) }

/* empty / loading states inside the panel */
.mega__note{ font-size:var(--t-sm); color:var(--ink-2) }
.mega__note--pad{ padding:var(--s-4) }

/* The folding rail's panel. It starts flush at the rail's edge and runs to
   the far edge of the container, so the rail and the panel read as one
   card, the way zoommer.ge draws it; 100cqi is the width of .zone__in, the
   query container home.css §1 declares. It is AS TALL AS ITS OWN CONTENT,
   capped at the window: --mega-max, written by layout.js when the panel
   opens, is the room from its top to the window's bottom edge, and the body
   scrolls inside under that. It used to be as tall as the unfolded list and
   stood 470 to 504px of empty paper under its names (audits L23, H33).
   The clip-path cuts the panel's shadow off its left edge, where it would
   otherwise fall across the rail it joins. Two columns of names; from a
   1300px container the category's photograph stands at the top of its own
   column beside them, 240px wide (design.md §7). */
@media (min-width:1024px){
  .railhost--fold .mega{
    inset-inline-start:100%;
    width:calc(100cqi - var(--rail-w));
    max-height:var(--mega-max, calc(100dvh - var(--hdr-h) - var(--s-8)));
    border-radius:var(--r-lg); border-start-start-radius:0;
    box-shadow:var(--sh-2);
    clip-path:inset(calc(var(--s-16) * -1) calc(var(--s-16) * -1) calc(var(--s-16) * -1) 0);
    transform:translateX(calc(var(--s-2) * -1));
  }
  .railhost--fold .mega.is-open{ transform:none }
  .railhost--fold .mega__body{ flex:1 1 auto }
  .railhost--fold .mega__main{ align-self:start; display:flex; flex-direction:column; gap:var(--s-5); min-width:0 }
  .railhost--fold .mega__subs--cols{ column-gap:var(--s-8) }
}
/* the category's biggest brands, a wrapped row of plain links */
.mega__brands:empty{ display:none }
.mega__brands .mega__lab{ margin-bottom:var(--s-1) }
.mega__bl{ display:flex; flex-wrap:wrap; gap:0 var(--s-4); margin-inline-start:calc(var(--s-2) * -1) }
.mega__ba{
  display:inline-flex; align-items:center;
  min-height:44px; padding-inline:var(--s-2);
  border-radius:var(--r-xs);
  font-size:var(--t-sm); line-height:var(--lh-ui); color:var(--ink-2);
  transition:color var(--d-hover) var(--ease), background-color var(--d-hover) var(--ease);
}
@media (hover:hover) and (pointer:fine){ .mega__ba{ min-height:40px } }
@media (hover:hover){ .mega__ba:hover{ color:var(--ink-strong); background:var(--page-2) } }
.mega__ba:active,
.mega__sa:active,
.mega__ca:active{ background:var(--bd) }
.mega__ph{ display:none }
@container zone (min-width:1300px){
  .railhost--fold .mega__body{ grid-template-columns:minmax(0,1fr) 240px; column-gap:var(--s-8) }
  .railhost--fold .mega__ph{
    display:block; align-self:start;
    aspect-ratio:4 / 3; overflow:hidden;
    border-radius:var(--r); background:var(--page-2);
  }
  .railhost--fold .mega__ph img{ display:block; width:100%; height:100%; object-fit:cover }
}


/* ── 6. DRAWER: two-level push navigation (<1024px) ──────────────────────
   design.md §6 "Drawer". Level 1: „ყველა პროდუქტი" with the total, every
   category, then the wishlist and the information links. Tapping a
   category pushes level 2 (--d-ui). Rows ≥56px, every inner edge on --gut.
   The foot is one row at every width; where the phone number and the
   language pair do not both fit (320 and 360px), the pair moves into the
   head beside the close control (a container query on the drawer, below).
   The overlay primitive (core.js) gives it the lock, the inert page, focus
   and Escape.
   ---------------------------------------------------------------------- */
.drawer{
  position:fixed; z-index:var(--z-drawer);
  inset-block:0; inset-inline-start:0;
  width:min(400px, 92vw); height:100dvh;
  display:flex; flex-direction:column;
  background:var(--paper);
  box-shadow:var(--sh-3);
  transform:translateX(-102%);
  transition:transform var(--d-panel) var(--ease);
  container:drawer / inline-size;
}
.drawer[hidden]{ display:none }
.drawer.is-open{ transform:none }

.drawer__bar{
  display:flex; align-items:center; gap:var(--s-2); flex:none;
  min-height:56px; padding:var(--s-2) var(--s-2) var(--s-2) var(--gut);
  padding-top:calc(var(--s-2) + env(safe-area-inset-top));
  border-bottom:var(--bw-1) solid var(--bd);
}
/* the panel title role (design.md §3) */
.drawer__t{
  flex:1 1 auto; min-width:0;
  font-size:var(--t-h3); line-height:var(--lh-h3); font-weight:700;
  letter-spacing:var(--ls-heading);
}

.drawer__view{ flex:1 1 auto; min-height:0; overflow:hidden }
/* Two panes, each exactly one drawer wide. The track keeps width:100% and
   lets the second column overflow to the right: with a 200%-wide track a
   `100%` column would resolve against the track, not the view, and each pane
   would come out double width. */
.drawer__track{
  display:grid; grid-template-columns:repeat(2, 100%);
  width:100%; height:100%;
  transition:transform var(--d-ui) var(--ease);
}
.drawer__track[data-level="2"]{ transform:translateX(-100%) }
.drawer__pane{
  min-width:0; height:100%;
  overflow-y:auto; overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch;
  visibility:visible;
  transition:visibility 0s;
}
/* the inactive pane leaves the tab order (JS also sets `inert`) */
.drawer__track[data-level="1"] .drawer__pane--2,
.drawer__track[data-level="2"] .drawer__pane--1{
  visibility:hidden; transition:visibility 0s linear var(--d-ui);
}

/* A nav row (design.md §2 state table): --ink at rest, a --page-2 wash and
   --ink-strong on hover (pointer only), a --bd fill under the thumb. */
.drow{ border-bottom:var(--bw-1) solid var(--bd) }
.drow__a{
  position:relative;
  display:flex; align-items:center; gap:var(--s-3);
  width:100%; min-height:56px;
  padding:var(--s-2) var(--gut);
  color:var(--ink); text-align:start;
  transition:background-color var(--d-press) var(--ease-out);
}
@media (hover:hover){ .drow__a:hover{ background:var(--page-2); color:var(--ink-strong) } }
.drow__a:active{ background:var(--bd) }
.drow__chip{
  flex:none; display:grid; place-items:center;
  width:36px; height:36px; border-radius:var(--r-xs);
  background:var(--page-2); color:var(--ink);
}
.drow__n{
  flex:1 1 auto; min-width:0;
  font-size:var(--t-body); line-height:var(--lh-ui); font-weight:500;
}
/* the whole catalogue, level 1's first row: the one row that says so */
.drow--all .drow__n{ font-weight:600 }
.drow__c{ flex:none; font-family:var(--f-disp); font-size:var(--t-sm); color:var(--ink-3) }
.drow__chev{ flex:none; color:var(--ink-3) }

/* the level-2 back row */
.dback{
  position:sticky; top:0; z-index:2;
  display:flex; align-items:center; gap:var(--s-3);
  width:100%; min-height:56px; padding:var(--s-2) var(--gut);
  background:var(--page-2); color:var(--ink-strong);
  border-bottom:var(--bw-1) solid var(--bd);
  font-size:var(--t-body); line-height:var(--lh-ui); font-weight:600; text-align:start;
}
@media (hover:hover){ .dback:hover{ background:var(--bd) } }
/* The back row names the category level 2 is inside, so it is never cut:
   it takes up to two lines and the row grows with them (it ellipsised
   „სამზარეულო და საოჯახო ნივთები" by 49px at 320 and 12px at 360, verify
   S-5). The clamp is only the fallback for a name longer than any on file. */
.dback__n{
  min-width:0;
  display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2;
  overflow:hidden; overflow-wrap:break-word;
}

/* the drawer's secondary links: the rows' text on --gut, their press fill
   reaching --s-2 past it */
.dsec{
  padding:var(--s-4) calc(var(--gut) - var(--s-2)) var(--s-2);
  border-top:var(--bw-1) solid var(--bd);
}
/* a group label: the label role in --ink-2 at 600 (design.md §3) */
.dsec__h{
  padding-inline:var(--s-2);
  font-size:var(--t-small-ka); line-height:var(--lh-ui); font-weight:600; color:var(--ink-2);
}
.dsec__a{
  display:flex; align-items:center; gap:var(--s-3);
  min-height:48px; padding-inline:var(--s-2);
  color:var(--ink-2); font-size:var(--t-body); line-height:var(--lh-ui);
  border-radius:var(--r-xs);
}
@media (hover:hover){ .dsec__a:hover{ color:var(--ink-strong); background:var(--page-2) } }
.dsec__a[aria-current="page"]{ color:var(--ink-strong); font-weight:600 }
.dsec__a .icon{ color:var(--ink-2); flex:none }
/* the wishlist row: a name that can wrap and a count pinned to the end, the
   same ledger the category rows above it use */
.dsec__n{ flex:1 1 auto; min-width:0 }
.dsec__c{ flex:none; font-family:var(--f-disp); font-size:var(--t-sm); color:var(--ink-3) }
.dsec__c[hidden]{ display:none }

/* One row at every width, at most 64px plus the safe area (audit M15: it
   wrapped to 125px at 320). */
.drawer__foot{
  flex:none;
  display:flex; align-items:center; justify-content:space-between; gap:var(--s-3);
  padding:var(--s-2) var(--gut);
  padding-bottom:calc(var(--s-2) + env(safe-area-inset-bottom));
  border-top:var(--bw-1) solid var(--bd);
  background:var(--paper-2);
}
.drawer__tel{
  display:inline-flex; align-items:center; gap:var(--s-2);
  min-height:44px; min-width:0; white-space:nowrap;
  font-family:var(--f-disp); font-weight:700; font-size:var(--t-body); line-height:var(--lh-num);
  color:var(--ink-strong);
  font-variant-numeric:tabular-nums;
}
/* the phone icon is not a state, so it is not red (design.md §2) */
.drawer__tel .icon{ color:var(--ink-2) }
@media (hover:hover){ .drawer__tel:hover{ color:var(--red-700) } }
.drawer__tel:active{ color:var(--red-800) }

/* The language pair lives in the foot where it fits beside the number and in
   the head where it does not. Both copies are in the markup and one is
   display:none, so only one is ever in the tab order and the tree. The foot
   needs 337px: the number link (172px), a gap and the pair (121px) inside
   the gutters; 340px leaves room for rendering differences, so a 390px
   phone gets the foot and 320 and 360px get the head. The head copy's
   halves are the compact 44px ones, so the title keeps its line. */
.drawer .lang{ margin-inline-start:0 }
.drawer__bar .lang .seg__b{ min-width:44px; padding-inline:var(--s-2) }
.drawer__foot .lang{ display:none }
@container drawer (min-width:340px){
  .drawer__bar .lang{ display:none }
  .drawer__foot .lang{ display:inline-flex }
}


/* ── 7. SCRIM ──────────────────────────────────────────────────────────────
   The wash is the overlay primitive's (.scrim, components.css: --scrim-dark
   fading over --d-panel); the layer is the caller's, and the drawer's sits
   on the shell's rung, under the drawer. */
.scrim--shell{ z-index:var(--z-scrim) }


/* ── 8. FOOTER ─────────────────────────────────────────────────────────────
   A light band on --page-2 in two rows: the brand, the information links and
   the contact block on top, and under them every category in straight
   columns (design.md §6, "Footer").

   --page-2 (#F0F0F4) is the recessed token, which is what a footer is, but
   it sits only four steps off --page (#F7F7F9) and that difference alone
   does not read as an edge. The hairline draws the boundary. Muted text in
   here is --ink-2 (6.31:1 on --page-2). It was --ink-3 at 4.34:1, the pair
   the 2026-09-28 audit caught on every page; --ink-3 has moved since and is
   4.88:1 there (design.md §2), but the footer keeps the stronger tier.

   The categories used to share the top row as a fourth column, split into
   two sub-columns of ten. Nineteen names in a quarter of the width wrapped
   onto two lines at every desktop width and the two sub-columns zigzagged
   (the owner's complaint, audit T21 and D9). With every category listed
   (Step 2, DECISIONS.md) the list has a row of its own: full width, one
   name per line, balanced columns.

   ONE COLUMN TRACK FOR BOTH ROWS (design.md §14.9, audit L31): the top row
   is 2 equal tracks from 768px (the brand across both), 3 from 1024px
   (brand, information, contact) and 4 from 1440px (the brand across two);
   the category band runs in the same 2, 3 and 4 columns with the same gap,
   so its columns start where the tracks above start. The count follows the
   data: a column is never narrower than the longest category name in either
   language at 16px (285.7px today, checked by build.mjs), which 4 columns
   give only from 1440px (320px; 280px at 1280).

   PHONES: the brand block, then three groups on one rhythm: information and
   categories as compact disclosures, contact open, each under one 48px
   heading row and a hairline (audit L27: a 24px heading between two 52px
   triggers).
   ---------------------------------------------------------------------- */
.footer{
  background:var(--page-2); color:var(--ink-2);
  border-top:var(--bw-1) solid var(--bd);
  margin-top:var(--gap-page-end);          /* the footer owns the page end */
}
.footer__in{
  display:grid;
  padding-block:var(--s-10) 0;
}
.fbrand{ padding-bottom:var(--s-8) }
.footer__in > .fcol,
.footer__cats > .fcol{ border-top:var(--bw-1) solid var(--bd) }
@media (min-width:768px){
  .footer__in{
    grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--s-10) var(--s-8);
    padding-block:var(--s-10);
  }
  .fbrand{ padding-bottom:0 }
  .footer__in > .fcol,
  .footer__cats > .fcol{ border-top:0 }
  /* two tracks for three blocks: the brand takes the whole first row */
  .fbrand{ grid-column:1 / -1 }
}
@media (min-width:1024px){
  .footer__in{ grid-template-columns:repeat(3,minmax(0,1fr)); column-gap:var(--s-8) }
  .fbrand{ grid-column:auto }
}
@media (min-width:1440px){
  .footer__in{ grid-template-columns:repeat(4,minmax(0,1fr)) }
  .fbrand{ grid-column:span 2 }
}

/* The category band: a disclosure on phones like the information group,
   from 768px a heading and a balanced run of CSS columns on the top row's
   tracks (above). A name that is ever longer than its column wraps inside it
   rather than being cut: nothing here clips. */
@media (min-width:768px){
  .footer__cats{ padding-block:var(--s-8); border-top:var(--bw-1) solid var(--bd) }
  .footer__cats .fcol__l{ columns:2; column-gap:var(--s-8) }
  .footer__cats .fcol__l > li{ break-inside:avoid }
}
@media (min-width:1024px){ .footer__cats .fcol__l{ columns:3 } }
@media (min-width:1440px){ .footer__cats .fcol__l{ columns:4 } }

.fbrand{ display:flex; flex-direction:column; gap:var(--s-4); min-width:0 }
/* The white plate is gone with the dark surface. It existed so a colour
   logo drawn for white paper had white paper to stand on; on --page-2 the
   mark sits on the footer directly and the plate would now read as a
   floating card containing nothing. 44px tall: it is a link home.       */
.fbrand__logo{
  display:inline-flex; align-items:center; align-self:flex-start; min-height:44px;
  transition:transform var(--d-press) var(--ease-press);
}
.fbrand__logo:active{ transform:scale(.97) }
/* explicit on both axes: the mark is lazy-loaded and `width:auto` leaves the
   box unresolved until decode (logo.png is 3482×1355 → 93×36) */
.fbrand__logo img{ width:93px; height:36px }
/* the footer's brand line: a sentence that stands alone, --measure-short */
.fbrand__d{ color:var(--ink-2); font-size:var(--t-body); line-height:var(--lh-body); max-width:var(--measure-short) }

.fsocial{ display:flex; align-items:center; gap:var(--s-2) }
.fsocial__a{
  display:grid; place-items:center;
  width:44px; height:44px; flex:none;
  border-radius:var(--r-pill);
  color:var(--ink-2);
  border:var(--bw-1) solid var(--bd-2);
  transition:color var(--d-hover) var(--ease), background-color var(--d-hover) var(--ease),
             border-color var(--d-hover) var(--ease),
             transform var(--d-press) var(--ease-press);
}
/* Hover inverts to the dark surface rather than lightening toward it: on
   --page-2 there is no lighter step left that still reads as a change. */
@media (hover:hover){
  .fsocial__a:hover{ color:var(--on-fill); background:var(--slate-800); border-color:var(--slate-800) }
}
.fsocial__a:active{ background:var(--slate-900); border-color:var(--slate-900);
                    color:var(--on-fill); transform:scale(.97) }

.fcol{ min-width:0 }
/* the groups draw their own hairline above (§8 top), not the disclosure's */
.footer .acc__item{ border-bottom:0 }
/* Phones: every group heading is one 48px row, the compact disclosure's
   (components.css §14, the footer carries .acc--compact: --t-body 600 on
   --lh-ui, a 20px chevron), whether it is a trigger (information,
   categories) or the open contact group's heading. From 768px the
   headings are the panel title role over their columns. */
.fcol__h{
  display:flex; align-items:center; min-height:48px;
  margin:0;
  font-size:var(--t-body); line-height:var(--lh-ui); font-weight:600; color:var(--ink);
}
@media (min-width:768px){
  .fcol__h{
    display:block; min-height:0;
    font-size:var(--t-h3); line-height:var(--lh-h3); font-weight:700;
    letter-spacing:var(--ls-heading);
  }
}
.fcol__p{
  display:grid; grid-template-rows:0fr; visibility:hidden;
  transition:grid-template-rows var(--d-ui) var(--ease-out),
             visibility 0s linear var(--d-ui);
}
.fcol.is-open > .fcol__p{
  grid-template-rows:1fr; visibility:visible;
  transition:grid-template-rows var(--d-ui) var(--ease-out), visibility 0s;
}
.fcol__p--static{ grid-template-rows:1fr; visibility:visible; transition:none }
.fcol__inner{ overflow:hidden; min-height:0 }
/* The clip exists for the phone disclosure's 0fr to 1fr animation. A static
   column never animates, and there the clip only ever cut text: at 1024 it
   sliced the phone number to "+995 591 58 2" (audit T8). */
.fcol__p--static > .fcol__inner{ overflow:visible }
.fcol__l{ padding-block:0 var(--s-4) }
/* 44px at every width: a tablet at 768px is still a touch device.
   Nav links on --page-2 (design.md §2): --ink-2, hover --ink underlined,
   press a --bd fill, the current page --ink at 600. */
.fcol__a{
  display:flex; align-items:center; gap:var(--s-2);
  min-height:44px; padding-block:var(--s-1);
  color:var(--ink-2); font-size:var(--t-body); line-height:var(--lh-ui);
  transition:color var(--d-hover) var(--ease);
}
@media (hover:hover){
  .fcol__a:hover{ color:var(--ink); text-decoration:underline; text-underline-offset:3px }
}
.fcol__a[aria-current="page"]{ color:var(--ink); font-weight:600 }
.fcol__a span{ min-width:0 }
@media (min-width:768px){
  .fcol__h{ margin-bottom:var(--s-3) }
  .fcol__l{ padding-block:0 }
}

.fcontact{ display:flex; flex-direction:column; gap:var(--s-3); padding-bottom:var(--s-4) }
.fcontact li{ display:flex; flex-direction:column; gap:var(--s-1); min-width:0 }
/* The footer's row names are the label role (design.md §3: 500): they were
   400 while the same names on contact and about („ტელეფონი", „ელ. ფოსტა")
   stood at 500, one screen apart at 390 (review S12). */
.fcontact__k{ font-size:var(--t-small-ka); line-height:var(--lh-ui); font-weight:500; color:var(--ink-2) }
.fcontact__v{
  display:inline-flex; align-items:center; min-height:32px;
  color:var(--ink); font-size:var(--t-body); line-height:var(--lh-ui);
}
/* the e-mail is a real link: a full tap target */
a.fcontact__v{ min-height:44px; align-self:flex-start }
@media (hover:hover){ a.fcontact__v:hover{ text-decoration:underline; text-underline-offset:3px } }

/* The contact column's phone block: label, number, hours, on the same
   rhythm as the e-mail and address rows under it. It sat in a white box
   with a hairline, and a box around one line of contact reads as a widget
   rather than as part of the column (the owner's complaint, audit D8).
   The number is the phone role (design.md §3): --t-num-xl, capped at 26px
   so it never wraps in the 1024px column, its icon in --ink-2 (a phone
   icon is not a state, so it is not red, §2). */
.fphone{
  display:flex; flex-direction:column; align-items:flex-start; gap:var(--s-1);
  margin-bottom:var(--s-4);
}
.fphone__k{ font-size:var(--t-small-ka); line-height:var(--lh-ui); font-weight:500; color:var(--ink-2) }
.fphone__n{
  display:inline-flex; align-items:center; gap:var(--s-2);
  min-height:44px;
  color:var(--ink); font-size:var(--t-num-xl); font-weight:700;
  letter-spacing:var(--ls-heading); line-height:var(--lh-num);
  font-variant-numeric:tabular-nums; white-space:nowrap;
}
.fphone__n .icon{ color:var(--ink-2) }
@media (hover:hover){ .fphone__n:hover{ text-decoration:underline; text-underline-offset:3px } }
.fphone__n:active{ color:var(--ink-strong) }
.fphone__h{ font-size:var(--t-sm); line-height:var(--lh-sm); color:var(--ink-2) }

/* The payment band that stood here is gone with online payment: the catalog
   build takes orders by phone and in the shop (README). */

.footer__bar{
  display:flex; align-items:center; justify-content:space-between;
  flex-wrap:wrap; gap:var(--s-2) var(--s-4);
  padding-block:var(--s-5);
  border-top:var(--bw-1) solid var(--bd);
  font-size:var(--t-sm); color:var(--ink-2);
}
.footer__made{ display:inline-flex; align-items:center; gap:var(--s-2) }
/* The route arrow is set in the text's own ink. Red is spent on actions and
   state (design.md §2, "Where red is allowed"), and a decorative glyph in a
   legal line is neither (audit D43). */
.footer__arrow{ color:var(--ink-2) }


/* ── 9. MOBILE BOTTOM BAR: <768px, fixed ────────────────────────────────
   design.md §7. Exactly five items: home · catalog · search · wishlist ·
   call. --bar-nav (56px) plus the safe area, opaque, never translucent over
   content. The items fill the bar's content box, so none sticks 1px out of
   it (audit L24): the top hairline is an inset shadow, not a border.
   The active item is marked by its ink and a 3px red bar above its icon.

   LABELS (the owner's D41 default, OD8): every label a slot can hold whole,
   and never a clipped one. All five show whenever all five fit, which
   layout.js measures (fitBarLabels) and says with .bottombar--labels: in
   equal slots in Georgian from 410px (the five need 62, 74, 40, 82 and 62px
   at 14px) and in English from 360px, and in slots sized by their labels
   (.bottombar--fit, below) in Georgian at 400 to 409px and in English at
   320 to 359px („Catalogue" is 67px). Otherwise only the active item's label
   shows, and it may run past its own slot into its neighbours' empty label
   space, centred on its icon, so no icon ever moves. Every label keeps its
   line box (visibility, not display), which is also what keeps the icons
   still. A label is the label role on --lh-ui, never line-height 1 in a
   clipping box, which cut every Georgian descender (audit TC2).

   While the product call bar is on, it takes this bar's place (design.md
   §14.13, the owner's OD16 default): the bar slides away, and --bottombar
   drops to 0px so the call bar, positioned on it, lands where this bar was.
   ---------------------------------------------------------------------- */
.bottombar{
  position:fixed; z-index:var(--z-bar);
  inset-inline:0; bottom:0;
  display:flex; align-items:stretch;
  height:calc(var(--bar-nav) + env(safe-area-inset-bottom));
  padding-bottom:env(safe-area-inset-bottom);
  background:var(--paper);
  box-shadow:inset 0 var(--bw-1) 0 var(--bd), var(--sh-up);
  transition:transform var(--d-ui) var(--ease), visibility 0s;
}
@media (min-width:768px){ .bottombar{ display:none } }
:root:has(body.buybar-on){ --bottombar:0px }
:root:has(body.buybar-on) .bottombar{
  transform:translateY(100%); visibility:hidden;
  transition:transform var(--d-ui) var(--ease), visibility 0s linear var(--d-ui);
}

.bbi{
  --mark:3px;                   /* the active marker's height */
  position:relative;
  flex:1 1 0; min-width:0;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:var(--s-1);
  color:var(--ink-2);
  transition:color var(--d-hover) var(--ease), background-color var(--d-press) var(--ease-out);
}
.bbi:active{ background:var(--bd) }
.bbi::before{
  content:""; position:absolute; top:0; left:50%;
  width:32px; height:var(--mark); margin-left:-16px;
  border-radius:0 0 var(--r-pill) var(--r-pill);
  background:var(--red);
  transform:scaleX(0); transform-origin:center;
  transition:transform var(--d-ui) var(--ease-out);
}
.bbi.is-on{ color:var(--ink-strong) }
.bbi.is-on::before{ transform:scaleX(1) }
.bbi__ic{ display:grid; place-items:center }
/* THE COUNT BADGE ON THE BAR (design.md §6 "Count badge", §7). The item is
   its host here, not the icon. At the icon's top inline end, as in the
   header, the badge covered 16px of the red marker above the icon and rose
   1.1px over the bar's edge: one red shape on the wishlist page, the one
   page where the heart is current (final constraints check, 1.1). It
   stands --s-1 under the marker, on the heart's inline shoulder (the glyph
   ends 10px past the item's centre; the badge starts 2px inside that), and
   its --paper ring still cuts it from the glyph. The item's inside focus
   ring (§10b) keeps clear of it at the narrowest slot, 64px at 320. */
.bbi .count--icon{
  top:calc(var(--mark) + var(--s-1));
  inset-inline-start:calc(50% + 8px);
}
.bbi__l{
  position:relative; z-index:1;   /* over an item's inside ring, §10b */
  font-size:var(--t-small-ka); line-height:var(--lh-ui); font-weight:500;
  white-space:nowrap;
  visibility:hidden;
}
/* A shown label takes its bar's visibility, never `visible`: a child's
   `visible` overrides a hidden ancestor. Under reduced motion the bar
   stays in place, hidden, while the call bar has its place (§11), and
   `visible` printed the labels over the call bar's article code and let
   them take the taps meant for its copy control and its call (final
   accessibility check, P1). */
.bbi.is-on .bbi__l,
.bottombar--labels .bbi__l{ visibility:inherit }
/* At the bar's two ends a label keeps --s-2 from the screen's edge: it
   moves itself, never its icon, and only as far as it must. „მთავარი" is
   62px, centred on a 64px slot at 320, and stood 1.2px from the edge
   (verify S-6). 10cqi is half a slot; a label that fits its slot, as all
   five do from 410px, does not move. */
.bottombar{ container:bbar / inline-size }
.bbi:first-child .bbi__l{ translate:max(0px, calc(50% - 10cqi + var(--s-2))) 0 }
.bbi:last-child .bbi__l{ translate:min(0px, calc(10cqi - var(--s-2) - 50%)) 0 }
/* the last fallback, for a label that outgrows its slot after the check */
.bottombar--labels .bbi__l{ max-width:100%; overflow:hidden; text-overflow:ellipsis }
/* SLOTS SIZED BY THEIR LABELS, when the five labels do not fit five equal
   slots but do fit the bar: each slot is its label and an equal share of
   the spare width, never under the 44px target. fitBarLabels only chooses
   this when every label has --s-4 of air, so the first and the last keep
   --s-2 from the screen's edge without moving. „Catalogue" is 67px and a
   slot is 64px at 320px; English spells it one way now (translator). */
.bottombar--fit .bbi{ flex:1 1 auto; min-width:44px }
.bottombar--fit .bbi:first-child .bbi__l,
.bottombar--fit .bbi:last-child .bbi__l{ translate:none }


/* ── 10. BREADCRUMB BAR ───────────────────────────────────────────────────
   LS.layout.breadcrumb([…]) mounts a .crumbs (components.css §8) in here;
   the information pages print the same markup statically. design.md §7
   "Breadcrumbs" and §14.6: a 44px row, --s-1 above and --s-2 below.
   ---------------------------------------------------------------------- */
.crumbbar{ padding-block:var(--s-1) var(--s-2) }
/* An empty mount holds one crumb row. Every page that puts `#ls-crumbs` in
   its markup fills it from script, so the bar is never permanently empty; it
   is only empty for the few hundred milliseconds before the data lands, and
   without a reservation everything below it drops by a whole row when it
   does. A crumb is `min-height:44px` (components.css §8) and this bar adds
   its own padding, which is what the calc says. */
.crumbbar:empty{ min-height:calc(44px + var(--s-1) + var(--s-2)) }

/* BELOW 768px THE TRAIL IS ONE BACK LINK: a 16px chevron and the parent's
   name (the crumb before the current page: the subcategory or category on a
   product page, the category on a subcategory page, home on an information
   page), the label role in --ink-2, ellipsised if the name is long. The
   product's own name is never in it; the h1 says it. The sideways scrolling
   trail parked at its end showed a fragment from the middle of the product
   title and hid the categories (audits D27, M13, C15, K7, P13, F9). One
   link is one row, so the reservation above always holds.
   The chevron is drawn here, as the station dots are, so the static trails
   of the information pages match the helper's without a script.
   The link is a block here, not the component's flex box: only a block
   container draws an ellipsis, and in the flex box a long name (the
   „ჯანმრთელობა და პირველადი დახმარება" aisle at 320) was cut mid-letter.
   Its padding makes the 44px row around one line box, and the chevron sits
   in the middle of that line box whatever face is painting. */
@media (max-width:767.98px){
  .crumbbar .crumbs li{ display:none }
  .crumbbar .crumbs li:has(+ li:last-child){ display:flex; max-width:100% }
  .crumbbar .crumbs li::before{ display:none }
  .crumbbar .crumbs li:has(+ li:last-child) > a{
    display:block; padding-block:calc((44px - 1lh) / 2);
    font-size:var(--t-small-ka); line-height:var(--lh-ui); font-weight:500; color:var(--ink-2);
  }
  .crumbbar .crumbs li:has(+ li:last-child) > a::before{
    content:""; display:inline-block; vertical-align:top;
    margin-block-start:calc((1lh - 16px) / 2); margin-inline-end:var(--s-2);
    width:16px; height:16px;
    background:currentColor;
    -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 4.5 7.5 12l7.5 7.5'/%3E%3C/svg%3E") center / 16px 16px no-repeat;
            mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 4.5 7.5 12l7.5 7.5'/%3E%3C/svg%3E") center / 16px 16px no-repeat;
  }
}
/* FROM 768px THE FULL TRAIL ON ONE LINE: the last crumb ellipsises when the
   line runs out; it never wraps (a wrapped trail started its second line
   with a dot). The current crumb is a block for the same reason as the
   back link above: the component's flex box cut the product name without
   an ellipsis. It is not a target, so it needs no 44px of its own; the
   links beside it hold the row. */
@media (min-width:768px){
  .crumbbar .crumbs ol{ flex-wrap:nowrap }
  .crumbbar .crumbs li{ flex:none }
  .crumbbar .crumbs li:last-child{ flex:0 1 auto; min-width:0 }
  .crumbbar .crumbs li:last-child > [aria-current]{ display:block; min-height:0 }
}


/* ── 10b. FOCUS RINGS INSIDE CLIPPING SCROLLERS ───────────────────────────
   A 3px ring at +2px offset is cut off by any ancestor that clips. In these
   five containers, and on the bottom bar's items, which stand on the
   screen's edges, the ring draws inward instead, so it is never truncated.
   The ring itself is never removed anywhere (design.md §12).
   ---------------------------------------------------------------------- */
.rail-nav-list :focus-visible,
.mega__body :focus-visible,
.drawer__pane :focus-visible,
.hsearch__pop :focus-visible,
.fcol__inner :focus-visible{ outline-offset:var(--ring-in) }
/* The screen's own edges cut a ring the same way. Below 768px the bottom
   bar's items end on the screen's foot, the first and the last on its
   sides too: an outside ring lost those sides, and under a phone's rounded
   corners more (final accessibility check, 5). Theirs draws inside. A bar
   label may run past its slot (§9), so while the bar holds keyboard focus
   the labels stand over the rings on the bar's paper: a ring passes behind
   a label, never through its letters. */
@media (max-width:767.98px){
  .bbi:focus-visible{ outline-offset:var(--ring-in) }
}
.bottombar:has(.bbi:focus-visible) .bbi__l{ background:var(--paper) }
.bottombar:has(.bbi:focus-visible) .bbi:active .bbi__l{ background:none }


/* ── 10c. PRESS STATES ────────────────────────────────────────────────────
   The shell turns the platform's tap highlight off (§0), so every surface in
   that list owes the thumb an answer of its own, never gated (design.md §2:
   press is the touch answer). One step of luminance under the press, --bd on
   light (the footer included), --bd-2 where the rest is already --page-2;
   the two brand marks and the icon controls take the press scale instead.
   ---------------------------------------------------------------------- */
.sg__opt:active,
.dsec__a:active{ background:var(--bd) }
.dback:active{ background:var(--bd-2) }
.pmini:active{ background:var(--page-2) }
.fcol__a:active{ background:var(--bd) }


/* ── 10d. THE TEXT PAGES' FONT SWAP (SH13) ───────────────────────────────
   Google Sans can arrive after the first paint (font-display swap; only the
   page's own script file is preloaded, base.css §0), so a text page may
   first paint in the fallback face and reflow when the face lands: while
   the face came from gstatic, on terms, privacy and contact
   that was a layout shift of 0.1 to 0.5 at 768 to 1440 with the header
   reserved (0 with the font blocked). Two things moved. A column measured
   in ch changed width, because a ch is the zero of the face painting it
   (the tokens are em now, base.css; page.css's 64ch is its own until IN2);
   and the lines re-broke, because the fallback's Georgian is wider. On
   Windows that fallback is Segoe UI, and these faces are Segoe UI scaled to
   Google Sans per weight and per class of character, measured on the terms
   text: the Georgian letters to their width (3 to 9% narrower), the space
   to its width (15% narrower), the digits to the zero (17 to 20% wider, so
   a ch is the same) and the punctuation to its width. Google Sans arrives
   in two files, the Georgian letters and the rest, often a frame apart:
   matched class by class, each file's arrival is width-neutral on its own,
   so the swap moves glyphs and never lines. Scoped to the information
   pages' column and the status page: the home page reserves boxes measured
   in the plain fallback. The Latin letters are matched too, since the
   English pages carry their own long texts: unmatched, /en/terms and
   /en/privacy shifted 0.11 to 0.21 at 320 and 430 when the Latin file
   landed (shared-r1). Measured the same way on the English terms, privacy
   and about (10 420 letters; the method gives the space its 84.7% again):
   Google Sans is 2.6 to 4.9% wider than Segoe UI. Where Segoe UI is absent
   (Android, Apple) the faces do not load and the stack goes on as before. */
@font-face{ font-family:"LS Georgian Fallback"; font-weight:400; src:local("Segoe UI"); size-adjust:97.1%;
            unicode-range:U+10A0-10FF, U+1C90-1CBF, U+2D00-2D2F; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:500; src:local("Segoe UI Semibold"); size-adjust:94.9%;
            unicode-range:U+10A0-10FF, U+1C90-1CBF, U+2D00-2D2F; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:600; src:local("Segoe UI Semibold"); size-adjust:96%;
            unicode-range:U+10A0-10FF, U+1C90-1CBF, U+2D00-2D2F; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:700; src:local("Segoe UI Bold"); size-adjust:91.3%;
            unicode-range:U+10A0-10FF, U+1C90-1CBF, U+2D00-2D2F; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:400; src:local("Segoe UI"); size-adjust:84.7%;
            unicode-range:U+0020, U+00A0, U+202F; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:500; src:local("Segoe UI Semibold"); size-adjust:84.8%;
            unicode-range:U+0020, U+00A0, U+202F; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:600; src:local("Segoe UI Semibold"); size-adjust:84.8%;
            unicode-range:U+0020, U+00A0, U+202F; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:700; src:local("Segoe UI Bold"); size-adjust:84.8%;
            unicode-range:U+0020, U+00A0, U+202F; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:400; src:local("Segoe UI"); size-adjust:119.3%;
            unicode-range:U+0030-0039; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:500; src:local("Segoe UI Semibold"); size-adjust:118.3%;
            unicode-range:U+0030-0039; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:600; src:local("Segoe UI Semibold"); size-adjust:119.8%;
            unicode-range:U+0030-0039; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:700; src:local("Segoe UI Bold"); size-adjust:116.8%;
            unicode-range:U+0030-0039; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:400; src:local("Segoe UI"); size-adjust:101.7%;
            unicode-range:U+0021-002F, U+003A-0040, U+2010-2027; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:500; src:local("Segoe UI Semibold"); size-adjust:101.5%;
            unicode-range:U+0021-002F, U+003A-0040, U+2010-2027; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:600; src:local("Segoe UI Semibold"); size-adjust:104.2%;
            unicode-range:U+0021-002F, U+003A-0040, U+2010-2027; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:700; src:local("Segoe UI Bold"); size-adjust:100.2%;
            unicode-range:U+0021-002F, U+003A-0040, U+2010-2027; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:400; src:local("Segoe UI"); size-adjust:102.9%;
            unicode-range:U+0041-005A, U+0061-007A, U+00C0-00FF; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:500; src:local("Segoe UI Semibold"); size-adjust:103.1%;
            unicode-range:U+0041-005A, U+0061-007A, U+00C0-00FF; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:600; src:local("Segoe UI Semibold"); size-adjust:104.9%;
            unicode-range:U+0041-005A, U+0061-007A, U+00C0-00FF; }
@font-face{ font-family:"LS Georgian Fallback"; font-weight:700; src:local("Segoe UI Bold"); size-adjust:102.6%;
            unicode-range:U+0041-005A, U+0061-007A, U+00C0-00FF; }
.pg,
.status{ font-family:"Google Sans", "LS Georgian Fallback", var(--f-ui) }


/* ── 10e. STATUS PAGE (404.html) ─────────────────────────────────────────
   design.md §14.12: the page header pattern whose h1 is the state's title
   (the empty state's whole-page variant, components.css §12), the state's
   sentence, then the way on: the search field (§6, the one large field,
   here a plain form to the results page) and the biggest aisles as
   suggestion chips, which layout.js fills from the category tree.
   The page is at least one screen tall (svh, the smallest viewport, so the
   height holds while a phone's browser bars come and go): the chips arrive
   after the first paint and wrap to one row or six depending on the width
   and the names, and in a shorter page they pushed the footer down inside
   the first screen (0.113 at 390). Now they land in space that is already
   the page's, and the footer starts below the fold. */
.status{ min-height:100vh; min-height:100svh }
.status__search{ width:100%; max-width:var(--measure-short) }


/* ── 11. REDUCED MOTION ─────────────────────────────────────────────────
   The duration tokens are 0s here (base.css); what is left is to take the
   travel out: panels and bars simply appear and leave, presses do not
   scale. A state carried by a rotation (a chevron) keeps its end state. */
@media (prefers-reduced-motion: reduce){
  .mega{ transform:none }
  .mega.is-open{ transform:none }
  .drawer{ transform:none; opacity:0 }
  .drawer.is-open{ opacity:1 }
  .drawer__track{ transition:none }
  .bbi::before{ transition:none }
  /* no slide: the bar is simply hidden where it stands, labels included
     (they inherit its visibility, §9) */
  :root:has(body.buybar-on) .bottombar{ transform:none }
  .hdr__brand:active,
  .fbrand__logo:active,
  .act:active,
  .fsocial__a:active{ transform:none }
  .catbtn[aria-expanded="true"] .icon:last-child{ transform:rotate(180deg) }
}
/* the see-all arrow's hover step, taken out with the rest of the travel */
@media (prefers-reduced-motion: reduce) and (hover:hover){
  .mega__all:hover .icon{ transform:none }
}
