/* ===========================================================================
   Components — the reusable kit shared by every page.
   Large one-off page compositions (hero, ecosystem, bento, insights)
   live in sections.css.
   =========================================================================== */

/* =========================================================== 1. buttons == */

.btn {
  --btn-py: 0.72rem;
  --btn-px: 1.4rem;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55em;
  padding: var(--btn-py) var(--btn-px);
  border-radius: var(--radius-pill);
  border: 1px solid transparent;
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: -0.01em;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur) var(--ease-out),
    background-color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out),
    color var(--dur) var(--ease-out);
}

.btn:active {
  transform: translateY(1px) scale(0.985);
}

.btn__icon {
  width: 1em;
  height: 1em;
  flex: none;
  transition: transform var(--dur) var(--ease-spring);
}

.btn:hover .btn__icon {
  transform: translateX(3px);
}

/* Primary — solid brand teal.
   There was a sheen pseudo-element here that swept across on hover. It is
   gone: parked off-screen at translateX(-120%) with nothing clipping it, it
   was permanently visible as a grey smear to the left of every primary
   button. The lift, colour shift and shadow below carry the hover on their
   own, and read calmer besides. */
.btn--primary {
  background: var(--brand-teal);
  color: var(--brand-ink);
  box-shadow: var(--shadow-brand);
}

.btn--primary:hover {
  background: #12c9a8;
  transform: translateY(-2px);
  box-shadow: 0 14px 30px -14px rgba(10, 178, 151, 0.42);
}

/* Gold — reserved for the single most important action on a dark band. */
.btn--gold {
  background: var(--brand-gold);
  color: #3a2a00;
  box-shadow: 0 12px 32px -12px rgba(255, 198, 46, 0.5);
}

.btn--gold:hover {
  background: var(--brand-gold-bright);
  transform: translateY(-2px);
  box-shadow: 0 18px 40px -14px rgba(255, 198, 46, 0.6);
}

/* Outline — secondary weight, borrows the surface so it works on any band.
   The inset hairline along the top edge is what stops it reading as a flat
   dark rectangle next to the solid primary; on hover the whole thing warms
   to a brand tint rather than only swapping its border colour. */
.btn--outline {
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--text-primary) 6%, var(--bg-surface)) 0%,
    var(--bg-surface) 100%
  );
  border-color: var(--border-strong);
  color: var(--text-primary);
  box-shadow: var(--shadow-sm), inset 0 1px 0 color-mix(in srgb, var(--text-primary) 10%, transparent);
}

.btn--outline:hover {
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--brand-teal) 16%, var(--bg-surface)) 0%,
    color-mix(in srgb, var(--brand-teal) 6%, var(--bg-surface)) 100%
  );
  border-color: var(--brand-teal);
  color: var(--color-primary);
  transform: translateY(-2px);
  box-shadow: 0 12px 28px -14px color-mix(in srgb, var(--brand-teal) 55%, transparent),
    inset 0 1px 0 color-mix(in srgb, var(--text-primary) 14%, transparent);
}

.btn--outline:active {
  box-shadow: none;
}

/* Line — border and label only, nothing behind it. For a secondary action
   standing beside a solid primary, where --outline is still too much weight:
   it borrows --bg-surface for its fill, which on a white card is a second
   filled pill and on the ink header is a dark slab. This one paints no
   background at all, so the same class reads correctly on either. */
.btn--line {
  background: transparent;
  border-color: var(--border-brand);
  color: var(--color-primary);
  box-shadow: none;
}

.btn--line:hover {
  background: var(--bg-brand-subtle);
  border-color: var(--brand-teal);
  transform: translateY(-2px);
}

.btn--line:active {
  transform: translateY(1px) scale(0.985);
}

/* Ghost — lowest weight, for tertiary links that still need a hit area. */
.btn--ghost {
  color: var(--text-secondary);
}

.btn--ghost:hover {
  background: var(--bg-brand-subtle);
  color: var(--color-primary);
}

.btn--lg {
  --btn-py: 0.95rem;
  --btn-px: 1.85rem;
  font-size: 1rem;
}

.btn--sm {
  --btn-py: 0.55rem;
  --btn-px: 1rem;
  font-size: var(--fs-xs);
}

.btn--block {
  width: 100%;
}

/* Secondary action sitting on a permanently-dark band, where --bg-surface
   would be the wrong base. */
.btn--on-ink {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(150, 220, 208, 0.3);
  color: #eaf5f2;
  box-shadow: none;
}

