/* The module map on /plataforma/ — "el mapa del modelo operativo".

   The markup this file styles is GENERATED: scripts/plans.mjs
   renderModulesBlock() emits it at build time from the platform's
   published capability catalog, so nothing here may depend on how many
   clusters or tiles exist. The map is an interactive stage bar: seven
   milestone buttons (the six journey stages plus "Todo el recorrido")
   over one stage panel of half-width cluster cards, shown on hover or
   click. src/assets/modulos.js drives it; without that script every
   panel renders stacked and readable — the collapse is gated on the
   is-live class the script adds, never on the markup alone.

   Every colour pair below was measured against WCAG 1.4.3 before use:

     --ink   #0e0e1a on --canvas #fbfbfd  18.53:1   stop names
     --ink   #0e0e1a on --surface #fff    19.15:1   tile names, cluster names, hovered stops
     --muted #5b5b70 on --surface #fff     6.61:1   cluster intros
     --quiet #68687d on --canvas #fbfbfd   5.26:1   count label
     violet  #7c3aed on #f3eefd            5.01:1   index pills + tag pills (site tones)
     purple  #8b2fd6 on #f7eefd            5.35:1
     pink    #a21caf on #fbeefc            5.64:1
     blue    #1667d0 on #eaf3fe            4.83:1
     green   #0f7150 on #e8f7f0            5.43:1
     sky     #0e7490 on #e7f6fd            4.85:1
     lilac   #7c3aed on #ede7fb            4.73:1   the "whole journey" pills
     white on --dot-text gradients         5.36–6.32 the ACTIVE index pill, per tone
     white on #7c3aed / #8b2fd6            5.70 / 6.04  the active "whole journey" index
     gradient #7c3aed / #a21caf on canvas  5.51 / 6.12  the counter number */

/* The [hidden] guard: modulos.js collapses inactive panels with the
   hidden attribute, and [hidden] loses to any class rule that sets
   display — this keeps it winning no matter what lands on the panel. */
.modmap [hidden] {
  display: none !important;
}

/* ---------- the live counter ---------- */
.modmap-count {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  margin: var(--space-8) 0 0;
}

.modmap-count-number {
  background: linear-gradient(100deg, var(--grad-text-from), var(--grad-text-to));
  background-clip: text;
  color: transparent;
  font-size: var(--display-lg);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1;
}

.modmap-count-label {
  color: var(--quiet);
  font-size: var(--text-lg);
  font-weight: 600;
}

/* ---------- the stage bar ----------
   Seven milestone buttons on one drawn track. The bar is the page's real
   control: each stop is a genuine tab (role=tab, 44px+ hit target), and
   the pulse the site already taught rides the track to the active stop.
   On narrow screens the whole bar scrolls sideways inside itself — the
   rail keeps a min-width so the seven columns stay equal, which is what
   keeps the pulse's percentage positions truthful at every size. */
.modmap-bar {
  margin: var(--space-8) 0 0;
  overflow-x: auto;
}

.modmap-rail {
  position: relative;
  min-width: 640px;
  padding: 6px 2px 8px;
}

/* The track spans the first node's center to the last node's center:
   seven equal columns make each center sit half a column (100% / 14)
   from the edge, and the active-stop positions below interpolate in
   sixths of the remaining span. The gradient walks the same tone order
   as the stops, closing back on violet for the whole-journey stop. */
