/* Purpose: Shared components - buttons, eyebrow, cards, forms, header, footer, drawer.
   BEM naming. .js- prefixed classes are behaviour hooks and are never styled here. */

/* ============================================================
   EYEBROW - pentagon marker, the BeeZeta1 cage motif
   ============================================================ */
.eyebrow{
  display:flex;align-items:center;gap:14px;
  font-family:var(--font-body);
  font-size:var(--fs-12);
  font-weight:var(--weight-semibold);
  line-height:20px;
  letter-spacing:2px;
  text-transform:uppercase;
  color:var(--c-crimson);
  margin-bottom:0;
}
/* The square red marker the design puts before every eyebrow. */
.eyebrow::before{
  content:"";flex:none;
  width:6px;height:6px;
  background:var(--c-crimson);
  border-radius:3px;
}
.eyebrow--center{justify-content:center}
/* The label is one line in the design. Where it has to wrap - a long label on a narrow
   screen - the flex row leaves the dot stranded at the far left, because the text block
   centres its own lines inside a box the dot sits outside of. Letting the dot flow inline
   instead keeps it against the first word, and the whole thing still centres. */
@media (max-width:767px){
  .eyebrow--center{display:block;text-align:center}
  .eyebrow--center::before{display:inline-block;vertical-align:middle;margin-right:14px}
}

/* ============================================================
   BUTTONS
   16px Montserrat, 2px tracking, uppercase, 4px radius, 16/32 padding.

   Hover is a lift + a diagonal light sweep + a colour-matched glow, not
   just a flat colour swap - one shared ::before handles the sweep for
   every variant, so a new .btn-- modifier only has to set a colour.
   ============================================================ */
/* Matches the real ATC button (.woocommerce .button in woocommerce.css) byte-for-byte,
   so every button on the site - hero, footer, drawer, cart, checkout, my-account, product
   cards - reads as the same control. That WC rule is unconditional (no breakpoint of its
   own), so this one carries no separate mobile override either - one size, everywhere. */
.btn{
  position:relative;overflow:hidden;isolation:isolate;
  display:inline-flex;align-items:center;justify-content:center;gap:var(--space-8);
  font-family:var(--font-body);
  font-weight:var(--weight-medium);
  font-size:13px;
  line-height:24px;
  letter-spacing:1.5px;
  text-transform:uppercase;
  padding:var(--space-12) var(--space-24);
  min-height:0;
  border-radius:var(--r-sm);
  border:1px solid transparent;
  text-align:center;
  transition:background var(--dur-base) var(--ease-out),
             color var(--dur-base) var(--ease-out),
             border-color var(--dur-base) var(--ease-out),
             transform var(--dur-base) var(--ease-spring),
             box-shadow var(--dur-slow) var(--ease-out);
}
/* The sweep. Sits between the button's own background and its label -
   isolation:isolate on .btn gives every child a fresh stacking order, so
   this needs no z-index gymnastics to land in the right place. */
.btn::before{
  content:"";position:absolute;inset:0;
  background:linear-gradient(115deg,transparent 28%,rgba(255,255,255,.6) 50%,transparent 72%);
  transform:translateX(-140%) skewX(-12deg);
  transition:transform .85s var(--ease-out);
  pointer-events:none;
}
.btn:hover{transform:translateY(-3px)}
.btn:hover::before{transform:translateX(140%) skewX(-12deg)}
.btn:active{transform:translateY(-1px) scale(.98);transition-duration:var(--dur-fast)}
.btn:focus-visible{outline:2px solid var(--c-accent-high);outline-offset:3px}

.btn svg{position:relative;flex:none;transition:transform var(--dur-base) var(--ease-spring)}
.btn:hover svg{transform:translateX(var(--space-4))}

/* The label sits above the sweep explicitly, so it never dims mid-hover. */
.btn > :not(svg){position:relative}

.btn--primary,.btn--crimson{background:var(--c-crimson);color:var(--c-text-on-brand)}
.btn--primary:hover,.btn--crimson:hover{background:var(--c-primary-hover);box-shadow:var(--shadow-crimson)}

.btn--ghost{border-color:var(--c-text);color:var(--c-text);background:transparent}
.btn--ghost:hover{background:var(--c-text);color:var(--c-bg);box-shadow:var(--shadow-md);border-color:var(--c-text)}

@media (prefers-reduced-motion:reduce){
  .btn{transition:background var(--dur-fast) linear,color var(--dur-fast) linear,border-color var(--dur-fast) linear}
  .btn::before{display:none}
  .btn:hover,.btn:active{transform:none}
  .btn:hover svg{transform:none}
}

.btn--sm{padding:var(--space-12) var(--space-24);min-height:48px;font-size:var(--fs-caption)}
.btn--block{width:100%}

/* Per-letter reveal on the label. Words are kept whole so a label never breaks
   between letters. */
.btn__label{display:inline}
.btn__word{display:inline-block;white-space:nowrap}
.btn__letter{display:inline-block}
@media (prefers-reduced-motion:no-preference){
  .btn__letter{
    opacity:0;
    transform:translateY(0.4em);
    animation:btn-letter var(--dur-base) var(--ease-out) forwards;
    animation-delay:calc(var(--i, 0) * 22ms);
  }
  .reveal:not(.is-in) .btn__letter{animation:none;opacity:0}
}
@keyframes btn-letter{to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  .btn__letter{opacity:1;transform:none;animation:none}
}

/* Underlined text link with a small chevron - the design's card link. */
.tlink{
  display:inline-flex;align-items:center;gap:6px;
  font-family:var(--font-heading);
  font-weight:var(--weight-regular);
  font-size:var(--fs-12);
  line-height:22px;
  letter-spacing:2px;
  text-transform:uppercase;
  text-decoration:underline;
  text-underline-offset:3px;
  color:var(--c-text);
  transition:color var(--dur-base) var(--ease-out);
}
/* The exported arrow points down; the design turns it a quarter turn to point along the
   line of the link. Orientation is held on `rotate` and the hover nudge on `translate` -
   both standalone properties, which compose in a fixed order. Putting the nudge on
   `transform` instead would apply it after the rotation, sending the arrow upwards. */
.tlink img,.tlink svg{
  width:12px;height:12px;flex:none;
  rotate:-90deg;
  translate:0 0;
  transition:translate var(--dur-base) var(--ease-out);
}
.tlink:hover{color:var(--c-accent)}
.tlink:hover img,.tlink:hover svg{translate:var(--space-4) 0}

/* ============================================================
   ICON BADGE
   A red rounded square carrying a white line icon. The reference uses this
   as the marker on every feature and pillar card.
   ============================================================ */
.icon-badge{
  display:inline-flex;align-items:center;justify-content:center;
  width:var(--space-40);height:var(--space-40);
  flex:none;
  background:var(--c-crimson);
  color:var(--c-text-on-brand);
  border-radius:var(--r-md);
}
.icon-badge img,.icon-badge svg{width:var(--icon-20);height:var(--icon-20)}
.icon-badge--lg{width:var(--space-48);height:var(--space-48)}
.icon-badge--lg svg{width:var(--icon-24);height:var(--icon-24)}

