/* =============================================================
   Egcentral — Landing page styles
   Handwritten layer that sits on top of Tailwind.
   Only the things Tailwind is genuinely bad at live here:
   grain, marquees, reveal choreography, and a few hand-made bits.
   ============================================================= */

/* ---------- 1. Tokens ------------------------------------------------ */
:root {
  --ink-900: #0a1020;
  --ink-700: #1c2740;
  --ink-500: #4a5670;
  --ink-300: #8b95ab;

  --paper: #fbfaf7;
  --paper-2: #f4f2ed;

  --brand-600: #4f2ff0;
  --brand-500: #6244f5;
  --brand-400: #8a72fa;
  --brand-050: #efeaff;

  --saffron: #ff9d2e;
  --mint: #16b981;
  --coral: #f2545b;

  --edge: rgb(10 16 32 / 0.08);

  --shadow-sm: 0 1px 2px rgb(10 16 32 / .05), 0 1px 1px rgb(10 16 32 / .04);
  --shadow-md: 0 4px 6px -2px rgb(10 16 32 / .05), 0 12px 20px -6px rgb(10 16 32 / .10);
  --shadow-lg: 0 2px 4px rgb(10 16 32 / .04), 0 24px 48px -12px rgb(10 16 32 / .16);
  --shadow-brand: 0 10px 30px -10px rgb(79 47 240 / .45);
}

/* ---------- 2. Base -------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: 96px; /* clears the sticky header on anchor jumps */
}

body {
  background: var(--paper);
  color: var(--ink-900);
  font-feature-settings: "cv02", "cv03", "cv04", "cv11";
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

body.is-locked { overflow: hidden; }

::selection {
  background: var(--brand-500);
  color: #fff;
}

/* Tighter optical spacing on the big display type */
.display-tight {
  letter-spacing: -0.035em;
  line-height: 1.02;
}

/* ---------- 3. Paper grain + soft grid ------------------------------- */
/* Very low-opacity SVG noise. Kills the flat-gradient, stock-template look. */
.grain::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .38;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.32'/%3E%3C/svg%3E");
}

.dotgrid {
  background-image: radial-gradient(rgb(10 16 32 / .13) 1px, transparent 1px);
  background-size: 22px 22px;
}

.linegrid {
  background-image:
    linear-gradient(to right, rgb(10 16 32 / .05) 1px, transparent 1px),
    linear-gradient(to bottom, rgb(10 16 32 / .05) 1px, transparent 1px);
  background-size: 64px 64px;
}