.btn--on-ink:hover {
  background: rgba(255, 255, 255, 0.14);
  border-color: var(--brand-teal);
  color: #ffffff;
  transform: translateY(-2px);
}

.btn[disabled],
.btn[aria-disabled='true'] {
  opacity: 0.5;
  pointer-events: none;
}

/* Text link with a sliding arrow. */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--color-primary);
  transition: gap var(--dur) var(--ease-spring);
}

.link-arrow svg {
  width: 1.05em;
  height: 1.05em;
  transition: transform var(--dur) var(--ease-spring);
}

.link-arrow:hover {
  gap: 0.75em;
}

.link-arrow:hover svg {
  transform: translateX(2px);
}

/* A link-arrow closing a copy block, rather than sitting inline in a row. */
.link-arrow--block {
  margin-top: var(--sp-8);
}

/* Chip treatment: an outline only — no fill, so it keeps whatever band it sits
   on. nowrap because the label and its arrow have to stay on one line; the
   border makes a wrap look like a broken control rather than a folded link. */
.link-arrow--chip {
  padding: 0.6em 1.1em;
  border: 1px solid var(--border-brand);
  border-radius: var(--radius-pill);
  background: transparent;
  white-space: nowrap;
  transition: gap var(--dur) var(--ease-spring), border-color var(--dur) var(--ease-out),
    box-shadow var(--dur) var(--ease-out);
}

.link-arrow--chip:hover {
  border-color: color-mix(in srgb, var(--brand-teal) 55%, transparent);
  box-shadow: var(--shadow-sm);
}

/* ============================================================ 2. pills === */

.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.42em 0.9em;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-color);
  background: var(--bg-surface);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  color: var(--text-secondary);
  white-space: nowrap;
}

.pill--brand {
  border-color: var(--border-brand);
  background: var(--bg-brand-subtle);
  color: var(--color-primary);
}

.pill--gold {
  border-color: rgba(255, 198, 46, 0.4);
  background: var(--bg-gold-subtle);
  color: var(--color-accent-text);
}

.pill__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

/* Live indicator — the pulse marks the hero badge as "active network". */
.pill__dot--live {
  position: relative;
  background: var(--brand-teal);
}

.pill__dot--live::after {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 1.5px solid var(--brand-teal);
  animation: ping 2.4s var(--ease-out) infinite;
}

/* ============================================================ 3. cards === */

.card {
  position: relative;
  padding: clamp(1.35rem, 2.4vw, 2rem);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-color);
  background: var(--bg-surface);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out),
    border-color var(--dur) var(--ease-out), background-color var(--dur) var(--ease-out);
}

/* Gradient hairline that only appears on hover. Painted into the border box
   with a mask so it stays a true 1px edge at any radius. */
.card--interactive::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(140deg, var(--brand-teal), transparent 42%, transparent 62%, var(--brand-gold));
  -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;
  transition: opacity var(--dur) var(--ease-out);
  pointer-events: none;
}

.card--interactive:hover,
.card--interactive:focus-within {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  border-color: transparent;
  /* Pista wash on the light bands. The lift and the gradient hairline alone
     were easy to miss against white. The fallback is the card's own surface,
     so the dark bands — which define no --card-hover-bg — are untouched. */
  background: var(--card-hover-bg, var(--bg-surface));
}

.card--interactive:hover::before,
.card--interactive:focus-within::before {
  opacity: 1;
}

.card__icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: var(--radius-md);
  background: var(--bg-brand-subtle);
  border: 1px solid var(--border-brand);
  margin-bottom: var(--sp-5);
  flex: none;
  transition: transform var(--dur) var(--ease-spring), background-color var(--dur) var(--ease-out),
    border-color var(--dur) var(--ease-out);
}

.card__icon img,
.card__icon svg {
  width: 24px;
  height: 24px;
  color: var(--color-primary);
  transition: color var(--dur) var(--ease-out), transform var(--dur) var(--ease-spring);
}

/* Hover: the tile inverts to ink and the glyph goes white, which is the only
   treatment that still reads once the cards moved onto white and pista bands
   — the old pale-amber tile under a gold glyph washed out against them. The
   glyph still zooms; an earlier version also rotated the tile a few degrees,
   which read as the icon slipping rather than responding. */
.card--interactive:hover .card__icon,
.card--interactive:focus-within .card__icon {
  background: var(--brand-ink);
  border-color: var(--brand-ink);
  transform: scale(1.08);
}

