/* ==========================================================================
   REXZEE SPORTS - sections, cards, poster art, forms, admin
   ========================================================================== */

/* ---------- 1. HERO ------------------------------------------------------ */

.hero {
  position: relative;
  min-height: calc(100dvh - 70px);
  display: flex;
  align-items: center;
  padding-block: clamp(40px, 6vw, 88px);
  overflow: hidden;
}
.hero-wash {
  position: absolute;
  inset: -10% -5%;
  z-index: 0;
  pointer-events: none;
}
/* one wash layer per category, crossfaded by the hero loop */
.hw {
  position: absolute;
  inset: 0;
  opacity: 0.14;
  filter: blur(10px);
  transition: opacity 1.1s var(--e-out);
  background: radial-gradient(
      46% 46% at 13% 9%,
      color-mix(in srgb, var(--c) 26%, transparent),
      transparent 70%
    ),
    radial-gradient(
      44% 44% at 87% 84%,
      color-mix(in srgb, var(--c) 20%, transparent),
      transparent 72%
    );
}
.hw.is-on {
  opacity: 1;
}
/* the wash and the wordmark deliberately bleed past the section edges, so
   the section clips them rather than letting them size the page */
.hero {
  overflow-x: clip;
}
.hero .wrap {
  position: relative;
  z-index: 2;
}
/* ---------- HERO WORDMARK : extruded, always turning -------------------
   The letters are outlines with no fill, so a drop shadow would sit behind
   nothing and read as a smudge. Real depth needs real geometry: ten copies
   stacked along Z inside a preserve-3d parent, so the glyphs have thickness
   and the slow turn reads as a solid object rotating rather than a flat
   image skewing.

   Everything animated here is a transform or an opacity. The turn runs
   forever because it is composited and costs the compositor, not the main
   thread, but it is deliberately slow: the wordmark is the backdrop to the
   headline, and a backdrop that competes with the copy has failed. */

.hero-word {
  position: absolute;
  left: 50%;
  top: 46%;
  transform: translate(-50%, -50%);
  z-index: 1;
  font-size: clamp(7rem, 27vw, 26rem);
  white-space: nowrap;
  perspective: 1300px;
  pointer-events: none;
  user-select: none;
}
/* the pointer nudges the resting angle that the slow turn oscillates around.
   Separate element from .hw-stack because a keyframe animation on transform
   would otherwise overwrite this declaration outright. */
.hw-tilt {
  display: block;
  transform-style: preserve-3d;
  rotate: y calc(var(--px, 0) * 9deg);
  transition: rotate 1.1s var(--e-out);
}
.hero.is-live .hw-tilt {
  transition: rotate 0.5s var(--e-out);
}
.hw-stack {
  position: relative;
  display: block;
  transform-style: preserve-3d;
  /* two animations on one element would fight, so the turn lives here and the
     drift lives on the layer beneath it */
  animation: hwTurn 15s var(--e-inout) infinite;
  /* the stack is expensive to raster and cheap to move, so it is promoted
     once and then only composited */
  will-change: transform;
}
.hw-tilt {
  animation: hwDrift 11s var(--e-inout) infinite;
}
.hw-stack i {
  display: block;
  font-family: var(--f-display);
  font-weight: 800;
  letter-spacing: -0.05em;
  line-height: 0.8;
  color: transparent;
  /* --l is the layer index: 0 is the deepest, the face sits in front */
  transform: translateZ(calc(var(--l, 0) * -14px));
  -webkit-text-stroke: 1.2px var(--line-strong);
  opacity: calc(0.55 - var(--l, 0) * 0.085);
}
.hw-stack i + i {
  position: absolute;
  inset: 0;
}

/* the front face carries the active line's colour, so the wordmark shifts
   hue with the banner instead of sitting inert behind it */
.hw-face {
  --l: -1;
  -webkit-text-stroke: 1.6px color-mix(in srgb, var(--hc, var(--volt)) 46%, transparent) !important;
  opacity: 0.85 !important;
  transition: -webkit-text-stroke-color 0.9s var(--e-out);
}

/* a light band travelling across the glyphs. Clipped to the text so it only
   lights the strokes, never the space between them. */
/* Cost note: background-clip: text cannot be composited. Every frame this
   band moves, the browser re-rasterises 340px glyph outlines across roughly
   four hundred thousand pixels on the main thread. That is fine for a glint
   and ruinous for a loop, so the sweep is short and the rest of the cycle
   parks the gradient on a value that does not change, which paints nothing.
   The whole thing also stops when the hero leaves the screen (see REST). */
.hw-sheen {
  --l: -2;
  -webkit-text-stroke: 0 !important;
  opacity: 1 !important;
  color: transparent;
  background: linear-gradient(
    100deg,
    transparent 42%,
    color-mix(in srgb, var(--hc, var(--volt)) 70%, transparent) 50%,
    transparent 58%
  );
  background-size: 260% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  animation: hwSheen 11s linear infinite;
}

@keyframes hwTurn {
  0%,
  100% {
    transform: rotateY(-9deg) rotateX(2.5deg);
  }
  50% {
    transform: rotateY(9deg) rotateX(-2.5deg);
  }
}
/* the whole mass drifts and breathes on a different period to the turn, so
   the two never sync up into an obvious loop */
/* Translate only. The earlier version also animated scale, which changes the
   rasterisation size of 385px stroked glyph outlines and therefore forced a
   full repaint of the whole stack on every frame. Translate moves a texture
   that was rastered once. */
@keyframes hwDrift {
  0%,
  100% {
    translate: 0 0;
  }
  50% {
    translate: 0 -1.6%;
  }
}
@keyframes hwSheen {
  0% {
    background-position: 190% 0;
  }
  /* The band crosses, then rests off screen for the remainder of the loop so
     it reads as an occasional glint rather than a strobe. The rest is also the
     only cheap part: the value is constant from here to 100%, so no frame in
     that stretch repaints. Shortening the crossing from 48% of six seconds to
     13% of eleven cut the painting duty cycle by roughly four times. */
  13%,
  100% {
    background-position: -90% 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hw-stack,
  .hw-tilt {
    animation: none;
  }
  .hw-tilt {
    rotate: none;
  }
  .hw-sheen {
    animation: none;
    opacity: 0 !important;
  }
}

.hero-grid {
  display: grid;
  grid-template-columns: 1.06fr 0.94fr;
  gap: clamp(28px, 4vw, 68px);
  align-items: center;
}
.hero-copy {
  max-width: 660px;
  container-type: inline-size;
}
/* Two lines doing two different jobs, so they get two different treatments.
   Sizing both from one scale meant the longest string, "WE MANUFACTURE",
   capped the category word too, and the category is what a buyer is meant to
   read first. Splitting them lets the category go far larger while the
   manufacturing message steps back into a label above it. */
.hero h1 {
  margin-bottom: var(--s-5);
  line-height: 1;
}
/* line one: the message, set as a label */
.hero h1 .ln:not(.ln-rot) {
  font-family: var(--f-cond);
  font-size: clamp(0.95rem, 1.5vw, 1.3rem);
  font-weight: 600;
  letter-spacing: 0.28em;
  line-height: 1.2;
  color: var(--ink-2);
  margin-bottom: 0.4em;
}
/* line two: the category, and the focal point of the page */
.hero h1 .ln-rot {
  font-family: var(--f-display);
  font-size: clamp(2.5rem, 7vw, 5.4rem);
  font-weight: 800;
  letter-spacing: -0.05em;
  line-height: 0.92;
}
@supports (container-type: inline-size) {
  .hero h1 .ln-rot {
    /* the longest variant is FITNESS WEAR. at 13 characters, so it sets the
       container scale and nothing shorter can overflow */
    font-size: clamp(2.5rem, 13.1cqw, 5.4rem);
  }
  .hero h1 .ln:not(.ln-rot) {
    font-size: clamp(0.95rem, 2.8cqw, 1.3rem);
  }
}
.hero h1 .ln {
  display: block;
  white-space: nowrap;
}
.hero h1 em {
  font-style: normal;
  color: var(--volt-ink);
}
.hero .lede {
  margin-bottom: var(--s-6);
  font-size: clamp(1.06rem, 1.5vw, 1.28rem);
  font-weight: 500;
  color: var(--ink-2);
}
.hero-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: var(--s-5);
}

/* ---------- 1b. LOOPING HERO -------------------------------------------- */

/* rotating headline word. All three words live in the DOM stacked in one
   grid cell, so the line never reflows and crawlers still read all three. */
.rot {
  display: inline-grid;
  vertical-align: top;
  perspective: 700px;
}
.rot i {
  grid-area: 1 / 1;
  font-style: normal;
  color: var(--volt-ink);
  opacity: 0;
  transform: translateY(0.42em) rotateX(-52deg);
  transform-origin: top center;
  transition: opacity 0.45s var(--e-out), transform 0.65s var(--e-out);
}
.rot i.is-on {
  opacity: 1;
  transform: none;
}

.rot i.is-on {
  text-shadow: 0 0 28px color-mix(in srgb, var(--volt-ink) var(--glow), transparent);
}

/* ---------- CONTENT PAGES : process steps and floor stations ------------ */

.phead-note {
  margin-top: var(--s-5);
  padding: 14px 18px;
  border-left: 2px solid var(--volt);
  background: var(--surface);
  border-radius: 0 var(--r-input) var(--r-input) 0;
  font-size: 0.92rem;
  max-width: 62ch;
}

.psteps {
  display: grid;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  overflow: hidden;
}
.pstep {
  display: grid;
  grid-template-columns: 66px 52px 1fr;
  gap: var(--s-5);
  align-items: start;
  padding: var(--s-5) var(--s-6);
  background: var(--bg);
  transition: background-color var(--t-mid);
}
.pstep:hover {
  background: var(--surface);
}
.pstep-n {
  font-family: var(--f-mono);
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  color: var(--volt-ink);
  padding-top: 5px;
}
.pstep-ico {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--line);
  border-radius: var(--r-input);
  color: var(--ink-2);
  transition: color var(--t-fast), border-color var(--t-fast), transform var(--t-mid);
}
.pstep:hover .pstep-ico {
  color: var(--volt-ink);
  border-color: var(--volt);
  transform: translateY(-2px);
}
.pstep-ico svg {
  width: 20px;
  height: 20px;
}
.pstep h3 {
  margin-bottom: 7px;
}
.pstep p {
  font-size: 0.95rem;
}
@media (max-width: 720px) {
  .pstep {
    grid-template-columns: 46px 1fr;
    gap: var(--s-4);
    padding: var(--s-5);
  }
  .pstep-ico {
    display: none;
  }
}

