/*
Theme Name: Jörden Piper
Theme URI: https://jordenpiper.ee
Description: Advanced Carbon & Material Solutions — technical datasheet design language for
             an industrial materials catalogue. Child theme of Extendable.
Author: Jörden Piper
Template: extendable
Version: 1.8.0
Text Domain: jordenpiper
*/

/* ---------------------------------------------------------------------------
   Tokens. theme.json carries the palette for the block editor; these are the
   extras the editor has no concept of — line weights, radii, shadows, rails.
   Dark is the default here: an instrument reads as dark, paper reads as retail.
   --------------------------------------------------------------------------- */
:root {
  --jp-ground:      #101418;
  --jp-surface:     #171C21;
  --jp-surface-2:   #1F252B;
  --jp-ink:         #E8EBEC;
  --jp-ink-2:       #C2C8CB;
  --jp-muted:       #8B959C;
  --jp-line:        #2E363D;
  --jp-line-soft:   #232A30;
  --jp-accent:      #3E8FFF;
  --jp-accent-ink:  #08111F;
  --jp-accent-soft: #16233A;
  --jp-blueprint:   #7FB0DA;

  --jp-ok:   #4C9A63;
  --jp-warn: #C08A1E;
  --jp-out:  #6E777D;

  /* Near-square corners. Instruments have edges; consumer apps have pills. */
  --jp-r-sm: 2px;
  --jp-r:    3px;
  --jp-r-lg: 5px;

  --jp-maxw: 1320px;
  --jp-rail: 250px;

  --jp-font-sans: ui-sans-serif, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --jp-font-mono: ui-monospace, "Cascadia Mono", "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
}

/* No light-mode variant.
 *
 * An earlier revision flipped these tokens under prefers-color-scheme: light.
 * That produced a broken hybrid: theme.json's palette is fixed dark, so only the
 * parts painted from these custom properties — the mobile menu overlay, form
 * fields, the spec table — turned light, while the rest of the page stayed dark.
 * On a phone in light mode the menu opened as a white panel on a dark site.
 *
 * The brand is dark-first by design, so the palette is unconditional.
 */

/* ---------------------------------------------------------------------------
   Technical data. Any figure a buyer might compare across products — purity,
   particle size, CAS, SKU — goes monospace so digits line up column-wise.
   --------------------------------------------------------------------------- */
.jp-spec,
.jp-spec-table,
.woocommerce-product-attributes,
.sku_wrapper,
.sku {
  font-family: var(--jp-font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.875rem;
}

.jp-spec-table {
  width: 100%;
  border-collapse: collapse;
}

.jp-spec-table th,
.jp-spec-table td {
  border-bottom: 1px solid var(--jp-line-soft);
  padding: 0.5rem 0.75rem;
  text-align: left;
  vertical-align: top;
}

.jp-spec-table th {
  color: var(--jp-muted);
  font-weight: 500;
  white-space: nowrap;
  width: 40%;
}

/* A missing value is information too. Never render an empty row. */
.jp-spec-table td:empty::after {
  content: "Data available on request";
  color: var(--jp-muted);
  font-style: italic;
}

/* ---------------------------------------------------------------------------
   Quote-only products. Regulated materials show an enquiry route instead of a
   cart button; the visual weight stays identical so neither reads as inferior.
   --------------------------------------------------------------------------- */
.jp-quote-button {
  display: inline-block;
  padding: 0.7rem 1.4rem;
  border: 1px solid var(--jp-accent);
  border-radius: var(--jp-r);
  color: var(--jp-accent);
  background: transparent;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-decoration: none;
}

.jp-quote-button:hover,
.jp-quote-button:focus-visible {
  background: var(--jp-accent-soft);
}

.jp-regulated-note {
  margin-top: 0.75rem;
  padding-left: 0.75rem;
  border-left: 2px solid var(--jp-warn);
  color: var(--jp-muted);
  font-size: 0.8125rem;
}

/* Document downloads: SDS / TDS / COA. Rendered only when a file exists. */
.jp-docs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 1.25rem 0;
}

.jp-doc-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.45rem 0.8rem;
  border: 1px solid var(--jp-line);
  border-radius: var(--jp-r-sm);
  color: var(--jp-ink-2);
  font-family: var(--jp-font-mono);
  font-size: 0.8125rem;
  text-decoration: none;
}

.jp-doc-link:hover {
  border-color: var(--jp-accent);
  color: var(--jp-accent);
}

