/* ============================================================
   XQUBE GLOBAL — SERVICE 02 · MULTI-STATE TAX COMPLIANCE
   Page-specific styles only. The system lives in main.css.

   The page has one argument and it is spatial: a footprint is
   scattered across a map, and a scattered footprint is scattered
   calendars. The signature scene lights the states one at a time,
   then folds eight filing calendars into one.
   ============================================================ */

/* ---------- you are here ---------- */
.nav-links a.is-here { color: var(--text); }
.nav-links a.is-here::after { transform: scaleX(1); opacity: 0.55; }
.mobile-links a.is-here { color: var(--text); }
.mobile-links a.is-here .mono { color: var(--pink); }

/* ============================================================
   1 · THE TITLE SCENE
   ============================================================ */
.scene.svc-title { height: 200vh; }

.svc-title-block { max-width: 1040px; }
.svc-h1 {
  font-size: clamp(34px, 5.4vw, 76px);
  line-height: 1.06;
  letter-spacing: -0.028em;
  font-weight: 600;
  max-width: 17ch;
  margin: 0 auto;
  text-wrap: balance;
}
.svc-sub {
  margin: clamp(30px, 4.5vh, 52px) auto 0;
  max-width: 60ch;
  text-align: center;
}
@media (prefers-reduced-motion: no-preference) {
  .js .svc-title-stage .svc-sub {
    opacity: var(--subop, 0);
    transform: translateY(calc((1 - var(--subop, 0)) * 20px));
    transition: opacity 0.12s linear;
  }
}
.svc-index {
  display: flex; align-items: baseline; justify-content: center; gap: 12px;
  margin-top: clamp(30px, 4.5vh, 52px);
  font-size: 10.5px; letter-spacing: 0.26em;
  color: var(--faint);
}
.svc-index em {
  font-style: normal;
  font-size: 15px; letter-spacing: 0.1em;
  color: var(--purple-soft);
  text-shadow: 0 0 16px rgba(91, 76, 255, 0.6);
}

/* ============================================================
   2 · THE PROBLEM — a reading rest, unhurried
   ============================================================ */
.msx-head {
  font-size: 11px; letter-spacing: 0.22em; font-weight: 400;
  color: var(--faint);
  margin-bottom: clamp(28px, 4vh, 48px);
}
.msx-measure {
  max-width: 62ch;
  font-size: clamp(17.5px, 1.6vw, 21px);
  line-height: 1.85;
}
.msx-quote {
  margin-top: clamp(34px, 5vh, 58px);
  max-width: 32ch;
}

/* ============================================================
   3 · WHAT WE DO / WHAT CHANGES FOR YOU — rhymed panels
   ============================================================ */
.msx-panels {
  display: grid;
  grid-template-columns: 1.12fr 0.88fr;
  gap: clamp(20px, 2.6vw, 34px);
  align-items: stretch;
}
.msx-panel {
  position: relative;
  display: flex; flex-direction: column; gap: var(--s3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.09);
  padding: clamp(26px, 3vw, 44px);
  overflow: hidden;
  transition: border-color 0.4s ease, box-shadow 0.4s ease;
}
.msx-panel:hover {
  border-color: rgba(148, 138, 255, 0.42);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.09),
              0 20px 52px rgba(0, 0, 0, 0.45), 0 0 30px rgba(91, 76, 255, 0.1);
}
.msx-panel-head {
  font-size: 10.5px; letter-spacing: 0.22em; font-weight: 400;
  color: var(--faint);
  border-bottom: 1px solid var(--line);
  padding-bottom: var(--s2);
  margin-bottom: var(--s1);
}
.msx-panel-body { max-width: 56ch; }
.msx-panel-out {
  background:
    linear-gradient(180deg, rgba(91, 76, 255, 0.09), rgba(255, 255, 255, 0.018) 55%),
    var(--surface);
}
.msx-panel-out .msx-panel-head { color: var(--purple-soft); }
.msx-payoff {
  font-size: clamp(19px, 2.1vw, 26px);
  line-height: 1.5;
  letter-spacing: -0.016em;
  color: var(--text);
}
.msx-panel-rule {
  display: flex; align-items: center; gap: 14px;
  margin-top: auto;
  font-size: 12px; letter-spacing: 0.18em;
  color: var(--pink-soft);
}
.msx-panel-rule i {
  flex: 1; height: 1px;
  background: linear-gradient(90deg, var(--pink), var(--purple));
  box-shadow: 0 0 12px rgba(91, 76, 255, 0.45);
}
.msx-panel-rule span:last-child { color: var(--purple-soft); }

/* ============================================================
   4 · SIGNATURE DEVICE — the nexus map and the one calendar
   ============================================================ */
.scene.msx-scene { height: 460vh; }
.scene.msx-scene .msx-stage {
  justify-content: center;
  padding-top: calc(var(--nav-h) + var(--s3));
  padding-bottom: var(--s4);
}
.msx-stage-inner {
  position: relative; z-index: 2;
  width: 100%;
  max-width: 980px;
  margin: 0 auto;
}
/* the number-field is atmosphere here, not a layer to read through:
   a soft well of ground colour keeps the instrument legible */
