/* Precision Labs — shared chrome: promo bar, header, search panel, checkout
   step header, newsletter band, footer.

   Two things govern every rule below:

   1. Horizontal padding is NEVER set here. Every band's inner element also
      carries .pl-wrap, which owns `padding: 0 var(--pl-gutter)`. Writing the
      `padding` shorthand on those elements wipes the gutter out, so vertical
      padding is always `padding-block`.
   2. Text on navy/ink uses var(--pl-on-dark) rather than white. The design's
      on-dark palette has no pure white; #F3F5F4 is the token for it. */

/* ─────────────────────────────────────────────────
   PROMO BAR
   ───────────────────────────────────────────────── */
/* A continuous ticker rather than three centred phrases.
 *
 * Centred inside .pl-wrap the messages huddled in the middle of a 1280px column
 * with empty navy either side of them on any wide screen. The marquee fills the
 * bar edge to edge and gives each message its own turn at the eye.
 *
 * How the seamless loop works: header.php prints the message set TWICE inside
 * .pl-promo__track, and the animation moves the track by exactly -50%. At the
 * end of the cycle the second copy occupies the position the first started in,
 * so the reset is invisible. Change the number of copies and the -50% must
 * change with it. */
.pl-promo {
  background: var(--pl-navy);
  color: var(--pl-on-dark);
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
}

/* Full-bleed on purpose: no .pl-wrap here, or the track would be clipped to the
   content column and the scroll would visibly start and stop mid-screen. */
.pl-promo__viewport {
  overflow: hidden;
  height: 38px;
  display: flex;
  align-items: center;
  /* Fade the two ends so messages arrive and leave rather than being sliced
     off at a hard edge. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

.pl-promo__track {
  display: flex;
  flex: none;
  width: max-content;
  animation: pl-marquee 38s linear infinite;
}

/* Hovering or tabbing into the bar stops it, so a message can be read at
   leisure and a link inside it could be clicked. */
.pl-promo:hover .pl-promo__track,
.pl-promo:focus-within .pl-promo__track { animation-play-state: paused; }

.pl-promo__set {
  display: flex;
  align-items: center;
  flex: none;
  list-style: none;
  margin: 0;
  padding: 0;
}

.pl-promo__item {
  flex: none;
  padding: 0 30px;
  white-space: nowrap;
  position: relative;
}
/* The separator is drawn, not typed: a dot character between items would need
   its own element and would break the two-copy symmetry the loop depends on. */
.pl-promo__item::after {
  content: "";
  position: absolute;
  right: -2px;
  top: 50%;
  width: 4px;
  height: 4px;
  margin-top: -2px;
  background: var(--pl-accent-lt);
}

@keyframes pl-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* Reduced motion: no scroll at all. One copy is shown, spread across the bar,
   and the duplicate is removed — otherwise the same three claims would sit on
   screen twice with no movement to explain why. */
@media (prefers-reduced-motion: reduce) {
  .pl-promo__track {
    animation: none;
    width: 100%;
    justify-content: center;
  }
  .pl-promo__set:nth-child(2) { display: none; }
  .pl-promo__set { flex: 1; justify-content: space-evenly; }
}

/* ─────────────────────────────────────────────────
   HEADER BAR
   ───────────────────────────────────────────────── */
/* Sticky.
 *
 * The promo marquee above it is NOT sticky and is allowed to scroll away — it
 * is an announcement, not navigation, and pinning both would cost 100px of
 * every screen.
 *
 * `top` is a variable rather than 0 because the WordPress admin bar is itself
 * fixed at the top for logged-in users; without the offset the header hides
 * underneath it. The body class WordPress adds is the only reliable signal
 * that the bar is present.
 *
 * z-index 50 sits above page content and below the search overlay (90), so
 * opening search still covers the header rather than fighting it. */
.pl-head {
  position: sticky;
  top: var(--pl-head-top, 0px);
  z-index: 50;
  background: var(--pl-surface);
  border-bottom: 1px solid var(--pl-bd);
}
body.admin-bar { --pl-head-top: 32px; }
@media screen and (max-width: 782px) {
  /* WordPress switches the admin bar to 46px here, and it stops being fixed
     below 600px — at which point the offset must go back to 0 or the header
     floats a gap below the top of the viewport. */
  body.admin-bar { --pl-head-top: 46px; }
}
@media screen and (max-width: 600px) {
  body.admin-bar { --pl-head-top: 0px; }
}

/* The checkout header is deliberately NOT sticky: the reduced bar exists to
   stop the shopper wandering off mid-payment, and pinning it would put a
   permanent "back to cart" link over the payment form. */
.pl-head--checkout { position: relative; top: auto; z-index: auto; }
.pl-head__inner {
  display: flex;
  align-items: center;
  gap: 30px;
  padding-block: 17px;
}

/* ── drawer toggle ──
   Hidden outright above the mobile breakpoint: there is no drawer up there, so
   the control that opens one must not exist either. Turned on — and sized to a
   44px target — in the <768px block. */
.pl-menubtn {
  display: none;
  padding: 0;
  border: 0;
  background: none;
  color: var(--pl-ink);
  cursor: pointer;
  /* iOS rounds a native <button> even with no background or border. */
  border-radius: 0;
  -webkit-appearance: none;
  appearance: none;
}
.pl-menubtn__bars { display: block; width: 20px; }
.pl-menubtn__bars i {
  display: block;
  height: 1.5px;
  background: currentColor;
  transition: transform .2s, opacity .2s;
}
.pl-menubtn__bars i + i { margin-top: 5px; }
/* Bars sit at y = 0 / 6.5 / 13, so ±6.5px collapses them onto the middle one:
   the same control reads as a close affordance while the drawer is open. */
.pl-menubtn[aria-expanded="true"] .pl-menubtn__bars i:nth-child(1) {
  transform: translateY(6.5px) rotate(45deg);
}
.pl-menubtn[aria-expanded="true"] .pl-menubtn__bars i:nth-child(2) { opacity: 0; }
.pl-menubtn[aria-expanded="true"] .pl-menubtn__bars i:nth-child(3) {
  transform: translateY(-6.5px) rotate(-45deg);
}

/* pl_logo() emits width="237" height="44" attributes and base.css relaxes them
   to height:auto — the design's 22px cap has to be reasserted here. */
/* ── logo: helix mark + typeset wordmark ──
   The flat lockup PNG set the words in a face that is not this site's, so
   beside nav links in Plus Jakarta Sans it read as a pasted-in image. Setting
   the words in type also lets the header (ink on white) and the footer (white
   on navy) share one component. */
.pl-logo { flex: none; display: block; }
.pl-logo img { height: 22px; width: auto; }

.pl-logo--mark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
}
/* Sized against the header bar, not against the words.
 *
 * The helix is a tall, narrow glyph — roughly 44x96, so it is only about
 * 0.46 as wide as it is high. Matching its HEIGHT to the two-line wordmark
 * (26px) therefore drew a mark barely 12px wide, which read as a speck rather
 * than a logo. It is set from the bar instead: 38px in a ~64px header leaves
 * the same breathing room above and below as the nav links have. */
