/* =============================================================================
   hub.css — the front page: findbar, then the standing index of every course.

   Loaded after site.css, which supplies the colour tokens, and after
   theme-warm.css, which supplies the serif and the warm palette.

   The page is a findbar about 170px tall and then every one of the courses as a
   one-line link, grouped under its subject, packed into columns that end at the
   fold. Nothing here collapses and nothing opens, so there are no disclosure
   rules below and no state to remember except the descriptions toggle.

   The five numbers the column packer works in are declared on #index as custom
   properties. The render script in index.html holds the same five as JS
   integers, because it has to add them up before the DOM exists. Change one and
   change it in both places; index.html says so at the declaration.
   ========================================================================== */

body{ -webkit-font-smoothing:antialiased }
.wrap{max-width:1120px; margin:0 auto; padding:0 28px}
.measure{max-width:66ch}
.skip{position:fixed; left:12px; top:10px; z-index:90; transform:translateY(-150%);
  padding:9px 13px; border:2px solid var(--accent); border-radius:8px;
  background:var(--panel); color:var(--txt); font-weight:650; text-decoration:none}
.skip:focus{transform:translateY(0); outline:none}

/* Visually hidden, still read aloud and still found by a rotor. Used for the
   search field's label, the chip group's label, and nothing decorative. */
.sr{position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip-path:inset(50%); white-space:nowrap; border:0}

/* ------------------------------------------------------------------ header */
.sitehead{position:sticky; top:0; z-index:40; background:color-mix(in srgb,var(--bg) 88%,transparent);
  backdrop-filter:saturate(150%) blur(10px); border-bottom:1px solid var(--line)}
.sitehead .in{display:flex; align-items:center; gap:20px; height:58px;
  max-width:1120px; margin:0 auto; padding:0 28px}
.wordmark{display:flex; align-items:center; gap:9px; font-weight:700; font-size:.92rem;
  color:var(--txt); text-decoration:none; white-space:nowrap}
.wordmark:hover{text-decoration:none}
.wordmark .glyph{width:22px; height:22px; border-radius:6px; flex:none;
  background:linear-gradient(135deg,var(--accent),var(--accent2))}
.sitehead nav{display:flex; gap:18px; margin-left:auto; align-items:center}
.sitehead nav a{font-size:.86rem; color:var(--dim); text-decoration:none; white-space:nowrap}
/* "Where to start" is two words, and between 760 and 930 the bar is narrow
   enough that the label broke into both of them, giving the header a ragged
   second line. The two in-page links leave at the width where the bar stops
   fitting, not at the phone width the hiding class was first written for. */
@media (max-width:930px){
  .sitehead nav a.hide-sm{display:none}
}
.sitehead nav a:hover{color:var(--txt); text-decoration:none}
.tbtn{font:inherit; font-size:.82rem; color:var(--txt); background:var(--panel2);
  border:1px solid var(--line2); border-radius:8px; padding:5px 11px; cursor:pointer}
.tbtn:hover{border-color:var(--accent); color:var(--accent)}
/* The theme control is an icon, and which icon it is has to answer to all
   three theme states: an explicit choice either way, and the untouched default
   that follows the system. Only prefers-color-scheme separates the last two,
   so each state is written out rather than inferred from one attribute. */
/* Every rule below carries .tbtn.icon and then the icon class, so they all sit
   at the same specificity and the theme selectors can win by adding one more.
   A general ".tbtn.icon svg{display:block}" was here first, and at three
   components it quietly outranked ".tbtn .i-sun{display:none}" at two: both
   icons showed at once, a moon and a sun side by side in the nav. */
.tbtn.icon{display:inline-flex; align-items:center; justify-content:center;
  width:34px; height:34px; padding:0}
.tbtn.icon .i-moon{display:block}
.tbtn.icon .i-sun{display:none}
:root[data-theme="dark"] .tbtn.icon .i-moon{display:none}
:root[data-theme="dark"] .tbtn.icon .i-sun{display:block}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .tbtn.icon .i-moon{display:none}
  :root:not([data-theme="light"]) .tbtn.icon .i-sun{display:block}
}

/* --------------------------------------------------------------------------
   404.html shares this stylesheet and is the only page left that uses .hero,
   .lede and .cta. The front page has no hero and no call-to-action button: the
   courses themselves are the call to action.
   ----------------------------------------------------------------------- */
