/* Real OMAX palette, forked from yamamotor-old (same vendor template —
   oldomax/*_files/style.css + style01.css + indexsection.css use the
   identical "cis1/cis2/cis3" client color-scheme system, confirmed
   byte-identical framework selectors/values). --action (#e60012) is
   OMAX's own cis2/button/badge override from style01.css (5 raw hits,
   confirmed against .active/:focus states) — the one color that's
   actually brand-specific; --action-2 has no confirmed site value (no
   lighter-red state found in the CSS) so it's a derived lighter tint,
   not a literal capture. Every other token below (navy #012956, accent
   red #861e0c, grays, footer two-tone) is confirmed present with the
   SAME values in oldomax's CSS too — shared framework defaults neither
   site customized, not something to re-derive per client. */
:root {
  --page: #ffffff;
  --surface: #ffffff;
  --surface-2: #f5f5f5;
  --ink: #333333;
  --muted: #777777;
  --muted-2: #939393;
  --line: #eeeeee;
  --line-2: #e3e3e3;
  --navy: #012956;
  --navy-dark: #01162e;
  --navy-light: #013c7e;
  --sea: #012956;
  --sea-2: #013c7e;
  --chart: #e60012;
  --action: #e60012;
  --action-2: #ff4d4d;
  --accent-red: #861e0c;
  --success: #1f7a6b;
  --table-label-bg: #cccccc;
  --footer-bg: #eeeeee;
  --footer-copyright-bg: #333333;
  --footer-copyright-text: #eeeeee;
  --shadow: 0 8px 24px rgba(1, 41, 86, 0.14);
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  scrollbar-gutter: stable;
}

body {
  margin: 0;
  color: var(--ink);
  background: var(--page);
  /* Real font stack from style.css's body{} rule. */
  font-family: "Helvetica Neue", Helvetica, Arial, "Microsoft JhengHei", "Noto Sans TC", sans-serif;
  font-size: 15px;
  line-height: 1.6;
  letter-spacing: 0;
}

/* .title-sm (Lora, 32px, #777, border-bottom #eee) and .title-c (Microsoft
   JhengHei, 19px) — real selectors from style.css, used for section/company
   titles and news list/detail headings respectively. */
.title-sm {
  font-family: Lora, "Noto Serif TC", serif;
  font-size: 32px;
  margin: 20px 0;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
  color: var(--muted);
}

.title-c {
  font-family: "Microsoft JhengHei", "PMingLiU", var(--font-body, Arial), sans-serif;
}

a {
  color: inherit;
  text-decoration: none;
}

img {
  display: block;
  max-width: 100%;
}

.section {
  width: min(1180px, calc(100% - 32px));
  margin: 0 auto;
  padding: 40px 0;
}

/* Products page only — .site-header already contributes the intended ~30px
   banner-to-content gap, so remove the generic .section top padding here
   and move the filter row plus product list up together. */
.products-section {
  padding-top: 0;
}

/* Same width-centering job as .section, plus min-height so short pages
   (e.g. a product with no related items) don't collapse the footer up
   against the hero. Used by the product detail page. */
.page-shell {
  width: min(1180px, calc(100% - 32px));
  min-height: 45vh;
  margin: 0 auto;
  padding: 20px 0 50px;
}

.copy-block {
  max-width: 820px;
  color: #555;
  line-height: 1.8;
}

.section.tight {
  padding: 24px 0;
}

.eyebrow {
  color: var(--sea);
  font-size: 12px;
  font-weight: 900;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.display-title {
  margin: 6px 0 12px;
  max-width: 820px;
  font-size: clamp(26px, 4.2vw, 44px);
  line-height: 1.1;
}

.lead {
  max-width: 680px;
  color: var(--muted);
  font-size: 16px;
  line-height: 1.7;
  overflow-wrap: break-word;
}

.btn {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  border: 0;
  border-radius: 6px;
  padding: 10px 18px;
  background: var(--ink);
  color: white;
  font-weight: 900;
  cursor: pointer;
  transition: transform 0.16s ease, background 0.16s ease, box-shadow 0.16s ease;
}

.btn:hover {
  transform: translateY(-1px);
  box-shadow: 0 10px 24px rgba(24, 38, 48, 0.18);
}

.btn.primary {
  background: var(--action);
}

/* Search/Clear-filters buttons follow this site's own brand accent
   (--action), not the shared navy framework color (--sea) — otherwise
   they render dark navy on every fork regardless of brand (e.g. still
   navy on OMAX instead of red), unlike .header-search button's own navy
   treatment, which IS the real site's deliberate color and stays as-is. */
.btn.sea {
  background: var(--action);
}

.btn.ghost {
  border: 1px solid var(--line);
  background: transparent;
  color: var(--ink);
}

/* =========================================================================
   HEADER — ported verbatim (values, not just structure) from the
   oldyamamotor-react reference build's "olddone" pass, itself sourced from
   the real yamamotor.com.tw markup: logo + utility links float as a
   transparent-background overlay across the TOP of the banner image
   (.toplink01), and the search box + nav pill float lower down, also over
   the banner (.topMenu) — there is no separate white bar tier at all.
   `.site-header` wraps everything as a transparent element with a bottom
   margin (`.olddone-header`); `pointer-events: none` on the toplink
   wrapper + `pointer-events: auto` on just the logo/links buttons keeps
   the transparent overlay from stealing clicks meant for the banner or
   whatever sits below it. ================================================ */

.site-header {
  margin-bottom: 30px;
  background: transparent;
}

/* Inner pages (Company/News/Contact/Product/detail) stay height-driven —
   a fixed height + object-fit: cover, same as before this banner work
   started. banner-inner.jpg's real aspect ratio (1160x200 ≈ 5.8:1) is too
   wide-and-short to look right filled edge-to-edge without cropping: full-
   width auto-height would collapse it into an awkwardly thin strip at
   ordinary viewport widths (it needed a 210px min-height floor just to
   stay usable, and that floor is what caused the aspect-ratio/width
   interaction bug in the first place — see git history). Only the home
   page's carousel actually benefits from full-image aspect-ratio display
   (its banners are a normal 2.16:1 and read fine at any height), so it's
   the only one that keeps it. */
.header-banner {
  position: relative;
  overflow: hidden;
  width: 100%;
  height: 328px;
  background: var(--line);
}

.header-banner img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.header-banner.home {
  height: auto;
  aspect-ratio: 1903 / 883;
}

.header-banner.home img {
  object-fit: contain;
}

/* Homepage carousel: all 3 real banner images stacked, crossfaded by
   toggling .active (see site-header.tsx's slide-interval effect) — mirrors
   the real #banner01 slick carousel's fade transition without pulling in
   slick.js itself. */
.header-banner.home > img {
  position: absolute;
  inset: 0;
  opacity: 0;
  transform: scale(1.035);
  transition: opacity 0.72s ease, transform 1.2s ease;
}

.header-banner.home > img.active {
  opacity: 1;
  transform: scale(1);
}

/* Logo + "Inquiry" link overlay — the real .toplink01, floating across the
   very top of the banner on a transparent background. z-index: 4 matches
   .header-overlay (search+nav) — kept level with it rather than above, so
   the logo layer never outranks (and covers) the nav pill; pointer-events:
   none on this wrapper plus pointer-events: auto on just the logo/Inquiry
   children is what actually keeps clicks routed correctly regardless of
   paint order. */
.header-utility {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 4;
  width: 100%;
  padding: 10px 50px;
  pointer-events: none;
}

.header-utility-inner {
  display: block;
}

.header-utility-inner::after {
  content: "";
  display: table;
  clear: both;
}

.brand {
  float: left;
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  pointer-events: auto;
}

.brand img {
  width: 246px;
  height: auto;
  object-fit: contain;
}

.header-utility .brand small {
  display: none;
}

/* .sf-toplink's real treatment (navbar.css): dark translucent pill, white
   text — just the "Inquiry" link, language switcher removed per spec. */
.utility-links {
  float: right;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 8px;
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.4);
  font-size: 12px;
  pointer-events: auto;
}

.utility-links a,
.utility-links button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 0;
  background: transparent;
  padding: 6px 8px;
  color: #fff;
  font-weight: 700;
  cursor: pointer;
}

.utility-links a:hover,
.utility-links button:hover,
.utility-links button.active {
  color: var(--action);
}

.utility-links .cart-count {
  position: static;
  margin-left: 2px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--action);
  color: white;
  font-size: 11px;
  font-weight: 800;
  line-height: 18px;
  text-align: center;
}

/* Search box + nav pill overlay — the real .Bbox_full .topMenu, floating
   lower on the banner, centered. top/gap are vw-based (2.86vw ≈ 55px,
   2.4vw ≈ 46px at the 1920px width they were tuned against) rather than
   fixed px: the home page's banner height itself scales with viewport
   width (aspect-ratio, not a fixed height — see .header-banner.home
   above), so a fixed-px offset there would keep eating a bigger share of
   an ever-shorter banner as the viewport narrows, eventually pushing the
   nav pill down into the home banner's own baked-in title text. Scaling
   by vw keeps this cluster at the same relative height on the image at
   every width instead — harmless on inner pages too, since their banner
   stays a generous fixed height regardless. */
