/* ==========================================================================
   ERA Sanitary & Plumbing Solutions
   Dark brand ground, amber accent. Bengali copy uses Noto Sans Bengali, which
   is listed after Barlow everywhere so each script falls to the right face.
   ========================================================================== */

/* ==========================================================================
   Web fonts — self-hosted, not loaded from Google
   RULES.md rule 5 bans third-party scripts on customer-facing pages. A
   stylesheet was within the letter of that rule, which is why the Google Fonts
   link survived this long, but it is still a render-blocking request to a host
   we do not control, on the connection where that hurts most. These files were
   the site's last third-party request.

   It saves no bytes — they are the same files Google served. What it buys is
   two fewer DNS+TLS handshakes and one fewer cross-origin round trip before
   any text paints. Cross-site cache partitioning left no shared-cache benefit
   to give up by self-hosting.

   Archivo and Noto Sans Bengali are variable fonts: one file covers every
   weight, which is why each is declared 100 900 rather than once per weight.
   Noto replaced Hind Siliguri, which was static and cost three files and
   213.7 KB to do the same job in 105.2 KB.

   Barlow ships at 400 and 700 only. Every 500 and 600 in this stylesheet sits
   under a rule that sets --font-display, so it resolves to Archivo's variable
   file and never to Barlow — checked by resolving the family for each of those
   rules, and again by crawling all 32 pages and recording what the browser
   actually asked for. Shipping 500 and 600 was 43.7 KB nothing could reach.

   "Bengali Switch" is the same Noto face cut down to the three characters বাং
   and nothing else, 952 bytes. The language switch is the ONLY Bengali on an
   English page, and drawing it from the full face cost 71 KB with Hind Siliguri
   and would have cost 105 KB with Noto — about half an English page's font
   weight, for three glyphs. It needs its own family name: two @font-face rules
   on one family with overlapping unicode-ranges resolve to the last declared,
   so the full face would win and the saving would vanish. See .langswitch below.

   The subsets do the rest. Measured by loading each page and recording every
   woff2 the browser actually asked for: 79.0 KB of fonts on an English page,
   183.2 KB on a Bengali one. Before this face changed, 149.3 and 291.7. No
   English page fetches the full Bengali face at all any more — checked on all
   five page types in both languages, not inferred.

   Generated by tools/fetch-web-fonts.py. Re-run it rather than hand-editing a
   unicode-range: a wrong range does not error, it silently stops a face being
   used for the script it was fetched for. Adding a weight to this stylesheet
   means adding it to WANT in that script, or the browser synthesises it.
   ========================================================================== */

@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/archivo-latin-var.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Barlow";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/barlow-latin-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Barlow";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/barlow-latin-700.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Noto Sans Bengali";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/noto-sans-bengali-var.woff2") format("woff2");
  unicode-range: U+0951-0952, U+0964-0965, U+0980-09FE, U+1CD0, U+1CD2, U+1CD5-1CD6, U+1CD8, U+1CE1, U+1CEA, U+1CED, U+1CF2, U+1CF5-1CF7, U+200C-200D, U+20B9, U+25CC, U+A8F1, U+11DF0-11DF1;
}
@font-face {
  font-family: "Bengali Switch";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/noto-sans-bengali-switch-700.woff2") format("woff2");
  unicode-range: U+982, U+9ac, U+9be;
}

:root {
  --bg:        #0b0b0d;
  --bg-2:      #0e0f12;
  --surface:   #141519;
  --surface-2: #16171b;
  --line:      #22242a;   /* decorative dividers */
  --line-2:    #2a2c33;   /* decorative borders */
  --line-ui:   #6b6e78;   /* interactive boundaries — 3.75:1 on --bg, meets 1.4.11 */

  --text:   #f3f3f4;
  --muted:  #c9cbd2;
  --muted-2:#a7a9b2;   /* 8.0:1 on --bg */

  --amber:    #f7b500;
  --amber-hi: #ffcb2e;
  --star:     #f7b500;   /* 10.1:1 on --surface; empty stars use --line-ui at 3.6:1 */
  --blue:     #1b69c4;
  --red:      #d8232a;
  --ink:      #151515;

  --font-display: "Archivo", "Noto Sans Bengali", system-ui, sans-serif;
  --font-body:    "Barlow", "Noto Sans Bengali", system-ui, sans-serif;

  --shell: 1200px;
  --r-sm: 8px;
  --r: 12px;
  --r-lg: 18px;
  --section-y: clamp(52px, 6.5vw, 92px);
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.6;
  overflow-x: hidden;
}
img, svg { display: block; max-width: 100%; }
img { height: auto; }
h1, h2, h3 { font-family: var(--font-display); line-height: 1.12; letter-spacing: -0.015em; margin: 0 0 .5em; }
p { margin: 0 0 1em; }
ul, ol { margin: 0; padding: 0; list-style: none; }
a { color: var(--amber); text-decoration: none; }
a:hover { color: var(--amber-hi); }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
table { border-collapse: collapse; width: 100%; }
::selection { background: var(--amber); color: var(--ink); }

:focus-visible { outline: 3px solid var(--amber); outline-offset: 3px; border-radius: 4px; }

.skip-link {
  position: absolute; left: 16px; top: -64px; z-index: 200;
  padding: 10px 18px; background: var(--amber); color: var(--ink);
  border-radius: 0 0 8px 8px; font-weight: 700; transition: top .2s ease;
}
.skip-link:focus { top: 0; }

.shell { width: min(100% - 40px, var(--shell)); margin-inline: auto; }
.section { padding-block: var(--section-y); }
.ic { width: 20px; height: 20px; flex: none; }
.amber { color: var(--amber); }
.muted { display: flex; align-items: center; gap: 8px; color: var(--muted-2); font-size: 14px; }

