/* BlackRidge HQ — the design system.
 *
 * Rewritten as one system rather than three rounds of additions. The rules it
 * is built on, in order of how much they matter:
 *
 *   One question per screen.
 *   One primary action per block; everything else is quiet.
 *   A number earns its place by changing a decision.
 *   Colour means one thing — this needs you. Everything else is ink on paper.
 *   Nothing is stated twice.
 *
 * Practically that means: four type sizes rather than eleven, one chip rather
 * than three, borders only where something genuinely separates, and whitespace
 * doing the work that boxes used to do.
 */

:root{
  /* Ink. Four weights of the same idea rather than a palette. */
  --ink:#16201B;          /* primary text */
  --ink-2:#5A6862;        /* secondary text, labels */
  --ink-3:#95A09A;        /* tertiary, placeholders, empty */
  --line:#E8E0D2;         /* hairlines */
  --line-2:#F2ECE1;       /* inner hairlines, table rows */

  /* Surface — three levels, so a card is genuinely a card */
  --paper:#F6F1E8;        /* the page */
  --surface:#FFFFFF;      /* cards sit on it */
  --surface-2:#FAF6EE;    /* quiet fill inside a card */
  --surface-3:#F1EADD;    /* pressed / hovered */

  /* Elevation. Two levels only; more than that and it becomes a lava lamp. */
  --lift:0 1px 2px rgba(22,54,42,.04), 0 1px 3px rgba(22,54,42,.06);
  --lift-2:0 2px 4px rgba(22,54,42,.04), 0 8px 24px -12px rgba(22,54,42,.18);

  /* Brand, from blackridgeglobal.co.uk */
  --navy:#16362A;
  --bronze:#B4653C;
  --sand:#E4BB94;

  /* Meaning. Used sparingly and only where stated. */
  --urgent:#A8442F;       /* this needs you now */
  --good:#2F6B4F;         /* done, passed, settled */

  /* Space — one scale, so nothing is ever "about 14px" */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px;
  --s6:32px; --s7:48px; --s8:64px;

  --r:8px;                /* one radius */
  --r-sm:5px;
  --rail:212px;
  --max:1180px;
}

*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%}
body{font-family:'Inter',system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
  color:var(--ink);background:var(--paper);font-size:14px;line-height:1.55;
  -webkit-font-smoothing:antialiased;font-feature-settings:"cv11","ss01"}
a{color:inherit;text-decoration:none}
button,input,select,textarea{font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--sand);outline-offset:2px;border-radius:3px}

/* ── TYPE — four sizes, and that is all ──────────────────────────────── */
.t-display{font-family:'Fraunces',Georgia,serif;font-weight:500;font-size:28px;
  line-height:1.15;letter-spacing:-.02em}
.t-title{font-family:'Fraunces',Georgia,serif;font-weight:500;font-size:18px;
  line-height:1.25;letter-spacing:-.01em}
.t-body{font-size:14px;line-height:1.55}
.t-small{font-size:13px;line-height:1.5;color:var(--ink-2)}
.t-label{font-size:11px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink-3)}
h1,h2,h3,h4{font-family:'Fraunces',Georgia,serif;font-weight:500;letter-spacing:-.01em;
  line-height:1.2}
h1{font-size:28px} h2{font-size:20px} h3{font-size:16px} h4{font-size:14px}
.num{font-variant-numeric:tabular-nums}
.muted{color:var(--ink-2)}
.quiet{color:var(--ink-3)}
.urgent{color:var(--urgent)}

/* ── SHELL ───────────────────────────────────────────────────────────── */
.shell{display:grid;grid-template-columns:var(--rail) 1fr;min-height:100vh}

.nav{background:var(--navy);color:#B9C8BF;position:sticky;top:0;height:100vh;
  display:flex;flex-direction:column;overflow-y:auto;scrollbar-width:thin}
