/* ==========================================================================
   COMPONENTS — self-contained, reusable blocks. Each one is documented in
   README.md and depends only on tokens.css + base.css.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Site header — five evenly distributed items, fixed
   -------------------------------------------------------------------------- */

.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 90;
  /* The bar itself is only a positioning frame — the capsule inside is what
     is painted, so the page shows through on either side of it. */
  background: none;
  padding-block: clamp(0.75rem, 1.6vw, 1.25rem);
  padding-inline: var(--pad-x);
  /* …which means the empty margins must not swallow clicks meant for the
     page underneath. The capsule takes them back. */
  pointer-events: none;
  transition: transform var(--dur-base) var(--ease-out);
}

/* The wordmark owns 1/5 of the bar and the four links share the remaining
   4/5 in equal columns — so all five items land on an exact 20% rhythm while
   the list keeps real <ul>/<li> semantics. */
/* All four items — wordmark included — share one distribution, so every gap
   across the bar is equal. The nav and its list collapse to `display: contents`
   so the <li>s become flex children of this row; with the list boxed, the
   wordmark could only ever be spaced against the nav as a whole, never against
   the individual links. */
.site-header__inner {
  pointer-events: auto;
  display: flex;
  align-items: center;
  /* Sized to its contents and centred, rather than spanning the viewport —
     the capsule is a floating object on the page, not a bar across it. */
  width: fit-content;
  max-width: 100%;
  margin-inline: auto;
  gap: clamp(1.25rem, 3.2vw, 3rem);
  min-height: var(--header-h);
  padding-inline: clamp(1.5rem, 3.4vw, 3.25rem);
  background: var(--c-offwhite);
  border-radius: 999px;
  box-shadow:
    0 1px 2px rgb(0 0 0 / 0.04),
    0 8px 28px rgb(0 0 0 / 0.06);
  transition: box-shadow var(--dur-base) var(--ease-out);
}

/* Two links, the wordmark, two links. The DOM order is wordmark-then-nav, so
   the split is done with `order` rather than by moving the markup — which
   keeps the wordmark first for a screen reader and for a no-CSS render. */
.site-header__inner .wordmark { order: 3; }
.site-nav__list > li:nth-child(1) { order: 1; }  /* About    */
.site-nav__list > li:nth-child(2) { order: 2; }  /* Work     */
.site-nav__list > li:nth-child(3) { order: 4; }  /* Services */
.site-nav__list > li:nth-child(4) { order: 5; }  /* Contact  */
.menu-toggle { order: 6; }

/* Once all five are on the bar, the row becomes a symmetric grid.
   With flex, the wordmark lands wherever the link widths leave it — and
   "About Work" is narrower than "Services Contact", so it sat about 30px
   left of centre. Two equal columns either side of an `auto` column put it
   dead centre whatever the labels say, and keep every gap the same. */
@media (min-width: 60.0625rem) {
  .site-header__inner {
    display: grid;
    grid-template-columns: 1fr 1fr auto 1fr 1fr;
    width: min(100%, 46rem);
  }

  .site-header__inner > *,
  .site-nav__list > li {
    justify-self: center;
  }
}

.site-header.is-stuck .site-header__inner {
  box-shadow:
    0 1px 2px rgb(0 0 0 / 0.06),
    0 10px 34px rgb(0 0 0 / 0.1);
}

/* Distribute the links across the nav's own column, flush at both ends.
   Equal 1fr columns with each label aligned to its column's start left the
   last column's remainder as dead space on the right — the nav stopped short
   of the margin while the wordmark sat flush left, and that lopsidedness is
   what read as off balance. space-between anchors both ends and makes every
   gap between links identical. */
/* Both boxes are removed so their children join the header's flex row.
   Current browsers keep the landmark and list semantics through this, but
   older Safari and Firefox strip implicit roles from a `display: contents`
   element — so the markup carries role="navigation" and role="list"
   explicitly rather than depending on that being fixed. */
.site-nav,
.site-nav__list {
  display: contents;
}

/* Compact, sturdy nav lettering without relying on synthetic bold. */
.nav-item {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  justify-self: start;
  font-size: clamp(0.6875rem, 0.62rem + 0.3vw, 0.9375rem);
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--c-black);
  padding-block: 0.5rem;
}

