/* ═══════════════════════════════════════════════════════════════════════
   QUANTUM LEVITATION — WordPress bridge
   Sits on top of quantum-proto.css and reconciles the prototype design
   with the legacy Bridge/Qode theme wrappers and WooCommerce markup.
   Load order: theme CSS → Customizer CSS → quantum-proto.css → this file.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 0a. ROOT FONT SIZE ────────────────────────────────────────────── */
/* The legacy theme sets html{font-size:62.5%} (10px) so its own rules can use
   rem as "px/10". The prototype stylesheet assumes a normal 16px root, so
   every clamp()/rem size in it was resolving ~37% too small — an h1 specced
   at 3.3rem (52.8px) rendered at 33px. Restore a 16px root; theme rules that
   relied on the 10px base are superseded by the prototype design anyway. */

/* the theme declares font-size:62.5%!important, so this has to match it */
html{ font-size:100% !important; }

/* Legacy theme components that still depend on the 10px base and are not
   otherwise restyled get their scale pinned back. */
.spinner-loader,
.b-page-filter,
.woof,
.woocommerce-message,
.woocommerce-info,
.woocommerce-error{ font-size:15px; }

/* ── 0. HEADING RESET ──────────────────────────────────────────────── */
/* The legacy theme sets Open Sans / 600 / uppercase on headings with
   selectors more specific than the prototype's element-level rules.
   This restores the prototype's Jost, light-weight, sentence-case headings
   everywhere without needing !important on every property. */

body h1, body h2, body h3, body h4, body h5,
body .h1, body .h2, body .h3, body .h4,
.l-main h1, .l-main h2, .l-main h3, .l-main h4, .l-main h5,
.woocommerce div.product .product_title,
.woocommerce ul.products li.product .woocommerce-loop-product__title{
  font-family:var(--display);
  font-weight:300;
  line-height:1.12;
  letter-spacing:-.012em;
  text-transform:none;
  color:var(--ink);
  margin:0;
}
body h1, .l-main h1{ font-weight:250; }

.pinfo h1{ font-size:clamp(1.85rem,3.2vw,2.5rem); margin-bottom:var(--s2); }
.head h2{ font-size:clamp(1.85rem,3.3vw,2.55rem); margin-bottom:var(--s2); }
.card-b h3{ font-size:18px; margin-bottom:8px; line-height:1.24; }
.prose h3{ font-size:21px; margin:var(--s5) 0 14px; }
.prose h3:first-child{ margin-top:0; }
.inst h2,.helper h2,.dlband h2{ color:#fff; }
.strip blockquote{ font-family:var(--display); font-weight:250; }

/* legacy theme link colour/underline defaults */
.l-main a{ text-decoration:none; }
.prose a,.post-body a,.article a{ color:var(--accent); text-decoration:underline; }

/* ── CONVERTED GIFS ────────────────────────────────────────────────────
   Animated GIFs in post content are served as <video> (see quantum-content.php).
   They need to behave exactly like the <img> they replaced: flow inline with
   the prose, scale down on small screens, never overflow the measure. */
video.gif-video{
  display:block;
  max-width:100%;
  height:auto;
  margin:var(--s4) 0;
  border:1px solid var(--rule);
  background:var(--paper-2);
}
.post-body video.gif-video{ margin:var(--s4) 0; }

/* ── PRODUCT BLOCKS EMBEDDED IN ARTICLES ───────────────────────────────
   Several posts embed an Elementor WooCommerce products widget in their body.
   Its markup relies on the legacy Foundation grid (.row / .column.medium-6
   .large-3), and that CSS was removed when style.css was cut from 167 KB to
   12 KB. With no grid, every card fell to full content width: three products
   rendering at 753 x 798 px each, a 2,482 px tall stack of giant cards in the
   middle of the prose.

   Restyled here as a compact three-up grid consistent with the blog cards
   rather than reinstating the Foundation grid, which would have brought back
   the weight the trim removed. Scoped to .post-body so the shop archive — which
   has its own template — is untouched. */
.post-body .woocommerce .products,
.post-body .products.b-catalog{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:1px;                      /* hairline rule between cards, as .blist */
  background:var(--rule);
  border:1px solid var(--rule);
  margin:var(--s5) 0;
  padding:0;
  list-style:none;
}
.post-body .woocommerce .products > .column,
.post-body .woocommerce .products > li.product{
  width:auto !important;
  float:none !important;
  margin:0 !important;
  padding:0 !important;
  background:#fff;
  list-style:none;
}
.post-body .b-box-product{
  display:flex;
  flex-direction:column;
  height:100%;
  padding:0 0 16px;
  border:0;
}
/* The image sat inside .responsive-embed, a legacy wrapper that created its
   aspect ratio with a padding-bottom hack and positioned the <img> absolutely
   inside it. That padding rule was in the removed style.css, so the wrapper
   collapsed to height:0 with overflow:hidden — clipping the photo out of
   existence. Every card was rendering with no image at all. Rebuilt on
   aspect-ratio, which needs no padding trick. */
.post-body .b-box-product__pic,
.post-body .b-box-product .img-wrap,
.post-body .b-box-product .responsive-embed{
  position:relative;
  display:block;
  margin:0;
  padding:0;
  height:auto;
  aspect-ratio:4/3;
  overflow:hidden;
  background:var(--paper-2);
}
.post-body .b-box-product__pic img,
.post-body .b-box-product img.responsive{
  position:absolute;
  inset:0;
  display:block;
  width:100%;
  height:100%;
  object-fit:cover;
  mix-blend-mode:multiply;
  margin:0;
  border:0;
}

/* Each card also carries .b-box-product__popover — a hover overlay repeating
   the title and price and adding the full "Includes…" description and a Read
   more link. It was absolutely positioned and revealed on hover; with that
   CSS gone it rendered inline underneath, which is why every card showed its
   title twice, its price twice, and a wall of specification text.

   Hidden rather than restored: inside an article the useful card is image,
   name and price. Anyone wanting the detail clicks through. */
.post-body .b-box-product__popover{ display:none !important; }

/* The card is wrapped in a link, and .post-body a is styled for prose —
   accent colour and underline. That made some product names render as blue
   underlined body links while others stayed black. */
.post-body .b-box-product a,
.post-body .products a{
  color:inherit;
  text-decoration:none;
}
.post-body .products a:hover .woocommerce-loop-product__title{ color:var(--accent); }

/* Woo's screen-reader price range duplicates the visible price. */
.post-body .b-box-product .screen-reader-text{
  position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0);
  white-space:nowrap;
}
.post-body .b-box-product__body{ padding:14px 16px 0; }
.post-body .b-box-product__title{ margin:0 0 6px; }
.post-body .b-box-product__title h2,
.post-body .woocommerce-loop-product__title{
  font-family:var(--display); font-weight:300; font-size:15px; line-height:1.3;
  letter-spacing:-.01em; text-transform:none; color:var(--ink); margin:0;
}
.post-body .b-box-product__price .price,
.post-body .b-box-product__price .amount{
  font-family:var(--mono); font-size:13.5px; color:var(--ink-2); font-weight:400;
}
.post-body .b-box-product:hover .woocommerce-loop-product__title{ color:var(--accent); }

/* The widget often carries a stray heading/description from Elementor. */
.post-body .elementor-widget-container > .woocommerce{ margin:0; }

@media(max-width:860px){
  .post-body .woocommerce .products,
  .post-body .products.b-catalog{ grid-template-columns:1fr 1fr; }
}
@media(max-width:520px){
  .post-body .woocommerce .products,
  .post-body .products.b-catalog{ grid-template-columns:1fr; }
}

/* Product SKU, shown under the price. Set in the mono face like the price
   itself, since a SKU is a code to be read and quoted rather than prose — it
   also makes it scannable for institutional buyers raising a purchase order.
   The .sku span is updated in place by WooCommerce's variation script, so it
   must stay inline and must not be given generated content. */
.pinfo .p-sku{
  margin: calc(-1 * var(--s2)) 0 var(--s3);
  font-family: var(--mono);
  font-size: 12.5px;
  letter-spacing: .04em;
  color: var(--ink-3);
}
.pinfo .p-sku .sku_wrapper{ display: inline-flex; gap: 8px; align-items: baseline; }
.pinfo .p-sku .sku{ color: var(--ink); }

/* Variation SKU: sits directly beneath the resolved variation price, so the
   code and the figure a buyer quotes stay together and change together. The
   negative top margin pulls it tight under the price, which WooCommerce renders
   in its own block above. */
.woocommerce-variation-sku{
  margin: -6px 0 var(--s2);
  font-family: var(--mono);
  font-size: 12.5px;
  letter-spacing: .04em;
  color: var(--ink-3);
}
.woocommerce-variation-sku .sku_wrapper{ display: inline-flex; gap: 8px; align-items: baseline; }
.woocommerce-variation-sku .sku{ color: var(--ink); }

/* The SKU row sits directly above the attribute table and should read as part
   of it, so the seam between the two is collapsed. */
.spec-sku{ margin-bottom: 0; }
.spec-sku + .spec-table{ margin-top: 0; }
.spec-sku + .spec-table table,
.spec-sku + .spec-table dl{ border-top: 0; }

/* ── ABOUT PAGE ──────────────────────────────────────────────────────
   Converted off Elementor, so these sections are plain markup now.
   Measure is held at 70ch for reading passages; the facts strip and the
   quote grid are allowed the full container. */
.ab-hero, .ab-why, .ab-facts, .founder, .ab-quotes, .ab-social{
  padding: var(--s5) 0;
  border-bottom: 1px solid var(--rule);
}
.ab-social{ border-bottom: 0; }
.ab-hero h1{ max-width: 18ch; margin: 10px 0 var(--s3); }
.ab-hero .lede, .ab-why p, .ab-social p{ max-width: 70ch; }
.ab-why h2, .founder h2, .ab-quotes h2, .ab-social h2{ margin: 10px 0 var(--s3); }

/* Column flow, not row flow: with dt and dd as separate grid items, the
   default row flow lays them out as label, value, label, value across the
   row. Filling down two rows instead puts each label above its own value,
   which is how the strip was designed to read. */
.ab-facts dl{
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: auto auto;
  grid-auto-flow: column;
  gap: 1px;
  margin: 0;
  background: var(--rule);
  border: 1px solid var(--rule);
}
.ab-facts dt{
  background: var(--paper);
  padding: 18px 18px 0;
  font-family: var(--mono, var(--display));
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 0;
}
.ab-facts dd{
  background: var(--paper);
  padding: 6px 18px 18px;
  margin: 0;
  font-size: 15px;
}

/* Founder. The supplied photograph is 597px wide, so it is capped at its
   native size rather than stretched across the column — upscaling a 597px
   image into a 560px+ slot on a retina screen is what makes founder photos
   look soft. Text sits beside it on desktop, under it on narrow screens. */