/* Fades a decorative background out at the edges so it never fights content */
.mask-fade {
  -webkit-mask-image: radial-gradient(ellipse 70% 60% at 50% 40%, #000 40%, transparent 100%);
          mask-image: radial-gradient(ellipse 70% 60% at 50% 40%, #000 40%, transparent 100%);
}

.mask-sides {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
          mask-image: linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
}

/* ---------- 4. Type flourishes --------------------------------------- */
.text-gradient {
  background: linear-gradient(96deg, var(--brand-600) 0%, #8a5bff 42%, var(--saffron) 110%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
}

/* Hand-drawn underline that sits behind the word, slightly off-register.
   The wonkiness is deliberate — a perfect rectangle reads as generated. */
.pen-underline {
  position: relative;
  display: inline-block;
  white-space: nowrap;
}
.pen-underline > svg {
  position: absolute;
  left: -2%;
  bottom: -.28em;
  width: 104%;
  height: .42em;
  overflow: visible;
  pointer-events: none;
}
/* Resting state is DRAWN. The entrance animation replays it from empty via
   `backwards` fill. Doing it the other way round means a failed animation
   (or a stalled rAF) leaves the underline permanently invisible. */
.pen-underline > svg path {
  fill: none;
  stroke: var(--saffron);
  stroke-width: 6;
  stroke-linecap: round;
  stroke-dasharray: 640;
  stroke-dashoffset: 0;
}
.is-revealed .pen-underline > svg path,
.pen-underline.draw > svg path {
  animation: penDraw 1.1s cubic-bezier(.65, 0, .35, 1) .35s backwards;
}
@keyframes penDraw {
  from { stroke-dashoffset: 640; }
  to   { stroke-dashoffset: 0; }
}

/* Same idea for dark panels — brand-600 is too dark to read on ink-900. */
.text-gradient-light {
  background: linear-gradient(96deg, #a78bfa 0%, #c4b5fd 38%, var(--saffron) 105%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
}

.highlight-ink {
  background: linear-gradient(180deg, transparent 58%, rgb(255 157 46 / .38) 58%);
  padding-inline: .08em;
}

/* ---------- 5. Surfaces ---------------------------------------------- */
.card-hair {
  border: 1px solid var(--edge);
  background: #fff;
  box-shadow: var(--shadow-sm);
}

.glass {
  background: rgb(255 255 255 / .72);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
          backdrop-filter: saturate(180%) blur(14px);
  border: 1px solid rgb(255 255 255 / .6);
}

/* Gradient hairline border, masked so the fill stays transparent */
.border-sheen { position: relative; }
.border-sheen::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(140deg, rgb(98 68 245 / .55), rgb(255 157 46 / .35) 45%, rgb(10 16 32 / .06) 80%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
}

.lift {
  transition: transform .35s cubic-bezier(.2, .7, .3, 1), box-shadow .35s cubic-bezier(.2, .7, .3, 1);
  will-change: transform;
}
.lift:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}

/* ---------- 6. Buttons ----------------------------------------------- */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .55rem;
  font-weight: 600;
  letter-spacing: -.011em;
  border-radius: 999px;
  transition: transform .18s ease, box-shadow .25s ease, background-color .2s ease, color .2s ease, filter .2s ease;
  white-space: nowrap;
}
.btn:active { transform: translateY(1px) scale(.995); }

.btn-primary {
  background: var(--ink-900);
  color: #fff;
  box-shadow: 0 1px 0 rgb(255 255 255 / .12) inset, 0 8px 22px -8px rgb(10 16 32 / .55);
}
.btn-primary:hover {
  background: #131c33;
  box-shadow: 0 1px 0 rgb(255 255 255 / .14) inset, 0 14px 30px -10px rgb(10 16 32 / .6);
}

.btn-brand {
  background: linear-gradient(180deg, var(--brand-500), var(--brand-600));
  color: #fff;
  box-shadow: 0 1px 0 rgb(255 255 255 / .22) inset, var(--shadow-brand);
}
.btn-brand:hover { filter: brightness(1.07); }

.btn-ghost {
  background: #fff;
  color: var(--ink-900);
  border: 1px solid var(--edge);
  box-shadow: var(--shadow-sm);
}
.btn-ghost:hover { border-color: rgb(10 16 32 / .18); }

/* Shine sweep on the primary CTA — subtle, runs once on hover */
.btn-shine { overflow: hidden; }
.btn-shine::after {
  content: "";
  position: absolute;
  top: 0;
  left: -140%;
  width: 60%;
  height: 100%;
  background: linear-gradient(100deg, transparent, rgb(255 255 255 / .30), transparent);
  transform: skewX(-18deg);
  transition: left .65s cubic-bezier(.2, .7, .3, 1);
}
.btn-shine:hover::after { left: 150%; }

/* ---------- 7. Header ------------------------------------------------ */
.site-header {
  transition: background-color .3s ease, box-shadow .3s ease, border-color .3s ease;
}
.site-header.is-stuck {
  background: rgb(251 250 247 / .82);
  -webkit-backdrop-filter: saturate(180%) blur(16px);
          backdrop-filter: saturate(180%) blur(16px);
  border-bottom-color: var(--edge);
  box-shadow: 0 1px 0 rgb(10 16 32 / .04), 0 10px 30px -22px rgb(10 16 32 / .5);
}

/* Desktop dropdown */
.nav-item > .nav-panel {
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, 8px);
  transition: opacity .22s ease, transform .28s cubic-bezier(.2, .7, .3, 1), visibility .22s;
}
.nav-item:hover > .nav-panel,
.nav-item:focus-within > .nav-panel {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
}
.nav-link .chev { transition: transform .25s ease; }
.nav-item:hover .nav-link .chev { transform: rotate(180deg); }

/* Mobile drawer */
.drawer {
  transform: translateX(100%);
  transition: transform .42s cubic-bezier(.16, 1, .3, 1);
}
.drawer.is-open { transform: translateX(0); }
.drawer-backdrop {
  opacity: 0;
  pointer-events: none;
  transition: opacity .3s ease;
}
.drawer-backdrop.is-open {
  opacity: 1;
  pointer-events: auto;
}
.drawer.is-open .drawer-row {
  animation: drawerIn .5s cubic-bezier(.16, 1, .3, 1) backwards;
}
@keyframes drawerIn {
  from { opacity: 0; transform: translateX(18px); }
  to   { opacity: 1; transform: none; }
}

.burger span {
  display: block;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transition: transform .3s cubic-bezier(.2, .7, .3, 1), opacity .2s ease, width .3s ease;
}

/* ---------- 8. Marquee ----------------------------------------------- */
.marquee {
  display: flex;
  width: max-content;
  animation: marquee var(--marquee-duration, 46s) linear infinite;
}
.marquee--reverse { animation-direction: reverse; }
.marquee-wrap:hover .marquee { animation-play-state: paused; }
@keyframes marquee {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

/* ---------- 9. Scroll reveal ----------------------------------------- */
/* Gated on html.js, which main.js adds only once it has an observer running.
   If the script never runs — or throws — the content simply stays visible
   instead of being stranded at opacity 0. */
.js .reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .7s cubic-bezier(.2, .7, .3, 1), transform .7s cubic-bezier(.2, .7, .3, 1);
  transition-delay: var(--d, 0ms);
}
.js .reveal.is-revealed {
  opacity: 1;
  transform: none;
}

/* ---------- 10. Rate calculator -------------------------------------- */
.calc-tab.is-active {
  background: #fff;
  color: var(--ink-900);
  box-shadow: var(--shadow-sm);
}

.rate-row { animation: rateIn .45s cubic-bezier(.16, 1, .3, 1) backwards; }
@keyframes rateIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

.field input,
.field select {
  transition: border-color .2s ease, box-shadow .2s ease, background-color .2s ease;
}
.field input:focus,
.field select:focus {
  outline: none;
  border-color: var(--brand-400);
  box-shadow: 0 0 0 4px rgb(98 68 245 / .13);
}
.field input.is-error,
.field select.is-error {
  border-color: var(--coral);
  box-shadow: 0 0 0 4px rgb(242 84 91 / .12);
}

/* Number spinners look cheap in a pricing widget */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

/* ---------- 11. Tabs / segmented ------------------------------------- */
.seg-btn { transition: color .22s ease; }
.seg-btn.is-active { color: #fff; }
.seg-pill { transition: transform .38s cubic-bezier(.2, .7, .3, 1), width .38s cubic-bezier(.2, .7, .3, 1); }

.panel { display: none; }
.panel.is-active {
  display: block;
  animation: panelIn .45s cubic-bezier(.16, 1, .3, 1);
}
@keyframes panelIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* ---------- 12. Accordion -------------------------------------------- */
.faq-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .38s cubic-bezier(.2, .7, .3, 1);
}
.faq-body > div { overflow: hidden; }
.faq-item.is-open .faq-body { grid-template-rows: 1fr; }
.faq-item.is-open .faq-plus { transform: rotate(45deg); }
.faq-plus { transition: transform .3s cubic-bezier(.2, .7, .3, 1); }

/* ---------- 13. Testimonials ----------------------------------------- */
.rail {
  scrollbar-width: none;
  -ms-overflow-style: none;
  scroll-snap-type: x mandatory;
}
.rail::-webkit-scrollbar { display: none; }
.rail > * { scroll-snap-align: start; }


/* ---------- 14. Dashboard mock --------------------------------------- */
.mock-shadow {
  box-shadow:
    0 2px 6px rgb(10 16 32 / .06),
    0 18px 40px -14px rgb(10 16 32 / .22),
    0 60px 90px -50px rgb(79 47 240 / .55);
}

/* Same rule as the pen underline: the chart is content, so its resting
   state must be "fully drawn", never "empty waiting for an animation". */
.spark path {
  stroke-dasharray: 1200;
  stroke-dashoffset: 0;
}
.is-revealed .spark path { animation: sparkDraw 1.6s cubic-bezier(.4, 0, .2, 1) .2s backwards; }
@keyframes sparkDraw {
  from { stroke-dashoffset: 1200; }
  to   { stroke-dashoffset: 0; }
}

.bar-grow { transform-origin: bottom; }
.is-revealed .bar-grow { animation: barGrow .8s cubic-bezier(.16, 1, .3, 1) backwards; }
@keyframes barGrow { from { transform: scaleY(.04); opacity: .3; } }

/* Dashed route line in the how-it-works band */
.route-dash {
  stroke-dasharray: 8 10;
  animation: routeMove 1.6s linear infinite;
}
@keyframes routeMove { to { stroke-dashoffset: -36; } }

/* ---------- 15. Pricing ---------------------------------------------- */
.plan-featured {
  background:
    radial-gradient(120% 120% at 50% -10%, rgb(138 114 250 / .22), transparent 60%),
    var(--ink-900);
}

/* ---------- 16. Misc ------------------------------------------------- */
.to-top {
  opacity: 0;
  transform: translateY(12px) scale(.9);
  pointer-events: none;
  transition: opacity .3s ease, transform .35s cubic-bezier(.2, .7, .3, 1);
}
.to-top.is-visible {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

.pulse-dot { position: relative; }
.pulse-dot::before {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: 999px;
  background: currentColor;
  opacity: .35;
  animation: pulseRing 2.2s cubic-bezier(.4, 0, .6, 1) infinite;
}
@keyframes pulseRing {
  0%   { transform: scale(.6); opacity: .5; }
  70%  { transform: scale(1.5); opacity: 0; }
  100% { transform: scale(1.5); opacity: 0; }
}

.float-slow { animation: floatY 7s ease-in-out infinite; }
.float-slower { animation: floatY 9.5s ease-in-out infinite reverse; }
@keyframes floatY {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-12px); }
}