.header-overlay {
  position: absolute;
  left: 50%;
  top: 2.86vw;
  transform: translateX(-50%);
  z-index: 4;
  width: min(670px, 95%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2.4vw;
}

/* .header-overlay itself stays a fixed 670px wide at every desktop
   viewport (min(670px, 95%) only shrinks below 706px, i.e. already
   mobile), so a fixed-width search box doesn't actually narrow with the
   viewport the way it looks like it should — a viewport-relative clamp()
   here is what actually keeps it clear of the logo/Inquiry link at
   moderate laptop widths (~1024-1300px), not just at the full 580px it
   reaches on wide screens. */
.header-search {
  display: flex;
  align-items: stretch;
  min-width: 0;
  width: clamp(300px, 42vw, 580px);
  max-width: 100%;
  border: 1px solid var(--line-2);
  border-radius: 6px;
  background: #fff;
  overflow: hidden;
  pointer-events: auto;
}

.header-search input {
  flex: 1;
  min-width: 0;
  min-height: 45px;
  border: 0;
  padding: 7px 9px;
  background: transparent;
  color: var(--ink);
  font-size: 16px;
}

/* Real .headSearch button: navy idle, brand-blue on hover. */
.header-search button {
  flex-shrink: 0;
  width: 45px;
  border: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--action);
  color: white;
  cursor: pointer;
}

.header-search button:hover {
  background: #b8000e;
}

.header-search button svg {
  width: 18px;
  height: 18px;
}

/* Real .Bbox_full .navmenu01 treatment: translucent black pill floating
   over the banner, white link text — not a plain horizontal link row.
   max-width was 580px, sized for the original 5-link row (Home/Company/
   News/Product/Contact us) — adding "Genuine Package" (a 6th link, and
   the longest label in the row) pushed the total width past that cap,
   squeezing "Contact us" onto two lines. Widened to 640px and each
   link's own horizontal padding trimmed (14px -> 11px) so 6 links fit
   on one line again without any of them wrapping. */
.nav-links {
  position: relative;
  z-index: 12;
  display: flex;
  align-items: center;
  gap: 2px;
  width: auto;
  max-width: min(640px, 100%);
  padding: 6px 10px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.3);
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.2);
  pointer-events: auto;
}

.nav-links a {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 36px;
  border-radius: 999px;
  padding: 8px 11px;
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  transition: background 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
}

.nav-links a:hover {
  color: #fff;
  background: var(--action);
  transform: translateY(-2px);
  box-shadow: 0 6px 14px rgba(0, 0, 0, 0.28);
}

.nav-links a.active {
  color: #fff;
  background: var(--action);
}

.icon-btn {
  position: relative;
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface);
  color: var(--ink);
  cursor: pointer;
  pointer-events: auto;
}

.icon-btn svg {
  width: 20px;
  height: 20px;
}

/* Fixed mobile top bar (blue, logo-centered, hamburger+search icons),
   its hide-on-scroll behavior, the off-canvas panel + backdrop
   animations, the mobile search overlay, and the bottom-tools bar are all
   ported from the oldyamamotor-react reference build — see the 780px
   media query below for the full treatment; these are just the inert
   desktop-hidden defaults. */
.mobile-top-icon,
.mobile-bottom-tools,
.mobile-menu,
.mobile-menu-backdrop,
.mobile-search-layer {
  display: none;
}

/* Homepage banner prev/next + dot controls (desktop) — the mobile 780px
   query below restyles/repositions these for touch, doesn't duplicate the
   markup. */
.slidcontrol {
  position: absolute;
  inset: 0;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: space-between;
  pointer-events: none;
}

/* Reference treatment: large transparent text-arrow, no circular button
   background — not a small dark pill. */
.slidcontrol .slick-prev,
.slidcontrol .slick-next {
  position: absolute;
  top: 50%;
  pointer-events: auto;
  margin-top: -1em;
  border: 0;
  background: transparent;
  color: #fff;
  padding: 0;
  font-size: 48px;
  line-height: 1;
  text-align: center;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.55);
  cursor: pointer;
}

.slidcontrol .slick-prev {
  left: 5%;
}

.slidcontrol .slick-next {
  right: 5%;
}

/* Reference dots: solid black idle, white active, sitting flush at the
   very bottom of the banner. */
.header-banner.home .slick-dots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 4;
  display: flex;
  justify-content: center;
  gap: 8px;
  list-style: none;
  margin: 0;
  padding: 10px 0;
}

.header-banner.home .slick-dots button {
  width: auto;
  height: auto;
  min-height: 0;
  margin: 5px;
  overflow: hidden;
  border: 0;
  border-radius: 50%;
  background: #000;
  color: transparent;
  padding: 5px;
  font-size: 0;
  cursor: pointer;
}

.header-banner.home .slick-dots button:hover,
.header-banner.home .slick-dots li.slick-active button {
  background: #fff;
}

/* =========================================================================
   HOMEPAGE — one dense, unbroken category-tile grid immediately below the
   header. No hero copy/stat pills/news teaser: the old homepage had none
   of those, just the tile wall. Real .indexPro rules (indexsection.css):
   6 columns desktop (16.666% each) -> 4 at <=1200px -> 2 at <=768px -> 1
   at <=480px, plain square photo with no card border/background, caption
   turns brand blue on hover. ============================================ */

/* Full-bleed with the real .indexPro ul's own side padding — not a
   .section-width-capped column. */
.category-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 0;
  margin-top: 0;
  padding: 60px 75px 50px;
}

.category-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
  padding: 0 15px 60px;
  text-align: center;
}

.category-tile:hover span {
  color: var(--action);
}

/* Was "no card/background feel — a plain photo, no border" (a deliberate
   choice at the time, matching the real .indexPro li .itemImg's own flat
   look) — now carries a solid border + hover color transition instead,
   matching the fixed "for more" tile below (.category-tile-more-img)
   this pattern originated on. Solid (not that tile's dashed) is the
   deliberate visual distinction kept between the two: dashed still reads
   as "functional see-more link", solid as "real product category", even
   though both now transition the same way on hover. aspect-ratio
   corrected to 214/300 (was 1, a plain square) — the admin's own
   Featured Category image cropper
   (src/components/admin/featured-category-form.tsx) already forces
   every uploaded tile image to a 214×300 portrait crop and says so
   directly in its own hint text ("Portrait 214×300 to match the real
   site's category photos"), so this square box never actually matched
   the images landing inside it; confirmed live via screenshot comparison
   against the "for more" tile, which is what surfaced the mismatch. */
.category-tile-img {
  width: 100%;
  aspect-ratio: 214 / 300;
  overflow: hidden;
  border: 1px solid var(--line-2);
  border-radius: 4px;
  background: var(--surface-2);
  transition: border-color 0.2s ease, background 0.2s ease;
}

.category-tile:hover .category-tile-img {
  border-color: var(--action);
  background: var(--surface);
}

.category-tile-img img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.category-tile span {
  margin-top: 15px;
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--ink);
  overflow-wrap: break-word;
}

/* Fixed 9th "browse everything else" tile appended after the real
   FeaturedCategory tiles (page.tsx) — reuses .category-tile's layout
   (same grid cell, same img-then-label shape) but the image slot has no
   real photo behind it, so it gets its own panel instead of
   .category-tile-img's photo treatment. Was a muted dashed-border panel
   (gray text/border, only turning brand-red on hover) — now a solid
   brand-red panel at rest instead, per feedback that it needed to stand
   out more once the grid grew to the full 54-tile taxonomy: a pale
   dashed placeholder that only differentiated itself on hover was easy
   to lose among that many real photo tiles, so the "this is different in
   kind — a functional see-more link, not one more category" cue now has
   to read at a glance, not just on interaction. */
.category-tile-more-img {
  /* .category-tile-img's own width/aspect-ratio (100%/214:300, line 608)
     was expected to carry over since this element also has that class —
     but confirmed live via screenshot comparison against the real photo
     tiles: display: flex + a centered child let the box's rendered size
     follow its flex content instead of staying pinned to the portrait
     aspect-ratio, so this tile's box came out a different shape than
     every other tile's. Restated explicitly here rather than trusting
     the shared class alone. Must stay numerically identical to
     .category-tile-img's own aspect-ratio (both trace back to the
     admin's 214×300 crop — see that rule's own comment) or this tile's
     box mismatches the other 8 again. */
  width: 100%;
  aspect-ratio: 214 / 300;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  border: 1px solid var(--action);
  border-radius: 4px;
  background: var(--action);
  transition: background 0.2s ease, border-color 0.2s ease;
}

.category-tile-more:hover .category-tile-more-img {
  background: var(--action-2);
  border-color: var(--action-2);
}

/* The panel used to hold a plain arrow icon, with the "for more ...
   products" text living only in a separate label span below the panel
   (like every other tile's image-then-caption shape). Per feedback the
   string now lives directly inside the panel instead — one copy, not an
   icon-plus-label split — so this span sits centered in the solid-red
   box rather than underneath it, undoing .category-tile span's own
   margin-top/uppercase/13px defaults (written for a caption below an
   image, not text centered inside one). White at all times (not a
   gray→red hover swap) since the background is solid red from the
   start now, not white/gray waiting for hover to introduce color. */
.category-tile-more-img span {
  margin-top: 0;
  max-width: 22ch;
  font-size: 14px;
  font-weight: 900;
  letter-spacing: 0.01em;
  text-transform: none;
  text-align: center;
  line-height: 1.4;
  color: #ffffff;
}

/* =========================================================================
   FOOTER — single centered flat block: logo, one inline nav list (repeats
   the header's links), copyright. No multi-column sitemap/social icons.
   Real two-tone treatment (indexsection.css .footer_03 rules): the nav
   area sits on a light gray band (#eee), the copyright line below it is
   its own dark strip (#333 bg, light text) — not one uniform dark footer. */

.footer {
  background: var(--footer-bg);
  color: var(--ink);
}

.footer-inner {
  width: min(1180px, calc(100% - 32px));
  margin: 0 auto;
  padding: 30px 0 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 14px;
  text-align: center;
}

.footer-inner img {
  width: 108px;
  opacity: 0.9;
}

.footer-nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px;
}

.footer-nav a {
  padding: 6px 12px;
  color: var(--navy);
  font-size: 13px;
  font-weight: 700;
}