.card--interactive:hover .card__icon svg,
.card--interactive:hover .card__icon img,
.card--interactive:focus-within .card__icon svg,
.card--interactive:focus-within .card__icon img {
  color: #ffffff;
  transform: scale(1.14);
}

/* Inverted again on the dark bands, where an ink tile would simply vanish —
   and gold rather than teal, because on a teal-tinted dark band a teal tile is
   barely a change. Gold is the accent this site already reserves for dark
   surfaces, so the hover lands as a warm highlight against the cool band. */
.section:not(.section--light):not(.section--soft) .card--interactive:hover .card__icon,
.section:not(.section--light):not(.section--soft) .card--interactive:focus-within .card__icon {
  background: var(--brand-gold);
  border-color: var(--brand-gold);
}

.section:not(.section--light):not(.section--soft) .card--interactive:hover .card__icon svg,
.section:not(.section--light):not(.section--soft) .card--interactive:hover .card__icon img,
.section:not(.section--light):not(.section--soft) .card--interactive:focus-within .card__icon svg,
.section:not(.section--light):not(.section--soft) .card--interactive:focus-within .card__icon img {
  color: var(--brand-ink);
}

.section--ink .card--interactive::before {
  background: linear-gradient(140deg, var(--brand-gold), transparent 42%, transparent 62%, var(--brand-gold-bright));
}

.section--ink .card--interactive:hover,
.section--ink .card--interactive:focus-within {
  box-shadow: var(--shadow-lg), 0 18px 44px -24px rgba(255, 198, 46, 0.38);
}

.card__title {
  font-size: var(--fs-h4);
  margin-bottom: var(--sp-3);
}

.card__text {
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  line-height: var(--lh-body);
}

.card__foot {
  margin-top: var(--sp-5);
}

.glass-panel {
  border-radius: var(--radius-lg);
  border: 1px solid var(--glass-border);
  background: var(--glass-bg);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
  backdrop-filter: blur(var(--glass-blur)) saturate(140%);
  box-shadow: var(--shadow-md);
}

.surface {
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-color);
  background: var(--bg-surface);
}

/* Grid presets used by card collections. */
.grid {
  display: grid;
  gap: clamp(1rem, 2vw, 1.5rem);
}

/* Explicitly three columns, not auto-fit. auto-fit let a "grid--3" become
   four columns once the container grew, which is what split a six-card
   section into 4 + 2. Every grid on the site holds a multiple of three, so
   this keeps every row full. Stepped down at the breakpoints in
   responsive.css. */
.grid--3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

/* =========================================================== 4. header === */

.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-header);
  height: var(--header-h);
  display: flex;
  align-items: center;
  border-bottom: 1px solid transparent;
  transition: background-color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out),
    box-shadow var(--dur) var(--ease-out), backdrop-filter var(--dur) var(--ease-out);
}

/* Scrolled state — added by navigation.js. */
.site-header.is-scrolled {
  background: var(--header-bg);
  border-bottom-color: var(--header-border);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  backdrop-filter: blur(16px) saturate(160%);
  box-shadow: 0 1px 24px -8px rgba(0, 0, 0, 0.18);
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  width: 100%;
}

.brand {
  display: flex;
  align-items: center;
  flex: none;
  transition: opacity var(--dur) var(--ease-out);
}

.brand:hover {
  opacity: 0.82;
}

/* The mark is a stacked lockup — dot pyramid over the wordmark — so it needs
   real height before the "VITRAK Extendreach" type is legible at all. The
   header grows with it (--header-h), rather than the logo being squeezed to
   fit a chrome bar sized for a horizontal lockup. */
.brand img {
  height: clamp(46px, 4.8vw, 64px);
  width: auto;
}

/* Two real exports rather than a filter. The primary logo is dark-ink type
   for light backgrounds; the footer export is the same mark in brighter teal
   and gold, drawn for dark ones. Inverting the first would have flattened the
   brand to white and thrown the gold apex away. */
.brand__dark {
  display: none;
}

[data-theme='dark'] .brand__light {
  display: none;
}

[data-theme='dark'] .brand__dark {
  display: block;
}

/* ------------------------------------------------------------ desktop nav */

.nav {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
}

.nav__link {
  position: relative;
  padding: 0.62rem 1rem;
  border-radius: var(--radius-sm);
  font-size: clamp(0.9375rem, 1vw, 1.0625rem);
  font-weight: var(--fw-medium);
  color: var(--text-secondary);
  transition: color var(--dur) var(--ease-out), background-color var(--dur) var(--ease-out);
}

