/* bj-responsive.css
   Shared responsive header + three-tier OUTLINE menu.
   Never edits bartonjames.css. Tokens from the site.
   (No version number: see the note at the top of inc/bjnav.php.)

   Interaction. The full spec is docs/HANDOFF.md section 6.2; this is the map
   of what lives in this file.
     - AREA -> LINE on intent-delayed hover (120ms open / 280ms close, done
       with transition-delay so it survives without JS) or on click. Hover is
       gated behind (hover:hover) and (pointer:fine) so tablets get tap only.
     - LINE -> POINT on click. The old open-on-mouse-travel is gone: it fired
       on a plain pointer move rather than a drag and reflowed the list under
       the cursor while you were aiming at it.
     - Every panel is newspaper columns, up to four, one column earned per
       four chapters. ~113px per column, 6px gutter, so four columns occupy
       the 470px three used to need. Nothing is truncated; the "N more"
       ellipsis was removed in v21 along with the markup that carried it.
     - A chapter with no cards is a plain link, not a disclosure.
     - A chapter's cards open as a BAND under the panel, never inside the
       column flow, which would reflow every chapter below them.
     - p-words grid: 16 across -> 8+8 at <=900px -> phone drawer at <=600px.
       The drawer drills one level at a time, sets both the p-words and each
       chapter list in three columns, and slides horizontally when a list
       needs more than three.
   Everything the menu renders is read from the folders on each request;
   nothing in this file needs touching when cards are added or removed. */
:root{ --ink:#333; --blue:#006699; --slate:#334d55; --grey:#666;
  --hair:#d7d7d7; --hover:#f2f6f7; --panel:#fff;
  --body:Arial, sans-serif; --display:Verdana, Arial, sans-serif; }
.bj-wrap{ max-width:1024px; margin:0 auto; padding:0 14px; font-size:85%; }

/* banner */
.bj-banner{ display:flex; align-items:center; justify-content:space-between; gap:12px; padding:6px 0; }
.bj-banner .who{ line-height:1.15; }
.bj-banner .name{ font-family:var(--display); font-size:147%; font-weight:bold; color:var(--slate); margin:0; }
.bj-banner .name .np{ white-space:nowrap; }
.bj-banner .role{ font-size:82%; color:var(--grey); margin:1px 0 0; }
.bj-banner img{ display:block; height:auto; max-width:100%; }

/* nav shell */
.bj-nav{ border-top:1px solid var(--hair); border-bottom:1px solid var(--hair); }
.bj-nav ul{ list-style:none; margin:0; padding:0; }
/* AREA row: left-justified grid, 16 across */
.bj-nav > ul{ display:grid; grid-template-columns:repeat(16,max-content);
  justify-content:start; column-gap:2px; }
.bj-nav .area-item{ position:relative; }
.bj-nav .area{ display:block; background:none; border:0; cursor:pointer; text-align:left;
  font-family:var(--body); font-size:84%; font-weight:normal; color:var(--blue);
  padding:3px 6px; line-height:1.25; white-space:nowrap; }
.bj-nav .area-item:hover > .area,
.bj-nav .area-item.open > .area{ color:var(--slate); text-decoration:underline; }

/* LINE outline panel: opens directly UNDER the AREA, scroll-capped.
   v20: hover no longer opens instantly. Opening waits ~120ms and closing
   ~280ms - the "hover intent" rule, standard practice since the mid-2000s.
   Travelling across the fifteen p-words no longer flickers a panel open
   under every one of them, and a diagonal move down into a panel no longer
   loses it on the way. Done with transition-delay rather than script, so it
   still holds if the JS never runs. Uses visibility rather than display
   because display cannot be delayed, and because visibility:hidden keeps the
   hidden links out of the tab order exactly as display:none did. */
.bj-nav .submenu{ position:absolute; left:0; top:100%; z-index:40; min-width:200px; padding:2px 0;
  max-height:70vh; overflow:auto;   /* overridden to none >=601px, see v21 block */
  background:var(--panel); border:1px solid var(--hair);
  box-shadow:0 4px 10px rgba(0,0,0,.14);
  visibility:hidden; opacity:0;
  transition:visibility 0s .28s, opacity 0s .28s; }
/* pointer-gated: a tablet reports no true hover, and used to get hover-open
   and tap-toggle firing on the same finger press, which left panels stuck */
@media (hover:hover) and (pointer:fine){
  .bj-nav .area-item:hover > .submenu{ visibility:visible; opacity:1;
    transition:visibility 0s .12s, opacity 0s .12s; }
}
/* deliberate opens - click, or keyboard focus landing inside - are immediate
   and are not taken away while focus is still in there */
.bj-nav .area-item.open > .submenu,
.bj-nav .submenu:focus-within{ visibility:visible; opacity:1; transition:none; }
/* v20: flip to the right edge when the panel would otherwise leave the
   window. The right-hand p-words used to push their panels past the viewport
   and give the whole page a horizontal scrollbar. Class set by the nav JS,
   which measures the panel against .bj-wrap's own frame. */
.bj-nav .submenu.flip{ left:auto; right:0; }

.bj-nav .line-item{ position:relative; }
.bj-nav .line{ display:block; width:100%; text-align:left; background:none; border:0; cursor:pointer;
  font-family:var(--body); font-size:86%; color:var(--blue); padding:2px 8px 2px 11px; line-height:1.3; }
.bj-nav .line-item:hover > .line,
.bj-nav .line-item.open > .line{ color:var(--slate); text-decoration:underline; }

/* POINT list: OUTLINE, in-flow under its LINE, ~1/2 inch to the right */
.bj-nav .pointmenu{ display:none; }
.bj-nav .line-item.open > .pointmenu{ display:block; }
.bj-nav .pointmenu a{ display:block; font-size:85%; padding:2px 8px 2px 22px; line-height:1.3; }
.bj-nav .pointmenu a:hover{ text-decoration:underline; }

/* the auto "more" ellipsis */

.bj-nav .navtoggle{ display:none; background:none; border:0; cursor:pointer;
  font-family:var(--body); font-size:90%; color:var(--blue); padding:7px 12px; width:100%; text-align:left; }
:focus-visible{ outline:2px solid var(--blue); outline-offset:2px; }

/* ---------------------------------------------------------------------------
   BREADCRUMB  (v27: legacy placement and weight)
   The original site put this as one quiet line across the very top of every
   page, above everything else, in 85% Arial, and greyed out whatever was not
   a working link rather than removing it - so the bar is always in the same
   place, always the same shape, and easy to read past. That is reproduced
   here. What is NOT reproduced is the original's content: its AREA and LINE
   slots were hand-maintained and, on every page ever shipped, left empty. The
   path here comes from bj_here() reading the file's own location, so it is
   always right and always complete.
   --------------------------------------------------------------------------- */
.bj-crumb{ display:flex; justify-content:space-between; align-items:baseline; gap:14px;
  font-family:var(--body); font-size:85%; color:var(--grey);
  padding:5px 6px; border-bottom:1px solid var(--hair); white-space:nowrap; }