/* the factory floor, tilted slightly so the row reads as a line of stations
   rather than a table of cards */
.stations {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(248px, 1fr));
  gap: clamp(12px, 1.4vw, 18px);
  perspective: 1400px;
}
.station {
  position: relative;
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: var(--surface);
  transform-style: preserve-3d;
  transition: transform 0.5s var(--e-out), border-color var(--t-mid),
    box-shadow var(--t-mid);
}
.station:hover {
  transform: rotateX(6deg) translateY(-5px);
  border-color: var(--volt);
  box-shadow: 0 18px 44px color-mix(in srgb, var(--volt) var(--glow-soft), transparent);
}
.station-ico {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin-bottom: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-input);
  color: var(--volt-ink);
  transition: transform 0.5s var(--e-out);
}
.station:hover .station-ico {
  transform: translateZ(26px);
}
.station-ico svg {
  width: 20px;
  height: 20px;
}
.station-n {
  position: absolute;
  right: 18px;
  top: 14px;
  font-family: var(--f-mono);
  font-size: 0.66rem;
  letter-spacing: 0.16em;
  color: var(--ink-3);
}
.station h3 {
  margin-bottom: 8px;
}
.station p {
  font-size: 0.92rem;
}

/* a card that is information rather than a link */
.sc-card.is-static {
  cursor: default;
}
.sc-card.is-static:hover {
  transform: none;
  border-color: var(--line-strong);
  box-shadow: none;
}

@media (prefers-reduced-motion: reduce) {
  .station:hover,
  .station:hover .station-ico {
    transform: none;
  }
}

/* ---------- WHO WE SUPPLY (B2B buyer segments) -------------------------- */