.nav__link::after {
  content: '';
  position: absolute;
  left: 1rem;
  right: 1rem;
  bottom: 0.3rem;
  height: 2px;
  border-radius: 2px;
  background: var(--color-primary-fill);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur) var(--ease-out);
}

.nav__link:hover {
  color: var(--text-primary);
}

.nav__link:hover::after {
  transform: scaleX(1);
}

.nav__link[aria-current='page'] {
  color: var(--text-primary);
  font-weight: var(--fw-semibold);
}

.nav__link[aria-current='page']::after {
  transform: scaleX(1);
}

/* The auto margin lives here, not on .brand — that puts the nav immediately
   after the logo (left-aligned) and pushes only the login / app buttons to
   the far right. */
.header-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex: none;
  margin-left: auto;
}

/* The header pair sits between --sm and the default size: --sm was too slight
   against a 94px bar and the enlarged logo. */
.header-actions .btn {
  --btn-py: 0.72rem;
  --btn-px: 1.4rem;
  font-size: 0.9375rem;
}

/* -------------------------------------------------- 6. mobile nav drawer */

.nav-toggle {
  display: none;
  width: 42px;
  height: 42px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-color);
  background: var(--bg-surface);
  place-items: center;
  flex: none;
}

.nav-toggle__bars {
  position: relative;
  width: 18px;
  height: 12px;
}

.nav-toggle__bars span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  border-radius: 2px;
  background: var(--text-primary);
  transition: transform var(--dur) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
}

.nav-toggle__bars span:nth-child(1) {
  top: 0;
}
.nav-toggle__bars span:nth-child(2) {
  top: 5px;
}
.nav-toggle__bars span:nth-child(3) {
  top: 10px;
}

.nav-toggle[aria-expanded='true'] .nav-toggle__bars span:nth-child(1) {
  transform: translateY(5px) rotate(45deg);
}
.nav-toggle[aria-expanded='true'] .nav-toggle__bars span:nth-child(2) {
  opacity: 0;
}
.nav-toggle[aria-expanded='true'] .nav-toggle__bars span:nth-child(3) {
  transform: translateY(-5px) rotate(-45deg);
}

.drawer-scrim {
  position: fixed;
  inset: 0;
  z-index: calc(var(--z-drawer) - 1);
  background: var(--scrim);
  opacity: 0;
  visibility: hidden;
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  /* visibility flips instantly on the way in and is delayed on the way out,
     so the scrim is never a transparent click-blocker mid-fade. */
  transition: opacity var(--dur) var(--ease-out), visibility 0s linear var(--dur);
}

.drawer-scrim.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--dur) var(--ease-out), visibility 0s;
}

.drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-drawer);
  width: min(400px, 88vw);
  display: flex;
  flex-direction: column;
  background: var(--bg-page);
  border-left: 1px solid var(--border-color);
  box-shadow: var(--shadow-lg);
  transform: translateX(100%);
  visibility: hidden;
  /* Interpolating visibility would leave it computing as `hidden` for the
     first frame of the opening transition, and .focus() on a hidden subtree
     is silently dropped — which stranded keyboard focus on the burger. It is
     switched instantly on open and delayed only on close. */
  transition: transform var(--dur-slow) var(--ease-out), visibility 0s linear var(--dur-slow);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-bottom: max(var(--sp-8), env(safe-area-inset-bottom));
}

.drawer.is-open {
  transform: translateX(0);
  visibility: visible;
  transition: transform var(--dur-slow) var(--ease-out), visibility 0s;
}

.drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  min-height: var(--header-h);
  border-bottom: 1px solid var(--border-color);
}

.drawer__close {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-color);
  color: var(--text-secondary);
  flex: none;
}

.drawer__close:hover {
  color: var(--text-primary);
  background: var(--bg-page-alt);
}

.drawer__close svg {
  width: 18px;
  height: 18px;
}

.drawer__nav {
  padding: var(--sp-5);
  display: grid;
  gap: var(--sp-1);
}

.drawer__link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-4) var(--sp-4);
  border-radius: var(--radius-md);
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-heading);
  color: var(--text-primary);
  /* staggered entrance, driven by --d set inline per item */
  opacity: 0;
  transform: translateX(18px);
  transition: opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-out),
    background-color var(--dur-fast) var(--ease-out);
}

.drawer.is-open .drawer__link {
  opacity: 1;
  transform: translateX(0);
  transition-delay: calc(var(--d, 0) * 45ms + 90ms);
}