.pl-logo__mark {
  height: 38px;
  width: auto;
  flex: none;
}

/* Kept for any caller that asks for the mark alone (pl_logo($v, false)). The
   header no longer does: it shows the full lockup and the <768px block hides
   the words instead, so one piece of markup serves both widths. */
.pl-logo--markonly .pl-logo__mark { height: 46px; }

/* Breathing room between the lockup and the first nav item. Without it the
   wordmark and "Bundles" read as one run of text. */
.pl-head__inner > .pl-logo { margin-right: 8px; }
.pl-logo__words {
  display: flex;
  flex-direction: column;
  /* The two lines are set tight so the lockup reads as one object rather than
     two stacked words. */
  line-height: 1;
  gap: 3px;
}
.pl-logo__name {
  font-size: 16px;
  font-weight: 800;
  letter-spacing: -.02em;
  color: var(--pl-ink);
  text-transform: uppercase;
  white-space: nowrap;
}
.pl-logo__sub {
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .28em;
  /* .28em of tracking adds a trailing space after the last letter; the negative
     margin pulls the block back so RESEARCH optically aligns under the P
     instead of sitting a few pixels right of it. */
  margin-right: -.28em;
  text-transform: uppercase;
  color: var(--pl-muted);
  white-space: nowrap;
}
/* Dark surfaces: the footer passes variant "white". */
.pl-logo--white .pl-logo__name { color: var(--pl-on-dark); }
.pl-logo--white .pl-logo__sub  { color: var(--pl-on-dark-ft); }

.pl-logo--text {
  font-size: 16px;
  font-weight: 800;
  letter-spacing: -.02em;
  color: var(--pl-ink);
}

/* ── primary nav ── */
.pl-nav { min-width: 0; }
.pl-nav__list {
  display: flex;
  align-items: center;
  gap: 24px;
  list-style: none;
}
.pl-nav__list > li { position: relative; }
.pl-nav__list a {
  display: inline-block;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--pl-t3);
  padding-bottom: 2px;
  border-bottom: 1.5px solid transparent;
  transition: color .16s, border-color .16s;
}
.pl-nav__list a:hover { border-bottom-color: var(--pl-info-bd); }

/* WordPress supplies the active state; the fallback markup in header.php has no
   equivalent, so these are the only selectors that can ever match. */
.pl-nav__list > .current-menu-item > a,
.pl-nav__list > .current-menu-ancestor > a,
.pl-nav__list > .current-menu-parent > a,
.pl-nav__list > .current_page_item > a,
.pl-nav__list a[aria-current="page"] {
  color: var(--pl-navy);
  font-weight: 700;
  border-bottom-color: var(--pl-navy);
}

