/* ---------------------------------------------------------------------------
   THE CHURCH DIRECTORY   /members/directory/

   Layout, and only layout. Who may see this page is settled in
   plugin/tcf-church/includes/directory-page.php, which renders nothing at all
   for a guest; nothing here is load-bearing for that and nothing here should
   ever become so.

   Component-scoped rather than scoped to a body class, because the shortcode
   can be pasted onto any page and the styling has to travel with it - the same
   reasoning the PHP gives for carrying its own login check.

   THE UNIT IS A HOUSEHOLD. Two accounts that share a surname and gave the same
   address are one entry, headed "The Grissom Family", with the first names of
   the people in it on the line below. The PHP header explains the merge rule at
   length; what it means HERE is that an entry is now five or six short lines
   rather than four, and there are roughly half as many of them.

   DRAWN FOR 60-150 HOUSEHOLDS. The first version of this file assumed "forty to
   seventy fits on one page". At a hundred and fifty the one-column mobile list
   is about nine thousand pixels and the three-column desktop list about five and
   a half thousand, which is why there is now a letter band in the list and a
   sticky letter strip above it. Both are gated on `.tcf-dir--indexed`, a class
   the PHP only emits above twenty-five households, so a church with nine
   families gets exactly the plain list it had before.

   STYLE.CSS ALREADY CARRIES ITS HALF OF THIS. The prose-link chain at :708 and
   :723 scores (0,10,4) - ten classes, because every :not() contributes its
   argument's weight - and it beats every link rule below. `:not(.tcf-dir a)` is
   in both chains. That is what makes the rules in this file apply at all, and it
   is also why EVERY link inside .tcf-dir has to be styled here: the global prose
   treatment no longer reaches any of them, including the one in the footnote.
   --------------------------------------------------------------------------- */

/* ---- the component --------------------------------------------------------

   A directory is a wide thing and WordPress's constrained layout wants to
   centre and cap every child of .entry-content. This is the same escape the
   figures and the map already take at style.css:827.
   --------------------------------------------------------------------------- */

.entry-content > .tcf-dir {
  max-width: none;
  margin-left: auto !important;
  margin-right: auto !important;
}

.tcf-dir {
  margin-top: var(--tcf-space-6);
  font-family: var(--tcf-font-ui);
}

/* ---- head: search, home group, count, print --------------------------------

   THE ONE PINNED THING ON A DESKTOP, and that is what changed. It used to be a
   static two-column row and the letter strip below it was what stuck. The strip
   is gone below a hundred and fifty households (see the measurement in
   directory-page.php: the letter bands cost +4400px on a 2923px list at
   thirty-nine households), so the pinned thing is now the bar itself - which is
   the better one to pin anyway, for a reason that only appears once there is a
   filter:

   A FILTER THAT SCROLLS AWAY IS A FILTER THE READER FORGETS IS ON. A member
   three thousand pixels down a directory narrowed to one home group sees twelve
   households and concludes the page is broken. Keeping the select on screen
   keeps the reason on screen with it, and the count beside it says the same
   thing in words.

   On mobile it dissolves (see the media query at the bottom) so the bar can
   stick to the whole page rather than to a hundred-pixel parent, and the filter
   and print link flow underneath it. One pinned thing per surface, about a
   hundred pixels tall, holding whatever that surface actually navigates by.
   --------------------------------------------------------------------------- */

.tcf-dir__head {
  position: sticky;
  top: 0;
  /* Above the list, and above the letter strip's 3 on the off-chance both are
     ever on screen at once. */
  z-index: 4;
  display: flex;
  flex-wrap: wrap;
  /* Bottoms in line: the search field, the select and the print link are three
     different heights and it is their baselines that want to agree. */
  align-items: flex-end;
  column-gap: var(--tcf-space-6);
  row-gap: var(--tcf-space-3);
  margin: 0;
  padding: var(--tcf-space-2) 0 var(--tcf-space-3);
  background-color: var(--tcf-page);
  border-bottom: 1px solid var(--tcf-rule);
}

/* WHERE THE LETTER STRIP EXISTS, THE STRIP IS THE PINNED THING AND THIS IS NOT.
   Both are sticky at top: 0 and they would sit on top of each other; there is no
   honest way to offset one by the other's height in CSS, because that height is
   a label plus a field plus whatever the reader's text size does to them.

   This only ever binds above a hundred and fifty households, which no church on
   this site has yet. Whoever crosses that line should re-measure the two
   together rather than trust this line: the right answer at that size is
   probably one bar holding both, not two bars taking turns. */
.tcf-dir--indexed .tcf-dir__head {
  position: static;
  padding: 0;
  border-bottom: 0;
}

/* THE BASIS IS THE FIELD'S OWN MEASURE, and without it the field shrinks.
   A flex item's automatic basis is its max-content width, and an <input> whose
   width is 100% of its parent contributes almost nothing to max-content - the
   browser falls back to the control's intrinsic ~20-character size. So the bar
   asked for about 220px, got it, and the placeholder rendered as
   "A name, a street, a phoi" at 768px while 125px of the row sat empty.

   `0 0` rather than `0 1`: if a longer set of home group names ever pushes the
   select past the room available, the right failure is the select wrapping to
   its own line, not the search box getting narrower. */
.tcf-dir__bar {
  min-width: 0;
  flex: 0 0 var(--tcf-field-measure-md);
}

