/* navbar.css — cleaned and organized
   Sections: variables, layout, containers, search, controls
*/

:root {
  --navbar-bg: #04202C;
  --navbar-search-w: 520px;
  --navbar-search-h: 2.5rem;
  --navbar-search-bg: #506578;
}

/* -----------------------------
   Layout
   ----------------------------- */
#mainNavbar {
  background: var(--navbar-bg);
  width: 100%;
  z-index: 3000;
  padding: 0;
  position: fixed;
  top: 0; left: 0; right: 0;
}

#searchContainer {
  background: var(--color-forest);
  color: #fff;
  width: 100%;
  z-index: 2000;
  position: sticky;
  top: 0;
}

.navbar-main-row {
  display: flex;
  align-items: center;
  min-height: 50px;
  width: 100%;
  padding: 12px;
  gap: .5rem;
}

/* When navbars are fixed, the page content needs top offset. Use `.pt-navbar` on <main>. */
.pt-navbar { padding-top: calc(var(--navbar-search-h) + 24px); }

/* Spacer div to offset fixed navbar while keeping bg-color from the page header */
.mercat-navbar-spacer { height: calc(var(--navbar-search-h) + 24px); }

/* -----------------------------
   Search containers
   ----------------------------- */
.navbar-search-wrap { width: 100%; max-width: var(--navbar-search-w); margin: 0 auto; position: relative; }
.navbar-search-wrap.w-100 {
  max-width: 900px;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 12px;
  width: 100%;
  box-sizing: border-box;
}

/* IMPORTANT: keep this specific override — do not remove it. */
.navbar-search-wrap.w-100 .navbar-back-btn{margin-right:0 !important;margin-inline-end:0 !important}

/* -----------------------------
   Search input
   ----------------------------- */
.navbar-search {
  width: 100%;
  font-size: 1rem;
  height: var(--navbar-search-h);
  line-height: var(--navbar-search-h);
  padding-top: 0;
  padding-bottom: 0;
  padding: 0 12px;
  background: var(--navbar-search-bg);
  border: none;
  color: #fff;
  border-radius: 1.25rem;
  box-sizing: border-box;
  transition: background .2s, border-color .2s, width .2s, padding .2s;
}
.navbar-search::placeholder { color: rgba(255,255,255,.5); }
#mainNavbar .navbar-search,
#mainNavbar .navbar-search:focus,
#searchContainer .navbar-search,
#searchContainer .navbar-search:focus { color: #fff; }
#mainNavbar .navbar-search:focus,
#searchContainer .navbar-search:focus {
  background: #516578;
  border: 0 solid #7ec3ff;
  box-shadow: 0 0 0 1px #7ec3ff, 0 2px 16px 0 rgba(126,195,255,.15);
  outline: none;
}

/* -----------------------------
   Load guard: while the page is loading, no navbar element may transition.
   Browsers can apply styles in stages during load (especially with heavy
   pages like the AI assistant); without this, buttons visibly "appear" and
   shift mid-load. navbar.js removes .navbar-preload once the page settles.
   ----------------------------- */
#mainNavbar.navbar-preload .navbar-back-btn,
#mainNavbar.navbar-preload .navbar-cart-btn,
#mainNavbar.navbar-preload .navbar-assistant-chip,
#mainNavbar.navbar-preload .navbar-assistant-chip-label,
#mainNavbar.navbar-preload .navbar-search,
#mainNavbar.navbar-preload .navbar-search-icon,
#mainNavbar.navbar-preload .navbar-search-clear {
  transition: none !important;
}

/* -----------------------------
   Back button
   ----------------------------- */
.navbar-back-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: var(--navbar-search-h);
  height: var(--navbar-search-h);
  min-width: var(--navbar-search-h);
  padding: 0;
  margin-right: 0;
  background: #516578;
  border: none;
  border-radius: 50%;
  overflow: hidden;
  color: #fff;
  font-size: 1.1rem;
  cursor: pointer;
  transition: background .18s, color .18s, transform .22s cubic-bezier(.2,.8,.2,1),
              opacity .22s ease, width .22s ease, min-width .22s ease, margin-right .22s ease;
  box-shadow: 0 0 0 1px #7ec3ff, 0 2px 8px 0 rgba(126,195,255,.1);
  -webkit-tap-highlight-color: transparent; /* el feedback de toc el dona el :active */
}
.navbar-back-btn:active { transform: scale(0.9); }

.navbar-search { padding-left: 34px; padding-right: 12px; }

