/* ==========================================================================
   THE GENESYS - home
   Design: "Nuova proposta grafica.dc.html" -> data-screen-label="Web - Home
   (tema chiaro)" (Turn 11a), on the GENESIS direction from Turn 3.

   A RESTYLE of the parent's templates/home.php, not a fork. That template is
   574 lines of WP_Query blocks feeding a Swiper hero, product carousels, a
   creator strip, partners/press grids and a vendor block - all client-managed
   content. None of it is forked; this file only re-dresses it.

   ⚠️ The canvas gives ONE home screen and it is a single 760px viewport: the
   hero. It says nothing about the nine sections below the fold. So the hero is
   built to the design, and the rest is brought onto the same ground, type
   scale and palette so the page reads as one thing.

   The canvas hero is text-left / model-right with a technical grid behind the
   model and a floating product card. The site's existing slider already has
   that structure - image, heading, copy, CTA - which is why this is a restyle:
   the slides stay ACF-managed and the composition survives.

   Not reproduced, for want of data (consistent with the rest of the redesign):
   "ready at 3 nodes near you" on the hero card - there is no node data.
   ========================================================================== */

body.gns-home {
  background-color: var(--gns-bg);
  color: var(--gns-text);
}
body.gns-home .site,
body.gns-home #page,
body.gns-home #content,
body.gns-home .site-main {
  background-color: var(--gns-bg);
}

/* --------------------------------------------------------- typography ---- */

/*
 * ⚠️ !important on colour, not just the fill. The parent styles these headings
 * from inside their container - e.g. `.overalls-container .card h3` (0,2,1) -
 * which out-specifies a plain `body.gns-home h3` (0,1,2). Two symptoms, both
 * seen on this page:
 *
 *   - the Recommended / Best Seller headings computed rgb(0,0,0): black on a
 *     dark card
 *   - the Kickstarter / Waitlist headings computed rgba(0,0,0,0): the parent
 *     paints them as gradient text with `color: transparent`, and killing the
 *     gradient without also setting a colour left them invisible
 *
 * The element hash varies per card, so there is no generic selector to
 * out-specify; forcing the two properties is the containable fix.
 */
body.gns-home h1,
body.gns-home h2,
body.gns-home h3,
body.gns-home h4,
body.gns-home .section-title,
body.gns-home .vendor-title,
body.gns-home .title-section,
body.gns-home .card h1,
body.gns-home .card h2,
body.gns-home .card h3,
body.gns-home .card h4 {
  font-family: var(--gns-font);
  font-weight: 500;
  letter-spacing: -.03em;
  text-transform: none;
  color: var(--gns-text) !important;
  background: none !important;
  -webkit-background-clip: border-box !important;
          background-clip: border-box !important;
  -webkit-text-fill-color: var(--gns-text) !important;
}
body.gns-home p,
body.gns-home li,
body.gns-home .vendor-content,
body.gns-home .info-card-content {
  color: var(--gns-body);
}

/*
 * The parent tints two words of the partners heading blue and purple. On the
 * dark ground the blue is unreadable, so both take the brand accents instead -
 * ink variants, since they are text.
 */
body.gns-home .title-blue {
  color: var(--gns-cyan-ink) !important;
  -webkit-text-fill-color: var(--gns-cyan-ink) !important;
}
body.gns-home .title-purple {
  color: var(--gns-magenta-ink) !important;
  -webkit-text-fill-color: var(--gns-magenta-ink) !important;
}

/* --------------------------------------------------------------- hero ---- */

body.gns-home .slider-container,
body.gns-home .slider-overlay {
  background: none;
  background-color: transparent;
}
body.gns-home .slider-container {
  position: relative;
  background-color: var(--gns-bg);
  /* The canvas puts a technical grid behind the hero model. */
  background-image: var(--gns-grid);
  border-bottom: 1px solid var(--gns-border-faint);
}

/*
 * ⚠️ The hero's "Find out more" ran off the right edge of the screen on wide
 * viewports - cut in half at 1885px.
 *
 * The parent caps the SWIPER WRAPPER:
 *
 *   .product-slider .swiper-wrapper { max-width: 920px }
 *
 * The wrapper is the rail that holds every slide side by side, and Swiper
 * writes each slide's width inline from the container - `width: 1885px` here.
 * So a 1885px slide sat inside a 920px rail, which centred itself and started
 * at x=483; the slide then ran to 2368 and everything positioned against its
 * right-hand side went off screen. `.product-slider` has `overflow: hidden`,
 * so the page never scrolled and nothing announced it.
 *
 * Swiper's own stylesheet says `.swiper-wrapper { width: 100% }` for exactly
 * this reason. Restoring that is the fix; the cap was never doing anything a
 * cap should.
 *
 * Deliberately NOT also constraining `.slide-content`. Its width -
 * `calc(100% - 320px)` - is the parent's hero composition, it is what the page
 * has always looked like, and narrowing it here would be redesigning the hero
 * rather than fixing the overflow.
 */
body.gns-home .product-slider .swiper-wrapper {
  max-width: none;
}

/*
 * The hero band: image left, copy left of it, CTA on the right, the whole thing
 * centred. Rebuilt here because the parent's own geometry cannot hold it.
 *
 * What the parent gives us, and why each piece bites:
 *
 *   .swiper-slide      display:block; height:280px
 *   .swiper-slide img  float:left; width:280px
 *   .slide-content     width:calc(100% - 320px); height:calc(100% - 80px) = 200px;
 *                      display:flex; flex-direction:COLUMN; flex-wrap:wrap
 *   .slide-content h3  overflow:hidden
 *
 * The column is 200px tall and fixed. Heading (33.6) + copy (84) + CTA (30)
 * plus the 32px gaps comes to 211.6, so the flex box shrinks the only
 * shrinkable item - the heading - to 21px, and `overflow: hidden` then CLIPS
 * it. That is the cut-off title.
 *
 * With the parent's `flex-wrap: wrap` the overflow escaped sideways into a
 * second column instead of shrinking, which is how the CTA ended up on the
 * right - and also how it ended up off the screen entirely once the column
 * grew. So the old layout and the cut title were the same bug wearing two
 * faces: a fixed-height column that its contents do not fit.
 *
 * A two-column GRID states the intended layout directly instead of relying on
 * a column overflowing in the right direction: everything goes in column one,
 * the CTA is placed in column two spanning the rows, and the height is free.
 */
@media (min-width: 768px) {
  body.gns-home .product-slider .swiper-slide {
    /* Centre the band - image and copy together - at the site's measure. */
    padding-inline: max(24px, calc((100% - 1180px) / 2));
    height: auto;
    min-height: 280px;
    display: flex;
    align-items: center;
  }

  body.gns-home .product-slider .swiper-slide .slide-content {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    column-gap: 48px;
    row-gap: 10px;
    /* The 200px cap is what squashed the heading. */
    height: auto;
    width: auto;
    flex: 1 1 auto;
  }
  /* Copy stacks down the first column... */
  body.gns-home .product-slider .swiper-slide .slide-content > * {
    grid-column: 1;
  }
  /* ...and the CTA sits out on the right, centred against the whole block. */
  body.gns-home .product-slider .swiper-slide .slide-content > .buy-now {
    grid-column: 2;
    grid-row: 1 / -1;
    align-self: center;
    justify-self: end;
  }
}

/*
 * The heading is never clipped again, at ANY width - the rules above are
 * gated at 768px, and below it the parent's `height: calc(100% - 80px)` still
 * squeezed the column. Freeing the height here covers the phone layout too,
 * and the slide keeps its 280px as a MINIMUM so the band does not collapse.
 *
 * `overflow: hidden` on a heading only ever hides content; with the height
 * free there is nothing to hide.
 */
body.gns-home .product-slider .swiper-slide {
  height: auto;
  min-height: 280px;
}
body.gns-home .product-slider .swiper-slide .slide-content {
  height: auto;
}
body.gns-home .slide-content h3 {
  overflow: visible;
}

body.gns-home .slide-content img {
  filter: var(--gns-shadow-model);
}
body.gns-home .content-holder h1,
body.gns-home .content-holder h2 {
  font-size: clamp(34px, 4.6vw, 56px);
  line-height: 1.02;
  letter-spacing: -.04em;
}
body.gns-home .content-holder p {
  max-width: 46ch;
  font-size: 15px;
  line-height: 1.65;
  color: var(--gns-body);
  text-wrap: pretty;
}

/* Swiper's arrows are the parent's blue; make them chrome. */
body.gns-home .swiper-button-next,
body.gns-home .swiper-button-prev {
  color: var(--gns-secondary);
  transition: color .15s ease;
}
body.gns-home .swiper-button-next:hover,
body.gns-home .swiper-button-prev:hover { color: var(--gns-cyan-ink); }
body.gns-home .swiper-pagination-bullet {
  background: var(--gns-secondary);
  opacity: .4;
}
body.gns-home .swiper-pagination-bullet-active {
  background: var(--gns-cyan);
  opacity: 1;
}

/* ------------------------------------------------------------ buttons ---- */

/*
 * Standalone CTAs only. `.add-to-cart` and `.cart-button` used to be in this
 * list, and neither is a standalone CTA:
 *
 *   <div class="add-to-cart">          <- a CONTAINER, not a button, 30 of them
 *     <span class="amount">$149</span>
 *     <a class="cart-button"><i class="fa-eye"></i></a>   <- nested INSIDE it
 *   </div>
 *
 * So the gradient painted twice, once on the container and again on the child
 * sitting on top of it, and the eye link inherited the full 48px height and
 * 24px side padding meant for a text button - a 79x48 blob around a 13px icon,
 * with a seam down the middle of the pill where the two gradients met. Both
 * now have their own rules below.
 */
body.gns-home .buy-now,
body.gns-home .button-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 48px;
  padding: 0 24px;
  border: 0;
  border-radius: var(--gns-r-pill);
  background: var(--gns-gradient) !important;
  color: var(--gns-on-accent) !important;
  font-family: var(--gns-font);
  font-size: 14px;
  font-weight: 700;
  text-decoration: none !important;
  transition: box-shadow .15s ease;
}
body.gns-home .buy-now:hover,
body.gns-home .button-link:hover {
  color: var(--gns-on-accent) !important;
  box-shadow: var(--gns-glow-cta);
}

/* ------------------------------------------------- product card footer ---- */

/*
 * The card foot, built the way card.css builds it on every other screen: the
 * price as plain text carrying its own weight, and ONE compact action beside
 * it. A full-width gradient slab under every card turned the accent into the
 * loudest thing on the page and left the price as dark text on a mid-tone
 * gradient; as text on the card ground it is both quieter and easier to read.
 */
body.gns-home .add-to-cart {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  height: auto;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none !important;
  color: var(--gns-text) !important;
  font-family: var(--gns-font);
  font-size: 15px;
  font-weight: 700;
}
body.gns-home .add-to-cart .amount,
body.gns-home .add-to-cart bdi {
  color: var(--gns-text);
}
/* The currency mark is not the number - it recedes. */
body.gns-home .add-to-cart .woocommerce-Price-currencySymbol {
  color: var(--gns-secondary);
  font-weight: 500;
  margin-right: 1px;
}

body.gns-home .cart-button {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--gns-gradient) !important;
  color: var(--gns-on-accent) !important;
  text-decoration: none !important;
  transition: box-shadow .15s ease, transform .15s ease;
}
body.gns-home .cart-button:hover {
  color: var(--gns-on-accent) !important;
  box-shadow: var(--gns-glow-cta);
  transform: translateY(-1px);
}
/* `ml-3` is a Bootstrap left margin on the icon, which off-centres it the
   moment the button becomes a circle. */
body.gns-home .cart-button i {
  margin: 0 !important;
  font-size: 13px;
  line-height: 1;
}

/* A 36px circle is right for the mouse and under the 44px WCAG 2.2 target
   size, so coarse pointers get the bigger one. Gated on the pointer rather
   than on width, so a small laptop window keeps the compact card. */
@media (pointer: coarse) {
  body.gns-home .cart-button {
    width: 44px;
    height: 44px;
  }
}

/* "View all →" style links stay quiet. */
body.gns-home .view-all-arrow,
body.gns-home .title-section .how,
body.gns-home .new-products-content .button {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: none !important;
  border: 0;
  padding: 0;
  height: auto;
  color: var(--gns-cyan-ink) !important;
  font-size: 13px;
  font-weight: 500;
  text-decoration: none !important;
  box-shadow: none !important;
}
body.gns-home .view-all-arrow:hover,
body.gns-home .new-products-content .button:hover { text-decoration: underline !important; }

/* -------------------------------------------------------------- cards ---- */
/*
 * One panel treatment for every card-shaped thing on the page: the four hub
 * cards, printer and filament cards, blog cards and the vendor blocks.
 */