/* ---------- Topbar + header ---------- */
.topbar {
  background: var(--amber); color: var(--ink);
  font-family: var(--font-display); font-weight: 600; font-size: 13px; letter-spacing: .03em;
}
.topbar__inner { display: flex; flex-wrap: wrap; gap: 6px 28px; justify-content: space-between; padding-block: 9px; }

/* Opaque by default, translucent-and-blurred only at desktop — see the
   min-width: 1025px block at the end of this file. The blur CANNOT live here:
   backdrop-filter makes an element the containing block for its position:fixed
   descendants, and .nav is fixed inside this header below 1025px. With the
   blur applied, the mobile menu resolved top/bottom against this 85px header
   instead of the viewport and rendered 43px tall holding 360px of content —
   the first link sliced in half and every link below it unreachable. The whole
   mobile navigation was dead and it shipped that way. */
.site-header {
  position: sticky; top: 0; z-index: 60;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}
.header__inner { display: flex; align-items: center; gap: 22px; padding-block: 13px; }

.brand { display: inline-flex; align-items: center; gap: 12px; color: var(--text); }
.logo img { width: 44px; height: 44px; border-radius: 50%; }
.brand__text strong { display: block; font-family: var(--font-display); font-weight: 800; font-size: 19px; letter-spacing: -0.01em; line-height: 1.05; }
/* Scoped to the class, not to any span inside the strong — the second line of
   the name is a span too, and the old selector would have turned it amber. */
.brand__text strong .brand__gold { color: var(--amber); }
/* The rest of the registered name, subordinate to it: the shopfront sign sets
   "& Plumbing Solutions" the same way. letter-spacing is reset because the
   -0.01em tightening above is for 19px display type, not for 13px. */
.brand__text strong .brand__sub {
  display: block; margin-top: 3px;
  font-size: 13px; font-weight: 600; letter-spacing: 0; line-height: 1.2;
  color: var(--text);
}
.brand__text small { display: block; font-size: 12px; color: var(--muted-2); }

.nav { display: flex; align-items: center; gap: 20px; margin-left: auto; }
.nav__list { display: flex; align-items: center; gap: 4px; }
.nav__list a {
  display: block; padding: 10px 16px; border-radius: var(--r-sm);
  font-family: var(--font-display); font-weight: 600; font-size: 15px; color: var(--muted);
  transition: background-color .18s ease, color .18s ease;
}
.nav__list a:hover { color: var(--amber); background: var(--surface-2); }
.nav__list a[aria-current="page"] { background: var(--surface-2); color: var(--amber); }
.nav__aside { display: flex; align-items: center; gap: 14px; }

.langswitch { display: flex; align-items: center; gap: 2px; margin: 0; padding: 3px; border: 1px solid var(--line-2); border-radius: 999px; }
.langswitch > * {
  display: block; padding: 6px 14px; border-radius: 999px;
  font-family: var(--font-display); font-weight: 700; font-size: 13px;
}
.langswitch__on { background: var(--amber); color: var(--ink); }
.langswitch a { color: var(--muted-2); }
.langswitch a:hover { color: var(--amber); }

/* On an ENGLISH page this <a lang="bn"> holds বাং and is the only Bengali on
   the page. It gets a face cut to those three characters — 952 bytes — instead
   of pulling the whole 105 KB Bengali font to draw them. The full face sits
   behind it as a safety net and is never reached, because the subset covers
   every character here.

   A Bengali page does not match: its own বাং is in the <span class="langswitch__on">,
   which carries no lang attribute and inherits bn from <html>, so it draws from
   the page's face — already downloaded for the rest of the page.

   (0,2,0) against the (0,1,0) of `.langswitch > *` above, which sets
   --font-display. Specificity, not !important.

   Change the label text and the subset no longer covers it. build.js refuses
   the build in that case — see checkLangSwitchSubset(). */
.langswitch [lang="bn"] {
  font-family: "Bengali Switch", "Noto Sans Bengali", sans-serif;
}

.nav-toggle { display: none; margin-left: auto; width: 44px; height: 44px; padding: 10px; }
.nav-toggle span { display: block; height: 2px; border-radius: 2px; background: var(--text); transition: transform .22s ease, opacity .22s ease; }
.nav-toggle span + span { margin-top: 5px; }
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  min-height: 48px; padding: 12px 24px; border-radius: 999px;
  font-family: var(--font-display); font-weight: 700; font-size: 15px;
  border: 1px solid transparent; transition: transform .16s ease, background-color .16s ease, border-color .16s ease;
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: none; }
.btn--accent { background: var(--amber); color: var(--ink); }
.btn--accent:hover { background: var(--amber-hi); color: var(--ink); }
.btn--ghost { border-color: var(--line-ui); color: var(--text); }
.btn--ghost:hover { border-color: var(--amber); color: var(--amber); }
.btn--sm { min-height: 40px; padding: 8px 18px; font-size: 14px; }
.btn--block { display: flex; width: 100%; }

.link-more {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--font-display); font-weight: 700; font-size: 14px; color: var(--amber);
}
.link-more .ic { width: 17px; height: 17px; transition: transform .16s ease; }
.link-more:hover .ic { transform: translateX(3px); }