/* -----------------------------
   Search icon — a decorative magnifying glass inside the field, in front of
   the placeholder/typed text. Positioned relative to `.navbar-search-wrap`
   (like the clear button/chip/cart), not the input itself (an <input> can't
   have children), so its `left` must track the input's own left edge, which
   shifts when the back button collapses on the market root — same 52px
   (button+gap) used by the assistant chip's math, mirrored here from the
   left instead of the right. Always 12px inside the input's own edge either
   way, matching the collapsed chip's 6px-per-side gutter in spirit.
   ----------------------------- */
.navbar-search-icon {
  position: absolute;
  left: 64px; /* 52 (back button + gap) + 12 (inset inside the input) */
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  color: rgba(255, 255, 255, .55);
  font-size: .95rem;
  pointer-events: none;
  transition: left .22s ease;
}
body.is-mercat-root .navbar-search-icon { left: 12px; /* back button collapsed: input starts flush at the wrap's edge */ }

/* -----------------------------
   Cart button (mirrors .navbar-back-btn visuals)
   Hidden/collapsed until the cart has items — navbar-cart.js toggles
   `.is-collapsed`; the search field width follows via flexbox.
   ----------------------------- */
.navbar-cart-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: var(--navbar-search-h);
  height: var(--navbar-search-h);
  min-width: var(--navbar-search-h);
  padding: 0;
  background: #516578;
  border: none;
  border-radius: 50%;
  color: #fff;
  font-size: 1.1rem;
  cursor: pointer;
  box-shadow: 0 0 0 1px #7ec3ff, 0 2px 8px 0 rgba(126,195,255,.1);
  -webkit-tap-highlight-color: transparent;
  transition: background .18s, color .18s, transform .22s cubic-bezier(.2,.8,.2,1),
              opacity .22s ease, width .22s ease, min-width .22s ease, margin-left .22s ease;
}
.navbar-cart-btn:active { transform: scale(0.9); }

.navbar-cart-btn.is-collapsed {
  width: 0;
  min-width: 0;
  margin-left: -12px; /* swallow the flex gap so the search recovers full width */
  opacity: 0;
  transform: scale(0.6);
  box-shadow: none;
  overflow: hidden;
  pointer-events: none;
}

/* Disable transitions during initial sync so a pre-filled cart doesn't animate on load */
.navbar-cart-btn--instant { transition: none !important; }

.navbar-cart-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 999px;
  background: #fff;
  color: var(--color-forest, #04202C);
  font-size: 11px;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
  box-shadow: 0 1px 3px rgba(0,0,0,.25);
}

