/* === BEGIN shared tokens — generated by sync_tokens.py, do not edit === */
/* ============================================================================
   Design tokens — ONE source for the whole family.
   Generated into every site by W:/systems/code/rules/sync_tokens.py.
   DO NOT edit a site's copy: it is overwritten on the next sync.

   Origin: extracted from the Beacon app (C:/Repos/vault-mobile-site), which
   already carried the most complete and best-tested token set. The sites had
   drifted from it — and from each other:

     structureddiagrams   --accent:#2f7d5c; the sites are documents built for reading an argument. Same
   materials, different buildings.
   ============================================================================ */

:root {
  /* surfaces */
  --bg:        #eef1f6;   /* page background */
  --surface:   #ffffff;   /* cards, panels */
  --surface2:  #e6ebf3;   /* inset / secondary surface */
  --line:      #dbe2ec;   /* borders, rules */

  /* ink */
  --ink:       #0f172a;   /* body text — deep navy, never pure black */
  --fg:        #0f172a;   /* alias: the sites use --fg, the app uses --ink */
  --muted:     #64748b;   /* secondary text */

  /* brand */
  --accent:    #2f7d5c;   /* the one blue */
  --accent-dk: #256349;   /* pressed / hover-dark */
  --accent-soft:#2f7d5c14;/* tinted background wash */
  --gold:      #b88a1b;

  /* shape + depth — from jacovanderlaan-site, which had these and the rest of
     the family did not. A shared radius/shadow is what makes cards on five
     different sites look like they came from one place. */
  --radius:    16px;
  --shadow:    0 10px 30px rgba(15,23,42,.07);
  --ink-soft:  #475569;   /* secondary text: nav, captions */
  --ink-faint: #94a3b8;   /* tertiary: metadata, disabled */

  /* ---- type scale ----
     From jacovanderlaan-site, which Jaco reads as the stronger-looking site.
     Measured, the difference was real: its h1 tops out at 64px/6vw/800 where
     BTM and SD sat at 49.6px/5vw with no extra weight — a quarter smaller.
     Nothing typographic was shared before, so each site had invented its own
     heading size and three had drifted apart. */
  --h1:        clamp(40px, 6vw, 64px);
  --h1-weight: 800;
  --h1-track:  -1px;      /* tight tracking is what makes big type look set */
  --h1-lead:   1.05;
  --h2:        clamp(26px, 3.2vw, 36px);
  --lede:      clamp(17px, 1.6vw, 20px);   /* payoff word ONLY — never a background */

  /* entity colours — the same three kinds of thing, app and sites alike */
  --e-action:   #2563eb;  /* activities: what the method DOES */
  --e-idea:     #b88a1b;  /* concepts: ideas it OWNS */
  --e-incident: #dc2626;  /* anti-patterns / incidents / warnings */

  /* mobile safe areas (app only, harmless elsewhere) */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bot: env(safe-area-inset-bottom, 0px);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:        #0b1120;
    --surface:   #131a2b;
    --surface2:  #1c2740;
    --line:      #24304a;
    --ink:       #e6edf7;
    --fg:        #e6edf7;
    --muted:     #8ea0bd;
    --accent:    #2f7d5c;
    --accent-dk: #256349;
    --accent-soft:#2f7d5c14;
  }
}

/* Explicit theme override — a site's toggle stamps data-theme on :root and
   must beat the media query in both directions. */
:root[data-theme="light"] {
  --bg:#eef1f6; --surface:#ffffff; --surface2:#e6ebf3; --line:#dbe2ec;
  --ink:#0f172a; --fg:#0f172a; --muted:#64748b;
  --accent:#2f7d5c; --accent-dk:#256349; --accent-soft:#2f7d5c14;
}
:root[data-theme="dark"] {
  --bg:#0b1120; --surface:#131a2b; --surface2:#1c2740; --line:#24304a;
  --ink:#e6edf7; --fg:#e6edf7; --muted:#8ea0bd;
  --accent:#2f7d5c; --accent-dk:#256349; --accent-soft:#2f7d5c14;
}

/* ---------------------------------------------------------------------------
   ⚠️ Structured Wandering is the one deliberate exception: its accent is TEAL
   #0d7d7d, not the family blue. It is a different brand with a different
   audience. sync_tokens.py rewrites --accent for that site only; everything
   else — ink, surfaces, gold, entity colours — stays shared.
   --------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
   Figures. Shared because every site in the family carries generated
   illustrations, and four hand-maintained copies of five rules is exactly the
   drift this file exists to prevent (ADR-128).

   ⚠️ width/height belong on the <img> element, not here: the browser needs the
   intrinsic ratio in the markup to reserve space before the file lands.
   Without it the text below jumps when the image arrives.
   --------------------------------------------------------------------------- */
figure { margin: 32px 0 }
figure img { width: 100%; height: auto; border-radius: 10px; display: block }
figcaption { margin-top: 10px; font-size: .92rem; color: var(--muted) }
.hero-figure { margin: 36px 0 0 }


/* ============================================================================
   Base menu — ONE source for the whole family.
   Generated into every site by W:/systems/code/rules/sync_tokens.py.
   DO NOT edit a site's copy: it is overwritten on the next sync.

   Taken from structurebeatsmagic (31 Jul 2026), which had the most mature
   implementation. Two things it does that the others did not:

     1. The group label is a real <button>, not a link or a dead <span>.
        Keyboard-focusable, and a tap opens the menu instead of navigating away.
     2. On mobile the submenus FLATTEN inline instead of vanishing. The other
        sites hid whole groups below 820px with nth-of-type(n+4){display:none},
        which made those sections unreachable on a phone — a real defect, not a
        style choice.

   Also carried over: the ▾ caret, so a group label announces that it opens.
   ============================================================================ */