body.gns-home .card,
body.gns-home .info-card,
body.gns-home .printer-card,
body.gns-home .filament-card,
body.gns-home .product-card,
body.gns-home .press-item,
body.gns-home .partner-item {
  background: var(--gns-card) !important;
  border: 1px solid var(--gns-border) !important;
  border-radius: var(--gns-r-card) !important;
  box-shadow: none !important;
  transition: border-color .15s ease, box-shadow .15s ease;
}
body.gns-home .card:hover,
body.gns-home .printer-card:hover,
body.gns-home .filament-card:hover,
body.gns-home .product-card:hover {
  border-color: var(--gns-border-cyan) !important;
  box-shadow: var(--gns-glow-card);
}

body.gns-home .product-title,
body.gns-home .printer-content h3,
body.gns-home .info-card h3 {
  font-family: var(--gns-font);
  font-size: 14px;
  font-weight: 700;
  color: var(--gns-text);
}

body.gns-home .product-image,
body.gns-home .product-card-inner img {
  border-radius: var(--gns-r-chip);
  background: var(--gns-elevated);
}

body.gns-home .info-card-list li {
  color: var(--gns-body);
}
body.gns-home .info-card-list i,
body.gns-home .view-all-arrow i,
body.gns-home .button-link i {
  color: inherit;
}

/* -------------------------------------------------------------- price ---- */

body.gns-home .woocommerce-Price-amount,
body.gns-home .amount {
  font-family: var(--gns-font);
  font-weight: 700;
  color: var(--gns-text);
}
body.gns-home .woocommerce-Price-currencySymbol {
  font-weight: 500;
  color: var(--gns-secondary);
}

/* ----------------------------------------------------------- sections ---- */

body.gns-home .hub-container,
body.gns-home .printer-container,
body.gns-home .filament-container,
body.gns-home .new-products-container,
body.gns-home .creator-section,
body.gns-home .partners-section,
body.gns-home .vendor-section {
  background: none;
  background-color: transparent;
  border-top: 1px solid var(--gns-border-faint);
}
/* The parent pins this one white with !important. */
body.gns-home .partners-section {
  background-color: transparent !important;
}

body.gns-home .title-section {
  font-size: clamp(20px, 2.4vw, 26px);
}

/* Creator strip: image tiles with an overlay caption. */
body.gns-home .creator-box {
  border-radius: var(--gns-r-card);
  overflow: hidden;
  border: 1px solid var(--gns-border);
}
/*
 * The caption sits on the creator's own photo, so it keeps scrim text in both
 * themes - see --gns-on-scrim in tokens.css.
 */
body.gns-home .creator-overlay {
  background: var(--gns-scrim-grad);
}
body.gns-home .creator-overlay .name,
body.gns-home .creator-overlay .count {
  color: var(--gns-on-scrim) !important;
  -webkit-text-fill-color: var(--gns-on-scrim) !important;
}
body.gns-home .creator-box .badge {
  background: var(--gns-gradient) !important;
  color: var(--gns-on-accent) !important;
  border: 0;
  border-radius: var(--gns-r-pill);
  font: 700 10px var(--gns-font-mono);
  letter-spacing: .1em;
  text-transform: uppercase;
}

/*
 * Partner and press logos are supplied as artwork for a light page. On the
 * dark ground they sit on a light chip rather than being inverted, which would
 * wreck any logo that is not monochrome.
 */
body.gns-home .partner-item,
body.gns-home .press-item {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px 18px;
}
body.gns-home .partner-item img,
body.gns-home .press-item img {
  max-width: 100%;
  height: auto;
}

body.gns-home .vendor-image img {
  border-radius: var(--gns-r-card);
  border: 1px solid var(--gns-border);
}

/* ---------------------------------------------------------- responsive --- */

@media (max-width: 767px) {
  body.gns-home .slider-container { background-image: none; }
  body.gns-home .content-holder h1,
  body.gns-home .content-holder h2 { font-size: clamp(28px, 8vw, 38px); }
  body.gns-home .buy-now,
  body.gns-home .button-link { width: 100%; }
}

/* ------------------------------------------------- client-supplied art --- */
/*
 * Two things on this page are artwork authored for a white page, and neither
 * survives a dark ground. Both are handled the way the rest of the redesign
 * handles arbitrary imagery: match the ground, or sit the art on its own chip.
 * Never invert - that wrecks any logo which is not monochrome.
 */

/*
 * The waitlist card fades a crowd photo into white so dark copy can sit on it
 * (`linear-gradient(#fff 35%, transparent)`). Reversed on the dark ground -
 * the light heading landed on white. Fading to the card colour instead works
 * in both themes, because --gns-card flips.
 */
body.gns-home .waiting-card .overlay {
  background-image: linear-gradient(var(--gns-card) 38%, transparent) !important;
}

/*
 * The Kickstarter lockup is a raster PNG with dark ink on transparent, so on
 * the dark card it disappeared. Give it a light chip rather than filtering it.
 */
body.gns-home .promotion-card:not(.waiting-card) img {
  padding: 12px 16px;
  border-radius: var(--gns-r-card);
  background: #FFFFFF;
}

/* --------------------------------------------------------- legibility --- */
/*
 * The parent sets these in black (#000), near-black (#0F0F10) or its mid grey
 * (#7D7D7D), all chosen for a white page. Against the dark ground they measure
 * around 1.1:1 - invisible - and against the LIGHT theme's own ground the grey
 * is 3.81:1, still under AA. Tokenised so both themes are right.
 *
 * Audited rather than guessed: these eight selectors were every failing group
 * on the page (71 elements).
 */
body.gns-home .product-title,
body.gns-home .product-title a,
body.gns-home .creator-name,
body.gns-home .creator-name a {
  color: var(--gns-text) !important;
}
body.gns-home .info-card-list span,
body.gns-home .card p,
body.gns-home .common-sec p,
body.gns-home .description p,
body.gns-home .date p,
/* .pills-tab itself carries the text, not a child - a descendant selector
   alone misses it. */
body.gns-home .pills-tab,
body.gns-home .pills-tab div {
  color: var(--gns-body) !important;
}

/*
 * .printer-content is a translucent dark overlay sitting on a printer photo -
 * rgba(20,25,32,.64) from the parent. Like every other scrim in the redesign
 * it stays dark in BOTH themes, so its text must stay light too; otherwise the
 * light theme paints --gns-body on a dark panel (measured 3.78:1).
 */
body.gns-home .printer-content {
  background: var(--gns-scrim) !important;
}
body.gns-home .printer-content,
body.gns-home .printer-content p,
body.gns-home .printer-content h1,
body.gns-home .printer-content h2,
body.gns-home .printer-content h3 {
  color: var(--gns-on-scrim) !important;
  -webkit-text-fill-color: var(--gns-on-scrim) !important;
}
body.gns-home .date p,
body.gns-home .description p {
  color: var(--gns-secondary) !important;
}

/*
 * "Unlimited copies" is an amber status chip (#9E5600) chosen for a white
 * card - 2.87:1 here. It is a licence/stock signal, not decoration, so it
 * keeps a warm accent rather than becoming plain body text; --gns-magenta-ink
 * is the palette's own "attention" colour and clears AA in both themes.
 */
body.gns-home .meta-copies,
body.gns-home .meta-copies span {
  color: var(--gns-magenta-ink) !important;
}
/*
 * The category pill on blog cards has a WHITE ground from the parent. Forcing
 * only its text to a token was wrong - it fixed the one instance sitting on a
 * tint and broke the one sitting on white. Restyle the chip itself so ground
 * and text move together, in both themes.
 */
body.gns-home .category-pill {
  background: var(--gns-cyan-tint) !important;
  border: 1px solid var(--gns-border-cyan);
  border-radius: var(--gns-r-pill);
  padding: 3px 10px;
}
body.gns-home .category-pill,
body.gns-home .category-pill p {
  color: var(--gns-cyan-ink) !important;
  font-size: 11px;
  margin: 0;
}

/*
 * Product-card meta ("7 parts", the print time) keeps the parent's
 * --wp--preset--color--darkgrey (#7D7D7D), a grey chosen for a white page. It
 * measures 4.12:1 on the light ground - under AA on 24 elements - and the home
 * page does not load card.css, so nothing else was correcting it here.
 */
body.gns-home span.meta-parts,
body.gns-home .product-meta span {
  color: var(--gns-secondary);
}

/*
 * The mobile "View All". The parent emits a SECOND copy of this button inside
 * `p.text-center.only-mobile`, outside the `.title-section` the rule above
 * targets, so below the breakpoint it kept --wp--preset--color--black: black
 * on the dark ground at 1.07:1. Desktop never renders it, which is how it
 * survived the first audit.
 */
body.gns-home .only-mobile .button.how,
body.gns-home .only-mobile a.button.how {
  color: var(--gns-cyan-ink);
}

/*
 * The section slider's nav box carries the parent's fixed
 * --wp--preset--color--lightgrey border, which on the dark ground drew a
 * near-white rectangle around the arrows. --gns-border-strong rather than
 * --gns-border: it outlines a control, not a panel.
 */
body.gns-home .navigation-bar {
  border-color: var(--gns-border-strong);
}

/* ===================================================== info cards (hub) === */
/*
 * The "Find the perfect template" / "Monetize your creations safely" pair.
 *
 * ⚠️ Their wash is an Elementor-style background OVERLAY on a pseudo-element:
 *
 *   .info-card::before { position: absolute; inset: 0;
 *     background-image: linear-gradient(102.04deg, rgba(215,245,255,0) 12.7%, …) }
 *
 * a fixed pastel that does not invert, drawn across the whole card. The card
 * itself is correctly --gns-card and the text correctly --gns-text - the
 * measured colours look right, which is why the contrast probe passed. The
 * overlay is ABSOLUTE and the content is STATIC, so the pastel painted on top
 * of every word rather than behind it, and the copy read as washed out on the
 * dark ground.
 *
 * Same treatment as the Terms band and the G-Coin cards: --gns-band, the
 * parent's pastel on light and the elevated surface on dark.
 *
 * ⚠️ getComputedStyle(el) does not see ::before - pass the pseudo-element as a
 * second argument. Doc 17.
 */
body.gns-home .info-card::before {
  background-image: var(--gns-band);
}

/*
 * ...and put the content above it. An absolutely positioned ::before paints
 * over static siblings whatever its background is, so without this the copy
 * sits under the overlay in BOTH themes.
 */
body.gns-home .info-card > * {
  position: relative;
  z-index: 1;
}



/* ==========================================================================
   PRODUCT CARDS - the same card the shop grid carries
   Design: "Nuova proposta grafica.dc.html" -> the Trending rail card.

   The home page does NOT go through woocommerce/content-product.php. Its cards
   come from four of the parent's template parts -

       template-parts/home-printer.php          "Printers"        (4 cards)
       template-parts/home-new-products.php     "New Products"    (10)
       template-parts/home-trending-offer.php   offers rail       (14)
       template-parts/home-filament.php         "Filaments"

   - each emitting `.product-card > .product-card-inner` directly. So this is a
   restyle, not a second copy of the card: the markup stays the parent's and
   these rules give it the same reading as `.gns-card`.

   ⚠️ There are TWO shapes behind that one class name, and both are handled:

     A  printer / filament: image, title, price - the text nodes are direct
        children of .product-card-inner, with no wrapper to pad.
     B  new products / offers: image, then a `.product-info` wrapper holding
        creator, title, parts/copies and price.

   What a restyle cannot reach, and why it does not matter much here: the
   design's price row puts the euro figure left and the G-Coin figure right,
   while the parent prints both inside ONE span separated by a literal " / ".
   The G-Coin half still takes the design's magenta (see below) - it simply
   keeps its separator instead of being pushed to the other end of the row.
   ========================================================================== */

body.gns-home :is(.product-card, .filament-card) {
  overflow: hidden;
  padding: 0 !important;
}
body.gns-home :is(.product-card, .filament-card) .product-card-inner {
  display: flex;
  flex-direction: column;
  gap: 0;
  height: 100%;
  padding: 0;
  margin: 0;
}

/* ---------------------------------------------------------- media band --- */
/*
 * The 2:1 stage, glow and all - the same numbers card.css uses, so a product
 * does not change shape between the home page and the shop.
 *
 * `border-radius: 0` and the background override are undoing the generic panel
 * treatment further up this file, which gave every `.product-image` a rounded
 * elevated box: inside a card that already has its own rounded corners that
 * read as a second card nested in the first.
 */
body.gns-home :is(.product-card, .filament-card) .product-image {
  position: relative;
  order: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 2 / 1;
  margin: 0;
  padding: 0;
  border-radius: 0 !important;
  background: radial-gradient(closest-side at 50% 70%, rgba(0, 191, 255, .18), transparent) !important;
  overflow: hidden;
}
body.gns-home :is(.product-card, .filament-card) .product-image > a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}
body.gns-home :is(.product-card, .filament-card) .product-image img,
body.gns-home :is(.product-card, .filament-card) .product-card-inner img {
  max-width: 76%;
  max-height: 84%;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: 6px;
  background: none !important;
  filter: var(--gns-shadow-model-sm);
}

