/* --------------------------------------------------------------------------
   1 · HERO LEDE ON PHONES
   --------------------------------------------------------------------------
   The inherited stylesheet hides `.intro-supporting` outright below 699px:

       @media (max-width: 699px) { .intro-supporting { display: none !important; } }

   Its comment explains why — the five intro chips need to clear the floating
   bottom nav on shorter phones. That was fine when the lede was a decorative
   sentence. It is not fine now: the lede carries the core positioning
   statement, and hiding it means phone visitors never see what Florian does.

   Measured (test-mobile-lede.mjs, chips bottom vs floating-nav top):

       375x667 (iPhone SE)   shown -> chips 647 vs nav 595   COLLIDES
       390x844               shown -> chips 735 vs nav 772   clears
       430x932               shown -> chips 792 vs nav 860   clears

   So it is a SHORT-PHONE problem, not a mobile problem. Show the lede whenever
   there is vertical room for it, and keep the inherited hide where the collision
   is real.

   Finding the floor took two passes. 720px was a guess and it was WRONG — at
   exactly 720 the chips still collide (662 vs 648). Measured sweep:

       375 x 667   chips 647 vs nav 595   collides
       390 x 700   chips 664 vs nav 628   collides
       390 x 720   chips 662 vs nav 648   collides   <- the guessed floor, bad
       390 x 780   chips 689 vs nav 708   clears by 19px  (tight)
       390 x 844   chips 724 vs nav 772   clears by 48px
       430 x 932   chips 781 vs nav 860   clears by 79px

   800px is the floor used below: comfortably past the last collision, and it
   keeps the 19px squeeze at 780 out of scope. Modern phones (iPhone 12 and
   later are 844+, most Android 800+) get the lede; short and older phones keep
   the inherited hide.
   -------------------------------------------------------------------------- */
@media (max-width: 699px) and (min-height: 800px) {
  .intro-supporting {
    display: block !important;
    margin: 14px 16px 0;
    font-size: 15px;
    line-height: 1.45;
    max-width: 34ch;
  }
}


/* --------------------------------------------------------------------------
   2 · INTRO KEYWORD PILLS — drop in, don't just fade
   --------------------------------------------------------------------------
   The pills previously only cross-faded their opacity, which read as flat. They
   now fall a short distance into place, land with a slight overshoot, and stagger
   one after another rather than arriving as a block.

   Two things make this work:
     - `js/site.js` no longer sets an inline `transform` on intro pills. It
       writes the rotation to `--pill-rot` instead, so the stylesheet can compose
       translate + rotate. An inline transform would win and kill the movement.
     - `--pill-delay` is set per pill from its placement index.

   The overshoot curve (0.34, 1.4, 0.64, 1) goes slightly past the resting
   position and settles back — that is what reads as weight rather than a slide.
   -------------------------------------------------------------------------- */
#intro-pills .footer-pill {
  opacity: 0;
  transform: translateY(-38px) var(--pill-rot, rotate(0deg));
  transition:
    opacity 0.34s ease-out var(--pill-delay, 0ms),
    transform 0.66s cubic-bezier(0.34, 1.4, 0.64, 1) var(--pill-delay, 0ms);
}

#intro-pills.is-visible .footer-pill {
  opacity: 1;
  transform: translateY(0) var(--pill-rot, rotate(0deg));
}

/* Anyone who has asked their system not to animate gets them placed, not
   thrown. The inherited JS already skips the pill field entirely under
   reduced-motion, but this keeps the CSS honest on its own terms. */
@media (prefers-reduced-motion: reduce) {
  #intro-pills .footer-pill,
  #intro-pills.is-visible .footer-pill {
    opacity: 1;
    transform: var(--pill-rot, rotate(0deg));
    transition: none;
  }
}


/* --------------------------------------------------------------------------
   3 · FOOTER PILLS — motion support
   --------------------------------------------------------------------------
   The footer pills now move: they spawn into a pile, then cycle between a
   scattered layout across the whole footer and settling back down. See the
   long comment in js/site.js for why (short version: the reference site's
   pills span 1,124px of a 906px container and move on their own, and a static
   packer can never match that).

   Three inherited rules needed adjusting.
   -------------------------------------------------------------------------- */

#footer-pills {
  /* base-extracted.css:4624 sets `overflow: hidden` to hide pills parked above
     the box before they drop. Our spawn parks them via transform instead, and
     a footer-wide scatter needs the full box usable — clipping would cut pills
     at the edges mid-cycle. Placement keeps everything inside the container
     anyway, so nothing should ever actually need to overflow.

     NOTE: we deliberately do NOT reproduce the reference's pills-at-negative-y.
     That comes from a real coordinate-space bug in its code (it mixes viewport
     and container origins), not from a design decision. */
  overflow: visible;
}