/* ---- top level ---- */
nav.main{display:flex;align-items:center;flex-wrap:nowrap;gap:20px}
nav.main > a,
.navgroup > .navtop{
  color:var(--muted);font-size:.92rem;font-weight:500;white-space:nowrap;
  cursor:pointer;background:none;border:none;font-family:inherit;padding:.2rem .1rem}
nav.main > a:hover,
.navgroup:hover > .navtop,
.navgroup:focus-within > .navtop{color:var(--fg);text-decoration:none}
/* Active section. ⚠️ This used to read `.navgroup > .navtop.on`, which only
   matched items inside a dropdown — a top-level link like Timeline set the
   class and got no styling at all, so the reader could not tell which section
   they were in. Match both shapes.

   The underline is what carries it: colour alone fails for the ~8% of men with
   a colour vision deficiency, and here the accent is close enough to the body
   ink that it barely reads for anyone. */
.navtop.on{color:var(--accent);font-weight:600}
a.navtop.on{text-decoration:underline;text-underline-offset:6px;
  text-decoration-thickness:2px}
.navgroup > .navtop.on{text-decoration:none;border-bottom:2px solid var(--accent);
  padding-bottom:2px}

/* ⚠️ Two conventions exist for "this is the current page": the generated nav
   emits `.navtop.on`, hand-written headers use `.active`. Rather than rewrite
   twenty pages, style both the same — a reader cannot see which class did it,
   and a half-migrated site should not look half-migrated.
   breakthroughsabbatical carries both on the same page. */
nav.site a.active{color:var(--accent);font-weight:600;
  text-decoration:underline;text-underline-offset:6px;text-decoration-thickness:2px;
  border-bottom:0;padding-bottom:0}

/* The brand is a link to the homepage, not a menu item. Browsers underline it
   by default in some resets, which makes it look like the active section. */
a.brand{text-decoration:none}
.navgroup > .navtop::after{content:" \25be";color:var(--muted);font-size:.7em;opacity:.7}
.navgroup > .navtop:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:3px}

/* ---- dropdown ---- */
.navgroup{position:relative;display:inline-block}
.navmenu{display:none;position:absolute;top:100%;left:0;min-width:200px;
  background:var(--surface);border:1px solid var(--line);border-radius:6px;
  box-shadow:0 8px 28px rgba(15,23,42,.12);padding:.35rem 0;z-index:60;
  width:max-content;max-width:280px}
.navgroup:hover .navmenu,
.navgroup:focus-within .navmenu{display:block}
.navmenu a{display:block;margin:0;padding:.5rem 1.1rem;font-size:.9rem;
  color:var(--muted);white-space:nowrap}
.navmenu a:hover{color:var(--accent);background:var(--bg);text-decoration:none}

/* ---- the call to action ----
   Taken from jacovanderlaan-site (1 Aug 2026), which had the better version:
   a filled pill reads as a button, where a coloured link reads as one more
   nav item. Jaco: "de loop van jacovanderlaan vind ik juist erg mooi" - so
   the borrowing runs that way round, not the other. */
nav.main a.cta,
nav.main a.nav-cta{
  margin-left:10px;padding:9px 18px;border-radius:999px;
  background:var(--accent);color:#fff;font-weight:600;white-space:nowrap;
  transition:background .15s ease,transform .15s ease}
nav.main a.cta:hover,
nav.main a.nav-cta:hover{
  background:var(--accent-dk);color:#fff;text-decoration:none;
  transform:translateY(-1px)}

/* ---- narrow: shrink, never hide ---- */
@media(max-width:1040px){
  nav.main{gap:15px}
  nav.main > a,.navgroup > .navtop{font-size:.86rem}
}

/* ---- mobile: one row of sections, submenus collapsed ----
   ⚠️ The old rule flattened every submenu into an inline list, because hiding
   a group on a phone made its pages unreachable — there is no hover to open it
   with. Correct at the time, but it meant fifteen links stacked above the fold
   before a single word of content.
   Each group now has a SECTION PAGE (build_section_pages.py), so the label is
   a destination rather than a lid. Tapping it opens a page that explains the
   section and links every child. Nothing is unreachable, and the header is
   four taps wide instead of fifteen lines tall.
   ⚠️ A group WITHOUT a section page must keep its children visible — check
   build_section_pages.py output before assuming one exists. */
@media(max-width:820px){
  nav.main{
    flex-wrap:nowrap;gap:0;width:100%;
    /* more sections than fit simply scroll, rather than wrapping into rows */
    overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none}
  nav.main::-webkit-scrollbar{display:none}
  nav.main > a,.navgroup > .navtop{
    margin:0;padding:.6rem .8rem;font-size:.92rem;white-space:nowrap}
  .navgroup{position:relative}
  .navgroup > .navtop::after{display:none}
  /* collapsed: the section page carries these links now */
  .navmenu{display:none}
}

/* ---- header chrome on a phone ----
   The brand line is long ("Jaco van der Laan · Breakthrough Sabbatical") and
   on a 360px screen it pushed the nav off the bottom. Abbreviate rather than
   shrink to unreadable. */