/* The sale flash and the favourite toggle ride on the band, not in the flow. */
body.gns-home :is(.product-card, .filament-card) .onsale {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 2;
  margin: 0;
}
body.gns-home :is(.product-card, .filament-card) .add-to-favorites {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 2;
}

/* --------------------------------------------------------------- body ---- */
/*
 * Shape B has a wrapper to pad. Shape A does not, so the two text rows carry
 * their own padding - which is why the horizontal value is repeated rather
 * than set once on a parent.
 */
body.gns-home :is(.product-card, .filament-card) .product-info {
  order: 2;
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 14px 16px 16px;
}
body.gns-home :is(.product-card, .filament-card) .product-card-inner > .product-title {
  order: 2;
  padding: 14px 16px 0;
}
/*
 * ⚠️ The parent pins this row with `position: absolute; bottom: 0` - the same
 * pin shape B carries, described under `.product-info > .add-to-cart` below.
 * Unpinning it matters more here: the printer row stretches all four cards to
 * the height of the "Printers" aside beside them, so with the price out of the
 * flow the image and the title stacked at the top of a 308px card and the price
 * hung at the floor with a 130px void between. `margin-top: auto` keeps it at
 * the floor when a card IS taller than its content, without leaving the flow.
 */
body.gns-home :is(.product-card, .filament-card) .product-card-inner > .add-to-cart {
  order: 3;
  position: static;
  width: auto;
  margin-top: auto;
  padding: 8px 16px 16px;
}

/*
 * ...and the band takes the surplus, so the space closes instead of merely
 * moving. The printer row is the only place on the page where a product card is
 * stretched well past its own content, and the `aspect-ratio` above becomes the
 * floor rather than the whole story: the printer photograph grows into the rest
 * of the card, which is the one image in this chapter worth showing large.
 *
 * ⚠️ Scoped to `.printer-container`. Everywhere else the cards size to their
 * own content and a growing band would have nothing to grow into.
 */
body.gns-home .printer-container .product-card .product-image {
  flex: 1 1 auto;
}

/*
 * Shape B's own order. The parent prints the creator ABOVE the title; the
 * design names the thing first and attributes it second.
 */
body.gns-home :is(.product-card, .filament-card) .product-info > .product-title  { order: 1; }
body.gns-home :is(.product-card, .filament-card) .product-info > .creator-name   { order: 2; }
body.gns-home :is(.product-card, .filament-card) .product-info > .product-meta   { order: 3; }
/*
 * ⚠️ `position: static` is the load-bearing one. The parent pins the price row
 * to `position: absolute; bottom: 0; left: 0` so it hugs the floor of a
 * fixed-height slider card - which means it contributes NO height to the flow,
 * and the parts/copies line ran straight underneath it. Back in the flow, the
 * card sizes to its own content and the swiper wrapper follows, because its
 * slides stretch to the tallest one.
 */
body.gns-home :is(.product-card, .filament-card) .product-info > .add-to-cart {
  order: 4;
  position: static;
  width: auto;
  padding: 4px 0 0;
}

/* --------------------------------------------------------- typography ---- */

body.gns-home :is(.product-card, .filament-card) .product-title {
  margin: 0;
  font-family: var(--gns-font);
  font-size: 13.5px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--gns-text);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
body.gns-home :is(.product-card, .filament-card) .product-title a {
  color: inherit;
  text-decoration: none;
}

/* The attribution line. The avatar shrinks to a mark beside the name rather
   than being a second image on a card that already has one. */
body.gns-home :is(.product-card, .filament-card) .creator-name {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  font-size: 11.5px;
  line-height: 1.3;
  color: var(--gns-secondary-2);
}
body.gns-home :is(.product-card, .filament-card) .creator-name img {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  max-width: 16px;
  max-height: 16px;
  border-radius: 50%;
  object-fit: cover;
  filter: none;
}
body.gns-home :is(.product-card, .filament-card) .creator-name a {
  color: inherit;
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
body.gns-home :is(.product-card, .filament-card) .creator-name a:hover { color: var(--gns-text); }

/* Parts and copies. Mono and small, so the line reads as specification rather
   than as a second title. */
/* One line, clipped rather than wrapped: two short facts that wrapped to a
   second row made the card a line taller than every other card on the site. */
body.gns-home :is(.product-card, .filament-card) .product-meta {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  overflow: hidden;
  gap: 4px 12px;
  margin: 0;
  font: 500 10px var(--gns-font-mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--gns-muted);
}
body.gns-home :is(.product-card, .filament-card) .product-meta img {
  width: 11px;
  height: 11px;
  max-width: 11px;
  max-height: 11px;
  margin-right: 4px;
  opacity: .7;
  filter: invert(1);
}
[data-theme="light"] body.gns-home :is(.product-card, .filament-card) .product-meta img { filter: none; }
body.gns-home :is(.product-card, .filament-card) .meta-parts,
body.gns-home :is(.product-card, .filament-card) .meta-copies {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  min-width: 0;
}
/* The parts count is short and fixed; the copies phrase is the long one, so it
   is the one that gives way - with an ellipsis rather than a hard clip, which
   reads as a bug. */
body.gns-home :is(.product-card, .filament-card) .meta-parts { flex: 0 0 auto; }
body.gns-home :is(.product-card, .filament-card) .meta-copies {
  flex: 0 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  display: block;
}

/* -------------------------------------------------------------- price ---- */

body.gns-home :is(.product-card, .filament-card) .add-to-cart {
  font-size: 12.5px;
}
body.gns-home :is(.product-card, .filament-card) .add-to-cart .woocommerce-Price-amount,
body.gns-home :is(.product-card, .filament-card) .add-to-cart .amount {
  font: 500 12.5px var(--gns-font-mono);
  color: var(--gns-text);
}

/*
 * The G-Coin figure. The parent writes "<euro> / <gcoin>" as two
 * `.woocommerce-Price-amount` siblings inside one span, so the SECOND one is
 * the G-Coin half - and the adjacent-sibling combinator finds it, because that
 * combinator steps over the " / " text node between them.
 *
 * --gns-magenta-ink rather than the brand magenta: this is text, so it takes
 * the alias that clears 4.5:1 in both palettes. Same rule as the shop cards.
 */
body.gns-home :is(.product-card, .filament-card) .add-to-cart .woocommerce-Price-amount + .woocommerce-Price-amount,
body.gns-home :is(.product-card, .filament-card) .add-to-cart .woocommerce-Price-amount + .woocommerce-Price-amount .amount {
  color: var(--gns-magenta-ink);
}

/* The eye link keeps the compact circular treatment set earlier in this file;
   it only wants to stop stretching now that the row is a flex line. */
body.gns-home :is(.product-card, .filament-card) .cart-button { flex: 0 0 auto; }


/* ------------------------------------------------------ filament cards --- */
/*
 * The "Filaments" rail is the same card under a different class name, with one
 * extra box in the middle: home-filament.php wraps the image and the title in a
 * `.flex-div` so they sit SIDE BY SIDE, and hangs the price row off
 * `.product-card-inner` below them -
 *
 *     .filament-card > .product-card-inner
 *         .flex-div                 <- image | title, in a row
 *             .product-image > a > img
 *             .product-title > a
 *         .add-to-cart
 *
 * `display: contents` dissolves that wrapper so the band, the name and the
 * price stack like every other card on the page.
 *
 * ⚠️ The title needs its own rule rather than riding on the shared
 * `.product-card-inner > .product-title` one above. `display: contents` changes
 * how a box is LAID OUT, not where it sits in the tree - the title is still a
 * child of `.flex-div`, so the child combinator never reaches it.
 *
 * ⚠️ NOT extended to `.featured-filament-card`, the wide block beside this
 * rail. That one is a featured printer with a description and a "View All" CTA
 * - an editorial feature, not a product card - and giving it a 2:1 band would
 * mean dropping the two things that make it one.
 */
body.gns-home .filament-card .product-card-inner > .flex-div {
  display: contents;
}
body.gns-home .filament-card .flex-div > .product-title {
  order: 2;
  width: 100%;
  padding: 14px 16px 0;
}
body.gns-home .filament-card .flex-div > .product-image {
  order: 1;
}

/* The price row is already a direct child of .product-card-inner here, so the
   shared `.product-card-inner > .add-to-cart` rule above covers it whole -
   including the unpin, which used to live in a rule of its own here. */


/* ==================================================== partner + press ===== */
/*
 * Third-party logos on a near-black page. These are not our artwork and cannot
 * be redrawn, so the page has to give them a ground they were designed for.
 *
 * Measured, rather than guessed - every file sampled on a canvas for its
 * transparent fraction and the mean luminance of its opaque pixels:
 *
 *   dark ink on transparency        Machina Lonati  76% clear, luminance 11
 *   (invisible on the dark ground)  Il Messaggero   71% clear, luminance 12
 *                                   affaritaliani   62% clear, luminance 45
 *                                   Libero          85% clear, luminance 14
 *
 *   baked-in white background       Il Giorno / La Nazione    0% clear, lum 243
 *   (a white slab on the dark card) Tiscali                   0% clear, lum 230
 *                                   Regione Lombardia         0% clear, lum 210
 *                                   Resto del Carlino        21% clear, lum 206
 *                                   Leggo (red on white)     36% clear, lum 125
 *
 * NOT ONE of them is light-on-transparent, which is what makes the fix below
 * safe: a light plate would erase a white logo, and there isn't one here. That
 * check is the reason for the canvas pass - it is the failure mode that a
 * screenshot does not show you, because such a logo is already invisible.
 *
 * So: one light plate under every logo, and `mix-blend-mode: multiply` on the
 * image. Multiply leaves any pixel darker than the plate alone and collapses
 * anything lighter INTO the plate - so the first group gets a ground it can be
 * read on, and the second group's baked white background merges into that same
 * ground and stops being a slab. Brand colour survives both ways: Leggo stays
 * red, Tiscali stays blue.
 *
 * ⚠️ `isolation: isolate` on the plate is required, not decorative. Without a
 * stacking context of its own the image would multiply against everything
 * painted behind the plate as well - the card, the section, the page - and the
 * dark ground would come back through it.
 *
 * The same plate serves the light theme: there it sits on a white card, so it
 * is invisible, and multiply behaves identically.
 */

body.gns-home .partner-item,
body.gns-home .press-item {
  padding: 0;
  overflow: hidden;
}

body.gns-home .partner-item > a,
body.gns-home .press-item > a {
  isolation: isolate;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  min-height: 96px;
  padding: 20px 26px;
  box-sizing: border-box;
  border-radius: inherit;
  background: #F2F4F7;
  transition: background-color .15s ease;
}
body.gns-home .partner-item > a:hover,
body.gns-home .press-item > a:hover { background: #FFFFFF; }

body.gns-home .partner-item > a:focus-visible,
body.gns-home .press-item > a:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--gns-cyan-tint-2), 0 0 0 1px var(--gns-focus) inset;
}

/* One optical size for logos whose source files run 176-392px wide at a common
   90px height - so they read as a row rather than as ten different scales. */
body.gns-home .partner-item img,
body.gns-home .press-item img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 46px;
  object-fit: contain;
  mix-blend-mode: multiply;
  filter: none;
  background: none !important;
  border-radius: 0;
}

/* The partner row carries two large marks; it can afford a little more. */
body.gns-home .partner-item > a { min-height: 118px; }
body.gns-home .partner-item img { max-height: 62px; }

@media (prefers-reduced-motion: reduce) {
  body.gns-home .partner-item > a,
  body.gns-home .press-item > a { transition: none; }
}


/* ============================================================== hero ===== */
/*
 * "GENESIS" home hero - Turn 3, screen 3a: copy on the left, and on the right a
 * materialisation stage where a dot-matrix file is swept by a gradient beam and
 * arrives as a solid object.
 *
 * Markup: template-parts/genesis-hero.php, rendered in place of the parent's
 * Swiper carousel - see the note in templates/home.php.
 *
 * ⚠️ It renders INSIDE the parent's `.slider-overlay`, because that wrapper
 * also holds the four promo cards below and could not be dissolved without
 * taking them with it. Hence the resets at the end of this section.
 */

.gns-hero {
  position: relative;
  display: grid;
  grid-template-columns: 500px minmax(0, 1fr);
  align-items: stretch;
  min-height: 560px;
  overflow: hidden;
}

/* ---------------------------------------------------------------- copy --- */

.gns-hero__copy {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 24px;
  padding: 48px 24px 48px 36px;
}

/*
 * The staggered entrance the canvas gives this column (`animation: gup .7s`
 * at .1s, .22s, .34s, .46s, .58s). Held to the copy only - a hero that
 * reassembles itself on every visit is charming once and tiresome after.
 */
.gns-hero__eyebrow,
.gns-hero__title,
.gns-hero__lede,
.gns-hero__actions,
.gns-hero__marks {
  animation: gns-up .7s both;
}
.gns-hero__eyebrow { animation-delay: .10s; }
.gns-hero__title   { animation-delay: .22s; }
.gns-hero__lede    { animation-delay: .34s; }
.gns-hero__actions { animation-delay: .46s; }
.gns-hero__marks   { animation-delay: .58s; }

