:root {
  --primary: #16305c;
  --primary-dark: #0a1730;
  --primary-mid: #24447a;
  --accent: #8a94a3;
  --accent-dark: #5c6577;
  /* Brand accent — the site's single blue. Was gold until the logo-blue
     rebrand, then briefly a lighter mid-blue accent alongside this navy;
     both were folded into one shade so the whole site reads as one blue,
     not two. The amber that remains in the admin is deliberate and semantic
     (pending/warning states), not decorative, so it was left alone. Ink is
     white because this token is only ever used as text sitting on the accent.
     */
  --brand-accent: #103a68;
  --brand-accent-ink: #ffffff;
  /* A lighter tint of the same navy — not a second colour — used only where
     text sits on the dark footer/navy panels. Solid navy-on-navy fails
     contrast there (~1.9:1); this tint clears 4.9:1 while staying the same hue. */
  --brand-accent-on-dark: #7089a4;

  /* The hero palette, promoted out of the .hero block so the rest of the page
     can share it. Section headings, eyebrows and body copy were previously
     drawing from a second set of navies and greys, so the same kind of text
     rendered in different colours depending on which section it sat in.
     .hero still declares these itself, so the admin colour pickers keep
     overriding the hero without disturbing anything else. */
  --hero-heading: #0a2748;
  --hero-accent: #103a68;
  --hero-cta: #103a68;
  --hero-cta-hover: #0a2748;
  --hero-silver: #878687;
  --hero-silver-dark: #5e5e5e;
  --hero-silver-light: #c8c9ca;
  --hero-body: #5a6472;
  --text: #12161d;
  --text-muted: #5c6470;
  --bg-light: #e7eaf0;
  --bg-page: #f5f6f8;
  --white: #ffffff;
  --border: #e1e4e9;
  --radius: 14px;
  /* Real height of the sticky header. Seeded here and re-measured by JS on load
     and resize, because the logo the owner uploads changes the header height —
     hardcoding it left every nav jump landing under the header. */
  --header-h: 91px;
  --ticker-h: clamp(32px, 5vh, 48px);
  --max-width: 1160px;
  --font-display: 'Century Gothic', 'Segoe UI Semibold', 'Segoe UI', ui-sans-serif, system-ui, sans-serif;
  --font-mono: 'Cascadia Code', 'Consolas', 'SFMono-Regular', ui-monospace, monospace;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; }

body {
  font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
  color: var(--text);
  line-height: 1.6;
  background: var(--bg-page);
}

h1, h2, h3, .logo-name { font-family: var(--font-display); }

section[id] { scroll-margin-top: var(--header-h); outline: 3px solid transparent; outline-offset: -3px; transition: outline-color 0.3s ease; }
section[id].preview-highlight-flash { outline-color: var(--brand-accent); }

/* Every non-hero primary-nav section gets a full-viewport-tall, vertically
   centred treatment (a floor, not a fixed height, so a short window shrinks
   the section to fit instead of leaving dead space at the bottom). Brands
   joined this list when the nav gained a Brands link, and Products joined it
   when its two bands (search header + results) were merged into one section
   — before that, Products used its own calc() estimating the header band's
   height, which could only ever be an approximation. #about/#services/
   #quality are gone from this list because those sections were removed
   outright.
   #hero is deliberately NOT in this list — it is a slider stage, not a
   centred block, and needs column flow with stretched children so the slide
   track fills the width. This rule's ID specificity would beat .hero's own
   flex settings. */
#faq, #contact, #brands, #products {
  /* svh, not vh — same reasoning as the hero below: on iOS vh is the LARGEST
     viewport (toolbars hidden), so a vh-sized section is taller than what the
     reader can actually see and leaves a band of dead space they have to
     scroll past. The vh line is the fallback for browsers without svh. */
  min-height: max(360px, calc(100vh - var(--header-h)));
  min-height: max(360px, calc(100svh - var(--header-h)));
  display: flex;
  align-items: center;
}
/* #faq and #contact each wrap everything in one child, so row (the flex
   default) versus column never mattered — align-items:center just centred
   that single child vertically. #brands does not: the hex watermark,
   .container and .brands-marquee are three separate children, and row-flow
   laid them out side by side — shrinking the heading to a 180px sliver and
   stretching the logo marquee to its full unrolled width. Column restores
   normal top-to-bottom stacking; justify-content does the vertical centring
   column-flow needs it for, and align-items:stretch keeps .container and
   .brands-marquee at full width the way block layout would (align-items:
   center, inherited from the rule above, would shrink them to content width
   instead). */
#brands {
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
}
/* Desktop keeps the full-viewport floor above — a wide screen has room to
   spare either way. On a phone the same floor held sixteen small logos open
   to 727px, 90% of a 375x812 screen, to show three of them at a time; the
   content here never came close to needing a full screen. Dropping just the
   floor (not the column/centred layout it sits on top of) lets the section
   shrink to whatever its own content actually needs — see the mobile block
   further down for the rest of what that content shrinks to. */
@media (max-width: 640px) {
  #brands { min-height: 0; }
}

/* Keyboard access: a visible focus ring everywhere, and a skip link that stays
   off-screen until tabbed to. */
:focus-visible { outline: 3px solid var(--brand-accent); outline-offset: 3px; border-radius: 4px; }
.skip-link {
  position: absolute; left: 12px; top: -60px; z-index: 400;
  background: var(--primary-dark); color: var(--white);
  padding: 10px 18px; border-radius: 0 0 8px 8px; font-weight: 600;
  transition: top 0.2s ease;
}
.skip-link:focus { top: 0; }

a { text-decoration: none; color: inherit; }
ul { list-style: none; }
img { max-width: 100%; display: block; }

.container {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 24px;
}

/* Header */
.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 24px;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  background: var(--white);
  z-index: 100;
}
.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}
.logo { display: flex; align-items: center; gap: 12px; font-weight: 700; font-size: 1.2rem; color: var(--hero-heading); font-family: var(--font-display); }
.logo img { height: 48px; width: auto; }
.logo-text { display: flex; flex-direction: column; line-height: 1.15; }
.logo-name { font-size: 1.15rem; font-weight: 800; letter-spacing: 0.02em; }
.logo-tagline { font-size: 0.65rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--hero-silver-dark); }
.nav-links { display: flex; align-items: center; gap: 4px; }
.nav-links > a, .nav-group-toggle {
  /* Display face and the shared navy, so the nav reads as part of the same
     system as the headings rather than defaulting to body text in near-black. */
  font-weight: 600; color: var(--hero-cta); font-family: var(--font-display); font-size: 0.97rem;
  padding: 7px 13px; border-radius: 30px;
  border: none; background: none; cursor: pointer;
  transition: color 0.2s ease, background 0.2s ease;
}
.nav-links > a:hover, .nav-group-toggle:hover { color: var(--primary); }
.nav-links > a.active, .nav-group-toggle.active { background: var(--brand-accent); color: var(--brand-accent-ink); font-weight: 600; }
.nav-links > a.active:hover, .nav-group-toggle.active:hover { color: var(--brand-accent-ink); }

/* "Company" dropdown */
.nav-group { position: relative; }
.nav-group-toggle { display: inline-flex; align-items: center; gap: 6px; }
.nav-caret { width: 13px; height: 13px; stroke: currentColor; fill: none; stroke-width: 2.4; transition: transform 0.2s ease; }
.nav-group.open .nav-caret { transform: rotate(180deg); }
.nav-dropdown {
  position: absolute; top: calc(100% + 10px); left: 50%;
  transform: translateX(-50%) translateY(-6px);
  min-width: 220px; padding: 8px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 16px 36px rgba(22,48,92,0.14);
  display: flex; flex-direction: column; gap: 2px;
  opacity: 0; visibility: hidden;
  transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s;
  z-index: 120;
}
.nav-group.open .nav-dropdown { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); }
.nav-dropdown a {
  padding: 9px 14px; border-radius: 8px; font-size: 0.92rem; font-weight: 500;
  color: var(--text); white-space: nowrap;
  transition: background 0.15s ease, color 0.15s ease;
}
.nav-dropdown a:hover { background: var(--bg-page); color: var(--primary); }
.nav-dropdown a.active { background: rgba(16,58,104,0.16); color: var(--primary-dark); font-weight: 700; }

/* Hamburger — only rendered below the desktop breakpoint, so this size only
   ever applies on mobile/tablet; 44px matches the touch-target floor the
   rest of the mobile UI (catalog filters, letter picker) already uses. */
.nav-toggle {
  display: none;
  width: 44px; height: 44px; flex-shrink: 0; border-radius: 10px;
  border: 1px solid var(--border); background: var(--white);
  cursor: pointer; padding: 0;
  flex-direction: column; align-items: center; justify-content: center; gap: 5px;
}
.nav-toggle-bar {
  display: block; width: 18px; height: 2px; border-radius: 2px;
  background: var(--primary-dark);
  transition: transform 0.25s ease, opacity 0.2s ease;
}
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Mobile drawer */
.mobile-nav { position: fixed; inset: 0; z-index: 250; }
.mobile-nav[hidden] { display: none; }
.mobile-nav-backdrop {
  position: absolute; inset: 0; background: rgba(6,11,24,0.5);
  opacity: 0; transition: opacity 0.28s ease;
}
.mobile-nav.is-open .mobile-nav-backdrop { opacity: 1; }
.mobile-nav-panel {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: min(320px, 84vw);
  background: var(--white);
  padding: 26px 22px;
  display: flex; flex-direction: column; gap: 2px;
  overflow-y: auto;
  box-shadow: -12px 0 40px rgba(6,11,24,0.24);
  transform: translateX(100%);
  transition: transform 0.32s cubic-bezier(0.22, 0.8, 0.3, 1);
}
.mobile-nav.is-open .mobile-nav-panel { transform: translateX(0); }
.mobile-nav-close {
  align-self: flex-end;
  width: 36px; height: 36px; border-radius: 50%; margin-bottom: 10px;
  border: none; background: var(--bg-light); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.mobile-nav-close svg { width: 15px; height: 15px; stroke: var(--text); fill: none; stroke-width: 2.2; }
.mobile-nav-panel > a {
  padding: 12px 14px; border-radius: 10px;
  /* Same display face and navy as the desktop nav — this is the same
     navigation, just in a drawer. */
  font-weight: 600; color: var(--hero-cta); font-family: var(--font-display);
  transition: background 0.15s ease, color 0.15s ease;
}
.mobile-nav-panel > a:hover { background: var(--bg-page); color: var(--primary); }
.mobile-nav-panel > a.active { background: var(--brand-accent); color: var(--brand-accent-ink); }
.mobile-nav-label {
  font-family: var(--font-mono); font-size: 0.64rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text-muted);
  margin: 16px 0 4px; padding-left: 14px;
}


@media (prefers-reduced-motion: reduce) {
  .mobile-nav-panel, .mobile-nav-backdrop, .nav-dropdown, .nav-caret, .nav-toggle-bar { transition: none; }
}
.btn {
  display: inline-block;
  padding: 12px 26px;
  border-radius: 6px;
  font-weight: 600;
  transition: 0.2s;
  border: 2px solid transparent;
  /* A <button> doesn't inherit the page font/line-height the way an <a> does,
     so without this reset a button-based .btn renders visibly smaller than
     an anchor-based one sitting right next to it in the same row. */
  font-family: inherit;
  font-size: 1rem;
  line-height: 1.2;
  box-sizing: border-box;
  cursor: pointer;
}
.btn-primary { background: var(--primary); color: var(--white); }
.btn-primary:hover { background: var(--primary-dark); }
.btn-outline { border-color: var(--primary); color: var(--primary); }
.btn-outline:hover { background: var(--primary); color: var(--white); }

/* Hero — sized to always fill the viewport below the header (so landing on Home,
   or nav-jumping back to it, never leaves the next section peeking in at the
   bottom) while staying collapsible on short windows. min-height (a floor), not
   height, so it can still grow on a phone where wrapped copy genuinely needs
   more room than the screen offers. Every internal spacing/font value below is
   clamp()'d against vh/vw instead of stepped at a few fixed breakpoints, so the
   whole hero — including the ticker pinned to its bottom edge — scales
   continuously with the window instead of jumping between fixed states. */
/* The hero runs on a light blue/white/silver field taken from the logo, while
   every other section on the page stays navy. Each colour below reads from a
   custom property that index.php sets inline from the admin settings, with the
   finalised value as the fallback — so the section still renders correctly if
   the database has no hero_* rows yet (a fresh install, or an upgrade that has
   not saved settings once). Never hardcode these colours further down; change
   the fallback here and the admin default in settings.php together. */
.hero {
  --hero-bg-from: #eef2f7;
  --hero-bg-mid: #f7f9fb;
  --hero-bg-to: #ffffff;
  --hero-heading: #0a2748;
  --hero-accent: #103a68;
  /* The logo's own navy, which is slightly brighter and more azure than the
     site-wide --primary (#16305c). Scoped to the hero so the rest of the page
     keeps its existing navy untouched. */
  --hero-cta: #103a68;
  --hero-cta-hover: #0a2748;
  --hero-silver: #878687;
  --hero-silver-dark: #5e5e5e;
  --hero-silver-light: #c8c9ca;
  --hero-body: #5a6472;

  /* Aliases for the slider CSS further down, which was authored against the
     demo's shorter variable names. Pointing them at the --hero-* values rather
     than hardcoding hexes keeps the whole slider — buttons, dots, arrows and
     every SVG illustration — driven by the admin colour pickers. Without these
     the slider renders with transparent fills: an undefined custom property
     resolves to nothing, it does not fall back. */
  --logo-navy: var(--hero-cta);
  --logo-navy-deep: var(--hero-cta-hover);
  --accent: var(--hero-accent);
  --silver: var(--hero-silver);
  --silver-dark: var(--hero-silver-dark);
  --silver-light: var(--hero-silver-light);

  position: relative;
  background: radial-gradient(circle at 78% 14%, var(--hero-bg-from) 0%, var(--hero-bg-mid) 42%, var(--hero-bg-to) 100%);
  color: var(--text);
  overflow: hidden;
  /* svh, not vh. On a phone vh is the LARGEST viewport, so a 100vh hero sits
     partly behind the browser's own toolbar until the reader scrolls; svh is
     the smallest stable height, which is what actually fits on screen. The vh
     line above it is the fallback for browsers without svh. */
  min-height: max(520px, calc(100vh - var(--header-h)));
  min-height: max(520px, calc(100svh - var(--header-h)));
  /* A column stage: the slides take the free space and the controls sit under
     them. The slides carry their own padding, so the hero itself has none. */
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: 0;
}
/* Reserve room for the ticker band pinned to the hero's bottom edge so the hero
   copy is never sitting underneath it. */
.hero.has-ticker { padding-bottom: var(--ticker-h); }
/* #hero also matches the shared "#hero, #about, #features, ..." rule earlier in
   this file, whose ID selector otherwise outranks .hero's own min-height. */
#hero.hero {
  min-height: max(520px, calc(100vh - var(--header-h)));
  min-height: max(520px, calc(100svh - var(--header-h)));
}
.hero-lattice { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0.55; z-index: 0; }
.hero .hero-lattice { opacity: 0.62; }
.hero-formulas { position: absolute; inset: 0; pointer-events: none; z-index: 0; font-family: var(--font-mono); color: rgba(255,255,255,0.08); font-weight: 600; }
.hero-formulas span { position: absolute; white-space: nowrap; }
/* Watermarks on the light hero. All three business lines share the silver so
   the field stays one material — weight and letter-spacing carry the
   distinction, not colour, which is what keeps the palette to blue + silver. */
.hero .hero-formulas { color: rgba(94,94,94,0.11); }
.hero .hero-formulas span[data-family="nutra"] { font-weight: 500; letter-spacing: 0.04em; }
.hero .hero-formulas span[data-family="api"] { color: rgba(16,58,104,0.09); font-weight: 700; letter-spacing: 0.08em; }
.hero-content { position: relative; z-index: 2; text-align: center; margin: 0 auto; }
.eyebrow {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 18px;
}
/* Brushed-silver rule, matching the hero. It was a flat blue bar here, which
   made the same eyebrow look like two different components depending on the
   section. Width stays 24px because the reveal animation animates to it. */
.eyebrow::before { content: ""; width: 24px; height: 2px; border-radius: 2px; background: linear-gradient(90deg, var(--hero-silver-light), var(--hero-silver), var(--hero-accent)); }
/* Left-aligned: every slide is a .slide-split whose text column is left-aligned,
   so a centred eyebrow floated toward the middle of the column and read as
   misaligned against the headline beneath it. */
.hero .eyebrow { justify-content: flex-start; color: var(--hero-silver-dark); margin-bottom: clamp(4px, 2vh, 18px); }
/* Brushed-metal rule, echoing the silver S in the logo. Slightly wider and
   thicker than the shared 24x1 rule so it still registers on a light field. */
.hero .eyebrow::before {
  width: 34px; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--hero-silver-light), var(--hero-silver), var(--hero-accent));
}
/* Weighted toward vh (not vw) on purpose — a wide-but-short window (a laptop's
   full-width, half-height browser pane) needs this to shrink on HEIGHT, not
   just width, or the heading stays large enough to push the ticker off screen
   even though there's plenty of horizontal room. */
.hero h1 {
  font-size: clamp(1.4rem, 1vw + 3.6vh, 3.2rem);
  color: var(--hero-heading);
  max-width: 900px;
  margin: 0 auto clamp(6px, 2vh, 20px);
  font-weight: 800;
  text-wrap: balance;
}
/* Optional emphasis on one word. The colour comes from the highlight setting;
   the underline is what actually makes it read as emphasis, because the accent
   blue only sits ~2.25:1 against the heading navy and is easy to miss on its
   own. Turning the highlight off in admin removes the span entirely. */
.hero h1 .hero-hl { position: relative; }
.hero h1 .hero-hl::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -0.1em;
  height: 0.07em; border-radius: 2px;
  background: linear-gradient(90deg, transparent, currentColor 18%, currentColor 82%, transparent);
  opacity: 0.85;
}
.hero p {
  max-width: 700px;
  margin: 0 auto clamp(10px, 3.5vh, 34px);
  color: var(--hero-body);
  font-size: clamp(0.85rem, 0.3vw + 1vh, 1.05rem);
}
.hero-actions { display: flex; gap: 16px; justify-content: center; flex-wrap: wrap; }
/* Navy fill is the loudest thing in the hero, which is what a primary CTA on a
   light field should be. */
.hero .btn-primary { background: var(--hero-cta); color: var(--white); }
.hero .btn-primary:hover { background: var(--hero-cta-hover); }
/* Silver border gives the secondary action its own identity instead of a second
   navy outline competing with the primary. */
.hero .btn-outline { border-color: var(--hero-silver); color: var(--hero-cta); background: rgba(255,255,255,0.5); }
.hero .btn-outline:hover { border-color: var(--hero-cta); background: var(--hero-cta); color: var(--white); }

/* Hero stats — inline within the hero, not separate white cards */
.hero-stats {
  display: flex;
  justify-content: center;
  gap: clamp(10px, 3vh, 48px) clamp(20px, 4vw, 48px);
  margin-top: clamp(6px, 4vh, 36px);
  padding-top: clamp(6px, 2vh, 22px);
  /* Fades out at both ends so it reads as a divider, not a table rule.
     border-image needs the border-style set for the gradient to paint. */
  border-top: 1px solid transparent;
  border-image: linear-gradient(90deg, transparent, var(--hero-silver-light), var(--hero-silver), var(--hero-silver-light), transparent) 1;
}
.hero-stat { text-align: left; }
.hero-stat .num { font-family: var(--font-mono); font-size: clamp(1.2rem, 0.5vw + 1.8vh, 1.9rem); font-weight: 800; color: var(--hero-accent); font-variant-numeric: tabular-nums; }
.hero-stat .label { color: var(--hero-silver-dark); margin-top: 4px; font-size: clamp(0.72rem, 0.6vh + 0.5rem, 0.85rem); }

/* Capability ticker — seamless marquee band pinned to the hero's bottom edge.
   Sitting inside the hero (rather than as a sibling below it) keeps it on screen
   at first paint and stops a nav jump from scrolling straight past it. */
.capability-ticker {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 3;
  height: var(--ticker-h);
  display: flex;
  align-items: center;
  /* Light scrim, matched to the hero's own background rather than the old
     near-black. The edge fades below must stay the same colour as the hero's
     gradient end or the strip shows a visible seam at both ends. */
  background: rgba(255, 255, 255, 0.78);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border-top: 1px solid var(--hero-silver-light, #c8c9ca);
  overflow: hidden;
}
/* Fades the strip out at both edges so items enter and leave softly */
.capability-ticker::before,
.capability-ticker::after {
  content: ''; position: absolute; top: 0; bottom: 0; width: 90px; z-index: 1; pointer-events: none;
}
.capability-ticker::before { left: 0; background: linear-gradient(90deg, var(--hero-bg-to, #ffffff), transparent); }
.capability-ticker::after { right: 0; background: linear-gradient(270deg, var(--hero-bg-to, #ffffff), transparent); }
.capability-track {
  display: flex;
  width: max-content;
  animation: tickerScroll 38s linear infinite;
}
.capability-ticker:hover .capability-track { animation-play-state: paused; }
.capability-set { display: flex; align-items: center; }
.capability-set li {
  display: inline-flex; align-items: center; gap: 12px;
  padding: 0 30px;
  font-family: var(--font-mono);
  font-size: 0.76rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--hero-cta, var(--primary)); white-space: nowrap;
}
.capability-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--hero-accent, var(--brand-accent)); flex-shrink: 0; }
/* Each set is exactly half the track, so -50% lands on an identical frame */
@keyframes tickerScroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  /* No marquee: show one static set the reader can swipe through instead. */
  .capability-ticker { overflow-x: auto; scrollbar-width: none; }
  .capability-ticker::-webkit-scrollbar { display: none; }
  .capability-track { animation: none; }
  .capability-set:nth-child(2) { display: none; }
}
@media (max-width: 640px) {
  /* Hero spacing/sizing is fluid (clamp-based, see the .hero rules above) and
     already scales down on a narrow phone — only the ticker's own decorative
     edge-fade width needs a fixed-width tweak at this size. */
  .capability-set li { padding: 0 20px; }
  .capability-ticker::before, .capability-ticker::after { width: 48px; }
}

/* Hero background on smaller screens.

   The watermark terms are positioned by percentage against the hero's edges.
   On a wide screen those edges are far from the centred copy, but as the hero
   narrows the "edge" columns close in on the headline and the terms start
   sitting underneath it. Rather than reposition them per breakpoint, the layer
   is dropped below tablet width — it is decoration, and the drifting motifs
   already carry the same meaning. */
@media (max-width: 860px) {
  .hero .hero-formulas { display: none; }
}
@media (max-width: 640px) {
  /* Stats read better centred once they wrap on a phone; the 860px rule above
     left-aligns them for the tablet case where they still sit on one row. */
  .hero .hero-stats { justify-content: center; }
  .hero .hero-stat { text-align: center; }
  .hero .eyebrow::before { width: 24px; }
  /* The motif canvas costs more per frame than the hex-only version it
     replaced, and at this width the shapes are large relative to the column
     and crowd the copy. Dropping it on phones saves the battery and the
     layout at once — the only rule elsewhere that hides this canvas is the
     reduced-motion one, which is a different condition. */
  .hero .hero-lattice { display: none; }
}

/* Scroll-reveal animations */
.reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.7s ease, transform 0.7s ease;
}
.reveal.in-view { opacity: 1; transform: translateY(0); }

/* Section wipe — nav jumps between full-height sections used to teleport with no
   sense of travel. A navy curtain sweeps up, the page jumps behind it, then it
   lifts away while the destination's content reveals. It is clipped to the area
   below the sticky header, so the nav never blanks out and the curtain has
   somewhere off-screen to travel from and to. */
.section-wipe {
  position: fixed; top: var(--header-h); left: 0; right: 0; bottom: 0;
  z-index: 1200;
  overflow: hidden;
  pointer-events: none;
  visibility: hidden;
}
.section-wipe.is-active { visibility: visible; pointer-events: auto; }
/* The nav-jump curtain. It used to be near-black, which read as a deliberate
   beat between navy sections. Against the light page it would now flash dark on
   every jump — so it takes the same tint as the sections it covers, and the
   label carries the contrast instead. */
.section-wipe-panel {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 50% 40%, #f7f9fb 0%, #eef2f7 55%, #e4eaf2 100%);
  transform: translateY(100%);
}
.section-wipe.is-covering .section-wipe-panel { transform: translateY(0); transition: transform 0.42s cubic-bezier(0.76, 0, 0.24, 1); }
.section-wipe.is-clearing .section-wipe-panel { transform: translateY(-100%); transition: transform 0.5s cubic-bezier(0.76, 0, 0.24, 1); }

.section-wipe-label {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: #103a68;
  display: flex; align-items: center; gap: 14px;
  opacity: 0;
  transition: opacity 0.25s ease 0.12s;
}
.section-wipe-label::before,
.section-wipe-label::after { content: ''; width: 34px; height: 1px; background: rgba(135,134,135,0.7); }
.section-wipe.is-covering .section-wipe-label { opacity: 1; }
/* Once the curtain starts lifting the label should already be gone. */
.section-wipe.is-clearing .section-wipe-label { opacity: 0; transition: opacity 0.18s ease; }

@media (prefers-reduced-motion: reduce) {
  .section-wipe { display: none; }
}

/* Sticky header shadow once scrolled */
.site-header.scrolled { box-shadow: 0 2px 16px rgba(0,0,0,0.06); }

/* Section — fluid vertical padding (see the min-height rule above) so a short
   window's sections compress instead of clipping or forcing a scroll for
   content that would otherwise fit. */
.section { padding: clamp(36px, 8vh, 80px) 24px; position: relative; overflow: hidden; }
.section-head { max-width: 640px; margin: 0 auto clamp(24px, 5vh, 48px); text-align: center; }
.section-head.align-left { text-align: left; margin-left: 0; }
.section-title { text-align: center; font-size: 2rem; font-weight: 800; margin-bottom: 0; color: var(--hero-heading); text-wrap: balance; }
/* Section titles land at 1.5rem on mobile everywhere else already — Products'
   .catalog-hero-title clamps down to exactly this floor below 640px on its
   own. FAQ and Contact use the bare .section-title above and had no mobile
   override at all, so they were still rendering at the full 2rem desktop
   size — the one genuinely inconsistent heading size found in a pass over
   every mobile section. This brings them to the size the rest of the page
   already settles on, rather than introducing a new one. Placed after the
   base rule above on purpose: same specificity, so source order is what
   decides the cascade, and a media query earlier in the file loses to an
   unconditional rule that comes after it regardless of viewport. */
@media (max-width: 640px) {
  .section-title { font-size: 1.5rem; }
}
.section-subtitle { text-align: center; color: var(--hero-body); margin-top: 14px; font-size: 1.02rem; }
.section-head.align-left .section-subtitle { text-align: left; }
.section-head .eyebrow { color: var(--hero-silver-dark); }
.section-head.align-left .eyebrow { justify-content: flex-start; }

/* Hex watermark, used behind section content */
.hex-watermark {
  position: absolute;
  top: -40px; right: -60px;
  width: 380px; height: 380px;
  opacity: 0.45;
  pointer-events: none;
  z-index: 0;
}
.section .container { position: relative; z-index: 1; }

/* Features — "Why Choose Us". Inherits the tint from .section-tint; the
   gradient origin is shifted so consecutive tinted bands do not all carry
   their highlight in the same corner. */
.features-section {
  background: radial-gradient(circle at 88% 12%, var(--hero-bg-from) 0%, var(--hero-bg-mid) 45%, var(--hero-bg-to) 100%);
}
.features-section .hex-watermark g { stroke: rgba(16,58,104,0.06); }
.features-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}
/* Solid white cards, not the translucent "glass" this used to be. A 4%-white
   fill reads as a card on navy but is invisible on a light field, so the card
   is now given a real surface, a silver hairline and a soft shadow to lift it
   off the tint. */
.feature-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 28px 26px;
  box-shadow: 0 4px 16px rgba(16,58,104,0.05);
  transition: 0.2s ease;
}
/* Grows to fill leftover space so .feature-stat's divider lands at the same
   height on every card regardless of how many lines the description wraps to */