/* About's dropdown. The <li> is a flex item of the header row (the nav and its
   list are display:contents), which still makes a fine positioning context. */
.nav-has-sub {
  position: relative;
}

/* Stacked under About — no panel, no border, just the links on one vertical
   axis with the word above them. `nowrap` keeps each on its own single line.
   The top padding is deliberate: it bridges the gap between the nav item and
   the stack so the pointer never crosses dead space on the way down, which
   would flicker the menu shut mid-travel. */
.nav-sub {
  position: absolute;
  top: 100%;
  /* Centred on About rather than aligned to its left edge, so the word sits
     over the middle of the pair below it. The -50% has to ride along in every
     transform below, or the row would jump left as it animates in. */
  left: 50%;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  white-space: nowrap;
  padding-top: 0.55rem;
  /* visibility, not just opacity: a transparent menu would still swallow
     clicks and still be reachable by Tab while invisible. */
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, -0.4rem);
  transition:
    opacity var(--dur-fast) var(--ease-out),
    transform var(--dur-fast) var(--ease-out),
    visibility 0s linear var(--dur-fast);
}

/* Focusing About alone flips :focus-within, which un-hides the panel and makes
   its links focusable — so Tab walks into it without any JavaScript. */
.nav-has-sub:hover .nav-sub,
.nav-has-sub:focus-within .nav-sub {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%);
  transition-delay: 0s;
}

.nav-sub__link {
  font-size: clamp(0.6875rem, 0.62rem + 0.3vw, 0.9375rem);
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--fg-muted);
  transition: color var(--dur-fast) var(--ease-out);
}

.nav-sub__link:hover,
.nav-sub__link:focus-visible {
  color: var(--c-black);
}

/* Nav items get the same gesture as Seed and See in the hero: the word turns
   accent and brackets open around it. This replaces the underline that used to
   run on ::after — the closing bracket needs that pseudo, and two effects on
   one hover would be noise.

   The space for the brackets is reserved permanently and cancelled by an equal
   negative margin. Opening it on hover instead would widen the item, and since
   the header distributes its items with space-between, every other item would
   shuffle sideways each time the pointer crossed one. */
.nav-item {
  padding-inline: 0.58em;
  margin-inline: -0.58em;
  transition: color var(--dur-base) var(--ease-out);
}

.nav-item:hover,
.nav-item:focus-visible {
  color: var(--accent);
}

.nav-item::before,
.nav-item::after {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  color: var(--accent);
  pointer-events: none; /* the brackets must never eat their own hover */
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}

.nav-item::before {
  content: "(";
  left: 0;
}

.nav-item::after {
  content: ")";
  right: 0;
}

.nav-item:hover::before,
.nav-item:hover::after,
.nav-item:focus-visible::before,
.nav-item:focus-visible::after {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .nav-item,
  .nav-item::before,
  .nav-item::after {
    transition-duration: 1ms;
  }
}

.nav-item[aria-current="page"] .nav-item__dot {
  background: var(--c-cyan);
}

.nav-item__dot {
  width: 0.4em;
  height: 0.4em;
  border-radius: 50%;
  background: transparent;
  transition: background var(--dur-fast) var(--ease-out);
}

/* Wordmark occupies the first column and pairs mark + type. */
.wordmark {
  display: inline-flex;
  align-items: center;
  /* Hit area to the 24px minimum without moving the mark: the padding grows
     the target, the negative margin gives the layout its space back. */
  padding-block: 0.35rem;
  margin-block: -0.35rem;
  gap: 0.55em;
  justify-self: start;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  font-size: clamp(0.8125rem, 0.7rem + 0.4vw, 1.0625rem);
  color: var(--c-black);
}

.wordmark__mark {
  width: 1.5em;
  height: 1.5em;
  flex: none;
  color: var(--c-cyan);
  transition: transform var(--dur-base) var(--ease-out);
}

.wordmark:hover .wordmark__mark {
  transform: rotate(-90deg);
}

/* Mobile menu trigger */
.menu-toggle {
  display: none;
  grid-column: 5;
  justify-self: end;
  align-items: center;
  gap: 0.6rem;
  font-size: var(--t-small);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  padding: 0.5rem 0;
  color: var(--c-black);
}

.menu-toggle__bars {
  display: grid;
  gap: 4px;
  width: 22px;
}

