  /* Clinical Organicism — inherited from ~/Projects/RfoodX/DESIGN.md, which is the
     authority. Depth comes from stacking surface tones, never from borders or
     stacked shadows (the No-Line Rule). Radii are "tumbled river stone": nothing
     sharp. Plus Jakarta Sans display / Inter body / Public Sans labels.
     Supersedes this app's former "Clinical Vitality". */
  :root{
    /* surface stack — the whole depth system. A lighter tone on a darker one IS
       the boundary; that is why almost nothing below draws a border. */
    --bg:#f4f4f3;            /* surface-container-low — page */
    --panel:#ffffff;         /* surface-container-lowest — cards lift off --bg */
    --panel2:#eeeeed;        /* surface-container — grouping, zebra */
    --panel3:#e8e8e7;        /* surface-container-high — elevated wells */
    /* "Ghost border": outline-variant at 15%. Felt, not seen. Reserved for the
       rare divider a tonal shift cannot carry. --line2 is stronger because an
       input must be findable by someone who cannot rely on tonal contrast. */
    --line:rgba(189,202,186,.15);
    --line2:rgba(110,123,108,.34);
    --ink:#1a1c1c;           /* on-surface — never pure black */
    --mut:#3e4a3d;           /* on-surface-variant */
    --mut2:#5f5e5e;          /* secondary */
    --side:#1e201f;          /* sidebar — surface-container, dark end of the stack */
    --side2:#101211;         /* topbar — warm dark charcoal, never pure black */
    --side-mut:#bdcaba;      /* on-surface-variant, dark */
    --primary:#006b2c; --primary2:#00873a; --primary-dark:#005320;
    --primary-fixed:#7ffc97; --primary-dim:#62df7d;
    --green:#006b2c; --green-fg:#005320; --green-bg:#dcf5e1; --green-ln:transparent;
    /* Stale must not share a hue with Lead — audit #18 had both as amber pills
       sitting next to each other. Lead is now neutral; amber means Stale only. */
    --amber:#8a5a06; --amber-fg:#7a5006; --amber-bg:#fbead0; --amber-ln:transparent;
    --info-fg:#25576a; --info-bg:#dceaf2; --info-ln:transparent;
    --gray-fg:#3e4a3d; --gray-bg:#e8e8e7; --gray-ln:transparent;
    --red:#ba1a1a; --red-fg:#93000a; --red-bg:#ffdad6; --red-ln:transparent;
    /* Tumbled River Stone */
    --r-card:24px;           /* cards, panels, modals */
    --r-ctl:8px;             /* inputs, small chips */
    --r-pill:9999px;         /* status pills, avatars */
    --topbar-h:60px;
    /* The one sanctioned shadow: ambient, tinted with on-surface. Modals/FABs. */
    --lift:0 12px 32px -4px rgba(26,28,28,.06);
  }
  *{box-sizing:border-box}
  body{margin:0;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
    font:17px/1.55 "Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
    background:var(--bg);color:var(--ink)}
  h1,h2,h3,.card .n{font-family:"Plus Jakarta Sans","Inter",sans-serif}
  td .v,.card .n,td,th,.asof,.cnt{font-variant-numeric:tabular-nums}
  a{color:var(--primary);text-decoration:none}
  /* !important because this has to beat an ID rule that sets display. It did not:
     #pcols{display:grid} (1-0-0) outranked [hidden] (0-1-0), so the Board grid
     rendered under the Worklist at all times and hung off the right edge below
     900px. `hidden` is an override by definition — every id rule must lose to it. */
  [hidden]{display:none!important}
  /* ===== topbar (dark) ===== */
  .topbar{height:var(--topbar-h);background:var(--side2);display:flex;align-items:center;
    justify-content:space-between;padding:0 22px;gap:20px;position:sticky;top:0;z-index:40;
    border-bottom:1px solid #0e1712}
  .topbar .brandrow{display:flex;align-items:center;gap:11px}
  .topbar .logo-txt{color:#eef2e8;font-family:"Plus Jakarta Sans",sans-serif;font-weight:700;font-size:19px;letter-spacing:-.01em}
  .topbar .logo-txt span{color:var(--primary-fixed,#88d982)}
  .mark{width:32px;height:32px;border-radius:8px;flex:none;display:grid;place-items:center;
    background:linear-gradient(135deg,#006b2c,#00873a)}
  .mark svg{width:18px;height:18px}
  .topright{display:flex;align-items:center;gap:14px}
  .userchip{font-size:13px;color:var(--side-mut)}
  /* A long address (aliases, plus-tags) was the one thing that made a phone scroll sideways. */
  @media(max-width:600px){
    .topright{gap:8px;min-width:0}
    .userchip{max-width:32vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  }
  .logout{background:linear-gradient(135deg,#006b2c,#00873a);border:none;color:#fff;border-radius:var(--r-ctl);
    padding:9px 16px;font-size:13px;font-weight:700;cursor:pointer;font-family:inherit}
  .logout:hover{filter:brightness(1.08)}
  /* ===== shell: sidebar + content ===== */
  .shell{display:flex;align-items:flex-start;min-height:calc(100vh - var(--topbar-h))}
  .side{width:246px;flex:none;background:var(--side);align-self:stretch;
    position:sticky;top:var(--topbar-h);height:calc(100vh - var(--topbar-h));overflow-y:auto;
    padding:20px 14px;display:flex;flex-direction:column;gap:4px}
  .side-head{padding:4px 12px 14px}
  .side-head .t{color:#eef2e8;font-family:"Plus Jakarta Sans",sans-serif;font-weight:700;font-size:16px}
  .side-head .s{color:var(--side-mut);font-size:12px;margin-top:2px}
  .side-foot{margin-top:auto;padding-top:14px;border-top:1px solid rgba(255,255,255,.08);display:flex;flex-direction:column;gap:4px}
  .newopp{margin-top:10px;padding:12px;border-radius:var(--r-ctl);border:none;cursor:pointer;font-family:inherit;
    background:#a5d6a7;color:#0a3d13;font-weight:700;font-size:14px;display:flex;align-items:center;justify-content:center;gap:8px}
  .newopp:hover{background:#b6e0b8}
  .content{flex:1;min-width:0;padding:30px 40px 64px}
  @media(max-width:960px){
    /* stretch, not the inherited flex-start: once .shell is a column, flex-start
       cross-sizes .content to fit-content, so any wide child (the kanban, a wide
       table) stretches .content past the viewport and the whole page scrolls
       sideways instead of the child scrolling inside it. */
    .shell{flex-direction:column;align-items:stretch}
    /* Stays a column so .tabs can be a full-width wrapping row. Wrapping the
       .side itself would not help: its children are three blocks, not fifteen
       pills, so the 1900px strip lives in .tabs and that is what must wrap.
       overflow-x:auto was unreachable with a plain mouse (no wheel gesture),
       which put Admin and the last several tabs out of reach entirely. */
    .side{width:100%;height:auto;position:static;overflow:visible;gap:8px;padding:10px 12px}
    .side-head{display:none}
    /* Now that nothing scrolls sideways there is room for the primary action. */
    .side-foot{margin-top:0;padding-top:10px;align-items:flex-start}
    .content{padding:22px 18px 56px}
  }
  /* ===== sidebar nav (the tabs) ===== */
  .tabs{display:flex;flex-direction:column;gap:3px}
  @media(max-width:960px){.tabs{flex-direction:row;flex-wrap:wrap}}
  .tab{padding:10px 14px;cursor:pointer;color:var(--side-mut);font-size:14.5px;font-weight:600;
    border-radius:var(--r-ctl);display:flex;align-items:center;gap:9px;white-space:nowrap;transition:background .12s,color .12s}
  .tab:hover{background:rgba(255,255,255,.07);color:#fff}
  .tab.on{background:var(--primary2);color:#fff;box-shadow:inset 0 0 0 1px rgba(255,255,255,.08)}
  .tab .cnt{margin-left:auto;min-width:20px;padding:1px 7px;border-radius:9px;text-align:center;
    font-size:11px;background:rgba(255,255,255,.16);color:#fff;font-weight:700}
  .tab.on .cnt{background:rgba(255,255,255,.28)}
  /* Grants and Rules count "new since last visit". Pipeline counts overdue work.
     One white pill for all three made the only actionable badge read as news.
     Same token pair as .badge.stale, so the sidebar count and the row badge it
     refers to are the same colour. 7.24:1, and it replaces a white-on-#69a16b
     selected state that measured 3.04:1. */
  .tab .cnt.due,.tab.on .cnt.due{background:var(--red-bg);color:var(--red-fg)}
  /* ===== section chips (the old feed tabs, inside Find / Qualify) ===== */
  #subnav .chips{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 18px}
  .tab.chip{padding:7px 13px;font-size:13.5px;color:var(--ink,#1c1c1c);background:var(--panel2);border-radius:var(--r-ctl);
    box-shadow:none;white-space:nowrap}
  .tab.chip:hover{background:var(--panel);color:var(--ink,#1c1c1c)}
  .tab.chip.on{background:var(--primary);color:#fff}
  .tab.chip .cnt{margin-left:6px;background:rgba(0,0,0,.08);color:inherit}
  .tab.chip.on .cnt{background:rgba(255,255,255,.28);color:#fff}
  /* ===== How it works (guide) — the journey palette, one hue per step ===== */
  :root{--c1:#0f6f73;--c2:#1f7a3a;--c3:#c9791c;--c4:#7a2e5c;--c5:#6f7f22;
        --c1s:#e3f2f2;--c2s:#e4f2e6;--c3s:#fbeedb;--c4s:#f4e4ee;--c5s:#eef0d9}
  .ghero{display:grid;grid-template-columns:1.4fr 1fr;gap:28px;align-items:center;background:var(--panel);border-radius:var(--r-card);padding:34px 36px;margin-bottom:26px}
  .ghero h2{font-family:"Plus Jakarta Sans",sans-serif;font-size:30px;line-height:1.15;margin:0 0 12px;letter-spacing:-.02em;text-wrap:balance}
  .ghero p{font-size:17px;line-height:1.55;margin:0 0 16px;max-width:60ch}
  .gpills{display:flex;flex-wrap:wrap;gap:8px}
  .gpill{padding:7px 12px;border-radius:999px;font-size:13.5px;font-weight:600;color:#fff}
  .gpill.c1{background:var(--c1)} .gpill.c2{background:var(--c2)} .gpill.c3{background:var(--c3)}
  .gstats{display:grid;grid-template-columns:1fr 1fr;gap:12px}
  .gstat{border-radius:16px;padding:16px 18px;color:#fff;display:flex;flex-direction:column;gap:2px}
  .gstat b{font-size:30px;font-family:"Plus Jakarta Sans",sans-serif;letter-spacing:-.02em} .gstat span{font-size:13px;opacity:.92}
  .gstat.c1{background:var(--c1)} .gstat.c2{background:var(--c2)} .gstat.c3{background:var(--c3)} .gstat.c4{background:var(--c4)}
  .gh{font-family:"Plus Jakarta Sans",sans-serif;font-size:21px;margin:30px 0 4px}
  .gsteps{display:grid;grid-template-columns:repeat(5,1fr);gap:10px;margin:14px 0 12px}
  .gstep{border:none;border-radius:14px;padding:14px 12px;text-align:left;cursor:pointer;font-family:inherit;color:var(--ink);background:var(--panel2);
    display:flex;flex-direction:column;gap:4px;transition:transform .15s cubic-bezier(.2,.8,.2,1),background .15s}
  .gstep:hover{transform:translateY(-2px)}
  .gstep b{font-size:16px} .gstep .gtag{font-size:12.5px;opacity:.75}
  .gstep .gnum{width:26px;height:26px;border-radius:999px;display:grid;place-items:center;font-weight:800;font-size:13px;color:#fff;margin-bottom:4px}
  .gstep.c1 .gnum{background:var(--c1)} .gstep.c2 .gnum{background:var(--c2)} .gstep.c3 .gnum{background:var(--c3)} .gstep.c4 .gnum{background:var(--c4)} .gstep.c5 .gnum{background:var(--c5)}
  .gstep.on{color:#fff} .gstep.on .gtag{opacity:.9} .gstep.on .gnum{background:rgba(255,255,255,.25)}
  .gstep.on.c1{background:var(--c1)} .gstep.on.c2{background:var(--c2)} .gstep.on.c3{background:var(--c3)} .gstep.on.c4{background:var(--c4)} .gstep.on.c5{background:var(--c5)}
  .gdet{display:grid;grid-template-columns:1fr 1fr 1fr auto;gap:22px;align-items:end;border-radius:var(--r-card);padding:22px 24px}
  .gdet p{margin:4px 0 0;font-size:15.5px;line-height:1.5}
  .gdet.c1{background:var(--c1s)} .gdet.c2{background:var(--c2s)} .gdet.c3{background:var(--c3s)} .gdet.c4{background:var(--c4s)} .gdet.c5{background:var(--c5s)}
  .gcheck{list-style:none;padding:0;margin:12px 0 0;display:grid;gap:8px}
  .gcheck li{display:flex;align-items:center;gap:12px;background:var(--panel);border-radius:12px;padding:12px 14px;font-size:15.5px}
  .gcheck li.ok{background:var(--c2s);color:var(--primary-dark)}
  .gbox{width:24px;height:24px;border-radius:8px;background:var(--panel2);display:grid;place-items:center;font-weight:800;flex:none}
  .gcheck li.ok .gbox{background:var(--c2);color:#fff}
  .gagents{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:12px;margin-top:12px}
  .gagent{border-radius:16px;padding:18px;color:#fff;display:flex;flex-direction:column;gap:6px}
  .gagent b{font-size:17px} .gagent p{margin:0;font-size:14.5px;line-height:1.5;opacity:.95} .gagent .gmeta{font-size:12.5px;opacity:.8;margin-top:auto}
  .gagent.c1{background:var(--c1)} .gagent.c2{background:var(--c2)} .gagent.c3{background:var(--c3)} .gagent.c4{background:var(--c4)}
  .glimits{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin-top:12px}
  .glimits div{background:var(--panel);border-radius:14px;padding:14px 16px;display:flex;flex-direction:column}
  .glimits b{font-size:26px;font-family:"Plus Jakarta Sans",sans-serif;color:var(--primary)} .glimits span{font-size:13.5px}
  .gwords{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:8px;margin-top:12px}
  .gword{background:var(--panel);border-radius:12px;padding:10px 14px}
  .gword summary{cursor:pointer;font-weight:700;font-size:15.5px} .gword p{margin:8px 0 2px;font-size:14.5px;line-height:1.5}
  .gsources{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:8px;margin-top:12px}
  .gsrc{background:var(--panel);border-radius:12px;padding:10px 14px;display:flex;flex-direction:column;gap:2px;color:var(--ink);text-decoration:none}
  .gsrc:hover{background:var(--c2s)} .gsrc span{font-size:12.5px;color:var(--secondary,#4c616c)}
  @media(max-width:960px){.ghero{grid-template-columns:1fr}.gsteps{grid-template-columns:1fr 1fr}.gdet{grid-template-columns:1fr}}
  @media(prefers-reduced-motion:reduce){.gstep{transition:none}.gstep:hover{transform:none}}
  /* ===== rendered draft document ===== */
  .draftdoc{background:#fff;border-radius:12px;padding:18px 20px;font-size:14.5px;line-height:1.5;max-height:520px;overflow:auto}
  .draftdoc h2{font-size:18px;margin:0 0 8px} .draftdoc h3{font-size:15.5px;margin:16px 0 4px} .draftdoc h4{font-size:14px;margin:12px 0 4px}
  .draftdoc p{margin:6px 0} .draftdoc ul,.draftdoc ol{margin:6px 0 6px 20px;padding:0} .draftdoc li{margin:2px 0}
  .draftdoc table{border-collapse:collapse;margin:8px 0;font-size:13.5px} .draftdoc th,.draftdoc td{border:1px solid var(--panel2);padding:4px 8px;text-align:left;vertical-align:top}
  .draftdoc mark.fill{background:#fff2a8;padding:0 3px;border-radius:3px}
  /* ===== Work this Deal: steps in the drawer ===== */
  .dmeta{display:grid;grid-template-columns:1fr 1fr;gap:14px}
  .dprog{font-size:14px;color:var(--secondary,#4c616c);margin:4px 0 10px}
  details.step{background:var(--panel2);border-radius:14px;margin:0 0 8px;overflow:hidden}
  details.step>summary{list-style:none;cursor:pointer;display:grid;grid-template-columns:30px 1fr;column-gap:12px;align-items:center;padding:12px 14px}
  details.step>summary::-webkit-details-marker{display:none}
  details.step .stepn{width:28px;height:28px;border-radius:999px;display:grid;place-items:center;font-weight:800;font-size:13px;background:#fff;color:var(--ink)}
  details.step.done .stepn{background:var(--primary);color:#fff}
  details.step.current .stepn{background:var(--c3,#c9791c);color:#fff}
  details.step .steptitle{font-weight:700;font-size:15.5px}
  details.step .stephint{grid-column:2;font-size:13px;color:var(--secondary,#4c616c);margin-top:2px}
  details.step.current{background:var(--c3s,#fbeedb)}
  details.step.done>summary .steptitle{color:var(--primary-dark)}
  details.step.locked{opacity:.65}
  details.step .stepbody{padding:4px 14px 16px 56px}
  @media(max-width:600px){details.step .stepbody{padding-left:14px}.dmeta{grid-template-columns:1fr}}
  /* ===== fit score chips (PR4) ===== */
  .scorechip{border:none;cursor:pointer;font-family:inherit;margin-left:6px}
  .scorepop{background:var(--panel);border-radius:12px;padding:12px 14px;margin:8px 0;font-size:14px;box-shadow:0 6px 24px rgba(0,0,0,.12);max-width:520px}
  .scorepop ul{margin:6px 0 8px 18px;padding:0} .scorepop li{margin:2px 0}
  .scorepop .row2{gap:6px;flex-wrap:wrap}
  /* ===== Today ===== */
  .intro .introgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px 18px;margin-top:12px}
  .intro .introgrid div{font-size:15px;line-height:1.45}
  .tlists{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:18px}
  .tlist{background:var(--panel);border-radius:var(--r-card);padding:18px 20px}
  .tlist h2{margin:0 0 4px;font-size:18px}
  .tlist>.fb{margin:0 0 12px}
  .trow{padding:10px 0;border-top:1px solid var(--panel2)}
  .trow:first-child{border-top:none}
  .trow .sub{font-size:13px;color:var(--secondary,#4c616c);margin-top:2px}
  /* ===== page header ===== */
  .pagehead{margin-bottom:22px}
  .pagehead .row{display:flex;justify-content:space-between;align-items:flex-start;gap:20px;flex-wrap:wrap}
  /* 28px against the 30px stat numerals. The h1 is now the tab name, so it has
     to hold its own: it wins on line length and position, and the numerals gave
     up their 800 weight to draw level. Shrinking both buys the vertical space
     the 17px reading text needs. */
  h1{margin:0;font-size:28px;font-weight:700;letter-spacing:-.02em;line-height:1.15}
  .sub{color:var(--mut);font-size:18px;max-width:64ch;margin-top:10px;line-height:1.5}
  .asof{color:var(--mut2);font-size:13px;text-align:right;line-height:1.6}
  /* ===== page identity =====
     Audit #19: all fifteen tabs shipped the same h1 and the same browser title,
     so the surfaces were indistinguishable in history, bookmarks and to a screen
     reader. Each page now states what it is (h1), what it is for (.phpurpose),
     where its data comes from (.phsource), and how it is worked (the panel). */
  .phmain{min-width:0;flex:1 1 34ch}
  .phpurpose{margin:10px 0 0;color:var(--mut);font-size:18px;line-height:1.5;max-width:68ch}
  .phsource{margin:8px 0 0;color:var(--mut2);font-size:12px;line-height:1.5;max-width:68ch;
    font-family:"Public Sans","Inter",sans-serif;font-weight:500;letter-spacing:.05em;text-transform:uppercase}
  .phsource b{color:var(--mut);font-weight:600}
  /* Collapsed by default: this is reference, not the work. It sits on a tonal
     step down from the page so it reads as a well rather than a card. */
  .usage{margin-top:20px;background:var(--panel2);border-radius:var(--r-card);overflow:hidden}
  .usage>summary{cursor:pointer;list-style:none;padding:14px 20px;font-family:"Public Sans","Inter",sans-serif;
    font-size:12px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--mut);
    display:flex;align-items:center;gap:10px;user-select:none}
  .usage>summary::-webkit-details-marker{display:none}
  /* Authored chevron, not a unicode glyph. Rotates to open. */
  .usage>summary::before{content:"";width:9px;height:9px;flex:none;border-right:2px solid var(--mut);
    border-bottom:2px solid var(--mut);transform:rotate(-45deg);margin-left:2px;
    transition:transform .28s cubic-bezier(.16,1,.3,1)}
  .usage[open]>summary::before{transform:rotate(45deg)}
  .usage>summary:hover{color:var(--ink)}
  .usagebody{padding:0 20px 20px}
  .usagebody svg{width:100%;height:auto;display:block;max-width:960px}
  .usagebody .dgnote{margin:4px 0 0;font-size:13px;color:var(--mut2);line-height:1.5;
    font-family:"Inter",sans-serif;letter-spacing:0;text-transform:none}
  @media (prefers-reduced-motion:reduce){ .usage>summary::before{transition:none} }
  /* ===== banner ===== */
  /* .warn is ALARM. Neutral explanatory copy uses .note — if every tab shows a red
     box, the one real warning (unverified waiver data) stops being read. */
  .warn{margin:0 0 20px;padding:16px 20px;background:var(--red-bg);border:none;
    border-radius:var(--r-card);color:#5f1512;font-size:15px;line-height:1.55}
  .warn b{color:var(--red-fg)}
  .warn a{color:var(--red-fg);font-weight:700}
  .note{margin:0 0 20px;padding:16px 20px;background:var(--panel2);border:none;
    border-radius:var(--r-card);color:var(--mut);font-size:15px;line-height:1.55}
  /* ===== stat cards ===== */
  .cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:16px;margin-bottom:22px}
  .card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);
    padding:20px 22px;box-shadow:0 2px 0 rgba(24,29,23,.03)}
  .card .n{display:block;font-size:30px;font-weight:700;line-height:1.05;letter-spacing:-.02em;color:var(--ink)}
  /* The label is the only thing that says what the number means, so it stops
     being the weakest text in the app: 13px sentence case on --mut (9.4:1). */
  .card .l{margin-top:6px;color:var(--mut);font-size:13px;text-transform:none;letter-spacing:normal;font-weight:600}
  .card.tam{border-color:var(--green-ln);background:linear-gradient(180deg,#eef8ef,#fff)}
  .card.tam .n{color:var(--primary)}
  /* ===== panel / controls / table ===== */
  main{display:block}
  .controls{display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin:0 0 16px}
  input,select{background:#fff;border:1px solid var(--line2);color:var(--ink);
    border-radius:var(--r-ctl);padding:12px 14px;font-size:15px;font-family:inherit}
  input{flex:1;min-width:220px}
  input::placeholder{color:var(--mut2)}
  input:focus,select:focus{outline:none;border-color:var(--primary);box-shadow:0 0 0 3px rgba(13,99,27,.12)}
  /* Every interactive thing gets a visible focus ring, not just inputs. The UA
     outline is invisible on the dark topbar and on solid-green .btn-primary. */
  a:focus-visible,button:focus-visible,select:focus-visible,[tabindex]:focus-visible{
    outline:3px solid var(--primary);outline-offset:2px;border-radius:2px}
  .side a:focus-visible,.topbar a:focus-visible,.topbar button:focus-visible{outline-color:#88d982}
  /* No overflow here: it would become the scroll container for the sticky thead
     below, which is why the headers never stuck. Corners move onto the table. */
  .tbl-wrap{border:1px solid var(--line);border-radius:var(--r-card);background:var(--panel);box-shadow:0 2px 0 rgba(24,29,23,.03)}
  /* table-layout:fixed is what keeps the table inside .content. With auto layout
     the widest cell sets the column and the table grows past the viewport, which
     scrolls the PAGE sideways and drags the sticky topbar/sidebar off screen.
     overflow-x:auto on .tbl-wrap is not the alternative: any non-visible overflow
     makes the wrap the scroll container in BOTH axes and the sticky thead below
     stops sticking to the viewport. Fixed layout + the column widths further down
     + .hide-sm/.hide-xs is how the table is made to fit instead of to scroll. */
  table{width:100%;table-layout:fixed;border-collapse:collapse;font-size:16px}
  /* top = topbar height, not 0: the topbar is sticky at z-index 40, so a header
     stuck at 0 would sit behind it. */
  thead th{position:sticky;top:var(--topbar-h);z-index:2;background:#eef3e7;color:var(--mut);font-weight:700;
    font-size:12px;text-transform:uppercase;letter-spacing:.04em;cursor:pointer;user-select:none;
    border-bottom:1px solid var(--line)}
  thead th:first-child{border-top-left-radius:var(--r-card)}
  thead th:last-child{border-top-right-radius:var(--r-card)}
  /* Only headers that actually sort look sortable. */
  th:not([data-k]),th[data-k^="_"]{cursor:default}
  th:not([data-k]):hover,th[data-k^="_"]:hover{color:var(--mut)}
  th[data-sort]::after{content:" ▼";font-size:10px}
  th[data-sort="asc"]::after{content:" ▲"}
  /* Under fixed layout a long unbroken string (a plan name, a URL, an email)
     would spill out of its cell and back into documentElement.scrollWidth. */
  th,td{text-align:left;padding:14px 16px;vertical-align:top;overflow-wrap:anywhere}
  /* ===== column widths (see table-layout:fixed above) =====
     Only the column that carries the long prose is named; table-layout:fixed
     splits what is left equally between the rest, which is what they want. Below
     601px the tables are down to 3-4 columns and an equal split is already right.
     nth-child counts DOM cells, so a .hide-sm/.hide-xs column still holds its
     position here and these stay correct at every width. */
  @media(min-width:601px){
    #tbl th:nth-child(8){width:20%}
    #rtbl th:nth-child(1),#rfptbl th:nth-child(1),#ldtbl th:nth-child(1){width:30%}
    #prgtbl th:nth-child(1){width:40%}
    #atbl th:nth-child(1),#autbl th:nth-child(1){width:26%}
    #matbl th:nth-child(5){width:24%}
    #wltbl th:nth-child(1){width:24%}#wltbl th:nth-child(4){width:22%}
    #chtbl th:nth-child(4){width:34%}
  }
  /* Shedding columns, never shrinking type: at 480px eight columns cannot be
     read at any size, so the ones that are not the answer to the tab's question
     are dropped. .hide-sm was already the pattern for the .pdrow grids. */
  @media(max-width:960px){.hide-sm{display:none}}
  @media(max-width:600px){
    .hide-xs{display:none}
    /* Buys back 12px per cell without touching the type scale. */
    th,td{padding:12px 10px}
    /* A nowrap pill is the one thing that can still out-measure a 111px column. */
    .badge,.rail{white-space:normal}
    /* The rounded top-right corner follows the last column still on screen. */
    #tbl th:nth-child(3),#prgtbl th:nth-child(3),#atbl th:nth-child(4),
    #dmtbl th:nth-child(4),#wltbl th:nth-child(5){border-top-right-radius:var(--r-card)}
  }
  tbody td{border-bottom:1px solid var(--line)}
  tbody tr:nth-child(even) td{background:#fafcf6}
  tbody tr:last-child td{border-bottom:none}
  thead th:hover{color:var(--ink)}
  tbody tr:hover td{background:#eef6ea}
  td a{color:var(--ink);border-bottom:1px solid transparent}
  td a b{color:var(--ink)}
  td a:hover,td a:hover b{color:var(--primary);border-bottom-color:rgba(13,99,27,.3)}
  /* ===== badges / chips ===== */
  .badge{display:inline-block;padding:4px 12px;border-radius:12px;font-size:12.5px;font-weight:700;white-space:nowrap;line-height:1.4}
  .approved{background:var(--green-bg);color:var(--green-fg);border:1px solid var(--green-ln)}
  .aop{background:var(--info-bg);color:var(--info-fg);border:1px solid var(--info-ln)}
  .pending{background:var(--amber-bg);color:var(--amber-fg);border:1px solid var(--amber-ln)}
  .unknown{background:var(--gray-bg);color:var(--gray-fg);border:1px solid var(--gray-ln)}
  .none{background:var(--gray-bg);color:var(--mut2);border:1px solid var(--gray-ln)}
  .yes{color:var(--primary);font-weight:700}
  .no{color:var(--mut2)}
  .fb{color:var(--mut);font-size:15px}
  .v{font-size:14px;color:var(--mut2)}
  .v.unver{color:var(--amber-fg)}
  .notes{color:var(--mut);font-size:14px;max-width:360px;line-height:1.5}
  .applylink{font-size:12.5px;color:var(--primary);white-space:nowrap;font-weight:700;margin-left:4px}
  .pulse{display:inline-block;margin-left:6px;padding:2px 10px;border-radius:12px;font-size:11.5px;font-weight:700;
    white-space:nowrap;text-decoration:none;background:#fbe9d3;color:#9a4f0c;border:1px solid #f0cfa6}
  .pulse:hover{background:#f7ddbe}
  footer{padding:26px 0 20px;color:var(--mut2);font-size:12.5px;border-top:1px solid var(--line);margin-top:28px}
  footer code{color:var(--mut);background:var(--panel2);padding:1px 5px;border-radius:4px;font-size:11px}
  /* ===== rails ===== */
  .rail{display:inline-block;padding:3px 10px;border-radius:6px;font-size:12.5px;font-weight:700;white-space:nowrap}
  .rail-1115{background:var(--green-bg);color:var(--green-fg);border:1px solid var(--green-ln)}
  .rail-oaa{background:var(--amber-bg);color:var(--amber-fg);border:1px solid var(--amber-ln)}
  .rail-food{background:var(--info-bg);color:var(--info-fg);border:1px solid var(--info-ln)}
  .rail-other{background:var(--gray-bg);color:var(--gray-fg);border:1px solid var(--gray-ln)}
  .new{display:inline-block;margin-left:6px;padding:1px 7px;border-radius:5px;font-size:9.5px;
    font-weight:700;letter-spacing:.04em;background:var(--green-bg);color:var(--green-fg);
    border:1px solid var(--green-ln);vertical-align:middle}
  /* ===== track select ===== */
  /* max-width so the widest <option> ("+ add to pipeline") cannot set the width
     of the Track column and push the table past the viewport. */
  select.track{padding:8px 10px;font-size:14px;border-radius:6px;background:#fff;max-width:100%}
  select.track[data-s="contacted"]{border-color:var(--info-ln);color:var(--info-fg)}
  select.track[data-s="proposal"]{border-color:var(--amber-ln);color:var(--amber-fg)}
  select.track[data-s="won"]{border-color:var(--green-ln);color:var(--green-fg);background:var(--green-bg)}
  select.track[data-s="lost"]{opacity:.55}
  .seenbtn{cursor:pointer;font-size:13px;font-weight:600;color:var(--secondary,#4c616c);background:#fff;
    border:1px solid var(--line2);border-radius:var(--r-ctl);padding:11px 15px;font-family:inherit}
  .seenbtn:hover{border-color:var(--primary);color:var(--primary)}
  /* ===== pipeline ===== */
  /* Five stages, five columns, left to right — a two-wide wrap is not a board.
     5*170 + 4*18 = 922px, so below ~900px the section scrolls sideways rather
     than reflowing and losing the progression. */
  #pcols{display:grid;grid-template-columns:repeat(5,minmax(170px,1fr));gap:18px}
  @media(max-width:900px){#pcols{overflow-x:auto;padding-bottom:10px}}
  .pcol .pnone{color:var(--mut2);font-size:14px;font-style:italic;padding:4px 0}
  .pcol{margin-bottom:6px}
  .pcol h3{font-size:12px;text-transform:uppercase;letter-spacing:.05em;color:var(--mut2);
    border-bottom:1px solid var(--line);padding-bottom:8px;margin:0 0 12px;font-weight:700}
  .pcard{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);padding:14px 16px;margin-bottom:10px;box-shadow:0 2px 0 rgba(24,29,23,.03)}
  .pcard a{color:var(--ink)}
  .pcard a:hover{color:var(--primary)}
  .pcard .meta{color:var(--mut2);font-size:13.5px;margin-top:6px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
  /* ===== auth ===== */
  #login{position:fixed;inset:0;z-index:100;display:flex;align-items:center;justify-content:center;
    background:radial-gradient(1200px 600px at 50% -10%,#e4f2e0,var(--bg))}
  .loginbox{background:#fff;border:1px solid var(--line);border-radius:16px;padding:36px 32px;
    width:390px;max-width:92vw;text-align:center;box-shadow:0 12px 40px rgba(24,29,23,.12)}
  .loginbox .mark{width:48px;height:48px;margin:0 auto 18px}
  .loginbox h2{margin:0 0 6px;font-size:24px;font-weight:700}
  .loginbox p{margin:0 0 22px;color:var(--mut);font-size:15px}
  .loginbox input{width:100%;margin-bottom:12px}
  .loginbox button{width:100%;padding:14px;border-radius:var(--r-ctl);border:none;cursor:pointer;min-height:48px;
    background:linear-gradient(135deg,#006b2c,#00873a);color:#fff;font-size:15.5px;font-weight:700;font-family:inherit}
  .loginbox button:hover{filter:brightness(1.08)}
  .loginbox button.ghost{background:transparent;border:1px solid var(--line2);color:var(--mut);margin-top:10px;font-weight:600}
  .loginbox button.ghost:hover{filter:none;color:var(--primary);border-color:var(--primary)}
  .loginbox label{display:block;text-align:left;font-size:14px;font-weight:600;color:var(--mut);margin:0 0 4px}
  #loginMsg{margin-top:14px;font-size:14px;color:var(--primary);min-height:18px}
  #loginMsg.err{color:var(--red-fg)}
  /* ===== topbar ===== */
  .topbar .logo-txt{color:#88d982;font-size:17px}
  .adminlink{color:#c7d2c6;font-size:14px;font-weight:600;cursor:pointer}
  .adminlink:hover{color:#fff}
  .topbar .spacer{flex:1}
  /* sidebar icons */
  .tab .tico{width:18px;height:18px;flex:none;opacity:.9}
  .tab.on .tico{opacity:1}
  /* ===== stat cards with delta ===== */
  .card .delta{font-size:13px;font-weight:700;margin-left:8px;vertical-align:middle}
  .card .delta.up{color:var(--primary)} .card .delta.down{color:var(--red)}
  .card .n.small{font-size:32px}
  .card.redn .n{color:var(--red)}
  /* ===== opportunity cards (Awards/Grants) ===== */
  .oppgrid{display:flex;flex-direction:column;gap:14px}
  .oppcard{display:flex;gap:20px;align-items:stretch;background:#fff;border:1px solid var(--line);
    border-radius:var(--r-card);padding:20px 22px}
  .oppcard.tier-partner{border-left-color:#8a6206}.oppcard.tier-maybe{border-left-color:var(--mut2)}
  /* De-emphasise by surface, not by opacity: .62 dragged the meta text, the fit
     ring and the deadline down with it, taking --mut2 to roughly 2.7:1. */
  .oppcard.tier-ignore{border-left-color:var(--line2);background:var(--panel2)}
  .oppcard .main{flex:1;min-width:0}
  .oppcard .tags{display:flex;gap:8px;align-items:center;margin-bottom:8px;flex-wrap:wrap}
  .tag{font-size:11px;font-weight:800;letter-spacing:.04em;padding:3px 9px;border-radius:6px;text-transform:uppercase}
  .tag.fed{background:var(--green-bg);color:var(--green-fg)} .tag.phil{background:var(--info-bg);color:var(--info-fg)}
  .tag.state{background:var(--amber-bg);color:var(--amber-fg)} .tag.other{background:var(--gray-bg);color:var(--gray-fg)}
  .oppcard h4{margin:0 0 4px;font-family:"Plus Jakarta Sans",sans-serif;font-size:19px;font-weight:700;line-height:1.25}
  .oppcard h4 a{color:var(--ink)} .oppcard h4 a:hover{color:var(--primary)}
  .oppcard .meta{display:flex;gap:26px;align-items:center;margin-top:12px;flex-wrap:wrap}
  .oppcard .meta .k{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--mut2);font-weight:700}
  .oppcard .meta .val{font-size:15px;font-weight:700;color:var(--ink);margin-top:2px}
  .oppcard .foot{display:flex;justify-content:space-between;align-items:center;margin-top:14px;padding-top:14px;border-top:1px solid var(--line);gap:12px;flex-wrap:wrap}
  .deadline{color:var(--red-fg);font-weight:700;font-size:13.5px}
  .oppcard .actions{display:flex;gap:10px}
  .btn-primary{background:var(--primary);color:#fff;border:none;border-radius:var(--r-ctl);padding:10px 16px;font-weight:700;font-size:13.5px;cursor:pointer;font-family:inherit}
  .btn-primary:hover{background:var(--primary-dark)}
  /* fit-score ring */
  .ring{--p:0;--c:var(--primary);width:56px;height:56px;border-radius:50%;flex:none;display:grid;place-items:center;
    background:conic-gradient(var(--c) calc(var(--p)*1%),#e6ebe0 0)}
  .ring::before{content:"";position:absolute;width:44px;height:44px;border-radius:50%;background:#fff}
  .ringwrap{display:flex;flex-direction:column;align-items:center;gap:5px;justify-content:center;position:relative}
  .ring span{position:relative;font-size:14px;font-weight:800;color:var(--ink)}
  .ringwrap .lbl{font-size:10px;text-transform:uppercase;letter-spacing:.05em;color:var(--mut2);font-weight:700}
  /* ===== partner directory rows ===== */
  .pdrow{display:grid;grid-template-columns:auto 1.4fr .8fr 1.2fr 1fr 1.3fr auto;gap:16px;align-items:center;
    padding:16px;border-bottom:1px solid var(--line)}
  /* Grid items default to min-width:auto, so one long plan name would refuse to
     shrink and widen the whole row past .content — same failure as the tables. */
  .pdrow>*{min-width:0;overflow-wrap:anywhere}
  .pdrow:nth-child(even){background:#fafcf6}
  .pdrow:hover{background:#eef6ea}
  .pdhead{background:#eef3e7;font-size:12px;text-transform:uppercase;letter-spacing:.04em;color:var(--mut);font-weight:700;border-bottom:1px solid var(--line);
    border-radius:var(--r-card) var(--r-card) 0 0}
  .pdhead:hover{background:#eef3e7}
  .avatar{width:44px;height:44px;border-radius:10px;background:#d4e8f2;color:#25576a;display:grid;place-items:center;font-weight:800;font-size:15px;flex:none}
  .pdname{font-weight:700;font-size:15.5px}
  .pdsub{color:var(--mut2);font-size:13px;margin-top:2px}
  .typechip{display:inline-block;background:var(--green-bg);color:var(--green-fg);border-radius:8px;padding:3px 9px;font-size:11.5px;font-weight:800;letter-spacing:.03em}
  .statusdot{display:inline-flex;align-items:center;gap:7px;font-weight:700;font-size:14px}
  .statusdot .dot{width:9px;height:9px;border-radius:50%;flex:none}
  /* .hide-sm is global now (see the table rules), so this only re-tracks the grid. */
  @media(max-width:960px){.pdrow{grid-template-columns:auto 1fr auto;row-gap:6px}}
  /* ===== market opportunity map ===== */
  .mkgrid{display:grid;grid-template-columns:1fr 340px;gap:18px}
  @media(max-width:1040px){.mkgrid{grid-template-columns:1fr}}
  .mkpanel{background:#fff;border:1px solid var(--line);border-radius:var(--r-card);box-shadow:0 2px 0 rgba(24,29,23,.03)}
  .mkpanel .ph{padding:16px 20px;border-bottom:1px solid var(--line);display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap}
  .mkpanel .ph h3{margin:0;font-size:18px}
  .seg{display:inline-flex;background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:3px}
  .seg button{border:none;background:transparent;padding:7px 14px;border-radius:6px;font-weight:700;font-size:13px;cursor:pointer;color:var(--mut);font-family:inherit}
  .seg button.on{background:#fff;color:var(--ink);box-shadow:0 1px 2px rgba(0,0,0,.08)}
  .filterbar{display:flex;gap:26px;align-items:flex-end;background:#fff;border:1px solid var(--line);border-radius:var(--r-card);padding:18px 20px;margin-bottom:18px;flex-wrap:wrap}
  .filterbar .fl{font-size:12px;text-transform:none;letter-spacing:normal;color:var(--mut2);font-weight:700;margin-bottom:6px}
  .pillbtns{display:inline-flex;gap:8px}
  .pillbtns button{border:1px solid var(--line2);background:#fff;border-radius:8px;padding:9px 16px;font-weight:700;font-size:13px;cursor:pointer;color:var(--mut);font-family:inherit}
  .pillbtns button.on{background:var(--primary);color:#fff;border-color:var(--primary)}
  .toprail{display:flex;flex-direction:column}
  .toprail .rh{padding:14px 18px;border-bottom:1px solid var(--line);font-size:12px;text-transform:uppercase;letter-spacing:.05em;color:var(--mut);font-weight:800}
  .stateitem{display:flex;align-items:center;gap:12px;padding:14px 18px;border-bottom:1px solid var(--line)}
  .stateitem:last-child{border-bottom:none}
  .rank{width:30px;height:30px;border-radius:50%;display:grid;place-items:center;color:#fff;font-weight:800;font-size:12px;flex:none;background:var(--primary2)}
  .rank.r1{background:var(--primary)}.rank.r4,.rank.r5{background:#9db99f}
  .stateitem .sn{flex:1;font-weight:700;font-size:15px}
  .stateitem .sv{font-weight:800;color:var(--primary);font-size:15px}
  .minichips{display:flex;gap:6px;margin-top:4px}
  .minichip{font-size:10px;font-weight:700;padding:2px 7px;border-radius:5px;text-transform:uppercase;letter-spacing:.03em}
  .mc-green{background:var(--green-bg);color:var(--green-fg)}.mc-blue{background:var(--info-bg);color:var(--info-fg)}.mc-red{background:var(--red-bg);color:var(--red-fg)}.mc-gray{background:var(--gray-bg);color:var(--gray-fg)}
  .densitybar{height:10px;border-radius:5px;background:var(--panel2);overflow:hidden;margin-top:6px}
  .densitybar>i{display:block;height:100%;background:linear-gradient(90deg,#7ffc97,#006b2c)}
  /* ===== CRM: worklist, drawer, write-error toast ===== */
  #wlrows tr{cursor:pointer}
  #wlrows td .sub{color:var(--mut2);font-size:12.5px;margin-top:3px}
  /* The row title is the way into the drawer, so it is a real button. */
  .rowopen{background:none;border:none;padding:0;font:inherit;font-weight:700;color:var(--ink);
    cursor:pointer;text-align:left;max-width:100%;overflow-wrap:anywhere}
  .rowopen:hover{color:var(--primary);text-decoration:underline}
  /* Stale is the one thing that demands action — it must not wear the same amber
     as the ordinary "Lead" stage badge sitting two columns away. */
  .badge.stale{background:var(--red-bg);color:var(--red-fg);border:1px solid var(--red-ln)}
  #ploading{font-size:16px;color:var(--mut)}
  #drawerScrim{position:fixed;inset:0;background:rgba(24,29,23,.34);z-index:60}
  /* 100dvh, not 100vh: on mobile Safari 100vh runs under the browser chrome and
     buries the Log Touch button. */
  #drawer{position:fixed;top:0;right:0;z-index:61;width:452px;max-width:94vw;height:100vh;height:100dvh;overflow-y:auto;
    background:var(--panel);border-left:1px solid var(--line);padding:22px 24px 48px}
  #drawer h3{margin:0 0 6px;font-size:21px;line-height:1.3}
  #drawer h3 a{color:var(--ink)} #drawer h3 a:hover{color:var(--primary)}
  #drawer .dsec{margin-top:20px;padding-top:18px;border-top:1px solid var(--line)}
  /* These name every field on the app's core editing surface. 11px uppercase was
     the smallest text in the file; 12px sentence case is the floor now. */
  #drawer .fl{font-size:12px;text-transform:none;letter-spacing:normal;color:var(--mut2);font-weight:700;margin-bottom:7px}
  #drawer input,#drawer select,#drawer textarea{width:100%;min-width:0;flex:none;font:inherit;font-size:14.5px;
    background:#fff;color:var(--ink);border:1px solid var(--line2);border-radius:var(--r-ctl);padding:10px 12px}
  #drawer textarea{resize:vertical}
  #drawer .row2{display:flex;gap:10px;align-items:center;margin-top:10px;flex-wrap:wrap}
  #drawer .row2 button{flex:none;white-space:nowrap}
  #drawer .dhead{display:flex;justify-content:space-between;align-items:flex-start;gap:14px}
  .touch{border:none;background:var(--panel2);
    border-radius:var(--r-ctl);padding:11px 13px;margin-bottom:9px}
  .touch .m{color:var(--mut2);font-size:12.5px;margin-top:5px}
  /* Agent draft body: escaped markdown as plain text inside the drawer. */
  .prop{background:var(--panel2);border-radius:6px;padding:10px 12px;margin:8px 0 0;font-size:14px;line-height:1.5}
  .prop.ok{border-left:3px solid var(--primary)}
  .prop .badge{margin-right:4px}
  .draftbody{background:var(--panel2);border-radius:6px;padding:12px 14px;margin:8px 0 0;
    max-height:340px;overflow:auto;white-space:pre-wrap;word-break:break-word;
    font-size:13px;line-height:1.5}
  #crmErr{position:fixed;left:50%;transform:translateX(-50%);bottom:24px;z-index:80;max-width:min(660px,92vw);
    background:var(--red-bg);border:none;color:#5f1512;
    border-radius:var(--r-card);padding:13px 18px;font-size:14.5px;line-height:1.5;box-shadow:0 8px 24px rgba(24,29,23,.18)}
  /* Same node, success skin. crmError() clears .className so an error after a
     success cannot render green. */
  #crmErr.ok{background:var(--green-bg);border-color:var(--green-ln);border-left-color:var(--primary);color:var(--green-fg)}
  #crmErr .errx{background:none;border:none;color:inherit;font-size:16px;cursor:pointer;
    margin-left:12px;padding:4px 8px;font-family:inherit}
  @media(max-width:560px){#drawer{width:100vw}}