.feature-card-body { flex: 1; }
.feature-card:hover {
  border-color: var(--hero-silver);
  box-shadow: 0 10px 26px rgba(16,58,104,0.10);
  transform: translateY(-2px);
}
.feature-card-top { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 20px; }
.feature-card .icon-badge {
  width: 46px; height: 46px; border-radius: 10px; background: rgba(16,58,104,0.10);
  display: flex; align-items: center; justify-content: center;
  transition: background 0.2s ease;
}
.feature-card:hover .icon-badge { background: rgba(16,58,104,0.18); }
.feature-card .icon-badge svg { width: 22px; height: 22px; stroke: var(--hero-accent); fill: none; stroke-width: 1.8; }
.feature-molecule { width: 26px; height: 26px; stroke: var(--hero-silver); fill: none; stroke-width: 1.4; }
.feature-card .formula { display: block; font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.04em; color: var(--hero-silver-dark); margin-bottom: 8px; min-height: 1.1em; }
.rotating-formula { transition: opacity 0.35s ease; }
.rotating-formula.formula-fade { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .rotating-formula { transition: none; } }
.feature-card h3 { color: var(--hero-heading); margin-bottom: 10px; font-size: 1.15rem; }
.feature-card p { color: var(--text-muted); font-size: 0.94rem; }
.feature-stat {
  margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--border);
  font-family: var(--font-mono);
}
.feature-stat strong { color: var(--hero-accent); font-size: 1.3rem; font-weight: 800; margin-right: 6px; }
.feature-stat span { color: var(--hero-silver-dark); font-size: 0.86rem; }

/* Product category chips (with count badge) — used in the unified catalog filter row */
.filter-row { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 16px; }
.filter-label {
  font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-muted); margin-right: 4px;
}
.category-chip {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--white); border: 1px solid var(--border); border-radius: 30px;
  padding: 8px 8px 8px 16px; font-weight: 600; font-size: 0.85rem; color: var(--primary-dark);
  cursor: pointer; transition: 0.15s ease;
}
.category-chip:hover { border-color: var(--primary); box-shadow: 0 4px 12px rgba(22,48,92,0.08); }
.category-chip .category-chip-icon { width: 16px; height: 16px; flex-shrink: 0; stroke: currentColor; }
.category-chip .count {
  font-family: var(--font-mono); font-size: 0.68rem; font-weight: 700;
  background: var(--bg-page); color: var(--text-muted); padding: 2px 9px; border-radius: 20px;
}

/* Tinted sections — the same light blue/white/silver field as the hero.
   These were solid navy until the palette change; the class is named for what
   it now does rather than for the colour it used to be.

   The page alternates tinted and plain-white sections so it still has vertical
   rhythm. With every band the same white, the sections run together and the
   page reads as one endless sheet — the tint is doing the job the navy used to
   do, just quietly.

   Colours come from the same custom properties as the hero, set inline by
   index.php from the admin settings, with the finalised values as fallbacks —
   so changing "Accent" in the admin panel moves the hero and every tinted
   section together instead of letting them drift apart. */
.section-tint {
  --hero-bg-from: #eef2f7;
  --hero-bg-mid: #f7f9fb;
  --hero-bg-to: #ffffff;
  --hero-heading: #0a2748;
  --hero-accent: #103a68;
  --hero-cta: #103a68;
  --hero-silver: #878687;
  --hero-silver-dark: #5e5e5e;
  --hero-silver-light: #c8c9ca;
  --hero-body: #5a6472;

  background: radial-gradient(circle at 78% 14%, var(--hero-bg-from) 0%, var(--hero-bg-mid) 42%, var(--hero-bg-to) 100%);
  color: var(--text);
  position: relative;
}
/* A hairline at the top of each tinted band. On a light-on-light page this is
   what actually separates one section from the next once the navy is gone. */
.section-tint::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px;
  background: linear-gradient(90deg, transparent, var(--hero-silver-light), transparent);
  z-index: 1;
}
.section-tint .eyebrow { color: var(--hero-silver-dark); }
.section-tint .eyebrow::before {
  width: 34px; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--hero-silver-light), var(--hero-silver), var(--hero-accent));
}
.section-tint .section-title { color: var(--hero-heading); }
.section-tint .section-subtitle { color: var(--hero-body); }
.section-tint .hex-watermark g { stroke: rgba(16,58,104,0.07); }
/* Tighter heading spacing so the title area doesn't dwarf the card grid below it */
.section-tint .section-head { margin-bottom: 36px; }

/* Fades the lattice/hex background out behind the grid so its lines don't run
   directly behind card text — a soft vignette, not a hard cut. */
.industry-grid-wrap {
  position: relative;
  z-index: 1;
}
.industry-grid-wrap::before {
  content: '';
  position: absolute;
  inset: -32px;
  /* Was a solid navy ellipse masking the lattice behind the cards. On the light
     field the same job needs a near-white wash instead: enough to quiet the
     linework under the card text, transparent at the edges so it reads as a
     vignette rather than a panel. */
  background: radial-gradient(ellipse at center, rgba(255,255,255,0.82) 45%, rgba(255,255,255,0) 100%);
  z-index: -1;
  pointer-events: none;
}

/* Same glass-card treatment as the Features/Services dark sections, for a
   consistent look across every navy block on the page — sized up slightly
   and each card's icon tinted a touch differently so the row doesn't read
   as one badge repeated six times. */
.industry-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
}
.industry-card {
  position: relative;
  background: var(--white);
  border: 1px solid var(--border);
  /* The top edge keeps its accent stripe — it was amber on navy, blue here. */
  border-top: 2px solid rgba(16,58,104,0.45);
  border-radius: 14px;
  padding: 32px 28px;
  text-align: center;
  box-shadow: 0 4px 16px rgba(16,58,104,0.05);
  transition: 0.2s ease;
}
.industry-card:hover {
  border-color: var(--hero-silver);
  border-top-color: var(--hero-accent);
  transform: translateY(-6px);
  /* Shadow tinted with the brand navy rather than black — a neutral drop
     shadow turns grey against the blue-tinted background. */
  box-shadow: 0 16px 32px rgba(16,58,104,0.14);
}
.industry-card .icon-badge {
  width: 50px; height: 50px; border-radius: 12px;
  background: rgba(16,58,104,0.10);
  display: flex; align-items: center; justify-content: center;
  margin: 0 auto 20px;
  transition: background 0.2s ease, transform 0.2s ease;
}
/* Two cards in the row take a silver badge instead of blue, so six identical
   badges don't read as one repeated element. */
.industry-card:nth-child(2) .icon-badge { background: rgba(135,134,135,0.16); }
.industry-card:nth-child(2):hover .icon-badge { background: rgba(135,134,135,0.26); }
.industry-card:nth-child(2) .icon-badge svg { stroke: var(--hero-silver-dark); }
.industry-card:nth-child(5) .icon-badge { background: rgba(135,134,135,0.16); }
.industry-card:nth-child(5):hover .icon-badge { background: rgba(135,134,135,0.26); }
.industry-card:nth-child(5) .icon-badge svg { stroke: var(--hero-silver-dark); }

/* Brand-partner logo marquee — a continuously drifting strip rather than a
   static grid or a manual scroller. It runs full-bleed (outside .container) so
   logos travel the whole width and read as an ongoing roster rather than a
   boxed-in list, with the track duplicated into two identical halves so a
   translate of -50% lands on a matching frame and the loop is seamless. */
/* The section drops its own horizontal padding so the marquee is edge to edge
   without negative margins that would silently drift if .section's padding ever
   changed. The heading keeps its gutter from .container's own padding. */
.brands-section {
  /* No background of its own — it sits on the page ground like the other
     untinted sections, so the white logo cards read as cards the same way
     feature/industry/service cards do. --brands-fade tracks that ground so the
     edge fades stay invisible if the section is ever moved or tinted. */
  --brands-fade: var(--bg-page);
  overflow: hidden;
  padding-left: 0;
  padding-right: 0;
}
.brands-section.section-tint { --brands-fade: var(--hero-bg-mid); }
.brands-marquee {
  position: relative;
  z-index: 1;
  padding: 4px 0;
}
/* Soft fade at both ends so logos enter and leave rather than being cut off */
.brands-marquee::before,
.brands-marquee::after {
  content: ''; position: absolute; top: 0; bottom: 0; width: 120px;
  z-index: 2; pointer-events: none;
}
.brands-marquee::before { left: 0; background: linear-gradient(90deg, var(--brands-fade), transparent); }
.brands-marquee::after { right: 0; background: linear-gradient(270deg, var(--brands-fade), transparent); }
.brands-track {
  display: flex;
  width: max-content;
  animation: brandsScroll var(--brands-duration, 60s) linear infinite;
}
.brands-marquee:hover .brands-track { animation-play-state: paused; }
.brands-set { display: flex; align-items: center; list-style: none; margin: 0; padding: 0; }
.brand-logo-card {
  flex: 0 0 auto;
  width: 190px; height: 104px;
  margin: 0 10px;
  display: flex; align-items: center; justify-content: center;
  padding: 22px 26px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--white);
  transition: border-color 0.25s ease, box-shadow 0.25s ease, transform 0.25s ease;
}
.brand-logo-card:hover {
  border-color: rgba(22,48,92,0.18);
  box-shadow: 0 10px 26px rgba(22,48,92,0.10);
  transform: translateY(-3px);
}
.brand-logo-card img {
  max-width: 100%; max-height: 100%; object-fit: contain;
}
/* Each half is exactly 50% of the track, so -50% is an identical frame */
@keyframes brandsScroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  /* No drift: the strip becomes a plain swipeable row instead. */
  .brands-marquee { overflow-x: auto; scrollbar-width: none; }
  .brands-marquee::-webkit-scrollbar { display: none; }
  .brands-track { animation: none; }
  .brands-set:nth-child(2) { display: none; }
}
@media (max-width: 640px) {
  /* What the section shrinks TO once the min-height floor above is dropped —
     desktop's own padding, heading and card sizing are untouched; every rule
     here is scoped to .brands-section/.brands-marquee/.brand-logo-card so
     no other section is affected. Card size and fade width were 150x88 and
     56px at this same breakpoint before; both were sized for the old
     desktop-height card, which no longer applies here. */
  /* Sections on this site butt directly against each other everywhere — a
     shared background tint plus a 1px hairline (.section-tint::before) is
     the only separator, never a margin between them. So the only way to
     give Brands breathing room from Products above and FAQ below is its
     own top/bottom padding — bumped past the initial 22px, which read as
     cramped against two neighbours that both keep their full-viewport
     mobile height. */
  .brands-section { padding-top: 40px; padding-bottom: 44px; }
  /* Heading TEXT SIZE is not overridden here — it now comes from the general
     .section-title mobile rule above, same as FAQ/Contact, so the heading
     hierarchy reads the same across every section. Only the gap below it
     shrinks, proportional to the much shorter content (a logo strip, not an
     accordion or a form) that follows. */
  .brands-section .section-head { margin-bottom: 14px; }
  .brands-marquee { padding: 0; }
  .brands-marquee::before, .brands-marquee::after { width: 32px; }
  .brand-logo-card { width: 92px; height: 40px; padding: 6px 10px; margin: 0 8px; border-radius: 9px; }
}
.industry-card:hover .icon-badge { background: rgba(16,58,104,0.28); transform: scale(1.08); }
.industry-card .icon-badge svg { width: 24px; height: 24px; stroke: var(--hero-accent); fill: none; stroke-width: 1.8; }
.industry-card h3 { color: var(--hero-heading); font-size: 1.1rem; margin-bottom: 10px; }
.industry-card p { color: var(--text-muted); font-size: 0.92rem; }

/* About + Foundation */
.about-grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 44px;
  align-items: start;
}
.lead-text { color: var(--text-muted); font-size: 1.05rem; margin-top: 16px; }

.fact-chips { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 26px; }
.fact-chip {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--white); border: 1px solid var(--border); border-radius: 30px;
  padding: 9px 16px 9px 12px; font-size: 0.85rem; font-weight: 600; color: var(--primary-dark);
}
.fact-chip .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--brand-accent); flex-shrink: 0; }

.foundation-card {
  background: var(--primary-dark);
  color: var(--white);
  border-radius: var(--radius);
  padding: 32px 28px;
  display: flex; flex-direction: column; justify-content: center;
}
.foundation-card .tag {
  font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255,255,255,0.45); margin-bottom: 12px;
}
.foundation-card h3 { margin-bottom: 12px; font-size: 1.3rem; }
.foundation-card p { color: #c6cddb; }
.foundation-card .principle-list { margin-top: 20px; display: flex; flex-direction: column; gap: 10px; }
.foundation-card .principle {
  display: flex; align-items: baseline; gap: 10px; font-size: 0.88rem; color: rgba(255,255,255,0.85);
  padding-top: 10px; border-top: 1px solid rgba(255,255,255,0.12);
}
.foundation-card .principle .num { font-family: var(--font-mono); color: var(--brand-accent); font-size: 0.78rem; flex-shrink: 0; }

/* Business Services ("What We Do") — split layout: intro + stats left, hex icon-card grid right.
   Light silver field (not navy) so the page alternates navy → silver → navy between the
   "Why Choose Us" section above and the catalog header below, instead of three dark blocks in a row. */
.services-section {
  background: linear-gradient(180deg, var(--white) 0%, var(--bg-light) 100%);
}
.services-section .lead-text { color: var(--text-muted); }

.services-split {
  display: grid;
  grid-template-columns: 0.9fr 1.5fr;
  gap: 44px;
  align-items: start;
}
/* Both columns share the same top baseline as the heading — the grid's first
   row of cards lines up with the eyebrow, not the paragraph below it. */
.services-grid { margin-top: 2px; }

.services-stats {
  display: flex; flex-wrap: wrap; gap: 28px;
  margin-top: 28px; padding-top: 24px;
  border-top: 1px solid var(--border);
}
.services-stat { display: flex; flex-direction: column; gap: 4px; }
/* Fixed line-height so every value — numeral or qualitative — occupies the
   same vertical space; otherwise the smaller qualitative stat's shorter line
   pulls its label up out of line with the other stats' labels. */
.services-stat strong {
  font-family: var(--font-mono); font-size: 1.6rem; font-weight: 800;
  line-height: 1.9rem; white-space: nowrap; color: var(--primary-dark);
}
/* A qualitative stat (e.g. "Pan-India") can't take a "+" numeral format —
   styled deliberately smaller instead of forced into the same numeral scale,
   so the mismatch reads as intentional rather than an inconsistency. */
.services-stat strong.is-qualitative { font-size: 1.15rem; letter-spacing: 0.01em; }
.services-stat span { font-size: 0.82rem; color: var(--text-muted); }

.services-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 18px;
}
.service-card {
  grid-column: span 2;
  position: relative;
  background: var(--white);
  border: 1px solid var(--border);
  border-top: 2px solid transparent;
  border-radius: 14px;
  padding: 24px 22px;
  box-shadow: 0 6px 18px rgba(22,48,92,0.05);
  transition: 0.2s ease;
}
/* When the last row has exactly two cards left over, they widen to split the
   row evenly instead of leaving a dead gap where a third card would sit. */
.services-grid.grid-fill-last-two .service-card:nth-last-child(-n+2) { grid-column: span 3; }
.service-card:hover {
  border-color: rgba(22,48,92,0.14);
  border-top-color: var(--brand-accent);
  box-shadow: 0 16px 32px rgba(22,48,92,0.14);
  transform: translateY(-6px);
}
.service-card .icon-badge {
  width: 46px; height: 46px;
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 18px;
  transition: transform 0.2s ease;
}
.service-card:hover .icon-badge { transform: scale(1.08); }
.service-card .icon-hex {
  background: rgba(16,58,104,0.22);
  border: 1px solid rgba(16,58,104,0.3);
  clip-path: polygon(25% 3%, 75% 3%, 100% 50%, 75% 97%, 25% 97%, 0% 50%);
}
.service-card:hover .icon-hex { background: rgba(16,58,104,0.36); }
.service-card .icon-badge svg { width: 21px; height: 21px; stroke: #9c6423; fill: none; stroke-width: 2; }
.service-card h3 { color: var(--primary-dark); font-size: 1.05rem; margin-bottom: 8px; }
.service-card p { color: var(--text-muted); font-size: 0.9rem; }

.hidden { display: none !important; }

/* Unified catalog: header band (title + live-stock ticker only — the
   search bar now lives with the filters below, see .catalog-toolbar, so
   this band is shorter than it used to be). Tinted rather than navy since the
   palette change; the gradient starts top-left so it does not repeat the
   features band directly above it. */
.catalog-hero {
  position: relative; overflow: hidden;
  background: var(--bg-page);
  color: var(--text);
  padding: 56px 24px;
  display: flex; align-items: center;
}
/* The tinted gradient only paints when .section-tint is also present — an
   admin toggle (Section Backgrounds) adds or removes that class per section.
   A compound selector beats .section-tint's own rule on specificity alone,
   so this doesn't depend on which one is declared later in the file. The
   origin point (12% 20%, top-left) differs from .section-tint's default
   (78% 14%) on purpose, so this band doesn't look like a repeat of the one
   above it when both are tinted. */
.catalog-hero.section-tint {
  background: radial-gradient(circle at 12% 20%, var(--hero-bg-from) 0%, var(--hero-bg-mid) 48%, var(--hero-bg-to) 100%);
}
.catalog-hero .hero-lattice { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0.55; }
.catalog-hero .container { position: relative; z-index: 1; width: 100%; }
.catalog-hero .eyebrow { color: var(--hero-silver-dark); }
.catalog-hero .eyebrow::before {
  width: 34px; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--hero-silver-light), var(--hero-silver), var(--hero-accent));
}
.catalog-hero-title {
  font-family: var(--font-display); font-size: clamp(1.5rem, 2.6vw, 2.1rem); font-weight: 700;
  text-wrap: balance; margin-bottom: 8px; max-width: 640px; color: var(--hero-heading);
}

.ticker-line {
  font-family: var(--font-mono); font-size: 0.82rem; color: var(--hero-silver-dark);
  margin-bottom: 0; display: inline-flex; align-items: center; gap: 8px;
}
.ticker-line .live-dot { width: 6px; height: 6px; border-radius: 50%; background: #4fd17a; flex-shrink: 0; animation: pulseDot 1.6s ease-in-out infinite; }
.ticker-line .ticker-val { color: var(--brand-accent); font-weight: 600; transition: opacity 0.35s ease; }
.ticker-line .ticker-val.formula-fade { opacity: 0; }
@keyframes pulseDot { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) { .ticker-line .live-dot { animation: none; } }

/* Search + category filters + letter jump, one unified card so they read as
   a single filter panel instead of a search bar stranded in the navy band
   above and a separate filter strip below it. */
.catalog-toolbar {
  background: var(--white); border: 1px solid var(--border); border-radius: 18px;
  padding: 24px; margin-bottom: 28px;
  box-shadow: 0 10px 30px rgba(22,48,92,0.06);
  display: flex; flex-direction: column; gap: 18px;
}
.catalog-toolbar .filter-row,
.catalog-toolbar .letter-row { margin-bottom: 0; }

.catalog-toolbar-search { position: relative; width: 100%; max-width: 420px; margin: 0 auto; }
.catalog-toolbar-search > svg {
  position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  width: 17px; height: 17px; stroke: var(--text-muted); fill: none; stroke-width: 1.8;
  pointer-events: none;
}
.catalog-toolbar-search input {
  width: 100%; padding: 12px 42px 12px 40px;
  border: 1.5px solid var(--border); border-radius: 10px;
  font-size: 0.92rem; font-family: inherit;
  background: var(--bg-page); color: var(--text);
  transition: 0.2s ease;
}
.catalog-toolbar-search input::placeholder { color: var(--text-muted); }
.catalog-toolbar-search input:focus {
  outline: none; border-color: var(--primary); background: var(--white);
  box-shadow: 0 0 0 4px rgba(22,48,92,0.08);
}
.catalog-toolbar-search .clear-search {
  position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
  width: 20px; height: 20px; border-radius: 50%; background: var(--bg-page); border: none;
  color: var(--text-muted); cursor: pointer; display: none; align-items: center; justify-content: center;
  transition: 0.15s ease;
}
.catalog-toolbar-search .clear-search:hover { background: var(--border); color: var(--primary-dark); }
.catalog-toolbar-search .clear-search.show { display: flex; }
.catalog-toolbar-search .clear-search svg { width: 11px; height: 11px; stroke: currentColor; stroke-width: 2.4; }

/* Letters (greys out when zero matches in current search scope) */
.letter-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin-bottom: 16px; }
.letter-tab {
  font-family: var(--font-mono); width: 28px; height: 28px; border-radius: 6px;
  background: var(--white); border: 1px solid var(--border); color: var(--primary-mid);
  font-size: 0.82rem; font-weight: 700; cursor: pointer; transition: 0.15s ease;
  display: flex; align-items: center; justify-content: center;
}
.letter-tab:hover { border-color: var(--primary); color: var(--primary); }
.letter-tab.active { background: var(--primary); border-color: var(--primary); color: var(--white); }
.letter-tab.disabled { opacity: 0.3; cursor: default; pointer-events: none; }

/* Phone-only stand-in for .filter-row + .letter-row above — see the design
   note beside .catalog-toolbar-mobile in index.php. Hidden by default; the
   640px media query below swaps it in for the two desktop rows, which keep
   rendering exactly as they do today above that width. */
.catalog-toolbar-mobile { display: none; }

.catalog-fold-btn {
  display: flex; align-items: center; justify-content: space-between; width: 100%;
  min-height: 44px; padding: 0 14px; margin-bottom: 8px;
  border: 1px solid var(--border); border-radius: 22px; background: var(--white);
  font-family: inherit; font-size: 0.86rem; font-weight: 600; color: var(--primary-dark); cursor: pointer;
}
.catalog-fold-btn .label { display: flex; align-items: baseline; gap: 6px; min-width: 0; }
.catalog-fold-btn .picked {
  font-family: var(--font-mono); font-weight: 700; color: var(--primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 46vw;
}
.catalog-fold-btn .caret { flex: 0 0 auto; margin-left: 10px; transition: transform 0.2s ease; font-size: 0.7rem; color: var(--text-muted); }
.catalog-fold-btn[aria-expanded="true"] .caret { transform: rotate(180deg); }

/* Category panel: chips wrap onto as many rows as needed so every option is
   visible at once — the fix for a sideways-scrolling row that hid most of
   them past whatever fit the first screenful. */
.catalog-fold-panel { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.catalog-fold-panel[hidden] { display: none; }
.catalog-fold-chip {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 44px; padding: 0 14px; border-radius: 22px;
  border: 1px solid var(--border); background: var(--white); color: var(--primary-dark);
  font-family: inherit; font-size: 0.86rem; font-weight: 600; white-space: nowrap; cursor: pointer;
  transition: 0.15s ease;
}
.catalog-fold-chip .category-chip-icon { width: 16px; height: 16px; flex-shrink: 0; stroke: currentColor; }
.catalog-fold-chip .count {
  font-family: var(--font-mono); font-size: 0.68rem; font-weight: 700;
  background: var(--bg-page); color: var(--text-muted); padding: 2px 9px; border-radius: 20px;
}
.catalog-fold-chip.active { background: var(--primary); border-color: var(--primary); color: var(--white); }
.catalog-fold-chip.active .count { background: rgba(255,255,255,0.22); color: var(--white); }
.catalog-fold-chip.disabled { opacity: 0.3; cursor: default; pointer-events: none; }

/* First-letter panel reuses .letter-tab — same on/disabled states as the
   desktop letter row — just sized as a real touch target (44px vs desktop's
   28px) via this descendant override, so desktop's own rule above is untouched. */
.catalog-fold-panel-az { display: grid; grid-template-columns: repeat(auto-fill, minmax(44px, 1fr)); gap: 6px; }
.catalog-fold-panel-az .letter-tab { width: auto; height: 44px; border-radius: 10px; font-size: 0.92rem; }

.results-meta { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; flex-wrap: wrap; gap: 10px; }

/* Keeps the section from visibly shrinking/jumping as filters narrow the result count */
.catalog-results-body { min-height: 200px; }

.catalog-prompt { position: relative; overflow: hidden; text-align: center; padding: 60px 20px 70px; border-radius: 12px; }
.catalog-prompt-lattice { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0.5; pointer-events: none; }
.catalog-prompt-icon {
  position: relative; z-index: 1;
  display: flex; align-items: center; justify-content: center;
  width: 64px; height: 64px; border-radius: 50%;
  background: var(--bg-light); margin: 0 auto 22px;
}
.catalog-prompt-icon svg { width: 26px; height: 26px; stroke: var(--primary-mid); fill: none; stroke-width: 1.8; }
.catalog-prompt-title { position: relative; z-index: 1; font-family: var(--font-display); font-size: 1.15rem; font-weight: 700; color: var(--primary-dark); margin-bottom: 8px; }
.catalog-prompt-sub { position: relative; z-index: 1; color: var(--text-muted); font-size: 0.92rem; }
.catalog-empty-state { text-align: center; padding: 40px 0; color: var(--text-muted); }
.catalog-empty-state p { margin-bottom: 14px; }
.catalog-empty-state .btn { display: inline-flex; }
.results-count { color: var(--text-muted); font-size: 0.9rem; }
.results-count strong { color: var(--primary-dark); font-family: var(--font-mono); }

.catalog-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 12px;
}
.catalog-card {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 13px 10px;
  text-align: center;
  transition: 0.2s ease;
}
.catalog-card:hover { border-color: var(--primary); box-shadow: 0 8px 20px rgba(22,48,92,0.1); transform: translateY(-2px); }
.catalog-name { font-size: 0.86rem; font-weight: 600; color: var(--text); letter-spacing: 0.01em; }
.catalog-formula { font-family: var(--font-mono); font-size: 0.72rem; color: var(--text-muted); }

.catalog-pagination { display: flex; gap: 6px; justify-content: center; margin-top: 16px; flex-wrap: wrap; }
.catalog-page-btn {
  min-width: 30px; height: 30px; padding: 0 8px;
  border: 1px solid var(--border); border-radius: 6px; background: var(--white);
  color: var(--text); font-size: 0.85rem; cursor: pointer; transition: 0.15s ease;
}
.catalog-page-btn:hover:not(:disabled):not(.active) { border-color: var(--primary); color: var(--primary); }
.catalog-page-btn.active { background: var(--primary); border-color: var(--primary); color: var(--white); }
.catalog-page-btn.active:hover { background: var(--primary-dark); border-color: var(--primary-dark); }
.catalog-page-btn:disabled { opacity: 0.35; cursor: not-allowed; }
.catalog-page-ellipsis { display: flex; align-items: center; justify-content: center; min-width: 20px; height: 30px; color: var(--text-muted); font-size: 0.85rem; }

@media (max-width: 640px) {
  .catalog-hero { padding: 44px 20px; }
  /* Real pagination on mobile too (not the "Show more" append button this
     used to be) — see the note above measurePageSize() in main.js for why:
     appending kept growing the scroll back to the search box every time a
     product wasn't in what had already loaded. The 30px desktop buttons
     were sized for a mouse pointer; bumped to a real touch target here,
     desktop's own size above is untouched. */
  .catalog-page-btn { min-width: 44px; height: 44px; font-size: 0.9rem; }
  .catalog-page-ellipsis { height: 44px; }
  .catalog-toolbar { padding: 18px; gap: 16px; }
  /* Swap the desktop category/letter rows for the fold-button pickers above —
     nothing here runs above 640px, so desktop's own layout is untouched. */
  .filter-row, .letter-row { display: none; }
  .catalog-toolbar-mobile { display: block; }
}

/* Products */
.products-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 26px;
}
.product-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--white);
}
.product-card .img-wrap { aspect-ratio: 4/3; background: var(--bg-light); display:flex; align-items:center; justify-content:center; color: var(--text-muted); }
.product-card .body { padding: 20px; }
.product-card .category { color: var(--accent-dark); font-size: 0.8rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; }
.product-card h3 { margin: 8px 0; color: var(--primary-dark); }
.product-card p { color: var(--text-muted); font-size: 0.95rem; }