@media(max-width:560px){
  /* ⚠️ Measured, not guessed. At 360px the brand ran to x=432 and the CTA to
     x=439 — 72 and 79 pixels off-screen. `overflow-x:hidden` on body hid that
     without fixing it, which is worse: the content was simply unreachable.
     Root cause: header.site .wrap is a fixed-height flex row with
     justify-content:space-between and no wrapping, so three children each kept
     their intrinsic width and the row overran. */
  header.site .wrap{
    height:auto;min-height:0;flex-wrap:wrap;gap:6px 10px;
    padding-top:10px;padding-bottom:6px}

  /* Both markups exist across the family — some pages carry <a class="brand">,
     others <div class="brand"> with an inline SVG. Style the class, not the
     tag, or half the pages keep overflowing. */
  /* ⚠️ `:not(nav *)` is load-bearing. structuredmemories puts its brand INSIDE
     nav.main; letting these rules reach it made a 215px-tall link — the text
     wrapped character by character inside a nowrap flex row. A brand that is a
     nav item is a nav item, and must stay on one line. */
  header.site .wrap > .brand,
  header.site .wrap > a.brand{
    font-size:.94rem;line-height:1.3;flex:1 1 100%;min-width:0;
    margin-bottom:2px;display:flex;align-items:center;gap:.45rem;
    /* the three that were being overridden */
    white-space:normal;flex-shrink:1;overflow-wrap:anywhere}
  header.site .wrap > .brand svg,header.site .wrap > a.brand svg{
    flex:0 0 auto;width:22px;height:22px}
  header.site .wrap > .brand .abbr,header.site .wrap > a.brand .abbr,
  header.site .wrap > .brand span,header.site .wrap > a.brand span{
    font-size:.86em;opacity:.85;white-space:normal}

  /* A brand that lives inside the nav scrolls with it, on one line. */
  header.site nav .brand{white-space:nowrap;flex:0 0 auto}

  /* The CTA is the last item on a nav that scrolls; it must be allowed to
     shrink rather than push the row wider than the screen. */
  header.site nav.main,header.site nav.site{min-width:0;max-width:100%}
  header.site a.nav-cta,header.site .nav-sys,header.site a.cta{
    padding:.4rem .7rem;font-size:.82rem;flex:0 1 auto;min-width:0;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

  /* ⚠️ Tap targets. Measured "Practice", "Timeline" and "Systems" at under
     30px tall — below the ~44px Apple and Google both recommend, and the
     reason a phone user taps twice. Height comes from padding here, so set it
     on everything the finger aims at. */
  header.site nav.main > a,header.site .navgroup > .navtop,
  header.site nav.site > a{
    min-height:40px;display:inline-flex;align-items:center}
}


/* ---- headings ----
   Applied here so a site gets the family's type scale by syncing, rather than
   by each one redeclaring an h1 and drifting. A site that wants a different
   voice overrides --h1 etc. in its own stylesheet, not the rule. */
h1,.hero h1{
  font-size:var(--h1);font-weight:var(--h1-weight);
  letter-spacing:var(--h1-track);line-height:var(--h1-lead);
  text-wrap:balance}
h2{font-size:var(--h2);line-height:1.15;letter-spacing:-.01em}
.lede{font-size:var(--lede);line-height:1.55;color:var(--ink-soft)}


/* ============================================================================
   browse.css — faceted listing + view switcher. Shared; synced into each site.
   Facets and image-beside-text follow jacovanderlaan.com; the view switcher and
   card density follow the Beacon app.
   ============================================================================ */
.bw{display:flex;gap:28px;align-items:flex-start}
.bw-side{flex:0 0 220px;position:sticky;top:76px;font-size:.9rem}
.bw-side-h{display:flex;justify-content:space-between;align-items:baseline;
  font-size:.74rem;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);margin-bottom:.5rem}
.bw-clear{background:none;border:0;color:var(--accent);cursor:pointer;font-size:.78rem;padding:0}
.bw-search{width:100%;padding:.5rem .7rem;border:1px solid var(--line);border-radius:6px;
  background:var(--surface);color:var(--fg);font:inherit;font-size:.88rem;margin-bottom:1rem}
.bw-fgroup{margin-bottom:1.1rem}
.bw-flabel{font-size:.74rem;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);margin-bottom:.35rem}
.bw-f{display:flex;align-items:center;gap:.5rem;padding:.22rem 0;cursor:pointer;line-height:1.3}
.bw-f input{margin:0;flex:0 0 auto}
.bw-f span:first-of-type{flex:1;min-width:0}
.bw-n{color:var(--muted);font-size:.8rem;font-variant-numeric:tabular-nums}
.bw-main{flex:1;min-width:0}
.bw-bar{display:flex;align-items:center;gap:12px;margin-bottom:1.1rem;
  padding-bottom:.7rem;border-bottom:1px solid var(--line)}
.bw-count{color:var(--muted);font-size:.86rem}
.bw-spacer{flex:1}
.bw-sort{border:1px solid var(--line);border-radius:6px;background:var(--surface);
  color:var(--fg);font:inherit;font-size:.84rem;padding:.3rem .5rem}
.bw-views{display:inline-flex;border:1px solid var(--line);border-radius:6px;overflow:hidden}
.bw-views button{background:var(--surface);border:0;border-left:1px solid var(--line);
  padding:.35rem .7rem;font:inherit;font-size:.82rem;color:var(--muted);cursor:pointer}
.bw-views button:first-child{border-left:0}
.bw-views button.on{background:var(--accent);color:#fff}
/* list + cards: image beside the text (jacovanderlaan.com) */
.bw-item{display:flex;gap:20px;align-items:flex-start;padding:1.1rem 0;border-bottom:1px solid var(--line)}
.bw-body{flex:1;min-width:0}
.bw-item h3{margin:0 0 .25rem;font-size:1.06rem;line-height:1.3}
.bw-item p{margin:.45rem 0 .5rem;color:var(--muted);font-size:.92rem}
.bw-img{flex:0 0 180px;width:180px;height:auto;border-radius:8px;border:1px solid var(--line)}
.bw-meta{color:var(--muted);font-size:.8rem}
.bw-chips{display:flex;flex-wrap:wrap;gap:.35rem;margin:.4rem 0}
.bw-chip{font-size:.72rem;padding:.12em .55em;border-radius:4px;background:var(--surface2);color:var(--muted)}
.bw-more{font-size:.86rem;font-weight:600}
.bw-cards .bw-item{border:1px solid var(--line);border-radius:10px;padding:1rem 1.2rem;margin-bottom:.9rem;background:var(--surface)}
.bw-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(215px,1fr));gap:14px}
.bw-cell{display:block;border:1px solid var(--line);border-radius:10px;padding:.9rem;
  background:var(--surface);color:var(--fg)}
