/* ══════════════════════════════════════════════════════════════════
   THE WALL — LIVING UNIVERSE
   Constellation on desktop, honest stacked list on small screens.
   Positions are percentages of a 1536x1024 space, so the stage scales
   as one piece and the SVG wires stay attached to their nodes.
   ══════════════════════════════════════════════════════════════════ */
.uni {
  background:
    radial-gradient(ellipse 60% 45% at 50% 42%, #f4f6fd 0%, rgba(244,246,253,0) 70%),
    linear-gradient(180deg, var(--white), var(--cream));
  padding: 44px 20px 56px;
  overflow: hidden;
}
.uni-head { text-align: center; margin-bottom: 6px; }
.uni-word {
  font-family: var(--serif); font-size: 34px; font-weight: 600; letter-spacing: .22em;
  color: var(--navy); text-transform: uppercase;
}
.uni-word em { font-style: normal; color: var(--blue); }
.uni-kicker {
  font-size: 11px; letter-spacing: .3em; text-transform: uppercase;
  color: var(--muted); margin-top: 8px;
}
/* Who this page is for, in one sentence, before anything else. */
.uni-who {
  max-width: 640px; margin: 16px auto 0; padding: 12px 18px; border-radius: 12px;
  background: var(--white); border: 1px solid #e6ebf3;
  font-size: 14px; line-height: 1.6; color: var(--text);
}
.uni-who strong { color: var(--navy); }
.uni-who a { color: var(--blue); font-weight: 600; text-decoration: none; border-bottom: 1px solid var(--border-blue); }

/* How this page is ordered, stated rather than left to be guessed at. */
.uni-order { font-size: 12.5px; color: var(--muted); margin-top: 10px; }
.uni-order strong { color: var(--navy); font-weight: 600; }
.uni-order a { color: var(--blue); font-weight: 600; text-decoration: none; border-bottom: 1px solid var(--border-blue); }

/* A category the viewer actually works in. Marked, not shouted about. */
.uni-node.is-mine { border-color: var(--blue-soft); }
.uni-node.is-mine::after {
  content: ""; position: absolute; top: 9%; right: 9%;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--blue); box-shadow: 0 0 0 3px var(--white);
}
.uni-card-dist { color: var(--blue); font-weight: 700; }