/* The search block ships `hidden` and the script un-hides it, so a reader with
   no JavaScript gets the whole directory rather than a dead control. Any
   element given an explicit display has to say this again - it has already
   cost this project a Listen button that would not go away. */
.tcf-dir__search { display: block; }
.tcf-dir__search[hidden] { display: none; }

/* 15px and 8px under it, not 14px and 4px. A field label is a field label on
   every surface: the sign-in card and the profile form both take §1.2's `ui`
   role with an 8px gap, and this one was quietly a step smaller and half as far
   away. DESIGN_SYSTEM_FIELDS.md §4.1 - label size, weight, case and gap are
   constant across surfaces; only colour moves. */
.tcf-dir__search label,
.tcf-dir__filter label {
  display: block;
  margin: 0 0 var(--tcf-space-2);
  font-size: var(--tcf-text-ui);
  font-weight: 600;
  line-height: var(--tcf-leading-sm);
  color: var(--tcf-field-label);
}

/* On the field tokens now. Three notes on what changed and why:

   --tcf-field-text is 16px, down from 17. 17 was chosen to clear the 16px line
   at which iOS zooms the page on focus; 16 IS that line, and the token carries
   the reason. This is the only field on the site that was above it, so it was
   also the only field a step larger than every other.

   --tcf-field-border resolves to #918470, which is the value this rule already
   had. The comment that used to sit here called it "a departure from every
   other field on this site". It is not, any more - it is the token, and the
   argument it makes (a border is the only thing marking where the control is,
   which is what WCAG 1.4.11 asks 3:1 for; `rule` measures 1.24:1) is now made
   once beside the token instead of five times in five files.

   `height: auto` is new and it is why the padding above renders at all: Blocksy
   sets `height` on every form control from --theme-form-field-height, and with
   border-box that swallows the padding. This field only ever cleared 44px
   because it had a `min-height`; every other field on the site was 40.

   `scroll-margin-top` is new too, and it is the letter strip's fault: the
   strip's first item is a link back to this box, and without a scroll margin
   the box lands underneath the very bar that sent you to it. */
.tcf-dir__search input[type="search"] {
  display: block;
  width: 100%;
  /* `md`, 320. The band is the same one an email address takes, and a search
     box has no better claim to width than the longest thing anyone types into
     it. It was 24rem, which was this file's own invention. */
  max-width: var(--tcf-field-measure-md);
  height: auto;
  min-height: var(--tcf-field-min-h);
  padding: var(--tcf-field-pad-y) var(--tcf-field-pad-x) !important;
  font-family: var(--tcf-font-ui);
  font-size: var(--tcf-field-text);
  line-height: 1.4;
  color: var(--tcf-ink);
  background-color: var(--tcf-field-fill);
  border: var(--tcf-field-border-w) solid var(--tcf-field-border);
  border-radius: var(--tcf-radius);
  -webkit-appearance: none;
  appearance: none;
  scroll-margin-top: var(--tcf-space-8);
  transition: border-color var(--tcf-motion-hover) var(--tcf-ease);
}

/* `appearance: none` is needed to stop iOS drawing its own rounded search
   field, and it also takes WebKit's clear button with it. Putting the button
   back is worth the two lines: it is the only mouse-only way to empty the box,
   and the keyboard has Escape. */
.tcf-dir__search input[type="search"]::-webkit-search-cancel-button {
  -webkit-appearance: searchfield-cancel-button;
  appearance: auto;
  cursor: pointer;
}

/* A placeholder is not a label (§5.5) so it may be quiet, but it still has to
   be readable: muted is 5.64:1. `opacity: 1` because several browsers fade
   their default placeholder and would fade this one on top of that. */
.tcf-dir__search input[type="search"]::placeholder {
  color: var(--tcf-muted);
  opacity: 1;
}

.tcf-dir__search input[type="search"]:hover { border-color: var(--tcf-ink); }
.tcf-dir__search input[type="search"]:focus-visible { border-color: var(--tcf-accent); }

/* ---- the home group filter -------------------------------------------------

   THE ONE FACET. "Who is in my home group" is the question a name search cannot
   answer, because the answer is a set rather than a family, and it is the only
   second axis this data has that anyone would navigate by. The argument against
   a SORT control, and against every other field as a second order, is in the
   header of directory-page.php.

   A NATIVE SELECT, LEFT LOOKING LIKE ONE. It takes the field system's border,
   radius, type and padding so it belongs to the same family as the search box
   beside it, and it keeps its own disclosure arrow. Stripping that with
   `appearance: none` would buy a slightly tidier box and cost the one mark that
   tells a reader this control opens rather than accepts typing - and it would
   have to be replaced with a drawn arrow, which is an icon, which §1.9 does not
   want on this site.

   WIDTH IS `auto`, WHICH IS THE FIELD SYSTEM'S OWN RULE APPLIED HONESTLY. A
   select is exactly as wide as its widest option and never wider; the longest
   here is "Whitfield-Amaya group" at about 232px including the arrow, well
   inside the 280px a 320px phone has. DESIGN_SYSTEM_FIELDS §measures asks for
   the width the value needs rather than the width the box offers, and for this
   one control the browser already knows it.
   --------------------------------------------------------------------------- */

/* Ships `hidden` and the script un-hides it, exactly as the search block does.
   Restated because an element given an explicit display has to say it again. */
.tcf-dir__filter { display: block; }
.tcf-dir__filter[hidden] { display: none; }

