/* ==========================================================================
   NEXISTEK — Components
   Reusable, context-free building blocks. Layout lives in style.css.
   ========================================================================== */

/* --- Eyebrow / section label --------------------------------------------- */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--text-energised);
}

.eyebrow::before {
  content: "";
  width: 1.75rem;
  height: 1px;
  background: var(--gradient-energy);
  flex: none;
}

.eyebrow--bare::before {
  display: none;
}

/* --- Glass panel ---------------------------------------------------------- */
.glass {
  position: relative;
  background-color: var(--surface-glass);
  background-image: var(--gradient-panel);
  border: 1px solid var(--border-hairline);
  border-radius: var(--r-lg);
  box-shadow: var(--elev-2);
  overflow: hidden;
}

/* Hairline highlight along the top edge — reads as light catching an edge. */
.glass::before {
  content: "";
  position: absolute;
  inset-inline: 12%;
  top: 0;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent,
    rgb(var(--rgb-text) / 0.5),
    transparent
  );
  pointer-events: none;
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .glass {
    -webkit-backdrop-filter: blur(var(--blur-glass));
    backdrop-filter: blur(var(--blur-glass));
  }
}

/* --- Buttons -------------------------------------------------------------- */
.btn {
  --btn-bg: transparent;
  --btn-fg: var(--text-primary);
  --btn-border: var(--border-soft);

  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  min-height: 3rem; /* ≥44px touch target */
  padding: var(--sp-3) var(--sp-6);
  background-color: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid var(--btn-border);
  border-radius: var(--r-full);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: 500;
  letter-spacing: var(--tracking-normal);
  /* Was `nowrap` with no width cap, which cropped long labels on narrow
     screens: "Discuss a corporate programme" needed 358px inside a 286px
     panel on a 390px phone, and .corporate's `overflow: hidden` sliced the
     rest off. Two other buttons went the same way at 360px.

     A label only wraps when it genuinely cannot fit — an inline-flex box
     still sizes to its content wherever there is room, so nothing that used
     to sit on one line starts breaking. */
  max-width: 100%;
  white-space: normal;
  text-align: center;
  text-wrap: balance;
  cursor: pointer;
  isolation: isolate;
  overflow: hidden;
  transition: color var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out),
    transform var(--dur-fast) var(--ease-out);
}

/* Wipe fill: scales from the bottom on hover. transform only — no reflow. */
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: var(--z-below);
  background: var(--gradient-energy);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform var(--dur-slow) var(--ease-out);
}

.btn:hover::before,
.btn:focus-visible::before {
  transform: scaleY(1);
}

.btn:hover,
.btn:focus-visible {
  color: var(--text-on-primary);
  border-color: transparent;
  box-shadow: var(--glow-md);
}

.btn:active {
  transform: scale(0.975);
}

.btn__icon {
  width: 1rem;
  height: 1rem;
  flex: none;
  transition: transform var(--dur-base) var(--ease-out);
}

.btn:hover .btn__icon {
  transform: translateX(0.2rem);
}

/* Primary — already filled, so the wipe runs in reverse (fills with white). */
.btn--primary {
  --btn-bg: var(--c-primary);
  --btn-fg: var(--text-on-primary);
  --btn-border: transparent;
  font-weight: 600;
  box-shadow: var(--glow-sm);
}

.btn--primary::before {
  background: var(--c-text);
}

.btn--primary:hover,
.btn--primary:focus-visible {
  color: var(--text-on-primary);
}

.btn--ghost {
  --btn-bg: var(--surface-glass);
  --btn-border: var(--border-hairline);
}

.btn--lg {
  min-height: 3.5rem;
  padding-inline: var(--sp-7);
  font-size: var(--fs-body);
}

/* --- Text link with a drawn underline ------------------------------------ */
.link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  color: var(--text-primary);
  font-weight: 500;
  padding-block: var(--sp-1);
  transition: color var(--dur-base) var(--ease-out);
}

.link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--gradient-energy);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--dur-slow) var(--ease-out);
}

.link:hover,
.link:focus-visible {
  color: var(--text-energised);
}

.link:hover::after,
.link:focus-visible::after {
  transform: scaleX(1);
  transform-origin: left;
}

