/* Layer on top of deskmat/styles.css — reuses its CSS variables,
   only adds the pieces that don't exist yet for the new catalog. */

.nav-menu.active, .desktop-nav a.active { color: var(--blue); }

/* deskmat/styles.css defines .product-art at TWO specificities:
     .product-art               (aspect-ratio:1.6, padding:17px, gradient bg, border-top)
     .product-card .product-art (aspect-ratio:16/9  — wins over the plain rule above)
   Both were built for deskmat's own text-overlay card style (name/size
   text absolutely positioned over a gradient, plus decorative blurred
   circles) — the padding/background is what reads as a "frame" around
   the image once you drop in a plain <img> like the new catalog cards
   do. Matching deskmat's own specificity here (rather than a plain
   .product-art) is what actually wins the override, since equal-
   specificity ties go to whichever stylesheet loads last — which is
   this one, on every Keyboard/Accessories/Mouse page. Deskmat's own
   pages never load this file, so nothing above changes there. */
.product-card .product-art{
  aspect-ratio:1;
  padding:0;
  background:none;
  border-top:none;
  overflow:hidden;
}
.product-card .product-art img,
.product-art img{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
}
/* Plain fallback for .product-art used outside a .product-card (e.g. the
   main image frame on the product detail page). Overrides deskmat's
   padded gradient frame so the photo fills the box edge-to-edge.
   #mainImageFrame.product-art is a belt-and-suspenders duplicate of the
   inline style already set on that element in product.html — keep both,
   product.html's inline style has been reverted by accident before. */
.product-art,
#mainImageFrame.product-art{
  aspect-ratio:1;
  padding:0;
  border:none;
  border-top:none;
  background:none;
  background-image:none;
  overflow:hidden;
}
.product-art img,
#mainImageFrame.product-art img{
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:center;
  display:block;
}

.category-tiles{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:14px;
}
/* Homepage's 4 top-level sections — same tile grid, one extra column.
   Kept as a modifier (rather than changing .category-tiles itself) so
   the keyboard subtype page's 6-tile 3-column layout is untouched. */
.category-tiles.cols-4{ grid-template-columns:repeat(4,1fr); }
.category-tile{
  border:1px solid var(--line);
  background:#0f1518;
  padding:22px;
  display:block;
  transition:.2s;
}
.category-tile:hover{ border-color:var(--blue); transform:translateY(-3px); }
.category-tile strong{ font:600 16px "Space Grotesk"; display:block; margin-bottom:6px; }
.category-tile span{ color:var(--muted); font-size:13px; }

.variant-group{ margin:18px 0; }
.variant-group-label{
  font:600 10px "Space Grotesk";
  letter-spacing:.1em;
  text-transform:uppercase;
  color:var(--muted);
  margin-bottom:8px;
  display:block;
}
.variant-options{ display:flex; flex-wrap:wrap; gap:8px; }
.variant-chip{
  border:1px solid var(--line);
  background:var(--panel);
  color:var(--text);
  padding:8px 14px;
  font-size:13px;
  cursor:pointer;
  transition:.15s;
}
.variant-chip:hover{ border-color:#3b5962; }
.variant-chip.selected{ border-color:var(--blue); color:var(--blue); background:rgba(32,195,223,.08); }

.catalog-specs{ color:var(--muted); font-size:13px; margin:10px 0 18px; }

.product-gallery-thumbs{
  display:flex;
  gap:8px;
  margin-top:10px;
  flex-wrap:wrap;
}
.product-gallery-thumb{
  width:64px;
  height:64px;
  border:1px solid var(--line);
  background:var(--panel);
  cursor:pointer;
  padding:0;
  overflow:hidden;
  transition:.15s;
}
.product-gallery-thumb img{ width:100%; height:100%; object-fit:cover; display:block; }
.product-gallery-thumb.selected{ border-color:var(--blue); }

.product-info-section{
  border:1px solid var(--line);
  border-radius:6px;
  margin-top:10px;
}
.product-info-section summary{
  padding:13px 16px;
  cursor:pointer;
  font:600 14px "Space Grotesk";
  color:white;
  list-style:none;
  display:flex;
  align-items:center;
  justify-content:space-between;
}
.product-info-section summary::-webkit-details-marker{ display:none; }
.product-info-section summary::after{
  content:"+";
  color:var(--muted);
  font-size:16px;
}
.product-info-section[open] summary::after{ content:"–"; }
.product-info-section .product-info-body{
  padding:0 16px 14px;
}
.product-info-section ul{
  margin:0;
  padding-left:18px;
  color:var(--muted);
  font-size:13px;
  line-height:1.7;
}
.product-info-section ul strong{
  color:var(--text);
}
.product-info-section .product-info-heading{
  margin:16px 0 6px;
  font:600 11px "Space Grotesk";
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--text);
}
.product-info-section .product-info-body > .product-info-heading:first-child{
  margin-top:0;
}
.product-info-section .product-info-subhead{
  margin:12px 0 2px;
  font:600 13px "Space Grotesk";
  color:var(--text);
}
.product-info-section .product-info-body > .product-info-subhead:first-child{
  margin-top:0;
}
.product-info-section ul.product-info-sublist{
  margin:4px 0 2px;
  padding-left:16px;
}