.nav .brand{display:flex;align-items:center;gap:var(--s2);padding:var(--s5) var(--s4) var(--s4);
  font-family:'Fraunces',serif;font-size:16px;color:#fff;letter-spacing:-.01em}
.nav .brand svg{width:22px;height:22px;flex:none}
.nav .group{padding:var(--s5) var(--s4) var(--s2);font-size:10px;letter-spacing:.14em;
  text-transform:uppercase;color:#5E7368;font-weight:600}
.nav .group:first-of-type{padding-top:var(--s2)}
.nav a{display:flex;align-items:center;gap:var(--s2);margin:1px var(--s2);
  padding:7px 10px;border-radius:var(--r);font-size:13.5px;color:#B9C8BF;
  transition:background .12s,color .12s}
.nav a:hover{background:rgba(255,255,255,.07);color:#fff}
.nav a.on{background:rgba(255,255,255,.12);color:#fff;font-weight:500}
/* The only number in the navigation is one that means "this needs you". */
.nav a .n{margin-left:auto;font-size:11.5px;font-weight:600;color:var(--sand);
  font-variant-numeric:tabular-nums}
.nav a.on .n{color:#fff}
.nav .foot{margin-top:auto;padding:var(--s4);font-size:12px;color:#7A8D83;
  border-top:1px solid rgba(255,255,255,.07)}
.nav .foot a{display:inline;margin:0;padding:0;background:none;color:#9FB2A7}
.nav .foot a:hover{color:#fff;background:none}

.main{min-width:0;display:flex;flex-direction:column}
.top{display:flex;align-items:center;gap:var(--s4);padding:0 var(--s6);height:64px;
  border-bottom:1px solid var(--line);background:rgba(252,249,243,.88);
  backdrop-filter:saturate(150%) blur(8px);position:sticky;top:0;z-index:40}
.top h1{font-size:19px}
.top .where{min-width:0}
.top .where .sub{font-family:'Inter',sans-serif;font-size:12.5px;color:var(--ink-2);
  letter-spacing:0;font-weight:400;margin-top:-2px}
.top form{margin-left:auto;position:relative}
.top input[type=search]{width:240px;padding:7px 12px 7px 32px;border:1px solid transparent;
  border-radius:var(--r);background:rgba(22,54,42,.05);font-size:13px}
.top input[type=search]:focus{background:var(--surface);border-color:var(--line)}
.top .si{position:absolute;left:11px;top:9px;opacity:.4}
.avatar{width:28px;height:28px;border-radius:50%;background:var(--navy);color:#fff;
  display:grid;place-items:center;font-size:11px;font-weight:600;flex:none}

.page{padding:var(--s6);max-width:var(--max);width:100%}
.page.wide{max-width:1560px}

/* ── SECTIONS — whitespace instead of boxes ──────────────────────────── */
.sec{margin-top:var(--s7)}
.sec:first-child{margin-top:0}
.sec > header{display:flex;align-items:baseline;gap:var(--s3);margin-bottom:var(--s4)}
.sec > header h2{font-size:17px}
.sec > header .t-small{color:var(--ink-3)}
.sec > header .more{margin-left:auto;font-size:13px;color:var(--ink-2)}
.sec > header .more:hover{color:var(--bronze)}
.rule{height:1px;background:var(--line);border:0;margin:var(--s6) 0}

/* A panel is used only where content genuinely needs separating from the page. */
.panel{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--lift)}
.panel > .pad{padding:var(--s5)}
.panel.quiet{background:var(--surface-2);border-color:transparent;box-shadow:none}
.panel.attention{border-color:#E4CBBF;background:#FDF6F3}

/* A card is the default container now. Subtle, but present. */
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--lift);padding:var(--s5)}
.card + .card{margin-top:var(--s4)}
.card > h3{font-size:11px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink-3);margin-bottom:var(--s4);display:flex;align-items:center;gap:var(--s2)}
.card > h3::after{content:"";flex:1;height:1px;background:var(--line-2)}
.card > h3 .act{flex:none;font-size:12px;text-transform:none;letter-spacing:0;
  font-weight:500;color:var(--bronze)}

/* ── THE HEADLINE NUMBERS — inline, never tiles ──────────────────────── */
.figures{display:flex;gap:var(--s7);flex-wrap:wrap;align-items:baseline}
.figure .v{font-family:'Fraunces',serif;font-size:30px;line-height:1;
  font-variant-numeric:tabular-nums;color:var(--navy)}
.figure .v.is-urgent{color:var(--urgent)}
.figure .k{font-size:12.5px;color:var(--ink-2);margin-top:6px;display:block}
a.figure:hover .v{color:var(--bronze)}

/* ── LISTS — the main unit of the interface ──────────────────────────── */
.list{list-style:none}
.list > li{display:flex;gap:var(--s4);align-items:flex-start;padding:var(--s4) 0;
  border-top:1px solid var(--line-2);transition:background .12s}
.list.boxed{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--lift);padding:0 var(--s5)}
.list.boxed > li:hover{background:transparent}
.list > li:hover .title{color:var(--navy)}
.list > li:first-child{border-top:0}
.list .grow{min-width:0;flex:1}
.list .title{font-size:14.5px;font-weight:500;line-height:1.35}
.list .why{font-size:13px;color:var(--ink-2);margin-top:3px;line-height:1.5}
.list .meta{font-size:12.5px;color:var(--ink-3);margin-top:4px}
.list .end{flex:none;display:flex;align-items:center;gap:var(--s3);padding-top:1px}
.list .stamp{font-size:12.5px;color:var(--ink-3);white-space:nowrap;
  font-variant-numeric:tabular-nums}

/* ── TABLES — five columns, generous rows ────────────────────────────── */
.tbl{width:100%;border-collapse:collapse}
.tbl th{text-align:left;font-size:11px;font-weight:600;letter-spacing:.08em;
  text-transform:uppercase;color:var(--ink-3);padding:0 var(--s4) var(--s3) 0;
  white-space:nowrap}
.tbl td{padding:var(--s3) var(--s4) var(--s3) 0;border-top:1px solid var(--line-2);
  vertical-align:baseline}
.tbl tr:hover td{background:var(--surface-2)}
.tbl td:last-child,.tbl th:last-child{padding-right:0;text-align:right}
.tbl .r,.tbl th.r{text-align:right}
.tbl .name{font-weight:500}
.tbl .sub{font-size:12.5px;color:var(--ink-3);margin-top:2px}
.tbl a.row{display:block}
.scroll{overflow-x:auto}

/* ── ONE CHIP, THREE STATES ──────────────────────────────────────────── */
.tag{display:inline-block;font-size:12px;color:var(--ink-2);white-space:nowrap}
.tag + .tag::before{content:"·";margin:0 6px;color:var(--ink-3)}
.pill{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;font-weight:500;
  padding:2px 9px;border-radius:99px;background:var(--surface-2);color:var(--ink-2);
  white-space:nowrap;border:1px solid var(--line)}
.pill.now{background:#FBEEE9;border-color:#EBD0C4;color:var(--urgent)}
.pill.done{background:#EEF4F0;border-color:#D4E4DA;color:var(--good)}

/* ── BUTTONS — one primary, everything else quiet ────────────────────── */
.btn{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:500;
  padding:7px 14px;border-radius:var(--r);border:1px solid var(--line);
  background:var(--surface);color:var(--ink);cursor:pointer;white-space:nowrap;
  transition:border-color .12s,background .12s}
.btn:hover{border-color:var(--ink-3)}
.btn-primary{background:var(--navy);border-color:var(--navy);color:#fff}
.btn-primary:hover{background:#1D4534;border-color:#1D4534}
.btn-urgent{background:var(--urgent);border-color:var(--urgent);color:#fff}
.btn-urgent:hover{background:#943B29;border-color:#943B29}
/* A quiet action looks like text, because most actions should. */
.btn-quiet{border-color:transparent;background:none;color:var(--ink-2);padding:7px 4px}
.btn-quiet:hover{color:var(--ink);border-color:transparent;background:none}
.btn-sm{padding:4px 10px;font-size:12.5px}
.btn[disabled]{opacity:.4;cursor:not-allowed}
.btns{display:flex;gap:var(--s2);flex-wrap:wrap;align-items:center}

/* ── FORMS ───────────────────────────────────────────────────────────── */
.f{margin-bottom:var(--s4)}
.f label{display:block;font-size:12.5px;color:var(--ink-2);margin-bottom:6px}
.f input,.f select,.f textarea{width:100%;padding:9px 12px;border:1px solid var(--line);
  border-radius:var(--r);background:var(--surface);font-size:14px}
.f textarea{min-height:88px;resize:vertical;line-height:1.55}
.f .hint{font-size:12.5px;color:var(--ink-3);margin-top:5px}
.fs{display:grid;gap:0 var(--s5);grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}
.fs.three{grid-template-columns:repeat(auto-fit,minmax(170px,1fr))}
@media(max-width:760px){.fs,.fs.three{grid-template-columns:minmax(0,1fr)}}

/* ── BOOKING A MEETING ────────────────────────────────────────────────── */
.bookform{padding:var(--s5);max-width:640px}
.f .hint.warn{color:var(--ink-2);background:#FBF3E4;border:1px solid #EBD9B4;
  border-radius:var(--r-sm);padding:8px 10px}

/* BOTH CLOCKS, ALWAYS ON SCREEN.
   The form used to carry a standing instruction to add an hour by hand. That
   sum stops being true on the last Sunday in October, when Spain falls back and
   Nigeria — which has no daylight saving — becomes the same time. */
.twoclocks{margin:-2px 0 var(--s4);padding:9px 12px;border-radius:var(--r-sm);
  background:var(--surface-2);border:1px solid var(--line-2);
  font-size:13px;color:var(--ink);line-height:1.5}
.twoclocks:empty{display:none}
.twoclocks.unknown{color:var(--ink-2)}

/* Who the invitation names, stated rather than assumed. */
.goesto{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}
.goesto .chip{display:inline-flex;align-items:baseline;gap:7px;padding:5px 11px;
  border-radius:100px;background:var(--surface-2);border:1px solid var(--line-2);
  font-size:13px;color:var(--ink)}
.goesto .chip .who{font-size:11.5px;color:var(--ink-3)}
.goesto .chip .who.missing{color:#9B5B2E}

/* ── FACTS — label/value pairs, the calmest way to show what we know ─── */
.facts{display:grid;gap:10px 0}
.facts .row{display:grid;grid-template-columns:140px 1fr;gap:var(--s4);align-items:baseline}
.facts dt{font-size:13px;color:var(--ink-2)}
.facts dd{font-variant-numeric:tabular-nums;min-width:0;word-break:break-word}
.facts .row.blank dd{color:var(--ink-3)}

/* ── TIMELINE ────────────────────────────────────────────────────────── */
.tl{list-style:none}
.tl li{display:grid;grid-template-columns:82px 1fr;gap:var(--s4);padding:var(--s3) 0;
  border-top:1px solid var(--line-2);align-items:baseline}
.tl li:first-child{border-top:0}
.tl .when{font-size:12.5px;color:var(--ink-3);font-variant-numeric:tabular-nums}
.tl .what{min-width:0}
.tl .what b{font-weight:500}
/* A TRUNCATED NOTE HAS TO LOOK TRUNCATED.
   This clipped at nine lines with overflow:hidden, so a fact find needing 810px
   of height stopped dead at 115px — mid-word, with nothing to say there was
   more. The entry is a <details> and does expand, but nothing on screen said
   so. A line clamp ends it on an ellipsis instead, which is the difference
   between "there is more" and "this is all there is". */
.tl .what p{color:var(--ink-2);margin-top:3px;font-size:13px;white-space:pre-wrap;
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:7;
  overflow:hidden}
/* Open the entry and the clamp comes off, or expanding would show the same
   seven lines it already showed. */
.tl details[open] .what p,.tl .what details[open] p,
.noteedit[open] > summary p{-webkit-line-clamp:unset;display:block}
.tl li.inbound .what b{color:var(--good)}

/* ── PROGRESS ────────────────────────────────────────────────────────── */
.track{height:3px;background:var(--line);border-radius:2px;overflow:hidden;flex:1;
  min-width:60px}
.track i{display:block;height:100%;background:var(--navy);border-radius:2px}
.track.is-urgent i{background:var(--urgent)}
.stepline{display:flex;align-items:center;gap:var(--s3);font-size:13px;color:var(--ink-2)}

/* ── BOARD ───────────────────────────────────────────────────────────── */
.board{display:flex;gap:var(--s3);overflow-x:auto;padding-bottom:var(--s3)}
.col{flex:0 0 218px;min-height:80px}
.col > h3{font-size:12px;font-weight:600;letter-spacing:.04em;color:var(--ink-2);
  padding:0 0 var(--s2);display:flex;align-items:baseline;gap:var(--s2)}
.col > h3 .n{margin-left:auto;font-variant-numeric:tabular-nums;color:var(--ink-3)}
.col .items{display:flex;flex-direction:column;gap:var(--s2)}
.dcard{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:10px 12px;display:block;transition:border-color .12s}
.dcard:hover{border-color:var(--ink-3)}
.dcard .n{font-size:13.5px;font-weight:500;line-height:1.3}
.dcard .u{font-size:12.5px;color:var(--ink-3);margin-top:2px}
.dcard .f{display:flex;align-items:baseline;gap:var(--s2);margin-top:8px;font-size:12px;
  color:var(--ink-3)}
.dcard .f .amt{margin-left:auto;font-weight:600;color:var(--ink);
  font-variant-numeric:tabular-nums}
.dcard.stale{border-left:2px solid var(--urgent)}
.col.over{background:var(--surface-2);border-radius:var(--r)}
.dcard[draggable=true]{cursor:grab}

/* ── TABS ────────────────────────────────────────────────────────────── */
.tabs{display:flex;gap:var(--s5);border-bottom:1px solid var(--line);
  margin-bottom:var(--s5);overflow-x:auto}
.tabs a{padding:0 0 11px;font-size:13.5px;color:var(--ink-2);
  border-bottom:2px solid transparent;margin-bottom:-1px;white-space:nowrap}
.tabs a:hover{color:var(--ink)}
.tabs a.on{color:var(--ink);border-bottom-color:var(--navy);font-weight:500}

/* ── EMPTY — a sentence and the thing that fixes it, never furniture ─── */
.none{padding:var(--s6) 0;color:var(--ink-3);font-size:14px;max-width:52ch}
.none b{display:block;color:var(--ink);font-family:'Fraunces',serif;font-weight:500;
  font-size:16px;margin-bottom:5px}
.none .btns{margin-top:var(--s4)}

/* ── NOTES ───────────────────────────────────────────────────────────── */
.msg{border-radius:var(--r);padding:var(--s3) var(--s4);font-size:13.5px;
  background:var(--surface-2);color:var(--ink-2);border:1px solid var(--line)}
.msg.now{background:#FDF6F3;border-color:#EBD0C4;color:#7A3422}
.msg.done{background:#F0F5F2;border-color:#D4E4DA;color:#255440}

/* ── GRID ────────────────────────────────────────────────────────────── */
.two{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--s7)}
.main-side{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(0,1fr);gap:var(--s7)}
.three-up{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:var(--s5)}
@media(max-width:1080px){.main-side,.two,.three-up{
  grid-template-columns:minmax(0,1fr);gap:var(--s6)}}
/* ── ADDED TO THE HOME SCREEN ────────────────────────────────────────────
   base.html asks iOS for `apple-mobile-web-app-status-bar-style:
   black-translucent`, which is what gives the installed app the full screen
   with no browser chrome. The cost is that the page then starts at y=0 —
   UNDERNEATH the clock, the battery and, on a notched device, the notch.

   Found 7 Oct 2026, when Luca asked for the CRM on his iPad: in Safari it
   looks right, and the moment it is added to the home screen the top of the
   navigation sits behind the status bar.

   env(safe-area-inset-*) is zero in an ordinary browser tab, so none of this
   changes anything until the app is actually installed, and max() keeps the
   normal padding when it is not. The left and right insets matter in
   landscape, which is how an iPad is held. */
@supports (padding: max(0px)) {
  .nav{padding-top:max(var(--s2), env(safe-area-inset-top))}
  .page{padding-left:max(var(--s6), env(safe-area-inset-left));
        padding-right:max(var(--s6), env(safe-area-inset-right));
        padding-bottom:max(var(--s6), env(safe-area-inset-bottom))}
  .top{padding-left:max(var(--s6), env(safe-area-inset-left));
       padding-right:max(var(--s6), env(safe-area-inset-right))}
}

@media(max-width:820px){
  .shell{grid-template-columns:minmax(0,1fr)}
  /* THE NAVIGATION ON A PHONE.
     Found 7 Oct 2026 with Luca travelling and working off a handset. All
     twenty-four destinations were present, in a 60px strip with overflow:auto
     and nothing to say it scrolled — so Meetings, Payments, Settings and a
     dozen others were reachable only by a sideways swipe nobody would guess at.
     The targets were 34px tall, under the 44px a thumb wants, and Sign out was
     hidden outright, so there was no way to leave the CRM from a phone.

     Kept as one scrolling row rather than rebuilt as a drawer: a drawer is a
     tap before every move, and this is software for somebody working quickly.
     What it needed was to look scrollable and be comfortable to hit. */
  .nav{position:static;height:auto;flex-direction:row;flex-wrap:nowrap;
    align-items:center;padding:var(--s2) 0;
    overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;
    scrollbar-width:none;
    /* The right edge fades, which is the cheapest honest way to say "there is
       more this way" without spending a row on arrows. */
    -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent);
    mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent)}
  .nav::-webkit-scrollbar{display:none}
  .nav .group{display:none}
  .nav a{flex:none;min-height:44px;padding-top:11px;padding-bottom:11px;
    scroll-snap-align:start}
  .nav .brand{padding:var(--s2) var(--s3);flex:none}
  /* Sign out was display:none here, which left no way off the CRM on a phone.
     The name beside it is noise at this width; the link is not. */
  .nav .foot{display:flex;align-items:center;margin:0;padding:0 var(--s3) 0 var(--s2);
    flex:none;font-size:0;border:0}
  .nav .foot a{display:inline-flex;align-items:center;min-height:44px;
    font-size:13px;color:#9FB2A7;white-space:nowrap}
  .nav .foot br{display:none}
  .page{padding:var(--s4)}
  .top{padding:0 var(--s4)}
  /* The same insets at phone/tablet width, against the tighter padding. */
  @supports (padding: max(0px)) {
    .page{padding-left:max(var(--s4), env(safe-area-inset-left));
          padding-right:max(var(--s4), env(safe-area-inset-right))}
    .top{padding-left:max(var(--s4), env(safe-area-inset-left));
         padding-right:max(var(--s4), env(safe-area-inset-right))}
  }
  .top form{display:none}
  .figures{gap:var(--s5)}
  /* Tables become stacked records rather than something to scroll sideways. */
  .tbl thead{display:none}
  .tbl tr{display:block;border-top:1px solid var(--line-2);padding:var(--s3) 0}
  .tbl td{display:block;border:0;padding:2px 0;text-align:left!important}
  .tbl td:last-child{text-align:left;margin-top:var(--s2)}
}

/* ── THE RECORD ──────────────────────────────────────────────────────────
   HubSpot's three-column shape, which Luca already reads fluently: who they
   are on the left, what happened in the middle, what they are buying on the
   right. The differences are all subtractions — no collapsed card stack, no
   repeated header, and the next action promoted above all three columns
   instead of buried in a sidebar widget. */
.rec-head{display:flex;align-items:flex-start;gap:var(--s5);flex-wrap:wrap;
  padding-bottom:var(--s5);border-bottom:1px solid var(--line)}
.rec-head .who{min-width:0;flex:1}
.rec-head .nm{font-family:'Fraunces',serif;font-size:26px;line-height:1.15;
  letter-spacing:-.02em}
.rec-head .sm{font-size:13.5px;color:var(--ink-2);margin-top:5px}
.rec-head .acts{display:flex;gap:var(--s2);flex-wrap:wrap;flex:none}

/* The next action. One block, stated once, the most prominent thing on the page. */
.next{display:flex;align-items:center;gap:var(--s5);flex-wrap:wrap;
  background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r);
  padding:var(--s4) var(--s5);margin:var(--s5) 0}
.next.now{background:#FDF6F3;border-color:#EBD0C4}
.next .txt{min-width:0;flex:1}
.next .lab{font-size:11px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;
  color:var(--bronze)}
.next.now .lab{color:var(--urgent)}
.next .hd{font-family:'Fraunces',serif;font-size:17px;margin-top:3px}
.next .wy{font-size:13px;color:var(--ink-2);margin-top:3px}

/* The journey, as one line rather than fifteen boxes. */
.stage{display:flex;align-items:center;gap:var(--s3);font-size:13px;color:var(--ink-2);
  margin:var(--s5) 0}
.stage b{font-weight:500;color:var(--ink)}
.stage .dots{display:flex;gap:3px;flex:none}
.stage .dots i{width:14px;height:3px;border-radius:2px;background:var(--line);display:block}
.stage .dots i.done{background:var(--navy)}
.stage .dots i.at{background:var(--bronze)}

.rec{display:grid;grid-template-columns:302px minmax(0,1fr) 278px;gap:var(--s4);
  align-items:start;margin-top:var(--s4)}
@media(max-width:1240px){.rec{grid-template-columns:288px minmax(0,1fr);gap:var(--s4)}
  .rec .third{grid-column:1 / -1}
  .rec .third .side{display:inline-block;width:calc(50% - var(--s2));vertical-align:top}
  .rec .third .side + .side{margin-top:0;margin-left:var(--s3)}}
@media(max-width:820px){.rec{grid-template-columns:minmax(0,1fr)}}
.rec .side h3{font-size:11px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink-3);margin-bottom:var(--s3)}
.rec .side + .side{margin-top:var(--s6)}
.rec .side .facts{gap:9px 0}
.rec .side .facts .row{grid-template-columns:96px 1fr;gap:var(--s3)}
.rec .side .facts dt{font-size:12.5px;color:var(--ink-3)}
.rec .side .facts dd{font-size:13.5px}
/* The record header carries the summary and the actions; the name is already
   in the page title above it and does not need saying twice. */
.rec-head{padding-bottom:var(--s4)}
.logbox textarea{min-height:38px}
.logbox textarea:focus{min-height:88px}

/* The log box sits at the top of the timeline, as it does in HubSpot — the
   thing you came to do is the first thing you can do.

   WIDTH:100% IS NOT DECORATION. A <textarea> with no width falls back to its
   `cols` default — about twenty characters — so this rendered 185px wide in a
   528px column: a stamp-sized box to type a call note into, which is exactly
   the defect Luca reported on the notes tab, in a second place nobody had
   looked. The rule below catches it everywhere rather than here only. */
.logbox textarea{min-height:44px;transition:min-height .15s}
.logbox textarea:focus{min-height:96px}
.logbox .row{display:flex;gap:var(--s2);margin-top:var(--s2);align-items:center;
  flex-wrap:wrap}
.logbox select{width:auto;padding:6px 10px;font-size:13px}

/* The stat-tile vocabulary the migrated screens still use, mapped onto the
   inline-figure treatment so nothing renders as a box. */
.figure .k2{font-size:12.5px;color:var(--ink-2);display:block;margin-bottom:6px}
.figure .v{display:block}
.figures .figure{min-width:0}
.pad{padding:var(--s5)}
.panel > .pad:first-child{padding-bottom:var(--s4)}

/* ── STAGE BAR — the one HubSpot idea worth copying wholesale ────────────
   A clickable chevron strip across the top of a deal. Recognisable instantly,
   shows the whole journey, and moves the deal in one gesture. The differences:
   no colour until the current stage, and the strip is the control rather than
   a picture with a dropdown underneath it. */
.stagebar{display:flex;gap:2px;margin:var(--s5) 0;overflow-x:auto}
.stagebar button{flex:1;min-width:92px;border:0;background:var(--surface-2);
  color:var(--ink-2);padding:9px 10px;font-size:12px;font-weight:500;cursor:pointer;
  text-align:center;white-space:nowrap;border-top:2px solid transparent;
  transition:background .12s}
.stagebar button:first-child{border-radius:var(--r) 0 0 var(--r)}
.stagebar button:last-child{border-radius:0 var(--r) var(--r) 0}
.stagebar button:hover{background:var(--line-2);color:var(--ink)}
.stagebar button.done{background:#EEF2EF;color:var(--ink-2);border-top-color:var(--navy)}
.stagebar button.at{background:var(--navy);color:#fff;border-top-color:var(--bronze)}
.stagebar button.lost{background:var(--surface-2);color:var(--ink-3)}
.stagebar button.lost:hover{background:#FBEEE9;color:var(--urgent)}

/* The chosen property — the fact the whole deal turns on. */
.unit{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr);gap:var(--s6);
  padding:var(--s5);background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r)}
.unit .nm{font-family:'Fraunces',serif;font-size:19px;line-height:1.2}
.unit .ad{font-size:13px;color:var(--ink-2);margin-top:4px}
@media(max-width:900px){.unit{grid-template-columns:minmax(0,1fr);gap:var(--s5)}}

/* A measure — a labelled bar. Used only where the shape of a distribution is
   the point; a number would do for anything else. */
.meter{display:grid;grid-template-columns:132px 1fr 58px;gap:var(--s4);
  align-items:center;font-size:13.5px;padding:7px 0}
.meter .bar{height:6px;background:var(--line-2);border-radius:3px;overflow:hidden}
.meter .bar i{display:block;height:100%;background:var(--navy);border-radius:3px}
.meter .bar i.good{background:var(--good)}
.meter .bar i.warn{background:var(--sand)}
.meter .bar i.bad{background:var(--urgent)}
.meter .val{text-align:right;font-variant-numeric:tabular-nums;color:var(--ink-2)}

/* ── INDEX SCREENS — HubSpot's shape, which Luca reads fluently ──────────
   Saved views as tabs, then search + filter + sort, then a row of quick
   filters, then the table. The improvements are subtractions: no checkbox
   column until you need one, no horizontal scrollbar hiding two columns, and
   filters that show what they are set to rather than all reading the same. */
.qfilters{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap;
  padding-bottom:var(--s4);margin-bottom:var(--s2)}
.qf{position:relative}
.qf > summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;
  gap:5px;font-size:13px;padding:6px 11px;border:1px solid var(--line);
  border-radius:var(--r);background:var(--surface);color:var(--ink-2);white-space:nowrap}
.qf > summary::-webkit-details-marker{display:none}
.qf > summary::after{content:"";width:0;height:0;border-left:3.5px solid transparent;
  border-right:3.5px solid transparent;border-top:4px solid currentColor;opacity:.55}
.qf > summary:hover{border-color:var(--ink-3);color:var(--ink)}
.qf.set > summary{background:var(--navy);border-color:var(--navy);color:#fff}
.qf .menu{position:absolute;left:0;top:calc(100% + 5px);z-index:30;min-width:212px;
  max-height:340px;overflow-y:auto;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r);box-shadow:0 14px 36px -18px rgba(20,33,27,.4);padding:var(--s2)}
.qf .menu a{display:block;padding:7px 10px;border-radius:4px;font-size:13px;
  color:var(--ink);white-space:nowrap}
.qf .menu a:hover{background:var(--surface-2)}
.qf .menu a.on{background:var(--surface-2);font-weight:500}
.qf .menu .hd{font-size:11px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-3);padding:var(--s2) 10px 5px}

/* A filter that takes more than one value. The tick sits in its own column so
   the labels still line up when only some are ticked — without it the list
   ragged-edges and reads as a mistake. */
.qf .menu a.tick{display:flex;align-items:center;gap:8px}
.qf .menu a.tick .box{flex:none;width:15px;height:15px;border:1px solid var(--line);
  border-radius:3px;background:var(--surface);font-size:10px;line-height:13px;
  text-align:center;color:transparent}
.qf .menu a.tick.on .box{background:var(--navy);border-color:var(--navy);color:#fff}

/* ── SORTING BY THE COLUMN HEADING ───────────────────────────────────── */
/* The whole cell is the target, not the six characters of the word: a heading
   you have to hit precisely is a heading nobody presses twice. */
/* The cell gives up ALL its padding to the link inside it, so the link fills
   the cell and the label still lines up with the column under it. Written
   `tr > th` to outrank `.tblcard .tbl th:last-child`, which sets a padding of
   its own further down this file — without that the Score heading sat 24px
   left of its own numbers. */
.tbl tr > th.sortcol,.tblcard .tbl tr > th.sortcol{padding:0}
.tbl th.sortcol > a{display:block;padding:var(--s3) var(--s4);color:inherit;
  text-decoration:none;white-space:nowrap}
.tblcard .tbl tr > th.sortcol:first-child > a{padding-left:var(--s5)}
.tblcard .tbl tr > th.sortcol:last-child > a{padding-right:var(--s5)}
.tbl th.sortcol.r > a{text-align:right}
.tbl th.sortcol > a:hover{color:var(--ink);background:var(--line-2)}
.tbl th.sortcol.sorted > a{color:var(--ink)}
.tbl th.sortcol .arrow{margin-left:5px;font-size:8px;vertical-align:1px;
  color:var(--navy);letter-spacing:0}

.ix-head{display:flex;align-items:center;gap:var(--s2);margin-bottom:var(--s4);flex-wrap:wrap}
.ix-head .search{position:relative;flex:1;max-width:320px}
.ix-head .search input{width:100%;padding:8px 12px 8px 32px;border:1px solid var(--line);
  border-radius:var(--r);font-size:13.5px;background:var(--surface)}
.ix-head .search svg{position:absolute;left:11px;top:10px;opacity:.4}
.ix-foot{display:flex;align-items:center;gap:var(--s3);margin-top:var(--s5);
  padding-top:var(--s4);border-top:1px solid var(--line);font-size:13px;color:var(--ink-2)}

/* The initials disc HubSpot uses to make a row scannable by shape. */
.ini{width:28px;height:28px;border-radius:50%;background:var(--surface-2);
  border:1px solid var(--line);color:var(--ink-2);display:grid;place-items:center;
  font-size:11px;font-weight:600;flex:none}
.rowname{display:flex;align-items:center;gap:10px;min-width:0}

/* ── RECORD ACTION RAIL — HubSpot's icon row, with the rooms added ─────── */
.qa{display:grid;grid-template-columns:repeat(4,1fr);gap:2px;margin-top:var(--s4)}
.qa a,.qa button{display:flex;flex-direction:column;align-items:center;gap:5px;
  padding:10px 4px;border:0;background:none;border-radius:var(--r);cursor:pointer;
  font-size:11px;color:var(--ink-2);text-align:center;line-height:1.25}
.qa a:hover,.qa button:hover{background:var(--surface-2);color:var(--ink)}
.qa svg{width:17px;height:17px;stroke:currentColor;fill:none;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round}
.qa .go{color:var(--bronze)}

/* Activity grouped by month, as HubSpot does — it makes a long timeline
   skimmable without reading a single date. */
.tl-month{font-size:12px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-3);padding:var(--s5) 0 var(--s2);border-top:1px solid var(--line)}
.tl-month:first-child{border-top:0;padding-top:0}
a.pill{transition:background .12s,border-color .12s}
a.pill:hover{border-color:var(--ink-3);color:var(--ink)}
a.pill.now{background:var(--navy);border-color:var(--navy);color:#fff}

@media(max-width:820px){
  /* A three-part section header crammed into 375px is unreadable. Stack it. */
  .sec > header{flex-direction:column;align-items:flex-start;gap:4px}
  .sec > header .more{margin-left:0}
  .list > li{flex-direction:column;gap:var(--s2)}
  .list .end{width:100%;justify-content:flex-start}
  .rec-head{flex-direction:column}
  .next{flex-direction:column;align-items:flex-start}
  .qa{grid-template-columns:repeat(3,1fr)}
  .stagebar{gap:1px}
  .stagebar button{min-width:76px;font-size:11px;padding:8px 6px}
  .figure .v{font-size:25px}
}

/* ═══ RICHNESS — put back what the strip-down took too far ════════════════
   The audit was right that the old screens were cluttered. It went one step
   past calm into bare: white text on cream with no containment and no colour
   anywhere. These are the things that make a premium interface feel designed
   rather than unfinished — depth, a considered accent, and status that carries
   meaning at a glance. None of it adds information. */

/* Status, with actual meaning. Six states, one shape, and never more than one
   coloured thing per row. */
.badge{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;font-weight:600;
  padding:3px 10px;border-radius:99px;letter-spacing:.01em;white-space:nowrap;
  background:var(--surface-2);color:var(--ink-2);border:1px solid var(--line)}
.badge::before{content:"";width:5px;height:5px;border-radius:50%;background:currentColor;
  opacity:.85}
.badge.new{background:#FBEEE9;border-color:#F0D6C9;color:#A8442F}
.badge.working{background:#FDF6E9;border-color:#EFE0C2;color:#8A6520}
.badge.live{background:#EDF4F0;border-color:#CFE3D7;color:#2F6B4F}
.badge.client{background:#16362A;border-color:#16362A;color:#fff}
.badge.cold{background:var(--surface-2);border-color:var(--line);color:var(--ink-3)}
.badge.plain::before{display:none}

/* The avatar disc, tinted from the name so a record is recognisable by colour
   before it is read. */
.ini{width:30px;height:30px;border-radius:50%;display:grid;place-items:center;
  font-size:11.5px;font-weight:600;flex:none;letter-spacing:.02em;
  background:var(--surface-3);color:var(--navy);border:1px solid var(--line)}
.ini.t0{background:#E9F0EB;color:#2F6B4F;border-color:#D3E3D8}
.ini.t1{background:#F6EBE3;color:#A8562F;border-color:#EDD8C7}
.ini.t2{background:#EAEEF4;color:#39527A;border-color:#D5DEEA}
.ini.t3{background:#F3EDF6;color:#5F4278;border-color:#E4D8EB}
.ini.t4{background:#FBF0DC;color:#8A6520;border-color:#EFE0C2}
.ini.lg{width:44px;height:44px;font-size:14px}

/* The record's left rail becomes a proper card, with the action grid inset. */
.rec .side{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--lift);padding:var(--s5)}
.rec .side + .side{margin-top:var(--s4)}
.rec .side h3{font-size:11px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink-3);margin-bottom:var(--s4);display:flex;align-items:center;gap:var(--s2)}
.rec .side h3::after{content:"";flex:1;height:1px;background:var(--line-2)}
.rec .side h3 a{flex:none;font-size:12px;text-transform:none;letter-spacing:0;
  font-weight:500;color:var(--bronze)}

/* Action tiles — a grid with real surfaces, not floating glyphs. */
.qa{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-top:var(--s4);
  padding-top:var(--s4);border-top:1px solid var(--line-2)}
.qa a,.qa button{display:flex;flex-direction:column;align-items:center;gap:6px;
  padding:11px 4px;border:1px solid transparent;background:var(--surface-2);
  border-radius:var(--r-sm);cursor:pointer;font-size:10.5px;color:var(--ink-2);
  text-align:center;line-height:1.2;transition:background .12s,color .12s,border-color .12s}
.qa a:hover,.qa button:hover{background:var(--surface);border-color:var(--line);
  color:var(--ink);box-shadow:var(--lift)}
.qa svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}
.qa .go{background:#FBF4EC;color:var(--bronze)}
.qa .go:hover{background:#fff;border-color:#EBD8C4}
.qa form{display:contents}

/* The journey, with the current step named and the passed ones filled. */
.stage{display:flex;align-items:center;gap:var(--s4);font-size:13.5px;color:var(--ink-2);
  margin:var(--s5) 0;padding:var(--s3) var(--s5);background:var(--surface);
  border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--lift)}
.stage b{font-weight:600;color:var(--ink)}
.stage .dots{display:flex;gap:3px;flex:none}
.stage .dots i{width:16px;height:4px;border-radius:2px;background:var(--line);display:block;
  transition:background .2s}
.stage .dots i.done{background:var(--navy)}
.stage .dots i.at{background:var(--bronze);box-shadow:0 0 0 3px rgba(180,101,60,.14)}
.stage .pc{margin-left:auto;flex:none;font-size:12.5px;color:var(--ink-3);
  font-variant-numeric:tabular-nums}

/* The next action — the one place a gradient earns its keep. */
.next{display:flex;align-items:center;gap:var(--s5);flex-wrap:wrap;
  background:linear-gradient(101deg,#FFFDFA 0%,#FAF2E9 100%);
  border:1px solid #EADBC8;border-radius:var(--r);
  padding:var(--s5);margin:0 0 var(--s5);box-shadow:var(--lift)}
.next.now{background:linear-gradient(101deg,#FFFAF8 0%,#FBEFE9 100%);border-color:#EBD0C4}
.next .hd{font-family:'Fraunces',serif;font-size:19px;margin-top:4px;letter-spacing:-.01em}
.next .wy{font-size:13.5px;color:var(--ink-2);margin-top:5px;line-height:1.5}

/* Figures get a hairline separator, which reads as deliberate rather than
   as three numbers that happen to be near each other. */
.figures{display:flex;gap:0;flex-wrap:wrap;align-items:stretch;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--lift);overflow:hidden}
.figures > *{padding:var(--s4) var(--s6);border-left:1px solid var(--line-2);flex:1;
  min-width:150px}
.figures > *:first-child{border-left:0}
.figure .v{font-family:'Fraunces',serif;font-size:27px;line-height:1.05;display:block;
  font-variant-numeric:tabular-nums;color:var(--navy);letter-spacing:-.02em}
.figure .k{font-size:12.5px;color:var(--ink-2);margin-top:7px;display:block;line-height:1.35}
a.figure{transition:background .12s}
a.figure:hover{background:var(--surface-2)}

/* Tables sit on a surface too. */
.tblcard{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--lift);overflow:hidden}
.tblcard .tbl th{padding:var(--s3) var(--s4);background:var(--surface-2);
  border-bottom:1px solid var(--line)}
.tblcard .tbl td{padding:var(--s3) var(--s4)}
.tblcard .tbl td:first-child,.tblcard .tbl th:first-child{padding-left:var(--s5)}
.tblcard .tbl td:last-child,.tblcard .tbl th:last-child{padding-right:var(--s5)}
.tblcard .tbl tr:hover td{background:var(--surface-2)}

/* Empty states get a shape rather than a sentence floating in space. */
.none{padding:var(--s6) var(--s5);color:var(--ink-2);font-size:13.5px;max-width:none;
  background:var(--surface-2);border:1px dashed var(--line);border-radius:var(--r);
  text-align:center}
.none b{display:block;color:var(--ink);font-family:'Fraunces',serif;font-weight:500;
  font-size:16px;margin-bottom:6px}
.none .btns{margin-top:var(--s4);justify-content:center}

/* Section headings get a small accent mark — cheap, and it makes a long page
   navigable by eye. */
.sec > header h2{position:relative;padding-left:14px}
.sec > header h2::before{content:"";position:absolute;left:0;top:.5em;width:5px;height:5px;
  border-radius:50%;background:var(--sand)}
.sec > header h2.urgent::before{background:var(--urgent)}

.dcard{box-shadow:var(--lift)}
.dcard:hover{border-color:var(--sand);box-shadow:var(--lift-2)}
.top{background:rgba(246,241,232,.9)}

/* The activity feed is content and belongs on a surface like everything else. */
.feed{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--lift);padding:var(--s3) var(--s5) var(--s5)}
.feed .tabs{margin:0 calc(var(--s5) * -1) var(--s4);padding:0 var(--s5)}
.feed .tl-month:first-child{padding-top:var(--s2)}
.logbox{margin-bottom:var(--s4)}
.logbox textarea{font-size:14px}

/* Board columns need a surface, or the cards float and an empty stage looks
   like a rendering fault rather than an empty stage. */
.board{gap:var(--s2)}
.col{flex:0 0 226px;background:var(--surface-2);border:1px solid var(--line);
  border-radius:var(--r);padding:var(--s3);min-height:120px}
.col > h3{padding:2px 4px var(--s3);border-bottom:1px solid var(--line);
  margin-bottom:var(--s3);font-size:11.5px;letter-spacing:.03em;color:var(--ink-2)}
.col > h3 .n{background:var(--surface);border:1px solid var(--line);border-radius:99px;
  padding:1px 7px;font-size:11px;color:var(--ink-2)}
.col .items:empty::after{content:"—";display:block;text-align:center;color:var(--ink-3);
  font-size:13px;padding:var(--s4) 0}
.col.over{background:#F0E7D6;border-color:var(--sand)}

/* One figure alone should not stretch across the whole page. */
.figures > *{flex:0 1 auto;min-width:160px}
.figures{display:flex}

/* Consistency: a figure always reads value first, then what it is, then any
   qualifier. The migrated screens had the label above the number, which meant
   two different reading orders in one system. Fixed by ordering rather than by
   rewriting every template. */
.figure{display:flex;flex-direction:column}
.figure .v{order:1}
.figure .k2{order:2;font-size:12.5px;color:var(--ink-2);margin:7px 0 0;line-height:1.35}
.figure .k{order:3;font-size:12px;color:var(--ink-3);margin-top:3px}

/* The bulk bar. Hidden until something is picked — the default state of a list
   should be a list. */
.bulkbar{display:none;align-items:center;gap:var(--s2);padding:var(--s3) var(--s4);
  margin-bottom:var(--s3);background:var(--navy);border-radius:var(--r);color:#fff;
  flex-wrap:wrap}
.bulkbar.on{display:flex}
.bulkbar .n{font-size:13px;font-weight:500;margin-right:var(--s2)}
.bulkbar select,.bulkbar input{width:auto;padding:5px 9px;font-size:13px;
  border:1px solid rgba(255,255,255,.22);border-radius:var(--r-sm);
  background:rgba(255,255,255,.1);color:#fff}
.bulkbar select option{color:var(--ink)}
.bulkbar .btn{background:#fff;border-color:#fff;color:var(--navy)}
.tbl input[type=checkbox]{width:15px;height:15px;accent-color:var(--navy);cursor:pointer}

/* An inline editor should look like the value it replaces until you touch it. */
.inline-status select{width:auto;max-width:150px;padding:3px 22px 3px 8px;font-size:12.5px;
  border:1px solid transparent;border-radius:99px;background:var(--surface-2);
  color:var(--ink-2);cursor:pointer;appearance:none;
  background-image:linear-gradient(45deg,transparent 50%,var(--ink-3) 50%),
                   linear-gradient(135deg,var(--ink-3) 50%,transparent 50%);
  background-position:calc(100% - 11px) 52%,calc(100% - 7px) 52%;
  background-size:4px 4px,4px 4px;background-repeat:no-repeat}
.inline-status select:hover{border-color:var(--line);background-color:var(--surface)}
.inline-status select:focus{border-color:var(--navy);background-color:var(--surface)}
.tbl td .sub.urgent{color:var(--urgent);font-weight:500}

/* The one choice at the top of the rooms page. */
.roompick{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--lift);padding:var(--s4) var(--s5);margin-bottom:var(--s5)}
.roompick label{font-size:11px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink-3)}
.roompick select{width:auto;min-width:330px;padding:8px 12px;font-size:14px;
  border:1px solid var(--line);border-radius:var(--r);background:var(--surface)}
a.card{display:block;transition:border-color .12s,box-shadow .12s}
a.card:hover{border-color:var(--sand);box-shadow:var(--lift-2)}

/* ── PROPERTY CARDS — the website's own shape ────────────────────────────
   A consultant on a call needs the same thing a client sees: a photograph of
   the building, what stage it is at, and the price. Matching the site exactly
   means the two can never describe a scheme differently. */
.pgrid{display:grid;gap:var(--s4);grid-template-columns:repeat(auto-fill,minmax(268px,1fr))}
.pcard{display:block;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r);overflow:hidden;box-shadow:var(--lift);
  transition:box-shadow .16s,border-color .16s,transform .16s}
.pcard:hover{box-shadow:var(--lift-2);border-color:var(--sand);transform:translateY(-2px)}
.pcard .shot{position:relative;aspect-ratio:4/3;background:var(--surface-3);overflow:hidden}
.pcard .shot img{width:100%;height:100%;object-fit:cover;display:block}
.pcard .shot .none-img{display:grid;place-items:center;height:100%;color:var(--ink-3);
  font-size:12.5px;text-align:center;padding:var(--s4)}
.pcard .status{position:absolute;left:10px;top:10px;background:rgba(22,54,42,.9);
  color:#fff;font-size:10.5px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  padding:5px 10px;border-radius:99px;backdrop-filter:blur(4px)}
.pcard .count{position:absolute;right:10px;bottom:10px;background:rgba(255,255,255,.94);
  color:var(--ink);font-size:11px;font-weight:600;padding:4px 9px;border-radius:99px}
.pcard .body{padding:var(--s4)}
.pcard .loc{font-size:10.5px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;
  color:var(--bronze);display:block}
.pcard .nm{font-family:'Fraunces',serif;font-size:19px;margin-top:5px;line-height:1.15;
  letter-spacing:-.01em}
.pcard .hl{font-size:12.5px;color:var(--ink-2);margin-top:7px;line-height:1.45}
.pcard .price{margin-top:var(--s3);padding-top:var(--s3);border-top:1px solid var(--line-2);
  display:flex;align-items:baseline;gap:var(--s2)}
.pcard .price .lab{font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-3);font-weight:600}
.pcard .price .val{font-family:'Fraunces',serif;font-size:15px;color:var(--navy);
  font-variant-numeric:tabular-nums;margin-left:auto}
.pcard.hmo{border-color:#DCCBB4;background:linear-gradient(170deg,#FFFDF9,#FAF3E9)}

/* The gallery on a development. */
.gallery{display:grid;gap:var(--s2);grid-template-columns:repeat(auto-fill,minmax(150px,1fr))}
.gallery a{display:block;aspect-ratio:4/3;border-radius:var(--r-sm);overflow:hidden;
  border:1px solid var(--line);background:var(--surface-3)}
.gallery img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .2s}
.gallery a:hover img{transform:scale(1.04)}
.shot-hero{border-radius:var(--r);overflow:hidden;border:1px solid var(--line);
  box-shadow:var(--lift);margin-bottom:var(--s5);max-height:340px}
.shot-hero img{width:100%;height:100%;object-fit:cover;display:block}

/* ── the invoice document ──────────────────────────────────────────────────
   A faithful copy of the invoice already issued to clients, so a second one
   from the CRM is indistinguishable from the first. A4 on screen and in print. */
.inv-sheet{width:210mm;max-width:100%;min-height:297mm;margin:0 auto;background:#FBF5EB;
  box-shadow:0 30px 70px -40px rgba(20,45,35,.55);display:flex;flex-direction:column;
  color:#14211B;line-height:1.6}
.inv-top{background:#16362A;color:#E7EEE9;padding:26px 34px 24px;display:flex;
  justify-content:space-between;align-items:flex-start;gap:30px}
.inv-brand{display:flex;align-items:center;gap:11px;font-family:Fraunces,serif;font-size:22px;
  font-weight:600;color:#fff;letter-spacing:-.02em}
.inv-brand .mark{width:30px;height:30px;flex:none}
.inv-from{margin-top:11px;font-size:12.5px;color:#BCCCC1;line-height:1.7}
.inv-from .nm{color:#fff;font-weight:600}
.inv-doc{text-align:right;flex:none}
.inv-doc .ttl{font-family:Fraunces,serif;font-size:31px;color:#fff;letter-spacing:.02em}
.inv-doc dl{margin-top:12px;display:grid;grid-template-columns:auto auto;gap:5px 16px;
  font-size:12.5px;align-items:baseline}
.inv-doc dt{color:#9FB2A6;text-align:left;white-space:nowrap}
.inv-doc dd{color:#fff;font-weight:600;text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
.inv-body{padding:22px 34px 0;flex:1}
.inv-cust{padding-bottom:18px;border-bottom:1px solid #EADFCD}
.inv-cust .lbl{font-size:11px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:#55635A}
.inv-cust .who{margin-top:8px;font-size:19px;font-weight:600;color:#16362A}
table.inv-items{width:100%;border-collapse:collapse;margin-top:20px}
table.inv-items thead th{font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;color:#55635A;
  font-weight:600;text-align:right;padding:0 0 9px;border-bottom:1.5px solid #16362A;background:none}
table.inv-items thead th:first-child{text-align:left}
table.inv-items tbody td{padding:11px 0;border-bottom:1px solid #EADFCD;text-align:right;
  font-variant-numeric:tabular-nums;font-size:15px}
table.inv-items tbody td:first-child{text-align:left;font-weight:600}
table.inv-items .sub{display:block;margin-top:4px;font-size:12.5px;color:#55635A;font-weight:400}
.inv-totals{display:flex;justify-content:flex-end;margin-top:14px}
.inv-totals table{width:52%;border-collapse:collapse}
.inv-totals td{padding:4px 0;font-size:14px;text-align:right;font-variant-numeric:tabular-nums}
.inv-totals td:first-child{text-align:left;color:#55635A}
.inv-totals tr.grand td{padding-top:13px;border-top:1.5px solid #16362A;font-family:Fraunces,serif;
  font-size:23px;color:#16362A;font-weight:600}
.inv-totals tr.grand td:first-child{font-size:12px;font-family:Inter,sans-serif;letter-spacing:.1em;
  text-transform:uppercase;color:#14211B;font-weight:600;vertical-align:middle}
.inv-due{margin-top:12px;display:flex;justify-content:flex-end;align-items:baseline;gap:10px;
  font-size:14px;color:#55635A}
.inv-due b{color:#14211B;font-weight:600;font-variant-numeric:tabular-nums}
.inv-bank{margin-top:15px;border:1px solid #EADFCD;border-radius:8px;padding:14px 20px;background:#fff}
.inv-bank h4{font-size:11px;font-family:Inter,sans-serif;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:#55635A;margin-bottom:11px}
.inv-bank .rows{display:grid;grid-template-columns:1fr 1fr;gap:4px 34px}
.inv-bank .rows .wide{grid-column:1 / -1}
.inv-bank .kv{display:flex;justify-content:space-between;gap:14px;padding:3px 0;font-size:13.5px;
  border-bottom:1px dotted #EADFCD}
.inv-bank .kv span{color:#55635A}
.inv-bank .kv b{color:#14211B;font-weight:600;font-variant-numeric:tabular-nums}
.inv-cut{margin-top:14px;border-top:1.5px dashed #EADFCD;position:relative}
.inv-cut span{position:absolute;top:-9px;left:50%;transform:translateX(-50%);background:#FBF5EB;
  padding:0 12px;font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:#B4653C;font-weight:600}
.inv-advice{margin-top:12px;display:grid;grid-template-columns:1fr 1fr;gap:30px;align-items:start}
.inv-advice h4{font-family:Fraunces,serif;font-size:17px;color:#16362A}
.inv-advice .to{margin-top:10px;font-size:12.5px;color:#55635A;line-height:1.7}
.inv-advice .adv-t{width:100%;border-collapse:collapse}
.inv-advice .adv-t td{padding:5px 0;font-size:13.5px;border-bottom:1px solid #EADFCD;
  font-variant-numeric:tabular-nums;text-align:right;color:#14211B;font-weight:600}
.inv-advice .adv-t td:first-child{text-align:left;color:#55635A;font-weight:400}
.inv-advice .adv-t tr:last-child td{border-bottom:0}
.inv-advice .adv-t .encl td{padding-top:11px}
.inv-foot{margin-top:16px;padding:12px 34px 15px;border-top:1px solid #EADFCD;font-size:11px;
  color:#55635A;line-height:1.7}
.inv-foot .co{color:#14211B;font-weight:600}
@media print{
  @page{size:A4;margin:0}
  body{background:#fff}
  .rail,.topbar,.crumb,#invoice-actions,.pagehead,footer{display:none !important}
  .inv-sheet{width:auto;min-height:0;margin:0;box-shadow:none}
  main,.page,.wrap{padding:0 !important;margin:0 !important;max-width:none !important}
}

/* The must-have block at the top of anything that produces a document. */
.must{border:1px solid var(--accent-line, var(--line));border-radius:var(--r);
  padding:var(--s4);margin-bottom:var(--s5);background:var(--surface-2, #fff)}
.must-h{font-size:11px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--bronze, #B4653C);margin-bottom:var(--s4)}
.req{font-size:10px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  color:var(--bronze, #B4653C);margin-left:6px}

/* ── the second-meeting brief ──────────────────────────────────────────────
   Branded, printable, internal. Reads like a one-page note, not a dashboard. */
.brief{max-width:900px;margin:0 auto;background:#FBF5EB;border:1px solid #EADFCD;
  border-radius:10px;overflow:hidden;color:#14211B}
.brief-top{background:#16362A;color:#E7EEE9;padding:20px 30px;display:flex;
  justify-content:space-between;align-items:flex-start;gap:24px}
.brief-brand{display:flex;align-items:center;gap:10px;font-family:Fraunces,serif;font-size:20px;
  font-weight:600;color:#fff;letter-spacing:-.02em}
.brief-brand span{font-family:Inter,sans-serif;font-size:10px;font-weight:600;letter-spacing:.16em;
  text-transform:uppercase;color:#E4BB94;margin-left:4px}
.brief-meta{text-align:right;font-size:12.5px;color:#BCCCC1;line-height:1.7}
.brief-meta b{color:#fff;font-weight:600}
.brief-body{padding:24px 30px 6px}
.brief-facts{display:flex;flex-wrap:wrap;gap:8px 30px;padding-bottom:16px;
  border-bottom:1px solid #EADFCD}
.brief-facts .k{display:block;font-size:10px;font-weight:600;letter-spacing:.12em;
  text-transform:uppercase;color:#55635A}
.brief-facts b{font-size:15px;font-weight:600;color:#16362A;font-variant-numeric:tabular-nums}
.brief-h{font-family:Fraunces,serif;font-size:19px;font-weight:500;color:#16362A;
  margin:24px 0 12px;letter-spacing:-.01em}
.brief-list{list-style:none;counter-reset:b;margin:0;padding:0}
.brief-list li{counter-increment:b;position:relative;padding:12px 0 12px 42px;
  border-bottom:1px solid #EADFCD}
.brief-list li:last-child{border-bottom:0}
.brief-list li::before{content:counter(b);position:absolute;left:0;top:12px;width:26px;height:26px;
  border-radius:50%;background:#16362A;color:#E4BB94;font-size:12px;font-weight:600;
  display:flex;align-items:center;justify-content:center}
.brief-list.closes li::before{background:#B4653C;color:#fff}
.brief-list .t{font-size:15px;font-weight:600;color:#14211B;line-height:1.35}
.brief-list .d{margin-top:4px;font-size:13.5px;color:#39463E;line-height:1.6}
.brief-list .e{margin-top:5px;font-size:11.5px;color:#7A867E;font-style:italic}
.brief-none{font-size:13.5px;color:#55635A;padding:12px 0}
.brief-hist{list-style:none;margin:0;padding:0;font-size:13px;color:#39463E}
.brief-hist li{padding:6px 0;border-bottom:1px dotted #EADFCD}
.brief-hist .e{display:block;font-size:11.5px;color:#7A867E;font-style:italic;margin-top:2px}
.brief-foot{margin-top:18px;padding:12px 30px 16px;border-top:1px solid #EADFCD;
  font-size:11px;color:#55635A}
@media print{
  #brief-actions{display:none !important}
  .brief{border:0;border-radius:0;max-width:none}
}

/* ── classes the templates used that the stylesheet never defined ──────────
   Found by walking every page and diffing the classes in the HTML against the
   selectors here. Until now a figure marked `alert` — "Tool server: down",
   "AML platform: down" — rendered identically to a healthy one, which is the
   one case where the colour is the whole message. */
.figure.good .v{color:var(--good)}
.figure.alert .v{color:var(--urgent)}
.figure.alert .k2::after{content:" — needs attention";color:var(--urgent);
  font-size:11px;letter-spacing:.02em}

/* A button meant to fill its column. Without this, "Set the property" and
   "Set it" sat half-width in a panel built for them to span it. */
.btn-block{display:flex;width:100%;justify-content:center}

/* ── phone ────────────────────────────────────────────────────────────────
   Two problems found by measuring rather than looking: the four figures on a
   screen stacked into 447px — the entire first screen of a phone spent on
   numbers before a single thing you can act on — and rows built as
   avatar / body / buttons pushed 46px past the right edge. */
@media(max-width:560px){
  /* Two up. Four numbers still fit above the fold with room for the work. */
  .figures{display:grid;grid-template-columns:1fr 1fr;gap:0}
  .figures .figure{padding:var(--s3) var(--s4)}
  .figure .v{font-size:22px}
  .figure .k,.figure .k2{font-size:11.5px}

  /* Any row of avatar + body + actions wraps instead of clipping. */
  .panel .pad > div[style*="display:flex"]{flex-wrap:wrap}
  .panel .pad .grow{min-width:100%}
  .panel .pad .end{width:100%;text-align:left!important;
    display:flex;align-items:center;gap:var(--s2);margin-top:var(--s2)}
  .panel .pad .end .btn{flex:1}
}

/* ── THE SALES EXPERT, REACHABLE FROM ANYWHERE ────────────────────────────
   A launcher in the corner and a panel that slides over the page. Deliberately
   not a modal: the record stays visible behind it, because the whole point is
   reading the advice against the client you are looking at. */
.xp-launch{position:fixed;right:22px;bottom:22px;z-index:60;
  background:var(--navy);color:#fff;border:0;border-radius:999px;
  padding:13px 22px;font-size:13.5px;font-weight:600;letter-spacing:.01em;
  font-family:inherit;cursor:pointer;
  box-shadow:0 6px 24px rgba(11,42,28,.28);transition:transform .14s ease,
  box-shadow .14s ease}
.xp-launch:hover{transform:translateY(-1px);box-shadow:0 10px 30px rgba(11,42,28,.34)}
.xp-launch:focus-visible{outline:none;box-shadow:0 0 0 3px var(--sand)}

.xp{position:fixed;right:22px;bottom:82px;z-index:61;width:min(440px,calc(100vw - 44px));
  max-height:min(72vh,760px);display:flex;flex-direction:column;
  background:var(--surface);border:1px solid var(--line);border-radius:14px;
  box-shadow:0 18px 60px rgba(11,42,28,.22);overflow:hidden}
.xp-head{display:flex;align-items:center;justify-content:space-between;
  padding:13px 16px;border-bottom:1px solid var(--line);background:var(--surface-2)}
.xp-x{background:none;border:0;font-size:20px;line-height:1;cursor:pointer;
  color:var(--ink-2);padding:0 4px;font-family:inherit}
.xp-x:hover{color:var(--ink)}
.xp-ask{display:flex;gap:8px;padding:13px 16px;border-bottom:1px solid var(--line)}
.xp-ask input{flex:1;min-width:0}
.xp-chips{display:flex;flex-wrap:wrap;gap:6px;padding:11px 16px;
  border-bottom:1px solid var(--line);background:var(--surface-2)}
.xp-chips .btn{font-size:11.5px;padding:5px 9px}
.xp-out{padding:14px 16px;overflow-y:auto;font-size:13.5px;line-height:1.5}
.xp-out h4{margin:0 0 4px;font-size:15px}
.xp-out h5{margin:14px 0 5px;font-size:12px;text-transform:uppercase;
  letter-spacing:.07em;color:var(--ink-2)}
.xp-out ul{margin:0 0 0 17px;padding:0}
.xp-out li{margin-bottom:5px}
.xp-body{white-space:pre-wrap;margin:0 0 8px}
.xp-scope{font-size:11.5px;color:var(--ink-2);margin:0 0 10px}
.xp-note{font-size:11.5px;color:var(--ink-2);margin:6px 0 0;font-style:italic}

@media(max-width:560px){
  .xp{right:10px;left:10px;bottom:74px;width:auto;max-height:68vh}
  .xp-launch{right:14px;bottom:14px;padding:11px 18px}
}

/* ── TABLES THAT DO NOT SHRED THEIR OWN CONTENT ───────────────────────────
   Measured on Payments at 1440px: eight columns sharing 657px, every cell
   eighty-odd pixels wide, every row six lines tall. "BRG-PAY-2026-0001" was
   broken over three lines, "Chidinma Okafor (DEMO)" over three, and the Open
   button was cut off the right-hand edge entirely.

   Nothing here makes a column wider by guesswork. It stops the things that
   should never wrap from wrapping, which lets the table claim an honest width —
   and .scroll then gives it a scrollbar rather than hiding the end. */

/* A reference, a date, a rate, a sum of money and a button are all single
   objects. Breaking them across lines does not save space, it just makes them
   unreadable and makes the row six times taller. */
.tbl td.num, .tbl td.r, .tbl th.r,
.tbl td .ref, .tbl td .stamp, .tbl td time,
.tbl td:last-child { white-space: nowrap; }

/* The name column is the one that must not stack a word at a time.
   The width goes on the CELL, never on .rowname — that is a flex row holding
   the avatar beside the name, and setting inline-block on it pinned the name to
   168px inside a 294px cell and wrapped it while a third of the cell sat empty.
   A reminder that a layout fix has to be measured, not assumed. */
.tbl td:has(.rowname), .tbl td:has(> .name) { min-width: 210px; }
.tbl td:has(> .chk), .tbl th:has(> .chk) { width: 34px; min-width: 34px; }

/* An email or a source is one thing, not a paragraph. Let it take the width it
   has and finish with an ellipsis rather than stacking into a ribbon. */
.tbl td.sub { max-width: 230px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.tbl td.sub.wrap { white-space: normal; }

/* Prose inside a cell — a reason, a note, a next action — needs a readable
   measure. Below about 22 characters a line it stops being a sentence. */
.tbl td .sub, .tbl td .why, .tbl td .wy { min-width: 0; }
.tbl td.wide, .tbl td.prose { min-width: 220px; }

/* A cell holding buttons keeps them on one line and away from the text. */
.tbl td .btn { white-space: nowrap; }

/* Any table that genuinely needs more width scrolls, rather than clipping the
   last column. The wrapper already exists; this makes it behave on a trackpad
   and stops the shadowless edge looking like the table simply ends. */
.scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.scroll > .tbl { min-width: max-content; }

/* ── CONTAINMENT ─────────────────────────────────────────────────────────
   Measured, not guessed. Every rule below fixes a box something was sticking
   out of at a 1440px window, found by walking all 65 pages and comparing
   scrollWidth with clientWidth.

   A <select> is the worst offender in the building. It sizes itself to its
   longest <option>, ignores its container, and will not shrink: the property
   picker on a deal carries "One Trafalgar Square, Manchester — Unit 402 — 2
   bed — £285,000", which came out 437px wide inside a 228px column and pushed
   the whole record sideways — .side, then .third, then .rec, then the page
   itself grew a horizontal scrollbar. Nothing on the page looked broken; the
   right-hand column was simply off the edge of the screen. */
select{max-width:100%;min-width:0}
.rec select,.cf select,.side select{width:100%}
/* The rooms picker asked for a 330px minimum and sat in a 278px column. */
.roompick select{min-width:min(330px,100%)}

/* Grid and flex children default to min-width:auto, which means "never shrink
   below my content". On .rec that let a wide child widen a fixed column. */
.rec > *,.rec .third,.rec .side{min-width:0}

/* A section heading is a flex row: label, then a rule, then sometimes a status
   badge. The badge is nowrap ("Partially qualified" = 183px), so on a 252px
   heading it pushed 103px past the edge. Let the row wrap instead. */
.rec .side h3{flex-wrap:wrap;row-gap:4px}
.rec .side h3 > span{min-width:0}
.rec .side h3::after{min-width:12px}

/* The next-move card: number, text, buttons. At 200px the buttons alone were
   187px. It already wraps below 820px — but the card is 248px inside a 1440px
   window, so the viewport query never fired. Wrap on content, not on window. */
.rung-h{flex-wrap:wrap;row-gap:var(--s2)}
.rung-h .acts{flex-wrap:wrap}

/* A permissions list is not a name: ellipsising "tasks:all, invoices:all,
   contacts:all, deals:all, reports:all" at 240px of 889px hides the answer to
   the only question the column is there to answer. Let this one wrap. */
.tbl td.sub.perms{white-space:normal;max-width:320px;overflow:visible;
  text-overflow:clip;line-height:1.5}

/* Permission grants, one chip each — see the note in admin.html. */
.tbl td.perms{white-space:normal;max-width:none}
.grants{display:flex;flex-wrap:wrap;gap:4px}
.grants b{font-weight:500;font-size:11px;letter-spacing:.01em;color:var(--ink-2);
  background:var(--surface-2);border:1px solid var(--line-2);border-radius:4px;
  padding:2px 6px;font-variant-numeric:tabular-nums}

/* A long email in the record's identity block is one unbreakable word. In a
   252px rail "chidinma.okafor.demo@blackridgeglobal.co.uk" pushed 27px past
   the card edge. Truncate the address, keep the whole of it on hover and in
   the link itself. */
.rec .side .rowname{min-width:0}
.rec .side .rowname a.sub{display:block;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;max-width:100%}

/* ── CONTAINMENT, PHONE AND LAPTOP ───────────────────────────────────────
   Measured at a real 375px viewport, with the page navigated rather than
   swapped in — replacing documentElement drops the viewport meta, so the first
   set of "mobile" numbers were quietly taken at 1030px and were worthless.

   The stage bar is fifteen steps of nowrap label in 92px buttons, so
   "Instructed with solicitors" needed 135px and lost its last two words. The
   bar already scrolls; the labels just were not allowed to wrap. */
.stagebar{align-items:stretch}
.stagebar button{white-space:normal;line-height:1.25;hyphens:auto}

/* The journey summary is a flex row of dots and text. On a phone it pushed the
   page to 486px on a 375px screen — a sideways scroll on the record. */
@media(max-width:560px){
  .stage{flex-wrap:wrap;row-gap:var(--s2)}
  .stage .dots{order:3}
}

/* A timeline note carries whatever was pasted into it: a room link, an ics
   URL, a reference with no spaces. pre-wrap keeps the newlines, which is
   right, but it will not break inside a long token. */
.what p,.feed p,.what pre{overflow-wrap:anywhere}

/* One setting: label and help on the left, the control on the right. */
.setting-row{display:grid;grid-template-columns:minmax(0,1fr) min(var(--ctl,300px),55%);
  gap:var(--s5);align-items:start;padding:var(--s4) 0;
  border-top:1px solid var(--line-2)}
.setting-row > *{min-width:0}
/* A SETTING YOU WRITE PROSE INTO GETS THE ROW, NOT THE CONTROL COLUMN.
   The grid caps every control at 300px, which is right for a percentage or a
   fee and wrong for an address: the company address rendered 300px wide in a
   770px row. Third instance of the same defect — a writing surface that does
   not fill what it sits in. The label goes above and the textarea takes the
   width, which is what every other composer in here does. */
.setting-row:has(textarea){grid-template-columns:minmax(0,1fr)}
.setting-row:has(textarea) textarea{min-height:88px}
@media(max-width:560px){
  .setting-row{grid-template-columns:minmax(0,1fr);gap:var(--s2)}
}

/* One room on the record: its name, and whether it has been sent. Baseline-
   aligned on a wide rail, wrapped on a narrow one — at 114px the label and the
   badge together needed 131px and pushed out of the card. */
.roomline{display:flex;align-items:baseline;gap:var(--s2);flex-wrap:wrap}
.roomline > a{min-width:0;overflow-wrap:anywhere}
.roomline > span{margin-left:auto}
@media(max-width:560px){.roomline > span{margin-left:0}}

/* Permission chips wrap, but a table cell will still grow to fit them all on
   one line, so the card scrolls instead of the page. */
.tbl td.perms .grants{max-width:min(46ch,100%)}

/* ── OWED TO THEM — tasks you can act on where you are ───────────────────
   A tick on the left, the task, a "+1d" on the right. Both are real forms
   posting to routes that already existed; the record simply never offered
   them, so ticking a task off meant going to /tasks and finding it again. */
.tasklets{list-style:none;margin:0 0 var(--s4);padding:0}
.tasklets li{display:flex;align-items:flex-start;gap:var(--s2);
  padding:var(--s2) 0;border-top:1px solid var(--line-2)}
.tasklets li:first-child{border-top:0}
.tasklets .grow{flex:1;min-width:0}
.tasklets b{display:block;font-weight:500;font-size:13px;line-height:1.35;
  overflow-wrap:anywhere}
.tasklets .when{display:block;font-size:11px;color:var(--ink-2);margin-top:1px;
  text-transform:uppercase;letter-spacing:.04em}
.tasklets li.late .when{color:var(--urgent)}
.tasklets form{flex:none;margin:0}
.tasklets .tick button{width:20px;height:20px;padding:0;border-radius:50%;
  border:1.5px solid var(--line);background:var(--surface);cursor:pointer;
  display:flex;align-items:center;justify-content:center;margin-top:1px}
.tasklets .tick svg{width:12px;height:12px;fill:none;stroke:var(--ink-3);
  stroke-width:2.6;stroke-linecap:round;stroke-linejoin:round}
.tasklets .tick button:hover{border-color:var(--good);background:#EEF2EF}
.tasklets .tick button:hover svg{stroke:var(--good)}
/* "+1d" is a real control — it pushes a task to tomorrow — and it was 21px
   tall, which on a trackpad is a thing you miss and then hit the task itself.
   The label stays small; the target does not. */
.tasklets .later button{min-height:24px;padding:0 6px;
  border:0;background:none;cursor:pointer;font-size:11px;
  color:var(--ink-3);padding:2px 4px;font-variant-numeric:tabular-nums}
.tasklets .later button:hover{color:var(--bronze)}

.addtask{margin:0;padding-top:var(--s3);border-top:1px solid var(--line-2)}
.addtask > input[name=title]{width:100%;border:1px solid var(--line);
  border-radius:var(--r-sm);padding:7px 9px;font:inherit;font-size:13px;
  background:var(--surface);min-width:0}
.addtask .row{display:flex;align-items:center;gap:var(--s2);margin-top:var(--s2);
  flex-wrap:wrap}
.addtask input[type=date]{border:1px solid var(--line);border-radius:var(--r-sm);
  padding:4px 6px;font:inherit;font-size:12px;background:var(--surface);
  min-width:0;max-width:100%}

/* A row in the palette that changes something rather than going somewhere. It
   is a <button>, so it needs to look exactly like the <a> rows beside it. */
.cmd-row.cmd-do{width:100%;border:0;background:none;font:inherit;text-align:left;
  cursor:pointer;color:inherit}
.cmd-row.cmd-do .fig{color:var(--bronze);font-size:10.5px;letter-spacing:.06em;
  text-transform:uppercase}

/* Reach them from the list. The number is the call; the mark beside it is the
   WhatsApp. Both were a page load away before. */
.tbl td.reach{white-space:nowrap}
.tbl td.reach .tel{font-size:12.5px;color:var(--ink-2);font-variant-numeric:tabular-nums}
.tbl td.reach .tel:hover{color:var(--navy)}
.tbl td.reach .wa{display:inline-flex;align-items:center;justify-content:center;
  width:20px;height:20px;margin-left:6px;border-radius:5px;vertical-align:middle;
  border:1px solid var(--line-2);background:var(--surface)}
.tbl td.reach .wa svg{width:12px;height:12px;fill:none;stroke:var(--ink-3);
  stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.tbl td.reach .wa:hover{border-color:var(--good);background:#EEF2EF}
.tbl td.reach .wa:hover svg{stroke:var(--good)}

/* A BACKGROUND SEND HAS TO LOOK LIKE SOMETHING. The button now sends rather
   than opening a tab, so without this a press produces no visible event at all
   and you press it again — which is how somebody gets messaged twice. The word
   sits beside the mark and clears itself; a failure stays until it is read. */
.tbl td.reach button.wa{padding:0;cursor:pointer}
.tbl td.reach .wa.said::after{content:attr(data-said);margin-left:5px;
  font-size:11px;letter-spacing:.02em;color:var(--good);white-space:nowrap}
.tbl td.reach .wa.said{width:auto;padding:0 7px 0 4px;border-color:var(--good)}
.tbl td.reach .wa.said svg{stroke:var(--good)}
.tbl td.reach .wa.said-bad::after{color:var(--urgent)}
.tbl td.reach .wa.said-bad{border-color:var(--urgent)}
.tbl td.reach .wa.said-bad svg{stroke:var(--urgent)}
/* Already messaged from this list, so the row says so at a glance. */
.tbl td.reach .wa.done{border-color:var(--good);background:#EEF2EF}
.tbl td.reach .wa[data-sending]{opacity:.6;cursor:progress}

/* Call beside the number — the same mark as WhatsApp and email, and the first
   of the three, because ringing is what this list is for. Navy rather than
   grey on hover: it is the action, not an alternative to it. */
.tbl td.reach .ca{display:inline-flex;align-items:center;justify-content:center;
  width:20px;height:20px;margin-left:6px;border-radius:5px;vertical-align:middle;
  border:1px solid var(--line-2);background:var(--surface);padding:0;cursor:pointer}
.tbl td.reach .ca svg{width:12px;height:12px;fill:none;stroke:var(--ink-3);
  stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.tbl td.reach .ca:hover{border-color:var(--navy);background:var(--surface-2)}
.tbl td.reach .ca:hover svg{stroke:var(--navy)}
/* Sending switched off: still visible, plainly not pressable. */
.tbl td.reach .ca[disabled]{opacity:.4;cursor:not-allowed}
.tbl td.reach .ca[disabled]:hover{border-color:var(--line-2);background:var(--surface)}
.tbl td.reach .ca[disabled]:hover svg{stroke:var(--ink-3)}

/* Email beside the number, same size as the WhatsApp mark. */
.tbl td.reach .em{display:inline-flex;align-items:center;justify-content:center;
  width:20px;height:20px;margin-left:4px;border-radius:5px;vertical-align:middle;
  border:1px solid var(--line-2);background:var(--surface)}
.tbl td.reach .em svg{width:12px;height:12px;fill:none;stroke:var(--ink-3);
  stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.tbl td.reach .em:hover{border-color:var(--navy);background:var(--surface-2)}
.tbl td.reach .em:hover svg{stroke:var(--navy)}

/* The contacts table was 1622px in a 1228px page, so budget and score were off
   the right-hand edge of the screen on the list used more than any other. These
   two columns hold short values and were taking the room. */
.tbl th.src,.tbl td.src{max-width:150px}
/* The advert name is clipped; the "part-filled" flag underneath is not. An
   abandoned form has to be visible on the row — that is the whole point of the
   flag — and nowrap+ellipsis on the cell was hiding it off the right edge. */
.tbl td.src .who,.tbl th.src{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tbl td.src{overflow:visible}
.tbl td.src .st{margin-top:3px;display:inline-block}
.tbl th.nexthead{min-width:170px}
.tbl td.nextcell{max-width:230px}

/* The name column took 334px for names that average half that. Capped, with the
   full name on hover, which brings the table to the width of the page — so
   budget and score are on screen instead of past the right-hand edge. */
.tbl td:has(.rowname){max-width:262px}
.tbl .rowname{min-width:0}
.tbl .rowname .name{display:block;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;max-width:100%}
.tbl .rowname .sub{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  max-width:100%}

/* The select-all column was 34px of checkbox in 57px of cell. The last 23px of
   padding was the difference between the score column being on screen and not. */
.tbl td:has(> .chk),.tbl th:has(> .chk){padding-left:10px;padding-right:4px}

/* People in a Sales Expert answer — clickable, with the reason underneath. */
.expertrows{margin:0}
.expertrows li{display:flex;align-items:flex-start;gap:var(--s3);
  padding:var(--s2) 0;border-top:1px solid var(--line-2)}
.expertrows li:first-child{border-top:0}
.expertrows .grow{flex:1;min-width:0}
.expertrows .title{font-weight:500;font-size:13.5px}
.expertrows .why{font-size:12px;color:var(--ink-2);margin-top:1px;line-height:1.45}
.expertrows .end{flex:none}

/* ── ALSO EARNED ON THIS CLIENT ──────────────────────────────────────────
   Revenue beside the commission, never folded into it. */
.extras{list-style:none;margin:0 0 var(--s4);padding:0}
.extras li{display:flex;align-items:flex-start;gap:var(--s2);padding:var(--s2) 0;
  border-top:1px solid var(--line-2)}
.extras li:first-child{border-top:0}
.extras .grow{flex:1;min-width:0}
.extras b{display:block;font-weight:500;font-size:13px;line-height:1.35;
  overflow-wrap:anywhere}
.extras .meta{display:block;font-size:11px;color:var(--ink-2);margin-top:1px;
  overflow-wrap:anywhere}
.extras li.is-received b{color:var(--good)}
.extras li.is-lost{opacity:.55}
.extras li.is-lost b{text-decoration:line-through}
.extras .mv{flex:none;margin:0}
.addextra{margin:0;padding-top:var(--s3);border-top:1px solid var(--line-2)}
.addextra .row{display:flex;align-items:center;gap:var(--s2);margin-bottom:var(--s2);
  flex-wrap:wrap}
.addextra input{border:1px solid var(--line);border-radius:var(--r-sm);
  padding:6px 8px;font:inherit;font-size:12.5px;background:var(--surface);
  min-width:0;flex:1}

/* The four facts that answer "what is this deal" before anything else. */
.facts.headline{padding-bottom:var(--s3);margin-bottom:var(--s3);
  border-bottom:1px solid var(--line-2)}
.facts.headline dd{font-size:13.5px}

/* Editable facts in the deal's left rail. The controls have to shrink to the
   cell: a date input asks for 160px by default and the cell is 144px. */
.facts.edit dd{min-width:0}
.facts.edit form{margin:0;min-width:0}
.facts.edit .cell{width:100%;max-width:100%;min-width:0;border:1px solid transparent;
  border-radius:var(--r-sm);padding:3px 6px;font:inherit;font-size:13.5px;
  background:transparent;color:var(--ink);font-variant-numeric:tabular-nums}
.facts.edit .cell:hover{border-color:var(--line-2);background:var(--surface-2)}
.facts.edit .cell:focus{border-color:var(--navy);background:var(--surface);
  outline:none}
.facts.edit input[type=date].cell{font-size:12.5px}
.facts.edit select{max-width:100%;min-width:0}

/* An action that cannot run keeps its place and says why. Removing it moved
   every tile after it, so the same click ran a different action on the next
   record — which is how "Request fee" opened a calendar. */
.qa .off{display:flex;flex-direction:column;align-items:center;gap:6px;
  padding:11px 4px;border:1px dashed var(--line-2);background:transparent;
  border-radius:var(--r-sm);font-size:10.5px;color:var(--ink-3);text-align:center;
  line-height:1.2;cursor:not-allowed;opacity:.55}
.qa .off svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}

/* The dashboard, embedded as it is. */
.roomframe{border:1px solid var(--line);border-radius:var(--r);overflow:hidden;
  background:var(--surface);box-shadow:var(--lift)}
.roomframe iframe{display:block;width:100%;height:78vh;min-height:520px;border:0}
@media(max-width:820px){.roomframe iframe{height:70vh;min-height:420px}}

/* ── THE ROOM BAR ────────────────────────────────────────────────────────
   Every room built for this client, at the top of the record. One of a kind is
   a button; several is a button that opens the list, because some clients have
   four deal rooms and the old ones still get opened. "Where they stand" sits
   here too — worth reading before a call, in the way every other time. */
.roombar{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:flex-start;
  margin-bottom:var(--s5)}
.roombar .is-off{opacity:.5;cursor:not-allowed;background:transparent;
  border-style:dashed}
.roomset{position:relative}
.roomset > summary{list-style:none;cursor:pointer;user-select:none}
.roomset > summary::-webkit-details-marker{display:none}
.roomset > summary::after{content:"▾";margin-left:6px;font-size:10px;opacity:.6}
.roomset[open] > summary::after{content:"▴"}
.roomlist{position:absolute;z-index:40;top:calc(100% + 4px);left:0;min-width:260px;
  max-width:340px;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r);box-shadow:var(--lift-2);padding:4px;overflow:hidden}
.roomlist a{display:block;padding:7px 9px;border-radius:var(--r-sm);
  text-decoration:none}
.roomlist a:hover{background:var(--surface-2)}
.roomlist b{display:block;font-size:13px;font-weight:500;color:var(--ink);
  overflow-wrap:anywhere}
.roomlist span{display:block;font-size:11px;color:var(--ink-2);margin-top:1px}
/* The read-up opens in place and full width rather than in a dropdown. The bar
   is a flex row, so without this the opened card is sized to its summary — 144px
   of prose, which is the ribbon this was moved out of a sidebar to escape. */
.roomset.stand{position:static}
.roomset.stand > summary{width:max-content}
.roomset.stand[open]{flex-basis:100%;width:100%}
.standout{margin-top:var(--s3);width:100%}
.roomset.stand .brief-card{margin-bottom:0}

/* Editing a note in the timeline. Closed it reads exactly as it did before;
   open it is a textarea. No JavaScript, so it cannot half-work. */
.noteedit > summary{list-style:none;cursor:text}
.noteedit > summary::-webkit-details-marker{display:none}
.noteedit > summary p{margin:2px 0 0;border:1px solid transparent;border-radius:var(--r-sm);
  padding:2px 4px;margin-left:-4px}
.noteedit > summary:hover p{border-color:var(--line-2);background:var(--surface-2)}
.noteedit textarea{width:100%;margin-top:6px;border:1px solid var(--line);
  border-radius:var(--r-sm);padding:7px 9px;font:inherit;font-size:13px;
  background:var(--surface);resize:vertical}
.noteedit .row{display:flex;align-items:center;gap:var(--s3);margin-top:6px;
  flex-wrap:wrap}
.noteedit .row .btn{margin-left:auto}

/* Five goals, five closes. The "ask" rows are the honest gaps — a question the
   record cannot answer — and read differently from the ones it can. */
.briefpoints .title{font-size:13.5px;line-height:1.4}
.briefpoints .why{font-size:12px;line-height:1.5;margin-top:2px}
.briefpoints .why.quiet{color:var(--ink-3);font-size:11.5px}
.briefpoints li.ask .title{color:var(--bronze);font-weight:500}
.briefpoints li.ask{background:#FBF7F1}

/* ═══ NOTES, THE WAY HUBSPOT SHOWS THEM ═══════════════════════════════════
   The first version of this tab stacked an open textarea for every note, each
   with a Save button and a sentence of explanation underneath. It was a wall of
   form controls: you could not read a note without reading an input, and twelve
   of them on a record was unusable.

   HubSpot's is a reading surface. A note is prose in a quiet card, with "Note by
   <who>" and the time above it. It is collapsed to a couple of lines with a
   fade, opens on the chevron, and only then offers Actions. The editor is
   somewhere you go, not something you are looking at.

   Done with <details>/<summary> because the CSP forbids inline script and this
   needs none: the disclosure behaviour is in the markup. */
.notes{display:flex;flex-direction:column;gap:var(--s3)}

.note-card{background:var(--surface);border:1px solid var(--line);border-radius:8px}
/* The summary is a column: the header row, then the two-line preview. Both
   have to be in here — a closed <details> renders nothing but its summary. */
.note-card summary{list-style:none;cursor:pointer;display:block;
  padding:var(--s3) var(--s4);font-size:13px;color:var(--ink-2)}
.note-card summary .head{display:flex;align-items:baseline;gap:var(--s2)}
.note-card summary::-webkit-details-marker{display:none}
.note-card summary:hover{background:var(--surface-2);border-radius:8px}
.note-card[open] summary:hover{border-radius:8px 8px 0 0}
/* The chevron. Rotates on open, which is the only cue that the card has more
   in it — so it has to be visible without being loud. */
.note-card summary .chev{flex:none;width:14px;color:var(--ink-2);
  transition:transform .12s;font-size:15px;line-height:1.35;
  transform-origin:45% 55%}
.note-card[open] summary .chev{transform:rotate(90deg)}
.note-card summary .who{color:var(--ink)}
.note-card summary .who b{font-weight:600}
.note-card summary .when{margin-left:auto;flex:none;color:var(--ink-3);font-size:12.5px;
  white-space:nowrap}

/* The collapsed preview: two lines, faded out at the bottom rather than cut
   mid-letter, so it reads as "there is more" and not as broken text. */
.note-card .peek{margin-top:6px;font-size:14px;line-height:1.55;color:var(--ink);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;
  mask-image:linear-gradient(180deg,#000 55%,transparent);
  -webkit-mask-image:linear-gradient(180deg,#000 55%,transparent)}
.note-card[open] .peek{display:none}

.note-card .full{padding:0 var(--s4) var(--s4);white-space:pre-wrap;
  font-size:14px;line-height:1.6}
/* An edit that has been made is worth seeing without opening the editor. */
.note-card .full .prev{margin-top:var(--s3);padding-top:var(--s3);
  border-top:1px dashed var(--line);color:var(--ink-3);font-size:13px}

/* Actions, on the card and only once it is open — as in HubSpot. */
.note-card .acts{padding:0 var(--s4) var(--s4);display:flex;gap:var(--s3);
  align-items:center}
.note-card .editor{padding:0 var(--s4) var(--s4)}
.note-card .editor summary{padding:0;font-size:13px;color:var(--bronze);
  display:inline-block}
.note-card .editor summary:hover{background:none;text-decoration:underline}
.note-card .editor textarea{margin-top:var(--s2)}

/* The composer. Closed it is a button, open it is the form — so the tab opens
   on the notes rather than on an empty box.

   FULL WIDTH, AND THAT IS THE POINT. This used to be a flex item beside the
   search box, which meant the open panel was as wide as the leftover space:
   a small textarea adrift in a wide column. A writing surface that does not
   fill its column reads as unfinished however good the type is. */
.note-new{margin:0 0 var(--s5);display:block;width:100%}
.note-new > summary{list-style:none;cursor:pointer;display:inline-flex;
  align-items:center;gap:7px;font-size:13.5px;font-weight:500;
  padding:9px var(--s4);border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--surface);color:var(--ink);
  transition:border-color var(--fast),background var(--fast),box-shadow var(--fast)}
.note-new > summary::-webkit-details-marker{display:none}
.note-new > summary:hover{border-color:#DBD2C2;box-shadow:var(--lift)}
.note-new > summary svg{color:var(--ink-3);flex:none}
.note-new[open] > summary{background:var(--navy);border-color:var(--navy);color:#fff;
  border-radius:var(--r-sm) var(--r-sm) 0 0}
.note-new[open] > summary svg{color:var(--sand);transform:rotate(45deg)}
.note-new .body{background:var(--surface);border:1px solid var(--line);
  border-top-color:var(--navy);
  border-radius:0 var(--r) var(--r) var(--r);padding:var(--s5);box-shadow:var(--lift)}
.note-new .body textarea{width:100%;display:block;min-height:150px;resize:vertical;
  line-height:1.6;font-size:14.5px;padding:var(--s3) var(--s4)}
/* The action sits on the right of its own row, with the explanation on the
   left — so the button is where the eye finishes rather than where it starts. */
.note-new .foot{display:flex;align-items:center;gap:var(--s4);
  margin-top:var(--s4);padding-top:var(--s4);border-top:1px solid var(--line-2)}
.note-new .foot .t-small{flex:1;min-width:0}
.note-new .foot .btn{flex:none}

/* The row above the notes: search on its own, the composer full width below. */
.note-bar{display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap;
  margin-bottom:var(--s4)}
.note-search{display:flex;gap:var(--s2);align-items:center;margin:0}
.note-bar input[type=search],.note-bar input[name=nq],
.note-search input[name=nq]{max-width:260px}
.note-bar .sp{margin-left:auto}

/* ── nothing can be sent ────────────────────────────────────────────────
   Deliberately the loudest thing on the page, because the failure it reports
   is otherwise completely silent: every outbound path refuses, each record
   shows its own small "not sent", and nothing anywhere names the cause. */
.sendoff{border:1px solid var(--urgent);border-left-width:3px;border-radius:var(--r);
  background:#FBF1EE;padding:var(--s4) var(--s5);margin:0 0 var(--s5)}
.sendoff .row{display:flex;gap:var(--s3);align-items:flex-start}
.sendoff .row + .row{margin-top:var(--s3);padding-top:var(--s3);
  border-top:1px solid rgba(168,68,47,.15)}
.sendoff .dot{flex:none;width:7px;height:7px;border-radius:50%;
  background:var(--urgent);margin-top:6px}
.sendoff b{color:var(--urgent);font-weight:600}
.sendoff .t-small{margin-top:2px}
.sendoff code{display:inline-block;margin-top:6px;font-size:12px;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:3px 8px;color:var(--ink-2)}

/* ── the meetings card in the rail ──────────────────────────────────────
   A meeting you have not invited anyone to is the single most expensive thing
   on a contact record, so the action sits on the card rather than one click
   away on a screen you have to know exists. */
.mcard{border:1px solid var(--line);border-radius:var(--r);background:var(--surface);
  padding:var(--s3) var(--s4);margin-bottom:var(--s2);transition:border-color var(--fast)}
.mcard:hover{border-color:#DBD2C2}
.mcard > a{display:block}
.mcard .n{font-weight:600;font-size:13.5px;color:var(--ink)}
.mcard .u{font-size:12.5px;color:var(--ink-2);margin-top:2px}
.mcard .f{display:flex;align-items:center;gap:var(--s2);margin-top:var(--s3)}
.mcard .f .state{font-size:12px;color:var(--ink-2);text-transform:capitalize}
.mcard .f .sent{margin-left:auto;font-size:12px;color:var(--good);font-weight:500}
.mcard .f form{margin-left:auto}
.mcard .warn{margin-top:var(--s2);padding-top:var(--s2);
  border-top:1px solid var(--line-2);color:var(--urgent)}
.mcard .warn a{text-decoration:underline}


/* ── a textarea is never twenty columns wide ────────────────────────────
   The browser default for a <textarea> with no cols is ~185px regardless of
   the column it sits in. Every writing surface in this CRM is meant to fill
   its container, and the two places that did not were both found by
   measurement rather than by looking. This is the floor, not a fix. */
textarea{width:100%}


/* ── a control you are meant to press is at least 24px tall ─────────────
   Disclosure summaries came out at 20-22px — "Or sign in with a password",
   "See the 7 outstanding documents", "7 sources produced leads". They work,
   and they are small enough to feel fiddly, which is the difference between
   a tool that is used and one that is tolerated. */
summary{min-height:24px;display:flex;align-items:center;gap:6px}
summary.t-small,summary.sub,summary.t-small.quiet{padding:2px 0}
/* Ones that are laid out as blocks keep their own display. */
.note-new > summary,.noteedit > summary,.hs-ev > summary{display:flex}
.noteedit > summary{display:block;min-height:0}

/* ── a call on the record ───────────────────────────────────────────────
   The outcome leads, because "no answer, three times" is the thing you act on.
   The recording sits under it rather than behind a link: a call you have to go
   and find is a call nobody listens to. */
.callcard{border:1px solid var(--line);border-radius:var(--r);background:var(--surface);
  padding:var(--s3) var(--s4);margin-bottom:var(--s2);transition:border-color var(--fast)}
.callcard:hover{border-color:#DBD2C2}
.callcard .top{display:flex;align-items:baseline;gap:var(--s2)}
.callcard .out{font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-3)}
.callcard .out.good{color:var(--good)}
.callcard .when{margin-left:auto;font-size:12px;color:var(--ink-3);
  font-variant-numeric:tabular-nums}
.callcard audio{border-radius:var(--r-sm)}
.callcard .outcome{display:flex;gap:var(--s2);align-items:center;margin-top:var(--s2);
  padding-top:var(--s2);border-top:1px solid var(--line-2)}
.callcard .outcome select{flex:1;min-width:0;font-size:12.5px;padding:4px 8px}

/* ── what happened when you pressed something ───────────────────────────
   Pressing Call and seeing nothing at all is the worst possible outcome: you
   cannot tell a refused call from a broken button, and you press it again. */
.saidline{border:1px solid var(--line);border-left:3px solid var(--good);
  border-radius:var(--r);background:var(--surface);padding:var(--s3) var(--s4);
  margin:0 0 var(--s4);font-size:13.5px}
.saidline.bad{border-left-color:var(--urgent);background:#FBF1EE;color:var(--ink)}

/* ── the softphone bar ──────────────────────────────────────────────────
   Fixed to the bottom because a call outlives the page you started it on —
   scrolling the record while you talk must not hide the hang-up button. */
.softphone{position:fixed;left:50%;bottom:20px;transform:translateX(-50%);
  display:none;align-items:center;gap:var(--s4);z-index:200;
  background:var(--navy);color:#fff;border-radius:999px;
  padding:10px var(--s3) 10px var(--s5);box-shadow:var(--lift-2)}
.softphone.open{display:flex}
.softphone .who{font-weight:600;font-size:14px}
.softphone .state{font-size:13px;color:rgba(255,255,255,.72)}
.softphone.live .state{color:var(--sand)}
.softphone .hang{border:0;border-radius:999px;background:var(--urgent);color:#fff;
  font:inherit;font-size:13px;font-weight:600;padding:7px 16px;cursor:pointer}
.softphone .hang:hover{background:#8f3626}

/* "Book the next one" — the panel that closes the loop after a meeting.
   Recording an outcome used to end at Save, with no way through to the next
   meeting, so the most certain next action in the business was the one the
   screen did not offer. Tinted so it reads as the way forward rather than as
   another box of fields. */
.panel.nextup{background:var(--surface-2);border-color:#E3DBCB}
.panel.nextup h3{margin-bottom:4px}
.panel.nextup .sub{margin-bottom:var(--s4)}
.panel.nextup .btns{display:flex;gap:var(--s3);flex-wrap:wrap}

/* Inline saves — the word that says it happened, and the reason box.
   A change that saves silently in the background looks exactly like one that
   did not save at all, so it says so for a moment. */
.inline-said{margin-left:7px;font-size:11.5px;color:var(--ink-3);white-space:nowrap}
.inline-said.bad{color:#9B5B2E;font-weight:500}
/* Disqualifying asks why here rather than sending you to the record — that was
   another page load, and a page load ends a call in progress. */
.inline-reason{display:block;margin-top:6px}
.inline-reason input{width:100%;max-width:230px;padding:5px 8px;font-size:12.5px;
  border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface)}
.inline-reason input:focus{border-color:var(--navy);box-shadow:var(--focus);outline:none}

/* The Call icon in a results table is a button, not a link, so it needs the
   same shape as the icon links beside it. */
button.iconbtn{font:inherit;cursor:pointer}
button.iconbtn[disabled]{opacity:.4;cursor:not-allowed}

/* ── The WhatsApp inbox ──────────────────────────────────────────────────
   Two panes: who is talking on the left, what was said on the right. A list
   of conversations ordered by what moved last, which is what an inbox is —
   before this the only way to find a reply was to open five hundred records
   one at a time. */
.wa-wrap{display:grid;grid-template-columns:300px 1fr;gap:var(--s4);
  align-items:start}
@media (max-width:900px){.wa-wrap{grid-template-columns:1fr}
  .wa-list{max-height:260px}}

.wa-list{border:1px solid var(--line);border-radius:var(--r);
  background:var(--surface);max-height:calc(100vh - 230px);overflow:auto}
.wa-row{display:block;padding:10px 12px;border-bottom:1px solid var(--line);
  text-decoration:none;color:inherit}
.wa-row:last-child{border-bottom:0}
.wa-row:hover{background:var(--surface-2)}
.wa-row.on{background:var(--surface-2);box-shadow:inset 3px 0 0 var(--navy)}
/* Something new in it. A left edge rather than a colour wash, so a long list
   of unread threads does not become a wall. */
.wa-row.new{box-shadow:inset 3px 0 0 var(--urgent)}
.wa-row.new.on{box-shadow:inset 3px 0 0 var(--urgent),inset 0 0 0 99px rgba(0,0,0,.015)}
.wa-row-top{display:flex;justify-content:space-between;gap:8px;align-items:baseline}
.wa-row-top .who{font-weight:560;font-size:13px}
.wa-row-top .when{font-size:11px;color:var(--ink-3);white-space:nowrap}
.wa-row-last{font-size:12px;color:var(--ink-2);margin-top:2px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.wa-row-last .mine{color:var(--ink-3)}
.wa-row-tags{display:flex;gap:5px;margin-top:5px;flex-wrap:wrap}

.wa-thread{border:1px solid var(--line);border-radius:var(--r);
  background:var(--surface);display:flex;flex-direction:column;
  min-height:420px;max-height:calc(100vh - 230px)}
.wa-head{display:flex;justify-content:space-between;align-items:flex-start;
  gap:var(--s4);padding:var(--s4);border-bottom:1px solid var(--line)}
.wa-name{font-weight:600;font-size:15px;color:var(--ink);text-decoration:none}
.wa-name:hover{color:var(--navy)}
.wa-head-right{display:flex;gap:6px;align-items:center}

.wa-msgs{flex:1;overflow:auto;padding:var(--s4);
  display:flex;flex-direction:column;gap:10px}
.wa-msg{display:flex;flex-direction:column;max-width:72%}
.wa-msg.in{align-self:flex-start;align-items:flex-start}
.wa-msg.out{align-self:flex-end;align-items:flex-end}
.wa-bubble{padding:9px 12px;border-radius:12px;font-size:13px;line-height:1.5;
  white-space:pre-wrap;word-break:break-word;border:1px solid var(--line-2)}
.wa-msg.in .wa-bubble{background:var(--surface-2);border-bottom-left-radius:4px}
.wa-msg.out .wa-bubble{background:#EEF4F0;border-color:#D4E4DA;
  border-bottom-right-radius:4px}
.wa-msg.bad .wa-bubble{background:#FBF0EE;border-color:#E8CFC9}
.wa-meta{font-size:10.5px;color:var(--ink-3);margin-top:3px;letter-spacing:.02em}
.wa-meta .bad{color:var(--urgent)}

.wa-send{border-top:1px solid var(--line);padding:var(--s4)}
.wa-form{display:flex;gap:8px;align-items:flex-end}
.wa-form textarea{flex:1;resize:vertical;min-height:44px;font:inherit;
  font-size:13px;padding:9px 11px;border:1px solid var(--line-2);
  border-radius:var(--r-sm);background:var(--surface)}
.wa-form textarea:focus{outline:none;border-color:var(--navy)}
.wa-send .sub{margin:6px 0 0;font-size:11.5px}
.wa-cold .wa-bubble.preview{background:var(--surface-2);max-width:none;
  margin:8px 0 10px;display:block}
/* The assistant's three states, on the screen it affects. */
.wa-bot{display:inline-flex;gap:4px;align-items:center}
.wa-bot .sub{margin-right:4px}

/* The funnel. One row, left to right, because that is the journey: messaged,
   replied, talked, booked, happened. The booked column is marked because it is
   the number the business runs on. */
.wa-funnel{display:grid;grid-template-columns:repeat(5,1fr);gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:var(--r);
  overflow:hidden;margin-bottom:var(--s3)}
.wa-step{background:var(--surface);padding:10px 12px}
.wa-step .n{font-size:20px;font-weight:600;line-height:1.1;
  font-variant-numeric:tabular-nums}
.wa-step .lbl{font-size:11px;color:var(--ink-3);margin-top:2px;
  text-transform:uppercase;letter-spacing:.05em}
.wa-step .pc{font-size:11.5px;color:var(--ink-2);margin-top:3px;
  font-variant-numeric:tabular-nums}
.wa-step.key{background:#EEF4F0}
.wa-step.key .n,.wa-step.key .pc{color:var(--good)}
@media (max-width:900px){.wa-funnel{grid-template-columns:repeat(2,1fr)}}

/* The lost-reason picker. A radio list that is comfortable to hit — the whole
   row is the target, not the 13px dot — and shows which one is chosen without
   needing colour to carry it. See app/lostreasons.py for why this screen
   exists at all. */
.pick{border:1px solid transparent;transition:background .12s ease,border-color .12s ease}
.pick:hover{background:var(--surface-2)}
.pick.on,.pick:has(input:checked){background:var(--surface-2);border-color:var(--line)}
.pick:focus-within{outline:2px solid var(--navy);outline-offset:1px}