.buyers {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(12px, 1.4vw, 18px);
}
.buyer {
  display: flex;
  flex-direction: column;
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: var(--surface);
  transition: border-color var(--t-mid), transform 0.45s var(--e-out);
}
.buyer:hover {
  border-color: var(--line-strong);
  transform: translateY(-3px);
}
.buyer-ico {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  margin-bottom: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-input);
  color: var(--volt-ink);
}
.buyer-ico svg {
  width: 20px;
  height: 20px;
}
.buyer h3 {
  font-size: clamp(1.02rem, 1.3vw, 1.18rem);
  margin-bottom: 10px;
}
.buyer p {
  font-size: 0.93rem;
  flex: 1;
  margin-bottom: var(--s-5);
}
.buyer-tag {
  font-family: var(--f-mono);
  font-size: 0.6rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
}
@media (max-width: 1040px) {
  .buyers {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 560px) {
  .buyers {
    grid-template-columns: 1fr;
  }
}

/* ---------- HERO : swapping eyebrow, lede and buyer facts ---------------- */

/* Both swap in step with the banner. inline-grid stacks every variant in the
   same cell so the tallest one sizes the box once and nothing reflows as the
   copy cycles. */
.rot-line {
  display: inline-grid;
  width: 100%;
}
.rot-line i {
  grid-area: 1 / 1;
  font-style: normal;
  opacity: 0;
  transform: translateY(9px);
  transition: opacity 0.4s var(--e-out), transform 0.55s var(--e-out);
}
.rot-line i.is-on {
  opacity: 1;
  transform: none;
}

.hero-eyebrow {
  display: block;
  margin-bottom: var(--s-4);
  font-family: var(--f-mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-3);
  max-width: none;
}
.hero-eyebrow i {
  display: flex;
  align-items: center;
  gap: 12px;
  white-space: nowrap;
}
/* On a narrow phone "05 Bags and Accessories / 9 subcategories" is wider than
   the screen, and nowrap turned that into 40px hanging off the edge. The
   subcategory count is the least useful part of the line, so it goes first. */
@media (max-width: 620px) {
  .hero-eyebrow i {
    flex-wrap: wrap;
    white-space: normal;
    gap: 8px;
  }
  .hero-eyebrow em {
    display: none;
  }
}
.hero-eyebrow b {
  color: var(--hc, var(--volt-ink));
  font-weight: 500;
}
.hero-eyebrow em {
  font-style: normal;
  color: var(--ink-3);
  opacity: 0.62;
}
.hero-eyebrow em::before {
  content: '/ ';
}

.lede-rot {
  margin-top: var(--s-4);
  min-height: 3.4em;
}
.rot-lede i {
  transition-delay: 0.06s;
}

/* the buyer facts strip: the four questions that decide whether a B2B visitor
   bothers to write to you at all */
.hero-facts {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  margin: var(--s-6) 0 var(--s-6);
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-input);
  overflow: hidden;
}
.hero-facts > div {
  padding: 14px 16px;
  background: var(--bg);
}
.hero-facts dt {
  font-family: var(--f-mono);
  font-size: 0.58rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 5px;
}
.hero-facts dd {
  font-family: var(--f-cond);
  font-size: 1.14rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--ink);
}
.hero-note {
  margin-top: var(--s-4);
  font-family: var(--f-mono);
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  color: var(--ink-3);
}
@media (max-width: 620px) {
  .hero-facts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.hero-banner {
  position: relative;
  isolation: isolate;
  perspective: 1100px;
  transform-style: preserve-3d;
}
/* The frame has no entrance animation, so it can own `transform` outright. */
.hero-banner .hb-stage {
  transform: rotateY(calc(var(--px, 0) * 5.5deg)) rotateX(calc(var(--py, 0) * -5.5deg));
  transition: transform 0.7s var(--e-out);
  will-change: transform;
}
.hero.is-live .hb-stage {
  /* while the pointer is live the rAF loop owns the easing, so the CSS
     transition steps aside or the two fight and the motion feels laggy */
  transition: none;
}

/* Everything inside the frame already runs a keyframe animation on `transform`
   with fill-mode both, which would win over any transform declared here. The
   independent `translate` property composes with it instead of replacing it,
   so the entrance animation and the parallax can both drive the same element. */

/* the artwork sits in front of the frame and leads it */
.hero-banner .hb-slide .hb-art {
  translate: calc(var(--px, 0) * -17px) calc(var(--py, 0) * -15px);
  transition: translate 0.75s var(--e-out);
}
/* the index number and caption trail behind it */
.hero-banner .hb-num {
  translate: calc(var(--px, 0) * 7px) calc(var(--py, 0) * 5px);
  transition: translate 0.8s var(--e-out);
}
.hero-banner .hb-cap {
  translate: calc(var(--px, 0) * 4px) calc(var(--py, 0) * 3px);
  transition: translate 0.8s var(--e-out);
}
/* and the halo drifts furthest, which is what sells the depth */
.hero-banner::before {
  translate: calc(var(--px, 0) * 24px) calc(var(--py, 0) * 20px);
  transition: background 0.9s var(--e-out), translate 0.9s var(--e-out);
}
.hero.is-live .hb-art,
.hero.is-live .hb-num,
.hero.is-live .hb-cap,
.hero.is-live .hero-banner::before {
  transition-property: background;
}

@media (prefers-reduced-motion: reduce) {
  .hero-banner .hb-stage {
    transform: none;
  }
  .hero-banner .hb-art,
  .hero-banner .hb-num,
  .hero-banner .hb-cap,
  .hero-banner::before {
    translate: none;
  }
}
/* neon halo that takes the colour of whichever line is on screen */
.hero-banner::before {
  content: '';
  position: absolute;
  inset: -10% -8% 6%;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(
    closest-side,
    color-mix(in srgb, var(--hc, var(--volt)) var(--glow), transparent),
    transparent
  );
  filter: blur(52px);
  transition: background 0.9s var(--e-out);
  pointer-events: none;
  /* A 52px blur is applied when the layer is rastered. Without this the halo
     shares a layer with the page, so nudging it 24px on a pointer move re-runs
     the blur over the whole region every frame. Promoted, it is rastered once
     and then simply moved, which is what the parallax actually wants. */
  will-change: translate;
}
.hb-stage {
  position: relative;
  aspect-ratio: 1 / 1.04;
  border: 1px solid color-mix(in srgb, var(--hc, var(--line)) 42%, transparent);
  border-radius: var(--r-panel);
  background: var(--surface);
  overflow: hidden;
  isolation: isolate;
  box-shadow: var(--shadow-sm),
    0 0 0 1px color-mix(in srgb, var(--hc, transparent) var(--glow-soft), transparent);
  transition: border-color 0.9s var(--e-out), box-shadow 0.9s var(--e-out);
}

/* ---- slide choreography ------------------------------------------------
   Each line enters from somewhere different: teamwear wipes in from the
   left, fitness rises from the floor, combat opens as an iris. The garment
   inside follows on its own path, then settles into a slow float. */

.hb-slide {
  --c: var(--volt-ink);
  --in: hbFade;
  --inArt: hbArtUp;
  position: absolute;
  inset: 0;
  opacity: 0;
  visibility: hidden;
}
.hb-slide[data-anim='wipe'] {
  --in: hbWipe;
  --inArt: hbArtLeft;
}
.hb-slide[data-anim='rise'] {
  --in: hbRise;
  --inArt: hbArtZoom;
}
.hb-slide[data-anim='iris'] {
  --in: hbIris;
  --inArt: hbArtRight;
}
.hb-slide.is-on {
  opacity: 1;
  visibility: visible;
  animation: var(--in) 1.05s var(--e-out) both;
}
.hb-slide.was-on {
  opacity: 1;
  visibility: visible;
  animation: hbOut 0.6s var(--e-inout) both;
}
.hb-slide.is-on .hb-num {
  animation: hbNumIn 0.9s 0.06s var(--e-out) both;
}
.hb-slide.is-on .hb-cap {
  animation: hbCapIn 0.8s 0.28s var(--e-out) both;
}
.hb-slide.is-on .hb-art,
.hb-slide.is-on .hb-photo {
  animation: var(--inArt) 1.1s 0.12s var(--e-out) both;
}
.hb-slide.is-on .hb-art svg {
  animation: hbFloat 7s 1.3s ease-in-out infinite;
}

@keyframes hbFade {
  from { opacity: 0; transform: scale(1.05); }
  to { opacity: 1; transform: none; }
}
@keyframes hbWipe {
  from { clip-path: inset(0 100% 0 0); transform: scale(1.1) translateX(-3%); }
  to { clip-path: inset(0 0 0 0); transform: none; }
}
@keyframes hbRise {
  from { clip-path: inset(100% 0 0 0); transform: translateY(9%) scale(1.08); }
  to { clip-path: inset(0 0 0 0); transform: none; }
}
@keyframes hbIris {
  from { clip-path: circle(0% at 74% 24%); transform: scale(1.16) rotate(2.5deg); }
  to { clip-path: circle(150% at 74% 24%); transform: none; }
}
@keyframes hbOut {
  from { opacity: 1; transform: none; filter: blur(0); }
  to { opacity: 0; transform: scale(0.93) translateY(-3%); filter: blur(7px); }
}
@keyframes hbArtUp {
  from { opacity: 0; transform: translateY(18%) scale(0.9); }
  to { opacity: 1; transform: none; }
}
@keyframes hbArtLeft {
  from { opacity: 0; transform: translateX(-26%) rotate(-8deg) scale(0.92); }
  to { opacity: 1; transform: none; }
}
@keyframes hbArtRight {
  from { opacity: 0; transform: translateX(26%) rotate(9deg) scale(0.92); }
  to { opacity: 1; transform: none; }
}
@keyframes hbArtZoom {
  from { opacity: 0; transform: scale(0.55) rotate(-11deg); }
  to { opacity: 1; transform: none; }
}
@keyframes hbNumIn {
  from { opacity: 0; transform: translate(26px, -16px); }
  to { opacity: 1; transform: none; }
}
@keyframes hbCapIn {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: none; }
}
@keyframes hbFloat {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-2.6%); }
}
.hb-slide::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    152deg,
    color-mix(in srgb, var(--c) 30%, transparent) 0%,
    transparent 56%
  );
}
.hb-slide::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: radial-gradient(var(--c) 1.15px, transparent 1.2px);
  background-size: 12px 12px;
  opacity: 0.19;
  mask-image: linear-gradient(205deg, #000 0%, transparent 64%);
  -webkit-mask-image: linear-gradient(205deg, #000 0%, transparent 64%);
}
.hb-num {
  position: absolute;
  right: 18px;
  top: 6px;
  font-family: var(--f-display);
  font-weight: 800;
  font-size: clamp(4rem, 9vw, 7.2rem);
  line-height: 1;
  letter-spacing: -0.06em;
  color: transparent;
  -webkit-text-stroke: 1.4px color-mix(in srgb, var(--c) 55%, transparent);
  user-select: none;
}
.hb-art {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 13% 15% 27%;
}
.hb-art svg {
  width: 100%;
  height: 100%;
  overflow: visible;
}
.hb-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hb-cap {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 20px 22px;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 14px;
  background: linear-gradient(to top, var(--bg) 36%, transparent);
}
.hb-cap b {
  display: block;
  font-family: var(--f-display);
  font-size: clamp(1.3rem, 2.2vw, 1.9rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.02;
  color: var(--ink);
}
.hb-cap i {
  display: block;
  font-family: var(--f-mono);
  font-style: normal;
  font-size: 0.63rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: 6px;
}
.hb-go {
  width: 46px;
  height: 46px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: var(--r-pill);
  border: 1px solid var(--line-strong);
  color: var(--ink);
  transition: background-color var(--t-mid), color var(--t-mid),
    border-color var(--t-mid), transform var(--t-mid);
}
.hb-go svg {
  width: 18px;
  height: 18px;
}
.hb-slide:hover .hb-go,
.hb-go:hover {
  background: var(--c);
  border-color: var(--c);
  color: var(--bg);
  transform: rotate(-45deg);
}

/* ---------- the whole slide is the link -------------------------------
   The destination was a 46px arrow in the corner. Everything a buyer
   actually looks at - the garment drawing, the line name, the caption - did
   nothing when clicked, on the largest element on the homepage.

   The category panels solve this with a stretched ::after on the link, and
   that cannot work here: .hb-cap is position: absolute, so an ::after on the
   arrow inside it resolves against the 560x100 caption strip rather than the
   560x583 slide, and covers the bottom sixth of the panel. An absolutely
   positioned ancestor cannot be skipped in CSS.

   So the slide forwards its clicks in app.js instead. The <a> stays exactly
   as it was - real href, real accessible name, in the tab order, crawlable -
   and nothing about the markup or the screen reader output changes. */
.hb-slide.is-on {
  cursor: pointer;
}
/* the arrow answers to a hover anywhere on the slide, so the whole panel
   reads as one control rather than a picture with a button on it */
.hb-slide.is-on:hover .hb-go {
  background: var(--c);
  border-color: var(--c);
  color: var(--bg);
  transform: rotate(-45deg);
}
/* keyboard: the link is a 46px circle but the focus ring belongs around the
   thing that is actually clickable */
.hb-slide.is-on .hb-go:focus-visible {
  outline: none;
}
.hb-stage:has(.hb-slide.is-on .hb-go:focus-visible) {
  outline: 3px solid var(--c-focus, var(--volt));
  outline-offset: 3px;
}
@supports not selector(:has(*)) {
  .hb-slide.is-on .hb-go:focus-visible {
    outline: 3px solid var(--volt);
    outline-offset: 2px;
  }
}

/* the loop controls double as a progress readout */
.hb-dots {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 9px;
  margin-top: 12px;
}
.hb-dot {
  position: relative;
  overflow: hidden;
  min-height: 44px;
  padding: 0 10px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  font-family: var(--f-cond);
  font-size: 0.84rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-3);
  transition: color var(--t-mid), border-color var(--t-mid);
}
.hb-dot span {
  position: relative;
  z-index: 1;
}
.hb-dot i {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  background: var(--on-volt);
  opacity: 0.32;
  transform: scaleX(0);
  transform-origin: left;
}
.hb-dot:hover {
  color: var(--ink);
  border-color: var(--line-strong);
}
.hb-dot.is-on {
  background: var(--volt);
  color: var(--on-volt);
  border-color: var(--volt);
  box-shadow: 0 0 26px color-mix(in srgb, var(--volt) var(--glow-soft), transparent);
}
.hb-dot.is-on i {
  animation: hb-fill var(--dwell, 5000ms) linear forwards;
}
@keyframes hb-fill {
  to {
    transform: scaleX(1);
  }
}
.hero-banner.is-paused .hb-dot.is-on i {
  animation-play-state: paused;
}

@media (prefers-reduced-motion: reduce) {
  .hb-slide.is-on,
  .hb-slide.was-on,
  .hb-slide.is-on .hb-num,
  .hb-slide.is-on .hb-cap,
  .hb-slide.is-on .hb-art,
  .hb-slide.is-on .hb-photo,
  .hb-slide.is-on .hb-art svg {
    animation: none;
  }
  .hb-slide.was-on {
    opacity: 0;
    visibility: hidden;
  }
  .hb-dot.is-on i {
    animation: none;
    transform: scaleX(1);
  }
  .rot i {
    transition: none;
  }
}

/* ---------- 1c. SLANT BAND (the tilted strip under the hero) ------------ */

.slant {
  position: relative;
  z-index: 3;
  height: clamp(126px, 15vw, 188px);
  margin-top: clamp(-72px, -6vw, -40px);
  /* the page head is shorter than the hero, so it needs a gentler bite */
}
.phead + .slant {
  margin-top: clamp(-40px, -3vw, -16px);
}
.phead:has(+ .slant) {
  padding-bottom: clamp(58px, 7vw, 96px);
  overflow: hidden;
  pointer-events: none;
  isolation: isolate;
}
.slant-strip {
  position: absolute;
  left: -8%;
  width: 116%;
  overflow: hidden;
  border-block: 1px solid;
}
.slant-a {
  top: 16%;
  transform: rotate(-3.4deg);
  background: var(--volt);
  color: var(--on-volt);
  border-color: var(--volt-deep);
  box-shadow: 0 0 46px color-mix(in srgb, var(--volt) var(--glow), transparent);
}
.slant-b {
  top: 52%;
  transform: rotate(2.6deg);
  background: var(--ink);
  color: var(--bg);
  border-color: var(--ink);
}
.slant-track {
  display: flex;
  width: max-content;
  animation: slant-run 30s linear infinite;
}
.slant-b .slant-track {
  animation-duration: 38s;
  animation-direction: reverse;
}
.slant-track span {
  display: inline-flex;
  align-items: center;
  gap: 28px;
  padding: 11px 14px;
  font-family: var(--f-display);
  font-size: clamp(0.95rem, 1.8vw, 1.5rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  white-space: nowrap;
}
.slant-track b {
  opacity: 0.4;
}
@keyframes slant-run {
  to {
    transform: translate3d(-50%, 0, 0);
  }
}
@media (prefers-reduced-motion: reduce) {
  .slant-track {
    animation: none;
  }
}
@media (max-width: 620px) {
  .slant {
    height: 118px;
    margin-top: -34px;
  }
  .slant-a {
    top: 10%;
  }
  .slant-b {
    top: 52%;
  }
}

/* fanned poster stack */
.poster-stack {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(12px, 1.6vw, 20px);
  align-items: start;
}
.poster-stack .poster:nth-child(1) {
  grid-row: span 2;
  margin-top: clamp(14px, 3vw, 42px);
}
.poster-stack .poster:nth-child(3) {
  margin-top: clamp(6px, 1.4vw, 16px);
}

/* ---------- 2. POSTER (hero portrait / category art) --------------------- */

.poster {
  --c: var(--volt-ink);
  position: relative;
  display: block;
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: var(--surface);
  overflow: hidden;
  isolation: isolate;
  transition: transform 0.5s var(--e-out), border-color var(--t-mid),
    box-shadow 0.5s var(--e-out);
}
.poster-tall {
  aspect-ratio: 3 / 4.4;
}
.poster-wide {
  aspect-ratio: 4 / 3.1;
}
.poster:hover {
  border-color: color-mix(in srgb, var(--c) 65%, transparent);
  box-shadow: var(--shadow-sm),
    0 0 40px color-mix(in srgb, var(--c) var(--glow-soft), transparent);
}

/* colour field */
.poster::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background: linear-gradient(
    148deg,
    color-mix(in srgb, var(--c) 26%, transparent) 0%,
    transparent 52%
  );
  transition: opacity 0.55s var(--e-out);
}
/* halftone dots */
.poster::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: radial-gradient(var(--c) 1.1px, transparent 1.15px);
  background-size: 11px 11px;
  opacity: 0.17;
  mask-image: linear-gradient(200deg, #000 0%, transparent 62%);
  -webkit-mask-image: linear-gradient(200deg, #000 0%, transparent 62%);
}
.poster:hover::before {
  opacity: 0.68;
}

.poster-num {
  position: absolute;
  right: 12px;
  top: 4px;
  z-index: 1;
  font-family: var(--f-display);
  font-weight: 800;
  font-size: clamp(3.4rem, 7vw, 5.6rem);
  line-height: 1;
  letter-spacing: -0.06em;
  color: transparent;
  -webkit-text-stroke: 1.2px color-mix(in srgb, var(--c) 52%, transparent);
  user-select: none;
}
.poster-art {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: grid;
  place-items: center;
  padding: 14% 14% 28%;
  transition: transform 0.6s var(--e-out);
}
/* the wide crop gives the caption a bigger share, so lift the art further */
.poster-wide .poster-art {
  padding: 10% 17% 38%;
}
.poster-art svg {
  width: 100%;
  height: 100%;
  overflow: visible;
}
.poster:hover .poster-art {
  transform: scale(1.055) translateY(-4px);
}
/* uploaded photo replaces the art when present */
.poster-photo {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.7s var(--e-out);
}
.poster:hover .poster-photo {
  transform: scale(1.06);
}
.poster-photo + .poster-art {
  display: none;
}

.poster-cap {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 3;
  padding: 14px 16px;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 10px;
  background: linear-gradient(to top, var(--bg) 34%, transparent);
}
.poster-cap b {
  display: block;
  font-family: var(--f-cond);
  font-size: clamp(1.02rem, 1.5vw, 1.3rem);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1.08;
  color: var(--ink);
}
.poster-cap i {
  display: block;
  font-family: var(--f-mono);
  font-style: normal;
  font-size: 0.6rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: 4px;
}
.poster-go {
  width: 34px;
  height: 34px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: var(--r-pill);
  border: 1px solid var(--line-strong);
  color: var(--ink);
  transition: background-color var(--t-mid), color var(--t-mid),
    border-color var(--t-mid), transform var(--t-mid);
}
.poster-go svg {
  width: 15px;
  height: 15px;
}
.poster:hover .poster-go {
  background: var(--c);
  border-color: var(--c);
  /* --c is bright in dark mode and deep in light mode, so the page
     background is always the readable counterpart */
  color: var(--bg);
  transform: rotate(-45deg);
}
/* corner ticks */
.poster-tick {
  position: absolute;
  z-index: 3;
  width: 13px;
  height: 13px;
  border: 1px solid var(--line-strong);
  opacity: 0.6;
}
.poster-tick.tl {
  left: 9px;
  top: 9px;
  border-right: 0;
  border-bottom: 0;
}
.poster-tick.br {
  right: 9px;
  bottom: 9px;
  border-left: 0;
  border-top: 0;
}

/* ---------- 3. TRUST MARKS ---------------------------------------------- */

.marks {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: var(--s-5);
  align-items: center;
}
.marks a,
.marks span {
  display: grid;
  place-items: center;
  color: var(--ink-3);
  opacity: 0.72;
  transition: color var(--t-mid), opacity var(--t-mid), transform var(--t-mid);
}
.marks a:hover {
  color: var(--ink);
  opacity: 1;
  transform: translateY(-3px);
}
.marks svg {
  width: 100%;
  max-width: 132px;
  height: 34px;
}
@media (max-width: 860px) {
  .marks {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--s-5) var(--s-4);
  }
}

/* ---------- 4. CATEGORY BENTO ------------------------------------------- */

.cat-bento {
  display: grid;
  grid-template-columns: 1.32fr 1fr;
  grid-template-rows: auto auto;
  gap: clamp(14px, 1.8vw, 22px);
}
.cat-bento > :nth-child(1) {
  grid-row: span 2;
}

.cat-panel {
  --c: var(--volt-ink);
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 300px;
  padding: clamp(22px, 2.6vw, 38px);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: var(--surface);
  overflow: hidden;
  isolation: isolate;
  transition: border-color var(--t-mid), transform 0.5s var(--e-out);
}
.cat-bento > :nth-child(1).cat-panel {
  min-height: 560px;
}
.cat-panel::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(
      120% 90% at 100% 0%,
      color-mix(in srgb, var(--c) 22%, transparent),
      transparent 62%
    ),
    linear-gradient(180deg, transparent 40%, var(--surface-2) 100%);
  transition: opacity 0.55s var(--e-out);
  opacity: 0.9;
}
.cat-panel:hover {
  border-color: color-mix(in srgb, var(--c) 62%, transparent);
  transform: translateY(-4px);
  box-shadow: 0 0 46px color-mix(in srgb, var(--c) var(--glow-soft), transparent);
}
.cat-panel:hover::before {
  opacity: 1;
}
.cat-panel .cat-art {
  position: absolute;
  right: -3%;
  top: 44%;
  transform: translateY(-50%);
  width: 46%;
  max-width: 292px;
  z-index: -1;
  opacity: 0.9;
  /* fade the leading edge so the drawing never fights the copy */
  mask-image: linear-gradient(90deg, transparent, #000 30%);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 30%);
  transition: transform 0.7s var(--e-out);
}
.cat-bento > :nth-child(1) .cat-art {
  right: 3%;
  top: 40%;
  width: 50%;
  max-width: 380px;
}
.cat-panel .chip-row {
  max-width: 30rem;
}
.cat-panel:hover .cat-art {
  transform: translateY(-52%) scale(1.05);
}
.cat-rule {
  position: absolute;
  left: 0;
  top: 0;
  height: 3px;
  width: 100%;
  background: var(--c);
  transform: scaleX(0.16);
  transform-origin: left;
  transition: transform 0.6s var(--e-out);
}
.cat-panel:hover .cat-rule {
  transform: scaleX(1);
}
.cat-panel h3 {
  margin-bottom: 10px;
  max-width: 12ch;
}
.cat-panel p {
  font-size: 0.97rem;
  max-width: 42ch;
  margin-bottom: var(--s-5);
}
.cat-panel .chip-row {
  margin-bottom: var(--s-5);
}
.cat-panel .tag {
  pointer-events: none;
}
.cat-link {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--f-cond);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink);
}
.cat-link svg {
  width: 16px;
  height: 16px;
  transition: transform var(--t-mid);
}
.cat-panel:hover .cat-link svg {
  transform: translateX(6px);
}