.tcf-dir__filter select {
  display: block;
  width: auto;
  max-width: 100%;
  /* `height: auto` is what makes the padding render: Blocksy sets a height on
     every form control from --theme-form-field-height, and with border-box that
     swallows it. The same note is on the search field above and it is the same
     trap. */
  height: auto;
  min-height: var(--tcf-field-min-h);
  padding: var(--tcf-field-pad-y) var(--tcf-field-pad-x) !important;
  font-family: var(--tcf-font-ui);
  font-size: var(--tcf-field-text);
  line-height: 1.4;
  color: var(--tcf-ink);
  background-color: var(--tcf-field-fill);
  border: var(--tcf-field-border-w) solid var(--tcf-field-border);
  border-radius: var(--tcf-radius);
  cursor: pointer;
  transition: border-color var(--tcf-motion-hover) var(--tcf-ease);
}

.tcf-dir__filter select:hover { border-color: var(--tcf-ink); }
.tcf-dir__filter select:focus-visible { border-color: var(--tcf-accent); }
/* The 2px brick ring comes from the global rule at style.css:675, the same way
   the search field gets it. One focus rule for the whole site is what stops a
   control added later from quietly having none. */

/* ---- the qualification under the filter ------------------------------------

   One sentence, shown only while "No group listed" is the chosen option, and it
   is there so that result does not read as a roll of the unattached. The page
   knows what members have written down, not who is in a group.

   Same size and colour as the count line, because it is the same kind of fact:
   the page explaining its own result.
   --------------------------------------------------------------------------- */

.tcf-dir__hint {
  margin: 0;
  max-width: var(--tcf-measure);
  font-size: var(--tcf-text-meta);
  line-height: var(--tcf-leading-sm);
  color: var(--tcf-muted);
}
.tcf-dir__hint[hidden] { display: none; }

/* ---- with JavaScript off ---------------------------------------------------

   The state this component claimed to have for months and did not. Both control
   blocks ship `hidden`, so without JavaScript a member got the whole directory
   and no account of why the page talks about a search box that is not there.

   15.5px rather than 14: this is a sentence a member reads, and §1.2 puts a
   15px floor under anything that is - the same ruling that took the scope line
   below from 14 to 15.5.
   --------------------------------------------------------------------------- */

.tcf-dir__nojs {
  margin: 0;
  max-width: var(--tcf-measure);
  font-size: var(--tcf-text-body-sm);
  line-height: var(--tcf-leading-sm);
  color: var(--tcf-muted);
}
/* The 2px brick ring at 2px offset comes from the global rule at style.css:675.
   It is not restated here on purpose: one focus rule for the whole site is what
   stops a control added later from quietly having none. */

/* The one live region on the page. It reports three states - everybody, a
   subset, and nobody - and the third of those is why there is no separate
   "nothing matched" panel below the list.

   It counts HOUSEHOLDS now rather than members. It was always counting rows;
   the rows just stopped being people. */
.tcf-dir__count {
  margin: var(--tcf-space-2) 0 0;
  font-size: var(--tcf-text-meta);
  line-height: var(--tcf-leading-sm);
  color: var(--tcf-muted);
  font-variant-numeric: tabular-nums;
}

/* Nothing matched. The line steps up to ink, so the state change is carried by
   weight of colour and by the words, and not by position alone (§5.1). */
.tcf-dir__count.is-none { color: var(--tcf-ink); }

/* The §1.4 inline link: brick, 600, 1px underline at 4px offset. No arrow -
   §1.9 gives the arrow to links that go forward to another page, and this
   opens a printable version of the page you are already on. */
/* Under the pinned bar rather than in it, and right-aligned so it stays out of
   the reading path on its way to the list. The measurement that moved it, and
   why this link is the one of the three controls that gives way, is in the
   markup beside it. */
.tcf-dir__print {
  margin: var(--tcf-space-3) 0 var(--tcf-space-5);
  font-size: var(--tcf-text-ui);
  line-height: 1;
  text-align: right;
}

.tcf-dir .tcf-dir__print a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-weight: 600;
  color: var(--tcf-accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--tcf-link-underline);
  text-underline-offset: 4px;
  transition:
    color var(--tcf-motion-hover) var(--tcf-ease),
    text-decoration-color var(--tcf-motion-hover) var(--tcf-ease);
}
.tcf-dir .tcf-dir__print a:hover,
.tcf-dir .tcf-dir__print a:focus-visible {
  color: var(--tcf-accent-strong);
  text-decoration-color: currentColor;
}

/* ---- the head, laid out (768px and up) -------------------------------------

   Four things on two lines, and the second line is the only one that has to be
   read: the labels sit over their own controls and the count sits beside the
   search field rather than under it.

       Search the directory                 Home group
       [ field, 320px ]  12 of 39 households  [ select ]      Print or save as PDF

   The count moved. It used to be a third row under the field, which is fine in
   a static block and costs about 22px of a bar that is now pinned to the top of
   the window for the whole page. Beside the field it is also nearer the thing it
   describes, and it is what confirms a filter is on when the reader has scrolled
   past everything else.

   `order` on the print link is the one place source order and visual order part
   on this page. The link is last in the flex row and second-to-last in the
   markup, so that on a phone - where this whole block dissolves and the source
   order is what renders - the hint about optional home groups lands under the
   select that produced it rather than under a link about paper. Nothing between
   them is focusable, so the tab order is identical either way.
   --------------------------------------------------------------------------- */

