/* Home page. */

/* ---- Hero: three role panels filling the first screen -------------------------
   Singer, Composer, Conductor side by side with even gaps. The open panel is wider and
   in full colour; the open one takes turns (home.js), and hovering or focusing a panel
   opens it. The name sits across the bottom of all three. Photos crop themselves
   (object-fit); set the crop per panel with object-position below. */
.hero {
  --gap: clamp(0.5rem, 1.5vw, 1rem);
  position: relative;
  height: calc(100svh - 4.5rem);
  min-height: 32rem;
  padding: var(--gap);
}

.hero__panels {
  display: flex;
  gap: var(--gap);
  height: 100%;
}

.hero__panel {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  border-radius: var(--radius-l);
  background: var(--ground-850);
  color: var(--color-text);
  text-decoration: none;
  transition: flex-grow 900ms var(--ease-out);
}

.hero__panel.is-active {
  flex-grow: 2.4;
}

.hero__panel picture {
  display: block;
  height: 100%;
}

.hero__panel img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.55) saturate(0.5);
  transform: scale(1.04);
  transition: filter 900ms var(--ease-out), transform 6s var(--ease-out);
}

.hero__panel.is-active img {
  filter: none;
  transform: scale(1.1);
}

.hero__panel--singer img { object-position: 35% 0%; transform-origin: 35% 30%; }
.hero__panel--composer img { object-position: 30% 55%; }
.hero__panel--conductor img { object-position: 45% 22%; }

/* Darkens the bottom of every panel so the name reads over any photo. */
.hero__panel::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, var(--ground) 0%, color-mix(in srgb, var(--ground) 70%, transparent) 28%, transparent 58%);
  pointer-events: none;
}


.hero__panel:focus-visible {
  outline-offset: -4px;
}

/* The name and buttons, laid over the bottom of the panels. Clicks pass through to the
   panels except on the buttons. */
.hero__text {
  position: absolute;
  z-index: 2;
  inset-inline: calc(var(--gap) * 2);
  inset-block-end: calc(var(--gap) * 2);
  padding: clamp(0.75rem, 2.5vw, 2rem);
  pointer-events: none;
}

.hero__text .cluster {
  pointer-events: auto;
}

.hero__text > * + * {
  margin-block-start: var(--space-s);
}

.hero h1 {
  font-size: clamp(3.25rem, 11vw, 10rem);
  font-weight: 400;
  line-height: 0.92;
  letter-spacing: -0.02em;
  text-shadow: 0 2px 30px color-mix(in srgb, var(--ground) 60%, transparent);
}

.hero .lead {
  max-width: 30ch;
}

/* Scroll button: bottom-right of the hero. A thin ring with a line that drops through
   it, and a small "Scroll" beside it. It rises in a second after the hero shows, and
   fades away once the page is scrolled (home.js). */
.hero__scroll {
  position: absolute;
  z-index: 3;
  inset-inline-end: calc(var(--gap) * 2 + clamp(0.75rem, 2.5vw, 2rem));
  inset-block-end: calc(var(--gap) * 2 + clamp(0.75rem, 2.5vw, 2rem));
  display: flex;
  gap: var(--space-xs, 0.75rem);
  align-items: center;
  color: var(--text);
  text-decoration: none;
  transition: opacity 500ms var(--ease-out), translate 500ms var(--ease-out);
}

.hero__scroll.is-gone {
  opacity: 0;
  translate: 0 0.75rem;
  pointer-events: none;
}

.hero__scroll-label {
  font-size: var(--step--1);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--text) 80%, transparent);
  transition: color 300ms, letter-spacing 400ms var(--ease-out);
}

.hero__scroll-ring {
  position: relative;
  display: grid;
  place-items: center;
  width: 3.25rem;
  aspect-ratio: 1;
  overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--text) 45%, transparent);
  border-radius: 50%;
  background: color-mix(in srgb, var(--ground) 35%, transparent);
  backdrop-filter: blur(8px);
  transition: border-color 300ms, background-color 300ms, scale 400ms var(--ease-out);
}

/* A short line with a fine arrowhead, drawn in the middle of the ring. */
.hero__scroll-line {
  position: relative;
  width: 1px;
  height: 1.25rem;
  background: currentColor;
}