/* ---- the whole panel is the link ---------------------------------------
   The panel already lifts, glows and slides its arrow on hover, so it reads
   as one button, but only the line of text at the bottom actually navigated.
   A visitor aiming at the heading or the artwork clicked nothing.

   One stretched pseudo element over the panel fixes that without a second
   <a> in the markup, which matters because this block is generated: there is
   still exactly one link per category, so the crawler and the screen reader
   see the same single, fully labelled destination they saw before. */
.cat-panel {
  cursor: pointer;
}
.cat-link::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: inherit;
}
/* keyboard: the link is still the focus target, so the ring has to be drawn
   on the panel around it rather than on a 1px-tall overlay */
.cat-link:focus-visible {
  outline: none;
}
.cat-panel:has(.cat-link:focus-visible) {
  outline: 2px solid var(--c);
  outline-offset: 3px;
  border-color: color-mix(in srgb, var(--c) 62%, transparent);
  transform: translateY(-4px);
}
.cat-panel:has(.cat-link:focus-visible) .cat-rule {
  transform: scaleX(1);
}
/* :has() is everywhere now, but a browser without it must still show a ring */
@supports not selector(:has(*)) {
  .cat-link:focus-visible {
    outline: 2px solid var(--c);
    outline-offset: 3px;
  }
}

/* Equal lines read better as a grid than as one hero panel plus leftovers,
   so the flat variant drops the feature treatment on the first child. */
.cat-bento-flat {
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: auto;
}
.cat-bento-flat > :nth-child(1) {
  grid-row: auto;
}
.cat-bento-flat > :nth-child(1).cat-panel {
  min-height: 340px;
}
.cat-bento-flat > :nth-child(1) .cat-art {
  right: -3%;
  top: 44%;
  width: 46%;
  max-width: 292px;
}
.cat-bento-flat .cat-panel {
  min-height: 340px;
}
.cat-bento-flat .cat-panel h3 {
  max-width: 14ch;
}

/* Seven lines in a three column grid leaves the seventh alone on its own row,
   in a third of the width, with a two thirds hole beside it. Let whichever
   card ends up alone take the rest of the row instead. Written against the
   position rather than the count, so an eighth line needs no new rule. */
.cat-bento-flat > :last-child:nth-child(3n + 1) {
  grid-column: 1 / -1;
}
.cat-bento-flat > :last-child:nth-child(3n + 2) {
  grid-column: span 2;
}

@media (max-width: 1180px) {
  .cat-bento-flat {
    grid-template-columns: repeat(2, 1fr);
  }
  /* two columns now, so the three column rules above are the wrong shape */
  .cat-bento-flat > :last-child:nth-child(3n + 1),
  .cat-bento-flat > :last-child:nth-child(3n + 2) {
    grid-column: auto;
  }
  .cat-bento-flat > :last-child:nth-child(2n + 1) {
    grid-column: 1 / -1;
  }
}

/* the three-panel layout collapses at 900, the six-panel one holds two
   columns down to 720, so :not() keeps them from overwriting each other */