/* Its own line inside the pinned bar, full width, under the two controls. Both
   are sentences rather than controls: one appears for a single filter option,
   the other only when there is no JavaScript to build the controls at all. */
.tcf-dir__hint,
.tcf-dir__nojs { width: 100%; }

/* ---- the count comes up beside the field (1024px and up) -------------------

   THE TABLET IS WHY THIS IS NOT IN THE BLOCK ABOVE. With the count in its own
   column the bar is about 466px wide, and 466 + 206 for the select + 140 for
   the print link + two 40px gaps is 892px against the 691px a 768px tablet has
   between its gutters. Everything wrapped, and the pinned bar measured 194px -
   twenty-two per cent of the window, permanently, on the surface with the least
   of it to give.

   Stacked, the bar is 320px wide and the whole head fits on one line at 768:
   320 + 40 + 206 = 566. Measured at 127px instead of 194.

   So between 768 and 1023 the count stays under the field, where it has always
   been, and above 1024 - where there is room for it - it comes up beside the
   field and takes 22px off the pinned bar.
   --------------------------------------------------------------------------- */

@media (min-width: 1024px) {

  .tcf-dir__bar {
    /* The count now sits in a second column, so the basis has to grow to hold
       both. `auto` hands it back to the grid, whose intrinsic width is the
       320px track plus the gap plus the count. */
    flex-basis: auto;
    display: grid;
    /* BOTH COLUMNS ARE CAPPED, and the second one has to be.
       The count is usually five words and becomes a sentence at zero matches:
       "No match for that. Try part of a surname, or a first name." is about
       410px at 14px. With an `auto` track it took that width, the bar grew to
       roughly 700px, the select had nowhere to go and wrapped to a second row -
       so typing one letter too many made the pinned bar jump from 101px to
       194px and moved the home group control 92px down the screen, under the
       reader's own cursor. Measured at 1024.

       Capped at the same measure as the field, the sentence wraps to two lines
       of 45px inside a row the 48px field already sets, so the bar does not
       move at all. */
    grid-template-columns:
      minmax(0, var(--tcf-field-measure-md))
      minmax(0, var(--tcf-field-measure-md));
    align-items: center;
    column-gap: var(--tcf-space-4);
    row-gap: var(--tcf-space-2);
  }

  /* The block dissolves so its label and its field can be placed in the bar's
     grid rather than stacked inside a box of their own. Gated on .is-enhanced,
     the class the script adds at the moment it un-hides the block, so that with
     JavaScript off nothing here applies and there is nothing to place. */
  .tcf-dir.is-enhanced .tcf-dir__search { display: contents; }

  .tcf-dir.is-enhanced .tcf-dir__search label {
    grid-column: 1;
    grid-row: 1;
    margin: 0;
  }
  .tcf-dir.is-enhanced .tcf-dir__search input[type="search"] {
    grid-column: 1;
    grid-row: 2;
    max-width: none;
  }
  .tcf-dir.is-enhanced .tcf-dir__count {
    grid-column: 2;
    grid-row: 2;
    margin: 0;
  }
}

/* ---- the letter strip ------------------------------------------------------

   The alphabet index the first spec ruled out, and the ruling is reversed on
   its own terms. It said "seventy entries with a working search box does not
   need one, and it would be a second navigation model to explain to a
   volunteer". Both halves change at a hundred and fifty: it is no longer
   seventy, and there is nothing to explain because there is nothing to
   maintain - the strip is derived from the surnames that exist, so it can never
   offer a letter nobody is filed under.

   IT IS A DESKTOP AND TABLET AFFORDANCE, HIDDEN UNDER 768px. Twenty-six targets
   big enough for a thumb is three rows of chrome on a phone, on the one surface
   where the search box is ALREADY pinned to the top of the screen and is the
   better tool. Hidden rather than wrapped, because a nav nobody can use well is
   twenty-six things to swipe past.

   32px and not 44px. §5.8's 44 is this page's rule for its two standalone
   controls - the search field and the print link - and 24px is its floor for
   dense in-content links, which is WCAG 2.2 SC 2.5.8's own minimum. A row of
   single letters is the densest thing on the page; 32px sits comfortably above
   the floor and keeps the whole alphabet on one line at 1024px and up.

   Sticky, and this is the inverse of the search bar's arrangement below: the
   bar sticks on the phone and not on the desktop, the strip sticks on the
   desktop and does not exist on the phone. Each surface gets one pinned thing,
   about 44px tall, and it is the one that surface actually navigates by.
   --------------------------------------------------------------------------- */

.tcf-dir__index { display: none; }

/* While a search is running the strip goes away. Jumping to "M" in a filtered
   list is a jump to whatever survived the filter, which is not what the letter
   promises; and a reader who is typing is not browsing. Scores (0,3,0) so it
   beats the display rule in the media query below whatever the order. */
.tcf-dir.is-filtering .tcf-dir__index { display: none; }