.founder{ display: grid; grid-template-columns: 1fr; gap: var(--s3); }
.founder .eyebrow, .founder h2{ grid-column: 1 / -1; }
@media (min-width: 861px){
  .founder{ grid-template-columns: minmax(0, 520px) minmax(0, 1fr); column-gap: var(--s4); align-items: start; }
}
.founder-img{ margin: 0; }
.founder-img img{
  display: block;
  width: 100%;
  max-width: 597px;
  height: auto;
  filter: saturate(.92);
}
.founder-img figcaption{
  margin-top: 10px;
  font-size: 13px;
  color: var(--ink-2);
}
.founder-txt p{ max-width: 62ch; }
.founder-txt p + p{ margin-top: var(--s2); }
.founder-credit{
  margin-top: var(--s3);
  padding-top: 14px;
  border-top: 1px solid var(--rule);
  font-size: 13px;
  color: var(--ink-2);
}
/* The legacy Foundation stylesheet styles every <cite> as a block and injects
   an em dash before it, which is right for a pull-quote attribution and wrong
   for a work title inside a sentence — it broke the TED talk link onto its own
   line with a stray dash. Reset it inside the founder copy only. */
.founder-txt cite{
  display: inline;
  font-style: italic;
  font-size: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-transform: none;
}
.founder-txt cite::before{ content: none; }

/* In memoriam. A bordered rectangle rather than another open section, so it
   reads as a set-apart tribute instead of a third block of company copy.
   Photograph left, text right on desktop; stacked below 860px. */
.memoriam{ padding: var(--s5) 0; border-bottom: 1px solid var(--rule); }
.memoriam h2{ margin: 10px 0 var(--s3); }

.mem-box{
  border: 1px solid var(--rule);
  padding: var(--s4);
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s4);
  background: var(--paper);
}
@media (min-width: 861px){
  .mem-box{ grid-template-columns: minmax(0, 46%) minmax(0, 1fr); align-items: start; }
}

.mem-img{ margin: 0; }
.mem-img img{ display: block; width: 100%; height: auto; }
.mem-img figcaption{
  margin-top: 10px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-2);
}

.mem-txt p{ max-width: 62ch; }
.mem-txt blockquote{
  margin: var(--s3) 0 0;
  padding: 0 0 0 18px;
  border-left: 2px solid var(--ink);
  font-family: var(--display);
  font-weight: 300;
  font-size: 18px;
  line-height: 1.55;
  color: var(--ink);
}
.mem-attrib{
  margin-top: 12px;
  padding-left: 20px;
  font-family: var(--display);
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.ab-quotes .qgrid{
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s4);
}
.ab-quotes figure{ margin: 0; }
.ab-quotes blockquote{
  margin: 0;
  padding: 0 0 0 18px;
  border-left: 2px solid var(--rule);
  font-family: var(--display);
  font-size: 19px;
  line-height: 1.5;
}
.ab-quotes figcaption{
  margin-top: 12px;
  padding-left: 20px;
  font-size: 13px;
  color: var(--ink-2);
}

@media (max-width: 860px){
  .ab-facts dl{ grid-template-columns: 1fr 1fr; grid-template-rows: repeat(4, auto); }
  .ab-quotes .qgrid{ grid-template-columns: 1fr; }
}
@media (max-width: 520px){
  .ab-facts dl{ grid-template-columns: 1fr; grid-auto-flow: row; grid-template-rows: none; }
}

/* Route list on the science fair hub. Each entry is a plain <p> inside
   .routes rather than a grid or flex container, for the same reason as
   figure.step below: wpautop can inject phantom paragraphs between blocks in
   post content, and in a grid every one of them becomes a visible cell.
   A left rule and generous padding give the block card-like weight without
   needing a layout container, and it survives the 70ch measure of .post-body. */
.post-body .routes{
  margin:var(--s4) 0;
  border-top:1px solid var(--rule);
}
.post-body .routes p{
  margin:0;
  padding:18px 0 18px 18px;
  border-bottom:1px solid var(--rule);
  border-left:2px solid transparent;
  transition:border-left-color .2s, padding-left .2s;
}
.post-body .routes p:hover{ border-left-color:var(--ink); }
.post-body .routes a{ text-decoration:none; }
.post-body .routes a strong{
  font-family:var(--display);
  font-weight:400;
  font-size:1.15em;
  color:var(--ink);
  border-bottom:1px solid var(--rule);
  padding-bottom:2px;
}
.post-body .routes a:hover strong{ border-bottom-color:var(--ink); }
.post-body .routes br{ line-height:2.2; }

/* Assembly steps (maglev-kit). Inline-block rather than a grid container:
   wpautop can inject stray paragraphs between block elements in post content,
   and inside a grid every phantom <p> becomes a cell. Inline-block flow simply
   ignores them. */
figure.step{
  display:inline-block;
  vertical-align:top;
  width:calc(33.333% - 12px);
  min-width:210px;
  margin:0 8px var(--s4) 0;
}
figure.step video.gif-video{ margin:0; width:100%; }
figure.step figcaption{
  font-family:var(--display); font-weight:400; font-size:10.5px;
  letter-spacing:.18em; text-transform:uppercase; color:var(--ink-3);
  padding-top:10px;
}
@media(max-width:860px){ figure.step{ width:calc(50% - 10px); } }
@media(max-width:520px){ figure.step{ width:100%; margin-right:0; } }

/* ── HERO VERTICAL RHYTHM ON SHORT VIEWPORTS ───────────────────────────
   quantum-style.css sets `.hero-txt{padding:var(--s7) …}` — a flat 96px
   top and bottom — and `.hero-grid{min-height:620px}`. Both assume a tall
   display. On a 13" laptop the browser viewport is roughly 1300x600, so the
   hero renders ~800px tall: the headline is pushed a long way below the nav
   and the CTAs fall past the fold.

   Scaled by viewport HEIGHT, not width — this is a vertical-space problem,
   and a 13" laptop is wide but short, so width breakpoints miss it entirely.
   Gated to >1000px so the phone layout keeps its own hero padding. */
@media (min-width:1001px) and (max-height:900px){
  .hero-txt{ padding-top:var(--s5); padding-bottom:var(--s5); }   /* 96 → 48 */
  .hero-grid{ min-height:0; }
}
@media (min-width:1001px) and (max-height:720px){
  .hero-txt{ padding-top:var(--s4); padding-bottom:var(--s4); }   /* 96 → 32 */
}

/* ── HERO FULL-BLEED CORRECTION ────────────────────────────────────────
   quantum-style.css bleeds the hero panel to the right edge with
   `margin-right: calc(50% - 50vw)`. That is the standard full-bleed trick,
   but it only works when the element's containing block is the centred page
   container. Here the containing block is the right-hand grid column
   (~547px), so 50% resolves to ~274px instead of half the page, and the
   panel ends up ~285px wider than the viewport at 1440px.

   `.hero{overflow:hidden}` hid the damage, so with a still image it merely
   looked like a tighter crop. With video it clipped the disc's right edge.

   Correct amount: minus the gutter between the wrap's content box and the
   viewport edge.
       content width = min(--max, 100vw) - 2 * --s4
       gutter        = (100vw - content width) / 2
   Below --max the gutter collapses to the wrap padding, which is right. */
.hero-img{
  margin-right: calc( (min(var(--max), 100vw) - (2 * var(--s4)) - 100vw) / 2 ) !important;
}

@media(max-width:1000px){
  /* Below 1000px the grid collapses to one column, so the panel spans the
     whole wrap and needs to bleed on both sides.

     Deliberately NOT done with percentages. `margin-left:50%` on a grid item
     resolves against the grid area in some engines and the viewport in
     others — Chrome resolved it to 50% of 100vw here, which exactly
     cancelled a translateX(-50%) and left the panel inset by the wrap
     padding. Negative margins equal to that padding are unambiguous: the
     element keeps its auto width (the grid area) and grows by the gutter on
     each side, landing flush on both viewport edges.

     The two values mirror .wrap's own padding in quantum-style.css —
     var(--s4) normally, 22px under its 620px breakpoint. */
  .hero-img{
    width:auto;
    transform:none;
    margin-left:  calc(-1 * var(--s4)) !important;
    margin-right: calc(-1 * var(--s4)) !important;
  }
}
@media(max-width:620px){
  .hero-img{
    margin-left:-22px !important;
    margin-right:-22px !important;
  }
}

/* ── HERO VIDEO ────────────────────────────────────────────────────────
   The homepage hero panel used to hold a still <img>. quantum-style.css
   only positions `.hero-img img`, so the <video> needs the identical
   absolute-fill treatment or it collapses to its intrinsic 1280x720 and
   the hero grid jumps. The poster frame is the same first frame, so there
   is no visible swap when playback starts. */
.hero-img video,
.hero-img video + img{
  width:100%; height:100%; object-fit:cover;
  position:absolute; inset:0; display:block;
  background:var(--paper-2);
}
/* The <img> inside <video> is a fallback for engines without video support;
   browsers that do support video ignore it, but belt-and-braces. */
.hero-img video::-webkit-media-controls{ display:none !important; }

/* Anyone who has asked their OS for less motion gets the still poster
   instead. The JS pauses playback; this keeps the frame visible. */
@media (prefers-reduced-motion: reduce){
  .hero-img video{ /* poster stays painted while paused */ }
}

/* ── 1. NEUTRALISE LEGACY THEME WRAPPERS ───────────────────────────── */

.s-content-wrp,
.s-content-wrp._header-offset{ margin:0 !important; padding:0 !important; }

.l-main > .s-content-wrp > .section,
.l-main > .section{ padding:0; }

/* the theme's grid system fights the prototype's own .wrap/.grid */
.l-main .container{ max-width:none; width:auto; margin:0; padding:0; }
.l-main .row{ display:block; margin:0; max-width:none; }
.l-main .row > .column,
.l-main .row > [class*="small-"],
.l-main .row > [class*="col-sm-"]{
  width:auto; max-width:none; flex:none; padding:0; float:none;
}

/* theme adds a fixed-header offset we no longer need — header is sticky */
body.has-transparent-header .l-main{ padding-top:0; }

/* the theme's own H1 page-title banner */
.l-main > .s-content-wrp > .section > .container > .row > .column > h1:first-child{ display:none; }

/* ── 2. PAGE CONTENT SHELL ─────────────────────────────────────────── */
/* Pages authored with prototype markup get a full-bleed canvas; the markup
   supplies its own .wrap elements. */

.entry-content > .wrap:first-child,
.article > .wrap:first-child{ padding-top:0; }

.page .entry-content,
.page .article{ font-size:16.5px; line-height:1.64; color:var(--ink); }

.page .entry-content > p,
.page .entry-content > ul,
.page .entry-content > ol,
.page .entry-content > h2,
.page .entry-content > h3{
  max-width:var(--max); margin-left:auto; margin-right:auto; padding:0 var(--s4);
}

/* ── 3. FOOTER ─────────────────────────────────────────────────────── */
/* Prototype footer is light (paper-2), not dark. Menus come from WP so the
   list markup needs the .fcol treatment applied to generated <ul>/<li>. */

.fcol ul li{ margin:0; list-style:none; }
.fcol ul li a{ color:var(--ink-2); text-decoration:none; font-size:14.5px; }
.fcol ul li a:hover{ color:var(--accent); }
.fsoc a{ color:var(--ink-2); text-decoration:none; }
.fsoc a:hover{ color:var(--accent); }
.fsoc li{ list-style:none; }
.fbot a{ color:var(--ink-3); }