@keyframes gns-up {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: none; }
}

.gns-hero__eyebrow {
  margin: 0;
  font: 500 10.5px var(--gns-font-mono);
  letter-spacing: .16em;
  color: var(--gns-secondary);
}

.gns-hero__title {
  margin: 0;
  font-family: var(--gns-font);
  font-size: 64px;
  line-height: 1;
  letter-spacing: -.04em;
  font-weight: 500;
  color: var(--gns-text);
}
/*
 * ⚠️ The gradient is on a SPAN, not the heading. `background-clip: text` with a
 * transparent fill applies to the whole element it is set on, so putting it on
 * the <h1> would take the first two lines with it - and the design lifts only
 * the third.
 */
.gns-hero__grad {
  background: var(--gns-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.gns-hero__lede {
  margin: 0;
  max-width: 380px;
  font-size: 15.5px;
  line-height: 1.65;
  color: var(--gns-secondary);
  text-wrap: pretty;
}

/* ----------------------------------------------------------- the calls --- */

.gns-hero__actions { display: flex; flex-wrap: wrap; gap: 10px; }

/*
 * The primary call takes the brand gradient, the same as every other primary
 * call on the site - Add to cart, the card buttons, and the four on this page.
 *
 * ⚠️ This DEPARTS from the canvas, deliberately. Turn 3 draws "Explore objects"
 * as a solid light plate (`background:#ECEFF4; color:#0A0C10`) and keeps the
 * gradient for the beam a few hundred pixels away, so the two never run against
 * each other. That restraint is right in a static mockup of one screen; it is
 * wrong here, because a visitor meets this button after having seen the
 * gradient mean "primary action" on every product card and every product page.
 * One treatment for one job beats one screen's internal balance.
 *
 * `--gns-on-accent` is the ink the gradient is designed to carry, and it holds
 * in both themes since the brand colours do not invert.
 */
.gns-hero__cta {
  display: inline-flex;
  align-items: center;
  height: 48px;
  padding: 0 24px;
  /*
   * ⚠️ `border: 0`, never a transparent one. A transparent border still makes
   * the browser paint the gradient out to the BORDER box and then composite the
   * ring on top as a second pass, which leaves a visible seam on the corner arcs
   * - the "pixelated" edge. Every other gradient call in this theme is border: 0
   * for the same reason.
   */
  border: 0;
  border-radius: var(--gns-r-pill);
  background: var(--gns-gradient);
  color: var(--gns-on-accent) !important;
  font-family: var(--gns-font);
  font-size: 14px;
  font-weight: 700;
  text-decoration: none !important;
  transition: transform .15s ease, box-shadow .15s ease;
}
/*
 * ⚠️ `:not(--ghost)`. The ink below belongs to the GRADIENT fill, and the ghost
 * button shares this class - so pinning `--gns-on-accent` on every hover put
 * #06222E on a transparent ground and the secondary call vanished under the
 * cursor. A hover colour has to be scoped to the fill it was chosen against.
 */
.gns-hero__cta:not(.gns-hero__cta--ghost):hover {
  transform: translateY(-1px);
  box-shadow: var(--gns-glow-cta);
  color: var(--gns-on-accent) !important;
}

.gns-hero__cta--ghost {
  padding: 0 22px;
  background: none;
  border-color: var(--gns-border-heavy);
  color: var(--gns-text) !important;
  font-weight: 500;
}
/* The ghost keeps its own ink and gains a faint fill, so the hover is visible
   without borrowing the primary's colours. */
.gns-hero__cta--ghost:hover {
  transform: translateY(-1px);
  border-color: var(--gns-text);
  background: var(--gns-tint-weak);
  color: var(--gns-text) !important;
  box-shadow: none;
}

.gns-hero__cta:focus-visible {
  outline: none;
  border-color: var(--gns-focus);
  box-shadow: 0 0 0 3px var(--gns-cyan-tint-2);
}

/* --------------------------------------------------------- trust marks --- */

.gns-hero__marks {
  display: flex;
  flex-wrap: wrap;
  gap: 26px;
  margin: 0;
  padding: 8px 0 0;
  list-style: none;
}
.gns-hero__marks li {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0;
  font-size: 12px;
  color: var(--gns-secondary);
}
.gns-hero__mark { flex: 0 0 auto; width: 12px; height: 12px; }
.gns-hero__mark--square { border: 1.5px solid var(--gns-cyan); border-radius: 4px; }
.gns-hero__mark--dot { border-radius: 50%; background: linear-gradient(135deg, var(--gns-cyan), var(--gns-magenta)); }

/* --------------------------------------------------------------- stage --- */

.gns-hero__stage {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  overflow: hidden;
}

/* The technical grid, inset from the edges so it reads as a panel the object
   sits in rather than as page furniture. */
.gns-hero__frame {
  position: absolute;
  inset: 24px 36px 24px 0;
  border: 1px solid var(--gns-border-faint);
  border-radius: var(--gns-r-hero);
  background: var(--gns-grid);
  pointer-events: none;
}

.gns-hero__meta {
  position: absolute;
  top: 48px;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  font: 500 10px var(--gns-font-mono);
  letter-spacing: .13em;
  color: var(--gns-muted);
}
.gns-hero__meta--source { left: 24px; }
.gns-hero__meta--node { right: 60px; }
.gns-hero__meta-live { color: var(--gns-cyan-ink); }

/* ------------------------------------------------------ materialisation -- */
/*
 * Three layers over one another: the file as a dot matrix, the object solid,
 * and the beam that turns one into the other. The canvas runs all three on a
 * single 7.5s cycle, so the beam's edge and the reveal's edge are the same
 * moving line.
 */
/*
 * ⚠️ No `aspect-ratio` here on purpose. The solid layer is in FLOW and gives the
 * wrapper its shape; the dot layer and the beam are absolute over it. A fixed
 * ratio letterboxes whichever object does not happen to match it - the car
 * render is 5:3 and the dragon 4:3 - and a letterboxed object is a smaller
 * object for no reason.
 */
.gns-hero__materialise {
  position: relative;
  width: min(600px, 88%);
}
.gns-hero__layer {
  display: block;
  width: 100%;
  height: auto;
}
.gns-hero__layer--dots {
  position: absolute;
  inset: 0;
  height: 100%;
  object-fit: contain;
}
/*
 * ⚠️ The radius applies ONLY in `.is-photo`, which the template sets when the
 * stage is showing a catalogue product rather than the brand render.
 *
 * A cut-out has no rectangle to round, so on the default render this would do
 * nothing but risk clipping a wheel or a tail. A product photograph does have
 * one - opaque, usually white - and an unrounded white slab sliding in behind
 * the beam reads as a rendering fault rather than an object arriving. Rounded,
 * it reads as a plate the object sits on, which is the same concession the
 * product cards make for the same reason.
 */
.gns-hero__materialise.is-photo .gns-hero__layer { border-radius: 14px; }
/*
 * The unbuilt state. The mask punches the picture into a dot grid - the file,
 * before it is anything. A browser without mask support simply shows a faint
 * copy of the object, which is the same idea with less texture.
 */
.gns-hero__layer--dots {
  opacity: .15;
  filter: grayscale(1) brightness(1.9) contrast(1.05);
  -webkit-mask-image: radial-gradient(circle, #000 1.1px, transparent 1.6px);
  mask-image: radial-gradient(circle, #000 1.1px, transparent 1.6px);
  -webkit-mask-size: 7px 7px;
  mask-size: 7px 7px;
}
.gns-hero__layer--solid {
  filter: var(--gns-shadow-model);
  animation: gns-clip 7.5s cubic-bezier(.4, .05, .45, .95) infinite;
}
@keyframes gns-clip {
  0%, 6%    { clip-path: inset(-4% 100% -4% -4%); }
  64%, 100% { clip-path: inset(-4% -4% -4% -4%); }
}

.gns-hero__beam {
  position: absolute;
  top: -6%;
  height: 112%;
  width: 72px;
  margin-left: -36px;
  pointer-events: none;
  animation: gns-beam 7.5s cubic-bezier(.4, .05, .45, .95) infinite;
}
@keyframes gns-beam {
  0%, 6%    { left: -1%; }
  64%, 100% { left: 101%; }
}
.gns-hero__beam-wash,
.gns-hero__beam-edge {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
}
.gns-hero__beam-wash {
  width: 60px;
  margin-left: -30px;
  background: linear-gradient(90deg, transparent, rgba(0, 191, 255, .14), transparent);
}
.gns-hero__beam-edge {
  width: 2px;
  margin-left: -1px;
  background: linear-gradient(180deg, transparent, var(--gns-cyan) 24%, var(--gns-magenta) 76%, transparent);
  box-shadow: 0 0 18px rgba(0, 191, 255, .9), 0 0 40px rgba(255, 110, 255, .5);
}

/* ------------------------------------------------------------- caption --- */

.gns-hero__caption {
  position: absolute;
  left: 24px;
  right: 60px;
  bottom: 44px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.gns-hero__caption-link {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  text-decoration: none !important;
  color: inherit;
}
.gns-hero__chip {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: var(--gns-tint);
  border: 1px solid var(--gns-border-strong);
}
.gns-hero__chip::after {
  content: "";
  width: 14px;
  height: 14px;
  border-radius: 4px;
  background: linear-gradient(135deg, var(--gns-cyan), var(--gns-magenta));
}
.gns-hero__caption-text { min-width: 0; }
.gns-hero__caption-name {
  display: block;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--gns-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gns-hero__caption-meta {
  display: block;
  margin-top: 3px;
  font-size: 11.5px;
  color: var(--gns-secondary);
}
.gns-hero__caption-meta .woocommerce-Price-amount { color: inherit; font-weight: 400; }

.gns-hero__print {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  height: 40px;
  padding: 0 18px;
  border-radius: var(--gns-r-pill);
  background: var(--gns-cyan);
  color: var(--gns-on-accent) !important;
  font-size: 13px;
  font-weight: 700;
  text-decoration: none !important;
}
.gns-hero__print:hover { box-shadow: var(--gns-glow-cta); }

/* ----------------------------------------------------- parent resets ----- */
/*
 * The hero replaces `.product-slider` inside the parent's `.slider-overlay`,
 * which was laid out for a carousel: a fixed height, and padding that assumed
 * Swiper's own arrows sat outside it.
 */
body.gns-home .slider-container,
body.gns-home .slider-overlay {
  height: auto !important;
  min-height: 0 !important;
  padding: 0 !important;
  background: none !important;
}

/* ---------------------------------------------------------- narrow ------- */

@media (max-width: 1100px) {
  .gns-hero {
    grid-template-columns: minmax(0, 1fr);
    min-height: 0;
  }
  .gns-hero__copy { padding: 40px 20px 8px; }
  .gns-hero__title { font-size: 48px; }
  .gns-hero__stage { min-height: 420px; }
  .gns-hero__frame { inset: 12px 20px; }
  .gns-hero__meta--node { right: 28px; }
  .gns-hero__caption { left: 20px; right: 28px; bottom: 24px; }
}

@media (max-width: 620px) {
  .gns-hero__title { font-size: 38px; }
  .gns-hero__stage { min-height: 320px; }
  .gns-hero__meta { display: none; }
  .gns-hero__caption { flex-direction: column; align-items: flex-start; gap: 10px; }
}

/*
 * ⚠️ The materialisation is the one thing on this page that loops forever, so
 * it is also the one that most needs turning off. Reduced motion gets the
 * finished object and no beam - the END of the animation, not the start, or the
 * hero would sit there showing an object that never arrives.
 */
@media (prefers-reduced-motion: reduce) {
  .gns-hero__eyebrow,
  .gns-hero__title,
  .gns-hero__lede,
  .gns-hero__actions,
  .gns-hero__marks { animation: none; }
  .gns-hero__layer--solid { animation: none; clip-path: none; }
  .gns-hero__beam { display: none; }
  .gns-hero__cta { transition: none; }
}


/* ==========================================================================
   EDITORIAL CHAPTERS
   The chosen direction for the Explore page: the page reads as a sequence -
   what you can print, how it reaches you, who made it - with a centred hero
   stating the thesis and a full-bleed band between the first two chapters.

   Everything below is treatment. No section was deleted and no client copy was
   rewritten; templates/home.php only reordered the parts and wrapped them in
   chapters. What this file does is give the whole page one rhythm, one section
   header and one button hierarchy, which is what the hero was missing.

   ⚠️ It is APPENDED, so it deliberately overrides the generic panel treatment
   earlier in this file. Read this section as the later word on anything the two
   disagree about.
   ========================================================================== */

body.gns-home {
  /* One measure for the whole page. Every chapter, band and closing block
     aligns to it, which is most of what "one feel" turns out to mean. */
  --measure: 1180px;
  --gutter: 36px;
  --chapter-gap: 96px;
}

/* ------------------------------------------------------------- the hero -- */
/*
 * Centred, not split. The two-column hero read as a slide; on a page that now
 * opens an argument, the thesis belongs on the centre line with the object
 * beneath it, so the eye goes copy -> object -> chapter one rather than
 * bouncing left to right.
 */
body.gns-home .gns-hero {
  display: block;
  min-height: 0;
  padding: 72px var(--gutter) 0;
  text-align: center;
  background: var(--gns-grid);
}
body.gns-home .gns-hero__copy {
  align-items: center;
  gap: 20px;
  max-width: 760px;
  margin: 0 auto;
  padding: 0;
}
body.gns-home .gns-hero__title {
  font-size: clamp(40px, 6.2vw, 68px);
  line-height: .98;
  letter-spacing: -.045em;
}
body.gns-home .gns-hero__lede {
  max-width: 46ch;
  font-size: 16px;
}
body.gns-home .gns-hero__actions,
body.gns-home .gns-hero__marks { justify-content: center; }
body.gns-home .gns-hero__marks { gap: 22px; }

/*
 * The stage loses its panel. A framed box beside the copy made sense as a
 * viewport; under a centred headline it becomes a second card on a page that is
 * trying to stop being made of cards. The grid already runs behind the whole
 * hero, so the frame has nothing left to say.
 */
body.gns-home .gns-hero__stage {
  min-height: 0;
  padding: 8px 0 64px;
}
body.gns-home .gns-hero__frame { display: none; }
body.gns-home .gns-hero__materialise { width: min(620px, 76%); }

/* The stream labels sit on the page's measure, not the stage's corners. */
body.gns-home .gns-hero__meta {
  top: auto;
  bottom: 18px;
  align-items: flex-start;
  text-align: left;
}
body.gns-home .gns-hero__meta--source { left: max(var(--gutter), calc(50% - var(--measure) / 2)); }
body.gns-home .gns-hero__meta--node {
  right: max(var(--gutter), calc(50% - var(--measure) / 2));
  text-align: right;
}

/* ---------------------------------------------------------- the chapter -- */

.gns-chap {
  max-width: var(--measure);
  margin: 0 auto;
  padding: var(--chapter-gap) var(--gutter) 0;
}

/*
 * ⚠️ THE NUMERALS CAME OUT, exactly as the note that stood here said they
 * should if the sections turned out to have no order. They did not: the
 * catalogue, the machines and the makers are three categories, and no reading
 * of the third makes it the third step of anything. The numerals moved to
 * .gns-process, which is a sequence, and each chapter takes a category eyebrow
 * instead - see genesys_redesign_chapter_open() in functions.php.
 */
.gns-chap__head {
  display: block;
  padding-bottom: 34px;
}
/*
 * The eyebrow carries a short gradient tick. It is the page's one repeated
 * mark - the hero's beam, cut to 22px - and it appears once per section
 * opener and nowhere else, which is what stops it becoming wallpaper.
 */
.gns-chap__eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 14px;
  font: 500 10.5px/1 var(--gns-font-mono);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--gns-muted);
}
.gns-chap__eyebrow::before {
  content: '';
  flex: none;
  width: 22px;
  height: 2px;
  border-radius: 2px;
  background: var(--gns-gradient);
}
.gns-chap__title {
  margin: 0;
  font-family: var(--gns-font);
  font-size: clamp(24px, 3vw, 33px);
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -.03em;
  color: var(--gns-text);
  text-wrap: balance;
}
.gns-chap__lead {
  margin: 10px 0 0;
  max-width: 52ch;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--gns-secondary);
}
.gns-chap__body { display: flex; flex-direction: column; gap: 40px; }

/*
 * The parts inside a chapter give up their own containers. Each arrived with
 * its own width, padding and background, which is what made four rails read as
 * four unrelated pages.
 */
.gns-chap__body > *,
.gns-chap__body .new-products-container,
.gns-chap__body .printer-container,
.gns-chap__body .filament-container,
.gns-chap__body .creator-container {
  width: auto;
  max-width: none;
  margin: 0;
  padding: 0;
  background: none;
}

/*
 * One section header for the whole page. The parts brought three different
 * ones - a heading inside a card, a bare arrow, and a "View all" - so they are
 * demoted to a single mono label with the link as text. The chapter title above
 * is the heading now; these name the shelf under it.
 */
.gns-chap__body .title-section,
.gns-chap__body .filament-products-list > h3,
.gns-chap__body .new-products-content > .title-section {
  display: flex;
  align-items: baseline;
  gap: 14px;
  margin: 0 0 16px;
  padding: 0 0 12px;
  border-bottom: 1px solid var(--gns-border-faint);
}
.gns-chap__body .title-section h3,
.gns-chap__body .filament-products-list > h3 {
  margin: 0;
  font: 500 10.5px/1 var(--gns-font-mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--gns-muted);
}
.gns-chap__body .title-section .button,
.gns-chap__body .view-all-arrow {
  margin-left: auto;
  height: auto;
  padding: 0;
  border: 0;
  background: none !important;
  color: var(--gns-secondary) !important;
  font-size: 12px;
  font-weight: 500;
}
.gns-chap__body .title-section .button:hover,
.gns-chap__body .view-all-arrow:hover { color: var(--gns-text) !important; }

/*
 * The printer block's text panel. It is real client copy, so it stays - but as
 * an aside beside the products rather than a card competing with them.
 */
.gns-chap__body .printer-card {
  background: none !important;
  border: 0 !important;
  border-left: 1px solid var(--gns-border) !important;
  border-radius: 0 !important;
  padding: 0 0 0 22px !important;
}
.gns-chap__body .printer-content h3 {
  font: 500 10.5px/1 var(--gns-font-mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--gns-muted);
}
.gns-chap__body .printer-content p {
  margin-top: 10px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--gns-body);
}

/* ------------------------------------------------------ from file to object */
/*
 * template-parts/home-process.php - the page's argument, between the shelves
 * under the hero and the catalogue.
 *
 * ⚠️ It is deliberately NOT a band. The hub further down is already a
 * full-bleed panel with a cyan glow, and a second one here would give the page
 * two identical set pieces and no hierarchy between them. This section sits on
 * the page ground on the same measure as the chapters; everything it has comes
 * from the numerals, the type and one line.
 *
 * That line is the whole idea. The hero materialises an object under a
 * gradient beam; this is the same beam laid flat, running left to right
 * through the three steps, so the sequence reads as one movement rather than
 * as three cards. It is drawn on the <ol>, behind the numerals.
 */

.gns-process {
  max-width: var(--measure);
  margin: 0 auto;
  padding: var(--chapter-gap) var(--gutter) 0;
}

.gns-process__head { margin-bottom: 40px; }

/*
 * (0,2,0): the eyebrow is a <p>, and `body.gns-home p` further up this file
 * sets the body colour at (0,1,1). One class more is enough to be heard.
 */
body.gns-home .gns-process__eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 14px;
  font: 500 10.5px/1 var(--gns-font-mono);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--gns-muted);
}
.gns-process__eyebrow::before {
  content: '';
  flex: none;
  width: 22px;
  height: 2px;
  border-radius: 2px;
  background: var(--gns-gradient);
}

