/* Kidlo — site styles */

/* ==========================================================================
   TRUST-COLOR PALETTE  (Color Psychology)
   ---------------------------------------------------------------------------
   The original design used a saturated coral (#FF6B6B) as the dominant color
   for backgrounds, borders, icons AND text. In large doses, warm/saturated
   hues keep the nervous system mildly activated — it reads as "energetic"
   but also raises visual fatigue and subtle stress, which works against a
   parent trying to calmly evaluate a stranger's used children's items.

   Fix: the app's *surfaces* (background, cards, borders) now use soft,
   desaturated mint/off-white tones — colors associated with cleanliness,
   safety and calm. The coral is not removed; it is demoted to a single job:
   marking the ONE action we want the eye to land on first (the Isolation /
   von Restorff Effect — an item that differs from its surroundings is
   disproportionately noticed and remembered). So --color-cta now appears
   almost nowhere except primary "buy-side" conversion buttons.

   A second, calmer accent (teal) fills the role coral used to play for
   everyday interactive elements (links, active filters, icons, the "sell"
   flow) — it still signals "interactive" without spending the one truly
   attention-grabbing color on things that aren't the primary conversion.

   All colors below were checked against WCAG 2.1 AA (4.5:1 for normal text)
   wherever they are used as text or as a button fill with white text —
   see the Fluency Heuristic note further down for why that matters.
   ========================================================================== */
:root {
  --color-bg:             #F5FAF8; /* app background: soft mint-tinted off-white, replaces #FFF9F5 peach */
  --color-surface:        #FFFFFF; /* cards / header / sidebar / modals */
  --color-surface-alt:    #EAF6F2; /* soft mint fill for icon buttons & active states, replaces peach #FFF0EB */
  --color-border:         #DCEEE8; /* soft mint-grey border/divider, replaces pink #FFE8DC everywhere */

  --color-text:           #3A4568; /* Kidlo brand navy (sampled from the wordmark) — 9.4:1 on white, AAA */
  --color-text-secondary: #5C6580; /* muted navy-gray, ~5.3:1 on white (AA) */

  --color-cta:            #CF3B26; /* primary "buy" CTA only — 4.88:1 with white text (AA-safe) */
  --color-cta-hover:      #B8301C;

  --color-accent:         #158048; /* Kidlo green, darkened for AA: the wordmark's #12A45E gives white text only 3.2:1, this functional shade gives 4.98:1. The pure brand green lives in the logo. */
  --color-accent-hover:   #116B3C;
  --color-accent-soft:    #E2F4EA; /* light Kidlo-green fill for hover/active chip backgrounds */

  --color-gold:           #B45309; /* rating gold, darkened from #FBBF24 (1.67:1) to 5.0:1 so it's AA-safe as text */
  --color-gold-soft:      #FBEEDD; /* light amber fill for the rating badge, same role as --color-accent-soft */

  /* Borders that must be SEEN, not just felt: the outline of an input,
     select or textarea is what tells a user "this is a control you can type
     into". WCAG 1.4.11 asks 3:1 for that boundary; --color-border above is
     1.20:1 on white and only ever meant to divide sections. 3.07:1 here. */
  --color-border-control: #8FB0A4;

  /* Accent and gold are AA as text on WHITE (4.98:1 / 5.02:1 — see above),
     but both are also used as text ON THEIR OWN SOFT FILL, where the ratio
     drops below 4.5:1 (4.36:1 and 4.39:1). These are the shades to use in
     that pairing: 5.72:1 on #E2F4EA and 5.14:1 on #FBEEDD. */
  --color-accent-on-soft: #116B3C;
  --color-gold-on-soft:   #9A4708;
}

/* ==========================================================================
   CORNER RADIUS — squarer, less "bubbly" than Tailwind's defaults.
   ---------------------------------------------------------------------------
   Cards, buttons, chips, badges and pills across the site used Tailwind's
   rounded-full/rounded-2xl/rounded-xl utilities (16-9999px), which reads as
   very soft/"pill-shaped". Overriding the utility classes here (one place,
   !important to beat Tailwind's own injected stylesheet regardless of load
   order) keeps rounded corners but pulls every one of those elements to a
   consistent, noticeably squarer radius in a single pass, rather than
   editing each of the ~100 call sites individually.
   True circles that represent something round by nature (color swatches,
   the range-slider handle, small status dots) are hand-coded with
   border-radius:50% further down and are intentionally left untouched.
   ========================================================================== */
.rounded-full { border-radius: 8px !important; }
.rounded-2xl  { border-radius: 12px !important; }
.rounded-xl   { border-radius: 8px !important; }

* { margin: 0; padding: 0; box-sizing: border-box; }
/* touch-action:manipulation kills double-tap-to-zoom (a second zoom path
   some mobile browsers still allow even with user-scalable=no on the
   viewport meta tag) without restricting scroll direction the way pan-x/
   pan-y would — normal vertical scrolling, and the deliberate horizontal
   strips (category bar, home tiles) that set their own overflow-x, are
   both unaffected. */
html, body { height: 100%; overflow: hidden; touch-action: manipulation; }
body { font-family: 'Inter', sans-serif; background: var(--color-bg); color: var(--color-text); }
/* Type system (clean/technical): Montserrat gives headings a strong,
   geometric, authoritative presence; Inter (body) is the on-screen legibility
   gold standard for UI text; Roboto handles the mechanical numerals. The tiny
   negative tracking on headings keeps Montserrat crisp rather than airy. */
.font-display { font-family: 'Montserrat', sans-serif; letter-spacing: -0.01em; }

.product-card { transition: transform 0.3s ease, box-shadow 0.3s ease; }
.product-card:hover { transform: translateY(-6px); box-shadow: 0 16px 40px rgba(0,0,0,0.12); }
.product-card:hover .product-img-overlay { opacity: 1; }
.product-card:hover .quick-view-btn { transform: translateY(0); opacity: 1; }
.quick-view-btn { transform: translateY(10px); opacity: 0; transition: all 0.3s ease; }
.product-img-overlay { opacity: 0; transition: opacity 0.3s ease; }
.nav-btn { transition: transform 0.25s ease, background-color 0.25s ease, color 0.25s ease, box-shadow 0.25s ease; }
.nav-btn:hover { transform: scale(1.05); }

/* ==========================================================================
   HERO — layered gradient + soft blurred brand shapes.
   The old hero was one flat, near-white mint gradient with two faint white
   circles that read as broken image placeholders. This gives it depth
   (three stacked radial/linear gradients) and warmth, and fills the dead
   space around the centred copy with playful colour instead of nothing.
   ========================================================================== */