.footer-nav a:hover {
  color: var(--action);
}

.footer-copyright {
  margin-top: 20px;
  padding: 5px 0;
  background: var(--footer-copyright-bg);
  color: var(--footer-copyright-text);
  text-align: center;
}

.footer-copyright p {
  margin: 0;
  font-size: 10px;
}

.footer-copyright a {
  color: var(--footer-copyright-text);
  text-decoration: underline;
}

.page-title {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

.page-title .section {
  padding: 24px 0;
}

/* =========================================================================
   PRODUCTS — left sidebar (full flat category list, single-select) + a
   horizontal filter bar of dropdown popovers (Brand / HP-2S / HP-4S /
   Displacement / Tags / Model Year / Engine Model) sitting above a column
   of stacked full-width product rows (not a card grid). This mirrors the
   old site's sidebar-of-categories + fake-<select> filter row + one-row-
   per-product prodlist, while keeping the current multi-select/facet-count
   filtering engine (architecture.md §5-A/§5-D upgrade over the old site's
   single-click-navigates dropdowns). ===================================== */

.products-layout {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 20px;
  align-items: start;
}

/* top: 77px = the full-bleed .product-toolbar's real rendered height
   (40px button min-height + 10px*2 padding + 1px border = 61px) + the
   original 16px breathing gap this had before that toolbar existed —
   keeps this sidebar's sticky edge flush under the toolbar's sticky
   edge instead of drifting apart mid-scroll (2026-09-23; see
   .product-toolbar's comment for the overlap this fixes). If the
   toolbar's own height ever changes, this needs to move with it. */
.filter-sidebar {
  position: sticky;
  top: 77px;
  max-height: calc(100vh - 93px);
  overflow: auto;
  scrollbar-gutter: stable;
  background: var(--surface);
}

/* Product Line / Category lists, desktop sidebar only — white background,
   red text, selected row flips to red background/white text. Scoped to
   .filter-sidebar (not .option-list/.filter-option directly) since the
   Brand/HP dropdown panels and the mobile filter drawer reuse the exact
   same markup/classes and keep their default look; the heading
   (.category-nav-head) and Part No. search box are untouched since
   neither lives inside .option-list. */
.filter-sidebar .option-list {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 6px;
}

.filter-sidebar .filter-option {
  color: var(--action);
}

.filter-sidebar .filter-option .count {
  color: var(--muted);
}

.filter-sidebar .filter-option:not(.active):not(:disabled):hover {
  background: var(--line-2);
}

.filter-sidebar .filter-option.active {
  background: var(--action);
  color: #fff;
}

.filter-sidebar .filter-option.active .count {
  color: #fff;
}

.category-nav-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
  font-size: 12px;
  font-weight: 900;
  text-transform: uppercase;
  color: var(--muted);
}

.category-nav-head::before {
  content: "";
  flex: 0 0 auto;
  width: 4px;
  height: 14px;
  background: var(--action);
}

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 14px;
}

.filter-dropdown {
  position: relative;
}

/* Real .proSelect .select styling (indexsection.css): white box, #e3e3e3
   border, muted #939393 label text — a fake-<select>, not styled as a
   modern button. */
.filter-dropdown-btn {
  min-height: 40px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--line-2);
  border-radius: 0;
  padding: 8px 12px;
  background: #fff;
  color: var(--muted-2);
  font-size: 13px;
  font-weight: 400;
  cursor: pointer;
}

.filter-dropdown-btn[aria-expanded="true"],
.filter-dropdown-btn.active {
  border-color: var(--action);
  color: var(--action);
  background: #fff;
}

.filter-dropdown-btn svg {
  width: 14px;
  height: 14px;
  transition: transform 0.15s ease;
}

.filter-dropdown-btn[aria-expanded="true"] svg {
  transform: rotate(180deg);
}

.filter-dropdown-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 20;
  width: min(300px, 88vw);
  max-height: 360px;
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  box-shadow: var(--shadow);
  padding: 12px;
}

.filter-search {
  width: 100%;
  min-height: 38px;
  margin-bottom: 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 8px 10px;
  background: #fff;
}

.sku-search-row {
  display: flex;
  align-items: stretch;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fff;
  overflow: hidden;
}

.sku-search-row .filter-search {
  flex: 1;
  min-width: 0;
  margin-bottom: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
}

.sku-search-btn {
  flex-shrink: 0;
  width: 42px;
  min-height: 0;
  padding: 0;
  border-radius: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.sku-search-btn:hover {
  background: #b8000e;
  transform: none;
  box-shadow: none;
}

.sku-search-btn svg {
  width: 18px;
  height: 18px;
}

.option-list {
  display: grid;
  gap: 4px;
}

.filter-option,
.check-option {
  min-height: 32px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  border-radius: 0;
  padding: 6px 8px;
  color: var(--muted-2);
  font-size: 13px;
}

.filter-option {
  border: 0;
  background: transparent;
  text-align: left;
  cursor: pointer;
}

.filter-option:not(.active):not(:disabled):hover,
.check-option:not(:has(input:checked)):not(.disabled):hover {
  background: var(--line-2);
}

/* Real .select ul li.selected state: background:#39f; color:#fff. */
.filter-option.active,
.check-option:has(input:checked) {
  background: var(--action-2);
  color: #fff;
  font-weight: 700;
}

.filter-option:disabled,
.check-option.disabled {
  opacity: 0.42;
}

.check-option input {
  width: 16px;
  height: 16px;
  accent-color: var(--sea);
}

.count {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.filter-option-hidden {
  display: none;
}

.filter-show-more {
  min-height: 32px;
  width: 100%;
  border: 0;
  background: transparent;
  border-radius: 6px;
  padding: 6px 8px;
  text-align: left;
  cursor: pointer;
  color: var(--sea);
  font-weight: 700;
  font-size: 13px;
}

.filter-show-more:hover {
  background: rgba(1, 41, 86, 0.08);
}

/* Mobile-only 2x2 filter grid — ported directly from oldyamamotor-react's
   .mobile-product-filter-bar (hidden by default, 2-column grid only inside
   the mobile breakpoint below). */
.mobile-product-filter-pack {
  display: none;
}

.mobile-product-filter-bar {
  display: none;
}

.active-chips {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding-bottom: 2px;
}

.chip {
  flex: 0 0 auto;
  min-height: 30px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 1px solid rgba(1, 41, 86, 0.16);
  border-radius: 999px;
  padding: 5px 10px;
  background: #fff;
  color: var(--sea);
  font-size: 12px;
  font-weight: 900;
}

.chip button {
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
}

.results-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 12px;
}

.results-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Filter bar (Brand/2-Stroke/4-Stroke/Tags dropdowns) + sort + product
   count all sit on one row — ported from oldyamamotor-react's
   .product-toolbar. The filter dropdowns themselves keep the existing
   filter-panel.tsx/use-product-filters.ts logic untouched; only the
   surrounding row layout and the sort control's visual treatment change
   here. */
/* Full-bleed sticky bar (2026-09-23, revised from an earlier version that
   was just a sticky flex row nested inside .products-section's centered
   max-width column). That version's white background only covered the
   ~1180px content column, not the full viewport, and .filter-sidebar's
   own independent sticky `top` didn't line up with it — the sidebar
   could scroll a few px under the toolbar before its own `top` engaged,
   reading as a slight overlap of the filter row/product list. Now a full
   `width: 100%` section, same shape as .page-band, with the real flex
   row moved to .product-toolbar-inner (which reuses .section's own
   centering) — see products-client.tsx. .filter-sidebar's `top` is set
   to this bar's real rendered height so the two sticky elements clear
   each other exactly instead of drifting apart mid-scroll. Desktop only
   — the mobile toolbar at this class name is a totally different
   `display: none` layout (see the max-width:768px override below),
   untouched here. */
.product-toolbar {
  width: 100%;
  box-sizing: border-box;
  position: sticky;
  top: 0;
  z-index: 30;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

.product-toolbar-inner {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 0;
}

.product-toolbar .filter-bar {
  flex: 1 1 auto;
  margin-bottom: 0;
  align-items: center;
}

.product-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-start;
  gap: 6px;
  flex: 0 0 112px;
  color: var(--muted);
  font-size: 16px;
}

.product-head strong {
  color: var(--muted);
  font-size: 13px;
  font-weight: 400;
  line-height: 1.2;
  white-space: nowrap;
}

/* Desktop already has Displacement inside the 7-item .filter-bar — this is
   mobile-only (shown at the breakpoint below), placed left of the sort
   control since .product-head's justify-content: flex-end keeps DOM order
   as visual left-to-right order. */
.mobile-displacement-filter {
  display: none;
}

/* Sort is a real FilterDropdown (see products-client.tsx's SortDropdown),
   not a native <select> restyled to merely look like one — .product-head
   is a column flex container with the default flex-start cross-axis
   alignment, and .filter-dropdown-btn is inline-flex, so neither stretches
   to fill the 112px column on its own the way the old select's own
   width: 100% did; both need it set explicitly. */
.product-head .filter-dropdown,
.product-head .filter-dropdown-btn {
  width: 100%;
}

/* -- product rows --------------------------------------------------------
   Ported from oldyamamotor-react's .product-card/.pro_showimg/.pro-align/
   .pro_table/.proBrand system (literal old-site class names) — desktop
   uses their @media(min-width:769px) grid refinement directly rather than
   the float-based base rules, since the grid version is the intended
   final desktop layout. Only presentation changes here; product data,
   filters, and pagination are untouched. ================================ */

.product-rows {
  display: grid;
  gap: 0;
}

.product-card {
  position: relative;
  padding-top: 22px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--line);
}

.product-card > div {
  min-height: 220px;
  display: grid;
  grid-template-columns: 25% minmax(0, 1fr);
  gap: 18px;
}