.menu-toggle__bars i {
  display: block;
  height: 1px;
  background: currentColor;
  transition: transform var(--dur-base) var(--ease-out);
}

.menu-toggle[aria-expanded="true"] .menu-toggle__bars i:first-child {
  transform: translateY(2.5px) rotate(12deg);
}

.menu-toggle[aria-expanded="true"] .menu-toggle__bars i:last-child {
  transform: translateY(-2.5px) rotate(-12deg);
}

/* Full-screen mobile panel */
.menu-panel {
  position: fixed;
  inset: 0;
  z-index: 85;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.25rem;
  padding: calc(var(--header-h) + 8vh) var(--pad-x) 10vh;
  background: var(--c-offwhite);
  clip-path: inset(0 0 100% 0);
  transition: clip-path var(--dur-base) var(--ease-inout);
}

.menu-panel.is-open {
  clip-path: inset(0 0 0 0);
}

/* The closed panel is removed outright rather than merely made invisible:
   `visibility: hidden` would block the focus move into the menu, and the
   `hidden` attribute alone loses to `.menu-panel { display: flex }`. */
.menu-panel[hidden] {
  display: none;
}

.menu-panel__link {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding-block: clamp(0.5rem, 2vw, 1rem);
  border-bottom: 1px solid var(--c-rule);
  font-size: clamp(2rem, 11vw, 4rem);
  line-height: 1;
  letter-spacing: var(--tracking-display);
  text-transform: uppercase;
}

.menu-panel__link span {
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
  color: var(--c-grey);
}

/* About is a <details> here, so its pages stay folded away until tapped —
   the touch equivalent of the desktop hover. The summary is dressed as an
   ordinary menu link; only the +/– at the right edge says it opens. */
.menu-panel__group summary {
  cursor: pointer;
  list-style: none; /* Firefox */
  justify-content: flex-start;
  gap: 0.5rem;
}

/* The marker is a ::after, so it lands after the number in source order.
   Ordering the number last and floating it right instead keeps 01 on the
   same edge as 02 and 03, with the +/– tucked against the word. */
.menu-panel__group summary span {
  order: 1;
  margin-left: auto;
}

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

.menu-panel__group summary::after {
  content: "+";
  font-size: clamp(1.25rem, 5vw, 1.75rem);
  line-height: 1;
  color: var(--c-grey);
  transition: color var(--dur-fast) var(--ease-out);
}

.menu-panel__group[open] summary::after {
  content: "\2013"; /* en dash — reads as a minus at this weight */
}

.menu-panel__group summary:hover::after {
  color: var(--fg);
}

/* Open, the rule below belongs to the sub-list; closed, the summary keeps
   its own so the row still reads as one of the stack. */
.menu-panel__group[open] summary {
  border-bottom: 0;
}

/* The browser's own hiding of closed <details> content loses to the
   `display: flex` below, which would leave these links laid out and tabbable
   while folded away. Take the hiding back explicitly. */
.menu-panel__group:not([open]) .menu-panel__sub {
  display: none;
}

/* Bian and How read as a tier below About: smaller, and sharing one rule
   rather than each carrying their own. Flush left with About rather than
   indented — the size difference already carries the hierarchy, and the
   shared left edge keeps the whole menu on one margin. */
.menu-panel__sub {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.75rem;
  margin-top: calc(clamp(0.5rem, 2vw, 1rem) * -1);
  padding: clamp(0.7rem, 2.2vw, 1rem) 0 clamp(0.7rem, 2.4vw, 1.1rem);
  border-bottom: 1px solid var(--c-rule);
}

.menu-panel__sublink {
  font-size: clamp(0.9375rem, 3.2vw, 1.25rem);
  letter-spacing: var(--tracking-tight);
  text-transform: uppercase;
  color: var(--fg-muted);
  transition: color var(--dur-fast) var(--ease-out);
}

.menu-panel__sublink:hover,
.menu-panel__sublink:focus-visible {
  color: var(--fg);
}

/* Links only. About is a <summary> you rest the pointer on to open, so greying
   it would leave it sitting pale beside two black rows — and it would trade
   places with its own marker, which darkens on hover. The +/– carries the
   feedback there instead. */
a.menu-panel__link:hover {
  color: var(--c-grey);
}