/* ── Stage ───────────────────────────────────────────────────────── */
.uni-stage {
  position: relative;
  width: 100%; max-width: 1180px; margin: 6px auto 0;
  aspect-ratio: var(--uw) / var(--uh);
}
.uni-links { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.uni-wire {
  fill: none; stroke: #cdd7e6; stroke-width: 1.1;
  stroke-dasharray: 3 9; stroke-linecap: round;
  animation: uniFlow 3.4s linear infinite;
  transition: stroke .3s, opacity .3s;
}
.uni-wire-out { stroke-dasharray: 2 10; animation-duration: 4.6s; }
/* Each wire is drawn node to hub, so a shrinking offset walks the dashes
   along it in that direction: information flowing into the marketplace. */
@keyframes uniFlow { to { stroke-dashoffset: -48; } }

/* ── Hub ─────────────────────────────────────────────────────────── */
.uni-hub {
  position: absolute; transform: translate(-50%, -50%);
  width: 17.5%; aspect-ratio: 1; display: grid; place-items: center;
}
.uni-hub-ring {
  position: absolute; inset: -6%; border-radius: 50%;
  background: radial-gradient(circle, #fbfcff 0%, #f1f4fc 62%, rgba(241,244,252,0) 100%);
  border: 1px solid #e4e9f6;
  animation: uniPulse 5s ease-in-out infinite;
}
@keyframes uniPulse {
  0%, 100% { transform: scale(1);     box-shadow: 0 0 0 0 rgba(91,141,184,.10); }
  50%      { transform: scale(1.035); box-shadow: 0 0 0 16px rgba(91,141,184,0); }
}
.uni-hub-in { position: relative; text-align: center; padding: 4px; }
.uni-hub-name {
  display: block; font-family: var(--serif); font-size: clamp(15px, 1.9vw, 25px);
  letter-spacing: .13em; color: var(--navy); text-transform: uppercase; font-weight: 600;
}
.uni-hub-name em { font-style: normal; color: var(--blue); }
.uni-hub-count { display: block; font-size: clamp(9px, .82vw, 12px); color: var(--muted); margin-top: 5px; }
.uni-post {
  display: inline-flex; align-items: center; gap: 6px; margin-top: clamp(7px, 1.1vw, 14px);
  background: var(--navy); color: #fff; text-decoration: none;
  font-size: clamp(9px, .85vw, 12.5px); font-weight: 600;
  padding: clamp(6px,.75vw,10px) clamp(10px,1.25vw,18px); border-radius: 999px;
  transition: transform .25s, box-shadow .25s, background .25s;
}
.uni-post:hover { background: var(--blue); transform: translateY(-1px); box-shadow: var(--shadow-sm); }
/* A new ad entering the ecosystem: a ripple leaving the hub. */
.uni-post:active { animation: uniRipple .5s ease-out; }
@keyframes uniRipple {
  from { box-shadow: 0 0 0 0 rgba(91,141,184,.45); }
  to   { box-shadow: 0 0 0 42px rgba(91,141,184,0); }
}

/* ── Category nodes ──────────────────────────────────────────────── */
.uni-node {
  position: absolute; transform: translate(-50%, -50%);
  width: 11.2%; aspect-ratio: 1; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  background: var(--white); border: 1px solid #e6ebf3; text-decoration: none;
  box-shadow: 0 2px 10px rgba(30,58,95,.05);
  animation: uniDrift 9s ease-in-out infinite; animation-delay: var(--d);
  transition: box-shadow .3s, border-color .3s, background .3s, opacity .35s;
  z-index: 3;
}
/* Orbit is a few pixels: enough to feel alive, never enough to distract. */
@keyframes uniDrift {
  0%, 100% { translate: 0 0; }
  33%      { translate: 3px -4px; }
  66%      { translate: -3px 2px; }
}
.uni-node .uni-ico { color: var(--navy); width: 24%; height: auto; }
.uni-node-label {
  font-size: clamp(8px, .78vw, 11.5px); font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--navy);
}
.uni-node-count { font-size: clamp(7px, .68vw, 10.5px); color: var(--muted); }
/* A category with nothing in it: still there, so the shape holds, but it
   visibly has nothing to offer and does not pretend to be clickable. */
.uni-node.is-quiet { opacity: .5; box-shadow: none; cursor: default; animation: none; }
.uni-node.is-quiet .uni-ico { color: var(--muted); }
.uni-node.is-quiet .uni-node-label { color: var(--muted); }
.uni-node.is-quiet .uni-node-count { font-style: italic; }
.uni-node:hover, .uni-node:focus-visible, .uni-node.is-on {
  border-color: var(--blue); background: #fbfdff;
  box-shadow: 0 6px 20px rgba(91,141,184,.18);
}
.uni-node:hover .uni-ico, .uni-node.is-on .uni-ico { color: var(--blue); }

/* ── Service cards ───────────────────────────────────────────────── */
.uni-card {
  position: absolute; transform: translate(-50%, -50%);
  width: 25.4%; display: flex; gap: 10px; align-items: stretch;
  background: var(--white); border: 1px solid #e9edf4; border-radius: 14px;
  padding: 9px; text-decoration: none; overflow: hidden;
  box-shadow: 0 3px 14px rgba(30,58,95,.06);
  animation: uniFloat 11s ease-in-out infinite; animation-delay: var(--d);
  transition: box-shadow .35s, border-color .35s, opacity .35s;
  z-index: 4;
}
@keyframes uniFloat {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -5px; }
}
.uni-card-thumb {
  flex: 0 0 25%; border-radius: 9px; overflow: hidden; background: var(--blue-pale);
  display: grid; place-items: center; min-height: 60px;
}
.uni-card-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.uni-card-thumb.is-glyph .uni-ico { color: var(--blue); width: 46%; height: auto; }
.uni-card-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.uni-card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 7px; }
/* Two lines, not an ellipsis after four characters. At this width a single
   nowrap line cut "Gel manicure with nail art" down to "Gel manicu…", which
   tells a browsing provider nothing about the job. */