.pro_showimg {
  width: 100%;
}

.pro_showimg > div {
  margin: 0;
}

.pro_showimg a {
  display: block;
  cursor: zoom-in;
}

.pro_showimg img {
  box-sizing: border-box;
  width: 220px;
  max-width: 100%;
  height: 220px;
  object-fit: contain;
}

.pro-align {
  min-width: 0;
  min-height: 220px;
  display: grid;
  grid-template-rows: auto 1fr;
}

.pro-align > div:first-child {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 142px;
  column-gap: 22px;
  align-items: start;
}

.pro-main {
  min-width: 0;
}

.pro-align h3 {
  margin: 0 0 4px;
  font-size: 18px;
}

.sku {
  color: var(--muted);
  font-family: "Roboto Mono", Consolas, monospace;
  font-size: 12px;
}

/* Real .pro_table (style01.css): label cell is its own centered gray
   (#ccc) box (~20% width), value cell is left-padded muted (#777) text. */
.pro_table > div {
  display: table;
  width: 100%;
}

.pro_table > div > div {
  display: table-row;
}

.pro_table > div > div > div {
  display: table-cell;
  border-right: 1px solid #fff;
}

.pro_table > div > div > div:nth-child(1) {
  width: 90px;
  min-width: 90px;
  padding: 3px 6px;
  vertical-align: middle;
  background: var(--table-label-bg);
  color: var(--ink);
  line-height: 1.45;
  text-align: center;
}

.pro_table > div > div > div:nth-child(2) {
  padding: 3px 8px;
  color: var(--muted);
  text-align: left;
  line-height: 1.45;
  word-break: break-all;
}

.product-card-actions {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.product-card-actions .btn-warning {
  width: 142px;
  min-height: 39px;
  margin: 0;
  border: 0;
  border-radius: 0;
  background: var(--action);
  color: #fff;
  padding: 7px 12px;
  font-size: 16px;
  text-align: center;
  cursor: pointer;
}

.product-card-actions .btn-warning:hover {
  background: #b8000e;
}

.product-card-actions .btn-warning.ghost {
  border: 1px solid var(--action);
  background: #fff;
  color: var(--action);
}

/* AddInquiryButton's "Added ✓" state — was a per-click inline style
   (background: var(--success)), moved to a class since CSP's style-src
   blocks inline style attributes. Covers every className this button is
   given (btn-warning/btn-warning.ghost on product cards, the default
   "btn primary" on the product detail page's add-to-cart panel) via a
   plain .added selector rather than one rule per base class combo. */
.added,
.added.ghost {
  background: var(--success) !important;
  border-color: var(--success) !important;
  color: #fff !important;
}

.proBrand {
  align-self: end;
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 18px;
}

.proBrand span {
  color: var(--ink);
  line-height: 27px;
}

.proBrand ul {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Real .proBrand ul li a treatment: solid brand-blue pill, white text. */
.proBrand .badge {
  min-height: 27px;
  border-radius: 3px;
  background: var(--action);
  color: #fff;
  padding: 4px 6px;
  font-size: 15px;
  font-weight: 700;
}

.tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.badge {
  display: inline-flex;
  align-items: center;
  min-height: 23px;
  border-radius: 999px;
  padding: 3px 8px;
  background: rgba(1, 41, 86, 0.1);
  color: var(--sea);
  font-size: 11px;
  font-weight: 900;
  line-height: 1.2;
}

.badge.tag {
  background: rgba(31, 122, 107, 0.1);
  color: var(--success);
}

/* Numbered pagination only — style01.css's `.pager { display: none; }`
   confirms the real site actually hides the Older/Newer prev/next pager
   markup and shows only the numbered list, so this doesn't render one. */
.pagination-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin-top: 20px;
}

.pagination {
  display: flex;
  gap: 6px;
}

/* Real .pagination (style.css's Bootstrap layer): no border at all — a
   later `.pagination > li > a { border: 0 }` override wins the cascade
   over the earlier bordered rule. Both interactive states follow this
   site's own brand accent instead of Bootstrap/framework defaults (navy-
   light hover, #337ab7 active) — same fix as .btn.sea and .header-search
   button: hover uses the lighter --action-2 tint (matching .filter-
   option.active's convention), active uses the full --action color. */
.pagination a {
  min-height: 36px;
  min-width: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  padding: 6px 10px;
  background: transparent;
  color: var(--muted);
  font-weight: 400;
  cursor: pointer;
}

.pagination a:hover {
  background: var(--action-2);
  color: #fff;
}

.pagination a.active {
  background: var(--action);
  color: #fff;
}

/* =========================================================================
   PRODUCT DETAIL — no old-site template was captured (product_detail.html
   was empty in the source snapshot). Structure/classes ported from
   oldyamamotor-react's ProductDetail component (its own extrapolation from
   the same gap), which this build otherwise didn't have a reference for.
   ========================================================================= */

.product-detail-page {
  color: var(--ink);
}

.detail-breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 18px;
  color: var(--muted);
  font-size: 13px;
}

.detail-breadcrumb a {
  color: var(--navy);
  font-weight: 700;
}

.detail-breadcrumb a:hover {
  color: var(--action);
}

.product-detail-hero {
  display: grid;
  grid-template-columns: minmax(260px, 430px) minmax(0, 1fr);
  gap: 34px;
  align-items: start;
  margin-bottom: 30px;
}

/* Red accent bar on the media frame (::before, no extra markup needed) —
   echoes the homepage hero's bolder use of the brand red instead of the
   photo frame reading as a plain undecorated box. */
.product-detail-media {
  position: relative;
  width: 100%;
  min-width: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  background: #fff;
  padding: 18px;
}

.product-detail-media::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 5px;
  height: 100%;
  background: var(--action);
}

.product-detail-media img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: contain;
}

.product-detail-media .photo-box {
  width: 100%;
  aspect-ratio: 1;
  min-height: 0;
  border: 0;
  background: none;
}

/* Active/hover thumbnail now uses the brand red (was --sea navy) — keeps
   the accent consistent with the media frame's own red bar above. */
.gallery-thumbs button.active,
.gallery-thumbs button:hover {
  border-color: var(--action);
  box-shadow: 0 0 0 2px rgba(230, 0, 18, 0.16);
}

.product-detail-summary {
  min-width: 0;
  padding-top: 4px;
}

.summary-lines {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.detail-category {
  display: inline-flex;
  align-items: center;
  margin: 0 0 10px;
  background: var(--action);
  color: #fff;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 900;
  letter-spacing: 0.03em;
}

/* Leaf subcategory (e.g. FUEL PARTS), shown alongside the top-level
   Product Line badge above — outlined rather than solid-red so the two
   tiers (Line vs. subcategory) stay visually distinct. */
.detail-line {
  display: inline-flex;
  align-items: center;
  margin: 0 0 10px;
  border: 1px solid var(--line-2);
  color: var(--muted);
  padding: 5px 11px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.03em;
}

.product-detail-summary h1 {
  margin: 0 0 20px;
  color: var(--ink);
  font-size: 34px;
  font-weight: 900;
  line-height: 1.2;
}

.detail-part-no {
  display: grid;
  grid-template-columns: 130px minmax(0, 1fr);
  max-width: 560px;
  margin-bottom: 20px;
  border: 1px solid var(--line);
  background: #fff;
}

.detail-part-no span,
.detail-part-no strong {
  padding: 12px 14px;
}

.detail-part-no span {
  background: var(--table-label-bg);
  color: var(--ink);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
}

.detail-part-no strong {
  color: var(--navy);
  font-family: "Roboto Mono", Consolas, monospace;
  font-size: 17px;
  font-weight: 700;
  word-break: break-all;
}

.product-detail-summary .copy-block {
  max-width: 560px;
  margin-bottom: 20px;
  color: #555;
  line-height: 1.8;
}

/* Boxed action bar — was a bare `margin-top: 15px` with no visual
   grouping, so the quantity field and Add Inquiry button read as two
   loose controls rather than one primary action. The "Back to Parts
   Finder" link moves outside this box in the markup (see page.tsx) so it
   stays a lightweight secondary action, not a third item competing for
   space inside the primary one. */
.detail-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  margin-top: 15px;
  padding: 20px;
  max-width: 560px;
  background: var(--surface-2);
  border: 1px solid var(--line);
}

.detail-actions #add-to-cart-quantity {
  height: 44px;
  max-width: 90px;
}

/* Spacing only — BackToProductsLink renders its own .btn.ghost button
   styling (shared elsewhere), so this row exists purely to give it room
   below the new boxed .detail-actions rather than sitting inside it. */
.detail-back-link-row {
  margin-top: 16px;
}

.product-detail-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(280px, 0.8fr);
  gap: 24px;
  margin-bottom: 34px;
}

.detail-panel {
  min-width: 0;
  border: 1px solid var(--line);
  background: #fff;
  padding: 18px;
}

/* Red left-accent bar via ::before rather than a wrapper element — keeps
   Specification/Compatibility's own JSX untouched (page.tsx renders a
   bare <h2>Specification</h2> etc.) while still reading as the same
   "section heading with a brand-colored mark" language as the hero and
   Related Products headings elsewhere on this page. */