/* --- Chip / tag ----------------------------------------------------------- */
.chip {
  display: inline-flex;
  align-items: center;
  padding: var(--sp-1) var(--sp-3);
  background-color: rgb(var(--rgb-text) / 0.05);
  border: 1px solid var(--border-hairline);
  border-radius: var(--r-full);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-secondary);
  transition: color var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out);
}

.chip-set {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

/* Interactive sibling of .chip — a filter toggle rather than a label, so it
   takes a pointer, a hover state and a pressed state the static chip has no
   use for. */
.filter-chip {
  display: inline-flex;
  align-items: center;
  padding: var(--sp-2) var(--sp-4);
  background-color: rgb(var(--rgb-text) / 0.05);
  border: 1px solid var(--border-hairline);
  border-radius: var(--r-full);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-secondary);
  cursor: pointer;
  transition: color var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out),
    background-color var(--dur-base) var(--ease-out);
}

.filter-chip:hover {
  color: var(--text-primary);
  border-color: var(--border-energised);
}

.filter-chip.is-active {
  background-color: rgb(var(--rgb-primary) / 0.12);
  border-color: var(--c-primary);
  color: var(--text-energised);
}

/* --- Index numeral -------------------------------------------------------- */
.index-num {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-wide);
  color: var(--text-tertiary);
}

/* --- Section heading block ------------------------------------------------ */
.section-head {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
  max-width: 46rem;
}

.section-head__title {
  font-size: var(--fs-h1);
  font-weight: 500;
  line-height: var(--lh-snug);
  letter-spacing: var(--tracking-tight);
}

.section-head__title em {
  font-style: normal;
  color: var(--text-energised);
}

.section-head__lead {
  font-size: var(--fs-lead);
  color: var(--text-secondary);
  max-width: 38rem;
}

/* --- Hairline divider ----------------------------------------------------- */
.rule {
  height: 1px;
  border: 0;
  background: linear-gradient(
    90deg,
    transparent,
    var(--border-hairline) 15%,
    var(--border-hairline) 85%,
    transparent
  );
}

/* --- Tech object (SVG line-art illustration) ------------------------------ */
/* Block in its own right, not by way of the media reset: these are standalone
   illustrations, and left inline each one sits on the text baseline and adds
   a few pixels of descender space under itself. */
.tech-object {
  display: block;
  width: 100%;
  height: auto;
  color: var(--c-primary);
  overflow: visible;
}

.tech-object .to-body {
  stroke: currentColor;
  stroke-width: 1.25;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.9;
}

.tech-object .to-detail {
  stroke: var(--c-muted);
  stroke-width: 1;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.55;
  transition: opacity var(--dur-slow) var(--ease-out);
}

/* Heavy structural members — robot limbs, chassis spars */
.tech-object .to-limb {
  stroke: currentColor;
  stroke-width: 4.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.85;
}

/* fill-opacity (not opacity) so an element can carry .to-body and .to-fill
   together without the stroke inheriting the transparency. */
.tech-object .to-fill {
  fill: currentColor;
  fill-opacity: 0.1;
  transition: fill-opacity var(--dur-slow) var(--ease-out);
}

.tech-object .to-node {
  fill: currentColor;
  opacity: 0.9;
}

/* Live element: dashes travel along the path to read as current flow. */
.tech-object .to-flow {
  stroke: var(--c-accent);
  stroke-width: 1.25;
  stroke-linecap: round;
  stroke-dasharray: 4 10;
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-out);
}

/* Loop variant — the About page's Our Approach diagram. Standalone rather
   than hover-triggered, so its current runs by default rather than
   waiting for a hover that never comes; keeps the sitewide orange. */
.tech-object--loop .to-flow {
  opacity: 1;
}

/* --- Custom cursor (pointer devices only; see responsive.css) ------------- */
.cursor {
  position: fixed;
  top: 0;
  left: 0;
  z-index: var(--z-cursor);
  display: none;
  pointer-events: none;
  will-change: transform;
}

.cursor__dot {
  width: 6px;
  height: 6px;
  margin: -3px 0 0 -3px;
  border-radius: var(--r-full);
  background-color: var(--c-primary);
}

.cursor__ring {
  width: 34px;
  height: 34px;
  margin: -17px 0 0 -17px;
  border: 1px solid var(--border-energised);
  border-radius: var(--r-full);
  transition: width var(--dur-base) var(--ease-out),
    height var(--dur-base) var(--ease-out),
    margin var(--dur-base) var(--ease-out),
    background-color var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out);
}