/* Depth 2 is enabled in header.php, so a submenu can appear. It is not drawn in
   the prototype — this is the minimum needed to stop children stacking inline
   and breaking the bar. */
.pl-nav__list .sub-menu {
  display: none;
  position: absolute;
  left: 0;
  top: 100%;
  z-index: 60;
  min-width: 212px;
  padding: 8px 0;
  list-style: none;
  background: var(--pl-surface);
  border: 1px solid var(--pl-bd);
}
.pl-nav__list > li:hover > .sub-menu,
.pl-nav__list > li:focus-within > .sub-menu { display: block; }
.pl-nav__list .sub-menu a {
  display: block;
  padding: 9px 16px;
  border-bottom: 0;
  color: var(--pl-t3);
}
.pl-nav__list .sub-menu a:hover {
  background: var(--pl-canvas);
  color: var(--pl-navy);
}

/* ── right-hand cluster ── */
.pl-head__end {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 20px;
}

/* One ink for the whole bar.
 *
 * Search sat at --pl-faint, Account at --pl-muted and the nav links at --pl-t3:
 * three different greys across one row of equally important controls, which is
 * what made the header look unresolved. They now share the nav's colour, size
 * and weight, so the only deliberate contrast in the bar is the navy cart
 * button — which is the one thing that should stand out.
 *
 * No border, no background, no field: the affordance is still just the word
 * "Search" until the overlay opens. */
.pl-searchbtn,
.pl-head__quiet {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--pl-t3);
  transition: color .16s;
}

.pl-searchbtn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  /* iOS keeps its own corner radius on a native <button> even after the
     background and border are removed. Square is not the default here. */
  border-radius: 0;
  -webkit-appearance: none;
  appearance: none;
}
.pl-searchbtn:hover,
.pl-head__quiet:hover { color: var(--pl-navy); }

/* Desktop shows the word; the icon is the small-screen half of the same
   control and is switched on in the <768px block. Hidden with display rather
   than clipped, because here it is genuinely redundant — the label is
   visible and carries the name. */
.pl-head__quiet-icon { display: none; }

/* The nav tail is markup for the off-canvas menu only. Above 768px there is no
   drawer — #pl-nav is the inline nav bar — and every destination in the tail is
   already in the bar or the footer, so it must not render there. Hidden by
   default and turned on inside the <768px block, so a new breakpoint cannot
   leak it onto a desktop header by omission.

   NAMED pl-navtail, not pl-drawer: drawer.css already owns `.pl-drawer` for the
   CART drawer, is enqueued after this file, and sets `display: flex` with no
   media query — so a tail using that class rendered on desktop whatever this
   rule said, and inherited the cart drawer's fixed positioning with it. */
.pl-navtail { display: none; }
.pl-searchbtn[aria-expanded="true"] { color: var(--pl-navy); }
.pl-searchbtn .pl-i { flex: none; }

.pl-cartbtn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 17px;
  background: var(--pl-navy);
  color: var(--pl-on-dark);
  transition: filter .18s;
}
.pl-cartbtn:hover { filter: brightness(.92); color: var(--pl-on-dark); }
.pl-cartbtn__label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  white-space: nowrap;
}
.pl-cartbtn__total {
  font-size: 11px;
  color: var(--pl-on-dark-nv);
  white-space: nowrap;
}

/* ─────────────────────────────────────────────────
   SEARCH OVERLAY
   ─────────────────────────────────────────────────
   Full-page layer with a dark scrim, opened from the header's Search button.
   header.php renders it as a SIBLING of <header>, not inside it: .pl-head is
   sticky and therefore its own stacking context, so an overlay nested within it
   can never paint above the page whatever z-index it is given. */
.pl-search {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: clamp(60px, 12vh, 140px) var(--pl-gutter) var(--pl-gutter);
}
/* The overlay ships with the `hidden` attribute; the display above would
   outrank the UA's [hidden] rule and leave it permanently open. Same trap as
   .pl-pf__step in finder.css. */
.pl-search[hidden] { display: none; }

/* A <button>, not a <div>: it is the click-away target, and making it a real
   control means it is never an unlabelled clickable div. It is aria-hidden and
   tabindex -1 because the panel already has its own close button. */
.pl-search__scrim {
  position: absolute;
  inset: 0;
  border: 0;
  padding: 0;
  cursor: pointer;
  background: rgba(9, 13, 24, .72);
  -webkit-backdrop-filter: blur(3px);
          backdrop-filter: blur(3px);
  animation: pl-search-fade .16s ease-out;
}

.pl-search__panel {
  position: relative;
  width: 100%;
  max-width: 760px;
  display: flex;
  flex-direction: column;
  max-height: 100%;
  background: var(--pl-surface);
  border: 1px solid var(--pl-bd);
  box-shadow: 0 30px 90px rgba(9, 13, 24, .45);
  animation: pl-search-rise .18s ease-out;
}