.bw-cell:hover{text-decoration:none;border-color:var(--accent)}
.bw-cell .bw-img{width:100%;flex:none;margin-bottom:.5rem}
.bw-loading,.bw-empty,.bw-err{color:var(--muted);padding:1.2rem 0}
/* the static fallback is for crawlers and no-JS readers; hidden once JS runs */
.bw-fallback{border-top:1px solid var(--line);margin-top:2rem;padding-top:1rem}
.bw-ready .bw-fallback{display:none}
@media(max-width:860px){
  .bw{display:block}
  .bw-side{position:static;width:auto;margin-bottom:1.4rem}
  .bw-img{flex-basis:110px;width:110px}
}
/* prev/next stepper on a detail page — steps through the FILTERED set the
   reader came from, with a route back to that same filtered view */
.bw-stepper{display:flex;align-items:center;gap:14px;margin:0 0 1.4rem;
  padding-bottom:.7rem;border-bottom:1px solid var(--line);font-size:.86rem}
.bw-stepper a{color:var(--accent)}
.bw-prev,.bw-next{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bw-next{text-align:right}
.bw-pos{color:var(--muted);flex:0 0 auto;font-variant-numeric:tabular-nums}
.bw-off{visibility:hidden}
.toc a.on{color:var(--accent);font-weight:600}
@media(max-width:640px){.bw-stepper{font-size:.8rem;gap:8px}}

/* listing header — eyebrow, a claim, a lede saying what the section is FOR.
   Pattern from structurebeatsmagic /writing/: the header earns its space by
   telling the reader why the list below matters, not by naming the page type. */
.listing-head{padding-bottom:8px}
.listing-head h1{max-width:16ch}
.listing-head .lede{font-size:1.06rem;color:var(--muted);max-width:60ch;margin:.5em 0 0}
@media(max-width:700px){.listing-head h1{max-width:none}}

/* ---- document layout: content + sticky left TOC ----
   ⚠️ This lived only in structureddiagrams/assets/site.css, so every other site
   rendered detail.js's TOC ABOVE the article instead of beside it — the layout
   existed, the CSS did not. Shared, and using theme variables rather than the
   hardcoded greys it had locally. */
.pagewrap{display:flex;gap:2.5rem;align-items:flex-start}
.pagebody{flex:1;min-width:0}
.pagebody h2,.pagebody h3{scroll-margin-top:1.5rem}
.toc{position:sticky;top:1.5rem;width:210px;flex:0 0 210px;font-size:.9em}
.toc-inner{border-left:2px solid var(--line);padding-left:.9rem}
.toc-h{font-size:.75em;text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted);margin-bottom:.5rem}
.toc ul{list-style:none;padding:0;margin:0}
.toc li{padding:.22rem 0;line-height:1.35}
.toc li.l3{padding-left:.8rem;font-size:.94em}
.toc a{color:var(--muted);text-decoration:none;display:block}
.toc a:hover,.toc a.on{color:var(--accent)}
/* always visible: revealing it on hover made it undiscoverable on touch */
.toc-toggle{display:block;background:none;border:0;font-size:1.15rem;line-height:1;
  color:var(--muted);cursor:pointer;padding:.15rem .3rem;margin-bottom:.5rem;border-radius:4px}
.toc-toggle:hover{color:var(--accent);background:var(--accent-soft)}
.toc-toggle:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
body.toc-off .toc-inner{display:none}
body.toc-off .toc{width:auto;flex-basis:auto}
html{scroll-behavior:smooth}
@media(max-width:900px){.pagewrap{display:block}.toc{display:none}}
/* a row with no page of its own — rendered, not linked */
.bw-cell.bw-nolink{cursor:default}
.bw-cell.bw-nolink:hover{border-color:var(--line)}

/* listing hero — beside the header text, not above the page. The reader should
   reach the filter without scrolling past a full-width band. */
/* ⚠️ The shared block is PREPENDED, so a site's own .hero rules load after it.
   Match .hero.listing-head (two classes) so the layout wins on specificity
   rather than on order — appending would repeat the ADR-128 mistake. */
.hero.listing-head{display:flex;gap:2.5rem;align-items:center;flex-wrap:wrap;
  padding-top:48px;padding-bottom:16px}
.hero.listing-head .listing-head-text{flex:1 1 22rem;min-width:0}
.hero.listing-head .listing-hero{flex:0 1 380px;margin:0;min-width:0;max-width:380px}
.hero.listing-head .listing-hero img{width:100%;max-width:100%;height:auto;
  display:block;border-radius:10px}
@media(max-width:820px){.hero.listing-head .listing-hero{display:none}}

/* the family page — the current site is marked, not linked */
.family-cards .card.is-here{border-color:var(--accent);background:var(--accent-soft)}
.fam-here{font-size:.7rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;
  color:var(--accent);background:var(--bg);border:1px solid var(--accent);
  border-radius:999px;padding:.1em .6em;margin-left:.5em;vertical-align:middle}