.cursor.is-hovering .cursor__ring {
  width: 56px;
  height: 56px;
  margin: -28px 0 0 -28px;
  background-color: rgb(var(--rgb-primary) / 0.12);
  border-color: var(--c-primary);
}

.cursor.is-pressed .cursor__ring {
  width: 26px;
  height: 26px;
  margin: -13px 0 0 -13px;
  background-color: rgb(var(--rgb-primary) / 0.28);
}

/* --- Scroll progress rail -------------------------------------------------- */
/* 3px rather than 2: at two device pixels on a laptop this read as a stray
   line rather than a progress indicator, and a faint track behind it gives
   the filled portion something to be measured against. */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  z-index: var(--z-nav);
  width: 100%;
  height: 3px;
  background-color: rgb(var(--rgb-text) / 0.09);
  pointer-events: none;
}

.scroll-progress__bar {
  height: 100%;
  width: 100%;
  background: var(--gradient-energy);
  transform: scaleX(0);
  transform-origin: left;
  box-shadow: var(--glow-sm);
}

/* --- Form field ----------------------------------------------------------- */
.field {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.field__label {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-secondary);
}

.field__required {
  color: var(--c-primary);
}

.field__input {
  min-height: 3rem;
  padding: var(--sp-3) var(--sp-4);
  background-color: rgb(var(--rgb-text) / 0.04);
  border: 1px solid var(--border-hairline);
  border-radius: var(--r-sm);
  color: var(--text-primary);
  font-size: var(--fs-body);
  transition: border-color var(--dur-base) var(--ease-out),
    background-color var(--dur-base) var(--ease-out);
}

.field__input::placeholder {
  color: var(--text-tertiary);
}

.field__input:hover {
  border-color: var(--border-soft);
}

.field__input:focus {
  outline: none;
  border-color: var(--c-primary);
  background-color: rgb(var(--rgb-text) / 0.06);
}

textarea.field__input {
  min-height: 9rem;
  resize: vertical;
  line-height: var(--lh-body);
}

/* --- Select ----------------------------------------------------------------
 * The control is ours; the popup belongs to the operating system. Style what
 * can be styled, and pick popup colours that still read correctly wherever
 * a browser decides to ignore them.
 */
.field__select {
  position: relative;
  display: block;
}

select.field__input {
  appearance: none;
  cursor: pointer;
  width: 100%;
  /* Clear of the caret sitting over the control's right edge. */
  padding-right: var(--sp-9);
}

/* The same drawn chevron the nav dropdowns and the FAQ use, rather than the
   pair of gradients this used to paint: an SVG takes a theme colour, and
   two triangles taped together never matched the rest of the interface. */
.field__select-caret {
  position: absolute;
  top: 50%;
  right: var(--sp-4);
  width: 1.125rem;
  height: 1.125rem;
  transform: translateY(-50%);
  color: var(--c-primary);
  pointer-events: none;
  transition: transform var(--dur-base) var(--ease-out);
}

.field__select:hover .field__select-caret {
  transform: translateY(-50%) translateY(1px);
}

/* Grouped options: the headings are the only thing separating twelve
   entries into something readable, so they are marked as headings rather
   than left in the browser's default italic. */
select.field__input optgroup {
  background-color: var(--c-void);
  color: var(--c-primary);
  font-family: var(--font-mono);
  font-style: normal;
  font-weight: 400;
  text-transform: uppercase;
}

select.field__input option {
  background-color: var(--c-deep);
  color: var(--text-primary);
  font-family: var(--font-body);
  text-transform: none;
}

.field__help {
  font-size: var(--fs-xs);
  color: var(--text-tertiary);
}

/* Error state: colour is never the only signal — the message carries the
   meaning and the icon marks it independently of hue. */
.field__error {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-xs);
  color: var(--c-accent);
}

.field__error::before {
  content: "";
  width: 0.9rem;
  height: 0.9rem;
  flex: none;
  border: 1px solid currentColor;
  border-radius: var(--r-full);
  background: linear-gradient(currentColor, currentColor) center / 1px 0.45rem
    no-repeat;
}