.pl-search__form {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 14px;
  border-bottom: 1px solid var(--pl-bd);
  flex: none;
}
.pl-search__icon { display: inline-flex; color: var(--pl-muted); flex: none; }

.pl-search__input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: none;
  /* 16px is a floor, not a preference: anything smaller makes iOS zoom the
     viewport when the field takes focus, and the page never zooms back. */
  font: inherit;
  font-size: 17px;
  padding: 20px 0;
  color: var(--pl-ink);
}
.pl-search__input:focus { outline: none; }
.pl-search__input::-webkit-search-cancel-button { -webkit-appearance: none; }

.pl-search__close {
  flex: none;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  background: none;
  cursor: pointer;
  font-size: 26px;
  line-height: 1;
  color: var(--pl-muted);
}
.pl-search__close:hover { color: var(--pl-ink); }

.pl-search__body { overflow-y: auto; }

.pl-search__group { padding: 10px 0; }
.pl-search__group + .pl-search__group { border-top: 1px solid var(--pl-bd-light); }
.pl-search__group-label { padding: 6px 18px; color: var(--pl-muted); }

/* ── one suggestion ── */
.pl-sugg {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 18px;
  min-height: 56px;
  text-decoration: none;
  color: var(--pl-ink);
}
/* Hover and keyboard selection are the SAME state deliberately: the arrow keys
   move .is-active, and a shopper switching between mouse and keys should not
   see two different highlights disagreeing about what is selected. */
.pl-sugg:hover,
.pl-sugg.is-active { background: var(--pl-surface-alt); }
.pl-sugg:focus-visible { outline: 2px solid var(--pl-navy); outline-offset: -2px; }
.pl-sugg.is-muted .pl-sugg__name { color: var(--pl-muted); }

.pl-sugg__img {
  width: 44px;
  height: 44px;
  object-fit: contain;
  background: var(--pl-bd-light);
  flex: none;
}
.pl-sugg__glyph {
  width: 44px;
  height: 44px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--pl-navy);
  background: var(--pl-bd-light);
  font-size: 15px;
}

.pl-sugg__txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pl-sugg__name { font-size: 15px; font-weight: 600; }
.pl-sugg__meta { font-size: 12.5px; color: var(--pl-muted); }
.pl-sugg__trail {
  margin-left: auto;
  padding-left: 12px;
  flex: none;
  font-size: 13px;
  font-weight: 700;
  color: var(--pl-navy);
  font-variant-numeric: tabular-nums;
}
.pl-sugg.is-muted .pl-sugg__trail {
  color: var(--pl-muted);
  font-weight: 500;
  text-transform: uppercase;
  font-size: 12px;
  letter-spacing: .1em;
}

.pl-search__none { padding: 26px 18px; color: var(--pl-muted); font-size: 14.5px; }

/* ── before anything is typed ── */
.pl-search__idle { padding: 20px 18px 24px; }
.pl-search__idle[hidden] { display: none; }
.pl-search__idle-label { color: var(--pl-muted); margin-bottom: 12px; }
.pl-search__chips { display: flex; flex-wrap: wrap; gap: 8px; list-style: none; margin: 0; padding: 0; }
.pl-search__tip {
  margin-top: 18px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--pl-muted);
}

/* Locking the page behind the overlay. Applied to <html> by theme.js. */
.pl-noscroll { overflow: hidden; }

@keyframes pl-search-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes pl-search-rise {
  from { opacity: 0; transform: translateY(-10px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .pl-search__scrim,
  .pl-search__panel { animation: none; }
}

/* The old inline drop-down panel. Kept only so a cached page mid-deploy does
   not render an unstyled block; nothing emits this markup any more. */
.pl-searchpanel {
  background: var(--pl-surface);
  border-top: 1px solid var(--pl-bd);
  padding-block: 18px;
}
/* The panel ships with the `hidden` attribute. Any display value declared above
   would outrank the UA's [hidden] rule and leave it permanently open, so the
   attribute is re-honoured explicitly. */
.pl-searchpanel[hidden] { display: none; }
/* 16px keeps iOS from zooming the viewport when the field takes focus. */
.pl-searchpanel input[type="search"] {
  font-size: 16px;
  padding: 15px 16px;
}
.pl-searchresults:empty { display: none; }
.pl-searchresults { margin-top: 14px; }

/* ─────────────────────────────────────────────────
   CHECKOUT HEADER + STEP INDICATOR
   ───────────────────────────────────────────────── */
.pl-head--checkout .pl-head__inner {
  gap: 28px;
  padding-block: 20px;
}
.pl-steps {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-left: 8px;
  list-style: none;
}
.pl-steps__i {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--pl-faint);
}
.pl-steps__i.is-on { color: var(--pl-navy); }
.pl-steps__rule {
  flex: none;
  width: 34px;
  height: 1px;
  background: var(--pl-bd-strong);
}
.pl-head--checkout .pl-head__end {
  gap: 18px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--pl-muted);
}
.pl-secure {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.pl-secure .pl-i { flex: none; }
/* base .pl-link is 13px sentence case; the checkout bar sets it in the same
   uppercase key as "Encrypted checkout" beside it. */
.pl-head--checkout .pl-head__end .pl-link {
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
}

/* ─────────────────────────────────────────────────
   NEWSLETTER BAND
   ───────────────────────────────────────────────── */
.pl-news {
  background: var(--pl-navy-deep);
  color: var(--pl-on-dark);
  padding-block: 44px;
}
.pl-news__inner {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: 56px;
  align-items: center;
}
.pl-eyebrow--onnavy {
  color: var(--pl-accent-lt);
  font-size: 11px;
  letter-spacing: .24em;
}
.pl-news__h {
  margin-top: 12px;
  max-width: 460px;
}
.pl-news__sub {
  margin-top: 12px;
  max-width: 440px;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--pl-on-dark-nv);
  text-wrap: pretty;
}
.pl-news__form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
/* Field and button butt together as one unit: the field drops its right border
   so the seam is a single hairline, not two. */