/* ---------------------------------------------------------------------------
   Product figures are generated SVG, not photography. Graphene, GO and rGO all
   photograph as identical black powder; a structural drawing carries the
   information a photograph cannot.
   --------------------------------------------------------------------------- */
.jp-glyph {
  display: block;
  width: 100%;
  height: auto;
  background: var(--jp-surface-2);
  border: 1px solid var(--jp-line-soft);
  border-radius: var(--jp-r);
}

.jp-glyph .jp-glyph-stroke {
  stroke: var(--jp-blueprint);
  fill: none;
  stroke-width: 1.25;
  vector-effect: non-scaling-stroke;
}

.jp-glyph .jp-glyph-accent {
  stroke: var(--jp-accent);
  fill: none;
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
}

.jp-glyph .jp-glyph-fill {
  fill: var(--jp-line-soft);
}

@media (prefers-reduced-motion: no-preference) {
  .jp-glyph { transition: border-color 120ms ease; }
  .jp-glyph:hover { border-color: var(--jp-accent); }
}


/* ---------------------------------------------------------------------------
   Product figures via CSS.

   WooCommerce renders the shop grid with blocks, which ignore the classic
   template hooks — but every card still carries a `product_cat-<slug>` class.
   So the figure is attached by category in CSS instead: no PHP hook, no media
   library entry, and no SVG upload (which WordPress blocks by default).

   The stock placeholder image is faded rather than removed, so it keeps the
   grid's aspect ratio intact while the figure shows through behind it.
   --------------------------------------------------------------------------- */

.wc-block-components-product-image,
.woocommerce-product-gallery__image {
  background-color: var(--jp-surface);
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
  border: 1px solid var(--jp-line-soft);
  border-radius: var(--jp-r);
  overflow: hidden;
}

/* Only the placeholder gets hidden. A real supplier photo always wins. */
.wc-block-components-product-image img[src*="woocommerce-placeholder"],
.woocommerce-product-gallery__image img[src*="woocommerce-placeholder"] {
  opacity: 0;
}

.product_cat-graphite .wc-block-components-product-image,
.product_cat-graphite .woocommerce-product-gallery__image {
  background-image: url("figures/jp-graphite.svg");
}

.product_cat-graphene .wc-block-components-product-image,
.product_cat-graphene .woocommerce-product-gallery__image {
  background-image: url("figures/jp-graphene.svg");
}

.product_cat-graphene-oxide .wc-block-components-product-image,
.product_cat-graphene-oxide .woocommerce-product-gallery__image {
  background-image: url("figures/jp-graphene-oxide.svg");
}

.product_cat-reduced-graphene-oxide .wc-block-components-product-image,
.product_cat-reduced-graphene-oxide .woocommerce-product-gallery__image {
  background-image: url("figures/jp-reduced-graphene-oxide.svg");
}

.product_cat-carbon-materials .wc-block-components-product-image,
.product_cat-carbon-materials .woocommerce-product-gallery__image {
  background-image: url("figures/jp-carbon-materials.svg");
}

.product_cat-carbon-powders .wc-block-components-product-image,
.product_cat-carbon-powders .woocommerce-product-gallery__image {
  background-image: url("figures/jp-carbon-powders.svg");
}

.product_cat-metal-oxides .wc-block-components-product-image,
.product_cat-metal-oxides .woocommerce-product-gallery__image {
  background-image: url("figures/jp-metal-oxides.svg");
}

.product_cat-ceramic-oxides .wc-block-components-product-image,
.product_cat-ceramic-oxides .woocommerce-product-gallery__image {
  background-image: url("figures/jp-ceramic-oxides.svg");
}

.product_cat-nanomaterials .wc-block-components-product-image,
.product_cat-nanomaterials .woocommerce-product-gallery__image {
  background-image: url("figures/jp-nanomaterials.svg");
}

/* ---------------------------------------------------------------------------
   Masthead scale.

   The brand was set at 16px with a 42px mark — correct for a small retail
   header, too quiet for a supplier whose name has to carry authority on a
   datasheet-like page. Doubled to 32px / 84px, with the title clamped so it
   does not wrap awkwardly on narrow screens.
   --------------------------------------------------------------------------- */
.wp-block-site-title,
.wp-block-site-title.has-medium-font-size,
.wp-block-site-title a {
  font-size: clamp(1.25rem, 2.4vw, 2rem);
  line-height: 1.15;
  font-weight: 600;
  letter-spacing: 0.01em;
}