.detail-panel h2 {
  position: relative;
  margin: 0 0 14px;
  padding-left: 12px;
  color: var(--ink);
  font-size: 15px;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.detail-panel h2::before {
  content: "";
  position: absolute;
  left: 0;
  top: 2px;
  bottom: 2px;
  width: 4px;
  background: var(--action);
}

.detail-specs {
  display: grid;
  gap: 0;
  margin: 0;
}

.detail-specs div {
  display: grid;
  grid-template-columns: 110px minmax(0, 1fr);
  border-bottom: 1px solid var(--line);
  padding: 7px 0;
}

.detail-specs dt {
  margin: 0;
  color: var(--muted);
}

.detail-specs dd {
  margin: 0;
  word-break: break-all;
}

.detail-chip-group + .detail-chip-group {
  margin-top: 18px;
}

.detail-chip-group h3 {
  margin: 0 0 8px;
  color: var(--muted);
  font-size: 14px;
}

.detail-chip-group > div {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}

/* Outline pill chips (same visual language as the sitewide .chip class
   used for filter tags) instead of solid-red blocks — reads as "these are
   filterable links" rather than static labels, and matches Related
   Products' own chip-like treatment on this page. */
.detail-chip-group a,
.detail-chip-group span {
  display: inline-flex;
  min-height: 30px;
  align-items: center;
  border-radius: 999px;
  border: 1px solid rgba(1, 41, 86, 0.22);
  background: #fff;
  color: var(--navy);
  padding: 6px 13px;
  font-size: 12px;
  font-weight: 900;
}

.detail-chip-group span {
  border-color: var(--line-2);
  color: var(--muted);
}

.detail-chip-group a:hover {
  background: var(--action);
  border-color: var(--action);
  color: #fff;
}

.related-products {
  border-top: 1px solid var(--line);
  padding-top: 24px;
}

.related-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 18px;
}

.related-products h2 {
  margin: 0;
  color: var(--ink);
  font-size: 20px;
  font-weight: 900;
}

.related-head .related-subtitle {
  color: var(--muted);
  font-size: 13px;
}

.related-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px;
}

.related-card {
  min-width: 0;
  border: 1px solid var(--line);
  background: #fff;
  transition: border-color 0.15s ease;
}

.related-card:hover {
  border-color: var(--action);
}

.related-card a {
  display: block;
  padding: 16px;
}

.related-card .thumb {
  width: 100%;
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 12px;
  background: var(--surface-2);
}

.related-card .thumb img,
.related-card .thumb .product-image-fallback {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.related-card .sku,
.related-card strong {
  display: block;
}

.related-card strong {
  margin-top: 2px;
  color: var(--navy);
  font-size: 14px;
  font-weight: 700;
  line-height: 1.4;
}

.gallery-main {
  position: relative;
  overflow: hidden;
  cursor: zoom-in;
}

.gallery-main img {
  display: block;
}

@media (hover: hover) and (pointer: fine) {
  .gallery-main.zooming img {
    opacity: 0;
  }

  .gallery-main.zooming {
    background-repeat: no-repeat;
    background-size: 220%;
  }
}

.gallery-lightbox {
  position: fixed;
  inset: 0;
  z-index: 110;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(16, 25, 32, 0.92);
  padding: 24px;
}

.gallery-lightbox img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  touch-action: pinch-zoom;
}

.gallery-lightbox-close {
  position: absolute;
  top: 18px;
  right: 18px;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  cursor: pointer;
}

.gallery-lightbox-close:hover {
  background: rgba(255, 255, 255, 0.22);
}

.gallery-thumbs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
  gap: 8px;
  margin-top: 12px;
}

.gallery-thumbs button {
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fff;
  padding: 4px;
  aspect-ratio: 1;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.gallery-thumbs button.active,
.gallery-thumbs button:hover {
  border-color: var(--sea);
  box-shadow: 0 0 0 2px rgba(27, 113, 184, 0.16);
}

.gallery-thumbs img {
  width: 100%;
  height: 100%;
  aspect-ratio: 1;
  object-fit: contain;
}

/* =========================================================================
   Contact / Inquiry Cart / News — content-grid (main + narrow right rail)
   already matches the old site's Bbox_in_2c_L8 + Rbox two-column
   pattern, so it's reused as-is. Inquiry Cart uses .narrow-column (old
   inquiry.html is a single narrow centered column, not a two-column
   layout). Company used to be single-column too (old company.html has
   no sidebar at all) but now uses its own .company-grid below — see that
   rule's own comment for why it's a separate class rather than reusing
   this one. ============================================================= */

.content-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(280px, 320px);
  gap: 20px;
  align-items: start;
}

.content-grid > *,
.content-grid aside {
  min-width: 0;
  max-width: 100%;
}

/* Company page's own two-column layout (page.tsx) — added 2026-09-23 to
   reserve space for two venue/facility photos, requested wider than
   .content-grid's own 280-320px rail (that width was tuned for Contact's
   info card/map/Facebook widget, not photos) so the photos read as a
   real visual feature rather than a cramped afterthought. Deliberately a
   separate class from .content-grid rather than widening that one's own
   right column — Contact/Inquiry Cart/News all still depend on
   content-grid's narrower rail for their own sidebar content, and
   widening it there would make their sidebars disproportionately wide
   relative to their own main column content. */
.company-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(320px, 400px);
  gap: 24px;
  align-items: start;
}

.company-grid > * {
  min-width: 0;
  max-width: 100%;
}

/* Full-bleed statement header for Company / Genuine Package (design
   redesign applied 2026-09-23, from a Claude Design canvas pass over
   the site's own real color/type language — not a new brand
   direction). Deliberately its own class, not a reuse of .page-title
   (that class is the existing plain --surface band used elsewhere) —
   this needed a genuinely different, full-bleed treatment, and
   changing .page-title itself would have altered every other page that
   already uses it. Originally shipped navy-bg/white-text; flipped to
   white-bg/navy-text same day per feedback. */
.page-band {
  width: 100%;
  box-sizing: border-box;
  /* Tightened repeatedly per feedback, all 2026-09-23: 56px/48px →
     32px/28px (still a navy block) → 24px/20px (after the bg flipped to
     plain --surface below) → 16px/14px → 10px/10px → 0. Text now sits
     flush against the band edges by request — deliberately tighter than
     .page-title's own 24px/24px, not an oversight. */
  padding: 0;
  background: var(--surface);
}

.page-band .section {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.page-band .eyebrow-rule {
  display: flex;
  align-items: center;
  gap: 14px;
}

.page-band .eyebrow-rule .rule {
  width: 36px;
  height: 2px;
  background: var(--action);
}

.page-band .eyebrow-rule span {
  font-size: 12px;
  font-weight: 900;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--action-2);
}

.page-band h1 {
  margin: 0;
  max-width: 820px;
  font-size: clamp(28px, 3.2vw, 40px);
  line-height: 1.15;
  font-weight: 900;
  letter-spacing: -0.01em;
  color: var(--navy);
}

/* Band flipped from navy-bg/white-text to white-bg/navy-text
   (2026-09-23) — .lead's own var(--muted) gray already reads fine on
   white, so this override just makes that explicit rather than
   inheriting .lead's default. */
.page-band .lead {
  color: var(--muted);
}

.narrow-column {
  max-width: 640px;
  margin: 0 auto;
}

.panel {
  min-width: 0;
  max-width: 100%;
  border: 1px solid var(--line);
  border-radius: 0;
  background: var(--surface);
}

.panel.pad {
  padding: 20px;
}

.info-list {
  display: grid;
  gap: 10px;
}

.info-row {
  display: grid;
  grid-template-columns: minmax(80px, 104px) minmax(0, 1fr);
  gap: 12px;
  border-top: 1px solid var(--line);
  padding-top: 10px;
}

.info-row:first-child {
  border-top: 0;
  padding-top: 0;
}

.info-row span {
  color: var(--muted);
  font-size: 11px;
  font-weight: 900;
  text-transform: uppercase;
}

.info-row strong {
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: break-word;
}

.form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.field {
  display: grid;
  gap: 6px;
}

.field.full {
  grid-column: 1 / -1;
}

.field label {
  color: var(--ink);
  font-size: 13px;
  font-weight: 900;
}

.field input,
.field textarea,
.field select {
  width: 100%;
  min-height: 42px;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 10px 12px;
  background: #fff;
  color: var(--ink);
}

/* Real .form-control:focus: navy border + soft navy glow. */
.field input:focus,
.field textarea:focus,
.field select:focus {
  outline: 0;
  border-color: var(--navy);
  box-shadow: 0 0 8px rgba(1, 41, 86, 0.6);
}

.field textarea {
  min-height: 120px;
  resize: vertical;
}

.map-box,
.photo-box {
  max-width: 100%;
  min-height: 220px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface-2);
  color: var(--sea);
  font-weight: 900;
  text-align: center;
}

/* Company page's redesigned strengths list (page.tsx, replaces a plain
   <ul>) — numbered red index, two-column grid with 1px hairline
   dividers (built from a background-color grid gap, same technique as
   .info-list's own divider rules). The 5th item spans both columns
   since 5 items don't fill a 2-column grid evenly. */
.strengths-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}

.strengths-grid > div {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 22px 24px;
  background: var(--surface);
}

.strengths-grid > div:last-child:nth-child(odd) {
  grid-column: span 2;
}

.strengths-grid .strengths-index {
  font-size: 13px;
  font-weight: 900;
  color: var(--action);
}

.strengths-grid .strengths-label {
  font-size: 15px;
  font-weight: 700;
  color: var(--ink);
}

/* Company page's redesigned stat block — one navy strip holding all
   four values in a 2x2 grid, replacing four separate .panel boxes.
   Reuses .sku's existing small-caps/muted-label look for the labels
   (same "Since"/"Markets"/etc. captions the old four-box version had)
   but overridden to a lighter blue since .sku's own var(--muted) gray
   has no contrast against this navy background. */
.stat-rail {
  background: var(--navy);
  padding: 32px 28px;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px 20px;
}