/* ============================================================
   CARD - the base surface every card variant extends
   ============================================================ */
.card{
  background:transparent;
  border:1px solid var(--c-border);
  border-radius:var(--r-card);
  padding:var(--space-32);
  height:100%;
  display:flex;flex-direction:column;
  transition:border-color var(--dur-base) var(--ease-out),
             background var(--dur-base) var(--ease-out);
}
.card:hover{border-color:var(--c-border-strong)}
.card--interactive:hover{
  border-color:var(--c-border-strong);
  background:var(--c-surface-raised);
  transform:translateY(-4px);
}
.card__icon{
  width:var(--icon-40);height:var(--icon-40);
  color:var(--c-accent);
  margin-bottom:var(--space-24);
}
.card__title{
  font-family:var(--font-body);
  font-size:var(--fs-lead);
  font-weight:var(--weight-semibold);
  letter-spacing:normal;
  line-height:1.3;
  margin-top:var(--space-32);
  margin-bottom:var(--space-12);
}
.card__text{color:var(--c-text-muted);font-size:var(--fs-caption);line-height:1.6}
.card__link{margin-top:auto;padding-top:var(--space-24)}

/* Stat card - the number-led trust card */
.stat{
  border-top:1px solid var(--c-border);
  padding-top:var(--space-24);
}
.stat__num{
  font-family:var(--font-heading);
  font-size:var(--fs-h3);
  font-weight:var(--weight-semibold);
  letter-spacing:var(--tracking-tight);
  line-height:var(--lh-tight);
  color:var(--c-text);
}
.stat__cap{
  font-family:var(--font-mono);
  font-size:var(--fs-caption);
  letter-spacing:var(--tracking-wide);
  text-transform:uppercase;
  color:var(--c-accent);
  margin-top:var(--space-8);
}
.stat__text{
  color:var(--c-text-muted);
  font-size:var(--fs-body);
  line-height:var(--lh-loose);
  margin-top:var(--space-12);
}

/* Checklist with pentagon bullets */
.checklist{display:flex;flex-wrap:wrap;gap:var(--space-12) var(--space-24)}
.checklist li{
  display:inline-flex;align-items:center;gap:var(--space-8);
  color:var(--c-text-muted);font-size:var(--fs-body);
}
.checklist li::before{
  content:"";width:var(--space-8);height:var(--space-8);flex:none;
  background:var(--c-accent);clip-path:var(--pentagon);
}

/* Pill / tag row */
.pills{display:flex;flex-wrap:wrap;gap:var(--space-8)}
.pill{
  display:inline-flex;align-items:center;
  font-family:var(--font-mono);
  font-size:var(--fs-caption);
  letter-spacing:var(--tracking-wide);
  text-transform:uppercase;
  color:var(--c-text-muted);
  border:1px solid var(--c-border);
  border-radius:var(--r-full);
  padding:var(--space-8) var(--space-16);
}
.pill--accent{color:var(--c-accent);border-color:var(--c-border-strong)}

/* Media frame - deliberate aspect ratios, no CLS */
.media{
  position:relative;overflow:hidden;
  border:1px solid var(--c-border);
  border-radius:var(--r-hairline);
  background:var(--c-bg-alt);
}
.media img,.media video{width:100%;height:100%;object-fit:cover}
.media--16x9{aspect-ratio:16/9}
.media--4x3{aspect-ratio:4/3}
.media--1x1{aspect-ratio:1/1}
.media--4x5{aspect-ratio:4/5}

/* ============================================================
   FORMS
   ============================================================ */
.field{display:flex;flex-direction:column;gap:var(--space-8)}
.field__label{
  font-family:var(--font-mono);
  font-size:var(--fs-caption);
  letter-spacing:var(--tracking-wide);
  text-transform:uppercase;
  color:var(--c-text-muted);
}
.field__label .req{color:var(--c-crimson-light)}
.field__control,
.rte input[type="text"],.rte input[type="email"],.rte textarea{
  width:100%;
  min-height:var(--space-48);
  padding:var(--space-12) var(--space-16);
  background:var(--c-bg-alt);
  border:1px solid var(--c-border);
  border-radius:var(--r-hairline);
  color:var(--c-text);
  font-family:var(--font-body);
  font-size:var(--fs-body);
  transition:border-color var(--dur-base) var(--ease-out);
}
textarea.field__control{min-height:var(--space-128);resize:vertical;line-height:var(--lh-normal)}
select.field__control{appearance:none;cursor:pointer}
.field__control::placeholder{color:var(--c-text-dim)}
.field__control:focus{border-color:var(--c-accent);outline:none}
.field__control:focus-visible{outline:2px solid var(--c-accent-high);outline-offset:2px}
.field__error{font-size:var(--fs-caption);color:var(--c-error)}
.field__control[aria-invalid="true"]{border-color:var(--c-error)}
.field__hint{font-size:var(--fs-caption);color:var(--c-text-dim)}

.form__grid{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-20)}
@media (min-width:640px){
  .form__grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .form__grid .field--wide{grid-column:1 / -1}
}
.form__status{
  margin-top:var(--space-16);
  padding:var(--space-16);
  border-radius:var(--r-hairline);
  font-size:var(--fs-body);
}
.form__status--ok{border:1px solid var(--c-success);color:var(--c-text)}
.form__status--err{border:1px solid var(--c-error);color:var(--c-text)}
.form__status[hidden]{display:none}