/* ---------- Photo slots (pending client photography) ---------- */
.slot {
  display: grid; place-items: center; padding: 24px; min-height: 180px;
  border: 1px dashed var(--line-2); border-radius: var(--r-lg);
  background:
    repeating-linear-gradient(135deg, rgb(247 181 0 / 4%) 0 10px, transparent 10px 20px),
    var(--bg-2);
  color: var(--muted-2); text-align: center;
}
.slot span { font-family: var(--font-display); font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.slot--hero { min-height: 400px; }
.slot--card { min-height: 148px; border-radius: var(--r) var(--r) 0 0; border-bottom: 0; }
.slot--cat { min-height: 260px; }
.slot--why, .slot--about { min-height: 300px; }

/* ---------- Google reviews ----------
   Real reviews, typed into content/reviews.json by hand. The section is left
   out entirely while that file is empty, so none of this renders until there is
   something true to put in it. */
.revs { background: var(--bg-2); border-block: 1px solid var(--line); }
.revs .section-head h2 { display: flex; align-items: center; gap: 11px; }
.revs .section-head h2 .ic { color: var(--star); }

.stars { display: inline-flex; gap: 2px; vertical-align: middle; }
.stars .star { display: block; width: 17px; height: 17px; color: var(--line-ui); }
.stars .star.is-on { color: var(--star); }
.stars .ic { display: block; width: 100%; height: 100%; }

.revs__score {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  margin: 0 0 22px; font-family: var(--font-display);
}
.revs__score strong { font-size: 22px; font-weight: 800; }
.revs__score span { color: var(--muted-2); font-size: 14.5px; font-weight: 600; }

.revs__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(14px, 1.8vw, 20px); }
.rev {
  display: flex; flex-direction: column; gap: 12px; margin: 0;
  padding: 22px; border: 1px solid var(--line); border-radius: var(--r);
  background: var(--surface);
}
.rev blockquote {
  margin: 0; font-size: 15px; line-height: 1.6; color: var(--muted);
  /* A long review should not stretch one card past the others in its row. */
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 7; overflow: hidden;
}
.rev figcaption {
  margin-top: auto; padding-top: 4px;
  font-family: var(--font-display); font-weight: 700; font-size: 14.5px; color: var(--text);
}
.rev figcaption span { display: block; font-weight: 500; font-size: 13px; color: var(--muted-2); }

/* The real photographs, once they exist. Each variant matches the placeholder
   it replaces — same corners, same edges, same position in its grid — so a page
   with nine photos and twelve placeholders still reads as one page rather than
   two half-finished ones. Kept together here, rather than beside each component,
   because what matters is that they agree with the .slot rules above.

   aspect-ratio does the work the placeholders' min-height did: the box is the
   right shape before the image has loaded, so nothing moves as they arrive. The
   files are already cut to these ratios, and object-fit: cover is insurance
   against a hand-placed file that is not. */
.photo {
  display: block; overflow: hidden; border-radius: var(--r-lg);
  background: var(--bg-2);
}
.photo img { display: block; width: 100%; height: 100%; object-fit: cover; }

.photo--hero { aspect-ratio: 4 / 3; }
.photo--why, .photo--about { aspect-ratio: 5 / 4; }
.photo--cat { aspect-ratio: 4 / 3; }
.photo--trade { aspect-ratio: 16 / 10; }
.photo--face { aspect-ratio: 1 / 1; }
.photo--card {
  aspect-ratio: 16 / 9; border-radius: var(--r) var(--r) 0 0;
}
.photo--svc {
  aspect-ratio: 4 / 3; border-radius: 0;
  border-bottom: 1px solid var(--line);
}

/* ---------- Hero ---------- */
.hero { padding-block: clamp(36px, 5vw, 66px) clamp(30px, 4vw, 48px); }
.hero__grid { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); gap: clamp(28px, 4vw, 52px); align-items: center; }
.badge {
  display: inline-flex; align-items: center; gap: 9px; margin: 0 0 20px;
  padding: 8px 16px; border: 1px solid var(--line-2); border-radius: 999px;
  background: var(--surface); color: var(--muted);
  font-family: var(--font-display); font-weight: 600; font-size: 13px;
}
.badge .ic { color: var(--amber); }
.hero h1 { font-size: clamp(34px, 4.6vw, 56px); font-weight: 800; margin-bottom: 18px; }
.lede { font-size: clamp(16px, 1.3vw, 18px); color: var(--muted); max-width: 56ch; }
.hero__actions { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 28px; }
.facts { display: flex; flex-wrap: wrap; gap: 14px 40px; margin-top: 34px; padding-top: 26px; border-top: 1px solid var(--line); }
.facts strong { display: block; font-family: var(--font-display); font-size: 26px; font-weight: 800; color: var(--amber); line-height: 1.1; }
.facts span { font-size: 14px; color: var(--muted-2); }

/* ---------- Pillars ---------- */
.pillars-band { background: var(--bg-2); border-block: 1px solid var(--line); }
.pillars { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(18px, 2.4vw, 32px); }
.pillar__n { margin: 0 0 8px; font-family: var(--font-display); font-size: 13px; font-weight: 800; letter-spacing: .16em; color: var(--amber); }
.pillar h3 { font-size: 20px; font-weight: 700; margin-bottom: 8px; }
.pillar p { margin: 0; font-size: 15px; color: var(--muted-2); }

/* ---------- Section head + category cards ---------- */
.section-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 14px; margin-bottom: clamp(24px, 3vw, 38px); }
.section-head h2 { margin: 0; font-size: clamp(26px, 3vw, 36px); font-weight: 700; }

.cat-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(16px, 2vw, 24px); }
.cat-card {
  display: flex; flex-direction: column; overflow: hidden; color: var(--text);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  transition: border-color .18s ease, transform .18s ease;
}
.cat-card:hover { border-color: var(--amber); transform: translateY(-3px); color: var(--text); }
.cat-card__body { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; padding: 18px; }
.cat-card__size { margin: 0; font-family: var(--font-display); font-size: 12px; font-weight: 700; letter-spacing: .1em; color: var(--amber); }
.cat-card h3 { margin: 0; font-size: 17px; font-weight: 700; }
.cat-card p { margin: 0; font-size: 14px; color: var(--muted-2); }
.cat-card .link-more { margin-top: auto; padding-top: 10px; }

/* An odd category count leaves the last card alone on its row; let it span
   the row and turn side-on rather than sit as a stranded third. */
.cat-grid > .cat-card:last-child:nth-child(3n + 1) { grid-column: 1 / -1; }