/* ── 3b. CHECKBOX / RADIO RESET ────────────────────────────────────── */
/* quantum-proto.css styles `input, select, textarea` as full-width text
   fields (width:100%; min-height:52px; padding:14px 16px; appearance:none).
   That rule also catches radios and checkboxes, which is why the cart's
   shipping options rendered as huge empty circles. Put them back. */

input[type="radio"],
input[type="checkbox"]{
  appearance:auto; -webkit-appearance:auto;
  width:16px; height:16px; min-height:0; min-width:0;
  padding:0; margin:0; border:0; border-radius:0; background:none;
  flex:0 0 auto; vertical-align:middle; accent-color:var(--accent);
  box-shadow:none;
}
input[type="radio"]{ border-radius:50%; }

/* ── 4. WOOCOMMERCE — GLOBAL ───────────────────────────────────────── */

/* WooCommerce ships visually-hidden price labels ("Original price was: …").
   Without this they render as visible text inside the price row. */
.screen-reader-text{
  position:absolute !important; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0,0,0,0); clip-path:inset(50%); white-space:nowrap; border:0;
}

/* price rendering inside the prototype .price-row */
.price-row .now .price,
.price-row .now ins,
.price-row .now del{ font-family:var(--mono); }
.price-row .now ins{ text-decoration:none; background:none; color:var(--ink); }
.price-row .now del{ font-size:.55em; color:var(--ink-3); opacity:1; margin-right:10px; }
.price-row .now bdi{ font-family:var(--mono); }
.price-row .save bdi,.price-row .save .amount{ font-family:inherit; }
.sticky .sp del{ display:none; }

.woocommerce .woocommerce-breadcrumb{
  font-family:var(--display); font-weight:400; font-size:11px; letter-spacing:.18em;
  text-transform:uppercase; color:var(--ink-3); padding:var(--s3) 0 var(--s4); margin:0;
}
.woocommerce .woocommerce-breadcrumb a{ color:var(--ink-3); text-decoration:none; }
.woocommerce .woocommerce-breadcrumb a:hover{ color:var(--accent); }

.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce #respond input#submit,
.woocommerce a.button.alt,
.woocommerce button.button.alt,
.woocommerce .single_add_to_cart_button{
  display:inline-flex; align-items:center; justify-content:center;
  min-height:52px; padding:0 28px; border:1px solid transparent; border-radius:0;
  background:var(--ink); color:#fff;
  font-family:var(--body); font-size:14.5px; font-weight:500; letter-spacing:.02em;
  line-height:1; text-transform:none; transition:background .18s;
}
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover,
.woocommerce a.button.alt:hover,
.woocommerce button.button.alt:hover,
.woocommerce .single_add_to_cart_button:hover{ background:var(--accent); color:#fff; }

.woocommerce span.onsale{
  background:var(--sale); border-color:var(--sale); color:#fff; border-radius:0;
  font-family:var(--display); font-weight:400; font-size:10px; letter-spacing:.18em;
  text-transform:uppercase; min-height:0; min-width:0; line-height:1;
  padding:5px 10px; top:14px; left:14px; right:auto; margin:0;
}

.woocommerce div.product .stock{
  font-family:var(--display); font-weight:400; font-size:9.5px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--ok); border:1px solid var(--ok-br);
  background:var(--ok-lt); padding:4px 8px; display:inline-block;
}

.woocommerce-message,
.woocommerce-info,
.woocommerce-error{
  border-top:0; border-left:2px solid var(--accent); border-radius:0;
  background:var(--accent-lt); color:var(--ink-2);
}
.woocommerce-message::before,
.woocommerce-info::before{ color:var(--accent); }
.woocommerce-error{ border-left-color:var(--sale); background:var(--sale-lt); }
.woocommerce-error::before{ color:var(--sale); }

/* quantity input inherits the prototype .qty look */
.woocommerce .quantity .qty{
  border:1px solid var(--rule-2); border-radius:0; background:var(--paper);
  font-family:var(--mono); height:52px; color:var(--ink);
}

/* ── 5. WOOCOMMERCE — SINGLE PRODUCT (prototype .buy layout) ───────── */

.woocommerce div.product form.cart{ margin:0; }
.woocommerce div.product form.cart .quantity{ float:none; margin:0; }

/* The .buy grid uses fr units, whose default min-width:auto lets a wide child
   (the variations table) starve the gallery column down to a few pixels.
   Allowing both tracks to shrink is what keeps the product image visible. */
.buy > *{ min-width:0; }
.buy .pinfo{ min-width:0; }

/* Simple products: qty + button sit side by side.
   Variable products: the form also contains the variations table and the
   variation price, so it must stay a block — only the add-to-cart row flexes. */
.qty-row{ display:block; width:100%; }
.qty-row form.cart{ display:block; width:100%; margin:0; }

.qty-row form.cart:not(.variations_form){
  display:flex; gap:12px; align-items:stretch; flex-wrap:wrap;
}
.woocommerce-variation-add-to-cart{
  display:flex; gap:12px; align-items:stretch; flex-wrap:wrap;
}

.qty-row form.cart .quantity{
  display:flex; align-items:center; border:1px solid var(--rule-2); flex:0 0 auto;
}
.qty-row form.cart .quantity input.qty{
  width:64px; height:52px; border:0; text-align:center; background:transparent;
  font-family:var(--mono); font-size:15px; min-height:0; padding:0;
}
.qty-row form.cart .quantity .minus,
.qty-row form.cart .quantity .plus{
  width:40px; height:52px; border:0; background:none; cursor:pointer;
  color:var(--ink-2); font-size:17px; line-height:1; padding:0; min-height:0;
}

/* Buttons must not wrap their label onto three lines, and Add-to-cart +
   Buy Now must share one row with the quantity stepper rather than each
   claiming a full line (the .buy right column is only ~480px). */
/* !important is deliberate: the express-checkout plugin ships flex:1 with
   higher specificity, which collapses the basis to 0 and pushes Buy Now
   onto its own full-width row. */
.qty-row form.cart button.single_add_to_cart_button,
.qty-row form.cart .button,
.qty-row form.cart [class*="buy-now"],
.woocommerce-variation-add-to-cart [class*="buy-now"]{
  flex:1 1 110px !important; min-width:110px !important; width:auto !important;
  margin:0; white-space:nowrap; padding:0 16px; font-size:14px;
}

/* variations table → prototype spec-row treatment */
.woocommerce div.product form.cart .variations{
  margin:0 0 var(--s3); border:0; width:100%; display:block;
}
.woocommerce div.product form.cart .variations tbody,
.woocommerce div.product form.cart .variations tr{ display:block; width:100%; }
.woocommerce div.product form.cart .variations th,
.woocommerce div.product form.cart .variations td{
  border:0; padding:0 0 8px; vertical-align:middle; display:block; width:100%; background:none;
}
.woocommerce div.product form.cart .variations th.label,
.woocommerce div.product form.cart .variations th.label label{
  font-family:var(--display); font-weight:400; font-size:10.5px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--ink-3); padding:0 0 6px; white-space:normal;
  line-height:1.4; margin:0;
}
.woocommerce div.product form.cart .variations select{
  border:1px solid var(--rule-2); border-radius:0; background:var(--paper);
  height:52px; min-height:52px; padding:0 40px 0 16px; width:100%; max-width:420px;
  font-family:var(--body); font-size:15.5px; color:var(--ink);
}
.woocommerce div.product form.cart .reset_variations{
  font-family:var(--body); font-size:13px; color:var(--accent);
  text-transform:none; letter-spacing:0; display:inline-block; margin-top:8px;
}
.woocommerce div.product .single_variation_wrap{ display:block; width:100%; }
.woocommerce div.product .woocommerce-variation-price{ margin:0 0 var(--s2); }
.woocommerce div.product .woocommerce-variation-price .price{
  font-family:var(--mono); font-size:26px; color:var(--ink);
}
.woocommerce div.product .woocommerce-variation-description p{
  font-size:14.5px; color:var(--ink-2); margin:0 0 var(--s2);
}

/* hide the stock theme/Woo chrome we replace with prototype blocks */
.s-product .woocommerce-product-gallery,
.s-product .product > .summary,
.s-product .woocommerce-tabs,
.s-product .related.products,
.s-product .up-sells{ display:none !important; }

/* prototype spec table rendering of Woo attributes */
.woocommerce table.shop_attributes{ border:0; border-top:1px solid var(--ink); margin:0; }
.woocommerce table.shop_attributes tr{ display:grid; grid-template-columns:auto 1fr; }
.woocommerce table.shop_attributes th,
.woocommerce table.shop_attributes td{
  border:0; border-bottom:1px solid var(--rule); padding:15px 0; font-style:normal; background:none;
}
.woocommerce table.shop_attributes th{
  font-family:var(--display); font-weight:400; font-size:10.5px; letter-spacing:.18em;
  text-transform:uppercase; color:var(--ink-3); padding-right:26px; white-space:nowrap;
}
.woocommerce table.shop_attributes td{ font-family:var(--mono); font-size:14px; color:var(--ink); }
.woocommerce table.shop_attributes td p{ margin:0; padding:0; }

/* ── 6. WOOCOMMERCE — REVIEWS ──────────────────────────────────────── */

.woocommerce #reviews #comments ol.commentlist li .comment-text{
  border:0; border-bottom:1px solid var(--rule); border-radius:0;
  padding:0 0 var(--s4); margin:0 0 var(--s4);
}
.woocommerce #reviews #comments ol.commentlist li img.avatar{ display:none; }
.woocommerce #reviews #comments ol.commentlist li .comment-text .description{
  font-family:var(--display); font-weight:300; font-size:19px; line-height:1.45; color:var(--ink);
}
.woocommerce .star-rating span::before,
.woocommerce p.stars a::before{ color:var(--warn); }

/* ── 6b. SHOP CONTROLS ─────────────────────────────────────────────── */
/* The legacy theme styles bare <button> and <select> as solid dark blocks,
   which swamps the prototype's outlined chips and quiet selects. */