.hero{padding:76px 0 8px; position:relative}
.hero h1{font-size:clamp(2.1rem, 4.6vw, 3.35rem); line-height:1.08; letter-spacing:-.028em;
  margin:0 0 18px; max-width:22ch}
.lede{font-size:1.14rem; line-height:1.62; color:var(--dim); max-width:62ch; margin:0 0 14px}
.lede b{color:var(--txt); font-weight:600}
.cta{display:inline-flex; align-items:center; gap:9px; font:inherit; font-size:.95rem; font-weight:650;
  background:var(--accent); color:var(--on-accent); border:1px solid var(--accent); border-radius:10px;
  padding:12px 22px; cursor:pointer; text-decoration:none}
.cta:hover{filter:brightness(1.1); text-decoration:none}

/* ===================================================================== findbar
   Four rows on the 1064px measure, 170px tall in total, so the index below it
   starts at a known y and the packer's arithmetic can be checked against a
   ruler. The rows are laid out by wrapping one flex container rather than by
   nesting, because under 660px the whole findbar becomes display:contents and
   the search row has to be a direct child of <main> for position:sticky to
   have the page as its containing block rather than a 44px-tall parent.
   ======================================================================== */
.findbar{display:flex; flex-wrap:wrap; align-items:center; column-gap:12px;
  padding:14px 0 12px}
.fbtitle{flex:1 0 100%; display:flex; flex-wrap:wrap; align-items:baseline; gap:11px;
  row-gap:3px; min-height:28px; scroll-margin-top:78px}
/* The h1 owns its whole row. Without this the hairline and byline share the
   title's first line, and any width at which the title wraps leaves them
   floating at the top right while the second line of the title runs under
   them. Full-row, the pair drops below the title as a signature line and the
   arrangement is the same at every width. */
.fbtitle h1{flex:1 0 100%}
.fbtitle h1{font-size:clamp(1.15rem,1.6vw,1.32rem); line-height:28px; margin:0;
  letter-spacing:-.02em; min-width:0}
.fbtitle .rule{width:26px; height:1px; background:var(--line2); flex:none}
.fbtitle .who{font-size:.82rem; color:var(--dim); font-weight:600; white-space:nowrap}

.fbsearch{flex:0 0 340px; max-width:100%; margin-top:8px}
.fbsearch input[type=search]{display:block; width:100%; min-height:44px; font:inherit;
  font-size:.92rem; color:var(--txt); background:var(--panel);
  border:1px solid color-mix(in srgb,var(--txt) 32%,var(--panel));
  border-radius:999px; padding:9px 15px}
.fbsearch input[type=search]:focus-visible{outline:2px solid var(--accent); outline-offset:2px;
  border-color:var(--accent)}
.fbchips{flex:1 1 auto; display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  margin-top:8px; min-height:44px}
.chips{display:flex; align-items:center; gap:7px; flex-wrap:wrap}
.chipbtn{font:inherit; font-size:.8rem; color:var(--dim); background:transparent;
  border:1px solid color-mix(in srgb,var(--txt) 32%,var(--panel)); border-radius:999px;
  min-height:38px; padding:6px 13px; cursor:pointer; white-space:nowrap}
.chipbtn:hover{color:var(--txt); border-color:var(--accent)}
.chipbtn.on{background:var(--accent); border-color:var(--accent); color:var(--on-accent)}
.chipbtn[hidden]{display:none}
.chipbtn:focus-visible,.textbtn:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
#startedBtn{border-style:dashed}
#startedBtn.on{border-style:solid}

.fbutil{flex:1 0 100%; display:flex; align-items:center;
  gap:16px; margin-top:8px; min-height:34px}
.fbutil .textbtn{margin-left:auto}
.resultnote{margin:0; font-size:.78rem; line-height:1.35; color:var(--dimmer); min-width:0}
/* At rest the note repeats what the placeholder already demonstrates, as a
   third size of small grey print in five rows of controls. Clipped, it stays
   the search field's description for a screen reader and the live region a
   count lands in; the script lifts the class whenever it writes a count, so
   the row reappears exactly when it has something to say. */
.resultnote.quiet{position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip-path:inset(50%); white-space:nowrap}
.textbtn{font:inherit; font-size:.78rem; font-weight:650; color:var(--dim); background:var(--panel2);
  border:1px solid color-mix(in srgb,var(--txt) 30%,var(--panel)); border-radius:999px;
  min-height:34px; padding:6px 13px; cursor:pointer; white-space:nowrap; flex:none}