/* Honeypot - hidden from humans, visible to bots */
.hp-field{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* ============================================================
   SITE HEADER - flat solid black on every page (Figma node 213:6706),
   smart sticky (hides on scroll-down, returns on scroll-up).
   ============================================================ */
.site-header{
  position:fixed;inset:0 0 auto 0;
  z-index:var(--z-sticky);
  background:var(--c-bg);
  transition:transform var(--dur-slow) var(--ease-out),border-color var(--dur-slow) var(--ease-out);
  border-bottom:1px solid transparent;
  will-change:transform;
}
.site-header--scrolled{border-bottom-color:var(--c-border)}
/* On mobile the header sits flush against the page below it with nothing
   separating them at the top of the page (the scrolled-state border only
   shows up once you've moved past it) - a permanent hairline here instead. */
@media (max-width:767px){
  .site-header{border-bottom-color:var(--c-border)}
}
.site-header--hidden{transform:translateY(-100%)}
.site-header--revealed{transform:translateY(0)}
@media (prefers-reduced-motion:reduce){
  .site-header--hidden{transform:none}
}

/* Announcement bar - visible only at the top of the page */
.announce{
  background:var(--c-navy);
  color:var(--c-text);
  overflow:hidden;
  max-height:var(--space-96);
  transition:max-height var(--dur-slow) var(--ease-out),
             opacity var(--dur-base) var(--ease-out);
}
.site-header--scrolled .announce{max-height:0;opacity:0}
.announce__inner{
  display:flex;align-items:center;justify-content:center;gap:var(--space-12);
  flex-wrap:wrap;
  min-height:var(--header-announcement-target);
  padding:var(--space-8) 0;
  font-family:var(--font-mono);
  font-size:var(--fs-caption);
  letter-spacing:var(--tracking-wide);
  text-align:center;
}
.announce__link{
  color:var(--c-accent-high);
  text-decoration:underline;
  text-underline-offset:var(--space-4);
}

.header__bar{
  display:flex;align-items:center;justify-content:space-between;gap:var(--space-16);
  padding-block:var(--space-16);
  min-height:auto;
}
.header__side{display:flex;align-items:center;gap:6px;flex:1 1 0;min-width:0}
.header__side--end{justify-content:flex-end}

.brand{display:flex;align-items:center;justify-content:center;flex:1 1 0;min-width:0;margin:0}
/* Fixed width AND height (not height + width:auto) - an auto width from a
   2069x1164 source at 70px tall resolves to a fractional 124.4px, which
   forces the browser into sub-pixel scaling and reads as a soft/pixelated
   logo even though the source itself is high-res. Locking both axes to
   whole pixels and letting object-fit do the aspect-ratio work renders
   sharp at any zoom level. */
.brand img{width:124px;height:70px;object-fit:contain;max-width:100%}
@media (max-width:767px){ .brand img{width:95px;height:56px} }

.burger{
  display:inline-flex;align-items:center;justify-content:center;
  width:44px;height:38px;flex:none;background:none;border:0;
}
.burger img{width:44px;height:24px}
@media (max-width:767px){
  .burger{width:40px;height:36px}
  .burger img{width:32px;height:16px}
}

.icon-btn{
  position:relative;
  display:inline-flex;align-items:center;justify-content:center;
  width:38px;height:38px;
  border-radius:2px;
  color:var(--c-text);
  transition:opacity var(--dur-base) var(--ease-out);
}
.icon-btn:hover{opacity:.7}
.icon-btn .ui-icon{width:22px;height:22px}

/* FiboSearch's icon (dgwt-wcas layout="icon") ships black by default - invisible
   on this site's dark header, matching the other icon-btns' size/colour instead.
   overflow:hidden clips the plugin's own search-form markup (real width in the
   DOM even collapsed, just hidden until opened) to this box, so it can't widen
   the flex item past its icon and throw off the equal gap to its siblings. */
.header__search{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;overflow:hidden}
.header__search .dgwt-wcas-search-wrapp{width:22px;height:22px}
.header__search .dgwt-wcas-search-icon{
  display:flex;align-items:center;justify-content:center;
  width:100%;height:100%;color:var(--c-text);
  transition:opacity var(--dur-base) var(--ease-out);
}
.header__search .dgwt-wcas-search-icon:hover{opacity:.7}
/* The real export (like the other 3 header icons) is stroke-only - forcing a
   fill here paints its circle solid instead of leaving it a hollow ring. */
.header__search .dgwt-wcas-ico-magnifier-handler{width:100%;height:100%}
/* Account moved into the drawer's own nav list on mobile (right after Blog),
   so only its topbar icon drops off below 768px. The other two sit in a
   tight tap box with no visible padding of their own - the even gap between
   them comes entirely from the flex row's own `gap`, not from box size, so
   it stays even no matter which of the two boxes (icon-btn vs the plugin's
   own search wrapper) is really the tighter fit. */
@media (max-width:767px){
  .header__side--end .icon-btn--account{display:none}
  .header__side--end{gap:12px}
  .header__side--end .icon-btn,
  .header__side--end .header__search{width:36px;height:36px;padding:0}
  .header__side--end .icon-btn .ui-icon,
  /* FiboSearch ships its own `max-width:20px` on this element for the icon
     layout - a fixed cap our plain width here can't out-specificity, since
     their selector is `html:not(.class) .wrapp.layout-icon`. !important is
     the honest way to say "override the plugin", not a workaround. */
  .header__side--end .header__search .dgwt-wcas-search-wrapp{width:24px!important;max-width:24px!important;height:24px!important}
  .header__side--end .ui-icon img{object-fit:contain}
}

/* ------------------------------------------------------------
   Utility icons
   Each is two exported vector layers stacked in a 22px box. The outer inset
   places the layer; the inner one is Figma's own stroke compensation. Both are
   reproduced exactly so the icons match the design rather than approximating it.
   ------------------------------------------------------------ */
.ui-icon{position:relative;display:block;width:22px;height:22px;flex:none;overflow:hidden}
.ui-icon__l{position:absolute}
.ui-icon__l > i{position:absolute;display:block;inset:0}
.ui-icon__l img{display:block;width:100%;height:100%}

/* Figma node 196:668 - search/wishlist/account/cart are each one self-contained
   22x22 export now, so the layer just fills the box - no per-icon insets. */
.ui-icon--search .ui-icon__l--1,
.ui-icon--wishlist .ui-icon__l--1,
.ui-icon--account .ui-icon__l--1,
.ui-icon--cart .ui-icon__l--1{inset:0}
.ui-icon--search .ui-icon__l--1 > i,
.ui-icon--wishlist .ui-icon__l--1 > i,
.ui-icon--account .ui-icon__l--1 > i,
.ui-icon--cart .ui-icon__l--1 > i{inset:0}

/* The three sequence callout badges. Same two-layer construction as the header icons; the
   glyph box is 20px inside the 40px crimson tile rather than 22px. */
.icon-badge .ui-icon{width:var(--icon-20);height:var(--icon-20)}
.icon-badge .ui-icon__l img{width:100%;height:100%}

.ui-icon--designed .ui-icon__l--1,
.ui-icon--designed .ui-icon__l--2{inset:9.38%}
.ui-icon--designed .ui-icon__l--1 > i,
.ui-icon--designed .ui-icon__l--2 > i{inset:-2.89%}

.ui-icon--nabl .ui-icon__l--1{inset:9.38% 15.63%}
.ui-icon--nabl .ui-icon__l--1 > i{inset:-2.89% -3.41%}
.ui-icon--nabl .ui-icon__l--2{inset:40.63% 34.38% 39.06% 34.38%}
.ui-icon--nabl .ui-icon__l--2 > i{inset:-11.55% -7.51%}

.ui-icon--support .ui-icon__l--1{inset:31.25%}
.ui-icon--support .ui-icon__l--1 > i{inset:-6.26%}
.ui-icon--support .ui-icon__l--2{inset:15.63%}
.ui-icon--support .ui-icon__l--2 > i{inset:-3.41%}

.icon-btn__count{
  position:absolute;top:7px;right:6px;
  width:12px;height:12px;
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--c-crimson);color:var(--c-text-on-brand);
  border-radius:7.5px;
  font-family:var(--font-display);font-weight:var(--weight-bold);
  font-size:8px;line-height:12px;
}
.icon-btn__count.is-empty{display:none}

/* The design has no inline navigation; everything lives behind the menu control. */
.nav{display:none}