.gns-process__title {
  margin: 0;
  font-family: var(--gns-font);
  font-size: clamp(28px, 4vw, 44px);
  font-weight: 500;
  line-height: 1.05;
  letter-spacing: -.035em;
  color: var(--gns-text);
}

/* ------------------------------------------------------------- the steps -- */

.gns-process__steps {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0 34px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.gns-process__step {
  position: relative;
  padding-top: 46px;          /* clears the beam */
}

/*
 * The beam, drawn one SEGMENT per step: from this step's node to the next
 * one's, and never after the last.
 *
 * ⚠️ Drawn per step rather than as one line across the row, because a single
 * line has no way to know where the last node is. Spanning the whole row and
 * fading out would run the sequence past its own end - the reader would see a
 * fourth step coming that does not exist - and the arithmetic that would stop
 * it exactly (`right: calc((100% - 86px) / 3)`) hard-codes the column count
 * and the gap, so it breaks silently the day either changes. A segment is
 * measured by the step it belongs to, and stays correct.
 *
 * `100%` is the step's own width; `+ 16px` carries it across the 34px gap to
 * the next node, less the 18px it starts past this one.
 */
.gns-process__step::after {
  content: '';
  position: absolute;
  top: 13px;
  left: 18px;
  width: calc(100% + 16px);
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--gns-cyan), var(--gns-magenta));
  opacity: .45;
}

.gns-process__step:last-child::after { content: none; }

/*
 * The node on the beam. The numeral sits under it, so the eye reads
 * line -> node -> number -> step, in that order.
 */
/*
 * `--gns-cyan-ink`, not `--gns-cyan`: brand cyan measures 1.96:1 against the
 * light ground, so on the light theme a 2px ring in it all but disappears.
 * The ink alias resolves to the brand colour on dark and to a darker blue on
 * light - see tokens.css. The glow behind it stays raw brand, because a glow
 * that vanishes on light is a glow doing its job.
 */
.gns-process__step::before {
  content: '';
  position: absolute;
  top: 8px;
  left: 0;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--gns-bg);
  border: 2px solid var(--gns-cyan-ink);
  box-shadow: 0 0 0 4px var(--gns-bg), 0 0 14px rgba(0, 191, 255, .45);
}

.gns-process__step:last-child::before {
  border-color: var(--gns-magenta-ink);
  box-shadow: 0 0 0 4px var(--gns-bg), 0 0 14px rgba(255, 110, 255, .45);
}

.gns-process__num {
  display: block;
  font: 500 13px/1 var(--gns-font-mono);
  letter-spacing: .16em;
  color: var(--gns-cyan-ink);
}

.gns-process__label {
  display: block;
  margin-top: 8px;
  font: 500 10px/1 var(--gns-font-mono);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--gns-muted);
}

.gns-process__step-title {
  margin: 14px 0 0;
  font-family: var(--gns-font);
  font-size: clamp(17px, 1.6vw, 20px);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -.02em;
  color: var(--gns-text);
  text-wrap: balance;
}

.gns-process__text {
  margin: 9px 0 0;
  max-width: 38ch;
  font-size: 14px;
  line-height: 1.65;
  color: var(--gns-secondary);
}

.gns-process__link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 14px;
  font: 500 13px/1 var(--gns-font);
  color: var(--gns-cyan-ink) !important;   /* answers the parent's `a { color: black }` */
  text-decoration: none !important;
}
.gns-process__link:hover { color: var(--gns-text) !important; }
.gns-process__link span { transition: transform .18s var(--gns-ease-slice); }
.gns-process__link:hover span { transform: translateX(3px); }

/* ------------------------------------------------------------ the band --- */
/*
 * home-hub, between chapters one and two. Same ACF copy the client wrote, same
 * two calls; what changes is that it stops being two bright cards floating on
 * the page and becomes the full-bleed moment that separates "what you can
 * print" from "what prints it".
 */
body.gns-home .hub-container {
  max-width: none;
  margin: var(--chapter-gap) 0 0;
  padding: 76px var(--gutter);
  border-top: 1px solid var(--gns-border-faint);
  border-bottom: 1px solid var(--gns-border-faint);
  background:
    radial-gradient(900px 300px at 50% 50%, rgba(0, 191, 255, .09), transparent 72%),
    var(--gns-grid);
  text-align: center;
}
body.gns-home .hub-container > .flex-div:first-child {
  max-width: 40ch;
  margin: 0 auto 44px;
  text-align: center;
}
body.gns-home .hub-container .hub-title {
  font-size: clamp(23px, 3vw, 31px);
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -.03em;
  text-wrap: balance;
}
/*
 * The standfirst. It was marked up as an <h2> under an <h1> - see the header of
 * template-parts/home-hub.php for why both changed - and now reads as what it
 * is: a line of copy, one step down from the title.
 */
body.gns-home .hub-container .hub-desc {
  margin: 12px 0 0;
  font-size: 15px;
  line-height: 1.6;
  color: var(--gns-body);
  text-wrap: balance;
}
body.gns-home .hub-container > .flex-div:last-child {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
  max-width: var(--measure);
  margin: 0 auto;
  text-align: left;
}
body.gns-home .hub-container .info-card {
  width: auto;
  max-width: none;
  margin: 0;
  background: var(--gns-tint-weak) !important;
  border: 1px solid var(--gns-border) !important;
  border-radius: var(--gns-r-panel) !important;
  padding: 26px !important;
}

/* --------------------------------------------------------- the closing --- */

.gns-closing {
  max-width: var(--measure);
  margin: var(--chapter-gap) auto 0;
  padding: 0 var(--gutter);
}
.gns-closing__cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
}
body.gns-home .gns-closing .promotion-card {
  width: auto;
  max-width: none;
  margin: 0;
  padding: 28px;
  border-radius: var(--gns-r-panel) !important;
}
body.gns-home .gns-closing .promotion-card h2 {
  font-size: 20px;
  font-weight: 500;
  letter-spacing: -.02em;
}
body.gns-home .gns-closing .promotion-card p {
  margin-top: 8px;
  font-size: 13px;
  color: var(--gns-body);
}