.msx-stage::before {
  content: "";
  position: absolute; inset: 0;
  background:
    radial-gradient(62% 50% at 50% 52%, rgba(10, 10, 14, 0.9), rgba(10, 10, 14, 0.55) 55%, transparent 78%);
  pointer-events: none;
}

.msx-scene-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
  font-size: 10.5px; letter-spacing: 0.24em;
  color: var(--faint);
  border-bottom: 1px solid var(--line);
  padding-bottom: var(--s2);
  margin-bottom: var(--s3);
}
.msx-scene-label { color: var(--mist); }
.msx-scene-count em {
  font-style: normal;
  color: var(--purple-soft);
  text-shadow: 0 0 14px rgba(91, 76, 255, 0.6);
}

/* ---- the 50-state grid ---- */
/* the nexus map — a US map with the eight touched states pinned on it (the
   .usmap-* / .map-pin styles are global, in main.css). --mapdim still dims the
   whole thing as the calendars step forward in beat two. */
.msx-map { opacity: var(--mapdim, 1); }
.msx-map .usmap-plot { width: min(100%, 540px); margin: 0 auto; }

/* ---- eight calendars becoming one ---- */
.msx-cal-wrap {
  margin-top: clamp(20px, 3vh, 34px);
  opacity: var(--calin, 1);
  /* the block re-centres itself once the eight have folded away */
  transform: translateY(calc(var(--merge, 0) * 46px));
}
.msx-cal-head {
  display: grid;
  grid-template-columns: 120px repeat(12, 1fr);
  gap: 4px;
  padding: 0 12px;
  font-size: 9.5px; letter-spacing: 0.2em;
  color: var(--faint);
  margin-bottom: 10px;
  /* as the eight fold inward, the column header follows them down */
  transform: translateY(calc(var(--merge, 0) * 88px));
}
.msx-cal-head b { font-weight: 400; text-align: center; }

.msx-cals { position: relative; height: 250px; }
.msx-cal {
  position: absolute;
  left: 0; right: 0;
  top: calc(var(--i, 0) * 32px);
  height: 26px;
  display: grid;
  grid-template-columns: 120px repeat(12, 1fr);
  gap: 4px;
  align-items: center;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: rgba(255, 255, 255, 0.022);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
  transform: translate(calc((1 - var(--merge, 0)) * var(--sx, 0px)),
                       calc(var(--merge, 0) * var(--dy, 0px)));
  opacity: calc(1 - var(--merge, 0));
}
.msx-cal-lab {
  font-size: 9.5px; letter-spacing: 0.13em;
  color: var(--faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.msx-cal i {
  display: block;
  height: 11px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.055);
}
.msx-cal i.on {
  background: rgba(255, 77, 128, 0.6);
  box-shadow: 0 0 10px rgba(255, 77, 128, 0.35);
}
.msx-cal-one {
  /* the survivor gains weight as the other seven give theirs up */
  top: calc(112px - var(--merge, 0) * 8px);
  height: calc(26px + var(--merge, 0) * 16px);
  opacity: var(--merge, 0);
  border-color: rgba(148, 138, 255, 0.55);
  background: rgba(91, 76, 255, 0.09);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.09),
              0 12px 42px rgba(0, 0, 0, 0.45), 0 0 34px rgba(91, 76, 255, 0.18);
}
.msx-cal-one .msx-cal-lab { color: var(--purple-soft); letter-spacing: 0.2em; }
.msx-cal-one i.on {
  background: rgba(110, 96, 255, 0.85);
  box-shadow: 0 0 12px rgba(91, 76, 255, 0.6);
}

.msx-legend {
  position: relative;
  height: 14px;
  margin-top: 18px;
  font-size: 10px; letter-spacing: 0.22em;
  color: var(--faint);
  transform: translateY(calc(var(--merge, 0) * -104px));
}
.msx-legend span { position: absolute; left: 0; top: 0; white-space: nowrap; }
.msx-legend-a { opacity: calc(1 - var(--merge, 0)); }
.msx-legend-b { opacity: var(--merge, 0); color: var(--purple-soft); }

/* short desktop windows: scale the instrument rather than clip it */
@media (min-width: 981px) and (max-height: 760px) {
  .msx-stage-inner { transform: scale(0.84); transform-origin: 50% 50%; }
}

/* ============================================================
   5 · SCOPE OF WORK — the length is the argument
   ============================================================ */