.drawer__link:hover,
.drawer__link:focus-visible {
  background: var(--bg-brand-subtle);
  color: var(--color-primary);
}

.drawer__link svg {
  width: 16px;
  height: 16px;
  opacity: 0.4;
}

.drawer__link[aria-current='page'] {
  color: var(--color-primary);
}

.drawer__foot {
  margin-top: auto;
  padding: var(--sp-5);
  border-top: 1px solid var(--border-color);
  display: grid;
  gap: var(--sp-3);
}

/* ============================================================= 7. tabs === */

/* The track is deliberately the darkest surface so the thumb has something to
   read against. */
.tabs {
  display: inline-flex;
  padding: 5px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-color);
  background: var(--bg-sunken);
  position: relative;
  max-width: 100%;
}

/* A solid brand fill, same language as .btn--primary. The previous version
   used --bg-surface on --bg-page-alt, which on the dark theme are four values
   apart — the selected tab was effectively invisible. */
.tabs__thumb {
  position: absolute;
  top: 5px;
  bottom: 5px;
  border-radius: var(--radius-pill);
  background: var(--brand-teal);
  box-shadow: 0 8px 20px -8px rgba(10, 178, 151, 0.65);
  /* left/width are written by main.js from the active tab's box */
  transition: transform var(--dur) var(--ease-spring), width var(--dur) var(--ease-spring);
  pointer-events: none;
}

.tabs__btn {
  position: relative;
  z-index: 1;
  padding: 0.75rem 1.5rem;
  border-radius: var(--radius-pill);
  font-size: clamp(0.9375rem, 1vw, 1.0625rem);
  font-weight: var(--fw-semibold);
  color: var(--text-secondary);
  white-space: nowrap;
  transition: color var(--dur) var(--ease-out);
}

.tabs__btn:hover {
  color: var(--text-primary);
}

.tabs__btn[aria-selected='true'] {
  color: var(--text-on-brand);
  font-weight: var(--fw-bold);
}

.tab-panel[hidden] {
  display: none;
}

/* ======================================================== 8. accordion === */

.accordion {
  display: grid;
  gap: var(--sp-3);
}

.acc-item {
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
  background: var(--bg-surface);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
}

.acc-item.is-open {
  border-color: var(--border-brand);
  box-shadow: var(--shadow-md);
}

.acc-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  width: 100%;
  padding: clamp(1rem, 2vw, 1.35rem) clamp(1.1rem, 2.4vw, 1.6rem);
  text-align: left;
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-heading);
  color: var(--text-primary);
  transition: color var(--dur) var(--ease-out);
}

.acc-trigger:hover {
  color: var(--color-primary);
}

.acc-icon {
  position: relative;
  width: 22px;
  height: 22px;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  transition: background-color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out),
    transform var(--dur) var(--ease-spring);
}

.acc-icon::before,
.acc-icon::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 10px;
  height: 1.5px;
  border-radius: 2px;
  background: currentColor;
  transform: translate(-50%, -50%);
  transition: transform var(--dur) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
}

.acc-icon::after {
  transform: translate(-50%, -50%) rotate(90deg);
}

.acc-item.is-open .acc-icon {
  background: var(--bg-brand-subtle);
  border-color: var(--border-brand);
  transform: rotate(180deg);
}

.acc-item.is-open .acc-icon::after {
  opacity: 0;
}

/* grid-template-rows 0fr→1fr animates to auto height without measuring. */
.acc-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-slow) var(--ease-out);
}

.acc-item.is-open .acc-body {
  grid-template-rows: 1fr;
}

.acc-body > div {
  overflow: hidden;
}

.acc-body p {
  padding: 0 clamp(1.1rem, 2.4vw, 1.6rem) clamp(1.1rem, 2.2vw, 1.5rem);
  color: var(--text-secondary);
  max-width: 68ch;
}

/* ============================================================ 9. forms === */

.form {
  display: grid;
  gap: var(--sp-4);
}

.form__row {
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
}

.field {
  display: grid;
  gap: var(--sp-2);
}

/* [hidden] is only a UA display:none, and the author rule above beats it —
   which is why the conditional "Tell us which" field sat on screen in every
   state instead of appearing with "Other". It fades in when it does show;
   the global reduced-motion rule collapses that to instant. */
.field[hidden] {
  display: none;
}

.field[data-conditional]:not([hidden]) {
  animation: field-in 260ms var(--ease-out);
}

@keyframes field-in {
  from {
    opacity: 0;
    transform: translateY(-6px);
  }
}