/* ------------------------------------------------- one button hierarchy -- */
/*
 * The page had five button styles competing: a gradient pill, a cyan pill, a
 * white pill, a ghost outline and a text-and-arrow. It now has three, and the
 * gradient is the primary one.
 *
 * ⚠️ An earlier pass here spent the gradient ONCE and made everything else an
 * outline, on the argument that the canvas keeps it rare. That was wrong for
 * THIS site: the gradient is already the primary call everywhere else in the
 * product - Add to cart on the product page, the cart button on every card -
 * so a home page whose calls were all outlines read as the odd one out rather
 * than as restraint. Consistency with the rest of the site beats a rule the
 * rest of the site does not follow.
 *
 *   primary    gradient pill, dark ink        - every call on this page
 *   secondary  ghost outline                  - "Watch the process" in the hero
 *   tertiary   text and arrow                 - "View all" on each shelf
 */
body.gns-home .buy-now,
body.gns-home .button-link {
  height: 44px;
  padding: 0 22px;
  /* border: 0 for the corner-seam reason noted on .gns-hero__cta above. */
  border: 0 !important;
  border-radius: var(--gns-r-pill);
  background: var(--gns-gradient) !important;
  color: var(--gns-on-accent) !important;
  font-size: 13.5px;
  font-weight: 700;
  box-shadow: none;
  transition: box-shadow .15s ease, transform .15s ease;
}
body.gns-home .buy-now:hover,
body.gns-home .button-link:hover {
  background: var(--gns-gradient) !important;
  color: var(--gns-on-accent) !important;
  transform: translateY(-1px);
  box-shadow: var(--gns-glow-cta);
}
body.gns-home .buy-now:focus-visible,
body.gns-home .button-link:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--gns-cyan-tint-2), 0 0 0 1px var(--gns-focus);
}

/* --------------------------------------------------- closing sections ---- */
/*
 * Partners, press and the blog are supporting matter, not chapters. They keep
 * the measure and the mono label but take no numeral - numbering them would
 * claim they are part of the argument, which they are not.
 */
body.gns-home .partners-container,
body.gns-home .press-container,
body.gns-home .blog-container,
body.gns-home .vendor-container {
  max-width: var(--measure);
  margin: var(--chapter-gap) auto 0;
  padding: 0 var(--gutter);
}
body.gns-home .partners-container h2,
body.gns-home .press-container h2,
body.gns-home .blog-container h2,
body.gns-home .blog-container h3 {
  font: 500 10.5px/1 var(--gns-font-mono) !important;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--gns-muted) !important;
  background: none !important;
  -webkit-text-fill-color: currentColor;
  text-align: left;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--gns-border-faint);
  margin-bottom: 20px;
}

body.gns-home .vendor-container { padding-bottom: var(--chapter-gap); }

/* ------------------------------------------------------------- narrow ---- */

@media (max-width: 900px) {
  body.gns-home {
    --gutter: 20px;
    --chapter-gap: 60px;
  }
  body.gns-home .gns-hero { padding-top: 44px; }
  .gns-chap__head {
    grid-template-columns: minmax(0, 1fr);
    gap: 10px;
  }
  .gns-chap__num { font-size: 30px; }
  body.gns-home .hub-container { padding: 52px var(--gutter); }
  body.gns-home .gns-hero__meta { display: none; }
}

/* ------------------------------------------------- alignment corrections -- */
/*
 * Measured against the rendered page rather than guessed: the chapters, the
 * closing block and the blog all land on the 1180px measure, and these four did
 * not. Two of them were the wrong class name on my part - the markup says
 * `.partners-section` and `.vendor-section`, not `-container`.
 */

/*
 * The collections shelf under the hero. It was a full-bleed flex row holding
 * two 304px cards hard against the left edge, because it was built for four -
 * the Kickstarter and waitlist cards that now close the page. Two columns on
 * the measure is what it actually contains.
 */
body.gns-home .overalls-container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 20px;
  width: auto;
  max-width: var(--measure);
  margin: 40px auto 0;
  padding: 0 var(--gutter);
}
/*
 * ⚠️ THE PANELS CAME OFF.
 *
 * These two shelves sat in bordered, rounded cards on the elevated surface,
 * while every other shelf on the page - four of them, in the chapters below -
 * sits open on the page ground under a mono label and a hairline. Two
 * treatments for the same object, and the boxed one came FIRST, so the page
 * introduced its shelves with the exception and then never used it again.
 *
 * They now take the chapter shelves' header exactly: same 10.5px mono label,
 * same hairline, same rules underneath. The top of the page stops being a
 * different design from the rest of it.
 */
body.gns-home .overalls-container > .card {
  width: auto;
  max-width: none;
  margin: 0;
  padding: 0;
  background: none !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
}
body.gns-home .overalls-container > .card > h3 {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--gns-border-faint);
  font: 500 10.5px/1 var(--gns-font-mono);
  letter-spacing: .16em;
  text-transform: uppercase;
}
body.gns-home .overalls-container > .card > h3 img { width: 14px; height: 14px; }
body.gns-home .overalls-container > .card > h3 .home-card-title {
  color: var(--gns-muted) !important;
  font: inherit;
  text-decoration: none !important;
}
body.gns-home .overalls-container > .card > h3 .home-card-title:hover { color: var(--gns-text) !important; }

/* Partners and press: the real wrapper is .partners-section > .container. */
body.gns-home .partners-section > .container {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 var(--gutter);
}
body.gns-home .partners-section {
  margin-top: var(--chapter-gap);
  padding: 0;
}

/*
 * The vendor band stays full-bleed - it is an image beside a call, and it is
 * the last thing on the page, so bleeding is the point. Only its content
 * column comes back to the measure.
 */
body.gns-home .vendor-section { margin-top: var(--chapter-gap); }
body.gns-home .vendor-section .vendor-content-section { padding: 0 var(--gutter); }

/* The band should reach both edges; the parent leaves it 25px short each side. */
body.gns-home .hub-container { width: 100%; margin-left: 0; margin-right: 0; }

/*
 * The vendor call needs no special case now that the gradient is the page's
 * primary treatment - it takes the same rule as every other call. The block
 * that used to single it out has gone with the hierarchy it belonged to.
 */

/*
 * ⚠️ The band's two cards carry `width: 280px` and `max-width: calc(50% - 10px)`
 * from the parent's float-era grid. The grid track above is 580px wide and they
 * sat at 280 inside it, wrapping the headings two words to a line. `!important`
 * here answers the parent's own, which is why the earlier `width: auto` lost.
 */
body.gns-home .hub-container .info-card {
  width: auto !important;
  max-width: none !important;
  flex: 0 1 auto !important;
}

/*
 * The partner and press headings. Same correction as the container above -
 * the wrapper is `.partners-section`, so the label rule was pointing at
 * nothing and these two kept the old centred gradient-text treatment, which is
 * the last place on the page where a heading disagreed with every other one.
 */
body.gns-home .partners-section h2,
body.gns-home .partners-section h3 {
  font: 500 10.5px/1 var(--gns-font-mono) !important;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--gns-muted) !important;
  background: none !important;
  -webkit-text-fill-color: currentColor;
  text-align: left;
  margin: 0 0 20px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--gns-border-faint);
}
body.gns-home .partners-section .press-block { margin-top: var(--chapter-gap); }

/* ------------------------------------------------------ two corrections -- */
/*
 * 1. THE BAND WAS NOT CENTRED ABOVE 1440px.
 *
 * `.hub-container` carries `max-width: 1440px` from the parent, and the
 * full-bleed rule above set its side margins to 0 - which is only harmless
 * while the viewport is narrower than that cap. On a 1900px screen the band
 * clamped to 1440 and pinned LEFT, so its headline and cards sat 223px left of
 * the page centre while every chapter around them was centred. Measured, not
 * guessed: chapters centre at 943, the band's content centred at 720.
 *
 * ⚠️ This is the failure mode of testing one width. At 1280 the cap never
 * engages and a left-pinned container is indistinguishable from a centred one.
 */
body.gns-home .hub-container {
  max-width: none !important;
  margin-inline: auto;
}

/*
 * 2. THE CLOSING BUTTONS STRETCHED TO THE FULL CARD WIDTH.
 *
 * The parent leaves `.buy-now` and `.button-link` as block-level flex items, so
 * inside a flex column with the default `align-items: stretch` they grew to
 * fill it - 486px in the closing cards and 249px at 60px tall in the band,
 * against the 186px pill the vendor call renders as. Same paint, wrong shape,
 * which is exactly how a button stops looking like the others.
 *
 * `align-self` is the operative one: `width: auto` alone does not stop a
 * stretched flex item from filling its cross axis.
 */
body.gns-home .buy-now,
body.gns-home .button-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: auto;
  min-width: 0;
  align-self: flex-start;
  flex: 0 0 auto;
  height: 44px;
  text-align: center;
}
/* The band's two cards centre their contents, so their calls centre with them. */
body.gns-home .hub-container .info-card .buy-now { align-self: center; }

body.gns-home .buy-now i,
body.gns-home .button-link i { font-size: 12px; }

/*
 * The cards these sit in: content top-aligned, the call at the bottom on its
 * own line, so the two closing panels agree with each other whatever length
 * their copy runs to.
 */
body.gns-home .gns-closing .promotion-card,
body.gns-home .gns-closing .promotion-card .content {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
}
body.gns-home .gns-closing .promotion-card .button-link { margin-top: auto; }
body.gns-home .gns-closing .waiting-card .content { width: 100%; }

/*
 * The band's two calls resolved to 60px against the 44px every other button on
 * the page now uses.
 *
 * ⚠️ `!important` because the parent's is: `.info-card-content .buy-now` sets
 * `height: 60px !important` along with a 20px font. No amount of specificity
 * beats that - only another !important does. Found by listing the rules that
 * actually matched the element rather than by guessing at the selector.
 */
body.gns-home .hub-container .info-card .buy-now {
  height: 44px !important;
  padding: 0 22px !important;
  font-size: 13.5px !important;
  font-weight: 500 !important;
  line-height: 42px !important;
}

/*
 * ⚠️ Regression from the flex-column rule above. The Kickstarter logo had been
 * sized by the card stretching it; `align-items: flex-start` handed it back its
 * intrinsic width and it blew straight through the card. A flex item stops
 * being stretched the moment you stop stretching it, and anything that was
 * relying on that needs its own size.
 */
body.gns-home .gns-closing .promotion-card img {
  width: auto;
  max-width: 100%;
  max-height: 46px;
  height: auto;
  align-self: flex-start;
}

/* The waitlist card centred its heading while its neighbour left-aligned - the
   last disagreement between the two closing panels. */
body.gns-home .gns-closing .waiting-card,
body.gns-home .gns-closing .waiting-card .content,
body.gns-home .gns-closing .waiting-card .common-sec,
body.gns-home .gns-closing .waiting-card h2,
body.gns-home .gns-closing .waiting-card p { text-align: left; }
body.gns-home .gns-closing .waiting-card .overlay { display: none; }


/* ==========================================================================
   EXPLORE REVIEW - the five findings, implemented
   --------------------------------------------------------------------------
   Appended last on purpose: home.css is written "the later word wins", and
   several of these answer rules stated earlier in this same file. Each block
   names the finding it closes and what was measured on the live page.
   ========================================================================== */

/* --------------------------------------------------- 05 - clipped cards --- */
/*
 * Measured: `.product-title` reported scrollWidth 181 in a 172px box, and
 * `.meta-copies` 138 in 80 - so "Unlimited copies" rendered as six characters
 * and an ellipsis on EVERY card in every rail.
 *
 * ⚠️ The two-line clamp was already written further up this file and was never
 * in effect. The parent sets `.product-title { white-space: nowrap }` at
 * (0,1,0); the child rule raised specificity but never restated `white-space`,
 * so `-webkit-box` had nothing to wrap. Naming it here is the whole fix.
 */
body.gns-home :is(.product-card, .filament-card) .product-title,
body.gns-home :is(.product-card, .filament-card) .product-title a {
  white-space: normal;
}
/*
 * The clamp stays on `.product-title` itself. It was already written that way
 * further up this file and was never the problem - `white-space` was.
 *
 * ⚠️ Do not "fix" this by moving the clamp onto the <a> inside. The clamped box
 * is block-level, so the template's newlines either side of the link become
 * their own line boxes and the wrapper grows a third line that nothing clips.
 *
 * ⚠️ And do not read `getComputedStyle().display === "flow-root"` here as the
 * clamp having failed. Chrome 140+ reports a clamped `-webkit-box` that way;
 * it is what an ACTIVE clamp looks like now, not a blockified one.
 */
body.gns-home :is(.product-card, .filament-card) .product-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  /* Two lines of 13.5px/1.3 - reserved so a one-line name and a two-line name
     put their price rows on the same baseline across a shelf. */
  min-height: calc(2 * 1.3 * 13.5px);
}

/*
 * The copies figure goes. It is "Unlimited" on essentially the whole
 * catalogue, so it was spending the card's one meta line to say nothing - and
 * it was the half that got clipped. Parts count stays: that one varies, and it
 * tells a printer something real.
 */