@media (max-width: 900px) {
  .cat-bento:not(.cat-bento-flat) {
    grid-template-columns: 1fr;
  }
  .cat-bento:not(.cat-bento-flat) > :nth-child(1) {
    grid-row: auto;
  }
  .cat-bento:not(.cat-bento-flat) > :nth-child(1).cat-panel {
    min-height: 400px;
  }
}

@media (max-width: 720px) {
  .cat-bento-flat {
    grid-template-columns: 1fr;
  }
  .cat-bento-flat > :last-child {
    grid-column: auto;
  }
}

/* ---------- 5. MANIFESTO (scroll scrub) --------------------------------- */

.manifesto {
  padding-block: clamp(84px, 13vw, 190px);
  background: var(--bg);
  border-block: 1px solid var(--line);
}
.manifesto-type {
  font-family: var(--f-display);
  font-weight: 800;
  font-size: clamp(2rem, 6.2vw, 5.4rem);
  line-height: 1.03;
  letter-spacing: -0.04em;
  max-width: 20ch;
}
.manifesto-type .w {
  display: inline-block;
  margin-right: 0.24em;
}
.manifesto-type .w.hl {
  color: var(--volt-ink);
}
.manifesto.js-dim .w {
  opacity: 0.16;
}
.manifesto-foot {
  margin-top: var(--s-7);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-6);
  align-items: center;
  padding-top: var(--s-5);
  border-top: 1px solid var(--line);
}
.manifesto-foot p {
  max-width: 44ch;
  font-size: 0.97rem;
}

/* ---------- 6. PROCESS (horizontal pan) --------------------------------- */

.pan {
  position: relative;
  overflow: hidden;
  background: var(--bg-2);
  border-block: 1px solid var(--line);
}
.pan-head {
  /* block only: the shorthand would wipe out .wrap's inline padding */
  padding-block: clamp(48px, 6vw, 84px) var(--s-6);
}
.pan-track {
  display: flex;
  gap: clamp(14px, 1.8vw, 24px);
  padding: 0 var(--pad-x) clamp(52px, 6vw, 88px);
  width: max-content;
}
.step {
  position: relative;
  width: clamp(268px, 30vw, 360px);
  flex: none;
  padding: var(--s-6) var(--s-5) var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: var(--surface);
  overflow: hidden;
  transition: border-color var(--t-mid), background-color var(--t-mid);
}
.step:hover {
  border-color: var(--line-strong);
  background: var(--surface-2);
}
.step-ico {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  color: var(--volt-ink);
  margin-bottom: var(--s-5);
}
.step-ico svg {
  width: 21px;
  height: 21px;
}
.step h3 {
  /* these are h3 for the document outline but keep the h4 scale, so a
     card title never competes with the section heading above it */
  font-size: clamp(1.02rem, 1.3vw, 1.18rem);
  letter-spacing: -0.012em;
  line-height: 1.2;
  margin-bottom: 8px;
}
.step p {
  font-size: 0.94rem;
  color: var(--ink-2);
}
.step-tick {
  position: absolute;
  right: 16px;
  top: 14px;
  font-family: var(--f-mono);
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  color: var(--ink-3);
}
.step-bar {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 100%;
  background: var(--volt);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.5s var(--e-out);
}
.step:hover .step-bar {
  transform: scaleX(1);
}
/* mobile fallback: native horizontal snap, no pin */
@media (max-width: 860px) {
  .pan-track {
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    width: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .pan-track::-webkit-scrollbar {
    display: none;
  }
  .step {
    scroll-snap-align: start;
    width: 78vw;
  }
}

/* ---------- 7. PRODUCT CARDS -------------------------------------------- */

.p-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(248px, 1fr));
  gap: clamp(14px, 1.7vw, 22px);
}
.p-rail {
  display: flex;
  gap: clamp(14px, 1.7vw, 22px);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: var(--s-4);
  scrollbar-width: none;
}
.p-rail::-webkit-scrollbar {
  display: none;
}
.p-rail .pc {
  width: min(310px, 74vw);
  flex: none;
  scroll-snap-align: start;
}

.pc {
  --c: var(--volt-ink);
  position: relative;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: var(--surface);
  overflow: hidden;
  isolation: isolate;
  transform-style: preserve-3d;
  transition: border-color var(--t-mid), box-shadow 0.45s var(--e-out);
}
.pc:hover {
  border-color: color-mix(in srgb, var(--c) 62%, transparent);
  box-shadow: var(--shadow-sm),
    0 0 34px color-mix(in srgb, var(--c) var(--glow-soft), transparent);
}
/* cursor spotlight */
.pc-glow {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(
    170px circle at var(--mx, 50%) var(--my, 50%),
    color-mix(in srgb, var(--c) 22%, transparent),
    transparent 62%
  );
  transition: opacity 0.35s var(--e-out);
}
.pc:hover .pc-glow {
  opacity: 1;
}

.pc-media {
  position: relative;
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
  padding: 15%;
  background: linear-gradient(
    160deg,
    color-mix(in srgb, var(--c) 11%, transparent),
    transparent 60%
  );
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}
.pc-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.65s var(--e-out);
}
.pc:hover .pc-media img {
  transform: scale(1.07);
}
.pc-media svg.p-ic {
  width: 100%;
  height: 100%;
  overflow: visible;
  transition: transform 0.55s var(--e-out);
}
.pc:hover .pc-media svg.p-ic {
  transform: scale(1.07) rotate(-1.5deg);
}
.pc-badge {
  position: absolute;
  left: 11px;
  top: 11px;
  z-index: 2;
}
.pc-body {
  position: relative;
  z-index: 1;
  padding: var(--s-4) var(--s-4) var(--s-5);
  display: flex;
  flex-direction: column;
  gap: 7px;
  flex: 1;
}
.pc-cat {
  font-family: var(--f-mono);
  font-size: 0.6rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--c);
}
.pc-name {
  font-family: var(--f-cond);
  font-size: 1.16rem;
  font-weight: 700;
  letter-spacing: 0.015em;
  text-transform: uppercase;
  line-height: 1.12;
  color: var(--ink);
}
.pc-sub {
  font-size: 0.87rem;
  color: var(--ink-3);
  font-family: var(--f-mono);
}
.pc-foot {
  margin-top: auto;
  padding-top: var(--s-3);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.pc-moq {
  font-family: var(--f-mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  color: var(--ink-3);
}
.pc-cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--f-cond);
  font-size: 0.88rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink);
}
.pc-cta svg {
  width: 14px;
  height: 14px;
  transition: transform var(--t-mid);
}
.pc:hover .pc-cta svg {
  transform: translateX(4px);
}
.pc-link {
  position: absolute;
  inset: 0;
  z-index: 3;
}

/* empty state */
.empty {
  grid-column: 1 / -1;
  padding: clamp(48px, 8vw, 90px) var(--s-5);
  text-align: center;
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-panel);
}
/* ---------- SIZE GUIDE : charts and the custom sizing note --------------
   The charts sit left, the "we will build to yours" note sits beside them
   and keeps moving, because it is the single most useful sentence on the page
   and a static paragraph next to five tables never gets read. */

.sz-wrap {
  display: grid;
  gap: var(--s-5);
}
@media (min-width: 1000px) {
  .sz-wrap {
    grid-template-columns: minmax(0, 1fr) 320px;
    align-items: start;
    gap: var(--s-6);
  }
  .sz-wrap > .chip-row {
    grid-column: 1;
  }
  .sz-wrap > .tab-panel {
    grid-column: 1;
  }
  .sz-custom {
    grid-column: 2;
    grid-row: 1 / span 99;
    position: sticky;
    top: 96px;
  }
}
.sz-custom {
  padding: var(--s-5);
  border: 1px solid var(--volt);
  border-radius: var(--r-panel);
  background: color-mix(in srgb, var(--volt) 7%, transparent);
  overflow: hidden;
  position: relative;
}
/* a slow sheen crossing the panel: enough to catch the eye at the edge of
   vision without competing with the table being read */
.sz-custom::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    100deg,
    transparent 42%,
    color-mix(in srgb, var(--volt) 26%, transparent) 50%,
    transparent 58%
  );
  background-size: 260% 100%;
  animation: szSheen 7s linear infinite;
}
@keyframes szSheen {
  0% {
    background-position: 190% 0;
  }
  55%,
  100% {
    background-position: -90% 0;
  }
}
.sz-custom-tag {
  display: inline-block;
  margin-bottom: var(--s-3);
  padding: 5px 11px;
  border-radius: var(--r-pill);
  background: var(--volt);
  color: var(--on-volt);
  font-family: var(--f-mono);
  font-size: 0.58rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  /* a slow pulse on the tag alone, so the movement has a source */
  animation: szPulse 2.6s var(--e-inout) infinite;
}
@keyframes szPulse {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.06);
  }
}
.sz-custom-h {
  margin-bottom: 12px;
}
.sz-custom p {
  font-size: 0.93rem;
  margin-bottom: var(--s-4);
}
.sz-custom .btn {
  position: relative;
  z-index: 1;
}
@media (prefers-reduced-motion: reduce) {
  .sz-custom::after,
  .sz-custom-tag {
    animation: none;
  }
}
html.rx-lite .sz-custom::after,
html.rx-lite .sz-custom-tag {
  animation: none;
}

/* ---------- DOUBLE MARQUEE (homepage featured) --------------------------
   Two rows travelling against each other. The opposition is the whole point:
   a single scrolling strip reads as decoration, two moving apart read as a
   catalogue too big to fit on the page.

   Each row contains its cards twice, back to back, and translates by exactly
   -50%. At the end of the cycle the second copy sits precisely where the
   first began, so the loop restarts on an identical frame with no jump. */

.marquee {
  display: grid;
  gap: clamp(12px, 1.4vw, 18px);
  /* the rows run past the wrap, so the section clips them itself */
  margin-inline: calc(var(--pad-x) * -1);
  padding-inline: 0;
  overflow: hidden;
  /* fade both ends so cards enter and leave instead of being cut off */
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}
.mq-row {
  display: flex;
  gap: clamp(12px, 1.4vw, 18px);
  width: max-content;
  animation: mqRun 46s linear infinite;
}
.mq-rev {
  /* same keyframes, run backwards: one declaration instead of a second set */
  animation-direction: reverse;
  animation-duration: 54s;
}
.mq-row .pc {
  width: clamp(230px, 24vw, 300px);
  flex: none;
}
/* A buyer reading a card should not have it slide out from under them, but
   only the row being read stops. Hanging the rule off .marquee paused both
   rows at once: reaching for a card in the top row froze the bottom one too,
   which reads as the section having crashed rather than as it waiting.
   The row itself is the hover target, so the other keeps running. */