/* ---- timeline: the working record, newest first ---- */
.tl{display:flex;gap:2.5rem;align-items:flex-start}
.tl-side{flex:0 0 200px;position:sticky;top:76px;font-size:.9rem;max-height:80vh;overflow-y:auto}
.tl-main{flex:1;min-width:0;border-left:2px solid var(--line);padding-left:1.6rem}
.tl-entry{position:relative;padding:0 0 1.6rem}
/* the dot on the spine — the sequence is the point, so make it visible */
.tl-entry::before{content:"";position:absolute;left:-1.95rem;top:.45rem;width:9px;height:9px;
  border-radius:50%;background:var(--surface);border:2px solid var(--accent)}
.tl-entry[data-kind="note"]::before,
.tl-entry[data-kind="observation"]::before{border-color:var(--muted)}
.tl-meta{display:flex;gap:.6rem;align-items:baseline;font-size:.8rem;color:var(--muted)}
.tl-kind{text-transform:uppercase;letter-spacing:.05em;font-size:.68rem;font-weight:600;
  color:var(--accent);background:var(--accent-soft);padding:.1em .5em;border-radius:3px}
.tl-entry h3{margin:.2rem 0 .3rem;font-size:1.02rem;line-height:1.35}
.tl-entry p{margin:.25rem 0;font-size:.93rem;color:var(--muted)}
.tl-source{font-style:italic}
.tl-links{font-size:.85rem}
@media(max-width:820px){
  .tl{display:block}
  .tl-side{position:static;max-height:none;margin-bottom:1.4rem}
  .tl-main{border-left:0;padding-left:0}
  .tl-entry::before{display:none}
}

/* ---------------------------------------------------------------------------
   Timeline display modes. The entries are the same DOM in every mode — only
   the container class changes, so filtering, deep links and indexability
   (ADR-129) are untouched.

   Timeline is a sequence, so List stays the default: it is the only mode where
   "what came after what" survives. Cards and Grid trade that for scanning a
   few hundred entries at once, which is why they exist on the larger sites.
   --------------------------------------------------------------------------- */
/* The column that holds the view bar and the entries. Without it the bar would
   be a flex sibling of the sidebar and sit alongside it rather than above the
   entries. */
.tl-body-col { flex: 1; min-width: 0 }
.tl-bar { margin-bottom: 1rem }

.tl-main.view-cards,
.tl-main.view-grid { border-left: 0; padding-left: 0 }

.tl-main.view-cards { display: grid; gap: 1rem; grid-template-columns: 1fr }
.tl-main.view-grid  { display: grid; gap: 1rem;
                      grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)) }

.tl-main.view-cards .tl-entry,
.tl-main.view-grid .tl-entry {
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
  padding: 1rem 1.1rem; margin: 0;
}
/* The dot on the spine belongs to the list; without a spine it is a stray mark. */
.tl-main.view-cards .tl-entry::before,
.tl-main.view-grid .tl-entry::before { display: none }

/* Grid cells hold a few hundred entries at a glance, so the body is clamped and
   the source line dropped — the title, date and kind are what you scan by. */
.tl-main.view-grid .tl-entry p { font-size: .92rem }
.tl-main.view-grid .tl-source { display: none }
.tl-main.view-grid .tl-body {
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical;
  overflow: hidden;
}

@media (max-width: 640px) {
  /* One column is one column: the switch is pointless below this width. */
  .tl-main.view-grid { grid-template-columns: 1fr }
}

/* ── detail page for a rule, mantra, habit or model ────────────────────────
   These are short. A concept page carries a hero, related links and a TOC;
   these carry three sentences and their provenance, and the layout has to
   make that feel deliberate rather than unfinished. Narrow measure, large
   opening line, metadata set apart at the foot. */
.rule-detail{max-width:660px;padding:64px 0 88px}
.rule-detail .eyebrow{font-size:.78rem;letter-spacing:.09em;text-transform:uppercase;
  color:var(--muted);margin:0 0 18px}
.rule-detail .eyebrow a{color:inherit;text-decoration:none;border-bottom:1px solid transparent}
.rule-detail .eyebrow a:hover{border-bottom-color:currentColor}
.rule-detail h1{font-size:clamp(1.9rem,4.2vw,2.7rem);line-height:1.18;margin:0 0 28px;
  letter-spacing:-.015em}
/* The first paragraph is the tagline — it carries the weight the title sets up. */
.rule-detail h1 + p{font-size:1.16rem;line-height:1.6;color:var(--lede)}
.rule-detail p{margin:0 0 20px;line-height:1.68}

.rule-meta{margin:44px 0 0;padding-top:22px;border-top:1px solid var(--line);
  display:grid;grid-template-columns:auto 1fr;gap:10px 22px;font-size:.9rem}
.rule-meta dt{color:var(--muted);letter-spacing:.02em}
.rule-meta dd{margin:0}
.rule-meta dd a{overflow-wrap:anywhere}

@media (max-width:560px){
  .rule-detail{padding:44px 0 64px}
  .rule-meta{grid-template-columns:1fr;gap:4px 0}
  .rule-meta dt{margin-top:12px}
}

/* ── new / updated flags ───────────────────────────────────────────────────
   Small, next to the title, never a whole chip row of its own. "New" carries
   the accent because it is the one worth interrupting for; "Updated" is quieter
   — a revision is news for a returning reader only.
   ⚠️ If these ever appear on every row, the freshness window or the source
   dates are wrong, not the styling. A badge on everything says nothing. */
.bw-flag{display:inline-block;vertical-align:middle;margin-left:.55em;
  font-size:.62rem;font-weight:600;letter-spacing:.07em;text-transform:uppercase;
  padding:.18em .5em;border-radius:3px;line-height:1.5;white-space:nowrap}