body.gns-home :is(.product-card, .filament-card) .meta-copies { display: none; }
body.gns-home :is(.product-card, .filament-card) .product-meta { min-height: 0; }

/* ------------------------------------------------ 02 - one gradient ------- */
/*
 * Seven calls to action, four of them wearing the same gradient pill:
 * Explore objects, Watch the process, Sign up, Start selling, Back us now,
 * Sign up here, Become a vendor.
 *
 * The rule now: the gradient marks the page's primary call, and no two are
 * ever in the same viewport. It stays on "Explore objects" at the top and
 * "Become a vendor" at the bottom - the two ends of what this page is for.
 * Everything between steps down to the ghost outline that already exists.
 */
body.gns-home .hub-container .info-card .buy-now,
body.gns-home .gns-closing .promotion-card .button-link {
  background: transparent !important;
  border: 1px solid var(--gns-border-strong) !important;
  color: var(--gns-text) !important;
  box-shadow: none;
}
body.gns-home .hub-container .info-card .buy-now:hover,
body.gns-home .gns-closing .promotion-card .button-link:hover {
  background: transparent !important;
  border-color: var(--gns-cyan) !important;
  color: var(--gns-text) !important;
  box-shadow: none;
}

/*
 * The hero's second call becomes text and an arrow - the page's third button
 * level, the same one every "View all" already uses. An outline beside a
 * gradient still reads as a choice between two things; a text link reads as
 * the aside it is.
 */
body.gns-home .gns-hero__cta--ghost {
  height: auto;
  padding: 0 2px;
  border: 0;
  background: none;
  color: var(--gns-secondary) !important;
  font-weight: 500;
}
body.gns-home .gns-hero__cta--ghost::after {
  content: " →";
  color: inherit;
}
body.gns-home .gns-hero__cta--ghost:hover {
  background: none;
  border: 0;
  color: var(--gns-text) !important;
}

/* ------------------------------------------- 03 - the render behind copy -- */
/*
 * Measured: the hero ran 1278px on a 900px viewport, because the copy and the
 * object were stacked in two bands - 1.4 screens before the first product with
 * a name and a price on it.
 *
 * The object moves BEHIND the copy instead of below it. The band now sizes to
 * the text, and the render fills the space that text does not use, which is
 * the right half of a 1180px measure.
 *
 * ⚠️ Supersedes the centred treatment above it. The centre line was right when
 * the object had a band of its own; sharing one band, centred copy over a
 * centred render is unreadable, so the copy comes back to the left rail.
 */
body.gns-home .gns-hero {
  position: relative;
  max-width: var(--measure);
  margin: 0 auto;
  padding: 78px var(--gutter) 72px;
  overflow: hidden;
  text-align: left;
  background: var(--gns-grid);
}
body.gns-home .gns-hero__copy {
  position: relative;
  z-index: 2;
  align-items: flex-start;
  max-width: 34rem;
  margin: 0;
}
body.gns-home .gns-hero__actions,
body.gns-home .gns-hero__marks { justify-content: flex-start; }
body.gns-home .gns-hero__lede { max-width: 40ch; }

body.gns-home .gns-hero__stage {
  position: absolute;
  z-index: 0;
  top: 0;
  right: 0;
  bottom: 0;
  left: auto;
  width: min(56%, 660px);
  min-height: 0;
  padding: 0;
  pointer-events: none;
}
body.gns-home .gns-hero__materialise {
  width: 100%;
  max-height: 100%;
}
/*
 * The render is the ground, so it yields to the words: it fades out towards
 * the copy rather than being cropped at a hard edge, and the mask does that
 * without a second gradient overlay that would also dim the page grid.
 */