.uni-card-t {
  font-size: clamp(10px, .9vw, 13px); font-weight: 600; color: var(--navy);
  line-height: 1.28; overflow: hidden;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.uni-card-p { font-size: clamp(10px, .95vw, 14px); font-weight: 700; color: #6d5bd0; white-space: nowrap; }
/* A request has no price to show, so it carries a label instead of a number —
   never the customer's budget. */
.uni-card-p.is-want {
  font-size: clamp(8px, .7vw, 10.5px); font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--blue); background: var(--blue-pale); border-radius: 999px; padding: 2px 7px;
}
.uni-card-area, .uni-card-meta {
  font-size: clamp(8px, .72vw, 11px); color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.uni-card-meta { display: flex; gap: 5px; align-items: center; }
/* The action is always visible. It used to appear only on hover, which looks
   tidy and hides the one thing a first-time visitor needs to know: what
   clicking does. Hover still lifts the card and brightens the action. */
.uni-card-cta {
  font-size: clamp(8px, .72vw, 11px); font-weight: 700; color: var(--blue);
  margin-top: 3px; opacity: .85; transition: opacity .2s;
}
.uni-card:hover, .uni-card:focus-visible {
  border-color: var(--border-blue);
  box-shadow: 0 14px 34px rgba(30,58,95,.14);
  z-index: 6;
}
.uni-card:hover .uni-card-cta, .uni-card:focus-visible .uni-card-cta { opacity: 1; }

/* Category name inside the card. Desktop hides it — the branch node says it —
   but on a phone the constellation is a flat list and the card has to. */
.uni-card-cat {
  display: none; font-size: 10px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--blue); margin-bottom: 2px;
}

/* Focusing one branch brings it forward and lets the rest recede.
   JS adds .uni-focus to the stage and .is-lit to the branch. */
.uni-stage.uni-focus .uni-card,
.uni-stage.uni-focus .uni-node { opacity: .26; }
.uni-stage.uni-focus .uni-card.is-lit,
.uni-stage.uni-focus .uni-node.is-lit { opacity: 1; }
.uni-stage.uni-focus .uni-wire { opacity: .18; }
.uni-stage.uni-focus .uni-wire.is-lit { opacity: 1; stroke: var(--blue); }

/* ── Open slots: cards act, they do not navigate ──────────────────────
   A slot card wraps a form rather than being a link, because the whole
   point is one-click booking. It therefore needs its own hover lift —
   :hover on a div does not inherit the anchor rules above. */
.uni-card.uni-slot { cursor: default; }
.uni-slot-when { color: var(--navy); font-weight: 600; }
.uni-book { margin-top: 6px; }
.uni-book-btn {
  width: 100%; border: 1px solid var(--border-blue); background: var(--white);
  color: var(--blue); border-radius: 8px; cursor: pointer;
  font-size: clamp(8px, .72vw, 11.5px); font-weight: 700;
  padding: clamp(4px,.5vw,7px) 8px;
  transition: background .2s, color .2s, transform .2s;
}
.uni-card.uni-slot:hover .uni-book-btn { background: var(--blue); color: #fff; }
.uni-book-btn:hover { transform: translateY(-1px); }
.uni-card.uni-slot:hover {
  border-color: var(--border-blue);
  box-shadow: 0 14px 34px rgba(30,58,95,.14);
  z-index: 6;
}
.uni-flash { max-width: 620px; margin: 16px auto 0; }

/* ── Who has times open: the roster under the slot universe ───────── */
.uni-roster { max-width: 1020px; margin: 30px auto 0; }
.uni-roster-head { text-align: center; margin-bottom: 16px; }
.uni-roster-h { font-family: var(--serif); font-size: 24px; font-weight: 600; color: var(--navy); }
.uni-roster-sub { font-size: 13px; color: var(--muted); margin-top: 5px; }
.uni-roster-sub a { color: var(--blue); font-weight: 600; text-decoration: none; }
.uni-roster-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 10px;
}
.uni-prov {
  background: var(--white); border: 1px solid #e9edf4; border-radius: 14px; padding: 12px 14px;
  display: flex; flex-direction: column; gap: 9px;
  transition: border-color .2s, box-shadow .2s;
}
.uni-prov:hover { border-color: var(--border-blue); box-shadow: 0 6px 18px rgba(30,58,95,.08); }
.uni-prov.is-on { border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-pale); }
.uni-prov-id { display: flex; align-items: center; gap: 11px; text-decoration: none; min-width: 0; }
.uni-prov-logo {
  flex: 0 0 40px; width: 40px; height: 40px; border-radius: 11px; overflow: hidden;
  background: var(--blue-pale); color: var(--blue); font-weight: 700; font-size: 16px;
  display: grid; place-items: center;
}
.uni-prov-logo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.uni-prov-body { min-width: 0; }
.uni-prov-name { display: block; font-size: 14px; font-weight: 700; color: var(--navy); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uni-prov-meta { display: block; font-size: 12px; color: var(--muted); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uni-prov-meta b { color: var(--blue); }
.uni-prov-star { color: #e5bc4a; }
.uni-prov-n { color: var(--muted); }
.uni-prov-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; border-top: 1px solid var(--border); padding-top: 9px; }
.uni-prov-next { font-size: 12px; color: var(--muted); }
.uni-prov-next b { color: var(--navy); }
.uni-prov-cta {
  flex-shrink: 0; font-size: 12px; font-weight: 700; color: var(--blue); text-decoration: none;
  border: 1px solid var(--border-blue); border-radius: 999px; padding: 5px 12px;
  transition: background .2s, color .2s;
}
.uni-prov-cta:hover { background: var(--blue); color: #fff; }

/* ── Explore + stats ─────────────────────────────────────────────── */
.uni-explore { display: flex; justify-content: center; align-items: center; gap: 14px; margin-top: 22px; flex-wrap: wrap; }
.uni-explore-btn {
  display: inline-flex; align-items: center; gap: 9px;
  background: var(--white); border: 1px solid #e4e9f2; border-radius: 999px;
  padding: 13px 26px; font-size: 14px; font-weight: 600; color: var(--navy);
  text-decoration: none; box-shadow: 0 2px 10px rgba(30,58,95,.05);
  transition: transform .3s cubic-bezier(.2,.8,.3,1), box-shadow .3s, border-color .3s;
}
.uni-explore-btn:hover {
  transform: translateY(-2px) scale(1.015);
  box-shadow: 0 10px 26px rgba(30,58,95,.12); border-color: var(--border-blue);
}
.uni-explore-btn svg { color: var(--blue); }
.uni-explore-arrow { color: var(--muted); font-size: 19px; line-height: 1; transition: transform .3s; }
.uni-explore-btn:hover .uni-explore-arrow { transform: translateX(3px); }
.uni-clear { font-size: 13px; color: var(--muted); text-decoration: none; border-bottom: 1px solid var(--border); }
.uni-clear:hover { color: var(--blue); border-color: var(--blue); }

.uni-stats {
  display: flex; justify-content: center; flex-wrap: wrap; gap: 8px 46px;
  max-width: 820px; margin: 26px auto 0; padding: 18px 26px;
  background: var(--white); border: 1px solid #e9edf4; border-radius: 16px;
  box-shadow: 0 2px 12px rgba(30,58,95,.04);
}
.uni-stat { text-align: center; min-width: 96px; }
.uni-stat strong { display: block; font-family: var(--serif); font-size: 25px; font-weight: 600; color: var(--navy); line-height: 1; }
.uni-stat span { display: block; font-size: 11.5px; color: var(--muted); margin-top: 5px; }

.uni-foot { text-align: center; font-size: 12.5px; color: var(--muted); margin-top: 20px; line-height: 1.7; }
.uni-foot a { color: var(--blue); font-weight: 600; text-decoration: none; }

/* ── Small screens ───────────────────────────────────────────────────
   Polar positioning at phone width collapses into overlapping mush, so
   the same markup reflows: hub panel, a wrapping filter strip, a card
   stack. Nothing is hidden — it is the same content, laid out honestly. */
@media (max-width: 900px) {
  .uni { padding: 30px 16px 40px; }
  .uni-stage { aspect-ratio: auto; display: block; max-width: 560px; text-align: left; }
  .uni-links { display: none; }

  .uni-hub, .uni-node, .uni-card { position: static; transform: none; animation: none; }

  .uni-hub {
    width: 100%; aspect-ratio: auto; padding: 24px 18px; margin-bottom: 16px;
    border: 1px solid #e6ebf3; border-radius: 18px; background: var(--white);
  }
  .uni-hub-ring { display: none; }
  .uni-hub-name { font-size: 21px; }
  .uni-hub-count { font-size: 12.5px; }
  .uni-post { font-size: 13px; padding: 10px 18px; margin-top: 12px; }

  .uni-node {
    width: auto; aspect-ratio: auto; border-radius: 999px; flex-direction: row; gap: 7px;
    padding: 9px 14px; display: inline-flex; margin: 0 6px 8px 0; vertical-align: top;
  }
  .uni-node .uni-ico { width: 17px; }
  .uni-node-label { font-size: 11.5px; }
  .uni-node-count { font-size: 10.5px; }

  .uni-card { width: 100%; margin-top: 9px; }
  .uni-card-cat { display: block; }
  .uni-node.is-quiet { display: none; }   /* a quiet chip in a filter strip is just noise */
  .uni-who { font-size: 13.5px; padding: 11px 14px; }
  .uni-card-t, .uni-card-p { font-size: 14px; }
  .uni-card-p.is-want { font-size: 10px; }
  .uni-card-area, .uni-card-meta, .uni-card-cta { font-size: 12px; }
  .uni-card-cta { max-height: 20px; opacity: 1; margin-top: 3px; }
  .uni-card-thumb { flex: 0 0 78px; }

  .uni-stats { gap: 14px 26px; padding: 16px; }
  .uni-stat { min-width: 68px; }
  .uni-stat strong { font-size: 20px; }
}

/* ── Motion off ──────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .uni-wire, .uni-hub-ring, .uni-node, .uni-card { animation: none !important; }
  .uni-explore-btn, .uni-card, .uni-node, .uni-post { transition-duration: .01ms !important; }
}