.menu-panel__foot {
  margin-top: auto;
  padding-top: 2.5rem;
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
}

/* --------------------------------------------------------------------------
   2. Link with sliding arrow / masked underline
   -------------------------------------------------------------------------- */

.link-line {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.7em;
  padding-bottom: 0.35em;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  font-size: var(--t-small);
}

.link-line::before,
.link-line::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 1px;
  width: 100%;
}

.link-line::before {
  background: var(--c-rule-strong);
}

.link-line::after {
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--dur-base) var(--ease-out);
}

.link-line:hover::after,
.link-line:focus-visible::after {
  transform: scaleX(1);
  transform-origin: left;
}

.link-line__arrow {
  transition: transform var(--dur-base) var(--ease-out);
}

.link-line:hover .link-line__arrow {
  transform: translate(0.28em, -0.28em);
}

/* Oversized version used for “All Works” / “More About Us” */
.link-xl {
  font-size: clamp(1.25rem, 0.6rem + 2.6vw, 3rem);
  letter-spacing: var(--tracking-display);
  gap: 0.4em;
  padding-bottom: 0.12em;
}

/* --------------------------------------------------------------------------
   3. Work card
   -------------------------------------------------------------------------- */

.work-card {
  display: block;
  position: relative;
}

.work-card__media {
  aspect-ratio: var(--ratio, 4 / 5);
}

.work-card:hover .media :is(img, video),
.work-card:focus-visible .media :is(img, video) {
  transform: scale(1.055);
}

.work-card:hover .media::after,
.work-card:focus-visible .media::after {
  opacity: 1;
}

.work-card__meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  margin-top: clamp(0.75rem, 1.4vw, 1.25rem);
  padding-top: clamp(0.6rem, 1vw, 0.9rem);
  border-top: 1px solid var(--c-rule);
}

.work-card__title {
  font-size: clamp(1rem, 0.75rem + 0.85vw, 1.75rem);
  line-height: 1.1;
  letter-spacing: var(--tracking-tight);
  text-transform: uppercase;
  transition: color var(--dur-fast) var(--ease-out);
}

.work-card:hover .work-card__title {
  color: var(--c-grey);
}

/* Corner arrow — sits over the image and drifts on hover. */
.work-card__arrow {
  position: absolute;
  top: clamp(0.75rem, 1.4vw, 1.5rem);
  right: clamp(0.75rem, 1.4vw, 1.5rem);
  z-index: 2;
  display: grid;
  place-items: center;
  color: var(--c-offwhite);
  mix-blend-mode: difference;
  transition: transform var(--dur-base) var(--ease-out);
}

.work-card:hover .work-card__arrow,
.work-card:focus-visible .work-card__arrow {
  transform: translate(0.25rem, -0.25rem);
}

.work-card__index {
  position: absolute;
  top: clamp(0.75rem, 1.4vw, 1.5rem);
  left: clamp(0.75rem, 1.4vw, 1.5rem);
  z-index: 2;
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
  color: var(--c-offwhite);
  mix-blend-mode: difference;
}

/* --------------------------------------------------------------------------
   4. Custom cursor (pointer-fine devices only)
   -------------------------------------------------------------------------- */

/* The pointer is the Seedsee mark itself, read as an eye: the parentheses are
   eyelids, the ring is the iris, the dot is the pupil. */
.cursor {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 120;
  display: none;
  justify-items: center;
  width: var(--cursor-size, 3rem);
  margin: calc(var(--cursor-size, 3rem) / -2.9) 0 0
    calc(var(--cursor-size, 3rem) / -2);
  color: var(--c-cyan);
  pointer-events: none;
  opacity: 0;
  transition:
    opacity var(--dur-fast) linear,
    width var(--dur-base) var(--ease-out),
    margin var(--dur-base) var(--ease-out);
}

.cursor.is-awake {
  opacity: 1;
}

/* Over anything interactive the eye opens wider. */
.cursor.is-active {
  --cursor-size: 4.25rem;
}

.cursor__eye {
  width: 100%;
  height: auto;
  overflow: visible;
  filter: drop-shadow(0 2px 10px color-mix(in srgb, var(--c-black) 18%, transparent));
}