.bw-flag-new{background:var(--accent);color:#fff}
.bw-flag-updated{background:transparent;color:var(--muted);
  border:1px solid var(--line)}
.bw-chips .bw-flag{margin-left:0;margin-right:.4em}

/* ── section hub: one page per menu group ──────────────────────────────────
   A dropdown label that goes nowhere is a dead spot, and on a phone there is
   no hover at all. This page is what the label points at: what the section is
   for, then a card per child saying why you would open it. */
.section-hub{padding:56px 0 88px;max-width:940px}
.section-hub .eyebrow{font-size:.78rem;letter-spacing:.09em;text-transform:uppercase;
  color:var(--muted);margin:0 0 14px}
.section-hub h1{margin:0 0 20px;letter-spacing:-.015em}
.section-hub > .lede{font-size:1.14rem;line-height:1.65;color:var(--lede);
  max-width:62ch;margin:0 0 8px}

.hub-block{margin-top:48px}
.hub-block-title{font-size:1.05rem;letter-spacing:.01em;margin:0 0 6px}
.hub-block-intro{color:var(--muted);margin:0 0 22px;max-width:60ch;line-height:1.6}

.hub-grid{display:grid;gap:18px;grid-template-columns:repeat(auto-fit,minmax(268px,1fr))}
.hub-card{display:block;padding:22px 22px 18px;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--radius);
  text-decoration:none;color:inherit;
  transition:border-color .15s ease,transform .15s ease,box-shadow .15s ease}
.hub-card:hover{border-color:var(--accent);transform:translateY(-2px);
  box-shadow:var(--shadow);text-decoration:none}
.hub-card h2{font-size:1.06rem;margin:0 0 8px;letter-spacing:0}
.hub-card p{margin:0 0 14px;color:var(--muted);line-height:1.58;font-size:.94rem}
.hub-go{font-size:.84rem;font-weight:600;color:var(--accent)}

.hub-cta{margin:56px 0 0;padding-top:26px;border-top:1px solid var(--line);
  color:var(--muted)}
.hub-cta a{font-weight:600}

@media(max-width:560px){
  .section-hub{padding:36px 0 60px}
  .hub-block{margin-top:34px}
  .hub-grid{grid-template-columns:1fr;gap:14px}
  .hub-card{padding:18px}
}

/* ── phones ────────────────────────────────────────────────────────────────
   Everything above is written for a laptop and degrades at 860px, which is a
   tablet. A 360-390px phone is the common case and needs its own pass.

   ⚠️ Test at 360px, not 414px. The iPhone-width default hides exactly the
   overflow that a cheaper Android shows. */
@media(max-width:560px){
  /* 1. Horizontal overflow. A grid demanding 215px per column plus the page
        gutters exceeds 360px, so the whole page scrolls sideways — the single
        most obvious "not made for a phone" signal there is. */
  .bw-grid{grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:10px}
  .bw-cell{padding:10px}
  .bw-cell strong{font-size:.9rem;line-height:1.3}

  /* 2. The image beside the text leaves ~180px for a headline. Stack instead. */
  .bw-item{display:block}
  .bw-item .bw-img{width:100%;flex-basis:auto;height:auto;margin:0 0 .7rem;
    border-radius:var(--radius)}
  .bw-body{width:100%}
  .bw-item h3{font-size:1.02rem;line-height:1.32}

  /* 3. Facets: a sidebar with six checkbox groups pushes the results below
        two screens of chrome. Collapsed into a <details> the reader opens. */
  .bw-side{border:1px solid var(--line);border-radius:var(--radius);
    padding:0;margin-bottom:1rem}
  .bw-side > *{padding-left:12px;padding-right:12px}
  .bw-facets{max-height:52vh;overflow-y:auto}

  /* 4. Controls wrap rather than squeeze — a 3-way view switcher beside a
        search box and a sort menu does not fit on one 360px line. */
  .bw-top{flex-wrap:wrap;gap:8px}
  .bw-search{flex:1 1 100%;min-width:0}
  .bw-views{margin-left:0}

  /* 5. Long words — slugs, URLs, compound titles — must break, not overflow. */
  .bw-item h3,.bw-item p,.bw-cell strong{overflow-wrap:anywhere}

  /* 6. ⚠️ Measured 11.5px text on the chips. Anything under 12px is a
        squint on a phone and iOS zooms the page on focus at 16px inputs.
        The chip is metadata, so it may stay smaller than body copy — but
        not smaller than readable. */
  /* ⚠️ Measured: .bw-chip at 11.5px and .tl-kind at 10.9px. Uppercase
     letter-spaced text reads even smaller than its size suggests, so these
     two are the worst offenders on the site. 12.5px is the floor. */
  .bw-chip,.bw-flag,.tl-kind{font-size:.78rem;padding:.22em .6em}
  .bw-meta,.tl-date{font-size:.82rem}

  /* 7. Tap targets. "Read more" and the chips measured under 30px tall;
        44px is the recommended minimum and 40 is the practical floor. */
  .bw-more{font-size:.9rem;min-height:40px;display:inline-flex;align-items:center}
  .bw-item h3 a{display:inline-block;padding:.15em 0}

  /* 8. A search box under 16px makes iOS Safari zoom the whole page on focus,
        and it never zooms back. This is the single most common phone-form bug. */
  .bw-search,.bw-sort,input,select,textarea{font-size:16px}

  /* 9. ⚠️ Measured: the List/Cards/Grid switcher ran to x=368 on a 360px
        screen, and "clear" was a 14px-tall tap target. The switcher sits on
        the same line as the sort menu, and three buttons plus a select do not
        fit. Give the switcher its own line and let it fill the width. */
  .bw-views{display:flex;width:100%;margin-top:6px}
  .bw-views button{flex:1 1 0;min-width:0;min-height:40px;padding:0}
  .bw-clear{min-height:40px;padding:0 .4rem;font-size:.86rem}

  /* 10. Facet chips are checkboxes in disguise — the label IS the target. */
  .bw-facets label{min-height:36px;display:flex;align-items:center;gap:.5rem}
}