.pl-news__row { display: flex; }
.pl-news__row input[type="email"] {
  flex: 1;
  min-width: 0;
  padding: 17px 18px;
  font-size: 13.5px;
  color: var(--pl-on-dark);
  background: rgba(9, 13, 24, .4);
  border: 1px solid rgba(243, 245, 244, .3);
  border-right: 0;
}
.pl-news__row input[type="email"]::placeholder { color: var(--pl-on-dark-nv); }
/* base.css focuses inputs to navy on a navy band — invisible. */
.pl-news__row input[type="email"]:focus {
  border-color: var(--pl-accent-lt);
  box-shadow: none;
}
.pl-news__row .pl-btn {
  padding: 17px 28px;
  white-space: nowrap;
}
.pl-news__claims {
  display: flex;
  gap: 20px;
  list-style: none;
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--pl-on-dark-nv);
}

/* ─────────────────────────────────────────────────
   FOOTER
   ───────────────────────────────────────────────── */
.pl-foot {
  background: var(--pl-ink);
  color: var(--pl-on-dark);
}
.pl-foot__grid { padding-block: 44px; }
.pl-foot__cols {
  display: grid;
  grid-template-columns:
    minmax(0, 1.5fr) minmax(0, .8fr) minmax(0, .8fr) minmax(0, .8fr) minmax(0, .9fr);
  gap: 32px;
}
.pl-foot__brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 18px;
}
/* `.pl-logo__img` — the flat lockup PNG — NOT a bare `img`.
 *
 * This rule used to read `.pl-foot__brand .pl-logo img { width: 200px }`, which
 * at (0,2,1) outranked `.pl-logo__mark { height: 26px }` at (0,1,0). The helix
 * mark is a tall, narrow glyph, so 200px wide made it roughly 440px tall and it
 * filled the whole footer. Sizing the two images separately is the fix; sizing
 * "any img in the logo" is what caused it. */
.pl-foot__brand .pl-logo__img { width: 200px; height: auto; }

/* The mark + typeset wordmark, a step larger than the header's. */
.pl-foot__brand .pl-logo__mark { height: 46px; width: auto; }
.pl-foot__brand .pl-logo--mark { gap: 12px; }
.pl-foot__brand .pl-logo__name { font-size: 19px; }
.pl-foot__brand .pl-logo__sub  { font-size: 10px; }
.pl-foot__brand .pl-logo--text {
  color: var(--pl-on-dark);
  font-size: 20px;
}
.pl-foot__pos {
  max-width: 300px;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--pl-on-dark-mu);
  text-wrap: pretty;
}
.pl-foot__contact {
  display: flex;
  flex-direction: column;
  gap: 7px;
  font-size: 12px;
  color: var(--pl-on-dark-mu);
}

.pl-foot__col {
  display: flex;
  flex-direction: column;
  gap: 11px;
}
.pl-label--ondark {
  color: var(--pl-on-dark-ft);
  font-size: 10.5px;
  letter-spacing: .18em;
  margin-bottom: 4px;
}
.pl-foot__links {
  display: flex;
  flex-direction: column;
  gap: 11px;
  list-style: none;
  font-size: 13.5px;
  color: var(--pl-on-dark-mu);
}
.pl-foot__note {
  margin-top: 3px;
  padding: 12px 14px;
  border: 1px solid rgba(243, 245, 244, .18);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--pl-on-dark-mu);
}

.pl-foot__legalbar { border-top: 1px solid rgba(243, 245, 244, .12); }
.pl-foot__legal {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding-block: 18px;
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--pl-on-dark-ft);
}
.pl-foot__legallinks {
  display: flex;
  gap: 22px;
  list-style: none;
}
/* The prototype's own hover for every on-dark link. Wrapped in :where() because
   it is a blanket rule: at plain specificity it would outrank the link hover of
   any component later dropped into the footer. */