/* ============================================================
   MENU DRAWER - the only navigation; the bar carries no inline links
   ============================================================ */
.drawer{
  position:fixed;inset:0;
  z-index:var(--z-drawer);
  background:var(--c-bg);
  overflow-y:auto;
  transform:translateY(-100%);
  visibility:hidden;
  /* visibility flips instantly on open so focus can move in on the same tick,
     and waits for the slide-out to finish on close. Opens downward from the
     top, not in from the side - matches where the hamburger itself sits. */
  transition:transform var(--dur-slow) var(--ease-out),
             visibility 0s linear var(--dur-slow);
}
.drawer.is-open{
  transform:translateY(0);
  visibility:visible;
  transition:transform var(--dur-slow) var(--ease-out), visibility 0s linear 0s;
}
@media (prefers-reduced-motion:reduce){
  .drawer{transition:visibility 0s linear var(--dur-fast)}
  .drawer.is-open{transition:visibility 0s linear 0s}
}

.drawer__inner{
  display:flex;flex-direction:column;min-height:100%;
}
@media (min-width:1280px){
  .drawer__inner{flex-direction:row;align-items:stretch}
}

.drawer__panel{
  flex:1 1 auto;min-width:0;
  display:flex;flex-direction:column;gap:var(--space-8);
  padding:var(--space-128) var(--container-pad) var(--space-48);
}
/* Clear of the close control, but not so deep that the CTAs drop off a short screen. */
@media (max-height:860px){ .drawer__panel{padding-top:var(--space-96)} }
@media (min-width:1280px){
  .drawer__panel{flex:0 1 560px;padding-right:var(--space-64)}
}
.drawer__close{
  position:absolute;top:var(--space-32);left:var(--container-pad);
  width:44px;height:38px;flex:none;background:none;border:0;cursor:pointer;
}
/* Two hairlines crossed - matches icon-menu.svg's 1px white stroke and round caps. */
.drawer__close span,
.drawer__close span::before{
  position:absolute;top:50%;left:50%;
  display:block;width:28px;height:1px;
  background:var(--c-text);border-radius:1px;
  content:'';
}
.drawer__close span{transform:translate(-50%,-50%) rotate(45deg)}
.drawer__close span::before{transform:translate(-50%,-50%) rotate(-90deg)}
.drawer__close:focus-visible{outline:2px solid var(--c-accent);outline-offset:4px}
/* main.js marks the burger/close button with this the instant it moves
   focus there by script (opening/closing the drawer) - skips the ring for
   just that one programmatic focus, not for a real keyboard Tab onto it. */
.js-no-focus-ring:focus-visible{outline:none}

.drawer__list,
.drawer__actions,
.drawer__meta{width:100%;max-width:520px}
.drawer__list{display:flex;flex-direction:column;list-style:none;margin:0;padding:0}
/* My Account (custom menu item, class set via wp menu item) stands in for
   the topbar account icon, which only drops off below 768px - so the drawer
   only needs this entry there too, not once the icon is already back. */
@media (min-width:768px){
  .drawer__list .drawer-item--mobile-only{display:none}
}
.drawer a:not(.btn){
  display:block;
  font-family:var(--font-heading);
  font-size:var(--fs-h5);
  font-weight:var(--weight-semibold);
  letter-spacing:var(--tracking-tight);
  padding-block:var(--space-8);
  border-bottom:1px solid var(--c-border);
  transition:color var(--dur-fast) var(--ease-out);
}
.drawer a:not(.btn):hover,
.drawer a:not(.btn):focus-visible{color:var(--c-accent)}
@media (min-width:1280px) and (min-height:860px){
  .drawer a:not(.btn){font-size:var(--fs-h3);padding-block:var(--space-16)}
}
.drawer__utils{
  display:none;list-style:none;margin:var(--space-24) 0 0;padding:0;
  width:100%;max-width:520px;
  gap:var(--space-24);flex-wrap:wrap;
}
.drawer__utils a{
  font-family:var(--font-label);font-size:var(--fs-caption);
  font-weight:var(--weight-semibold);letter-spacing:var(--tracking-wide);
  text-transform:uppercase;color:var(--c-text-muted);
}
.drawer__utils a:hover,.drawer__utils a:focus-visible{color:var(--c-accent)}
@media (max-width:767px){ .drawer__utils{display:flex} }
.drawer__actions{display:flex;flex-direction:column;gap:var(--space-12);margin-top:var(--space-32)}
.drawer__actions .btn{padding:var(--space-8) var(--space-20);min-height:40px}
@media (min-width:1280px){
  .drawer__actions .btn{padding:var(--space-12) var(--space-24);min-height:48px}
}
.drawer__meta{
  padding-top:var(--space-32);
  font-family:var(--font-mono);font-size:var(--fs-caption);
  color:var(--c-text-dim);letter-spacing:var(--tracking-wide);
}
/* Only pin to the panel's bottom edge once the visual side panel is back
   (1280px+) - below that the panel's height stretches to the full drawer,
   and an auto push there shoves the contact line off-screen. */
@media (min-width:1280px){
  .drawer__meta{margin-top:auto}
}
/* Real tel:/mailto: links now, not plain text - reset the generic nav-link
   rule above (huge font, full-width, border-bottom) back down to inline
   text, with the same smooth accent hover used on the breadcrumbs. Bumped
   to ".drawer .drawer__meta a" to outrank ".drawer a:not(.btn)"'s own
   specificity rather than losing to it silently. */
.drawer .drawer__meta a{
  display:inline;font-family:inherit;font-size:inherit;font-weight:inherit;
  letter-spacing:inherit;color:inherit;border-bottom:0;padding-block:0;
  transition:color var(--dur-base) var(--ease-out);
}
.drawer .drawer__meta a:hover,
.drawer .drawer__meta a:focus-visible{color:var(--c-accent)}

/* The right-hand visual panel - a full honeycomb-network scene (glow, mark,
   hover-preview photos) from 1280px up. Below that there's no room for a
   side panel, but the drawer shouldn't go flat black either: the same
   particle field sits as a quiet full-bleed backdrop instead, same low-key
   treatment as the 404 page, just dimmed further since it's sitting behind
   readable nav text here rather than being the whole page. Reuses the exact
   float/ping keyframes the preloader and the 404 page already define,
   rather than inventing a third variant of the same idea. */
