/* ============================================================
   Visitech — Site chrome (2026 prototype)
   Floating pill header · megamenu · AI search · footer.
   Stands on tokens.css + styles.css only — NO legacy theme CSS.
   Ported 1:1 from the approved front-page draft (June 2026);
   values mapped to tokens. Conscious changes are marked DELTA.
   ============================================================ */

/* ------------------------------------------------------------
   0 · Layout wraps (replaces the old theme's .wrap / .big-wrap)
   ------------------------------------------------------------ */
.wrap {
  width: 100%;
  max-width: 1210px;              /* old theme's content width — kept */
  margin-inline: auto;
  padding-inline: 32px;
}
.wrap--wide { max-width: 1640px; }  /* old theme's big-wrap (header/footer) */
@media (max-width: 600px) { .wrap { padding-inline: 20px; } }   /* tighter gutters on phones — 32px wasted too much width (mobile pass 2026-06-22) */

/* ------------------------------------------------------------
   1 · Typography helpers (see TYPOGRAPHY.md)
   ------------------------------------------------------------ */
p, li, blockquote, figcaption,
h1, h2, h3, h4, h5, h6 { text-wrap: pretty; }

.tm {
  font-size: 0.5em;
  vertical-align: super;
  line-height: 0;
  font-weight: inherit;
}

/* ============================================================
   2 · FLOATING HEADER — logo · centered nav pill · utils
   ============================================================ */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 1002;
  padding: 24px 0;

  /* The desktop row's fluid knobs, at the values the header has always had.
     The ramp in 2a overrides them once the pill appears; every consumer below
     reads the variable, so the ramp is stated in exactly one place.
     Declared HERE and not on __inner because .mobile-nav is a SIBLING of
     __inner (the Safari backdrop-filter neutraliser needs the drawer inside
     the header), and the drawer's own login pill reads --hdr-login-pad. */
  --hdr-logo-h:    26px;
  --hdr-util-gap:  18px;
  --hdr-login-pad: 18px;
  --nav-fs:        15px;
  --nav-pad:       20px;
  --nav-gap:        4px;
  --nav-pill-pad:  12px;
  transition: padding var(--dur-base) var(--ease-standard),
              background var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard);
}
.site-header__inner {
  position: relative;             /* anchor for the mega panel */
  display: flex;
  align-items: center;
  gap: 16px;
}

/* DELTA (new state): scrolled — translucent dark strip so the white
   logo/utils stay readable over light content below the hero */
.site-header.is-scrolled {
  padding: 10px 0;
  background: rgba(13, 10, 24, 0.78);
  -webkit-backdrop-filter: saturate(160%) blur(18px);
  backdrop-filter: saturate(160%) blur(18px);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.08);
}

/* --- Left zone: logo, outside the pill (equal-flex side zone) --- */
.site-header__logo {
  flex: 1 1 0;
  min-width: 0;
  display: block;
  line-height: 0;
}
.site-header__logo img {
  height: var(--hdr-logo-h);
  width: auto;
  filter: brightness(0) invert(1);   /* white wordmark on dark */
}

/* --- Right zone: search + language + login (equal-flex side zone) --- */
.site-header__utils {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--hdr-util-gap);
}
/* The side zones are `flex: 1 1 0` so the pill sits centred between them,
   which means this box can be narrower than what is in it. Its children must
   not answer that by shrinking: a squeezed search circle or a "Customer
   login" broken over two lines is the ugly failure. They keep their size and
   spend the row's gap instead — the ramp in 2a is what guarantees there is
   gap to spend. */
.site-header__utils > * { flex: 0 0 auto; }

/* ------------------------------------------------------------
   2a · Nav pill (desktop)
   ------------------------------------------------------------ */