.msx-scope-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
  border-bottom: 1px solid var(--line);
  padding-bottom: var(--s2);
  max-width: 920px;
}
.msx-scope-head .msx-head { margin-bottom: 0; }
.msx-scope-count {
  font-size: 10.5px; letter-spacing: 0.24em;
  color: var(--purple-soft);
  white-space: nowrap;
}
.msx-scope-list {
  list-style: none;
  margin: var(--s3) 0 0;
  padding: 0;
  max-width: 920px;
}
.msx-scope-item {
  display: grid;
  grid-template-columns: 54px 1fr 26px;
  gap: var(--s3);
  align-items: baseline;
  padding: var(--s3) 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.js .msx-scope-item {
  transition: opacity 0.75s cubic-bezier(0.22, 0.6, 0.2, 1),
              transform 0.75s cubic-bezier(0.22, 0.6, 0.2, 1),
              padding-left 0.35s cubic-bezier(0.3, 0.7, 0.3, 1),
              border-color 0.35s ease;
}
.msx-scope-item:hover {
  padding-left: 12px;
  border-bottom-color: rgba(148, 138, 255, 0.35);
}
.msx-scope-num {
  font-size: 11.5px; letter-spacing: 0.12em;
  color: var(--faint);
  transition: color 0.35s ease;
}
.msx-scope-item:hover .msx-scope-num { color: var(--purple-soft); }
.msx-scope-text {
  font-size: clamp(17px, 1.9vw, 22px);
  line-height: 1.45;
  letter-spacing: -0.012em;
  color: var(--text);
}
.msx-scope-tick {
  justify-self: end;
  font-size: 12px;
  color: rgba(148, 138, 255, 0.22);
  transition: color 0.6s ease 0.25s;
}
.msx-scope-item.in .msx-scope-tick { color: var(--purple-soft); }

/* ============================================================
   6 · QUESTIONS WE ASK — THE TRAVEL LOG

   Nexus is made by movement, so the four questions are not a list:
   they are stops on one continuous route. The rail ahead of the
   reader is dashed — an itinerary, not yet travelled. The ink
   behind is solid, laid down by the scroll, with a lit tip at the
   head of it. Each stop is a state code that flares as the tip
   arrives and hands its question out to the side of the line.
   Every code is one of the eight states lit on the nexus map
   earlier in the page, in travelling order.
   ============================================================ */
.scene.msx-route-scene { height: 400vh; }
.scene.msx-route-scene .msx-route-stage {
  justify-content: center;
  padding-top: calc(var(--nav-h) + var(--s3));
  padding-bottom: var(--s4);
}
.msx-route-stage::before {
  content: "";
  position: absolute; inset: 0;
  background: radial-gradient(66% 54% at 50% 50%, rgba(10, 10, 14, 0.88), rgba(10, 10, 14, 0.46) 58%, transparent 82%);
  pointer-events: none;
}
.msx-route-block {
  position: relative; z-index: 2;
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
}

/* ---- the log header, rhymed with the nexus scene's own head ---- */
.msx-route-top {
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
  border-bottom: 1px solid var(--line);
  padding-bottom: var(--s2);
  margin-bottom: clamp(22px, 4vh, 44px);
}
.msx-route-title {
  font-size: 11px; letter-spacing: 0.22em; font-weight: 400;
  color: var(--mist);
}
.msx-route-tally {
  display: flex; align-items: baseline; gap: 18px;
  font-size: 10.5px; letter-spacing: 0.24em;
  color: var(--faint);
  white-space: nowrap;
}
.msx-route-tally b { font-weight: 400; color: var(--pink-soft); }
.msx-route-tally em {
  font-style: normal;
  color: var(--purple-soft);
  text-shadow: 0 0 14px rgba(91, 76, 255, 0.6);
}

/* ---- the route itself ---- */
.msx-route {
  --railw: 76px;
  --railx: 50%;
  --rgap: clamp(18px, 2.2vw, 34px);
  --rowgap: clamp(24px, 5.6vh, 60px);
  --capH: 34px;
  position: relative;
}

/* the planned itinerary: dashed, waiting */
.msx-rail {
  position: absolute;
  left: var(--railx);
  top: calc(var(--capH) * 0.5);
  bottom: calc(var(--capH) * 0.5);
  width: 1px;
  margin-left: -0.5px;
  background-image: repeating-linear-gradient(180deg,
    rgba(255, 255, 255, 0.20) 0 4px, rgba(255, 255, 255, 0) 4px 10px);
}
/* the ink actually laid down — purple at the origin, pink at the head */
.msx-rail-ink {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, var(--purple), var(--pink));
  box-shadow: 0 0 14px rgba(91, 76, 255, 0.5);
  transform: scaleY(var(--draw, 1));
  transform-origin: 50% 0;
}
/* the head of the trace, with its crosshair */
.msx-rail-tip {
  position: absolute; left: 50%;
  top: calc(var(--draw, 1) * 100%);
  width: 9px; height: 9px;
  margin: -4.5px 0 0 -4.5px;
  border-radius: 50%;
  background: var(--pink);
  box-shadow: 0 0 18px 2px rgba(255, 77, 128, 0.5);
  opacity: var(--tipop, 0);
  transition: opacity 0.35s ease;
}
.msx-rail-tip::before {
  content: "";
  position: absolute; left: 50%; top: 50%;
  width: 36px; height: 1px;
  margin: 0 0 0 -18px;
  background: linear-gradient(90deg, transparent, rgba(255, 125, 161, 0.55), transparent);
}