/* A radio group is a fieldset, which carries UA borders and padding. */
fieldset.field {
  border: 0;
  padding: 0;
  min-inline-size: 0;
}

fieldset.field legend {
  padding: 0;
  margin-bottom: var(--sp-1);
}

.field__label {
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--text-secondary);
}

.field__label .req {
  color: var(--color-accent-text);
}

.field__control {
  width: 100%;
  padding: 0.85rem 1rem;
  border-radius: var(--radius-md);
  /* --border-color is a hairline meant for separating blocks; on an input it
     left the box almost impossible to see. --border-strong plus a faint inset
     gives the control a readable edge on both the light and dark themes. */
  border: 1px solid var(--border-strong);
  box-shadow: inset 0 1px 2px rgba(6, 32, 28, 0.05);
  background: var(--bg-surface);
  color: var(--text-primary);
  font-size: var(--fs-sm);
  transition: border-color var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
}

.field__control::placeholder {
  color: var(--text-muted);
}

.field__control:focus {
  outline: none;
  border-color: var(--brand-teal);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-teal) 18%, transparent);
}

textarea.field__control {
  min-height: 96px;
  resize: vertical;
}

select.field__control {
  appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%236b8681' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: 12px;
  padding-right: 2.5rem;
}

.field__error {
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  color: #e0524f;
  min-height: 1em;
}

[data-theme='dark'] .field__error {
  color: #ff8b88;
}

.field.has-error .field__control {
  border-color: #e0524f;
}

.field.has-error .field__control:focus {
  box-shadow: 0 0 0 3px rgba(224, 82, 79, 0.18);
}

/* Radio group rendered as selectable chips. */
.choice-group {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

.choice {
  position: relative;
}

.choice input {
  position: absolute;
  opacity: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  cursor: pointer;
}

.choice span {
  display: block;
  padding: 0.6rem 1.05rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-color);
  background: var(--bg-surface);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text-secondary);
  transition: all var(--dur) var(--ease-out);
}

.choice input:hover + span {
  border-color: var(--border-strong);
}

.choice input:checked + span {
  border-color: var(--brand-teal);
  background: var(--bg-brand-subtle);
  color: var(--color-primary);
  font-weight: var(--fw-semibold);
}

.choice input:focus-visible + span {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* On the ink band the form panel and the controls inside it both resolve to
   --bg-surface, so every field became an invisible box marked only by its
   border. Sink the controls below the panel instead: a dark well with a light
   hairline reads as something you type into, which a 4.5%-white rectangle on
   4.5%-white does not. The inset highlight is the shared one flipped — the
   light-theme version paints a dark inset, which is invisible here. */
.section--ink .contact__form-wrap {
  background: rgba(255, 255, 255, 0.05);
}

.section--ink .field__control,
.section--ink .choice span {
  background: rgba(3, 12, 11, 0.55);
  border-color: rgba(150, 220, 208, 0.26);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.35);
}

.section--ink .choice input:checked + span {
  background: rgba(10, 178, 151, 0.16);
  border-color: var(--brand-teal);
  color: var(--brand-teal-bright);
}

/* Submission feedback. */
.form__status {
  display: none;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-radius: var(--radius-md);
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
}

.form__status.is-visible {
  display: flex;
}

.form__status--ok {
  background: var(--bg-brand-subtle);
  border: 1px solid var(--border-brand);
  color: var(--color-primary);
}

.form__status--err {
  background: rgba(224, 82, 79, 0.1);
  border: 1px solid rgba(224, 82, 79, 0.35);
  color: #c0403d;
}

[data-theme='dark'] .form__status--err {
  color: #ff9b98;
}

.form__status svg {
  width: 18px;
  height: 18px;
  flex: none;
  margin-top: 1px;
}

/* Spinner shown while a submit is in flight. */
.btn.is-loading {
  pointer-events: none;
  color: transparent;
}

.btn.is-loading::after {
  content: '';
  position: absolute;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid rgba(4, 16, 14, 0.25);
  border-top-color: var(--brand-ink);
  animation: spin 0.7s linear infinite;
}

/* =========================================================== 10. quote === */

.quote {
  position: relative;
  padding-left: clamp(1.5rem, 4vw, 3rem);
}

.quote::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.35em;
  bottom: 0.35em;
  width: 3px;
  border-radius: 3px;
  background: var(--grad-brand);
}

.quote__text {
  font-family: var(--font-display);
  font-size: var(--fs-quote);
  font-weight: var(--fw-medium);
  line-height: 1.45;
  letter-spacing: var(--ls-heading);
  color: var(--text-primary);
  text-wrap: balance;
}