.stat-rail > div {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.stat-rail .sku {
  color: #7fa8d9;
}

.stat-rail strong {
  font-size: 30px;
  font-weight: 900;
  color: #ffffff;
}

/* Company page's two facility photos — an offset stack (front photo
   overlapping the back one with a white border + shadow) instead of a
   plain vertical pair, so the pairing reads as a deliberate photo
   composition rather than two interchangeable placeholders. */
.facility-photos {
  position: relative;
  padding-top: 8px;
}

.facility-photos .photo-box {
  min-height: 0;
  aspect-ratio: 4 / 3;
  border-radius: 0;
}

/* Real facility photos (2026-09-23) replace the placeholder text these
   boxes used to hold — .photo-box itself has no img rule since every
   other .photo-box on the site (package-panel, product galleries) is
   still a placeholder or has its own scoped img treatment. */
.facility-photos .photo-box img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.facility-photos .photo-box:first-child {
  width: 100%;
}

.facility-photos .photo-box:last-child {
  width: 72%;
  margin-top: -14%;
  margin-left: 24px;
  border: 4px solid var(--surface);
  outline: 1px solid var(--line);
  box-shadow: 0 18px 34px rgba(1, 41, 86, 0.16);
}

/* Genuine Package page's callout — pulls the lead paragraph's closing
   sentence ("Please make sure you have our products in correct OMAX
   package") out into its own accent block instead of leaving it buried
   mid-paragraph. */
.warning-strip {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 24px 28px;
  background: #fff5f5;
  border-left: 4px solid var(--action);
}

.warning-strip svg {
  flex-shrink: 0;
}

.warning-strip span {
  font-size: 17px;
  font-weight: 700;
  color: var(--accent-red);
  line-height: 1.5;
}

/* Genuine Package page's single merged label, "Genuine box & bag
   packaging" (2026-09-23) — went through two earlier layouts first: a
   two-photo .package-panel grid, then a two-pill label row (box left /
   bag right via justify-content: space-between) that broke on narrow
   viewports once both pills' widths plus the row gap outgrew the
   available space. One merged pill has no row width to distribute
   across, so it can't break the same way. */
.package-panel-label {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 20px;
  background: var(--navy);
}

.package-panel-label span {
  font-size: 13px;
  font-weight: 900;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #ffffff;
}

/* Identification-guide callout graphic (2026-09-23) — a single fixed
   1600x586 raster (see make_web_callout.py), not a live layout, so this
   just needs to scale it responsively at its own aspect ratio. */
.package-callout img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--line);
}

/* News detail page's og:image preview box (news/[slug]/page.tsx) — was two
   React inline style attributes (fixed 1200:630 aspect-ratio + 480px cap on
   the wrapper, cover-fit on the <img>), moved to a class since CSP's
   style-src blocks inline style attributes. Both values are fixed
   constants, not per-post computed ones, so a plain class (not a
   generated <style nonce> block) is enough — see the image-cropper.tsx
   fix for the same pattern. Scoped under its own class rather than
   folded into .photo-box above so the shared placeholder styling used on
   Company/Contact/other News list cards stays untouched. */
.news-detail-og-photo {
  width: 100%;
  aspect-ratio: 1200 / 630;
  max-width: 480px;
}

.news-detail-og-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.product-image-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: #fff;
}

.product-image-fallback img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 12%;
}

.map-box {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  min-height: 0;
  padding: 0;
  background: #fff;
  color: inherit;
}

.map-box iframe {
  display: block;
  width: 100%;
  max-width: 100%;
  height: 100%;
  min-height: 0;
  border: 0;
}

.cart-list {
  display: grid;
  gap: 10px;
}

.cart-item {
  display: grid;
  grid-template-columns: 80px minmax(0, 1fr) 120px;
  gap: 12px;
  align-items: center;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 10px;
  background: #fff;
}

.cart-item img {
  width: 80px;
  height: 80px;
  object-fit: contain;
  border-radius: 6px;
  background: var(--surface-2);
}

.cart-item .product-image-fallback {
  width: 80px;
  height: 80px;
  border-radius: 6px;
}

.qty-control {
  display: flex;
  align-items: center;
  gap: 8px;
}

.qty-control button {
  width: 32px;
  height: 32px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  font-weight: 900;
  cursor: pointer;
}

/* -- News list — plain stacked rows (date badge + optional thumb + title),
   not a card grid, matching the old news_list.html article stack. ------- */

.news-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}