/* ---- origin and terminus caps, sitting on the line ---- */
.msx-cap {
  position: relative;
  height: var(--capH);
  font-size: 9.5px; letter-spacing: 0.22em;
  color: var(--faint);
}
.msx-cap i {
  position: absolute; left: var(--railx); top: 50%;
  width: 7px; height: 7px;
  margin: -4px 0 0 -4px;
  border: 1px solid var(--line-strong);
  background: var(--bg);
  transform: rotate(45deg);
  transition: border-color 0.5s ease, background 0.5s ease, box-shadow 0.5s ease;
}
.msx-cap span {
  position: absolute; left: calc(var(--railx) + 17px); top: 50%;
  transform: translateY(-50%);
  white-space: nowrap;
  transition: color 0.5s ease;
}
.msx-cap-b i { transform: none; border-radius: 2px; }
.msx-cap-b.lit i {
  border-color: rgba(148, 138, 255, 0.75);
  background: rgba(91, 76, 255, 0.35);
  box-shadow: 0 0 18px rgba(91, 76, 255, 0.55);
}
.msx-cap-b.lit span { color: var(--purple-soft); }

/* ---- the stops ---- */
.msx-stops {
  list-style: none;
  margin: 0; padding: 0;
  display: flex; flex-direction: column;
  gap: var(--rowgap);
}
.msx-stop {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--railw) minmax(0, 1fr);
  column-gap: var(--rgap);
  align-items: center;
}
/* both cells are placed explicitly: a card on the left of the line comes
   after its node in source order, and sparse auto-placement would drop it
   into an implicit second row */
.msx-stop-node { grid-column: 2; grid-row: 1; justify-self: center; position: relative; }
.msx-node-code {
  display: block;
  min-width: 48px;
  padding: 5px 8px 4px;
  text-align: center;
  font-size: 11.5px; letter-spacing: 0.14em;
  color: var(--faint);
  border: 1px solid var(--line-strong);
  border-radius: 6px;
  background: rgba(10, 10, 14, 0.94);
  transition: color 0.5s ease, border-color 0.5s ease,
              background 0.5s ease, box-shadow 0.5s ease;
}
.msx-stop.lit .msx-node-code {
  color: #fff;
  border-color: rgba(255, 77, 128, 0.62);
  background: rgba(255, 77, 128, 0.13);
  box-shadow: 0 0 22px rgba(255, 77, 128, 0.34);
}
.msx-stop:hover .msx-node-code { border-color: rgba(255, 125, 161, 0.72); }
/* the arrival flare */
.msx-stop-node::after {
  content: "";
  position: absolute; inset: -7px;
  border: 1px solid rgba(255, 77, 128, 0.55);
  border-radius: 11px;
  opacity: 0;
  pointer-events: none;
}
@keyframes msx-ping {
  from { opacity: 0.85; transform: scale(0.7); }
  to   { opacity: 0;    transform: scale(1.45); }
}
@keyframes msx-tip {
  0%, 100% { box-shadow: 0 0 16px 2px rgba(255, 77, 128, 0.42); }
  50%      { box-shadow: 0 0 26px 5px rgba(255, 77, 128, 0.62); }
}

/* ---- the waypoint between two stops ---- */
.msx-leg {
  position: absolute;
  left: var(--railx);
  top: calc(var(--rowgap) * -0.5);
  transform: translate(-50%, -50%);
  padding: 3px 10px 2px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(10, 10, 14, 0.94);
  font-size: 9px; letter-spacing: 0.2em;
  color: rgba(135, 140, 156, 0.7);
  white-space: nowrap;
  transition: color 0.5s ease, border-color 0.5s ease,
              background 0.5s ease, box-shadow 0.5s ease;
}
.msx-leg.lit {
  color: var(--purple-soft);
  border-color: rgba(148, 138, 255, 0.5);
  background: rgba(91, 76, 255, 0.12);
  box-shadow: 0 0 18px rgba(91, 76, 255, 0.22);
}

/* ---- the question, handed out to the side of the line ---- */
.msx-stop-card { position: relative; grid-row: 1; max-width: 42ch; }
.msx-stop-l .msx-stop-card { grid-column: 1; justify-self: end; text-align: right; }
.msx-stop-r .msx-stop-card { grid-column: 3; justify-self: start; }
.msx-stop-card::before {
  content: "";
  position: absolute; top: 50%;
  width: var(--rgap); height: 1px;
  transform: scaleX(var(--branch, 1));
  transition: transform 0.6s cubic-bezier(0.22, 0.6, 0.2, 1) 0.08s;
  pointer-events: none;
}
.msx-stop-r .msx-stop-card::before {
  left: calc(var(--rgap) * -1);
  transform-origin: 0 50%;
  background: linear-gradient(90deg, rgba(255, 125, 161, 0.8), rgba(255, 255, 255, 0.12));
}
.msx-stop-l .msx-stop-card::before {
  right: calc(var(--rgap) * -1);
  transform-origin: 100% 50%;
  background: linear-gradient(270deg, rgba(255, 125, 161, 0.8), rgba(255, 255, 255, 0.12));
}
.msx-stop-ix {
  font-size: 10px; letter-spacing: 0.24em;
  color: var(--faint);
  margin-bottom: 8px;
}
.msx-stop.lit .msx-stop-ix { color: var(--pink-soft); }
.msx-stop-q {
  font-size: clamp(17px, 1.8vw, 24px);
  line-height: 1.36;
  letter-spacing: -0.014em;
  color: var(--mist);
  text-wrap: balance;
}