@media (min-width: 1025px) {
  .cat-grid > .cat-card:last-child:nth-child(3n + 1) { flex-direction: row; align-items: stretch; }
  .cat-grid > .cat-card:last-child:nth-child(3n + 1) .slot {
    flex: 0 0 32%; min-height: 0; border-radius: var(--r) 0 0 var(--r);
    border-right: 0; border-bottom: 1px dashed var(--line-2);
  }
  .cat-grid > .cat-card:last-child:nth-child(3n + 1) .cat-card__body { flex: 1 1 auto; justify-content: center; padding: 26px 30px; }
}

/* ---------- Why ---------- */
.why__grid { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr); gap: clamp(26px, 3.5vw, 48px); align-items: center; }
.why h2 { font-size: clamp(24px, 2.8vw, 34px); font-weight: 700; margin-bottom: 22px; }
.reasons { display: grid; gap: 18px; }
.reasons li { display: flex; gap: 13px; }
.reasons .ic { color: var(--amber); margin-top: 3px; }
.reasons h3 { margin: 0 0 3px; font-size: 16px; font-weight: 700; }
.reasons p { margin: 0; font-size: 15px; color: var(--muted-2); }

/* ---------- Areas marquee ---------- */
.areas { padding-block: clamp(36px, 4vw, 56px); background: var(--bg-2); border-block: 1px solid var(--line); overflow: hidden; }
.areas__title { font-size: clamp(20px, 2.2vw, 26px); font-weight: 700; margin-bottom: 22px; }
.marquee { position: relative; -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
.marquee__track { display: flex; gap: 12px; width: max-content; animation: era-marquee 42s linear infinite; }
.marquee__track li {
  padding: 10px 20px; border: 1px solid var(--line-2); border-radius: 999px;
  background: var(--surface); color: var(--muted);
  font-family: var(--font-display); font-weight: 600; font-size: 14px; white-space: nowrap;
}
@keyframes era-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* ---------- Band CTA ---------- */
.band { padding-block: clamp(38px, 4.5vw, 60px); background: linear-gradient(115deg, var(--amber) 0%, #ffd45e 100%); color: var(--ink); }
.band__inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 26px; }
.band h2 { margin: 0 0 6px; font-size: clamp(22px, 2.6vw, 30px); font-weight: 800; color: var(--ink); max-width: 30ch; }
.band p { margin: 0; font-size: 15px; max-width: 58ch; color: #3a3118; }
.band__actions { display: flex; flex-wrap: wrap; gap: 12px; }
.band .btn--accent { background: var(--ink); color: #fff; }
.band .btn--accent:hover { background: #000; color: #fff; }
.band .btn--ghost { border-color: rgb(21 21 21 / 35%); color: var(--ink); }
.band .btn--ghost:hover { border-color: var(--ink); color: var(--ink); background: rgb(255 255 255 / 30%); }

/* ---------- Page head + products ---------- */
.page-head { padding-block: clamp(40px, 5vw, 64px) clamp(20px, 2.4vw, 30px); border-bottom: 1px solid var(--line); }
.page-head h1 { font-size: clamp(30px, 4vw, 46px); font-weight: 800; margin-bottom: 14px; }

.cats { display: grid; gap: clamp(28px, 3.4vw, 48px); padding-block: clamp(36px, 4.5vw, 64px); }
.cat { display: grid; grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); gap: clamp(20px, 3vw, 40px); align-items: center; }
/* Alternate sides, but keep the text measure constant: swap the tracks too,
   otherwise the copy column changes width row to row. */
.cat:nth-child(even) { grid-template-columns: minmax(0, 1.2fr) minmax(0, .8fr); }
.cat:nth-child(even) .slot { order: 2; }
.cat__n { display: flex; align-items: center; gap: 10px; margin: 0 0 8px; font-family: var(--font-display); font-size: 13px; font-weight: 700; letter-spacing: .12em; color: var(--amber); }
.cat__n span { padding: 3px 9px; border-radius: 6px; background: rgb(247 181 0 / 14%); }
.cat h2 { font-size: clamp(22px, 2.6vw, 30px); font-weight: 700; margin-bottom: 10px; }
.cat__long { color: var(--muted); font-size: 16px; }

.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chips li {
  padding: 7px 14px; border: 1px solid var(--line-2); border-radius: 999px;
  background: var(--surface); color: var(--muted); font-size: 14px;
}

/* ---------- Product items ----------
   One card per catalogue item, with the plain chip list kept underneath as the
   reference. Each category keeps its own grid inside its own <article>, so
   nothing here is shared between sections and opening one item leaves every
   other section exactly where it was.

   No letter-spacing on .item__name on purpose. Tracking breaks Bengali
   conjuncts, and while html[lang="bn"] body * would reset it anyway at (0,1,2),
   a rule that never sets it cannot be the one that gets overridden wrongly
   later. Eighty-two Bengali labels is not where to find that out. */
.items {
  display: grid; gap: 12px; margin: 0 0 18px; padding: 0; list-style: none;
  grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
}
.item {
  display: flex; flex-direction: column; overflow: hidden;
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--surface);
}
.item__name {
  padding: 8px 10px 10px; font-size: 13px; line-height: 1.35;
  color: var(--muted); text-align: center;
}

/* The whole picture is the control, so the tap target is the card, never a
   small icon on it — this grid is read on a phone. */
.item__hit {
  display: block; width: 100%; padding: 0; border: 0; background: none;
  cursor: zoom-in; color: inherit; font: inherit;
}
.item__hit .photo, .item__hit .slot { border-radius: 0; }
.item__hit:focus-visible { outline: 3px solid var(--amber); outline-offset: -3px; }

.photo--item { aspect-ratio: 1 / 1; border-radius: 0; }
.slot--item {
  aspect-ratio: 1 / 1; min-height: 0; padding: 10px; border: 0;
  border-bottom: 1px dashed var(--line-2); border-radius: 0;
}

/* The reference list, now sitting under the cards rather than instead of them.
   Quieter than it was, because the pictures carry the page and this is the
   thing you scan when you already know the name of the part you want. */
.chips--ref { margin-top: 4px; }
.chips--ref li { font-size: 13px; padding: 5px 11px; color: var(--muted-2); }

/* One dialog per page, reused by every card. */
.lightbox {
  width: min(92vw, 560px); padding: 0; border: 1px solid var(--line-2);
  border-radius: var(--r-lg); background: var(--surface); color: var(--text);
}
.lightbox::backdrop { background: rgb(0 0 0 / 72%); }
.lightbox__img { display: block; width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: cover; }
.lightbox__cap {
  margin: 0; padding: 14px 16px; text-align: center;
  font-family: var(--font-display); font-weight: 600;
}
.lightbox__close {
  position: absolute; inset-block-start: 10px; inset-inline-end: 10px;
  min-height: 44px; min-width: 44px; padding: 0 14px;
  border: 1px solid var(--line-ui); border-radius: 999px;
  background: var(--bg-2); color: var(--text); font: inherit; cursor: pointer;
}

/* ---------- About ---------- */
.about__grid { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, .8fr); gap: clamp(26px, 3.5vw, 48px); align-items: start; padding-block: clamp(32px, 4vw, 52px); }
.about__copy p { color: var(--muted); }

/* The owner, under the About story.

   A 120px circle, and the size is the whole argument. The photograph is a
   formal studio headshot on a plain white background, which sits at roughly
   20:1 against --bg: not a contrast failure, a weight problem. Drawn at card
   size it is the brightest object on the page and outweighs both the shopfront
   photo beside it and the copy it belongs to. At 120px and round, the white
   reads as a deliberate light disc and the eye sees a face — which is the same
   move .logo img already makes with the gold badge at 44px.

   The ring is --line-ui at a measured 3.75:1 on --bg, so the circle has a
   boundary that meets 1.4.11 without introducing a colour. */
.owner {
  display: flex; align-items: center; gap: 16px;
  /* figure defaults to margin: 1em 40px, and that 40px would indent the block
     out of line with the paragraphs above it. */
  margin: clamp(22px, 3vw, 30px) 0 0;
  padding-top: clamp(22px, 3vw, 30px);
  border-top: 1px solid var(--line);
}
/* The placeholder is cut to the same circle as the photograph, so the box does
   not change shape on the day the file lands. .slot is built for a big dashed
   panel — its 180px floor and 24px padding both have to go. */
.owner .photo, .owner .slot {
  flex: 0 0 120px; width: 120px; min-height: 0;
  aspect-ratio: 1 / 1; padding: 0;
  border-radius: 50%; overflow: hidden;
  border: 1px solid var(--line-ui);
}
/* Size and padding only. A letter-spacing here would be (0,2,1) and beat the
   (0,1,2) Bengali reset at the end of this file, putting tracking back on
   Bengali conjuncts in the one place nobody would look. */
.owner .slot span { font-size: 11px; padding: 0 10px; }
.owner figcaption strong {
  display: block;
  font-family: var(--font-display); font-weight: 700; font-size: 18px;
  color: var(--text);
}
.owner figcaption span { font-size: 14px; color: var(--muted-2); }
.stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 18px; padding: clamp(22px, 2.6vw, 32px); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); }
.stats strong { display: block; font-family: var(--font-display); font-size: clamp(24px, 3vw, 34px); font-weight: 800; color: var(--amber); line-height: 1.05; }
.stats span { font-size: 14px; color: var(--muted-2); }