/* Eyelids slide in to close; iris and pupil fade out behind them. */
.cursor__lid {
  transition: transform 150ms ease-in-out;
}

.cursor.is-winking .cursor__lid--left {
  transform: translateX(180px);
}

.cursor.is-winking .cursor__lid--right {
  transform: translateX(-180px);
}

.cursor__iris,
.cursor__pupil {
  transition:
    opacity 150ms ease-in-out,
    transform 420ms var(--ease-out);
}

.cursor.is-winking .cursor__iris,
.cursor.is-winking .cursor__pupil {
  opacity: 0;
}

@media (hover: hover) and (pointer: fine) {
  .cursor {
    display: grid;
  }

  /* The mark replaces the native arrow — restored under reduced motion. */
  html.has-eye-cursor,
  html.has-eye-cursor * {
    cursor: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .cursor {
    display: none !important;
  }

  html.has-eye-cursor,
  html.has-eye-cursor * {
    cursor: auto;
  }
}

/* --------------------------------------------------------------------------
   5. Stat block
   -------------------------------------------------------------------------- */

.stat {
  padding-top: clamp(1rem, 2vw, 2rem);
  border-top: 1px solid var(--c-rule);
}

.stat__value {
  display: flex;
  align-items: baseline;
  font-size: var(--t-numeral);
  line-height: 0.9;
  letter-spacing: var(--tracking-display);
  font-variant-numeric: tabular-nums;
}

.stat__suffix {
  color: var(--c-cyan);
}

.stat__label {
  margin-top: clamp(0.75rem, 1.4vw, 1.25rem);
  font-size: clamp(0.9375rem, 0.85rem + 0.4vw, 1.25rem);
  text-transform: uppercase;
  letter-spacing: var(--tracking-tight);
}

.stat__note {
  margin-top: 0.5rem;
  font-size: var(--t-small);
  line-height: 1.45;
  color: var(--fg-muted);
  max-width: 26ch;
}

/* --------------------------------------------------------------------------
   6. Team card
   -------------------------------------------------------------------------- */

.person__media {
  aspect-ratio: 4 / 5;
}

.person:hover .media :is(img, video) {
  transform: scale(1.05);
}

.person__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-top: clamp(0.75rem, 1.2vw, 1.1rem);
  padding-top: 0.75rem;
  border-top: 1px solid var(--c-rule);
}

.person__name {
  font-size: clamp(1.25rem, 0.9rem + 1.3vw, 2.25rem);
  text-transform: uppercase;
  line-height: 1;
}


/* --------------------------------------------------------------------------
   7b. CV entry row — used on the Bian page for experience and education
   -------------------------------------------------------------------------- */

.entry {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: 0.75rem;
  padding-block: clamp(1.25rem, 2.4vw, 2.25rem);
  border-top: 1px solid var(--c-rule);
}

.entry:last-child {
  border-bottom: 1px solid var(--c-rule);
}

.entry__when {
  grid-column: 1 / span 2;
  font-size: var(--t-small);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--fg-muted);
}

.entry__org {
  grid-column: 3 / span 4;
}

.entry__name {
  font-size: clamp(1.125rem, 0.85rem + 1vw, 2rem);
  line-height: 1.05;
  text-transform: uppercase;
  letter-spacing: var(--tracking-tight);
}

.entry__role {
  margin-top: 0.35rem;
  font-size: var(--t-small);
  color: var(--fg-muted);
}

.entry__points {
  grid-column: 8 / span 5;
  display: grid;
  gap: 0.5rem;
  align-content: start;
  font-size: var(--t-small);
  line-height: 1.5;
}

.entry__points li {
  display: flex;
  gap: 0.75rem;
}

.entry__points li::before {
  content: "";
  flex: none;
  width: 1.25rem;
  height: 1px;
  margin-top: 0.7em;
  background: var(--c-cyan);
}

@media (max-width: 60rem) {
  .entry__when {
    grid-column: 1 / span 12;
  }

  .entry__org {
    grid-column: 1 / span 12;
  }

  .entry__points {
    grid-column: 1 / span 12;
  }
}

/* Photography sits inside the monochrome system by default and only warms up
   on hover — an art-direction rule, not a decoration. */
.duotone :is(img, video) {
  filter: grayscale(1) contrast(1.06);
  transition:
    filter var(--dur-base) var(--ease-out),
    transform var(--dur-image) var(--ease-image) var(--d, 0ms);
}