.variant-chip.out-of-stock{
  opacity:.4;
  cursor:not-allowed;
  text-decoration:line-through;
}

.product-components{ margin:22px 0; }
.component-links{
  display:flex;
  flex-direction:column;
  gap:8px;
}
.component-link{
  display:flex;
  align-items:center;
  gap:12px;
  border:1px solid var(--line);
  background:var(--panel);
  padding:8px;
  text-decoration:none;
  color:var(--text);
  transition:.15s;
}
.component-link:hover{ border-color:var(--blue); }
.component-link img,
.component-link-noimg{
  width:46px;
  height:46px;
  object-fit:cover;
  background:#0f1518;
  flex-shrink:0;
}
.component-link-text{ display:flex; flex-direction:column; line-height:1.35; }
.component-role{
  font-size:11px;
  letter-spacing:.06em;
  text-transform:uppercase;
  color:var(--muted);
}
.component-link-text strong{ font:600 14px "Space Grotesk"; }

@media (max-width: 900px){
  .category-tiles,
  .category-tiles.cols-4{ grid-template-columns:repeat(2,1fr); }
}
@media (max-width: 650px){
  .category-tiles,
  .category-tiles.cols-4{ grid-template-columns:1fr; }
}

/* Keyboard/Mouse/Accessories product page: image column + info column.
   Same two-column desktop layout the inline style used to set, but with
   a real mobile breakpoint (the inline style had none, so these pages
   stayed squeezed side-by-side on phones instead of stacking). */
.catalog-product-layout{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:40px;
  align-items:start;
}
@media (max-width: 700px){
  .catalog-product-layout{
    grid-template-columns:1fr;
    gap:24px;
  }
}

/* =========================
   KEYBOARD LISTING — FILTER SIDEBAR
   Only keyboard/collection.html includes the markup this styles
   (.listing-body / .filter-sidebar / .filter-toggle), so nothing
   here changes how accessories/mouse render even though they load
   this same stylesheet.
========================= */
.listing-body{
  display:grid;
  grid-template-columns:220px 1fr;
  gap:32px;
  align-items:start;
}

.listing-results-count{
  color:var(--muted);
  font-size:12px;
  margin-bottom:16px;
}

.filter-toggle{
  display:none;
  width:100%;
  border:1px solid var(--line);
  background:var(--panel);
  color:var(--text);
  font:600 13px "Space Grotesk";
  padding:12px 16px;
  margin-bottom:18px;
  cursor:pointer;
}
.filter-toggle:hover{ border-color:var(--blue); }

.filter-sidebar{
  border:1px solid var(--line);
  background:#0f1518;
  padding:18px;
  position:sticky;
  top:20px;
}

.filter-sidebar-head{
  display:flex;
  justify-content:space-between;
  align-items:center;
  margin-bottom:6px;
  font:600 13px "Space Grotesk";
  color:var(--text);
}
.filter-sidebar-head button{
  background:none;
  border:0;
  color:var(--muted);
  font-size:11px;
  text-decoration:underline;
  cursor:pointer;
  padding:0;
}
.filter-sidebar-head button:hover{ color:var(--blue); }

.filter-section{
  border-top:1px solid var(--line);
  padding:14px 0;
}
.filter-section:first-of-type{ border-top:none; padding-top:10px; }

.filter-section-label{
  display:block;
  font:600 10px "Space Grotesk";
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--muted);
  margin-bottom:10px;
}

.filter-options{
  display:flex;
  flex-direction:column;
  gap:9px;
}

.filter-option{
  display:flex;
  align-items:center;
  gap:9px;
  font-size:13px;
  color:#cdd3d5;
  cursor:pointer;
}
.filter-option:hover{ color:var(--text); }