.mq-row:hover {
  animation-play-state: paused;
}
/* the rows sit edge to edge, so the pointer is over a row almost the whole
   time it is over the section; the grid gap is the only dead strip and it
   deliberately pauses nothing */
@keyframes mqRun {
  to {
    transform: translate3d(-50%, 0, 0);
  }
}
@media (prefers-reduced-motion: reduce) {
  .marquee {
    overflow-x: auto;
  }
  .mq-row {
    animation: none;
  }
}
html.rx-lite .mq-row {
  animation: none;
}
html.rx-lite .marquee {
  overflow-x: auto;
}

/* ---------- CATALOGUE FILTER RAIL --------------------------------------- */

.search-lg {
  flex: 1 1 380px;
}
.filters {
  display: grid;
  gap: var(--s-4);
  padding: var(--s-5);
  margin-bottom: var(--s-6);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: var(--surface);
}
.filter-row {
  display: grid;
  grid-template-columns: 118px 1fr;
  gap: var(--s-4);
  align-items: start;
}
.filter-row[hidden] {
  display: none;
}
.filter-lbl {
  font-family: var(--f-mono);
  font-size: 0.62rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding-top: 11px;
}
.filters .chip {
  min-height: 34px;
  font-size: 0.82rem;
}
.filters #f-clear {
  justify-self: start;
}
.more-row {
  display: flex;
  justify-content: center;
  margin-top: var(--s-7);
}
@media (max-width: 760px) {
  .filter-row {
    grid-template-columns: 1fr;
    gap: 8px;
  }
  .filter-lbl {
    padding-top: 0;
  }
  .filters {
    padding: var(--s-4);
  }
}

/* ---------- SUBCATEGORY GRID (category landing pages) ------------------- */

.sc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
  gap: clamp(12px, 1.4vw, 18px);
}
.sc-card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: var(--surface);
  overflow: hidden;
  isolation: isolate;
  transition: border-color var(--t-mid), transform 0.45s var(--e-out),
    box-shadow var(--t-mid);
}
.sc-card::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0;
  background: radial-gradient(
    110% 80% at 100% 0%,
    color-mix(in srgb, var(--c) 18%, transparent),
    transparent 65%
  );
  transition: opacity var(--t-mid);
}
.sc-card:hover {
  transform: translateY(-4px);
  border-color: color-mix(in srgb, var(--c) 55%, transparent);
  box-shadow: 0 0 40px color-mix(in srgb, var(--c) var(--glow-soft), transparent);
}
.sc-card:hover::before {
  opacity: 1;
}
.sc-n {
  font-family: var(--f-mono);
  font-size: 0.62rem;
  letter-spacing: 0.2em;
  color: var(--c, var(--volt-ink));
  margin-bottom: var(--s-4);
}
.sc-card h3 {
  font-size: clamp(1.15rem, 1.5vw, 1.42rem);
  margin-bottom: 8px;
}
.sc-card p {
  font-size: 0.92rem;
  margin-bottom: var(--s-5);
  flex: 1;
}
.sc-go {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--f-mono);
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
  transition: color var(--t-fast);
}
.sc-card:hover .sc-go {
  color: var(--ink);
}

/* related subcategory links on a subcategory page */
.rel-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.rel-links a {
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  font-family: var(--f-cond);
  font-size: 0.88rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-2);
  transition: color var(--t-fast), border-color var(--t-fast);
}
.rel-links a:hover {
  color: var(--ink);
  border-color: var(--line-strong);
}

.pc-quote {
  color: var(--ink-3);
}

/* product detail: section headings and unconfirmed spec values */
.pd-h {
  font-size: clamp(1.1rem, 1.5vw, 1.3rem);
  margin: var(--s-6) 0 var(--s-4);
}
.pd-spec b.tbc {
  color: var(--ink-3);
  font-weight: 500;
}
.pd .tag[href] {
  transition: color var(--t-fast), border-color var(--t-fast);
}
.pd .tag[href]:hover {
  color: var(--ink);
  border-color: var(--line-strong);
}

.empty h1,
.empty h3 {
  margin-bottom: 10px;
}
/* the not-found state carries the page's only h1, so it is pinned to the h3
   size rather than the display scale */
.empty h1 {
  font-size: clamp(1.3rem, 2.1vw, 1.85rem);
  letter-spacing: -0.025em;
}
.empty p {
  margin: 0 auto var(--s-5);
}

/* ---------- 8. CAPABILITY BENTO ----------------------------------------- */

.bento {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: clamp(14px, 1.7vw, 22px);
}
.bx {
  position: relative;
  padding: clamp(22px, 2.4vw, 34px);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: var(--surface);
  overflow: hidden;
  isolation: isolate;
  transition: border-color var(--t-mid), transform 0.45s var(--e-out);
}
.bx:hover {
  border-color: var(--line-strong);
  transform: translateY(-3px);
}
.bx h3 {
  /* these are h3 for the document outline but keep the h4 scale, so a
     card title never competes with the section heading above it */
  font-size: clamp(1.02rem, 1.3vw, 1.18rem);
  letter-spacing: -0.012em;
  line-height: 1.2;
  margin-bottom: 9px;
}
.bx p {
  font-size: 0.93rem;
}
.bx-ico {
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  color: var(--volt-ink);
  margin-bottom: var(--s-5);
}
.bx-ico svg {
  width: 19px;
  height: 19px;
}
.bx-a {
  grid-column: span 3;
}
.bx-b {
  grid-column: span 3;
}
.bx-c {
  grid-column: span 2;
}
.bx-wide {
  grid-column: span 6;
}
/* visual variation so the grid is not 6 flat text cards */
.bx-fill {
  background: linear-gradient(
      142deg,
      color-mix(in srgb, var(--volt) 20%, transparent),
      transparent 58%
    ),
    var(--surface);
}
.bx-dots::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: radial-gradient(var(--line-strong) 1px, transparent 1.05px);
  background-size: 13px 13px;
  opacity: 0.5;
  mask-image: linear-gradient(230deg, #000, transparent 66%);
  -webkit-mask-image: linear-gradient(230deg, #000, transparent 66%);
}
.bx-rules::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: repeating-linear-gradient(
    -45deg,
    var(--line-faint) 0 1px,
    transparent 1px 11px
  );
}
.bx-big {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: 250px;
}
.bx-stat {
  font-family: var(--f-display);
  font-weight: 800;
  font-size: clamp(2.6rem, 5vw, 4.2rem);
  line-height: 0.94;
  letter-spacing: -0.05em;
  color: var(--ink);
}
.bx-stat small {
  font-size: 0.34em;
  color: var(--volt-ink);
  vertical-align: super;
  margin-left: 2px;
}
@media (max-width: 940px) {
  .bento {
    grid-template-columns: repeat(2, 1fr);
  }
  .bx-a,
  .bx-b,
  .bx-c,
  .bx-wide {
    grid-column: span 2;
  }
}

/* ---------- 9. STATS BAND ----------------------------------------------- */

.stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s-5);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding-block: clamp(34px, 4.4vw, 60px);
}
.stat {
  padding-right: var(--s-5);
  border-right: 1px solid var(--line);
}
.stat:last-child {
  border-right: 0;
}
.stat b {
  display: block;
  font-family: var(--f-display);
  font-weight: 800;
  font-size: clamp(2.4rem, 5.2vw, 4rem);
  line-height: 0.94;
  letter-spacing: -0.05em;
  font-variant-numeric: tabular-nums;
}
.stat b i {
  font-style: normal;
  color: var(--volt-ink);
}
.stat span {
  display: block;
  margin-top: 9px;
  font-family: var(--f-mono);
  font-size: 0.66rem;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--ink-3);
}
@media (max-width: 760px) {
  .stats {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--s-6) var(--s-4);
  }
  .stat:nth-child(2) {
    border-right: 0;
  }
}

/* ---------- 10. TESTIMONIALS -------------------------------------------- */

.quotes {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(14px, 1.7vw, 22px);
}
.quote {
  padding: clamp(22px, 2.4vw, 34px);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: var(--surface);
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
  transition: border-color var(--t-mid), transform 0.45s var(--e-out);
}
.quote:hover {
  border-color: var(--line-strong);
  transform: translateY(-3px);
}
.quote blockquote {
  font-family: var(--f-cond);
  font-size: clamp(1.1rem, 1.6vw, 1.34rem);
  font-weight: 500;
  line-height: 1.34;
  letter-spacing: 0.005em;
  color: var(--ink);
}
.quote figcaption {
  margin-top: auto;
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: 12px;
}
.q-mono {
  width: 42px;
  height: 42px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-family: var(--f-display);
  font-weight: 800;
  font-size: 1rem;
  letter-spacing: -0.03em;
  color: var(--volt-ink);
}
.q-who b {
  display: block;
  font-family: var(--f-cond);
  font-size: 1.03rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}
.q-who span {
  display: block;
  font-family: var(--f-mono);
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  color: var(--ink-3);
  margin-top: 2px;
}
@media (max-width: 900px) {
  .quotes {
    grid-template-columns: 1fr;
  }
}

/* ---------- 11. FAQ / ACCORDION ----------------------------------------- */