.quote__by {
  margin-top: var(--sp-5);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--color-primary);
}

/* ========================================================= 11. marquee === */
/* Two identical tracks translated -50% give a seamless loop with no JS. */

/* The vertical padding is load-bearing: overflow is hidden for the loop, so
   without it the chips' shadow is clipped off at the top and bottom edges. */
.marquee {
  position: relative;
  overflow: hidden;
  padding-block: 0.9rem;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

.marquee__track {
  display: flex;
  width: max-content;
  gap: clamp(0.7rem, 1.2vw, 1rem);
}

/* The -50% loop needs two identical copies of the track; main.js makes the
   clone and then adds .is-ready. Until (or unless) that happens the strip is
   a static complete row rather than a half-empty one. */
.marquee.is-ready .marquee__track {
  animation: marquee var(--marquee-dur, 46s) linear infinite;
}

.marquee.is-ready:hover .marquee__track {
  animation-play-state: paused;
}

.marquee--reverse .marquee__track {
  animation-direction: reverse;
}

/* No hover state, and so no transition either: the chips are labels riding an
   auto-scroller, not targets — lighting one up under the cursor promised an
   affordance that isn't there.

   Glass on ink rather than the solid teal blocks these used to be. Twelve
   saturated slabs in a row read as a colour bar; a translucent panel with one
   lit mark inside it reads as a card, and the band behind is what supplies
   the contrast the old near-white one could not. */
.marquee__item {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0.8em;
  min-width: clamp(190px, 15.5vw, 244px);
  padding: 0.8rem 1.4rem;
  /* One step down from .netstat__item's --radius-xl: at a chip's height that
     radius is half the box and the card turns back into a pill. */
  border-radius: var(--radius-lg);
  /* Same surface, border and halo as .netstat__item — a chip is a small card
     off the network band, not a shape of its own. */
  border: 1px solid var(--border-color);
  background: var(--bg-surface);
  overflow: hidden;
  font-size: clamp(0.9375rem, 1vw, 1.0625rem);
  font-weight: var(--fw-medium);
  color: var(--text-primary);
  white-space: nowrap;
}

/* .netstat__icon's puck, one size down, and gold rather than teal.

   Gold is already the far end of the network band's own gradients — the
   numerals and the growth lines both run out to it — so the marks pick up
   that accent instead of repeating the teal the chip's border already
   carries. No halo behind them: at chip scale the pool read as a shadow the
   puck was casting rather than as light. */
.marquee__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: var(--radius-md);
  border: 1px solid rgba(255, 198, 46, 0.38);
  background: color-mix(in srgb, var(--brand-gold) 13%, transparent);
  color: var(--brand-gold);
}

.marquee__icon svg {
  width: 18px;
  height: 18px;
}
/* ============================================================ 13. stat === */

.stat {
  display: grid;
  gap: var(--sp-2);
}

.stat__value {
  font-family: var(--font-display);
  font-size: var(--fs-numeral);
  font-weight: var(--fw-bold);
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.stat__label {
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  line-height: var(--lh-snug);
}

/* ====================================================== 14. checklist ==== */

.checklist {
  display: grid;
  gap: var(--sp-4);
}

.checklist li {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
}

.checklist li svg {
  width: 20px;
  height: 20px;
  flex: none;
  margin-top: 1px;
  color: var(--color-primary);
}

.checklist--spaced {
  margin-top: var(--sp-8);
}

/* ========================================================= 15. footer ==== */

.site-footer {
  position: relative;
  overflow: hidden;
  background: var(--brand-ink);
  color: #cfe3df;
  padding-top: clamp(3.5rem, 7vw, 6rem);
  isolation: isolate;
}

.site-footer::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(ellipse 70% 100% at 50% 0%, rgba(10, 178, 151, 0.16), transparent 62%);
}

/* The city line-art anchors the footer to the "reach across India" idea. */
.site-footer__scene {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: -1;
  width: 100%;
  opacity: 0.14;
  filter: invert(74%) sepia(46%) saturate(480%) hue-rotate(122deg) brightness(95%);
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 60%);
  mask-image: linear-gradient(180deg, transparent, #000 60%);
  pointer-events: none;
}

.footer-grid {
  display: grid;
  gap: clamp(2rem, 4vw, 3.5rem);
  grid-template-columns: minmax(260px, 1.4fr) repeat(3, minmax(140px, 1fr));
  padding-bottom: clamp(2.5rem, 5vw, 4rem);
}