.filter-option input[type="checkbox"]{
  appearance:none;
  -webkit-appearance:none;
  width:15px;
  height:15px;
  border:1px solid var(--line);
  background:var(--panel);
  position:relative;
  flex-shrink:0;
  cursor:pointer;
}
.filter-option input[type="checkbox"]:checked{
  border-color:var(--blue);
  background:var(--blue);
}
.filter-option input[type="checkbox"]:checked::after{
  content:"✓";
  position:absolute;
  inset:0;
  display:flex;
  align-items:center;
  justify-content:center;
  font-size:10px;
  color:#04181d;
}

.filter-option span:nth-child(2){ flex:1; }
.filter-count{ color:#69757a; font-size:11px; }

@media (max-width: 950px){
  .filter-toggle{ display:block; }
  .listing-body{ grid-template-columns:1fr; }
  .filter-sidebar{
    display:none;
    position:static;
    margin-bottom:24px;
  }
  .filter-sidebar.open{ display:block; }
}


/* === HUB + KEYBOARD LANDING (Medium polish) === */

.hero-visual{
  width:100%;
}
.hero-grid > *{
  min-width: 0;
}
.hero-visual-frame{
  width:100%;
  aspect-ratio: 4 / 3;
  border-radius: 18px;
  border: 1px solid var(--line, #26313a);
  background-size: cover;
  background-position: center;
  background-color: #0f1518;
  box-shadow: 0 28px 70px rgba(0,0,0,.45);
}

.hub-hero,
.keyboard-hero{
  padding-bottom: 48px;
}

.hero-social a{
  width: 46px;
  height: 46px;
  border: 1px solid var(--line, #26313a);
  border-radius: 50%;
  display: grid;
  place-items: center;
  transition: .2s;
}
.hero-social a img{
  width: 20px;
  height: 20px;
  object-fit: contain;
  filter: brightness(0) invert(1);
  opacity: .9;
}
.hero-social a:hover{
  border-color: var(--blue);
  transform: translateY(-2px);
}
.hero-social a:hover img{
  opacity: 1;
}

.how-to-line{
  margin: 20px 0 0;
  font-size: 13px;
  color: #7a868c;
  max-width: 420px;
  line-height: 1.45;
}

.trust-strip{
  border-bottom: 1px solid var(--line, #26313a);
  background: #0d1215;
  padding: 22px 0;
}
.trust-strip-grid{
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
}
.trust-item{
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 4px 0;
}
.trust-item strong{
  font: 600 13px "Space Grotesk", sans-serif;
  color: #e8eef0;
}
.trust-item span{
  font-size: 12px;
  color: #7a868c;
  line-height: 1.4;
}

.hub-categories,
.keyboard-categories{
  padding: 48px 0 80px;
}
.section-head-inline{
  margin-bottom: 22px;
}
.section-head-inline h2{
  font: 600 clamp(22px, 3vw, 28px) "Space Grotesk", sans-serif;
  margin: 0;
  letter-spacing: -.03em;
}
.section-head-inline .eyebrow{
  margin-bottom: 8px;
}

/* Taller category tiles on hub / keyboard landings */
.hub-categories .collection-card.featured,
.keyboard-categories .collection-card.featured{
  min-height: 240px;
}

@media (max-width: 900px){
  .hero-grid{
    grid-template-columns: 1fr;
    gap: 36px;
  }
  .hero-visual-frame{
    aspect-ratio: 16 / 10;
    max-height: 320px;
  }
  .trust-strip-grid{
    grid-template-columns: 1fr;
    gap: 14px;
  }
}

@media (max-width: 650px){
  .hub-categories .collection-card.featured,
  .keyboard-categories .collection-card.featured{
    min-height: 180px;
  }
}

/* === Hero carousel (home) === */
.hero-visual{
  width: 100%;
  min-width: 0; /* prevent grid child overflow */
}
.hero-carousel{
  position: relative;
  width: 100%;
  max-width: 100%;
  /* deskmat/styles.css's .hero-carousel sets aspect-ratio:1.55 for its own
     markup. We don't redeclare it above, so it leaks through and makes this
     outer box taller than .hero-carousel-track below, leaving a gap above
     the dots. Reset it so the track's own aspect-ratio/max-height controls
     the visible height instead. */
  aspect-ratio: unset;
  border-radius: 18px;
  overflow: hidden;
  border: 1px solid var(--line, #26313a);
  box-shadow: 0 28px 70px rgba(0,0,0,.45);
  background: #0f1518;
  isolation: isolate;
}
.hero-carousel-track{
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 10;
  max-height: min(420px, 52vw);
  background: #0f1518;
}
.hero-carousel-slide{
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
  opacity: 0;
  transition: opacity .5s ease;
  pointer-events: none;
  z-index: 0;
}
.hero-carousel-slide.is-active{
  opacity: 1;
  pointer-events: auto;
  z-index: 1;
}
.hero-carousel-slide img{
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  border: 0;
}
/* subtle bottom fade so dots stay readable */
.hero-carousel::after{
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 56px;
  background: linear-gradient(to top, rgba(6,10,12,.55), transparent);
  pointer-events: none;
  z-index: 2;
}
.hero-carousel-btn{
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,.28);
  background: rgba(8,12,14,.72);
  color: #fff;
  font-size: 26px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(8px);
  transition: background .2s, border-color .2s, opacity .2s;
  opacity: .92;
}
.hero-carousel-btn:hover{
  background: rgba(8,12,14,.92);
  border-color: var(--blue, #4ec3e0);
  opacity: 1;
}
.hero-carousel-btn.prev{ left: 10px; }
.hero-carousel-btn.next{ right: 10px; }
.hero-carousel-dots{
  position: absolute;
  left: 0;
  right: 0;
  bottom: 12px;
  z-index: 3;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  pointer-events: none;
  /* deskmat/styles.css defines .hero-carousel-dots too (its own pill-shaped
     dot tray, translateX(-50%) centered). Equal specificity + later load
     order means our declared properties above win, but properties we don't
     redeclare (transform, padding, border, etc.) still leak through from
     deskmat's rule. Reset them explicitly so nothing carries over. */
  transform: none;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  backdrop-filter: none;
}
.hero-carousel-dot{
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 0;
  padding: 0;
  background: rgba(255,255,255,.4);
  cursor: pointer;
  pointer-events: auto;
  transition: background .2s, transform .2s;
}
.hero-carousel-dot.is-active{
  background: var(--blue, #4ec3e0);
  transform: scale(1.2);
}
@media (max-width: 900px){
  .hero-carousel-track{
    aspect-ratio: 16 / 10;
    max-height: 280px;
  }
  .hero-carousel-btn{
    width: 36px;
    height: 36px;
    font-size: 22px;
  }
}
@media (max-width: 520px){
  .hero-carousel-track{
    max-height: 220px;
  }
}

/* =========================
   PCHUM BEN FESTIVAL DISCOUNT
========================= */

/* Struck-through original + sale price, used anywhere catalogPriceRangeHTML()
   renders (collection cards, homepage "All Products" grid). */
.catalog-price-was{
  color: var(--muted);
  font-size: 12px;
  font-weight: 500;
  text-decoration: line-through;
  margin-right: 6px;
}
.catalog-price-now{
  color: #4ade80;
}

/* "-20%" ribbon pinned to a product thumbnail. Card/art wrapper needs
   position:relative — .product-art already establishes a stacking context
   via overflow:hidden, so we add position:relative alongside it here. */
.product-card .product-art,
.collection-card .product-art{
  position: relative;
}
.catalog-discount-badge{
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 2;
  display: inline-block;
  background: #d81e3f;
  color: hwb(0 100% 0%);
  font: 800 12px/1 "Space Grotesk", sans-serif;
  letter-spacing: .01em;
  white-space: nowrap;
  padding: 5px 9px;
  border-radius: 4px;
  box-shadow: 0 2px 6px rgba(0,0,0,.35);
  text-shadow: 0 1px 1px rgba(0,0,0,.25);
  /* Prevents mobile browsers' "font boosting" (auto-inflating small text
     in narrow columns) from blowing this badge up to several times its
     real size — without this, -webkit text-size-adjust can make an
     11-12px badge render 3-4x larger and blurrier on phones. */
  -webkit-text-size-adjust: 100%;
  -moz-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* Homepage promo banner announcing the sale, shown above/below the hero
   when the festival discount is currently active. */
.festival-banner{
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
  text-align: center;
  padding: 12px 20px;
  background: linear-gradient(90deg, rgba(224,71,90,.14), rgba(224,71,90,.05));
  border-top: 1px solid rgba(224,71,90,.35);
  border-bottom: 1px solid rgba(224,71,90,.35);
  color: var(--text);
  font: 600 14px "Space Grotesk", sans-serif;
}
.festival-banner strong{
  color: #ff6b7a;
}
.festival-banner .festival-banner-sub{
  color: var(--muted);
  font-weight: 500;
  font-size: 12px;
}

/* "All Products" grid on the homepage, below SHOP BY CATEGORY. Reuses
   .listing-grid / .product-card (defined in deskmat/styles.css) for the
   same look as the Keyboard/Accessories/Mouse listing pages. */
.hub-all-products{
  margin-top: 44px;
}
.hub-all-products .pc-cat-tag{
  display: block;
  color: var(--muted);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .06em;
  margin-bottom: 2px;
}