/* ⚠️ Belt and braces: nothing may scroll the page sideways, whatever a future
   listing renders. A table or a code block scrolls INSIDE its own box. */
html,body{overflow-x:hidden}
.bw table,.section-hub table,.rule-detail table{display:block;max-width:100%;
  overflow-x:auto}
.bw pre,.section-hub pre,.rule-detail pre{overflow-x:auto;max-width:100%}
img,svg,video{max-width:100%;height:auto}

/* ── minimum legible size, family-wide ─────────────────────────────────────
   ⚠️ Measured across the family at 360px: labels rendering at 10.9–11.5px on
   four sites. Each was a different class in a different stylesheet, so fixing
   them one at a time would have meant finding them one at a time — and the
   next small label would arrive unmeasured.
   This sets a floor on the ELEMENTS that carry small text rather than on the
   classes, so a new eyebrow or chip inherits it without being listed. Body
   copy is already well above this and is unaffected. */
@media(max-width:560px){
  /* ⚠️ Two classes deep. sync_tokens.py PREPENDS this block so a site's own
     rules win on a tie — right for design, wrong for a legibility floor: the
     first attempt used single class selectors and lost to `.badge{...}` and
     `.post-face{...}` declared later in the same file. Measured 11.0px and
     11.5px still rendering after the "fix". */
  body .eyebrow,body .chip,body .tag,body .badge,body .kicker,body .meta,
  body .card-face,body .post-face,body .bw-chip,body .bw-flag,body .bw-meta,
  body .tl-kind,body .tl-date,body .hub-go,body .pill,body .label,
  body small,body figcaption{font-size:max(0.78rem,12.5px)}
}
/* === END shared tokens === */