.drawer__visual{
  display:block;position:absolute;inset:0;z-index:-1;
  overflow:hidden;pointer-events:none;
  opacity:.5;
}
@media (min-width:1280px){
  .drawer__visual{
    position:relative;inset:auto;z-index:auto;
    display:flex;align-items:center;justify-content:center;
    flex:1 1 auto;opacity:1;pointer-events:auto;
    border-left:1px solid var(--c-border);
    background:radial-gradient(120% 100% at 50% 50%, rgba(var(--rgb-panel),.4) 0%, var(--c-bg) 70%);
  }
}
.drawer__particles{position:absolute;inset:0;display:block;width:100%;height:100%}
.drawer__glow{
  position:absolute;width:420px;height:420px;border-radius:50%;
  background:radial-gradient(circle,rgba(var(--rgb-crimson),.18) 0%,rgba(var(--rgb-crimson),0) 65%);
  pointer-events:none;
}
.drawer__mark{position:relative;width:96px;height:96px;display:grid;place-items:center}
.drawer__mark img{
  position:relative;width:96px;height:96px;object-fit:contain;
  animation:error-404-float 4.5s var(--ease-inout) infinite;
  filter:drop-shadow(0 0 24px rgba(var(--rgb-crimson),.45));
}
.drawer__ping{
  position:absolute;inset:0;border-radius:50%;
  border:1px solid rgba(var(--rgb-crimson),.5);
  animation:error-404-ping 2.6s var(--ease-out) infinite;
}
.drawer__ping--2{animation-delay:1.3s}

/* The hover-preview photo - crossfades over the particle scene when a nav
   link with a real data-menu-image is hovered/focused (assets/js/drawer-visual.js
   toggles which of the two stacked layers is "front"; plain CSS transition,
   no GSAP/three.js dependency for the same reason as the reveal stagger
   above - it has to feel instant on hover, not wait on a script fetch).
   Each photo starts zoomed in (1.15) and settles to 1 over several seconds
   while shown - a slow continuous zoom-*out*, not a snap to size. Leaving
   only fades (the scale resets to 1.15 while invisible, so nothing pops). */
.drawer__preview{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;transform:scale(1.15);z-index:1;
  transition:opacity var(--dur-slow) var(--ease-out);
}
.drawer__preview.is-active{
  opacity:1;transform:scale(1);z-index:2;
  transition:opacity var(--dur-slow) var(--ease-out), transform 6s linear;
}
/* A permanent dark wash over whichever photo is showing - keeps every real
   photo reading as the same clean, dark, moody scene regardless of how
   bright or busy its own background is. */
.drawer__preview-wash{
  position:absolute;inset:0;z-index:3;pointer-events:none;
  background:linear-gradient(200deg, rgba(0,0,0,.35) 0%, rgba(0,0,0,.55) 55%, rgba(0,0,0,.75) 100%);
  opacity:0;transition:opacity var(--dur-slow) var(--ease-out);
}
.drawer__visual.has-preview .drawer__preview-wash{opacity:1}
.drawer__visual.has-preview .drawer__glow,
.drawer__visual.has-preview .drawer__mark{
  opacity:0;transition:opacity var(--dur-base) var(--ease-out);
}
@media (prefers-reduced-motion:reduce){
  .drawer__preview{transition:opacity var(--dur-fast) linear}
  .drawer__preview.is-active{transform:scale(1);transition:opacity var(--dur-fast) linear}
}
/* Glow, mark and hover-preview photos are desktop-only decoration - below
   1280px only the particle field itself shows, as a backdrop. Declared last
   so it actually wins the cascade against the unconditional display:grid/etc
   above it, instead of losing the source-order tiebreak. */
@media (max-width:1279px){
  .drawer__glow,
  .drawer__mark,
  .drawer__preview,
  .drawer__preview-wash{display:none}
}

/* Stagger reveal - the list, then the utility row, the two CTAs and the
   contact line settle in just after, so the drawer opens as one small
   choreographed sequence rather than a flat cut. Pure CSS transitions
   (no GSAP/three.js): this fires the instant the hamburger is clicked, with
   no dependency on a script finishing a network fetch first. */
.drawer__list li,
.drawer__utils li,
.drawer__actions .btn,
.drawer__meta{
  opacity:0;transform:translateY(18px);
}
.drawer.is-open .drawer__list li,
.drawer.is-open .drawer__utils li,
.drawer.is-open .drawer__actions .btn,
.drawer.is-open .drawer__meta{
  opacity:1;transform:none;
  transition:opacity .5s var(--ease-out), transform .5s var(--ease-out);
}
.drawer.is-open .drawer__list li:nth-child(1){transition-delay:.08s}
.drawer.is-open .drawer__list li:nth-child(2){transition-delay:.14s}
.drawer.is-open .drawer__list li:nth-child(3){transition-delay:.20s}
.drawer.is-open .drawer__list li:nth-child(4){transition-delay:.26s}
.drawer.is-open .drawer__list li:nth-child(5){transition-delay:.32s}
.drawer.is-open .drawer__list li:nth-child(6){transition-delay:.38s}
.drawer.is-open .drawer__list li:nth-child(7){transition-delay:.44s}
.drawer.is-open .drawer__list li:nth-child(8){transition-delay:.50s}
.drawer.is-open .drawer__list li:nth-child(9){transition-delay:.56s}
.drawer.is-open .drawer__utils li:nth-child(1){transition-delay:.56s}
.drawer.is-open .drawer__utils li:nth-child(2){transition-delay:.60s}
.drawer.is-open .drawer__utils li:nth-child(3){transition-delay:.64s}
.drawer.is-open .drawer__actions .btn:nth-child(1){transition-delay:.62s}
.drawer.is-open .drawer__actions .btn:nth-child(2){transition-delay:.68s}
.drawer.is-open .drawer__meta{transition-delay:.74s}

@media (prefers-reduced-motion:reduce){
  .drawer__list li,
  .drawer__utils li,
  .drawer__actions .btn,
  .drawer__meta{opacity:1;transform:none}
  .drawer__mark img,.drawer__ping{animation:none}
}

/* ============================================================
   SITE FOOTER
   Figma node 121:4583. The supplied backdrop under an 80% black wash, then
   the brand column and the link columns 120 apart, and a hairline bottom bar.
   ============================================================ */
.site-footer{
  position:relative;
  background:var(--c-bg);
  padding:var(--section-pad-lg) 0;
  color:var(--c-text);
}
/* The backdrop, and the wash the design lays over it.

   Note the stacking: the footer paints an opaque background of its own, as a fallback for a
   missing picture. A negative z-index here would put the backdrop *behind* that background
   and it would never be seen. So the backdrop stays at the default level - above the parent's
   background, below anything positioned after it - and the content is lifted over it
   instead. */
.site-footer__bg{position:absolute;inset:0;overflow:hidden;pointer-events:none}
.site-footer__bg img{display:block;width:100%;height:100%;object-fit:cover}
/* No wash here. The design lays 80% black over its picture, but the supplied export is the
   flattened result and already carries it - its brightest pixel is 41 of 255. Applying it a
   second time takes the mean to 2.9 and the backdrop disappears, which is what it did. The
   CTA's export is the raw photograph (max 195), so that one keeps its 20%. */
.site-footer > .container{position:relative;z-index:1}

.footer__inner{display:flex;flex-direction:column;gap:var(--space-40)}
.footer__top{display:flex;flex-direction:column;gap:var(--space-48)}
/* This row layout needs its brand column plus two fixed-253px columns plus
   two 60px/120px gaps to all fit side by side - real desktop width (1280px+,
   matching --container-max), not 1024. Between 768-1279 that math doesn't
   fit and was forcing genuine horizontal overflow on tablet/small-laptop
   widths (the whole page, not just the footer) - stays stacked/wrapping
   there instead. */