.hero-section {
  background:
    radial-gradient(1100px 480px at 12% -20%, #E4F6EE 0%, rgba(228,246,238,0) 60%),
    radial-gradient(900px 460px at 92% -10%, #E7F0FF 0%, rgba(231,240,255,0) 58%),
    linear-gradient(135deg, #E7F6EF 0%, #EBF2FC 52%, #FDEFE6 100%);
}
.hero-blob {
  position: absolute; border-radius: 50%; z-index: 0; pointer-events: none;
  filter: blur(10px); opacity: 0.6;
}
.hero-blob-1 { width: 130px; height: 130px; top: 12%;  left: 7%;  background: #FFD5E4; }  /* pink   */
.hero-blob-2 { width: 84px;  height: 84px;  top: 24%;  right: 11%; background: #FFE7A8; }  /* yellow */
.hero-blob-3 { width: 170px; height: 170px; bottom: -46px; left: 15%; background: #CDE6FF; } /* blue */
.hero-blob-4 { width: 74px;  height: 74px;  bottom: 18%; right: 17%; background: #B9E9CF; }  /* green  */
.hero-blob-5 { width: 56px;  height: 56px;  top: 16%;  left: 33%; background: #FFCFC2; opacity: 0.5; } /* peach */
@media (max-width: 640px) { .hero-blob-1, .hero-blob-5 { display: none; } }

.hero-eyebrow {
  display: inline-block; background: #FFFFFF; color: var(--color-accent);
  font-weight: 800; font-size: 12px; letter-spacing: 0.01em;
  padding: 6px 15px; border-radius: 999px; margin-bottom: 16px;
  box-shadow: 0 3px 14px rgba(21,128,72,0.12);
}
.hero-title {
  color: var(--color-text); max-width: 46rem;
  font-size: clamp(1.95rem, 4.2vw, 3.1rem); line-height: 1.08; letter-spacing: -0.02em;
}
.hero-cta { box-shadow: 0 8px 22px rgba(21,128,72,0.28); }
.hero-trust {
  display: inline-flex; align-items: center; gap: 7px;
  background: rgba(255,255,255,0.75); border: 1px solid var(--color-border);
  color: var(--color-text); font-size: 12.5px; font-weight: 700;
  padding: 7px 14px; border-radius: 999px; backdrop-filter: blur(4px);
}
/* The Protecția Kidlo pill is a real <button> (opens the info modal) —
   the other three are plain <span>s, so the pointer/hover affordance is
   scoped to the button element only. */
button.hero-trust { cursor: pointer; transition: border-color 0.15s ease, transform 0.15s ease; }
button.hero-trust:hover { border-color: var(--color-accent); transform: translateY(-1px); }

/* ==========================================================================
   HOME CATEGORY STRIP — colourful one-tap shortcuts under the hero.
   ========================================================================== */
.home-cat-strip {
  display: flex; gap: 12px; overflow-x: auto; padding-bottom: 6px;
  flex: 1; min-width: 0; scroll-behavior: smooth;
  scrollbar-width: none; -ms-overflow-style: none;
}
.home-cat-strip::-webkit-scrollbar { display: none; }
.home-cat-tile {
  flex: 1 0 108px; min-width: 108px;
  display: flex; flex-direction: column; align-items: center; gap: 9px;
  padding: 16px 10px; border: none; border-radius: 20px; cursor: pointer;
  background: var(--tile, var(--color-surface-alt));
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.home-cat-tile:hover { transform: translateY(-3px); box-shadow: 0 10px 24px rgba(58,69,104,0.12); }
.home-cat-ic {
  width: 46px; height: 46px; border-radius: 50%;
  background: rgba(255,255,255,0.72);
  display: flex; align-items: center; justify-content: center;
}
.home-cat-ic svg { width: 22px; height: 22px; color: var(--color-text); }
.home-cat-lb { font-size: 12px; font-weight: 800; color: var(--color-text); text-align: center; line-height: 1.15; }
/* Always rendered (with a non-breaking space when empty) so tiles keep a
   uniform height whether or not a category has stock yet. */
.home-cat-ct { font-size: 10.5px; font-weight: 700; color: var(--color-text-secondary); text-align: center; line-height: 1.1; }

/* ==========================================================================
   "CUM FUNCȚIONEAZĂ" steps — coloured icon tiles + a big faint step number.
   ========================================================================== */
.how-step {
  position: relative; text-align: center;
  background: var(--color-surface); border: 2px solid var(--color-border);
  border-radius: 20px; padding: 26px 20px;
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.how-step:hover { transform: translateY(-4px); box-shadow: 0 14px 30px rgba(58,69,104,0.10); }
.how-num {
  position: absolute; top: 12px; right: 18px;
  font-family: 'Roboto', sans-serif; font-weight: 700; font-size: 30px;
  /* Was --color-border: 1.20:1 on white, unreadable. These digits are the
     ordering information for "cum functioneaza", not decoration. #7C8AA3 is
     3.55:1, which clears the 3:1 large-text threshold at 30px/700. */
  line-height: 1; color: #7C8AA3;
}
.how-ic {
  width: 58px; height: 58px; border-radius: 17px; margin: 0 auto;
  display: flex; align-items: center; justify-content: center;
}
.how-ic svg { width: 27px; height: 27px; }

/* Reusable coloured feature-icon tile (verify / donate / profile teasers) */
.feat-ic {
  width: 48px; height: 48px; border-radius: 14px; margin: 0 auto 10px;
  display: flex; align-items: center; justify-content: center;
}
.feat-ic svg { width: 22px; height: 22px; }
.feat-card {
  background: var(--color-surface); border: 2px solid var(--color-border);
  border-radius: 18px; padding: 20px 16px; text-align: center;
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.feat-card:hover { transform: translateY(-3px); box-shadow: 0 12px 26px rgba(58,69,104,0.09); }

/* Donation band inner card + soft badge */
.donate-band { background: linear-gradient(135deg, #FDEFE9 0%, #FCF4DE 55%, #F3F0FF 100%); border-top: 2px solid var(--color-border); }
.donate-badge {
  width: 54px; height: 54px; border-radius: 50%; flex-shrink: 0;
  background: #FFFFFF; display: flex; align-items: center; justify-content: center;
  box-shadow: 0 4px 16px rgba(207,59,38,0.14);
}

/* Keyboard focus ring: :focus-visible shows ONLY for keyboard navigation
   (Tab), never on a mouse click — so the clean, ring-free look on click is
   kept while keyboard users get a clear, brand-colored indicator that tracks
   the element's rounded shape. Covers every interactive control. */
a:focus-visible,
button:focus-visible,
.nav-btn:focus-visible,
[role="button"]:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 3px solid rgba(21,128,72,0.55);
  outline-offset: 2px;
  border-radius: 8px;
}

/* Skip link: off-screen (not display:none — that would drop it from the
   Tab order entirely) until keyboard focus lands on it, then slides into
   view top-left above everything else on the page. */
.skip-link {
  position: fixed; top: 0; left: 0; z-index: 1000;
  transform: translateY(-100%); transition: transform 0.15s ease;
  background: var(--color-accent); color: #fff; font-weight: 800; font-size: 13px;
  padding: 10px 18px; border-radius: 0 0 10px 0;
}
.skip-link:focus { transform: translateY(0); }

/* Everyday interactive chips (sizes, ages, conditions) now use the calm
   accent teal instead of coral on hover/active — coral is reserved for the
   handful of real conversion buttons (Isolation Effect). */
.search-bar { transition: box-shadow 0.3s ease, border-color 0.3s ease; border-color: var(--color-border) !important; }
.search-bar:focus-within { box-shadow: 0 0 0 3px rgba(21,128,72,0.18); border-color: var(--color-accent); }

.fade-in { animation: fadeIn 0.5s ease forwards; opacity: 0; }
@keyframes fadeIn { to { opacity: 1; } }

.login-modal-bg { background: rgba(0,0,0,0.45); backdrop-filter: blur(4px); }

.pw-field { position: relative; }
.pw-field input { padding-right: 40px !important; }
.pw-toggle-btn {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  width: 32px; height: 32px; display: flex; align-items: center; justify-content: center;
  background: none; border: none; cursor: pointer; color: var(--color-text-secondary);
}

.toast { animation: slideUp 0.4s ease, fadeOut 0.4s ease 2s forwards; }
@keyframes slideUp { from{transform:translateY(30px);opacity:0} to{transform:translateY(0);opacity:1} }
@keyframes fadeOut { to{opacity:0;transform:translateY(-10px)} }

.account-dropdown {
  display: none; position: absolute; top: calc(100% + 8px); right: 0;
  background: var(--color-surface); border-radius: 10px; border: 2px solid var(--color-border);
  box-shadow: 0 8px 24px rgba(0,0,0,0.12); min-width: 190px; z-index: 100;
  /* Notif/msg dropdowns set their own fixed inline width (320-330px) —
     this caps it so it can't run off the left edge on a narrow phone,
     same treatment #help-panel already gets. */
  max-width: calc(100vw - 32px);
}
.account-dropdown.open { display: block; }

/* Notifications page (#/notificari) — same card-row treatment as the
   rest of the site's list pages, not the compact flat-list dropdown rows
   (.msg-preview-item) the header popup used before notifications became
   a real page. */
/* Now a <button> rather than a click-only <div> (keyboard + screen reader):
   reset the UA chrome and restore the full-width block the div gave it. */
.notif-page-item { background: none; border: none; font-family: inherit; text-align: left; width: 100%; }
.notif-page-item {
  display: flex; align-items: flex-start; gap: 12px; padding: 14px 16px;
  cursor: pointer; background: var(--color-surface); border: 2px solid var(--color-border);
  border-radius: 14px; transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.notif-page-item:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(58,69,104,0.08); }
.account-dropdown-item {
  display: flex; align-items: center; gap: 8px; padding: 10px 16px;
  font-size: 13px; font-weight: 600; color: var(--color-text); cursor: pointer; transition: background 0.2s;
}
.account-dropdown-item:hover { background: var(--color-surface-alt); color: var(--color-accent); }
.account-dropdown-item:last-child { border-radius: 0 0 8px 8px; }

.sidebar-section { border-bottom: 1px solid var(--color-border); padding-bottom: 12px; margin-bottom: 12px; }

/* ==========================================================================
   TOP CATEGORY BAR + HOVER MEGA-MENUS
   ---------------------------------------------------------------------------
   Replaces the always-visible sidebar category tree. Categories are a
   navigation decision, not a purchase one, so — same reasoning as the old
   sidebar — they use the calm accent teal rather than the reserved CTA coral.
   ========================================================================== */
/* Scrollable single-row category bar + arrow controls (replaces the old
   flex-wrap-to-a-second-line approach). Only this inner viewport scrolls —
   see the comment in index.html on why the mega-menu had to move to
   position:fixed for this to work without clipping it. */
.cat-bar-viewport {
  flex: 1; min-width: 0; overflow-x: auto; overflow-y: hidden;
  scroll-behavior: smooth; scrollbar-width: none; -ms-overflow-style: none;
}
.cat-bar-viewport::-webkit-scrollbar { display: none; }
.cat-scroll-arrow {
  flex-shrink: 0; width: 30px; height: 30px; border-radius: 50%; border: none;
  display: flex; align-items: center; justify-content: center; cursor: pointer;
  background: var(--color-surface-alt); color: var(--color-accent); transition: opacity 0.15s;
}
.cat-scroll-arrow:hover { background: var(--color-accent-soft); }
.cat-scroll-arrow svg { width: 16px; height: 16px; }
/* Hidden rather than just disabled when there's nothing to scroll to in
   that direction (see updateCatScrollArrows in app.js) — an arrow that's
   always visible but sometimes inert reads as broken, not as "at the end". */
.cat-scroll-arrow.hidden { display: none !important; }

/* Mobile: swap the horizontal scroll bar for a single "Categorii" button
   (see #mobile-cat-menu-btn / #category-drawer-overlay in index.html) —
   the drawer it opens is the only way to browse categories under 1024px. */
.mobile-cat-menu-btn { display: none; }
@media (max-width: 1023px) {
  .mobile-cat-menu-btn {
    display: flex !important; align-items: center; gap: 6px;
    padding: 9px 14px; margin: 8px 0; border-radius: 999px;
    border: 2px solid var(--color-border); background: var(--color-surface);
    font-size: 13px; font-weight: 800; color: var(--color-text);
    white-space: nowrap; cursor: pointer;
  }
  .mobile-cat-menu-btn svg { width: 16px; height: 16px; color: var(--color-accent); }
  #cat-scroll-left, #cat-scroll-right, #category-bar-viewport { display: none !important; }
}

/* Mobile category drawer: slides in from the left over a blurred backdrop
   (login-modal-bg) instead of the centered-card pattern other modals use —
   a side panel reads as "app navigation menu" rather than "dialog", which
   matches what it actually is. */
.category-drawer {
  position: absolute; top: 0; left: 0; height: 100%; width: min(320px, 86vw);
  background: #FFFFFF; box-shadow: 8px 0 30px rgba(0,0,0,0.18);
  display: flex; flex-direction: column;
  transform: translateX(-100%); transition: transform 0.28s ease;
}
#category-drawer-overlay.open .category-drawer { transform: translateX(0); }
.category-drawer-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px; border-bottom: 2px solid var(--color-border); flex-shrink: 0;
}
.category-drawer-list { flex: 1; overflow-y: auto; padding: 6px 10px 24px; }
.cat-drawer-item { border-bottom: 1px solid var(--color-border); }
.cat-drawer-row { display: flex; align-items: center; }
.cat-drawer-label {
  flex: 1; display: flex; align-items: center; gap: 10px; padding: 13px 4px;
  background: none; border: none; text-align: left; cursor: pointer;
  font-size: 14px; font-weight: 700; color: var(--color-text);
}
.cat-drawer-label svg { width: 18px; height: 18px; color: var(--color-accent); flex-shrink: 0; }
.cat-drawer-item.active-cat .cat-drawer-label { color: var(--color-accent); }
.cat-drawer-toggle {
  width: 38px; height: 38px; flex-shrink: 0; display: flex; align-items: center;
  justify-content: center; background: none; border: none; cursor: pointer;
}
.cat-drawer-toggle svg { width: 16px; height: 16px; color: var(--color-text-secondary); transition: transform 0.2s ease; }
.cat-drawer-item.open .cat-drawer-toggle svg { transform: rotate(180deg); }
.cat-drawer-sub { max-height: 0; overflow: hidden; transition: max-height 0.25s ease; }
.cat-drawer-item.open .cat-drawer-sub { max-height: 1400px; }
.cat-drawer-sub-item {
  display: block; width: 100%; text-align: left; background: none; border: none;
  padding: 9px 4px 9px 32px; font-size: 13.5px; font-weight: 600;
  color: var(--color-text-secondary); cursor: pointer;
}
.cat-drawer-sub-item:active { color: var(--color-accent); }
.cat-drawer-group-label {
  padding: 10px 4px 4px 32px; font-size: 11px; font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-text-secondary); opacity: 0.7;
}

.cat-nav-item { position: relative; flex-shrink: 0; }
/* Pill-style entries (was: plain text with an underline indicator). The
   rest of the site's interactive vocabulary is soft rounded chips (age
   chips, condition chips, offer buttons) — the nav was the one element
   still speaking "underlined text link". A filled pill on hover/active
   also gives a bigger, more obvious hit target than a 2px underline. */
/* Taller pills (margin 9px, padding 9px) make the bar a more substantial
   band under the header instead of a cramped strip — navigation this
   central deserves the breathing room, and the bigger hit area helps on
   touch screens too. */
.cat-nav-label {
  /* Now a <button> (it was a click-only <span>): reset the UA chrome so it
     still looks exactly like the pill it always was. */
  background: none; border: none; font-family: inherit; text-align: left;
  display: flex; align-items: center; gap: 6px; margin: 9px 1px; padding: 9px 12px;
  font-size: 12.5px; font-weight: 700; color: var(--color-text); cursor: pointer;
  white-space: nowrap; border-radius: 8px; transition: background 0.15s, color 0.15s;
}
.cat-nav-label:hover { background: var(--color-surface-alt); color: var(--color-accent); }
.cat-nav-chevron { width: 12px; height: 12px; opacity: 0.6; }
.cat-nav-item.active .cat-nav-label,
.cat-nav-item.mega-open .cat-nav-label { background: var(--color-accent-soft); color: var(--color-accent); }
/* Category line icons: always accent teal, independent of the label's
   idle/hover color — a constant-color anchor per entry so a returning
   user relocates "their" category by its mark without re-reading nine
   labels (recognition over recall), while a single hue + uniform stroke
   keeps the bar reading as one designed system. */
.cat-nav-icon { width: 16px; height: 16px; color: var(--color-accent); flex-shrink: 0; }

/* The dropdown itself: a floating rounded card. Now that the trigger is a
   pill rather than an underlined tab, a flat-topped menu "attached" to the
   bar no longer lines up with anything — full corners + full border read
   as one coherent popover. Still anchored flush to the bar (no visual gap)
   so the cursor never crosses dead space that would fire the
   mouseleave-close timer.
   position:fixed (not absolute) + top/left set inline by openMegaMenu() in
   app.js: the trigger lives inside #category-bar-viewport, which scrolls
   (overflow-x:auto) — an absolutely-positioned descendant of a scrolling
   ancestor gets clipped the moment it extends past that ancestor's box
   (see the comment on #category-bar-viewport in index.html/style.css).
   Fixed positioning is computed against the viewport instead, so it's
   immune to that regardless of where in the DOM it lives. */
.mega-menu {
  display: none; position: fixed; min-width: 230px;
  background: var(--color-surface); border: 2px solid var(--color-border);
  border-radius: 10px; box-shadow: 0 14px 30px rgba(0,0,0,0.14);
  padding: 10px 0; z-index: 50;
}
.mega-menu.open { display: block; }
.mega-menu.two-col { padding: 10px 8px; min-width: 400px; }
.mega-menu.two-col .mega-menu-cols { columns: 2; column-gap: 4px; }
/* Three columns once a dropdown passes ~14 entries (Bebe & Îngrijire, Fete):
   two columns would make it taller than a laptop viewport. */
.mega-menu.three-col { padding: 10px 8px; min-width: 580px; }
.mega-menu.three-col .mega-menu-cols { columns: 3; column-gap: 4px; }
@media (max-width: 1100px) {
  .mega-menu.three-col { min-width: 400px; }
  .mega-menu.three-col .mega-menu-cols { columns: 2; }
}
/* A dropdown built from labeled groups: each group is its own grid column,
   so a header can never be separated from the items under it. Collapses to
   fewer columns on a narrow desktop before it would overflow. */
.mega-menu.grouped {
  padding: 10px 8px; min-width: 0;
  /* width:max-content, not a viewport-relative max-width: the menu is
     position:fixed, so a width that depends on the space to its right makes
     it widen as the edge-clamp moves it left, and the clamp then chases its
     own result. Content-sized, its width is the same wherever it sits. */
  width: max-content; max-width: calc(100vw - 24px);
}
/* Flex, not grid: the items are white-space:nowrap, so each group needs its
   own natural width — a fixed track size either clips the longest label or
   leaves a dead column. Groups wrap onto a second row on a narrow screen
   rather than overflowing. */
.mega-menu.grouped .mega-menu-cols { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 4px 14px; }
.mega-menu.grouped .mega-menu-group { flex: 0 1 auto; min-width: 0; }
.mega-menu.grouped .mega-menu-group-label { padding-top: 4px; }
/* Stock count beside a category or subcategory. Present only where there is
   something to count (see subCountHtml) — a row of "(0)" would read as a
   broken catalogue rather than a new one. */
.cat-count {
  display: inline-block; margin-left: 5px; padding: 0 5px;
  border-radius: 999px; background: var(--color-accent-soft);
  color: var(--color-accent-on-soft); font-size: 10px; font-weight: 800;
  line-height: 16px; vertical-align: 1px;
}
/* A subcategory with nothing in it is still reachable — a shopper may want
   to confirm for themselves, and the sell form uses the same list — but it
   stops competing for attention with the ones that have stock. */
.mega-menu-item.is-empty, .cat-drawer-sub-item.is-empty { opacity: 0.55; }
/* Full-width footer of a dropdown: the explicit "everything in this
   category" exit that a list of subcategories alone never offers. */
.mega-menu-all {
  display: block; width: 100%; margin-top: 6px; padding: 9px 18px;
  border: none; border-top: 1px solid var(--color-border);
  background: none; font-family: inherit; text-align: left;
  font-size: 12.5px; font-weight: 800; color: var(--color-accent);
  cursor: pointer; white-space: nowrap;
}
.mega-menu-all:hover { background: var(--color-surface-alt); }
.mega-menu-item {
  /* Same story as .cat-nav-label — now a <button>. width:100% keeps the
     full-row hover target the <span> had by virtue of being display:block. */
  background: none; border: none; font-family: inherit; text-align: left; width: 100%;
  display: block; padding: 7px 18px; font-size: 12.5px; font-weight: 600;
  color: var(--color-text-secondary); cursor: pointer; white-space: nowrap;
  break-inside: avoid; transition: background 0.15s, color 0.15s;
}
.mega-menu-item:hover { background: var(--color-surface-alt); color: var(--color-accent); }
/* Group header inside a merged dropdown (e.g. "Hrănire" vs "Igienă &
   Sănătate" within "Îngrijire & Hrănire Bebe") — same treatment the old
   Fete/Băieți sub-headers used, so a merged category still reads as two
   clearly labeled groups instead of one undifferentiated list. */
.mega-menu-group-label {
  display: block; padding: 8px 18px 2px; font-size: 11px; font-weight: 800;
  color: var(--color-accent); text-transform: uppercase; letter-spacing: 0.3px;
  /* break-after:avoid stops the CSS column-balancer from stranding a group
     header at the bottom of one column while its items flow into the next —
     it forces the header to move down with its first item instead. */
  break-inside: avoid; break-before: auto; break-after: avoid;
}

/* Filters panel: hidden until a category is actually chosen (Hick's Law —
   don't show narrowing controls before there's anything to narrow). */
.filters-hidden { display: none !important; }

/* Color filter swatches — also reused read-only on the product page to show
   a listing's available colors. */
.color-swatch {
  width: 22px; height: 22px; border-radius: 50%; cursor: pointer; display: inline-block;
  border: 2px solid var(--color-border); transition: transform 0.15s, border-color 0.15s;
}
/* 22x22 visually, 44x44 to the finger: the swatch grid would look clumsy at
   full size, but a 22px target on a phone is a mis-tap waiting to happen. */
.color-swatch { position: relative; }
.color-swatch::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
.color-swatch:hover { transform: scale(1.15); }
.color-swatch.active { border-color: var(--color-accent); box-shadow: 0 0 0 2px var(--color-accent-soft); }

.condition-chip {
  cursor: pointer; transition: all 0.2s; border: 2px solid var(--color-border);
  border-radius: 8px; padding: 3px 9px; font-size: 11px; font-weight: 700; color: var(--color-text-secondary); background: #fff;
}
.condition-chip.active { background: var(--color-accent); color: #fff; border-color: var(--color-accent); }
/* A condition with no matches in the current result set: still announced to
   assistive tech, but not clickable into a guaranteed-empty grid. Never
   applied to the chip that is currently doing the filtering. */
.condition-chip:disabled { opacity: 0.42; cursor: not-allowed; }
.chip-count { font-weight: 800; opacity: 0.75; }
.delivery-chip {
  cursor: pointer; transition: all 0.2s; border: 2px solid var(--color-border);
  border-radius: 8px; padding: 3px 9px; font-size: 11px; font-weight: 700;
  color: var(--color-text-secondary); background: #fff;
}
.delivery-chip.active { background: var(--color-accent); color: #fff; border-color: var(--color-accent); }

/* ==========================================================================
   ACTIVE FILTER CHIPS
   One chip per applied filter, directly above the results, on every
   viewport. Each removes only itself — the panel used to offer a single
   all-or-nothing "Resetează".
   ========================================================================== */
.filter-chip {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 32px; padding: 5px 10px 5px 12px;
  border: 2px solid var(--color-accent); border-radius: 999px;
  background: var(--color-accent-soft); color: var(--color-accent-on-soft);
  font-family: inherit; font-size: 12px; font-weight: 800; cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.filter-chip span { font-size: 13px; line-height: 1; opacity: 0.75; }
.filter-chip:hover { background: var(--color-accent); color: #fff; }
.filter-chip:hover span { opacity: 1; }
.filter-chip-clear {
  min-height: 32px; padding: 5px 12px; border: none; background: none;
  font-family: inherit; font-size: 12px; font-weight: 800;
  color: var(--color-accent); cursor: pointer; text-decoration: underline;
}

/* Dual-handle range slider — accent teal instead of coral (filter UI, not a CTA) */
.dual-range-wrap { position: relative; height: 24px; margin: 6px 0; }
.dual-range-track { position: absolute; top: 50%; transform: translateY(-50%); left: 0; right: 0; height: 4px; background: var(--color-border); border-radius: 2px; }
.dual-range-fill { position: absolute; height: 100%; background: var(--color-accent); border-radius: 2px; }
.dual-range-wrap input[type="range"] {
  position: absolute; top: 0; left: 0; width: 100%; height: 24px;
  -webkit-appearance: none; appearance: none; background: transparent;
  pointer-events: none; outline: none; margin: 0; padding: 0;
}
.dual-range-wrap input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; pointer-events: all;
  width: 18px; height: 18px; border-radius: 50%; background: var(--color-accent);
  cursor: pointer; box-shadow: 0 2px 6px rgba(21,128,72,0.35); border: 2px solid #fff;
}
.dual-range-wrap input[type="range"]::-moz-range-thumb {
  pointer-events: all; width: 14px; height: 14px; border-radius: 50%;
  background: var(--color-accent); cursor: pointer; box-shadow: 0 2px 6px rgba(21,128,72,0.35); border: 2px solid #fff;
}

/* Sidebar scrollbar */
.sidebar-scroll { scrollbar-width: thin; scrollbar-color: var(--color-border) transparent; }
.sidebar-scroll::-webkit-scrollbar { width: 4px; }
.sidebar-scroll::-webkit-scrollbar-thumb { background: var(--color-border); border-radius: 4px; }

/* Profile page */
/* Pill tabs (was folder tabs): same interactive vocabulary as the category
   bar — icon + label pills, filled when active. */
.profile-tab-btn {
  display: inline-flex; align-items: center; gap: 6px;
  transition: all 0.2s; border-radius: 8px; padding: 8px 14px;
  font-size: 12.5px; font-weight: 700; cursor: pointer; border: none;
}
.profile-tab-btn.active { background: #fff; color: var(--color-accent); box-shadow: 0 3px 10px rgba(35,48,43,0.10); }
.profile-tab-btn:not(.active) { background: rgba(35,48,43,0.06); color: var(--color-text-secondary); }
.profile-tab-btn:not(.active):hover { background: rgba(35,48,43,0.1); color: var(--color-text); }

/* Translucent stat tiles on the gradient header. */
.profile-stat-card {
  background: rgba(255,255,255,0.65); border: 1px solid rgba(255,255,255,0.9);
  border-radius: 10px; padding: 10px 12px; text-align: center;
}
.profile-stat-icon { width: 15px; height: 15px; color: var(--color-accent); margin: 0 auto 3px; display: block; }

/* Toggle switch (settings): hidden checkbox + track/knob. */
.switch { position: relative; display: inline-flex; flex-shrink: 0; }
.switch input { position: absolute; opacity: 0; pointer-events: none; }
.switch-track {
  width: 38px; height: 22px; border-radius: 11px; background: var(--color-border);
  display: inline-block; transition: background 0.2s; position: relative;
}
.switch-knob {
  position: absolute; top: 3px; left: 3px; width: 16px; height: 16px;
  border-radius: 50%; background: #fff; box-shadow: 0 1px 4px rgba(0,0,0,0.25);
  transition: transform 0.2s;
}
.switch input:checked + .switch-track { background: var(--color-accent); }
.switch input:checked + .switch-track .switch-knob { transform: translateX(16px); }

.listing-card { transition: box-shadow 0.2s; }
.listing-card:hover { box-shadow: 0 4px 16px rgba(0,0,0,0.08); }

/* Sell page */
#sell-subcategory-wrap { display: none; }
.sell-select {
  width: 100%; border: 2px solid var(--color-border-control); border-radius: 8px; padding: 10px 14px;
  font-size: 13px; background: var(--color-bg); outline: none; color: var(--color-text); transition: border-color 0.2s;
}
.sell-select:focus { border-color: var(--color-accent); }
/* .sell-select is shared by plain <input>s too — the custom dropdown
   arrow (replacing the OS-native one every <select> otherwise falls back
   to) is scoped to the element itself so it never paints onto a text
   field. */
select.sell-select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none; cursor: pointer;
  padding-right: 36px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235C6580' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; background-size: 16px;
}
select.sell-select:disabled { cursor: not-allowed; opacity: 0.6; }
/* input[data-datalist] (județ→localitate autocomplete, sell-brand) draws
   the same chevron the <select>s use, so it reads as the same kind of
   control instead of a plain text field. Deliberately not a real
   list="..." attribute — see isAutocompleteInput() in app.js. */
input[data-datalist].sell-select {
  padding-right: 36px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235C6580' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; background-size: 16px;
}

/* Custom select popup — replaces the native OS option list (see the
   CUSTOM SELECT DROPDOWNS section in app.js). Appended to <body>, so
   z-index just needs to clear the modal overlays (z-50) it can open
   from (report/settings/sell forms, ...). */
.custom-select-popup {
  position: fixed; z-index: 9999; background: var(--color-bg);
  border: 2px solid var(--color-border); border-radius: 12px; padding: 6px;
  box-shadow: 0 12px 28px rgba(20,26,44,0.16);
  max-height: 280px; max-width: min(90vw, 360px); overflow-y: auto;
  display: flex; flex-direction: column; gap: 1px;
}
.custom-select-option {
  display: block; width: 100%; text-align: left; border: none; background: none; cursor: pointer;
  padding: 9px 12px; border-radius: 8px; font-size: 13px; color: var(--color-text);
}
.custom-select-option:hover, .custom-select-option.highlighted { background: var(--color-surface-alt); }
.custom-select-option.active { background: var(--color-accent-soft); color: var(--color-accent); font-weight: 700; }
.custom-select-option.disabled { color: var(--color-text-secondary); opacity: 0.5; cursor: not-allowed; }

/* Micro-labels: uppercase + letterspacing reads as a designed form system
   (the "editorial" register), and the extra letterforms make an 10.5px
   label as legible as a plain 11px one. */
.sell-label { font-size: 10.5px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.5px; color: var(--color-text-secondary); display: block; margin-bottom: 4px; }
.sell-char-count { font-size: 10.5px; font-weight: 700; color: var(--color-text-secondary); opacity: 0.75; }

/* Checkout step wizard (Livrare → Plată → Confirmare) — same numbered-
   stepper pattern most Romanian e-commerce checkouts (dr.max included)
   use, in Kidlo's own accent color rather than copying anyone's look. */
/* Enlarged from the original 32px/11.5px pass — a checkout that's meant
   to read as a real dedicated page (like a full-scale retailer's, e.g.
   GymBeam's own multi-step checkout) needs a stepper with real visual
   weight, not one sized like an inline form hint. */
.checkout-steps { display: flex; list-style: none; margin: 0 0 28px; padding: 0; }
.checkout-step {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 8px;
  position: relative; text-align: center;
}
.checkout-step-line {
  position: absolute; top: 19px; left: 50%; width: 100%; height: 3px;
  background: var(--color-border); z-index: 0;
}
.checkout-step:last-child .checkout-step-line { display: none; }
.checkout-step.done .checkout-step-line { background: var(--color-accent); }
.checkout-step-circle {
  position: relative; z-index: 1; width: 40px; height: 40px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 15px; background: var(--color-surface);
  color: var(--color-text-secondary); border: 2px solid var(--color-border);
  transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}
.checkout-step.active .checkout-step-circle { background: var(--color-accent); color: #fff; border-color: var(--color-accent); }
.checkout-step.done .checkout-step-circle { background: var(--color-accent-soft); color: var(--color-accent); border-color: var(--color-accent); }
.checkout-step-label { font-size: 13px; font-weight: 700; color: var(--color-text-secondary); }
.checkout-step.active .checkout-step-label { color: var(--color-text); }

.checkout-step-panel { display: none; }
.checkout-step-panel.active { display: block; }

/* Payment method cards (step 2) — a tappable choice instead of a <select>,
   the same interaction dr.max's own payment step uses. */
.checkout-pay-option {
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px; text-align: left;
  padding: 14px 16px; border-radius: 14px; border: 2px solid var(--color-border);
  background: var(--color-bg); cursor: pointer; transition: border-color 0.15s ease, background 0.15s ease;
}
.checkout-pay-option svg { width: 19px; height: 19px; color: var(--color-accent); margin-bottom: 4px; }
.checkout-pay-option.active { border-color: var(--color-accent); background: var(--color-accent-soft); }
.checkout-pay-option .cpo-title { font-weight: 800; font-size: 13.5px; color: var(--color-text); }
.checkout-pay-option .cpo-sub { font-size: 11.5px; color: var(--color-text-secondary); }

/* Carrier logo images (src/assets/carrier-logo-{gls,dpd}.png) on the
   checkout delivery-method rows — real brand logos, transparent bg. */
.carrier-logo { object-fit: contain; }

/* Delivery-method list: longitudinal rows (logo left, price right)
   instead of the square .checkout-pay-option cards — GymBeam's own
   shipping-method list shape. */
.checkout-carrier-row {
  display: flex; align-items: center; gap: 14px; width: 100%; text-align: left;
  padding: 10px 16px; border-radius: 14px; border: 2px solid var(--color-border);
  background: var(--color-bg); cursor: pointer; transition: border-color 0.15s ease, background 0.15s ease;
}
.checkout-carrier-row.active { border-color: var(--color-accent); background: var(--color-accent-soft); }
.checkout-carrier-row .carrier-logo { width: 58px; height: 30px; flex: none; }
.checkout-carrier-row .ccr-info { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.checkout-carrier-row .cpo-title { font-weight: 800; font-size: 13.5px; color: var(--color-text); }
.checkout-carrier-row .cpo-sub { font-size: 11.5px; color: var(--color-text-secondary); }
.checkout-carrier-row .ccr-price { flex: none; font-weight: 800; font-size: 13.5px; color: var(--color-text); white-space: nowrap; }

/* Read-only recap (step 3). */
.checkout-review-row {
  display: flex; justify-content: space-between; gap: 12px; padding: 10px 0;
  border-bottom: 1px solid var(--color-border); font-size: 13px;
}
.checkout-review-row:last-child { border-bottom: none; }
.checkout-review-row span { color: var(--color-text-secondary); }
.checkout-review-row strong { color: var(--color-text); text-align: right; }

/* Numbered section header: number chip + title + one-line helper. */
.sell-section-head { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 14px; padding-bottom: 12px; border-bottom: 1px solid var(--color-border); }
.sell-section-num {
  font-family: 'Roboto', sans-serif; font-size: 13px; font-weight: 700; color: var(--color-accent-on-soft);
  background: var(--color-accent-soft); border-radius: 8px; width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}

/* 5-slot photo grid. Empty slots are visible sockets (they say "up to 5"
   without prose); the first slot doubles as the cover. */
/* Now <button>s (they were click-only <div>s, so there was no keyboard path
   to adding a photo at all — the file input they proxy for is hidden). */
.photo-slot { background: none; font-family: inherit; }
.photo-slot {
  aspect-ratio: 1; border: 2px dashed var(--color-border); border-radius: 8px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  cursor: pointer; background: var(--color-bg); transition: border-color 0.15s, background 0.15s;
  position: relative; overflow: hidden;
}
.photo-slot:hover { border-color: var(--color-accent); background: var(--color-surface-alt); }
.photo-slot.filled { border-style: solid; cursor: default; }
.photo-slot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.photo-slot-label { font-size: 9.5px; font-weight: 700; color: var(--color-text-secondary); }
.photo-slot-cover-badge {
  position: absolute; bottom: 4px; left: 4px; z-index: 2;
  font-size: 9px; font-weight: 800; padding: 2px 6px; border-radius: 5px;
  background: rgba(35,48,43,0.75); color: #fff; letter-spacing: 0.3px;
}
.photo-slot-remove {
  position: absolute; top: 4px; right: 4px; z-index: 2; width: 18px; height: 18px;
  border: none; border-radius: 6px; background: rgba(35,48,43,0.75); color: #fff;
  font-size: 10px; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center;
}
/* Same reasoning as .color-swatch: an 18px "remove photo" button sits on top
   of the photo it deletes, so it cannot grow visually — but it can grow as a
   target. Kept to 36px rather than 44 so it does not swallow taps meant for
   the photo underneath. */
.photo-slot-remove::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 36px; height: 36px; transform: translate(-50%, -50%);
}

/* Reorder controls on a filled photo slot. The cover is simply whatever is
   in slot 1, so moving a photo forward is how you promote it — no separate
   "set as cover" concept to explain. Shown on hover/focus on a pointer
   device; always visible on touch, where there is no hover to reveal them. */
.photo-slot-order {
  position: absolute; inset: auto 0 0 0; z-index: 2;
  display: flex; justify-content: space-between; padding: 3px;
  opacity: 0; transition: opacity 0.15s;
}
.photo-slot.filled:hover .photo-slot-order,
.photo-slot-order:focus-within { opacity: 1; }
@media (hover: none) { .photo-slot-order { opacity: 1; } }
.photo-slot-order button {
  width: 22px; height: 22px; border: none; border-radius: 6px;
  background: rgba(35,48,43,0.75); color: #fff; font-size: 14px; line-height: 1;
  cursor: pointer; display: flex; align-items: center; justify-content: center;
  font-family: inherit; position: relative;
}
/* Same trick as .photo-slot-remove: a 22px control on top of the photo it
   moves, given a 36px tap target without growing visually. */
.photo-slot-order button::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 36px; height: 36px; transform: translate(-50%, -50%);
}
.photo-slot-order button:only-child { margin-left: auto; }
.photo-slot-loading { border-style: solid; cursor: default; }
.photo-spinner {
  width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid var(--color-border); border-top-color: var(--color-accent);
  animation: photoSpin 0.7s linear infinite;
}
@keyframes photoSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .photo-spinner { animation-duration: 2.4s; } }

/* Condition as radio cards. Was a <select> that hid the one sentence which
   decides between two adjacent options until the list was open — and
   truncated it on a phone even then. */
.condition-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 8px; }
.condition-card {
  border: 2px solid var(--color-border); border-radius: 8px; padding: 10px 12px;
  display: flex; flex-direction: column; gap: 2px; cursor: pointer;
  background: var(--color-bg); transition: border-color 0.15s, background 0.15s;
  position: relative;
}
.condition-card input { position: absolute; opacity: 0; pointer-events: none; }
.condition-card:hover { border-color: var(--color-accent); }
.condition-card:has(input:checked) { border-color: var(--color-accent); background: var(--color-accent-soft); }
.condition-card:has(input:focus-visible) { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.condition-card-title { font-size: 12.5px; font-weight: 800; color: var(--color-text); }
.condition-card-sub { font-size: 10.5px; color: var(--color-text-secondary); line-height: 1.3; }

/* Declared defects, on the product page. Deliberately not a warning colour:
   a seller who writes down the scuff is doing the right thing and should not
   be visually penalised for it. */
.flaws-block {
  display: flex; gap: 10px; align-items: flex-start;
  border: 2px solid var(--color-border); border-radius: 12px; padding: 12px 14px;
  background: var(--color-surface-alt);
}
.flaws-block.flaws-none { background: var(--color-bg); }
.flaws-icon { width: 16px; height: 16px; color: var(--color-accent); flex-shrink: 0; margin-top: 2px; }
.flaws-title { font-size: 12.5px; font-weight: 800; color: var(--color-text); }
.flaws-text { font-size: 13px; color: var(--color-text-secondary); line-height: 1.5; margin-top: 2px; }

/* Delivery options as selectable cards (hidden radio, whole card is the
   control; :has() flips the selected state). */
.delivery-card {
  border: 2px solid var(--color-border); border-radius: 8px; padding: 12px 10px;
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: 3px;
  cursor: pointer; background: var(--color-bg); transition: border-color 0.15s, background 0.15s;
}
.delivery-card input { position: absolute; opacity: 0; pointer-events: none; }
.delivery-card:hover { border-color: var(--color-accent); }
.delivery-card:has(input:checked) { border-color: var(--color-accent); background: var(--color-accent-soft); }
.delivery-card-icon { width: 18px; height: 18px; color: var(--color-accent); }
.delivery-card-title { font-size: 12px; font-weight: 800; color: var(--color-text); }
.delivery-card-sub { font-size: 10.5px; color: var(--color-text-secondary); line-height: 1.3; }

/* Listing-strength meter */
.strength-track { height: 8px; border-radius: 4px; background: var(--color-border); overflow: hidden; }
.strength-fill { height: 100%; width: 0%; border-radius: 4px; background: var(--color-accent); transition: width 0.35s ease, background 0.35s ease; }

/* Age filter chips */
.age-chip { cursor: pointer; transition: all 0.2s; border: 2px solid var(--color-border); border-radius: 8px; padding: 4px 10px; font-size: 11px; font-weight: 700; color: var(--color-text-secondary); background: #fff; display: inline-block; }
.age-chip:hover, .age-chip.active { background: var(--color-accent); color: #fff; border-color: var(--color-accent); }
/* !important + a class-specific selector, rather than relying on Tailwind's
   generic .hidden utility: this rule sets `display` too, and which of two
   same-specificity rules wins depends on injection order against Tailwind's
   runtime-generated stylesheet — not worth leaving to chance. */
.age-chip.hidden { display: none !important; }

/* Size filter chips — same component as age chips, kept as a separate
   class (not a shared selector) because the two sections toggle
   independently: clothing categories show size chips and hide age chips,
   every other category does the reverse. */
.size-chip { cursor: pointer; transition: all 0.2s; border: 2px solid var(--color-border); border-radius: 8px; padding: 4px 10px; font-size: 11px; font-weight: 700; color: var(--color-text-secondary); background: #fff; display: inline-block; }
.size-chip:hover, .size-chip.active { background: var(--color-accent); color: #fff; border-color: var(--color-accent); }

/* Legal page (#/legal) — quick nav, numbered subsections */
.legal-toc { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 20px; }
.legal-toc button { font-size: 12px; font-weight: 700; padding: 7px 14px; border-radius: 999px; background: var(--color-surface-alt); color: var(--color-accent); border: none; cursor: pointer; }
.legal-toc button:hover { background: var(--color-accent); color: #fff; }
.legal-updated { font-size: 12px; color: var(--color-text-secondary); margin-bottom: 20px; }
.legal-section-head { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; padding-bottom: 14px; border-bottom: 1px solid var(--color-border); }
.legal-section-icon { width: 38px; height: 38px; border-radius: 11px; display: flex; align-items: center; justify-content: center; background: var(--color-accent-soft); color: var(--color-accent); flex-shrink: 0; }
.legal-item { padding: 13px 0; border-bottom: 1px solid var(--color-border); }
.legal-item:last-child { border-bottom: none; padding-bottom: 0; }
.legal-item-title { display: flex; align-items: baseline; gap: 8px; font-weight: 700; font-size: 14px; color: var(--color-text); margin-bottom: 4px; }
.legal-num { color: var(--color-accent); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Quick view seller card — OLX-style: sits beside the photo, at its own
   natural/compact height (not stretched to match the photo). */
.qv-seller-card { background: var(--color-bg); border: 2px solid var(--color-border); border-radius: 10px; padding: 16px; }
.review-item { padding: 10px 0; border-bottom: 1px solid var(--color-border); }
.review-item:last-child { border-bottom: none; }

/* Image upload area */
.upload-area { border: 2px dashed var(--color-border); border-radius: 8px; padding: 20px; text-align: center; cursor: pointer; transition: all 0.2s; background: var(--color-bg); }
.upload-area:hover { border-color: var(--color-accent); background: var(--color-surface-alt); }

/* Chat & Messaging */
/* Same as .notif-page-item — this row is a <button> now. */
.conv-item { background:none; border:none; font-family:inherit; text-align:left; width:100%; }
.conv-item { display:flex; align-items:center; gap:10px; padding:12px 14px; cursor:pointer; transition:background 0.2s; border-bottom:1px solid var(--color-border); }
.conv-item:hover { background:var(--color-bg); }
.conv-item.active { background:var(--color-surface-alt); border-left:3px solid var(--color-accent); }
/* Message preview dropdown rows (header icon) — same idea as .conv-item,
   compacted for a quick-glance popup rather than a full inbox pane. */
/* Now a <button role="menuitem"> — it was a click-only <div> inside a popup
   that could not be reached with a keyboard at all. */
.msg-preview-item { background:none; border:none; font-family:inherit; text-align:left; width:100%; }
.msg-preview-item { display:flex; align-items:flex-start; gap:10px; padding:10px 14px; cursor:pointer; transition:background 0.2s; border-bottom:1px solid var(--color-border); }
.msg-preview-item:hover { background:var(--color-bg); }
.msg-preview-item:last-child { border-bottom:none; }
.msg-row { display:flex; margin-bottom:10px; }
.msg-row.sent { justify-content:flex-end; }
.msg-row.received { justify-content:flex-start; }
/* max-width lives HERE, not on .msg-bubble — .msg-bubble-wrap is a flex
   item of .msg-row (which has a definite width), so a percentage here
   resolves unambiguously. Putting it on .msg-bubble instead (a grandchild,
   inside this same auto-sized wrapper) makes the percentage resolve
   against a containing block whose own size depends on ITS content in a
   circular way — engines fall back to treating it as ~0, so the bubble
   collapses to a couple pixels wide and every character of the message
   wraps onto its own line ("B" / "u" / "n" / "a" each on a separate row). */
.msg-bubble-wrap { max-width:72%; }
.msg-bubble { padding:9px 14px; font-size:13px; line-height:1.45; word-break:break-word; }
.msg-sent { background:var(--color-accent); color:#fff; border-radius:10px 10px 3px 10px; }
.msg-received { background:#F3F4F6; color:var(--color-text); border-radius:10px 10px 10px 3px; }
.msg-time { font-size:10px; margin-top:3px; opacity:0.55; }
.msg-row.sent .msg-time { text-align:right; }
.chat-input { border:2px solid var(--color-border); border-radius:8px; padding:10px 16px; font-size:13px; outline:none; flex:1; transition:border-color 0.2s; font-family:inherit; resize:none; max-height:80px; }
.chat-input:focus { border-color:var(--color-accent); }

/* Offer / counter-offer cards inside the chat thread (Vinted-style
   negotiation). A structured card instead of a plain text bubble so the
   price and status ("pending"/"accepted"/"declined") stay readable and
   the accept/decline/counter actions have somewhere to live — see
   renderOfferBubble() in app.js. */
/* width (not just max-width) is load-bearing here: .offer-card sits inside
   an un-widthed flex item (same wrapper .msg-bubble uses), so without a
   definite width its layout size is driven by its *content's* min-content
   — and the 3-button action row's min-content (esp. "Contraofertă", the
   longest label) is wider than the chat pane, pushing the whole card out
   past the visible message area instead of wrapping inside it. */
.offer-card { width:220px; max-width:78%; border:2px solid var(--color-border); border-radius:10px; padding:10px 12px; background:#fff; }
.msg-row.sent .offer-card { border-color:var(--color-accent); background:#F3FAF9; }
.offer-card-head { display:flex; align-items:center; gap:5px; font-size:11px; font-weight:800; color:var(--color-accent); text-transform:uppercase; letter-spacing:0.3px; }
.offer-price { font-family:'Montserrat',sans-serif; font-size:20px; font-weight:700; color:var(--color-text); margin:2px 0 4px; }
.offer-status { display:inline-block; font-size:11px; font-weight:700; padding:2px 8px; border-radius:6px; }
.offer-actions { display:flex; flex-wrap:wrap; gap:6px; margin-top:8px; }
.offer-btn { flex:1 1 auto; min-width:0; border:none; cursor:pointer; border-radius:8px; padding:6px 3px; font-size:10.5px; font-weight:800; text-align:center; white-space:normal; overflow-wrap:break-word; transition:opacity 0.15s; }
.offer-btn:hover { opacity:0.8; }
.offer-btn-accept { background:#2E7D32; color:#fff; }
.offer-btn-decline { background:#F3F4F6; color:#B3261E; }
.offer-btn-counter { background:var(--color-accent-soft); color:var(--color-accent); }
.offer-checkout-btn { display:block; width:100%; margin-top:8px; border:none; cursor:pointer; border-radius:8px; padding:8px; font-size:12px; font-weight:800; background:var(--color-cta); color:#fff; }
.offer-checkout-btn:hover { opacity:0.9; }
/* Notification badges (unread dot, message count) are a deliberate
   exception: they don't ask the user to click anything, they signal
   "something changed" — a role red/coral badges universally play in
   consumer apps, distinct from a CTA. Kept coral here on purpose. */
.unread-dot { width:8px; height:8px; border-radius:50%; background:var(--color-cta); flex-shrink:0; }
.msg-nav-badge { position:absolute; top:-4px; right:-4px; min-width:18px; height:18px; border-radius:9px; background:var(--color-cta); color:#fff; font-size:10px; font-weight:800; display:flex; align-items:center; justify-content:center; padding:0 4px; }

/* ==========================================================================
   Promoted cards — Contour Bias
   ---------------------------------------------------------------------------
   Previously: a 2px solid colored border ran around the whole card. A hard,
   saturated outline reads as a "fence" — it fights the soft, rounded,
   friendly language used everywhere else and adds clutter next to the
   product photo. Replaced with a soft, colored drop shadow: same "this is
   special" signal, but it reads as gentle depth/light instead of a barrier,
   which keeps the rounded-corner "safe and approachable" feeling intact.
   ========================================================================== */
.promoted-gold   { box-shadow: 0 10px 28px rgba(146,112,12,0.22); }
.promoted-silver { box-shadow: 0 10px 28px rgba(86,99,109,0.20); }
.promoted-bronze { box-shadow: 0 10px 28px rgba(138,75,35,0.20); }
/* The promo ribbon shrank from a full-width bar (competing with the product
   photo for attention) to a small rounded corner pill — same Social Proof
   signal ("this listing is promoted"), far less visual noise. Colors are
   solid (no gradient) and darkened so white text clears 4.5:1 AA.*/
.promo-tag {
  position:absolute; top:8px; right:8px; left:auto;
  display:flex; align-items:center; gap:4px;
  padding:4px 10px; border-radius:6px;
  font-size:10px; font-weight:800; letter-spacing:0.3px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.18);
}
.promo-gold   { background: #92700C; color:#fff; }
.promo-silver { background: #56636D; color:#fff; }
.promo-bronze { background: #8A4B23; color:#fff; }

/* "Exemplu" marker on seed/demo sellers, their listings, reviews, and chat
   — neutral slate rather than any trust/brand color, so it never reads as
   an endorsement or a warning, just informational. See demoBadgeHtml() /
   isDemoSeller() in app.js. */
.demo-badge {
  display: inline-flex; align-items: center; font-size: 10px; font-weight: 800;
  letter-spacing: 0.3px; padding: 3px 8px; border-radius: 6px;
  background: #EDEFF5; color: #4B5670; border: 1px solid #D5D9E6;
}

/* Phone-verified seller badge — blue reads as "verified identity" across
   every major platform (Twitter/Instagram/etc.), distinct from both the
   neutral grey demo-badge and the gold rating badge next to it. See
   verifiedBadgeHtml() in app.js. */
.verified-badge {
  display: inline-flex; align-items: center; gap: 2px; font-size: 10px; font-weight: 800;
  padding: 3px 7px; border-radius: 6px;
  background: #E3F0FF; color: #3457C7;
}
.verified-badge i { width: 11px; height: 11px; }

/* Fondator — the first 100 sellers. Deliberately warm/gold rather than
   another blue-green pill: it sits right beside the verified badge and the
   two say different things, so they should not look like one badge in two
   colours. Same shape and weight as .verified-badge, so the pair reads as one
   row of credentials. */
.founder-badge {
  display: inline-flex; align-items: center; gap: 3px; font-size: 10px; font-weight: 800;
  padding: 3px 7px; border-radius: 6px;
  background: var(--color-gold-soft); color: var(--color-gold-on-soft);
}
.founder-badge i { width: 11px; height: 11px; }

/* Seller click hint */
/* Now a <button>: the seller row is the most important trust link on a
   product page and it was mouse-only. */
.seller-clickable { background: none; border: none; font-family: inherit; text-align: left; width: 100%; }
.seller-clickable { cursor:pointer; transition:opacity 0.2s; }
.seller-clickable:hover { opacity:0.85; }

/* "În curând" pill for pre-launch pages (verification, donations). */
.coming-soon-pill {
  display: inline-block; padding: 3px 12px; border-radius: 6px;
  font-size: 11px; font-weight: 800; letter-spacing: 0.5px; text-transform: uppercase;
  background: rgba(35,48,43,0.08); color: var(--color-text-secondary);
}

/* Buyer-protection price — Vinted/OLX-style: the listed price is demoted
   to a small reference line, and this shield+total+"Protecția Kidlo" is
   the one row a buyer actually acts on (price and badge together, not
   stacked as two separate elements). Card version is a compact tappable
   row; the product page gets the full bordered box. Both open
   #kidlo-protection-modal via openKidloProtectionInfo() in app.js — see
   kidloProtectedPrice() there for the underlying commission formula. */
.kidlo-protected-price {
  display: flex; align-items: center; gap: 5px; margin-top: 2px;
  border: none; background: none; padding: 0; cursor: pointer;
}
.kidlo-protected-price i { width: 15px; height: 15px; color: var(--color-accent); flex-shrink: 0; }
.kidlo-protected-price span:not(.kpp-label) { font-size: 15px; }
.kidlo-protected-price .kpp-label {
  font-size: 9px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.3px;
  color: var(--color-accent); opacity: 0.85;
}
.kidlo-protected-price:hover .kpp-label { text-decoration: underline; }

.kidlo-protect-box {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  padding: 12px 14px; border-radius: 14px; cursor: pointer;
  background: var(--color-accent-soft); border: 1.5px solid var(--color-accent);
}
.kidlo-protect-box .kpb-shield { width: 20px; height: 20px; color: var(--color-accent); flex-shrink: 0; }
.kidlo-protect-box .kpb-total { font-family: var(--font-display, inherit); font-weight: 800; font-size: 20px; color: var(--color-accent); line-height: 1; }
.kidlo-protect-box .kpb-label { font-size: 12px; font-weight: 700; color: var(--color-accent-on-soft); }
.kidlo-protect-box .kpb-chevron { width: 14px; height: 14px; color: var(--color-accent); margin-left: auto; flex-shrink: 0; }
.kidlo-protect-box:hover .kpb-label { text-decoration: underline; }

/* Empty-state icon badge — a soft pastel circle instead of a flat grey
   icon, reusing the same badge-color family as the product-card social-
   proof pills (Bestseller/Popular) so an empty page still reads as
   designed, not as a placeholder nobody finished. Tint set per context
   via inline style on the wrapper (see products-grid/favorites/orders/
   notifications empty states). */
.empty-state-icon {
  width: 72px; height: 72px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  margin: 0 auto 14px;
}
.empty-state-icon i { width: 30px; height: 30px; }

/* No-photo placeholder for the big "hero" image slots on colorful
   cardTint backgrounds (main product card, product page, sell-form
   preview, ...) — see NO_PHOTO_HERO in app.js. Sized in em so it
   scales with whichever text-Nxl wrapper each call site already uses. */
.no-photo-hero {
  width: 1.5em; height: 1.5em; border-radius: 50%;
  background: rgba(255,255,255,0.55);
  display: flex; align-items: center; justify-content: center;
}

/* ==========================================================================
   PRODUCT PAGE — photo sits in its own left-hand column (md:w-3/5, next
   to the seller card in md:w-2/5) instead of a full-bleed hero, so it's
   naturally left-aligned under the title above it, not centered on the
   page. See renderProductPage() in app.js. Full-width within that column
   at every breakpoint — the column itself is what constrains its size. */
.pdp-hero {
  width: 100%; aspect-ratio: 4 / 3; border-radius: 18px; overflow: hidden;
  position: relative;
}
.pdp-hero-nophoto { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 72px; }
@media (min-width: 768px) { .pdp-hero-nophoto { font-size: 80px; } }
/* Prev/next arrows overlaid directly on the hero (separate from the
   lightbox's own prev/next) — see pdpImageNav() in app.js. */
.pdp-hero-nav {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 5;
  width: 38px; height: 38px; border-radius: 50%; border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,0.85); box-shadow: 0 4px 12px rgba(20,26,44,0.18);
  transition: background 0.15s ease;
}
.pdp-hero-nav:hover { background: #fff; }
.pdp-hero-nav-prev { left: 12px; }
.pdp-hero-nav-next { right: 12px; }
.pdp-hero-nav i { width: 20px; height: 20px; color: var(--color-text); }
.pdp-hero-count {
  position: absolute; bottom: 12px; left: 50%; transform: translateX(-50%); z-index: 5;
  background: rgba(20,26,44,0.55); color: #fff; font-size: 11px; font-weight: 700;
  padding: 3px 10px; border-radius: 999px;
}

/* Lightbox click-to-zoom — see toggleLightboxZoom() in app.js. transform-
   origin is set inline per-click (JS) so the zoom centers on whatever
   was tapped, not always the middle of the photo. */
#lightbox-img { cursor: zoom-in; transition: transform 0.25s ease; }
#lightbox-img.zoomed { cursor: zoom-out; transform: scale(2.3); }

/* Termeni de retur / Drepturile consumatorului — a new progressive-
   disclosure pattern (not used elsewhere on the site yet) so the legal
   detail is available without turning the page into a wall of text. */
.pdp-accordion-item {
  border-radius: 16px; border: 2px solid var(--color-border);
  background: var(--color-surface); overflow: hidden;
}
.pdp-accordion-item + .pdp-accordion-item { margin-top: 10px; }
.pdp-accordion-trigger {
  width: 100%; display: flex; align-items: center; gap: 12px; padding: 14px 16px;
  background: none; border: none; cursor: pointer; text-align: left;
}
.pdp-acc-icon { width: 34px; height: 34px; border-radius: 10px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.pdp-acc-title { flex: 1; font-weight: 800; font-size: 13.5px; color: var(--color-text); }
.pdp-acc-chevron { width: 16px; height: 16px; color: var(--color-text-secondary); transition: transform 0.2s ease; flex-shrink: 0; }
.pdp-accordion-item.open .pdp-acc-chevron { transform: rotate(180deg); }
.pdp-accordion-body { max-height: 0; overflow: hidden; transition: max-height 0.25s ease; }
.pdp-accordion-item.open .pdp-accordion-body { max-height: 500px; }
.pdp-accordion-body-inner { padding: 0 16px 16px 62px; font-size: 12.5px; color: var(--color-text-secondary); line-height: 1.55; }
.pdp-accordion-body-inner p + p { margin-top: 8px; }

/* Favorite (heart) button on product cards / product page. Filled state
   uses the coral CTA red — the universally-understood "saved" color. */
.fav-btn {
  width: 40px; height: 40px; border-radius: 8px; border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,0.92); box-shadow: 0 2px 8px rgba(0,0,0,0.15);
  transition: transform 0.15s;
}
.fav-btn:hover { transform: scale(1.1); }
.fav-btn svg { width: 17px; height: 17px; color: var(--color-text-secondary); }
.fav-btn.faved svg { color: var(--color-cta); fill: var(--color-cta); }

/* Promotion package cards (sell form step 06 + promote modal). Radio-card
   pattern like .delivery-card; tier identity via the small colored label
   in the existing bronze/silver/gold promo colors. */
.promo-pkg-card {
  position: relative; border: 2px solid var(--color-border); border-radius: 10px;
  padding: 12px 10px 10px; display: flex; flex-direction: column; gap: 2px;
  cursor: pointer; background: var(--color-bg); transition: border-color 0.15s, background 0.15s;
}
.promo-pkg-card input { position: absolute; opacity: 0; pointer-events: none; }
.promo-pkg-card:hover { border-color: var(--color-accent); }
.promo-pkg-card:has(input:checked) { border-color: var(--color-accent); background: var(--color-accent-soft); }
.promo-pkg-tier { font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.4px; }
.promo-pkg-tier.t-none   { color: var(--color-text-secondary); }
.promo-pkg-tier.t-bronze { color: #8A4B23; }
.promo-pkg-tier.t-silver { color: #56636D; }
.promo-pkg-tier.t-gold   { color: #92700C; }
.promo-pkg-name { font-family: 'Montserrat', sans-serif; font-size: 15px; font-weight: 700; color: var(--color-text); }
.promo-pkg-price { font-size: 13px; font-weight: 800; color: var(--color-text); }
.promo-pkg-price small { font-weight: 600; color: var(--color-text-secondary); }
.promo-pkg-tag { font-size: 10.5px; color: var(--color-text-secondary); line-height: 1.35; }
.promo-pkg-popular {
  position: absolute; top: -8px; right: 8px; padding: 2px 8px; border-radius: 5px;
  font-size: 9px; font-weight: 800; letter-spacing: 0.3px; text-transform: uppercase;
  background: var(--color-cta); color: #fff;
}

/* Recently-viewed strip cards (horizontal scroll). */
.recent-card {
  flex: 0 0 130px; border: 2px solid var(--color-border); border-radius: 10px;
  overflow: hidden; cursor: pointer; background: var(--color-surface);
  transition: transform 0.2s, box-shadow 0.2s;
}
.recent-card:hover { transform: translateY(-3px); box-shadow: 0 8px 20px rgba(0,0,0,0.10); }
.recent-card .recent-thumb {
  height: 90px; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--color-surface-alt), var(--color-border));
  font-size: 34px; overflow: hidden; position: relative;
}
.recent-card .recent-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* Help widget — floating corner button + panel that slides up from it.
   Kept in the DOM at all times (not display:none) so the transform/opacity
   transition can actually animate; .open is what makes it visible. */
#help-fab:hover { transform: scale(1.06); }
#help-panel {
  position: absolute; bottom: 68px; right: 0;
  width: 320px; max-width: calc(100vw - 40px);
  background: var(--color-surface); border: 2px solid var(--color-border);
  border-radius: 12px; box-shadow: 0 16px 40px rgba(0,0,0,0.18);
  opacity: 0; transform: translateY(16px) scale(0.98);
  pointer-events: none; transition: opacity 0.22s ease, transform 0.22s ease;
  transform-origin: bottom right;
}
#help-panel.open { opacity: 1; transform: translateY(0) scale(1); pointer-events: all; }

/* Self-tucking dock (see initHelpFabAutoDock in app.js): stays put at its
   normal bottom-right corner (no dragging, no roaming the screen) — after
   a few idle seconds it slides itself ~70% of its own width further right,
   off the edge, leaving just a sliver peeking in. calc(70% + 20px) accounts
   for the wrap's own 20px right gap so the peeking edge ends up flush
   against the viewport edge instead of floating with a gap past it. Any
   tap on the fab (via the wake() listener in app.js) slides it back. */
.help-fab-wrap { transition: transform 0.4s cubic-bezier(.2,.8,.2,1); }
.help-fab-wrap.auto-docked { transform: translateX(calc(70% + 20px)); }
.help-fab-wrap.auto-docked #help-fab { opacity: 0.88; }


/* ==========================================================================
   MEGA-BATCH: skeletons, mobile bottom nav, micro-interactions, misc.
   ========================================================================== */

/* Skeleton loading — the catalog now loads over the network from Supabase;
   shimmering placeholders make the wait read as "fast site working" instead
   of "broken empty page" (perceived performance). */
.skeleton-card { border-radius: 12px; overflow: hidden; background: var(--color-surface); border: 2px solid var(--color-border); }
.skeleton-block { background: linear-gradient(90deg, var(--color-border) 25%, var(--color-surface-alt) 50%, var(--color-border) 75%); background-size: 200% 100%; animation: shimmer 1.3s infinite; }
@keyframes shimmer { to { background-position: -200% 0; } }
.skeleton-img { aspect-ratio: 1; }
.skeleton-line { height: 12px; border-radius: 6px; margin: 8px 12px; }
.skeleton-line.short { width: 40%; }

/* Mobile bottom navigation — app-style tab bar; the center "Vinde" action
   is elevated because listing items is the marketplace's supply engine.
   Carries every icon that used to live in the header on mobile (bell,
   favorites, account) — see .header-dup-nav below — so the header itself
   stays a plain logo + search bar row with nothing fighting the search
   bar for width. */
#bottom-nav { display: none; }
@media (max-width: 1023px) {
  #bottom-nav {
    display: flex; position: fixed; bottom: 0; left: 0; right: 0; z-index: 45;
    background: var(--color-surface); border-top: 2px solid var(--color-border);
    padding: 6px 2px calc(6px + env(safe-area-inset-bottom));
    justify-content: space-around; align-items: flex-end;
    transition: transform 0.25s ease;
  }
  /* Auto-hide on scroll (see initBottomNavAutoHide in app.js): slides
     fully off-screen while reading down the page, back in on any upward
     scroll — the reserved padding below stays fixed either way so
     content never jumps when the bar hides/shows. */
  #bottom-nav.bottom-nav-hidden { transform: translateY(100%); }
  /* keep page content + floating helpers clear of the bar */
  #app { padding-bottom: 70px; }
  .help-fab-wrap { bottom: 84px !important; }
  #toast-container { bottom: 88px !important; }
  /* Both #cookie-consent and #bottom-nav are position:fixed;bottom:0 —
     without this they'd sit directly on top of each other on mobile. */
  #cookie-consent { bottom: 70px !important; }
  /* Every icon that used to sit in the header at this breakpoint (bell,
     favorites, messages, account, Vinde) now lives only in #bottom-nav —
     same destination, one tap away either place, and it's what stops the
     header row from ever having to fight the search bar for width. */
  .header-dup-nav { display: none !important; }
  /* iOS Safari (and some other mobile browsers) auto-zooms the whole page
     on focus for any text input/select/textarea whose computed font-size
     is under 16px — a SEPARATE mechanism from the maximum-scale/
     user-scalable viewport lock in index.html, and not prevented by it.
     Every form control in this app is 13-14px by design (.sell-select,
     .chat-input, the search bar's Tailwind text-sm, ...) — !important
     reliably wins over that whole mix of utility and custom classes
     without touching each one individually, so tapping into a field
     can't silently break the "fixed phone app" feel the viewport lock
     was added for. */
  input, select, textarea { font-size: 16px !important; }
}
.bottom-nav-item {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  background: none; border: none; cursor: pointer; padding: 4px 6px;
  font-size: 9.5px; font-weight: 700; color: var(--color-text-secondary);
  white-space: nowrap;
}
.bottom-nav-item svg { width: 21px; height: 21px; }
.bottom-nav-item.active { color: var(--color-accent); }
/* #bottom-msg-badge's own wrapper span carries position:relative directly
   (see index.html) rather than this whole flex-column button — anchoring
   to the button would put the badge in the button's corner, not the
   icon's. */
.bottom-nav-item .msg-nav-badge { top: -6px; right: -8px; }
.bottom-nav-sell {
  width: 48px; height: 48px; border-radius: 14px; margin-top: -18px;
  background: var(--color-accent); color: #fff; border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 6px 16px rgba(21,128,72,0.35);
}
.bottom-nav-sell svg { width: 24px; height: 24px; }

/* Heart pop micro-interaction when a listing gets saved. */
@keyframes fav-pop { 0% { transform: scale(1); } 40% { transform: scale(1.45); } 100% { transform: scale(1); } }
.fav-btn.faved svg { animation: fav-pop 0.35s ease; }

/* Second-photo-on-hover (fashion e-commerce classic): the card swaps to
   the listing's 2nd photo while hovered — more information, zero clicks. */
.card-img-hover { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 0.25s ease; }
.product-card:hover .card-img-hover { opacity: 1; }

/* Toast types — colored, so success/error reads before the words do. */
.toast.t-success { background: var(--color-accent) !important; }
.toast.t-error   { background: #B3261E !important; }

/* Sold overlay badge on cards. */
.sold-overlay {
  position: absolute; inset: 0; z-index: 6; display: flex; align-items: center; justify-content: center;
  background: rgba(58,69,104,0.45);
}
.sold-overlay span {
  background: #fff; color: var(--color-text); font-weight: 800; font-size: 13px;
  padding: 6px 18px; border-radius: 8px; letter-spacing: 0.5px; text-transform: uppercase;
}

/* Search suggestions dropdown. */
#search-suggest {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 60;
  background: var(--color-surface); border: 2px solid var(--color-border);
  border-radius: 10px; box-shadow: 0 12px 30px rgba(0,0,0,0.14); overflow: hidden; display: none;
}
#search-suggest.open { display: block; }
.suggest-item { display: flex; align-items: center; gap: 12px; padding: 8px 14px; cursor: pointer; font-size: 13px; color: var(--color-text); }
.suggest-item.active,
.suggest-item:hover { background: var(--color-surface-alt); }
.suggest-item .s-cat { margin-left: auto; font-size: 11px; color: var(--color-text-secondary); white-space: nowrap; }
/* Real product photo (or an emoji fallback in an equally-sized tile) —
   was a bare inline emoji at the default 13px text size, easy to miss and
   not actually a "photo" even when the listing had real images. */
.suggest-thumb { width: 60px; height: 60px; border-radius: 10px; object-fit: cover; flex-shrink: 0; }
.suggest-thumb-emoji { display: flex; align-items: center; justify-content: center; font-size: 30px; background: var(--color-surface-alt); }

/* Chat page on phones: the two-pane conversation-list + thread layout was
   fixed at width:280px for the list with no mobile handling at all, forcing
   either horizontal overflow or an unusably narrow thread pane. Below the
   site's existing 1023px breakpoint, only one pane shows at a time — the
   list by default, the thread once #page-chat gets .thread-open (toggled by
   openConversation()/backToConvList() in app.js) — with a back button
   (.chat-back-btn, rendered into #chat-subheader) to return to the list. */
.chat-back-btn { display: none; }
@media (max-width: 1023px) {
  .chat-panes { height: 75vh; }
  .chat-list-col { width: 100% !important; border-right: none !important; }
  .chat-thread-col { display: none !important; }
  #page-chat.thread-open .chat-list-col { display: none !important; }
  #page-chat.thread-open .chat-thread-col { display: flex !important; }
  .chat-back-btn { display: inline-flex !important; }
}

/* Size-guide table */
.size-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.size-table th { text-align: left; padding: 7px 10px; background: var(--color-surface-alt); color: var(--color-accent); font-size: 11px; text-transform: uppercase; letter-spacing: 0.4px; }
.size-table td { padding: 7px 10px; border-bottom: 1px solid var(--color-border); color: var(--color-text); }
.size-table tr:last-child td { border-bottom: none; }


/* Mobile filters bottom-sheet: on phones the (desktop-sticky) sidebar
   becomes a slide-up sheet when .mobile-open is set. */
@media (max-width: 1023px) {
  #filters-sidebar.mobile-open {
    display: block !important;
    position: fixed !important;
    left: 0; right: 0; bottom: 0; top: auto !important;
    width: 100% !important;
    max-height: 78vh !important;
    z-index: 48;
    background: var(--color-surface);
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -12px 40px rgba(0,0,0,0.25);
    padding: 0;
    /* The sheet itself no longer scrolls: it is a column whose card scrolls
       and whose footer does not. Sticky positioning could not do this — the
       footer's containing block is the card, so it stopped short of the
       sheet's own bottom edge and left filter rows visible underneath it. */
    display: flex !important; flex-direction: column;
    overflow: hidden !important;
    animation: sheetUp 0.25s ease;
  }
  #filters-sidebar.mobile-open > div:first-child {
    border: none !important;
    flex: 1 1 auto; overflow-y: auto; padding: 8px 12px 4px;
  }
  #filters-sidebar.mobile-open #mobile-filters-close { display: flex !important; }
  #filters-sidebar.mobile-open #mobile-filters-footer {
    flex: 0 0 auto;
    padding: 10px 12px calc(12px + env(safe-area-inset-bottom));
    background: var(--color-surface);
    box-shadow: 0 -8px 18px rgba(0,0,0,0.06);
  }
  /* The cookie bar is fixed to the same bottom edge the sheet occupies and
     was landing on top of the filter controls. Same treatment an open
     dialog already gets (see body.dialog-open below). */
  body.filters-open #cookie-consent { display: none !important; }
}
/* Only ever part of the bottom sheet — on a desktop sidebar the results are
   already visible next to it, so there is nothing to confirm. */
#mobile-filters-footer { display: none; }
@media (max-width: 1023px) { #filters-sidebar.mobile-open #mobile-filters-footer { display: block; } }
@keyframes sheetUp { from { transform: translateY(40%); opacity: 0.4; } to { transform: translateY(0); opacity: 1; } }
#mobile-filters-btn { display: none; }
@media (max-width: 1023px) { #mobile-filters-btn.available { display: inline-flex !important; } }

/* Share buttons on the product page */
.share-btn { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 800;
  padding: 6px 12px; border-radius: 8px; border: none; cursor: pointer; }
.share-wa { background: #E7F8EE; color: #0F6B60; } /* was #128C7E, 3.75:1 */
.share-copy { background: var(--color-surface-alt); color: var(--color-accent); }


/* Mobile category tiles (horizontal scroll under the hero). */
.cat-tile {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px;
  padding: 9px 13px; border-radius: 10px; border: 2px solid var(--color-border);
  background: var(--color-surface); font-size: 12px; font-weight: 800;
  color: var(--color-text); cursor: pointer; white-space: nowrap;
}
.cat-tile svg { width: 15px; height: 15px; color: var(--color-accent); }
.cat-tile.active { border-color: var(--color-accent); background: var(--color-accent-soft); color: var(--color-accent); }

/* Breadcrumb entries on the product page. Were click-only <span>s; now real
   buttons, styled back to look like the inline text links they read as. */
.crumb-link {
  background: none; border: none; padding: 0; font: inherit; color: inherit;
  cursor: pointer; text-decoration: none;
}
.crumb-link:hover { text-decoration: underline; }

/* The search field itself was only 20px tall inside a ~44px bar, so a tap a
   few pixels above or below the text landed on the bar and focused nothing.
   Stretching the input to the bar's height makes the whole row the target
   without changing how it looks. */
.search-bar { min-height: 44px; }
.search-bar #search-input { align-self: stretch; min-height: 24px; }

/* Fondator counter on the seller band. The number carries the message, so it
   gets the weight — and the gold family, matching the badge it is offering
   rather than the green everything else on the page already uses. */
.founder-slots {
  display: inline-flex; align-items: baseline; gap: 8px;
  padding: 10px 16px; border-radius: 12px;
  background: var(--color-gold-soft); border: 2px solid rgba(154, 71, 8, 0.18);
}
.founder-slots-num {
  font-family: 'Montserrat', sans-serif; font-size: 30px; font-weight: 800; line-height: 1;
  color: var(--color-gold-on-soft); font-variant-numeric: tabular-nums;
}
.founder-slots-label { font-size: 12px; font-weight: 700; color: var(--color-text-secondary); max-width: 19ch; line-height: 1.35; }

/* Consent banner steps aside while a dialog is open — at z-index 200 it
   otherwise floats above every modal in the app (all z-50) and covers their
   buttons. !important because the banner's own visibility is set inline by
   initCookieConsent/acceptCookies. */
body.dialog-open #cookie-consent { display: none !important; }

/* ---------------------------------------------------------------------------
   Product detail sheet
   The old version was a two-column grid with no separators: ten facts in it
   read as one grey block and the eye had nothing to land on. A definition
   list with a hairline per row gives each fact its own line to scan, and the
   label/value contrast does the rest — no boxes, no zebra striping, nothing
   that competes with the photo above it.
   --------------------------------------------------------------------------- */
.spec-sheet {
  border: 2px solid var(--color-border); border-radius: 14px;
  background: var(--color-surface); overflow: hidden; margin-top: 4px;
}
.spec-row {
  display: flex; align-items: baseline; gap: 16px;
  padding: 10px 14px; border-bottom: 1px solid var(--color-border);
}
.spec-row:last-child { border-bottom: none; }
.spec-row dt {
  flex: 0 0 40%; max-width: 170px;
  font-size: 12px; color: var(--color-text-secondary);
}
.spec-row dd {
  margin: 0; flex: 1; min-width: 0;
  font-size: 13px; font-weight: 700; color: var(--color-text);
}
@media (max-width: 380px) {
  /* Below this the two columns squeeze the value onto three lines; stacking
     keeps each fact on one. */
  .spec-row { flex-direction: column; gap: 2px; }
  .spec-row dt { flex: none; max-width: none; }
}

/* Household / safety statements. Deliberately quieter than the trust chips in
   the hero: these are reassurances a reader looks for once they are already
   interested, not a reason to click. */
.household-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.household-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: 999px;
  font-size: 12px; font-weight: 700;
  background: var(--color-accent-soft); color: var(--color-accent-on-soft);
}
.household-chip svg { width: 14px; height: 14px; flex-shrink: 0; }

/* The same two statements as inputs on the sell form — same visual language
   as .delivery-card just above them, so the section reads as one set of
   choices rather than radio cards followed by loose checkboxes. */
.household-check {
  display: flex; align-items: center; gap: 10px; cursor: pointer;
  padding: 12px 14px; border-radius: 12px;
  border: 2px solid var(--color-border); background: var(--color-bg);
  font-size: 13px; font-weight: 600; color: var(--color-text);
  transition: border-color 0.15s, background 0.15s;
}
.household-check:hover { border-color: var(--color-accent); }
.household-check input { width: 16px; height: 16px; accent-color: var(--color-accent); flex-shrink: 0; }
.household-check-icon { width: 16px; height: 16px; color: var(--color-accent); flex-shrink: 0; }
.household-check:has(input:checked) {
  border-color: var(--color-accent); background: var(--color-accent-soft);
}

/* Professional-seller mark. Neutral blue rather than a trust colour: it is a
   statement of legal status, not a compliment — and for the buyer it is good
   news (it is the badge that brings the 14-day withdrawal right with it). */
.trader-badge {
  display: inline-flex; align-items: center; gap: 3px; font-size: 10px; font-weight: 800;
  padding: 3px 7px; border-radius: 6px;
  background: #E7ECFB; color: #34479B;
}
.trader-badge svg { width: 11px; height: 11px; }