.two-col { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(26px, 3.5vw, 48px); }
.two-col h2 { display: flex; align-items: center; gap: 10px; font-size: 20px; font-weight: 700; margin-bottom: 16px; }
.two-col h2 .ic { color: var(--amber); }
.ticks { display: grid; gap: 10px; }
.ticks li { display: flex; align-items: center; gap: 10px; font-size: 15px; color: var(--muted); }
.ticks .ic { width: 18px; height: 18px; color: var(--amber); }

/* ---------- Contact ---------- */
.contact__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(18px, 2.2vw, 26px); padding-block: clamp(32px, 4vw, 52px); align-items: start; }
.card { padding: clamp(20px, 2.4vw, 28px); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); }
.card__label { font-family: var(--font-display); font-size: 12px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--amber); margin: 0 0 10px; }
.card__label + .card__label,
.card__list + .card__label,
.link-more + .card__label { margin-top: 26px; }
.card__addr { font-size: 16px; color: var(--text); margin-bottom: 10px; }
.card__list { display: grid; gap: 12px; margin-bottom: 22px; }
.card__list li { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.card__list a { font-family: var(--font-display); font-size: 19px; font-weight: 700; }
/* Both numbers take WhatsApp, so each row carries its own chat action. */
.card__list .chat-link {
  display: inline-flex; align-items: center; gap: 6px; margin-left: auto;
  padding: 5px 12px; border: 1px solid var(--line-ui); border-radius: 999px;
  font-size: 13px; font-weight: 600; color: var(--muted);
  transition: border-color .16s ease, color .16s ease;
}
.card__list .chat-link:hover { border-color: var(--amber); color: var(--amber); }
.card__list .chat-link .ic { width: 15px; height: 15px; }
/* The address is long enough to need breaking; the numbers are not. */
.card__list--email a { font-size: 16px; overflow-wrap: anywhere; }
.card .muted { margin: 12px 0 0; }
.card--form h2 { font-size: 20px; font-weight: 700; margin-bottom: 6px; }

.hours th, .hours td { padding: 10px 0; border-bottom: 1px solid var(--line); text-align: left; font-weight: 400; font-size: 15px; }
.hours th { color: var(--muted-2); }
.hours td { color: var(--text); font-family: var(--font-display); font-weight: 600; text-align: right; white-space: nowrap; }
.hours tr:last-child th, .hours tr:last-child td { border-bottom: 0; }

.field { display: grid; gap: 6px; margin: 0 0 14px; }
.field label { font-family: var(--font-display); font-size: 11px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--muted-2); }
.field input, .field select, .field textarea {
  width: 100%; min-height: 46px; padding: 11px 14px;
  background: var(--bg); color: var(--text);
  border: 1px solid var(--line-ui); border-radius: var(--r-sm);
  font-family: var(--font-body); font-size: 16px;
}
.field textarea { min-height: 104px; resize: vertical; }
.field input::placeholder, .field textarea::placeholder { color: #7f818a; }
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--amber); outline-offset: 1px; }
.form-error { margin: 0 0 12px; padding: 10px 14px; border-radius: var(--r-sm); background: rgb(216 35 42 / 14%); border: 1px solid var(--red); color: #ffb3b6; font-size: 14px; }

/* ---------- Footer ---------- */
.site-footer { border-top: 1px solid var(--line); background: var(--bg-2); padding-top: clamp(38px, 4.5vw, 60px); }
.footer__grid { display: grid; grid-template-columns: 1.6fr 1fr 1.4fr; gap: clamp(24px, 3vw, 44px); }
.footer__brand p { margin: 16px 0 0; font-size: 14px; color: var(--muted-2); max-width: 44ch; }
.footer__col h2 { font-family: var(--font-display); font-size: 12px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--amber); margin: 0 0 14px; }
.footer__col li + li { margin-top: 9px; }
.footer__col a { color: var(--muted); font-size: 15px; }
.footer__col a:hover { color: var(--amber); }
.footer__contact li { display: flex; align-items: flex-start; gap: 10px; }
.footer__contact .ic { color: var(--amber); margin-top: 3px; }
.footer__contact .wrap { overflow-wrap: anywhere; }
.footer__legal { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px; margin-top: clamp(30px, 3.5vw, 46px); padding-block: 18px; border-top: 1px solid var(--line); }
.footer__legal p { margin: 0; font-size: 13px; color: var(--muted-2); }

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width: 1024px) {
  .revs__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .nav-toggle { display: block; }
  .nav {
    position: fixed; inset: auto 0 0; top: var(--header-bottom, 108px); z-index: 55;
    flex-direction: column; align-items: stretch; gap: 10px;
    max-height: calc(100dvh - var(--header-bottom, 108px)); overflow-y: auto;
    padding: 16px 20px 26px; background: var(--bg); border-top: 1px solid var(--line);
    transform: translateY(-10px); opacity: 0; visibility: hidden;
    transition: transform .2s ease, opacity .2s ease, visibility .2s;
  }
  .nav.is-open { transform: none; opacity: 1; visibility: visible; }
  .nav__list { flex-direction: column; align-items: stretch; gap: 2px; }
  .nav__list a { padding: 12px 14px; font-size: 16px; }
  .nav__aside { justify-content: space-between; }

  .hero__grid, .why__grid, .about__grid { grid-template-columns: 1fr; }
  .cat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .contact__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .card--form { grid-column: 1 / -1; }
  .footer__grid { grid-template-columns: 1fr 1fr; }
  .footer__brand { grid-column: 1 / -1; }
}