@media (min-width:1440px){ .footer__top{flex-direction:row;gap:120px;align-items:flex-start} }

/* Brand column: the mark at 215 x 128, the line about the company on a 326 measure,
   then the social row. */
.footer__brand{display:flex;flex-direction:column;gap:var(--space-24);flex:none}
.footer__logo img{display:block;width:215px;height:128px;object-fit:contain;max-width:100%}
.footer__about{
  font-family:var(--font-body);font-size:var(--fs-body);line-height:24px;
  color:var(--c-text-muted);max-width:326px;
}
.footer__social{display:flex;gap:var(--space-24);align-items:flex-start}
.footer__social a{display:block;line-height:0;opacity:.9;transition:opacity var(--dur-base) var(--ease-out)}
.footer__social a:hover,.footer__social a:focus-visible{opacity:1}
.footer__social img{display:block;width:24px;height:24px}

.footer__cols{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-40)}
/* Tablet (768-1099): a plain 2x2, both columns an even 50/50 - brand over
   Quick Links on the left, Contact Info over the QR on the right. .footer__cols has no
   box of its own here - display:contents lets its three children join .footer__top's
   grid directly, so brand (outside .footer__cols) and the rest can share the same grid. */
@media (min-width:768px) and (max-width:1099px){
  .footer__top{
    display:grid;
    grid-template-columns:repeat(2,minmax(0,1fr));
    column-gap:var(--space-64);
    row-gap:var(--space-40);
    align-items:start;
  }
  .footer__cols{display:contents}
  .footer__brand{grid-column:1;grid-row:1}
  .footer__col--links{grid-column:2;grid-row:1}
  .footer__col--contact{grid-column:1;grid-row:2}
  .footer__col--qr{grid-column:2;grid-row:2}
}
@media (min-width:1440px){
  .footer__cols{display:flex;gap:60px;align-items:flex-start;flex:1 1 auto;min-width:0}
  .footer__col--links{flex:none}
  .footer__col--contact,.footer__col--qr{width:253px;flex:none}
}
.footer__col{display:flex;flex-direction:column;gap:var(--space-16)}
.footer__col--links{gap:var(--space-24)}
.footer__col-title{
  font-family:var(--font-heading);font-size:var(--fs-body);font-weight:var(--weight-medium);
  line-height:24px;letter-spacing:0.16px;text-transform:capitalize;color:var(--c-text);
}

.footer__links{display:flex;flex-direction:column;gap:var(--space-8);list-style:none;margin:0;padding:0}
.footer__links a{
  font-family:var(--font-body);font-size:var(--fs-caption);line-height:22px;color:var(--c-text);
  transition:color var(--dur-base) var(--ease-out);
}
.footer__links a:hover,.footer__links a:focus-visible{color:var(--c-accent)}

.footer__contact{display:flex;flex-direction:column;gap:var(--space-16);list-style:none;margin:0;padding:0}
.footer__contact li{display:flex;gap:var(--space-8);align-items:center}
.footer__contact-address{align-items:flex-start}
.footer__contact img{display:block;width:24px;height:24px;flex:none}
.footer__contact a,.footer__contact address{
  font-family:var(--font-body);font-size:var(--fs-caption);line-height:22px;
  color:var(--c-text);font-style:normal;
  transition:color var(--dur-base) var(--ease-out);
}
.footer__contact a:hover,.footer__contact a:focus-visible{color:var(--c-accent)}

.footer__qr img{display:block;width:146px;height:146px;object-fit:cover}

/* Bottom bar: a half-pixel hairline, then the three groups pushed apart. */
.footer__bottom{
  display:flex;flex-direction:column;gap:var(--space-16);
  border-top:0.5px solid rgba(var(--rgb-white),.4);
  padding:var(--space-24) 0;
}
@media (min-width:1024px){
  .footer__bottom{flex-direction:row;justify-content:space-between;align-items:flex-start;padding-inline:60px}
}
/* Matches the footer's own 768-1099 tablet tier above. */
@media (min-width:768px) and (max-width:1099px){
  .footer__bottom{padding-inline:0}
}
.footer__copyright,.footer__gstin{
  font-family:var(--font-body);font-size:var(--fs-caption);font-weight:var(--weight-medium);
  line-height:22px;color:var(--c-text);
}
.footer__legal-links{display:flex;gap:var(--space-8);align-items:center;flex-wrap:wrap}
.footer__legal-links a{
  font-family:var(--font-body);font-size:var(--fs-caption);font-weight:var(--weight-medium);
  line-height:22px;color:var(--c-text);
  transition:color var(--dur-base) var(--ease-out);
}
.footer__legal-links a:hover,.footer__legal-links a:focus-visible{color:var(--c-accent)}
/* The rules between the legal links, drawn rather than shipped as an image. */
.footer__legal-links a + a::before{
  content:"";
  display:inline-block;
  width:1px;height:14px;
  margin-right:var(--space-8);
  vertical-align:-2px;
  background:rgba(var(--rgb-white),.4);
}

/* Declared last so these actually win the cascade against the unconditional
   footer rules above (equal specificity, later source wins) instead of
   losing the tie - the same class of bug the drawer's glow/mark hide had. */
@media (max-width:767px){
  .site-footer{padding:48px 0}
  .footer__inner{gap:32px}
  .footer__top{gap:32px}
  .footer__brand{gap:20px}
  .footer__logo img{width:200px;height:120px}
  .footer__about{width:100%}
  .footer__col{gap:20px}
  .footer__col--links{gap:20px}
  .footer__col-title{font-size:20px;line-height:28px}
  .footer__links a{font-size:16px;line-height:24px}
  .footer__contact a,.footer__contact address{font-size:16px;line-height:24px}
  .footer__bottom{padding:32px 0}
  .footer__copyright,.footer__gstin{font-size:14px;line-height:22px}
  .footer__legal-links a{font-size:12px;font-weight:var(--weight-medium);line-height:20px}
}

/* ============================================================
   PRELOADER - the brand mark assembles once per session, never on
   every page click. Transform + opacity only, so it composites for
   free; the ring, glow and bar all run on CSS, JS only decides when
   to let go.
   ============================================================ */
.preloader{
  position:fixed;inset:0;z-index:9999;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:var(--space-24);
  background:var(--c-bg);
  transition:opacity var(--dur-slower) var(--ease-inout),visibility 0s linear var(--dur-slower);
}
.preloader__mark{
  position:relative;width:120px;height:120px;display:grid;place-items:center;
  transition:transform var(--dur-slower) var(--ease-inout),filter var(--dur-slower) var(--ease-inout);
}
.preloader__glow{
  position:absolute;inset:-24px;border-radius:var(--r-full);
  background:radial-gradient(circle,rgba(var(--rgb-crimson),.35) 0%,rgba(var(--rgb-crimson),0) 70%);
  animation:preloader-pulse 2.2s var(--ease-inout) infinite;
}
/* The honeycomb ring - the brand mark's own hexagon motif, not a generic
   spinner. Outer hex sits still (a faint frame); the inner one draws itself
   once via stroke-dashoffset (dasharray 252 = 6 x 42px sides), then keeps
   turning slowly so the mark still reads as "working" while assets load. */