/* motion only: the questions ride in off the line as it reaches them */
@media (prefers-reduced-motion: no-preference) {
  .js .msx-stop { --branch: 0; }
  .js .msx-stop.lit { --branch: 1; }
  .js .msx-stop .msx-stop-ix,
  .js .msx-stop .msx-stop-q {
    opacity: 0.18;
    transition: opacity 0.7s ease, transform 0.7s cubic-bezier(0.22, 0.6, 0.2, 1), color 0.7s ease;
  }
  .js .msx-stop .msx-stop-q { transition-delay: 0.1s; }
  .js .msx-stop-r .msx-stop-ix,
  .js .msx-stop-r .msx-stop-q { transform: translateX(-14px); }
  .js .msx-stop-l .msx-stop-ix,
  .js .msx-stop-l .msx-stop-q { transform: translateX(14px); }
  .js .msx-stop.lit .msx-stop-ix,
  .js .msx-stop.lit .msx-stop-q { opacity: 1; transform: none; }
  .js .msx-stop.lit .msx-stop-q { color: var(--text); }
  .js .msx-stop.lit .msx-stop-node::after { animation: msx-ping 900ms cubic-bezier(0.2, 0.7, 0.3, 1) 1; }
  .js .msx-rail-tip { animation: msx-tip 2.4s ease-in-out infinite; }
}

/* short desktop windows: scale the route rather than clip it */
@media (min-width: 981px) and (max-height: 760px) {
  .msx-route-block { transform: scale(0.86); transform-origin: 50% 50%; }
}

/* ============================================================
   7 · NEXT
   ============================================================ */
.msx-next-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(44px, 6vw, 96px);
  align-items: start;
}
.msx-next-chips {
  display: flex; flex-wrap: wrap; gap: var(--s2);
  margin-top: var(--s5);
}
.msx-sib-cards { display: grid; gap: var(--s2); }
.msx-sib-cards .svc-card { min-height: 0; }

/* ============================================================
   STATICS — no-JS, reduced motion, and small screens all get the
   whole argument, laid out flat and fully lit.
   ============================================================ */
.no-js .msx-map,
.no-js .msx-cal-wrap { opacity: 1; }
.no-js .msx-map .map-pin .pin-dot { opacity: 1; transform: none; box-shadow: 0 0 14px rgba(255, 77, 128, 0.75); }
.no-js .msx-map .map-pin .pin-lbl { opacity: 1; color: var(--text); }
.no-js .msx-map .usmap-thread { stroke-dashoffset: 0; }
.no-js .msx-cals { position: static; height: auto; display: flex; flex-direction: column; gap: 6px; }
.no-js .msx-cal { position: static; top: auto; transform: none; opacity: 1; }
.no-js .msx-cal-one { margin-top: 12px; }
.no-js .msx-legend { position: static; height: auto; display: flex; flex-wrap: wrap; gap: 20px; }
.no-js .msx-legend span { position: static; opacity: 1; }

/* the route is fully travelled: every stop lit, every question read */
.no-js .msx-rail-ink { transform: none; }
.no-js .msx-rail-tip { display: none; }
.no-js .msx-node-code {
  color: #fff;
  border-color: rgba(255, 77, 128, 0.62);
  background: rgba(255, 77, 128, 0.13);
}
.no-js .msx-leg {
  color: var(--purple-soft);
  border-color: rgba(148, 138, 255, 0.5);
  background: rgba(91, 76, 255, 0.12);
}
.no-js .msx-stop-ix { color: var(--pink-soft); }
.no-js .msx-stop-q { color: var(--text); }
.no-js .msx-cap-b i {
  border-color: rgba(148, 138, 255, 0.75);
  background: rgba(91, 76, 255, 0.35);
}
.no-js .msx-cap-b span { color: var(--purple-soft); }