:where(.pl-foot a:hover) { color: var(--pl-accent-lt); }

/* ─────────────────────────────────────────────────
   768–1199px — fluid
   ───────────────────────────────────────────────── */
@media (max-width: 1199px) {
  .pl-head__inner { gap: 20px; }
  .pl-head--checkout .pl-head__inner { gap: 20px; }
  .pl-nav__list { gap: 16px; }
  .pl-head__end { gap: 14px; }

  /* Five nav items plus the end cluster overflow before the mobile breakpoint;
     the bar scrolls rather than wrapping and doubling the header height. */
  .pl-nav {
    overflow-x: auto;
    scrollbar-width: none;
  }
  .pl-nav::-webkit-scrollbar { display: none; }
  .pl-nav__list { flex-wrap: nowrap; }
  .pl-nav__list > li { flex: none; }

  .pl-news__inner {
    grid-template-columns: minmax(0, 1fr);
    gap: 28px;
  }
  .pl-news__h, .pl-news__sub { max-width: none; }

  /* Five footer columns are unreadable under ~1140px of content width; the
     brand block takes a full row and the four link columns share the next. */
  .pl-foot__cols {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 30px 32px;
  }
  .pl-foot__brand { grid-column: 1 / -1; }
  .pl-foot__pos { max-width: 520px; }
}

/* ─────────────────────────────────────────────────
   <768px — single column
   ───────────────────────────────────────────────── */