.preloader__hex{position:absolute;inset:0;overflow:visible}
.preloader__hex-outer{
  fill:none;stroke:var(--c-border-strong);stroke-width:1.5;opacity:.4;
  transform-origin:60px 60px;animation:preloader-hex-spin 16s linear infinite;
}
.preloader__hex-inner{
  fill:none;stroke:var(--c-crimson);stroke-width:2;stroke-linecap:round;
  stroke-dasharray:252;stroke-dashoffset:252;transform-origin:60px 60px;
  animation:preloader-hex-draw 1.4s var(--ease-out) .1s forwards,
             preloader-hex-spin 7s linear 1.5s infinite;
}
.preloader__logo{
  position:relative;width:64px;height:64px;object-fit:contain;
  opacity:0;transform:scale(.7);filter:blur(6px);
  animation:preloader-logo-in .7s var(--ease-spring) .1s forwards;
}
.preloader__brand{
  font-family:var(--font-heading);font-size:var(--fs-caption);font-weight:var(--weight-medium);
  letter-spacing:.32em;text-transform:uppercase;color:var(--c-text-muted);
  opacity:0;transform:translateY(8px);
  animation:preloader-text-in .6s var(--ease-out) .5s forwards;
}
/* The live percentage - JS eases this toward 99% while real assets are
   still loading, then snaps it to 100 the instant hide() actually fires,
   so the number always tells the truth about "still going" vs "done". */
.preloader__progress{
  display:flex;align-items:baseline;gap:2px;
  opacity:0;transform:translateY(8px);
  animation:preloader-text-in .6s var(--ease-out) .55s forwards;
}
.preloader__percent{
  font-family:var(--font-heading);font-size:28px;line-height:1;font-weight:var(--weight-medium);
  color:var(--c-text);font-variant-numeric:tabular-nums;min-width:2ch;text-align:right;
}
.preloader__percent-sign{
  font-family:var(--font-heading);font-size:14px;font-weight:var(--weight-medium);color:var(--c-crimson);
}

@keyframes preloader-hex-spin{ to{ transform:rotate(360deg) } }
@keyframes preloader-hex-draw{ to{ stroke-dashoffset:0 } }
@keyframes preloader-pulse{
  0%,100%{ opacity:.5; transform:scale(.9) }
  50%{ opacity:1; transform:scale(1.08) }
}
@keyframes preloader-logo-in{ to{ opacity:1; transform:scale(1); filter:blur(0) } }
@keyframes preloader-text-in{ to{ opacity:1; transform:none } }

/* JS adds this once the page (and the minimum dwell time) are ready - the
   mark gets a last small zoom+blur on the way out rather than a flat cut. */
.preloader.is-hidden{ opacity:0; visibility:hidden; pointer-events:none }
.preloader.is-hidden .preloader__mark{ transform:scale(1.08); filter:blur(3px) }
.preloader[hidden]{ display:none !important }

/* The inline snippet right after this markup adds this instantly, before
   first paint, on every page after the first one in a session - so
   navigating the site never re-plays the splash. */
.preloader--skip{ display:none !important }

html.has-preloader{ overflow:hidden }

@media (prefers-reduced-motion:reduce){
  .preloader{ transition:opacity var(--dur-fast) linear }
  .preloader__mark{ transition:opacity var(--dur-fast) linear }
  .preloader.is-hidden .preloader__mark{ transform:none; filter:none }
  .preloader__hex-outer,.preloader__hex-inner,.preloader__glow{ animation:none; opacity:.6 }
  .preloader__hex-inner{ stroke-dashoffset:0 }
  .preloader__logo{ animation:none; opacity:1; transform:none; filter:none }
  .preloader__brand,.preloader__progress{ animation:none; opacity:1; transform:none }
}

@media print{ .preloader{ display:none !important } }

/* ============================================================
   FLOATING WHATSAPP - the channel the KB says they actually sell on.
   Lives bottom-LEFT so it never competes with Back To Top on the right.
   A slow pulse keeps it findable without being noisy; hover pauses it,
   scales the button up and opens a name tag to its right.
   ============================================================ */
.wa-float{
  position:fixed;left:var(--space-16);bottom:var(--space-16);
  z-index:var(--z-overlay);
  display:inline-flex;align-items:center;justify-content:center;
  width:40px;height:40px;
  background:var(--c-crimson);color:var(--c-text-on-brand);
  border-radius:var(--r-full);
  box-shadow:var(--shadow-lg);
  transition:transform var(--dur-base) var(--ease-spring),box-shadow var(--dur-base) var(--ease-out);
  animation:wa-pulse 2.6s var(--ease-inout) infinite;
}
.wa-float:hover,.wa-float:focus-visible{
  transform:scale(1.1);box-shadow:var(--shadow-crimson);animation-play-state:paused;
}
@keyframes wa-pulse{
  0%,100%{ box-shadow:var(--shadow-lg), 0 0 0 0 rgba(var(--rgb-crimson),.45) }
  50%{ box-shadow:var(--shadow-lg), 0 0 0 10px rgba(var(--rgb-crimson),0) }
}
.wa-float__tip{
  position:absolute;left:calc(100% + var(--space-8));top:50%;
  transform:translate(-8px,-50%);
  background:var(--c-bg-alt);color:var(--c-text);
  padding:var(--space-4) var(--space-8);
  border-radius:var(--r-sm);
  font-family:var(--font-body);font-size:var(--fs-12);font-weight:var(--weight-medium);
  white-space:nowrap;box-shadow:var(--shadow-md);
  opacity:0;pointer-events:none;
  transition:opacity var(--dur-base) var(--ease-out),transform var(--dur-base) var(--ease-out);
}
.wa-float__tip::before{
  content:"";position:absolute;right:100%;top:50%;
  transform:translateY(-50%);
  border:5px solid transparent;border-right-color:var(--c-bg-alt);
}
.wa-float:hover .wa-float__tip,.wa-float:focus-visible .wa-float__tip{
  opacity:1;transform:translate(0,-50%);
}
@media (max-width:767px){
  .wa-float{width:54px;height:54px}
  .wa-float svg{width:24px;height:24px}
}
@media (min-width:768px) and (max-width:1023px){
  .wa-float{width:54px;height:54px}
  .wa-float svg{width:24px;height:24px}
}
@media (min-width:1024px){
  .wa-float{left:var(--space-32);bottom:var(--space-32);width:54px;height:54px}
  .wa-float svg{width:24px;height:24px}
}

/* ============================================================
   BACK TO TOP - mirrors WhatsApp on the right. Hidden until there is
   somewhere to scroll back FROM; the ring around it is a live read of
   how far down the page you are, filled with one conic-gradient and
   punched into a ring with a radial mask, so it costs nothing to
   animate every scroll frame - background-position, not layout.
   ============================================================ */