/* Contact */
.contact-grid { display: grid; grid-template-columns: 1fr 1.3fr; gap: 48px; align-items: start; }

/* Left column — floats free on the page, no card wrapper */
.contact-info-plain { display: flex; flex-direction: column; gap: 26px; padding-top: 6px; }
.contact-intro { color: var(--text-muted); font-size: 0.98rem; margin-bottom: 6px; }

.contact-item { display: flex; align-items: flex-start; gap: 16px; }
.contact-item-link { transition: transform 0.15s ease; }
.contact-item-link:hover { transform: translateX(4px); }
.contact-item-link:hover span { color: #1da851; }
.contact-item .icon-badge {
  width: 46px; height: 46px; border-radius: 50%; flex-shrink: 0;
  background: var(--bg-light);
  display: flex; align-items: center; justify-content: center;
}
.contact-item .icon-badge svg { width: 21px; height: 21px; stroke: var(--primary); fill: none; stroke-width: 1.8; }
.contact-item .icon-badge-solid { background: var(--primary); }
.contact-item .icon-badge-solid svg { stroke: var(--white); }
.contact-item strong {
  display: block; font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--text-muted); font-weight: 600; margin-bottom: 4px;
}
.contact-item span { font-size: 1rem; font-weight: 600; color: var(--text); line-height: 1.4; }

/* Right column — the form card */
.contact-form-card {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 36px 32px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.05);
}
.contact-form-title { font-family: var(--font-display); font-size: 1.3rem; color: var(--primary); margin-bottom: 24px; }

.form-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }
.form-group { margin-bottom: 13px; }
.form-group:last-of-type { margin-bottom: 18px; }
.form-group label { display: block; font-weight: 600; margin-bottom: 6px; font-size: 0.9rem; }
.form-group input, .form-group textarea, .form-group select {
  width: 100%; padding: 10px 14px; border: 1px solid var(--border); border-radius: 8px; font-size: 1rem; font-family: inherit;
  background: var(--bg-page);
  transition: border-color 0.2s ease, background 0.2s ease;
}
.form-group input:focus, .form-group textarea:focus, .form-group select:focus {
  outline: none; border-color: var(--primary); background: var(--white);
}
.contact-form-card .btn-primary { width: 100%; text-align: center; padding: 13px 26px; }

@media (max-width: 640px) {
  .form-grid-2 { grid-template-columns: 1fr; }
  /* Quantity + delivery stay side by side even here — both are short values
     (a select and "500 kg, 2 drums"), unlike name/company or email/phone,
     so collapsing them to full width like the others cost a full row of
     height on mobile for no legibility gain, right where the modal needed
     it least. */
  .form-grid-2-tight { grid-template-columns: 1fr 1fr; gap: 0 10px; }
}

/* Map embed */
.map-wrap {
  position: relative;
  margin-top: 40px;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--border);
  box-shadow: 0 10px 28px rgba(0,0,0,0.08);
}
.map-wrap iframe { width: 100%; height: 340px; border: 0; display: block; }
.map-open-btn {
  position: absolute; top: 16px; left: 16px; z-index: 2;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 30px;
  padding: 10px 18px;
  font-size: 0.85rem; font-weight: 600;
  color: var(--primary);
  box-shadow: 0 4px 14px rgba(0,0,0,0.12);
  transition: 0.2s ease;
}
.map-open-btn:hover { background: var(--primary); color: var(--white); border-color: var(--primary); }

/* Footer */
/* Footer — dark closing band with link columns and a contact block */
.site-footer {
  background: var(--primary-dark);
  color: #c9d1e2;
  padding: 56px 24px 0;
  font-size: 0.88rem;
}
/* Three tracks, not four — the grid used to reserve a fourth column for a
   "Company" links list that got folded into "Explore" earlier, leaving a
   blank track the width of a whole column on the right. */