.tools .chip,
.tools .clear,
.qpick button{
  appearance:none; -webkit-appearance:none;
  border-radius:0; box-shadow:none; text-transform:none; letter-spacing:normal;
  font-weight:400; width:auto; height:auto; line-height:normal;
}
.tools .chip{
  background:transparent; border:1px solid var(--rule-2); color:var(--ink-2);
  padding:8px 14px; font-family:var(--body); font-size:13px; min-height:0; cursor:pointer;
}
.tools .chip:hover{ border-color:var(--ink-3); color:var(--ink); background:transparent; }
.tools .chip[aria-pressed="true"]{ background:var(--ink); border-color:var(--ink); color:#fff; }
.tools .clear{ background:none; border:0; color:var(--accent); text-decoration:underline; padding:0; min-height:0; }
.tools select{
  appearance:auto; -webkit-appearance:menulist;
  width:auto; min-height:0; height:auto; padding:8px 12px; font-size:13px;
  font-family:var(--body); background:transparent; color:var(--ink);
  border:1px solid var(--rule-2); border-radius:0; text-transform:none; letter-spacing:normal;
}
.qpick button{
  background:none; border:0; border-right:1px solid var(--rule);
  padding:var(--s3) var(--s3) var(--s3) 0; text-align:left; color:inherit;
  font-family:inherit; cursor:pointer; display:block; position:relative;
}
.qpick button:last-child{ border-right:0; }
.qpick button:hover{ background:var(--paper-2); }
.qpick button[aria-pressed="true"]{ background:var(--paper-2); }
.qpick h3{ font-size:20px; margin-bottom:7px; }
.qpick p{ font-size:13.5px; color:var(--ink-2); padding-right:12px; margin:0; }
.qpick .n{
  font-family:var(--display); font-weight:500; font-size:12px; letter-spacing:.18em;
  color:var(--ink); margin-bottom:12px;
}
.tools{ top:76px; }

/* card price html from WooCommerce */
.card-b .pr .price{ font-family:var(--mono); font-size:15.5px; color:var(--ink); }
.card-b .pr del{ color:var(--ink-3); font-size:12.5px; opacity:1; margin-right:6px; }
.card-b .pr ins{ text-decoration:none; background:none; color:var(--ink); }
.card-b .pr bdi{ font-family:var(--mono); }

/* ── 6c. GRAVITY FORMS → prototype form styling ────────────────────── */
/* Gravity Forms ships its own label/field chrome and the legacy theme adds
   more on top. Map both onto the prototype's .frm / .fr treatment. */

.gf-wrap{ display:block; }
.gform_wrapper{ margin:0; }

/* Gravity Forms' own "gravity-theme" lays fields out on a 12-column grid and
   sets grid-column spans per field. Keep that grid — just tune the rhythm. */
.gform_wrapper.gravity-theme .gform_fields{ grid-row-gap:var(--s3); }
.gform_wrapper .gfield{ display:grid; gap:8px; align-content:start; }

.gform_wrapper .gfield_label,
.gform_wrapper legend.gfield_label{
  font-family:var(--display); font-weight:400; font-size:10.5px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--ink-3); margin:0; line-height:1.4;
}
.gform_wrapper .gfield_required{ color:var(--sale); font-size:inherit; letter-spacing:inherit; }

.gform_wrapper .gfield input[type=text],
.gform_wrapper .gfield input[type=email],
.gform_wrapper .gfield input[type=tel],
.gform_wrapper .gfield input[type=url],
.gform_wrapper .gfield input[type=number],
.gform_wrapper .gfield select,
.gform_wrapper .gfield textarea{
  font-family:var(--body); font-size:15.5px; color:var(--ink);
  background:var(--paper); border:1px solid var(--rule-2); border-radius:0;
  padding:14px 16px; width:100%; min-height:52px; height:52px; box-shadow:none;
}
.gform_wrapper .gfield textarea{ min-height:120px; height:auto; resize:vertical; line-height:1.55; }
.gform_wrapper .gfield input[type=file]{
  padding:13px 16px; height:auto; min-height:52px; border:1px solid var(--rule-2); width:100%;
}
.gform_wrapper input:focus,
.gform_wrapper select:focus,
.gform_wrapper textarea:focus{
  outline:2px solid var(--accent); outline-offset:-1px; border-color:transparent;
}

/* radios / checkboxes read as body copy, not as labels */
.gform_wrapper .gfield_radio label,
.gform_wrapper .gfield_checkbox label,
.gform_wrapper .gchoice label{
  font-family:var(--body); font-size:14.5px; letter-spacing:0; text-transform:none;
  color:var(--ink-2); font-weight:400;
}
.gform_wrapper .gchoice{ display:flex; gap:11px; align-items:center; padding:2px 0; }
.gform_wrapper .gfield_radio input,
.gform_wrapper .gfield_checkbox input{
  width:18px; height:18px; min-height:0; margin:0; padding:0;
  accent-color:var(--accent); flex-shrink:0;
}

.gform_wrapper .gfield_description,
.gform_wrapper .gform_fileupload_rules{
  font-size:13px; color:var(--ink-3); line-height:1.5; padding-top:2px;
}
.gform_wrapper .gform_footer{ margin:0; padding:var(--s2) 0 0; }
.gform_wrapper .gform_button{
  display:inline-flex; align-items:center; justify-content:center;
  min-height:52px; padding:0 28px; border:0; border-radius:0;
  background:var(--ink); color:#fff; width:auto;
  font-family:var(--body); font-size:14.5px; font-weight:500; cursor:pointer;
}
.gform_wrapper .gform_button:hover{ background:var(--accent); }
.gform_wrapper .gform_validation_errors{
  border:0; border-left:2px solid var(--sale); background:var(--sale-lt);
  border-radius:0; box-shadow:none;
}

/* The quote form is a single column of full-width fields; cap its measure so
   the inputs don't run the full 1180px content width. */
.gform_wrapper form{ max-width:760px; }

/* ── 6d. LN2 SUPPLIER MAP ──────────────────────────────────────────── */
/* The legacy theme sizes bare inputs from its own scale, which blows the
   toolbar field up to ~26px. Pin it back to the prototype's field styling. */

.map-tools input[type="text"],
.map-tools input{
  font-family:var(--body); font-size:15.5px; line-height:1.4; color:var(--ink);
  height:48px; min-height:48px; padding:0 16px; margin:0;
  border:1px solid var(--rule-2); border-radius:0; background:var(--paper);
  flex:1; min-width:200px; box-shadow:none;
}
.map-tools input::placeholder{ color:var(--ink-3); font-size:15.5px; }
.map-tools .btn{ min-height:48px; height:48px; font-size:13.5px; padding:0 20px; flex:0 0 auto; }
.map-frame iframe{ position:absolute; inset:0; width:100%; height:100%; border:0; }
.map-resolved{
  margin:0; padding:12px var(--s4); border-bottom:1px solid var(--rule);
  background:var(--accent-lt); font-size:13px; line-height:1.5; color:var(--ink-2);
}
.map-resolved strong{ color:var(--ink); }
.map-resolved a{ color:var(--accent); }
.map-resolved[hidden]{ display:none; }
.map-status{ white-space:nowrap; }
.map-foot code,.map-keywarn code{ font-family:var(--mono); font-size:12px; }

/* ── 6e. MINI-CART DRAWER ──────────────────────────────────────────── */

.cart.has-items{ color:var(--ink); }
.cart .cart-n{ font-family:var(--mono); }

.mini-cart{
  position:fixed; top:0; right:0; bottom:0; width:100%; max-width:420px;
  background:var(--paper); border-left:1px solid var(--rule);
  z-index:220; display:flex; flex-direction:column;
  transform:translateX(100%); transition:transform .3s ease;
  box-shadow:-18px 0 48px rgba(10,11,13,.10);
}
.mini-cart.is-open{ transform:translateX(0); }
.mini-cart[hidden]{ display:none; }

.mini-cart__top{
  display:flex; align-items:center; justify-content:space-between;
  padding:var(--s3) var(--s4); border-bottom:1px solid var(--rule); flex-shrink:0;
}
.mini-cart__top h2{
  font-size:20px; margin:0; text-transform:none !important;
  font-family:var(--display); font-weight:300; letter-spacing:-.012em; color:var(--ink);
}
.mini-cart__close{
  appearance:none; background:none; border:0; font-size:28px; line-height:1;
  color:var(--ink-2); cursor:pointer; padding:0; width:32px; height:32px; min-height:0;
}
.mini-cart__close:hover{ color:var(--ink); }

.mini-cart__inner{ display:flex; flex-direction:column; flex:1; min-height:0; }

.mini-cart__list{
  list-style:none; margin:0; padding:0; overflow-y:auto; flex:1; min-height:0;
}
.mini-cart__item{
  display:grid; grid-template-columns:64px 1fr auto; gap:14px; align-items:start;
  padding:var(--s3) var(--s4); border-bottom:1px solid var(--rule);
  transition:opacity .2s;
}
.mini-cart__item.is-removing{ opacity:.4; }
.mini-cart__thumb{ background:var(--paper-2); aspect-ratio:1; overflow:hidden; }
.mini-cart__thumb img{ width:100%; height:100%; object-fit:cover; mix-blend-mode:multiply; }
.mini-cart__name{ font-size:14.5px; line-height:1.35; margin-bottom:4px; }
.mini-cart__name a{ color:var(--ink); text-decoration:none; }
.mini-cart__name a:hover{ color:var(--accent); }
.mini-cart__meta{ font-size:12.5px; color:var(--ink-3); margin-bottom:4px; }
.mini-cart__meta p{ margin:0; }
.mini-cart__line{
  display:flex; gap:6px; align-items:baseline;
  font-family:var(--mono); font-size:13.5px; color:var(--ink-2);
}
.mini-cart__line .price,.mini-cart__line bdi{ font-family:var(--mono); font-size:13.5px; }
.mini-cart__line del{ display:none; }
.mini-cart__remove{
  font-size:20px; line-height:1; color:var(--ink-3); text-decoration:none;
  padding:2px 4px; align-self:start;
}
.mini-cart__remove:hover{ color:var(--sale); }

.mini-cart__foot{
  border-top:1px solid var(--ink); padding:var(--s3) var(--s4);
  flex-shrink:0; background:var(--paper);
}
.mini-cart__total{
  display:flex; justify-content:space-between; align-items:baseline;
  padding-bottom:var(--s3);
}
.mini-cart__total span{
  font-family:var(--display); font-weight:400; font-size:10.5px;
  letter-spacing:.2em; text-transform:uppercase; color:var(--ink-3);
}
.mini-cart__total b{ font-family:var(--mono); font-size:20px; font-weight:400; color:var(--ink); }
.mini-cart__total bdi{ font-family:var(--mono); }
.mini-cart__actions{ display:grid; grid-template-columns:1fr 1fr; gap:10px; }
.mini-cart__actions .btn{ min-height:48px; font-size:14px; padding:0 14px; }
.mini-cart__note{ font-size:12.5px; color:var(--ink-3); margin:var(--s2) 0 0; text-align:center; }
.mini-cart__note a{ color:var(--accent); }

.mini-cart__empty{ padding:var(--s6) var(--s4); text-align:center; }
.mini-cart__empty p{ color:var(--ink-2); margin:0 0 var(--s3); }

.mini-cart__backdrop{
  position:fixed; inset:0; background:rgba(10,11,13,.42); z-index:219;
  opacity:0; transition:opacity .3s ease;
}
.mini-cart__backdrop.is-open{ opacity:1; }
.mini-cart__backdrop[hidden]{ display:none; }

/* Woo's "added to cart" confirmation link is redundant beside the drawer */
.woocommerce .added_to_cart{ display:none; }

@media(max-width:620px){
  .mini-cart{ max-width:none; }
  .mini-cart__actions{ grid-template-columns:1fr; }
}

/* ── 6f. CART & CHECKOUT ───────────────────────────────────────────── */
/* The legacy theme sets `table.shop_table{display:flex}` for a custom
   responsive treatment, which lays <thead> and <tbody> side by side and
   collapses the whole cart. Restore real table semantics, then dress the
   table in the prototype's spec-table language. */

