/* ============================================================
   TTCC — FILTER PILL
   "We design <discipline> for <sector>". Shared verbatim by the
   home hero and the works page filter — linked by both, never
   duplicated. Positioning is the caller's job: index.html places
   it over the slider via .hero-filter (hero.css), works.html
   centres it above the heading via .works-filter (works.css).
   ============================================================ */

/* ============================================================
   HERO PILL — single source of type
   Every font-size, line-height, padding, margin and
   vertical-align used anywhere inside the pill is declared on
   .filter-pill and nowhere else. Ordinary elements (the two
   words, the two .filter-dd wrappers, the rolling spans)
   inherit that for free through normal CSS cascade — nothing
   to restate. The one exception is the real <button>: a UA
   stylesheet stops buttons inheriting font at all, so
   `font: inherit` has to be repeated there — not because the
   button defines its own type, but because it would otherwise
   silently NOT have the container's. Height throughout comes
   from line-height + padding, or — for the rolling window —
   1em, which tracks the container's font-size exactly and so
   can never drift from it. There is no fixed pixel height
   anywhere in the pill.
   ============================================================ */
.filter-pill {
  /* Positioning context for both dropdown panels, and the one
     interactive island inside .hero-filter's pointer-events: none. */
  position: relative;
  pointer-events: auto;

  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: "TTCC Sans", sans-serif;
  font-weight: 400;
  font-size: clamp(14px, 0.9vw, 18px);
  line-height: 1;
  padding: clamp(9px, 0.6vw, 13px) clamp(16px, 1.1vw, 22px);

  /* Frosted glass. The border is a hairline highlight along the top
     edge of the blur, not a containing outline. Border-box sizing is
     global, so adding the 1px border does not change the pill's height
     or shift its baseline. */
  border-radius: 4px;
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: rgba(235, 235, 235, 0.72);
  -webkit-backdrop-filter: blur(14px) saturate(1.15);
  backdrop-filter: blur(14px) saturate(1.15);
  transition: background 200ms ease;

  white-space: nowrap;
}

.filter-pill:hover {
  background: rgba(240, 240, 240, 0.8);
}

/* No backdrop-filter (older Firefox, some Android): the translucent
   fill would sit over unblurred media and lose all contrast, so fall
   back to the original opaque chip with no edge highlight. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .filter-pill {
    background: #ececec;
    border-color: transparent;
  }

  .filter-pill:hover {
    background: #ececec;
  }
}

/* Universal reset for every direct child — the two static words and the
   two .filter-dd wrappers. A future child dropped in here picks up the
   same baseline automatically, with nothing to remember to restate. */
.filter-pill > * {
  display: inline-flex;
  align-items: center;
  font: inherit;
  line-height: 1;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  appearance: none;
  color: inherit;
  vertical-align: baseline;
}

/* Position only — display, alignment and type all come from the reset
   above. */
.filter-dd {
  position: static;
}

/* The two static words are not interactive, so they sit back; the two
   values carry the full-strength text. Colour only — no type metrics. */
.filter-pill > span:not(.filter-pill__break) {
  color: rgba(0, 0, 0, 0.55);
}

/* Forces the pill's two-line break under 900px; inert above it. Its own
   `display: none` has to be restated: it is exactly as specific as the
   universal reset above and comes later in the file, so without it the
   reset's `display: inline-flex` would win and the spacer would never
   hide. */
.filter-pill__break {
  display: none;
  flex-basis: 100%;
  height: 0;
}

/* The real <button> sits a level deeper than the universal reset
   reaches, and is the one element in the pill that needs `font:
   inherit` stated explicitly — the UA stylesheet stops it inheriting
   on its own. Everything else here mirrors the reset above for the
   same reason it exists on every other child. */
.filter-dd__btn {
  display: inline-flex;
  align-items: center;
  font: inherit;
  border: 0;
  background: none;
  appearance: none;
  vertical-align: baseline;

  /* The only interactive part of the pill, so it alone gets full-strength
     text and a pointer. */
  color: #000000;
  cursor: pointer;

  /* The hover chip's box, carried at rest with a transparent background
     and cancelled by an equal negative margin — so the margin-box still
     measures exactly what `padding: 0` gave it and the flex layout,
     gaps and baseline are all unchanged. Hover then only has to animate
     a colour, never geometry: nothing can shift.
     This is not a per-child type metric — no font-size, line-height or
     vertical-align is introduced, and the box nets to zero. */
  padding: 3px 6px;
  margin: -3px -6px;
  border-radius: 3px;
  transition: background 200ms ease;
}

.filter-dd__btn:hover {
  background: rgba(0, 0, 0, 0.06);
}

/* ----- Rolling value -----
   A window with the text absolutely positioned inside it: the outgoing
   line rolls up and out while the incoming one rolls in from below, so
   the value reads as a counter wheel. The width is set by JS from an
   off-screen measurement and transitions on the same curve, so the
   pill grows and shrinks with the text instead of snapping. Both spans
   carry no type CSS of their own — they inherit it from the button
   above, so there is nothing here to fall out of sync with the
   container. */
