/* ======== About · the skill constellation ========
   Two separate skies — the work, the field — that converge on one line.
   Stars sit at authored coordinates; hovering one lights it, expands its
   note, and (for field stars) washes a photo in behind the whole sky. */

.constellation {
  padding: clamp(40px, 7vw, 96px) clamp(20px, 6vw, 80px) clamp(30px, 5vw, 60px);
}

/* the section needs a name, or the star field reads as decoration */
.const-head {
  max-width: 1100px;
  margin: 0 auto clamp(28px, 5vw, 56px);
}

.const-title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.6rem, 3.4vw, 2.5rem);
  line-height: 1.12;
  color: var(--text);
  max-width: 20ch;
}

.const-title em { font-style: italic; color: var(--rose); }

.const-stage {
  position: relative;
  max-width: 1100px;
  margin: 0 auto;
  /* taller than it was: every note is now permanently visible, so each star
     occupies roughly half again the height it used to */
  min-height: clamp(480px, 62vh, 700px);
  isolation: isolate;
}

/* ---- the joins between stars. Drawn under the stars, over the wash. ---- */
.const-lines {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}

.const-lines polyline {
  fill: none;
  /* a hairline, and deliberately fainter than the dust is dark. Joins on a
     real chart are an annotation over the sky, not the structure of it: at
     full --line weight they turned the whole section into a flowchart. */
  stroke: rgba(28, 31, 26, 0.14);
  stroke-width: 0.75;
  stroke-linejoin: round;
  /* the viewBox is stretched by preserveAspectRatio="none", which would smear
     the stroke to a different weight on each axis without this */
  vector-effect: non-scaling-stroke;
  transition: stroke 0.5s ease;
}

.const-stage.is-lit .const-lines polyline { stroke: rgba(122, 82, 20, 0.26); }

/* ---- the unnamed field ----
   An engraved celestial chart, not a night sky: the ground is paper, so the
   dust is INK at low alpha rather than white. This is what stops the named
   stars reading as nodes in a diagram. Positions and sizes come from an
   authored table in about.js. */
.const-dust {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.const-dust i {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--s);
  height: var(--s);
  margin: calc(var(--s) / -2) 0 0 calc(var(--s) / -2);
  border-radius: 50%;
  background: var(--text);
  opacity: var(--o);
  transition: opacity 0.6s ease;
}

/* the sky recedes a touch while a star is lit, so the lit one carries it */
.const-stage.is-lit .const-dust { opacity: 0.55; }

/* ---- the photo wash: atmosphere, not a gallery ---- */
.const-wash {
  position: absolute;
  inset: -6% -3%;
  z-index: 0;
  border-radius: 28px;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  opacity: 0;
  filter: saturate(0.9);
  transition: opacity 0.75s ease, transform 1.2s var(--ease-pen);
  transform: scale(1.03);
  pointer-events: none;
  /* fade the photo out at the edges so it reads as atmosphere */
  -webkit-mask-image: radial-gradient(72% 68% at 50% 50%, #000 38%, transparent 78%);
  mask-image: radial-gradient(72% 68% at 50% 50%, #000 38%, transparent 78%);
}

.const-stage.is-washed .const-wash {
  opacity: 0.3;
  transform: scale(1);
}

/* ---- the divide between the two skies ---- */
.const-split {
  position: absolute;
  left: 50%;
  top: 4%;
  bottom: 4%;
  width: 1px;
  z-index: 1;
  background: linear-gradient(to bottom, transparent, var(--line) 18%, var(--line) 82%, transparent);
  pointer-events: none;
}

/* ---- sky labels ---- */
.const-sky {
  position: absolute;
  top: -6px;
  z-index: 2;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.68rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--muted);
  pointer-events: none;
}

.const-sky--work  { left: 2%; }
.const-sky--field { right: 2%; }

/* ---- a star ---- */
.c-star {
  position: absolute;
  left: var(--x);
  top: var(--y);
  transform: translate(-50%, -50%);
  z-index: 3;
  display: grid;
  justify-items: center;
  gap: 7px;
  padding: 10px 14px;
  width: max-content;
  max-width: 46vw;
  background: none;
  border: 0;
  border-radius: 14px;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-align: center;
  transition: transform 0.45s var(--ease-pen);
}

.c-mark {
  display: block;
  color: var(--muted);
  line-height: 0;
  transition: color 0.4s ease, transform 0.5s var(--ease-pen), filter 0.4s ease;
}

/* heritage.js injects the star with width/height attrs — CSS overrides them.
   --mag is each star's magnitude, set inline per star: a chart where every
   star is identical in size is a diagram, not a sky. */
.c-mark svg {
  width: calc(22px * var(--mag, 1));
  height: calc(22px * var(--mag, 1));
  display: block;
}

.c-name {
  font-family: var(--font-display);
  font-size: clamp(1rem, 1.5vw, 1.22rem);
  line-height: 1.15;
  color: var(--text);
  white-space: nowrap;
  transition: color 0.35s ease;
}

/* the note stays collapsed until the star is lit */
.c-note {
  font-family: var(--font-body);
  font-size: 0.64rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  white-space: nowrap;
  /* Always legible. The note used to be collapsed until hover, which hid real
     information from touch devices and from anyone scanning the page. The
     hover reward now lives in the brightness step below, plus the photo wash
     and the dimming of every other star. */
  opacity: 0.6;
  transition: opacity 0.4s ease;
}

/* ---- lit state ---- */
.c-star:hover,
.c-star:focus-visible {
  outline: none;
  transform: translate(-50%, -50%) scale(1.06);
}

.c-star:hover .c-mark,
.c-star:focus-visible .c-mark {
  color: var(--accent);
  transform: rotate(14deg) scale(1.28);
  filter: drop-shadow(0 0 12px var(--accent-soft));
}

.c-star:hover .c-note,
.c-star:focus-visible .c-note { opacity: 1; }

.c-star:focus-visible .c-name { color: var(--accent); }

/* dim the rest of the sky so the lit star carries the moment */
.const-stage.is-lit .c-star:not(:hover):not(:focus-visible) {
  opacity: 0.42;
  transition: opacity 0.5s ease;
}

/* ---- the convergence ---- */
.const-converge {
  max-width: 1100px;
  margin: clamp(26px, 4vw, 48px) auto 0;
  text-align: center;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3.4vw, 2.4rem);
  line-height: 1.2;
  color: var(--text);
}

.const-converge em { font-style: italic; color: var(--accent); }

/* ---- small screens: drop the sky, flow as two readable columns ---- */
@media (max-width: 720px) {
  .const-stage {
    min-height: 0;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 22px 14px;
    padding-top: 34px;
  }
  .const-split,
  .const-lines,
  .const-dust,
  .const-wash { display: none; }

  .const-sky {
    position: static;
    grid-column: span 1;
    align-self: end;
  }

  .c-star {
    position: static;
    transform: none;
    justify-items: start;
    text-align: left;
    max-width: none;
    padding: 6px 0;
  }
  .c-star:hover,
  .c-star:focus-visible { transform: none; }

  /* on touch there is no hover, so the notes sit at full strength */
  .c-note { opacity: 1; }
  .const-stage.is-lit .c-star:not(:hover) { opacity: 1; }
  .c-name { white-space: normal; }
}

/* ---- reduced motion ---- */
@media (prefers-reduced-motion: reduce) {
  .c-star,
  .c-mark,
  .c-note,
  .const-wash { transition: none !important; }
  .c-star:hover .c-mark,
  .c-star:focus-visible .c-mark { transform: none; }
}