@media (min-width: 768px) {

  .tcf-dir--indexed .tcf-dir__index {
    display: block;
    position: sticky;
    top: 0;
    z-index: 3;
    margin: 0 0 var(--tcf-space-5);
    padding: var(--tcf-space-2) 0;
    background-color: var(--tcf-page);
    border-bottom: 1px solid var(--tcf-rule);
  }

  .tcf-dir__index ul {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .entry-content .tcf-dir__index ul { margin: 0; padding: 0; }
  .tcf-dir__index li { margin: 0; }

  /* No underline at rest, and that is allowed here where it is not allowed in
     prose: §1.1's underline rule is about links inside running text, and this
     is a bar of controls - the same ruling the teaching filters and the month
     grid's arrows already carry. The affordance at rest is the bar itself, and
     hover and focus add both colour AND an underline, so the change is legible
     to somebody who cannot separate the two reds (§5.6). */
  .tcf-dir .tcf-dir__index a {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 32px;
    min-height: 32px;
    padding: 0 var(--tcf-space-1);
    font-size: var(--tcf-text-ui);
    font-weight: 600;
    line-height: 1;
    color: var(--tcf-ink);
    text-decoration: none;
    border-radius: var(--tcf-radius);
    transition:
      color var(--tcf-motion-hover) var(--tcf-ease),
      background-color var(--tcf-motion-hover) var(--tcf-ease);
  }

  .tcf-dir .tcf-dir__index a:hover,
  .tcf-dir .tcf-dir__index a:focus-visible {
    color: var(--tcf-accent);
    background-color: var(--tcf-surface);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
  }

  /* The way back to the search box, first in the strip because the strip is
     the thing that is still on screen when you are four thousand pixels down.
     Worded as what it does and styled as the one brick item in the bar, so it
     does not read as a letter. */
  .tcf-dir .tcf-dir__index-search a {
    padding: 0 var(--tcf-space-3);
    margin-right: var(--tcf-space-2);
    color: var(--tcf-accent);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-decoration-color: var(--tcf-link-underline);
    text-underline-offset: 3px;
  }
  .tcf-dir .tcf-dir__index-search a:hover,
  .tcf-dir .tcf-dir__index-search a:focus-visible {
    color: var(--tcf-accent-strong);
    text-decoration-color: currentColor;
  }
}

/* ---- who can see this -----------------------------------------------------

   The one thing a member cannot work out for themselves and does wonder, said
   once, as a fact, and then dropped. Everything else about privacy is either
   structural (a guest gets no markup at all) or lives on the printed sheet,
   where it reaches whoever is holding the paper.
   --------------------------------------------------------------------------- */

/* 15.5, not 14. This is a sentence a member reads - it tells them the directory
   is not public - and §1.2 puts a 15px floor under anything that is.
   check_design.py failed it outright once the member area became visible to the
   gates (MAINTAINABILITY_REVIEW M-7); the same ruling already took the sign-in
   card's reset line from 14 to 15: "the way to honour a floor is to not go near
   it." */
.tcf-dir__scope {
  margin: 0 0 var(--tcf-space-5);
  max-width: var(--tcf-measure);
  font-size: var(--tcf-text-body-sm);
  line-height: var(--tcf-leading-sm);
  color: var(--tcf-muted);
}

/* ---- the list -------------------------------------------------------------

   Snaking across rows rather than down columns, which is the opposite of what
   the printed sheet does and is deliberate. A balanced two-column block of
   sixty entries is about three thousand pixels tall, so reading it A to Z on a
   screen means scrolling to the bottom and then all the way back up for the
   second column. A page is a fixed frame; a scroll is not.

   auto-fill and NOT auto-fit: with auto-fit a single search result would
   stretch to the full container width. With auto-fill the empty tracks stay
   and one result keeps the width of one entry, which is what one result should
   look like.

   min(19rem, 100%) and NOT 19rem: at 320px the container is about 282px, which
   is under the track floor, and a bare 19rem would push the page sideways.
   §1.10 - nothing horizontally scrolls, ever.

   The .entry-content duplicates are not belt and braces. Blocksy and the block
   library both put margins on a ul and on its items, and the teaching list had
   to say the same thing at style.css:1028 for the same reason.
   --------------------------------------------------------------------------- */

.tcf-dir__list,
.entry-content .tcf-dir__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(19rem, 100%), 1fr));
  column-gap: var(--tcf-space-6);
  row-gap: var(--tcf-space-5);
  align-items: start;
}

/* The hairline goes on the TOP of an entry, so it sits nearer what it
   introduces than what it follows - the same logic that gives a heading a big
   margin above and a small one below (style.css:556).

   The bar above the list has no bottom border, deliberately: the first row of
   entries supplies that line, and a border on both would double up under a
   filtered result whose first match is entry forty. */
.tcf-dir__entry,
.entry-content .tcf-dir__list > .tcf-dir__entry {
  margin: 0;
  padding: var(--tcf-space-4) 0 0;
  border-top: 1px solid var(--tcf-rule);
  min-width: 0;
}

.tcf-dir__entry[hidden] { display: none; }

/* ---- the letter band -------------------------------------------------------

   A full-width row in the same grid, so the alphabet is a spine down the page
   rather than twenty separate grids with twenty ragged last rows. One grid also
   means the search filter reflows across the whole list instead of inside
   twenty containers.

   NO RULE UNDER THE LETTER. The row of entries below it already draws one
   hairline per column, and a border here would sit two or three pixels above
   those and read as a doubled line. The letter floats and the hairlines beneath
   it are its rule - which is also why the band has no bottom margin: the grid's
   28px row gap is the gap.

   It is a real <h2>, with the household names below it at <h3>, so the outline
   reads page title, letter, family. The glyph itself is aria-hidden and a
   sentence is read in its place; "A", announced alone, twenty times down a
   page, is not navigation.
   --------------------------------------------------------------------------- */

