/* The bar on a phone.

   Its own file for the reason share.css gives about itself: a great many
   agents edit site.css at once, and a stylesheet merge conflict is a site that
   renders wrong rather than one that fails loudly. Loaded last in
   web/templates/base.html on purpose, so it wins ties against search.css,
   which sets `.bar nav{width:100%}` below 620px at the same specificity. The
   rule that has to beat that one carries an extra class as well, so it wins on
   specificity rather than only on load order.

   Note for whoever maintains tools/test-design-rules.py: its CSS checks read
   web/static/site.css only, so nothing here is scanned by them. Nothing here
   declares a font-family or a face, so there is nothing for them to catch, but
   that scope is worth knowing before anyone moves a type rule into this file.

   ── the breakpoint, and why 720 ──────────────────────────────────────────────
   720px is the site's own number rather than a new one. site.css already
   concedes twice that the bar runs out of room: at 820 the nav takes a whole
   row of its own, and at 720 `.navsearch` takes a second one. Below 720 the
   bar is therefore three rows before anything is even open, and that is the
   width where folding earns its keep.

   Above 720 nothing in this file applies. The 720-to-820 band, where the nav
   sits on its own row with the theme toggle at the right end of it, renders
   exactly as it did: the theme toggle never moves in the markup, so no rule
   that positions it changes.

   ── what it is not ──────────────────────────────────────────────────────────
   Neither panel is a drawer. The site has no overlay pattern to copy and one
   would be a new register: a full-height slide, a scrim, and a transform far
   past the 3px this site's motion budget allows. Both panels here are the
   collapse the bar already uses, which is a full-width row under the top one.
   The search row is literally that, reusing the `order:3; flex:1 1 100%` that
   site.css line 413 already defines for it. The menu is the same idea drawn
   under the bar rather than inside it, which is the one thing that lets the
   theme toggle stay on the top row.

   ── what fits on the top row, measured ──────────────────────────────────────
   At 390px, `.wrap` leaves 358px of content. To the right of the wordmark sit
   three 40px controls with 8px between them, and 8px between the wordmark and
   the first of them: 144px in total.

   That 144 is the whole reason the theme toggle is a glyph down here. With its
   words showing it is about 98px rather than 40, and the row asked for roughly
   58px more than the screen had, which is what made it overflow.

   At 390 the row still does not quite fit. Measured at a true 390 on
   2026-08-29: the wordmark plus 144 is over 358, so the nav wraps to a second
   row, carrying the theme toggle with it. That puts the wordmark somewhere
   above 214px, wider than an estimate from character counts had it. The
   wordmark is not the thing to shrink over this: site.css:380 sized it UP to
   20px deliberately, and it is the site's own name. The second row is the
   honest collapse, so the job here is only to make it land in the right place,
   which is what the justify-content rule below does.

   A MEASUREMENT TRAP, WRITTEN DOWN SO THE NEXT PERSON DOES NOT PAY FOR IT
   TWICE. Chrome headless with --window-size silently floors at about 505px on
   at least one machine here: a run requesting 390 renders at ~505 and rescales
   the image afterwards, so the screenshot is 390 pixels wide and shows a
   layout that never existed. Two rounds of this file's history were spent
   chasing a bug that artefact invented. Use the DevTools Protocol with device
   emulation and confirm window.innerWidth from inside the page before
   believing any narrow-width reading of this bar.

   ── motion ──────────────────────────────────────────────────────────────────
   Both reveals animate rather than transition, because an element coming back
   from display:none has no transition to run. site.css's reduced-motion block
   caps animation-duration on every element on the page, so both are already
   covered by it and this file adds no second switch.

   ── contrast ────────────────────────────────────────────────────────────────
   All three icons are --grey on --paper, the colour the nav links beside them
   already carry: 5.88:1 in light (#5F5F5F on #FAF5EA) and 8.89:1 in dark
   (#A6A6A6 on #0E0E0E), both computed in site.css's own contrast block. A UI
   component needs 3:1. Hover goes to --ink, which is higher again. The menu
   panel's ground is --paper, the same surface the bar sits on, so every link
   in it keeps the ratio it has in the bar. */

/* Above 720 the links are direct flex children of the nav, exactly as they
   were before the div existed, and every `.bar nav a` rule still reaches
   them. */
.navlinks{display:contents}

/* Nothing to fold above the breakpoint, so there is nothing to press, and the
   theme toggle shows its words instead of a glyph. */
.barbtn{display:none}
.mode .ic{display:none}