.modmap-track {
  position: absolute;
  top: 46.5px;
  right: calc(100% / 14);
  left: calc(100% / 14);
  display: block;
  height: 3px;
  border-radius: 999px;
  background: linear-gradient(90deg, #8b5cf6, #a855f7, #d946ef, #2380f2, #1d9a6c, #29b6f6, #8b5cf6);
}

/* The traveling pulse: an 11px dot whose center rides the 3px track.
   modulos.js moves it by flipping data-active on the root; the ~3.4s
   glide inside the 4s auto-advance beat is what makes the tour read as
   "the pulse walks, the stage follows". After the first interaction
   (is-manual) it snaps along faster so clicks feel answered. */
.modmap-pulse {
  position: absolute;
  top: 50%;
  left: 0%;
  z-index: 3;
  width: 11px;
  height: 11px;
  margin: -5.5px 0 0 -5.5px;
  border: 3px solid #7c3aed;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 12px rgb(124 58 237 / 55%);
  transition: left 3400ms cubic-bezier(0.45, 0, 0.55, 1);
}

.modmap[data-active="1"] .modmap-pulse {
  left: calc(100% / 6);
}

.modmap[data-active="2"] .modmap-pulse {
  left: calc(200% / 6);
}

.modmap[data-active="3"] .modmap-pulse {
  left: 50%;
}

.modmap[data-active="4"] .modmap-pulse {
  left: calc(400% / 6);
}

.modmap[data-active="5"] .modmap-pulse {
  left: calc(500% / 6);
}

.modmap[data-active="6"] .modmap-pulse {
  left: 100%;
}

.modmap.is-manual .modmap-pulse {
  transition-duration: 500ms;
}

.modmap-stops {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
}

/* One milestone button. The 46.5px track offset above is this button's
   node-center arithmetic: rail padding 6 + border 1 + padding 8 + the
   20px index pill + 6px gap + half the 14px node puts the node's center
   48px from the rail's top, and the 3px track centers on it. The two
   numbers were tuned together and must move together. */
.modmap-stop {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: var(--space-2) var(--space-2) var(--space-3);
  border: 1px solid transparent;
  border-radius: 14px;
  background: transparent;
  color: var(--ink);
  text-align: center;
  transition: border-color 160ms ease, background 160ms ease, box-shadow 160ms ease;
}

.modmap-stop:hover {
  border-color: var(--chip, #8b5cf6);
  background: var(--surface);
  box-shadow: 0 10px 24px -18px rgb(14 14 26 / 40%);
}

.modmap-stop.is-active {
  border-color: var(--line-strong);
  background: var(--surface);
  box-shadow: 0 14px 30px -22px rgb(14 14 26 / 45%);
}

.modmap-stop-index {
  display: inline-flex;
  height: 20px;
  align-items: center;
  justify-content: center;
  padding: 0 8px;
  border-radius: 999px;
  background: var(--pill-bg, #f3eefd);
  color: var(--pill-ink, #7c3aed);
  font-size: var(--text-3xs);
  font-weight: 800;
  letter-spacing: 0.1em;
}

/* White on the tone's --dot-text gradient measured 5.36–6.32 (site.css
   documents each pair); the whole-journey stop falls back to the violet
   pair, 5.70 / 6.04. */
.modmap-stop.is-active .modmap-stop-index {
  background: var(--dot-text, linear-gradient(120deg, #7c3aed, #8b2fd6));
  color: #fff;
}

.modmap-node {
  position: relative;
  width: 14px;
  height: 14px;
  border: 2px solid var(--surface);
  border-radius: 50%;
  background: var(--chip, #8b5cf6);
  box-shadow: 0 0 0 4px var(--pill-bg, #f3eefd);
}

.modmap-stop-name {
  max-width: 14ch;
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 700;
  line-height: 1.3;
}

/* The whole-journey stop: the lilac pill pair (4.73:1) and a node that
   spans the map's gradient instead of one stage tone. */
.modmap-stop.is-span {
  --pill-bg: #ede7fb;
  --pill-ink: #7c3aed;
}

.modmap-stop.is-span .modmap-node {
  background: linear-gradient(120deg, #8b5cf6, #29b6f6);
}

/* ---------- the stage panels ----------
   Without JS all seven render stacked (readable, crawlable); modulos.js
   adds is-live and hides all but the active one. The min-height damps
   the reflow between stages while the tour runs. */
.modmap-panels {
  margin-top: var(--space-6);
}

.modmap-panel + .modmap-panel {
  margin-top: var(--space-5);
}

.modmap.is-live .modmap-panel + .modmap-panel {
  margin-top: 0;
}

/* A damper, not a contract: measured at 1280px six of the seven stage
   panels sit at ~200-250px, so this floor keeps the strip below from
   bobbing while the tour walks them; only the whole-journey stop grows
   past it. */
.modmap.is-live .modmap-panels {
  min-height: 260px;
}

.modmap.is-live .modmap-panel {
  animation: modmap-panel-in 250ms cubic-bezier(0.33, 1, 0.68, 1) both;
}

@keyframes modmap-panel-in {
  from {
    opacity: 0;
    transform: translateY(10px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

/* Every cluster card is HALF the container, by the owner's rule: a pair
   fills the row, the whole-journey trio wraps two-and-one, and a lone
   cluster never sprawls across the full width. */
.modmap-panel-grid {
  display: grid;
  align-items: stretch;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-5);
}

/* A lone card slides under the stop that opened it — "justificado con el
   número" — while staying EXACTLY half the container. The half-width is
   the grid column itself, so the shift cannot touch it: the card sits in
   the left or right column and a transform nudges it toward its stop's
   center. A margin- or padding-based offset was tried first and rejected
   measurably — percentages in grid columns resolve against the box the
   margin just shrank, so the card narrowed as it moved (49% → 24% by the
   last stop). transform is paint-only and leaves layout alone.

   translateX percentages resolve against the CARD (half the container),
   so a container shift of D% is written as 2·D%. Stops 1-2 pin left,
   6-7 pin right; Factura centers exactly under its stop (50%), Pago
   shifts to put the card's center at its stop's 64.3%. Live only: the
   no-JS stacked view keeps every panel flush left. */
.modmap.is-live .modmap-panel.is-solo[data-modmap-panel="3"] .modmap-cluster {
  transform: translateX(50%);
}

.modmap.is-live .modmap-panel.is-solo[data-modmap-panel="4"] .modmap-cluster {
  grid-column: 2;
  transform: translateX(-22%);
}

.modmap.is-live .modmap-panel.is-solo[data-modmap-panel="5"] .modmap-cluster,
.modmap.is-live .modmap-panel.is-solo[data-modmap-panel="6"] .modmap-cluster {
  grid-column: 2;
}

/* ---------- cluster cards ---------- */
.modmap-cluster {
  /* The violet defaults every tone class overrides; spanning clusters
     (and unknown categories) keep them. */
  --tag-bg: #ede7fb;
  --tag-ink: #7c3aed;
  padding: var(--space-6);
  border: 1px solid var(--line-soft);
  border-radius: 18px;
  background: var(--surface);
  box-shadow: 0 24px 60px -44px rgb(14 14 26 / 30%);
}

.modmap-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0 0 var(--space-3);
}

.modmap-tag {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--pill-bg, var(--tag-bg));
  color: var(--pill-ink, var(--tag-ink));
  font-size: var(--text-3xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.modmap-tag::before {
  content: "";
  width: 6px;
  height: 6px;
  flex: none;
  border-radius: 50%;
  background: var(--chip, #8b5cf6);
}

/* Each tag pill carries its own stage tone class, so a cluster serving
   two stages shows both colours. The whole-journey pill spans the map's
   gradient instead of one stage. */
.modmap-tag.is-span {
  background: #ede7fb;
  color: #7c3aed;
}

.modmap-tag.is-span::before {
  background: linear-gradient(120deg, #8b5cf6, #29b6f6);
}

.modmap-cluster-name {
  margin: 0;
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--text-xl);
  font-weight: 700;
}

.modmap-cluster-intro {
  margin: var(--space-2) 0 0;
  color: var(--muted);
  font-size: var(--text-sm);
  line-height: 1.6;
}

/* ---------- module tiles ---------- */
.modmap-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: var(--space-2);
  margin: var(--space-5) 0 0;
  padding: 0;
  list-style: none;
}

.modmap-tile {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line-faint);
  border-radius: 12px;
  background: var(--surface-sunken);
  transition: transform 180ms ease, box-shadow 180ms ease, border-color 180ms ease, background 180ms ease;
}

.modmap-tile:hover {
  transform: translateY(-2px);
  border-color: var(--pill-bg, #ede7fb);
  background: var(--surface);
  box-shadow: 0 12px 26px -16px rgb(14 14 26 / 30%);
}

.modmap-tile-icon {
  display: flex;
  width: 28px;
  height: 28px;
  flex: none;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: var(--pill-bg, var(--tag-bg));
  color: var(--step, var(--tag-ink));
}

.modmap-tile-icon svg {
  width: 17px;
  height: 17px;
}

.modmap-tile-name {
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1.3;
}

/* ---------- responsive ----------
   The bar keeps its seven equal columns and scrolls inside itself on
   phones (the rail's min-width, never page overflow); modulos.js keeps
   the active stop scrolled into view. Panels and strip reflow on their
   own via auto-fit / flex-wrap. */
@media (max-width: 700px) {
  .modmap-count {
    flex-direction: column;
    gap: var(--space-1);
  }

  .modmap.is-live .modmap-panels {
    min-height: 0;
  }

}

/* ---------- reduced motion ----------
   modulos.js never auto-advances under reduced motion; here the pulse
   stops gliding (it jumps to the stop a person chose — an indicator,
   not an animation), the panel entrance snaps, and hover lifts park. */
@media (prefers-reduced-motion: reduce) {
  .modmap-pulse {
    transition: none;
  }

  .modmap-stop,
  .modmap-tile,

  .modmap-tile:hover,

  .modmap.is-live .modmap-panel {
    animation: none;
  }
}

/* Paper gets every panel, active or not, and no pulse. */
@media print {
  .modmap .modmap-panel[hidden] {
    display: block !important;
  }

  .modmap.is-live .modmap-panel + .modmap-panel {
    margin-top: var(--space-5);
  }

  .modmap-pulse {
    display: none;
  }
}