@media (prefers-reduced-motion: reduce) {
  .msx-map, .msx-cal-wrap { opacity: 1; }
  .msx-map .map-pin .pin-dot { opacity: 1; transform: none; box-shadow: 0 0 14px rgba(255, 77, 128, 0.75); }
  .msx-map .map-pin .pin-lbl { opacity: 1; color: var(--text); }
  .msx-map .usmap-thread { stroke-dashoffset: 0; }
  .msx-cals { position: static; height: auto; display: flex; flex-direction: column; gap: 6px; }
  .msx-cal { position: static; top: auto; transform: none; opacity: 1; }
  .msx-cal-one { margin-top: 12px; }
  .msx-legend { position: static; height: auto; display: flex; flex-wrap: wrap; gap: 20px; }
  .msx-legend span { position: static; opacity: 1; }
  .msx-stage-inner { transform: none; }
  .svc-sub { opacity: 1; transform: none; }

  /* the whole route is already travelled; nothing waits on scroll */
  .msx-route-block { transform: none; }
  .msx-rail-ink { transform: none; }
  .msx-rail-tip { display: none; }
  .msx-node-code {
    color: #fff;
    border-color: rgba(255, 77, 128, 0.62);
    background: rgba(255, 77, 128, 0.13);
  }
  .msx-leg {
    color: var(--purple-soft);
    border-color: rgba(148, 138, 255, 0.5);
    background: rgba(91, 76, 255, 0.12);
  }
  .msx-stop-ix { color: var(--pink-soft); }
  .msx-stop-q { color: var(--text); }
  .msx-cap-b i {
    border-color: rgba(148, 138, 255, 0.75);
    background: rgba(91, 76, 255, 0.35);
  }
  .msx-cap-b span { color: var(--purple-soft); }
}

@media (max-width: 980px) {
  /* The title and the travel log collapse into the flow. The NEXUS DEVICE
     does not: it keeps its pin, and is re-laid to fit a handset stage in
     "THE DEVICES, RUNNING ON A PHONE" further down this file. Its height
     and stage padding live there too, because the pin is only correct when
     the engine is up and motion is allowed. */
  .scene.svc-title { height: auto; }
  .scene.msx-route-scene { height: auto; }
  .scene.msx-route-scene .msx-route-stage {
    position: static;
    height: auto;
    overflow: visible;
    padding-top: var(--section-gap);
    padding-bottom: 0;
  }
  .msx-stage-inner { transform: none; }

  .svc-h1 { font-size: clamp(30px, 8vw, 44px); max-width: 100%; }
  .svc-sub { text-align: left; }
  .svc-index { justify-content: flex-start; }
  .svc-title-stage .ghost-center { display: none; }
  .svc-title-block { text-align: left; }

  .msx-panels { grid-template-columns: 1fr; }
  .msx-next-grid { grid-template-columns: 1fr; }

  /* the flat, fully-lit nexus device used to be hard-frozen here for every
     phone; it now lives under .js .scene.unfit, where it is the fit guard's
     fallback rather than the default. See below. */

  /* ---- the travel log unpins and runs down the left edge ---- */
  .msx-route-block { max-width: 100%; transform: none; }
  .msx-route {
    --railw: 54px;
    --railx: calc(var(--railw) / 2);
    --rgap: 18px;
    --rowgap: 30px;
    --capH: 30px;
  }
  .msx-stop { grid-template-columns: var(--railw) minmax(0, 1fr); column-gap: 0; }
  .msx-stop-node,
  .msx-stop-l .msx-stop-node,
  .msx-stop-r .msx-stop-node { grid-column: 1; justify-self: center; }
  .msx-stop-card,
  .msx-stop-l .msx-stop-card,
  .msx-stop-r .msx-stop-card {
    grid-column: 2;
    justify-self: stretch;
    text-align: left;
    max-width: 100%;
    padding-left: var(--rgap);
  }
  .msx-stop-card::before,
  .msx-stop-l .msx-stop-card::before,
  .msx-stop-r .msx-stop-card::before {
    left: 0; right: auto;
    transform-origin: 0 50%;
    background: linear-gradient(90deg, rgba(255, 125, 161, 0.8), rgba(255, 255, 255, 0.12));
  }
  .msx-leg { left: 0; transform: translateY(-50%); }

  /* the pre-lit, pre-inked travel log that used to be frozen here has moved
     to the .no-js / reduced-motion statics only — the route now travels on a
     phone. See "THE DEVICES, RUNNING ON A PHONE". */

  .msx-cal-head, .msx-cal { grid-template-columns: 92px repeat(12, 1fr); gap: 3px; padding: 0 8px; }
  .msx-cal-lab { font-size: 8.5px; letter-spacing: 0.08em; }
  .msx-scope-item { grid-template-columns: 40px 1fr 22px; gap: var(--s2); }
}