.wp-block-site-logo img,
.wp-block-site-logo.is-default-size img {
  width: 84px !important;
  max-width: 84px !important;
  height: auto !important;
}

/* The front page opens with its own hero, so the template's page title would
   just repeat "Home" above it. Hidden only there — every other page still
   needs its heading for orientation and for screen readers. */
body.home .wp-block-post-title,
body.home .wp-block-query-title {
  display: none;
}

/* ---------------------------------------------------------------------------
   Brand lockup.

   The logo already contains the wordmark, so rendering the site title beside it
   would print the company name twice. The title is hidden visually but kept in
   the document for screen readers and for the accessible name of the home link.
   --------------------------------------------------------------------------- */
.wp-block-site-title {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.wp-block-site-logo img,
.wp-block-site-logo.is-default-size img {
  /* The block stores its own width attribute, so both have to be overridden
     or the image silently caps at whatever the editor last saved. */
  width: min(560px, 72vw) !important;
  max-width: none !important;
  height: auto !important;
}

/* ---------------------------------------------------------------------------
   Header actions as buttons.

   Every item in the masthead — nav links, the account and cart icons — takes
   the same filled treatment as the primary call to action, so the header reads
   as one row of controls rather than text links with a button bolted on the end.
   --------------------------------------------------------------------------- */
.wp-block-navigation .wp-block-navigation-item__content,
.wc-block-customer-account,
.wc-block-customer-account__link,
.wp-block-woocommerce-mini-cart > a,
.wc-block-mini-cart__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  min-height: 2.25rem;
  padding: 0.45rem 1.1rem;
  border: 1px solid var(--jp-accent);
  border-radius: var(--jp-r);
  background-color: var(--jp-accent);
  color: var(--jp-accent-ink) !important;
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none !important;
  white-space: nowrap;
  transition: background-color 120ms ease, border-color 120ms ease;
}

/* Icon-only controls stay square rather than stretching to a pill. */
.wc-block-customer-account,
.wc-block-customer-account__link,
.wp-block-woocommerce-mini-cart > a,
.wc-block-mini-cart__button {
  padding: 0.45rem;
  min-width: 2.25rem;
}

.wp-block-navigation .wp-block-navigation-item__content:hover,
.wp-block-navigation .wp-block-navigation-item__content:focus-visible,
.wc-block-customer-account:hover,
.wc-block-customer-account__link:hover,
.wp-block-woocommerce-mini-cart > a:hover,
.wc-block-mini-cart__button:hover {
  background-color: var(--jp-blueprint);
  border-color: var(--jp-blueprint);
}

/* The icons themselves inherit the button's foreground rather than staying
   accent-blue on an accent-blue field. */
.wc-block-customer-account svg,
.wc-block-customer-account__link svg,
.wc-block-mini-cart__button svg,
.wp-block-woocommerce-mini-cart svg {
  fill: currentColor;
  stroke: currentColor;
}

.wc-block-mini-cart__badge {
  background: var(--jp-ground);
  color: var(--jp-ink);
}

/* Breathing room so the row of buttons does not collide. */
.wp-block-navigation__container,
.ext-nav-extras {
  gap: 0.6rem;
}

/* ---------------------------------------------------------------------------
   Header alignment and cart weight.

   The standalone "Explore products" call to action was removed — it went to the
   same place as the Shop link, and two buttons competing for one destination
   just split attention. The remaining controls take its position at the right.

   All four controls share one size, so the row reads as a single set.
   --------------------------------------------------------------------------- */
.ext-nav-extras {
  margin-left: auto;
  justify-content: flex-end;
  align-items: center;
}

.wp-block-woocommerce-mini-cart > a,
.wc-block-mini-cart__button {
  min-width: 2.25rem;
  min-height: 2.25rem;
  padding: 0.45rem;
}

.wc-block-mini-cart__button svg,
.wp-block-woocommerce-mini-cart svg,
.wc-block-customer-account__link svg {
  width: 1.1rem;
  height: 1.1rem;
}

.wc-block-mini-cart__badge {
  font-size: 0.8125rem;
  font-weight: 700;
}

/* ---------------------------------------------------------------------------
   Quote request form.
   --------------------------------------------------------------------------- */
.jp-quote-form {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem 1.25rem;
  max-width: 820px;
  margin-block: 2rem;
}

.jp-quote-field { margin: 0; display: flex; flex-direction: column; gap: 0.35rem; }
.jp-quote-field--message,
.jp-quote-context,
.jp-quote-submit,
.jp-quote-notice { grid-column: 1 / -1; }