.hero__scroll-line::after {
  content: "";
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 50%;
  width: 0.45rem;
  aspect-ratio: 1;
  border-inline-end: 1px solid currentColor;
  border-block-end: 1px solid currentColor;
  translate: -50% 0;
  rotate: 45deg;
}

.hero__scroll:hover .hero__scroll-ring,
.hero__scroll:focus-visible .hero__scroll-ring {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  scale: 1.06;
}

.hero__scroll:hover .hero__scroll-label,
.hero__scroll:focus-visible .hero__scroll-label {
  color: var(--accent);
  letter-spacing: 0.26em;
}

.hero__scroll:focus-visible {
  outline: none;
}

.hero__scroll:focus-visible .hero__scroll-ring {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* Phones: just the ring, so it stays clear of the buttons. */
@media (max-width: 47.99rem) {
  .hero__scroll-label {
    display: none;
  }

  .hero__scroll-ring {
    width: 2.75rem;
  }
}

[data-parallax] {
  transform: translateY(var(--parallax, 0%)) scale(1.12);
  will-change: transform;
}

.bio-teaser {
  display: grid;
  gap: var(--space-xl);
  align-items: center;
}

@media (min-width: 52rem) {
  .bio-teaser {
    grid-template-columns: 0.8fr 1.2fr;
  }
}

.contact-cta {
  text-align: center;
}

.contact-cta > * {
  margin-inline: auto;
}

.contact-cta .cluster {
  justify-content: center;
}

/* ---- Hero motion ------------------------------------------------------------
   The entrance starts when the page shows, or right after the intro when it plays
   (intro.js removes .intro-on from <html>). */

/* Each word rises out of its own mask. The padding gives italic letters room to
   lean past their box (the "d" in Menard); the negative margin cancels it in the layout. */
.hero__word {
  display: inline-block;
  overflow: hidden;
  padding: 0.1em 0.2em 0.12em;
  margin: -0.1em -0.2em -0.12em;
}

.hero__word > span {
  display: inline-block;
}

@media (prefers-reduced-motion: no-preference) {
  .intro-on .hero__text > *,
  .intro-on .hero__word > span,
  .intro-on .hero__panel {
    opacity: 0;
  }

  .js:not(.intro-on) .hero__text > * {
    animation: rise-in 900ms var(--ease-out) both;
  }

  .js:not(.intro-on) .hero__text > :nth-child(1) { animation-delay: 500ms; }
  .js:not(.intro-on) .hero__text > :nth-child(3) { animation-delay: 950ms; }
  .js:not(.intro-on) .hero__text > :nth-child(4) { animation-delay: 1100ms; }

  /* The heading itself stays put; its words slide up. */
  .js:not(.intro-on) .hero__text > h1 {
    animation: none;
  }

  .js:not(.intro-on) .hero__word > span {
    animation: word-up 1100ms var(--ease-out) both;
    animation-delay: 600ms;
  }

  .js:not(.intro-on) .hero__word + .hero__word > span {
    animation-delay: 730ms;
  }

  /* Panels wipe up one after another. */
  .js:not(.intro-on) .hero__panel {
    animation: photo-in 1300ms var(--ease-out) both;
  }

  .js:not(.intro-on) .hero__panel:nth-child(2) { animation-delay: 140ms; }
  .js:not(.intro-on) .hero__panel:nth-child(3) { animation-delay: 280ms; }

  /* The scroll button rises in a second after the hero, then its line keeps
     slipping down through the ring. */
  .intro-on .hero__scroll {
    opacity: 0;
  }

  .js:not(.intro-on) .hero__scroll {
    animation: scroll-cue-in 900ms var(--ease-out) 1000ms backwards;
  }

  .js:not(.intro-on) .hero__scroll-line {
    animation: scroll-cue-drop 2.4s cubic-bezier(0.65, 0, 0.35, 1) 1900ms infinite;
  }
}

@keyframes scroll-cue-in {
  from {
    opacity: 0;
    translate: 0 1rem;
    filter: blur(4px);
  }
}

/* Slides down out of the ring, then back in from the top. */
@keyframes scroll-cue-drop {
  0%, 15% { translate: 0 0; opacity: 1; }
  50% { translate: 0 2.2rem; opacity: 0; }
  51% { translate: 0 -2.2rem; opacity: 0; }
  85%, 100% { translate: 0 0; opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .hero__panel,
  .hero__panel img {
    transition: none;
  }
}

@keyframes word-up {
  from {
    transform: translateY(105%);
  }
}

@keyframes photo-in {
  from {
    clip-path: inset(100% 0 0 0 round var(--radius-l));
    opacity: 0.4;
  }
  to {
    clip-path: inset(0 0 0 0 round var(--radius-l));
    opacity: 1;
  }
}

/* ---- Ensembles marquee ------------------------------------------------------ */
.marquee {
  display: grid;
  gap: var(--space-s);
  padding-block: var(--space-l);
  border-block: 1px solid var(--color-border-subtle);
}

.marquee__viewport {
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

.marquee__track {
  display: flex;
  width: max-content;
}

.marquee__list {
  display: flex;
  flex: none;
  margin: 0;
  padding: 0;
  list-style: none;
}

.marquee__list li {
  display: flex;
  align-items: center;
  font-family: var(--font-display);
  font-size: var(--step-3);
  font-style: italic;
  white-space: nowrap;
  color: var(--text);
}

/* A thin upright rule between names. */
.marquee__list li::after {
  content: "";
  width: 1px;
  height: 0.9em;
  margin-inline: var(--space-l);
  background: var(--color-border-subtle);
}

@media (prefers-reduced-motion: no-preference) {
  .marquee__track {
    animation: marquee 40s linear infinite;
  }

  .marquee:hover .marquee__track {
    animation-play-state: paused;
  }
}

/* Reduced motion: no scrolling; the names wrap and the copy is hidden. */
@media (prefers-reduced-motion: reduce) {
  .marquee__track,
  .marquee__list {
    flex-wrap: wrap;
    width: auto;
    padding-inline: var(--gutter);
  }

  .marquee__list[aria-hidden] {
    display: none;
  }

  .marquee__viewport {
    mask-image: none;
  }
}

@keyframes marquee {
  to {
    transform: translateX(-50%);
  }
}

/* ---- Explore: photo cards to the other music pages --------------------------- */
.explore {
  display: grid;
  gap: var(--space-s);
  margin-block-start: var(--space-m);
  padding: 0;
  list-style: none;
}

@media (min-width: 48rem) {
  .explore {
    grid-template-columns: repeat(2, 1fr);
  }
}

.explore__item {
  position: relative;
  display: grid;
  overflow: hidden;
  border-radius: var(--radius-l);
  isolation: isolate;
}

.explore__item > * {
  grid-area: 1 / 1;
}

.explore__item .photo {
  aspect-ratio: 3 / 2;
  border-radius: 0;
}

@media (min-width: 48rem) {
  .explore__item .photo {
    aspect-ratio: 5 / 4;
  }
}

.explore__item .photo img {
  object-position: center 20%; /* Keeps faces in frame on the wide phone crop. */
  transition: transform 1.4s var(--ease-out);
}

.explore__item:hover .photo img {
  transform: scale(1.06);
}

/* Solid ground behind the text (fading out only above it), so contrast never depends on the photo. */
.explore__text {
  position: relative;
  z-index: 1;
  align-self: end;
  display: grid;
  gap: var(--space-2xs);
  padding: var(--space-xl) var(--space-m) var(--space-m);
  background: linear-gradient(to top, var(--ground-950) calc(100% - var(--space-xl)), transparent);
}

.explore__text h3 a {
  color: var(--text);
  text-decoration: none;
}

.explore__text h3 a::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
}

.explore__text h3 a::after {
  content: "→";
  display: inline-block;
  margin-inline-start: 0.3em;
  color: var(--accent);
  transition: transform var(--dur-med) var(--ease-out);
}

.explore__item:hover h3 a::after {
  transform: translateX(4px);
}

.explore__item:has(a:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.explore__text h3 a:focus-visible {
  outline: none;
}

.explore__text p {
  color: var(--text-muted);
  font-size: var(--step--1);
}

/* ---- Featured scores: staggered, the second set a little lower ------------ */
.featured .work-card:nth-child(even) {
  margin-block-start: var(--space-l);
}

/* ---- Roles band: Singer, Composer, Conductor in big type between thin rules.
   Each title opens a short bio underneath (a native <details>, so it works without JS). */
.stats__list {
  display: grid;
  gap: var(--space-l);
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 48rem) {
  .stats__list {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: start;
    gap: 0;
  }

  .stats__list > li {
    padding-inline: var(--space-l);
  }

  .stats__list > li + li {
    border-inline-start: 1px solid var(--color-border-subtle);
  }

  .stats__list > li:first-child {
    padding-inline-start: 0;
  }
}

/* The title scales with its column so the longest word ("Conductor") plus the toggle
   always fit, from phones up to wide screens. */
.stats__list > li {
  container-type: inline-size;
}

.role summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-s);
  cursor: pointer;
  list-style: none;
}

.role summary::-webkit-details-marker {
  display: none;
}

.role__title {
  font-family: var(--font-display);
  font-size: clamp(2rem, (100cqi - 3.5rem) / 4.9, 4.6rem);
  font-weight: 300;
  line-height: 1.05;
  letter-spacing: -0.03em;
  color: var(--accent);
  transition: color var(--dur-med) ease;
}

.role summary:hover .role__title {
  color: var(--accent-hover);
}

/* A plus in a ring that turns into a minus when open. */
.role__toggle {
  position: relative;
  flex: none;
  width: 2.25rem;
  height: 2.25rem;
  border: 1px solid var(--color-border-control);
  border-radius: 50%;
  transition: border-color var(--dur-med) ease, background-color var(--dur-med) ease;
}

.role__toggle::before,
.role__toggle::after {
  content: "";
  position: absolute;
  inset: 50% auto auto 50%;
  width: 0.8rem;
  height: 1.5px;
  background: var(--accent);
  translate: -50% -50%;
  transition: scale var(--dur-med) var(--ease-out);
}

.role__toggle::after {
  rotate: 90deg;
}

.role[open] .role__toggle::after {
  scale: 0 1;
}

/* While the bio slides shut (home.js), the minus already turns back into a plus. */
.role.is-closing .role__toggle::after {
  scale: 1;
}

.role summary:hover .role__toggle {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}

.role summary:focus-visible {
  outline: var(--focus-width) solid var(--color-focus);
  outline-offset: var(--focus-offset);
  border-radius: var(--radius-s);
}

.role__bio {
  display: grid;
  gap: var(--space-s);
  justify-items: start;
  padding-block-start: var(--space-s);
  max-width: 36ch;
  color: var(--text-muted);
}

/* ---- Photo strip: a row you scroll sideways --------------------------------- */
.strip {
  display: flex;
  gap: var(--space-s);
  margin: 0;
  padding: var(--space-2xs) max(var(--gutter), (100% - var(--page-max)) / 2) var(--space-s);
  list-style: none;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: max(var(--gutter), (100% - var(--page-max)) / 2);
  scrollbar-width: thin;
  scrollbar-color: var(--panel) transparent;
}

/* With a mouse the strip can be dragged (home.js). */
@media (hover: hover) and (pointer: fine) {
  .strip {
    cursor: grab;
  }

  .strip.is-dragging {
    cursor: grabbing;
    scroll-snap-type: none;
    user-select: none;
  }
}

.strip:focus-visible {
  outline-offset: -4px;
}

.strip > li {
  flex: none;
  scroll-snap-align: start;
}

.strip .photo {
  height: clamp(16rem, 34vw, 26rem);
  border-radius: var(--radius-l);
}

.strip .photo img {
  width: auto;
  height: 100%;
}

.strip__button {
  display: inline-grid;
  place-items: center;
  width: 2.75rem;
  aspect-ratio: 1;
  border: 1.5px solid var(--panel-200);
  border-radius: 50%;
  background: none;
  color: var(--text);
  font-size: var(--step-1);
  cursor: pointer;
  transition: border-color var(--dur-med) ease, background-color var(--dur-med) ease, transform var(--dur-med) var(--ease-out);
}

.strip__button:hover {
  border-color: var(--accent);
  background: var(--ground-800);
  transform: scale(1.06);
}

.strip__button:disabled {
  opacity: 0.4;
  cursor: default;
  transform: none;
}

.strip__controls {
  align-items: center;
}

/* Bio teaser: give the arch room. */
.bio-teaser .arch {
  margin-block: var(--space-m);
}

/* The portrait drifts in very slowly, as if breathing. */
@media (prefers-reduced-motion: no-preference) {
  .arch img {
    animation: breathe 18s ease-in-out infinite alternate;
  }
}

@keyframes breathe {
  to {
    scale: 1.06;
  }
}