@media (max-width: 760px) {
  body { font-size: 16px; }
  .topbar__delivery { display: none; }
  .pillars { grid-template-columns: 1fr; }
  .revs__grid { grid-template-columns: 1fr; }
  /* One per row on a phone, so nothing is clamped that does not need to be. */
  .rev blockquote { -webkit-line-clamp: none; }
  .cat { grid-template-columns: 1fr; }
  .cat:nth-child(even) .slot { order: 0; }
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .two-col { grid-template-columns: 1fr; }
  .contact__grid { grid-template-columns: 1fr; }
  .band__inner { flex-direction: column; align-items: flex-start; }
  .facts { gap: 14px 28px; }
}

@media (max-width: 520px) {
  .cat-grid { grid-template-columns: 1fr; }
  .footer__grid { grid-template-columns: 1fr; }
  .hero__actions .btn, .band__actions .btn { flex: 1 1 100%; }
  .slot--hero { min-height: 240px; }
  .owner { gap: 14px; }
  .owner .photo, .owner .slot { flex-basis: 96px; width: 96px; }
}

/* ==========================================================================
   Motion + print
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
  .marquee__track { animation: none; flex-wrap: wrap; width: auto; }
  .marquee { -webkit-mask-image: none; mask-image: none; }
}

/* ==========================================================================
   Phone-first
   Most of this audience is on an Android phone on mobile data. These rules
   come from measuring the built site at 390x844, not from taste. Every number
   quoted below was read off that measurement.
   ========================================================================== */

/* ---------- The contact bar ----------
   Hidden at desktop, where the header already carries a WhatsApp button that
   is always on screen. Below 760px that button is inside the collapsed nav and
   therefore NOT visible, which left the phone with one contact action (the
   hero's, at y=458) on a page 7.7 screens tall. */
.callbar { display: none; }