.tcf-dir__band,
.entry-content .tcf-dir__list > .tcf-dir__band {
  grid-column: 1 / -1;
  /* 12px, not 28. The grid's own 28px row gap is already above this, so the
     token that looks right here doubles into 56px of white above every letter -
     and there are twenty-five of them. */
  margin: var(--tcf-space-3) 0 0;
  padding: 0;
  border-top: 0;
}
.tcf-dir__list > .tcf-dir__band:first-child { margin-top: 0; }
.tcf-dir__band[hidden] { display: none; }

/* Every global heading rule undone, exactly as .tcf-dir__name has to do it.
   An h2 in this theme is 28-40px fluid, carries a 56px top margin and takes
   -0.01em or, above 800px, -0.02em of tracking.

   `scroll-margin-top` clears the sticky strip. 72px is the strip's ~44px plus
   room, and it is what makes a jump land with the letter visible rather than
   underneath the bar that sent you there. */
.tcf-dir .tcf-dir__band-h {
  margin: 0;
  font-family: var(--tcf-font-display);
  font-size: var(--tcf-text-stat);
  font-weight: 400;
  line-height: 1;
  letter-spacing: 0;
  color: var(--tcf-ink);
  scroll-margin-top: var(--tcf-space-8);
}

/* ---- one entry ------------------------------------------------------------

   The name is what you scan for; the phone is what you came for; everything
   else is context. Nothing in an entry hovers except its links, because nothing
   else does anything.
   --------------------------------------------------------------------------- */

/*
 * An <h2> in a plain list and an <h3> under a letter band, so a hundred and
 * fifty surnames are a heading list a screen-reader user can jump through - and
 * because filtering hides entries with `hidden`, which takes them out of the
 * accessibility tree, that list follows the search.
 *
 * Which means the global heading rules have to be undone, for both levels. An
 * h2 in this theme is 28-40px fluid (style.css:493), carries a 56px top margin
 * (:556) and takes -0.01em or, above an 800px viewport, -0.02em of tracking
 * (:537); h3 shares the margin and the tracking. All of it is reset here. Miss
 * any of it and the page is a wall of headlines.
 *
 * Sized at `lede` rather than `card-title`: 17-19px of Newsreader against the
 * Public Sans around it already ranks the name, and 24-30px a hundred and fifty
 * times does not rank anything.
 */
.tcf-dir .tcf-dir__name {
  margin: 0;
  font-family: var(--tcf-font-display);
  font-size: var(--tcf-text-lede);
  font-weight: 400;
  line-height: var(--tcf-leading-card);
  letter-spacing: 0;
  color: var(--tcf-ink);
  overflow-wrap: break-word;
}

/* WHO LIVES HERE, and which home group they are in: "Chad and Kelly ·
   Craw-Hahn group".

   Under the name, not above it as an eyebrow. The teaching card puts its series
   above the title because people browse an archive by series; nobody opens a
   directory hunting a home group. It is a fact about somebody you have already
   found.

   This line is the reason the page can call itself a directory of households
   and still be honest. "The Grissom Family" cannot tell two Grissom households
   apart and does not say whose the number below is; the first names do both. */
.tcf-dir__meta {
  margin: var(--tcf-space-1) 0 0;
  font-size: var(--tcf-text-meta);
  line-height: var(--tcf-leading-sm);
  color: var(--tcf-muted);
}

/* 8px above the phone, which is the break between "who this is" and "how to
   reach them"; 4px between the contact lines themselves, which are one block.
   At a hundred and fifty households the difference between 8 and 4 on two lines
   an entry is about twelve hundred pixels of page, and there is no reading gain
   to buy with it: they are already separated by their own type sizes. */
.tcf-dir__phone {
  margin: var(--tcf-space-2) 0 0;
  min-width: 0;
}

.tcf-dir__email,
.tcf-dir__address {
  margin: var(--tcf-space-1) 0 0;
  min-width: 0;
}

/* Whose email, or whose phone when a household gave two. Small and quiet: it is
   a label on a value, not a second name, and it must never out-rank the family
   name three lines above it - which is what it did at the line's own size, where
   "Melanie" in 15.5px ink read as heavily as the address beside it.

   14px is the `meta` role, the same one the who line above takes, so the two
   quiet facts about a household are set at one size.

   MUTED RATHER THAN INK, WHICH REVERSES THE RULING ABOVE IT. That ruling was
   made when a household had at most one labelled line, and it read: "ink rather
   than muted because a 5.64:1 grey name in front of a 5.64:1 grey email address
   is one undifferentiated line."

   The merge rule changed the picture. A couple now renders four labelled lines -
   two phones and two emails - so an ink label appeared four times per entry, and
   at thirty-nine households that is a grid of black first names standing in
   front of the family name they belong to. Photographed side by side, the entry
   with ink labels reads as a block of black in which the family name is the
   faintest thing on it.

   The label is still legible against what follows it, and by two signals rather
   than by colour: it is 600 where the value is 400, and the value is underlined
   where the label is not. Colour was never carrying that difference alone. */
.tcf-dir__label {
  font-size: var(--tcf-text-meta);
  color: var(--tcf-muted);
  font-weight: 600;
}

.tcf-dir__phone {
  font-size: var(--tcf-text-body);
  line-height: var(--tcf-leading-sm);
}