.textbtn:hover{color:var(--accent); border-color:var(--accent)}
.textbtn[aria-pressed=true]{color:var(--txt); border-color:var(--line2); background:var(--panel3)}

.fbrow{flex:1 0 100%; display:flex; flex-wrap:wrap; align-items:baseline;
  justify-content:space-between; gap:22px; row-gap:4px; margin-top:4px; min-height:18px}
.fbnote,.fbdoor{margin:0; font-size:.78rem; line-height:18px; color:var(--dim); min-width:0}
.fbnote b{color:var(--txt); font-weight:600}
.fbdoor{color:var(--dimmer); white-space:nowrap; flex:none}
.fbdoor a{margin-left:7px}

/* ======================================================================= index
   Every course, one line each, grouped under its subject, packed into --cols
   columns by the script. --cols is written as an inline style on #index.
   ======================================================================== */
#index{
  --row:21px;          /* one-line course row, min-height. Paired with ROW in
                          index.html; changing one alone breaks the packer.     */
  --rtline:16px;       /* the line box inside that row                         */
  --hook:16px;         /* one wrapped line of hook, of facts, or of evidence   */
  --head:38px;         /* subject heading block plus the gap that follows it    */
  --kick:14px;         /* a kicker line: subject name on a solo row, Start here */
  --gap:10px;          /* trailing gap on a group                              */
  display:grid; grid-template-columns:repeat(var(--cols,4),minmax(0,1fr));
  padding-bottom:72px}
.col{padding:0 24px; min-width:0}
.col:first-child{padding-left:0}
.col:last-child{padding-right:0}
.col + .col{border-left:1px solid var(--line)}

.anchor{display:block; height:0; overflow:hidden; scroll-margin-top:78px}
.group{margin:0 0 var(--gap); scroll-margin-top:78px}
.group[hidden]{display:none}
/* 16px line box, 3px of padding, a 1px rule and 8px of margin come to 28, and
   the group's own 10px trailing gap makes the 38 the packer charges. */
.gname{font-family:var(--mono); font-size:.68rem; font-weight:700; line-height:16px;
  text-transform:uppercase; letter-spacing:.09em; color:var(--dimmer);
  margin:0 0 calc(var(--head) - var(--gap) - 20px); padding-bottom:3px;
  border-bottom:1px solid var(--line)}
.gname .glead{white-space:nowrap}
.gname.kick{font-size:.62rem; line-height:var(--kick); letter-spacing:.07em;
  border:0; padding:0; margin:0}
/* The subject blurb is searched in both languages and read by a screen reader
   at all times; it only takes space when the descriptions toggle is on. */
.gblurb{position:absolute; width:1px; height:1px; overflow:hidden; clip-path:inset(50%);
  margin:0; font-size:.74rem; line-height:var(--hook); color:var(--dim)}
#index.showdesc .gblurb{position:static; width:auto; height:auto; clip-path:none;
  margin:0 0 6px}

.rows{list-style:none; margin:0; padding:0}
.row{position:relative; display:grid; grid-template-columns:minmax(0,1fr) auto;
  align-items:baseline; min-height:var(--row); border-radius:6px;
  transition:background-color .12s}
.row[hidden]{display:none}
.rt{grid-column:1; display:block; padding:calc((var(--row) - var(--rtline))/2) 7px;
  font-size:.82rem; line-height:var(--rtline); color:var(--txt); text-decoration:none}
.rt:hover{color:var(--accent); text-decoration:none}
.row:hover,.row:focus-within,.row.top{background:color-mix(in srgb,var(--accent) 12%,var(--panel))}
.rt:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
/* The one visible marker on the page, and it means one thing: pressing Enter in
   the search field opens this row. It carries the word, not a glyph. */
.rmark{grid-column:2; align-self:center; margin-right:7px; flex:none;
  font-family:var(--mono); font-size:.6rem; font-weight:700; line-height:1;
  letter-spacing:.08em; text-transform:uppercase; color:var(--accent)}
.rmark[hidden]{display:none}

/* One description block per course, always in the DOM, always the target of the
   link's aria-describedby. Its lines are clipped rather than removed, so a
   screen reader hears in document order exactly what the descriptions toggle
   shows a sighted reader. Three lines escape the clip: the progress count, which
   is a reader's own state and belongs on the resting page; and everything, on a
   Start here row, in descriptions mode, or on a row a search matched. */
