/* weave.clinic search: the nav trigger and the Pagefind modal theme.
   Added 2026-09-04 with the site-wide index (intent 2026-09-04-site-search).

   Two vocabularies drink from this file. The estate carries css/tokens.css
   (--cloth, --ink, --hairline-firm, --thread-sage). The Family Library never
   links tokens.css and carries its own (--paper, --ink, --line-strong,
   --accent-strong). Every value below is written token-first with the family
   name as the fallback and a literal as the last resort, so one sheet themes
   both routes and neither has to grow a copy that can drift.

   The --pf-* variables are Pagefind's own theming surface. They are set on the
   elements that host the component, never on :root, which is the containment
   404.html chose when the study index shipped in June: the vendor's names are
   generic enough that leaking them sitewide would be a latent collision. */

/* ------------------------------------------------------------------ theme */
.nav-search,
.langbar-search,
pagefind-modal {
  --pf-font: var(--font-ui, "Switzer", system-ui, sans-serif);
  --pf-text: var(--ink, #2B2320);
  --pf-text-secondary: var(--ink-2, var(--muted, #574B41));
  /* The vendor paints the trigger label AND the trigger icon with
     --pf-text-muted. House rule 41 puts labels on the 4.5:1 floor, and the
     site's --ink-3 (#6E6157 on white) sits at 4.9:1 while the family --faint
     is 4.6:1, so both clear it. This is a label, not a placeholder. */
  --pf-text-muted: var(--ink-3, var(--faint, #6E6157));
  --pf-background: var(--cloth, var(--paper, #FFFFFF));
  --pf-border: var(--hairline-firm, var(--line-strong, #C9BFB1));
  --pf-border-focus: var(--thread-sage, var(--accent-strong, #587F59));
  --pf-outline-focus: var(--thread-sage, var(--accent-strong, #587F59));
  --pf-outline-width: 2px;
  --pf-outline-offset: 2px;
  --pf-hover: var(--fill-cool, var(--accent-soft, #F3EFE8));
  --pf-mark: var(--thread-sage, var(--accent-strong, #587F59));
  --pf-skeleton: var(--fill-cool, var(--accent-soft, #F3EFE8));
  --pf-skeleton-shine: var(--cloth-card, var(--paper, #FFFFFF));
  --pf-border-radius: var(--radius-sm, 0.5rem);
  /* Rule 42: 44 by 44 CSS px on every interactive control. The vendor default
     is 36px, and it drives the trigger button and the modal input alike. */
  --pf-input-height: 44px;
  --pf-input-font-size: 1rem;
  --pf-summary-font-size: 1rem;
  --pf-result-title-font-size: 1.0625rem;
  --pf-result-excerpt-font-size: 1rem;
}

/* ---------------------------------------------------------------- trigger */
/* The li reserves the trigger's finished size before the custom element
   upgrades, so the pill never reflows when the module lands. Measured on
   study/index.html at 1280 with the component script blocked: the natural
   defined width is 110.78px, so the reserve is 7rem (112px) and the button,
   at width 100 percent, fills it exactly. Reserved and defined then agree to
   the pixel and the only remaining question is the pill, which measured
   79.16px tall in both states, unchanged from before the trigger existed. */
.nav-search {
  display: flex;
  align-items: center;
  min-width: 7rem;
  min-height: 44px;
}

.nav-search pagefind-modal-trigger,
.langbar-search pagefind-modal-trigger {
  display: block;
  width: 100%;
}

/* The component's own rules carry :is(*, #\#) three times over, a documented
   trick in pagefind-component-ui.css that buys ID-level specificity without an
   ID. Two of its values fail house rules here: the trigger label ships at 14px
   against the 16px floor, and the border is a hairline the pill does not want.
   Height is a variable, so it is set in the theme block above. Font size is
   hard-coded, so this answers the vendor in its own idiom rather than reaching
   for !important, which would be harder to unpick later. */
:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) .nav-search .pf-trigger-btn,
:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) .langbar-search .pf-trigger-btn {
  gap: 0.5rem;
  padding: 0 0.875rem;
  border-radius: 4px 9px 5px 10px;
  font-family: var(--pf-font);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--pf-text-muted);
}

:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) .nav-search .pf-trigger-btn:hover,
:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) .langbar-search .pf-trigger-btn:hover {
  border-color: var(--pf-border-focus);
  color: var(--pf-text);
  background: var(--pf-hover);
}

/* The icon is a mask, so it takes its colour from background. 14px is the
   vendor size; the label beside it carries the meaning and the 16px floor. */
:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) .nav-search .pf-trigger-icon,
:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) .langbar-search .pf-trigger-icon {
  width: 16px;
  height: 16px;
}

/* ------------------------------------------------- family langbar variant */
/* The Family Library booklets have no site nav. Their header row is the
   langbar, five language links wide, and at 390 that row has no space left,
   so the trigger sits on its own row directly beneath it (measured, see the
   ledger entry for 2026-09-04). Left-aligned to the langbar's own inset. */
.langbar-search {
  display: flex;
  align-items: center;
  min-height: 44px;
  margin: 0 auto;
  padding: 0 var(--reader-pad, 1.25rem) 0.75rem;
  max-width: var(--reader-max, 46rem);
}

.langbar-search pagefind-modal-trigger {
  max-width: 14rem;
}

/* ------------------------------------------------------------------ modal */
/* pagefind-modal holds a real <dialog> opened with showModal(), so the focus
   trap, Escape and the backdrop click are the platform's, not ours. It sits at
   the end of body and paints nothing until it opens. */
pagefind-modal {
  display: block;
}

/* Three controls inside the modal ship under the 44px floor of house rule 42.
   Measured in the open modal on study/index.html, 2026-09-04: the search input
   40px tall (its own rule overrides --pf-input-height inside the header), the
   clear button 36px, and the close button 40 by 40, which only appears below
   768px. Everything else already passes: result cards 74px with 8px between,
   sub-result chips 52.4px, and the whole card is the target because the vendor
   stretches the link with an inset-0 ::after. Same specificity idiom as above. */
:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) pagefind-modal-header .pf-input,
:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) .pf-modal-header .pf-input {
  height: 44px;
}

:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) pagefind-modal .pf-input-clear {
  height: 44px;
  min-height: 44px;
}

:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) pagefind-modal .pf-modal-close {
  min-width: 44px;
  min-height: 44px;
}

/* ------------------------------------------- the text floor inside the modal */
/* An open dialog is a surface no page-loading gate has measured. cognitive-gate
   loads a page; it never opens the component, so rule 41's 16px body and label
   floor, its absolute floor and its 1.4 line-height all read on a modal that is
   not there. Measured with modal-text-probe.js, which opens the modal, runs a
   real query, expands a card so the sub-results render, and walks every element
   that owns a text node. The probe lives in
   intent/2026-09-04-site-search/evidence/ rather than scripts/capture-harness/,
   because plan.md names one file in that directory and a build lane does not
   widen its own plan; adopting it into the gate is todo c098c803. All four rows (1280 and 390,
   light and dark) returned the same five failures, and the vendor hard-codes
   every one of them with no variable:

     kbd.pf-keyboard-key      10px / 1.5    the key chips
     a.pf-heading-link        12px / 1.3    the sub-result titles
     button.pf-input-clear    12px          the Clear control's label
     div.pf-keyboard-hint     12px / 1.5    the hint row beside the chips
     p.pf-heading-excerpt     12px / 1.4    the sub-result excerpts

   All five come to 1rem here, and the two line-heights under 1.4 come up with
   them. The keyboard chip and its hint row move together: a 16px chip beside a
   12px label inverts the hierarchy the floor exists to protect, because the
   words are what a reader needs and the chip is only the key they press.

   Sub-results stay subordinate the way the ruling allows, by weight, colour
   and indent rather than by size. They already sit in an indented chip behind
   a "#" prefix and their excerpt already takes --pf-text-secondary; what was
   missing is weight on the thing they sit under, so the result title takes 600
   and leads at 17px against the sub-title's 16. No colour is touched, so no
   contrast reading moves. */
:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) pagefind-modal pagefind-keyboard-hints,
:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) pagefind-modal .pf-keyboard-hints,
:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) pagefind-modal .pf-keyboard-hint,
:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) pagefind-modal .pf-keyboard-key,
:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) pagefind-modal .pf-modal-footer-key,
:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) pagefind-modal .pf-input-clear {
  font-size: 1rem;
}

:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) pagefind-modal .pf-heading-link {
  font-size: 1rem;
  line-height: 1.4;
}

:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) pagefind-modal .pf-heading-excerpt {
  font-size: 1rem;
  line-height: 1.5;
}

:is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) pagefind-modal .pf-result-link {
  font-weight: 600;
}

/* ------------------------------------------------------- reduced motion */
/* The vendor already gates its two keyframe animations behind
   (prefers-reduced-motion: no-preference). Its trigger transition is not
   gated, so rule 40 is finished here. */
@media (prefers-reduced-motion: reduce) {
  :is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) .nav-search .pf-trigger-btn,
  :is(*, #\#):is(*, #\#):is(*, #\#):is(*, #\#) .langbar-search .pf-trigger-btn {
    transition: none;
  }
}