.footer-pill {
  /* base-extracted.css:4656 hints `will-change: top, transform`. `top` is a
     layout property — animating it forces layout on every frame. All motion
     now travels through `transform: translate3d()`, which the compositor can
     handle on its own, so re-hint accordingly. */
  will-change: transform;
  /* Rotation and position are composed into ONE transform string by the JS.
     Nothing else may write `transform` on a footer pill, or half of it is
     silently lost. */
  backface-visibility: hidden;
}

@media (prefers-reduced-motion: reduce) {
  /* Pills are placed instantly by the JS in this mode — belt and braces so no
     inherited transition can reintroduce movement. */
  #footer-pills .footer-pill {
    transition: none !important;
    animation: none !important;
  }
}


/* --------------------------------------------------------------------------
   4 · WORK DOT RAIL — show that more projects exist
   --------------------------------------------------------------------------
   `.section-pills__dots` is capped at `max-height: 50vh` with `overflow-y: auto`
   and its scrollbar hidden on purpose. Measured after "show more" at 1913x906:
   25 projects, 25 dots created, box 453px against 584px of content — so only 19
   were reachable. "Tallow" sat half-clipped on the bottom edge and everything
   from "Umbra" on was invisible, while its panels kept rendering on the right.

   The cap is not the problem: the rail shares the sidebar with Home / Trusted /
   Work / Process / Testimonials / About, and an uncapped 584px list would push
   those off screen — worse on short laptops. The problem was that nothing
   scrolled it and nothing showed there was more.

   site.js now scrolls the rail to follow the active project and toggles
   these two classes. The mask fades the dots out at whichever edge still has
   content beyond it, so the list reads as continuing rather than ending.
   -------------------------------------------------------------------------- */
.section-pills__dots.has-more-above {
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 22px);
          mask-image: linear-gradient(to bottom, transparent 0, #000 22px);
}