.rdetail{grid-column:1 / -1; padding:0 7px}
/* Every line is clipped by default and every margin is zero, so the height of a
   row is the sum of the line boxes that are showing and nothing else. That is
   what lets the packer add the page up before the browser lays it out. The
   selectors below are the only three ways a line comes back into flow, and each
   is more specific than the clip so it wins without !important. */
.rdetail > p{position:absolute; width:1px; height:1px; overflow:hidden;
  clip-path:inset(50%); white-space:nowrap; margin:0}
.rdetail > p.rprog,
.row.lead .rdetail > p.rlead,
.row.lead .rdetail > p.rhook,
#index.showdesc .rdetail > p,
#index.filtered .row:not([hidden]) .rdetail > p{
  position:static; width:auto; height:auto; overflow:visible; clip-path:none;
  white-space:normal}
.row.lead .rdetail,
#index.showdesc .rdetail,
#index.filtered .row:not([hidden]) .rdetail{padding-bottom:5px}
.rlead{font-family:var(--mono); font-size:.62rem; font-weight:700; line-height:var(--kick);
  text-transform:uppercase; letter-spacing:.07em; color:var(--hot)}
.rhook{font-size:.76rem; line-height:var(--hook); color:var(--dim)}
.rdetail > p.rprog{font-family:var(--mono); font-size:.68rem; line-height:var(--hook);
  color:var(--dimmer); margin:0 0 4px}
.rfacts{font-family:var(--mono); font-size:.68rem; line-height:var(--hook); color:var(--dimmer)}
.rwhy{font-size:.72rem; line-height:var(--hook); color:var(--dim)}
.rwhy mark{background:color-mix(in srgb,var(--hot) 34%,var(--panel)); color:var(--txt);
  border-radius:3px; padding:0 2px}

/* A query or the descriptions toggle relaxes the index to two columns, because
   every surviving row now carries several lines and 229px is too narrow for
   them. Six survivors or fewer and it goes to one measured column. */
#index.narrow{max-width:68ch}

.catalogempty{margin:0 0 30px; padding:26px; border:1px solid var(--line); border-radius:13px;
  background:var(--panel); text-align:center}
.catalogempty[hidden]{display:none}
.catalogempty h3{font-size:1.04rem; margin:0 0 7px}
.catalogempty p{color:var(--dim); font-size:.86rem; margin:0 auto 15px; max-width:52ch}
.catalogempty .nearmiss{font-family:var(--mono); font-size:.76rem; color:var(--dimmer)}
.catalogempty .nearmiss[hidden]{display:none}

/* ---------------------------------------------------------- the projects door */
.projband{margin:0; padding:26px 0 0; border-top:1px solid var(--line)}
.projband .d-k{display:block; font-family:var(--mono); font-size:.68rem; font-weight:700;
  text-transform:uppercase; letter-spacing:.11em; color:var(--dimmer); margin:0 0 8px}
.projband h2{font-size:1.34rem; margin:0 0 8px; letter-spacing:-.02em}
.projband p{color:var(--dim); font-size:.94rem; line-height:1.6; margin:0 0 12px; max-width:64ch}
.projband a{font-size:.9rem; font-weight:600}

/* -------------------------------------------------------------- the top band
   The engraving and the search controls share one row, so the drawing greets a
   first-time reader instead of sitting below seventy-eight course titles, and
   the index pays only the height by which the plate outgrows the findbar rather
   than the plate's whole height.

   Below 1180 there are not two tracks to share, so the band stacks. That costs
   the index the full height of the plate, which is the right trade there: the
   index stops being a one-screen object below 1180 in any case. */
.topband{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,380px);
  gap:40px; align-items:center}
/* The user-agent stylesheet gives a <figure> 40px of side margin and 1em top and
   bottom. Inside a grid cell that quietly takes 80px off the plate, so the
   engraving renders undersized in a half-empty cell rather than filling the
   track it was given. This bit the plate once already in the prose band. */
.topband .plate{margin:0; padding:16px 16px 12px}
.topband .cover-art{max-width:none}
/* The legend is the band's height, not the drawing: three sentences of mono at
   338px wrap to nearly seven lines, which cost more than the engraving above
   them. A tighter setting here is what keeps the whole plate inside the budget
   the index can afford. The prose is not shortened, only set closer. */
.topband .plate figcaption{font-family:inherit; font-size:.8rem; line-height:1.5;
  letter-spacing:0; margin-top:10px; padding-top:9px}