@media (min-width: 1240px) {

  /* --- The fluid fit (2026-09-09) --------------------------------------
     Six top-level items, one of them "Optical Variable Devices", do not fit
     the pill at the 15px/20px sizing the five-item nav wore: that row wants a
     1442px viewport and the pill appears at 1240px. So the whole desktop
     row — nav type, nav padding, item gap, pill padding, logo height, utils
     gap, login padding — is one RAMP from a tight-but-comfortable state at
     1240px to exactly today's values at 1520px. Above 1520px nothing has
     changed; below 1240px the pill is gone and none of this applies.

     Each clamp is `clamp(tight, slope·vw + intercept, today)`, with the slope
     solved so the middle term lands on `tight` at 1240px and on `today` at
     1520px. The numbers are MEASURED, not eyeballed: the six labels were set
     in Noto Sans Display at every step of the ramp against the real logo,
     search circle, language switch and login pill, and the row keeps ≥49px of
     slack at every width from 1240px up. That slack is the point — it absorbs
     both a classic scrollbar's ~15px of `vw` overestimate (`vw` counts it,
     the layout does not) and a label an editor lengthens later.

     Why a ramp and not a bigger breakpoint: handing 1280px and 1366px laptops
     to the hamburger to buy room for one nav item is a worse trade than 13px
     type on the two hundred pixels where it is actually needed. */
  .site-header {
    --hdr-logo-h:    clamp(22px, 1.429vw +  4.29px, 26px);
    --hdr-util-gap:  clamp(12px, 2.143vw - 14.57px, 18px);
    --hdr-login-pad: clamp(14px, 1.429vw -  3.71px, 18px);
    --nav-fs:        clamp(13px, 0.714vw +  4.14px, 15px);
    --nav-pad:       clamp(11px, 3.214vw - 28.86px, 20px);
    --nav-gap:       clamp( 2px, 0.714vw -  6.86px,  4px);
    --nav-pill-pad:  clamp( 8px, 1.429vw -  9.71px, 12px);
  }

  .pillnav {
    flex: 0 0 auto;                /* size to content, centred between equal side zones */
    display: inline-flex;
    background: rgba(22, 16, 30, 0.42);
    -webkit-backdrop-filter: saturate(160%) blur(16px);
    backdrop-filter: saturate(160%) blur(16px);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: var(--radius-pill);
    padding: 6px var(--nav-pill-pad);
  }
  .pillnav > ul {
    display: flex;
    flex-wrap: nowrap;             /* one row of items */
    align-items: center;
    gap: var(--nav-gap);
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .pillnav > ul > li { flex: 0 0 auto; }  /* never shrink → labels never wrap. NOT position:relative — so the mega panel anchors to .site-header__inner and opens in ONE consistent, container-aligned spot for all four items (not re-centered per item). */
  .pillnav > ul > li > a {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
    color: rgba(255, 255, 255, 0.82);
    padding: 10px var(--nav-pad);  /* airy at width, tighter as the row fills */
    font-size: var(--nav-fs);
    font-weight: var(--fw-regular);
    letter-spacing: 0.02em;
    border-radius: var(--radius-pill);
    text-decoration: none;
    transition: color var(--dur-base) var(--ease-standard),
                background var(--dur-base) var(--ease-standard);
  }
  .pillnav > ul > li > a:hover,
  .pillnav > ul > li:hover > a {
    color: #fff;
    background: rgba(255, 255, 255, 0.10);
    text-decoration: none;
  }

  /* chevron on items that open a panel */
  .pillnav .has-children > a::after,
  .pillnav .has-mega > a::after {
    content: "";
    width: 9px;
    height: 9px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: translateY(-2px) rotate(45deg);
    opacity: 0.5;
    transition: transform 0.22s var(--ease-standard), opacity 0.22s var(--ease-standard);
  }
  .pillnav .has-children:hover > a::after,
  .pillnav .has-mega:hover > a::after {
    transform: translateY(1px) rotate(-135deg);
    opacity: 1;
  }

  /* --- Simple dropdowns (DELTA: restyled as dark glass panels —
         the old theme's white sub-menu boxes are gone) --- */
  .pillnav .subnav {
    position: absolute;
    top: calc(100% + 14px);
    left: 50%;
    transform: translateX(-50%) translateY(-6px);
    min-width: 230px;
    margin: 0;
    padding: 6px;
    list-style: none;
    background: rgba(22, 16, 30, 0.92);
    -webkit-backdrop-filter: blur(16px);
    backdrop-filter: blur(16px);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: var(--radius-lg);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s var(--ease-standard),
                transform 0.2s var(--ease-standard),
                visibility 0.2s;
  }
  .pillnav .subnav::before {       /* hover bridge across the gap */
    content: "";
    position: absolute;
    top: -14px; left: 0; right: 0;
    height: 14px;
  }
  .pillnav li:hover > .subnav,
  .pillnav li:focus-within > .subnav {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
  }
  .pillnav .subnav a {
    display: block;
    padding: 9px 12px;
    color: rgba(255, 255, 255, 0.85);
    font-size: 14px;
    text-decoration: none;
    border-radius: 6px;
    white-space: nowrap;
  }
  .pillnav .subnav a:hover { background: rgba(255, 255, 255, 0.10); color: #fff; text-decoration: none; }
}

/* ============================================================
   3 · MEGA PANEL (Lithography) — centered, gap below header
   ============================================================ */
@media (min-width: 1240px) {

  .vmega {
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    width: min(1210px, calc(100vw - 48px));
    /* Close the dead zone between the pill item and the panel: the pill's 6px
       bottom padding sat between the <a> and the panel, dropping :hover. Pull the
       panel up 6px so its (transparent) top padding starts right at the item edge,
       then keep content where it was via a taller padding-top. (2026-06-12) */
    margin-top: -6px;
    padding-top: 20px;             /* GAP bridge below the header — now reaches the item with no gap */
    z-index: 1001;
    opacity: 0;
    visibility: hidden;            /* visibility (transitioned) gates interactivity — NOT pointer-events,
                                      which switched instantly and made the fading panel unreachable */
    transition: opacity 0.28s var(--ease-standard), visibility 0.28s;
    line-height: 1.4;
  }
  .has-mega:hover .vmega,
  .has-mega:focus-within .vmega {
    opacity: 1;
    visibility: visible;
  }
  .has-mega.is-dismissed .vmega { opacity: 0; visibility: hidden; }   /* clicked a link → close even while hovered/focused (reset on mouseleave) */
  .vmega a:hover { text-decoration: none; }

  .vmega__inner {
    /* LIGHT SOLID panel, dark/imagery featured card for contrast. Natural height —
       each panel sizes to its own content (forced equal-height removed 2026-06-12). */
    display: flex;
    flex-direction: column;
    background: #fdfbff;
    /* No border: it sat OUTSIDE the near-white panel background, so against the
       purple overview bar it read as a white frame around the whole menu. The
       shadow is what separates the panel from the page anyway. (2026-09-04) */
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xl);
    overflow: hidden;
    transform: translateY(-8px);
    transition: transform 0.28s var(--ease-standard);
  }
  .has-mega:hover .vmega__inner,
  .has-mega:focus-within .vmega__inner { transform: translateY(0); }

  .vmega__grid {
    display: grid;
    grid-template-columns: 4fr 8fr;   /* asymmetric — slim featured, roomy lineup */
    gap: 44px;                        /* air between the columns */
    padding: 40px;                    /* more outer margin */
  }

  /* ---- Featured card ---- */
  .vmega__featured {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    min-height: 260px;
    padding: 22px;
    border-radius: var(--radius-lg);
    background: var(--gradient-cinematic);
    border: 1px solid rgba(255, 255, 255, 0.10);
    color: #fff;
    text-decoration: none;
    overflow: hidden;
    transition: box-shadow 0.25s var(--ease-standard);
  }
  .vmega__featured::before {
    content: "";
    position: absolute;
    top: -30%; right: -20%;
    width: 80%; height: 120%;
    background: var(--gradient-glow-purple);
    pointer-events: none;
  }
  .vmega__featured:hover { box-shadow: 0 12px 32px rgba(46, 32, 59, 0.22); color: #fff; }   /* hold text white — base a:hover was flipping the (colour-inheriting) claim to dark blue */

  /* featured carries a REAL image (microscopy / team / facility) instead of the floating render */
  .vmega__featured-img {
    position: absolute; inset: 0; z-index: 0;
    width: 100%; height: 100%; object-fit: cover;
    transition: transform 0.5s var(--ease-standard);
  }
  .vmega__featured-scrim {
    position: absolute; inset: 0; z-index: 0;
    background: linear-gradient(155deg, rgba(20, 12, 32, 0.5) 0%, rgba(20, 12, 32, 0.34) 45%, rgba(20, 12, 32, 0.9) 100%);
  }
  .vmega__featured:hover .vmega__featured-img { transform: scale(1.05); }   /* slow zoom — the hover micro-interaction */

  /* staggered entrance — panel content settles in on open */
  @keyframes vmegaIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
  .has-mega:hover .vmega__featured,
  .has-mega:focus-within .vmega__featured { animation: vmegaIn 0.42s var(--ease-standard) both; }
  .has-mega:hover .vmega__lineup .vmega__row:nth-child(1),
  .has-mega:focus-within .vmega__lineup .vmega__row:nth-child(1) { animation: vmegaIn 0.42s var(--ease-standard) 0.06s both; }
  .has-mega:hover .vmega__lineup .vmega__row:nth-child(2),
  .has-mega:focus-within .vmega__lineup .vmega__row:nth-child(2) { animation: vmegaIn 0.42s var(--ease-standard) 0.12s both; }
  .has-mega:hover .vmega__footer,
  .has-mega:focus-within .vmega__footer { animation: vmegaIn 0.42s var(--ease-standard) 0.18s both; }
  /* same staggered entrance for the calm-columns (C2) content */
  .has-mega:hover .vmega__overview,
  .has-mega:focus-within .vmega__overview { animation: vmegaIn 0.42s var(--ease-standard) both; }
  .has-mega:hover .cmenu__feature,
  .has-mega:focus-within .cmenu__feature { animation: vmegaIn 0.42s var(--ease-standard) both; }
  .has-mega:hover .cmenu__col:nth-child(1),
  .has-mega:focus-within .cmenu__col:nth-child(1) { animation: vmegaIn 0.42s var(--ease-standard) 0.06s both; }
  .has-mega:hover .cmenu__col:nth-child(2),
  .has-mega:focus-within .cmenu__col:nth-child(2) { animation: vmegaIn 0.42s var(--ease-standard) 0.12s both; }
  .has-mega:hover .cmenu__col:nth-child(3),
  .has-mega:focus-within .cmenu__col:nth-child(3) { animation: vmegaIn 0.42s var(--ease-standard) 0.18s both; }
  @media (prefers-reduced-motion: reduce) {
    .has-mega:hover .vmega__featured, .has-mega:focus-within .vmega__featured,
    .has-mega:hover .vmega__lineup .vmega__row, .has-mega:focus-within .vmega__lineup .vmega__row,
    .has-mega:hover .vmega__footer, .has-mega:focus-within .vmega__footer,
    .has-mega:hover .vmega__overview, .has-mega:focus-within .vmega__overview,
    .has-mega:hover .cmenu__feature, .has-mega:focus-within .cmenu__feature,
    .has-mega:hover .cmenu__col, .has-mega:focus-within .cmenu__col { animation: none; }
    .vmega__featured-img, .vmega__featured:hover .vmega__featured-img { transition: none; transform: none; }
  }

  .vmega__pill {
    align-self: flex-start;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: max(10px, var(--fs-floor, 0px));
    letter-spacing: 0.18em;
    text-transform: uppercase;
    font-weight: var(--fw-bold);
    padding: 6px 12px;
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: var(--radius-pill);
    position: relative; z-index: 1;
  }
  .vmega__dot {
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--color-light-purple);
    box-shadow: 0 0 0 3px rgba(160, 104, 177, 0.3);
  }
  .vmega__featured-name {
    font-family: var(--font-display);
    font-weight: 200;
    font-size: 24px;
    margin: 0;
    color: rgba(255, 255, 255, 0.9);
    position: relative; z-index: 1;
  }
  .vmega__featured-claim {
    font-family: var(--font-display);
    font-weight: 200;
    font-size: clamp(28px, 3.4vw, 40px);   /* a touch smaller + more line air — was 45px/0.92 (Petter, 2026-06-12) */
    line-height: 1.02;
    margin: 6px 0 10px;
    letter-spacing: -0.04em;
    position: relative; z-index: 1;
  }
  .vmega__featured-claim strong { font-weight: var(--fw-medium); }
  .vmega__featured-sub {
    color: rgba(255, 255, 255, 0.7);
    font-size: 13px;
    font-weight: var(--fw-light);
    max-width: 30ch;
    margin: 0 0 16px;
    position: relative; z-index: 1;
  }
  .vmega__featured-cta {
    font-size: 12px;
    font-weight: var(--fw-bold);
    letter-spacing: 0.05em;
    color: #fff;
    position: relative; z-index: 1;
  }
  .vmega__featured:hover .vmega__featured-cta { color: var(--color-light-purple-60); }
  .vmega__render {
    position: absolute;
    bottom: 14px; right: 6%;
    height: auto;
    max-height: 168px;             /* fixed, consistent — no longer scales with panel height */
    width: auto;
    pointer-events: none;
    filter: brightness(1.15)
            drop-shadow(0 0 36px rgba(255, 255, 255, 0.22))
            drop-shadow(0 14px 32px rgba(0, 0, 0, 0.65));
  }

  /* ---- Lineup ---- */
  .vmega__lineup { display: grid; gap: 26px; align-content: start; }
  .vmega__row { display: grid; gap: 8px; }
  .vmega__label {
    font-size: max(10px, var(--fs-floor, 0px));
    text-transform: uppercase;
    letter-spacing: 0.16em;
    font-weight: var(--fw-bold);
    color: var(--color-text-subtle);
    margin: 0 0 4px;
    padding-bottom: 8px;
    border-bottom: 1px solid rgba(46, 32, 59, 0.06);
  }
  .vmega__chips {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
  }

  /* ---- Product chip ---- */
  .vmega-chip {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 12px;
    min-height: 88px;
    border: 1px solid rgba(46, 32, 59, 0.08);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
    text-decoration: none;
    overflow: hidden;
    transition: transform 0.18s var(--ease-standard),
                box-shadow 0.18s var(--ease-standard),
                border-color 0.18s var(--ease-standard);
  }
  .vmega-chip:hover {
    transform: translateY(-2px);
    border-color: rgba(160, 104, 177, 0.35);
    box-shadow: 0 10px 24px rgba(46, 32, 59, 0.08);
  }
  .vmega-chip__tier {
    position: absolute; top: 0; left: 0; right: 0;
    height: 3px;
  }
  .vmega-chip--entry    .vmega-chip__tier { background: var(--gradient-tier-entry); }
  .vmega-chip--standard .vmega-chip__tier { background: var(--gradient-tier-standard); }
  .vmega-chip--premium  .vmega-chip__tier { background: var(--gradient-tier-premium); }
  .vmega-chip--flagship .vmega-chip__tier { background: var(--gradient-tier-flagship); }
  .vmega-chip--flagship {
    background: linear-gradient(180deg, #faf3ff 0%, #ffffff 60%);
    border-color: rgba(160, 104, 177, 0.3);
  }
  .vmega-chip__top {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 6px;
    margin-top: 4px;
  }
  .vmega-chip__name {
    font-family: var(--font-display);
    font-weight: var(--fw-medium);
    font-size: 14px;
    color: var(--color-dark-purple);
    margin: 0;
  }
  .vmega-chip__badge {
    font-size: max(9px, var(--fs-floor, 0px));
    font-weight: var(--fw-bold);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    padding: 2px 7px;
    border-radius: var(--radius-pill);
    background: var(--color-light-purple);
    color: #fff;
    white-space: nowrap;
  }
  .vmega-chip__res {
    font-family: var(--font-display);
    font-weight: 200;
    font-size: 26px;
    line-height: 1;
    color: var(--color-light-purple);
    letter-spacing: -0.025em;
    margin-top: 2px;
  }
  .vmega-chip--premium .vmega-chip__res { color: var(--color-dark-purple); }
  .vmega-chip--flagship .vmega-chip__res {
    background: var(--gradient-brand);
    -webkit-background-clip: text; background-clip: text; color: transparent;
  }
  /* Forced colours drop the background the transparent text shows through (launch list B3) */
  @media (forced-colors: active) { .vmega-chip--flagship .vmega-chip__res { background: none; color: CanvasText; } }
  .vmega-chip__unit { font-size: 13px; font-weight: var(--fw-medium); margin-left: 1px; }
  .vmega-chip__meta {
    font-size: max(11px, var(--fs-floor, 0px));
    color: var(--color-text-subtle);
    letter-spacing: 0.02em;
    margin-top: auto;
  }

  /* ---- Footer row ---- */
  .vmega__footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 16px 28px;
    background: #faf8fc;
    border-top: 1px solid rgba(46, 32, 59, 0.06);
    font-size: 13px;
  }
  .vmega__footer-links { display: flex; flex-wrap: wrap; gap: 24px; }
  .vmega__footer-links a { color: var(--color-text-muted); text-decoration: none; }
  /* Royal Plum, not Mystic Lavender: #a068b1 on the #faf8fc strip is 3.89:1
     and this is 13px body text (WCAG 1.4.3 wants 4.5:1). Plum is 7.0:1 and
     still reads as "darkens under the pointer". (a11y pass 2026-09-18) */
  .vmega__footer-links a:hover { color: var(--color-dark-purple); }
  .vmega__cta {
    /* auto margin, not space-between, so the CTA still sits right when a panel
       has no footer links (all four panels' links now live in the columns). */
    margin-left: auto;
    font-size: 13px;
    font-weight: var(--fw-regular);
    letter-spacing: 0.02em;
    padding: 9px 20px;
    /* Royal Plum -> Deep Purple, not Mystic Lavender -> Royal Plum: white on
       #a068b1 is 4.11:1, under the 4.5:1 this 13px label needs. Both ends of
       the new pair are dark enough to keep the label crisp (7.4:1 / 11.7:1) —
       the same reason the footer's Subscribe button runs --gradient-button-deep
       (Petter 2026-06-17). (a11y pass 2026-09-18) */
    background: var(--color-dark-purple);
    color: #fff;
    border-radius: var(--radius-pill);
    text-decoration: none;
    white-space: nowrap;
    transition: background var(--dur-base) var(--ease-standard);
  }
  .vmega__cta:hover { background: var(--color-dark-blue); color: #fff; }

  /* arrow nudge on panel CTAs — precise, not showy */
  .vmega__cta .arrow,
  .vmega__featured-cta .arrow {
    display: inline-block;
    transition: transform var(--dur-base) var(--ease-standard);
  }
  .vmega__cta:hover .arrow,
  .vmega__featured:hover .vmega__featured-cta .arrow { transform: translateX(3px); }

  /* ---- Link list (News/Company panels) ---- */
  .vmega-list { display: grid; gap: 4px; align-content: start; }
  .vmega-list__item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px 12px;
    border-radius: 6px;
    text-decoration: none;
  }
  .vmega-list__item:hover { background: var(--color-bg-subtle); text-decoration: none; }
  .vmega-list__meta {
    font-size: max(10px, var(--fs-floor, 0px));
    text-transform: uppercase;
    letter-spacing: 0.12em;
    font-weight: var(--fw-bold);
    color: var(--color-text-subtle);
  }
  .vmega-list__title { font-size: 14px; color: var(--color-text); }
  .vmega-list__item:hover .vmega-list__title { color: var(--color-dark-purple); }

  /* ============================================================
     CALM COLUMNS (C2) — the live menu content. Feature anchor +
     ruled typographic columns; no boxes, no fake image. Ported
     verbatim from the approved megamenu-lab case C2.
     ============================================================ */
  /* ---- Overview bar (Lithography / Additive Manufacturing) ----
     The pill that opens the panel IS a link, but the panel dropping on hover
     made it read as a section label, so those two landing pages went unclicked.
     Solid Royal Plum across the top of the panel, above the columns: the first
     thing the eye lands on, and unmistakably a link. (2026-09-04) */
  .vmega__overview {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    padding: 15px 48px;                       /* 48px = the .cmenu gutter, so the bar lines up with the columns */
    background: var(--color-dark-purple);
    color: #fff;
    text-decoration: none;
    transition: background var(--dur-base) var(--ease-standard);
  }
  /* Hover lightens one step inside the plum ramp, not all the way to Mystic
     Lavender: white on #a068b1 is 4.11:1 and both the 19px title and the 13px
     "Go to page" are normal text. --color-dark-purple-80 is 4.51:1 and still
     visibly lifts. (a11y pass 2026-09-18) */
  .vmega__overview:hover { background: var(--color-dark-purple-80); color: #fff; }   /* hold the text white — the base a:hover flips colour-inheriting children to dark blue */
  /* .vmega__inner is overflow:hidden and this bar is full-bleed, so the global
     outset ring would be clipped to nothing. Same two rings, drawn inside:
     white on the plum bar is 7.4:1. (a11y pass 2026-09-18) */
  .vmega__overview:focus-visible {
    box-shadow: inset 0 0 0 2px #fff, inset 0 0 0 5px var(--color-dark-blue);
  }
  .vmega__overview-text { display: flex; align-items: baseline; gap: 14px; min-width: 0; }
  .vmega__overview-eyebrow {
    font-size: max(10px, var(--fs-floor, 0px));
    font-weight: var(--fw-bold);
    letter-spacing: 0.16em;
    text-transform: uppercase;
    /* 0.78, not 0.6: 60% white on the plum bar is 3.83:1 and dropped to 2.50:1
       on the old hover colour. 78% is 5.25:1 at rest and still sits a clear
       step below the title. (a11y pass 2026-09-18) */
    color: rgba(255, 255, 255, 0.78);
  }
  /* The lifted hover ground leaves no room for a tint — the eyebrow goes solid
     (4.51:1) and the title's weight keeps the hierarchy. */
  .vmega__overview:hover .vmega__overview-eyebrow { color: #fff; }
  .vmega__overview-title {
    font-family: var(--font-display);
    font-weight: var(--fw-medium);
    font-size: 19px;
    letter-spacing: -0.01em;
    color: #fff;
  }
  .vmega__overview-go {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    font-weight: var(--fw-medium);
    color: #fff;
    white-space: nowrap;
  }
  .vmega__overview-go .arrow { display: inline-block; transition: transform var(--dur-base) var(--ease-standard); }
  .vmega__overview:hover .arrow { transform: translateX(3px); }

  .cmenu { display: grid; grid-template-columns: 1fr 2.1fr; gap: 40px; padding: 44px 48px; }
  /* teaser sits on its own soft-lilac field (full-height), which separates it from the columns */
  /* feature column = static dark curated card on ALL panels (Petter 2026-06-16, global) */
  .cmenu__feature { position: relative; overflow: hidden; display: flex; flex-direction: column; align-items: flex-start; justify-content: center; min-height: 300px; padding: 34px 32px; background: var(--gradient-feature-dark); border-radius: var(--radius-lg); color: #fff; transition: box-shadow var(--dur-base) var(--ease-standard); }
  .cmenu__kicker { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; font-weight: var(--fw-bold); letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-dark-purple); margin: 0 0 18px; }
  .cmenu__kicker .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--color-light-purple); box-shadow: 0 0 0 3px rgba(160, 104, 177, 0.3); }
  /* only "live/new" eyebrows pulse (Lithography "New · 2026", News "Press release …"); categorical labels stay calm */
  .cmenu__kicker--live .dot { animation: kickerDotPulse 2.4s var(--ease-standard) infinite; }
  @keyframes kickerDotPulse {
    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(160, 104, 177, 0.5); }
    70%  { transform: scale(1.25); box-shadow: 0 0 0 8px rgba(160, 104, 177, 0); }
    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(160, 104, 177, 0); }
  }
  @media (prefers-reduced-motion: reduce) { .cmenu__kicker--live .dot { animation: none; } }
  .cmenu__name { font-size: 13px; font-weight: var(--fw-bold); letter-spacing: 0.04em; text-transform: uppercase; color: var(--color-text-muted); margin: 0 0 6px; }
  .cmenu__claim { font-family: var(--font-display); font-weight: 200; font-size: clamp(28px, 3.4vw, 40px); line-height: 1.05; letter-spacing: -0.03em; margin: 0 0 14px; color: var(--color-text); }
  .cmenu__claim strong { font-weight: var(--fw-medium); background: var(--gradient-electric); -webkit-background-clip: text; background-clip: text; color: transparent; }
  @media (forced-colors: active) { .cmenu__claim strong { background: none; color: CanvasText; } }   /* launch list B3, as .vmega-chip__res */
  .cmenu__claim--phrase { font-size: clamp(26px, 3vw, 34px); line-height: 1.06; }
  .cmenu__sub { font-size: 14px; line-height: 1.6; color: var(--color-text-muted); margin: 0 0 18px; max-width: 32ch; }
  .cmenu__more { font-size: 13px; font-weight: var(--fw-medium); color: var(--color-dark-purple); }
  .cmenu__more .arrow { display: inline-block; transition: transform var(--dur-base) var(--ease-standard); }
  .cmenu__more:hover .arrow { transform: translateX(3px); }

  .cmenu__cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0; }
  .cmenu__cols--2 { grid-template-columns: repeat(2, 1fr); }
  /* Four is a real case too, since Additive Manufacturing gained an Accessories
     column (Kurt, 2026-09-18): the LRS-MCx motion stage is a product Visitech
     sells but it is NOT a light engine or a photohead, so it does not belong in
     the light-engine list. Without this rule a fourth column wrapped onto a
     second row of the three-column grid. */
  .cmenu__cols--4 { grid-template-columns: repeat(4, 1fr); }
  /* One column is a real case, not a theoretical one: a panel column that
     auto-fills from the newsroom is DROPPED when it has nothing to show,
     and zh has no published stories yet (see panel_columns()). */
  .cmenu__cols--1 { grid-template-columns: 1fr; }
  .cmenu__col { padding: 2px 24px; }
  .cmenu__col:first-child { padding-left: 0; }
  .cmenu__col:last-child { padding-right: 0; }
  .cmenu__col:not(:first-child) { border-left: 1px solid var(--color-divider); }
  /* The BOX lives on the shared class, not on `a.`, because a column heading
     is an <a> only when it has somewhere to go — "Accessories" and
     "Software & resources" are plain <span>s (2026-09-22). Both forms must
     produce the same box or the columns' headings sit at different heights,
     which is exactly what a `span.`-only rule got wrong: inline layout gave
     the <span> its parent's --lh-normal strut (1.5 × 16px ≥ 24px) and let the
     10.5px text fall to the bottom of it, ~11px below the flex <a> beside it.
     display:flex is also what makes the 5px bottom margin apply at all —
     vertical margins do nothing on an inline box. */
  .cmenu__col-label { font-size: max(10.5px, var(--fs-floor, 0px)); font-weight: var(--fw-bold); letter-spacing: 0.05em; text-transform: uppercase; color: var(--color-dark-purple); margin: 0 0 5px; white-space: nowrap; display: flex; align-items: center; gap: 7px; }   /* all column labels are one line (nowrap) → they align naturally */
  a.cmenu__col-label { text-decoration: none; transition: color var(--dur-base) var(--ease-standard); }
  a.cmenu__col-label .arrow { font-size: max(11px, var(--fs-floor, 0px)); line-height: 1; opacity: 0; transform: translateX(-4px); transition: opacity var(--dur-base) var(--ease-standard), transform var(--dur-base) var(--ease-standard); }
  /* Deep Purple, not Mystic Lavender: #a068b1 on the #fdfbff panel is 4.00:1
     and these labels are 10.5px. Indigo is 11.4:1 and still shifts clearly off
     the resting plum. (a11y pass 2026-09-18) */
  a.cmenu__col-label:hover { color: var(--color-dark-blue); }
  a.cmenu__col-label:hover .arrow { opacity: 1; transform: translateX(0); }
  /* reserve equal description height so the three columns' links start on the same line */
  .cmenu__col-desc { font-size: 12.5px; line-height: 1.5; color: var(--color-text-muted); margin: 0 0 14px; max-width: 26ch; min-height: 4.5em; }
  .cmenu__link { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 9px 10px; margin: 0 -10px; border-radius: 8px; text-decoration: none; transition: background var(--dur-base) var(--ease-standard); }
  .cmenu__link--stack { flex-direction: column; align-items: flex-start; gap: 3px; }
  .cmenu__link:hover { background: var(--color-light-purple-10); text-decoration: none; }
  .cmenu__link-name { font-size: 14.5px; color: var(--color-text); transition: color var(--dur-base) var(--ease-standard); }
  .cmenu__link:hover .cmenu__link-name { color: var(--color-dark-purple); }
  .cmenu__link-meta { font-size: max(11px, var(--fs-floor, 0px)); text-transform: uppercase; letter-spacing: 0.1em; font-weight: var(--fw-bold); color: var(--color-text-muted); }
  /* uniform µm colour — the resolution reads from the number itself (the grey→electric spectrum failed WCAG on 4/5 stops) */
  .cmenu__link-um { font-family: var(--font-display); font-weight: var(--fw-medium); font-size: 15px; letter-spacing: -0.01em; flex: 0 0 auto; color: var(--color-dark-purple); }

  /* ----- DARK feature card details (white ink · render · under-glow) -------
     The feature column is dark on every panel now (Petter 2026-06-16, global),
     harmonising with the pill-nav + AI-search. A product render + a soft white
     under-glow appear only where a product is present (:has); the rest are clean
     dark text cards. The CTA is pinned to the foot. Ported from the cinematic
     prototype's .mpanel-featured. */
  .cmenu__feature:hover { box-shadow: var(--shadow-lg); }
  /* white ink on the dark surface, all copy above the render */
  .cmenu__feature .cmenu__kicker,
  .cmenu__feature .cmenu__name,
  .cmenu__feature .cmenu__claim,
  .cmenu__feature .cmenu__sub,
  .cmenu__feature .cmenu__more { position: relative; z-index: 1; }
  .cmenu__feature .cmenu__kicker { color: #fff; border: 1px solid rgba(255, 255, 255, 0.28); border-radius: var(--radius-pill); padding: 6px 12px; align-self: flex-start; }
  .cmenu__feature .cmenu__name { color: rgba(255, 255, 255, 0.85); }
  .cmenu__feature .cmenu__claim { color: #fff; margin: 4px 0 8px; }
  /* big heading keeps the electric periwinkle gradient from base .cmenu__claim strong */
  .cmenu__feature .cmenu__sub { color: rgba(255, 255, 255, 0.72); font-size: 13px; line-height: 1.65; max-width: 88%; }   /* smaller + wider — uses the box (Petter 2026-06-16) */
  /* Render cards: the copy has to clear the product on the right. 52% did not —
     measured at 1440px the sub ran 28px under the LLS1000 render and 62px under
     the LRS-MCx, which is wider. 42% plus the render's own max-width below puts
     ~27px of air between them on both. The two numbers are a pair: widen one and
     the other has to give. (2026-09-04) */
  .cmenu__feature:has(.cmenu__feature-render) .cmenu__sub { max-width: 42%; }
  .cmenu__feature .cmenu__more { color: #fff; margin-top: 4px; }   /* sits just under the lead; the whole block is vertically centred for air */
  .cmenu__feature .cmenu__more:hover { color: var(--color-light-purple-60); }
  .cmenu__feature .cmenu__more:hover .arrow { transform: translateX(3px); }
  /* product render + soft white under-glow — only where a product is present */
  .cmenu__feature:has(.cmenu__feature-render)::before {
    content: ""; position: absolute; inset: 0;
    background: radial-gradient(ellipse 52% 40% at 73% 76%, rgba(255, 255, 255, 0.18), transparent 70%);
    pointer-events: none;
  }
  .cmenu__feature-render {
    position: absolute; top: 50%; right: 5%;
    transform: translateY(-50%);
    height: 56%; width: auto;
    /* The render is bounded on BOTH axes, and the width bound is the load-bearing
       one. Height alone cannot keep it clear of the copy: `height: 60%` of a
       346px card gave the tall LLS1000 photohead a 178px footprint and the wide
       LRS-MCx a 211px one, so the same rule overlapped the copy by 28px in one
       panel and 62px in the other. A max-width bounds the axis the collision is
       actually on, whatever aspect ratio an editor drops in next.

       `object-fit` is required, not decoration: with `height` set and `width:
       auto`, a max-width that bites re-runs the width calculation but leaves the
       height alone — the box distorts. `contain` letterboxes the bitmap inside
       that box instead, and `right center` keeps it hugging the right edge the
       design anchors it to rather than drifting to the middle. */
    max-width: 44%;
    object-fit: contain;
    object-position: right center;
    z-index: 0;
    pointer-events: none;
    filter: brightness(1.12) drop-shadow(0 0 24px rgba(255, 255, 255, 0.16)) drop-shadow(0 10px 22px rgba(0, 0, 0, 0.5));
  }
  /* photo feature cards (News / Company) — a cover photo fills the right side and
     fades into the dark on its left edge; text stays clear on the left (Petter 2026-06-16) */
  .cmenu__feature-photo {
    position: absolute; top: 0; right: 0; bottom: 0;
    width: 52%;
    object-fit: cover;
    z-index: 0;
    pointer-events: none;
    -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 42%);
    mask-image: linear-gradient(90deg, transparent 0%, #000 42%);
  }
  .cmenu__feature:has(.cmenu__feature-photo) .cmenu__name,
  .cmenu__feature:has(.cmenu__feature-photo) .cmenu__claim,
  .cmenu__feature:has(.cmenu__feature-photo) .cmenu__sub,
  .cmenu__feature:has(.cmenu__feature-photo) .cmenu__more { max-width: 52%; }
}

/* ============================================================
   4 · AI SEARCH (magnifying glass → panel)
   ============================================================ */
.search-trigger { position: relative; display: inline-flex; }
.search-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: var(--radius-pill);
  color: rgba(255, 255, 255, 0.85);
  cursor: pointer;
  transition: all var(--dur-base) var(--ease-standard);
}
.search-btn:hover { border-color: #fff; color: #fff; background: rgba(255, 255, 255, 0.08); }
.search-btn svg { width: 17px; height: 17px; }

/* --- the AI variant: spark + the word, so the panel is not mistaken for search
   (client note 2026-09-16). Only rendered when visitech-assistant is on for the
   language; the plain magnifier above is still the fallback. --- */
.search-btn--ai {
  width: 38px; height: 38px;
  gap: 7px;
  padding: 0;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: var(--fw-medium);
  letter-spacing: 0.01em;
  color: #fff;
  border-color: rgba(255, 255, 255, 0.34);
  /* the AI accent the panel already uses, held back to a tint so the button
     stays chrome and never competes with the primary CTA */
  background: rgba(255, 255, 255, 0.06);
}
.search-btn--ai::before {
  content: "";
  position: absolute; inset: -1px;
  border-radius: inherit;
  padding: 1px;
  background: var(--gradient-electric);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  opacity: 0.85;
  pointer-events: none;
}
.search-btn--ai { position: relative; }
.search-btn--ai:hover { background: rgba(255, 255, 255, 0.12); border-color: transparent; }
.search-btn--ai:hover::before { opacity: 1; }
.search-btn--ai svg { width: 15px; height: 15px; }
.search-btn__label { white-space: nowrap; }

/* On light headers the gradient hairline carries the AI signal; the text goes ink. */
.site-header--light .search-btn--ai { color: var(--color-text); background: rgba(20, 18, 30, 0.04); }
.site-header--light .search-btn--ai:hover { color: var(--color-dark-purple); background: rgba(20, 18, 30, 0.07); }

.search-panel {
  position: absolute;
  top: calc(100% + 14px);
  right: 0;
  width: 440px;
  background: rgba(22, 16, 30, 0.92);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--radius-2xl);
  padding: 18px;
  box-shadow: 0 24px 60px -12px rgba(0, 0, 0, 0.5);
  opacity: 0; visibility: hidden; transform: translateY(-8px);
  transition: opacity 0.22s var(--ease-standard), transform 0.22s var(--ease-standard), visibility 0.22s;
  z-index: 5;
}
.search-trigger.is-open .search-panel {     /* DELTA: click/touch state via chrome.js */
  opacity: 1; visibility: visible; transform: translateY(0);
}
/* Hover and focus open the panel on the DESKTOP ROW only. Below 1240px the
   panel is pinned full-width (and a full-screen sheet under 820px), so
   brushing the button with a pointer threw a sheet over the page; on a real
   phone the tap left :hover stuck (iOS) or focus on the button (Android, and
   the ✕ hands focus back to it), so the sheet would not close. There the
   button's tap — .is-open — is the only way in. `hover: hover` keeps a
   desktop-width touchscreen from getting the same stuck hover. (2026-09-30) */
@media (min-width: 1240px) {
  .search-trigger:focus-within .search-panel { opacity: 1; visibility: visible; transform: translateY(0); }
}
@media (min-width: 1240px) and (hover: hover) {
  .search-trigger:hover .search-panel { opacity: 1; visibility: visible; transform: translateY(0); }
}
/* Escape pressed while the pointer still rests on the trigger — :hover alone
   would hold the panel open, and WCAG 2.1 SC 1.4.13 asks that hover content be
   dismissible WITHOUT moving the pointer. Same `is-dismissed` shape the mega
   panels already use; view.js clears it on mouseleave. (a11y pass 2026-09-18) */
.search-trigger.is-dismissed .search-panel { opacity: 0; visibility: hidden; }

.search-panel__field {
  display: flex; align-items: center; gap: 10px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--radius-pill);
  padding: 8px 16px;
}
.search-panel__field svg { width: 16px; height: 16px; color: rgba(255, 255, 255, 0.6); flex: 0 0 auto; }
.search-panel__field input {
  flex: 1; min-width: 0; background: transparent; border: 0; outline: 0;
  color: #fff; font-size: 14px; font-family: var(--font-body);
}
.search-panel__field input::placeholder { color: rgba(255, 255, 255, 0.5); }