.faq {
  border-top: 1px solid var(--line);
}
.faq details {
  border-bottom: 1px solid var(--line);
}
.faq summary {
  list-style: none;
  cursor: pointer;
  padding: var(--s-5) 44px var(--s-5) 0;
  position: relative;
  font-family: var(--f-cond);
  font-size: clamp(1.08rem, 1.7vw, 1.34rem);
  font-weight: 600;
  letter-spacing: 0.015em;
  color: var(--ink);
  transition: color var(--t-fast);
}
.faq summary::-webkit-details-marker {
  display: none;
}
.faq summary:hover {
  color: var(--volt-ink);
}
.faq summary::after {
  content: '';
  position: absolute;
  right: 10px;
  top: 50%;
  width: 13px;
  height: 2px;
  background: currentColor;
  transform: translateY(-50%);
}
.faq summary::before {
  content: '';
  position: absolute;
  right: 15.5px;
  top: 50%;
  width: 2px;
  height: 13px;
  background: currentColor;
  transform: translateY(-50%);
  transition: transform var(--t-mid), opacity var(--t-mid);
}
.faq details[open] summary::before {
  transform: translateY(-50%) rotate(90deg);
  opacity: 0;
}
.faq-body {
  padding-bottom: var(--s-5);
  max-width: 70ch;
}
.faq-body p + p {
  margin-top: var(--s-3);
}

/* ---------- 12. CTA BAND ------------------------------------------------ */

.cta-band {
  position: relative;
  overflow: hidden;
  background: var(--volt);
  padding-block: clamp(56px, 8vw, 108px);
  /* the band is always volt, so it carries its own ink scale. Without this
     the inherited near-white text lands on lime and fails contrast. */
  --ink: #0a0b0e;
  --ink-2: rgba(10, 11, 14, 0.8);
  --ink-3: rgba(10, 11, 14, 0.68);
  --line: rgba(10, 11, 14, 0.2);
  --line-strong: rgba(10, 11, 14, 0.4);
  --volt-ink: #0a0b0e;
  --surface: rgba(10, 11, 14, 0.06);
  --surface-2: rgba(10, 11, 14, 0.1);
  color: var(--ink);
}
.cta-band .kv dd a {
  text-decoration-color: transparent;
  text-underline-offset: 4px;
  transition: text-decoration-color var(--t-fast);
}
.cta-band .kv dd a:hover {
  text-decoration: underline;
  text-decoration-color: currentColor;
}
.cta-band::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgba(10, 11, 14, 0.19) 1.2px, transparent 1.25px);
  background-size: 15px 15px;
  mask-image: linear-gradient(160deg, #000, transparent 72%);
  -webkit-mask-image: linear-gradient(160deg, #000, transparent 72%);
}
.cta-band .wrap {
  position: relative;
  z-index: 1;
}
.cta-band h2 {
  color: var(--on-volt);
  max-width: 15ch;
  margin-bottom: var(--s-5);
}
.cta-band p {
  color: rgba(10, 11, 14, 0.72);
  max-width: 50ch;
  margin-bottom: var(--s-6);
}
.cta-band .btn-primary {
  background: var(--on-volt);
  color: var(--volt);
  border-color: var(--on-volt);
}
.cta-band .btn-primary::after {
  background: #ffffff;
}
.cta-band .btn-primary:hover {
  color: var(--on-volt);
}
.cta-band .btn-ghost {
  color: var(--on-volt);
  border-color: rgba(10, 11, 14, 0.38);
}
.cta-band .btn-ghost::after {
  background: var(--on-volt);
}
.cta-band .btn-ghost:hover {
  color: var(--volt-ink);
  border-color: var(--on-volt);
}
.cta-split {
  display: grid;
  grid-template-columns: 1.25fr 1fr;
  gap: var(--s-7);
  align-items: end;
}
@media (max-width: 860px) {
  .cta-split {
    grid-template-columns: 1fr;
    gap: var(--s-5);
  }
}

/* ---------- 13. PAGE HEAD (inner pages) --------------------------------- */

.phead {
  --c: var(--volt-ink);
  position: relative;
  padding-block: clamp(56px, 8vw, 112px) clamp(40px, 5vw, 64px);
  overflow: hidden;
  border-bottom: 1px solid var(--line);
}
.phead::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(
    62% 100% at 84% 0%,
    color-mix(in srgb, var(--c) 18%, transparent),
    transparent 68%
  );
}
.phead .wrap {
  position: relative;
  z-index: 1;
}
.phead h1 {
  font-size: clamp(2.4rem, 6.2vw, 5rem);
  max-width: 15ch;
}
.phead .lede {
  margin-top: var(--s-5);
}
.crumb {
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: var(--f-mono);
  font-size: 0.66rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s-5);
}
.crumb a:hover {
  color: var(--volt-ink);
}
/* THE WORD BEHIND THE HEADING.
   Measured on /sportswear/soccer/ it was 253px tall, sat at bottom: -34%
   inside a section with overflow: hidden, and had 180 of its 202 rendered
   pixels cut off - 11 percent of the word was visible. The stroke was
   rgba(10,11,14,.28) at opacity .5, an effective alpha of about .14. So it
   read as a rendering fault rather than as a design device: a few grey
   fragments along the bottom edge, chopped again on the right.

   Rebuilt so the crop is obviously deliberate. The word sits on the section's
   baseline with roughly two thirds showing, which is the way a stadium or kit
   graphic bleeds off an edge. It is sized to fit rather than to overflow, and
   it takes the line's own accent colour instead of flat grey, so the
   sportswear page reads orange, combat red, workwear steel blue.

   One transform animation, composited, and it stops when the section is off
   screen because .rx-rest already pauses everything inside a resting
   section. */
.phead-word {
  position: absolute;
  right: -1.5%;
  bottom: -7%;
  z-index: 0;
  font-size: clamp(4rem, 13.5vw, 11.5rem);
  opacity: 1;
  white-space: nowrap;
  -webkit-text-stroke: 2px color-mix(in srgb, var(--c, var(--line-strong)) 38%, transparent);
  animation: ghostDrift 26s ease-in-out infinite alternate;
}

/* The drift is deliberately small. It is there to stop the header feeling
   like a flat printed page, not to be noticed on its own. */
@keyframes ghostDrift {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-2.2%, 0, 0); }
}

/* -webkit-text-stroke is non standard. Where it is missing the letters would
   be transparent with nothing drawing them, so the word would simply vanish -
   a colour is set as the floor and the stroke refines it where supported. */
@supports not ((-webkit-text-stroke: 1px black) or (text-stroke: 1px black)) {
  .phead-word {
    color: color-mix(in srgb, var(--c, var(--line-strong)) 13%, transparent);
  }
}

@media (prefers-reduced-motion: reduce) {
  .phead-word { animation: none; }
}

/* A phone has no room for a 12 character word at this size; it becomes a wall
   of stroke behind the h1 rather than a backdrop to it. */
@media (max-width: 640px) {
  .phead-word {
    font-size: clamp(3.4rem, 22vw, 6rem);
    bottom: -5%;
    -webkit-text-stroke-width: 1.5px;
  }
}

/* ---------- 14. SPLIT / EDITORIAL --------------------------------------- */

.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(28px, 4vw, 68px);
  align-items: center;
}
.split-7-5 {
  grid-template-columns: 1.32fr 1fr;
}
@media (max-width: 900px) {
  .split,
  .split-7-5 {
    grid-template-columns: 1fr;
  }
}

.checks {
  display: grid;
  gap: var(--s-3);
  margin-top: var(--s-5);
}
.checks li {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  font-size: 0.98rem;
  color: var(--ink-2);
}
.checks svg {
  width: 19px;
  height: 19px;
  flex: none;
  margin-top: 3px;
  color: var(--volt-ink);
}

/* number-led feature rows (replaces long bulleted lists) */
.rows {
  border-top: 1px solid var(--line);
}
.rows-item {
  display: grid;
  grid-template-columns: 78px 1fr;
  gap: var(--s-5);
  padding-block: var(--s-5);
  border-bottom: 1px solid var(--line);
  align-items: start;
  transition: background-color var(--t-mid);
}
.rows-item:hover {
  background: var(--surface);
}
.rows-item b {
  font-family: var(--f-display);
  font-weight: 800;
  font-size: 1.6rem;
  letter-spacing: -0.04em;
  color: transparent;
  -webkit-text-stroke: 1.4px var(--ink-3);
}
.rows-item:hover b {
  color: var(--volt-ink);
  -webkit-text-stroke: 0;
}
.rows-item h3 {
  /* these are h3 for the document outline but keep the h4 scale, so a
     card title never competes with the section heading above it */
  font-size: clamp(1.02rem, 1.3vw, 1.18rem);
  letter-spacing: -0.012em;
  line-height: 1.2;
  margin-bottom: 5px;
}
.rows-item p {
  font-size: 0.94rem;
}
@media (max-width: 620px) {
  .rows-item {
    grid-template-columns: 50px 1fr;
    gap: var(--s-4);
  }
}

/* ---------- 15. PRODUCT DETAIL ------------------------------------------ */

.pd {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: clamp(28px, 4vw, 64px);
  align-items: start;
}
.pd-media {
  --c: var(--volt-ink);
  position: relative;
  aspect-ratio: 1 / 1;
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: linear-gradient(
      160deg,
      color-mix(in srgb, var(--c) 15%, transparent),
      transparent 60%
    ),
    var(--surface);
  display: grid;
  place-items: center;
  padding: 12%;
  overflow: hidden;
  position: sticky;
  top: 92px;
}
.pd-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.pd-media svg.p-ic {
  width: 100%;
  height: 100%;
  overflow: visible;
}
.pd h1 {
  font-size: clamp(2rem, 4vw, 3.1rem);
  margin-bottom: var(--s-4);
}
.pd-spec {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--s-4);
  margin: var(--s-6) 0;
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: var(--surface);
}
.pd-spec div span {
  display: block;
  font-family: var(--f-mono);
  font-size: 0.6rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 4px;
}
.pd-spec div b {
  font-family: var(--f-cond);
  font-size: 1.06rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
@media (max-width: 900px) {
  .pd {
    grid-template-columns: 1fr;
  }
  .pd-media {
    position: relative;
    top: 0;
  }
}

/* size table */
.tbl-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
}
table.tbl {
  width: 100%;
  border-collapse: collapse;
  min-width: 460px;
  font-family: var(--f-mono);
  font-size: 0.83rem;
}
table.tbl th,
table.tbl td {
  padding: 11px 14px;
  text-align: left;
  border-bottom: 1px solid var(--line);
}
table.tbl th {
  background: var(--surface-2);
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 500;
}
table.tbl tr:last-child td {
  border-bottom: 0;
}
table.tbl td {
  color: var(--ink-2);
}
table.tbl td:first-child {
  color: var(--ink);
  font-weight: 500;
}