.jp-quote-form label {
  color: var(--jp-muted);
  font-size: 0.8125rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.jp-quote-form input,
.jp-quote-form textarea {
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--jp-line);
  border-radius: var(--jp-r);
  background: var(--jp-surface);
  color: var(--jp-ink);
  font-family: inherit;
  font-size: 0.9375rem;
}

.jp-quote-form input:focus-visible,
.jp-quote-form textarea:focus-visible {
  outline: 2px solid var(--jp-accent);
  outline-offset: 1px;
  border-color: var(--jp-accent);
}

/* The product carried over from the product page, shown as fixed context. */
.jp-quote-context {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.35rem 1rem;
  padding: 0.9rem 1rem;
  border: 1px solid var(--jp-line);
  border-left: 2px solid var(--jp-accent);
  border-radius: var(--jp-r);
  background: var(--jp-surface);
  font-family: var(--jp-font-mono);
  font-size: 0.875rem;
}

.jp-quote-context__label { color: var(--jp-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.jp-quote-context__value { color: var(--jp-ink); }

.jp-quote-submit {
  justify-self: start;
  padding: 0.7rem 1.6rem;
  border: 1px solid var(--jp-accent);
  border-radius: var(--jp-r);
  background: var(--jp-accent);
  color: var(--jp-accent-ink);
  font-weight: 600;
  font-size: 0.9375rem;
  letter-spacing: 0.02em;
  cursor: pointer;
}

.jp-quote-submit:hover { background: var(--jp-blueprint); border-color: var(--jp-blueprint); }

.jp-quote-notice { padding: 0.9rem 1rem; border-radius: var(--jp-r); border-left: 2px solid; }
.jp-quote-notice--ok { border-color: var(--jp-ok); background: color-mix(in srgb, var(--jp-ok) 12%, transparent); }
.jp-quote-notice--error { border-color: var(--jp-warn); background: color-mix(in srgb, var(--jp-warn) 12%, transparent); }
.jp-quote-notice p { margin: 0; }

/* Honeypot: off-screen rather than display:none, which some bots detect. */
.jp-quote-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

@media (max-width: 640px) {
  .jp-quote-form { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------------
   Site background.

   Fixed behind the whole site rather than tiled into one section, so scrolling
   reads as moving over a surface instead of past a picture. The ground colour
   stays underneath: if the image fails to load, or on very tall pages where it
   runs out, the palette still holds and nothing goes white.

   A dark scrim sits over it so text contrast never depends on which part of the
   photograph a paragraph happens to land on.
   --------------------------------------------------------------------------- */
body {
  background-color: var(--jp-ground);
  background-image:
    linear-gradient(rgba(16, 20, 24, 0.82), rgba(16, 20, 24, 0.92)),
    url("assets/jp-bg.webp");
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center top;
  background-attachment: fixed;
}

/* Phones get the smaller file, and scroll rather than fixed — iOS renders
   fixed backgrounds by painting them at full viewport height, which causes
   visible jumps as the address bar hides and shows. */
@media (max-width: 782px) {
  body {
    background-image:
      linear-gradient(rgba(16, 20, 24, 0.84), rgba(16, 20, 24, 0.94)),
      url("assets/jp-bg-sm.webp");
    background-attachment: scroll;
  }
}

/* Sections that previously painted flat colour now let the background show,
   except where a raised surface is genuinely wanted (cards, form fields). */
.wp-site-blocks > .wp-block-group.has-background-background-color {
  background-color: transparent !important;
}

/* The parent theme's header overlays the first section on the front page. Once
   that section stopped painting its own background it began creating a stacking
   context above the header, which hid the logo behind it. Lifting the header
   settles the order explicitly rather than relying on document flow. */
header.wp-block-template-part,
.wp-site-blocks > header,
.ext-header-sticky {
  position: relative;
  z-index: 20;
}

/* ---------------------------------------------------------------------------
   Form controls.

   Selects, number inputs and text fields were still using browser defaults —
   dark text on a dark field, effectively invisible. Every control the shop
   renders (variation pickers, quantity, sorting, coupon and checkout fields)
   is brought onto the palette here, including <option>, which some browsers
   paint from the system theme rather than the page.
   --------------------------------------------------------------------------- */
select,
input[type="text"],
input[type="email"],
input[type="tel"],
input[type="url"],
input[type="number"],
input[type="search"],
input[type="password"],
input[type="date"],
textarea,
.woocommerce input.input-text,
.woocommerce select,
.woocommerce .quantity .qty,
.wc-block-components-text-input input,
.wc-block-components-sort-select__select {
  background-color: var(--jp-surface) !important;
  color: var(--jp-ink) !important;
  border: 1px solid var(--jp-line) !important;
  border-radius: var(--jp-r);
  padding: 0.5rem 0.7rem;
  font-family: inherit;
  font-size: 0.9375rem;
}

select option {
  background-color: var(--jp-surface);
  color: var(--jp-ink);
}

select:focus-visible,
input:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--jp-accent);
  outline-offset: 1px;
  border-color: var(--jp-accent) !important;
}

::placeholder { color: var(--jp-muted); opacity: 1; }

/* Quantity spinner sits next to the cart button, so it needs the same height. */
.woocommerce .quantity .qty {
  width: 4.5rem;
  text-align: center;
}

/* Shop actions use the accent rather than the parent theme's muted blue. */
.woocommerce button.button,
.woocommerce a.button,
.woocommerce button.button.alt,
.woocommerce input.button,
.wc-block-components-button {
  background-color: var(--jp-accent) !important;
  color: var(--jp-accent-ink) !important;
  border: 1px solid var(--jp-accent) !important;
  border-radius: var(--jp-r);
  font-weight: 600;
}

.woocommerce button.button:hover,
.woocommerce a.button:hover,
.woocommerce button.button.alt:hover,
.wc-block-components-button:hover {
  background-color: var(--jp-blueprint) !important;
  border-color: var(--jp-blueprint) !important;
}

/* A disabled cart button must read as disabled, not as a live control. */
.woocommerce button.button:disabled,
.woocommerce button.button.disabled {
  background-color: var(--jp-line) !important;
  border-color: var(--jp-line) !important;
  color: var(--jp-muted) !important;
}

/* Variation table labels and the reset link. */
.woocommerce div.product form.cart .variations label,
.woocommerce div.product form.cart .variations th {
  color: var(--jp-ink-2);
  font-weight: 600;
}

.woocommerce div.product form.cart .reset_variations { color: var(--jp-accent); }

/* Attribute and specification tables. */
.woocommerce table.shop_attributes th,
.woocommerce table.shop_attributes td,
.woocommerce-Tabs-panel table th,
.woocommerce-Tabs-panel table td {
  border-color: var(--jp-line-soft);
  color: var(--jp-ink-2);
}

/* ---------------------------------------------------------------------------
   Unselected variation prompt.

   "Choose an option" is a required action, not a value — showing it in red
   marks the product as not yet configured, and it returns to normal ink once a
   package size is picked. :has() handles the closed control (what the shopper
   sees before opening it); the option rule handles the open dropdown list.
   --------------------------------------------------------------------------- */
:root { --jp-prompt: #FF5A5A; }

.woocommerce div.product form.cart .variations select:has(option[value=""]:checked),
.woocommerce div.product form.cart .variations select:invalid {
  color: var(--jp-prompt) !important;
  border-color: var(--jp-prompt) !important;
}

.woocommerce div.product form.cart .variations select option[value=""] {
  color: var(--jp-prompt);
}

/* Specification block on the product page. */
.jp-spec { margin-top: 1.75rem; }
.jp-spec__title {
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--jp-muted);
  margin: 0 0 0.6rem;
}
.jp-spec__source {
  margin-top: 0.6rem;
  font-size: 0.75rem;
  color: var(--jp-muted);
}
.jp-spec-flag {
  margin-left: 0.4rem;
  padding: 0.05rem 0.35rem;
  border: 1px solid var(--jp-warn);
  border-radius: var(--jp-r-sm);
  color: var(--jp-warn);
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* ---------------------------------------------------------------------------
   Spec table legibility and control sizing.

   The table is the part of the page a technical buyer actually reads, so it was
   set too small and too dim. Values move up to ink-2 and labels stay muted, so
   the hierarchy survives while both become comfortably readable.

   The variation select was sized to its padding rather than its content, which
   clipped "10 g" — a select must be wide enough for its longest option plus the
   dropdown arrow.
   --------------------------------------------------------------------------- */
.jp-spec-table {
  font-size: 0.9375rem;
  line-height: 1.5;
}

.jp-spec-table th {
  color: var(--jp-ink-2);
  font-size: 0.9375rem;
  padding: 0.65rem 0.75rem 0.65rem 0;
}

.jp-spec-table td {
  color: var(--jp-ink);
  padding: 0.65rem 0;
}

/* "Data available on request" is real information, but secondary to a value. */
.jp-spec-table td:empty::after {
  color: var(--jp-muted);
  font-size: 0.875rem;
}

.jp-spec__title {
  font-size: 0.875rem;
  color: var(--jp-ink-2);
}

/* Room for the longest option plus the arrow, on every select in the shop. */
.woocommerce div.product form.cart .variations select,
.woocommerce select,
select {
  min-width: 11rem;
  padding-right: 2.25rem;
  line-height: 1.6;
  height: auto;
}

/* The mini-cart's clickable element is a nested <button>, so sizing the block
   wrapper left the button itself at its intrinsic size. Pin every header
   control to one box so they line up exactly. */
.ext-nav-extras .wp-block-navigation-item__content,
.ext-nav-extras .wc-block-customer-account__link,
.ext-nav-extras .wc-block-mini-cart__button,
.wp-block-woocommerce-mini-cart .wc-block-mini-cart__button {
  min-height: 2.5rem !important;
  height: 2.5rem !important;
  box-sizing: border-box !important;
}

.ext-nav-extras .wc-block-customer-account__link,
.wp-block-woocommerce-mini-cart .wc-block-mini-cart__button {
  min-width: 2.5rem !important;
  width: 2.5rem !important;
  padding: 0 !important;
}

.wp-block-woocommerce-mini-cart,
.wc-block-mini-cart {
  display: flex;
  align-items: center;
}

/* ---------------------------------------------------------------------------
   Scrolled header.

   At rest the masthead is a full-width glass panel, which is right at the top
   of the page. Once scrolling starts it was covering 221px of content across
   the whole viewport. On scroll the panel is dissolved and only its two ends
   remain — brand pinned left, controls pinned right — each carrying its own
   small backdrop so it stays readable over whatever passes beneath. The middle
   becomes a window rather than a wall.
   --------------------------------------------------------------------------- */
.wp-block-template-part.is-scrolled .ext-header-sticky,
.wp-block-template-part.is-scrolled .ext-header-glass,
.wp-block-template-part.is-scrolled .ext-header-overlay {
  background: transparent !important;
  backdrop-filter: none !important;
  box-shadow: none !important;
  border: 0 !important;
  /* Padding intentionally untouched: reducing it here made the bar visibly
     shrink the instant scrolling began, and any height change under a scroll
     trigger risks re-entering the oscillation loop. */
}

/* The logo deliberately keeps its size while scrolled. Shrinking it changed the
   header's height, which moved the scroll threshold that adds .is-scrolled — so
   the class toggled on and off repeatedly and the logo visibly oscillated. A
   scroll-triggered style must never change layout height. */

/* No local backdrops: a panel drawn tightly around the logo read as the header
   shrinking the moment scrolling began. The buttons already carry their own
   solid fill, and the logo fades before it can collide with anything. */

/* Reserve the header's height up front so the sticky box never resizes. */
.wp-block-template-part.is-scrolled .ext-header-sticky,
.wp-block-template-part.is-scrolled .ext-header-glass {
  min-height: 0;
}

/* ---------------------------------------------------------------------------
   Hide-on-scroll masthead.

   Only a transform is animated — never height — because a height change would
   move the scroll position that drives the script and start it oscillating.
   The element keeps its box, so nothing below it shifts as it comes and goes.
   --------------------------------------------------------------------------- */
/* No will-change here. It creates a containing block for fixed-position
   descendants, which trapped the mobile menu overlay inside the header's box
   and made the open menu invisible. The fade script that once needed the hint
   is no longer loaded. */


/* ---------------------------------------------------------------------------
   Header in normal flow.

   Extendable ships a sticky, overlaid, "glass" masthead. On a catalogue page
   that means a 220px panel permanently covering the top of whatever is being
   read. Returned to normal flow: it occupies its own space, content begins
   below it, and it scrolls out of view naturally.
   --------------------------------------------------------------------------- */
header.wp-block-template-part,
header.wp-block-template-part.is-scrolled,
.ext-header-sticky,
.ext-header-overlay,
.ext-header-sticky--floating-pill {
  position: static !important;
  top: auto !important;
  opacity: 1 !important;
  transform: none !important;
  backdrop-filter: none !important;
}

/* The overlay variant pulls the first section up underneath the header. */
.ext-header-overlay + *,
.wp-site-blocks > header + * {
  margin-top: 0 !important;
}

.wp-block-site-logo { transform: none !important; }

/* ---------------------------------------------------------------------------
   Phones.

   The masthead is one non-wrapping row: a 72vw logo beside ~267px of controls.
   That totals more than a phone is wide, so the cart and account buttons were
   pushed off the right edge with no way to scroll to them.

   Fixed by letting the row wrap and giving the logo a share that leaves room —
   brand first, controls beneath it, both fully on screen.
   --------------------------------------------------------------------------- */
@media (max-width: 782px) {
  header.wp-block-template-part .wp-block-group.alignwide,
  header.wp-block-template-part .wp-block-group.is-nowrap {
    flex-wrap: wrap !important;
    row-gap: 0.6rem;
    justify-content: center !important;
  }

  .wp-block-site-logo img,
  .wp-block-site-logo.is-default-size img {
    width: min(320px, 64vw) !important;
  }

  .ext-nav-extras {
    margin-left: 0;
    width: 100%;
    justify-content: center !important;
    flex-wrap: wrap;
    gap: 0.5rem;
  }

  /* Slightly tighter buttons so four controls fit one line on a small phone. */
  .ext-nav-extras .wp-block-navigation-item__content {
    padding: 0.45rem 0.8rem;
    font-size: 0.8125rem;
  }

  .wp-block-navigation__container { gap: 0.5rem; }
}

/* Nothing should ever scroll the page sideways. */
html, body { overflow-x: hidden; }

/* Wide content keeps its own scroller rather than pushing the page out. */
.woocommerce table.shop_attributes,
.jp-spec-table,
.woocommerce-Tabs-panel table {
  display: block;
  max-width: 100%;
  overflow-x: auto;
}


/* ---------------------------------------------------------------------------
   Mobile menu overlay.

   Plain light links on the ground colour, rather than the filled chips used in
   the desktop bar — stacked full-width buttons in a modal read as a wall of
   blue and lose the sense of a list.
   --------------------------------------------------------------------------- */
.wp-block-navigation__responsive-container.is-menu-open {
  background-color: var(--jp-ground) !important;
  color: var(--jp-ink) !important;
  padding: 2rem 1.5rem;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
  background-color: transparent !important;
  border: 0 !important;
  color: var(--jp-ink) !important;
  font-size: 1.25rem;
  padding: 0.7rem 0;
  min-height: 0 !important;
  height: auto !important;
  justify-content: flex-start;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content:hover {
  color: var(--jp-accent) !important;
  background-color: transparent !important;
}

.wp-block-navigation__responsive-container-open,
.wp-block-navigation__responsive-container-close {
  color: var(--jp-ink) !important;
}

/* ---------------------------------------------------------------------------
   Menu toggle.

   The hamburger rendered as a bare 24px icon with no background, sitting beside
   filled blue controls on a dark photographic backdrop — present in the DOM,
   invisible in practice. It now matches the account and cart buttons, so the
   row reads as one set of controls.
   --------------------------------------------------------------------------- */
.wp-block-navigation__responsive-container-open {
  /* No display override: WordPress hides this toggle above the responsive
     breakpoint, and forcing inline-flex put a stray hamburger on desktop. */
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0 !important;
  border: 1px solid var(--jp-accent);
  border-radius: var(--jp-r);
  background-color: var(--jp-accent) !important;
  color: var(--jp-accent-ink) !important;
}

.wp-block-navigation__responsive-container-open svg {
  width: 1.35rem;
  height: 1.35rem;
  fill: currentColor !important;
}

.wp-block-navigation__responsive-container-open:hover {
  background-color: var(--jp-blueprint) !important;
  border-color: var(--jp-blueprint) !important;
}

/* Closing control inside the overlay, same shape so it is obviously its pair. */
.wp-block-navigation__responsive-container-close {
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border: 1px solid var(--jp-line);
  border-radius: var(--jp-r);
  color: var(--jp-ink) !important;
}

.wp-block-navigation__responsive-container-close svg {
  width: 1.35rem;
  height: 1.35rem;
  fill: currentColor !important;
}

/* ---------------------------------------------------------------------------
   Mobile menu as a dropdown.

   WordPress's navigation block opens its responsive menu as a full-viewport
   modal, which on a two-item menu feels like being taken to another page. Here
   it is re-anchored under the toggle as a panel: the page stays visible behind
   it, and closing it returns you to exactly where you were.
   --------------------------------------------------------------------------- */
@media (max-width: 782px) {
  /* Anchor the panel to the navigation block, not the header. The header is a
     full-bleed element whose box extends past the viewport at this width, so
     positioning against it put the dropdown off the left edge. */
  .wp-block-navigation { position: relative !important; }

  .wp-block-navigation__responsive-container.is-menu-open {
    position: absolute !important;
    /* Opens straight down from the toggle: left-aligned to it, not hanging
       leftwards from a right edge. */
    top: calc(100% + 0.35rem) !important;
    left: 0 !important;
    right: auto !important;
    bottom: auto !important;
    /* Explicit width: max-content resolved to 338px here, because inner
       elements inherit a full-width box, which pushed the panel off the left
       edge once it was right-anchored. */
    width: 12rem !important;
    min-width: 0 !important;
    max-width: 60vw !important;
    height: auto !important;
    min-height: 0 !important;
    max-height: 70vh;
    overflow-y: auto;
    padding: 0.5rem 0.75rem !important;
    /* The modal layout leaves the panel 372px tall for two links; block layout
       lets it shrink to its content. */
    display: block !important;
    align-items: initial !important;
    justify-content: initial !important;
    background-color: var(--jp-ground) !important;
    border: 1px solid var(--jp-line);
    border-radius: var(--jp-r-lg);
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
    z-index: 60;
  }

  .wp-block-navigation__responsive-container.is-menu-open
  .wp-block-navigation__responsive-container-content {
    display: block !important;
    width: auto !important;
    min-width: 0 !important;
    height: auto !important;
    min-height: 0 !important;
  }

  .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
    display: block !important;
    gap: 0;
  }

  .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item {
    display: block;
    width: 100%;
  }

  .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
    font-size: 1rem;
    padding: 0.55rem 0.25rem;
    white-space: nowrap;
  }

  /* A dropdown closes by tapping the toggle again, so the modal's big close
     control would just take up room. */
  .wp-block-navigation__responsive-container-close { display: none !important; }
}

/* ---------------------------------------------------------------------------
   Dropdown spacing.

   WordPress reserves room at the top of the responsive dialog for its close
   button (margin-top 46px on the dialog, padding-top 32px on the content). The
   dropdown has no close button — it toggles — so that reservation left the two
   links stranded ~78px below the top of an otherwise empty panel.
   --------------------------------------------------------------------------- */
@media (max-width: 782px) {
  .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-dialog {
    margin-top: 0 !important;
    padding: 0 !important;
    height: auto !important;
    min-height: 0 !important;
  }

  .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
    padding: 0 !important;
    align-items: stretch !important;
  }

  .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
    padding: 0 !important;
    margin: 0 !important;
  }

  .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item {
    padding: 0 !important;
  }
}