/* "Product added" chip: fixed just below the cart button, same right margin */
.navbar-cart-chip {
  position: absolute;
  top: calc(100% + 18px);
  right: 0;
  z-index: 2900;
  max-width: min(85vw, 420px);
  padding: 8px 14px;
  border-radius: 999px;
  /* Same 70% opacity as the product stepper's own forest pill
     (.stepper/.cart-stepper in cart.css) — same colour, same transparency
     level, for visual consistency between the two "cart activity" cues. */
  background: color-mix(in srgb, var(--color-forest, #04202C) 70%, transparent 30%);
  color: #fff;
  font-size: .875rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  box-shadow: 0 2px 8px rgba(0,0,0,.1);
  opacity: 0;
  transform: translateY(-4px);
  pointer-events: none;
  transition: opacity .18s ease, transform .18s ease;
}
.navbar-cart-chip.is-visible { opacity: 1; transform: translateY(0); }
.navbar-cart-chip.is-hiding { transition: opacity .12s ease, transform .12s ease; }

/* The cart page itself: navigating to the cart from the cart is pointless */
body.cistella-page .navbar-cart-btn,
body.cistella-page .navbar-cart-chip { display: none !important; }

/* Checkout (Bloque 4): already past the cart, same reasoning as above */
body.comanda-page .navbar-cart-btn,
body.comanda-page .navbar-cart-chip { display: none !important; }

/* -----------------------------
   Assistant chip inside the search field
   Expanded: icon + "Assistent". Collapses to icon-only (same fluid feel as
   the back/cart buttons) whenever the search is active: on /search
   (body.search-page), input focused, or input has text — the last two via
   sibling selectors, so the chip markup must follow the input.
   ----------------------------- */
.navbar-assistant-chip {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  display: inline-flex;
  align-items: center;
  /* Explicit (not `auto`) so `width` is always a transitionable number — CSS
     transitions can't interpolate to/from `auto`. 103px matches this state's
     natural content size (icon + "Assistent" + padding); see the icon-only
     and ai-page rules below for the other two explicit widths. */
  width: 103px;
  height: 28px;
  padding: 0 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .14);
  color: #fff;
  font-size: .85rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
  transition: width .22s ease, right .22s ease, background .18s, transform .12s;
}
.navbar-assistant-chip:hover, .navbar-assistant-chip:focus { color: #fff; background: rgba(255, 255, 255, .22); }
.navbar-assistant-chip:active { transform: translateY(-50%) scale(0.92); }
.navbar-assistant-chip .bi-stars { font-size: 15px; line-height: 1; }

/* -----------------------------
   Background task indicator (static/js/navbar-assistant.js sets
   [data-task-status] on the chip; see AiAssistantTask in models.py for the
   possible values). Deliberately untouched here: chip size/position/icon/
   label/layout — only a ring+glow drawn OUTSIDE the pill via ::before, so
   the chip itself never resizes or shifts the search field.

   ::before is the RING ITSELF — a thin masked band (padding +
   mask-composite:exclude, so only a band shows, not a filled disc). It
   never moves: for `running` it's a static, softly-blended base tone at
   1.6px thick; for `needs_input`/`error`/`completed_unread` it's a static
   solid colour at 1px, matching the back/cart buttons' own outline
   thickness (an earlier version of `completed_unread` used a small
   filled corner dot instead — replaced for consistency with the other
   two). The `running` comet itself is a separate real SVG element
   (.navbar-assistant-chip-track, markup in navbar.html), not a
   pseudo-element — see its own comment further below for why. */
.navbar-assistant-chip::before {
  content: '';
  /* Flush with the chip's own edge (NOT inset:-3px as a earlier version
     had it): .navbar-assistant-chip has its own `overflow: hidden` a few
     rules above (clips the label text while its width transitions) —
     anything positioned outside the chip's own box gets silently clipped
     by that, which is why an earlier version of this ring/dot never
     actually rendered. Sitting exactly at inset:0, the masked band below
     stays fully inside those bounds. */
  position: absolute;
  inset: 0;
  border-radius: 999px;
  /* Ring thickness (1.5-2px): the gap between the two mask layers below */
  padding: 1.6px;
  background: transparent;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s ease;
}

/* running: the ring itself (::before) is a STATIC band in the same blue
   used for the back/cart buttons' outline (#7ec3ff, box-shadow 0 0 0 1px
   in .navbar-back-btn/.navbar-cart-btn) — it never rotates, never scales,
   never moves. A soft pulsing glow OUTSIDE the pill (box-shadow on the
   chip itself) breathes alongside it, echoing that same blue.

   The moving "comet" is a SEPARATE SVG (`.navbar-assistant-chip-track` in
   navbar.html, six stacked <rect> "wagons") rather than a pseudo-element
   pushed around with `offset-path` + a rotated shape. That earlier
   approach (see git history) could only ever APPROXIMATE the ring with a
   straight/elliptical shape reoriented every frame to the path's local
   tangent — fine on the long straight sides, but the chip's rounded ends
   are full 180° SEMICIRCLES with a 14px radius (half the fixed 28px chip
   height), and reproduced with dense Playwright screenshots across a full
   loop: any tail long enough to be worth having flew visibly outside the
   pill mid-turn, because a rigid shape rotated to match one instant's
   tangent necessarily diverges from a curve tightening as fast as that.
   No amount of tuning fixes that; the technique itself can't guarantee
   "always exactly on the curve."

   The SVG wagons can, because each one IS a literal segment of the same
   stroked shape as the ring itself (`pathLength="100"` normalises
   stroke-dasharray/-offset to percent-of-perimeter, so this works
   identically at every chip width — collapsed icon, default, or the wide
   ai-page pill). Like a train on rails: the rects define the track, each
   wagon's dash rides that exact track, so none of them can ever cut a
   corner or drift off it, however tight the turn. Six wagons, staggered
   via `animation-delay` on one shared keyframe (all riding the SAME
   track), give a locomotive (wagon-0, opaque) fading back through
   wagon-5 (faint) — together spanning ~15% of the perimeter. */
.navbar-assistant-chip[data-task-status="running"] {
  /* .navbar-assistant-chip's base rule sets overflow:hidden to clip the
     LABEL text while its own max-width/margin transition (label-collapse
     on search focus) — but that clipping also silently cuts off anything
     painted past the chip's own edge, including the wagons' outward glow
     (see .navbar-assistant-chip-track below): with overflow:hidden it
     could only ever glow INWARD, never past the border into the halo.
     Safe to lift here because the label already clips ITSELF
     independently (.navbar-assistant-chip-label has its own max-width +
     overflow:hidden, a few rules below) — so text truncation during a
     simultaneous collapse still works with this ancestor left open. */
  overflow: visible;
}
.navbar-assistant-chip[data-task-status="running"]::before {
  opacity: 1;
  background: linear-gradient(135deg,
    rgba(126, 195, 255, .95),
    rgba(126, 195, 255, .65) 50%,
    rgba(126, 195, 255, .95)
  );
}
/* The SVG sits UNDER the icon/label (first in source order) and takes no
   part in the chip's flex layout — absolutely positioned to exactly
   overlay it instead. `overflow: visible` on both the svg and (above) the
   chip itself is what lets the wagons' drop-shadow glow bleed past the
   ring, inward and outward at once, rather than being clipped like the
   very first version of this effect was.

   0.8px in from the chip's edge, not flush with it (top/left + explicit
   width/height below, not `inset: 0.8px` shorthand — see why below): the
   STATIC ring (::before) is a masked band that sits fully INSIDE the
   chip's true edge (padding:1.6px between the content-box and border-box
   masks — see that rule's own comment above), so its visible band runs
   from the true edge to 1.6px inward, centred 0.8px in. A stroke centred
   on a rect flush with the chip's true edge straddles that edge instead
   (0.8px out / 0.8px in), which visibly runs outside where the ring
   itself is. Insetting the SVG box by 0.8px on every side moves the
   rect's own edge — and so the stroke's centreline — onto that same
   0.8px-in centre, so the wagons ride the ring exactly instead of
   floating outside it. The rect's rx/ry in navbar.html (13.2, not 14) is
   half of the resulting 26.4px-tall box, keeping its ends true
   semicircles at this new size.

   Explicit `width`/`height: calc(100% - 1.6px)`, NOT the `inset: 0.8px`
   shorthand alone: measured this with getBoundingClientRect() across
   Chromium and WebKit after finding the wagons ran fine on the chip's top
   edge but visibly past the bottom edge on a real device. Two bugs, each
   masking symptoms of the other while chasing this:
   1. navbar.html's <svg> also carried width="100%" height="100%"
      ATTRIBUTES. For a replaced element like <svg>, those set its used
      size directly to 100% of the chip's full, un-inset box — `inset`'s
      top+left still applied as an offset, but with the size already
      pinned, the box ended up simply TRANSLATED by (0.8, 0.8) rather
      than shrunk on every side. The top edge lined up with the ring by
      coincidence (top moved the intended 0.8px); the bottom ended up a
      further 1.6px past it (bottom moved +0.8 instead of -0.8).
   2. Removing those attributes and trying `inset: 0.8px` with width/
      height left as CSS 'auto' isn't the fix either: 'auto' sizing for a
      REPLACED element (which <svg> is, per CSS2.1 §10.3.7) resolves to
      its INTRINSIC size — and a viewBox-less, attributeless <svg>'s
      intrinsic size is the UA default 300×150 — not "compute width/
      height from the inset offsets" the way it would for a plain <div>.
      The box came out pinned to top:0.8/left:0.8 but sized 300×150
      regardless of the chip's actual size.
   Giving width/height an explicit `calc()` value (neither an attribute
   nor 'auto') is what actually forces the intended size on a replaced
   element; `top`/`left` alone (no need for right/bottom/inset at all)
   then position it. */
.navbar-assistant-chip-track {
  position: absolute;
  top: .8px;
  left: .8px;
  width: calc(100% - 1.6px);
  height: calc(100% - 1.6px);
  overflow: visible;
  pointer-events: none;
}
.navbar-assistant-chip-wagon {
  fill: none;
  stroke: none;
}
.navbar-assistant-chip[data-task-status="running"] .navbar-assistant-chip-track {
  /* One shared glow for the whole assembled comet (all 25 wagons) rather
     than a filter per wagon — cheaper, and blends them into one
     continuous halo instead of 25 separate blurred copies. */
  filter: drop-shadow(0 0 3px rgba(126, 195, 255, .85));
}
.navbar-assistant-chip[data-task-status="running"] .navbar-assistant-chip-wagon {
  stroke: rgb(186, 222, 255);
  stroke-width: 3.2;
  /* Flat (butt) ends by default: with dashes exactly as long as the
     stagger between them (below), consecutive wagons then abut with
     ZERO overlap. An earlier version used round caps on every wagon —
     each cap extends the visible stroke by half the stroke-width past
     its nominal dash edge, so neighbouring wagons' rounded ends actually
     overlapped, doubling up opacity into a visible bright bead at every
     seam ("se ilumina entre vagones"). wagon-0 gets its round cap back
     below, only on the LEADING edge, since nothing precedes it there to
     overlap with. */
  stroke-linecap: butt;
  /* pathLength=100 (set in navbar.html) makes these percent-of-perimeter:
     25 wagons × 1 unit = 25 units = 25% of the perimeter, front to back —
     and matches the 1-unit stagger between them exactly, so the dashes
     tile the tail with no gap and no overlap. */
  stroke-dasharray: 1 99;
}
/* Round leading tip for the locomotive only (see the shared rule above
   for why every other wagon stays flat-capped). */
.navbar-assistant-chip-wagon-0 { stroke-linecap: round; }
/* Locomotive first, fading back to the last wagon — same blue family as
   the ring/back-cart buttons throughout, just thinning out. 25 steps so
   the fade reads as one smooth tapering tail rather than a handful of
   visibly distinct bands. */
.navbar-assistant-chip-wagon-0  { stroke-opacity: 1;   }
.navbar-assistant-chip-wagon-1  { stroke-opacity: .95; }
.navbar-assistant-chip-wagon-2  { stroke-opacity: .90; }
.navbar-assistant-chip-wagon-3  { stroke-opacity: .85; }
.navbar-assistant-chip-wagon-4  { stroke-opacity: .80; }
.navbar-assistant-chip-wagon-5  { stroke-opacity: .75; }
.navbar-assistant-chip-wagon-6  { stroke-opacity: .70; }
.navbar-assistant-chip-wagon-7  { stroke-opacity: .65; }
.navbar-assistant-chip-wagon-8  { stroke-opacity: .61; }
.navbar-assistant-chip-wagon-9  { stroke-opacity: .56; }
.navbar-assistant-chip-wagon-10 { stroke-opacity: .51; }
.navbar-assistant-chip-wagon-11 { stroke-opacity: .47; }
.navbar-assistant-chip-wagon-12 { stroke-opacity: .43; }
.navbar-assistant-chip-wagon-13 { stroke-opacity: .39; }
.navbar-assistant-chip-wagon-14 { stroke-opacity: .34; }
.navbar-assistant-chip-wagon-15 { stroke-opacity: .30; }
.navbar-assistant-chip-wagon-16 { stroke-opacity: .26; }
.navbar-assistant-chip-wagon-17 { stroke-opacity: .23; }
.navbar-assistant-chip-wagon-18 { stroke-opacity: .19; }
.navbar-assistant-chip-wagon-19 { stroke-opacity: .16; }
.navbar-assistant-chip-wagon-20 { stroke-opacity: .12; }
.navbar-assistant-chip-wagon-21 { stroke-opacity: .09; }
.navbar-assistant-chip-wagon-22 { stroke-opacity: .06; }
.navbar-assistant-chip-wagon-23 { stroke-opacity: .04; }
.navbar-assistant-chip-wagon-24 { stroke-opacity: .02; }
@media (prefers-reduced-motion: no-preference) {
  /* Longhand, NOT the `animation` shorthand: the shorthand also resets
     animation-delay (to its default 0s) as part of what it sets, and this
     selector (chip[data-task-status] + .wagon) is MORE specific than the
     per-wagon `-0`..`-24` delay rules below — so with the shorthand, that
     implicit "delay: 0s" would win the cascade on specificity and every
     wagon would collapse onto the exact same spot regardless of the
     per-wagon rules (caught this by inspecting getComputedStyle: all
     wagons reported animation-delay: 0s despite the rules below). Setting
     every other longhand here except animation-delay leaves the per-wagon
     rules free to win it on their own. */
  .navbar-assistant-chip[data-task-status="running"] .navbar-assistant-chip-wagon {
    animation-name: mercat-ai-wagon-travel;
    animation-duration: 3s;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
  }
  /* Negative delays stagger each wagon's phase on the SAME keyframe/track
     rather than giving them different keyframes — every 0.03s of delay is
     1 unit (1% of the pathLength=100 perimeter) at this 3s duration,
     matching the dash length above exactly. wagon-0 gets the LARGEST
     negative delay so it's always the most "progressed" (furthest along
     the direction of travel = the front of the train); wagon-24 gets
     none, so it's always furthest behind. */
  .navbar-assistant-chip-wagon-0  { animation-delay: -.72s; }
  .navbar-assistant-chip-wagon-1  { animation-delay: -.69s; }
  .navbar-assistant-chip-wagon-2  { animation-delay: -.66s; }
  .navbar-assistant-chip-wagon-3  { animation-delay: -.63s; }
  .navbar-assistant-chip-wagon-4  { animation-delay: -.6s;  }
  .navbar-assistant-chip-wagon-5  { animation-delay: -.57s; }
  .navbar-assistant-chip-wagon-6  { animation-delay: -.54s; }
  .navbar-assistant-chip-wagon-7  { animation-delay: -.51s; }
  .navbar-assistant-chip-wagon-8  { animation-delay: -.48s; }
  .navbar-assistant-chip-wagon-9  { animation-delay: -.45s; }
  .navbar-assistant-chip-wagon-10 { animation-delay: -.42s; }
  .navbar-assistant-chip-wagon-11 { animation-delay: -.39s; }
  .navbar-assistant-chip-wagon-12 { animation-delay: -.36s; }
  .navbar-assistant-chip-wagon-13 { animation-delay: -.33s; }
  .navbar-assistant-chip-wagon-14 { animation-delay: -.3s;  }
  .navbar-assistant-chip-wagon-15 { animation-delay: -.27s; }
  .navbar-assistant-chip-wagon-16 { animation-delay: -.24s; }
  .navbar-assistant-chip-wagon-17 { animation-delay: -.21s; }
  .navbar-assistant-chip-wagon-18 { animation-delay: -.18s; }
  .navbar-assistant-chip-wagon-19 { animation-delay: -.15s; }
  .navbar-assistant-chip-wagon-20 { animation-delay: -.12s; }
  .navbar-assistant-chip-wagon-21 { animation-delay: -.09s; }
  .navbar-assistant-chip-wagon-22 { animation-delay: -.06s; }
  .navbar-assistant-chip-wagon-23 { animation-delay: -.03s; }
  .navbar-assistant-chip-wagon-24 { animation-delay: 0s;    }
  .navbar-assistant-chip[data-task-status="running"] {
    animation: mercat-ai-glow-pulse 1.6s ease-in-out infinite;
  }
}
@keyframes mercat-ai-wagon-travel {
  to { stroke-dashoffset: -100; }
}
/* Outward glow, matching the back/cart buttons' blue: breathes between
   two intensities (never fully off) so there's no dead point in the loop
   where the "thinking" cue momentarily vanishes. Reused as-is (not
   redefined) by the AI composer input's own "still working" cue in
   ai-assistant.css, which mirrors this whole effect. */
@keyframes mercat-ai-glow-pulse {
  0%, 100% { box-shadow: 0 0 8px 1px rgba(126, 195, 255, .45); }
  50%      { box-shadow: 0 0 18px 5px rgba(126, 195, 255, .8); }
}

/* "Alive" ambient cue (UI/UX refinement sprint): while the Assistant Home
   is on screen (no conversation started yet — toggled from
   templates/public/ai_assistant.html's renderHome()/removeHome(), NOT
   navbar-assistant.js), the chip breathes with the exact same blue and
   the same mercat-ai-glow-pulse keyframe as a real `running` background
   task, echoing that the assistant "thinks" even before the first
   question. `:not([data-task-status])` is deliberate: a REAL task status
   (set independently by navbar-assistant.js's own polling) always wins —
   this purely decorative class must never fight or mask a genuine
   running/needs_input/error/completed_unread state. Ring only, no
   traveling wagons: those specifically read as "computing something right
   now", which would be misleading before any question has even been
   asked — the breathing glow alone already reads as "alive". A single
   breath (animation-iteration-count: 1, not infinite): confirmed this
   should read as a one-off "waking up" cue, not a continuous loop that
   would compete for attention with the rest of the Home indefinitely.
   Since renderHome() re-adds this class from scratch each time the Home
   is (re)shown (removeHome() removes it first), the single breath replays
   every time the user actually lands on the Home, not just the very
   first time ever. The ring itself (::before) fades out together with
   the glow instead of staying on permanently: opacity is 0 at rest, and
   only the animation below (mercat-ai-ring-fade, same 1.6s/1-iteration/
   forwards as the glow) brings it up then back down to 0, where the
   `forwards` fill keeps it once the breath ends — without `forwards` it
   would simply revert to this rule's own opacity:0 anyway, but forwards
   makes that explicit rather than incidental. */
.navbar-assistant-chip.is-home-idle:not([data-task-status]) {
  overflow: visible;
}
.navbar-assistant-chip.is-home-idle:not([data-task-status])::before {
  opacity: 0;
  background: linear-gradient(135deg,
    rgba(126, 195, 255, .95),
    rgba(126, 195, 255, .65) 50%,
    rgba(126, 195, 255, .95)
  );
}
@media (prefers-reduced-motion: no-preference) {
  .navbar-assistant-chip.is-home-idle:not([data-task-status]) {
    animation: mercat-ai-glow-pulse 1.6s ease-in-out 1;
  }
  .navbar-assistant-chip.is-home-idle:not([data-task-status])::before {
    animation: mercat-ai-ring-fade 1.6s ease-in-out 1 forwards;
  }
}
@keyframes mercat-ai-ring-fade {
  0%, 75% { opacity: 1; }
  100% { opacity: 0; }
}

/* needs_input / error / completed_unread: all three are the same static
   ring treatment (no motion, no glow), just a different colour — thinner
   than `running`'s 1.6px band (padding, above) and set to 1px instead so
   it matches the back/cart buttons' own outline exactly (box-shadow 0 0 0
   1px #7ec3ff in .navbar-back-btn/.navbar-cart-btn — see those rules). */
.navbar-assistant-chip[data-task-status="needs_input"]::before,
.navbar-assistant-chip[data-task-status="error"]::before,
.navbar-assistant-chip[data-task-status="completed_unread"]::before {
  opacity: 1;
  padding: 1px;
}
/* amber — waiting on the user's own next message */
.navbar-assistant-chip[data-task-status="needs_input"]::before {
  background: #e8a93c;
}
/* red — the turn ended in an error */
.navbar-assistant-chip[data-task-status="error"]::before {
  background: #d9503c;
}
/* Same blue as the back/cart buttons' outline: a finished reply is
   waiting to be read, not urgent/abnormal like needs_input or error, so
   it borrows their neutral accent colour rather than inventing a new one
   (an earlier version of this state used a small filled corner dot
   instead of a ring — replaced for consistency with the other two). */
.navbar-assistant-chip[data-task-status="completed_unread"]::before {
  background: #7ec3ff;
}

.navbar-assistant-chip-label {
  max-width: 90px;
  margin-left: 6px;
  opacity: 1;
  overflow: hidden;
  transition: max-width .22s ease, opacity .22s ease, margin-left .22s ease;
}

/* Longer label shown only on the assistant page itself (body.ai-page below)
   — swapped in for the short one rather than sharing it, since the collapse
   rules' max-width caps (sized for "Assistent") would otherwise clip it. */
.navbar-assistant-chip-label-full {
  display: none;
  margin-left: 6px;
  white-space: nowrap;
}

/* Collapsed (icon-only) states — 35px = icon (15px) + the chip's own 20px
   horizontal padding, once the label's width/margin above collapse to 0. */
body.search-page .navbar-assistant-chip,
.navbar-search:focus ~ .navbar-assistant-chip,
.navbar-search:not(:placeholder-shown) ~ .navbar-assistant-chip {
  width: 35px;
}

body.search-page .navbar-assistant-chip .navbar-assistant-chip-label,
.navbar-search:focus ~ .navbar-assistant-chip .navbar-assistant-chip-label,
.navbar-search:not(:placeholder-shown) ~ .navbar-assistant-chip .navbar-assistant-chip-label {
  max-width: 0;
  margin-left: 0;
  opacity: 0;
}

/* Follow the input's right edge when the cart button occupies the row end */
.navbar-search-wrap.has-cart .navbar-assistant-chip { right: calc(var(--navbar-search-h) + 18px); }

/* ...but on the cart page the cart button is display:none while the wrap
   keeps .has-cart — the input runs to the row end, so keep base offsets */
body.cistella-page .navbar-search-wrap.has-cart .navbar-assistant-chip { right: 6px; }
body.cistella-page .navbar-search-wrap.has-assistant.has-cart .navbar-search-clear { right: 44px; }

/* Reserve input space under the chip (values track chip width per state) */
.navbar-search-wrap.has-assistant .navbar-search { padding-right: 112px; }
body.search-page .navbar-search-wrap.has-assistant .navbar-search,
.navbar-search-wrap.has-assistant .navbar-search:focus,
.navbar-search-wrap.has-assistant .navbar-search:not(:placeholder-shown) { padding-right: 48px; }

/* Clear (×) button for navbar search */
.navbar-search-clear { position: absolute; right: 12px; top: 50%; transform: translateY(calc(-50% - 1px)); border: none; background: transparent; color: #fff; font-size: 18px; line-height: normal; padding: 0 8px; cursor: pointer; z-index: 3; height: var(--navbar-search-h); display: inline-flex; align-items: center; justify-content: center; transition: right .22s ease; }

/* Keep the × inside the input when the cart button occupies the right edge */
.navbar-search-wrap.has-cart .navbar-search-clear { right: calc(var(--navbar-search-h) + 24px); }

/* And left of the assistant chip (× is only visible with text, when the chip
   is already collapsed to icon-only ≈35px + 6px inset) */
.navbar-search-wrap.has-assistant .navbar-search-clear { right: 44px; }
.navbar-search-wrap.has-assistant.has-cart .navbar-search-clear { right: calc(var(--navbar-search-h) + 24px + 32px); }
.navbar-search-clear.d-none { display: none; }
.navbar-search-clear:focus { outline: none; }

/* Hide native browser 'clear' buttons for search inputs so we don't duplicate UI */
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-results-button,
input[type="search"]::-webkit-search-results-decoration {
  -webkit-appearance: none;
  appearance: none;
  display: none;
}
/* IE/Edge clear/reveal buttons */
input[type="search"]::-ms-clear,
input[type="search"]::-ms-reveal {
  display: none;
  width: 0;
  height: 0;
}

/* Collapse the back-button only on the exact mercat root URL (the template
   adds `is-mercat-root` to the body when request.path == '/' + slug_mercat).
   Same collapsed pattern as .navbar-cart-btn.is-collapsed so it appears with
   fade+scale and the search field width follows smoothly on SPA navigations.
   `!important` needed to beat `.navbar-search-wrap.w-100 .navbar-back-btn`. */
body.is-mercat-root .navbar-back-btn,
body.is-mercat-root .navbar-search-wrap.w-100 .navbar-back-btn {
  width: 0;
  min-width: 0;
  margin-right: -12px !important; /* swallow the flex gap so the search recovers full width */
  margin-inline-end: -12px !important;
  opacity: 0;
  transform: scale(0.6);
  box-shadow: none;
  pointer-events: none;
}

/* -----------------------------
   AI assistant page: the chip itself expands horizontally to fill the
   search field (rather than swapping to a different element) — the input
   stays in the DOM, unhidden, just visually covered by the now-wider chip
   sitting above it (z-index 3). Never grows vertically: height/top/transform
   are untouched, so it keeps the exact same 6px top/bottom margin (28px
   chip inside the 40px-tall row) it already had collapsed. `right` is also
   unchanged (still 6px, same as collapsed) — only `width` grows, which
   pushes the left edge leftward, landing 6px inside the input's own left
   edge (52px back-button-width+gap, +6px for that same margin, +6px for
   the unchanged right inset = 64px) so all four sides keep a matching 6px
   gutter, same as before expanding. Color is untouched — same translucent
   pill as always, just wider. */
/* !important: the input can carry leftover text from whatever page was
   SPA-navigated away from (its value isn't cleared on navigation), which
   keeps `:not(:placeholder-shown)` matching and would otherwise win — that
   selector's specificity (three class-level selectors) outranks this one
   (two classes + `body`) despite coming first in the file. */
body.ai-page .navbar-assistant-chip {
  width: calc(100% - 64px) !important;
  justify-content: center;
}

body.ai-page .navbar-search-wrap.has-cart .navbar-assistant-chip {
  width: calc(100% - 116px) !important; /* right inset grows to 58px (cart button + gap) when the cart is visible */
}

/* Swap the short label for the long one. `display` isn't touched by the
   collapse rules above (only max-width/opacity/margin), so no specificity
   fight here — a plain rule is enough, unlike the width rules above. */
body.ai-page .navbar-assistant-chip-label { display: none; }
body.ai-page .navbar-assistant-chip-label-full { display: inline; }

/* No icon either — the field is fully taken over by the assistant pill,
   with nothing of the search field peeking out beneath it. */
body.ai-page .navbar-search-icon { display: none; }