/* This export is already the dark-background variant — teal dots, gold apex.
   It was being inverted to flat white, which threw the brand colours away on
   the one surface it was drawn for. */
.footer-brand img {
  height: clamp(52px, 5vw, 68px);
  width: auto;
  margin-bottom: var(--sp-5);
}

.footer-brand p {
  color: #9ab8b2;
  font-size: var(--fs-sm);
  line-height: var(--lh-body);
  max-width: 38ch;
}

.footer-col__title {
  font-family: var(--font-body);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--brand-teal-bright);
  margin-bottom: var(--sp-5);
}

.footer-col ul {
  display: grid;
  gap: var(--sp-3);
}

.footer-col a {
  font-size: var(--fs-sm);
  color: #9ab8b2;
  transition: color var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
  display: inline-block;
}

.footer-col a:hover {
  color: #ffffff;
  transform: translateX(3px);
}

.footer-socials {
  display: flex;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
}

/* place-items centres the glyph in the circle in both axes; the old version
   relied on the img's own box and sat a pixel high. */
.footer-socials a {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 1px solid rgba(150, 220, 208, 0.2);
  background: rgba(255, 255, 255, 0.04);
  color: #b9d4cf;
  transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out),
    background-color var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}

/* The brand glyphs are drawn edge-to-edge in their own viewBox, so they can
   fill much more of the circle than a padded icon would. */
.footer-socials svg {
  width: 24px;
  height: 24px;
  display: block;
}

.footer-socials a:hover {
  border-color: var(--brand-teal);
  background: rgba(10, 178, 151, 0.16);
  color: #ffffff;
  transform: translateY(-2px);
}

.footer-contact {
  display: grid;
  gap: var(--sp-4);
  font-size: var(--fs-sm);
  color: #9ab8b2;
}

.footer-contact a {
  color: inherit;
}

.footer-contact a:hover {
  color: #ffffff;
}

/* Each address on its own line; the pair joined by "/" stays together. */
.footer-mails {
  display: grid;
  gap: var(--sp-2);
  margin-top: var(--sp-2);
}

.footer-contact strong {
  display: block;
  color: #eaf5f2;
  font-weight: var(--fw-semibold);
}





/* Second footer row — addresses, people and app badges. Auto-fit rather than
   the fixed 4-column grid above, because these blocks vary in width. */
.footer-contacts {
  display: grid;
  gap: clamp(2rem, 4vw, 3.5rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  padding-block: clamp(2rem, 4vw, 3rem);
}

.rule--footer {
  opacity: 0.2;
}

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding-block: var(--sp-6);
  border-top: 1px solid rgba(150, 220, 208, 0.12);
  font-size: var(--fs-xs);
  color: #7e9b96;
}

.footer-bottom nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5);
}

.footer-bottom a:hover {
  color: #ffffff;
}

/* =========================================================== 27. app cta == */
/* Replaces the store badges: there is no listing on either store yet, and an
   official badge that does not lead to that store is both misleading and
   against the stores' own badge terms. */

.app-cta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
}

/* The footer copy of this is a supporting link in a narrow column, not a
   headline action — it takes a smaller pill, and the note below it keeps a
   clear gap of its own rather than crowding the button. */
.app-cta--compact .btn {
  --btn-py: 0.45rem;
  --btn-px: 0.9rem;
  font-size: 0.75rem;
}

.app-cta--compact .btn__icon {
  width: 0.85em;
  height: 0.85em;
}

.app-cta--compact {
  gap: var(--sp-2);
  margin-top: var(--sp-4);
}

/* Spacing only. The tinted-outline treatment that used to live here fought
   the tile it sits in — a bordered button inside a bordered card reads as a
   second frame rather than as an action. Colour now comes from .btn--primary,
   so this matches every other real action on the page. */
.contact__item .btn {
  margin-top: var(--sp-2);
}

.app-cta__note {
  /* Deliberately below --fs-xs: this is a footnote to the button above it,
     not a second message competing with it. Kept on one line so it reads as a
     single aside rather than a two-line paragraph — the 42ch cap that used to
     be here is what was breaking it. */
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--text-muted);
  max-width: none;
  white-space: nowrap;
}

/* Narrow columns cannot hold the full sentence; let it wrap rather than
   push the layout sideways. */
@media (max-width: 620px) {
  .app-cta__note {
    white-space: normal;
  }
}

.app-cta--compact {
  margin-top: var(--sp-3);
}