.filter-dd__value {
  display: inline-flex;
  align-items: center;
  position: relative;
  overflow: hidden;
  height: 1em;
  transition: width 0.5s cubic-bezier(0.65, 0, 0.35, 1);
}

.filter-dd__text {
  position: absolute;
  left: 0;
  top: 0;
  display: block;
  height: 1em;
  white-space: nowrap;
  opacity: 1;
  transform: translateY(0);
  transition:
    transform 0.5s cubic-bezier(0.65, 0, 0.35, 1),
    opacity 0.5s cubic-bezier(0.65, 0, 0.35, 1);
}

/* Start state for the incoming line — no transition, so releasing the
   class is what animates it. */
.filter-dd__text.is-entering {
  opacity: 0;
  transform: translateY(100%);
  transition: none;
}

.filter-dd__text.is-leaving {
  opacity: 0;
  transform: translateY(-100%);
}

/* Off-screen ruler for measuring the incoming text. JS appends it
   inside the button, so it inherits the exact same type through the
   button's own `font: inherit`. It must NOT set a weight of its own —
   that was the bug that let the ruler measure at a different weight
   than the text actually rendered at, quietly mis-sizing every roll. */
.filter-dd__measure {
  position: absolute;
  left: -9999px;
  top: 0;
  white-space: nowrap;
  pointer-events: none;
  visibility: hidden;
}

/* Sizes every icon in the pill off the container's own font-size — a
   chevron, or any icon added later, matches automatically with nothing
   to tune per instance. */
.filter-pill svg {
  display: block;
  width: 0.62em;
  height: 0.62em;
  flex-shrink: 0;
  align-self: center;
  margin-left: 6px;
  transition: transform 200ms ease;
}

/* Overrides the SVG's own stroke-width attribute — a CSS property beats
   a presentation attribute regardless of source order. */
.filter-pill svg path {
  stroke-width: 1px;
}

/* Flips on hover as well as when open — hovering an already-open
   dropdown lands on the same 180deg, so the two states never fight. */
.filter-dd.is-open .filter-dd__chev,
.filter-dd__btn:hover .filter-dd__chev {
  transform: rotate(180deg);
}

/* ----- Panel: a wide light box ABOVE the pill, centred on it ----- */
.filter-dd__panel {
  position: absolute;
  bottom: calc(100% + 12px);
  left: 50%;
  min-width: 640px;
  z-index: 5;
  padding: 28px;
  border-radius: 4px;
  background: #e9e9e9;
  /* Closed: kept in the layout but inert, so the enter animation runs */
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateX(-50%) translateY(8px);
  transition:
    opacity 0.25s ease-out,
    transform 0.25s ease-out,
    visibility 0s linear 0.25s;
}

.filter-dd.is-open .filter-dd__panel {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateX(-50%) translateY(0);
  transition:
    opacity 0.25s ease-out,
    transform 0.25s ease-out,
    visibility 0s;
}

/* ----- Chips: inline tags wrapping across centred lines ----- */
.filter-dd__options {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  /* Cancels the chips' own 3px margin at the panel's inner edges. */
  margin: -3px;
}

.filter-dd__chip {
  margin: 3px;
  padding: 5px 9px;
  border: 0;
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.06);
  font: inherit;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.3;
  color: #111111;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.2s ease;
}

.filter-dd__chip:hover {
  background: rgba(0, 0, 0, 0.14);
}

/* ----- Clear: bottom-right of the panel's inner padding, under the chips.
   Plain text, no box of its own, so the panel's size and background are
   untouched. Inert while nothing is selected in that panel. ----- */
.filter-dd__clear {
  display: block;
  margin-left: auto;
  margin-top: 16px;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 12px;
  line-height: 1.3;
  color: #8a8a8a;
  cursor: pointer;
  transition: color 0.2s ease;
}

.filter-dd__clear:hover {
  color: #1a1a1a;
}

.filter-dd__clear.is-empty {
  opacity: 0.4;
  pointer-events: none;
  cursor: default;
}

@media (max-width: 900px) {
  /* Two lines: "We design <value>" / "for <value>". The break element
     forces the wrap at that exact point instead of leaving it to the
     value lengths. Only the pill wraps — each value keeps its own
     single-line roll window, so the animation is untouched. Font-size
     and padding are NOT overridden here: the container's clamp()
     already covers this width, and restating a fixed px value at this
     one breakpoint is exactly the kind of second source of truth the
     single-definition rule above exists to prevent. */
  .filter-pill {
    flex-wrap: wrap;
    justify-content: center;
    text-align: center;
    max-width: calc(100vw - 60px);
    white-space: normal;
  }

  .filter-pill__break {
    display: block;
  }

  .filter-dd__panel {
    min-width: calc(100vw - 40px);
    padding: 20px;
  }
}

@media (max-width: 700px) {
  .filter-dd__chip {
    font-size: 12px;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* Value swaps instantly; the panel still opens, just without the rise */
  .filter-dd__value,
  .filter-dd__text,
  .filter-dd__panel {
    transition: none !important;
  }
}