/* Focus ring for keyboard users only */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--brand-500);
  outline-offset: 3px;
  border-radius: 6px;
}

/* ---------- 19. Scroll progress -------------------------------------- */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 60;
  height: 3px;
  width: 0;
  border-radius: 0 3px 3px 0;
  background: linear-gradient(90deg, var(--brand-600), #8a5bff 45%, var(--saffron));
  box-shadow: 0 0 14px rgb(98 68 245 / .55);
}

/* ---------- 20. Aurora mesh ------------------------------------------ */
/* Slow-drifting colour fields. Three blobs on different periods never line
   up the same way twice, which stops it reading as a static gradient. */
.aurora { position: absolute; inset: 0; overflow: hidden; }
.aurora i {
  position: absolute;
  display: block;
  border-radius: 999px;
  filter: blur(88px);
  opacity: .68;
  will-change: transform;
}
.aurora .a1 {
  top: -16%; left: -12%;
  width: 44rem; height: 44rem;
  background: radial-gradient(circle at 30% 30%, #7c5cff, transparent 68%);
  animation: drift1 26s ease-in-out infinite;
}
.aurora .a2 {
  top: -6%; right: -14%;
  width: 38rem; height: 38rem;
  background: radial-gradient(circle at 60% 40%, #ffb45c, transparent 66%);
  animation: drift2 32s ease-in-out infinite;
}
.aurora .a3 {
  bottom: -28%; left: 26%;
  width: 40rem; height: 40rem;
  background: radial-gradient(circle at 50% 50%, #3ecf9a, transparent 68%);
  opacity: .4;
  animation: drift3 38s ease-in-out infinite;
}
@keyframes drift1 {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(7%, 5%, 0) scale(1.12); }
}
@keyframes drift2 {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1.06); }
  50%      { transform: translate3d(-8%, 7%, 0) scale(.94); }
}
@keyframes drift3 {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(6%, -6%, 0) scale(1.15); }
}