@media (max-width: 767px) {
  /* The promo bar needs nothing here any more: the marquee is already one
     nowrap line at every width, and it was the manual sideways-scrolling
     version that needed this block. Speed is reduced instead, because the same
     travel across a 375px viewport reads much faster than across 1280px. */
  .pl-promo__track { animation-duration: 26s; }

  /* ── one row, not two ──
   *
   * Measured at 390px before this: the bar was 125px tall because the controls
   * needed 322px of 390 and `flex-wrap: wrap` sent them onto a second line.
   * "Cart · 0 $0.00" alone was 134px — a third of the screen spent telling the
   * shopper their empty cart is worth nothing — and Search and Account cost
   * another 125px as words.
   *
   * The row now reads: menu · mark · [space] · search · account · cart, all as
   * icons except the cart count. nowrap is stated rather than left to the
   * default because the wrap is the whole bug. */
  .pl-head__inner {
    flex-wrap: nowrap;
    gap: 0 10px;
    padding-block: 10px;
  }

  /* The wordmark is dropped on a phone, not the mark: the bar has room for the
     hamburger, the mark and three utilities, and not for two lines of type as
     well — that combination is what made it wrap to 125px. The words stay in
     the DOM as the link's accessible name via .pl-sr, so the logo still
     announces as "Precision Labs Research".
     The mark is a tall, narrow glyph (roughly 0.46 as wide as it is high), so
     36px here is only ~17px across and does not crowd the hamburger. */
  /* SCOPED to the header bar. Written bare, this hid the wordmark on every
     logo on a phone — the footer lockup and the maintenance page lost
     "PRECISION LABS" too, leaving an unlabelled helix as the only brand on the
     screen. Only the header is short of room. */
  .pl-head .pl-logo__words { display: none; }
  .pl-head .pl-logo--mark .pl-logo__mark { height: 36px; }
  .pl-head .pl-logo--mark { margin-left: 6px; margin-right: 0; }

  /* Push the utilities to the far edge and let the logo sit next to the menu
     button, which is the arrangement a phone reads fastest. */
  .pl-head__end { margin-left: auto; gap: 4px; }

  /* Search and Account become icon-only. Both labels stay in the DOM and are
     visually hidden rather than removed, so the accessible name is still the
     word — an icon-only control with no name is the usual way this goes
     wrong. */
  .pl-searchbtn > span:not(.pl-sr),
  .pl-head__quiet-label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
  .pl-searchbtn,
  .pl-head__quiet {
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0;
  }
  .pl-head__quiet-icon { display: inline-flex; }

  /* Cart: the count is the useful part on a phone. The running total is
     dropped below 768px — it is the widest element in the bar and it is
     redundant with the cart page one tap away. The drawer shows the total in
     full, so the number is never more than one tap from view. */
  .pl-cartbtn { padding: 11px 13px; gap: 6px; }
  .pl-cartbtn__total { display: none; }

  /* ── drawer tail ──
     Nav links, then everything the bar had to give up for space: search, the
     cart with its total, the account, support links and the standing terms.
     Before this the drawer was four links and a screenful of white. */
  .pl-navtail {
    display: flex;
    flex-direction: column;
    gap: 22px;
    margin-top: 22px;
    padding-top: 22px;
    border-top: 1px solid var(--pl-bd);
  }

  .pl-navtail__search {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    min-height: 48px;
    padding: 12px 14px;
    border: 1px solid var(--pl-bd-strong);
    border-radius: 0;
    background: var(--pl-canvas);
    color: var(--pl-muted);
    font: inherit;
    font-size: 14px;
    text-align: left;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
  }
  .pl-navtail__search .pl-i { flex: none; color: var(--pl-t3); }
  .pl-navtail__search span {
    /* The full placeholder does not fit a 320px drawer; it truncates rather
       than wrapping the control onto two lines. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .pl-navtail__actions { display: flex; flex-direction: column; gap: 10px; }
  .pl-navtail__cart { justify-content: space-between; }
  .pl-navtail__carttotal { font-variant-numeric: tabular-nums; }

  .pl-navtail__sect { display: flex; flex-direction: column; gap: 12px; }
  .pl-navtail__label { color: var(--pl-muted); }
  .pl-navtail__links {
    display: flex;
    flex-direction: column;
    gap: 2px;
    list-style: none;
    margin: 0;
    padding: 0;
  }
  .pl-navtail__links a {
    display: flex;
    align-items: center;
    min-height: 44px;
    font-size: 15px;
    color: var(--pl-t3);
  }

  .pl-navtail__foot {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding-top: 20px;
    border-top: 1px solid var(--pl-bd);
  }
  .pl-navtail__mail {
    display: flex;
    align-items: center;
    min-height: 44px;
    font-size: 14.5px;
    color: var(--pl-navy);
    font-weight: 600;
    word-break: break-all;
  }
  .pl-navtail__note {
    font-size: 13px;
    line-height: 1.5;
    color: var(--pl-muted);
  }
  .pl-navtail__legal {
    font-size: 12px;
    line-height: 1.5;
    color: var(--pl-faint);
  }
  .pl-pays--navtail { justify-content: flex-start; gap: 6px; }

  /* ── drawer toggle ──
     44×44 and raised above the panel it opens, so it stays the close control
     once the drawer has slid over the header. */
  .pl-menubtn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 44px;
    height: 44px;
    position: relative;
    z-index: 81;
  }

  /* ── off-canvas drawer ──
     Addressed by #pl-nav rather than .pl-nav on purpose. lab.css is enqueued
     after this file and still carries the older `.pl-head--drawer .pl-nav
     { display: none }` panel written for the JS-injected .pl-navtoggle; an ID
     outranks every one of those class selectors, so this drawer wins whether or
     not that class is still applied. `display` is stated for the same reason —
     without it, lab.css could hide the panel outright.

     CLOSED IS THE DEFAULT AND IT IS CLOSED THREE WAYS: parked off-canvas,
     visibility:hidden (which also takes every link out of the tab order) and
     pointer-events:none. A transform alone leaves a full-height, tappable,
     focusable panel sitting over the page on load. */
  #pl-nav {
    display: block;
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 80;
    width: min(86vw, 320px);
    /* Clears the header row (12px + 44px + 12px) so the toggle above never
       lands on the first link. */
    padding: 76px 0 28px;
    background: var(--pl-surface);
    border-right: 1px solid var(--pl-bd);
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;

    transform: translateX(-100%);
    visibility: hidden;
    pointer-events: none;
    /* Visibility flips only after the slide out has finished. */
    transition: transform .24s ease, visibility 0s linear .24s;
  }
  /* The promo bar sits directly above the header, so the band to clear is 38px
     taller when it renders. */
  .pl-promo + .pl-head #pl-nav { padding-top: 114px; }

  /* Open. theme.js is being written separately and may drive this from the
     button's aria state alone or additionally from a class on the nav, so both
     are supported. They are two rules with identical bodies and NOT one
     comma-joined selector by deliberate decision: a selector list is not
     forgiving, so in any engine without :has() a combined list would be dropped
     whole and take the .is-open fallback down with it. */
  .pl-head:has(.pl-menubtn[aria-expanded="true"]) #pl-nav {
    transform: none;
    visibility: visible;
    pointer-events: auto;
    transition: transform .24s ease, visibility 0s;
  }
  #pl-nav.is-open {
    transform: none;
    visibility: visible;
    pointer-events: auto;
    transition: transform .24s ease, visibility 0s;
  }

  /* Rows, not a row of inline links: the desktop underline gives way to a
     full-width divider on the <li> and the whole row becomes the target. */
  #pl-nav .pl-nav__list {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }
  #pl-nav .pl-nav__list > li { border-bottom: 1px solid var(--pl-bd); }
  #pl-nav .pl-nav__list a {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 11px var(--pl-gutter);
    font-size: 15px;
    border-bottom: 0;
  }
  #pl-nav .pl-nav__list a:hover {
    background: var(--pl-canvas);
    color: var(--pl-navy);
  }
  /* The current-page marker is a bottom border on desktop, which the rows above
     just removed — carry the state on the row's fill instead. */
  #pl-nav .current-menu-item > a,
  #pl-nav .current-menu-ancestor > a,
  #pl-nav .current-menu-parent > a,
  #pl-nav .current_page_item > a,
  #pl-nav a[aria-current="page"] {
    background: var(--pl-info-bg);
    color: var(--pl-navy);
    font-weight: 700;
  }

  /* Depth 2 is enabled in header.php. Hover and focus-within cannot open a
     submenu on touch, so in the drawer children are simply always shown,
     indented under their parent. Placed after the row rules above because it
     matches at equal specificity. */
  #pl-nav .sub-menu {
    display: block;
    position: static;
    z-index: auto;
    min-width: 0;
    padding: 0;
    border: 0;
    background: none;
  }
  #pl-nav .sub-menu > li { border-top: 1px solid var(--pl-bd); }
  #pl-nav .sub-menu a {
    padding-left: calc(var(--pl-gutter) + 16px);
    font-size: 14px;
    color: var(--pl-muted);
  }

  .pl-head__end { gap: 12px; }

  /* Hit targets ≥44px. Nav links are sized by the drawer rules above, which
     also reach the submenu links this list would miss. */
  .pl-searchbtn,
  .pl-head__quiet,
  .pl-logo {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  .pl-searchbtn { min-width: 44px; }
  .pl-cartbtn { min-height: 44px; padding: 11px 14px; }

  .pl-head--checkout .pl-head__inner {
    flex-wrap: wrap;
    gap: 10px 14px;
    padding-block: 14px;
  }
  /* The indicator is the widest thing in the checkout bar. It takes its own
     row, is allowed to wrap within that row, and min-width:0 lets it shrink
     below its content width — a flex item defaults to min-width:auto and would
     otherwise push the bar sideways rather than break.

     MEASURED INERT: checkout.css sets `.pl-steps { display: none }` in its own
     <768px block and is enqueued after this file, so below 768px the indicator
     is not rendered at all and none of the rules below currently apply. They
     are kept because they are what stops it overflowing the moment that
     decision is revisited — whether progress should vanish from a two-step
     checkout on mobile is a design call, not a layout one. */
  .pl-steps {
    order: 3;
    flex-basis: 100%;
    max-width: 100%;
    min-width: 0;
    flex-wrap: wrap;
    margin-left: 0;
    gap: 6px 10px;
  }
  .pl-steps__i { font-size: 12px; min-width: 0; }
  /* Decorative connector: the first thing to give up room. */
  .pl-steps__rule { width: 16px; }
  .pl-head--checkout .pl-head__end { gap: 14px; }
  .pl-head--checkout .pl-head__end .pl-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  .pl-news { padding-block: 34px; }
  /* Stated at the breakpoint the design names, so the band still collapses if
     the 768–1199px rule above is ever re-scoped. */
  .pl-news__inner {
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
  }
  /* Stacked, so the seam trick is off and the field needs its fourth border. */
  .pl-news__row { flex-direction: column; gap: 10px; }
  .pl-news__row input[type="email"] { border-right: 1px solid rgba(243, 245, 244, .3); }
  .pl-news__row .pl-btn { width: 100%; min-height: 48px; }
  .pl-news__claims { flex-wrap: wrap; gap: 10px 18px; }

  .pl-foot__grid { padding-block: 34px; }
  .pl-foot__cols {
    grid-template-columns: minmax(0, 1fr);
    gap: 28px;
  }
  .pl-foot__brand { grid-column: auto; }
  /* The Ordering column's items are bare <li> text, not links — sizing the row
     rather than the anchor keeps every column on the same rhythm. */
  .pl-foot__links { gap: 0; }
  .pl-foot__links li {
    display: flex;
    align-items: center;
    min-height: 44px;
  }
  /* The row was already 44px but the anchor inside it was not: a block anchor
     only fills its own line box, measured at 20.9px, so two thirds of a row
     that looked like a 44px target was dead to the touch. Stretching the
     anchor to its row is what actually makes the target 44px. */
  .pl-foot__links a {
    display: flex;
    align-items: center;
    align-self: stretch;
    width: 100%;
  }
  /* The one link in the brand block sits outside .pl-foot__links. */
  .pl-foot__contact a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  .pl-foot__legallinks a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  .pl-foot__legal {
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
  }
  .pl-foot__legallinks { flex-wrap: wrap; gap: 0 18px; }
}

/* ─────────────────────────────────────────────────
   <768px — REDUCED MOTION
   ───────────────────────────────────────────────── */
/* base.css already collapses every transition-duration globally, but the drawer
   also carries a 240ms delay on `visibility`, and a delay is not a duration —
   that rule does not touch it, so the panel would stay focusable for a quarter
   second after closing. Killing transition-property outright is the only fix.
   Each open selector is repeated because it outranks the bare #pl-nav rule. */
@media (max-width: 767px) and (prefers-reduced-motion: reduce) {
  #pl-nav { transition: none; }
  .pl-head:has(.pl-menubtn[aria-expanded="true"]) #pl-nav { transition: none; }
  #pl-nav.is-open { transition: none; }
  .pl-menubtn__bars i { transition: none; }
}