/* The five level chips measure 538px and the search field is fixed at 340, so on
   the band's narrower left track they cannot share a row. Chips take their own,
   which they have room for, rather than wrapping mid-row. */
.topband .fbchips{flex:1 0 100%}
/* The chip groups with the toggle at the right end of the row. */
.fbutil #startedBtn{margin-left:auto}
/* Only a chip that is actually showing hands the auto margin over; the node is
   in the DOM either way, and [hidden] does not unmatch a sibling selector. */
.fbutil #startedBtn:not([hidden]) + .textbtn{margin-left:0}

/* Two tracks are worth keeping well below 1180, because stacking costs the index
   the plate's whole height while sharing a row costs only the difference. At
   1000px wide, measured: side by side is 74px off the index, stacked is 356px,
   which is 22 titles against 62. So the band narrows the drawing instead of
   dropping it under the controls, and only gives up at 940 where the five level
   chips can no longer fit the left track. */
@media (max-width:1179px) and (min-width:940px){
  .topband{grid-template-columns:minmax(0,1fr) minmax(0,340px); gap:28px}
  /* The left track bottoms out at 501px here and the five chips measure 538.
     Measured at the floor: padding 10px left them 7px over, and font metrics
     differ enough across platforms that a 3px fit is a wrap on someone's
     machine. A point of size and one more of padding buys real slack, and
     only inside the band, where the narrowed track is the cause. */
  .topband .chipbtn{padding:6px 9px; font-size:.78rem}
}
@media (max-width:939px){
  .topband{grid-template-columns:minmax(0,1fr); gap:24px}
  /* Stacked, the figure was left-flushed with a dead gutter to its right the
     whole way from 660 to 939. Centered it reads as a plate, not a leftover. */
  .topband .plate{max-width:520px; margin-inline:auto}
}
/* Under 660 the findbar becomes display:contents so its rows can lay out against
   the page rather than against each other. Inside a grid that turns all five of
   them into grid items, which then collect the band's gap between every one and
   added 120px to the top of a phone screen. Block flow puts them back where they
   were when the findbar was a direct child of <main>. */
@media (max-width:659px){
  .topband{display:block}
  .topband .plate{margin-top:22px}
}
/* #index breaks out of the 1064 measure to 1440 above 1500, so the band follows
   it. Left where it was, the plate stopped 376px short of the index's right edge
   and the two read as belonging to different pages. The wider left track also
   stops the findbar wrapping, and the extra room goes to the drawing. */
@media (min-width:1500px){
  .topband{width:min(1440px, calc(100vw - 56px));
    margin-inline:calc(50% - min(720px, 50vw - 28px));
    grid-template-columns:minmax(0,1fr) minmax(0,420px)}
}

/* ------------------------------------------------------------ the prose band */
.proseband{margin:54px 0 0; padding:34px 0 0; border-top:1px solid var(--line);
  display:grid; grid-template-columns:minmax(0,58ch); gap:44px; align-items:start}
.proseband .lede{font-size:1.02rem; line-height:1.62; color:var(--dim); max-width:none;
  margin:0 0 20px}
.howblock{margin:0 0 16px}
.howblock h3{font-size:.98rem; margin:0 0 5px; letter-spacing:-.01em}
.howblock p{font-size:.88rem; color:var(--dim); margin:0; line-height:1.58}
.proseband h2{font-size:1.16rem; margin:22px 0 10px}
.proseband > div > h2:first-child{margin-top:0}
.proseband .prosecol p{color:var(--dim); font-size:.9rem; line-height:1.64; margin:0 0 10px}
.proseband .prosecol p b{color:var(--txt)}

.sitefoot{margin:70px 0 0; padding:26px 0 80px; border-top:1px solid var(--line);
  color:var(--dimmer); font-size:.84rem; display:flex; gap:18px; flex-wrap:wrap; align-items:center}
.sitefoot a{color:var(--dim)}
/* pushed to the far end on a wide screen; it wraps under on a narrow one */
.sitefoot .copy{margin-left:auto}
@media (max-width:600px){ .sitefoot .copy{margin-left:0} }

/* --------------------------------------------------------------------------
   Wide screens: the index breaks out of the 1064px measure to 1440px and packs
   into five columns. It stays centred on the measure it broke out of, so the
   findbar above it and the prose below it still line up with each other.
   ----------------------------------------------------------------------- */
@media (min-width:1500px){
  #index{width:min(1440px, calc(100vw - 56px));
    margin-inline:calc(50% - min(720px, 50vw - 28px))}
}