@media (max-width: 760px) {
  .callbar {
    position: fixed; inset: auto 0 0; z-index: 50;
    display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
    background: var(--line-2);
    border-top: 1px solid var(--line-2);
    /* Phones with a home indicator put a strip of unusable screen below the
       viewport bottom. Without this the buttons sit under it. */
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  .callbar__btn {
    display: flex; align-items: center; justify-content: center; gap: 9px;
    min-height: 56px; padding: 10px 12px;
    background: var(--surface-2); color: var(--text);
    font-family: var(--font-display); font-weight: 700; font-size: 15.5px;
  }
  .callbar__btn--wa { background: var(--amber); color: var(--ink); }
  .callbar__btn--wa:hover, .callbar__btn--wa:active { color: var(--ink); }
  /* The bar is fixed, so it would sit on top of the footer and — worse — on
     the quote form's submit button. Reserve its height at the end of the page
     instead of letting it overlap. */
  body { padding-bottom: calc(56px + env(safe-area-inset-bottom, 0px)); }

  /* ---------- Tap targets ----------
     Twelve of 32 measured under 44px, and the worst of them were the two
     things that convert: the phone numbers at 85x24 and 86x24, and the footer
     navigation at 18px tall. 48px is Android's target, not the 44px floor.
     Padding rather than height, so nothing that wraps gets clipped. */
  .footer__col a { display: block; padding-block: 11px; }
  .footer__col li + li { margin-top: 0; }
  .footer__contact a { display: inline-block; padding-block: 12px; }
  .card__list a { display: inline-block; padding-block: 10px; }
  .link-more { padding-block: 11px; }
  .langswitch > * { min-height: 44px; display: inline-flex; align-items: center; }
  .btn--sm { min-height: 48px; }
  /* The per-number WhatsApp pill on the contact page (33px) and the trade
     pages' breadcrumb (14px). Both found by tools/check-mobile.py on pages the
     first mobile pass never looked at. */
  .card__list .chat-link { min-height: 44px; }
  .crumb a { display: inline-block; padding-block: 15px; }
  .crumb { margin-bottom: 0; }

  /* ---------- Placeholder slots ----------
     Nine of them totalled 1,576px — 24% of a 6,522px page — to say "photo
     pending". Shorter on a phone until the photographs arrive. The real images
     use aspect-ratio rather than these heights, so nothing moves on swap and
     this costs nothing once they land. */
  .slot { min-height: 140px; }
  .slot--card { min-height: 104px; }
  .slot--cat { min-height: 170px; }
  .slot--why, .slot--about { min-height: 190px; }

  /* ---------- Chrome above the fold ----------
     The topbar wrapped to 60px on a phone against 41px on desktop, so 145px of
     chrome preceded any content. */
  .topbar { font-size: 12px; }
  .topbar__inner { padding-block: 7px; }
}

/* ==========================================================================
   Bengali
   DESIGN.md has said from the start that "Bengali does not use uppercase or
   letter-spacing — it has no case, and tracking breaks conjuncts." The rule was
   written down and never implemented: the stylesheet had no Bengali selector at
   all, so all eleven letter-spacing rules and all four uppercase rules landed
   on Bengali text as well as Latin.

   Measured on the Bengali home page before this block: 45 elements carrying
   tracking they should not have. Every heading got NEGATIVE tracking
   (-0.51px on the h1), which squeezes conjuncts — the densest part of the
   script — and the category labels got +1.4px, which pulls them apart. The
   uppercase is merely a no-op, since Bengali has no case; the tracking is the
   damage.

   Scoped two ways on purpose. html[lang="bn"] covers the /bn/ pages, and the
   bare [lang="bn"] catches the one Bengali string on an English page: the
   language switch reads বাং and carries its own lang attribute.

   Specificity rather than !important: html[lang="bn"] body * is (0,1,2), which
   beats the single-class rules it has to override without taking a hammer to
   anything that might legitimately need to win later.
   ========================================================================== */
html[lang="bn"] body, html[lang="bn"] body *,
[lang="bn"], [lang="bn"] * {
  letter-spacing: normal;
  text-transform: none;
}

/* Bengali needs more leading than Latin at the same size: the matra joins the
   tops of the letters into a continuous line, and conjuncts hang below the
   baseline, so lines that are comfortable in Barlow collide in a Bengali face.
   1.6 is right for the Latin body copy and tight for the same text in Bengali.
   The heading figure matters more than the body one — 1.12 was set for Latin
   display type and leaves conjuncts touching the line above.

   Both numbers were set for Hind Siliguri and re-measured when Noto replaced
   it, rather than carried over on faith. They stand: the ink above the baseline
   differs by 3–5% between the two faces, and line-height multiplies font-size,
   not the font's own box — which is the metric that actually moved. Noto also
   descends less (41 against 50 per 100px), so 1.35 has more room than before,
   not less. DESIGN.md carries the measurements. */
html[lang="bn"] p, html[lang="bn"] li, html[lang="bn"] .lede,
html[lang="bn"] .cat__long, html[lang="bn"] blockquote {
  line-height: 1.85;
}
html[lang="bn"] h1, html[lang="bn"] h2, html[lang="bn"] h3 {
  line-height: 1.35;
}

/* ==========================================================================
   Desktop only
   The frosted header, quarantined above the breakpoint where .nav stops being
   position: fixed. Anything that establishes a containing block —
   backdrop-filter, filter, transform, perspective, will-change, contain —
   belongs in here and not in a rule that also applies to the phone, because a
   fixed child silently re-parents onto it. That is what killed the mobile
   menu. If a blur is ever wanted on the phone header, the nav has to move out
   of the header in the markup first.
   ========================================================================== */
@media (min-width: 1025px) {
  .site-header {
    background: rgb(11 11 13 / 92%);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
  }
}

@media print {
  .topbar, .site-header, .nav, .skip-link, .marquee, .slot, .callbar { display: none !important; }
  body { padding-bottom: 0; }
  body { background: #fff; color: #000; }
  a { color: #000; }
  .card, .stats, .chips li { border-color: #999; background: #fff; }
  .band { background: #fff; color: #000; }
}

/* ==========================================================================
   Services — the contracting side of the business
   ========================================================================== */

.svc-strip { border-top: 1px solid var(--line); }
.svc-strip .section-head h2 { display: flex; align-items: center; gap: 11px; }
.svc-strip .section-head h2 .ic { color: var(--amber); width: 26px; height: 26px; }
.svc-strip .lede { margin-bottom: 22px; }
.chips--svc li { border-color: var(--line-2); color: var(--text); font-family: var(--font-display); font-weight: 600; }

.svc-grid {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 24px);
}
/* Each trade gets a photo. Until the client sends them the slot holds a
   labelled placeholder at the right ratio, so nothing reflows on swap. */
.svc {
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  transition: border-color .18s ease, transform .18s ease;
}
.svc:hover { border-color: var(--amber); transform: translateY(-3px); }
.svc:hover .slot--svc { border-color: var(--amber); }
.slot--svc {
  min-height: 0; aspect-ratio: 4 / 3; padding: 16px;
  border-radius: 0; border-width: 0 0 1px 0; border-color: var(--line);
}
.svc__body { display: flex; flex-direction: column; gap: 5px; padding: 20px 22px 24px; }
.svc__n { margin: 0; font-family: var(--font-display); font-size: 12px; font-weight: 800; letter-spacing: .16em; color: var(--amber); }
.svc h3 { margin: 0; font-size: 19px; font-weight: 700; }
.svc p { margin: 0; font-size: 14.5px; line-height: 1.55; color: var(--muted-2); }

/* The works block sits on the alternate ground so it reads as its own half
   of the page, separate from the supply grid above it. */
.works { background: var(--bg-2); border-block: 1px solid var(--line); }
.works .section-head h2 { display: flex; align-items: center; gap: 11px; }
.works .section-head h2 .ic { color: var(--amber); width: 26px; height: 26px; }
.works .lede { margin-bottom: 26px; }

/* A trailing "etc." closes a list; it is not a product, so it reads quieter. */
.chips li.is-etc { background: transparent; border-style: dashed; color: var(--muted-2); font-style: italic; }

@media (max-width: 1024px) {
  .svc-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Five nav items no longer fit beside the brand and the WhatsApp button. */
  .nav__list { gap: 2px; }
}
@media (max-width: 640px) {
  .svc-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Open-now badge, trade pages, Google review block
   ========================================================================== */

/* The badge is display:flex, and a flex container ignores the [hidden]
   attribute — the browser's UA rule is display:none, which any display
   declaration overrides. Without this the badge would flash its empty shell
   on every load and stay visible with JavaScript off. */
[hidden] { display: none !important; }

.openbadge {
  display: inline-flex; align-items: center; gap: 7px; margin: 0 0 0 14px;
  padding: 2px 10px 2px 8px; border-radius: 999px;
  background: rgb(21 21 21 / 10%); color: var(--ink);
  font-family: var(--font-display); font-weight: 700; font-size: 12px;
  vertical-align: middle;
}
.openbadge::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor;
}
.openbadge.is-open::before { background: #0a7d32; }
.openbadge.is-closed::before { background: #b3261e; }

/* ---------- Trade pages ---------- */
.crumb { margin: 0 0 10px; font-family: var(--font-display); font-size: 13px; font-weight: 600; }
.crumb a { color: var(--amber); }
.page-head .hero__actions { margin-top: 26px; }

.trade__grid {
  display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, .65fr);
  gap: clamp(20px, 3vw, 40px); align-items: start;
  padding-block: clamp(28px, 3.5vw, 48px);
}
.slot--trade { min-height: 0; aspect-ratio: 16 / 10; }
.trade__side h2 {
  display: flex; align-items: center; gap: 10px;
  font-size: 18px; font-weight: 700; margin-bottom: 14px;
}
.trade__side h2 .ic { color: var(--amber); }

.trade__others { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.trade__others a {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 14px 16px; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); color: var(--text);
  font-family: var(--font-display); font-weight: 600; font-size: 14.5px;
  transition: border-color .18s ease, color .18s ease;
}
.trade__others a:hover { border-color: var(--amber); color: var(--amber); }
.trade__others .ic { width: 16px; height: 16px; flex: none; }

/* The whole service card is the link now that each trade has a page. */
/* Each card is clickable as a whole AND carries its own quote button. A link
   inside a link is invalid and RULES.md forbids nesting interactive elements,
   so the heading's link is stretched over the card with ::after and the button
   sits above it in the stacking order. Two sibling links, each with its own
   accessible name, reached by the keyboard in reading order. */
.svc { position: relative; }
.svc__link { color: inherit; }
.svc__link:hover { color: inherit; }
.svc__link::after { content: ''; position: absolute; inset: 0; }
/* The stretched link has no box of its own to ring, so the ring goes on the
   overlay — without this the card gives no focus feedback at all. */
.svc__link:focus-visible { outline: none; }
.svc__link:focus-visible::after { outline: 3px solid var(--amber); outline-offset: -3px; border-radius: var(--r); }
.svc__body .link-more { margin-top: auto; padding-top: 10px; }

/* Above the overlay, or the card's link would swallow the button's clicks. */
.svc__cta { position: relative; z-index: 1; margin: 16px 0 0; }
.svc__cta .btn { width: 100%; }

/* ---------- Google review block ---------- */
.review { display: flex; align-items: center; gap: 18px; }
.review__qr {
  flex: none; width: 132px; height: 132px; padding: 8px;
  background: #fff; border-radius: var(--r-sm);
}
.review__title { margin: 0 0 6px; font-size: 17px; font-weight: 700; }
.review__body p { margin: 0 0 10px; font-size: 14px; color: var(--muted-2); }
.review--footer { margin-top: 24px; padding-top: 22px; border-top: 1px solid var(--line); }
.review--footer .review__qr { width: 104px; height: 104px; }
.review-band { background: var(--bg-2); border-block: 1px solid var(--line); }
.review--page { max-width: 640px; }

/* The honeypot: off-screen rather than display:none, because some bots skip
   fields they can tell are not rendered. Never shown, never focusable. */
.hp {
  position: absolute; left: -9999px; width: 1px; height: 1px;
  overflow: hidden; margin: 0;
}

@media (max-width: 1024px) {
  .trade__grid { grid-template-columns: 1fr; }
  .trade__others { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .openbadge { margin-left: 10px; font-size: 11px; }
  .trade__others { grid-template-columns: 1fr; }
  .review { flex-direction: column; align-items: flex-start; gap: 14px; }
}