.s-cart .wrap,
.s-checkout .wrap{ padding-top:var(--s5); padding-bottom:var(--s7); }
.s-cart > .wrap > article > h1,
.s-checkout > .wrap > article > h1{ margin-bottom:var(--s5); }

.woocommerce table.shop_table{
  display:table !important; width:100%; border-collapse:collapse;
  border:0; border-top:1px solid var(--ink); border-radius:0; margin:0 0 var(--s5);
}
.woocommerce table.shop_table thead{ display:table-header-group !important; }
.woocommerce table.shop_table tbody{ display:table-row-group !important; }
.woocommerce table.shop_table tfoot{ display:table-footer-group !important; }
.woocommerce table.shop_table tr{ display:table-row !important; }
.woocommerce table.shop_table th,
.woocommerce table.shop_table td{
  display:table-cell !important; vertical-align:middle;
  border:0; border-bottom:1px solid var(--rule); background:none;
  padding:18px 16px 18px 0;
}
.woocommerce table.shop_table th{
  font-family:var(--display); font-weight:400; font-size:10.5px;
  letter-spacing:.2em; text-transform:uppercase; color:var(--ink-3);
  text-align:left; padding-bottom:14px;
}

/* product cell */
.woocommerce table.cart td.product-name{ font-size:15.5px; }
.woocommerce table.cart td.product-name a{
  font-family:var(--body); font-size:15.5px; letter-spacing:0;
  text-transform:none; color:var(--ink); text-decoration:none; font-weight:500;
}
.woocommerce table.cart td.product-name a:hover{ color:var(--accent); }
.woocommerce table.cart td.product-name .variation{
  font-size:13px; color:var(--ink-3); margin:4px 0 0;
}
.woocommerce table.cart td.product-name .variation dt,
.woocommerce table.cart td.product-name .variation dd{
  display:inline; margin:0; padding:0; font-family:var(--body);
  font-size:13px; text-transform:none; letter-spacing:0; border:0;
}

.woocommerce table.cart td.product-thumbnail{ padding-right:18px; }
.woocommerce table.cart td.product-thumbnail img{
  width:72px !important; height:72px !important; aspect-ratio:1 !important;
  max-width:none; object-fit:cover; background:var(--paper-2);
  mix-blend-mode:multiply; display:block;
}

.woocommerce table.cart td.product-price,
.woocommerce table.cart td.product-subtotal,
.woocommerce table.cart td.product-total{
  font-family:var(--mono); font-size:15px; color:var(--ink); white-space:nowrap;
}
.woocommerce table.cart td.product-price bdi,
.woocommerce table.cart td.product-subtotal bdi{ font-family:var(--mono); }

/* Column widths. Under table-layout:auto a cell `width` is only a hint and
   the browser was handing all the slack to the first (remove) column, which
   left a ~400px hole before the thumbnails. Fixed layout honours them. */
.woocommerce table.shop_table.cart{ table-layout:fixed; }
.woocommerce table.cart th.product-remove,
.woocommerce table.cart td.product-remove{ width:48px; padding-right:8px; }
.woocommerce table.cart th.product-thumbnail,
.woocommerce table.cart td.product-thumbnail{ width:96px; }
.woocommerce table.cart th.product-price,
.woocommerce table.cart td.product-price{ width:120px; }
.woocommerce table.cart th.product-quantity,
.woocommerce table.cart td.product-quantity{ width:150px; }
.woocommerce table.cart th.product-subtotal,
.woocommerce table.cart td.product-subtotal{ width:120px; }
/* name takes whatever is left */
.woocommerce table.cart th.product-name,
.woocommerce table.cart td.product-name{ width:auto; }
.woocommerce a.remove{
  display:inline-flex; align-items:center; justify-content:center;
  width:26px; height:26px; font-size:20px; line-height:1; border-radius:0;
  color:var(--ink-3); background:none; text-decoration:none; font-weight:400;
}
.woocommerce a.remove:hover{ color:var(--sale); background:none; }

/* Quantity stepper. The theme wraps the input in its own .ui-spinner with
   absolutely-positioned +/- anchors; lay it out as a flex row instead so
   the number field is actually visible. */
.woocommerce table.cart td.product-quantity{ width:140px; }
.woocommerce .quantity .ui-spinner,
.woocommerce table.cart td.product-quantity .quantity{
  display:inline-flex !important; align-items:center;
  border:1px solid var(--rule-2); margin:0; width:auto; height:46px;
  position:static; background:var(--paper);
}
.woocommerce .quantity .ui-spinner input.qty,
.woocommerce table.cart td.product-quantity input.qty{
  order:2; width:48px; height:44px; min-height:0; border:0; text-align:center;
  background:transparent; font-family:var(--mono); font-size:15px; padding:0;
  -moz-appearance:textfield;
}
.woocommerce .quantity input.qty::-webkit-outer-spin-button,
.woocommerce .quantity input.qty::-webkit-inner-spin-button{
  -webkit-appearance:none; margin:0;
}
.woocommerce .quantity .ui-spinner__btn{
  position:static !important; display:flex; align-items:center; justify-content:center;
  width:34px; height:44px; border:0; background:none; cursor:pointer;
  color:var(--ink-2); font-size:16px; line-height:1; text-decoration:none;
  font-family:var(--body);
}
.woocommerce .quantity .ui-spinner__btn:hover{ color:var(--ink); }
.woocommerce .quantity .ui-spinner__btn--down{ order:1; }
.woocommerce .quantity .ui-spinner__btn--up{ order:3; }

/* Coupon + actions row.
   NOTE: this cell carries colspan="6". Setting display:flex on it takes it
   out of the table layout, and under table-layout:fixed it then collapses
   to the first column's width (48px) with its children overflowing. So it
   must stay a real table-cell — float the two groups instead. */
.woocommerce table.cart td.actions{
  padding:var(--s3) 0; border-bottom:0;
  display:table-cell !important; text-align:left; vertical-align:middle;
}
.woocommerce table.cart td.actions::after{ content:""; display:table; clear:both; }

/* coupon left, "Update cart" right, both on one line */
.woocommerce table.cart td.actions .coupon{
  display:flex; gap:10px; align-items:center; float:left;
  margin:0; padding:0; border:0; width:auto;
}
.woocommerce table.cart td.actions button[name="update_cart"],
.woocommerce table.cart td.actions input[name="update_cart"]{
  float:right; margin:0;
}
.woocommerce table.cart td.actions .coupon label{ display:none; }
.woocommerce table.cart td.actions .coupon input#coupon_code{
  width:auto; min-width:190px; height:52px; min-height:52px; padding:0 16px;
  border:1px solid var(--rule-2); border-radius:0;
  font-family:var(--body); font-size:15px;
}
.woocommerce table.cart td.actions .button{ margin:0; white-space:nowrap; width:auto; }
.woocommerce table.cart td.actions .button[disabled]{ opacity:.35; cursor:not-allowed; }
.woocommerce table.cart td.actions button[name="update_cart"]{ margin-left:auto; }

/* totals panel */
.woocommerce .woocommerce-cart-form{ margin-bottom:var(--s5); }
.cart-collaterals{ display:block; width:100%; margin:0; }
.cart-collaterals::before,
.cart-collaterals::after{ content:none; }
.woocommerce-cart .cart-collaterals .cross-sells{ display:none; }
.cart-collaterals .cart_totals{
  float:none !important; width:100% !important; max-width:440px; margin-left:auto;
  border:1px solid var(--rule); background:var(--paper-2); padding:var(--s4);
}
.cart-collaterals .cart_totals h2{
  font-size:20px; margin:0 0 var(--s3); text-transform:none !important;
  font-family:var(--display); font-weight:300; color:var(--ink);
}
.cart-collaterals table.shop_table{ border-top:0; margin:0; }
.cart-collaterals table.shop_table th,
.cart-collaterals table.shop_table td{
  padding:14px 0; border-bottom:1px solid var(--rule); background:none;
}
.cart-collaterals table.shop_table th{ width:45%; }
.cart-collaterals table.shop_table td{
  text-align:right; font-family:var(--mono); font-size:15px; color:var(--ink);
  text-transform:none; letter-spacing:0;
}
.cart-collaterals .order-total td{ font-size:20px; }
/* Shipping methods: prose, left-aligned, one row per option.
   The surrounding td is right-aligned for prices, so this block has to opt
   back out of that or the radios centre themselves and the labels ragged. */
.cart-collaterals td[data-title="Shipping"],
.cart-collaterals .woocommerce-shipping-methods,
.cart-collaterals .woocommerce-shipping-methods li,
.cart-collaterals .woocommerce-shipping-methods label,
.cart-collaterals .woocommerce-shipping-destination,
.cart-collaterals .shipping-calculator-button{
  font-family:var(--body); font-size:13.5px; text-transform:none;
  letter-spacing:0; color:var(--ink-2); line-height:1.5; text-align:left;
}
.cart-collaterals .woocommerce-shipping-methods{
  list-style:none; margin:0; padding:0; display:grid; gap:8px;
}
.cart-collaterals .woocommerce-shipping-methods li{
  display:flex; align-items:flex-start; gap:9px; margin:0;
}
.cart-collaterals .woocommerce-shipping-methods li label{
  margin:0; cursor:pointer; flex:1; display:block;
}
.cart-collaterals .woocommerce-shipping-methods li input[type="radio"]{
  margin-top:3px;
}
.cart-collaterals .woocommerce-shipping-methods .amount,
.cart-collaterals .woocommerce-shipping-methods bdi{
  font-family:var(--mono); color:var(--ink); white-space:nowrap;
}
.cart-collaterals .woocommerce-shipping-destination{
  margin:var(--s2) 0 0; font-size:12.5px; color:var(--ink-3);
}
/* the calculator toggle sits in a right-aligned cell; keep it with the
   rest of the shipping block instead */
.cart-collaterals .woocommerce-shipping-calculator{ text-align:left; }
.cart-collaterals .shipping-calculator-button{
  display:inline-block; margin-top:6px; color:var(--accent);
  text-decoration:underline; font-weight:400;
}
/* the theme appends a decorative icon to this link */
.cart-collaterals .shipping-calculator-button::after,
.cart-collaterals .shipping-calculator-button i{ display:none; }
.cart-collaterals .shipping-calculator-form{ margin-top:var(--s2); }
.cart-collaterals .shipping-calculator-form .form-row{ margin-bottom:10px; }
.cart-collaterals .shipping-calculator-form .button{ width:100%; }
.cart-collaterals .wc-proceed-to-checkout{ padding:var(--s3) 0 0; }
.cart-collaterals .wc-proceed-to-checkout .checkout-button{
  display:flex; width:100%; text-align:center; margin:0; font-size:15px;
}
.woocommerce-shipping-destination,
.woocommerce-shipping-calculator{ font-size:13.5px; color:var(--ink-3); }
.shipping-calculator-button{ color:var(--accent); }

/* return-to-shop / empty cart */
.cart-empty,
.woocommerce .return-to-shop{ margin:var(--s4) 0; }
.cart-empty{ font-size:19px; color:var(--ink-2); }