.footer-grid {
  display: grid;
  grid-template-columns: 1.5fr 0.9fr 1.3fr;
  gap: 40px;
  padding-bottom: 40px;
}
.footer-col h4 {
  color: var(--white); font-size: 0.78rem; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase;
  margin-bottom: 16px; font-family: var(--font-mono);
}
.footer-name { display: block; font-family: var(--font-display); font-size: 1.2rem; font-weight: 800; color: var(--white); }
.footer-tagline {
  display: block; font-size: 0.66rem; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--white); margin-top: 3px;
}
.footer-about { margin-top: 16px; color: #a8b2c6; font-size: 0.86rem; max-width: 340px; }
.footer-social { display: flex; gap: 10px; margin-top: 20px; }
.footer-social a {
  width: 34px; height: 34px; border-radius: 9px;
  background: rgba(255,255,255,0.07); border: 1px solid rgba(255,255,255,0.12);
  display: flex; align-items: center; justify-content: center;
  color: #c9d1e2; transition: 0.2s ease;
}
.footer-social a:hover { background: var(--brand-accent); border-color: var(--brand-accent); color: var(--brand-accent-ink); }
.footer-social svg { width: 16px; height: 16px; }
.footer-links, .footer-contact { display: flex; flex-direction: column; gap: 11px; }
.footer-links a { color: #c9d1e2; transition: color 0.2s ease; }
.footer-links a:hover { color: var(--brand-accent-on-dark); }
.footer-links .js-quote-open { cursor: pointer; }
.footer-contact li { display: flex; flex-direction: column; gap: 2px; }
.footer-contact li span {
  font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: #7d879b;
}
.footer-contact a { color: #c9d1e2; transition: color 0.2s ease; }
.footer-contact a:hover { color: var(--brand-accent-on-dark); }
.footer-bottom {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px;
  padding: 20px 0 24px;
  border-top: 1px solid rgba(255,255,255,0.1);
  font-size: 0.82rem; color: #8b95a9;
}
.footer-credit { color: #7d879b; }

/* Our Process — numbered stages joined by a connecting rule */
.process-section { background: var(--bg-page); }
.process-track {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
  position: relative;
}
/* Steps are centred in their columns. Left-aligning them put every marker at the
   left edge of its column, so the visible circle-and-connector chain stopped at
   the last marker while its column ran on — reading as if the whole track were
   shifted left even though the container was dead centre. */
.process-step { position: relative; padding-top: 8px; text-align: center; }
.process-marker {
  width: 46px; height: 46px; border-radius: 50%;
  background: var(--white); border: 2px solid var(--brand-accent);
  color: var(--primary-dark); font-family: var(--font-mono); font-weight: 800; font-size: 0.9rem;
  display: flex; align-items: center; justify-content: center;
  margin: 0 auto 18px; position: relative; z-index: 1;
}
/* Connector runs from the edge of one centred marker to the edge of the next
   (46px marker = 23px radius; 24px grid gap), and never past the last step. */
.process-step:not(:last-child)::before {
  content: ''; position: absolute;
  top: 31px; left: calc(50% + 23px); right: calc(-50% - 1px); height: 2px;
  background: linear-gradient(90deg, var(--brand-accent) 0%, var(--border) 100%);
}
.process-step h3 { color: var(--primary-dark); font-size: 1.05rem; margin-bottom: 8px; }
.process-step p { color: var(--text-muted); font-size: 0.9rem; max-width: 26ch; margin: 0 auto; }

/* Quality & Compliance — checklist rows on the navy field */
.quality-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 18px;
}
.quality-card {
  display: flex; align-items: flex-start; gap: 16px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 24px 24px;
  box-shadow: 0 4px 16px rgba(16,58,104,0.05);
  transition: 0.2s ease;
}
.quality-card:hover {
  border-color: var(--hero-silver);
  box-shadow: 0 10px 26px rgba(16,58,104,0.10);
  transform: translateY(-4px);
}
.quality-check {
  flex-shrink: 0;
  width: 38px; height: 38px; border-radius: 10px;
  background: rgba(16,58,104,0.12);
  display: flex; align-items: center; justify-content: center;
}
.quality-check svg { width: 19px; height: 19px; stroke: var(--hero-accent); fill: none; stroke-width: 2.4; }
.quality-card h3 { color: var(--hero-heading); font-size: 1.02rem; margin-bottom: 6px; }
.quality-card p { color: var(--text-muted); font-size: 0.9rem; }

/* FAQ — native <details> accordion, no JS needed. Ruled list rather than a stack
   of cards: numbered in mono, hairline separated, so a long list reads as one
   calm column instead of a wall of boxes. */
/* Scoped to :not(.section-tint) rather than a flat .faq-section rule, so that
   when the Section Backgrounds toggle adds .section-tint here, that rule's
   own gradient wins on its own — no need to duplicate the gradient value
   just to out-specificity a later flat-colour rule. */
.faq-section:not(.section-tint) { background: var(--bg-page); }
.faq-grid { display: grid; grid-template-columns: 330px 1fr; gap: 72px; align-items: start; }
.faq-aside { position: sticky; top: calc(var(--header-h) + 40px); }
.faq-aside .section-head { margin-bottom: 28px; }

.faq-aside-card {
  border-left: 2px solid var(--brand-accent);
  padding: 4px 0 4px 20px;
}
.faq-aside-count {
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--primary-mid); margin-bottom: 10px;
}
.faq-aside-card p { color: var(--text-muted); font-size: 0.92rem; line-height: 1.65; margin-bottom: 18px; }
.faq-aside-btn { display: inline-flex; align-items: center; gap: 9px; }
.faq-aside-btn svg { width: 17px; height: 17px; }

.faq-list { display: flex; flex-direction: column; border-top: 1px solid var(--border); }
.faq-item { border-bottom: 1px solid var(--border); transition: background 0.25s ease; }
.faq-item[open] { background: linear-gradient(90deg, rgba(22,48,92,0.03), transparent 60%); }
.faq-item summary {
  display: grid; grid-template-columns: auto 1fr auto; align-items: baseline; gap: 18px;
  padding: 22px 18px 22px 4px; cursor: pointer; list-style: none;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:focus-visible { outline: 2px solid var(--brand-accent); outline-offset: -2px; border-radius: 6px; }
.faq-index {
  font-family: var(--font-mono); font-size: 0.74rem; font-weight: 700;
  color: rgba(22,48,92,0.35); letter-spacing: 0.04em;
  transition: color 0.25s ease;
}
.faq-q {
  font-family: var(--font-display); font-weight: 600; font-size: 1.02rem;
  color: var(--primary-dark); line-height: 1.45; text-wrap: pretty;
  transition: color 0.25s ease;
}
.faq-item summary:hover .faq-q, .faq-item[open] .faq-q { color: var(--primary-mid); }
.faq-item[open] .faq-index { color: var(--brand-accent); }

/* Plus that rotates into a cross — quieter than a chevron at this size */
.faq-mark { position: relative; width: 14px; height: 14px; flex-shrink: 0; align-self: center; transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); }
.faq-mark::before, .faq-mark::after {
  content: ''; position: absolute; top: 50%; left: 0; width: 100%; height: 1.5px;
  background: var(--brand-accent); border-radius: 1px; transform: translateY(-50%);
}
.faq-mark::after { transform: translateY(-50%) rotate(90deg); transition: opacity 0.3s ease; }
.faq-item[open] .faq-mark { transform: rotate(135deg); }

.faq-answer { padding: 0 44px 26px 46px; }
.faq-answer p { color: var(--text-muted); font-size: 0.94rem; line-height: 1.75; max-width: 62ch; }
.faq-item[open] .faq-answer { animation: faqAnswerIn 0.32s ease both; }
@keyframes faqAnswerIn { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

@media (max-width: 980px) {
  .faq-grid { grid-template-columns: 1fr; gap: 36px; }
  .faq-aside { position: static; }
}
@media (max-width: 560px) {
  .faq-item summary { gap: 12px; padding-right: 6px; }
  .faq-answer { padding: 0 12px 24px 36px; }
}
@media (prefers-reduced-motion: reduce) {
  .faq-mark { transition: none; }
  .faq-item[open] .faq-answer { animation: none; }
}

/* "Request Quote" button on each catalog card — revealed on hover/focus */
.catalog-card { position: relative; }
.catalog-enquire {
  margin-top: 8px;
  border: 1px solid var(--border); background: var(--bg-page);
  color: var(--primary); font-family: inherit; font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.02em; padding: 5px 12px; border-radius: 20px; cursor: pointer;
  opacity: 0; transform: translateY(-2px);
  transition: 0.18s ease;
}
.catalog-card:hover .catalog-enquire,
.catalog-enquire:focus-visible { opacity: 1; transform: translateY(0); }
.catalog-enquire:hover { background: var(--brand-accent); border-color: var(--brand-accent); color: var(--brand-accent-ink); }
/* Touch devices have no hover — keep the button permanently visible there */
@media (hover: none) {
  .catalog-enquire { opacity: 1; transform: none; }
}

/* Quote request modal */
.quote-modal { position: fixed; inset: 0; z-index: 300; display: flex; align-items: center; justify-content: center; padding: 24px; }
.quote-modal[hidden] { display: none; }
.quote-modal-backdrop { position: absolute; inset: 0; background: rgba(6,11,24,0.62); backdrop-filter: blur(2px); }
.quote-modal-panel {
  position: relative;
  background: var(--white);
  border-radius: 16px;
  width: 100%; max-width: 600px;
  /* svh so the modal never runs under iOS Safari's toolbar, which would put
     the submit button out of reach. vh line is the fallback. */
  max-height: 94vh;
  max-height: 94svh;
  overflow-y: auto;
  padding: 22px 26px 24px;
  box-shadow: 0 24px 60px rgba(6,11,24,0.4);
}
.quote-modal-close {
  position: absolute; top: 16px; right: 16px;
  width: 32px; height: 32px; border-radius: 50%;
  border: none; background: var(--bg-light); color: var(--text);
  cursor: pointer; display: flex; align-items: center; justify-content: center;
  transition: background 0.2s ease;
}
.quote-modal-close:hover { background: var(--border); }
.quote-modal-close svg { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 2.2; }
.quote-modal-panel h3 { color: var(--primary-dark); font-size: 1.2rem; margin-bottom: 4px; }
.quote-modal-intro { color: var(--text-muted); font-size: 0.86rem; line-height: 1.4; margin-bottom: 18px; }
.quote-form .btn { width: 100%; margin-top: 6px; cursor: pointer; }

/* Small screens: the modal takes almost the full viewport instead of
   floating with generous margins it doesn't have room for, and every
   internal spacing/font figure steps down a notch so the same content
   fits without seven different UI densities on one page. */
@media (max-width: 640px) {
  .quote-modal { padding: 0; align-items: flex-end; }
  .quote-modal-panel {
    max-width: none; width: 100%;
    max-height: 96vh;
    max-height: 96svh;
    border-radius: 16px 16px 0 0;
    padding: 16px 16px 14px;
  }
  .quote-modal-panel h3 { font-size: 1.08rem; margin-bottom: 3px; }
  .quote-modal-intro { font-size: 0.8rem; line-height: 1.4; margin-bottom: 14px; }
  .form-group { margin-bottom: 10px; }
  .enq-types { margin-bottom: 10px; }
}
@media (max-width: 400px) {
  /* The title already says "Request a Quote" — this subtitle is supplementary
     copy, not information the form needs to work, so it's the first thing to
     go on a screen this short. Input padding/font-size are NOT touched by
     any of this modal's compaction: shrinking those below a comfortable tap
     target is how you trade a scrollbar for missed taps. */
  .quote-modal-intro { display: none; }
}

/* Selected-products list inside the modal */
.quote-items {
  border: 1px solid var(--border); border-radius: 12px;
  padding: 10px 14px; margin-bottom: 12px; background: var(--bg-page);
}
.quote-items[hidden] { display: none; }
.quote-items-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 8px;
  font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--text-muted);
}
.quote-items-clear {
  border: none; background: none; cursor: pointer; padding: 0;
  font-family: inherit; font-size: inherit; letter-spacing: inherit;
  text-transform: inherit; color: var(--primary-mid); text-decoration: underline;
}
.quote-items-clear:hover { color: var(--primary); }
.quote-items-legend {
  display: grid; grid-template-columns: 1fr auto auto;
  padding: 0 12px 6px; gap: 10px;
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--text-muted);
}
.quote-items-legend span:last-child { padding-right: 52px; }
.quote-items-list { display: flex; flex-direction: column; gap: 6px; max-height: min(280px, 34vh); overflow-y: auto; }
.quote-items-list li {
  display: grid; grid-template-columns: 1fr auto auto; align-items: center; gap: 6px 10px;
  background: var(--white); border: 1px solid var(--border);
  border-radius: 8px; padding: 8px 10px 8px 12px;
  font-size: 0.87rem; font-weight: 600; color: var(--primary-dark);
}
.quote-item-name { overflow: hidden; text-overflow: ellipsis; }
.quote-item-qty { display: inline-flex; align-items: center; gap: 7px; }
.quote-qty-input {
  width: 78px; padding: 6px 8px; text-align: right;
  border: 1px solid var(--border); border-radius: 6px;
  font-family: var(--font-mono); font-size: 0.86rem; font-weight: 700;
  color: var(--primary-dark); background: var(--bg-page);
  -moz-appearance: textfield;
}
.quote-qty-input:focus { outline: none; border-color: var(--primary); background: var(--white); }
.quote-qty-input.is-invalid { border-color: #e5534b; background: #fff5f4; color: #b23c34; }
.quote-item-unit {
  font-family: var(--font-mono); font-size: 0.74rem; font-weight: 700;
  letter-spacing: 0.06em; color: var(--text-muted);
  min-width: 26px;
}
/* Preferred packaging size — same shape as the quantity control, just
   optional and visually quieter (it's a hint, not a requirement). */
.quote-item-pkg { display: inline-flex; align-items: center; gap: 7px; }
.quote-pkg-input {
  width: 66px; padding: 6px 8px; text-align: right;
  border: 1px solid var(--border); border-radius: 6px;
  font-family: var(--font-mono); font-size: 0.82rem; font-weight: 600;
  color: var(--text-muted); background: var(--bg-page);
  -moz-appearance: textfield;
}
.quote-pkg-input:focus { outline: none; border-color: var(--primary); background: var(--white); color: var(--primary-dark); }
.quote-pkg-input::placeholder { font-weight: 400; font-size: 0.72rem; }
.quote-item-pkg-unit {
  font-family: var(--font-mono); font-size: 0.74rem; font-weight: 700;
  letter-spacing: 0.06em; color: var(--text-muted);
  min-width: 20px;
}
/* Warning spans the full row so it never squeezes the name column */
.quote-qty-warn {
  grid-column: 1 / -1;
  font-size: 0.75rem; font-weight: 600; color: #b23c34;
}
.quote-qty-warn[hidden] { display: none; }
.quote-items-note { margin-top: 10px; font-size: 0.76rem; color: var(--text-muted); }
.quote-item-remove {
  flex-shrink: 0;
  width: 22px; height: 22px; border-radius: 50%;
  border: none; background: var(--bg-light); color: var(--text-muted);
  font-size: 1rem; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.15s ease, color 0.15s ease;
}
.quote-item-remove:hover { background: #e5534b; color: var(--white); }
@media (max-width: 520px) {
  .quote-items-list li { grid-template-columns: 1fr; }
  .quote-item-qty, .quote-item-pkg { justify-content: flex-end; }
  .quote-items-legend span:nth-child(n+2) { display: none; }
}
.quote-empty-note {
  background: var(--bg-page); border: 1px dashed var(--border);
  border-radius: 10px; padding: 9px 12px; margin-bottom: 12px;
  font-size: 0.82rem; color: var(--text-muted);
}

.quote-empty-note[hidden] { display: none; }

/* Add-to-quote toggle state on catalog cards */
.catalog-enquire .q-added { display: none; }
.catalog-enquire.is-added { opacity: 1; transform: none; background: var(--brand-accent); border-color: var(--brand-accent); color: var(--brand-accent-ink); }
.catalog-enquire.is-added .q-add { display: none; }
.catalog-enquire.is-added .q-added { display: inline; }
.catalog-card:has(.catalog-enquire.is-added) { border-color: var(--brand-accent); }

/* Floating quote basket */
.quote-bar {
  position: fixed; right: 24px; bottom: 24px; z-index: 220;
  display: flex; align-items: center; gap: 14px;
  background: var(--primary-dark); color: var(--white);
  border: 1px solid rgba(255,255,255,0.14);
  border-radius: 14px; padding: 12px 14px 12px 18px;
  box-shadow: 0 18px 40px rgba(6,11,24,0.35);
  animation: quoteBarIn 0.28s cubic-bezier(0.22, 0.8, 0.3, 1);
}
.quote-bar[hidden] { display: none; }
.quote-bar-info { display: flex; align-items: center; gap: 9px; }
.quote-bar-count {
  min-width: 26px; height: 26px; padding: 0 7px; border-radius: 13px;
  background: var(--brand-accent); color: var(--brand-accent-ink);
  font-family: var(--font-mono); font-weight: 800; font-size: 0.85rem;
  display: inline-flex; align-items: center; justify-content: center;
}
.quote-bar-label { font-size: 0.88rem; color: #c9d1e2; white-space: nowrap; }
.quote-bar-btn { padding: 9px 18px; background: var(--brand-accent); color: var(--brand-accent-ink); border-radius: 8px; }
.quote-bar-btn:hover { background: #16497f; }
.quote-bar-clear {
  width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0;
  border: none; background: rgba(255,255,255,0.1); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.15s ease;
}
.quote-bar-clear:hover { background: rgba(255,255,255,0.2); }
.quote-bar-clear svg { width: 13px; height: 13px; stroke: #c9d1e2; fill: none; stroke-width: 2.2; }
@keyframes quoteBarIn {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) { .quote-bar { animation: none; } }
/* Sits above the WhatsApp button on narrow screens rather than beside it */
@media (max-width: 560px) {
  .quote-bar { left: 16px; right: 16px; bottom: 92px; justify-content: space-between; padding: 12px 12px 12px 16px; }
  .quote-bar-label { display: none; }
}

/* Floating WhatsApp button */
.whatsapp-float {
  position: fixed;
  bottom: 24px; left: 24px;
  width: 58px; height: 58px;
  background: #25D366;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 8px 20px rgba(0,0,0,0.22);
  z-index: 200;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.whatsapp-float:hover { transform: scale(1.08); box-shadow: 0 10px 26px rgba(0,0,0,0.28); }
.whatsapp-float svg { width: 30px; height: 30px; fill: var(--white); }
@media (max-width: 860px) {
  .whatsapp-float { bottom: 18px; left: 18px; width: 52px; height: 52px; }
  .whatsapp-float svg { width: 26px; height: 26px; }
}

/* ---------------------------------------------------------------------------
   Assistant — launcher + panel, bottom right. WhatsApp holds the opposite
   corner; the quote basket shares this one, so the dock lifts when it appears.
   --------------------------------------------------------------------------- */
.ai-dock {
  position: fixed; right: 24px; bottom: 24px; z-index: 240;
  display: flex; flex-direction: column-reverse; align-items: flex-end; gap: 14px;
  transition: bottom 0.28s cubic-bezier(0.22, 0.8, 0.3, 1);
}
.ai-dock.has-quote-bar { bottom: 96px; }

.ai-launcher {
  position: relative; flex-shrink: 0;
  width: 58px; height: 58px; border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.16);
  background: radial-gradient(circle at 32% 26%, var(--primary-mid) 0%, var(--primary-dark) 72%);
  color: var(--white); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 12px 30px rgba(6,11,24,0.32);
  transition: transform 0.22s ease, box-shadow 0.22s ease;
}
.ai-launcher:hover { transform: translateY(-2px); box-shadow: 0 16px 36px rgba(6,11,24,0.38); }
.ai-launcher:focus-visible { outline: 2px solid var(--brand-accent); outline-offset: 3px; }
.ai-launcher svg { position: absolute; width: 25px; height: 25px; transition: opacity 0.2s ease, transform 0.28s cubic-bezier(0.22, 0.8, 0.3, 1); }
.ai-launcher-close { opacity: 0; transform: rotate(-90deg) scale(0.6); }
.ai-dock.is-open .ai-launcher-icon { opacity: 0; transform: rotate(90deg) scale(0.6); }
.ai-dock.is-open .ai-launcher-close { opacity: 1; transform: none; }
/* A single slow amber pulse — present enough to be noticed, not a blinking badge */
.ai-launcher-ring {
  position: absolute; inset: -5px; border-radius: 50%;
  border: 1px solid var(--brand-accent); opacity: 0;
  animation: aiPulse 3.6s cubic-bezier(0.22, 0.8, 0.3, 1) infinite;
}
@keyframes aiPulse {
  0%   { transform: scale(0.92); opacity: 0; }
  22%  { opacity: 0.55; }
  60%, 100% { transform: scale(1.28); opacity: 0; }
}
.ai-dock.is-open .ai-launcher-ring { animation: none; opacity: 0; }

.ai-panel {
  width: 384px; max-width: calc(100vw - 32px);
  height: 540px;
  /* svh so the panel is measured against the SMALLEST viewport — with plain vh
     on iOS the bottom of the panel (the input and send button) sits behind
     Safari's toolbar and can't be reached. vh line is the fallback. */
  max-height: calc(100vh - var(--header-h) - 110px);
  max-height: calc(100svh - var(--header-h) - 110px);
  background: var(--white);
  border: 1px solid rgba(22,48,92,0.10);
  border-radius: 18px;
  box-shadow: 0 30px 70px rgba(6,11,24,0.30), 0 2px 10px rgba(6,11,24,0.08);
  display: flex; flex-direction: column; overflow: hidden;
  transform-origin: bottom right;
  opacity: 0; transform: translateY(14px) scale(0.97);
  transition: opacity 0.22s ease, transform 0.24s cubic-bezier(0.22, 0.8, 0.3, 1),
    width 0.32s cubic-bezier(0.22, 0.8, 0.3, 1), height 0.32s cubic-bezier(0.22, 0.8, 0.3, 1),
    max-height 0.32s cubic-bezier(0.22, 0.8, 0.3, 1);
}
.ai-panel[hidden] { display: none; }
.ai-dock.is-open .ai-panel { opacity: 1; transform: none; }

/* Expanded state — same corner anchor, more room to read a longer transcript
   or a reply carrying several product cards. */
.ai-dock.is-maximized .ai-panel {
  width: 460px;
  height: calc(100vh - var(--header-h) - 32px);
  height: calc(100svh - var(--header-h) - 32px);
  max-height: calc(100vh - var(--header-h) - 32px);
  max-height: calc(100svh - var(--header-h) - 32px);
}

.ai-head {
  display: flex; align-items: center; gap: 12px;
  padding: 15px 14px 15px 18px;
  background: radial-gradient(circle at 12% 20%, var(--primary-mid) 0%, var(--primary-dark) 78%);
  color: var(--white);
  border-bottom: 1px solid rgba(255,255,255,0.10);
}
.ai-avatar {
  width: 36px; height: 36px; border-radius: 11px; flex-shrink: 0;
  background: rgba(16,58,104,0.16); border: 1px solid rgba(16,58,104,0.35);
  display: flex; align-items: center; justify-content: center;
}
.ai-avatar svg { width: 20px; height: 20px; stroke: var(--brand-accent); }
.ai-head-text { flex: 1; min-width: 0; }
.ai-title { font-family: var(--font-display); font-weight: 700; font-size: 0.95rem; color: var(--white); }
.ai-status { display: flex; align-items: center; gap: 6px; font-size: 0.74rem; color: rgba(255,255,255,0.6); margin-top: 2px; }
.ai-status-dot { width: 6px; height: 6px; border-radius: 50%; background: #4fd17a; animation: pulseDot 1.8s ease-in-out infinite; }

.ai-head-actions { display: flex; align-items: center; gap: 2px; flex-shrink: 0; }
.ai-close, .ai-maximize, .ai-clear {
  width: 30px; height: 30px; border-radius: 8px; flex-shrink: 0;
  background: transparent; border: none; cursor: pointer; color: rgba(255,255,255,0.65);
  display: flex; align-items: center; justify-content: center;
  transition: background 0.18s ease, color 0.18s ease;
}
.ai-close:hover, .ai-maximize:hover, .ai-clear:hover { background: rgba(255,255,255,0.10); color: var(--white); }
.ai-close svg, .ai-maximize svg, .ai-clear svg { width: 16px; height: 16px; }
.ai-clear[hidden] { display: none; }

/* Two glyphs, one shown at a time — same cross-fade idea as the launcher icon */
.ai-max-collapse { display: none; }
.ai-dock.is-maximized .ai-max-expand { display: none; }
.ai-dock.is-maximized .ai-max-collapse { display: flex; }

.ai-body {
  flex: 1; overflow-y: auto; padding: 18px;
  display: flex; flex-direction: column; align-items: flex-start; gap: 12px;
  background: linear-gradient(180deg, var(--white) 0%, var(--bg-page) 100%);
  scrollbar-width: thin; scrollbar-color: rgba(22,48,92,0.22) transparent;
}
.ai-body::-webkit-scrollbar { width: 6px; }
.ai-body::-webkit-scrollbar-thumb { background: rgba(22,48,92,0.20); border-radius: 3px; }

.ai-msg {
  max-width: 90%; padding: 12px 14px; border-radius: 14px;
  font-size: 0.89rem; line-height: 1.62;
  animation: aiMsgIn 0.26s cubic-bezier(0.22, 0.8, 0.3, 1) both;
}
.ai-msg p + p { margin-top: 8px; }
.ai-msg-bot {
  background: var(--white); color: var(--text);
  border: 1px solid var(--border); border-bottom-left-radius: 5px;
  box-shadow: 0 2px 10px rgba(22,48,92,0.05);
}
.ai-msg-user {
  align-self: flex-end;
  background: var(--primary-dark); color: rgba(255,255,255,0.94);
  border-bottom-right-radius: 5px;
}
.ai-msg-source {
  display: block; margin-bottom: 7px; padding-bottom: 7px;
  border-bottom: 1px solid var(--border);
  font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--primary-mid);
}
@keyframes aiMsgIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* Marks where a restored conversation resumes, so a returning visitor knows
   this is picking back up rather than a fresh reply appearing instantly. */
.ai-restored-marker {
  display: flex; align-items: center; gap: 10px;
  align-self: stretch; margin: 2px 0;
  font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-muted);
}
.ai-restored-marker::before, .ai-restored-marker::after { content: ''; flex: 1; height: 1px; background: var(--border); }

.ai-typing { display: flex; gap: 5px; padding: 15px 14px; }
.ai-typing span { width: 6px; height: 6px; border-radius: 50%; background: rgba(22,48,92,0.35); animation: aiTyping 1.3s ease-in-out infinite; }
.ai-typing span:nth-child(2) { animation-delay: 0.18s; }
.ai-typing span:nth-child(3) { animation-delay: 0.36s; }
@keyframes aiTyping { 0%, 60%, 100% { opacity: 0.28; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-3px); } }

/* Product hits rendered inside a reply */
.ai-product {
  margin-top: 10px; padding: 9px 12px;
  background: var(--bg-page); border: 1px solid var(--border);
  border-left: 2px solid var(--brand-accent); border-radius: 9px;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
.ai-product-info { min-width: 0; }
.ai-product-head { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.ai-product-name { font-weight: 700; font-size: 0.86rem; color: var(--primary-dark); }
.ai-product-formula { font-family: var(--font-mono); font-size: 0.73rem; color: var(--primary-mid); }
.ai-product-cat { display: block; margin-top: 3px; font-size: 0.72rem; color: var(--text-muted); }
/* Multiple products can turn up in one reply (a loose or misspelled search
   catching several near-matches) — each gets its own add button rather than
   the single generic "Request a quote" below the list forcing a re-search
   inside the modal for the one the visitor actually meant. No hover-reveal
   like the catalog card's version (.catalog-enquire): the chat is used on
   phones as much as anywhere else, where hover doesn't exist. */
.ai-product-add {
  flex-shrink: 0;
  border: 1px solid var(--border); background: var(--white);
  color: var(--primary); font-family: inherit; font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.02em; padding: 6px 12px; border-radius: 20px; cursor: pointer;
  transition: 0.16s ease;
}
.ai-product-add:hover { border-color: var(--brand-accent); color: var(--brand-accent); }
.ai-product-add .q-added { display: none; }
.ai-product-add.is-added {
  background: var(--brand-accent); border-color: var(--brand-accent); color: var(--brand-accent-ink);
}
.ai-product-add.is-added .q-add { display: none; }
.ai-product-add.is-added .q-added { display: inline; }
.ai-product-actions { display: flex; flex-direction: column; gap: 5px; flex-shrink: 0; }
/* "Which one did you mean?" answered per-card — same pill shape as +Add,
   filled instead of outlined so it doesn't read as a second identical
   button next to it. */
.ai-product-quote {
  border: 1px solid var(--brand-accent); background: var(--brand-accent);
  color: var(--brand-accent-ink); font-family: inherit; font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.02em; padding: 6px 12px; border-radius: 20px; cursor: pointer;
  transition: 0.16s ease; white-space: nowrap;
}
.ai-product-quote:hover { background: var(--hero-cta-hover, var(--brand-accent)); }

.ai-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.ai-action {
  display: inline-flex; align-items: center;
  padding: 7px 13px; border-radius: 999px;
  background: var(--primary-dark); color: var(--white);
  border: 1px solid var(--primary-dark);
  font-size: 0.78rem; font-weight: 600; cursor: pointer;
  transition: background 0.18s ease, transform 0.18s ease;
}
.ai-action:hover { background: var(--primary-mid); border-color: var(--primary-mid); transform: translateY(-1px); }
.ai-action + .ai-action { background: transparent; color: var(--primary-dark); border-color: var(--border); }
.ai-action + .ai-action:hover { background: var(--bg-light); color: var(--primary-dark); }
.ai-action:disabled { opacity: 0.6; cursor: default; transform: none; }

/* In-chat quote flow — the summary shown right before it actually sends */
.ai-quote-summary {
  margin-top: 10px; padding: 10px 12px;
  background: var(--bg-page); border: 1px solid var(--border); border-radius: 9px;
}
.ai-quote-summary-row { display: flex; justify-content: space-between; gap: 12px; padding: 4px 0; font-size: 0.84rem; }
.ai-quote-summary-row + .ai-quote-summary-row { border-top: 1px solid var(--border); }
.ai-quote-summary-label { color: var(--text-muted); flex-shrink: 0; }
.ai-quote-summary-value { color: var(--primary-dark); font-weight: 600; text-align: right; }

.ai-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.ai-chip {
  padding: 8px 13px; border-radius: 999px;
  background: var(--white); border: 1px solid var(--border);
  color: var(--primary-dark); font-size: 0.79rem; line-height: 1.35;
  text-align: left; cursor: pointer;
  transition: border-color 0.18s ease, color 0.18s ease, background 0.18s ease;
}
.ai-chip:hover { border-color: var(--brand-accent); color: var(--primary-mid); background: rgba(16,58,104,0.06); }

.ai-input {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 12px 8px; border-top: 1px solid var(--border); background: var(--white);
}
.ai-input input {
  flex: 1; min-width: 0; padding: 11px 14px;
  border: 1px solid var(--border); border-radius: 999px;
  font-family: inherit; font-size: 0.87rem; color: var(--text);
  background: var(--bg-page);
  transition: border-color 0.18s ease, background 0.18s ease;
}
.ai-input input:focus { outline: none; border-color: var(--primary-mid); background: var(--white); }
.ai-send {
  width: 38px; height: 38px; flex-shrink: 0; border-radius: 50%;
  background: var(--brand-accent); border: none; color: var(--brand-accent-ink); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.18s ease, transform 0.18s ease;
}
.ai-send:hover { background: #16497f; transform: translateY(-1px); }
.ai-send svg { width: 17px; height: 17px; }
.ai-foot {
  padding: 0 16px 12px; background: var(--white);
  font-size: 0.68rem; line-height: 1.5; color: var(--text-muted);
}

@media (max-width: 560px) {
  .ai-dock { right: 16px; bottom: 16px; }
  .ai-dock.has-quote-bar { bottom: 88px; }
  .ai-launcher { width: 52px; height: 52px; }
  .ai-panel, .ai-dock.is-maximized .ai-panel {
    width: calc(100vw - 32px);
    /* svh line wins where supported; on iOS plain vh would size the sheet to
       the toolbar-hidden viewport and bury the input behind the toolbar. */
    height: min(76vh, 560px); max-height: min(76vh, 560px);
    height: min(76svh, 560px); max-height: min(76svh, 560px);
  }
  /* Already close to full-screen at this width, so expanding adds little —
     drop the control rather than let it do almost nothing. */
  .ai-maximize { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .ai-launcher-ring { animation: none; }
  .ai-panel, .ai-msg, .ai-launcher svg { transition: none; animation: none; }
  .ai-typing span { animation: none; }
  .ai-status-dot { animation: none; }
}

@media (max-width: 1080px) {
  .services-grid { grid-template-columns: repeat(2, 1fr); }
  /* Cards (and the "last two span 3 of 6" remainder trick) are sized for the
     desktop 6-column grid — left active here they span into columns that no
     longer exist, collapsing cards to zero/partial width or forcing phantom
     implicit columns. Every card takes exactly one track at this breakpoint. */
  .service-card { grid-column: span 1; }
  .services-grid.grid-fill-last-two .service-card:nth-last-child(-n+2) { grid-column: span 1; }
  .process-track { grid-template-columns: repeat(2, 1fr); row-gap: 32px; }
  /* Connector only makes sense along a row — hide it where the row wraps */
  .process-step:nth-child(2n)::before { display: none; }
}
@media (max-width: 980px) {
  /* Desktop nav and the header CTA give way to the hamburger + drawer */
  .nav-links { display: none; }
  .nav-toggle { display: flex; }
}

@media (max-width: 860px) {
  .features-grid, .services-grid, .about-grid, .industry-grid, .services-split { grid-template-columns: 1fr !important; }
  .feature-card { border-left: none; border-top: 1px solid var(--border); }
  .feature-card:first-child { border-top: none; }
  .contact-grid { grid-template-columns: 1fr; }
  .process-track, .quality-grid { grid-template-columns: 1fr; }
  .process-step::before { display: none !important; }
  .footer-grid { grid-template-columns: 1fr; gap: 28px; }
  .hex-watermark { display: none; }
  .hero-stats { flex-wrap: wrap; justify-content: flex-start; gap: 28px; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-lattice { display: none; }
}

/* Admin — enterprise sidebar layout */
:root {
  --admin-sidebar-w: 250px;
  --admin-bg: #f2f4f7;
  --admin-ink: #1a1d21;
  --admin-muted: #6b7280;
  --admin-border: #e5e7eb;
}
.admin-body { background: var(--admin-bg); font-family: 'Segoe UI', system-ui, sans-serif; color: var(--admin-ink); }

.admin-sidebar {
  position: fixed; top: 0; left: 0; bottom: 0; width: var(--admin-sidebar-w);
  background: var(--primary-dark);
  display: flex; flex-direction: column;
  z-index: 100;
  transition: width 0.2s ease;
}
.admin-sidebar-brand { display: flex; align-items: center; gap: 12px; padding: 22px 20px; border-bottom: 1px solid rgba(255,255,255,0.1); overflow: hidden; }
.admin-sidebar-logo {
  width: 36px; height: 36px; border-radius: 8px; background: var(--brand-accent); color: var(--brand-accent-ink);
  display: flex; align-items: center; justify-content: center; font-weight: 800; font-family: var(--font-display); flex-shrink: 0;
}
.admin-sidebar-name { color: #fff; font-weight: 700; font-size: 0.92rem; line-height: 1.2; white-space: nowrap; }
.admin-sidebar-tag { color: rgba(255,255,255,0.5); font-size: 0.72rem; margin-top: 2px; white-space: nowrap; }

.admin-sidebar-collapse-btn {
  position: absolute; top: 24px; right: -12px; z-index: 2;
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--white); border: 1px solid var(--admin-border);
  display: flex; align-items: center; justify-content: center; cursor: pointer;
  box-shadow: 0 2px 6px rgba(0,0,0,0.15);
  transition: transform 0.2s ease;
}
.admin-sidebar-collapse-btn svg { width: 14px; height: 14px; stroke: var(--primary); fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

.admin-sidebar-nav { flex: 1; padding: 16px 12px; overflow-y: auto; overflow-x: hidden; }
.admin-nav-label {
  font-family: var(--font-mono); font-size: 0.65rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(255,255,255,0.35); padding: 16px 12px 8px; white-space: nowrap;
}
.admin-nav-label:first-child { padding-top: 4px; }
.admin-sidebar-nav a {
  display: flex; align-items: center; gap: 12px;
  color: rgba(255,255,255,0.75); text-decoration: none;
  padding: 10px 12px; border-radius: 8px; font-size: 0.9rem; font-weight: 500;
  margin-bottom: 2px; transition: 0.15s ease; white-space: nowrap;
}
.admin-sidebar-nav a svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; flex-shrink: 0; }
.admin-sidebar-nav a:hover { background: rgba(255,255,255,0.06); color: #fff; }
.admin-sidebar-nav a.active { background: var(--brand-accent); color: var(--brand-accent-ink); }

.admin-sidebar-footer { padding: 16px 20px; border-top: 1px solid rgba(255,255,255,0.1); display: flex; flex-direction: column; gap: 8px; overflow: hidden; }
.admin-sidebar-footer a { display: flex; align-items: center; gap: 12px; color: rgba(255,255,255,0.6); font-size: 0.85rem; white-space: nowrap; }
.admin-sidebar-footer a svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; flex-shrink: 0; }
.admin-sidebar-footer a:hover { color: #fff; }

.admin-topbar {
  margin-left: var(--admin-sidebar-w);
  display: flex; align-items: center; gap: 14px;
  padding: 12px 24px; background: var(--white); border-bottom: 1px solid var(--admin-border);
  transition: margin-left 0.2s ease;
}
.admin-topbar-toggle {
  width: 34px; height: 34px; border-radius: 6px; border: none; background: transparent;
  display: flex; align-items: center; justify-content: center; cursor: pointer; color: var(--admin-muted);
}
.admin-topbar-toggle:hover { background: var(--admin-bg); color: var(--admin-ink); }
.admin-topbar-toggle svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; }
.admin-topbar-spacer { flex: 1; }
.admin-topbar-user { font-weight: 600; font-size: 0.9rem; color: var(--admin-ink); }
.admin-role-badge {
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.05em; text-transform: uppercase; font-weight: 700;
  padding: 4px 10px; border-radius: 20px;
}
.admin-role-owner { background: #e8f0fe; color: var(--primary); }
.admin-role-product_manager { background: #fff4e5; color: #a86a1c; }

/* Notification bell — persistent backlog dropdown, distinct from the transient toasts */
.admin-bell-wrap { position: relative; }
.admin-bell-btn {
  position: relative; border: none; background: none; cursor: pointer;
  width: 36px; height: 36px; display: flex; align-items: center; justify-content: center;
  border-radius: 8px; color: var(--admin-muted);
}
.admin-bell-btn:hover { background: var(--admin-bg); color: var(--admin-ink); }
.admin-bell-btn svg { width: 19px; height: 19px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.admin-bell-badge {
  position: absolute; top: 2px; right: 2px; min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 10px; background: #c0392b; color: var(--white);
  font-size: 0.64rem; font-weight: 700; line-height: 16px; text-align: center;
}
.admin-bell-dropdown {
  position: absolute; top: calc(100% + 8px); right: 0; width: 320px; max-height: 420px;
  background: var(--white); border-radius: 12px; box-shadow: 0 16px 40px rgba(0,0,0,0.18);
  z-index: 500; display: flex; flex-direction: column; overflow: hidden;
}
.admin-bell-dropdown[hidden] { display: none; }
.admin-bell-head { padding: 14px 16px; font-weight: 700; font-size: 0.9rem; border-bottom: 1px solid var(--admin-border); }
.admin-bell-list { overflow-y: auto; max-height: 320px; }
.admin-bell-empty { padding: 24px 16px; text-align: center; color: var(--admin-muted); font-size: 0.85rem; }
.admin-bell-item {
  display: block; padding: 10px 16px; text-decoration: none; border-bottom: 1px solid var(--admin-border);
}
.admin-bell-item:last-child { border-bottom: none; }
.admin-bell-item:hover { background: var(--admin-bg); }
.admin-bell-item strong { display: block; font-size: 0.85rem; color: var(--admin-ink); margin-bottom: 2px; }
.admin-bell-item span { display: block; font-size: 0.78rem; color: var(--admin-muted); }
.admin-bell-footer {
  display: block; padding: 12px 16px; text-align: center; font-size: 0.83rem; font-weight: 600;
  color: var(--primary); border-top: 1px solid var(--admin-border);
}
.admin-bell-footer:hover { background: var(--admin-bg); }

/* Live-inserted row (see quotes.php) briefly highlighted so it's obvious
   something just arrived, then settles to the normal unread styling. */
.qv-row-new { background: #fff4e0; }
.qv-row-new.is-just-in { transition: background 1.8s ease; }
.qv-row-new.is-just-in { background: transparent; }

/* AdminLTE-style content header: page title + breadcrumb trail */
.admin-content-header {
  margin-left: var(--admin-sidebar-w);
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 8px;
  padding: 18px 32px; transition: margin-left 0.2s ease;
}
.admin-content-header h1 { font-size: 1.35rem; font-weight: 700; color: var(--admin-ink); }
.admin-breadcrumb { display: flex; align-items: center; gap: 6px; font-size: 0.82rem; color: var(--admin-muted); }
.admin-breadcrumb a { color: var(--primary); }
.admin-breadcrumb a:hover { text-decoration: underline; }
.admin-breadcrumb .current { color: var(--admin-muted); font-weight: 600; }
.admin-breadcrumb-sep { color: #cbd2d9; }

/* Capped for readability, but wide enough that a dashboard can hold two columns
   instead of stranding half the screen on large monitors. */
.admin-wrap { max-width: 1480px; padding: 8px 32px 48px; margin-left: var(--admin-sidebar-w); transition: margin-left 0.2s ease; }

/* Collapsed sidebar — icon-only rail */
body.sidebar-collapsed { --admin-sidebar-w: 76px; }
body.sidebar-collapsed .admin-sidebar-brand-text,
body.sidebar-collapsed .admin-nav-label,
body.sidebar-collapsed .admin-nav-text { display: none; }
body.sidebar-collapsed .admin-sidebar-nav a { justify-content: center; }
body.sidebar-collapsed .admin-sidebar-footer a { justify-content: center; }
body.sidebar-collapsed .admin-sidebar-collapse-btn svg { transform: rotate(180deg); }
/* AdminLTE-style "box" card: colored top accent + separated header rule */
.admin-card {
  background: #fff; border: 1px solid var(--admin-border); border-top: 3px solid var(--primary);
  border-radius: 4px; padding: 28px; box-shadow: 0 1px 3px rgba(0,0,0,0.06); margin-bottom: 24px;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.admin-card[data-section] { cursor: pointer; }
.admin-card[data-section].active-section { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(22,48,92,0.12); }
.admin-card h3:first-child { font-size: 1.05rem; font-weight: 700; padding-bottom: 14px; margin-bottom: 20px; border-bottom: 1px solid var(--admin-border); }

/* AdminLTE-style small-box: colored stat widgets */
.admin-stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; margin: 20px 0 28px; }
.admin-small-box {
  position: relative; overflow: hidden; border-radius: 12px; padding: 18px 20px 16px;
  background: var(--white); border: 1px solid var(--admin-border); color: var(--admin-ink);
  box-shadow: 0 1px 2px rgba(16,24,40,0.04);
}
.admin-small-box::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: var(--box-accent, var(--primary));
}
.admin-small-box .num {
  font-family: var(--font-mono); font-size: 1.6rem; font-weight: 800; line-height: 1.15;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; letter-spacing: -0.01em;
}
.admin-small-box .label { font-size: 0.86rem; font-weight: 700; color: var(--admin-ink); margin-top: 6px; }
.admin-small-box .sub { font-size: 0.76rem; color: var(--admin-muted); margin-top: 2px; opacity: 1; }
.admin-small-box .icon {
  position: absolute; right: 16px; top: 16px; width: 34px; height: 34px; border-radius: 9px;
  background: color-mix(in srgb, var(--box-accent, var(--primary)) 14%, transparent);
  display: flex; align-items: center; justify-content: center;
}
.admin-small-box .icon svg { width: 18px; height: 18px; stroke: var(--box-accent, var(--primary)); fill: none; stroke-width: 2; }
.admin-small-box-primary { --box-accent: var(--primary); }
.admin-small-box-success { --box-accent: #1a9e5c; }
.admin-small-box-warning { --box-accent: var(--brand-accent); }
.admin-small-box-info { --box-accent: #2b8bab; }

/* Every admin table gets wrapped in this (see nav.php) so a wide table
   scrolls sideways within its own card on a phone or tablet, instead of
   forcing the whole page to scroll sideways. */
.admin-table-scroll { overflow-x: auto; }

/* List-page header: title on the left, search + primary action on the right. */
.admin-list-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding-bottom: 16px; margin-bottom: 20px; border-bottom: 1px solid var(--admin-border); flex-wrap: wrap; }
.admin-list-head h3 { padding: 0; margin: 0; border: 0; display: flex; align-items: center; gap: 9px; }
.admin-list-count {
  font-weight: 700; color: var(--admin-muted); font-size: 0.72rem; font-family: var(--font-mono);
  background: var(--admin-bg); border-radius: 10px; padding: 2px 8px;
}

/* Small pulsing dot marking a live/real-time panel (Active Now). */
.live-dot {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: #1a9e5c; margin-right: 4px; vertical-align: middle;
  box-shadow: 0 0 0 rgba(26,158,92,0.5); animation: liveDotPulse 2s infinite;
}
@keyframes liveDotPulse {
  0%   { box-shadow: 0 0 0 0 rgba(26,158,92,0.5); }
  70%  { box-shadow: 0 0 0 6px rgba(26,158,92,0); }
  100% { box-shadow: 0 0 0 0 rgba(26,158,92,0); }
}
@media (prefers-reduced-motion: reduce) { .live-dot { animation: none; } }
.admin-list-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.admin-search-input, .admin-filter-select {
  padding: 9px 14px; border: 1px solid var(--admin-border); border-radius: 8px; font-size: 0.86rem;
  font-family: inherit; color: var(--admin-ink); background: #fff; transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.admin-search-input {
  width: 100%; max-width: 280px; padding-left: 34px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239aa3b2' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: 11px center; background-size: 14px;
}
.admin-filter-select {
  appearance: none; -webkit-appearance: none; padding-right: 32px; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239aa3b2' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; background-size: 14px;
}
.admin-search-input:hover, .admin-filter-select:hover { border-color: #c7cdd6; }
.admin-search-input:focus, .admin-filter-select:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px rgba(22,48,92,0.08); }

/* Plain flex-wrap alone only breaks the row once content literally doesn't
   fit — below that point it just squeezes the search box down to a few
   characters instead of actually stacking. Force a clean stack explicitly. */
@media (max-width: 640px) {
  .admin-list-head { flex-direction: column; align-items: stretch !important; }
  .admin-list-actions { width: 100%; justify-content: stretch !important; }
  .admin-list-actions input[type="text"] { max-width: none !important; }
  .admin-list-actions .btn { width: 100%; text-align: center; }
}

/* Supplier name pills in the Orders list — a quiet neutral chip per supplier,
   with a distinct dashed "not yet assigned" state so an empty cell doesn't
   read as a blank/broken one. */
.order-suppliers { display: flex; flex-wrap: wrap; gap: 4px; max-width: 200px; }
.supplier-pill {
  display: inline-block; padding: 2px 9px; border-radius: 20px; font-size: 0.76rem; font-weight: 600;
  background: #eef2f8; color: var(--primary); white-space: nowrap;
}
.supplier-pill-empty {
  display: inline-flex; align-items: center; gap: 5px; font-size: 0.78rem; color: var(--admin-muted);
  border: 1px dashed var(--admin-border); border-radius: 20px; padding: 2px 9px 2px 7px;
}
.supplier-pill-empty::before { content: ''; width: 5px; height: 5px; border-radius: 50%; background: var(--admin-border); }
.admin-table { width: 100%; border-collapse: collapse; }
.admin-table th { text-align: left; padding: 10px 12px; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--admin-muted); border-bottom: 1px solid var(--admin-border); }
.admin-table td { text-align: left; padding: 12px; border-bottom: 1px solid var(--admin-border); font-size: 0.92rem; vertical-align: middle; }
.admin-table tr:last-child td { border-bottom: none; }
.admin-table tbody tr:hover { background: var(--admin-bg); }
.admin-table .col-actions { text-align: right; white-space: nowrap; }

/* Sortable column headers — click to sort, click again to reverse */
.admin-table-sortable th[data-sort] {
  cursor: pointer; user-select: none; white-space: nowrap;
  transition: color 0.15s ease;
}
.admin-table-sortable th[data-sort]:hover { color: var(--primary); }
.admin-table-sortable th[data-sort]::after {
  content: '\2195'; margin-left: 5px; opacity: 0.32; font-size: 0.8em;
}
.admin-table-sortable th[data-sort].is-sorted-asc::after { content: '\2191'; opacity: 1; color: var(--primary); }
.admin-table-sortable th[data-sort].is-sorted-desc::after { content: '\2193'; opacity: 1; color: var(--primary); }

.admin-requests-cell { display: inline-flex; align-items: center; gap: 7px; font-family: var(--font-mono); font-size: 0.88rem; }
.admin-top-badge {
  display: inline-flex; align-items: center; padding: 1px 8px; border-radius: 20px;
  background: rgba(16,58,104,0.16); color: #16497f;
  font-family: var(--font-display); font-size: 0.66rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
}

.admin-badge { display: inline-block; padding: 3px 10px; border-radius: 20px; font-size: 0.75rem; font-weight: 700; }
.admin-badge-owner { background: #e8f0fe; color: var(--primary); }
.admin-badge-product_manager { background: #fff4e5; color: #a86a1c; }
.admin-badge-admin { background: #fdeaea; color: #a91b1b; }

/* Active/Hidden status pill (products, services, industries) */
.admin-status { display: inline-flex; align-items: center; gap: 6px; padding: 4px 11px; border-radius: 20px; font-size: 0.78rem; font-weight: 700; }
.admin-status::before { content: ""; width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.admin-status.is-active { background: #e6f4ea; color: #1a7a3d; }
.admin-status.is-active::before { background: #1a7a3d; }
.admin-status.is-hidden { background: #f1f2f4; color: #6b7280; }
.admin-status.is-hidden::before { background: #9ca3af; }

/* Extra status pill colours shared by lead / order / billing states — same
   dot-and-pill shape as the active/hidden pair above, just more of them. */
.admin-status.is-new       { background: #e8f0fe; color: var(--primary); }
.admin-status.is-new::before       { background: var(--primary); }
.admin-status.is-contacted { background: #fff4e5; color: #a86a1c; }
.admin-status.is-contacted::before { background: #c9903f; }
.admin-status.is-converted,
.admin-status.is-fulfilled,
.admin-status.is-paid      { background: #e6f4ea; color: #1a7a3d; }
.admin-status.is-converted::before,
.admin-status.is-fulfilled::before,
.admin-status.is-paid::before      { background: #1a7a3d; }
.admin-status.is-lost,
.admin-status.is-cancelled { background: #fde8e8; color: #a91b1b; }
.admin-status.is-lost::before,
.admin-status.is-cancelled::before { background: #a91b1b; }
.admin-status.is-pending   { background: #fff4e5; color: #a86a1c; }
.admin-status.is-pending::before   { background: #c9903f; }
.admin-status.is-confirmed { background: #e8f0fe; color: var(--primary); }
.admin-status.is-confirmed::before { background: var(--primary); }
.admin-status.is-invoiced  { background: #e8f0fe; color: var(--primary); }
.admin-status.is-invoiced::before  { background: var(--primary); }
.admin-status.is-unbilled  { background: #f1f2f4; color: #6b7280; }
.admin-status.is-unbilled::before  { background: #9ca3af; }

/* Inline status <select> styled to look like the pill it's replacing, so a
   changeable status reads the same as a static one until you hover it. */
.admin-status-select {
  appearance: none; -webkit-appearance: none; border: none; cursor: pointer;
  font: inherit; font-weight: 700; font-size: 0.78rem;
  padding: 4px 24px 4px 11px; border-radius: 20px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 6px center; background-size: 12px;
}
.admin-status-select.is-new       { background-color: #e8f0fe; color: var(--primary); }
.admin-status-select.is-contacted,
.admin-status-select.is-pending   { background-color: #fff4e5; color: #a86a1c; }
.admin-status-select.is-converted,
.admin-status-select.is-fulfilled,
.admin-status-select.is-paid      { background-color: #e6f4ea; color: #1a7a3d; }
.admin-status-select.is-lost,
.admin-status-select.is-cancelled { background-color: #fde8e8; color: #a91b1b; }
.admin-status-select.is-confirmed,
.admin-status-select.is-invoiced  { background-color: #e8f0fe; color: var(--primary); }
.admin-status-select.is-unbilled  { background-color: #f1f2f4; color: #6b7280; }

/* Order line-item editor rows inside the order modal */
.order-items-editor { border: 1px solid var(--admin-border); border-radius: 8px; overflow: hidden; margin-bottom: 8px; }
.order-item-row {
  display: grid; grid-template-columns: 2fr 0.8fr 0.6fr 0.8fr 0.9fr 1.2fr auto;
  gap: 8px; padding: 10px; align-items: center;
  border-bottom: 1px solid var(--admin-border); background: #fff;
}
.order-item-row:last-child { border-bottom: none; }
.order-item-row input, .order-item-row select {
  width: 100%; padding: 8px 10px; border: 1px solid var(--border); border-radius: 6px;
  font-size: 0.86rem; font-family: inherit; background: var(--bg-page);
}
.order-item-row input:focus, .order-item-row select:focus { outline: none; border-color: var(--primary); background: #fff; }
.order-item-remove {
  width: 28px; height: 28px; border-radius: 6px; border: 1px solid var(--admin-border);
  background: #fff; color: var(--admin-muted); cursor: pointer; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.order-item-remove:hover { background: #fef2f2; color: #a91b1b; border-color: #a91b1b; }
.order-item-remove svg { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 2; }
.order-items-head {
  display: grid; grid-template-columns: 2fr 0.8fr 0.6fr 0.8fr 0.9fr 1.2fr auto; gap: 8px; padding: 0 10px 6px;
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--admin-muted);
}
.order-items-total {
  display: flex; justify-content: flex-end; gap: 10px; align-items: baseline;
  padding: 12px 4px 0; font-size: 0.92rem;
}
.order-items-total strong { font-family: var(--font-mono); font-size: 1.15rem; color: var(--primary-dark); }
@media (max-width: 720px) {
  .order-items-head { display: none; }
  .order-item-row { grid-template-columns: 1fr 1fr; grid-auto-rows: auto; }
  .order-item-row > *:first-child { grid-column: 1 / -1; }
}

/* Icon action buttons in table rows */
.admin-action-btns { display: flex; gap: 6px; justify-content: flex-end; }
.admin-action-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 7px;
  border: 1px solid var(--admin-border); background: #fff; color: var(--admin-muted);
  transition: 0.15s ease; cursor: pointer;
}
.admin-action-btn svg { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.admin-action-btn:hover { background: var(--admin-bg); color: var(--primary); border-color: var(--primary); }
.admin-action-btn.danger:hover { background: #fef2f2; color: #a91b1b; border-color: #a91b1b; }
.admin-action-btn.transport-ready { background: #fef2f2; color: #d92d20; border-color: #fecdca; }
.admin-action-btn.transport-ready:hover { background: #d92d20; color: #fff; border-color: #d92d20; }
.admin-action-btn.transport-transit { background: #ecfdf3; color: #1a9e5c; border-color: #abefc6; }
.admin-action-btn.transport-transit:hover { background: #1a9e5c; color: #fff; border-color: #1a9e5c; }

/* Cleaner add-item form: label + control on one row for checkboxes */
.form-check-row { display: flex; align-items: center; gap: 10px; margin-bottom: 20px; }
.form-check-row input[type="checkbox"] { width: 17px; height: 17px; accent-color: var(--primary); cursor: pointer; }
.form-check-row label { font-weight: 600; font-size: 0.92rem; cursor: pointer; margin: 0; }

.alert { padding: 12px 16px; border-radius: 8px; margin-bottom: 16px; }
.alert-error { background: #fde8e8; color: #a91b1b; }
.alert-success { background: #e6f4ea; color: #1a7a3d; }
.qv-order-cta { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.qv-order-cta form { flex-shrink: 0; }

/* Table pagination */
.admin-pagination { display: flex; gap: 6px; justify-content: center; margin-top: 20px; flex-wrap: wrap; }
.admin-page-btn {
  min-width: 34px; height: 34px; padding: 0 10px;
  border: 1px solid var(--admin-border); border-radius: 6px; background: #fff;
  color: var(--admin-ink); font-size: 0.85rem; cursor: pointer; transition: 0.15s ease;
}
.admin-page-btn:hover:not(:disabled) { border-color: var(--primary); color: var(--primary); }
.admin-page-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.admin-page-btn.active { background: var(--primary); border-color: var(--primary); color: #fff; }

/* Add/Edit modal dialog */
.admin-modal-backdrop {
  display: none; position: fixed; inset: 0; z-index: 300;
  background: rgba(15,18,22,0.55);
  align-items: flex-start; justify-content: center;
  padding: 5vh 20px; overflow-y: auto;
}
.admin-modal-backdrop.open { display: flex; }
.admin-modal {
  background: #fff; border-radius: 10px; width: 100%; max-width: 560px;
  box-shadow: 0 20px 50px rgba(0,0,0,0.25);
  animation: adminModalIn 0.18s ease;
}
@keyframes adminModalIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } }
.admin-modal-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 24px; border-bottom: 1px solid var(--admin-border);
}
.admin-modal-header h3 { font-size: 1.05rem; font-weight: 700; }
.admin-modal-close {
  width: 30px; height: 30px; border-radius: 6px; border: none; background: transparent;
  display: flex; align-items: center; justify-content: center; cursor: pointer; color: var(--admin-muted);
}
.admin-modal-close:hover { background: var(--admin-bg); color: var(--admin-ink); }
.admin-modal-close svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; }
.admin-modal-body { padding: 22px 24px; max-height: 65vh; overflow-y: auto; }
.admin-modal-footer {
  display: flex; justify-content: flex-end; gap: 10px;
  padding: 16px 24px; border-top: 1px solid var(--admin-border);
}
@media (prefers-reduced-motion: reduce) {
  .admin-modal { animation: none; }
}

/* Settings live-preview split view */
.admin-wrap-preview { max-width: none; }
.preview-layout { display: grid; grid-template-columns: 480px 1fr; gap: 28px; align-items: start; }
.preview-form-col { max-height: calc(100vh - 90px); overflow-y: auto; padding-right: 6px; }
.preview-toolbar { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 16px; }
.preview-device-toggle { display: flex; align-items: center; gap: 6px; font-size: 0.85rem; color: var(--admin-muted); white-space: nowrap; cursor: pointer; }

.preview-frame-col { position: sticky; top: 16px; }
.preview-frame-wrap {
  border: 1px solid var(--admin-border);
  border-radius: 14px;
  overflow: hidden;
  background: #fff;
  box-shadow: 0 4px 16px rgba(0,0,0,0.06);
  height: calc(100vh - 90px);
  transition: max-width 0.25s ease;
  margin: 0 auto;
}
.preview-frame-wrap iframe { width: 100%; height: 100%; border: 0; display: block; }
.preview-frame-wrap.mobile { max-width: 400px; }

@media (max-width: 1200px) {
  .preview-layout { grid-template-columns: 1fr; }
  .preview-frame-col { position: static; }
  .preview-frame-wrap, .preview-form-col { height: 70vh; max-height: none; }
}

/* Below 900px the sidebar can't stay pinned open (there's no room for it
   alongside content), so it becomes a slide-in drawer over the page instead
   of just disappearing — the hamburger button in the topbar opens it, same
   pattern as the public site's mobile nav. */
@media (max-width: 900px) {
  .admin-topbar, .admin-wrap, .admin-content-header { margin-left: 0; }
  .admin-sidebar {
    transform: translateX(-100%);
    transition: transform 0.25s cubic-bezier(0.22, 0.8, 0.3, 1);
    z-index: 500;
    box-shadow: 0 0 0 transparent;
  }
  body.admin-sidebar-open .admin-sidebar {
    transform: translateX(0);
    box-shadow: 8px 0 32px rgba(0,0,0,0.28);
  }
  /* Collapsed-to-icons only makes sense as a permanent desktop rail; on a
     drawer it's just a smaller drawer with no label text, so ignore it. */
  body.sidebar-collapsed .admin-sidebar { width: var(--admin-sidebar-w); }
  body.sidebar-collapsed .admin-sidebar-brand-text,
  body.sidebar-collapsed .admin-nav-label,
  body.sidebar-collapsed .admin-nav-text { display: block; }
  body.sidebar-collapsed .admin-sidebar-nav a,
  body.sidebar-collapsed .admin-sidebar-footer a { justify-content: flex-start; }
  /* Repurposed as a close (×) button while the drawer is open, rather than
     the desktop collapse chevron. */
  .admin-sidebar-collapse-btn svg { transform: none !important; }
  .admin-sidebar-backdrop {
    position: fixed; inset: 0; z-index: 490;
    background: rgba(6,11,24,0.45);
    opacity: 0; pointer-events: none;
    transition: opacity 0.25s ease;
  }
  body.admin-sidebar-open .admin-sidebar-backdrop { opacity: 1; pointer-events: auto; }
  body.admin-sidebar-open { overflow: hidden; }
}

/* Quote requests inbox */
.admin-nav-badge {
  margin-left: auto;
  background: var(--brand-accent); color: var(--brand-accent-ink);
  font-family: var(--font-mono); font-size: 0.68rem; font-weight: 800;
  min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px;
  display: inline-flex; align-items: center; justify-content: center;
}
body.sidebar-collapsed .admin-nav-badge { display: none; }

.quote-inbox { display: flex; flex-direction: column; gap: 12px; }
.quote-row {
  border: 1px solid var(--border);
  border-left: 3px solid var(--border);
  border-radius: 10px;
  padding: 16px 18px;
  background: var(--white);
}
.quote-row.is-unread { border-left-color: var(--brand-accent); background: #f7fafd; }
.quote-row-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 8px; }
.quote-row-product { font-weight: 700; color: var(--primary-dark); font-size: 0.98rem; }
.quote-row-product.is-general { color: var(--text-muted); font-style: italic; font-weight: 600; }
.quote-row-date { display: block; font-family: var(--font-mono); font-size: 0.74rem; color: var(--text-muted); margin-top: 3px; }
.quote-row-meta { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 0.88rem; color: var(--text-muted); }
.quote-row-meta strong { color: var(--text); }
.quote-row-meta a { color: var(--primary-mid); }
.quote-row-meta a:hover { text-decoration: underline; }
.quote-qty { font-family: var(--font-mono); font-size: 0.82rem; color: var(--primary-dark); }
.quote-row-message {
  margin-top: 10px; padding-top: 10px;
  border-top: 1px solid var(--border);
  font-size: 0.9rem; color: var(--text); white-space: pre-line;
}

/* Lead lifecycle strip at the bottom of each quote row — status control on
   one side, the convert-to-customer / order shortcuts on the other. */
.quote-row-lead-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border);
}
.quote-row-lead-bar form { margin: 0; }

/* Visitor report: range tabs, bar rows, and the two mini charts */
.admin-range-tabs { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 20px; }
.admin-range-tabs a {
  padding: 8px 16px; border-radius: 30px; font-size: 0.88rem; font-weight: 600;
  background: var(--white); border: 1px solid var(--border); color: var(--text);
  transition: 0.15s ease;
}
.admin-range-tabs a:hover { border-color: var(--primary); color: var(--primary); }
.admin-range-tabs a.active { background: var(--primary); border-color: var(--primary); color: var(--white); }

.admin-two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start; }
@media (max-width: 900px) { .admin-two-col { grid-template-columns: 1fr; } }

.stat-bar-row { display: grid; grid-template-columns: 150px 1fr 48px; align-items: center; gap: 12px; margin-bottom: 9px; }
.stat-bar-label { font-size: 0.88rem; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stat-bar-track { height: 8px; border-radius: 4px; background: var(--bg-light); overflow: hidden; }
.stat-bar-fill { display: block; height: 100%; border-radius: 4px; background: var(--primary); }
.stat-bar-value { font-family: var(--font-mono); font-size: 0.84rem; font-weight: 700; text-align: right; color: var(--primary-dark); }
@media (max-width: 560px) { .stat-bar-row { grid-template-columns: 110px 1fr 40px; } }

.daily-chart, .hour-chart { display: flex; align-items: flex-end; gap: 6px; height: 160px; padding-top: 10px; }
.hour-chart { gap: 3px; height: 120px; }
.daily-col, .hour-col { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; }
.daily-bar, .hour-bar { width: 100%; max-width: 42px; border-radius: 4px 4px 0 0; background: var(--primary); transition: background 0.15s ease; }
.hour-bar { background: var(--primary-mid); max-width: none; }
.daily-col:hover .daily-bar, .hour-col:hover .hour-bar { background: var(--brand-accent); }
.daily-label, .hour-label {
  font-family: var(--font-mono); font-size: 0.68rem; color: var(--text-muted);
  margin-top: 6px; white-space: nowrap;
}

/* Multi-product tags in the quote inbox */
.quote-row-items { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }
.quote-item-tag {
  background: var(--bg-light); border: 1px solid var(--border);
  border-radius: 20px; padding: 3px 10px;
  font-size: 0.78rem; font-weight: 600; color: var(--primary-dark);
}

/* Quantity chips in the quote inbox */
.quote-item-tag strong {
  margin-left: 6px; padding-left: 7px;
  border-left: 1px solid var(--border);
  font-family: var(--font-mono); font-size: 0.74rem; color: var(--primary-mid);
}
.quote-item-qtytag {
  margin-left: 8px; padding: 2px 9px; border-radius: 20px;
  background: var(--bg-light); border: 1px solid var(--border);
  font-family: var(--font-mono); font-size: 0.76rem; font-weight: 700; color: var(--primary-mid);
}

/* "Remembered on this device" affordances on the enquiry forms */
.remember-note {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  background: rgba(16,58,104,0.1); border: 1px solid rgba(16,58,104,0.3);
  border-radius: 8px; padding: 7px 12px; margin-bottom: 12px;
  font-size: 0.82rem; color: var(--text-muted);
}
.remember-note[hidden] { display: none; }
.remember-clear {
  border: none; background: none; padding: 0; cursor: pointer;
  font-family: inherit; font-size: inherit; font-weight: 700;
  color: var(--primary-mid); text-decoration: underline;
}
.remember-clear:hover { color: var(--primary); }
.remember-toggle {
  display: flex; align-items: flex-start; gap: 9px;
  margin: 2px 0 12px;
  font-size: 0.82rem; color: var(--text-muted); cursor: pointer;
}
.remember-toggle input { margin-top: 3px; flex-shrink: 0; accent-color: var(--brand-accent); cursor: pointer; }

/* ---- Scroll-driven motion ---- */

/* Read-progress bar along the bottom edge of the sticky header */
.scroll-progress {
  position: absolute; left: 0; right: 0; bottom: -1px;
  height: 2px; background: var(--brand-accent);
  transform: scaleX(0); transform-origin: 0 50%;
  will-change: transform;
  pointer-events: none;
}

/* Parallax layers are transformed every frame — promote them so the browser
   composites rather than repainting, and stop the transform fighting layout. */
.hex-watermark, .hero-formulas { will-change: transform; }
.hero-content { will-change: transform, opacity; }

/* The eyebrow's rule draws itself in when its block enters view, so each
   section announces itself rather than simply appearing. */
.eyebrow::before { transition: width 0.6s cubic-bezier(0.22, 0.8, 0.3, 1) 0.15s; }
.reveal .eyebrow::before, .reveal.eyebrow::before { width: 0; }
.reveal.in-view .eyebrow::before, .reveal.eyebrow.in-view::before { width: 24px; }

/* Cards lift in with a touch of scale so a grid feels like it settles into
   place rather than sliding as one flat sheet. */
.feature-card.reveal, .service-card.reveal, .industry-card.reveal, .quality-card.reveal {
  transform: translateY(26px) scale(0.985);
}
.feature-card.reveal.in-view, .service-card.reveal.in-view,
.industry-card.reveal.in-view, .quality-card.reveal.in-view {
  transform: translateY(0) scale(1);
}

@media (prefers-reduced-motion: reduce) {
  .eyebrow::before { transition: none; }
  .reveal .eyebrow::before, .reveal.eyebrow::before { width: 24px; }
  .hex-watermark, .hero-formulas, .hero-content { will-change: auto; }
  .feature-card.reveal, .service-card.reveal, .industry-card.reveal, .quality-card.reveal { transform: none; }
}

/* Visitors who ask for reduced motion bypass the eased-scroll script entirely,
   so the CSS smooth scroll has to be turned off too — otherwise they still get
   a long animated travel, which is exactly what they opted out of. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

/* ---------------------------------------------------------------------------
   Back-to-top — the ring around the arrow fills in step with how far down the
   page you are, so it doubles as a position readout. Shares the bottom-left
   corner with WhatsApp (the right corner is the assistant's), and stacks above
   it when both are on screen.
   --------------------------------------------------------------------------- */
.to-top {
  position: fixed; left: 24px; bottom: 24px; z-index: 210;
  width: 48px; height: 48px; padding: 0;
  border: 1px solid var(--border); border-radius: 50%;
  background: var(--white); color: var(--primary-dark);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 8px 20px rgba(6, 11, 24, 0.16);
  cursor: pointer;
  opacity: 0; visibility: hidden; transform: translateY(12px) scale(0.9);
  transition: opacity 0.25s ease, transform 0.25s cubic-bezier(0.22, 0.8, 0.3, 1),
              visibility 0.25s, box-shadow 0.2s ease, background 0.2s ease;
}
.to-top.has-wa { bottom: 96px; }
.to-top.is-visible { opacity: 1; visibility: visible; transform: none; }
.to-top:hover { background: var(--primary-dark); color: var(--white); box-shadow: 0 12px 26px rgba(6, 11, 24, 0.26); }

.to-top-ring { position: absolute; inset: -1px; width: calc(100% + 2px); height: calc(100% + 2px); transform: rotate(-90deg); }
.to-top-ring circle { fill: none; stroke-width: 2.5; }
.to-top-track { stroke: rgba(22, 48, 92, 0.12); }
.to-top-bar {
  stroke: var(--brand-accent); stroke-linecap: round;
  /* 2πr for r=21 — the offset is written by main.js each scroll frame. */
  stroke-dasharray: 131.95;
  stroke-dashoffset: 131.95;
  transition: stroke-dashoffset 0.1s linear;
}
.to-top-arrow { width: 19px; height: 19px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }

@media (max-width: 860px) {
  .to-top { width: 44px; height: 44px; left: 18px; bottom: 18px; }
  .to-top.has-wa { bottom: 78px; }
  .to-top-arrow { width: 17px; height: 17px; }
}
/* Below 560px the quote basket spans the full width just above the WhatsApp
   button, so stacking here would collide — sit beside WhatsApp instead. */
@media (max-width: 560px) {
  .to-top.has-wa { bottom: 18px; left: 82px; }
}
@media (prefers-reduced-motion: reduce) {
  .to-top { transition: opacity 0.2s ease, visibility 0.2s; transform: none; }
  .to-top-bar { transition: none; }
}

/* Arriving at a section from the nav: its content eases up into place in a short
   cascade while the page settles onto it, so landing reads as the section being
   presented rather than the scroll simply stopping. */
@keyframes sectionArrive {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: none; }
}
section[id].is-arriving > .container > *,
section[id].is-arriving > .cta > * {
  /* `backwards` holds the start frame through the delay, so staggered children
     stay hidden until their turn instead of flashing in first. */
  animation: sectionArrive 0.55s cubic-bezier(0.22, 0.8, 0.3, 1) backwards;
}
section[id].is-arriving > .container > *:nth-child(1) { animation-delay: 0.04s; }
section[id].is-arriving > .container > *:nth-child(2) { animation-delay: 0.13s; }
section[id].is-arriving > .container > *:nth-child(3) { animation-delay: 0.20s; }
section[id].is-arriving > .container > *:nth-child(n+4) { animation-delay: 0.26s; }

/* The eyebrow rule redraws itself as the section lands — the same gesture the
   section uses when scrolled to normally, so the two entrances match. */
section[id].is-arriving .eyebrow::before {
  animation: eyebrowDraw 0.6s cubic-bezier(0.22, 0.8, 0.3, 1) 0.18s backwards;
}
@keyframes eyebrowDraw {
  from { width: 0; }
  to   { width: 24px; }
}

/* The catalog header is a fixed-height band, not a .container-based section. */
#products.is-arriving > .container > * { animation-delay: 0.04s; }

@media (prefers-reduced-motion: reduce) {
  section[id].is-arriving > .container > *,
  section[id].is-arriving > .cta > *,
  section[id].is-arriving .eyebrow::before { animation: none; }
}

/* ---- Admin dashboard ---- */
.dash-greeting {
  display: flex; align-items: flex-end; justify-content: space-between;
  flex-wrap: wrap; gap: 16px; margin-bottom: 22px;
}
.dash-greeting h2 { font-size: 1.5rem; font-weight: 700; color: var(--admin-ink); }
.dash-greeting p { color: var(--admin-muted); font-size: 0.88rem; margin-top: 2px; }
.dash-greeting-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.dash-greeting-actions .btn { padding: 10px 20px; font-size: 0.9rem; }

/* Stat boxes are links now — the number should take you to the detail behind it */
.admin-small-box { display: block; text-decoration: none; transition: transform 0.18s ease, box-shadow 0.18s ease; }
.admin-small-box:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(16,24,40,0.10); border-color: var(--box-accent, var(--admin-border)); }
.admin-small-box[disabled] { cursor: default; opacity: 0.7; }
.admin-small-box[disabled]:hover { transform: none; box-shadow: 0 1px 3px rgba(0,0,0,0.12); }

.dash-columns { display: grid; grid-template-columns: 1.55fr 1fr; gap: 24px; align-items: start; }
@media (max-width: 1180px) { .dash-columns { grid-template-columns: 1fr; } }

/* Card header with a title, a one-line explanation, and a corner action */
.admin-card-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 10px 16px;
  flex-wrap: wrap;
  margin-bottom: 16px; padding-bottom: 14px; border-bottom: 1px solid var(--admin-border);
}
.admin-card-head h3 { margin: 0; }
.admin-card-sub { color: var(--admin-muted); font-size: 0.82rem; margin-top: 3px; }
.admin-card-link { font-size: 0.82rem; font-weight: 600; color: var(--primary); white-space: nowrap; }
.admin-card-link:hover { text-decoration: underline; }
.admin-empty { color: var(--admin-muted); font-size: 0.9rem; }

/* Inline bar inside the search table, so ranking is readable at a glance */
.dash-bar-cell { display: flex; align-items: center; gap: 12px; }
.dash-bar { flex: 1; height: 7px; border-radius: 4px; background: var(--bg-light); overflow: hidden; }
.dash-bar span { display: block; height: 100%; border-radius: 4px; background: var(--primary); }
.dash-bar-cell strong { font-family: var(--font-mono); font-size: 0.85rem; min-width: 26px; text-align: right; }

.dash-taglist { display: flex; flex-wrap: wrap; gap: 8px; }
.dash-tag {
  display: inline-flex; align-items: center; gap: 8px;
  background: #fff7ed; border: 1px solid #f0d5ae; border-radius: 20px;
  padding: 6px 8px 6px 14px; font-size: 0.85rem; font-weight: 600; color: #8a5a1a;
}
.dash-tag strong {
  background: var(--brand-accent); color: var(--brand-accent-ink);
  font-family: var(--font-mono); font-size: 0.72rem;
  border-radius: 12px; padding: 1px 8px;
}

.dash-feed { display: flex; flex-direction: column; }
.dash-feed li { padding: 12px 0; border-bottom: 1px solid var(--admin-border); }
.dash-feed li:last-child { border-bottom: none; padding-bottom: 0; }
.dash-feed li:first-child { padding-top: 0; }
.dash-feed-top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.dash-feed-title { font-weight: 600; color: var(--admin-ink); font-size: 0.9rem; }
.dash-feed-time { font-family: var(--font-mono); font-size: 0.74rem; color: var(--admin-muted); white-space: nowrap; }
.dash-feed-meta { display: block; color: var(--admin-muted); font-size: 0.82rem; margin-top: 3px; }
/* Unread enquiries carry the same amber marker as the inbox */
.dash-feed li.is-unread .dash-feed-title { position: relative; padding-left: 14px; }
.dash-feed li.is-unread .dash-feed-title::before {
  content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 7px; height: 7px; border-radius: 50%; background: var(--brand-accent);
}

.dash-links { display: flex; flex-direction: column; }
/* Some of these trigger a state change (mark read, delete) rather than
   navigating, so they're <button type="submit"> inside a form, not <a> — the
   reset here makes a button match the link styling exactly. */
.dash-links button {
  all: unset; box-sizing: border-box; width: 100%; cursor: pointer; font: inherit; color: inherit;
}
.dash-links a,
.dash-links button {
  display: flex; flex-direction: column; gap: 2px;
  padding: 11px 12px; margin: 0 -12px; border-radius: 6px;
  font-weight: 600; color: var(--admin-ink); font-size: 0.9rem;
  transition: background 0.15s ease;
}
.dash-links a span,
.dash-links button span { font-weight: 400; color: var(--admin-muted); font-size: 0.79rem; }
.dash-links a:hover,
.dash-links button:hover { background: var(--bg-page); color: var(--primary); }

/* ---- Quote requests: inbox table + single-request view ---- */
.qv-search { display: flex; align-items: center; gap: 8px; }
.qv-search input[type="search"] {
  width: 260px; padding: 8px 13px; font-size: 0.87rem;
  border: 1px solid var(--admin-border); border-radius: 8px; font-family: inherit;
}
.qv-search .btn { padding: 8px 16px; font-size: 0.85rem; }
.qv-clear { font-size: 0.82rem; color: var(--admin-muted); }
.qv-clear:hover { text-decoration: underline; }

.qv-tabs { margin: 0 0 18px; }
.qv-tabs a { display: inline-flex; align-items: center; gap: 8px; padding: 7px 14px; font-size: 0.85rem; }
.qv-tab-count {
  background: var(--bg-light); color: var(--admin-muted);
  font-family: var(--font-mono); font-size: 0.7rem; font-weight: 700;
  border-radius: 10px; padding: 1px 7px;
}
.qv-tabs a.active .qv-tab-count { background: rgba(255,255,255,0.22); color: #fff; }

.qv-table tbody tr { cursor: pointer; }
.qv-table tbody tr:hover { background: var(--bg-page); }
.qv-row.is-unread .qv-subject { font-weight: 800; }
.qv-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--brand-accent); }
.qv-subject { font-weight: 600; color: var(--admin-ink); }
.qv-subject:hover { color: var(--primary); text-decoration: underline; }
.qv-itemline { display: flex; flex-wrap: wrap; gap: 4px 10px; margin-top: 4px; font-size: 0.78rem; color: var(--admin-muted); }
.qv-itemline span::after { content: ''; }
.qv-more { font-weight: 700; color: var(--primary); }
.qv-qty-updated { color: #a86a1c; font-weight: 600; cursor: help; }
.qv-from-name { display: block; font-weight: 600; font-size: 0.88rem; }
.qv-from-co { display: block; font-size: 0.79rem; color: var(--admin-muted); }
.qv-date { display: block; font-size: 0.85rem; }
.qv-ago-sm { display: block; font-size: 0.74rem; color: var(--admin-muted); }

/* Single request view */
.qv-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 16px; }
.qv-back { font-size: 0.87rem; font-weight: 600; color: var(--primary); }
.qv-back:hover { text-decoration: underline; }
.qv-pager { display: flex; gap: 14px; font-size: 0.84rem; }
.qv-pager a { color: var(--primary); font-weight: 600; }
.qv-pager a:hover { text-decoration: underline; }
.qv-pager span { color: #c3c9d2; }

.qv-header {
  display: flex; align-items: flex-start; justify-content: space-between;
  flex-wrap: wrap; gap: 16px; margin-bottom: 22px;
}
.qv-title-row { display: flex; align-items: center; gap: 12px; }
.qv-title-row h2 { font-size: 1.5rem; font-weight: 700; color: var(--admin-ink); }
.qv-received { color: var(--admin-muted); font-size: 0.87rem; margin-top: 4px; }
.qv-ago { color: #98a1ad; }
.qv-header-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.qv-header-actions .btn { padding: 10px 20px; font-size: 0.88rem; }

.qv-grid { display: grid; grid-template-columns: 1.6fr 1fr; gap: 24px; align-items: start; }
@media (max-width: 1100px) { .qv-grid { grid-template-columns: 1fr; } }

.qv-qty { font-family: var(--font-mono); font-weight: 700; color: var(--admin-ink); }
.qv-qty span { color: var(--admin-muted); font-weight: 600; font-size: 0.85em; }
.qv-qty-note { display: block; font-size: 0.72rem; color: #a86a1c; font-weight: 500; margin-top: 2px; }
.qv-freeqty { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--admin-border); }
.qv-label {
  display: block; font-family: var(--font-mono); font-size: 0.66rem;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--admin-muted); margin-bottom: 5px;
}
.qv-message {
  background: var(--bg-page); border-left: 3px solid var(--brand-accent);
  border-radius: 0 8px 8px 0; padding: 16px 18px;
  font-size: 0.93rem; line-height: 1.7; color: var(--admin-ink);
}

.qv-contact { display: grid; grid-template-columns: 92px 1fr; gap: 10px 12px; align-items: baseline; }
.qv-contact dt {
  font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--admin-muted);
}
.qv-contact dd { font-size: 0.9rem; color: var(--admin-ink); word-break: break-word; }
.qv-contact dd a { color: var(--primary); }
.qv-contact dd a:hover { text-decoration: underline; }
.qv-wa { display: inline-block; margin-left: 8px; font-size: 0.78rem; font-weight: 700; color: #128C7E; }

.dash-links a.is-danger,
.dash-links button.is-danger { color: #b23c34; }
.dash-links a.is-danger:hover,
.dash-links button.is-danger:hover { background: #fff5f4; color: #8f2e27; }

/* Status pills shared by the inbox and the detail view */
.admin-status.is-new { background: #e8effa; color: #24447a; }
.admin-status.is-contacted { background: #fff3e0; color: #8a5a1a; }
.admin-status.is-converted { background: #e4f6ec; color: #1a7a45; }
.admin-status.is-lost { background: #f2f3f5; color: #6b7280; }

/* ---- Contact: map beside details, actions instead of an inline form ---- */
.contact-split {
  display: grid; grid-template-columns: 1.15fr 1fr;
  background: var(--white); border: 1px solid var(--border);
  border-radius: 16px; overflow: hidden;
  box-shadow: 0 14px 40px rgba(22,48,92,0.08);
}
@media (max-width: 900px) { .contact-split { grid-template-columns: 1fr; } }

.contact-map { position: relative; min-height: 420px; background: var(--bg-light); }
.contact-map iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.contact-map-btn {
  position: absolute; left: 16px; bottom: 16px; z-index: 1;
  background: var(--white); border: 1px solid var(--border); border-radius: 8px;
  padding: 9px 16px; font-size: 0.84rem; font-weight: 700; color: var(--primary-dark);
  box-shadow: 0 4px 14px rgba(0,0,0,0.14);
}
.contact-map-btn:hover { background: var(--primary); color: var(--white); border-color: var(--primary); }
@media (max-width: 900px) { .contact-map { min-height: 300px; } }

.contact-details { padding: 40px 38px; display: flex; flex-direction: column; }
@media (max-width: 560px) { .contact-details { padding: 28px 22px; } }
.contact-address {
  font-family: var(--font-display); font-size: 1.12rem; font-weight: 700;
  line-height: 1.55; color: var(--primary-dark); margin-bottom: 22px;
}
.contact-lines { display: flex; flex-direction: column; gap: 13px; margin-bottom: 26px; }
.contact-lines li { display: flex; align-items: center; gap: 12px; font-size: 0.94rem; color: var(--text); }
.contact-line-icon {
  flex-shrink: 0; width: 34px; height: 34px; border-radius: 9px;
  background: var(--bg-light); color: var(--primary);
  display: flex; align-items: center; justify-content: center;
}
.contact-line-icon svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 1.9; }
.contact-line-icon.is-wa { background: rgba(37,211,102,0.14); color: #128C7E; }
.contact-lines a { color: var(--text); }
.contact-lines a:hover { color: var(--primary); text-decoration: underline; }

.contact-cta { margin-top: auto; padding-top: 24px; border-top: 1px solid var(--border); }
.contact-cta-label {
  font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text-muted); margin-bottom: 12px;
}
/* Three equal columns, all three cards the same size — a two-column grid
   with the primary action spanning row one read as lopsided rather than
   deliberate, so all three now sit in a single aligned row. */
.contact-cta-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
@media (max-width: 620px) { .contact-cta-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 480px) { .contact-cta-grid { grid-template-columns: 1fr; } }
.contact-cta-btn {
  display: flex; align-items: flex-start; gap: 11px; text-align: left;
  background: var(--white); border: 1px solid var(--border); border-radius: 11px;
  padding: 14px 14px; cursor: pointer; font-family: inherit;
  transition: 0.16s ease;
}
.contact-cta-btn:hover { border-color: var(--primary); box-shadow: 0 8px 20px rgba(22,48,92,0.1); transform: translateY(-2px); }
.contact-cta-btn svg { width: 19px; height: 19px; stroke: var(--primary); fill: none; stroke-width: 1.8; flex-shrink: 0; margin-top: 2px; }
.contact-cta-btn span { display: flex; flex-direction: column; gap: 2px; }
.contact-cta-btn strong { font-size: 0.89rem; font-weight: 700; color: var(--primary-dark); }
.contact-cta-btn span span, .contact-cta-btn strong + * { font-size: 0.78rem; }
.contact-cta-btn span { font-size: 0.78rem; color: var(--text-muted); }

/* ---- Enquiry modal: type selector, panels, product search ---- */
/* One row of 4 instead of a 2x2 grid — was the single biggest contributor
   to the modal needing a scroll on a normal-height screen. Icon-over-label,
   not icon-beside-label: at modal width a horizontal tab has no room left
   for "Request a Quote" once four of them share a row, so the full label
   moved into the button's title/aria-label and the visible text shortened
   to one word each. */
.enq-types { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; margin-bottom: 14px; }
.enq-type {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  background: var(--bg-page); border: 1px solid var(--border); border-radius: 10px;
  padding: 8px 4px; cursor: pointer;
  font-family: inherit; font-size: 0.7rem; font-weight: 600; color: var(--text);
  text-align: center; line-height: 1.15; transition: 0.15s ease;
}
.enq-type svg { width: 16px; height: 16px; stroke: var(--text-muted); fill: none; stroke-width: 1.8; flex-shrink: 0; }
.enq-type:hover { border-color: var(--primary-mid); color: var(--primary); }
.enq-type.is-active { background: var(--primary); border-color: var(--primary); color: var(--white); }
/* Was stroke: var(--brand-accent) — that variable is #103a68, a dark navy
   nearly identical to this active tab's own #16305c background, so the icon
   was rendering essentially invisible (navy-on-navy) rather than the
   high-contrast accent this was presumably going for. currentColor matches
   the "Quote" label right next to it, which already correctly turns white
   here via the .is-active rule above. */
.enq-type.is-active svg { stroke: currentColor; }

.enq-panel[hidden] { display: none; }
.field-hint { font-size: 0.78rem; color: var(--text-muted); margin-top: 5px; }

.prod-search { position: relative; margin-bottom: 10px; }
.prod-search > label {
  display: block; font-weight: 600; font-size: 0.88rem; margin-bottom: 5px; color: var(--text);
}
.prod-search-box { position: relative; }
.prod-search-box svg {
  position: absolute; left: 13px; top: 50%; transform: translateY(-50%);
  width: 16px; height: 16px; stroke: var(--text-muted); fill: none; stroke-width: 1.9; pointer-events: none;
}
.prod-search-box input {
  width: 100%; padding: 10px 14px 10px 38px;
  border: 1px solid var(--border); border-radius: 9px;
  font-size: 0.92rem; font-family: inherit; background: var(--bg-page);
}
.prod-search-box input:focus { outline: none; border-color: var(--primary); background: var(--white); }
.prod-search-results {
  position: absolute; left: 0; right: 0; top: calc(100% + 5px); z-index: 5;
  background: var(--white); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 14px 34px rgba(22,48,92,0.16);
  max-height: 260px; overflow-y: auto; padding: 5px;
}
.prod-search-results[hidden] { display: none; }
.prod-search-results li {
  display: flex; flex-direction: column; gap: 2px;
  padding: 9px 12px; border-radius: 7px; cursor: pointer;
}
.prod-search-results li:hover { background: var(--bg-page); }
.ps-name { font-weight: 600; font-size: 0.88rem; color: var(--primary-dark); }
.ps-meta { font-family: var(--font-mono); font-size: 0.72rem; color: var(--text-muted); }
.prod-search-none { color: var(--text-muted); font-size: 0.85rem; cursor: default !important; }
.prod-search-none:hover { background: none !important; }

/* Enquiry-type badges in the admin inbox and detail view */
.enq-badge {
  display: inline-block; margin-right: 8px; vertical-align: middle;
  font-family: var(--font-mono); font-size: 0.64rem; font-weight: 800;
  letter-spacing: 0.07em; text-transform: uppercase;
  padding: 3px 9px; border-radius: 20px;
}
.enq-badge.is-quote     { background: #e8effa; color: #24447a; }
.enq-badge.is-grievance { background: #fdeceb; color: #b23c34; }
.enq-badge.is-tracking  { background: #e6f4f7; color: #1c6d80; }
.enq-badge.is-general   { background: #f2f3f5; color: #5c6470; }
.qv-reference { margin-top: 6px; font-size: 0.88rem; color: var(--admin-muted); }
.qv-reference strong { font-family: var(--font-mono); color: var(--admin-ink); }

/* ---- Submission toast ---- */
.toast {
  position: fixed; right: 24px; bottom: 24px; z-index: 320;
  display: flex; align-items: flex-start; gap: 13px;
  max-width: 420px; padding: 15px 16px 15px 18px;
  background: var(--white);
  border: 1px solid var(--border);
  border-left: 4px solid var(--primary);
  border-radius: 12px;
  box-shadow: 0 18px 44px rgba(6,11,24,0.22);
  transform: translateY(20px); opacity: 0;
  transition: transform 0.3s cubic-bezier(0.22, 0.8, 0.3, 1), opacity 0.3s ease;
}
.toast.is-visible { transform: translateY(0); opacity: 1; }
.toast p { font-size: 0.9rem; line-height: 1.5; color: var(--text); margin: 0; }
.toast-icon { flex-shrink: 0; margin-top: 1px; }
.toast-icon svg { width: 20px; height: 20px; fill: none; stroke-width: 1.9; }
.toast-success { border-left-color: #1a9e5c; }
.toast-success .toast-icon svg { stroke: #1a9e5c; }
.toast-error { border-left-color: #e5534b; }
.toast-error .toast-icon svg { stroke: #e5534b; }
.toast-close {
  flex-shrink: 0; width: 24px; height: 24px; border-radius: 50%; margin-left: 2px;
  border: none; background: none; cursor: pointer; color: var(--text-muted);
  display: flex; align-items: center; justify-content: center;
  transition: background 0.15s ease, color 0.15s ease;
}
.toast-close:hover { background: var(--bg-light); color: var(--text); }
.toast-close svg { width: 13px; height: 13px; stroke: currentColor; fill: none; stroke-width: 2.2; }
/* Clear of the floating quote basket and the WhatsApp button on small screens */
@media (max-width: 560px) {
  .toast { left: 16px; right: 16px; bottom: 16px; max-width: none; }
}
@media (prefers-reduced-motion: reduce) {
  .toast { transition: none; transform: none; }
}

/* ---- Admin login ---- */
/* The login page has no sidebar, so it must not inherit .admin-wrap's
   sidebar-width left margin — it centres in the viewport instead. */
.login-body { min-height: 100vh; background: var(--admin-bg, #f2f4f7); }
.login-shell {
  min-height: 100vh;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 32px 20px; gap: 18px;
}
.login-card {
  width: 100%; max-width: 400px;
  background: #fff;
  border: 1px solid var(--admin-border);
  border-top: 3px solid var(--primary);
  border-radius: 10px;
  padding: 34px 32px;
  box-shadow: 0 14px 40px rgba(10,23,48,0.1);
}
.login-brand { display: flex; align-items: center; gap: 12px; margin-bottom: 26px; }
.login-logo {
  width: 42px; height: 42px; border-radius: 10px; flex-shrink: 0;
  background: var(--brand-accent); color: var(--brand-accent-ink);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: 1.3rem; font-weight: 800;
}
.login-company { display: block; font-family: var(--font-display); font-weight: 800; font-size: 1rem; color: var(--admin-ink); }
.login-sub {
  display: block; font-family: var(--font-mono); font-size: 0.64rem;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--admin-muted); margin-top: 1px;
}
.login-title { font-size: 1.3rem; font-weight: 700; color: var(--admin-ink); margin-bottom: 20px; }
.login-submit { width: 100%; margin-top: 6px; cursor: pointer; }
.login-foot { font-size: 0.84rem; }
.login-foot a { color: var(--admin-muted); }
.login-foot a:hover { color: var(--primary); text-decoration: underline; }

/* ---- Inventory & invoices ---- */
.num-col { text-align: right; }
.mono { font-family: var(--font-mono); font-size: 0.86rem; }
.is-pos { color: #1a7a45; }
.is-neg { color: #b23c34; }

.inv-name { display: block; font-weight: 600; }
.inv-cat { display: block; font-size: 0.78rem; color: var(--admin-muted); }
.inv-stock { font-family: var(--font-mono); font-weight: 700; }
.inv-stock small { font-weight: 500; color: var(--admin-muted); }
.inv-stock.is-low { color: #8a5a1a; }
.inv-stock.is-out { color: #b23c34; }
.inv-margin { font-weight: 700; color: #1a7a45; }
.inv-margin.is-neg { color: #b23c34; }
.inv-demand { font-family: var(--font-mono); font-weight: 700; color: var(--primary); }
.inv-demand small { font-weight: 500; color: var(--admin-muted); }

/* Month-to-date purchase/sale summary in Cost and Sale — this is the real,
   current figure (what's actually moved this month), so it's the primary
   line, not a faint footnote. The last-known single price still shows
   underneath for reference, in a quieter, smaller line. */
.inv-mtd-primary { display: block; font-size: 0.94rem; font-weight: 700; color: var(--admin-ink); white-space: nowrap; }
.inv-avg { font-weight: 600; color: var(--primary); font-size: 0.82rem; }
.inv-mtd-sub { display: block; font-size: 0.72rem; font-weight: 400; color: var(--admin-muted); margin-top: 2px; }

/* Sortable column headers — plain text by default, colored + arrowed once active */
.inv-sort-link {
  color: inherit; text-decoration: none; font: inherit; letter-spacing: inherit;
  text-transform: inherit; white-space: nowrap;
}
.inv-sort-link:hover { color: var(--primary); }
.inv-sort-link.is-active { color: var(--primary); font-weight: 800; }
.inv-sort-hint { color: var(--admin-border); font-weight: 400; }
.inv-sort-link:hover .inv-sort-hint { color: var(--admin-muted); }

/* Pagination */
.inv-pager { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 16px 4px 4px; flex-wrap: wrap; }
.inv-pager-note { font-size: 0.82rem; color: var(--admin-muted); }
.inv-pager-links { display: flex; align-items: center; gap: 4px; }
.inv-pager-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 30px; height: 30px; padding: 0 6px; border-radius: 7px;
  border: 1px solid var(--admin-border); background: #fff; color: var(--admin-ink);
  font-size: 0.84rem; font-family: var(--font-mono); text-decoration: none;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.inv-pager-btn:hover { background: var(--admin-bg); border-color: var(--primary); }
.inv-pager-btn.is-active { background: var(--primary); border-color: var(--primary); color: #fff; font-weight: 700; }
.inv-pager-btn.is-disabled { opacity: 0.4; pointer-events: none; }
.inv-pager-ellipsis { color: var(--admin-muted); padding: 0 2px; }
.inv-table tbody tr:hover { background: var(--bg-page); }

.mv-reason {
  font-family: var(--font-mono); font-size: 0.66rem; font-weight: 800;
  letter-spacing: 0.06em; text-transform: uppercase;
  padding: 3px 9px; border-radius: 20px;
}
.mv-reason.is-purchase   { background: #e4f6ec; color: #1a7a45; }
.mv-reason.is-sale       { background: #e8effa; color: #24447a; }
.mv-reason.is-adjustment { background: #fff3e0; color: #8a5a1a; }
.mv-reason.is-return     { background: #f2f3f5; color: #5c6470; }
.mv-reason.is-opening    { background: #f2f3f5; color: #5c6470; }

.inv-status {
  display: inline-block; font-size: 0.72rem; font-weight: 700;
  padding: 3px 11px; border-radius: 20px;
}
.inv-status.is-draft     { background: #f2f3f5; color: #5c6470; }
.inv-status.is-sent      { background: #e8effa; color: #24447a; }
.inv-status.is-part_paid { background: #fff3e0; color: #8a5a1a; }
.inv-status.is-paid      { background: #e4f6ec; color: #1a7a45; }
.inv-status.is-overdue   { background: #fdeceb; color: #b23c34; }
.inv-status.is-cancelled { background: #f2f3f5; color: #98a1ad; }

/* Invoice document */
.invoice-sheet { padding: 34px; }
.inv-doc-head { display: flex; justify-content: space-between; gap: 24px; flex-wrap: wrap; padding-bottom: 22px; border-bottom: 2px solid var(--admin-border); }
.inv-doc-label { font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--admin-muted); }
.inv-doc-head h2 { font-size: 1.5rem; font-weight: 800; color: var(--admin-ink); margin: 4px 0 8px; }
.inv-doc-from { text-align: right; font-size: 0.84rem; color: var(--admin-muted); display: flex; flex-direction: column; gap: 2px; }
.inv-doc-from strong { color: var(--admin-ink); font-size: 0.95rem; }
.inv-meta { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 20px; padding: 22px 0; }
.inv-meta strong { font-size: 0.92rem; color: var(--admin-ink); }
.inv-lines { margin-top: 6px; }
.inv-totals { margin-top: 20px; margin-left: auto; max-width: 320px; display: flex; flex-direction: column; gap: 8px; }
.inv-totals div { display: flex; justify-content: space-between; gap: 20px; font-size: 0.9rem; }
.inv-totals span { color: var(--admin-muted); }
.inv-totals strong { font-family: var(--font-mono); color: var(--admin-ink); }
.inv-totals .is-total { padding-top: 10px; border-top: 1px solid var(--admin-border); font-size: 1rem; }
.inv-totals .is-balance { padding-top: 10px; border-top: 2px solid var(--admin-ink); font-size: 1.05rem; }
.inv-totals .is-balance strong { font-weight: 800; }

/* Supplier PO document — company letterhead, colored title block, priced
   item table, signatory + totals footer (mirrors the layout suppliers get
   from other distributors, so it reads as familiar rather than bespoke). */
.spo-doc-head { display: flex; justify-content: space-between; gap: 24px; flex-wrap: wrap; padding-bottom: 20px; border-bottom: 2px solid var(--admin-border); }
.spo-doc-company { display: flex; align-items: flex-start; gap: 14px; }
.spo-doc-logo { height: 46px; width: auto; object-fit: contain; }
.spo-doc-company > div { display: flex; flex-direction: column; gap: 2px; font-size: 0.82rem; color: var(--admin-muted); }
.spo-doc-company strong { font-size: 1.05rem; color: var(--admin-ink); }
.spo-doc-title { text-align: right; display: flex; flex-direction: column; gap: 4px; }
.spo-doc-title span { font-family: var(--font-mono); font-size: 0.85rem; font-weight: 800; letter-spacing: 0.08em; color: var(--primary); }
.spo-doc-title strong { font-size: 1.15rem; color: var(--primary); }
.spo-doc-title em { font-style: normal; font-size: 0.82rem; color: var(--admin-muted); }
.spo-doc-parties { padding: 18px 0; border-bottom: 1px solid var(--admin-border); }
.spo-doc-terms { padding: 14px 0; border-bottom: 1px solid var(--admin-border); }
.spo-doc-terms p { margin: 6px 0 0; font-size: 0.86rem; color: var(--admin-ink); }
.spo-doc-table { margin-top: 16px; }
.spo-doc-footer { display: flex; justify-content: space-between; align-items: flex-end; gap: 24px; margin-top: 26px; flex-wrap: wrap; }
.spo-doc-signatory { display: flex; flex-direction: column; font-size: 0.86rem; }
.spo-doc-signatory strong { color: var(--admin-ink); }
.spo-doc-sign-space { height: 46px; }
.spo-doc-signatory span:last-child { color: var(--admin-muted); border-top: 1px solid var(--admin-border); padding-top: 6px; }
.spo-doc-totals { min-width: 260px; display: flex; flex-direction: column; gap: 6px; }
.spo-doc-totals div { display: flex; justify-content: space-between; gap: 20px; font-size: 0.88rem; }
.spo-doc-totals span { color: var(--admin-muted); }
.spo-doc-totals strong { font-family: var(--font-mono); color: var(--admin-ink); }
.spo-doc-grand { padding-top: 8px; border-top: 2px solid var(--admin-ink); font-size: 1.02rem !important; }
.spo-doc-grand strong { font-weight: 800; color: var(--primary); font-size: 1.1rem; }

/* Supplier PO summary card — inside the order view modal's "Supplier POs"
   list, showing each PO's line items + packaging inline so the admin doesn't
   need to open the print view just to check what was ordered from whom. */
.ord-sort-btn {
  display: inline-flex; align-items: center; gap: 4px; border: none; background: none; padding: 0;
  font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit; cursor: pointer; white-space: nowrap;
}
.ord-sort-btn:hover { color: var(--primary); }
.ord-sort-btn.is-active { color: var(--primary); font-weight: 800; }
.ord-sort-arrow { color: var(--primary); font-weight: 700; }

.ord-timeline { margin-top: 10px; padding-left: 2px; }
.ord-tl-row { display: flex; gap: 12px; position: relative; padding-bottom: 16px; }
.ord-tl-row:last-child { padding-bottom: 0; }
.ord-tl-row::before {
  content: ''; position: absolute; left: 3px; top: 14px; bottom: -2px; width: 1px; background: var(--admin-border);
}
.ord-tl-row:last-child::before { display: none; }
.ord-tl-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--primary); margin-top: 5px; z-index: 1; }
.ord-tl-row.is-approx .ord-tl-dot { background: var(--admin-border); }
.ord-tl-body { flex: 1; min-width: 0; }
.ord-tl-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.ord-tl-head strong { font-size: 0.86rem; color: var(--admin-ink); }
.ord-tl-at { font-size: 0.76rem; color: var(--admin-muted); white-space: nowrap; }
.ord-tl-at em { font-style: normal; opacity: 0.75; }
.ord-tl-detail { font-size: 0.8rem; color: var(--admin-muted); margin-top: 2px; }

.spo-summary-card {
  display: block; border: 1px solid var(--admin-border); border-radius: 8px; padding: 10px 12px;
  margin-bottom: 8px; transition: border-color 0.15s ease, background 0.15s ease;
}
.spo-summary-card:hover { border-color: var(--primary); background: var(--admin-bg); }
.spo-summary-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.spo-summary-head a { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; text-decoration: none; color: inherit; flex: 1; min-width: 0; }
.spo-summary-head strong { font-family: var(--font-mono); font-size: 0.88rem; color: var(--admin-ink); }
.spo-summary-head span { font-size: 0.82rem; color: var(--admin-muted); }
.spo-summary-edit {
  border: 1px solid var(--admin-border); background: #fff; color: var(--primary); border-radius: 6px;
  padding: 3px 10px; font-size: 0.76rem; font-weight: 600; cursor: pointer; white-space: nowrap;
}
.spo-summary-edit:hover { background: var(--admin-bg); border-color: var(--primary); }
.spo-summary-lines { margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--admin-border); display: flex; flex-direction: column; gap: 3px; }
.spo-summary-line { display: flex; justify-content: space-between; gap: 12px; font-size: 0.8rem; color: var(--admin-ink); }
.spo-summary-line em { font-style: normal; color: var(--admin-muted); }
.spo-summary-line > span:last-child { font-family: var(--font-mono); white-space: nowrap; color: var(--admin-muted); }
.spo-summary-loss {
  margin-top: 8px; padding: 6px 9px; border-radius: 6px; background: #fff8ec; color: #a86a1c;
  font-size: 0.78rem; line-height: 1.4;
}
.spo-summary-loss strong { font-weight: 700; }

/* Printable Supplier PO page — a single centered document, not the two-column
   qv-grid the quote/invoice views use (there's no side column here, so that
   grid just left-aligned the sheet and left the rest of the page empty). */
.spo-doc-wrap { max-width: 880px; margin: 0 auto; }
@media print { .spo-doc-wrap { max-width: none; margin: 0; } }

@media print {
  .no-print, .admin-sidebar, .admin-topbar, .admin-content-header, .qv-side { display: none !important; }
  .admin-wrap { margin-left: 0 !important; max-width: none !important; padding: 0 !important; }
  .qv-grid { grid-template-columns: 1fr !important; }
  .invoice-sheet { border: none !important; box-shadow: none !important; padding: 0 !important; }
  body { background: #fff !important; }
}

.admin-th-note { font-weight: 400; text-transform: none; letter-spacing: normal; color: var(--admin-muted); font-size: 0.72rem; }

/* ---- Quote versions (send/track) ---- */
.qver-list { display: flex; flex-direction: column; gap: 16px; }
.qver { border: 1px solid var(--admin-border); border-radius: 10px; padding: 16px 18px; }
.qver.is-accepted { border-color: #bfe3cc; background: #f5fbf7; }
.qver.is-rejected { border-color: #f3c9c5; background: #fdf6f6; }

/* Final Order Details — the accepted quote's own summary, deliberately not
   labelled with a version number since it represents the agreed outcome,
   not any one round of negotiation. */
.qfinal-card { border: 2px solid #4fae74; background: #f5fbf7; }
.qfinal-card .admin-card-head { align-items: flex-start; }
.qfinal-total { font-size: 1.15rem; font-weight: 800; color: #1f7a45; }

/* Secondary actions (view/send) sit as a quiet row; the primary action
   (Create Order / Upload PO) gets its own visually separated panel below so
   it reads as the one thing this card is actually asking you to do. */
.qfinal-secondary-actions {
  display: flex; flex-wrap: wrap; gap: 8px; padding-top: 14px; margin-top: 14px;
  border-top: 1px solid rgba(79,174,116,0.25);
}
.qfinal-secondary-actions .btn { padding: 7px 14px; font-size: 0.8rem; }
.qfinal-primary {
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
  margin-top: 14px; padding: 14px 16px;
  background: var(--white); border: 1px solid rgba(79,174,116,0.3); border-radius: 10px;
}
.qfinal-primary .btn { padding: 10px 22px; font-size: 0.9rem; }
.qfinal-po-note { font-size: 0.82rem; color: var(--admin-muted); }
.qfinal-po-note strong { color: var(--admin-ink); }
.qfinal-po-note a { color: var(--primary); font-weight: 600; margin-left: 4px; }
.qfinal-po-note span { margin-left: 4px; }

/* Once an order exists, the primary panel becomes a summary + link rather
   than a repeatable action — same panel treatment, different content. */
.qfinal-primary-done { justify-content: space-between; }
.qfinal-order-summary { display: flex; align-items: center; gap: 12px; }
.qfinal-order-no { font-weight: 700; color: var(--admin-ink); font-size: 0.95rem; }
.qfinal-order-value { font-weight: 700; color: #1f7a45; }

@media (max-width: 560px) {
  .qfinal-primary { flex-direction: column; align-items: stretch; }
  .qfinal-primary .btn { width: 100%; text-align: center; }
  .qfinal-order-summary { flex-wrap: wrap; }
}
.qver-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 6px; }
.qver-head > div { display: flex; align-items: center; gap: 10px; }
.qver-no { font-family: var(--font-mono); font-weight: 800; color: var(--admin-ink); }
.qver-total { font-size: 1.05rem; font-weight: 700; color: var(--admin-ink); }
.qver-meta { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 0.78rem; color: var(--admin-muted); margin-bottom: 10px; }
.qver-items { margin-bottom: 10px; }
.qver-items td { padding: 6px 10px; font-size: 0.85rem; }
.qver-pkg { display: block; font-size: 0.72rem; color: var(--admin-muted); font-weight: 400; margin-top: 2px; }
.qver-qty-note { color: #a86a1c; font-weight: 500; }
.qver-charges {
  display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 0.78rem; color: var(--admin-ink);
  padding: 6px 10px; margin-bottom: 10px; background: var(--bg-light); border-radius: 6px;
}
.qver-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.qver-accept:hover { border-color: #1a9e5c; color: #1a9e5c; }
.qver-reject:hover { border-color: #b23c34; color: #b23c34; }
.qver-decided { font-size: 0.82rem; font-weight: 600; color: var(--admin-muted); }
.qver-po-note {
  margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--admin-border);
  font-size: 0.8rem; color: var(--admin-muted);
}
.qver-po-note a { color: var(--primary); font-weight: 600; }

/* New Quote line builder */
.qbuild-legend {
  display: grid; grid-template-columns: 2fr 80px 70px 100px 100px 30px; gap: 8px;
  padding: 0 2px 6px;
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--admin-muted);
}
.qbuild-row { display: grid; grid-template-columns: 2fr 80px 70px 100px 100px 30px; gap: 8px; margin-bottom: 8px; }
.qbuild-row input {
  padding: 8px 10px; border: 1px solid var(--admin-border); border-radius: 6px; font-size: 0.85rem; font-family: inherit;
}
.qbuild-remove {
  border: none; background: var(--bg-light); border-radius: 6px; cursor: pointer;
  color: var(--admin-muted); font-size: 1rem; line-height: 1;
}
.qbuild-remove:hover { background: #fdeceb; color: #b23c34; }
.qbuild-add {
  border: 1px dashed var(--admin-border); background: none; border-radius: 8px;
  padding: 8px 14px; font-size: 0.82rem; font-weight: 600; color: var(--primary);
  cursor: pointer; margin-bottom: 4px;
}
.qbuild-add:hover { border-color: var(--primary); background: var(--bg-page); }
.qbuild-charge-row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.qbuild-charge-row select, .qbuild-charge-row input {
  padding: 8px 10px; border: 1px solid var(--admin-border); border-radius: 6px; font-size: 0.85rem; font-family: inherit;
}
@media (max-width: 560px) {
  .qbuild-legend { display: none; }
  .qbuild-row { grid-template-columns: 1fr 1fr; grid-template-areas: "name name" "qty unit" "package price" "remove remove"; }
  .qbuild-row input:nth-child(1) { grid-area: name; }
  .qbuild-row input:nth-child(2) { grid-area: qty; }
  .qbuild-row input:nth-child(3) { grid-area: unit; }
  .qbuild-row input:nth-child(4) { grid-area: package; }
  .qbuild-row input:nth-child(5) { grid-area: price; }
  .qbuild-row button { grid-area: remove; justify-self: start; }
}

/* Public quote response page */
.qresp-toolbar {
  display: flex; gap: 18px; margin-bottom: 14px; font-size: 0.85rem; font-weight: 600;
}
.qresp-toolbar a { color: var(--primary); }
.qresp-toolbar a:hover { text-decoration: underline; }
.qresp-actions { display: flex; gap: 12px; margin-top: 24px; }
.qresp-actions .btn { flex: 1; cursor: pointer; }

/* The public quote page has no sidebar, so it shouldn't inherit .admin-wrap's
   sidebar-offset margin — and centering it on the page (rather than pinning
   it to the left edge) reads as a deliberately designed page, not a stray
   admin-panel leftover. */
.qresp-page { margin-left: auto !important; margin-right: auto !important; }

/* Custom confirm modal — replaces window.confirm() across the admin panel */
.btn-danger { background: #c0392b; color: var(--white); }
.btn-danger:hover { background: #a3291b; }
.admin-confirm-backdrop {
  position: fixed; inset: 0; background: rgba(10,15,28,0.55);
  display: flex; align-items: center; justify-content: center;
  z-index: 3000; padding: 20px;
}
/* `[hidden]` and `.admin-confirm-backdrop` have equal specificity, so without
   this the class's `display: flex` above wins the cascade tie and the modal
   stays visible (and click-blocking) even while `hidden` is set. */
.admin-confirm-backdrop[hidden] { display: none; }
.admin-confirm-box {
  background: var(--white); border-radius: 12px; padding: 24px;
  max-width: 400px; width: 100%; box-shadow: 0 20px 50px rgba(0,0,0,0.25);
}
.admin-confirm-message { margin: 0 0 20px; color: var(--admin-ink); font-size: 0.95rem; line-height: 1.5; }
.admin-confirm-actions { display: flex; justify-content: flex-end; gap: 10px; }

/* Supplier PO modal — clearly separated sections, one topic each */
.spo-modal .admin-modal-body { padding: 4px 26px 22px; }
.spo-section { padding: 20px 0; border-top: 1px solid var(--admin-border); }
.spo-section:first-of-type { border-top: none; padding-top: 20px; }
.spo-section-last { padding-bottom: 4px; }
.spo-section-label {
  display: block; font-weight: 700; font-size: 0.86rem; color: var(--admin-ink); margin-bottom: 12px;
  letter-spacing: 0.01em;
}
.spo-section-label span { font-weight: 400; color: var(--admin-muted); }
.spo-field-label { display: block; font-size: 0.78rem; font-weight: 600; color: var(--admin-muted); margin-bottom: 6px; }
.spo-field-label span { font-weight: 400; }
.spo-input {
  width: 100%; padding: 10px 12px; border: 1px solid var(--admin-border);
  border-radius: 8px; font-size: 0.87rem; font-family: inherit; background: var(--bg-page);
  color: var(--admin-ink); transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.spo-input:focus { outline: none; border-color: var(--primary); background: #fff; box-shadow: 0 0 0 3px rgba(22,48,92,0.08); }
.spo-input::placeholder { color: #9aa2b1; }
.spo-input:disabled {
  background: #f0f4f0; border-color: #d7e5da; color: var(--admin-ink); opacity: 1;
  cursor: default; font-weight: 600;
}
.spo-search-wrap { position: relative; }
.spo-supplier-fields { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.spo-toggle-link { display: inline-block; margin-top: 12px; font-size: 0.82rem; font-weight: 600; color: var(--primary); text-decoration: none; }
.spo-toggle-link:hover { text-decoration: underline; }

/* Items table — real column header so qty/unit/pkg line up, not a loose row */
.spo-items-head {
  display: grid; grid-template-columns: 20px 1fr 62px 52px 68px 80px 88px; gap: 10px;
  padding: 0 14px 8px; font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--admin-muted); font-weight: 700;
}
.spo-items-head span:nth-child(3), .spo-items-head span:nth-child(5),
.spo-items-head span:nth-child(6), .spo-items-head span:nth-child(7) { text-align: right; }
.spo-items-list { border: 1px solid var(--admin-border); border-radius: 10px; overflow: hidden; box-shadow: 0 1px 2px rgba(15,18,22,0.03); }
.spo-item-row {
  display: grid; grid-template-columns: 20px 1fr 62px 52px 68px 80px 88px; gap: 10px; align-items: center;
  padding: 11px 14px; border-bottom: 1px solid var(--admin-border); background: #fff; transition: background 0.12s ease;
}
.spo-item-row:hover { background: var(--admin-bg); }
.spo-item-row:last-child { border-bottom: none; }
.spo-item-row input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--primary); cursor: pointer; }
.spo-item-row .spo-input { padding: 7px 9px; font-size: 0.85rem; text-align: right; }
.spo-item-row input[name^="spo_unit"] { text-align: left; }
.spo-item-name { font-size: 0.87rem; color: var(--admin-ink); font-weight: 500; }
.spo-item-name small { display: block; font-size: 0.74rem; color: var(--admin-muted); font-weight: 400; margin-top: 2px; }
.spo-item-amount { font-family: var(--font-mono); font-size: 0.85rem; font-weight: 700; color: var(--admin-ink); text-align: right; }
.spo-item-error { grid-column: 1 / -1; font-size: 0.76rem; color: #b23c34; margin-top: 4px; line-height: 1.4; }
.spo-item-row.has-error { background: #fdf6f6; }
.spo-item-row.has-error input[name^="spo_rate"] { border-color: #b23c34; }
.spo-item-error.is-warning { color: #a86a1c; }
.spo-item-row.has-warning { background: #fffaf0; }
.spo-item-row.has-warning input[name^="spo_rate"] { border-color: #c9903f; }
#spoSubmitBtn:disabled { opacity: 0.5; cursor: not-allowed; }

/* Live totals — same layout/rounding rule the printed PO and server share */
.spo-totals {
  margin-top: 16px; padding: 14px 16px; border-radius: 10px; background: var(--admin-bg);
  border: 1px solid var(--admin-border); display: flex; flex-direction: column; gap: 6px;
}
.spo-totals > div { display: flex; justify-content: space-between; font-size: 0.84rem; color: var(--admin-muted); }
.spo-totals > div strong { font-family: var(--font-mono); color: var(--admin-ink); font-weight: 600; }
.spo-totals-grand {
  margin-top: 6px; padding-top: 10px; border-top: 1px dashed var(--admin-border);
  font-size: 0.92rem !important; color: var(--admin-ink) !important; font-weight: 700;
}
.spo-totals-grand strong { font-size: 1.15rem; color: var(--primary) !important; }

/* Goods Receipt item rows — same visual family as .spo-item-row (border,
   hover, spacing) but a different column set (ordered / already-in /
   receiving-now instead of qty/unit/pkg/rate). */
.grn-item-row {
  display: grid; gap: 10px; align-items: center;
  padding: 11px 14px; border-bottom: 1px solid var(--admin-border); background: #fff; transition: background 0.12s ease;
}
.grn-item-row:hover { background: var(--admin-bg); }
.grn-item-row:last-child { border-bottom: none; }
.grn-item-row .spo-input { padding: 7px 9px; font-size: 0.85rem; text-align: right; }

/* Goods Receipts history — one card per delivery against this PO */
.grn-card { border: 1px solid var(--admin-border); border-radius: 10px; padding: 12px 14px; margin-bottom: 10px; }
.grn-card:last-child { margin-bottom: 0; }
.grn-card-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; font-size: 0.84rem; }
.grn-card-head strong { color: var(--admin-ink); font-size: 0.88rem; }
.grn-card-head span { color: var(--admin-muted); }
.grn-card-lines { margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--admin-border); display: flex; flex-direction: column; gap: 3px; }
.grn-card-line { display: flex; justify-content: space-between; gap: 12px; font-size: 0.82rem; color: var(--admin-ink); }
.grn-card-line > span:last-child { font-family: var(--font-mono); color: var(--admin-muted); white-space: nowrap; }
.grn-card-notes { margin: 8px 0 0; font-size: 0.82rem; color: var(--admin-muted); }
.grn-card-head a { font-size: 0.82rem; font-weight: 600; color: var(--primary); text-decoration: none; margin-left: auto; }
.grn-card-head a:hover { text-decoration: underline; }
.admin-link-btn { border: none; background: none; padding: 0; font: inherit; font-size: 0.82rem; font-weight: 600; color: var(--primary); cursor: pointer; text-decoration: none; }
.admin-link-btn:hover { text-decoration: underline; }
.grn-due-history { margin-top: 8px; font-size: 0.78rem; color: var(--admin-muted); }
.grn-due-history summary { cursor: pointer; font-weight: 600; }
.grn-due-history ul { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.grn-due-history li { padding-left: 10px; border-left: 2px solid var(--admin-border); }
.grn-payment-form { display: flex; gap: 8px; margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--admin-border); }
.grn-payment-form .spo-input { max-width: 160px; }
.grn-payment-form .btn { padding: 8px 14px; font-size: 0.82rem; white-space: nowrap; }

.spo-supplier-results {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 50;
  background: var(--white); border: 1px solid var(--admin-border); border-radius: 10px;
  box-shadow: 0 12px 30px rgba(0,0,0,0.15); max-height: 220px; overflow-y: auto;
}
.spo-supplier-result { padding: 10px 14px; cursor: pointer; border-bottom: 1px solid var(--admin-border); }
.spo-supplier-result:last-child { border-bottom: none; }
.spo-supplier-result:hover { background: var(--admin-bg); }
.spo-supplier-result strong { display: block; font-size: 0.87rem; color: var(--admin-ink); }
.spo-supplier-result span { display: block; font-size: 0.78rem; color: var(--admin-muted); }
/* Sticky footer for the Create/Edit Supplier PO modal — the form is long
   enough to scroll, so the primary action stays reachable without hunting
   for it at the bottom. */
.spo-modal-footer { background: #fff; }
.admin-confirm-actions .btn { padding: 9px 18px; font-size: 0.88rem; cursor: pointer; }

/* ===========================================================================
   HERO SLIDER
   Six slides sharing one fixed-height stage. Ported from the approved demo.
   One rename was needed to live alongside the existing stylesheet:
     .dot -> .hdot  (a bare .dot would also match .fact-chip .dot)
   .eyebrow, .btn and :focus-visible are deliberately NOT redefined here —
   the sheet already styles them, and overriding them would reach every
   section on the site rather than just the hero.
   =========================================================================== */
/* Every slide shares ONE grid cell rather than being absolutely positioned in a
   fixed-height box. Absolute slides contribute no height, so the stage was
   locked to 100svh-minus-header and any slide whose content needed more than
   that had its grid rows squeezed — the copy then overflowed its own row and
   printed on top of the illustration (5 of 6 slides did this on a short
   window). Stacked in a grid the stage grows to its TALLEST slide, so nothing
   is ever compressed, and because the inactive slides still occupy the cell the
   height stays put when the slide changes. The hero's own min-height still
   fills the viewport on normal screens. */
.slides {
  position: relative; flex: 1; z-index: 2;
  display: grid;
  grid-template-areas: "stage";
}

.slide {
  grid-area: stage;
  min-width: 0;
  opacity: 0; visibility: hidden;
  transition: opacity 0.28s ease, visibility 0.28s;
}
.slide.is-active { opacity: 1; visibility: visible; transition: opacity 0.42s ease 0.2s, visibility 0s; }

/* Both slide layouts sit inside the same centred measure the rest of the site
   uses (--max-width). Percentage columns spanning the whole viewport were the
   cause of the dead space in the middle: at 1800px a 40/60 split puts the copy
   hard left and the illustration hard right with a void between them. Holding
   the pair to 1160px and centring keeps them in conversation at any width, and
   the horizontal padding lives here so the two columns can sit flush together
   rather than each carrying its own inset. */
.slide-centre {
  /* min-height, not height: it must be free to grow past the stage when the
     copy needs it rather than forcing the content to overflow. */
  min-height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center;
  width: 100%; max-width: var(--max-width); margin: 0 auto;
  padding: clamp(16px, 4vh, 56px) clamp(56px, 6vw, 80px);
}
.slide-split {
  min-height: 100%;
  display: grid;
  /* minmax(0,…) so a long word can never push a column past its track */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.04fr);
  gap: clamp(12px, 2.5vw, 44px);
  align-items: center;
  width: 100%; max-width: var(--max-width); margin: 0 auto;
  padding: clamp(16px, 4vh, 48px) clamp(56px, 6vw, 80px);
}
.slide-text {
  position: relative; z-index: 2;
  padding: 0;
  display: flex; flex-direction: column; justify-content: center;
}
.slide-visual-wrap {
  position: relative; z-index: 2;
  padding: 0;
  display: flex; align-items: center; justify-content: center; min-height: 0;
}
.slide-visual { width: 100%; max-width: 520px; position: relative; z-index: 1; }
.slide-visual svg { width: 100%; height: auto; display: block; }
.slide-visual-wrap::before { content: none; }

.slide h2 {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(1.35rem, 4.8vw, 2.7rem); line-height: 1.16;
  color: var(--logo-navy-deep); text-wrap: balance; margin-bottom: clamp(8px, 1.8vh, 18px);
}
.slide-centre h2 { font-size: clamp(1.45rem, 5.4vw, 3.1rem); max-width: 900px; }
/* Same navy as the rest of the headline. A second, lighter blue mid-sentence
   read as a stray colour rather than emphasis, and slide 1 has no highlight —
   this keeps every slide headline a single colour. */
.slide h2 .accent { color: var(--logo-navy-deep); }
.slide p.lede {
  color: var(--text-muted); font-size: clamp(0.85rem, 3.3vw, 1rem);
  max-width: 46ch; margin-bottom: clamp(12px, 2.4vh, 26px);
}
.slide-centre p.lede { max-width: 62ch; }
.slide-facts { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: clamp(12px, 2.4vh, 26px); }
.slide-centre .slide-facts { justify-content: center; }
.fact {
  font-family: var(--font-mono); font-size: clamp(0.6rem, 2.5vw, 0.68rem); letter-spacing: 0.04em;
  padding: 6px 12px; border-radius: 30px; background: var(--white);
  border: 1px solid var(--border); color: var(--logo-navy);
}
.fact b { color: var(--accent); }
.actions { display: flex; gap: 10px; flex-wrap: wrap; }
.slide-centre .actions { justify-content: center; }
/* Button sizing scoped to the hero: 44px min target for touch. */
.hero .btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; padding: 11px 24px; border-radius: 30px;
  font-weight: 600; font-size: clamp(0.86rem, 3.2vw, 0.94rem); border: 1px solid transparent; cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}
.hero .btn-primary { background: var(--logo-navy); color: var(--white); }
.hero .btn-primary:hover { background: var(--logo-navy-deep); transform: translateY(-2px); }
.hero .btn-outline { border-color: var(--silver); color: var(--logo-navy); background: rgba(255,255,255,0.6); }
.hero .btn-outline:hover { border-color: var(--logo-navy); background: var(--logo-navy); color: var(--white); }
.hero-stats {
  display: flex; justify-content: center; flex-wrap: wrap;
  gap: clamp(8px, 2vh, 30px) clamp(18px, 5vw, 52px);
  margin-top: clamp(12px, 3vh, 34px); padding-top: clamp(8px, 2vh, 22px);
  border-top: 1px solid transparent;
  border-image: linear-gradient(90deg, transparent, var(--silver-light), var(--silver), var(--silver-light), transparent) 1;
}
.hero-stat .num { font-family: var(--font-mono); font-size: clamp(1.15rem, 4.6vw, 1.9rem); font-weight: 800; color: var(--accent); font-variant-numeric: tabular-nums; }
.hero-stat .label { font-size: clamp(0.65rem, 2.6vw, 0.83rem); color: var(--silver-dark); margin-top: 2px; }
/* ============ Shared copy entrance ============ */
@keyframes bloomUp { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
.slide.is-active .eyebrow     { animation: bloomUp 0.5s cubic-bezier(0.22,0.8,0.3,1) 0.25s both; }
.slide.is-active h2           { animation: bloomUp 0.55s cubic-bezier(0.22,0.8,0.3,1) 0.33s both; }
.slide.is-active p.lede       { animation: bloomUp 0.55s cubic-bezier(0.22,0.8,0.3,1) 0.41s both; }
.slide.is-active .slide-facts { animation: bloomUp 0.55s cubic-bezier(0.22,0.8,0.3,1) 0.48s both; }
.slide.is-active .actions     { animation: bloomUp 0.55s cubic-bezier(0.22,0.8,0.3,1) 0.54s both; }
.slide.is-active .hero-stats  { animation: bloomUp 0.55s cubic-bezier(0.22,0.8,0.3,1) 0.60s both; }

@keyframes drawIn { from { stroke-dashoffset: var(--dash, 1000); } to { stroke-dashoffset: 0; } }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes popIn  { from { opacity: 0; transform: scale(0.55); } to { opacity: 1; transform: none; } }
@keyframes floatY { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
.svg-el { transform-box: fill-box; transform-origin: center; }
.slide.is-active .visual-float { animation: floatY 8s ease-in-out 1.6s infinite; }

/* ============ 1 · LOGO ============
   The mark is now real vector — the B, the S, the molecule, the wordmark and
   the tagline are five separate paths traced from the original artwork — so
   each part can arrive on its own instead of one flat image fading in.
   Order follows how the mark is built: letterform, then the S sweeping through
   it, then the molecule it encircles, then the name. */
.bs-b, .bs-mol, .bs-word, .bs-tag { fill: var(--logo-navy); }
.bs-s { fill: url(#bsSilver); }
.bs-b, .bs-s, .bs-mol, .bs-word, .bs-tag { transform-box: fill-box; transform-origin: center; }

@keyframes riseIn  { from { opacity: 0; transform: translateY(22px); } to { opacity: 1; transform: none; } }
@keyframes sweepIn { from { opacity: 0; transform: translateX(34px) scale(0.92) rotate(4deg); } to { opacity: 1; transform: none; } }
@keyframes molIn   { from { opacity: 0; transform: scale(0.35); } to { opacity: 1; transform: none; } }
/* The metal catches the light once as it lands, then settles. */
@keyframes sheen   { 0%, 100% { filter: none; } 55% { filter: brightness(1.2) saturate(1.1); } }

[data-anim="hero"].is-active .bs-b    { animation: riseIn 0.65s cubic-bezier(0.22,1,0.3,1) 0.30s both; }
[data-anim="hero"].is-active .bs-s    { animation: sweepIn 0.75s cubic-bezier(0.22,1,0.3,1) 0.46s both, sheen 1.4s ease-out 1.05s 1; }
[data-anim="hero"].is-active .bs-mol  { animation: molIn 0.6s cubic-bezier(0.34,1.56,0.64,1) 0.80s both; }
[data-anim="hero"].is-active .bs-word { animation: riseIn 0.6s cubic-bezier(0.22,1,0.3,1) 0.98s both; }
[data-anim="hero"].is-active .bs-tag  { animation: riseIn 0.6s cubic-bezier(0.22,1,0.3,1) 1.10s both; }

/* ============ 2 · CONVERGENCE ============ */
@keyframes flyLeft  { from { opacity: 0; transform: translateX(-110px) scale(0.7); } to { opacity: 1; transform: none; } }
@keyframes flyRight { from { opacity: 0; transform: translateX(110px) scale(0.7); } to { opacity: 1; transform: none; } }
@keyframes flyTop   { from { opacity: 0; transform: translateY(-90px) scale(0.7); } to { opacity: 1; transform: none; } }
@keyframes coreGlow { 0% { opacity: 0; transform: scale(0.4); } 60% { opacity: 1; transform: scale(1.14); } 100% { opacity: 1; transform: scale(1); } }
@keyframes ringOut  { 0% { transform: scale(0.5); opacity: 0.55; } 100% { transform: scale(1.9); opacity: 0; } }
[data-anim="converge"].is-active .cv-top   { animation: flyTop 0.75s cubic-bezier(0.22,1,0.3,1) 0.35s both; }
[data-anim="converge"].is-active .cv-left  { animation: flyLeft 0.75s cubic-bezier(0.22,1,0.3,1) 0.50s both; }
[data-anim="converge"].is-active .cv-right { animation: flyRight 0.75s cubic-bezier(0.22,1,0.3,1) 0.65s both; }
[data-anim="converge"].is-active .cv-bond  { stroke-dasharray: var(--dash,70); animation: drawIn 0.5s ease-out both; }
[data-anim="converge"].is-active .cv-bond-1 { animation-delay: 1.05s; }
[data-anim="converge"].is-active .cv-bond-2 { animation-delay: 1.18s; }
[data-anim="converge"].is-active .cv-bond-3 { animation-delay: 1.31s; }
[data-anim="converge"].is-active .cv-core   { animation: coreGlow 0.7s cubic-bezier(0.22,1,0.3,1) 1.45s both; }
[data-anim="converge"].is-active .cv-ring   { animation: ringOut 1.5s ease-out 1.9s infinite; }
[data-anim="converge"].is-active .cv-orbit  { stroke-dasharray: var(--dash,900); animation: drawIn 1.4s ease-out 0.2s both; }

/* ============ 3 · CASCADE ============ */
@keyframes dealIn { from { opacity: 0; transform: translateX(70px) rotate(2.5deg); } to { opacity: 1; transform: none; } }
@keyframes tick   { from { stroke-dashoffset: 30; } to { stroke-dashoffset: 0; } }
[data-anim="cascade"].is-active .cd-card { animation: dealIn 0.6s cubic-bezier(0.22,1,0.3,1) both; }
[data-anim="cascade"].is-active .cd-1 { animation-delay: 0.35s; }
[data-anim="cascade"].is-active .cd-2 { animation-delay: 0.50s; }
[data-anim="cascade"].is-active .cd-3 { animation-delay: 0.65s; }
[data-anim="cascade"].is-active .cd-tick { stroke-dasharray: 30; animation: tick 0.4s ease-out both; }
[data-anim="cascade"].is-active .cd-1 .cd-tick { animation-delay: 0.85s; }
[data-anim="cascade"].is-active .cd-2 .cd-tick { animation-delay: 1.00s; }
[data-anim="cascade"].is-active .cd-3 .cd-tick { animation-delay: 1.15s; }
[data-anim="cascade"].is-active .cd-stat { animation: popIn 0.45s cubic-bezier(0.34,1.56,0.64,1) both; }
[data-anim="cascade"].is-active .cd-1 .cd-stat { animation-delay: 1.0s; }
[data-anim="cascade"].is-active .cd-2 .cd-stat { animation-delay: 1.15s; }
[data-anim="cascade"].is-active .cd-3 .cd-stat { animation-delay: 1.3s; }

/* ============ 4 · RIPPLE — sector chip grid ============
   Was a fixed 6-hexagon SVG honeycomb; now a wrap grid built from the
   "industries" table so the count and order live in the admin, not in this
   file. cellIn is reused as-is (same pop-and-settle the hexagons used) —
   only the stagger changes, from three fixed ring-delays to a per-chip
   --i custom property so any number of industries staggers evenly. */
@keyframes cellIn { from { opacity: 0; transform: scale(0.3) rotate(-12deg); } to { opacity: 1; transform: none; } }
[data-anim="ripple"].is-active .sector-chip {
  animation: cellIn 0.5s cubic-bezier(0.34,1.56,0.64,1) both;
  animation-delay: calc(0.32s + var(--i, 0) * 0.05s);
}

.sector-grid {
  display: flex; flex-wrap: wrap; align-content: center; justify-content: center;
  gap: 10px; width: 100%;
  padding: clamp(20px, 4vh, 36px) clamp(16px, 3vw, 28px);
  border: 1px solid var(--hero-silver-light); border-radius: 20px;
  background: rgba(255,255,255,0.55);
}
.sector-chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 18px 8px 12px; border-radius: 100px;
  border: 1px solid var(--border);
  background: var(--white);
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(0.76rem, 1.5vw, 0.88rem);
  color: var(--hero-cta); white-space: nowrap;
  transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease, transform 0.2s ease;
}
/* Compound selector (two classes) rather than .sector-chip-icon alone — the
   chip sits inside .slide-visual, and ".slide-visual svg { width:100%;
   height:auto }" (sized for this slide's one full illustration, not a grid
   of small inline icons) is a class+type selector that otherwise outranks a
   single class on specificity, stretching every icon to fill its chip. */
.sector-chip .sector-chip-icon {
  width: 18px; height: 18px; flex-shrink: 0;
  transition: stroke 0.2s ease;
}
.sector-chip:hover {
  background: var(--hero-cta); border-color: var(--hero-cta); color: var(--white);
  transform: translateY(-2px);
}
@media (max-width: 640px) {
  /* Twelve chips sized to their own (English-length-varying) text, in a
     263px-wide mobile container, packed one to a row for all but the two
     shortest pairs — an 11-row, 480px stack that, added to the heading and
     subtitle above it, ran past the hero's own box and visibly bled into
     the section below on real devices. A fixed two-column grid is a fixed
     six rows regardless of how the industry names happen to measure; the
     tradeoff is longer names ("Veterinary & Animal Health") now wrap to a
     second line inside their own cell rather than forcing the whole row
     to their width. */
  .sector-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; padding: 16px 12px; }
  .sector-chip {
    white-space: normal; text-align: left; justify-content: flex-start;
    padding: 8px 10px; font-size: 0.7rem; line-height: 1.2;
  }
  .sector-chip .sector-chip-icon { width: 15px; height: 15px; }
}

/* ============ 5 · ROUTE ============ */
@keyframes routeDraw { from { stroke-dashoffset: 1000; } to { stroke-dashoffset: 0; } }
@keyframes pulseRun  { from { stroke-dashoffset: 1000; } to { stroke-dashoffset: -1000; } }
@keyframes stepIn    { from { opacity: 0; transform: scale(0.4); } to { opacity: 1; transform: none; } }
[data-anim="route"].is-active .rt-path  { stroke-dasharray: 1000; animation: routeDraw 1.5s ease-in-out 0.35s both; }
[data-anim="route"].is-active .rt-pulse { stroke-dasharray: 40 960; animation: pulseRun 3.2s linear 1.9s infinite; }
[data-anim="route"].is-active .rt-step  { animation: stepIn 0.5s cubic-bezier(0.34,1.56,0.64,1) both; }
[data-anim="route"].is-active .rt-1 { animation-delay: 0.55s; }
[data-anim="route"].is-active .rt-2 { animation-delay: 0.85s; }
[data-anim="route"].is-active .rt-3 { animation-delay: 1.15s; }
[data-anim="route"].is-active .rt-4 { animation-delay: 1.45s; }
[data-anim="route"].is-active .rt-cap { animation: fadeIn 0.4s ease-out both; }
[data-anim="route"].is-active .rt-1 .rt-cap { animation-delay: 0.80s; }
[data-anim="route"].is-active .rt-2 .rt-cap { animation-delay: 1.10s; }
[data-anim="route"].is-active .rt-3 .rt-cap { animation-delay: 1.40s; }
[data-anim="route"].is-active .rt-4 .rt-cap { animation-delay: 1.70s; }

/* ============ 6 · STAMP ============ */
@keyframes sheetIn { from { opacity: 0; transform: translateY(24px) rotate(-1.5deg); } to { opacity: 1; transform: none; } }
@keyframes ruleIn  { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes stampDown {
  0% { opacity: 0; transform: scale(2.1) rotate(-14deg); }
  55% { opacity: 1; transform: scale(0.9) rotate(3deg); }
  75% { transform: scale(1.05) rotate(-1deg); }
  100% { opacity: 1; transform: scale(1) rotate(0); }
}
@keyframes shock { 0% { transform: scale(0.7); opacity: 0.5; } 100% { transform: scale(2); opacity: 0; } }
[data-anim="stamp"].is-active .st-sheet-back { animation: sheetIn 0.6s cubic-bezier(0.22,1,0.3,1) 0.30s both; }
[data-anim="stamp"].is-active .st-sheet      { animation: sheetIn 0.6s cubic-bezier(0.22,1,0.3,1) 0.42s both; }
[data-anim="stamp"].is-active .st-rule { transform-origin: left center; animation: ruleIn 0.4s ease-out both; }
[data-anim="stamp"].is-active .st-rule:nth-of-type(1) { animation-delay: 0.72s; }
[data-anim="stamp"].is-active .st-rule:nth-of-type(2) { animation-delay: 0.80s; }
[data-anim="stamp"].is-active .st-rule:nth-of-type(3) { animation-delay: 0.88s; }
[data-anim="stamp"].is-active .st-rule:nth-of-type(4) { animation-delay: 0.96s; }
[data-anim="stamp"].is-active .st-rule:nth-of-type(5) { animation-delay: 1.04s; }
[data-anim="stamp"].is-active .st-rule:nth-of-type(6) { animation-delay: 1.12s; }
[data-anim="stamp"].is-active .st-chip { animation: popIn 0.4s cubic-bezier(0.34,1.56,0.64,1) 1.22s both; }
[data-anim="stamp"].is-active .st-seal  { animation: stampDown 0.75s cubic-bezier(0.3,1.4,0.5,1) 1.45s both; }
[data-anim="stamp"].is-active .st-shock { animation: shock 0.8s ease-out 1.95s both; }

/* ============ 6 · WORLD MAP ============
   The land settles first, then routes reach out from the hub, then the markets
   light up one after another — the order tells the story: here we are, here is
   where we ship, here is who we ship to. */
.wm-shape { fill: rgba(16,58,104,0.09); stroke: rgba(94,94,94,0.5); stroke-width: 1; }
.wm-arc { fill: none; stroke: var(--accent); stroke-width: 1.4; opacity: 0.45; stroke-linecap: round; }
.wm-dot { fill: var(--accent); opacity: 0.75; }
.wm-hub-outer { fill: none; stroke: var(--accent); stroke-width: 1.6; }
.wm-hub-core { fill: var(--accent); }
.wm-ping { fill: none; stroke: var(--accent); stroke-width: 1.4; transform-box: fill-box; transform-origin: center; }
.wm-cap { font-family: 'Cascadia Code', Consolas, monospace; font-size: 11px; font-weight: 700; letter-spacing: 0.16em; fill: var(--accent); }
.wm-hub-label { letter-spacing: 0.12em; }

@keyframes landIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes radar  { 0% { transform: scale(0.5); opacity: 0.6; } 100% { transform: scale(3.2); opacity: 0; } }
[data-anim="worldmap"].is-active .wm-land { transform-box: fill-box; transform-origin: center; animation: landIn 0.75s cubic-bezier(0.22,1,0.3,1) 0.3s both; }
[data-anim="worldmap"].is-active .wm-arc  { stroke-dasharray: var(--dash,300); animation: drawIn 0.85s ease-out both; }
[data-anim="worldmap"].is-active .wm-arc:nth-of-type(1) { animation-delay: 0.75s; }
[data-anim="worldmap"].is-active .wm-arc:nth-of-type(2) { animation-delay: 0.87s; }
[data-anim="worldmap"].is-active .wm-arc:nth-of-type(3) { animation-delay: 0.99s; }
[data-anim="worldmap"].is-active .wm-arc:nth-of-type(4) { animation-delay: 1.11s; }
[data-anim="worldmap"].is-active .wm-arc:nth-of-type(5) { animation-delay: 1.23s; }
[data-anim="worldmap"].is-active .wm-arc:nth-of-type(6) { animation-delay: 1.35s; }
/* 25 markets would need 25 nth-of-type rules; each dot carries its own index
   instead and the delay is computed from it. */
[data-anim="worldmap"].is-active .wm-dot {
  transform-box: fill-box; transform-origin: center;
  animation: popIn 0.4s cubic-bezier(0.34,1.56,0.64,1) both;
  animation-delay: calc(1.0s + var(--i) * 0.045s);
}
[data-anim="worldmap"].is-active .wm-hub { animation: popIn 0.55s cubic-bezier(0.34,1.56,0.64,1) 0.62s both; transform-box: fill-box; transform-origin: center; }
[data-anim="worldmap"].is-active .wm-ping   { animation: radar 2.6s ease-out 1.4s infinite; }
[data-anim="worldmap"].is-active .wm-ping-2 { animation-delay: 2.7s; }
[data-anim="worldmap"].is-active .wm-cap { animation: bloomUp 0.6s ease-out 2.0s both; }

/* Illustration ink */
.ink      { stroke: var(--silver); fill: none; stroke-width: 1.4; }
.ink-soft { stroke: var(--silver-light); fill: none; stroke-width: 1.2; }
.ink-blue { stroke: var(--accent); fill: none; stroke-width: 1.6; }
.ink-navy { stroke: var(--logo-navy); fill: none; stroke-width: 1.6; }
.fill-blue { fill: var(--accent); }
.fill-navy { fill: var(--logo-navy-deep); }
.fill-white { fill: #fff; }
.corner { stroke: var(--accent); stroke-width: 1.1; opacity: 0.32; fill: none; }
.lbl { font-family: 'Cascadia Code', Consolas, monospace; font-size: 9px; letter-spacing: 0.1em; fill: var(--silver-dark); text-transform: uppercase; }
.lbl-b { font-family: 'Century Gothic', 'Segoe UI', sans-serif; font-size: 12px; font-weight: 700; fill: var(--logo-navy-deep); }
.lbl-n { font-family: 'Cascadia Code', Consolas, monospace; font-size: 13px; font-weight: 700; fill: var(--accent); }

/* ---------------- Edge arrows ---------------- */
.edge-nav {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 6;
  width: 46px; height: 46px; border-radius: 50%; cursor: pointer;
  background: rgba(255,255,255,0.88); border: 1px solid var(--border); color: var(--logo-navy);
  display: flex; align-items: center; justify-content: center;
  backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
  box-shadow: 0 4px 14px rgba(16,58,104,0.08);
  transition: border-color 0.2s ease, background 0.2s ease, color 0.2s ease;
}
.edge-nav:hover { border-color: var(--logo-navy); background: var(--logo-navy); color: var(--white); }
.edge-nav svg { width: 17px; height: 17px; stroke: currentColor; fill: none; stroke-width: 2; }
.edge-prev { left: clamp(8px, 1.6vw, 22px); }
.edge-next { right: clamp(8px, 1.6vw, 22px); }

/* ---------------- Controls ---------------- */
.slider-controls {
  position: relative; z-index: 4;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  padding: 0 clamp(16px, 5vw, 76px) clamp(8px, 2vh, 18px);
}
/* The fixed WhatsApp and assistant buttons own the bottom corners at every
   width — the assistant dock alone covers the rightmost 97px, more than the
   76px this row can ever inset by — so anything pinned to a corner here ends
   up underneath one of them. The whole group is centred instead, which keeps
   it in the clear lane between the two at all sizes. */
.slider-controls-right {
  display: flex; align-items: center; gap: 10px;
}

/* Above the phone breakpoint there is room to centre the dots exactly rather
   than centring the row as a whole: an empty first column balances the slide
   name and play button in the third, so the dots land on the section's true
   centre line. Below that the row stays a simple centred group — a third
   column there would push the play button back under the assistant launcher.
   980px is measured, not guessed: the widest slide name ("Why distributors
   choose us") needs 922px before the third column clears the launcher; 980
   leaves margin for fonts rendering wider on another machine. */
@media (min-width: 980px) {
  .slider-controls { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); }
  .dots { grid-column: 2; justify-self: center; }
  .slider-controls-right { grid-column: 3; justify-self: start; }
}

/* The slide name shows only where the grid above can centre the dots exactly.
   Below 980px it would sit beside the dots and shove them well off centre (126px
   at 701px), which is the opposite of what this row is for. Dropping it costs
   nothing: each dot already carries its slide name as an accessible label. */
@media (max-width: 979px) {
  .slide-name { display: none; }
}
.dots { display: flex; align-items: center; gap: 4px; }
.hdot { height: 44px; width: 34px; border: none; background: none; padding: 0; cursor: pointer; display: flex; align-items: center; justify-content: center; }
.hdot .bar { position: relative; height: 4px; width: 100%; border-radius: 4px; background: var(--silver-light); overflow: hidden; display: block; }
.hdot[aria-current="true"] .bar { background: rgba(16,58,104,0.22); }
.hdot .fill { position: absolute; inset: 0; width: 0; background: var(--accent); border-radius: 4px; }
.hdot[aria-current="true"] .fill.run { animation: dotFill var(--slide-ms, 7500ms) linear forwards; }
@keyframes dotFill { from { width: 0; } to { width: 100%; } }
.play-btn {
  display: none;
  width: 44px; height: 44px; border-radius: 50%; cursor: pointer; flex-shrink: 0;
  background: var(--white); border: 1px solid var(--border); color: var(--logo-navy);
  align-items: center; justify-content: center;
  transition: border-color 0.2s ease, background 0.2s ease, color 0.2s ease;
}
.play-btn:hover { border-color: var(--logo-navy); background: var(--logo-navy); color: var(--white); }
.play-btn svg { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 2; }
.slide-name { display: none; }

@media (max-width: 1080px) {
  /* Stacked: copy above, illustration below. Padding lives on the grid itself
     now, so the inset only needs stating once per breakpoint. It must clear the
     arrow's full box rather than approximate it — the arrow is 46px wide at up
     to ~17px inset here, reaching ~63px, so 70px leaves a genuine gap. */
  .slide-split {
    grid-template-columns: 1fr;
    /* Both rows size to their own content. The illustration row used to be
       minmax(0,1fr), which forces it to absorb whatever height is left over —
       so on a short window the copy row got squeezed below the height its text
       actually needs, and the copy (the CTA row in particular) spilled out of
       its row and printed over the illustration. align-content centres the
       pair when there IS spare room, which is what the 1fr was really for. */
    grid-template-rows: auto auto;
    align-content: center;
    /* Floor of 18px, not 6px: the copy enters via bloomUp, which starts each
       line 16px BELOW its resting spot. A gap smaller than that travel means
       the CTA row is drawn over the illustration for the first frames of the
       entrance even though the resting layout is clear. */
    gap: clamp(18px, 2.5vh, 24px);
    padding: clamp(14px,2.5vh,32px) 70px clamp(10px,2.5vh,28px);
  }
  .slide-text { justify-content: flex-end; text-align: center; align-items: center; }
  .slide p.lede { max-width: 54ch; }
  .slide-facts, .actions { justify-content: center; }
  .slide-centre { padding-left: 70px; padding-right: 70px; }
  .slide-visual { max-width: 400px; }
}

/* Card-stats mobile markup — hidden by default so desktop, which renders the
   SVG in .card-stats-visual just fine, never sees it. Placed here, before the
   640px query below that shows it, so the "display: flex" override there
   actually wins the cascade: same specificity, so source order decides, and
   an unconditional rule after a media query beats it regardless of viewport. */
.card-stats-mobile {
  display: none;
  flex-direction: column; gap: 10px;
  width: 100%; max-width: 340px; margin: 0 auto;
}
.cs-card {
  display: flex; align-items: center; gap: 12px;
  background: var(--white); border: 1px solid var(--border); border-radius: 14px;
  padding: 14px 16px;
}
.cs-check {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 50%;
  border: 2px solid var(--hero-accent); color: var(--hero-accent);
  display: flex; align-items: center; justify-content: center;
}
.cs-check svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 2.6; }
.cs-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.cs-title { font-size: 0.95rem; font-weight: 700; color: var(--hero-heading); line-height: 1.3; }
.cs-sub {
  font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-muted);
}
.cs-stat { flex: 0 0 auto; font-family: var(--font-mono); font-size: 1.2rem; font-weight: 800; color: var(--accent); }

/* Same mobile-only swap as .card-stats-mobile above, for slide 5's four
   process steps — see the comment beside .process-steps-mobile in index.php.
   Placed before the 640px query below for the same reason: an unconditional
   rule after a media query beats it regardless of viewport. */
.process-steps-mobile {
  display: none;
  flex-direction: column; gap: 10px;
  width: 100%; max-width: 340px; margin: 0 auto;
}
.ps-step {
  display: flex; align-items: center; gap: 12px;
  background: var(--white); border: 1px solid var(--border); border-radius: 14px;
  padding: 14px 16px;
}
.ps-num {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 50%;
  border: 2px solid var(--hero-accent); color: var(--hero-accent);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: 0.78rem; font-weight: 800;
}
.ps-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ps-badge {
  font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--accent);
}
.ps-title { font-size: 0.95rem; font-weight: 700; color: var(--hero-heading); line-height: 1.3; }
.ps-sub { font-size: 0.78rem; color: var(--text-muted); }

/* Slide 2's diagram gets a second, independently-drawn SVG for mobile rather
   than the HTML-card swap the other two slides use — see the comment beside
   .converge-mobile-visual in index.php for why. Hidden by default so desktop
   never sees it, same "declare before the 640px query" reasoning as above.
   Selector matches .slide-visual svg (line ~3690, "display: block") in
   specificity for the same reason as the mobile-toggle rule below: a bare
   class alone loses to that rule and would render on desktop regardless of
   this being unconditional. */
.slide-visual svg.converge-mobile-visual { display: none; }
/* Labels only exist on the mobile drawing, so no risk of this reaching the
   desktop SVG's — it shares the .lbl class but that stays 9px there. */
/* 16px let "Nutraceuticals" run to within 3 viewBox units of the 300-wide
   edge — reads fine but too tight a margin to be safe across font rendering
   variance. 14px keeps it centred with real clearance on both sides. */
.mobile-lbl { font-size: 14px; }

/* The world map is the one slide-6 visual made of hand-projected geography
   (real longitude/latitude paths), not simple shapes — redrawing it on a
   smaller viewBox the way slides 2/3/5 were isn't a safe hand-edit the way a
   circle or hexagon's coordinates are. Made bigger here the other way
   instead: letting just this slide's visual (not its text/button column,
   which keeps the normal 56px inset that clears the slider arrows) bleed
   past that padding on mobile, so the SAME map draws into more pixels
   without touching a single one of its coordinates. */
@media (max-width: 640px) {
  .worldmap-visual-wrap { margin-left: -24px; margin-right: -24px; }
  /* The extra width from the negative margin above was still being capped
     by the shared .slide-visual{max-width:280px} below (every other mobile
     slide's own cap, left untouched) rather than actually reaching the
     arrows — this raises the ceiling for just this one. */
  .worldmap-visual-wrap .slide-visual { max-width: 360px; }
  /* .wm-cap and .wm-hub-label (INDIA) are the map's only real text, and even
     at the bigger size above they're still 11-12px inside the map's own
     520-unit coordinate space — rendering under 7px on screen once that
     scales into a ~300px-wide mobile container. Bumped here rather than
     redrawn, same reasoning as the map's overall size above: this changes
     nothing about where anything on the map actually sits. Scoped to
     .worldmap-visual-wrap so .lbl-b elsewhere (slide 5's step titles) is
     untouched — that class is shared, this override isn't. */
  .worldmap-visual-wrap .wm-cap { font-size: 20px; }
  .worldmap-visual-wrap .wm-hub-label { font-size: 20px; }
  /* The dots marking each of the 25 export destinations were rendering at a
     4px diameter — present, but not something a visitor would actually
     notice. Same treatment as the ping rings and hub core around them. */
  .worldmap-visual-wrap .wm-dot { r: 5; }
  .worldmap-visual-wrap .wm-hub-core { r: 7; }
  .worldmap-visual-wrap .wm-hub-outer, .worldmap-visual-wrap .wm-ping { stroke-width: 2.2; }
}

@media (max-width: 640px) {
  .hero-lattice { display: none; }
  .slide-visual-wrap::before { display: none; }
  .slide-visual { max-width: 280px; }
  .slide p.lede { margin-bottom: 12px; }
  .hdot { width: 16px; }
  .hdot[aria-current="true"] { width: 30px; }
  .slider-controls { gap: 6px; }
  .actions { width: 100%; }
  /* Scoped to the slide action rows. Unscoped, this reached every .btn on the
     page — including the one in the mobile nav drawer, which is a column flex
     container, so flex-grow stretched it into a full-height block. */
  .actions .btn { flex: 1 1 auto; min-width: 44%; }
  /* Arrows stay, tucked to the edge and smaller. The content inset must clear
     the arrow's full box, not just look clear: at 375px the arrow spans 8→46px,
     and the CTA buttons stretch the full column here, so a 44px inset put a
     button's tap target underneath the arrow. 52px leaves a real gap. */
  .edge-nav { width: 38px; height: 38px; }
  .edge-nav svg { width: 15px; height: 15px; }
  .slide-centre { padding-left: 56px; padding-right: 56px; }
  .slide-split { padding-left: 56px; padding-right: 56px; }
  /* Slide 3's three stat cards swap from the SVG illustration to real HTML —
     see the comment beside .card-stats-mobile in index.php for why: the SVG's
     text is authored for a desktop-width render and there's no mobile screen
     size that scales it back to readable. Selector is .slide-visual svg.card-
     stats-visual, not just the bare class: .slide-visual svg (line ~3690,
     "display: block") outspecifies a single class alone and would win over a
     same-weight override regardless of this media query. */
  .slide-visual svg.card-stats-visual { display: none; }
  .card-stats-mobile { display: flex; }
  /* Same swap, same specificity reasoning, for slide 5's four process steps. */
  .slide-visual svg.process-steps-visual { display: none; }
  .process-steps-mobile { display: flex; }
  /* Slide 2 swaps to the second diagram redrawn on a smaller viewBox,
     rather than to HTML — see the comment beside .converge-mobile-visual
     in index.php. Both are <svg>, so this needs the same specificity fix
     as the two rules above it. */
  .slide-visual svg.converge-desktop-visual { display: none; }
  /* The mobile redraw is authored on a taller viewBox (300x330, vs the
     desktop original's 520x400) so the labels have room without shrinking
     to unreadable — at the same rendered width that's 289px tall against
     the original's 202px. That extra height ate most of the clearance
     between this and the fact-pill/button row above, which was tuned around
     the shorter original: fine at rest (~30px gap), but the entrance
     animation's flyTop keyframe (cubic-bezier(0.22,1,0.3,1), a curve that
     overshoots past its resting position before settling, by design — the
     same "settle into place" bounce every .cv-top/.cv-left/.cv-right node
     uses) pushes through that 30px during the bounce and out the other
     side, so the node visibly overlaps the button for the last stretch of
     its entrance rather than stopping short of it. A wider rest margin is
     what actually fixes it — 30px was never going to survive a bounce past
     its own target, whatever the exact overshoot turns out to be. */
  .slide-visual svg.converge-mobile-visual { display: block; margin-top: 28px; }
}
@media (max-width: 380px) {
  .hdot { width: 12px; }
  .hero-stats { gap: 8px 16px; }
}
@media (hover: none) { .hero .btn-primary:hover { transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .slide { transition: none; }
  .slide.is-active *, .slide.is-active { animation: none !important; }
  .slide.is-active .gl-line, .slide.is-active .cv-bond, .slide.is-active .cv-orbit,
  .slide.is-active .rt-path, .slide.is-active .cd-tick { stroke-dasharray: none; }
  .capability-track { animation: none; }
}

/* Collapsible per-slide groups inside the Hero Slides card — five slides of
   nine fields is 45 inputs, which is unusable as one flat list. */
.admin-slide { border: 1px solid var(--admin-border); border-radius: 10px; margin-bottom: 12px; background: #fbfcfd; }
.admin-slide > summary {
  cursor: pointer; padding: 12px 14px; font-weight: 600; font-size: 0.92rem;
  color: var(--admin-ink); list-style: none; display: flex; align-items: center; gap: 8px;
}
.admin-slide > summary::-webkit-details-marker { display: none; }
.admin-slide > summary::before {
  content: ""; width: 7px; height: 7px; flex-shrink: 0;
  border-right: 2px solid var(--admin-muted); border-bottom: 2px solid var(--admin-muted);
  transform: rotate(-45deg); transition: transform 0.2s ease;
}
.admin-slide[open] > summary::before { transform: rotate(45deg); }
.admin-slide[open] > summary { border-bottom: 1px solid var(--admin-border); margin-bottom: 14px; }
.admin-slide > *:not(summary) { padding-left: 14px; padding-right: 14px; }
.admin-slide > *:last-child { padding-bottom: 4px; }

/* Per-card save. The settings page is one long form, so a change near the top
   used to mean scrolling to the bottom to commit it. This submits the same
   form — every field still saves — it is just a closer place to click. */
.admin-card-save {
  display: flex; justify-content: flex-end; align-items: center; gap: 12px;
  margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--admin-border);
}
.admin-card-save .btn { padding: 9px 20px; font-size: 0.88rem; }
.admin-card-save .hint { font-size: 0.78rem; color: var(--admin-muted); }