body.gns-home .gns-hero__stage {
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 34%, #000 100%);
          mask-image: linear-gradient(90deg, transparent 0%, #000 34%, #000 100%);
}

/*
 * The stream labels become captions on the render, which is what they always
 * described. They were positioned against the page measure while the stage had
 * its own band; the stage is now the right half, so they take its edges.
 */
body.gns-home .gns-hero__meta {
  top: auto;
  bottom: 14px;
}
body.gns-home .gns-hero__meta--source { left: 4px; }
body.gns-home .gns-hero__meta--node { right: 4px; }

/* ------------------------------------------------- 04 - the two shelves --- */
/*
 * templates/home.php now prints the parent's own card shape in these two
 * shelves instead of a bare <img>, so nearly everything they need is already
 * inherited from the card rules further up this file. What is left is the
 * shelf's own grid, and undoing the panel-inside-a-panel the wrapper made.
 */
/*
 * ⚠️ Two across, not four. Each shelf sits in half of a 1180px measure, so
 * four cards in it measured 116px wide - narrower than the product names they
 * now carry, which is the problem this finding started with. Two across gives
 * ~239px, wider than the 172px cards in the chapter rails.
 */
body.gns-home .overalls-container .recommended-products {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  width: auto;
  margin: 0;
  padding: 0;
}
body.gns-home .overalls-container .recommended-products > .product-card {
  width: auto;
  min-width: 0;
  margin: 0;
}
body.gns-home .overalls-container .product-card .product-image { aspect-ratio: 3 / 2; }
body.gns-home .overalls-container .product-card .product-title { padding: 12px 12px 0; }
body.gns-home .overalls-container .product-card .add-to-cart { padding: 6px 12px 12px; }
/* Free is the price here, so it is set as one - not as a muted footnote. */
body.gns-home .gns-free {
  font: 500 12px var(--gns-font-mono);
  letter-spacing: .04em;
  color: var(--gns-text);
}

/* ------------------------------------------------------- 01 - the makers -- */
/*
 * Replaces the five rank posters. Markup: template-parts/home-creator.php in
 * this theme, which overrides the parent's.
 *
 * A row per creator: who they are, three things they made, and the way in. The
 * rank survives only as the "Top creator" badge on the first row, because
 * position 4 versus position 5 was never information anyone needed.
 */
.gns-makers {
  display: grid;
  /* 300px floors it at three columns on the 1180px measure, two on a tablet,
     one on a phone - and six creators fill whole rows in all three. */
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}
/*
 * ⚠️ A column, not a two-track row. Face, name and three thumbnails on ONE
 * line left the name 80px wide on a 361px card, so every creator was an
 * ellipsis - the same clipping this review is fixing on the product cards.
 * Stacked, the name gets the full width and the work gets thumbnails big
 * enough to actually show what was made.
 */
.gns-maker {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px 16px 16px;
  border: 1px solid var(--gns-border);
  border-radius: var(--gns-r-card);
  background: var(--gns-card);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.gns-maker:hover {
  border-color: var(--gns-border-cyan);
  box-shadow: var(--gns-glow-card);
}

.gns-maker__who {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  text-decoration: none !important;
}
.gns-maker__face {
  flex: 0 0 auto;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  object-fit: cover;
  /* No scrim. The photograph is the point of the section. */
  border: 1px solid var(--gns-border-strong);
  background: var(--gns-elevated);
}
.gns-maker--top .gns-maker__face { border-color: var(--gns-border-cyan); }

.gns-maker__id { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.gns-maker__name {
  font-family: var(--gns-font);
  font-size: 15px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--gns-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gns-maker__stat {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 8px;
  font: 500 10.5px var(--gns-font-mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--gns-muted);
}
.gns-maker__badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 7px;
  border: 1px solid var(--gns-border-cyan);
  border-radius: var(--gns-r-pill);
  color: var(--gns-cyan-ink);
}
.gns-maker__badge i { font-size: 9px; }

/* The work. Three squares, because three is what a row can show without the
   thumbnails getting smaller than the thing they depict. */
.gns-maker__work {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.gns-maker__work a {
  display: block;
  width: auto;
  aspect-ratio: 1;
  border-radius: 8px;
  overflow: hidden;
  background:
    radial-gradient(closest-side at 50% 70%, rgba(0, 191, 255, .18), transparent),
    var(--gns-elevated);
  border: 1px solid var(--gns-border-faint);
  transition: border-color .15s ease;
}
.gns-maker__work a:hover { border-color: var(--gns-cyan); }
.gns-maker__work img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
.gns-maker__empty {
  margin: 0;
  font-size: 12px;
  color: var(--gns-muted);
}

.gns-maker__go {
  /* Pushed to the floor so the links line up across a row whatever each card
     holds above them - including the one with no published work. */
  margin-top: auto;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 12.5px;
  color: var(--gns-secondary) !important;
  text-decoration: none !important;
}
.gns-maker__go i { font-size: 10px; }
.gns-maker:hover .gns-maker__go { color: var(--gns-text) !important; }
.gns-maker__go:focus-visible { outline: 2px solid var(--gns-focus); outline-offset: 3px; }

/* ============================================================ responsive == */

/* Tablet: the hero's right half stops being wide enough to hold the render
   beside the copy, so it goes back under it. */
@media (max-width: 900px) {
  body.gns-home .gns-hero {
    padding: 56px var(--gutter) 0;
    text-align: center;
  }
  body.gns-home .gns-hero__copy {
    align-items: center;
    max-width: 640px;
    margin: 0 auto;
  }
  body.gns-home .gns-hero__actions,
  body.gns-home .gns-hero__marks { justify-content: center; }
  body.gns-home .gns-hero__lede { max-width: 46ch; margin-inline: auto; }
  body.gns-home .gns-hero__stage {
    position: static;
    width: auto;
    padding: 4px 0 40px;
    -webkit-mask-image: none;
            mask-image: none;
  }
  body.gns-home .gns-hero__materialise { width: min(460px, 82%); }
  /* Nothing to caption once the render is back in its own band, and these two
     lines were the first thing to collide with it at this width. */
  body.gns-home .gns-hero__meta { display: none; }
}

@media (max-width: 620px) {
  body.gns-home .gns-hero { padding-top: 40px; }
  body.gns-home .gns-hero__materialise { width: min(360px, 88%); }
  body.gns-home .gns-hero__stage { padding: 0 0 28px; }

}

/* --------------------------------------------------- the shelves, narrow -- */
/*
 * ⚠️ MEASURED, not guessed. Below 768px the two shelves under the hero stacked
 * their four cards one per row - 1,460px each, 2,940px for the pair. That is
 * two and a half phone screens of scrolling between the hero and the first
 * word of the page's argument, and it was the single worst thing about this
 * page on a phone.
 *
 * A shelf is a shelf: it scrolls sideways. Four cards at 68% of the column put
 * the next one visibly cut at the edge, which is the only affordance a rail
 * needs. The pair now costs about 840px instead of 2,940.
 *
 * The negative margin bleeds the rail out through the page gutter, so the cut
 * card runs to the edge of the screen rather than stopping short of it - which
 * is what makes it read as "there is more this way" instead of as a clipped
 * layout.
 */
@media (max-width: 767px) {
  body.gns-home .overalls-container {
    overflow: visible;    /* the container scrolled; the rail inside it does now */
  }
  body.gns-home .overalls-container .recommended-products {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 68%;
    grid-template-columns: none;
    gap: 12px;
    margin: 0 calc(var(--gutter) * -1);
    padding: 0 var(--gutter) 2px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }
  body.gns-home .overalls-container .recommended-products::-webkit-scrollbar { display: none; }
  body.gns-home .overalls-container .recommended-products > .product-card {
    scroll-snap-align: start;
  }
  body.gns-home .overalls-container .product-card .product-image { aspect-ratio: 3 / 2; }
}

/* ------------------------------------------------- from file to object ---- */
/*
 * The beam turns through ninety degrees and runs down the left of the steps.
 * It is the same idea either way - one movement, three stops - and a vertical
 * rule is what a sequence looks like in a single column.
 */
@media (max-width: 900px) {
  body.gns-home .gns-process__steps {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
  }
  body.gns-home .gns-process__step {
    padding: 0 0 32px 34px;
  }
  body.gns-home .gns-process__step:last-child { padding-bottom: 0; }
  body.gns-home .gns-process__step::before { top: 6px; }
  /* Same segment, turned through ninety degrees: from under this node to the
     top of the next one, which is where the step's own box ends. */
  body.gns-home .gns-process__step::after {
    top: 20px;
    bottom: -8px;
    left: 5px;
    width: 2px;
    height: auto;
    background: linear-gradient(180deg, var(--gns-cyan), var(--gns-magenta));
  }
  body.gns-home .gns-process__text { max-width: none; }
}

/* ------------------------------------------- what the phone was overriding -- */
/*
 * ⚠️ THREE DECLARATIONS, ONE CAUSE.
 *
 * The parent theme has its own `@media (max-width: 767.98px)` block, and
 * everything in it is !important. Below 768px it was quietly undoing three of
 * this page's decisions, which is why the home page looked like a different
 * design on a phone than it does on a laptop:
 *
 *   .title-section h3            font-size: 20px !important
 *   .overalls-container .card h3 font-size: 12px !important
 *   .card .recommended-products img  height: 140px !important
 *
 * The first two turned every shelf label into wide-tracked caps LOUDER than
 * the chapter title above it. The third pinned the shelf photographs to 140px
 * inside a 273px stage, leaving 133px of empty card under each one - which is
 * most of why those cards looked oversized and half-empty.
 *
 * Each answer below is the same declaration this file already makes further
 * up, restated with !important because that is the only thing an !important
 * hears. Nothing new is decided here.
 */
@media (max-width: 767.98px) {
  .gns-chap__body .title-section h3,
  .gns-chap__body .filament-products-list > h3,
  body.gns-home .overalls-container > .card > h3 {
    font-size: 10.5px !important;
    line-height: 1 !important;
  }
  body.gns-home .overalls-container .recommended-products img {
    height: 100% !important;
    width: 100% !important;
    object-fit: cover;
  }
}

/* ------------------------------------------------- the band, off the edge -- */
/*
 * ⚠️ This was the horizontal scrollbar on the whole page. The parent gives the
 * band `margin: 0 10px 10px !important` inside its own
 * `@media (max-width: 767.98px)` (style.css) - from when it was an inset card
 * with a radius. It is full-bleed here, so the 10px pushed 416px of band 10px
 * to the right of a 416px viewport and every page below scrolled sideways.
 *
 * !important only because the declaration it answers is !important, and at
 * the same (0,1,0) weight; there is no way to out-specify it.
 */
@media (max-width: 767.98px) {
  body.gns-home .hub-container {
    width: 100%;
    margin: var(--chapter-gap) 0 0 !important;
  }
}

/* ------------------------------------------------------------- breathing -- */
/*
 * 96px between every section is right on a 1180px measure and far too much
 * stacked eight times down a phone. The page measured just under 13,000px.
 */
@media (max-width: 767px) {
  body.gns-home {
    --chapter-gap: 60px;
    --gutter: 20px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .gns-maker,
  .gns-maker__work a { transition: none; }
}


/* ================================================ the mark, in the band ====
   The brand mark - two hands drawn as vertical slices, cyan reaching to
   magenta - placed as the hinge of the hub band: after the statement, before
   the two cards it introduces.

   Why here and not in the hero: the band's own content already IS two sides.
   Its left card is "find a template" (buy) and its right card is "monetize
   your creations" (sell), and the mark's gradient runs cyan on the left hand
   to magenta on the right. The colour mapping was already correct; this only
   puts the picture where the meaning was.

   ASSET. assets/image/hands.png, 462x137, transparent - cropped from
   design_handoff_the_genesys/assets/logo-full.png, rows 4-140, measured by
   scanning the alpha channel for empty rows (hands 4-140, gap 141-159,
   wordmark 160-200).

   ⚠️ TWO reasons the crop is a real file rather than the handoff PNG used
   directly. `design_handoff_the_genesys/` is gitignored (.gitignore:61), so it
   does not deploy - referencing it would work locally and 404 in production.
   And the handoff image carries the wordmark under the hands, which would read
   as a second logo against the one already in the header.

   ⚠️ NOT the About-us copy. wp-content/uploads/2025/03/logo-chi-siamo.png is
   the same artwork at 1422px but 0% transparent and 84% opaque white - on this
   ground it renders as a white slab. If the mark is ever wanted larger than
   462px, that file has to be keyed out first; it is flat line-art on pure
   white, so a luminance key is clean.
   ========================================================================= */

/*
 * ⚠️ A grid item, not an absolutely positioned overlay. The cards row is
 * `display: grid`, so a `::before` on it becomes a real cell - `grid-column:
 * 1 / -1` gives it a row of its own above both cards, which means it makes its
 * own space and cannot overlap them at any width. An absolute overlay would
 * have needed the band's spacing hand-computed and re-computed at every
 * breakpoint.
 */
/*
 * ⚠️ The column count has to be pinned, and this is a REGRESSION THE PSEUDO
 * CAUSED. Line 1839 sizes this row `repeat(auto-fit, minmax(300px, 1fr))`. On
 * the 1180px measure that fits three tracks and auto-fit collapses the unused
 * third to zero, so two cards measured 580px each. Adding a third grid item
 * filled that track: the cards dropped to 380px and stopped reaching the
 * measure. Two explicit columns keep them where they were.
 *
 * 700px is where the auto-fit rule used to collapse to one column on its own
 * (two 300px minimums plus a 20px gap inside the band's 36px gutters), so the
 * stack point does not move either.
 */
body.gns-home .hub-container > .flex-div:last-child {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (max-width: 700px) {
  body.gns-home .hub-container > .flex-div:last-child {
    grid-template-columns: minmax(0, 1fr);
  }
}

body.gns-home .hub-container > .flex-div:last-child::before {
  content: "";
  grid-column: 1 / -1;
  justify-self: center;
  width: min(462px, 62vw);
  aspect-ratio: 462 / 137;
  /* 12 on top of the heading block's own 44px bottom margin = 56 above the
     mark; 44 below it matches the gap it replaced. */
  margin: 12px 0 44px;
  /*
   * The image sits over its own bloom - layer order is topmost first, so the
   * gradient is written second. The bloom is centred at 48.5% of the box,
   * which is where the fingertips actually meet: scanning the crop for empty
   * columns puts the gap at 220-228 of 462. So the light reads as coming FROM
   * the point of contact rather than from the middle of a rectangle.
   */
  background:
    url("../image/hands.png") center / contain no-repeat,
    radial-gradient(42% 78% at 48.5% 56%,
      rgba(0, 191, 255, .20),
      rgba(255, 110, 255, .09) 54%,
      transparent 78%);
}

/*
 * The band's own glow stays where it is, lighting the heading. This one is
 * tight and low, so the two do not pool into one wash.
 */

@media (max-width: 900px) {
  /* The cards stack here, so there is no seam left to meet over - the mark
     just introduces them both. */
  body.gns-home .hub-container > .flex-div:last-child::before {
    width: min(420px, 78vw);
    margin: 4px 0 36px;
  }
}

@media (max-width: 620px) {
  body.gns-home .hub-container > .flex-div:last-child::before {
    width: min(320px, 84vw);
    margin: 0 0 28px;
  }
}

/*
 * Light theme. theme-switch.js always stamps `data-theme`, so a single
 * `[data-theme="light"]` override is the convention this file already uses -
 * see the .product-meta rule further up.
 *
 * The artwork is cyan-to-magenta line art built for a dark ground. On the
 * light one the bloom behind it has nothing to glow against and reads as haze,
 * so it comes off, and the strokes are darkened a little to hold their weight.
 */
[data-theme="light"] body.gns-home .hub-container > .flex-div:last-child::before {
  background: url("../image/hands.png") center / contain no-repeat;
  filter: saturate(1.15) brightness(.82);
}


/* ============================================ the slice field in the cards ==
   The two hub cards are not text-only by design - they were built around
   artwork that this redesign suppresses.
   home-hub.php prints an ACF background on each card inline
   (`first_banner-min-scaled.jpeg`, `second_banner-min-scaled.jpeg`), the panel
   treatment earlier in this file overrides it to `background: none` because the
   photographs washed out their own text, and what survived the override is
   `.info-card-content { padding-left: 236.688px }` - a column reserved for an
   image that is no longer painted. That reserved column is the empty half of
   each card.

   So it gets filled with the language of the mark above rather than deleted:
   vertical slices, cyan on the card that buys and magenta on the card that
   sells, which are the same two colours the two hands carry.

   ⚠️ SLICES, NOT THE HANDS. Putting half a hand in each card was the obvious
   move and is the wrong one: it would print the brand mark three times inside
   one band, and the void sits on the LEFT of both cards - so the right hand
   would point away from its own text. The slices are the part of this mark
   that can repeat; the hands are the part that should not.
   ========================================================================= */

body.gns-home .hub-container .info-card::before {
  content: "";
  position: absolute;
  /* The card is already `position: relative; overflow: hidden`, so this is
     clipped to its rounded corners with nothing further to set. */
  inset: 0 auto 0 0;
  /*
   * ⚠️ A PERCENTAGE, tracking the parent's own reserved column - which is
   * `.info-card .info-card-content { padding-left: 45% }`, dropping to
   * `30% !important` inside its `@media (max-width: 767.98px)`. A fixed 262px
   * matched the desktop column and then ran straight under the text on a
   * phone, where the column is only 104px. 43% sits about 14px clear of where
   * the copy starts; the narrow value below does the same against the 30%.
   */
  width: 43%;
  pointer-events: none;
  /* 3px on, 6px off. The mark's own slices run about a 9px pitch at its
     natural 462px width, so the field and the hands above it are drawn at the
     same rhythm. */
  background: repeating-linear-gradient(
    90deg,
    var(--gns-slice) 0 3px,
    transparent 3px 9px
  );
  /* Without a mask this is a barcode in a box. The ellipse gives the slices a
     form and fades them out before they reach the text or the card's edges. */
  -webkit-mask-image: radial-gradient(115% 76% at 6% 52%,
    #000 10%, rgba(0, 0, 0, .5) 48%, transparent 84%);
          mask-image: radial-gradient(115% 76% at 6% 52%,
    #000 10%, rgba(0, 0, 0, .5) 48%, transparent 84%);
}

/* Each card takes the colour of the hand on its side of the mark above:
   cyan reaches from the left, magenta from the right. */
body.gns-home .hub-container .first-card  { --gns-slice: rgba(0, 191, 255, .38); }
body.gns-home .hub-container .second-card { --gns-slice: rgba(255, 110, 255, .34); }

/*
 * Light theme. The slices are drawn to glow on a near-black panel; on the
 * light card they need more weight to register at all, and the magenta needs
 * less of it than the cyan to stay the quieter of the two.
 */
[data-theme="light"] body.gns-home .hub-container .first-card  { --gns-slice: rgba(0, 145, 200, .34); }
[data-theme="light"] body.gns-home .hub-container .second-card { --gns-slice: rgba(190, 60, 190, .26); }

/*
 * The same breakpoint the parent uses to narrow the reserved column, so the
 * field and the column it fills always change together. Do not round this to
 * 768 - the parent's is 767.98, and a 0.02px window where the field is wide
 * and the column is not would put slices under the first line of the copy.
 */
@media (max-width: 767.98px) {
  body.gns-home .hub-container .info-card::before { width: 28%; }
}

/* The field is static by choice: the hero already carries the page's one
   sweeping beam, so there is nothing here for reduced-motion to turn off. */

/* ============================== the same card, on the Explore rails ========
   The shop and the printers archive render `.gns-card` (see card.css, "the
   card the canvas actually draws"); the home page renders the PARENT's
   `.product-card` markup restyled to match. Both have to change together or a
   product changes shape between the page that recommends it and the page that
   sells it - which is the whole reason this file restyles rather than forks.

   Same two moves, same reasoning: a square band takes the card from ~221 to
   ~340 against the reference's 355, and squaring it is what makes bleeding the
   image affordable (a portrait photo loses ~20% to a 1:1 crop against ~60% to
   a 2:1 one). The evidence that these sources are not cut-outs - 43 JPEGs of
   174, five of six PNGs opaque - is written up in card.css.
   ========================================================================= */

body.gns-home :is(.product-card, .filament-card) .product-image {
  aspect-ratio: 1 / 1;
}
body.gns-home :is(.product-card, .filament-card) .product-image img,
body.gns-home :is(.product-card, .filament-card) .product-card-inner img {
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  object-fit: cover;
  object-position: 50% 45%;
  border-radius: 0;
  filter: none;
}

/* The two shelves under the hero set their own shallower band; they follow. */
body.gns-home .overalls-container .product-card .product-image {
  aspect-ratio: 1 / 1;
}

/*
 * ⚠️ The filament card needs its own rule, and !important, because the parent
 * pins its image at a fixed size -
 *
 *     .filament-card .product-image img { min-width: 160px !important;
 *                                         max-width: 160px !important }
 *
 * - which held it to a 160px column inside a 260px band while every other card
 * on the page bled. Same three declarations as the shared rule above, restated
 * loudly enough to be heard.
 */
body.gns-home .filament-card .product-image img {
  min-width: 0 !important;
  max-width: none !important;
  width: 100% !important;
  min-height: 0 !important;
  height: 100% !important;
}

/*
 * ⚠️ The printer row keeps `flex: 1 1 auto` from the finding-05 block above -
 * its cards are stretched to the height of the "Printers" aside beside them,
 * so the band grows past square rather than being fixed by it. The
 * aspect-ratio is its floor, which is exactly the role it had before.
 */

@media (max-width: 620px) {
  /*
   * Same reasoning as card.css: the rails and the shelf go full width down
   * here, and a square band on a 348px card is a 350px photograph for one
   * product - about two products a screen. 4:3 keeps the bleed and gives the
   * screen back.
   *
   * ⚠️ The printer row is excluded because its band is not fixed by the
   * aspect-ratio anyway - it grows to fill a card stretched to the aside
   * beside it, so capping the ratio here would do nothing but mislead.
   */
  body.gns-home :is(.product-card, .filament-card) .product-image,
  body.gns-home .overalls-container .product-card .product-image {
    aspect-ratio: 4 / 3;
  }
}