.bj-crumb .bc{ min-width:0; overflow:hidden; text-overflow:ellipsis; }
.bj-crumb a{ color:var(--grey); text-decoration:none; }
.bj-crumb a:hover, .bj-crumb a:focus-visible{ color:var(--blue); text-decoration:underline; }
.bj-crumb .bc-sep{ color:#c4c4c4; }
/* #999999 is the legacy's own inactive grey, kept exactly */
.bj-crumb .bc-off{ color:#999999; }
.bj-pager{ white-space:nowrap; }
.bj-pager .pg-sl{ display:none; }   /* "12 of 33" on a desktop, "12/33" on a phone */

/* content helpers */
/* 640px is the original's own deliberate constant -- every AREA page's
   intro table used <table width="640"> (confirmed across all 15). Using
   it as the general content measure too (not just the intro) keeps one
   consistent width everywhere instead of juggling two close-but-different
   numbers, and reproduces the original's consistent "letter paper"
   reading measure -- text wrapped at a comfortable width instead of
   stretching edge-to-edge on a wide desktop. Unlike the original's fixed
   layout, this still shrinks naturally on narrow screens since max-width
   only clamps the upper bound. */
.bj-content{ padding:8px 2px; max-width:640px; }
.bj-list{ list-style:none; margin:0; padding:0; }
.bj-list li{ padding:3px 0; border-bottom:1px solid var(--hair); }
.bj-tiles{ display:flex; flex-wrap:wrap; gap:12px; }
.bj-tiles a{ flex:1 1 180px; border:1px solid var(--hair); padding:10px; background:var(--panel); }
.bj-img{ max-width:100%; height:auto; display:block; }
.siteinfo{ margin-top:16px; border:1px solid var(--hair); font-size:80%; padding:6px 10px; }

/* STAGE 2 - TWO ROWS, half the p-words on each, the first row taking the odd one.
   v152, Bart 2026-09-30: "two rows rather than this compact three (set it to
   stay 8 on one line and 7 on the other, if ever a sixteenth, then eight and
   eight)". This reverses the earlier choice of five across (three even rows of
   five), which had judged 8-then-7 lopsided; Bart prefers the two rows.
   The column count is half the AREAs rounded up, read from the list itself with
   :has(), so a sixteenth AREA needs no edit here: 15 and 16 give 8 across,
   17 and 18 give 9. */
@media (max-width:900px) and (min-width:601px){
  .bj-nav > ul{ grid-template-columns:repeat(8,max-content); }
  .bj-nav > ul:has(> li:nth-child(17)){ grid-template-columns:repeat(9,max-content); }
  .bj-nav > ul:has(> li:nth-child(19)){ grid-template-columns:repeat(10,max-content); }
}
/* STAGE 3 - the phone drawer. v20 makes it a real one.
   Before: .navtoggle toggled a class .expanded that no stylesheet ever
   defined, so the button did nothing and the whole tree stood open inline.
   Measured on a 375px screen: 1,413px of menu above the fold, with the page's
   own content starting past the second screenful. Now the drawer is closed
   until asked for, and it drills ONE level at a time with a Back row, so no
   screen ever carries more than a single list - the pattern every large
   catalogue has settled on, because a 143-card chapter cannot be browsed as
   part of a nested accordion. Levels are driven by .d1/.d2 on the nav plus
   .active on the item you drilled into, both set by the nav JS. */
@media (max-width:600px){
  .bj-nav .navtoggle{ display:block; }
  .bj-nav > ul{ display:none; max-width:none; }
  .bj-nav.expanded > ul{ display:block; }
  .bj-nav .area-item{ border-top:1px solid var(--hair); }
  .bj-nav .submenu{ position:static; max-height:none; overflow:visible; box-shadow:none;
    border:0; background:var(--hover); min-width:0;
    visibility:visible; opacity:1; transition:none; display:none; }
  .bj-nav .area-item.open > .submenu{ display:block; }   /* tap, never hover */
  /* Touch rows. 44px is the platform ideal on both phone OSes; WCAG 2.2's
     actual floor is 24px. 34px sits between them, which is what "three rows
     in the space of two" asks for while staying well clear of the floor.
     One number, here, if it ever wants changing again. */
  .bj-nav .navtoggle, .bj-nav .area, .bj-nav .line, .bj-nav .line-link,
  .bj-nav .pointmenu a, .bj-nav .gopage a{
    min-height:30px; display:flex; align-items:center; padding-top:0; padding-bottom:0; }
  .bj-nav .area{ padding-left:24px; }                    /* 1/4 in */
  .bj-nav .line, .bj-nav .line-link{ padding-left:48px; }/* 1/2 in */
  .bj-nav .pointmenu a{ padding-left:72px; }             /* 3/4 in */

  /* --- drilled in: show one level, hide the rest --- */
  .bj-nav.d1 > ul > .area-item:not(.active),
  .bj-nav.d2 > ul > .area-item:not(.active){ display:none; }
  .bj-nav.d1 > ul > .area-item.active > .area,
  .bj-nav.d2 > ul > .area-item.active > .area{ display:none; }
  .bj-nav.d1 > ul > .area-item.active > .submenu,
  .bj-nav.d2 > ul > .area-item.active > .submenu{ display:block; background:none; }
  .bj-nav.d2 .submenu > li:not(.active){ display:none; }
  .bj-nav.d2 .line-item.active > .line{ display:none; }
  .bj-nav.d2 .line-item.active > .pointmenu{ display:block; }
  /* one level on screen means one indent; the stepped 24/48/72 only makes
     sense when the levels are stacked together */

  .bj-nav.d2 .pointmenu a{ padding-left:24px; }
  .bj-nav.d1 .line-item, .bj-nav.d2 .pointmenu > li{ border-top:1px solid var(--hair); }
}
@media (prefers-reduced-motion:reduce){ *{ transition:none!important; } }

/* v14 additions: "overview" link that makes a parent card reachable from its own submenu */
/* The "{name} overview" row is the panel's own card - the supercategory the
   rest of the panel sits under - so it is set BOLD in the menu's own face
   rather than italic. Italic read as a footnote to the list; bold reads as its
   heading, which is what it is. */
.bj-nav .gopage a{ display:block; font-family:var(--body); font-size:86%;
  font-weight:bold; font-style:normal; color:var(--blue);
  padding:3px 8px 3px 11px; line-height:1.3; border-bottom:1px dotted var(--hair); }
.bj-nav .gopage a:hover{ color:var(--slate); text-decoration:underline; }
.bj-nav .pointmenu .gopage a{ padding-left:11px; }
/* v25: the home tiles get three across on a desktop.
   They used to sit inside .bj-content's 640px text measure, which allowed two,
   so fifteen tiles ran to eight rows. The measure is right for reading and
   wrong for a grid of pictures, so the grid alone is given a wider frame - the
   same min(frame, viewport) formula the hero images use - while every
   paragraph on the page stays at 640. Three 300px tiles plus their gaps come
   to 928, and the grid falls back to two and then one on its own. */
.bj-home{ display:grid; gap:14px;
  width:min(960px, calc(100vw - 28px));
  grid-template-columns:repeat(auto-fill, minmax(270px, 1fr)); }
.bj-home a{ box-sizing:border-box; border:1px solid var(--hair); background:#fff;
  padding:8px; text-align:center; }
.bj-home img{ max-width:100%; height:auto; display:block; margin:0 auto 6px; }
@media (max-width:600px){
  .bj-nav .gopage a{ padding-left:48px; } .bj-nav .pointmenu .gopage a{ padding-left:72px; }
}

/* v16: imported content uses the original site's own tags (h2/h3/h4,
   ul/li, hr, p) directly -- styled by bartonjames.css, which is already
   included site-wide -- instead of a custom boxed design, so pages read
   close to the original's fonts/sizes/colors/spacing. */
.bj-content p{ margin:0 0 10px; }
.bj-content ul{ margin:4px 0 12px; padding-left:22px; }
.bj-content li{ padding:1px 0; }
.bj-content hr{ border:0; border-top:1px solid var(--hair); margin:12px 0; }
.bj-placeholder{ color:var(--grey); font-style:italic; }

/* the original's photo-left/text-right intro table, as a flex row.
   Text column is capped (not flex:1-grow) so it wraps into narrower,
   taller lines that echo the photo's height -- matching the original's
   fixed-width table cell instead of stretching to fill a wide screen. */
/* 300 (img) + 20 (gap) + 320 (text) = 640, matching the original's
   <table width="640"> exactly. */
.bj-intro{ display:flex; gap:20px; align-items:flex-start; margin:6px 0 14px; flex-wrap:wrap; }
.bj-intro-img{ flex:0 0 300px; max-width:300px; height:auto; display:block; }
.bj-intro-text{ flex:0 1 320px; max-width:320px; min-width:0; }
@media (max-width:600px){
  .bj-intro-img{ flex-basis:100%; max-width:100%; }
  .bj-intro-text{ max-width:100%; }
}

/* v18: "hero" variant for a LINE whose image is a dense montage worth seeing
   at size (e.g. publish_AREA's book-chapter-spread collages, each a collage
   of every project in that chapter) -- the 300px column is too small to read
   a montage like that. Image stacks full width above the text instead of
   beside it. Opt-in via an extra class on the same .bj-intro wrapper, so the
   shared side-by-side layout above is untouched for the ~1,500 pages still
   using it. */
.bj-intro-hero{ flex-direction:column; }
.bj-intro-hero .bj-intro-text{ flex:0 0 auto; max-width:640px; }
.bj-intro-text h3{ margin-top:0; }

/* v19 (2026-08-21): let the hero image itself grow past .bj-content's 640px
   text measure, up to .bj-wrap's own frame -- min(1024px, 100vw-28px) is
   .bj-wrap's exact content-box formula (max-width:1024px, 14px padding each
   side), so the image's right edge lands under the header logo's right edge
   without introducing a second width constant. Body copy and headings stay
   at 640 (untouched above and in the h3/p blocks after this div) - only the
   image is asked to be given the wider frame it visually earns, on a screen
   wide enough to offer it; a browser narrower than 640 still just shows the
   image at its own full (narrower) width same as before. Works because
   .bj-intro-hero itself is a plain block child of .bj-content (not a
   flex/grid item of anything), so an explicit-width descendant can overflow
   its 640px box without being clamped back down - no negative-margin
   "breakout" trick needed since nothing here is centered to compensate for.
   The <img>'s usemap coordinates stay correct at any resulting size because
   inc/footer.php's v18 rescale script recalculates them against whatever
   size the image actually renders at, not a fixed assumption. */
.bj-intro-hero .bj-intro-img{
  flex:0 0 auto;
  width: min(1024px, calc(100vw - 28px));
  max-width: min(1024px, calc(100vw - 28px));
}

/* v50 (2026-08-22): the POINT card's own photograph gets the same wider frame
   the LINE hero got in v19 above -- up to .bj-wrap's content box, the same
   min(1024px, 100vw-28px) formula, so no second width constant enters the
   stylesheet. A photograph IS the content of a POINT card; leaving it at the
   640px text measure was sizing the subject to fit the caption.

   WHY max-width AND width:auto, where v19 used a flat width. v19's images are
   the 30 chapter montages, all 2400px, so asking for 1024 always has the pixels
   to fill it. POINT cards are not uniform: most photographs are now 2400+, but
   some originals are genuinely smaller (a 2003 camera at 1600x1200, one 640px
   phone capture), and every POINT card outside photo_AREA still carries the
   250x200 placeholder. A flat width would ENLARGE all of those - adding pixels
   without adding detail, which reads softer than leaving them alone. width:auto
   makes each image render at its own natural size and only capped by the
   max-width, so it expands to 1024 exactly when the quality permits and is
   otherwise untouched. Bart's instruction, 2026-08-22.

   Same reason as v19 this needs no breakout trick: .bj-img is a plain block
   child of .bj-content, not a flex or grid item, so it may overflow the 640px
   measure without being clamped, and nothing here is centered to compensate. */
.bj-content > .bj-img{
  width: auto;
  max-width: min(1024px, calc(100vw - 28px));
}

/* a small row of linked document thumbnails (e.g. resume/CV covers) */
.bj-thumbs{ display:flex; gap:14px; margin:10px 0; flex-wrap:wrap; }
.bj-thumb{ margin:0; text-align:center; font-size:85%; }
.bj-thumb img{ display:block; border:1px solid var(--hair); }
.bj-thumb figcaption{ margin-top:4px; }

/* ===========================================================================
   v17: "you are here" - orientation while drilling AREA > LINE > POINT.
   The crumb now renders the true path (see bj_breadcrumb in bjnav.php); the
   current rung is bold and unlinked. In the menu, the AREA/LINE/POINT you are
   on carry class "here" and are bolded, so the always-visible p-word row shows
   which area you are in without opening anything.
   =========================================================================== */
.bj-crumb .bc-here{ font-weight:bold; color:var(--slate); }
.bj-nav .area-item.here > .area{ font-weight:bold; color:var(--slate); }
.bj-nav .line-item.here > .line{ font-weight:bold; }
.bj-nav .pointmenu a.here{ font-weight:bold; color:var(--slate); }
/* position within the current folder, e.g. "7 of 31", beside prev|next */
.bj-pager .bj-pos{ color:var(--grey); padding-left:6px; }

/* v17: the site map - every card on one page, for Find-in-page and for
   seeing the shape of the whole site at once. */
.map-jump{ font-size:90%; line-height:1.7; margin:0 0 6px; }
.bj-map-note{ color:var(--grey); font-size:90%; margin:0 0 14px; }
.bj-map, .bj-map ul{ list-style:none; margin:0; padding:0; }
.bj-map ul{ padding-left:18px; }
.bj-map li{ padding:1px 0; }
.bj-map > .map-area{ margin:0 0 16px; padding-top:8px; border-top:1px solid var(--hair); }
.bj-map .map-area > a{ font-family:var(--display); font-weight:bold; font-size:112%; }
.bj-map .map-line > a{ font-weight:bold; }
.bj-map .map-n{ color:var(--grey); font-size:85%; }
.bj-map .map-empty{ font-style:italic; }

/* v18: the contact form. Plain, same tokens as everything else. */
.bj-form p{ margin:0 0 12px; }
.bj-form label{ display:block; font-weight:bold; margin-bottom:3px; }
.bj-form .req{ color:#a33; font-weight:normal; }
.bj-form input[type=text], .bj-form input[type=email], .bj-form textarea{
  width:100%; max-width:420px; box-sizing:border-box; padding:6px 7px;
  font-family:var(--body); font-size:100%; color:var(--ink);
  border:1px solid #bbb; background:#fff; }
.bj-form textarea{ max-width:100%; resize:vertical; }
.bj-form input:focus, .bj-form textarea:focus{ border-color:var(--blue); outline:none; }
.bj-form button{ font-family:var(--body); font-size:100%; color:#fff;
  background:var(--blue); border:0; padding:8px 18px; cursor:pointer; }
.bj-form button:hover{ background:var(--slate); }
/* the spam trap must be invisible to people but still submitted by bots, so
   it is moved off-screen rather than display:none, which some bots detect */
.bj-trap{ position:absolute; left:-5000px; width:1px; height:1px; overflow:hidden; }
.bj-ok{ border-left:3px solid var(--blue); padding:8px 12px; background:var(--hover); }
.bj-errors{ border-left:3px solid #a33; padding:8px 12px; background:#fdf3f3; margin-bottom:14px; }
.bj-errors ul{ margin:4px 0 0; }


/* ===========================================================================
   v20 (2026-08-21): menu behaviour, on top of the fixes made in place above.
   Nothing here is hand-maintained: every label, count and level still comes
   out of bj_menu() reading the folders at request time, so adding or removing
   a card in any AREA, LINE or POINT folder just changes what is rendered.
   =========================================================================== */

/* a chapter holding no cards is a link, not a disclosure. Styled to sit level
   with its sibling chapter buttons so the column still reads as one list. */
.bj-nav .line-link{ display:block; font-family:var(--body); font-size:86%; color:var(--blue);
  padding:2px 8px 2px 11px; line-height:1.3; text-decoration:none; }
.bj-nav .line-link:hover,
.bj-nav .line-item.leaf:hover > .line-link{ color:var(--slate); text-decoration:underline; }
.bj-nav .line-item.leaf.here > .line-link{ font-weight:bold; color:var(--slate); }

/* card count beside a chapter. Information scent: knowing a chapter holds 84
   cards before opening it is most of the decision. Counted from the folder. */
.bj-nav .n{ color:var(--grey); font-size:85%; font-weight:normal; padding-left:5px; }
.bj-nav .n::before{ content:"("; }
.bj-nav .n::after{ content:")"; }

/* skip link: with ~1,650 focusable nodes in the menu, reaching the page by
   keyboard without one means tabbing through the entire site index first.
   It is the first focusable thing in the document, so it is offscreen until
   focused and then drops in above the banner rather than shifting it. */
.bj-skip{ position:absolute; left:-9999px; top:0; z-index:100; }
.bj-skip:focus{ left:8px; top:8px; display:inline-block; padding:6px 10px;
  font-family:var(--body); font-size:85%; color:var(--blue);
  background:var(--panel); border:1px solid var(--hair); }

/* the phone drawer's Back row */
.bj-drill{ display:none; align-items:center; gap:10px; border-bottom:1px solid var(--hair); }
.bj-drill .bj-back{ background:none; border:0; cursor:pointer; font-family:var(--body);
  font-size:90%; color:var(--blue); padding:10px 12px; min-height:44px; }
.bj-drill .bj-drill-title{ font-family:var(--display); font-weight:bold; color:var(--slate); font-size:90%; }
@media (max-width:600px){
  .bj-nav.expanded .bj-drill:not([hidden]){ display:flex; }
}
@media (min-width:601px){ .bj-drill{ display:none !important; } }

/* reduced motion should not defeat the hover-intent delay: the delay is not
   an animation, it is what stops panels flickering open under a passing
   cursor. Restated with !important because the blanket rule above uses one. */
@media (prefers-reduced-motion:reduce){
  .bj-nav .submenu{ transition:visibility 0s .28s, opacity 0s .28s !important; }
  .bj-nav .area-item:hover > .submenu{ transition:visibility 0s .12s, opacity 0s .12s !important; }
  .bj-nav .area-item.open > .submenu,
  .bj-nav .submenu:focus-within{ transition:none !important; }
}

/* drill mode wins the indent argument against the stacked-level padding set
   further up, which is more specific for the overview rows */
@media (max-width:600px){
  .bj-nav.d2 .pointmenu .gopage a{ padding-left:24px; }
}

/* ---------------------------------------------------------------------------
   v20: columnar panels for an AREA whose chapters are all leaves.
   The class is decided in bj_menu() from what is actually in the folders, so
   a chapter gaining its first card turns its AREA back into a single-column
   panel by itself, and an AREA growing past 11 or 21 leaf chapters picks up
   its second or third column the same way. Nothing to set by hand.

   Columns rather than a grid on purpose: CSS columns fill top-to-bottom and
   then wrap, so an A-to-Z list still reads A-to-Z down the first column. A
   row-major grid of the same items would make the eye jump sideways between
   every pair of neighbours.
   --------------------------------------------------------------------------- */
/* Columns are sized by content width, not by a wide fixed panel: column-width
   sets the target and column-count caps how many, so a set of short chapter
   labels packs tight instead of being stretched across a 660px panel. The gap
   is deliberately small; these are one-line labels in a bordered panel, and
   they do not need a wide gutter to stay apart. */
/* column-count only, never column-width: with both set the browser drops to
   whatever count the width happens to allow, which silently turned a
   four-column panel into two wide ones. Panel width is set per column count
   so a column is always about 113px. The labels take that comfortably - the
   median chapter label measures 56px - so four columns now sit inside the
   width three used to need. */
.bj-nav .submenu{ column-gap:6px; column-fill:balance; }
.bj-nav .submenu > li{ break-inside:avoid; }
.bj-nav .submenu > .gopage{ column-span:all; }
/* Columns are 125px, not the 113 they were: the widest unbreakable unit in
   the menu is a chapter's last word plus its count, "Communication (21)" at
   105px, and at 113 minus the row's 8px of padding that did not fit, so the
   count was pushed onto a line by itself. 125 leaves it room. */
.bj-nav .submenu.cols-2{ column-count:2; min-width:256px; }
.bj-nav .submenu.cols-3{ column-count:3; min-width:387px; }
.bj-nav .submenu.cols-4{ column-count:4; min-width:518px; }
/* in a 113px column the row's own padding is the widest thing competing with
   the label, so it comes down too */
.bj-nav .submenu[class*="cols-"]{ padding:2px 6px; }
.bj-nav .submenu[class*="cols-"] .line,
.bj-nav .submenu[class*="cols-"] .line-link,
.bj-nav .submenu[class*="cols-"] > .gopage a{ padding-left:5px; padding-right:3px; }
/* a narrower desktop cannot carry a 470px panel under every p-word, so the
   widest panels step down one column rather than shoving the page sideways */
@media (max-width:900px) and (min-width:601px){
  .bj-nav .submenu.cols-4{ column-count:3; min-width:387px; }
}
/* The phone drawer gets columns too, and here BOTH column-count and
   column-width are set on purpose: with both, the browser uses as many
   columns as the width actually allows, up to the count. On a 375px screen
   that comes out at three; on a small phone in a narrow window it drops to
   two by itself rather than squeezing. Chapter labels are short enough to
   take it. Card titles are not, so the card list stays a single column. */
@media (max-width:600px){
  /* the desktop panel widths are for a floating overlay; in the drawer the
     panel is the page width */
  .bj-nav .submenu, .bj-nav .submenu[class*="cols-"]{ min-width:0; padding:0; }
  /* the p-words: FOUR columns (v153, Bart 2026-09-30: "tighter, 4x4 if ... sixteen, (or
     4 x 4, with the last [column] having only ... three if 15)"). The browser balances
     the columns, so fifteen land 4, 4, 4, 3 with the short column top-aligned, and
     sixteen land 4 by 4, with nothing to count. Was three columns of five. */
  .bj-nav > ul{ min-width:0; column-count:4; column-gap:4px; }
  .bj-nav > ul > li{ break-inside:avoid; }
  /* A chapter list fills one column top to bottom, then starts the next.
     --rows (set per panel by bj_menu, from the chapter count) is four
     columns' worth capped at SIX, so a normal chapter list lands in four
     columns and an unusually long one keeps going to the RIGHT and slides,
     rather than running down the page. Six rather than eight because
     vertical space is what a phone is short of: see bj_menu(). column-fill:
     auto is what makes a column fill before the next one starts; balance
     would spread them. */
  /* once drilled in, the root list is down to one visible item, so it must
     stop being a three-column layout or that item is stuck in a 110px column */
  .bj-nav.d1 > ul, .bj-nav.d2 > ul{ column-count:1; }
  /* iOS hides its scrollbar until you are already scrolling, so the styled
     bar is no affordance there at all. A fade at the right edge says "more"
     without needing a gesture first, and it only appears while there IS more
     to the right, because it is painted on the scrolling box itself. */
  .bj-nav.d1 > ul > .area-item.active{ overflow-x:auto; overflow-y:hidden;
    -webkit-overflow-scrolling:touch; padding-bottom:2px;
    -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 22px),transparent);
    mask-image:linear-gradient(to right,#000 calc(100% - 22px),transparent); }
  .bj-nav.d1 .submenu{
    /* A DEFINITE width, not max-content. With max-content every column takes
       the width of the longest unwrapped label - "ABook Cover3D" at 102px -
       so only three fitted across a phone and the fourth was clipped
       mid-word, which reads as broken text rather than as "there is more".
       Four columns are sized to the frame instead and the labels wrap inside
       them; --cols comes from bj_menu(), so a list needing five or more
       columns is exactly that much wider and slides. */
    /* A DEFINITE width, from --cols. max-content was tried and is wrong twice
       over: sized to the content it makes every column as wide as the longest
       unwrapped label, and sized with column-width it collapses to a single
       column. --cols is a PHP estimate and can be one short when a label wraps
       to two lines, so the nav script corrects it against the real layout
       after the drawer opens - see fitDrawer(). */
    --colw:calc((100vw - 46px) / 4);
    min-width:0;
    width:calc(var(--cols,4) * (var(--colw) + 6px) - 6px);
    column-count:var(--cols,4); column-width:auto;
    column-gap:6px; column-fill:auto;
    /* + 30px for the spanning heading above the columns */
    height:calc(var(--rows,6) * 30px + 30px); }
  .bj-nav.d1 .submenu > li{ break-inside:avoid; }
  /* The overview row is the panel's own card - the heading everything under
     it belongs to. As the first item of column one it read as just another
     chapter, only cramped, and it pushed that column out of step with the
     other three. It spans the full width above the columns instead, which is
     where a panel heading goes, and is set larger and bolder to match. */
  .bj-nav.d1 .submenu > .gopage{ column-span:all; }
  /* The heading stays put while the columns slide under it, so you never lose
     track of which AREA you are looking at however far right you scroll. It is
     the one fixed thing in a moving set - which is what a heading is for.
     Sticky against the scrolling box, and given the visible width rather than
     the content width so it fills the view rather than the (wider) column set. */
  .bj-nav.d1 .submenu > .gopage{ position:sticky; left:0; z-index:2;
    width:calc(100vw - 28px); background:var(--panel); }
  .bj-nav.d1 .submenu > .gopage a{ font-size:100%; font-weight:bold;
    color:var(--slate); text-align:center; padding:0 0 4px; margin-bottom:4px;
    border-top:1px solid var(--hair); border-bottom:1px solid var(--hair);
    padding-top:4px; }
  .bj-nav.d1 .submenu > .gopage a:hover{ color:var(--blue); }
  /* the stepped indent means nothing inside a column set, and it would eat a
     fifth of the column's measure */
  .bj-nav.d1 .line, .bj-nav.d1 .line-link,
  .bj-nav.d1 .gopage a{ padding-left:6px; padding-right:4px; }
  /* card titles are full sentences, not two words: they stay one column and
     scroll down the way a list of titles should */
  .bj-nav .pointmenu{ column-count:auto; column-width:auto; }
  .bj-nav.d2 > ul > .area-item.active{ overflow:visible; }
  .bj-nav.d2 .submenu{ min-width:0; width:auto; height:auto;
    column-width:auto; column-count:auto; }
  /* in columns the full-width rules between rows read as clutter; the column
     gap already separates them */
  .bj-nav .area-item{ border-top:0; }
  .bj-nav.d1 .line-item, .bj-nav.d2 .pointmenu > li{ border-top:0; }
  .bj-nav .line, .bj-nav .line-link, .bj-nav .area{ line-height:1.2; }
  /* v153: the top-level p-word grid is tighter. Rows 26px, still above WCAG 2.2's
     24px floor; the 1/4-inch indent (meant for a single-column list) comes down so
     the longest word fits a quarter of a phone's width. Drilled-in levels unchanged. */
  .bj-nav:not(.d1):not(.d2) > ul > .area-item > .area{
    min-height:26px; padding-left:6px; padding-right:2px; }
}

/* ---------------------------------------------------------------------------
   v21: the CARD BAND.
   With every panel in columns, a card list can no longer open inside the
   column flow: expanding one chapter would reflow every chapter below it into
   different columns while the reader was looking at them. So the open card
   list is lifted out and drawn as a full-width band directly under the panel,
   in its own columns. The chapter columns above never move, which is the whole
   point, and the band carries its own height cap and scroll so a 143-card
   chapter cannot run off the bottom of the screen.
   Desktop only; the phone drawer drills instead.
   --------------------------------------------------------------------------- */
@media (min-width:601px){
  /* the band anchors to the PANEL, so the chapter row must stop being a
     positioning context of its own */
  .bj-nav .submenu .line-item{ position:static; }
  .bj-nav .submenu{ overflow:visible; max-height:none; }
  .bj-nav .line-item.open > .pointmenu{
    position:absolute; left:-1px; top:100%;
    width:var(--band-w,700px);
    padding:2px 0; background:var(--panel);
    border:1px solid var(--hair);
    box-shadow:0 4px 10px rgba(0,0,0,.14);
    max-height:46vh; overflow:auto;
    /* card titles are long, so here BOTH are set on purpose: three columns
       where the band is wide, dropping to two by itself where it is not */
    column-count:3; column-width:200px; column-gap:10px; }
  /* follow the panel when it has flipped away from the right-hand edge */
  .bj-nav .submenu.flip .line-item.open > .pointmenu{ left:auto; right:-1px; }
  .bj-nav .pointmenu > li{ break-inside:avoid; }
  .bj-nav .pointmenu > .gopage{ column-span:all; }
}

/* v21: while a horizontal drag is being treated as a swipe, stop it selecting
   text or dragging an image out of the page. Removed the moment it ends. */
body.bj-swiping{ -webkit-user-select:none; user-select:none; cursor:grabbing; }

/* v22: the page never scrolls sideways of its own accord (the frame is 1024
   and the text measure 640), so the horizontal rubber-band that triggers the
   browser's back/forward gesture has nothing to do here. Switching it off lets
   the nav script use the two-finger swipe for prev/next instead. */
html{ overscroll-behavior-x:none; }

/* ===========================================================================
   v24 (2026-08-21)
   =========================================================================== */

/* --- a slim scrollbar wherever the menu runs off to the right ---------------
   Styled rather than left to the platform because on a Mac the overlay
   scrollbar is invisible until you are already scrolling, which is no use as
   an affordance: the whole point here is to advertise that there are more
   columns before the reader has thought to look. Sized and coloured from the
   same tokens as everything else. */
.bj-nav .area-item{ scrollbar-width:thin; scrollbar-color:#b9c4c8 transparent; }
.bj-nav .area-item::-webkit-scrollbar{ height:6px; }
.bj-nav .area-item::-webkit-scrollbar-track{ background:transparent; }
.bj-nav .area-item::-webkit-scrollbar-thumb{ background:#b9c4c8; border-radius:3px; }
.bj-nav .area-item::-webkit-scrollbar-thumb:hover{ background:var(--slate); }

/* --- the banner title is a link home ---------------------------------------
   The logo top right already went home and nothing else did, so from inside a
   submenu there was no obvious way back. The name now does the same job. It
   must look exactly as it did - Verdana bold, slate, no underline - so the
   only change a reader sees is the cursor and a colour shift on hover. */
.bj-banner .name a{ color:inherit; text-decoration:none; }
.bj-banner .name a:hover,
.bj-banner .name a:focus-visible{ color:var(--blue); text-decoration:none; }

/* --- the chevrons ------------------------------------------------------------
   One visual family, two jobs. Both are a translucent disc rather than a bare
   glyph: a grey chevron laid straight over a photograph disappears into it,
   which is exactly what happened here. The disc gives the glyph its own ground
   at any brightness, and is the treatment every image carousel has converged
   on for the same reason. Blur behind it where supported, a hairline edge, and
   a shadow so it lifts off the picture without shouting.

   They announce themselves once on arrival and then go quiet: the intro fades
   in at nearly full strength with a small drift outward, then settles back to
   resting opacity. A reader who was looking sees the movement; a reader who
   was not still finds the control there afterwards. Anyone who has asked for
   reduced motion gets the resting state with no animation at all.
   -------------------------------------------------------------------------- */
.bj-swipe, .bj-colnav, .bj-up{
  display:flex; align-items:center; justify-content:center;
  width:44px; height:44px; padding:0; border-radius:50%;
  border:1px solid rgba(51,77,85,.32);
  background:rgba(255,255,255,.82);
  -webkit-backdrop-filter:blur(3px); backdrop-filter:blur(3px);
  box-shadow:0 1px 5px rgba(0,0,0,.22);
  font-family:var(--display); font-size:26px; line-height:1; font-weight:normal;
  color:var(--slate); text-decoration:none; cursor:pointer;
  transition:opacity .18s ease, color .18s ease, background-color .18s ease; }
/* v42, Bart 2026-09-03: raised from .34/.42 resting opacity - against a busy
   photograph the old circle all but vanished. A visible ring at rest costs
   nothing once it is the thing a new visitor is meant to notice unprompted. */
.bj-swipe{ position:fixed; top:50%; transform:translateY(-50%); z-index:30; opacity:.62; }
.bj-swipe:hover, .bj-swipe:focus-visible,
.bj-colnav:hover, .bj-colnav:focus-visible,
.bj-up:hover, .bj-up:focus-visible{
  opacity:1; color:var(--blue); background:rgba(255,255,255,.96); }
.bj-swipe-prev{ left:6px; }
.bj-swipe-next{ right:6px; }
@media (max-width:600px){
  .bj-swipe{ width:38px; height:38px; font-size:23px; opacity:.68; }
  .bj-swipe-prev{ left:2px; }
  .bj-swipe-next{ right:2px; }
}
@media (min-width:1140px){
  .bj-swipe-prev{ left:calc((100vw - 1024px) / 4 - 22px); }
  .bj-swipe-next{ right:calc((100vw - 1024px) / 4 - 22px); }
}

/* the arrival cue */
@keyframes bj-chev-in-l{
  0%{ opacity:0; transform:translateY(-50%) translateX(10px); }
  30%{ opacity:.95; transform:translateY(-50%) translateX(-3px); }
  100%{ opacity:.34; transform:translateY(-50%) translateX(0); } }
@keyframes bj-chev-in-r{
  0%{ opacity:0; transform:translateY(-50%) translateX(-10px); }
  30%{ opacity:.95; transform:translateY(-50%) translateX(3px); }
  100%{ opacity:.34; transform:translateY(-50%) translateX(0); } }
.bj-swipe-prev{ animation:bj-chev-in-l 1.9s cubic-bezier(.22,.61,.36,1) 1 both; }
.bj-swipe-next{ animation:bj-chev-in-r 1.9s cubic-bezier(.22,.61,.36,1) 1 both; }
@media (prefers-reduced-motion:reduce){
  .bj-swipe-prev, .bj-swipe-next{ animation:none; opacity:.62; }
}

/* --- the up chevron (v42) ---
   Moves across levels (POINT to LINE, LINE to AREA, AREA to home) rather than
   within one, so it is placed and shaped differently on purpose: top centre,
   pointing up, never mistaken for the left/right pair even at a glance. A
   plain link, not swipe-armed - there is no natural up/down drag gesture on a
   page that already claims left/right for prev/next, so this stays a tap or
   click only. */
/* .bj-head is position:sticky at z-index:50 and varies in height (it shrinks
   once .stuck), so this sits fixed just clear of its tallest, unstuck state
   rather than trying to track it exactly; z-index:31 means if the two ever
   do overlap, the header wins and this waits underneath rather than sitting
   on top of breadcrumb text. */
.bj-up{ position:fixed; top:128px; left:50%; transform:translateX(-50%); z-index:31;
  opacity:.62; font-size:22px; }
.bj-up:hover, .bj-up:focus-visible{ transform:translateX(-50%); }
@keyframes bj-chev-in-u{
  0%{ opacity:0; transform:translateX(-50%) translateY(-10px); }
  30%{ opacity:.95; transform:translateX(-50%) translateY(3px); }
  100%{ opacity:.62; transform:translateX(-50%) translateY(0); } }
.bj-up{ animation:bj-chev-in-u 1.9s cubic-bezier(.22,.61,.36,1) 1 both; }
@media (prefers-reduced-motion:reduce){ .bj-up{ animation:none; opacity:.62; } }
@media (max-width:600px){ .bj-up{ width:38px; height:38px; font-size:19px; top:104px; opacity:.68; } }
body.bj-drawer-open .bj-up{ display:none; }

/* --- the menu's own column chevrons ---
   Same family, smaller, and placed over the columns themselves (the nav script
   sets `top`) so they read as belonging to the menu rather than to the page.
   The page's own pair stands down while the drawer is open, so only one kind
   of chevron is ever on screen and the two gestures cannot be confused. */
.bj-colnav{ position:absolute; z-index:60; width:34px; height:34px; font-size:21px;
  transform:translateY(-50%); opacity:.9; }
.bj-colnav[hidden]{ display:none; }
.col-prev{ left:2px; }
.col-next{ right:2px; }
.bj-nav{ position:relative; }
body.bj-drawer-open .bj-swipe{ display:none; }
/* v44, Bart 2026-09-06: "i can't click on the x here."
   The chevrons are position:fixed at z-index 30, pinned to the middle of the
   VIEWPORT, and the globe's artifact panel opens inside the page at z-index 9.
   30 beats 9, so the chevron sat on top of the panel's close button and
   swallowed the click - elementFromPoint at the centre of that X returned
   A.bj-swipe-next, not the button. The same overlap makes any hotspot within
   about 25px of the globe's edge unclickable at narrow widths: the click
   navigates to the next chapter instead of opening the artifact.
   The drawer rule above solved this exact problem once already, so this is the
   same answer: while the panel is open, the chevrons stand down. */
body.bjm-pop-open .bj-swipe{ display:none; }
/* on a wide screen the page is centred with room either side, so the arrows
   sit in that margin; on a narrow one they overlay the edge of the content,
   which is why they stay faint until touched */
@media (min-width:1140px){
  .bj-swipe-prev{ left:calc((100vw - 1024px) / 4 - 22px); }
  .bj-swipe-next{ right:calc((100vw - 1024px) / 4 - 22px); }
}
@media (prefers-reduced-motion:reduce){ .bj-swipe{ transition:none; } }

/* ===========================================================================
   v27
   =========================================================================== */

/* On the home page the banner's name is rendered as the page's <h1> instead of
   a <p> (see inc/header.php), which is what gives the page back the top-level
   heading it lost in v26. On the home page it is also set 75% larger than the
   112% it carries elsewhere: 112 x 1.75 = 196%. Sub-pages keep the compact
   112% version, so the name grows only where it is the page's own title. */
/* one size on every page: 75% of the 196% the home page briefly carried.
   The h1/p difference is semantic only (see inc/header.php) - both are .name
   and both render identically, so the banner is consistent everywhere. */
.bj-banner .name{ line-height:1.14; }

/* --------------------------------------------------------------------------
   Links must not change TYPEFACE on hover.
   bartonjames.css, the original stylesheet, carries this:

       a:hover{ color:#006699; text-decoration:underline;
                font-family: Arial, sans-serif; }

   so every link on the site is re-set to Arial the moment a pointer touches
   it. Where the surrounding text is already Arial that is invisible, which is
   why it survived this long; where it is not - the banner name, the site map's
   AREA headings, the drawer's title, all of which are Verdana - the text
   reflows and visibly shrinks under the cursor. Measured on the home page
   banner: 644px wide at rest, 545px hovered, and two pixels lower.

   bartonjames.css is not to be edited (section 11), and this file loads after
   it, so an equally specific rule here wins. `inherit` is right at every level:
   a link in Verdana stays Verdana, a link in Arial stays Arial.
   -------------------------------------------------------------------------- */
a:hover{ font-family:inherit; }

/* The banner name is a link home. Hovering it must change the COLOUR and
   nothing else: family, size, weight and underline are all pinned to what they
   were, so the text cannot reflow, grow, or shift the line beneath it. */
.bj-banner .name a{ font:inherit; letter-spacing:inherit; text-decoration:none; }
.bj-banner .name a:hover, .bj-banner .name a:focus-visible{
  font:inherit; text-decoration:none; }

/* the small row of document thumbnails, right-aligned beside the heading,
   as the original had it. Cells are emitted by bj_docs() only when both the
   thumbnail and its target exist, so this never renders a broken link. */
.bj-docs{ display:flex; gap:10px; justify-content:flex-end; align-items:flex-end;
  float:right; margin:0 0 8px 14px; }
.bj-doc{ display:block; text-align:center; text-decoration:none;
  font-family:var(--body); font-size:68%; color:#999999; letter-spacing:.02em; }
.bj-doc span{ display:block; margin-top:3px; }
.bj-doc img{ display:block; border:1px solid var(--hair); }
.bj-doc:hover{ color:var(--blue); }
.bj-doc:hover img{ border-color:var(--blue); }
@media (max-width:600px){
  .bj-docs{ float:none; justify-content:flex-start; margin:0 0 10px; }
}

/* ===========================================================================
   v30: the header stays put
   ---------------------------------------------------------------------------
   Breadcrumb, banner and menu are one block now (.bj-head, wrapped in
   inc/header.php) and that block is sticky, so the whole of it - where you
   are, who the site belongs to, and the way to anywhere else - is on screen
   at every scroll position, in all three responsive states. Everything below
   it scrolls underneath.

   position:sticky rather than fixed, on purpose: sticky keeps the block in
   normal flow, so it still occupies its own space at the top of the document
   and nothing has to be padded down by a hand-maintained number that would go
   stale the moment the banner changed height.

   The block has to be OPAQUE or scrolling text shows through it. It cannot
   simply be white, because the background swoosh passes behind the banner and
   is part of the design. Because that image is background-attachment:fixed, it
   is positioned against the viewport rather than the element, so painting the
   same fixed image on .bj-head lines it up pixel-for-pixel with the body's and
   the header looks exactly as it did while becoming opaque. That declaration
   lives in inc/header.php beside the body's, because it needs $BASE.
   =========================================================================== */
.bj-head{ position:sticky; top:0; z-index:50; padding-top:14px; }

/* Anything the page jumps to - the skip link's target, the site map's chapter
   links - must clear the sticky block instead of landing under it. */
#bjMain, .bj-map [id], [id]{ scroll-margin-top:170px; }
@media (max-width:600px){ #bjMain, .bj-map [id], [id]{ scroll-margin-top:150px; } }

/* The phone drawer opens INSIDE the sticky block, so it has to be bounded:
   a chapter with 85 cards would otherwise make the header taller than the
   screen and push the page out of reach. Cap it and let it scroll on its own.
   Desktop is left alone - its panels are absolutely positioned overlays and
   an overflow here would clip them. */
@media (max-width:600px){
  .bj-nav.expanded{ max-height:calc(100vh - 148px); overflow-y:auto; }
}

/* The side chevrons sit at z-index 30, below the header's 50, so they pass
   under it rather than over the menu. Stated here so it is not re-derived. */

/* ===========================================================================
   v31: no orphans
   ---------------------------------------------------------------------------
   A single word, or a bracketed count, left alone on a line of its own is the
   thing to avoid everywhere on this site. Three separate mechanisms, because
   the cause is different in each place:

   1. The menu's card counts are tied to the preceding word with &nbsp; in
      bj_menu(), and the columns above are sized to fit the widest such pair.
   2. Headings get text-wrap:balance, which splits a heading that must wrap
      into lines of even length instead of a long line and a stray word. That
      is what makes an AREA gloss break into halves on a phone.
   3. Body copy gets text-wrap:pretty, which is the same idea applied only to
      the last line of a paragraph.

   Browsers without these two properties simply wrap as they always did, so
   there is nothing to fall back to.
   =========================================================================== */
.bj-content h1, .bj-content h2, .bj-content h3,
.bj-banner .name, .bj-nav .line, .bj-nav .line-link{ text-wrap:balance; }
.bj-content p, .bj-content li{ text-wrap:pretty; }

/* On a desktop the AREA glosses should not wrap at all. The longest of them,
   product's "product/service; agreed expectations; concerted effort of people,
   materials, resources", measures 668px, and the reading measure for body copy
   is 640 - so the heading, and only the heading, is given a slightly wider
   frame. Paragraphs stay at 640. Below that width it wraps, and rule 2 above
   splits it evenly. */
.bj-content h2{ width:min(700px, calc(100vw - 28px)); max-width:100vw; }

/* ---------------------------------------------------------------------------
   ONE HEADING SCALE  (v36)
   bartonjames.css gives the headings no scale at all: h1 0/0, h2 5/0, h3 0/0,
   h4 15/3, in padding. Rendered, that came out as h3 sitting 10px below the
   block above it and ONE pixel above its own paragraph, while h4 had 27px
   above - so a section heading read as jammed into its text, and no two levels
   agreed.

   The rule here is proximity: a heading belongs to what FOLLOWS it, so the
   space above is roughly three to four times the space below. Everything is
   kept tight per section 6.18; the point is not more air, it is air in the right
   place. Set as margins so adjacent ones collapse sensibly, with the padding
   from the original stylesheet zeroed.

        h1  0 / 5      h2 (as subtitle, h1 + h2)  3 / 12
        h2  16 / 4     h3  14 / 4     h4  12 / 3     h5  10 / 3
   --------------------------------------------------------------------------- */
.bj-content h1{ padding:0; margin:0 0 5px; }
.bj-content h2{ padding:0; margin:16px 0 4px; }
.bj-content h3{ padding:0; margin:14px 0 4px; }
.bj-content h4{ padding:0; margin:12px 0 3px; }
.bj-content h5{ padding:0; margin:10px 0 3px; }
/* the card's subtitle hugs its title and then opens a gap before the body */
.bj-content h1 + h2{ margin:3px 0 12px; }
/* a heading that opens its block has nothing above to separate from */
.bj-content > :is(h1,h2,h3,h4,h5):first-child,
.bj-intro-text h3{ margin-top:0; }

/* ---------------------------------------------------------------------------
   v32: the four questions, as a list
   The prose version ended with a two-word orphan and buried the four questions
   inside one block. As a list each question is scannable and the p-words are
   reachable. The <ul> takes the site's own 8px bullet from bartonjames.css by
   inheritance, so nothing is redefined here. The label before each colon is
   styled to match the h4 used for chapter headings elsewhere (professor's
   "Graphic Design (GRID)" is one): Arial, 90%, bold, #666666. It is a span
   rather than a real <h4> because a block heading inside a list item would
   break the line and mislead a screen reader about the document outline.
   --------------------------------------------------------------------------- */
/* Measured before: 6.4px of visible whitespace between one row's ink and the
   next - 2.3px of leading plus 2px of padding each side. Halved to 3.2px by
   dropping the padding and setting the leading to exactly the gap wanted:
   line-height 1.235 on 13.6px type is 16.8px, and 16.8 - 13.6 = 3.2. Stated as
   a ratio so it holds if the type size changes. The margins around the list
   are halved to match, so the block reads tighter than the prose around it
   rather than merely tighter inside itself. */
.bj-content .bj-four{ margin:3px 0 7px; }
/* Between list items everywhere: the leading (2.3px) plus 1px, so about 3.3px
   of ink-to-ink whitespace, roughly half the 10px between paragraphs. Done
   with a margin between items rather than a line-height, so an item that wraps
   keeps the same leading INSIDE it as the prose around it - raising
   line-height would have spread wrapped items apart to tighten the gap
   between them, which is backwards. */
.bj-content li{ padding:0; }
.bj-content li + li{ margin-top:1px; }
/* Adjacent margins collapse to the LARGER of the two, so the list's 3px top
   margin loses to the 10px under the line introducing it and the block floats
   away from its own opening sentence. Pull that one paragraph in. :has() is
   the only way to say "the paragraph before a list" in CSS; where it is not
   supported the spacing simply stays as it was. */
.bj-content p:has(+ .bj-four){ margin-bottom:4px; }
.bj-four li{ padding:0; }
.bj-four .q{ font-family:Arial, sans-serif; font-size:90%; font-weight:bold; color:#666666; }

/* ---------------------------------------------------------------------------
   v33: the phone banner
   Measured at 375px before this: .who was squeezed into 264px beside the logo,
   so the name wrapped to THREE lines and the sub-header to two - even though
   the sub-header only needs 305px and the frame is 347px wide. The column was
   the problem, not the text.

   So on a phone the banner becomes a two-row grid: name and logo share the top
   row, and the sub-header gets a row of its own spanning the full width, which
   is what lets it run in one line UNDER the logo. .who is display:contents so
   its two children can take part in that grid without changing the markup,
   which keeps the desktop layout and the h1/p tag swap exactly as they were.
   --------------------------------------------------------------------------- */
@media (max-width:600px){
  .bj-banner{ display:grid; align-items:start; column-gap:10px;
    grid-template-columns:1fr auto;
    grid-template-areas:"name logo" "role role"; }
  .bj-banner .who{ display:contents; }
  .bj-banner .name{ grid-area:name; }
  /* Sized from Bart's prototype, 2026-08-22, read off the mock and converted
     against the 347px frame: the name comes DOWN and the sub-header goes UP,
     so the two sit closer in weight than they did. Widest name line 245px ->
     214, sub-header 305 -> 322, logo 92 -> 99, which totals 335 of 347. */
  /* the empty tail of the breadcrumb skeleton costs the current page its name
     on a 347px frame; the name is worth more than the shape here */
  .bj-crumb .bc-tail{ display:none; }
  /* The path was still 7px short of fitting while 22px of dead space sat
     between it and the prev/next control - the two halves are pushed apart by
     space-between, so the leftover all pooled in the middle. Closing the gap
     to 6px returns 8px, which is enough, and nothing had to be abbreviated:
     "< prev | next > 12 of 33" reads exactly as it did. */
  .bj-crumb{ gap:6px; }
  /* drop the ornament, keep every word that carries meaning */
  .bj-pager .pg-b, .bj-pager .pg-of{ display:none; }
  .bj-pager .pg-sl{ display:inline; }
  .bj-banner .name{ font-size:129%; }
  .bj-banner .role{ grid-area:role; margin-top:1px; font-size:87%; }
  .bj-banner > a{ grid-area:logo; }
  /* The signature gets more size, and is lifted so it sits slightly higher
     than the text beside it. 92px, not more: the name's two nowrap halves
     measure 231px and 245px at 147%, and the frame is 347px, so a logo wider
     than 347 - 245 - 10 would push the name into overflowing its column. The
     width goes on the LINK, which is the grid item; the image fills it. Set on
     the image alone it fought its own max-width:100% and collapsed to 82px. */
  .bj-banner > a{ width:99px; }
  /* "NOTHING COMPARES" sits on the very bottom edge of the PNG - its ink runs
     to row 84 of 86 - so the image's bottom edge IS the tagline's baseline.
     Dropped 3px from the old -5px so that baseline lands on the second line of
     the wrapped name beside it, and the two read as one level. */
  .bj-banner > a img{ width:100%; max-width:none; margin-top:-2px; }

  /* After the first view the banner gives some height back: the name steps
     down a size once the header is actually stuck. The crumb, the sub-header,
     the logo and the whole menu are untouched - only the largest thing on
     screen gets smaller, and only after it has been read once. */
  .bj-head.stuck .bj-banner .name{ font-size:118%; }
}
@media (max-width:600px) and (prefers-reduced-motion:no-preference){
  .bj-banner .name{ transition:font-size .12s ease; }
}
/* the sentinel is a measuring device, never a visible thing */
.bj-sentinel{ height:1px; margin:0; padding:0; }

/* the closing note on the home page: quieter than the copy above it */
.bj-density{ color:var(--grey); font-size:95%; }
.bj-density strong{ color:var(--slate); }



/* --- the chevrons, v151 (Bart 2026-09-30): subtle, no disc -------------------
   "the circle around them is intrusive ... black chevrons, sleek, slim (or
   barton james css darker blue grey) with a subtle white glow that gets more
   intense when the background is noisier."
   The disc (v42) existed because a bare grey glyph vanished into busy
   photographs. That job is now done by a white glow whose strength is set per
   chevron from the picture actually behind it: footer.php samples that patch
   and sets --glow from 0 (a plain field) to 1 (a noisy or dark one). The glyph
   is two slim strokes in the site's dark blue grey (#334d55, bartonjames.css);
   the character stays in the markup for screen readers, only hidden.
   The menu's own column chevrons (.bj-colnav) keep the disc; they sit on the
   plain menu panel, not on photographs. */
.bj-swipe, .bj-up{
  --chev:#334d55; --glow:.35;
  background:transparent; border:0; box-shadow:none;
  -webkit-backdrop-filter:none; backdrop-filter:none;
  font-size:0; color:transparent; overflow:visible;
  filter:drop-shadow(0 0 calc(1.5px + 5px * var(--glow)) rgba(255,255,255,calc(.30 + .60 * var(--glow))))
         drop-shadow(0 0 1px rgba(255,255,255,calc(.25 + .55 * var(--glow))));
  transition:opacity .18s ease, filter .35s ease; }
.bj-swipe::before, .bj-up::before{
  content:""; display:block; width:15px; height:15px;
  border-left:2px solid var(--chev); border-bottom:2px solid var(--chev);
  transition:border-color .18s ease; }
.bj-swipe-prev::before{ transform:translateX(3px) rotate(45deg); }
.bj-swipe-next::before{ transform:translateX(-3px) rotate(-135deg); }
.bj-up::before{ width:13px; height:13px; transform:translateY(3px) rotate(135deg); }
.bj-swipe:hover, .bj-swipe:focus-visible,
.bj-up:hover, .bj-up:focus-visible{
  background:transparent; opacity:1; --chev:#006699;
  filter:drop-shadow(0 0 7px rgba(255,255,255,.95)) drop-shadow(0 0 1px rgba(255,255,255,.9)); }
.bj-swipe{ opacity:.85; }
.bj-up{ opacity:.85; }
@keyframes bj-chev2-in-l{
  0%{ opacity:0; transform:translateY(-50%) translateX(10px); }
  30%{ opacity:1; transform:translateY(-50%) translateX(-3px); }
  100%{ opacity:.85; transform:translateY(-50%) translateX(0); } }
@keyframes bj-chev2-in-r{
  0%{ opacity:0; transform:translateY(-50%) translateX(-10px); }
  30%{ opacity:1; transform:translateY(-50%) translateX(3px); }
  100%{ opacity:.85; transform:translateY(-50%) translateX(0); } }
@keyframes bj-chev2-in-u{
  0%{ opacity:0; transform:translateX(-50%) translateY(-10px); }
  30%{ opacity:1; transform:translateX(-50%) translateY(3px); }
  100%{ opacity:.85; transform:translateX(-50%) translateY(0); } }
.bj-swipe-prev{ animation-name:bj-chev2-in-l; }
.bj-swipe-next{ animation-name:bj-chev2-in-r; }
.bj-up{ animation-name:bj-chev2-in-u; }
@media (prefers-reduced-motion:reduce){ .bj-swipe, .bj-up{ animation:none; opacity:.85; } }
@media (max-width:600px){ .bj-swipe, .bj-up{ opacity:.85; } }

/* v157, 2026-09-30: no focus ring around the whole content area. #bjMain is focusable
   (tabindex -1) so "Skip to content" can land on it, and Safari also focuses it on a
   click inside the page; the site-wide :focus-visible ring then wrapped the entire
   640px column, and on the Spalla pages, which run wider than that column, only its
   right edge showed: one long blue line down the page (Bart's screenshot). The
   landmark is not a control. Links, buttons and fields keep their ring. */
#bjMain:focus, #bjMain:focus-visible{ outline:none; }