@media (max-width:720px){

  /* The menu hangs off the bar. Scoped to the shell's own bar rather than
     `.bar`, which is also the name of a row in the `.bars` chart.

     column-gap only. site.css:612 sets both halves of the gap here and
     search.css:17 then resets the row half; overriding the shorthand would
     undo that quietly. 8px between three tap targets that are 40px wide is
     still 48px centre to centre.

     justify-content, replacing the space-between site.css:377 sets. Every
     control packs to the right and the wordmark's own auto margin below pushes
     it left, which reads identically to space-between while everything is on
     one row. The difference shows when the row runs out: space-between leaves
     a single wrapped item at flex-start, which stranded the theme toggle alone
     at the left edge while the two buttons it belongs with sat at the right of
     the row above. flex-end sends whatever wraps to the same side as the group
     it came from. */
  .wrap > .bar{position:relative; column-gap:var(--u); justify-content:flex-end}

  /* One auto margin, on the wordmark, doing the separating for every row.
     It used to sit on the first of the two icon buttons, which worked only
     while nothing wrapped: an auto margin absorbs free space on its own line,
     so it can push the group right but it cannot follow the group onto a
     second line, and it never applied to the nav at all. Two auto margins
     would not fix that either, since they would split the free space between
     them and separate the toggle from the buttons it sits with. */
  .wrap > .bar > .brand{margin-right:auto}

  /* An 18px icon with no padding is not a control you can hit with a thumb.
     40px square is the tap target; the glyph inside it is 20px, which is the
     wordmark's size rather than the 18px an icon takes when it sits in a line
     of text. */
  .barbtn{display:inline-flex; align-items:center; justify-content:center;
    width:40px; height:40px; padding:0; background:none; border:0;
    color:var(--grey); cursor:pointer;
    transition:color var(--beat) var(--ease)}
  .barbtn:hover{color:var(--ink)}
  .barbtn .ic{width:20px; height:20px}

  /* The nav is down to the theme toggle at this width, so it stops claiming a
     row of its own. Two rules to beat: site.css:616 sets the flex, search.css
     line 18 sets the width, and the extra class wins the second on specificity
     rather than trusting the order the two files load in. */
  .wrap > .bar nav{flex:0 0 auto; width:auto}

  /* The theme toggle, wearing the same clothes as the two buttons beside it.
     Its border goes with its words: three controls in a row, one of them in a
     box, reads as one of them being different, and it is not. */
  .bar .mode{display:inline-flex; align-items:center; justify-content:center;
    width:40px; height:40px; padding:0; background:none; border:0;
    color:var(--grey)}
  .bar .mode:hover{color:var(--ink)}
  .bar .mode .ic{width:20px; height:20px}
  /* site.css:358's own technique, applied at one width instead of always. The
     label is still the button's accessible name; it is only off the canvas. */
  .bar .mode .modetext{position:absolute; width:1px; height:1px; padding:0;
    margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap;
    border:0}

  /* Which glyph. The icon names where the button takes you rather than where
     you are, so a light page offers the moon and a dark one offers the sun.

     Three cases, not two, and this is the shape site.css:453 already uses for
     the two wordmark files: a reader who has never pressed the button has no
     data-theme at all, and the system decides for them. The default pair here
     is the light one, the media query below covers the reader whose system is
     dark, and the two data-theme rules cover the reader who has chosen. Those
     two win on specificity, which is what makes a manual choice beat the
     system setting rather than depending on which rule was written last. */
  .bar .mode .i-moon{display:block}
  .bar .mode .i-sun{display:none}
  :root[data-theme="dark"] .bar .mode .i-moon{display:none}
  :root[data-theme="dark"] .bar .mode .i-sun{display:block}
  :root[data-theme="light"] .bar .mode .i-moon{display:block}
  :root[data-theme="light"] .bar .mode .i-sun{display:none}

  /* Search. The row it opens into is the one site.css line 413 already
     describes; all this adds is whether you can see it. */
  .navsearch{display:none}
  .bar[data-search="open"] .navsearch{display:block;
    animation:bar-open var(--beat) var(--ease)}

  /* The menu. Bled to the window edges so it reads as the bar getting taller
     rather than a card floating over the page, and lifted over the hero, which
     is positioned and would otherwise paint on top of it. */
  .navlinks{display:none}
  .bar[data-nav="open"] .navlinks{display:flex; flex-direction:column;
    position:absolute; top:100%; z-index:90;
    left:calc(var(--pad) * -1); right:calc(var(--pad) * -1);
    padding:calc(var(--u)*1.5) var(--pad) calc(var(--u)*3);
    background:var(--paper); border-bottom:1px solid var(--hair);
    animation:bar-open var(--beat) var(--ease)}
  /* 22px, against the 15px site.css line 622 sets here. That 15px is a size
     for a link competing for a row with five others; once the link has a panel
     to itself it reads as a footnote, and a condensed face at 15px in an
     otherwise empty panel reads smaller still. 22px sits just under the --d3
     display step, which the panel has room for and which is close enough to
     the 20px wordmark above it that the two speak at one volume.

     The current page keeps the red underline it carries everywhere else,
     inherited from `.bar nav a.on`. Nothing about the marker changes; it just
     runs the width of the row now, which in a stacked list is the clearer
     reading of it. */
  .bar[data-nav="open"] .navlinks a{margin-left:0; font-size:22px;
    padding:calc(var(--u)*1.25) 0}
}

/* The reader who has never touched the button and whose system is dark. Paired
   with the default above rather than replacing it, so the two data-theme rules
   inside the block above still beat both. */
@media (max-width:720px) and (prefers-color-scheme:dark){
  .bar .mode .i-moon{display:none}
  .bar .mode .i-sun{display:block}
}

/* 3px and 160ms, the site's whole motion budget. Declared outside the media
   query because a keyframes rule is not conditional on one. */
@keyframes bar-open{
  from{opacity:0; transform:translateY(-3px)}
  to{opacity:1; transform:none}
}