.section-pills__dots.has-more-below {
  -webkit-mask-image: linear-gradient(to top, transparent 0, #000 22px);
          mask-image: linear-gradient(to top, transparent 0, #000 22px);
}

/* Both edges at once — the common case in the middle of a long list. */
.section-pills__dots.has-more-above.has-more-below {
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 22px, #000 calc(100% - 22px), transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0, #000 22px, #000 calc(100% - 22px), transparent 100%);
}

/* The rail follows the active project as you scroll. Smooth scrolling makes
   that legible rather than a jump — but honour a reduced-motion preference. */
.section-pills__dots { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  .section-pills__dots { scroll-behavior: auto; }
}


/* --------------------------------------------------------------------------
   5 · INVISIBLE HERO PILLS WERE EATING CLICKS (inherited bug)
   --------------------------------------------------------------------------
   Florian: the "Show more project examples" button "sometimes only works when
   I click exactly where the text is — it is almost like something is on top of
   it". He was right, and it was worse than one button.

   `#intro-pills` is `position: fixed; inset: 0; z-index: 500` — it covers the
   ENTIRE VIEWPORT, permanently, at a very high stacking level. The container
   sets `pointer-events: none`, but base-extracted.css:4597-4599 then gives every
   pill inside it `pointer-events: auto`. Scrolling away from the hero only sets
   the container to `opacity: 0` — and opacity does NOT stop hit-testing.

   So invisible hero pills float over the whole page and silently swallow any
   click that lands on one. Measured with document.elementFromPoint over a 9x5
   grid on the button:

       brand-site   1913x906  14% of the button blocked
                    1440x900  41%
                    1280x800  42%
       frozen reference 1440x900  63%   <- inherited, not introduced by us

   This affects anything the hero pills happen to sit over, not just this
   button — it was simply most noticeable on a small target.

   Fix: hero pills are only interactive while they are actually visible. The
   `.is-visible` class is toggled by site.js when scrollY < 60.
   -------------------------------------------------------------------------- */
#intro-pills:not(.is-visible) .footer-pill {
  pointer-events: none !important;
}


/* --------------------------------------------------------------------------
   6 · PROCESS PANELS — the section that was entirely missing
   --------------------------------------------------------------------------
   `#process-panel` and `#process-chips` both shipped empty. The stylesheet
   already carried the treatment (77 rules for `.process-panel`, 25 for
   `.ph-block`, plus `.ph-diagram-wrap`, `.ph-faqs-toggle`, `.ph-faqs-panel`),
   so what follows is only the pieces it had no rules for: the phase spine
   labels, the capability accordions, and the diagram placeholder.

   NOTE the inherited reset at base-extracted.css:1372 —
       .process-panel * { padding-left: 0 !important; max-width: none !important }
   — which is why several rules below need `!important` to restore any inset.
   -------------------------------------------------------------------------- */

/* --- FIX 1: only the chosen discipline may render ---
   base-extracted.css:1383 sets `.process-panel > * { display: block }`, and the
   `.ph-stack` rule resolves to `display: grid`. Either one beats the `hidden`
   attribute (which only works because the UA stylesheet says `display: none`),
   so ALL THREE stacks rendered at once no matter which chip was clicked —
   Florian saw one discipline's content followed by the other two. The JS was
   setting `hidden` correctly the whole time; nothing was listening. */
.process-panel .ph-stack[hidden] {
  display: none !important;
}

/* --- FIX 2: the em-dash bullet was sitting ON the text ---
   base-extracted.css:3307 draws list bullets as `content: '—'` positioned
   `absolute; left: 0`, relying on the `li` carrying `padding-left: 18px` to
   make room. The panel's brute-force reset — `.process-panel * { padding-left:
   0 !important }` at line 1372 — removes that padding, so the dash landed on
   top of the first characters and read as a strikethrough through the first two
   letters of every bullet. Restore the inset the bullet needs. */
.process-panel .faq-a ul li {
  padding-left: 20px !important;
  position: relative;
}
.process-panel .faq-a ul li::before {
  left: 0;
  opacity: 0.55;
}

/* The phase spine: Discover > Define > Design  ·  Build > Test > Handover.
   Repeated in all three panels, which is what makes them read as one method
   rather than three unrelated brochures. */
.process-panel .ph-phase {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 13px;
  letter-spacing: 0.06em;
  color: var(--text-2, #5A5650);
  margin: 34px 0 14px !important;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.process-panel .ph-phase span {
  opacity: 0.45;
}
.process-panel .ph-block--pills .ph-phase:first-child {
  margin-top: 0 !important;
}

/* Capability accordions — white pills, matching the intro chips, so the whole
   page uses one control vocabulary. Click, not hover. */
.process-panel .ph-cap-q {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  background: #ffffff;
  color: #1a1a18;
  border: none;
  border-radius: 999px;
  padding: 13px 26px !important;
  margin: 0 10px 10px 0 !important;
  font-family: 'Inter', sans-serif;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.3;
  text-align: left;
  cursor: pointer;
  transition: background 0.18s ease, transform 0.18s ease;
  box-shadow: 0 1px 2px rgba(26, 26, 24, 0.06);
}
.process-panel .ph-cap-q:hover {
  background: #F4F3EE;
}
/* NO colour change on the pill itself, and NO `::after` arrow of my own.
   State is carried by the `.faq-icon` badge, exactly as the landing FAQ does
   it: #FFD600 closed, #f0c800 hover, #FF5733 rotated when open. Inventing a
   second treatment here gave one interaction two appearances on one page. */

/* The expanded body. `.faq-a` visibility is handled by the inherited rules
   (display none/block off the sibling button's aria-expanded). */
.process-panel .ph-block--pills .faq-a {
  max-width: 62ch !important;
  margin: 2px 0 26px !important;
  padding-left: 26px !important;
  border-left: 2px solid rgba(26, 26, 24, 0.12);
}
.process-panel .ph-block--pills .faq-a p {
  font-family: 'Inter', sans-serif;
  font-size: 1.02rem;
  line-height: 1.7;
  color: var(--text-2, #5A5650);
  margin: 0 0 14px;
}
.process-panel .ph-block--pills .faq-a ul {
  margin: 0;
  padding-left: 1.15em !important;
}
.process-panel .ph-block--pills .faq-a li {
  font-family: 'Inter', sans-serif;
  font-size: 0.97rem;
  line-height: 1.6;
  margin-bottom: 6px;
}

/* --- FIX 3: FAQ questions are pills, not plain rows ---
   They were styled as full-width text with a hairline underneath, which reads
   as a plain list and is harder to scan. They now match the capability pills
   above them, so the whole panel uses one control vocabulary: a pill you click,
   which turns dark when open and drops its answer underneath. */
.process-panel .ph-faqs-panel .faq-q {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  width: auto;
  max-width: 100%;
  text-align: left;
  background: #ffffff;
  color: #1a1a18;
  border: none;
  border-radius: 999px;
  padding: 13px 26px !important;
  margin: 0 10px 10px 0 !important;
  font-family: 'Inter', sans-serif;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.3;
  cursor: pointer;
  transition: background 0.18s ease;
  box-shadow: 0 1px 2px rgba(26, 26, 24, 0.06);
}
.process-panel .ph-faqs-panel .faq-q:hover {
  background: #F4F3EE;
}
/* Same as the capability pills above: the pill stays white and the `.faq-icon`
   badge carries the state, matching the landing FAQ exactly. */
/* Answer drops below its pill, indented to line up with the pill's text and
   marked with a rule so it clearly belongs to the question above it. */
.process-panel .ph-faqs-panel .faq-a {
  max-width: 62ch !important;
  margin: 2px 0 22px !important;
  padding-left: 26px !important;
  border-left: 2px solid rgba(26, 26, 24, 0.12);
}
.process-panel .ph-faqs-panel .faq-a p {
  font-family: 'Inter', sans-serif;
  font-size: 1rem;
  line-height: 1.7;
  color: var(--text-2, #5A5650);
  margin: 0;
}

/* Diagram placeholder — holds the slot at a sensible ratio until Florian's
   real process diagram exists. Deliberately obvious rather than decorative,
   so nobody mistakes it for finished artwork. */
.process-panel .ph-diagram--placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 16 / 7;
  width: 100%;
  border: 1px dashed rgba(26, 26, 24, 0.25);
  border-radius: 14px;
  background: repeating-linear-gradient(
    45deg, rgba(26,26,24,0.02) 0 12px, rgba(26,26,24,0.05) 12px 24px);
  color: rgba(26, 26, 24, 0.45);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin: 8px 0 30px;
}

/* The discipline picker chips */
.process-chips {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  margin-top: 26px;
}
.process-chips[hidden] { display: none; }


/* --------------------------------------------------------------------------
   7 · INTRO CHIPS — five long labels
   --------------------------------------------------------------------------
   The five discipline chips now carry considerably longer labels than the
   placeholders they replaced. They already wrap and re-flow correctly at every
   width tested (1920 / 1440 / 1366 / 1280 / 834 / 390), so there is deliberately
   NO sizing override here — this block is a marker, not a fix.

   If a sixth chip is ever added, re-run:
       the hero check script in the project tooling
   and check `chipsBottom` against the viewport at 1366x768, which is the
   tightest common desktop case.
   -------------------------------------------------------------------------- */


/* ==========================================================================
   8 · SELECTED WORK — original cards, no images, sticky category rail
   --------------------------------------------------------------------------
   The card design is the page's own: .work-thumb boxes styled by
   `.work-zoom[data-view="rows"] .work-thumb` in base-extracted.css. Only the
   image strip was removed, so most of what follows is repairing the gaps that
   leaves — padding that assumed a photo beneath, a divider that assumed
   something after it, and a mobile rule that hid the text because the image
   was meant to carry the card.
   ========================================================================== */

/* The section is a 248px + 1fr grid for the sticky rail — that survives.
   Only the top padding changes, since the banner now sits above it. */
.work-zoom--list[data-view="rows"] { padding-top: 40px !important; }

/* ─── Group heading above each run of cards ──────────────────────────── */
.work-group {
  /* Clears the fixed chrome when a hero chip or a rail item jumps here. */
  scroll-margin-top: 100px;
}
.work-group + .work-group { margin-top: 72px; }
.work-group__title {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: clamp(1.1rem, 1.6vw, 1.5rem);
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--text);
  margin: 0 0 22px;
}

/* ─── Card repairs after removing the image strip ────────────────────── */
.work-zoom--list[data-view="rows"] .work-thumb {
  /* The card was sized by its images; with those gone it needs its own
     bottom padding or the pills sit flush against the edge. */
  padding-bottom: 4px;
}
.work-zoom--list[data-view="rows"] .work-thumb:hover {
  /* The lift implied "click me". Nothing here is clickable any more. */
  transform: none;
}
.work-zoom--list[data-view="rows"] .work-thumb__meta {
  /* Was 150px of right padding to clear the round arrow button. */
  padding-right: 28px;
  /* The rule below it separated the text from the images. Nothing follows
     it now, so it read as a stray line across the bottom of every card. */
  border-bottom: 0;
  margin-bottom: 0;
}

@media (max-width: 980px) {
  .work-zoom--list[data-view="rows"] .work-zoom__sticky {
    /* The rail unsticks and lies flat above the cards. */
    margin-bottom: 8px !important;
  }
}

@media (max-width: 699px) {
  /* The stock mobile rule hides the card text and reveals it only via an
     expand chevron — because on the original the image was the card. With no
     image there would be nothing left to see, so the text always shows. */
  .work-zoom--list[data-view="rows"] .work-thumb .work-thumb__meta {
    display: grid !important;
    grid-template-columns: 1fr !important;
    gap: 14px !important;
    padding: 0 18px 18px 18px !important;
  }
  .work-zoom--list[data-view="rows"] .work-thumb {
    padding-top: 18px !important;
    cursor: default !important;
  }
  .work-zoom--list[data-view="rows"] .work-thumb::after { display: none !important; }
  .work-group + .work-group { margin-top: 48px; }
  .work-group__title { font-size: 1.3rem; margin: 0 4px 16px; }
}

/* ==========================================================================
   9 · LAUNCH ADJUSTMENTS — see _internal/archive/REMOVED-FOR-LAUNCH.html
   ========================================================================== */

/* Florian's real biography is roughly twice the placeholder it replaced, and
   the stock 1200px cap clipped it against `overflow:hidden`. Still finite so
   the height transition keeps working. */
.about-more-body.is-expanded { max-height: 2600px; }

.about-tagline {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 1.02rem;
  line-height: 1.5;
  color: var(--text-2);
  margin: 14px 0 0;
  max-width: 46ch;
}

/* With the X card gone, LinkedIn's `flex:1` stretched it across the full row
   and read as a mistake. RESTORING THE X CARD MEANS DELETING THIS RULE. */
/* No width cap on .social-cards-row. One was added when the X card was removed,
   assuming a lone card would look stretched — it never applied (
   base-extracted.css:3686 uses `.social-profiles .social-cards-row`, which is
   more specific and wins), and with the real avatar, name and logo on it the
   row reads as a profile banner at its own 540px rather than as a gap. */


/* --- Card separation ------------------------------------------------------
   The old layout got its row gap from .work-panel__grid, which is not used
   here (rows() caps that grid at 11 items and would hide 24 of the 35).
   Without it the cards butt together and read as one long white slab.
   18px rather than the original 128px — that spacing existed to give a large
   image strip room to breathe, and there are no images now. */
.work-list { display: flex; flex-direction: column; gap: 18px; }
.work-group { display: flex; flex-direction: column; gap: 18px; }

/* The decorative "..." in each card's top-right implied there was more to
   open. There is not — the whole entry is already on the card. */
.work-zoom--list[data-view="rows"] .work-thumb::after { display: none !important; }

/* --- Mobile: room for the absolutely-positioned card title ----------------
   .work-thumb__label is `position:absolute; top:18px` by design — on the
   original it floated over the image strip. With the images gone the meta
   starts at the top of the card and the title landed on top of the "WHO"
   label. The card needs explicit headroom for it. */
@media (max-width: 699px) {
  .work-zoom--list[data-view="rows"] .work-thumb {
    padding-top: 48px !important;
  }
  .work-zoom--list[data-view="rows"] .work-thumb .work-thumb__meta {
    padding-top: 0 !important;
  }
  .work-zoom--list[data-view="rows"] .work-thumb__label {
    /* Wrap rather than run off the card on a 390px screen. */
    right: 18px;
    line-height: 1.25;
  }
}

/* One rule sets  on the card title (base-extracted.css:830)
   and a later one sets  without resetting it, so the title's box
   is stretched the full height of the card. Invisible when it floated over an
   image; here it makes the element's real position unreadable to anything
   measuring it. Reset so the box is the size of the text. */
.work-zoom--list[data-view="rows"] .work-thumb__label {
  bottom: auto;
}

@media (max-width: 699px) {
}

/* --- Mobile: let the card title flow instead of floating ------------------
   Fixed headroom only works if every title is the same height. It is not —
   "Raumfeld Worldwide Testing Programme" wraps to three lines at 390px and
   ran straight into the WHO label. Taking the title out of absolute
   positioning makes the card correct for any title length, now and later. */
@media (max-width: 699px) {
  .work-zoom--list[data-view="rows"] .work-thumb__label {
    position: static;
    display: block;
    top: auto; left: auto; right: auto; bottom: auto;
    padding: 18px 18px 12px 18px;
  }
  .work-zoom--list[data-view="rows"] .work-thumb {
    padding-top: 0 !important;
  }
}