.duotone:hover :is(img, video),
.duotone:focus-within :is(img, video) {
  filter: grayscale(0) contrast(1);
}

/* --------------------------------------------------------------------------
   8. Marquee (social strip)
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   9. Curtain (loading screen + page transition)
   -------------------------------------------------------------------------- */

/* Covers the page from first paint until the hero scene reports ready, so a
   half-built WebGL canvas is never on show. Above everything — including the
   skip link at 200, since there is nothing to skip to while this is up. */
.curtain {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: grid;
  place-items: center;
  background: var(--bg);
  transform-origin: top;
}

.curtain__mark {
  width: clamp(3.25rem, 8vw, 5.5rem);
  height: auto;
  color: var(--accent);
  /* A slow breath, so a long scene build reads as working rather than stuck. */
  animation: curtain-breathe 1800ms var(--ease-inout) infinite;
}

@keyframes curtain-breathe {
  0%,
  100% {
    opacity: 0.32;
  }
  50% {
    opacity: 1;
  }
}

/* Intro: curtain lifts away on first paint */
.curtain.is-lifting {
  animation: curtain-up 1000ms var(--ease-inout) forwards;
}

/* Outro: curtain drops before navigating away */
.curtain.is-dropping {
  transform-origin: bottom;
  animation: curtain-down 620ms var(--ease-inout) forwards;
}

.curtain.is-idle {
  display: none;
}

@keyframes curtain-up {
  0% {
    transform: scaleY(1);
  }
  100% {
    transform: scaleY(0);
  }
}

@keyframes curtain-down {
  0% {
    transform: scaleY(0);
  }
  100% {
    transform: scaleY(1);
  }
}

@media (prefers-reduced-motion: reduce) {
  .curtain {
    display: none !important;
  }
}

/* --------------------------------------------------------------------------
   10. Responsive — header collapse
   -------------------------------------------------------------------------- */

@media (max-width: 60rem) {
  /* header is flex; nothing to re-template. The nav hides and the toggle
     shows, and space-between puts the toggle where the nav was. */

  .site-nav {
    display: none;
  }

  .menu-toggle {
    display: flex;
    grid-column: 2;
  }
}

@media (min-width: 60.0625rem) {
  .menu-panel {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   11. Project Team — contributors inside the project info panel
   -------------------------------------------------------------------------- */

/* Spans the panel's two columns so the list never splits mid-name. */
.project-meta__team {
  grid-column: 1 / -1;
}

.teammates {
  display: grid;
  gap: 0.55rem;
}

.teammate {
  position: relative;
}

.teammate__trigger {
  display: inline-flex;
  align-items: baseline;
  gap: 0.55rem;
  padding: 0.1rem 0;
  font: inherit;
  letter-spacing: inherit;
  text-align: left;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

.teammate__dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--c-cyan);
  transform: translateY(-0.15em);
  transition: transform var(--dur-fast) var(--ease-out);
}

.teammate__name {
  font-size: var(--t-body);
  transition: color var(--dur-fast) var(--ease-out);
}

.teammate__role {
  font-size: var(--t-body);
  color: var(--fg-muted);
}

.teammate__trigger:hover .teammate__dot,
.teammate__trigger:focus-visible .teammate__dot {
  transform: translateY(-0.15em) scale(1.35);
}

/* -- The floating profile bubble ------------------------------------------- */

.teammate__bubble {
  position: absolute;
  left: 0;
  bottom: calc(100% + 0.6rem);
  z-index: 30;
  display: grid;
  justify-items: center;
  gap: 0.35rem;
  width: max-content;
  max-width: min(14rem, calc(100vw - 2 * var(--pad-x)));
  padding: 0.85rem 1rem;
  background: #fff;
  border-radius: 0.85rem;
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.06),
    0 12px 28px rgba(0, 0, 0, 0.12);
  opacity: 0;
  visibility: hidden;
  transform: scale(0.96);
  transform-origin: bottom left;
  transition:
    opacity 200ms var(--ease-out),
    transform 200ms var(--ease-out),
    visibility 200ms;
  pointer-events: none;
}

.teammate__bubble img {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--c-beige);
}

