/* ==========================================================================
   TradeBioIndia — application stylesheet
   Light theme. Single source for every page of the app.
   ========================================================================== */

:root {
  --ink: #0b1f2a;
  --body: #37475a;
  --muted: #6b7f92;
  --faint: #93a4b3;
  --line: #e3e9ef;
  --line-strong: #cfd9e3;
  --bg: #f6f8fa;
  --surface: #ffffff;
  --surface-alt: #fbfcfd;

  --brand: #0d6b7a;
  --brand-dark: #0a5361;
  --brand-light: #e7f4f6;
  --brand-ring: rgba(13, 107, 122, 0.18);

  --accent: #12704a;
  --accent-light: #e7f5ee;

  --warn: #9a6200;
  --warn-light: #fdf5e6;
  --warn-line: #f0dcb4;

  --danger: #b3261e;
  --danger-light: #fdecea;
  --danger-line: #f3c9c5;

  --radius: 10px;
  --radius-lg: 14px;
  --radius-sm: 7px;
  --shadow-sm: 0 1px 2px rgba(11, 31, 42, 0.05), 0 1px 3px rgba(11, 31, 42, 0.04);
  --shadow: 0 2px 6px rgba(11, 31, 42, 0.06), 0 8px 24px rgba(11, 31, 42, 0.06);
  --shadow-lg: 0 12px 40px rgba(11, 31, 42, 0.16);

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --header-h: 64px;
  --maxw: 1200px;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.6;
  color: var(--body);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  color: var(--ink);
  line-height: 1.25;
  margin: 0 0 .5em;
  letter-spacing: -0.015em;
  font-weight: 650;
}
h1 { font-size: clamp(1.75rem, 1.2rem + 2vw, 2.6rem); }
h2 { font-size: clamp(1.3rem, 1.05rem + .9vw, 1.75rem); }
h3 { font-size: 1.075rem; }
h4 { font-size: .95rem; }
p { margin: 0 0 1em; }
a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }
ul, ol { margin: 0 0 1em; padding-left: 1.25em; }
li { margin-bottom: .35em; }
img { max-width: 100%; display: block; }
strong { color: var(--ink); }
hr { border: 0; border-top: 1px solid var(--line); margin: 24px 0; }
code { font-family: var(--mono); font-size: .875em; background: var(--bg); padding: .1em .35em; border-radius: 4px; }

.container { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 20px; }
.container-narrow { max-width: 860px; }
.card > :last-child, .panel > :last-child, .section-head > :last-child { margin-bottom: 0; }

/* ---------- Header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 60;
  background: rgba(255,255,255,.94);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--line);
}
.header-inner { display: flex; align-items: center; gap: 18px; height: var(--header-h); }
.logo {
  font-weight: 750; font-size: 1.16rem; color: var(--ink);
  letter-spacing: -.02em; white-space: nowrap; flex-shrink: 0;
}
.logo span { color: var(--brand); }
.logo:hover { text-decoration: none; }
.main-nav { display: flex; align-items: center; gap: 4px; margin-left: 8px; }
.main-nav a {
  color: var(--body); font-size: .925rem; font-weight: 500;
  padding: 8px 11px; border-radius: var(--radius-sm); white-space: nowrap;
}
.main-nav a:hover { background: var(--bg); color: var(--ink); text-decoration: none; }
.main-nav a.active { color: var(--brand); background: var(--brand-light); }
.header-actions { margin-left: auto; display: flex; align-items: center; gap: 10px; }

/* The collapsed menu only exists inside the ≤900px block below. Without a base
   rule it renders as a plain block on desktop — a flattened row of links under
   the header, which is how it shipped before this fix. */
.mobile-nav { display: none; }