/* checkout */
.woocommerce-checkout .col2-set{ display:grid; grid-template-columns:1fr 1fr; gap:var(--s6); }
/* WooCommerce's base CSS puts a clearfix on .col2-set:
       ::before, ::after { content:" "; display:table; }
   In a float layout those are invisible. In a GRID they become real grid
   items: ::before occupies row-1-column-1, which pushes billing into column 2
   and shipping onto row 2 — billing and shipping render one after the other
   even though the two-column grid is applied and computes correctly. Kill the
   pseudo-elements and the two real children take the two cells. */
.woocommerce-checkout .col2-set::before,
.woocommerce-checkout .col2-set::after{ content:none; }
.woocommerce-checkout .col2-set .col-1,
.woocommerce-checkout .col2-set .col-2{ width:auto; float:none; }
.woocommerce-checkout h3{ font-size:21px; margin:0 0 var(--s3); text-transform:none !important; }
.woocommerce-checkout .form-row{ display:grid; gap:8px; padding:0; margin:0 0 var(--s2); }
.woocommerce-checkout .form-row label{
  font-family:var(--display); font-weight:400; font-size:10.5px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--ink-3);
}
.woocommerce-checkout .form-row input.input-text,
.woocommerce-checkout .form-row textarea,
.woocommerce-checkout .form-row select,
.woocommerce-checkout .select2-container .select2-selection--single{
  border:1px solid var(--rule-2); border-radius:0; background:var(--paper);
  height:52px; min-height:52px; padding:0 16px;
  font-family:var(--body); font-size:15.5px; color:var(--ink);
}
.woocommerce-checkout .form-row textarea{ height:auto; min-height:100px; padding:14px 16px; }
#order_review_heading{ margin-top:var(--s6); }
.woocommerce-checkout #payment{ background:var(--paper-2); border:1px solid var(--rule); border-radius:0; }
.woocommerce-checkout #payment ul.payment_methods{ border-bottom:1px solid var(--rule); }
.woocommerce-checkout #payment div.form-row{ padding:var(--s3); }
.woocommerce-checkout #place_order{ width:100%; }

@media(max-width:860px){
  .woocommerce-checkout .col2-set{ grid-template-columns:1fr; }
  .cart-collaterals .cart_totals{ max-width:none; }
}

@media(max-width:720px){
  /* Stack each line into a card. WooCommerce's shop_table_responsive mode
     injects data-title labels via td::before ("PRODUCT:", "PRICE:"…) and
     right-aligns the values; our layout is self-describing, so suppress
     both rather than let them collide with the grid. */
  .woocommerce table.shop_table.cart{ table-layout:auto; }
  .woocommerce table.shop_table.cart thead{ display:none !important; }
  .woocommerce table.shop_table.cart tbody{ display:block !important; }
  .woocommerce table.shop_table.cart tbody tr.woocommerce-cart-form__cart-item{
    display:grid !important;
    grid-template-columns:72px 1fr auto;
    grid-template-areas:
      "thumb name   remove"
      "thumb price  price"
      "thumb qty    subtotal";
    gap:8px 14px; padding:var(--s3) 0; border-bottom:1px solid var(--rule);
    align-items:start;
  }
  .woocommerce table.shop_table.cart tbody td{
    display:block !important; border:0 !important; padding:0 !important;
    width:auto !important; text-align:left !important; background:none !important;
  }
  .woocommerce table.shop_table_responsive.cart tbody td::before{ content:none !important; }
  /* The theme hides the price <span> itself on small screens
     (.woocommerce-Price-amount{display:none}), which is why the price and
     subtotal cells measured zero-height with their text still in the DOM. */
  .woocommerce table.shop_table.cart tbody td .woocommerce-Price-amount,
  .woocommerce table.shop_table.cart tbody td .woocommerce-Price-currencySymbol,
  .woocommerce table.shop_table.cart tbody td .amount,
  .woocommerce table.shop_table.cart tbody td bdi{
    display:inline !important; float:none !important;
  }
  .woocommerce table.shop_table.cart tbody td > *{ float:none !important; }
  .woocommerce table.shop_table.cart tbody td{ line-height:1.5; }
  .woocommerce table.cart td.product-price,
  .woocommerce table.cart td.product-subtotal{ font-family:var(--mono); }
  .woocommerce table.cart td.product-subtotal{ font-size:15px; color:var(--ink); }

  .woocommerce table.cart td.product-thumbnail{ grid-area:thumb; }
  .woocommerce table.cart td.product-thumbnail img{ width:72px !important; height:72px !important; }
  .woocommerce table.cart td.product-name{ grid-area:name; align-self:center; }
  .woocommerce table.cart td.product-price{ grid-area:price; font-size:13.5px; color:var(--ink-3); }
  .woocommerce table.cart td.product-quantity{ grid-area:qty; }
  .woocommerce table.cart td.product-subtotal{ grid-area:subtotal; text-align:right !important; align-self:center; }
  .woocommerce table.cart td.product-remove{ grid-area:remove; text-align:right !important; align-self:start; }

  /* The totals table keeps its <th> labels on mobile, so Woo's responsive
     td::before data-titles duplicate them ("SUBTOTAL" + "Subtotal:"). */
  .cart-collaterals table.shop_table_responsive tr td::before,
  .woocommerce-checkout table.shop_table_responsive tr td::before{ content:none !important; }
  .cart-collaterals table.shop_table th{ display:table-cell !important; }
  .cart-collaterals table.shop_table td{ text-align:right !important; }
  .cart-collaterals td[data-title="Shipping"]{ text-align:left !important; }

  .woocommerce table.cart td.actions{ display:block !important; padding:var(--s3) 0 !important; }
  .woocommerce table.cart td.actions .coupon{ float:none; margin-bottom:12px; }
  .woocommerce table.cart td.actions .coupon input#coupon_code{ min-width:0; flex:1; }
  .woocommerce table.cart td.actions .button{ width:100%; }
  .woocommerce table.cart td.actions button[name="update_cart"]{ float:none; width:100%; }
}

/* ── 7. SEARCH FORM IN HEADER ──────────────────────────────────────── */

.b-header__search-form-row{ display:flex; gap:8px; }
.b-header__search-form-row #search-field{
  height:48px; padding:0 14px; border:1px solid var(--rule-2); border-radius:0;
  font-family:var(--body); font-size:14.5px; min-width:0; flex:1;
}
.b-header__search-form-row .btn-dark{
  height:48px; padding:0 20px; border:0; border-radius:0;
  background:var(--ink); color:#fff; font-family:var(--body); font-size:13.5px; cursor:pointer;
}

/* ── 8. LEGACY ql-* FALLBACK ───────────────────────────────────────── */
/* Any page not yet converted still reads as prototype rather than serif/cream. */