/* ---------- 21. Cursor spotlight ------------------------------------- */
/* main.js writes --mx/--my per card; the glow tracks the pointer. */
.spot { position: relative; isolation: isolate; }
.spot::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  opacity: 0;
  pointer-events: none;
  transition: opacity .4s ease;
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 50%),
              rgb(98 68 245 / .13), transparent 62%);
}
.spot:hover::after { opacity: 1; }

.spot-dark::after {
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 50%),
              rgb(160 130 255 / .20), transparent 62%);
}

/* ---------- 22. Animated gradient border ----------------------------- */
@property --angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

/* A z-index:-1 pseudo-element paints ABOVE its own parent's background (only
   below the in-flow content), so it would wash the whole card. Mask the fill
   down to the border strip instead — same trick as .border-sheen. */
.ring-spin { position: relative; }
.ring-spin::before {
  content: "";
  position: absolute;
  inset: -1.5px;
  border-radius: inherit;
  padding: 1.5px;
  pointer-events: none;
  background: conic-gradient(from var(--angle, 0deg),
              transparent 0deg, var(--brand-400) 55deg,
              var(--saffron) 125deg, transparent 205deg, transparent 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  animation: ringSpin 6s linear infinite;
}
@keyframes ringSpin { to { --angle: 360deg; } }

/* Without @property the angle can't animate; the ring just sits static,
   which still reads as an accent border. Rotating instead would spin the
   mask along with it and break the shape. */
@supports not (background: conic-gradient(from var(--a, 0deg), red, blue)) {
  .ring-spin::before { animation: none; }
}

/* ---------- 23. Network coverage map --------------------------------- */
/* The panel goes single-column below lg, which would stretch the map very
   wide and blow the label sizes up with it. Cap the width, then compensate
   on phones where the shrunken viewBox makes 11.5 user units unreadable. */
.netmap svg { display: block; margin-inline: auto; max-width: 480px; }
@media (min-width: 1024px) { .netmap svg { max-width: none; } }
@media (max-width: 640px)  { .netmap text { font-size: 15px; } }

.netmap .arc-base {
  fill: none;
  stroke: rgb(255 255 255 / .2);
  stroke-width: 1.3;
}
.netmap .arc-flow {
  fill: none;
  stroke: url(#arcGrad);
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-dasharray: 12 230;
  animation: arcFlow 3.4s linear infinite;
}
@keyframes arcFlow {
  from { stroke-dashoffset: 237; }
  to   { stroke-dashoffset: 0; }
}

.netmap .hub-ring {
  transform-origin: center;
  transform-box: fill-box;
  animation: hubPulse 2.6s cubic-bezier(.4, 0, .6, 1) infinite;
}
@keyframes hubPulse {
  0%   { transform: scale(.5); opacity: .6; }
  75%  { transform: scale(2.7); opacity: 0; }
  100% { transform: scale(2.7); opacity: 0; }
}

/* ---------- 24. Type + accents --------------------------------------- */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  border-radius: 999px;
  padding: .38rem .85rem;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-700);
  background: rgb(255 255 255 / .75);
  border: 1px solid var(--edge);
  box-shadow: 0 1px 2px rgb(10 16 32 / .04);
  -webkit-backdrop-filter: blur(8px);
          backdrop-filter: blur(8px);
}
.eyebrow-dark {
  color: rgb(255 255 255 / .82);
  background: rgb(255 255 255 / .07);
  border-color: rgb(255 255 255 / .14);
}