.search-panel__section { margin-top: 18px; }
.search-panel__label {
  display: flex; align-items: center; gap: 7px;
  font-size: max(11px, var(--fs-floor, 0px)); letter-spacing: 0.08em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55); margin: 0 0 10px; font-weight: var(--fw-regular);
}
.ai-spark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--gradient-electric);
  color: #fff; font-size: 9px; flex: 0 0 auto;
}

/* suggested questions */
.search-q { display: flex; flex-direction: column; gap: 6px; }
.search-q__item {
  text-align: left;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: var(--radius-lg);
  padding: 10px 14px;
  color: rgba(255, 255, 255, 0.85);
  font-size: 13.5px;
  font-family: var(--font-body);
  cursor: pointer;
  transition: border-color 0.18s var(--ease-standard),
              background 0.18s var(--ease-standard),
              color 0.18s var(--ease-standard);
}
.search-q__item:hover { border-color: rgba(255, 255, 255, 0.3); background: rgba(255, 255, 255, 0.05); color: #fff; }
.search-q__item.is-active { border-color: rgba(160, 104, 177, 0.6); background: rgba(160, 104, 177, 0.12); color: #fff; }

/* example AI answer — light-purple ↔ electric-blue wash */
.search-answer {
  margin-top: 12px;
  background: linear-gradient(135deg, rgba(160, 104, 177, 0.16), rgba(110, 139, 255, 0.10));
  border: 1px solid rgba(160, 104, 177, 0.3);
  border-radius: var(--radius-lg);
  padding: 14px;
}
.search-answer__head {
  display: flex; align-items: center; gap: 7px;
  font-size: max(11px, var(--fs-floor, 0px)); letter-spacing: 0.08em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.7); margin-bottom: 8px; font-weight: var(--fw-regular);
}
.search-answer__text { margin: 0; font-size: 13.5px; line-height: 1.55; color: rgba(255, 255, 255, 0.9); }
.search-answer__text strong { color: #fff; font-weight: var(--fw-medium); }
/* "generating …" state */
.search-answer__dots { display: inline-flex; gap: 5px; align-items: center; padding: 3px 0; }
.search-answer__dots i {
  width: 6px; height: 6px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.6);
  animation: aiDot 1s infinite ease-in-out;
}
.search-answer__dots i:nth-child(2) { animation-delay: 0.15s; }
.search-answer__dots i:nth-child(3) { animation-delay: 0.3s; }
@keyframes aiDot { 0%, 100% { opacity: 0.25; transform: translateY(0); } 50% { opacity: 1; transform: translateY(-3px); } }
@media (prefers-reduced-motion: reduce) { .search-answer__dots i { animation: none; } }

/* matching internal hits */
.search-hits { display: flex; flex-direction: column; }
.search-hit {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: var(--radius-lg); text-decoration: none;
}
.search-hit:hover { background: rgba(255, 255, 255, 0.07); text-decoration: none; }
.search-hit__type {
  flex: 0 0 auto;
  font-size: max(9px, var(--fs-floor, 0px)); letter-spacing: 0.1em; text-transform: uppercase; font-weight: var(--fw-bold);
  color: var(--color-light-purple-60);
  border: 1px solid rgba(160, 104, 177, 0.4);
  border-radius: var(--radius-pill);
  padding: 3px 8px;
}
.search-hit__title { font-size: 13.5px; color: rgba(255, 255, 255, 0.82); }
.search-hit:hover .search-hit__title { color: #fff; }

/* --- Where the word fits ---------------------------------------------------
   The label is 52px wider than the 38px circle it replaces, and the desktop
   row's ramp (2a) was measured with ~49px of slack — so at 1240-1590px the
   button runs straight over the nav pill. Measured with the real row: the gap
   between pill and trigger is -44px at 1240, -20px at 1520, +20px at 1600 and
   +40px from 1680 up, where .wrap--wide stops growing. So the word appears at
   1680px and the spark carries it alone below that — still unmistakably not a
   magnifier, because of the gradient ring. Widening the word's reach means
   re-measuring the 2a ramp or dropping a top-level nav item; neither is worth
   13px nav type on the laptops where the pill is tightest. */
/* Clipped, NOT display:none. This span is the button's accessible name (the
   aria-label that used to duplicate it broke SC 2.5.3 — see render.php), and
   display:none would take the name out of the accessibility tree with it. The
   button keeps its 38px circle either way: an absolutely-positioned child is
   out of flow, so it neither widens the box nor spends the flex `gap`. */
.search-btn__label {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
}
@media (min-width: 1680px) {
  .search-btn--ai { width: auto; padding: 0 15px 0 13px; }
  .search-btn__label {
    position: static;
    width: auto; height: auto;
    margin: 0;
    overflow: visible;
    clip-path: none;
  }
}

@media (max-width: 1239.98px) {
  .search-panel {
    position: fixed;
    top: calc(72px + var(--wp-admin--admin-bar--height, 0px));   /* the header moves down under the logged-in toolbar, and so must this */
    left: 16px; right: 16px;
    width: auto;
  }
}

/* ============================================================
   5 · LANGUAGE SWITCH + CUSTOMER LOGIN
   ============================================================ */
.lang-switch { position: relative; }
.lang-switch__current {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 24px;   /* the tap target, not the 21px line of text: WCAG 2.2 SC 2.5.8 (launch list B16); phones raise it to 38px below */
  color: rgba(255, 255, 255, 0.85);
  font-size: 14px;
  font-weight: var(--fw-regular);
  text-decoration: none;
}
.lang-switch__current:hover { color: #fff; text-decoration: none; }
.lang-switch__current svg { width: 10px; height: 10px; opacity: 0.6; }
.lang-switch__menu {
  position: absolute;
  top: calc(100% + 12px);
  right: 0;
  margin: 0;
  padding: 6px;
  list-style: none;
  background: #fff;
  border: 1px solid var(--color-border);
  box-shadow: var(--shadow-lg);
  border-radius: var(--radius-lg);
  min-width: 140px;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity 0.2s var(--ease-standard), transform 0.2s var(--ease-standard), visibility 0.2s;
}
/* Same opening contract as the search panel above: the button's tap/press
   (.is-open, view.js) everywhere; hover and focus on the desktop row only. */
.lang-switch.is-open .lang-switch__menu { opacity: 1; visibility: visible; transform: translateY(0); }
@media (min-width: 1240px) {
  .lang-switch:focus-within .lang-switch__menu { opacity: 1; visibility: visible; transform: translateY(0); }   /* keyboard: open while tabbing through */
}
@media (min-width: 1240px) and (hover: hover) {
  .lang-switch:hover .lang-switch__menu { opacity: 1; visibility: visible; transform: translateY(0); }
}
.lang-switch.is-dismissed .lang-switch__menu { opacity: 0; visibility: hidden; }   /* Escape, per SC 1.4.13 — see .search-trigger.is-dismissed */
.lang-switch__menu a {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 10px;
  color: var(--color-text);
  font-size: 14px;
  text-decoration: none;
  border-radius: 6px;
}
.lang-switch__menu a:hover { background: var(--color-bg-subtle); color: var(--color-dark-purple); text-decoration: none; }

/* customer login — 1px pill, regular text */
.customer-login {
  margin: 0;
  display: inline-flex;
  align-items: center;
  border: 1px solid rgba(255, 255, 255, 0.5);
  border-radius: var(--radius-pill);
  padding: 9px var(--hdr-login-pad);
  font-size: 13px;
  font-weight: var(--fw-regular);
  line-height: 1;
  letter-spacing: 0.01em;
  white-space: nowrap;             /* two lines of "Customer login" is the bug, not the fix */
  color: #fff;
  background: transparent;
  text-decoration: none;
  transition: background var(--dur-base) var(--ease-standard),
              color var(--dur-base) var(--ease-standard),
              border-color var(--dur-base) var(--ease-standard);
}
.customer-login:hover {
  background: #fff;
  color: var(--color-text);
  border-color: #fff;
  text-decoration: none;
}

/* ============================================================
   Light header variant — for white-BG pages (e.g. photoheads).
   The floating header stays transparent on white: the logo shows
   the two-colour POSITIVE mark and all nav/utils go dark/positive.
   Element visibility is still governed by the base media rules.
   ============================================================ */
.site-header--light .site-header__logo img { filter: none; }   /* two-colour positive logo, not the white knockout */

.site-header--light .pillnav { background: rgba(20, 18, 30, 0.05); border-color: var(--color-divider); }
.site-header--light .pillnav > ul > li > a { color: var(--color-text); }
.site-header--light .pillnav > ul > li > a:hover,
.site-header--light .pillnav > ul > li:hover > a { color: var(--color-dark-purple); background: rgba(20, 18, 30, 0.06); }

.site-header--light .search-btn { color: var(--color-text); border-color: var(--color-border-strong); }
.site-header--light .search-btn:hover { color: var(--color-dark-purple); border-color: var(--color-dark-purple); background: rgba(20, 18, 30, 0.05); }

.site-header--light .lang-switch__current { color: var(--color-text); }
.site-header--light .lang-switch__current:hover { color: var(--color-dark-purple); }

.site-header--light .customer-login { color: var(--color-text); border-color: var(--color-border-strong); }
.site-header--light .customer-login:hover { background: var(--color-dark-purple); color: #fff; border-color: var(--color-dark-purple); }

.site-header--light .nav-toggle { background: rgba(20, 18, 30, 0.05); border-color: var(--color-border-strong); color: var(--color-text); }

/* on white pages the scrolled strip is light, not the dark bloom */
.site-header--light.is-scrolled {
  background: rgba(255, 255, 255, 0.9);
  box-shadow: 0 1px 0 var(--color-divider), 0 10px 30px -22px rgba(0, 0, 0, 0.35);
}

/* ============================================================
   6 · MOBILE HEADER + MENU (basic v1 state — DELTA: new; the old
       sketch had no header at all below 1240px once theme CSS left)
   ============================================================ */
.nav-toggle { display: none; }
.mobile-nav { display: none; }

@media (max-width: 1239.98px) {
  .pillnav { display: none; }
  .vmega { display: none; }   /* hide desktop mega panels on mobile so they can't ghost over content / full-page captures (Petter 2026-06-22) */
  .site-header { padding: 12px 0; }
  .site-header.is-scrolled { padding: 10px 0; }
  /* With no pill to centre, the equal side zones only cost room: the utils
     zone was held to half the row, which the language switch no longer fits
     in at phone widths (it spilled over the logo). Utils now take what they
     need and the logo — max-width: 100% — takes the rest. */
  .site-header__utils { flex: 0 0 auto; gap: 12px; }
  .site-header__utils .customer-login { display: none; }  /* lives in the menu instead */
  /* The language switch stays in the header (Yoann 2026-09-30). The button
     is as tall as the AI circle beside it, so the tap target is not the
     20px line of text it looks like. */
  .site-header__utils .lang-switch__current { min-height: 38px; padding-inline: 2px; }

  .nav-toggle {
    display: inline-flex;
    align-items: center;
    background: rgba(22, 16, 30, 0.42);
    -webkit-backdrop-filter: blur(16px);
    backdrop-filter: blur(16px);
    border: 1px solid rgba(255, 255, 255, 0.28);
    border-radius: var(--radius-pill);
    color: #fff;
    font-size: 14px;
    font-family: var(--font-body);
    padding: 10px 18px;
    cursor: pointer;
  }

  .mobile-nav {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 1001;
    background: rgba(13, 10, 24, 0.96);
    -webkit-backdrop-filter: blur(20px);
    backdrop-filter: blur(20px);
    padding: 96px 24px 40px;
    overflow-y: auto;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.25s var(--ease-standard), visibility 0.25s;
  }
  body.nav-open .mobile-nav { opacity: 1; visibility: visible; }
  body.nav-open { overflow: hidden; }
  /* The drawer lives INSIDE .site-header. When the header is .is-scrolled it gains
     backdrop-filter, which makes it the containing block for the fixed drawer and
     traps it to a strip at the top (Safari shows this as a black field at the top
     you can't close). Neutralise the filter while the menu is open, and lift the
     header row so the Close button stays above the drawer. (Petter 2026-06-22) */
  body.nav-open .site-header { -webkit-backdrop-filter: none; backdrop-filter: none; }
  body.nav-open .site-header__inner { z-index: 1003; }
  /* The open menu is dark, so the header chrome must read white even on .site-header--light pages */
  body.nav-open .site-header__logo img { filter: brightness(0) invert(1); }   /* white knockout wordmark */
  body.nav-open .search-btn { color: #fff; border-color: rgba(255, 255, 255, 0.5); }
  body.nav-open .lang-switch__current { color: #fff; }
  body.nav-open .nav-toggle { color: #fff; background: rgba(22, 16, 30, 0.42); border-color: rgba(255, 255, 255, 0.4); }

  .mobile-nav__group { border-top: 1px solid rgba(255, 255, 255, 0.10); }
  .mobile-nav__group:first-child { border-top: 0; }
  .mobile-nav__top {
    display: block;
    color: #fff;
    font-size: 18px;
    padding: 14px 0;
    text-decoration: none;
  }
  .mobile-nav__top:hover { color: #fff; text-decoration: none; }
  .mobile-nav__sub { list-style: none; margin: 0; padding: 0 0 12px; }
  .mobile-nav__sub a {
    display: block;
    padding: 8px 0;
    color: rgba(255, 255, 255, 0.7);
    font-size: 15px;
    text-decoration: none;
  }
  .mobile-nav__sub a:hover { color: #fff; text-decoration: none; }
  .mobile-nav__utils {
    margin-top: 28px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
  }
  .mobile-nav__utils .customer-login { display: inline-flex; }
}

/* ============================================================
   7 · FOOTER (light, informational — mirrors the old theme look)
   ============================================================ */
/* light-grey footer on a hairline divider — a clean break from the white CTA above */
.site-footer { background: var(--color-bg-subtle); border-top: 1px solid var(--color-border); }
.site-footer__main { padding-block: 80px 48px; }   /* inline gutter comes from .wrap (32px / 20px mobile) — don't zero it here, or the footer loses its left margin vs the content (Petter 2026-06-23) */
.site-footer__top {
  display: flex;
  flex-direction: column;
  gap: var(--space-7);
  margin-bottom: var(--space-7);
}
/* Two stacked rows on ONE shared column grid. Because the directory row is
   top-aligned, the first link-group headings line up with the first office
   heading ("Visitech Headquarters, Norway") whatever the newsletter/tagline
   heights happen to be — no pixel nudging. (2026-06-12) */
.site-footer__intro,
.site-footer__dir {
  display: grid;
  grid-template-columns: minmax(210px, 260px) 1fr;   /* narrow left, roomy right */
  gap: var(--space-8);
  align-items: start;
}
.site-footer__logo { width: 88px; height: auto; margin-bottom: var(--space-4); border-radius: var(--radius-lg); }   /* 10px rounded tile (Petter 2026-06-17) */
/* tagline = same size as the locations; air to the directory row is now the grid gap */
.site-footer__tagline {
  font-size: 13px;
  line-height: 1.5;
  color: var(--color-text-muted);
  margin: 0;
}

/* newsletter — a full-width strip at the foot of the directory: copy on the
   left, email field on the right. Moved out of the top-right corner where it
   read as misplaced (short module floating beside the taller brand block). (2026-06-12) */
.site-footer__signup {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5) var(--space-7);
  /* lifted: light amber→white panel (warm gold fading to white) so the newsletter
     stands out on the footer; same surface-tint technique as the other colours (Petter 2026-06-16) */
  background: var(--color-surface);   /* pure white (Petter 2026-06-17) */
  border: 1px solid var(--color-border);
  box-shadow: 0 12px 32px rgba(13, 10, 24, 0.06);
  border-radius: var(--radius-lg);   /* ≤10px, consistent with the other cards */
  padding: var(--space-6) var(--space-7);
  position: relative;
  overflow: hidden;
}
/* Variant A aurora-glow, recoloured to warm gold (Petter 2026-06-16) — two faint
   gold blooms drift slowly behind the newsletter copy, over the gold gradient */
.site-footer__signup::before,
.site-footer__signup::after { content: none; }   /* gold aurora removed — solid charcoal panel (Petter 2026-06-17) */
.site-footer__signup--legacy-bloom::before {
  content: ""; position: absolute; z-index: 0; border-radius: 50%;
  filter: blur(60px); pointer-events: none; will-change: transform;
}
.site-footer__signup::before {
  width: 52%; height: 220%; left: -8%; top: -60%;
  background: radial-gradient(circle, rgba(217, 161, 86, 0.34), transparent 70%);
  animation: footerAuroraA 22s ease-in-out infinite alternate;
}
.site-footer__signup::after {
  width: 46%; height: 210%; right: -6%; bottom: -60%;
  background: radial-gradient(circle, rgba(201, 138, 63, 0.26), transparent 70%);
  animation: footerAuroraB 27s ease-in-out infinite alternate;
}
.site-footer__signup .newsletter__intro,
.site-footer__signup .newsletter__row,
.site-footer__signup .newsletter__btn { position: relative; z-index: 1; }
@keyframes footerAuroraA { from { transform: translate(0, 0) scale(1); } to { transform: translate(18%, 12%) scale(1.22); } }
@keyframes footerAuroraB { from { transform: translate(0, 0) scale(1); } to { transform: translate(-16%, -10%) scale(1.18); } }
@media (prefers-reduced-motion: reduce) { .site-footer__signup::before, .site-footer__signup::after { animation: none; } }
.newsletter__intro { max-width: 460px; }
.site-footer__signup .newsletter__intro { max-width: 620px; }   /* longer text lines in the combined box on desktop (Petter 2026-08) */
.newsletter__label {
  font-size: var(--fs-base);
  font-weight: var(--fw-regular);
  color: var(--color-text);
  margin: 0 0 var(--space-2);
}
.newsletter__text { font-size: 14px; color: var(--color-text-muted); margin: 0; }
.newsletter__row { display: flex; gap: 8px; flex: 0 1 400px; }   /* comfortable field width on the strip; shrinks on narrow screens */
.newsletter__input {
  flex: 1;
  min-width: 0;
  padding: 10px 16px;
  font-size: 14px;
  font-family: var(--font-body);
  color: var(--color-text);
  background: var(--color-bg-subtle);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-pill);
  outline: none;
  transition: border-color var(--dur-base) var(--ease-standard), box-shadow var(--dur-base) var(--ease-standard);
}
.newsletter__input:focus { border-color: var(--color-light-purple); box-shadow: var(--focus-ring); }
/* now a link to the dedicated newsletter page (Petter 2026-06-17): inline-flex
   anchor with the site's arrow-nudge; same dark-purple pill + colour-shift hover */
.newsletter__btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 24px;
  font-size: 14px;
  font-family: var(--font-body);
  font-weight: var(--fw-regular);
  color: #fff;
  background-image: var(--gradient-button-deep);   /* deep purple→indigo sweep — both ends dark so "Subscribe now" stays crisp white (Petter 2026-06-17) */
  background-size: 200% 100%;
  background-position: 0% 0%;
  border: 0;
  border-radius: var(--radius-pill);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background-position 0.55s var(--ease-standard);
}
.newsletter__btn:hover { background-position: 100% 0%; text-decoration: none; }
.newsletter__btn .arrow { transition: transform var(--dur-base) var(--ease-standard); }
.newsletter__btn:hover .arrow { transform: translateX(3px); }
/* footer newsletter button = same solid purple as the megamenu CTA (light-purple → dark-purple on hover). Petter 18/6 */
.site-footer__signup .newsletter__btn { color: #fff; background-image: none; background-color: var(--color-light-purple); border: 1.5px solid transparent; transition: background-color var(--dur-base) var(--ease-standard), border-color var(--dur-base) var(--ease-standard); }
.site-footer__signup .newsletter__btn:hover { background-color: var(--color-dark-purple); }
/* combined contact + newsletter box — two buttons on the right (Petter 2026-08):
   Newsletter = outline on white · Contact Us = solid light-purple (both share .newsletter__btn shape) */
.newsletter__actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.site-footer__signup .newsletter__btn--outline { background-color: #fff; color: var(--color-dark-purple); border-color: var(--color-light-purple); }
.site-footer__signup .newsletter__btn--outline:hover { background-color: var(--color-light-purple-10); border-color: var(--color-dark-purple); color: var(--color-dark-purple); }

/* footer signup panel = pure white (Petter 2026-06-17); base dark label + muted text + dark-purple button carry through */
/* newsletter on the light amber footer panel — just a bigger heading; the base
   dark ink + dark-purple button carry through (good contrast on the gold→white) */
.site-footer__signup .newsletter__label { font-size: var(--fs-xl); margin-bottom: var(--space-1); }
.site-footer__cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));   /* 5 categories flow into 3 cols × 2 rows */
  gap: var(--space-7) var(--space-6);
}
.site-footer__col-title {
  font-family: var(--font-body);
  font-size: var(--fs-base);
  font-weight: var(--fw-regular);
  line-height: 1.3;
  color: var(--color-text);
  margin: 0 0 var(--space-3);
}
.site-footer__col p {
  margin: 0 0 var(--space-2);
  font-size: 15px;
  line-height: 1.6;
  color: var(--color-text-muted);
}
.site-footer__col ul { list-style: none; margin: 0; padding: 0; }
.site-footer__col li a {
  display: inline-block;
  padding: 5px 0;
  font-size: 15px;
  color: var(--color-text-muted);
}
.site-footer__col li a:hover { color: var(--color-link-hover); }

/* offices strip (live: HQ Drammen + Texas, Shanghai, Tokyo, Germany) */
/* locations = left column, stacked under the logo + tagline */
.site-footer__offices {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);   /* tighter — offices are now city + country one-liners (Petter 2026-06-16) */
}
.site-footer__offices li { font-size: 14px; line-height: 1.4; color: var(--color-text-muted); }
.site-footer__offices li span { display: block; font-size: 12px; color: var(--color-text-subtle); }
.site-footer__offices strong {
  display: block;
  font-size: 13px;
  font-weight: var(--fw-medium);
  color: var(--color-text);
  margin-bottom: 4px;
}

/* bottom bar: legal + social */
.site-footer__bottom {
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-divider);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}
.site-footer__copyright {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--color-text-muted);
}
.site-footer__social { display: flex; gap: 12px; }
.site-footer__social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
  border-radius: 50%;
  transition: color var(--dur-base) var(--ease-standard), border-color var(--dur-base) var(--ease-standard);
}
.site-footer__social a:hover { color: var(--color-dark-purple); border-color: var(--color-dark-purple); }
/* The prototype hand-wrote these glyphs with fill="currentColor"; the block
   renders CORE's social marks instead (one depository — inc/socials.php), and
   those carry no fill of their own, so an SVG's black default would win and the
   muted colour + hover above would do nothing. Same one line as
   .vt-person__social-icon svg in the people block. */
.site-footer__social svg { width: 16px; height: 16px; display: block; fill: currentColor; }

@media (max-width: 820px) {
  .site-footer__intro,
  .site-footer__dir { grid-template-columns: 1fr; }
  .site-footer__cols { grid-template-columns: 1fr; }   /* single, plain left-aligned column on mobile — content stays left, NOT stretched/justified across the width (Petter 2026-06-22) */
}

/* ------------------------------------------------------------
   7a · Footer bottom-bar clusters: internal sketch links + social
   ------------------------------------------------------------ */
.site-footer__bottom-right {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-5);
}
.site-footer__sketchlinks {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
}
.site-footer__sketchlinks span {
  font-size: max(10px, var(--fs-floor, 0px));
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-text-subtle);
}
.site-footer__sketchlinks a { font-size: 12px; color: var(--color-text-muted); text-decoration: none; }
.site-footer__sketchlinks a:hover { color: var(--color-dark-purple); }