@media (max-width: 640px) {
  .msx-scene-head { flex-direction: column; align-items: flex-start; gap: 8px; font-size: 9.5px; letter-spacing: 0.2em; }
  .msx-map .usmap-plot { max-width: 400px; }
  .msx-map .pin-lbl { font-size: 8px; }
  .msx-cal-head, .msx-cal { grid-template-columns: 84px repeat(12, 1fr); gap: 2px; padding: 0 6px; }
  .msx-cal i { height: 10px; border-radius: 2px; }
  .msx-cal-lab { font-size: 8px; letter-spacing: 0.04em; }
  .msx-cal-one .msx-cal-lab { letter-spacing: 0.08em; }
  .msx-cal-head { font-size: 8px; letter-spacing: 0.1em; }

  .msx-route-top { flex-direction: column; align-items: flex-start; gap: 10px; }
  .msx-route-title { font-size: 9.5px; letter-spacing: 0.18em; }
  .msx-route-tally { font-size: 9.5px; letter-spacing: 0.2em; gap: 14px; }
  .msx-route { --railw: 46px; --rgap: 15px; --rowgap: 26px; }
  .msx-node-code { min-width: 42px; font-size: 10.5px; padding: 4px 6px 3px; }
  .msx-stop-q { font-size: 17px; }
  .msx-stop-ix { font-size: 9px; letter-spacing: 0.2em; margin-bottom: 6px; }
  .msx-leg { font-size: 8.5px; letter-spacing: 0.16em; padding: 3px 8px 2px; }
  .msx-cap { font-size: 8.5px; letter-spacing: 0.18em; }

  .msx-next-chips .chip-link { width: 100%; justify-content: center; }
  .cta-row .btn { width: 100%; justify-content: center; }
}


/* ============================================================
   THE DEVICES, RUNNING ON A PHONE

   Both signature scenes used to be switched off below 980px — the stages
   unpinned and every element hard-frozen at its finished value. The phone
   was handed the ANSWER to an argument it never watched being made: a
   fully-lit map, nine calendars where the point is that eight become one,
   both legends printed at once, and a route already travelled. The page
   argues in the present tense, so it has to run here too.

   Two different problems, so two different answers:

   THE NEXUS DEVICE keeps a real pin. It is the page's thesis and a scrubbed
   instrument needs a stage that holds still while it performs. Stacked the
   desktop way it is roughly 590px of instrument under a header, which no
   handset stage can hold — and js/main.js's fit guard measures UNTRANSFORMED
   boxes, so scaling the block down would not save it, it would still be
   flattened. So on a phone the map and the calendars share one grid cell and
   beat two becomes a cross-dissolve rather than a shift of attention: the map
   owns the stage while it lights, then hands the space straight over as the
   calendars come up. Every beat, every threshold and every custom property is
   the desktop one, untouched — only the arrangement moves, and only here.

   THE TRAVEL LOG stays unpinned. Four approved questions at 17px are ~700px
   of copy on a 390px screen; there is no honest size at which they fit one
   viewport, and a pinned stage that cannot fit is torn straight back off by
   the guard. Instead the trace is driven by the rail's own travel past the
   reader (js/service-multi-state-tax.js, msxRoute): the ink head rides the
   eye line, the stops light as they pass under it, the codes decode, the
   waypoints light, the terminus goes purple. Same moment, no pin.

   Everything below is inside max-width:980 AND requires motion — desktop is
   untouched, and reduced motion keeps the flat statics it already had.
   ============================================================ */
@keyframes msx-tip-ring {
  0%        { opacity: 0.55; transform: scale(1); }
  70%, 100% { opacity: 0;    transform: scale(2.2); }
}

@media (max-width: 980px) and (prefers-reduced-motion: no-preference) {

  /* ---- the nexus device: pinned, and re-laid to fit ---- */
  /* 300vh is 0.65 of the desktop 460vh — the same ratio main.css uses when it
     shortens its own scenes for a phone (270->170, 520->400). */
  .js .scene.msx-scene { height: 300vh; }
  .js .scene.msx-scene .msx-stage {
    /* clears the nav AND the service bar, which is open by the time the
       reader is this far down the page */
    padding-top: calc(var(--nav-h) + var(--s6));
    padding-bottom: var(--s3);
  }
  /* map and calendars into one cell: the stage then only has to hold the
     taller of the two (~300px) instead of their sum */
  .js .scene.msx-scene .msx-stage-inner {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
  }
  .js .scene.msx-scene .msx-scene-head {
    grid-column: 1; grid-row: 1;
    margin-bottom: var(--s2);
  }
  .js .scene.msx-scene .msx-map {
    grid-column: 1; grid-row: 2;
    align-self: center;
    /* sharing a cell, a map still sitting at 0.45 would read as noise under
       the row labels. The same variable drives it on the same clock, remapped
       so the dissolve finishes exactly where the desktop dim lands. Unset —
       engine down, scene not yet reached — this still resolves to 1. */
    opacity: calc((var(--mapdim, 1) - 0.45) / 0.55);
  }
  .js .scene.msx-scene .msx-cal-wrap {
    grid-column: 1; grid-row: 2;
    align-self: start;
    margin-top: 0;
  }
  .js .scene.msx-scene .msx-legend { margin-top: 12px; }

  /* ---- the travel log: travelling, not pre-lit ---- */
  /* NEVER STRAND THE QUESTIONS. The reveal above parks .msx-stop-q at
     opacity 0.18 until its stop lights, which is only safe once the trace has
     PROVEN it runs on this viewport. msxRoute adds .msx-live to .msx-route on
     the first frame it has real rail geometry; until then — engine down mid
     boot, rail not yet measurable, anything at all — the four questions and
     their branch lines are simply on. */
  .js .msx-route:not(.msx-live) .msx-stop-ix,
  .js .msx-route:not(.msx-live) .msx-stop-q { opacity: 1 !important; transform: none !important; }
  .js .msx-route:not(.msx-live) .msx-stop-card::before { transform: none !important; }

  /* the tip's pulse is a box-shadow keyframe: a repaint every frame it runs.
     Desktop absorbs it; here the tip is on screen for the whole section, so
     the pulse is re-cut as a ring the compositor moves for free. */
  .js .msx-rail-tip {
    animation: none;
    box-shadow: 0 0 14px 2px rgba(255, 77, 128, 0.45);
  }
  .js .msx-rail-tip::after {
    content: "";
    position: absolute; inset: -3px;
    border: 1px solid rgba(255, 77, 128, 0.6);
    border-radius: 50%;
    animation: msx-tip-ring 2.4s ease-out infinite;
    pointer-events: none;
  }
}