/* Breakthrough Modeling (BTM) — site.css. No-nonsense, structure-first. Light + dark. */
:root{
  --bg:#f7f8fa; --fg:#0f172a; --muted:#475569; --line:#e2e8f0;
  --accent:#2f7d5c; --accent-soft:#2f7d5c14; --gold:#b88a1b; --card:#ffffff; --code:#eef2f6;
  --max:940px;
}
@media (prefers-color-scheme:dark){
  :root{ --bg:#0d1015; --fg:#e8ecef; --muted:#9aa6b0; --line:#222833;
    --accent:#6fb394; --accent-soft:#6fb3941a; --gold:#d0a94a; --card:#141922; --code:#161c25; }
}
:root[data-theme="light"]{ --bg:#f7f8fa;--fg:#0f172a;--muted:#475569;--line:#e2e8f0;--accent:#2f7d5c;--accent-soft:#2f7d5c14;--gold:#b88a1b;--card:#ffffff;--code:#eef2f6; }
:root[data-theme="dark"]{ --bg:#0d1015;--fg:#e8ecef;--muted:#9aa6b0;--line:#222833;--accent:#6fb394;--accent-soft:#6fb3941a;--gold:#d0a94a;--card:#141922;--code:#161c25; }

*{box-sizing:border-box}

body{margin:0;background:var(--bg);color:var(--fg);
  font:17px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  -webkit-font-smoothing:antialiased;}
.wrap{max-width:var(--max);margin:0 auto;padding:0 22px}
a{color:var(--accent);text-decoration:none}
a:hover{text-decoration:underline}
h1,h2,h3{line-height:1.2;letter-spacing:-.01em;font-weight:700}
h1{font-size:var(--h1);margin:.2em 0 .3em;font-weight:var(--h1-weight);letter-spacing:var(--h1-track);line-height:var(--h1-lead)}
h2{font-size:clamp(1.4rem,3vw,1.9rem);margin:2.4rem 0 .6rem}
h3{font-size:1.15rem;margin:1.6rem 0 .4rem}
p{margin:.7em 0}
strong{font-weight:650}
code{background:var(--code);padding:.12em .38em;border-radius:5px;font-size:.9em;
  font-family:ui-monospace,"SF Mono",Menlo,Consolas,monospace}

/* header */
header.site{border-bottom:1px solid var(--line);position:sticky;top:0;z-index:10;
  background:color-mix(in srgb,var(--bg) 88%,transparent);backdrop-filter:blur(8px)}
header.site .wrap{display:flex;align-items:center;justify-content:space-between;gap:16px;height:60px}
.brand{font-weight:800;color:var(--fg);letter-spacing:-.02em;font-size:1.02rem;white-space:nowrap;flex:0 0 auto;
  display:inline-flex;align-items:center;gap:9px;text-decoration:none}
/* The mark sits at cap-height so it optically aligns with the wordmark rather
   than the line box, which sits lower. 22px is the smallest size at which the
   gold diamond still reads as a diamond. */
.brand svg{width:22px;height:22px;flex:0 0 auto;display:block}
.brand .abbr{color:var(--accent)}

/* hero */
.hero{padding:72px 22px 44px}
.eyebrow{display:inline-block;color:var(--accent);background:var(--accent-soft);
  font-weight:650;font-size:.82rem;letter-spacing:.02em;text-transform:uppercase;
  padding:5px 12px;border-radius:999px;margin-bottom:18px}
.hero .sub{font-size:clamp(1.05rem,2.2vw,1.3rem);color:var(--muted);max-width:640px;margin:.6em 0 0}
.hero .formula{margin-top:26px;font-size:.95rem;color:var(--muted);
  border-left:3px solid var(--accent);padding-left:14px}
.hero-img{display:block;width:100%;max-width:100%;height:auto;margin:38px 0 0;
  border:1px solid var(--line);border-radius:14px}
.section-img{display:block;width:100%;height:auto;margin:0;
  border:1px solid var(--line);border-radius:12px}
.fig{margin:26px 0}
.fig figcaption{margin-top:9px;font-size:.88rem;color:var(--muted);text-align:center}
.model-figure{margin:22px 0 0}
.model-figure img{display:block;width:100%;height:auto;border:1px solid var(--line);border-radius:14px}

/* news */
.news-item{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:24px 26px;margin-top:8px}
.news-item h3{margin:.15em 0 .5em}
.news-date{display:inline-block;color:var(--accent);background:var(--accent-soft);
  font-weight:650;font-size:.78rem;letter-spacing:.03em;text-transform:uppercase;
  padding:4px 11px;border-radius:999px}
.news-photo{margin:20px 0 6px}
.news-photo img{display:block;width:100%;height:auto;
  border:1px solid var(--line);border-radius:12px}
.news-photo figcaption{margin-top:9px;font-size:.88rem;color:var(--muted);text-align:center}

/* sections */
section{padding:12px 0}
section.wrap{padding-top:8px;padding-bottom:8px}
.lead{font-size:1.12rem;color:var(--fg)}
.muted{color:var(--muted)}

/* the arc / steps */
.arc{display:flex;flex-wrap:wrap;gap:10px;margin:22px 0}
.arc .step{flex:1;min-width:120px;background:var(--card);border:1px solid var(--line);
  border-radius:12px;padding:14px 16px}
.arc .step .n{color:var(--accent);font-weight:700;font-size:.8rem;text-transform:uppercase;letter-spacing:.04em}
.arc .step h4{margin:.3em 0 .2em;font-size:1rem}
.arc .step p{margin:0;font-size:.9rem;color:var(--muted)}

/* compare table */
.cmp{width:100%;border-collapse:collapse;margin:18px 0;font-size:.95rem}
.cmp th,.cmp td{text-align:left;padding:10px 12px;border-bottom:1px solid var(--line);vertical-align:top}
.cmp th{color:var(--muted);font-weight:600;font-size:.82rem;text-transform:uppercase;letter-spacing:.03em}
.cmp .old{color:var(--muted)}
.cmp .new{font-weight:600}
.cmp-wrap{overflow-x:auto}

/* callout */
.callout{background:var(--card);border:1px solid var(--line);border-left:3px solid var(--accent);
  border-radius:10px;padding:18px 20px;margin:22px 0}
.callout p:first-child{margin-top:0}
.callout p:last-child{margin-bottom:0}

/* cards */
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px;margin:20px 0}
.card{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:18px 20px}
.card h3{margin:0 0 .3em}
.card p{margin:0;color:var(--muted);font-size:.94rem}

/* cta */
.cta-row{display:flex;flex-wrap:wrap;gap:12px;margin:30px 0}
.btn{display:inline-block;background:var(--accent);color:#fff;font-weight:600;
  padding:11px 20px;border-radius:10px;font-size:.95rem}
.btn:hover{text-decoration:none;filter:brightness(1.08)}
.btn.ghost{background:transparent;color:var(--accent);border:1px solid var(--accent)}

/* footer */
footer{border-top:1px solid var(--line);margin-top:56px;padding:28px 0 48px;color:var(--muted);font-size:.9rem}
footer a{color:var(--muted);text-decoration:underline}
hr{border:none;border-top:1px solid var(--line);margin:34px 0}
.badge{display:inline-block;background:var(--accent-soft);color:var(--accent);
  font-size:.72rem;font-weight:700;padding:3px 9px;border-radius:999px;letter-spacing:.04em}

/* concept detail pages */
.c-hero{margin:0 0 26px}
.c-hero img{display:block;width:100%;height:auto;border:1px solid var(--line);border-radius:12px}
.c-hero figcaption{margin-top:9px;font-size:.85rem;color:var(--muted);text-align:center}
.c-rel{margin-top:34px;border-top:1px solid var(--line);padding-top:20px}
.c-rel h3{font-size:.82rem;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);margin:0 0 .5rem}
.c-rel ul{margin:0;padding-left:1.1rem}
.c-rel li{margin:.3rem 0}

/* key concepts */
.key-badge{display:inline-block;background:var(--gold,#b88a1b);color:#fff;font-size:.62rem;
  font-weight:700;text-transform:uppercase;letter-spacing:.05em;padding:2px 7px;border-radius:5px;
  vertical-align:middle;margin-right:6px}
.key-section{background:var(--accent-soft);border:1px solid var(--line);border-radius:14px;
  padding:6px 22px 18px;margin:8px 0 30px}
.key-section h2{margin-top:1.2rem}
.card.is-key{border-color:var(--gold,#b88a1b)}
.c-rel.c-key h3{color:var(--gold,#b88a1b)}

/* references */
.ref-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:14px;margin:16px 0 8px}
.ref-book{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:16px 18px}
.ref-t{font-weight:700;font-size:1rem;line-height:1.3}
.ref-a{color:var(--accent);font-size:.85rem;font-weight:600;margin:.2rem 0 .5rem}
.ref-b{color:var(--muted);font-size:.92rem}

/* Key activities — what the method DOES, as opposed to ideas it names.
   Jaco's distinction (31 Jul 2026), same split as terms vs concepts. */
.act-section{background:transparent;border-style:dashed}
.act-badge{background:var(--accent)}

/* per-page TOC */

@media(max-width:900px){.toc{display:none}}