/* Extendable clones the site logo and title into the responsive menu, which
   makes sense for a full-screen modal but wasted 147px at the top of a dropdown
   that already opens directly beneath the real logo. */
@media (max-width: 782px) {
  .wp-block-navigation__responsive-container.is-menu-open .site-logo-title,
  .wp-block-navigation__responsive-container.is-menu-open .mobile-logo,
  .wp-block-navigation__responsive-container.is-menu-open [class*="cloned-for"] {
    display: none !important;
  }
}

/* ---------------------------------------------------------------------------
   Package pricing ladder.
   --------------------------------------------------------------------------- */
.jp-ladder { margin-top: 1.5rem; }

.jp-ladder__title {
  font-size: 0.875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--jp-ink-2);
  margin: 0 0 0.6rem;
}

.jp-ladder-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--jp-font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.9375rem;
}

.jp-ladder-table th,
.jp-ladder-table td {
  border-bottom: 1px solid var(--jp-line-soft);
  padding: 0.55rem 0.5rem 0.55rem 0;
  text-align: left;
}

.jp-ladder-table thead th {
  color: var(--jp-muted);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border-bottom-color: var(--jp-line);
}

.jp-ladder-table tbody th { color: var(--jp-ink); font-weight: 600; }
.jp-ladder-table tbody td { color: var(--jp-ink-2); }

/* The falling unit price is the argument for buying more, so it gets the accent. */
.jp-ladder__unit { color: var(--jp-accent) !important; }
.jp-ladder__per { color: var(--jp-muted); margin-left: 0.15rem; font-size: 0.8125rem; }

.jp-ladder__note {
  margin-top: 0.5rem;
  font-size: 0.8125rem;
  color: var(--jp-muted);
}