/*
 * Ink at 600 rather than brick, and this is a considered departure.
 *
 * §1.1 says brick is for action, and dialling is an action. §1.1 also says
 * brick is for emphasis ONLY, and a hundred and fifty brick phone numbers
 * emphasise nothing. The underline is what settles it: it stays, in the same
 * --tcf-link-underline the global rule already uses, so the affordance never
 * depends on hover (§5.6), while the colour stays quiet. Hover and focus take
 * it to brick AND strengthen the underline to currentColor - two signals, the
 * same pair style.css:634 uses, so the change is legible to somebody who
 * cannot separate the two reds.
 *
 * tabular-nums because a column of a hundred and fifty proportional phone
 * numbers will not scan.
 *
 * WEIGHT 400, WHICH WAS 600 UNTIL THE LIST GOT LONG. The 600 was doing the same
 * job the brick would have done and failing in the same way: at thirty-nine
 * households, sixty phone numbers set in bold black are the loudest thing on the
 * page, and the thing a reader scans a directory for is the family name. The
 * name cannot answer back - §1.2 permits Newsreader at 400 and nothing above it,
 * and check_design.py fails a heavier one because the browser would fake it - so
 * the correction has to come from this side.
 *
 * It is still the strongest sans line in an entry: 17px ink against 15.5px muted
 * for the email and the address, underlined where the address is not. Nothing
 * that told a reader "this is the number, and you can tap it" has been given up.
 */
.tcf-dir .tcf-dir__phone a {
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  color: var(--tcf-ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--tcf-link-underline);
  text-underline-offset: 0.15em;
  transition:
    color var(--tcf-motion-hover) var(--tcf-ease),
    text-decoration-color var(--tcf-motion-hover) var(--tcf-ease);
}
.tcf-dir .tcf-dir__phone a:hover,
.tcf-dir .tcf-dir__phone a:focus-visible {
  color: var(--tcf-accent);
  text-decoration-color: currentColor;
}

.tcf-dir__email {
  font-size: var(--tcf-text-body-sm);
  line-height: var(--tcf-leading-sm);
}

.tcf-dir .tcf-dir__email a {
  color: var(--tcf-muted);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--tcf-link-underline);
  text-underline-offset: 0.15em;
  overflow-wrap: break-word;
  transition:
    color var(--tcf-motion-hover) var(--tcf-ease),
    text-decoration-color var(--tcf-motion-hover) var(--tcf-ease);
}
.tcf-dir .tcf-dir__email a:hover,
.tcf-dir .tcf-dir__email a:focus-visible {
  color: var(--tcf-accent);
  text-decoration-color: currentColor;
}

/* Last and quietest. It is the most sensitive field on the page and the least
   often wanted, and where it sits says that more honestly than a warning would.

   ONE LINE ON SCREEN, comma-joined by the PHP, where the printed sheet keeps
   the three-line envelope shape. The envelope is right on paper, which is what
   somebody addresses an envelope from; on screen it is three lines of quiet
   grey per household, and at a hundred and fifty households that is four
   hundred and fifty lines bought for a shape nobody is copying. */
.tcf-dir__address {
  font-size: var(--tcf-text-body-sm);
  line-height: var(--tcf-leading-sm);
  color: var(--tcf-muted);
  overflow-wrap: break-word;
}

/* ---- the note at the foot --------------------------------------------------

   It now carries the merge rule, because a rule the reader cannot see is a rule
   they cannot act on: a couple who appear as two entries fix it themselves by
   putting the same address on both profiles.
   --------------------------------------------------------------------------- */

.tcf-dir__note {
  margin: var(--tcf-space-7) 0 0;
  padding-top: var(--tcf-space-4);
  border-top: 1px solid var(--tcf-rule);
  max-width: var(--tcf-measure);
  font-size: var(--tcf-text-body-sm);
  line-height: var(--tcf-leading-body);
  color: var(--tcf-muted);
}

/* The one genuine prose link on this page, and the only one that should look
   like the rest of the site's prose links: brick, 600, 1px underline at 4px
   offset (§1.4). It needs saying HERE because `:not(.tcf-dir a)` in style.css
   deliberately keeps the global chain out of this component - which is what
   lets the phone be ink, and which also left this one link at the browser
   default until it was written down. */
.tcf-dir .tcf-dir__note a {
  font-weight: 600;
  color: var(--tcf-accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--tcf-link-underline);
  text-underline-offset: 4px;
  transition:
    color var(--tcf-motion-hover) var(--tcf-ease),
    text-decoration-color var(--tcf-motion-hover) var(--tcf-ease);
}
.tcf-dir .tcf-dir__note a:hover,
.tcf-dir .tcf-dir__note a:focus-visible {
  color: var(--tcf-accent-strong);
  text-decoration-color: currentColor;
}

/* ---- nobody listed yet -----------------------------------------------------

   Top-anchored, left-aligned, small. Several member pages will be empty at the
   same time during the build, and a centred monument on each of them reads as
   a broken site rather than as a new one.
   --------------------------------------------------------------------------- */

.tcf-dir--empty {
  margin: var(--tcf-space-6) 0 0;
  max-width: var(--tcf-measure-lede);
}
.tcf-dir--empty p { margin: 0 0 var(--tcf-space-3); }
.tcf-dir__empty-title {
  font-family: var(--tcf-font-display);
  font-size: var(--tcf-text-lede);
  color: var(--tcf-ink);
}
.tcf-dir__empty-action { margin: var(--tcf-space-4) 0 0; }