.back-to-top{
  position:fixed;right:var(--space-16);bottom:var(--space-16);
  z-index:var(--z-overlay);
  width:40px;height:40px;
  display:inline-flex;align-items:center;justify-content:center;
  border-radius:var(--r-full);
  background:var(--c-bg-alt);color:var(--c-text);
  border:none;cursor:pointer;padding:0;
  box-shadow:var(--shadow-lg);
  opacity:0;transform:translateY(16px) scale(.8);pointer-events:none;
  transition:opacity var(--dur-base) var(--ease-out),
             transform var(--dur-base) var(--ease-spring),
             box-shadow var(--dur-base) var(--ease-out);
}
.back-to-top.is-visible{opacity:1;transform:translateY(0) scale(1);pointer-events:auto}
.back-to-top:hover,.back-to-top:focus-visible{
  box-shadow:var(--shadow-crimson);transform:translateY(-3px) scale(1.06);
}
.back-to-top:active{transform:translateY(-1px) scale(.96);transition-duration:var(--dur-fast)}
.back-to-top__ring{
  position:absolute;inset:-3px;border-radius:var(--r-full);
  background:conic-gradient(var(--c-crimson) calc(var(--progress,0) * 1%), rgba(255,255,255,.18) 0);
  -webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 3px),#000 calc(100% - 3px));
  mask:radial-gradient(farthest-side,transparent calc(100% - 3px),#000 calc(100% - 3px));
}
.back-to-top__icon{position:relative;display:inline-flex;transform:rotate(-90deg);transition:transform var(--dur-base) var(--ease-spring)}
.back-to-top:hover .back-to-top__icon{transform:translateY(-2px) rotate(-90deg)}
@media (max-width:767px){
  .back-to-top{width:54px;height:54px}
  .back-to-top__icon svg{width:18px;height:15px}
}
@media (min-width:768px) and (max-width:1023px){
  .back-to-top{width:54px;height:54px}
  .back-to-top__icon svg{width:18px;height:15px}
}
@media (min-width:1024px){
  .back-to-top{right:var(--space-32);bottom:var(--space-32);width:54px;height:54px}
  .back-to-top__icon svg{width:18px;height:15px}
}

@media (prefers-reduced-motion:reduce){
  .wa-float{animation:none}
  .wa-float,.wa-float__tip,.back-to-top,.back-to-top__icon{transition-duration:var(--dur-fast)}
  .back-to-top:hover,.back-to-top.is-visible{transform:none}
}

/* ============================================================
   BREADCRUMBS
   ============================================================ */
.breadcrumbs{
  font-family:var(--font-mono);font-size:var(--fs-caption);
  letter-spacing:var(--tracking-wide);color:var(--c-text-dim);
  display:flex;flex-wrap:wrap;gap:var(--space-8);align-items:center;
}
.breadcrumbs a{color:var(--c-text-muted);transition:color var(--dur-base) var(--ease-out)}
.breadcrumbs a:hover{color:var(--c-accent)}
.breadcrumbs span[aria-current]{color:var(--c-text)}

/* Product page (Figma node 213:6295) - every crumb is the same white, the
   current page just carries more weight; no dimmed links here. */
body.single-product .breadcrumbs{
  font-family:var(--font-heading);font-size:14px;font-weight:var(--weight-extralight);
  letter-spacing:2px;color:var(--c-text);gap:8px;
}
body.single-product .breadcrumbs a{color:var(--c-text);font-weight:var(--weight-extralight)}
body.single-product .breadcrumbs a:hover{color:var(--c-crimson)}
body.single-product .breadcrumbs span[aria-current]{color:var(--c-text);font-weight:var(--weight-regular)}

/* ============================================================
   PAGINATION
   ============================================================ */
.pagination{display:flex;flex-wrap:wrap;gap:var(--space-8);justify-content:center;margin-top:var(--space-64)}
@media (max-width:767px){ .pagination{margin-top:var(--space-32)} }
.pagination .page-numbers{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:var(--space-48);height:var(--space-48);
  padding-inline:var(--space-12);
  border:1px solid var(--c-border);border-radius:var(--r-hairline);
  font-family:var(--font-mono);font-size:var(--fs-body);color:var(--c-text-muted);
  transition:border-color var(--dur-base) var(--ease-out),color var(--dur-base) var(--ease-out);
}
.pagination .page-numbers:hover{border-color:var(--c-border-strong);color:var(--c-text)}
.pagination .page-numbers.current{background:var(--c-primary);border-color:var(--c-primary);color:var(--c-text-on-brand)}

/* ============================================================
   SCROLL REVEAL - opacity + transform only, never layout
   ============================================================ */
/* A softer deceleration than the sitewide --ease-out (used for hover/click
   feedback, where snappy is right) - reveals want to settle in gently, not snap. */
.reveal{
  opacity:0;transform:translateY(var(--space-32));
  transition:opacity 900ms cubic-bezier(.16,1,.3,1),transform 900ms cubic-bezier(.16,1,.3,1);
}
.reveal.is-in{opacity:1;transform:none}
.reveal[data-delay="1"]{transition-delay:80ms}
.reveal[data-delay="2"]{transition-delay:160ms}
.reveal[data-delay="3"]{transition-delay:240ms}
.reveal[data-delay="4"]{transition-delay:320ms}
@media (prefers-reduced-motion:reduce){
  .reveal{opacity:1;transform:none;transition:none}
}

/* ============================================================
   SCROLL TEXT FILL - colour only, never layout
   A passage starts dim and lights a word at a time as it is scrolled up the viewport.
   Every section heading takes part, plus any passage marked `data-text-fill`;
   `assets/js/text-fill.js` decides which and drives `--fill` per word.

   The words are only dimmed once the script has taken over - `is-filling` is what does
   that - so with no JavaScript, or under reduced motion, the copy reads at full strength.

   The lit end is `currentColor` rather than a fixed white. Inside the `color` property
   itself `currentColor` resolves to the inherited value, so each passage fills up to
   whatever colour it was already painted instead of being dragged towards one.

   The words stay inline. An inline-block per word would be a second thing that could
   change how a heading wraps, and buys nothing - a single word has no space to break at.
   ============================================================ */
.fill-word{color:inherit}
/* .16 alpha measured at 1.44:1 contrast against a black section background -
   real WCAG failure (needs 3:1 for this font size), not just a design
   nitpick. .38 keeps the same "dim, not yet read" look relative to the
   fully-lit end of the fill but actually clears the ratio (~3.4:1). */
.is-filling .fill-word{color:rgba(255,255,255,.38)}
@supports (color: color-mix(in srgb, red 50%, blue)){
  .is-filling .fill-word{
    color:color-mix(in srgb, currentColor calc(var(--fill, 1) * 100%), rgba(255,255,255,.38));
    transition:color var(--dur-fast) linear;
  }
}
@media (prefers-reduced-motion:reduce){
  .is-filling .fill-word{color:inherit}
}