/* ============================================================
   THE FIT GUARD'S FALLBACK — the flat, fully-lit nexus device.
   These are the rules that used to run for every phone. They are the right
   answer only where the instrument genuinely cannot be staged: a short
   landscape handset, a 320px window, a viewport whose text has grown.
   js/main.js's measure() marks exactly those scenes .unfit and unpins them,
   so that is where they belong. The choreography keeps writing its custom
   properties; these simply out-rank them, the way main.css's own .unfit
   overrides do.
   ============================================================ */
.js .scene.unfit .msx-stage-inner { display: block; }
.js .scene.unfit .msx-map,
.js .scene.unfit .msx-cal-wrap { opacity: 1 !important; }
.js .scene.unfit .msx-cal-wrap { margin-top: clamp(20px, 3vh, 34px); transform: none; }
.js .scene.unfit .msx-cal-head { transform: none; }
.js .scene.unfit .msx-map .map-pin .pin-dot { opacity: 1; transform: none; box-shadow: 0 0 14px rgba(255, 77, 128, 0.75); }
.js .scene.unfit .msx-map .map-pin .pin-lbl { opacity: 1; color: var(--text); }
.js .scene.unfit .msx-map .usmap-thread { stroke-dashoffset: 0; }
.js .scene.unfit .msx-cals { position: static; height: auto; display: flex; flex-direction: column; gap: 6px; }
.js .scene.unfit .msx-cal {
  position: static; top: auto;
  transform: none !important;
  opacity: 1 !important;
}
.js .scene.unfit .msx-cal-one { margin-top: 12px; height: 26px; }
.js .scene.unfit .msx-legend {
  position: static; height: auto;
  display: flex; flex-wrap: wrap; gap: 18px;
  margin-top: 18px;
  transform: none;
}
.js .scene.unfit .msx-legend span { position: static; opacity: 1 !important; }


/* ============================================================
   GLASS, COSTED FOR A PHONE (page-scoped)
   css/main.css flattens its OWN glass components below 980px, but it cannot
   reach the devices this page declares. backdrop-filter re-blurs everything
   behind an element on every frame it moves, and these sit inside a
   scrolling film — it is the most expensive thing a handset does here.

   Blur removed below 980px. Where the surface was too sheer to survive
   without it (var(--surface) is 3.5% white) an opaque base is added as
   background-COLOR, not background, so any ruled gradient painted on top
   of it is left intact.
   ============================================================ */
@media (max-width: 980px) {
  .msx-panel {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background-color: var(--glass-flat);
  }
}

/* ============================================================
   THE RELATED-SERVICE CARD, PLACED EXPLICITLY
   css/main.css authors .svc-card for the HOMEPAGE card, which wraps the
   name and the tagline together in .svc-body — three in-flow children for
   a three-column grid. The cards here have FOUR (num, name, line, arrow),
   so auto-placement dropped the tagline into the third column and pushed
   the arrow onto its own row: the tagline rendered one word per line.
   Same fix already applied to services.html and case-studies.html; this
   container was the one that got missed.
   ============================================================ */
.msx-sib-cards .svc-card {
  grid-template-columns: 56px minmax(0, 1fr) auto;
  grid-template-areas:
    "num name arrow"
    "num line arrow";
  align-items: start;
  row-gap: 6px;
}
.msx-sib-cards .svc-num   { grid-area: num; }
.msx-sib-cards .svc-name  { grid-area: name; }
.msx-sib-cards .svc-line  { grid-area: line; }
.msx-sib-cards .svc-arrow { grid-area: arrow; align-self: center; justify-self: end; }
@media (max-width: 560px) {
  .msx-sib-cards .svc-card {
    grid-template-columns: 40px minmax(0, 1fr) auto;
    gap: 4px 12px;
    row-gap: 5px;
  }
  .msx-sib-cards .svc-arrow { align-self: start; margin-top: 2px; transform: none; }
}