/* ---- phones ----------------------------------------------------------------

   Two changes, both about the parking lot.

   The head dissolves, which promotes the bar and the print link to children of
   .tcf-dir. That is what makes the bar's sticky containing block the whole
   page: a position: sticky element only sticks for the height of its parent,
   and the head is about a hundred pixels tall.

   And the bar sticks - on the phone and not on the desktop, which is the
   inverse of the usual instinct. One column of a hundred and fifty households
   is about nine thousand pixels. Scrolling to M, deciding to search, and having
   to flick four and a half thousand pixels back is the difference between a
   tool and a chore. On a desktop the list is a third as tall, the letter strip
   above it is what navigates, and the page reads better without a second bar
   following it down.

   Gated on .is-enhanced, the class the script adds, so with JavaScript off
   there is no search box and nothing pointless is pinned.
   --------------------------------------------------------------------------- */

@media (max-width: 767px) {

  .tcf-dir__head { display: contents; }

  /* THE FILTER IS NOT IN THE PINNED BAR ON A PHONE, and that is the one real
     difference between the two surfaces. A third row would take the bar to
     about 150px - a quarter of a 568px screen, permanently - and the thing it
     would keep on screen is already on screen in words: the count beside the
     search box reports what survived, whatever narrowed it.

     It also costs less than it looks. An unfiltered directory is the long one
     and has no state to clear; the moment a group is chosen the page is a
     twelfth of its height, so scrolling back to the select is one flick. */
  .tcf-dir__filter { margin: var(--tcf-space-3) 0 0; }

  .tcf-dir__hint { margin: var(--tcf-space-2) 0 0; }

  .tcf-dir__nojs { margin: var(--tcf-space-3) 0 0; }

  /* Left, with everything else. Right-aligning a line on a 280px column puts it
     against the gutter with nothing to balance it. */
  .tcf-dir__print { text-align: left; }

  .tcf-dir.is-enhanced .tcf-dir__bar {
    position: sticky;
    top: 0;                       /* see the note in the spec if the site header is sticky */
    z-index: 3;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline;
    column-gap: var(--tcf-space-4);
    row-gap: var(--tcf-space-1);
    margin: 0 0 var(--tcf-space-3);
    padding: var(--tcf-space-2) 0 var(--tcf-space-3);
    background-color: var(--tcf-page);
    border-bottom: 1px solid var(--tcf-rule);
  }

  /* The search block dissolves too, so its label can share a line with the
     count and its field can span both columns. The [hidden] rule above scores
     (0,2,0) and still wins over this, which is what keeps the no-JavaScript
     page from showing an empty box. */
  .tcf-dir.is-enhanced .tcf-dir__search { display: contents; }

  .tcf-dir.is-enhanced .tcf-dir__search label {
    grid-column: 1;
    grid-row: 1;
    margin: 0;
  }
  .tcf-dir.is-enhanced .tcf-dir__count {
    grid-column: 2;
    grid-row: 1;
    margin: 0;
    text-align: right;
  }
  .tcf-dir.is-enhanced .tcf-dir__search input[type="search"] {
    grid-column: 1 / -1;
    grid-row: 2;
    max-width: none;
  }
  /* At nothing-matched the message is a sentence, not a count, so it takes the
     whole row rather than being squeezed into the right-hand column. */
  .tcf-dir.is-enhanced .tcf-dir__count.is-none {
    grid-column: 1 / -1;
    grid-row: 3;
    text-align: left;
    margin-top: var(--tcf-space-2);
  }

  /* The letter band steps down a little on a phone, where it competes with a
     narrower column and there is no strip to answer it. */
  .tcf-dir .tcf-dir__band-h { font-size: var(--tcf-text-lede); }
}

/* At 320 the label and the count will not share a line - "Search the directory"
   wants about 152px and "55 households listed" about 132px, and there are 272px
   between the gutters. The label wrapped to two lines, which put a 140px bar on
   a 568px screen: a quarter of the viewport, permanently, to say two things.

   So below 400px the two stop competing and the count takes its own row under
   the field, which is where the desktop puts it anyway. It costs 22px and saves
   the 28px the wrap was costing, and the bar is a rectangle again. */
@media (max-width: 399px) {
  .tcf-dir.is-enhanced .tcf-dir__search label {
    grid-column: 1 / -1;
  }
  .tcf-dir.is-enhanced .tcf-dir__count,
  .tcf-dir.is-enhanced .tcf-dir__count.is-none {
    grid-column: 1 / -1;
    grid-row: 3;
    text-align: left;
    margin-top: var(--tcf-space-1);
  }

  /* The number becomes a real tap row: 44px tall per §5.8, and only as wide as
     the number, so a stray thumb further along the line does not dial somebody.
     `block` rather than `inline-flex` because text-decoration on a flex
     container has a history of not reaching its contents, and losing the
     underline would leave colour as the only affordance. */
  .tcf-dir__phone { margin-top: var(--tcf-space-1); }
  .tcf-dir .tcf-dir__phone a {
    display: block;
    width: max-content;
    max-width: 100%;
    min-height: 44px;
    padding-block: 10px;
  }
}

/* ---------------------------------------------------------------------------
   Stated preferences

   Nothing needs writing for either of them, and that is the point of having
   done this in tokens.

   prefers-reduced-motion: the only transitions here are the link-hover colours
   from §1.7's permitted list, and --tcf-motion-hover already drops to 0ms at
   style.css:725.

   prefers-contrast: more: --tcf-rule strengthens to #C9BFAE and --tcf-muted
   collapses into ink at style.css:752, so every hairline in this file gets
   firmer and the who line, email and address all go from 5.64:1 to 16.85:1
   without a rule being written.
   --------------------------------------------------------------------------- */