.segmented {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* Same pill treatment as .subnav-pill (the old site's real .nav-pills
   look): white idle pill with a blue outline, solid blue fill + white
   text when active — News' own category tabs now read as the same
   "pill tab" family as the section-label bar above them. */
.segmented button {
  min-height: 36px;
  border: 1px solid var(--action);
  border-radius: 4px;
  padding: 7px 16px;
  background: #fff;
  color: var(--muted);
  font-size: 13px;
  font-weight: 400;
  cursor: pointer;
}

.segmented button.active {
  border-color: var(--action);
  background: var(--action);
  color: #fff;
}

.news-list {
  display: grid;
  gap: 8px;
}

.news-row {
  display: flex;
  align-items: center;
  gap: 14px;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 10px 12px;
  background: var(--surface);
}

/* Desktop: the media+title wrapper contributes no box of its own, so its
   img/title children behave as direct flex items of .news-row (date, img,
   title inline) — same markup the mobile grid layout below re-nests into
   an image-left/title-right row under its own date line. */
.news-row-media-title {
  display: contents;
}

.news-row img {
  flex-shrink: 0;
  width: 64px;
  height: 64px;
  object-fit: cover;
  border-radius: 4px;
  background: var(--surface-2);
}

/* Real .badge.cis2-bk treatment (style01.css overrides cis2-bk to the
   brand blue for this site's date badges): solid blue, white text. */
.news-row-date {
  flex-shrink: 0;
  min-height: 24px;
  display: inline-flex;
  align-items: center;
  border-radius: 4px;
  padding: 3px 8px;
  background: var(--action);
  color: #fff;
  font-size: 11px;
  font-weight: 900;
}

/* Wraps title + excerpt so they stack as one flex item (desktop's
   .news-row-media-title is `display: contents`, so this wrapper — not
   the title span alone — is what actually sits in the row's flex
   layout; mobile's grid places it in the row's second column the same
   way the title alone used to sit there). */
.news-row-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.news-row-title {
  min-width: 0;
  font-size: 15px;
  font-weight: 800;
  overflow-wrap: break-word;
}

/* Excerpt was fetched (NewsListItem.excerpt) but never rendered — every
   title row sat with nothing under it. Single-line clamp, not full
   wrapped text: this is a dense list of rows, not a card grid with room
   for a multi-line summary. */
.news-row-excerpt {
  min-width: 0;
  font-size: 13px;
  font-weight: 400;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.toast {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 100;
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: min(360px, calc(100vw - 36px));
  transform: translateY(16px);
  opacity: 0;
  pointer-events: none;
  border-radius: 8px;
  padding: 14px 16px;
  background: var(--ink);
  color: white;
  box-shadow: var(--shadow);
  transition: opacity 0.18s ease, transform 0.18s ease;
}

.toast.show {
  transform: translateY(0);
  opacity: 1;
}

/* Only a toast carrying a real action becomes clickable — a plain
   confirmation toast has nothing to interact with, and staying
   pointer-events: none for that case means it can never accidentally eat
   a click meant for whatever's underneath it during the fade transition. */
.toast.show.has-action {
  pointer-events: auto;
}

.toast-action {
  flex: 0 0 auto;
  color: white;
  font-weight: 800;
  text-decoration: underline;
  white-space: nowrap;
}

.toast-action:hover {
  opacity: 0.8;
}

/* Real #gotop (style.css, confirmed against the live yamamotor.com.tw):
   plain gray square, no radius, no shadow, no hover state — right:20px,
   bottom:30px on desktop. Kept as an icon button (width/height, not the
   real site's font-size-driven glyphicon padding) since this renders an
   inline SVG chevron instead of a Glyphicons Halflings icon font. */
.back-to-top-btn {
  position: fixed;
  right: 20px;
  bottom: 30px;
  z-index: 60;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 0;
  border: none;
  background: #777;
  color: white;
  cursor: pointer;
}

.empty-state {
  border: 1px dashed var(--line);
  border-radius: 8px;
  padding: 30px;
  background: rgba(255, 255, 255, 0.58);
  text-align: center;
}

.cookie-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 95;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 24px;
  background: var(--navy);
  color: rgba(255, 255, 255, 0.92);
  box-shadow: 0 -8px 24px rgba(24, 38, 48, 0.24);
}

.cookie-banner p {
  margin: 0;
  font-size: 13px;
  line-height: 1.6;
  max-width: 640px;
}

.cookie-banner a {
  color: white;
  text-decoration: underline;
}

.cookie-banner-actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

.cookie-banner .btn.ghost {
  border-color: rgba(255, 255, 255, 0.4);
  color: white;
}

@media (max-width: 640px) {
  .cookie-banner {
    flex-direction: column;
    align-items: stretch;
  }

  .cookie-banner-actions {
    justify-content: flex-end;
  }
}

/* =========================================================================
   Responsive — 375/390px mobile QA is mandatory (design.md §3): no
   horizontal scroll, hamburger nav + mobile product filter bar all
   functional. ============================================================ */

@media (max-width: 1040px) {
  .products-layout,
  .content-grid,
  .company-grid {
    grid-template-columns: 1fr;
  }

  .product-toolbar {
    display: none;
  }

  .filter-sidebar {
    display: none;
  }

  .filter-bar {
    display: none;
  }

  .product-head strong {
    display: none;
  }

  .mobile-displacement-filter {
    display: block;
  }

  /* Ported verbatim from oldyamamotor-react's mobile breakpoint (see
     public/styles.css's matching comment above .mobile-product-filter-bar):
     2-column grid, full-width dropdown triggers with a divider line before
     the chevron. Scoped to .mobile-product-filter-bar so it doesn't affect
     the desktop .filter-bar's .filter-dropdown-btn (hidden above anyway) or
     the sidebar's unrelated .filter-option buttons. */
  .mobile-product-filter-pack {
    display: grid;
    gap: 20px;
    margin-bottom: 23px;
  }

  .mobile-product-filter-bar {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 26px;
    row-gap: 20px;
    margin-bottom: 0;
  }

  .mobile-product-filter-bar .filter-dropdown,
  .mobile-product-filter-extra .mobile-displacement-filter {
    min-width: 0;
  }

  .mobile-product-filter-bar .filter-dropdown-btn {
    position: relative;
    width: 100%;
    min-height: 32px;
    justify-content: flex-start;
    border: 1px solid #dcdcdc;
    background: #fff;
    color: #939393;
    padding: 0 42px 0 15px;
    font-size: 16px;
    line-height: 32px;
  }

  .mobile-product-filter-bar .filter-dropdown-btn svg {
    position: absolute;
    top: 50%;
    right: 8px;
    width: 16px;
    height: 16px;
    color: #777;
    transform: translateY(-50%) rotate(0deg);
    transition: transform 0.18s ease;
  }

  .mobile-product-filter-bar .filter-dropdown-btn::after {
    content: "";
    position: absolute;
    top: 0;
    right: 31px;
    width: 1px;
    height: 100%;
    background: #dcdcdc;
  }

  .mobile-product-filter-bar .filter-dropdown-btn[aria-expanded="true"] svg {
    transform: translateY(-50%) rotate(180deg);
  }

  .mobile-product-filter-bar .filter-dropdown-panel {
    width: min(300px, calc(100vw - 38px));
    max-height: 360px;
    border-radius: 0;
  }

  .mobile-product-filter-bar .filter-dropdown:nth-child(even) .filter-dropdown-panel {
    right: 0;
    left: auto;
  }
}

/* Desktop .filter-bar dropdowns + sort control — same look as the mobile
   .mobile-product-filter-bar treatment above (white bg, #dcdcdc border,
   #939393 text, right divider line, centered rotating chevron), just laid
   out as a horizontal row instead of a 2-column grid. Anti-clipping: the
   dropdown list here is fixed (MULTI_DIMENSIONS in filter-panel.tsx), so a
   static "last 2 open right-aligned" rule is stable — revisit with a JS
   getBoundingClientRect() check only if that list becomes dynamic/reorderable. */
@media (min-width: 1041px) {
  .product-toolbar .filter-dropdown-btn {
    position: relative;
    min-height: 34px;
    border: 1px solid #dcdcdc;
    border-radius: 0;
    background-color: #fff;
    color: #939393;
    padding: 0 42px 0 15px;
    font-size: 16px;
    line-height: 32px;
  }

  .product-toolbar .filter-dropdown-btn svg {
    position: absolute;
    top: 50%;
    right: 8px;
    width: 16px;
    height: 16px;
    color: #777;
    transform: translateY(-50%);
    transition: transform 0.18s ease;
  }

  .product-toolbar .filter-dropdown-btn[aria-expanded="true"] svg {
    transform: translateY(-50%) rotate(180deg);
  }

  .product-toolbar .filter-dropdown-btn::after {
    content: "";
    position: absolute;
    top: 0;
    right: 31px;
    width: 1px;
    height: 100%;
    background: #dcdcdc;
  }

  .product-toolbar .filter-dropdown:nth-last-child(-n + 2) .filter-dropdown-panel {
    left: auto;
    right: 0;
  }

}

@media (max-width: 1200px) {
  .category-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* Safety net for the moderate-desktop range where the logo/Inquiry
   overlay and the centered search+nav overlay sit closest together
   (roughly 781-1300px — narrower than this, the fixed mobile bar takes
   over entirely; wider, header-search's clamp() above already keeps
   clear on its own). Scoped narrowly rather than changing the z-index
   relationship at every width, so the intended equal-layer behavior at
   normal desktop sizes is untouched. */
@media (min-width: 781px) and (max-width: 1300px) {
  .header-utility {
    z-index: 5;
  }
}

/* Tablet band (781-1040px): the fixed 246px logo and the header-search
   box's clamp() floor (300px) were sized for desktop widths, so between
   the mobile bar's 780px cutoff and roughly 1020px they physically
   overlap (logo's right edge sits further right than the centered search
   box's left edge) instead of just sitting close together the way the
   z-index safety net above assumes. Shrinking the logo and the search
   box's own footprint here — rather than only reordering their layers —
   is what actually clears the overlap. (The banner itself needs no
   override here — inner pages stay a fixed height at every width down to
   the 780px mobile cutoff, and the home page's aspect-ratio already
   scales it proportionally on its own.) */
@media (min-width: 781px) and (max-width: 1040px) {
  .header-utility {
    padding: 10px 24px;
  }

  .brand img {
    width: 190px;
  }

  .header-search {
    width: clamp(240px, 34vw, 400px);
  }
}

@media (max-width: 900px) {
  .related-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 780px) {
  /* Tight padding so the tile wall sits right under the hero, not padded
     off with the large desktop gaps — and the caption drops to a plain
     16px gray label, matching the official mobile site. */
  .category-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    padding: 12px 16px 24px;
  }

  .category-tile {
    padding: 0 8px 24px;
  }

  .category-tile span {
    margin-top: 8px;
    font-size: 16px;
    font-weight: 400;
    text-transform: none;
    color: var(--muted);
  }

  /* Longer text than every real category tile's short label (see
     .category-tile-more-img span's own desktop-rule comment) — at the
     2-column mobile width each tile's own box is much narrower than
     desktop, so it needs to stay smaller than the 16px every other
     tile's label jumps to here, or it wraps to too many cramped lines
     inside the panel. */
  .category-tile-more-img span {
    font-size: 13px;
  }

  .product-detail-hero,
  .product-detail-grid,
  .related-grid {
    grid-template-columns: 1fr;
  }

  .related-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .product-detail-media {
    max-width: 480px;
    margin: 0 auto;
  }

  /* Mobile header: the overlay-on-banner treatment (logo/search/nav all
     floating on the photo) is replaced entirely below 768px by a fixed
     blue top bar (hamburger left / logo center / search icon right) that
     hides on scroll-down and reappears on scroll-up — matching the real
     yamamotor.com.tw mobile site, ported from oldyamamotor-react's
     `.olddone-toplink`/`.mobile-chrome-hidden` treatment. `mobileChromeHidden`
     is toggled by site-header.tsx's scroll listener. */
  .header-utility {
    position: fixed;
    top: 0;
    right: 0;
    left: 0;
    z-index: 320;
    height: 91px;
    padding: 0 15px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--action);
    transform: translateY(0);
    transition: transform 0.24s ease;
    will-change: transform;
    pointer-events: auto;
  }

  .mobile-chrome-hidden .header-utility {
    transform: translateY(-100%);
  }

  .header-utility-inner {
    width: 100%;
  }

  .brand {
    float: none;
    justify-content: center;
  }

  .brand img {
    width: 160px;
    filter: brightness(0) invert(1);
  }

  .utility-links {
    display: none !important;
  }

  .mobile-top-icon {
    position: absolute;
    top: 50%;
    z-index: 3;
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transform: translateY(-50%);
    border: 0;
    background: transparent;
    padding: 0;
  }

  .mobile-top-menu {
    left: 32px;
    flex-direction: column;
    gap: 4px;
  }

  .mobile-top-menu span {
    width: 18px;
    height: 2px;
    background: #fff;
  }

  .mobile-top-search {
    right: 32px;
    color: #fff;
  }

  /* JSX renders an inline <svg stroke="currentColor">, not an <img> — the
     old img-targeted rule never matched anything. */
  .mobile-top-search svg {
    width: 24px;
    height: 24px;
  }

  /* The fixed 91px blue bar is position:fixed (out of flow), so the banner
     itself reserves that space via padding-top and becomes an auto-height
     flex column — the image gets its own explicit height rather than
     filling a parent whose height would otherwise collapse under
     box-sizing: border-box (91px padding alone would exceed a fixed 84px/
     228px banner height). */
  .header-banner {
    width: 100%;
    height: auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: visible;
    padding-top: 91px;
  }

  .header-banner > img {
    order: 2;
    height: 84px;
    min-height: 84px;
    object-fit: cover;
  }

  /* Mobile home banner used a fixed 319px/228px box regardless of viewport
     width — cropping or letterboxing the real 1903x883 image depending on
     how far a given phone's width had drifted from what those numbers were
     tuned against. calc(91px + 46.4vw) reserves the fixed top bar's own
     height, then adds the image's real aspect ratio (883/1903 ≈ 46.4%)
     applied to the viewport width, so the banner is always exactly tall
     enough for the full image at whatever width it's actually rendered. */
  .header-banner.home {
    position: relative;
    height: calc(91px + 46.4vw);
    display: block;
    overflow: hidden;
  }

  .header-banner.home > img {
    position: absolute;
    top: 91px;
    right: 0;
    left: 0;
    width: 100%;
    height: auto;
    aspect-ratio: 1903 / 883;
  }

  .header-overlay {
    display: none;
  }

  .header-banner .slidcontrol {
    display: none;
  }

  /* More specific than the blanket rule above, so the homepage carousel's
     arrows stay visible on mobile — only non-home inner-page banners have
     no controls to hide in the first place. */
  .header-banner.home .slidcontrol {
    display: flex;
  }

  .header-banner.home .slidcontrol .slick-prev,
  .header-banner.home .slidcontrol .slick-next {
    top: calc(91px + 23.2vw);
  }

  .header-banner.home .slick-dots {
    bottom: 12px;
  }

  .nav-links {
    display: none;
  }

  /* Full-screen search overlay, opened from the mobile top bar's search
     icon — real Product search, not a stand-in: submits to /products?sku=
     just like the desktop header box. */
  .mobile-search-layer {
    position: fixed;
    inset: 0;
    z-index: 390;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    overflow-y: auto;
    background: rgba(255, 255, 255, 0.82);
    padding: 160px 22px 90px;
    animation: mobileSearchBackdropIn 0.2s ease both;
  }

  .mobile-search-dialog {
    position: relative;
    width: min(100%, 450px);
    min-height: 258px;
    background: #fff;
    box-shadow: 0 12px 31px rgba(0, 0, 0, 0.12);
    padding: 60px 32px 40px;
    animation: mobileSearchDialogIn 0.24s ease both;
  }

  .mobile-search-close {
    position: absolute;
    top: 9px;
    right: 16px;
    min-height: 30px;
    border: 0;
    background: transparent;
    color: var(--ink);
    padding: 0;
    font-size: 14px;
  }

  .mobile-search-form {
    display: grid;
    justify-items: center;
    gap: 17px;
  }

  .mobile-search-form input {
    width: 100%;
    min-height: 44px;
    border: 2px solid var(--line-2);
    background: #fff;
    color: var(--ink);
    padding: 7px 9px;
    font-size: 16px;
  }

  .mobile-search-form button {
    min-width: 122px;
    min-height: 38px;
    border: 0;
    background: var(--action);
    color: #fff;
    padding: 8px 18px;
    font-size: 16px;
  }

  @keyframes mobileSearchBackdropIn {
    from { opacity: 0; }
    to { opacity: 1; }
  }

  @keyframes mobileSearchDialogIn {
    from { opacity: 0; transform: translateY(14px) scale(0.98); }
    to { opacity: 1; transform: translateY(0) scale(1); }
  }

  /* Off-canvas nav: dark backdrop + a panel sliding in from the left,
     ported from oldyamamotor-react. */
  .mobile-menu-backdrop {
    position: fixed;
    inset: 0;
    z-index: 420;
    display: block;
    border: 0;
    background: rgba(0, 0, 0, 0.55);
    padding: 0;
    animation: mobileMenuBackdropIn 0.22s ease both;
  }

  .mobile-menu-backdrop.closing {
    animation: mobileMenuBackdropOut 0.2s ease both;
  }

  .mobile-menu,
  .mobile-menu.open {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 430;
    width: min(246px, 78vw);
    margin: 0;
    border: 0;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    background: var(--footer-bg);
    box-shadow: 4px 0 13px rgba(0, 0, 0, 0.36);
    transform-origin: left center;
  }

  .mobile-menu:not(.open) {
    display: none;
  }

  .mobile-menu.open {
    animation: mobileMenuPanelIn 0.28s cubic-bezier(0.2, 0.85, 0.25, 1) both;
  }

  .mobile-menu.open.closing {
    animation: mobileMenuPanelOut 0.22s ease both;
  }

  .mobile-menu-head {
    min-height: 62px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: var(--action);
    color: #fff;
    padding: 0 16px 0 20px;
    font-size: 18px;
    font-weight: 700;
    animation: mobileMenuItemIn 0.22s ease 0.04s both;
  }

  .mobile-menu-head button {
    width: 34px;
    min-height: 34px;
    border: 0;
    background: transparent;
    color: #fff;
    padding: 0;
    font-size: 30px;
    font-weight: 700;
    line-height: 1;
  }

  .mobile-menu nav {
    display: block;
    width: 100%;
  }

  .mobile-menu nav > a {
    min-height: 55px;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    border: 0;
    border-bottom: 1px solid var(--line-2);
    background: var(--footer-bg);
    color: #737373;
    padding: 0 15px;
    text-align: left;
    font-size: 15px;
    font-weight: 400;
    animation: mobileMenuItemIn 0.22s ease both;
  }

  .mobile-menu nav > a:nth-child(1) { animation-delay: 0.07s; }
  .mobile-menu nav > a:nth-child(2) { animation-delay: 0.1s; }
  .mobile-menu nav > a:nth-child(3) { animation-delay: 0.13s; }
  .mobile-menu nav > a:nth-child(4) { animation-delay: 0.16s; }
  .mobile-menu nav > a:nth-child(5) { animation-delay: 0.19s; }

  .mobile-menu.closing .mobile-menu-head,
  .mobile-menu.closing nav > a {
    animation: mobileMenuItemOut 0.16s ease both;
  }

  .mobile-menu nav > a:hover {
    background: var(--line-2);
    color: var(--ink);
  }

  @keyframes mobileMenuBackdropIn {
    from { opacity: 0; }
    to { opacity: 1; }
  }

  @keyframes mobileMenuBackdropOut {
    from { opacity: 1; }
    to { opacity: 0; }
  }

  @keyframes mobileMenuPanelIn {
    from { opacity: 0; transform: translateX(-18px) scaleX(0.92); }
    to { opacity: 1; transform: translateX(0) scaleX(1); }
  }

  @keyframes mobileMenuPanelOut {
    from { opacity: 1; transform: translateX(0) scaleX(1); }
    to { opacity: 0; transform: translateX(-18px) scaleX(0.92); }
  }

  @keyframes mobileMenuItemIn {
    from { opacity: 0; transform: translateX(-10px) scale(0.98); }
    to { opacity: 1; transform: translateX(0) scale(1); }
  }

  @keyframes mobileMenuItemOut {
    from { opacity: 1; transform: translateX(0) scale(1); }
    to { opacity: 0; transform: translateX(-8px) scale(0.98); }
  }

  @media (prefers-reduced-motion: reduce) {
    .mobile-menu-backdrop,
    .mobile-menu.open,
    .mobile-menu-head,
    .mobile-menu nav > a {
      animation: none;
    }
  }

  /* Fixed bottom "Inquiry" quick-tool bar — hides in sync with the top bar
     on scroll-down (shares the same .mobile-chrome-hidden toggle), so
     scrolling down doesn't leave the bottom bar stranded while the top
     bar disappears. */
  .mobile-bottom-tools {
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 300;
    height: 72px;
    display: grid;
    grid-template-columns: 1fr;
    background: var(--action);
    color: #fff;
    transform: translateY(0);
    transition: transform 0.24s ease;
    will-change: transform;
  }

  body.mobile-chrome-hidden .mobile-bottom-tools {
    transform: translateY(100%);
  }

  .mobile-bottom-tools .mobile-inquiry-full {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    border: 0;
    background: transparent;
    color: #fff;
    padding: 6px 4px;
    font-size: 14px;
  }

  .mobile-bottom-tools .tool-icon {
    width: 16px;
    height: 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: #fff;
    color: var(--action);
    font-size: 11px;
    font-weight: 800;
    line-height: 1;
  }

  .mobile-bottom-tools .cart-count {
    position: absolute;
    top: 4px;
    left: calc(50% + 20px);
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 999px;
    background: #fff;
    color: var(--action);
    font-size: 10px;
    font-weight: 800;
    line-height: 16px;
    text-align: center;
  }

  body {
    padding-bottom: 72px;
  }

  .back-to-top-btn {
    bottom: 102px;
  }

  .toast {
    bottom: 90px;
  }

  .cookie-banner {
    bottom: 72px;
  }


  .section {
    width: min(calc(100% - 28px), 1180px);
    padding: 28px 0;
  }

  .form-grid,
  .spec-grid,
  .related-grid {
    grid-template-columns: 1fr;
  }

  .product-card {
    padding-bottom: 24px;
  }

  .product-card > div {
    min-height: 0;
    display: block;
  }

  .pro_showimg {
    margin-bottom: 10px;
    text-align: center;
  }

  .pro_showimg img {
    width: min(220px, 68vw);
    height: min(220px, 68vw);
    margin: 0 auto;
  }

  .pro-align {
    min-height: 0;
    display: block;
  }

  .pro-align > div:first-child {
    display: block;
  }

  .pro_table {
    max-width: 100%;
  }

  .pro_table > div {
    width: 100%;
  }

  .pro_table > div > div > div:nth-child(1) {
    width: 89px;
    min-width: 89px;
    padding: 4px 6px;
    background: var(--table-label-bg);
    color: var(--ink);
    font-size: 14px;
    line-height: 1.55;
  }

  .pro_table > div > div > div:nth-child(2) {
    width: auto;
    padding: 4px 8px;
    color: var(--muted);
    font-size: 14px;
    line-height: 1.55;
  }

  .product-card-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 12px;
  }

  .product-card-actions .btn-warning {
    width: auto;
    flex: 1 1 auto;
    min-height: 38px;
    padding: 7px 10px;
    font-size: 15px;
    text-align: center;
  }

  .proBrand {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-top: 16px;
  }

  .proBrand span {
    color: var(--ink);
    font-size: 14px;
  }

  .proBrand ul {
    gap: 5px;
  }

  .news-toolbar {
    align-items: stretch;
    flex-direction: column;
  }

  .sku-search-row.max-w-md {
    max-width: none;
  }

  /* Real official-site mobile layout: date pill on its own line, then an
     image-left/title-right row below it — not one inline flex row. */
  .news-row {
    display: block;
  }

  .news-row-date {
    display: inline-flex;
    margin-bottom: 8px;
  }

  .news-row-media-title {
    display: grid;
    grid-template-columns: 84px minmax(0, 1fr);
    gap: 12px;
    align-items: center;
  }

  .news-row img {
    width: 84px;
    height: 84px;
    grid-row: 1 / -1;
  }

  .cart-item,
  .info-row {
    grid-template-columns: 1fr;
  }

  .footer-inner,
  .results-top {
    align-items: center;
  }

  .display-title {
    font-size: 30px;
  }
}

@media (max-width: 480px) {
  .category-grid {
    grid-template-columns: 1fr;
  }
}