/* ---------- 16. FORMS --------------------------------------------------- */

.form {
  display: grid;
  gap: var(--s-5);
}
.f2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-5);
}
@media (max-width: 640px) {
  .f2 {
    grid-template-columns: 1fr;
  }
}
.field {
  display: grid;
  gap: 8px;
}
.field label {
  font-family: var(--f-mono);
  font-size: 0.65rem;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.field label .req {
  color: var(--volt-ink);
}
.field input,
.field select,
.field textarea {
  width: 100%;
  min-height: 52px;
  padding: 14px 17px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-input);
  color: var(--ink);
  font-size: 1rem;
  transition: border-color var(--t-fast), background-color var(--t-fast);
}
.field textarea {
  min-height: 132px;
  resize: vertical;
  line-height: 1.6;
}
.field input::placeholder,
.field textarea::placeholder {
  color: var(--ink-3);
  opacity: 1;
}
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--volt);
  background: var(--surface-2);
}
/* The rule above drops the global focus ring and replaces it with a 1px
   border colour. That reads fine for a mouse user who already knows where
   they clicked, and it is the weakest possible signal for someone arriving by
   keyboard - on the quote form, which is the one thing every path on this
   site leads to. :focus-visible puts the ring back for exactly that case and
   leaves the mouse styling alone. */
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  outline: 3px solid var(--volt);
  outline-offset: 2px;
}
.field .help {
  font-size: 0.82rem;
  color: var(--ink-3);
}
.field .err {
  font-size: 0.82rem;
  color: #ff6a5c;
  display: none;
}
.field.bad input,
.field.bad select,
.field.bad textarea {
  border-color: #ff6a5c;
}
.field.bad .err {
  display: block;
}
.form-note {
  font-size: 0.85rem;
  color: var(--ink-3);
}
.form-ok {
  display: none;
  padding: var(--s-5);
  border: 1px solid var(--volt);
  border-radius: var(--r-panel);
  background: color-mix(in srgb, var(--volt) 12%, transparent);
}
.form-ok.show {
  display: block;
}

/* ---------- 17. TABS ----------------------------------------------------- */

.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  border-bottom: 1px solid var(--line);
  padding-bottom: var(--s-4);
  margin-bottom: var(--s-6);
}
.tab-panel {
  display: none;
}
.tab-panel.on {
  display: block;
}

/* ---------- 18. TOOLBAR (products page) --------------------------------- */

.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  align-items: center;
  justify-content: space-between;
  padding-block: var(--s-5);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--s-6);
}
.search {
  position: relative;
  flex: 1;
  min-width: 220px;
  max-width: 340px;
}
.search input {
  width: 100%;
  min-height: 46px;
  padding: 0 16px 0 44px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  color: var(--ink);
}
.search input:focus {
  outline: none;
  border-color: var(--volt);
}
/* same reasoning as the form fields: the border colour is the mouse
   affordance, the ring is the keyboard one */
.search input:focus-visible {
  outline: 3px solid var(--volt);
  outline-offset: 2px;
}
.search svg {
  position: absolute;
  left: 16px;
  top: 50%;
  transform: translateY(-50%);
  width: 17px;
  height: 17px;
  color: var(--ink-3);
  pointer-events: none;
}
.count {
  font-family: var(--f-mono);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* ---------- 19. ADMIN --------------------------------------------------- */

.adm-gate {
  min-height: 78vh;
  display: grid;
  place-items: center;
  padding: var(--s-7) 0;
}
.adm-card {
  width: min(430px, 92vw);
  padding: clamp(26px, 3vw, 38px);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: var(--surface);
}
.adm-card h2 {
  font-size: 1.9rem;
  margin-bottom: 8px;
}
.adm-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: var(--s-6);
}
.adm-list {
  display: grid;
  gap: 10px;
}
.adm-row {
  display: grid;
  grid-template-columns: 58px 1fr auto;
  gap: var(--s-4);
  align-items: center;
  padding: 11px;
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: var(--surface);
}
.adm-thumb {
  width: 58px;
  height: 58px;
  border-radius: var(--r-input);
  border: 1px solid var(--line);
  background: var(--surface-2);
  display: grid;
  place-items: center;
  overflow: hidden;
  padding: 7px;
}
.adm-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.adm-row b {
  display: block;
  font-family: var(--f-cond);
  font-size: 1.04rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.adm-row span {
  font-family: var(--f-mono);
  font-size: 0.66rem;
  letter-spacing: 0.11em;
  color: var(--ink-3);
}
.adm-acts {
  display: flex;
  gap: 7px;
}
.icon-btn {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  color: var(--ink-2);
  transition: color var(--t-fast), border-color var(--t-fast);
}
.icon-btn:hover {
  color: var(--ink);
  border-color: var(--line-strong);
}
.icon-btn.danger:hover {
  color: #ff6a5c;
  border-color: #ff6a5c;
}
.icon-btn svg {
  width: 16px;
  height: 16px;
}
.modal {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: none;
  place-items: center;
  padding: var(--s-5);
  background: rgba(4, 5, 7, 0.62);
  backdrop-filter: blur(6px);
}
.modal.open {
  display: grid;
}
.modal-in {
  width: min(720px, 96vw);
  max-height: 88vh;
  overflow-y: auto;
  padding: clamp(22px, 3vw, 34px);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: var(--bg-2);
}
.toast {
  position: fixed;
  left: 50%;
  bottom: 26px;
  transform: translate(-50%, 130%);
  z-index: 95;
  padding: 13px 22px;
  border-radius: var(--r-pill);
  background: var(--volt);
  color: var(--on-volt);
  font-family: var(--f-cond);
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  transition: transform 0.45s var(--e-out);
}
.toast.show {
  transform: translate(-50%, 0);
}

/* ---------- 20. RESPONSIVE ROLL-UP -------------------------------------- */

@media (max-width: 1040px) {
  .hero-grid {
    grid-template-columns: 1fr;
    gap: var(--s-7);
  }
  /* the ghost wordmark only reads as intentional behind the split layout */
  .hero-word {
    display: none;
  }
  .hero-copy {
    max-width: none;
  }
  .hero h1 .ln {
    white-space: normal;
  }
  .poster-stack .poster:nth-child(1) {
    margin-top: 0;
  }
}
@media (max-width: 620px) {
  .poster-stack {
    grid-template-columns: repeat(3, 74vw);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    padding-bottom: var(--s-4);
    margin-inline: calc(var(--pad-x) * -1);
    padding-inline: var(--pad-x);
    scrollbar-width: none;
  }
  .poster-stack::-webkit-scrollbar {
    display: none;
  }
  .poster-stack .poster {
    scroll-snap-align: center;
    margin-top: 0 !important;
    grid-row: auto !important;
    aspect-ratio: 3 / 4;
  }
  .p-grid {
    grid-template-columns: repeat(auto-fill, minmax(158px, 1fr));
    gap: 12px;
  }
  .pc-name {
    font-size: 1rem;
  }
  .pc-body {
    padding: 12px 12px 16px;
  }
  .btn {
    min-height: 46px;
  }
}

/* ---------- OFF SCREEN REST ---------------------------------------------
   Every looping animation on this site was running all the time, including
   the ones four screens above or below the fold. A paused animation costs
   nothing; a running one costs a frame of compositor work forever, and the
   homepage carries eight of them at once.

   RX.rest() in app.js marks a section .rx-rest whenever it is outside the
   viewport, and clears the mark when it comes back. The class is applied to
   the section, never to the animated element itself, so the animation keeps
   its own state and resumes mid stride instead of snapping back to frame one.

   Everything named here is decorative and infinite. Entrance animations are
   deliberately left out: they only ever run while their section is on screen,
   and pausing one halfway would freeze it in a half drawn state. */

.rx-rest .hw-stack,
.rx-rest .hw-tilt,
.rx-rest .hw-sheen,
.rx-rest .mq-row,
.rx-rest .slant-track,
.rx-rest .ticker-track,
.rx-rest .hb-slide.is-on .hb-art svg,
.rx-rest .hb-dot.is-on i {
  animation-play-state: paused;
}

/* A hidden tab is throttled, not stopped: the compositor still services
   animations that have been promoted to their own layer, which is why a
   backgrounded page can keep a laptop fan running. Nothing is visible, so
   nothing needs to move. */
html.rx-away .phead-word,
html.rx-away .hw-stack,
html.rx-away .hw-tilt,
html.rx-away .hw-sheen,
html.rx-away .mq-row,
html.rx-away .slant-track,
html.rx-away .ticker-track,
html.rx-away .hb-slide.is-on .hb-art svg,
html.rx-away .hb-dot.is-on i {
  animation-play-state: paused;
}

/* ---------- TARGET SIZE (WCAG 2.5.8) -----------------------------------
   Several links rendered under the 24px minimum: the phone number and email
   address wherever the .kv list is used (20px tall), the legal row at the
   very bottom (15px), and the breadcrumb links (14 to 18px). All of them are
   standalone links rather than links inside a sentence, so the "inline"
   exception in 2.5.8 does not cover them, and 14px is a genuinely awkward
   thumb target.

   On the inline elements the padding goes on an inline box deliberately: it
   grows the hit area without growing the line box, so the type size, the
   leading and the footer's vertical rhythm are all untouched.

   The breadcrumb is the one place the row does grow, by six pixels, because
   its links are flex items and their padding is part of the layout. That is
   the whole visual change and it buys a crumb trail that can actually be
   tapped. */
.kv dd a,
.foot-bot a,
.pd-spec a {
  display: inline-block;
  padding-block: 5px;
  /* a three letter subcategory - "BJJ", "MMA" - is narrower than the floor */
  min-width: 24px;
}

/* min-height rather than padding, because the crumb holds two different type
   sizes: the top level links run at 0.66rem and the ones product.js writes
   inside #pd-crumb at 0.62rem, so a single padding value overshoots one and
   leaves the other at 22px. A floor hits 24 for both. */
.crumb a,
.crumb [aria-current='page'] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 24px;
  /* a short label - "BJJ" - is only as wide as its text, which left it at
     23.6px and just under the floor on the narrow breakpoint */
  min-width: 24px;
}