.search-trigger {
  display: flex; align-items: center; gap: 9px;
  min-width: 240px; padding: 9px 12px;
  background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--muted); font-size: .9rem;
  cursor: pointer; font-family: inherit; text-align: left;
}
.search-trigger:hover { border-color: var(--line-strong); background: #fff; }
.search-trigger svg { flex-shrink: 0; }
.search-trigger kbd {
  margin-left: auto; font-family: var(--font); font-size: .68rem;
  border: 1px solid var(--line-strong); border-bottom-width: 2px;
  border-radius: 5px; padding: 1px 5px; color: var(--faint); background: #fff;
}
.nav-toggle {
  display: none; background: none; border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 8px; cursor: pointer; color: var(--ink);
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: inherit; font-size: .93rem; font-weight: 600; line-height: 1;
  padding: 12px 18px; border-radius: var(--radius);
  border: 1px solid transparent; cursor: pointer;
  transition: background .15s, border-color .15s, color .15s, transform .1s;
  text-decoration: none; white-space: nowrap;
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn-primary { background: var(--brand); color: #fff; }
.btn-primary:hover { background: var(--brand-dark); }
.btn-secondary { background: #fff; color: var(--ink); border-color: var(--line-strong); }
.btn-secondary:hover { border-color: var(--brand); color: var(--brand); }
.btn-ghost { background: transparent; color: var(--brand); padding: 10px 12px; }
.btn-ghost:hover { background: var(--brand-light); }
.btn-accent { background: var(--accent); color: #fff; }
.btn-accent:hover { background: #0d5a3b; }
.btn-sm { padding: 8px 13px; font-size: .85rem; }
.btn-lg { padding: 15px 26px; font-size: 1rem; }
.btn-block { width: 100%; }
.btn[disabled], .btn.is-busy { opacity: .62; pointer-events: none; }
.btn-link {
  background: none; border: 0; padding: 0; font: inherit;
  color: var(--brand); cursor: pointer; text-decoration: underline;
}

/* ---------- Global search overlay ---------- */
.search-layer {
  position: fixed; inset: 0; z-index: 90; display: none;
  background: rgba(11, 31, 42, .38); padding: 84px 20px 20px;
}
.search-layer.open { display: block; }
.search-panel {
  max-width: 660px; margin: 0 auto; background: #fff;
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); overflow: hidden;
}
.search-panel input {
  width: 100%; border: 0; outline: 0; font-family: inherit; font-size: 1.05rem;
  padding: 20px 22px; color: var(--ink); border-bottom: 1px solid var(--line);
}
.search-panel input::placeholder { color: var(--faint); }
.search-hint {
  padding: 9px 22px; font-size: .78rem; color: var(--faint);
  display: flex; gap: 14px; border-bottom: 1px solid var(--line); background: var(--surface-alt);
}
.search-results { max-height: 52vh; overflow-y: auto; }
.search-group-label {
  font-size: .7rem; text-transform: uppercase; letter-spacing: .09em;
  color: var(--faint); font-weight: 700; padding: 12px 22px 6px;
}
.search-item {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 22px; cursor: pointer; border-left: 3px solid transparent;
}
/* Placed before the hover/active rule on purpose: the keyboard-selected row is
   what the arrow keys are pointing at, and a paid tint must never win over it.
   The badge chip in .si-name is the disclosure; this is only a second, quieter
   signal that the row is a placement. */
.search-item.is-featured { background: #fffbf1; border-left-color: #f2e0b4; }
.search-item:hover, .search-item.active { background: var(--brand-light); border-left-color: var(--brand); }
.search-item .si-main { flex: 1; min-width: 0; }
.search-item .si-name { color: var(--ink); font-weight: 600; font-size: .95rem; }
.search-item .si-meta { color: var(--muted); font-size: .8rem; }
.search-item mark { background: #fff3c4; color: inherit; border-radius: 3px; padding: 0 1px; }
.search-empty { padding: 26px 22px; color: var(--muted); font-size: .92rem; }
.search-foot {
  border-top: 1px solid var(--line); padding: 11px 22px;
  font-size: .82rem; background: var(--surface-alt); display: flex; justify-content: space-between; gap: 10px;
}

/* ---------- Shell / sections ---------- */
main { display: block; min-height: 50vh; }
.section { padding: 56px 0; }
.section-tight { padding: 36px 0; }
.section-head { margin-bottom: 26px; max-width: 760px; }
.section-head.center { margin-left: auto; margin-right: auto; text-align: center; }
.eyebrow {
  display: inline-block; font-size: .72rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--brand);
  background: var(--brand-light); padding: 5px 10px; border-radius: 999px; margin-bottom: 12px;
}
.section-sub { color: var(--muted); font-size: 1.02rem; margin: 0; }
.band-white { background: #fff; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.band-ink { background: var(--ink); color: #cfdae2; }
.band-ink h2, .band-ink h3 { color: #fff; }
.band-brand { background: linear-gradient(150deg, #0d6b7a 0%, #0a5361 100%); color: #d8ecf0; }
.band-brand h2, .band-brand h3 { color: #fff; }
.band-brand a { color: #fff; }

/* ---------- Free band ---------- */
.free-band {
  background: var(--accent-light); color: #0d5a3b;
  border-bottom: 1px solid #cfe9dd;
  font-size: .855rem; font-weight: 600; text-align: center; padding: 9px 20px;
}

/* ---------- Hero ---------- */
.hero {
  position: relative; overflow: hidden;
  background: linear-gradient(165deg, #ffffff 0%, #eef6f8 60%, #e6f1f4 100%);
  border-bottom: 1px solid var(--line);
  padding: 62px 0 54px;
}
.hero::after {
  content: ""; position: absolute; right: -140px; top: -160px;
  width: 520px; height: 520px; border-radius: 50%;
  background: radial-gradient(circle, rgba(13,107,122,.10) 0%, rgba(13,107,122,0) 68%);
  pointer-events: none;
}
.hero-inner { position: relative; z-index: 1; max-width: 760px; }
.hero h1 { margin-bottom: 14px; }
.hero p.lead { font-size: 1.08rem; color: var(--body); margin-bottom: 26px; }
.hero-search { display: flex; gap: 10px; margin-bottom: 16px; }
.hero-search input {
  flex: 1; font-family: inherit; font-size: 1rem; padding: 15px 17px;
  border: 1px solid var(--line-strong); border-radius: var(--radius);
  background: #fff; color: var(--ink); box-shadow: var(--shadow-sm);
}
.hero-search input:focus { outline: 0; border-color: var(--brand); box-shadow: 0 0 0 4px var(--brand-ring); }
.hero-chips { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; font-size: .84rem; color: var(--muted); }
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: #fff; border: 1px solid var(--line-strong); border-radius: 999px;
  padding: 6px 13px; font-size: .85rem; color: var(--body); cursor: pointer; font-family: inherit;
}
.chip:hover { border-color: var(--brand); color: var(--brand); text-decoration: none; }
.chip.active { background: var(--brand); border-color: var(--brand); color: #fff; }
.hero-stats { display: flex; flex-wrap: wrap; gap: 34px; margin-top: 34px; }
.hero-stats div strong { display: block; font-size: 1.5rem; color: var(--ink); font-weight: 700; letter-spacing: -.02em; }
.hero-stats div span { font-size: .84rem; color: var(--muted); }
.page-hero { background: #fff; border-bottom: 1px solid var(--line); padding: 34px 0 30px; }
.page-hero h1 { margin-bottom: 8px; }

/* ---------- Grids ---------- */
.grid { display: grid; gap: 18px; }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
/* auto-fill instead of a fixed 4: a fixed count crushed cards to ~150px of
   content width next to the browse sidebar (blank thumbs, floating price
   chips, stacked buttons). 240px minimum keeps the CAS/MOQ + price row on one
   line, which is what caps the homepage at 4-across and browse at 3-across. */
.product-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 18px; }
/* Browse layout: filter rail on the left, results take the remaining width.
   The markup order is filter card → results, so the rail must be the FIRST
   column — otherwise the results grid gets crushed into 340px. */
.split { display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: 26px; align-items: start; }
.split > .card { position: sticky; top: calc(var(--header-h) + 18px); }

/* ---------- Cards ---------- */
.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: 22px; box-shadow: var(--shadow-sm);
}
.card-flush { padding: 0; overflow: hidden; }
.card h2 { font-size: 1.2rem; }
.card h3 { font-size: 1rem; }
.card-head {
  padding: 15px 22px; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  background: var(--surface-alt);
}
.card-head h2, .card-head h3 { margin: 0; font-size: 1rem; }
.card-body { padding: 20px 22px; }

.product-card {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; gap: 8px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: 17px;
  box-shadow: var(--shadow-sm); color: inherit;
  transition: border-color .15s, box-shadow .15s, transform .12s;
}
.product-card::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: linear-gradient(90deg, #0d6b7a, #3ba7b8);
}
.product-card.is-b::before { background: linear-gradient(90deg, #a8760a, #e0a82e); }
/* ---------- Featured placement ----------
   A promoted card is marked, not disguised. The `Featured` badge says why the
   row is where it is; the warm border and tint make the promoted set findable
   in a grid of otherwise identical cards. Deliberately restrained — a card that
   shouts reads as an advertisement, and an advertisement is what buyers learn
   to skip. Not a top bar, because that is already how wedge B is marked. */
.product-card.is-featured { border-color: #f2e0b4; background: #fffbf1; }
.product-card:hover {
  text-decoration: none; border-color: var(--brand);
  box-shadow: var(--shadow); transform: translateY(-2px);
}
.product-card h3 { margin: 0; font-size: 1.02rem; }
.product-card .pc-sub { font-size: .845rem; color: var(--muted); margin: 0; }
.product-card .pc-foot {
  margin-top: auto; padding-top: 10px; border-top: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: .8rem; color: var(--muted);
}
/* Cards without MOQ/CAS render only the price chip — keep it pinned right. */
.pc-foot .pc-price { margin-left: auto; }
.wedge-tag {
  align-self: flex-start; font-size: .68rem; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--brand); background: var(--brand-light);
  padding: 4px 8px; border-radius: 5px;
}
.wedge-tag.tag-b { color: #6b4b00; background: #fdf3dd; }

/* ---------- Badges ---------- */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: .74rem; font-weight: 650; padding: 3px 9px; border-radius: 999px;
  background: var(--bg); color: var(--body); border: 1px solid var(--line);
}
.badge-free { background: var(--accent-light); color: var(--accent); border-color: #cfe9dd; }
.badge-verified { background: var(--brand-light); color: var(--brand-dark); border-color: #c9e5e9; }
.badge-rx { background: var(--danger-light); color: var(--danger); border-color: var(--danger-line); }
.badge-warn { background: var(--warn-light); color: var(--warn); border-color: var(--warn-line); }
.badge-featured { background: #fff6e0; color: #8a5a00; border-color: #f2e0b4; }
.badge-plain { background: transparent; }

/* ---------- Notices ---------- */
.notice {
  display: flex; gap: 12px; padding: 15px 17px; border-radius: var(--radius);
  font-size: .9rem; border: 1px solid; margin-bottom: 18px;
}
.notice > div { flex: 1; }
.notice strong { display: block; margin-bottom: 2px; }
.notice-info { background: var(--brand-light); border-color: #c9e5e9; color: #0b4a55; }
.notice-warn { background: var(--warn-light); border-color: var(--warn-line); color: var(--warn); }
.notice-danger { background: var(--danger-light); border-color: var(--danger-line); color: var(--danger); }
.notice-ok { background: var(--accent-light); border-color: #cfe9dd; color: var(--accent); }
.notice p:last-child { margin-bottom: 0; }
.notice .notice-icon { flex-shrink: 0; font-size: 1.05rem; line-height: 1.4; }

/* ---------- Breadcrumb ---------- */
.breadcrumb {
  font-size: .82rem; color: var(--muted); padding: 16px 0 0;
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
}
.breadcrumb a { color: var(--muted); }
.breadcrumb a:hover { color: var(--brand); }
.breadcrumb .sep { color: var(--faint); }

/* ---------- Product page ---------- */
.product-head { padding: 14px 0 6px; }
.product-head h1 { margin-bottom: 12px; }
.product-head .meta-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 14px; }
.product-layout { display: grid; grid-template-columns: minmax(0, 1fr) 330px; gap: 26px; align-items: start; padding: 22px 0 0; }
.stack { display: flex; flex-direction: column; gap: 18px; }
.sidebar { display: flex; flex-direction: column; gap: 18px; position: sticky; top: calc(var(--header-h) + 18px); }
.kv { display: grid; grid-template-columns: 168px minmax(0, 1fr); gap: 0; }
.kv dt {
  font-size: .86rem; color: var(--muted); padding: 10px 0; border-top: 1px solid var(--line);
}
.kv dd {
  margin: 0; padding: 10px 0; border-top: 1px solid var(--line);
  font-size: .91rem; color: var(--ink);
}
.kv dt:first-of-type, .kv dd:first-of-type { border-top: 0; }

/* Key features (schema §20). A supplier types this as a plain list of lines,
   so it renders as a list rather than as prose — a buyer comparing three
   listings should be able to line the claims up. The marker is a small brand
   tick instead of a disc, because a disc next to "Assay 99.5%" reads like a
   bulleted paragraph and a tick reads like a check that was done. */
.feature-list { list-style: none; padding: 0; margin: 0; }
.feature-list li {
  position: relative; padding: 9px 0 9px 24px; border-top: 1px solid var(--line);
  font-size: .91rem; color: var(--ink);
}
.feature-list li:first-child { border-top: 0; }
.feature-list li::before {
  content: ""; position: absolute; left: 2px; top: 15px;
  width: 5px; height: 9px; border: solid var(--brand); border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* The company page identity panel. Its seven rows share the sidebar with the
   contact card, so the generic 168px label column (tuned for the wide product
   sidebar) leaves values like "Manufacturer · Supplier · Distributor" wrapping
   every other word. A narrower label column fits the longest label here —
   "Contact person" — and hands the rest to the value. Scoped above 640px: the
   small-screen rule below stacks .kv label over value, and this override is
   specific enough that it would otherwise win and keep two columns. */
@media (min-width: 641px) {
  .company-details .kv { grid-template-columns: 112px minmax(0, 1fr); }
  .company-details .kv dt, .company-details .kv dd { padding: 9px 0; }
  .company-details .kv dd { overflow-wrap: anywhere; }
}
/* The two facts the About us card carries as chips instead of as prose —
   "Employees" and "Export markets". They sit under a paragraph of running
   text, so they read as a small labelled strip rather than as tags: the
   label is quiet, the value is what the eye lands on. */
.fact-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.fact-chip {
  display: inline-flex; align-items: baseline; gap: 6px;
  padding: 5px 11px; border-radius: 999px;
  background: var(--bg); border: 1px solid var(--line);
  font-size: .82rem; color: var(--ink);
}
.fact-chip-k {
  font-size: .7rem; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted);
}

.spec-table { width: 100%; border-collapse: collapse; font-size: .9rem; }
.spec-table td { padding: 10px 0; border-top: 1px solid var(--line); vertical-align: top; }
.spec-table tr:first-child td { border-top: 0; }
.spec-table td:first-child { color: var(--muted); width: 42%; padding-right: 16px; }
.spec-table td:last-child { color: var(--ink); }
.price-or { font-size: 1.05rem; font-weight: 650; color: var(--ink); }
.price-note { font-size: .84rem; color: var(--muted); }
.prose { font-size: .95rem; }
.prose h3 { margin-top: 18px; font-size: .98rem; }
.prose ul { padding-left: 1.1em; }

/* tabs */
.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); overflow-x: auto; }
.tab {
  background: none; border: 0; border-bottom: 2px solid transparent; font-family: inherit;
  font-size: .9rem; font-weight: 600; color: var(--muted); padding: 11px 14px; cursor: pointer; white-space: nowrap;
}
.tab:hover { color: var(--ink); }
.tab.active { color: var(--brand); border-bottom-color: var(--brand); }
.tab-panel { display: none; padding: 20px 0 0; }
.tab-panel.active { display: block; }

/* faq */
.faq-item { border-top: 1px solid var(--line); }
.faq-item:first-child { border-top: 0; }
.faq-item summary {
  cursor: pointer; padding: 14px 0; font-weight: 600; color: var(--ink);
  font-size: .95rem; list-style: none; display: flex; justify-content: space-between; gap: 14px;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after { content: "+"; color: var(--brand); font-weight: 600; font-size: 1.1rem; line-height: 1; }
.faq-item[open] summary::after { content: "–"; }
.faq-item .faq-a { padding: 0 0 16px; font-size: .92rem; color: var(--body); }
.faq-item .faq-a p:last-child { margin-bottom: 0; }

/* ---------- Supplier / listing rows ---------- */
.supplier-row {
  display: flex; gap: 14px; align-items: flex-start;
  padding: 16px 0; border-top: 1px solid var(--line);
}
.supplier-row:first-child { border-top: 0; }
.supplier-avatar {
  width: 42px; height: 42px; border-radius: 9px; flex-shrink: 0;
  background: var(--brand-light); color: var(--brand-dark);
  display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: .95rem;
}
.supplier-row .sr-main { flex: 1; min-width: 0; }
.supplier-row h4 { margin: 0 0 3px; font-size: .96rem; }
.supplier-row .sr-meta { font-size: .82rem; color: var(--muted); display: flex; flex-wrap: wrap; gap: 8px; }
.placeholder-row {
  border: 1px dashed var(--line-strong); border-radius: var(--radius);
  padding: 18px; background: var(--surface-alt); font-size: .9rem; color: var(--muted);
}

/* ---------- Forms ---------- */
.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.form-grid .span-2 { grid-column: 1 / -1; }
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
.field label { font-size: .86rem; font-weight: 600; color: var(--ink); }
.field .req { color: var(--danger); margin-left: 2px; }
.field .hint { font-size: .78rem; color: var(--muted); }
/* type=search is easy to miss — the browse filter uses it, and WebKit adds
   its own decorations on search inputs that must be reset to match. */
.field input[type="text"], .field input[type="email"], .field input[type="tel"],
.field input[type="number"], .field input[type="password"], .field input[type="search"],
.field input[type="url"], .field select, .field textarea {
  font-family: inherit; font-size: .94rem; color: var(--ink);
  padding: 11px 13px; border: 1px solid var(--line-strong); border-radius: var(--radius);
  background: #fff; width: 100%;
  -webkit-appearance: none; appearance: none;
}
.field textarea { min-height: 110px; resize: vertical; }
.field select {
  appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23567489' stroke-width='1.7' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 13px center; padding-right: 34px;
}
.field select:hover { border-color: var(--brand); }
.field select option, .field select optgroup { font-family: inherit; color: var(--ink); background: #fff; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: 0; border-color: var(--brand); box-shadow: 0 0 0 4px var(--brand-ring);
}
.field.invalid input, .field.invalid select, .field.invalid textarea { border-color: var(--danger); background: #fffafa; }
.field .err { font-size: .78rem; color: var(--danger); display: none; }
.field.invalid .err { display: block; }
.check-row { display: flex; gap: 10px; align-items: flex-start; margin-bottom: 10px; font-size: .89rem; }
.check-row input { margin-top: 3px; flex-shrink: 0; }
.check-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 16px; margin-bottom: 8px; }
.fieldset { border: 0; padding: 0; margin: 0 0 8px; }
.fieldset > legend { font-size: .86rem; font-weight: 600; color: var(--ink); padding: 0; margin-bottom: 8px; }

.steps { display: flex; gap: 8px; margin-bottom: 24px; flex-wrap: wrap; }
.step-pill {
  display: flex; align-items: center; gap: 8px; font-size: .84rem; color: var(--muted);
  padding: 7px 13px; border-radius: 999px; background: var(--bg); border: 1px solid var(--line);
}
.step-pill .num {
  width: 20px; height: 20px; border-radius: 50%; background: var(--line-strong); color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: .72rem; font-weight: 700;
}
.step-pill.active { background: var(--brand-light); border-color: #bfe0e5; color: var(--brand-dark); font-weight: 600; }
.step-pill.active .num { background: var(--brand); }
.step-pill.done .num { background: var(--accent); }
.step { display: none; }
.step.active { display: block; }
.form-actions { display: flex; gap: 10px; align-items: center; margin-top: 8px; flex-wrap: wrap; }
.form-actions .spacer { flex: 1; }
.form-summary {
  background: var(--surface-alt); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 14px 16px; font-size: .87rem; margin-bottom: 18px;
}
.form-summary dl { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 6px 14px; margin: 0; }
.form-summary dt { color: var(--muted); }
.form-summary dd { margin: 0; color: var(--ink); }

/* ---------- Modal ---------- */
.modal-layer {
  position: fixed; inset: 0; z-index: 100; display: none;
  background: rgba(11, 31, 42, .45); padding: 24px 16px; overflow-y: auto;
}
.modal-layer.open { display: block; }
.modal {
  max-width: 620px; margin: 40px auto; background: #fff;
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); overflow: hidden;
}
.modal-head {
  padding: 18px 22px; border-bottom: 1px solid var(--line);
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
}
.modal-head h2 { margin: 0 0 3px; font-size: 1.15rem; }
.modal-head p { margin: 0; font-size: .86rem; color: var(--muted); }
.modal-close {
  background: none; border: 0; font-size: 1.4rem; line-height: 1; color: var(--muted);
  cursor: pointer; padding: 0 4px;
}
.modal-close:hover { color: var(--ink); }
.modal-body { padding: 20px 22px; max-height: 62vh; overflow-y: auto; }
.modal-foot {
  padding: 15px 22px; border-top: 1px solid var(--line); background: var(--surface-alt);
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
}

/* ---------- Submit success ---------- */
.success-box { text-align: center; padding: 12px 6px 4px; }
.success-mark {
  width: 54px; height: 54px; border-radius: 50%; background: var(--accent-light);
  color: var(--accent); display: flex; align-items: center; justify-content: center;
  margin: 0 auto 16px; font-size: 1.5rem;
}
.ref-code {
  font-family: var(--mono); font-size: 1.02rem; font-weight: 700; color: var(--ink);
  background: var(--bg); border: 1px dashed var(--line-strong); border-radius: var(--radius);
  padding: 10px 14px; display: inline-block; margin: 6px 0 14px; letter-spacing: .02em;
}

/* ---------- Toasts ---------- */
.toast-host { position: fixed; bottom: 22px; right: 22px; z-index: 130; display: flex; flex-direction: column; gap: 10px; }
.toast {
  background: var(--ink); color: #fff; padding: 13px 17px; border-radius: var(--radius);
  box-shadow: var(--shadow-lg); font-size: .9rem; max-width: 360px;
  animation: toast-in .22s ease-out;
}
.toast.err { background: #8f1d17; }
.toast.ok { background: #0d5a3b; }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ---------- Tables ---------- */
.table-wrap { overflow-x: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: .875rem; }
table.data th {
  text-align: left; font-size: .74rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); padding: 11px 14px; border-bottom: 1px solid var(--line);
  background: var(--surface-alt); white-space: nowrap; font-weight: 700;
}
table.data td { padding: 12px 14px; border-bottom: 1px solid var(--line); vertical-align: top; color: var(--ink); }
table.data tbody tr:hover { background: var(--surface-alt); }
table.data td.wrap { max-width: 320px; white-space: normal; }
.cell-sub { font-size: .8rem; color: var(--muted); display: block; }

/* ---------- Bulk selection in the console ---------- */
/* The tick cell is narrow and must not inherit the 12px vertical padding, or
   the row grows to fit a 16px box in a 40px cell and the table looks ragged. */
table.data th.cell-pick, table.data td.cell-pick {
  width: 34px; padding-left: 14px; padding-right: 0; text-align: left;
}
table.data td.cell-pick { padding-top: 14px; }
table.data input[type="checkbox"] {
  width: 16px; height: 16px; margin: 0; cursor: pointer;
  accent-color: var(--brand); vertical-align: middle;
}
table.data tr.picked { background: var(--brand-light); }
table.data tr.picked:hover { background: var(--brand-light); }

.bulk-bar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 10px 16px; border-bottom: 1px solid var(--line);
  background: var(--surface-alt); min-height: 48px;
}
.bulk-bar.active { background: var(--brand-light); }
.bulk-bar strong { margin-right: 4px; font-size: .86rem; }
.bulk-bar .btn[disabled] { opacity: .45; cursor: not-allowed; }
.bulk-bar .danger { color: var(--danger); border-color: var(--danger-line); }
.bulk-bar .danger:hover { background: var(--danger-light); }

/* A price typed as free text, rather than into the structured columns. Shown
   with a visible marker, because it is the one value in this column that may
   not be a price at all — "FOB Mumbai" has been found in that field. */
.price-note-warn {
  color: var(--warn); border-bottom: 1px dotted currentColor; cursor: help;
}

/* ---------- Read-only listing detail ---------- */
/* Deliberately not a form: no inputs, so there is nothing to save by accident
   while the desk is only trying to read what a supplier submitted. */
.detail-body { padding: 4px 22px 0; }
.detail-h {
  margin: 22px 0 10px; padding-top: 16px; border-top: 1px solid var(--line);
  font-size: .74rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted);
}
.detail-body > .detail-h:first-of-type { margin-top: 12px; }
.detail-row {
  display: grid; grid-template-columns: 148px 1fr; gap: 12px;
  padding: 6px 0; font-size: .9rem; align-items: baseline;
}
.detail-label { color: var(--muted); font-size: .82rem; }
.detail-value { color: var(--ink); }
.detail-value code { font-size: .78rem; word-break: break-all; }
.detail-block { padding: 10px 0 2px; }
.detail-block p { margin: 6px 0 0; font-size: .9rem; color: var(--body); white-space: pre-wrap; }
.tag-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.detail-gallery {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 10px; margin-top: 10px;
}
/* contain, not cover — "product photos are shown whole, never cropped" applies
   in the console detail view too. A square mat keeps the grid tidy and `contain`
   letterboxes a non-square photo inside it rather than slicing it. */
.detail-gallery img {
  width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: contain;
  padding: 6px; background: var(--bg);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
}
@media (max-width: 560px) {
  .detail-row { grid-template-columns: 1fr; gap: 2px; }
}
.empty-state { padding: 44px 20px; text-align: center; color: var(--muted); }
.empty-state strong { display: block; color: var(--ink); margin-bottom: 4px; }

/* ---------- Admin ---------- */
.admin-bar {
  background: var(--ink); color: #b9c9d4; font-size: .84rem;
  padding: 8px 0;
}
.admin-bar .container { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.admin-bar strong { color: #fff; }
.admin-bar .spacer { flex: 1; }
.admin-bar a, .admin-bar button { color: #cfe0e8; }
.auth-card { max-width: 440px; margin: 48px auto; }
.tabs-bar { display: flex; gap: 4px; border-bottom: 1px solid var(--line); margin-bottom: 20px; overflow-x: auto; }
.tabs-bar button {
  background: none; border: 0; border-bottom: 2px solid transparent; font-family: inherit;
  font-size: .9rem; font-weight: 600; color: var(--muted); padding: 11px 14px; cursor: pointer; white-space: nowrap;
}
.tabs-bar button.active { color: var(--brand); border-bottom-color: var(--brand); }
.tabs-bar .count {
  font-size: .72rem; background: var(--bg); border: 1px solid var(--line);
  border-radius: 999px; padding: 1px 7px; margin-left: 6px; color: var(--body);
}
.stat-row { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; margin-bottom: 24px; }
.stat-card { background: #fff; border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 16px 18px; }
.stat-card span { font-size: .78rem; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; font-weight: 650; }
.stat-card strong { display: block; font-size: 1.7rem; color: var(--ink); font-weight: 700; letter-spacing: -.02em; }

/* ---------- Footer ---------- */
.site-footer { background: var(--ink); color: #a9bcc8; margin-top: 0; padding: 48px 0 26px; font-size: .88rem; }
.footer-grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1.2fr; gap: 32px; margin-bottom: 30px; }
.footer-grid h4 { color: #fff; font-size: .82rem; text-transform: uppercase; letter-spacing: .08em; margin-bottom: 12px; }
.footer-grid a { display: block; color: #a9bcc8; margin-bottom: 7px; }
.footer-grid a:hover { color: #fff; text-decoration: none; }
.footer-grid .logo { color: #fff; margin-bottom: 10px; }
.footer-grid p { margin-bottom: 10px; }
.footer-muted { font-size: .84rem; color: #8296a4; line-height: 1.6; }
.footer-disclaimer {
  border-top: 1px solid #1d3646; padding-top: 20px; font-size: .79rem;
  color: #7d919f; line-height: 1.65; margin: 0;
}
.footer-bottom { display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin-top: 16px; font-size: .8rem; color: #7d919f; }

/* ---------- Utilities ---------- */
.muted { color: var(--muted); }
.small { font-size: .85rem; }
.tiny { font-size: .78rem; }
.mt-0 { margin-top: 0; } .mt-1 { margin-top: 8px; } .mt-2 { margin-top: 16px; } .mt-3 { margin-top: 26px; }
.mb-0 { margin-bottom: 0; } .mb-1 { margin-bottom: 8px; } .mb-2 { margin-bottom: 16px; } .mb-3 { margin-bottom: 26px; }
.center { text-align: center; }
.row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.row-between { display: flex; gap: 12px; align-items: center; justify-content: space-between; flex-wrap: wrap; }
.hide { display: none !important; }
.hr-soft { border-top: 1px solid var(--line); margin: 22px 0; }
.pill-list { display: flex; flex-wrap: wrap; gap: 7px; }
.list-plain { list-style: none; padding: 0; }
.list-plain li { padding: 9px 0; border-top: 1px solid var(--line); }
.list-plain li:first-child { border-top: 0; }
.link-arrow::after { content: " →"; }

/* ---------- Responsive ---------- */
@media (max-width: 1080px) {
  .product-grid, .grid-4 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .footer-grid { grid-template-columns: 1fr 1fr; gap: 26px; }
  .stat-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  .main-nav { display: none; }
  .nav-toggle { display: inline-flex; }
  .search-trigger { min-width: 0; }
  .search-trigger span, .search-trigger kbd { display: none; }
  .split, .product-layout { grid-template-columns: minmax(0, 1fr); }
  .sidebar, .split > .card { position: static; }
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .product-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .section { padding: 42px 0; }
  .mobile-nav {
    display: none; border-top: 1px solid var(--line); background: #fff; padding: 12px 20px 20px;
  }
  .mobile-nav.open { display: block; }
  .mobile-nav a { display: block; padding: 11px 4px; border-bottom: 1px solid var(--line); color: var(--ink); font-weight: 500; }
}
@media (max-width: 640px) {
  .grid-2, .grid-3, .product-grid, .form-grid, .check-grid { grid-template-columns: minmax(0, 1fr); }
  .hero { padding: 40px 0 36px; }
  .hero-search { flex-direction: column; }
  .hero-stats { gap: 22px; }
  .footer-grid { grid-template-columns: 1fr; }
  .kv, .form-summary dl { grid-template-columns: minmax(0, 1fr); }
  .kv dt { border-top: 1px solid var(--line); padding-bottom: 2px; }
  .kv dd { border-top: 0; padding-top: 0; }
  .modal-layer { padding: 0; }
  .modal { margin: 0; border-radius: 0; min-height: 100vh; }
  .stat-row { grid-template-columns: 1fr 1fr; }
}
@media print {
  .site-header, .site-footer, .free-band, .sidebar { display: none; }
}

/* ==========================================================================
   Accounts, dashboard, listings and console
   Added with the multi-user platform. Kept together so the account surfaces
   are easy to find and change as one unit.
   ========================================================================== */

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------- header additions */
.lang-switch { display: inline-flex; align-items: center; }
/* Match the custom .field select chevron — the native Windows/Chrome arrow
   and beveled frame clash with every other control on the site. */
.lang-switch select {
  font-family: inherit; font-size: .82rem; color: var(--ink);
  padding: 7px 26px 7px 10px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background-color: var(--surface); cursor: pointer; max-width: 118px;
  -webkit-appearance: none; appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 10 7'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%236b7f92' stroke-width='1.6' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 9px center;
}
.lang-switch select:hover, .lang-switch select:focus { border-color: var(--brand); }
.lang-switch select:focus { outline: 0; box-shadow: 0 0 0 3px var(--brand-ring); }

.account-slot { display: flex; align-items: center; gap: 8px; }
.account-menu { display: flex; align-items: center; gap: 6px; }
.account-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--brand-light); color: var(--brand-dark);
  font-size: .76rem; font-weight: 700;
}
.account-name { font-weight: 600; max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
[data-role-badge] { display: none; }
@media (min-width: 1280px) { [data-role-badge] { display: inline-flex; } }

/* ------------------------------------------------------------------- buttons */
.btn-xs { padding: 5px 9px; font-size: .76rem; border-radius: var(--radius-sm); }

/* -------------------------------------------------------------------- badges */
.badge-ok { background: var(--accent-light); color: var(--accent); border-color: #cfe9dd; }
.badge-warn { background: var(--warn-light); color: var(--warn); border-color: var(--warn-line); }
.badge-danger { background: var(--danger-light); color: var(--danger); border-color: var(--danger-line); }

.pill-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 19px; padding: 0 6px; margin-left: 4px;
  border-radius: 999px; background: var(--warn-light); color: var(--warn);
  font-size: .72rem; font-weight: 700;
}

/* --------------------------------------------------------------- auth screens */
.auth-wrap { max-width: 760px; margin: 0 auto; }
.auth-card { padding: 30px; }
.auth-card h1 { font-size: 1.55rem; margin-bottom: 6px; }
.auth-card form { margin-top: 18px; }

.role-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.role-card {
  display: flex; align-items: flex-start; gap: 10px; cursor: pointer;
  padding: 14px; border: 1px solid var(--line-strong); border-radius: var(--radius);
  background: var(--surface); transition: border-color .15s, background .15s;
}
.role-card:hover { border-color: var(--brand); }
.role-card.is-selected { border-color: var(--brand); background: var(--brand-light); }
.role-card input { margin-top: 3px; }
.role-card span { display: flex; flex-direction: column; gap: 2px; }
.role-card strong { font-size: .95rem; color: var(--ink); }
.role-card em { font-style: normal; font-size: .8rem; color: var(--muted); }

/* ----------------------------------------------------------------- dashboards */
.dash-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 18px; flex-wrap: wrap; padding: 8px 0 18px;
}
.dash-head h1 { font-size: 1.6rem; margin: 0 0 2px; }
.dash-head p { margin: 0; }

.field-wide { grid-column: 1 / -1; }

/* Section heading inside a long form — the listing form has three distinct
   groups (what the product is, how it is supplied, what it costs) and a single
   unbroken two-column grid of twelve fields reads like a form to be endured.
   Spans both columns and is not itself a field. */
.form-legend {
  grid-column: 1 / -1; margin: 8px 0 -4px; padding-bottom: 8px;
  border-bottom: 1px solid var(--line);
  font-size: .76rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--muted);
}
.form-legend:first-child { margin-top: 0; }

/* A field with a button beside it — the CAS lookup, and the "name your own
   category" row. */
.field-row { display: flex; gap: 8px; align-items: stretch; }
.field-row input { flex: 1; min-width: 0; }
.field-row .btn { white-space: nowrap; }
/* A `display` rule in an author stylesheet outranks the user agent's [hidden]
   rule, so the attribute silently does nothing on a flex row and the "new
   category" box showed on every product, always. Stated explicitly, exactly as
   .notif-panel and .notif-dot already are. */
.field-row[hidden] { display: none; }

/* A field's own status line: "Found in the catalog", "check digit does not
   match". Sits under the input and changes colour with the outcome. */
.cas-note { font-size: .78rem; color: var(--muted); }
.cas-note.is-ok { color: var(--brand); }
.cas-note.is-warn { color: var(--danger); }

/* ------------------------------------------------------------------- images */
.image-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px;
}
/* ------------------------------------------------------------------------
   Product photos are shown WHOLE, never cropped.

   Every one of these boxes used `object-fit: cover`, which is the right answer
   for a decorative image and the wrong one for a product photo. A supplier's
   shot of a drum, a pack or a label is the specification — the pack size, the
   grade and the batch number are printed on it. `cover` fills the box by
   cutting whatever does not fit, so a phone photo in portrait (3:4) inside a
   landscape box (4:3) showed barely half its height. The first supplier to
   upload a portrait photo reported exactly that: "its not the complete image,
   its just half of the image".

   So: `contain`, on a light mat, which keeps the grid and row heights uniform
   and guarantees the buyer sees the whole photo. Company logos were already
   `contain` for the same reason — this brings the product photos in line.

   `tools/smoke/photos.js` lints this file for a `cover` on any of these
   selectors, because the realistic regression is a new photo box written by
   copy-paste from an older rule.
   ------------------------------------------------------------------------ */
.image-tile {
  margin: 0; border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; background: var(--surface-alt);
}
.image-tile img { display: block; width: 100%; height: 120px; object-fit: contain; }
.image-tile figcaption {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  padding: 7px 9px; border-top: 1px solid var(--line); background: var(--surface);
}
.image-tile figcaption span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.cell-thumb img {
  display: block; width: 46px; height: 46px; object-fit: contain;
  background: var(--bg);
  border-radius: var(--radius-sm); border: 1px solid var(--line);
}
.thumb-empty { color: var(--faint); }

.inline-num {
  width: 66px; padding: 5px 7px; border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm); font-family: inherit; font-size: .84rem;
}

/* ------------------------------------------------- supplier listing detail */
.tag-supplier {
  background: var(--brand-light); color: var(--brand-dark); border-color: #c9e5e9;
  border-bottom-left-radius: 0; border-bottom-right-radius: 0;
}
.product-card.is-supplier { border-top: 3px solid var(--brand); }

.item-gallery { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.item-gallery img {
  display: block; width: 100%; height: 190px; object-fit: contain;
  border-radius: var(--radius); border: 1px solid var(--line); background: var(--surface-alt);
}
.item-gallery img:first-child { grid-column: 1 / -1; height: 320px; }
.item-gallery-empty {
  display: flex; align-items: center; justify-content: center;
  height: 200px; border: 1px dashed var(--line-strong); border-radius: var(--radius);
  color: var(--faint); font-size: .88rem;
}

/* --------------------------------------------------------------- admin tables */
.table-wrap table.data td.wrap { white-space: normal; min-width: 220px; }
.card-head .row { gap: 8px; }

/* ------------------------------------------------------------------ RTL
   Arabic flips the whole document. Grid tracks follow the writing direction
   automatically, so only the pieces that assume left-to-right need a rule. */
[dir="rtl"] .field .hint,
[dir="rtl"] .footer-disclaimer { text-align: right; }
[dir="rtl"] .btn kbd { margin-left: 0; margin-right: 8px; }
[dir="rtl"] .image-tile figcaption { flex-direction: row-reverse; }
[dir="rtl"] .dash-head { flex-direction: row-reverse; }
[dir="rtl"] .card-head { flex-direction: row-reverse; }
[dir="rtl"] .notice { flex-direction: row-reverse; }

/* --------------------------------------------------------- smaller screens */
@media (max-width: 1080px) {
  .lang-switch { display: none; }
  .header-actions .account-slot .btn-ghost { display: none; }
  .mobile-nav .lang-switch { display: inline-flex; }
}
@media (max-width: 900px) {
  .role-cards { grid-template-columns: 1fr; }
  .item-gallery { grid-template-columns: minmax(0, 1fr); }
  .item-gallery img:first-child { height: 240px; }
  /* Keep sign in / join reachable: the header copy gives way, the mobile
     menu copy takes over. */
  .header-actions .account-slot { display: none; }
}
@media (max-width: 640px) {
  .auth-card { padding: 20px; }
  .auth-wrap { max-width: none; }
  .image-grid { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); }
  .image-tile img { height: 96px; }
}

/* Language picker and account links inside the collapsed mobile menu. */
.mobile-nav-foot {
  display: flex; align-items: center; gap: 12px; padding: 14px 4px 2px;
}
.mobile-nav-foot .lang-switch { display: inline-flex; }
.mobile-nav-foot .lang-switch select { max-width: none; }

/* ==========================================================================
   Header layout
   --------------------------------------------------------------------------
   The header used to overflow the viewport: search had a hard min-width of
   240px, so it refused to shrink while the nav, language picker, two account
   buttons and the CTA all competed for the same row. Nothing here uses a
   fixed min-width — every element shrinks or hands off to the mobile menu,
   so the header fits from 320px to ultrawide.
   ========================================================================== */

.header-inner { flex-wrap: nowrap; min-width: 0; gap: 14px; }
.header-actions { min-width: 0; gap: 8px; }
/* flex-shrink: 0 — with min-width:0 alone the nav used to shrink below its
   content width and the nowrap links spilled over the search box ("Sell With
   Us" half-hidden at 1920px). The search trigger and account name give way
   instead; the nav is hidden entirely at ≤1360px. */
.main-nav { min-width: 0; flex-shrink: 0; }

/* The labelled search box can NEVER fit next to the 4-item nav inside the
   1200px container (116+510+216+~360 > 1160) — it used to shrink to a "Se…"
   stub at every desktop width, which read as broken. So the base header ships
   the icon + Ctrl K hint, and the label only returns once the nav has moved
   behind the hamburger (≤1360px block below). */
.search-trigger {
  min-width: 0;
  width: auto; padding: 9px 11px;
}
.st-label { display: none; }
.st-kbd { margin-left: 2px; }

/* Two labels on the CTA so the action survives a narrow header. */
.cta-post .cta-short { display: none; }

/* Ultrawide: everything on show. */

@media (max-width: 1560px) {
  /* The keyboard hint is the least valuable item in the row. */
  .st-kbd { display: none; }
}

@media (max-width: 1400px) {
  /* The CTA drops to its short label. */
  .cta-post .cta-full { display: none; }
  .cta-post .cta-short { display: inline; }
  .main-nav a { padding: 8px 9px; font-size: .9rem; }
  .header-inner { gap: 12px; }
}

@media (max-width: 1240px) {
  /* The nav moves behind the hamburger; the mobile menu already carries it. */
  .main-nav { display: none; }
  .nav-toggle { display: inline-flex; }
  .account-menu .account-name { max-width: 96px; }
}

@media (max-width: 1080px) {
  /* Language picker moves into the mobile menu (existing rule hides it).
     Search keeps the labelled width from the ≤1360 block — the nav is gone
     from 1360 down, so there is room; no extra override needed. */
}

@media (max-width: 900px) {
  .st-label, .st-kbd { display: none; }
  .search-trigger { width: auto; padding: 9px 11px; }
}

@media (max-width: 640px) {
  /* The CTA is the first thing to go: it is in the mobile menu. */
  .cta-post { display: none; }
  .header-inner { gap: 10px; }
  .logo { font-size: 1.06rem; }
  .free-band span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}

/* The account slot exists twice — header row and mobile menu foot. The rules
   above are scoped so that only the header copy can be hidden; the mobile copy
   is what a signed-in visitor on a phone uses to reach their dashboard. */
@media (max-width: 900px) {
  .mobile-nav-foot .account-slot { display: flex; }
  .mobile-nav-foot { flex-wrap: wrap; justify-content: space-between; gap: 10px; }
}

/* ------------------------------------------------- email confirmation page */
.confirm-card { text-align: center; padding: 38px 30px; }
.confirm-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 54px; height: 54px; margin: 0 auto 14px;
  border-radius: 50%; font-size: 1.5rem; line-height: 1;
}
.confirm-icon.is-wait { background: var(--bg); color: var(--muted); }
.confirm-icon.is-ok { background: var(--accent-light); color: var(--accent); }
.confirm-icon.is-err { background: var(--danger-light); color: var(--danger); }
.confirm-card h1 { font-size: 1.45rem; margin-bottom: 8px; }
.confirm-card .form-actions { justify-content: center; }
.confirm-card .form-actions .btn { min-width: 168px; }

/* A resend control shown inline under the sign-in form when Supabase reports
   that the address was never confirmed. */
.resend-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  margin-top: 10px; padding: 12px 14px;
  border: 1px solid var(--warn-line); background: var(--warn-light);
  border-radius: var(--radius);
}
.resend-bar p { margin: 0; font-size: .86rem; color: var(--warn-ink, var(--ink)); }

/* ==========================================================================
   Companies, earned badges and the category directory
   --------------------------------------------------------------------------
   Added with the company pages. The badge vocabulary is the trust signal the
   whole platform rests on — Model v2.0 §7, badges are earned by document and
   never sold — so it is styled to read as a credential, not as an advert.
   ========================================================================== */

/* ---------- Badge tones and sizes ---------- */
.badge svg { flex-shrink: 0; }
.badge-brand  { background: var(--brand-light);  color: var(--brand-dark); border-color: #c9e5e9; }
.badge-accent { background: var(--accent-light); color: var(--accent);     border-color: #cfe9dd; }

.badge-lg { font-size: .78rem; padding: 5px 11px; font-weight: 700; }

.badge-row { display: inline-flex; flex-wrap: wrap; gap: 6px; }

/* The console toggle. Reads as a chip when off, as an earned badge when on. */
.badge-chip {
  font-family: inherit; font-size: .72rem; font-weight: 650; cursor: pointer;
  padding: 3px 9px; border-radius: 999px; border: 1px dashed var(--line-strong);
  background: transparent; color: var(--faint); transition: all .12s;
}
.badge-chip:hover { border-color: var(--brand); color: var(--brand); border-style: solid; }
.badge-chip.on { border-style: solid; }
.badge-chip.is-busy { opacity: .5; pointer-events: none; }

.badge-legend { list-style: none; margin: 0; padding: 0; }
.badge-legend li { display: flex; gap: 10px; align-items: flex-start; padding: 9px 0; border-top: 1px solid var(--line); }
.badge-legend li:first-child { border-top: 0; }
.badge-legend li > span:last-child { font-size: .82rem; color: var(--muted); line-height: 1.5; }

/* ---------- Product cards carrying a company and its badges ---------- */
.product-card .pc-badges { margin: 2px 0 0; }
.product-card .pc-company {
  font-size: .78rem; font-weight: 650; color: var(--brand-dark);
  margin: 2px 0 0; padding-top: 6px; border-top: 1px dashed var(--line);
}

.h1-grade { font-size: .62em; font-weight: 600; color: var(--muted); letter-spacing: .01em; }

/* ---------- Company logo ---------- */
.company-logo {
  width: 44px; height: 44px; border-radius: var(--radius-sm); object-fit: contain;
  background: var(--surface); border: 1px solid var(--line); flex-shrink: 0;
}
.company-logo-lg { width: 72px; height: 72px; }
.company-logo-fallback {
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .95rem; font-weight: 750; letter-spacing: .02em;
  color: var(--brand-dark); background: var(--brand-light); border-color: #c9e5e9;
}

/* ---------- Company card (on a listing page) ---------- */
.company-card-head { display: flex; gap: 12px; align-items: flex-start; }
.company-card-head h3 { font-size: 1.02rem; }
.company-card-head h3 a { color: inherit; text-decoration: none; }
.company-card-head h3 a:hover { color: var(--brand); }

/* ---------- Company page header ---------- */
.company-hero-inner {
  display: flex; gap: 20px; align-items: flex-start; flex-wrap: wrap;
  justify-content: space-between; margin-top: 14px;
}
/* Identity block: logo beside a stacked text column (name → tagline →
   meta → badges), CTA pinned right. */
.company-hero-id { display: flex; gap: 18px; align-items: flex-start; flex: 1; min-width: 0; }
.company-hero-text { min-width: 0; }
.company-hero-text h1 { margin-bottom: 2px; }
.company-hero-inner .company-hero-logo {
  width: 84px; height: 84px; border-radius: var(--radius); object-fit: contain;
  background: var(--surface); border: 1px solid var(--line); flex-shrink: 0;
}
.company-hero-cta { flex-shrink: 0; min-width: 220px; }
.company-meta { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-top: 8px; }
.company-meta-item { font-size: .84rem; color: var(--muted); }
.company-meta-item + .company-meta-item::before { content: "·"; margin-right: 14px; color: var(--faint); }

@media (max-width: 760px) {
  .company-hero-cta { min-width: 0; width: 100%; }
  .company-hero-id { gap: 14px; }
  .company-hero-inner .company-hero-logo { width: 60px; height: 60px; }
}

/* ---------- Category directory ---------- */
/* No page per category: most hold one or two products, and 43 thin pages would
   suppress the whole site. These tiles filter the existing browse page. */
.cat-group + .cat-group { margin-top: 22px; }
.cat-group-head {
  font-size: .78rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); margin: 0 0 10px;
}
.cat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(228px, 1fr)); gap: 10px; }
.cat-tile {
  display: flex; flex-direction: column; gap: 3px; padding: 12px 14px;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface-alt);
  text-decoration: none; transition: border-color .12s, background .12s, transform .12s;
}
.cat-tile:hover { border-color: var(--brand); background: var(--surface); transform: translateY(-1px); }
.cat-tile strong { font-size: .89rem; color: var(--ink); }
.cat-tile .cat-ic { font-size: 1rem; margin-right: 7px; }
.cat-tile .cat-blurb { font-size: .78rem; color: var(--muted); line-height: 1.45; }

/* Homepage category index. Compact pills, not the full blurbs — 43 tiles with
   descriptions would bury the product grids. Each pill is an internal link
   into a filtered browse. */
.cat-pill-group + .cat-pill-group { margin-top: 26px; }
.cat-pill-head {
  font-size: .78rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); margin: 0 0 12px; text-align: center;
}
/* Icon cards, per the approved mockup: centred emoji over the name, hover
   lift with the teal glow. Cards stay linkable two-line tiles at 43 items. */
.cat-card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
.cat-card {
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
  text-align: center; gap: 5px; padding: 16px 10px 14px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  text-decoration: none;
  transition: border-color .15s, box-shadow .15s, transform .15s;
}
.cat-card:hover {
  text-decoration: none; border-color: var(--brand);
  box-shadow: 0 4px 14px rgba(14, 116, 144, .12); transform: translateY(-2px);
}
.cat-card.is-b:hover { border-color: var(--accent); box-shadow: 0 4px 14px rgba(15, 95, 69, .10); }
.cat-card .cat-ic { font-size: 26px; line-height: 1; margin-bottom: 2px; }
.cat-card strong {
  font-size: .84rem; font-weight: 600; color: var(--ink); line-height: 1.35;
}
.cat-card:hover strong { color: var(--brand-dark); }
.cat-card.is-b:hover strong { color: #0f5f45; }

.pill-list a.badge { text-decoration: none; }
.pill-list a.badge:hover { border-color: var(--brand); color: var(--brand); }

/* ---------- Small shared bits ---------- */
.steps-list { margin: 0; padding-left: 18px; }
.steps-list li { font-size: .87rem; color: var(--muted); margin-bottom: 8px; line-height: 1.55; }
.steps-list li:last-child { margin-bottom: 0; }

.check-row-wrap { display: flex; flex-wrap: wrap; gap: 6px 18px; }
.check-row-wrap .check-row { margin-bottom: 0; }

.card-mb { margin-bottom: 18px; }

/* Entries in the supplier's enquiry inbox are cards, and a card inside a card
   must not double the border. */
.stack > .card + .card { margin-top: 14px; }

/* ==========================================================================
   Product card, reworked
   --------------------------------------------------------------------------
   The card used to be one anchor, which made "contact this supplier from the
   list" impossible — a button cannot live inside a link. It is now a container
   with an inner link over the thumb and title, and an actions row below it.
   ========================================================================== */

.product-card .pc-link {
  display: flex; flex-direction: column; gap: 8px;
  color: inherit; text-decoration: none;
}
.product-card .pc-link:hover { text-decoration: none; }
.product-card h3 { margin: 0; font-size: 1.02rem; line-height: 1.35; }

/* Full-bleed thumb: bleeds over the card padding to the card edges. The card
   already clips with overflow:hidden, so no extra radius is needed. 118px —
   the old 148px turned photo-less cards into walls of blank colour. */
.pc-thumb {
  display: block; height: 118px; margin: -17px -17px 0; padding: 8px 10px;
  background: var(--bg); overflow: hidden;
}
/* contain, not cover — see "Product photos are shown WHOLE". */
.pc-thumb img { display: block; width: 100%; height: 100%; object-fit: contain; }
.pc-thumb-blank {
  display: flex; align-items: center; justify-content: center; text-align: center;
  padding: 0 14px;
  background: linear-gradient(135deg, #edf5f6 0%, #f7fbfa 60%, #fdfdfb 100%);
}
.pc-thumb-blank > span {
  font-size: .64rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--brand); opacity: .55; line-height: 1.4;
}

.pc-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.pc-tags .wedge-tag { align-self: auto; }

/* Two lines of summary, then stop — three left cards unevenly tall. */
.pc-sum {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; min-height: 2.6em;
}

/* One primary action per card, full width. The thumb and title are the link
   to the listing; this button is the enquiry ("Contact supplier" on supplier
   listings, "Request quotation" on catalog products). */
.pc-actions {
  margin-top: 2px; padding-top: 10px; border-top: 1px solid var(--line);
}
.pc-actions .btn { width: 100%; padding: 9px 12px; font-size: .84rem; }
.pc-actions .btn-primary > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The price, when the supplier states one. */
.price-card .price-big {
  font-size: 1.55rem; font-weight: 750; letter-spacing: -.01em;
  color: var(--ink); margin: 4px 0 8px; line-height: 1.2;
}

/* ==========================================================================
   Header, second pass
   --------------------------------------------------------------------------
   Overflow came back between 1240 and 1400: the nav stayed on the row while
   search, the language picker, two account buttons and the CTA competed for
   what was left. Collapse one step earlier and let the header grow rather
   than clip, so nothing can overlap at any width.
   ========================================================================== */

.header-inner { height: auto; min-height: var(--header-h); }

@media (max-width: 1360px) {
  /* The 5-item nav is the widest thing on the row after search. Moving it
     behind the hamburger at 1360 (was 1240) is what keeps 1366×768 laptops —
     the most common screen there is — out of the squeeze. With the nav gone
     there is finally room for the labelled search box again. */
  .main-nav { display: none; }
  .nav-toggle { display: inline-flex; }
  .account-menu .account-name { max-width: 96px; }
  .st-label { display: inline; }
  .search-trigger { width: clamp(170px, 20vw, 260px); padding: 9px 14px; }
}

.account-name {
  max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ==========================================================================
   Marketplace result list — /search/ (TradeIndia-style rows, our palette)
   ========================================================================== */
.results-list {
  display: flex; flex-direction: column; gap: 14px;
}
.result-card {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr) 210px;
  gap: 16px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px;
  position: relative;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.result-card:hover {
  border-color: var(--line-strong);
  box-shadow: var(--shadow-sm);
}
.result-card.is-supplier { border-left: 3px solid var(--brand); }
.result-card.is-b { border-left-color: #e0a82e; }
/* A promoted row in the results list. Same disclosure as the grid card — warm
   surface, amber edge — but the left rail is left to the two rules above: that
   rail is how a supplier listing is marked, and a promoted row is the row that
   most needs that label, not the one that should lose it. Written as compound
   selectors rather than relying on which rule comes last. */
.result-card.is-featured { background: #fffbf1; border-color: #f2e0b4; }
.result-card.is-featured.is-supplier { border-left-color: var(--brand); }
.result-card.is-featured.is-b { border-left-color: #e0a82e; }

.rc-thumb {
  display: block; width: 200px; height: 150px; padding: 6px;
  border-radius: var(--radius-sm);
  overflow: hidden; background: var(--bg);
  position: relative;
}
/* contain, not cover — see "Product photos are shown WHOLE". This is where the
   cropping was reported: a 960x1282 portrait photo in a 200x150 box is a 56%
   slice of the picture. */
.rc-thumb img { display: block; width: 100%; height: 100%; object-fit: contain; }
.rc-photo-count {
  position: absolute; right: 6px; bottom: 6px;
  padding: 2px 8px; border-radius: 999px;
  background: rgba(11, 31, 42, 0.72); color: #fff;
  font-size: .68rem; font-weight: 650; letter-spacing: .02em;
}
.rc-thumb-blank {
  display: flex; align-items: center; justify-content: center;
  text-align: center; padding: 8px;
  background: var(--brand-light); color: var(--brand-dark);
  font-size: .8rem; font-weight: 650; line-height: 1.35;
}

.rc-main { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.rc-title { margin: 0; font-size: 1.06rem; line-height: 1.35; }
.rc-title a { color: var(--ink); }
.rc-title a:hover { color: var(--brand); text-decoration: underline; }
.rc-chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.rc-chip {
  display: inline-block; padding: 2px 9px;
  font-size: .74rem; font-weight: 600; color: var(--body);
  background: var(--bg); border: 1px solid var(--line);
  border-radius: 999px;
}
.rc-sum {
  margin: 0; font-size: .855rem; color: var(--muted); line-height: 1.5;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.rc-supplier {
  margin-top: auto; display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding-top: 6px; border-top: 1px dashed var(--line);
}
.rc-co {
  font-size: .86rem; font-weight: 700; color: var(--brand-dark);
}
.rc-co:hover { text-decoration: underline; }
.rc-badges { display: inline-flex; flex-wrap: wrap; gap: 6px; }

.rc-side {
  display: flex; flex-direction: column; align-items: stretch; gap: 8px;
  padding-left: 16px; border-left: 1px solid var(--line);
  text-align: right;
}
.rc-price {
  margin: 0; font-size: 1.05rem; font-weight: 750; color: var(--ink);
  word-break: break-word;
}
.rc-moq { margin: 0; font-size: .78rem; color: var(--muted); }
.rc-cta { margin-top: auto; }
.rc-cta .btn { width: 100%; padding: 9px 12px; font-size: .84rem; }
.rc-cta .btn-primary > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rc-view {
  display: block; font-size: .8rem; font-weight: 600; color: var(--brand);
  text-align: center;
}
.rc-view:hover { text-decoration: underline; }

@media (max-width: 900px) {
  .result-card { grid-template-columns: 150px minmax(0, 1fr); }
  .rc-thumb { width: 150px; height: 112px; }
  .rc-side {
    grid-column: 1 / -1;
    border-left: 0; border-top: 1px solid var(--line);
    padding-left: 0; padding-top: 10px;
    flex-direction: row; align-items: center; flex-wrap: wrap; gap: 10px 14px;
    text-align: left;
  }
  .rc-price { font-size: .98rem; }
  .rc-cta { margin: 0 0 0 auto; }
  .rc-cta .btn { width: auto; }
  .rc-view { display: none; }
}
@media (max-width: 560px) {
  .result-card { grid-template-columns: 110px minmax(0, 1fr); padding: 11px; }
  .rc-thumb { width: 110px; height: 84px; }
  .rc-title { font-size: .97rem; }
  .rc-cta { margin-left: 0; width: 100%; }
  .rc-cta .btn { width: 100%; }
}

/* ==========================================================================
   Item hero — product & listing detail pages (gallery left, price box right)
   ========================================================================== */
.item-hero {
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr) 300px;
  gap: 22px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 20px;
  margin: 18px 0 6px;
  /* The photo column does NOT stretch — see `.item-hero-media` below. It sizes
     itself from the photo's own aspect ratio. */
}
.item-hero-media {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg);
  /* The photo column is its OWN containing block, so the picture is sized by
     the column and never by how long the description beside it happens to be.
     Without this the media box stretched to the tallest column in the grid row:
     a 40-word blurb made a 900px-tall box, `object-fit: contain` letterboxed the
     photo inside it, and the hero looked like an image with two grey bands —
     which is exactly what "the image looks odd when the description is long"
     was. `align-self: start` stops the stretch; the caps below decide the size. */
  align-self: start;
  width: 100%;
}
.item-hero-main {
  display: block;
  width: 100%;
  /* A fixed box the photo is FITTED into, rather than one that grows with the
     neighbouring text.
     SQUARE, not 4/3. Measured against the live catalogue: the photos are square
     (500x500) or portrait (960x1282) and none is landscape, so a 4/3 box fitted
     every square photo with two vertical bars — the same "odd" look, rotated.
     A square box is the only fixed shape that wastes nothing on either. It is a
     box, not a rule about the photo: `contain` still shows the whole picture. */
  aspect-ratio: 1 / 1;
  height: auto;
  max-height: 420px;
  /* contain, not cover — see "Product photos are shown WHOLE". The photo is the
     largest copy of the picture on the site and the worst one to cut. */
  object-fit: contain;
  background: var(--bg);
}
.item-hero-thumbs {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.item-hero-thumb {
  width: 62px; height: 50px; padding: 0;
  border: 2px solid transparent;
  border-radius: var(--radius-sm);
  overflow: hidden; cursor: pointer;
  background: none; opacity: .72;
  transition: opacity .12s ease, border-color .12s ease;
}
.item-hero-thumb img { display: block; width: 100%; height: 100%; object-fit: contain; }
.item-hero-thumb:hover { opacity: 1; }
.item-hero-thumb.active { border-color: var(--brand); opacity: 1; }
.item-hero-blank {
  display: flex; align-items: center; justify-content: center;
  min-height: 200px; padding: 16px; text-align: center;
  background: linear-gradient(160deg, var(--brand-light), #f2fafb);
  color: var(--brand-dark);
  font-size: 1.05rem; font-weight: 700; line-height: 1.4;
}
.item-hero-info { min-width: 0; }
.item-hero-info h1 {
  margin: 2px 0 10px; font-size: 1.55rem; line-height: 1.25; letter-spacing: -.01em;
}
.item-hero-info .h1-grade { color: var(--muted); font-weight: 500; }
.item-hero-sum { margin: 12px 0 0; color: var(--body); font-size: .95rem; line-height: 1.55; }
.item-hero-badges { margin-top: 12px; }
.item-hero-desc { margin-top: 12px; font-size: .9rem; color: var(--body); }
.item-hero-desc p { margin: 0 0 .6em; }

/* A supplier description long enough to push the specification table off the
   screen is folded to about four lines behind a toggle. The fold is applied in
   the markup rather than on load, so a slow connection does not watch the hero
   jump, and the full text is always in the HTML: a crawler reads every word,
   and the <noscript> rule in the head cancels the fold for a visitor without
   JavaScript, who could otherwise not open it. app.js removes the fold
   altogether when the text turns out to fit inside it anyway.

   The height is five line boxes and the fade runs over the last one and a bit,
   which is deliberate. The description is a run of <p>s with a bottom margin,
   so the cut lands mid-line for all but the first block — a bare overflow:hidden
   would slice a row of glyphs in half, which reads as a rendering fault rather
   than as a fold. The ramp hides the cut: roughly four lines stay readable and
   the fifth fades, which is also the cue that there is more to read. */
.item-hero-desc[data-desc-clamped] {
  max-height: 8em;                /* five lines at the inherited 1.6 line-height */
  overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, #000 74%, transparent);
  mask-image: linear-gradient(180deg, #000 74%, transparent);
}

/* Emitted hidden and revealed by app.js only once it has measured that
   something was really cut off, so a description that fits never grows a
   button that does nothing. `[hidden]` is restated because the display rule
   below would otherwise win over the attribute. */
.desc-toggle {
  display: inline-flex; align-items: center; gap: 5px;
  margin-top: 7px; padding: 0; border: 0; background: none;
  color: var(--brand); font: inherit; font-size: .85rem; font-weight: 650;
  cursor: pointer;
}
.desc-toggle[hidden] { display: none; }
.desc-toggle:hover { text-decoration: underline; }
.desc-toggle .desc-toggle-less { display: none; }
.desc-toggle[aria-expanded="true"] .desc-toggle-more { display: none; }
.desc-toggle[aria-expanded="true"] .desc-toggle-less { display: inline; }
.desc-toggle-chev { font-size: .7rem; line-height: 1; transition: transform .15s ease; }
.desc-toggle[aria-expanded="true"] .desc-toggle-chev { transform: rotate(180deg); }

.item-hero-side { min-width: 0; }
.price-box {
  background: var(--surface-alt);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  padding: 16px;
  display: flex; flex-direction: column; gap: 10px;
  position: sticky; top: 76px;
}
.price-box .price-label {
  margin: 0; font-size: .72rem; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--brand-dark);
}
.price-box .price-big {
  margin: 0; font-size: 1.3rem; font-weight: 800; color: var(--ink); line-height: 1.25;
}
.price-box .price-note { margin: 0; font-size: .78rem; color: var(--muted); line-height: 1.5; }
.price-box-perks { margin: 2px 0 0; padding-top: 10px; border-top: 1px dashed var(--line); }
.price-box-perks li { display: flex; gap: 6px; align-items: baseline; }
.price-box-perks li::before { content: "✓"; color: var(--accent); font-weight: 700; }

.item-hero .notice { margin: 12px 0 0; }

@media (max-width: 1020px) {
  .item-hero { grid-template-columns: 240px minmax(0, 1fr); }
  /* No min-height any more: the photo's own aspect ratio decides its height at
     every width, so the hero is the same shape whatever the description does. */
  .item-hero-side { grid-column: 1 / -1; }
  .price-box { position: static; }
  .price-box .btn { width: auto; display: inline-block; }
  .price-box .btn-block { width: auto; }
}
@media (max-width: 640px) {
  .item-hero { grid-template-columns: 1fr; padding: 14px; }
  /* The photo is capped by the BODY's width and the box ratio — width: 100% on
     the image, aspect-ratio: 1/1 on the box. A max-height here would beat the
     ratio and start cropping a square photo, so there is deliberately none. */
  .item-hero-blank { min-height: 120px; }
  .item-hero-info h1 { font-size: 1.28rem; }
  .price-box .btn, .price-box .btn-block { width: 100%; display: block; }
}

/* ==========================================================================
   About-the-supplier section — full-width company panel on listing pages
   ========================================================================== */
.company-section-head {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 14px;
  background: var(--surface-alt);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.company-section-head .company-logo { width: 52px; height: 52px; }
.company-section-id { flex: 1 1 220px; min-width: 0; }
.company-section-id h3 { font-size: 1.08rem; }
.company-section-id h3 a { color: var(--ink); }
.company-section-id h3 a:hover { color: var(--brand); }
.company-section-trust { margin-left: auto; }
@media (max-width: 640px) {
  .company-section-trust { margin-left: 0; width: 100%; }
}
.company-facts { margin-top: 16px; grid-template-columns: 190px minmax(0, 1fr); }
.company-about { margin-top: 16px; font-size: .92rem; }
.company-section .pill-list { margin-top: 14px; }
.company-section .row { align-items: center; }

/* ==========================================================================
   Notification centre — bell in the header, panel, dashboard tab
   ========================================================================== */
.header-account { display: flex; align-items: center; gap: 6px; min-width: 0; }

.notif-bell {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex: 0 0 auto;
  padding: 0; cursor: pointer;
  background: transparent; color: var(--body);
  border: 1px solid transparent; border-radius: 999px;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.notif-bell:hover { background: var(--brand-light); color: var(--brand-dark); }
.notif-bell.is-open { background: var(--brand-light); color: var(--brand-dark); border-color: var(--line); }
.notif-bell svg { display: block; }

.notif-dot {
  position: absolute; top: -2px; right: -2px;
  min-width: 17px; height: 17px; padding: 0 4px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--danger); color: #fff;
  font-size: .66rem; font-weight: 800; line-height: 1;
  border-radius: 999px; border: 2px solid var(--surface);
  font-variant-numeric: tabular-nums;
}

/* The panel is appended to <body> so it is never clipped by the header's
   own overflow, and fixed-positioned under the header on the right. */
.notif-panel {
  position: fixed; z-index: 90;
  top: calc(var(--header-h) + 8px); right: 16px;
  width: min(380px, calc(100vw - 32px));
  max-height: min(460px, calc(100vh - var(--header-h) - 40px));
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
}
.notif-panel[hidden] { display: none; }

.notif-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 11px 14px;
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; background: var(--surface); z-index: 1;
}
.notif-head strong { font-size: .92rem; }

.notif-list { display: flex; flex-direction: column; }
.notif-item {
  display: flex; flex-direction: column; gap: 3px;
  width: 100%; text-align: left;
  padding: 11px 14px; cursor: pointer;
  background: transparent; border: 0; border-bottom: 1px solid var(--line);
  font: inherit; color: inherit;
  transition: background .12s ease;
}
.notif-item:last-child { border-bottom: 0; }
.notif-item:hover { background: var(--surface-alt); }
.notif-item.is-unread { background: var(--brand-light); }
.notif-item.is-unread:hover { background: #dcf0f3; }
.notif-item.is-unread .notif-title::before {
  content: ""; display: inline-block; width: 6px; height: 6px; margin-right: 6px;
  border-radius: 999px; background: var(--brand); vertical-align: middle;
}
.notif-title { font-size: .855rem; font-weight: 700; color: var(--ink); line-height: 1.35; }
.notif-body {
  font-size: .8rem; color: var(--muted); line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.notif-meta { font-size: .73rem; color: var(--faint); }
.notif-empty { margin: 0; padding: 22px 14px; text-align: center; font-size: .85rem; color: var(--muted); }
.notif-all {
  display: block; padding: 10px 14px; text-align: center;
  font-size: .82rem; font-weight: 650; color: var(--brand);
  border-top: 1px solid var(--line); background: var(--surface-alt);
  border-radius: 0 0 var(--radius) var(--radius);
}
.notif-all:hover { background: var(--brand-light); text-decoration: none; }

/* Dashboard → Notifications tab */
.notif-row {
  display: flex; gap: 12px; align-items: flex-start;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 13px 14px;
}
.notif-row.is-unread { border-left: 3px solid var(--brand); background: var(--surface-alt); }
.notif-kind {
  flex: 0 0 auto; width: 30px; height: 30px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--brand-light); border-radius: 999px;
  font-size: .95rem; line-height: 1;
}
.notif-body-wrap { flex: 1 1 auto; min-width: 0; }
.notif-text { color: var(--body); line-height: 1.5; white-space: pre-wrap; word-break: break-word; }

@media (max-width: 640px) {
  .notif-panel { top: 66px; right: 8px; left: 8px; width: auto; }
  .notif-dot { top: -3px; right: -3px; }
}

/* ==========================================================================
   Enquiry attachments — shared thread box on both dashboards
   ========================================================================== */
.attach-box {
  margin-top: 12px; padding: 12px;
  background: var(--surface-alt);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
}
.attach-head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
.attach-head strong { font-size: .85rem; }
.attach-head [data-attach-status] { flex: 1 1 auto; }
.attach-add { margin-left: auto; cursor: pointer; white-space: nowrap; }
.attach-add input[type="file"] { display: none; }
.attach-hint { margin: 6px 0 0; }

.attach-block + .attach-block { margin-top: 8px; }
.attach-block > strong { display: block; margin-bottom: 5px; color: var(--muted); font-weight: 650; }

.attach-grid {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-top: 8px;
}
.attach-item {
  position: relative; margin: 0;
  width: 92px; flex: 0 0 auto;
}
.attach-item img {
  display: block; width: 92px; height: 92px;
  /* contain — an attached photo is the buyer's own evidence of what they want,
     and a cropped preview of it is a worse answer than a letterboxed one. */
  object-fit: contain; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--bg);
  cursor: pointer;
}
.attach-item img[data-attach-url]:hover { border-color: var(--brand); }
.attach-item figcaption {
  margin-top: 3px; font-size: .68rem; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.attach-file {
  position: relative; display: inline-flex; align-items: center;
}
.attach-file .link-btn {
  display: inline-block; max-width: 220px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding: 6px 10px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-size: .8rem; color: var(--brand-dark);
}
.attach-file .link-btn:hover { border-color: var(--brand); background: var(--brand-light); }

.attach-x {
  position: absolute; top: -6px; right: -6px;
  width: 20px; height: 20px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--ink); color: #fff;
  border: 2px solid var(--surface); border-radius: 999px;
  font-size: .7rem; line-height: 1; cursor: pointer;
}
.attach-x:hover { background: var(--danger); }
.attach-item .attach-x { top: 2px; right: 2px; }

/* Unread count on the dashboard's Notifications tab. */
.tab-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 17px; height: 17px; margin-left: 6px; padding: 0 5px;
  background: var(--danger); color: #fff;
  font-size: .66rem; font-weight: 800; line-height: 1;
  border-radius: 999px; font-variant-numeric: tabular-nums;
}

/* An upload in flight: keep the tiles visible but stop double-clicks. */
.attach-box.is-busy { opacity: .7; pointer-events: none; }

/* Author display rules beat the UA's [hidden] rule, so the badge needs its
   own: otherwise a zero count still paints. */
.notif-dot[hidden] { display: none; }