.teammate__card-name {
  font-size: var(--t-small);
  letter-spacing: var(--tracking-tight);
  color: var(--c-black);
}

.teammate__card-role {
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--c-grey);
  text-align: center;
}

/* Hover and keyboard focus on desktop; .is-open is the tap path on touch. */
@media (hover: hover) {
  .teammate__trigger:hover .teammate__bubble {
    opacity: 1;
    visibility: visible;
    transform: scale(1);
  }
}

.teammate__trigger:focus-visible .teammate__bubble,
.teammate.is-open .teammate__bubble {
  opacity: 1;
  visibility: visible;
  transform: scale(1);
}

/* Near the right edge the bubble flips its anchor so it stays on screen. */
.teammate--flip .teammate__bubble {
  left: auto;
  right: 0;
  transform-origin: bottom right;
}

@media (prefers-reduced-motion: reduce) {
  .teammate__bubble {
    transition: opacity 0.001ms, visibility 0.001ms;
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   12. Language switcher — inline links, no dropdown
   -------------------------------------------------------------------------- */

.lang {
  display: flex;
  align-items: center;
  gap: 0.55em;
  justify-self: end;
  font-size: clamp(0.625rem, 0.58rem + 0.25vw, 0.8125rem);
  letter-spacing: 0.06em;
  color: var(--c-grey);
}

.lang__link {
  padding: 0.4em 0.1em;
  color: var(--c-grey);
  transition: color var(--dur-fast) var(--ease-out);
}

.lang__link:hover,
.lang__link:focus-visible {
  color: var(--c-black);
}

/* The active route is stated, not merely styled. */
.lang__link[aria-current="true"] {
  color: var(--c-black);
  border-bottom: 1px solid var(--c-cyan);
}

.lang__sep {
  color: color-mix(in srgb, var(--c-grey) 55%, transparent);
  user-select: none;
}

/* The switcher takes the header's last column; the nav gives one back. */
.site-header__inner--i18n {
  grid-template-columns: 1fr 3fr auto;
  gap: clamp(1rem, 2vw, 2rem);
}

.site-header__inner--i18n .site-nav__list {
  grid-template-columns: repeat(4, 1fr);
}

@media (max-width: 60rem) {
  .site-header__inner--i18n {
    grid-template-columns: 1fr auto auto;
  }

  .lang {
    order: 2;
  }
}

@media (max-width: 30rem) {
  .lang {
    gap: 0.35em;
    font-size: 0.625rem;
  }
}


/* --------------------------------------------------------------------------
   Bracketed word — the studio's own mark, drawn around the word it is named
   for.

   The brackets open real space in the line rather than floating over it: the
   word's inline padding grows on hover and the neighbouring words ease apart
   to make room, exactly as if two characters had been typed in. Overlaying
   them instead was tidier to animate but sat the bracket on top of the word
   beside it, which read as a collision rather than as punctuation.

   Each bracket is pinned to the padding edge, so it is carried outward by the
   padding as that opens — the expansion comes for free from the layout, with
   nothing to keep in sync.
   -------------------------------------------------------------------------- */
.mark-word {
  position: relative;
  /* Must stay `inline`. As an inline-block its offsetTop sits a few pixels off
     the surrounding inline text, and the headline splitter groups words into
     lines by comparing offsetTop within a 4px tolerance — so the word was read
     as a new line and given its own block-level mask, breaking the heading in
     two. Inline still honours horizontal padding, which is what opens the
     space for the brackets. */
  display: inline;
  padding-inline: 0;
  transition:
    padding-inline var(--dur-slow) var(--ease-out),
    color var(--dur-base) var(--ease-out);
}

.mark-word:hover,
.mark-word:focus-visible {
  padding-inline: 0.58em;
  color: var(--accent);
}

.mark-word::before,
.mark-word::after {
  position: absolute;
  top: 0;
  color: var(--accent);
  pointer-events: none; /* the brackets must never eat their own hover */
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}

.mark-word::before {
  content: "(";
  left: 0;
}

.mark-word::after {
  content: ")";
  right: 0;
}

.mark-word:hover::before,
.mark-word:hover::after,
.mark-word:focus-visible::before,
.mark-word:focus-visible::after {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .mark-word,
  .mark-word::before,
  .mark-word::after {
    transition-duration: 1ms;
  }
}