/* --------------------------------------------------------------------------
   A finger needs the target more than the page needs the density, so rows grow
   to 44px on any coarse pointer. The index becomes taller than one screen on a
   touch laptop, and that is the right trade.
   ----------------------------------------------------------------------- */
@media (pointer:coarse){
  #index{--row:44px; --rtline:20px}
  .rt{font-size:.86rem}
  .chipbtn,.textbtn{min-height:44px}
}

/* The rule that used to sit here collapsed the prose band's two columns to one
   below 1180. The band is one 74ch track at every width now that the plate has
   left it, and `1fr` overrode that cap rather than collapsing anything: at
   1100px wide the About text ran 130 characters to the line. minmax(0,58ch)
   already shrinks below its cap on its own, so nothing replaces it. The 58 is
   measured against the band's own font while the paragraphs inside are .9rem,
   which is why it is not the 74 a reading measure would suggest. */

@media (max-width:760px){
  body{font-size:16px}
  .wrap,.sitehead .in{padding:0 18px}
  .hero{padding:44px 0 4px}
}

/* ---------------------------------------------------------------- mobile ----
   The wordmark and the nav cannot share a row on a phone, so the header wraps
   into two, and every control gets a comfortable tap height. */
@media (max-width:760px){
  .sitehead .in{height:auto; flex-wrap:wrap; row-gap:8px; padding:10px 18px}
  .wordmark{flex-basis:100%; font-size:.88rem}
  .sitehead nav{margin-left:0; width:100%; justify-content:flex-start;
    flex-wrap:wrap; gap:10px; align-items:center}
  .sitehead nav a{font-size:.85rem; padding:6px 0}
  .langbtn{min-height:40px; padding:0 13px; font-size:.84rem}
  .tbtn{min-height:40px; padding:8px 13px}
  .fbtitle{scroll-margin-top:126px}
  .group,.anchor{scroll-margin-top:126px}
  .fbutil{align-items:flex-start; flex-direction:column; gap:8px}
  /* The auto margin that groups the two buttons at the right end of a row pushes
     the chip to the far edge of a left-aligned column instead, leaving it alone
     out to the right of a flush-left stack. Only a reader with saved progress
     ever saw it, because that is the only time the chip is not hidden. */
  .fbutil #startedBtn,.fbutil .textbtn{margin-left:0}
}

/* --------------------------------------------------------------------------
   One column. The findbar stops being a box of its own so that the search row
   becomes a direct child of <main>: position:sticky is bounded by its
   containing block, and inside a 44px-tall flex row there is nothing to stick
   to. --headh is the wrapped mobile header, measured rather than assumed.
   ----------------------------------------------------------------------- */
@media (max-width:659px){
  .findbar{display:contents}
  .fbtitle,.fbsearch,.fbchips,.fbutil,.fbrow{margin-top:10px}
  /* The 28px line box is there to make the desktop title row exactly 28px. On a
     phone the title wraps to three lines and 28px between them is a gap, not a
     rhythm, so it goes back to a normal ratio and the findbar loses 22px. */
  .fbtitle{margin-top:14px; flex-wrap:wrap}
  .fbtitle h1{line-height:1.24}
  /* --headh is written onto the root element by the render script, which
     measures the header. It has to be measured: the mobile header wraps, so its
     height depends on how the nav happens to break, and the Sinhala nav breaks
     differently. A hardcoded 106px left an 11px gap under the real 95px header,
     and page content scrolled through it. Erring low would be safe (the header
     sits at a higher z-index and paints over the field) but a gap never is. */
  .fbsearch{flex:none; position:sticky; top:var(--headh,95px); z-index:20;
    padding:6px 0; background:var(--bg)}
  .fbsearch input[type=search]{min-height:46px}
  .fbrow{flex-direction:column; align-items:flex-start; gap:6px}
  .fbdoor{white-space:normal}
  #index{--cols:1; --row:44px; --rtline:20px; padding-bottom:40px}
  .col{padding:0; border:0}
  .col + .col{border-left:0}
  .rt{font-size:.9rem}
  .rhook,.rwhy{font-size:.82rem; line-height:1.45}
  .rfacts,.rprog{font-size:.72rem}
  .proseband{margin-top:40px}
  .projband{padding-top:22px}
}
@media (max-width:420px){
  .wrap{padding:0 16px}
  .sitehead .in{padding:10px 16px}
}

@media (prefers-reduced-motion: reduce){
  .row{transition:none}
}