/* Oversized quotation mark sitting behind testimonial copy */
.quote-mark {
  position: absolute;
  top: .5rem;
  right: 1.1rem;
  font-family: "Instrument Serif", Georgia, serif;
  font-size: 92px;
  line-height: 1;
  color: rgb(10 16 32 / .07);
  pointer-events: none;
  user-select: none;
}
.quote-mark-light { color: rgb(255 255 255 / .12); }

/* Coloured hairline across the top edge of a card */
.top-accent { position: relative; }
.top-accent::before {
  content: "";
  position: absolute;
  top: 0;
  left: 14%;
  right: 14%;
  height: 2px;
  border-radius: 0 0 2px 2px;
  background: linear-gradient(90deg, transparent, var(--accent, var(--brand-500)), transparent);
}

/* ---------- 25. Icon tiles ------------------------------------------- */
.icon-tile {
  position: relative;
  display: grid;
  place-items: center;
  transition: transform .35s cubic-bezier(.2, .7, .3, 1);
}
.icon-tile::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .35);
  pointer-events: none;
}
.lift:hover .icon-tile,
.spot:hover .icon-tile { transform: translateY(-2px) rotate(-5deg); }

/* ---------- 26. Button glow ------------------------------------------ */
.btn-brand { isolation: isolate; }
.btn-brand::before {
  content: "";
  position: absolute;
  inset: -2px;
  z-index: -1;
  border-radius: inherit;
  background: linear-gradient(120deg, var(--brand-400), var(--saffron));
  opacity: 0;
  filter: blur(11px);
  transition: opacity .35s ease;
}
.btn-brand:hover::before { opacity: .8; }

/* ---------- 17. Reduced motion --------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .js .reveal { opacity: 1 !important; transform: none !important; }
  .marquee { animation: none !important; }
  .aurora i,
  .netmap .arc-flow,
  .netmap .hub-ring,
  .ring-spin::before { animation: none !important; }
  .netmap .arc-flow { stroke-dasharray: none; }
}

/* ---------- 18. Print ------------------------------------------------ */
@media print {
  .site-header, .to-top, .drawer, .drawer-backdrop, .marquee-wrap { display: none !important; }
  body { background: #fff; }
}