.field.has-error .field__input {
  border-color: var(--c-accent);
  background-color: rgb(var(--rgb-accent) / 0.06);
}

/* --- Inline notice -------------------------------------------------------- */
.notice {
  display: flex;
  gap: var(--sp-4);
  padding: var(--sp-5);
  border: 1px solid var(--border-energised);
  border-radius: var(--r-md);
  background-color: rgb(var(--rgb-primary) / 0.07);
}

.notice__icon {
  width: 1.5rem;
  height: 1.5rem;
  flex: none;
  color: var(--c-primary);
}

.notice__title {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 500;
  margin-bottom: var(--sp-1);
}

.notice__text {
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}

.notice--error {
  border-color: var(--c-accent);
  background-color: rgb(var(--rgb-accent) / 0.07);
}

/* --- Icon button (nav toggles) --------------------------------------------- */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border: 1px solid var(--border-hairline);
  border-radius: var(--r-full);
  color: var(--text-primary);
  background-color: var(--surface-glass);
  transition: color var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out),
    background-color var(--dur-base) var(--ease-out);
}

.icon-btn:hover,
.icon-btn:focus-visible {
  color: var(--c-primary);
  border-color: var(--border-energised);
  background-color: rgb(var(--rgb-primary) / 0.08);
}

.icon-btn svg {
  width: 1.125rem;
  height: 1.125rem;
}

.icon-btn[aria-pressed="true"] {
  color: var(--text-on-primary);
  background-color: var(--c-primary);
  border-color: transparent;
}

/* --- WhatsApp floating button ----------------------------------------------
 * A circle that grows into a pill on hover or keyboard focus. Collapsed by
 * default so it never covers page content on a phone, where it is closest to
 * the thumb and most likely to be in the way.
 *
 * WhatsApp green is used for the mark and the ring only, over the site's own
 * dark glass — a solid green blob would be the one element on the page not
 * speaking the site's language, and it does not need to shout to be found.
 *
 * z-index sits below --z-overlay so an open modal covers it.
 */
.wa-fab {
  --wa: #25d366;

  position: fixed;
  right: var(--gutter);
  bottom: var(--gutter);
  z-index: var(--z-sticky);

  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);

  height: 3.5rem;
  padding-inline: 1rem;
  border-radius: var(--r-full);

  border: 1px solid rgb(37 211 102 / 0.45);
  background-color: rgb(var(--rgb-void) / 0.82);
  backdrop-filter: blur(var(--blur-glass));
  -webkit-backdrop-filter: blur(var(--blur-glass));
  box-shadow: var(--elev-3), 0 0 24px rgb(37 211 102 / 0.22);

  color: var(--text-primary);
  font-size: var(--fs-sm);
  font-weight: 500;
  line-height: 1;
  text-decoration: none;

  transition: transform var(--dur-base) var(--ease-spring),
    border-color var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out);
}

.wa-fab:hover,
.wa-fab:focus-visible {
  transform: translateY(-2px);
  border-color: var(--wa);
  box-shadow: var(--elev-3), 0 0 34px rgb(37 211 102 / 0.4);
}

.wa-fab__icon {
  display: grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  flex: none;
  color: var(--wa);
}

.wa-fab__icon svg {
  width: 100%;
  height: 100%;
}

/* Collapsed to nothing until the button is hovered or focused. Width rather
   than display, so the label slides out instead of snapping the layout. */
.wa-fab__label {
  max-width: 0;
  overflow: hidden;
  white-space: nowrap;
  opacity: 0;
  transition: max-width var(--dur-base) var(--ease-out),
    opacity var(--dur-fast) var(--ease-out);
}

.wa-fab:hover .wa-fab__label,
.wa-fab:focus-visible .wa-fab__label {
  max-width: 12rem;
  opacity: 1;
}

/* Touch: there is no hover to reveal the label, and a permanently expanded
   pill eats more of a small screen than it earns. Icon only, and centred. */
@media (hover: none) {
  .wa-fab {
    width: 3.5rem;
    padding-inline: 0;
    justify-content: center;
  }

  .wa-fab__label {
    display: none;
  }
}

/* Sits above the scroll rail's own gutter on very short screens rather than
   overlapping the footer bar. */
@media (max-height: 30rem) {
  .wa-fab {
    height: 3rem;
    width: 3rem;
  }
}