/* ============================================================
   PLACEHOLDER LINKS — menu items whose target page doesn't exist
   yet render as <span class="is-placeholder"> (LinkRef type "none").
   ============================================================ */
.site-header .is-placeholder,
.site-footer .is-placeholder { opacity: 0.4; pointer-events: none; cursor: default; }

/* On the DARK chrome surfaces a placeholder had no colour of its own. Every
   rule that paints those links is scoped to `a` — `.pillnav > ul > li > a`,
   `.mobile-nav__sub a` — and a placeholder is a <span>, so it fell through to
   the body's ink: #2a2a32 at 40% opacity on the near-black drawer is 1.09:1,
   i.e. the item was not dimmed, it was gone ("PCB" under Lithography). The
   dimming is what .is-placeholder's opacity is for; the colour has to come from
   the surface. White at that opacity lands on 3.8:1 — the same "clearly there,
   clearly not clickable" the light surfaces already get. (a11y pass 2026-09-18) */
.pillnav > ul > li > span.is-placeholder,
.mobile-nav__top.is-placeholder,
.mobile-nav__sub .is-placeholder { color: #fff; }

/* ============================================================
   WP ADAPTATION — the footer sits FLUSH on the content above it.

   Core gives every top-level child of .wp-site-blocks a root block gap
   (`:where(.wp-site-blocks) > * { margin-block-start: 24px }`), and the footer
   arrives as one of those children inside a .wp-block-template-part wrapper —
   so a template that ends with the footer gets 24px of dead air above it. The
   prototype had no wrapper and no such rule; the separation here is the
   hairline border-top on .site-footer, and nothing else belongs above it.

   Written against the WRAPPER via :has(), not the wrapper's tag, so it holds
   whichever tagName the template-part reference uses (ours is "div", to avoid
   nesting <footer> inside <footer>); the second selector covers the block being
   rendered without a wrapper at all. Core's rule is specificity 0 — :where() —
   so a single class out-specifies it.
   ============================================================ */
.wp-site-blocks > :has(> .site-footer),
.wp-site-blocks > .site-footer { margin-block-start: 0; }

/* ============================================================
   WP ADAPTATION — logged-in admin bar (32px desktop, 46px ≤782px).
   The fixed header and the fixed mobile drawer must start below it;
   the bar itself sits at z-index 99999, above both.
   ============================================================ */
body.admin-bar .site-header { top: 32px; }
body.admin-bar .mobile-nav { top: 32px; }
@media screen and (max-width: 782px) {
  body.admin-bar .site-header { top: 46px; }
  body.admin-bar .mobile-nav { top: 46px; }
}