.ql-label{
  font-family:var(--display); font-weight:400; font-size:11.5px; letter-spacing:.22em;
  text-transform:uppercase; color:var(--ink-3); display:flex; align-items:center;
  gap:var(--s2); margin-bottom:var(--s3);
}
.ql-label::after{
  content:""; flex:1; height:5px; max-width:96px;
  border-top:1px solid var(--rule); border-bottom:1px solid var(--rule); background:none;
}
.ql-lede,.ql-lede p{ font-size:19px; line-height:1.6; color:var(--ink-2); }
.ql-tone{ background:var(--paper-2); border-top:1px solid var(--rule); border-bottom:1px solid var(--rule); }
.ql-dark{ background:var(--ink); color:#fff; }
.ql-dark h1,.ql-dark h2,.ql-dark h3{ color:#fff; }
.ql-dark p{ color:rgba(255,255,255,.7); }
.ql-specs{ border-top:1px solid var(--ink); }
.ql-specs dl{ margin:0; display:grid; grid-template-columns:auto 1fr; }
.ql-specs dt{
  font-family:var(--display); font-weight:400; font-size:10.5px; letter-spacing:.18em;
  text-transform:uppercase; color:var(--ink-3); padding:15px 26px 15px 0;
  border-bottom:1px solid var(--rule); white-space:nowrap;
}
.ql-specs dd{ margin:0; padding:15px 0; border-bottom:1px solid var(--rule); font-family:var(--mono); font-size:14px; }
.ql-note{ background:var(--accent-lt); border-left:2px solid var(--accent); padding:22px 24px; margin:var(--s4) 0; color:var(--ink-2); }
.ql-warn{ background:var(--warn-lt); border-left:2px solid var(--warn); padding:22px 24px; margin:var(--s4) 0; color:var(--ink-2); }
.ql-checklist{ list-style:none; padding:0; margin:0; border-top:1px solid var(--ink); }
.ql-checklist li{ display:flex; gap:var(--s2); padding:17px 0; border-bottom:1px solid var(--rule); align-items:flex-start; }
.ql-checklist .st{
  font-family:var(--display); font-weight:400; font-size:9.5px; letter-spacing:.16em;
  text-transform:uppercase; padding:4px 8px; flex-shrink:0; margin-top:2px;
  border:1px solid var(--rule-2); color:var(--ink-3); background:var(--paper);
}
.ql-checklist .st.inc{ border-color:var(--ok-br); background:var(--ok-lt); color:var(--ok); }
.ql-checklist .st.you{ border-color:var(--warn-br); background:var(--warn-lt); color:var(--warn); }
.ql-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:1px; background:var(--rule); border:1px solid var(--rule); }
.ql-card{ background:var(--paper); display:flex; flex-direction:column; text-decoration:none; }
.ql-card:hover{ background:var(--paper-2); }
.ql-card img{ width:100%; aspect-ratio:4/3; object-fit:cover; mix-blend-mode:multiply; }
.ql-tag{
  font-family:var(--display); font-weight:400; font-size:10px; letter-spacing:.18em;
  text-transform:uppercase; padding:5px 10px; border:1px solid var(--rule-2);
  color:var(--ink-2); background:var(--paper); display:inline-block;
}
.ql-tag-sale{ background:var(--sale); border-color:var(--sale); color:#fff; }
.ql-tag-ok{ background:var(--ok-lt); border-color:var(--ok-br); color:var(--ok); }
.elementor-button{
  display:inline-flex; align-items:center; justify-content:center; min-height:52px;
  padding:0 28px; border-radius:0; background:var(--ink); color:#fff;
  font-family:var(--body); font-size:14.5px; font-weight:500; text-decoration:none;
}
.elementor-button:hover{ background:var(--accent); color:#fff; }

/* ── 9. BLOG ───────────────────────────────────────────────────────── */
/* Previously these lived as inline <style> blocks in partials/news-block.php
   and single.php, written against the superseded ql-* token set. Now a single
   source, on prototype tokens. */

/* ---- index ---- */
.b-blog{
  max-width:var(--max); margin:0 auto; padding:var(--s6) var(--s4) var(--s7);
  display:flex; gap:var(--s6); align-items:flex-start;
}
.b-blog__content{ flex:1; min-width:0; }
.b-blog__list{ display:flex; flex-direction:column; }
.b-blog__list-itm{ border-bottom:1px solid var(--rule); padding:var(--s4) 0; }
.b-blog__list-itm:first-child{ padding-top:0; }

.b-box-news{ display:flex; gap:var(--s4); align-items:flex-start; text-decoration:none; }
.b-box-news__pic{ flex-shrink:0; width:220px; }
.b-box-news__pic img{
  width:100%; aspect-ratio:4/3; object-fit:cover;
  mix-blend-mode:multiply; display:block; background:var(--paper-2);
}
.b-box-news__body{ flex:1; min-width:0; }
.b-box-news__title{ margin:0 0 8px; }
.b-box-news__title a{
  font-family:var(--display); font-weight:300; font-size:21px; line-height:1.24;
  letter-spacing:-.012em; text-transform:none; color:var(--ink); text-decoration:none;
}
.b-box-news__title a:hover{ color:var(--accent); }
.b-box-news__txt{
  color:var(--ink-2); font-size:15px; line-height:1.6; margin-bottom:14px;
}
.b-box-news__txt p{ margin:0; font-size:15px; }
.b-box-news__footer{ display:flex; align-items:center; gap:18px; }
.b-box-news__date,
.b-post__meta .b-box-news__date{
  font-family:var(--display); font-weight:400; font-size:10.5px; letter-spacing:.18em;
  text-transform:uppercase; color:var(--ink-3); display:flex; align-items:center; gap:6px;
}
.b-box-news__date .icon-calendar,
.b-post__meta .icon-calendar{ display:none; }
.more-link{
  font-family:var(--body); font-size:13.5px; font-weight:500; color:var(--accent);
  text-decoration:none; display:inline-flex; align-items:center; gap:4px;
}

/* ---- sidebar ---- */
.b-blog__aside{ width:300px; flex-shrink:0; }
.b-video-list{ background:var(--paper-2); border:1px solid var(--rule); padding:var(--s3); }
.b-video-list .b-box-news__title{ display:none; }
.b-video-list h3.b-box-news__title{
  display:block; font-family:var(--display); font-weight:400; font-size:10px;
  letter-spacing:.2em; text-transform:uppercase; color:var(--ink-3);
  margin:0 0 18px; border:0;
}
.b-video-list__itm{ margin-bottom:16px; }
.b-video-list__itm:last-child{ margin-bottom:0; }
.b-video-list__itm .responsive-embed{ border:1px solid var(--rule); overflow:hidden; }
.woocommerce-pagination{ max-width:var(--max); margin:0 auto; padding:0 var(--s4) var(--s6); }

/* ---- single post ---- */
.s-post .container,
.s-post > .wrap{ max-width:var(--max); margin:0 auto; padding:var(--s5) var(--s4) 0; }
.s-post__wrp{ display:flex; gap:var(--s6); align-items:flex-start; }
.s-post__content{ flex:1; min-width:0; max-width:760px; }
.s-post__aside{ width:300px; flex-shrink:0; }
.s-post__aside .b-post__section{ margin-top:0; }
.s-post__aside .b-box-list,
.s-post__aside .b-post__list{ display:flex; flex-direction:column; gap:18px; }

.b-post__title{
  font-family:var(--display); font-weight:250; letter-spacing:-.012em;
  font-size:clamp(1.9rem,3.4vw,2.6rem); line-height:1.12; color:var(--ink);
  text-transform:none; margin:0 0 18px;
}
.b-post__meta{ margin-bottom:var(--s4); }

.article{ font-size:16.5px; line-height:1.7; color:var(--ink-2); }
.article p{ margin:0 0 20px; }
.article h2,.article h3,.article h4{
  font-family:var(--display); font-weight:300; color:var(--ink);
  letter-spacing:-.012em; margin:40px 0 18px; line-height:1.25;
}
.article h2{ font-size:28px; }
.article h3{ font-size:21px; }
.article ul,.article ol{ padding-left:22px; margin:0 0 20px; }
.article li{ margin-bottom:8px; }
.article a{ color:var(--accent); }
.article img{ max-width:100%; height:auto; }
.article table{ width:100%; border-collapse:collapse; margin:24px 0; border-top:1px solid var(--ink); }
.article table th,.article table td{
  text-align:left; padding:14px 16px 14px 0; border-bottom:1px solid var(--rule); font-size:15px;
}
.article table th{
  font-family:var(--display); font-weight:400; font-size:10.5px; letter-spacing:.18em;
  text-transform:uppercase; color:var(--ink-3);
}

.b-post__footer{ margin-top:48px !important; padding-top:var(--s3); border-top:1px solid var(--rule); align-items:center; }
.b-post__soc-title,
.b-post__section-title span{
  font-family:var(--display); font-weight:400; font-size:10.5px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--ink-3); display:block; margin-bottom:10px;
}
.b-post__section-title span{ border-bottom:1px solid var(--rule); padding-bottom:14px; margin-bottom:20px; }
.b-post__section{ margin-top:var(--s6); }
.b-post__nav-link{
  font-family:var(--body); font-size:13.5px; font-weight:500; color:var(--accent);
  text-decoration:none; margin-left:20px;
}

@media(max-width:900px){
  .b-blog,.s-post__wrp{ flex-direction:column; }
  .b-blog__aside,.s-post__aside{ width:100%; }
  .b-box-news{ flex-direction:column; }
  .b-box-news__pic{ width:100%; }
}

/* ---- single post, prototype layout ----------------------------------- */
/* single.php now renders .crumb / .post-head / .post-hero / .post-body /
   .post-nav, all of which are styled in quantum-proto.css. Only the pieces
   WordPress adds on top need bridging. */

/* Editor-inserted media has no width ceiling in the prototype rules, and the
   media library serves originals well over 70ch wide. */
.post-body img,
.post-body iframe,
.post-body video,
.post-body table{ max-width:100%; height:auto; }
.post-body figure{ margin:var(--s4) 0; }
.post-body figcaption{
  font-size:13px; color:var(--ink-3); margin-top:8px; line-height:1.5;
}
.post-body table{
  width:100%; border-collapse:collapse; margin:var(--s4) 0;
  border-top:1px solid var(--ink); height:auto;
}
.post-body th,.post-body td{
  text-align:left; padding:14px 16px 14px 0;
  border-bottom:1px solid var(--rule); font-size:15px;
}
.post-body th{
  font-family:var(--display); font-weight:400; font-size:10.5px;
  letter-spacing:.18em; text-transform:uppercase; color:var(--ink-3);
}
.post-body > *:last-child{ margin-bottom:0; }

/* Share row appended to the end of the body. */
.post-share{
  margin-top:var(--s5); padding-top:var(--s3);
  border-top:1px solid var(--rule);
  display:flex; align-items:center; gap:16px; flex-wrap:wrap;
}
.post-share .k{
  font-family:var(--display); font-weight:400; font-size:10px;
  letter-spacing:.2em; text-transform:uppercase; color:var(--ink-3);
}
.post-share .sharedaddy,
.post-share .sd-content{ margin:0 !important; padding:0 !important; }
.post-share h3.sd-title{ display:none !important; }

/* .post-nav uses space-between; the empty placeholder keeps a lone "Next"
   pinned right when there is no previous post. */
.post-nav > span:empty{ flex:0 0 auto; }

/* ═══════════════════════════════════════════════════════════════════════
   SCIENCE KITS FOR KIDS — video-led landing page
   Prefixed .kv- throughout so nothing here can collide with the shared
   prototype classes (.phero, .grid, .card ...) used on every other page.

   The three step clips are encoded GREYSCALE at source, not desaturated in
   CSS: a filter on a playing video forces a repaint every frame on the
   compositor and is visibly expensive on low-end phones.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Hero ───────────────────────────────────────────────────────────── */
.kv-hero{ position:relative; background:var(--paper); overflow:hidden; }

/* The media box is inset from the LEFT rather than full-bleed, and this is the
   only thing that actually moves the levitating disc.
   object-position was tried first and does nothing here: the hero box is far
   wider than 16/9, so object-fit:cover scales the video to fill the WIDTH and
   the overflow is entirely vertical. With no horizontal overflow there is
   nothing for object-position's X value to slide, and the disc stays pinned to
   the centre of the box — which is exactly where the headline is.
   Insetting the box moves its centre: disc lands at (100 + left) / 2, so
   left:28% puts it at 64% of the viewport, clear of a 34rem text column.
   The hero background is --paper, not --paper-2, so the uncovered strip on the
   left is the same white as the footage's cyclorama and leaves no seam. */
.kv-hero-media{
  position:absolute; inset:0 0 0 28%; z-index:0;
  /* The footage's backdrop is a pale blue gradient, not the white I assumed,
     so the box's left edge showed as a hard vertical seam against --paper.
     Fading the whole layer in over its first 20% removes it. The scrim is a
     child of this element so it is masked too, which is correct: where the
     video has faded out there is nothing left to scrim. */
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 20%);
          mask-image:linear-gradient(90deg,transparent 0,#000 20%);
}
.kv-hero-media video{
  width:100%; height:100%; object-fit:cover; object-position:50% 50%;
  display:block;
}
/* The footage is a white cyclorama, so the scrim runs white -> transparent
   and the headline stays near-black. Reversing this (dark scrim, white text)
   was tried and looked like every other science-kit site. */
/* Scrim now only has to cover the left third of the media box rather than most
   of it, because the box itself starts at 28%. Shorter ramp = more of the
   footage stays visible. */
.kv-hero-media::after{
  content:""; position:absolute; inset:0;
  background:linear-gradient(100deg,
    rgba(255,255,255,.96) 0%, rgba(255,255,255,.72) 16%,
    rgba(255,255,255,.28) 34%, rgba(255,255,255,0) 52%);
}
.kv-hero-inner{
  position:relative; z-index:1;
  max-width:var(--max); margin:0 auto;
  /* Was --s7 (96px) top and bottom, which left a conspicuous empty band
     between the header rule and the eyebrow. The hero reads better tight to
     the header and looser underneath. */
  padding:var(--s4) var(--s3) var(--s6);
  min-height:clamp(380px,46vw,560px);
  display:flex; flex-direction:column; justify-content:center;
}
.kv-hero-txt{ max-width:34rem; }
.kv-hero h1{
  font-family:var(--display); font-weight:400;
  font-size:clamp(34px,5.4vw,60px); line-height:1.02;
  letter-spacing:-.022em; margin:0 0 var(--s2);
}
.kv-hero h1 em{ font-style:normal; display:block; color:var(--ink-3); }
.kv-hero .lede{ font-size:17px; color:var(--ink-2); margin:0 0 var(--s4); max-width:30rem; }
.kv-cta{ display:flex; gap:12px; flex-wrap:wrap; }

/* Trust strip pinned under the hero copy */
.kv-facts{
  display:flex; gap:var(--s4); flex-wrap:wrap;
  margin-top:var(--s5); padding-top:var(--s3);
  border-top:1px solid var(--rule-2);
}
.kv-facts div{ display:flex; flex-direction:column; gap:2px; }
.kv-facts .k{
  font-family:var(--display); font-size:10px; letter-spacing:.18em;
  text-transform:uppercase; color:var(--ink-3);
}
.kv-facts .v{ font-family:var(--mono); font-size:15px; color:var(--ink); }

/* ── Three-step demo strip ──────────────────────────────────────────── */
.kv-steps{ display:grid; grid-template-columns:repeat(3,1fr); gap:var(--s3); }
.kv-step{ display:flex; flex-direction:column; }
.kv-step-media{
  position:relative; aspect-ratio:16/9; background:var(--paper-3);
  overflow:hidden; margin-bottom:var(--s2);
}
.kv-step-media video{ width:100%; height:100%; object-fit:cover; display:block; }
.kv-num{
  position:absolute; top:0; left:0; z-index:2;
  font-family:var(--mono); font-size:11px; letter-spacing:.1em;
  background:var(--ink); color:var(--paper); padding:5px 9px;
}
.kv-step h3{
  font-family:var(--display); font-weight:400; font-size:19px;
  letter-spacing:-.01em; margin:0 0 6px;
}
.kv-step p{ font-size:14.5px; color:var(--ink-2); margin:0; }

/* ── Route cards (the liquid-nitrogen fork) ─────────────────────────── */
.kv-routes{ display:grid; grid-template-columns:1fr 1fr; gap:var(--s3); }
.kv-route{ border:1px solid var(--rule); padding:var(--s3); background:var(--paper); }
.kv-route.no{  border-color:var(--ok-br);   background:var(--ok-lt); }
.kv-route.yes{ border-color:var(--warn-br); background:var(--warn-lt); }
.kv-route .k{
  font-family:var(--display); font-size:10px; letter-spacing:.16em;
  text-transform:uppercase; display:block; margin-bottom:8px;
}
.kv-route.no  .k{ color:var(--ok); }
.kv-route.yes .k{ color:var(--warn); }
.kv-route h3{ font-family:var(--display); font-weight:400; font-size:20px; margin:0 0 6px; }
.kv-route p{ font-size:14.5px; color:var(--ink-2); margin:0; }

/* ── Responsive ─────────────────────────────────────────────────────── */
@media(max-width:900px){
  .kv-steps{ grid-template-columns:1fr; }
  .kv-routes{ grid-template-columns:1fr; }
}
@media(max-width:760px){
  /* On a phone the scrim would have to cover the whole frame to keep the
     headline legible, which hides the footage entirely. Stack instead:
     video above, copy below, both fully visible. */
  /* inset must be reset explicitly: left:28% still offsets a relatively
     positioned element, which would push the video off the right edge. */
  .kv-hero-media{
    position:relative; inset:auto; aspect-ratio:16/9;
    -webkit-mask-image:none; mask-image:none;
  }
  .kv-hero-media::after{
    background:linear-gradient(0deg,rgba(255,255,255,.85) 0%,rgba(255,255,255,0) 42%);
  }
  .kv-hero-inner{ min-height:0; padding:var(--s4) var(--s3) var(--s5); }
  .kv-hero-txt{ max-width:none; }
  .kv-facts{ gap:var(--s3); }
  .kv-cta .btn{ flex:1 1 100%; text-align:center; }
}

/* ── Motion and print ───────────────────────────────────────────────── */
@media(prefers-reduced-motion:reduce){
  .kv-hero-media video,
  .kv-step-media video{ display:none; }
  .kv-hero-media,
  .kv-step-media{
    background-size:cover; background-position:center; background-repeat:no-repeat;
  }
}
@media print{
  .kv-hero-media video, .kv-step-media video{ display:none; }
}

/* ═══════════════════════════════════════════════════════════════════════
   TOP NAV — dropdown for the "Blog" group
   WordPress emits <li class="menu-item-has-children"> containing a
   <ul class="sub-menu">. Desktop reveals on hover AND focus-within, so the
   group is reachable by keyboard without any JS. Touch devices get a tap
   toggle (see header.php) because :hover never resolves there.
   ═══════════════════════════════════════════════════════════════════════ */

@media(min-width:1001px){
  .nav ul li.menu-item-has-children{ position:relative; }

  /* Caret. Drawn in CSS rather than an icon font so it inherits colour and
     needs no extra request.

     It has to be ::before, because ::after already carries the theme's
     underline animation on every nav link. ::before would normally render to
     the LEFT of the text, so the anchor becomes an inline-flex container and
     the caret is pushed to the end with order:2 — the one property that
     reorders a pseudo-element without touching the markup. */
  .nav ul li.menu-item-has-children > a{
    display:inline-flex; align-items:center;
  }
  .nav ul li.menu-item-has-children > a::before{
    content:""; order:2; flex:0 0 auto;
    width:5px; height:5px; margin-left:8px; margin-top:-3px;
    border-right:1px solid currentColor; border-bottom:1px solid currentColor;
    transform:rotate(45deg); opacity:.55; transition:opacity .15s;
  }
  .nav ul li.menu-item-has-children:hover > a::before,
  .nav ul li.menu-item-has-children:focus-within > a::before{ opacity:1; }

  .nav ul .sub-menu{
    position:absolute; top:100%; left:-14px; z-index:60;
    display:block; flex-direction:column; gap:0;
    min-width:210px; padding:6px 0;
    background:var(--paper); border:1px solid var(--rule);
    box-shadow:0 16px 34px rgba(10,11,13,.11);
    opacity:0; visibility:hidden; transform:translateY(-4px);
    transition:opacity .16s, transform .16s, visibility 0s .16s;
  }
  .nav ul li.menu-item-has-children:hover > .sub-menu,
  .nav ul li.menu-item-has-children:focus-within > .sub-menu,
  .nav ul li.menu-item-has-children.open > .sub-menu{
    opacity:1; visibility:visible; transform:translateY(0);
    transition:opacity .16s, transform .16s, visibility 0s 0s;
  }
  /* The gap between the link and the panel would drop the hover on the way
     down. This pseudo-element bridges it without moving anything visually. */
  .nav ul li.menu-item-has-children::after{
    content:""; position:absolute; top:100%; left:0; right:0; height:14px;
  }

  .nav ul .sub-menu li{ width:100%; }
  .nav ul .sub-menu a{
    display:block; padding:10px 18px; white-space:nowrap;
    letter-spacing:.06em; border-bottom:0;
  }
  .nav ul .sub-menu a::after{ display:none; }
  .nav ul .sub-menu a:hover{ background:var(--paper-2); }
}

/* In the hamburger panel the group is always expanded — a dropdown inside a
   dropdown is a worse experience than three indented links. */
@media(max-width:1000px){
  .nav ul .sub-menu{
    display:flex; flex-direction:column; gap:0;
    margin:0; padding:0 0 0 18px; list-style:none;
    border-left:1px solid var(--rule);
  }
  .nav ul .sub-menu a{ font-size:11.5px; color:var(--ink-2); }
  .nav ul li.menu-item-has-children > a{ border-bottom:0; }
}

/* After a successful AJAX add, WooCommerce's add-to-cart.js injects
   <a class="added_to_cart">View cart</a> DIRECTLY AFTER the clicked button —
   i.e. between "Add to cart" and "Buy Now" inside form.cart. The extra ~90px
   forces the button row to wrap and the two buttons end up overlapping
   (user-reported on the Maglev Kit page; applies to every product). The link
   is redundant here: the drawer slides open on add and already contains
   "View cart". Hide the injection everywhere. */
form.cart a.added_to_cart{ display:none !important; }

/* ═══════════════════════════════════════════════════════════════════════
   CART — Composite Products rows
   A composite in the cart is TWO rows: the container (priced with the
   aggregate) and a component_table_item child. The plugin prints the child
   with its own thumbnail, the SAME price, a bare "1" for quantity and a
   "Subtotal: $x" string — which reads as a duplicate product and makes the
   totals look wrong (user-reported, twice). The child is configuration
   detail, so render it as exactly that: an indented, muted line under its
   container with the duplicated figures hidden. Nothing is lost — every
   hidden number is already on the container row.
   ═══════════════════════════════════════════════════════════════════════ */
.woocommerce-cart table.cart tr.component_table_item td{
  border-top:0; padding-top:0; font-size:13px; color:var(--ink-3);
}
.woocommerce-cart table.cart tr.component_table_item .product-thumbnail img{
  width:38px; height:auto; opacity:.65;
}
.woocommerce-cart table.cart tr.component_table_item .product-name{
  padding-left:26px;
}
.woocommerce-cart table.cart tr.component_table_item .product-name::before{
  content:"\21B3\00A0";           /* ↳ */
  color:var(--ink-3);
}
.woocommerce-cart table.cart tr.component_table_item .product-price,
.woocommerce-cart table.cart tr.component_table_item .product-quantity,
.woocommerce-cart table.cart tr.component_table_item .product-subtotal{
  /* visibility, not font-size:0 — the plugin's "↳" prefix is styled with its
     own size and survived the font trick as stray floating arrows. The cells
     stay in the row so the columns keep their alignment. */
  visibility:hidden;
}
/* The same duplication appears in the drawer; the template now adds
   mini-cart__item--component for child rows.

   The row's base layout is grid 64px 1fr auto (thumb / body / remove). With
   the thumb hidden, the BODY became the first grid child and was laid out in
   the 64px thumbnail column — the meta rendered one word per line down a
   sliver on the left (user-reported). Component rows therefore drop the grid
   entirely: they are a single text block, so there is nothing to misplace. */
.mini-cart__item--component{
  display:block; padding-left:calc(var(--s4) + 26px);
  padding-top:10px; padding-bottom:14px;
}
.mini-cart__item--component .mini-cart__thumb{ display:none; }
.mini-cart__item--component .mini-cart__name{
  font-size:12.5px; color:var(--ink-3); margin-bottom:2px;
}
.mini-cart__item--component .mini-cart__name::before{ content:"\21B3\00A0"; }
.mini-cart__item--component .mini-cart__line{ display:none; }
/* wc_get_formatted_cart_item_data() emits a <dl class="variation"> of dt/dd
   pairs, block-level by default — six stacked lines for two attributes. Render
   each pair as one "label: value" line. */
.mini-cart__item--component .mini-cart__meta dl{ margin:0; }
.mini-cart__item--component .mini-cart__meta dt,
.mini-cart__item--component .mini-cart__meta dd{
  display:inline; margin:0; padding:0; font-size:12px; color:var(--ink-3);
  font-weight:400;
}
.mini-cart__item--component .mini-cart__meta dd::after{ content:"\A"; white-space:pre; }
.mini-cart__item--component .mini-cart__meta dd p{ display:inline; margin:0; }

/* Inline privacy policy reader at checkout (see quantum-cart.js). */
.ql-privacy-inline{
  margin:14px 0; border:1px solid var(--rule); background:var(--paper);
  max-height:340px; overflow-y:auto; font-size:13.5px;
}
.ql-privacy-head{
  position:sticky; top:0; display:flex; justify-content:space-between;
  align-items:center; padding:10px 16px; background:var(--paper-2);
  border-bottom:1px solid var(--rule);
}
.ql-privacy-close{
  border:0; background:none; font-size:20px; line-height:1; cursor:pointer;
  color:var(--ink-3); padding:0 4px;
}
.ql-privacy-close:hover{ color:var(--ink); }
.ql-privacy-body{ padding:14px 16px; }
.ql-privacy-body h1{ display:none; }           /* page title is redundant here */
.ql-privacy-body h2{ font-size:15px; margin:14px 0 6px; }
.ql-privacy-body p, .ql-privacy-body li{ color:var(--ink-2); }
.ql-privacy-loading{ padding:14px 16px; margin:0; color:var(--ink-3); }
