/* Sales Manager (agency). Light theme; brand orange sampled from the Essence Automations
   logo pixels (#FE5105 deep to #FD8709 light), settled on #fb6e10 with #c2500a for anything
   carrying text, so it clears contrast on white. The yellow this replaced was sampled from
   Best in Auto's logo and had no business on Essence Automations' own screen. */
:root{
  --brand:#fb6e10; --brand-deep:#c2500a; --brand-soft:#fff3ea; --brand-line:#f6d3b4;
  --ink:#141414; --body:#3d3d3a; --muted:#8a8880;
  --bg:#f7f6f2; --card:#ffffff; --line:#e6e3d8;
  --green:#2e7d52; --green-soft:#eef7f1; --red:#b0492c; --red-soft:#fbf1ee;
  --blue:#2f5d8a; --amber:#a8760a;
  --radius:10px; --shadow:0 1px 3px rgba(20,20,20,.07), 0 1px 2px rgba(20,20,20,.04);
}
*{box-sizing:border-box;}
/* `hidden` must beat the display rules below, or an invisible full-screen overlay
   keeps swallowing clicks. */
[hidden]{display:none !important;}
body{
  margin:0; background:var(--bg); color:var(--body);
  font-family:"Segoe UI",-apple-system,BlinkMacSystemFont,"Helvetica Neue",Arial,sans-serif;
  font-size:14px; line-height:1.5;
}
body.loading #app,body.loading #gate{display:none;}
h1,h2,h3{color:var(--ink);margin:0 0 10px;}
h2{font-size:19px;} h3{font-size:14px;}
.muted{color:var(--muted);} .sm{font-size:12px;}
.grow{flex:1;}
a{color:var(--blue);}

/* ---- gate ---- */
.gate{position:fixed;inset:0;background:var(--bg);display:flex;align-items:center;justify-content:center;padding:20px;z-index:50;}
.gate-card{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:32px;max-width:380px;width:100%;box-shadow:var(--shadow);text-align:center;}
.gate-logo{height:64px;margin-bottom:14px;border-radius:10px;}
.gate-card form{text-align:left;margin-top:18px;}
label{display:block;margin-bottom:12px;font-size:12.5px;color:var(--ink);font-weight:600;}
input,select,textarea{
  width:100%;margin-top:4px;padding:9px 11px;border:1px solid var(--line);border-radius:8px;
  font:inherit;color:var(--ink);background:#fff;font-weight:400;
}
input:focus,select:focus,textarea:focus{outline:2px solid var(--brand);outline-offset:-1px;border-color:var(--brand-deep);}
textarea{resize:vertical;}
.err{background:var(--red-soft);color:var(--red);padding:8px 11px;border-radius:8px;margin-bottom:10px;font-size:12.5px;}

/* ---- buttons ---- */
.btn{
  border:1px solid var(--line);background:#fff;color:var(--ink);padding:8px 14px;border-radius:8px;
  font:inherit;font-weight:600;cursor:pointer;
}
.btn:hover{background:#faf9f4;}
.btn.primary{background:var(--brand);border-color:var(--brand-deep);color:#141414;}
.btn.primary:hover{background:#ff8332;}
.btn.ghost{background:transparent;border-color:transparent;color:var(--muted);}
.btn.ghost:hover{background:#efece2;color:var(--ink);}
.btn.sm{padding:6px 11px;font-size:12.5px;}
.btn.wide{width:100%;padding:10px;}
.btn.danger{color:var(--red);border-color:#e8cfc6;}

/* ---- sample-data banner ---- */
.demobar{
  background:var(--brand);border-bottom:1px solid var(--brand-deep);color:#141414;
  padding:8px 20px;font-size:12.5px;text-align:center;
}
.demobar b{font-weight:700;}
.demobar.paused{background:var(--red-soft);border-bottom-color:#eacfc6;color:var(--red);}

/* ---- topbar ---- */
.topbar{
  display:flex;align-items:center;gap:18px;padding:10px 20px;background:#fff;
  border-bottom:1px solid var(--line);position:sticky;top:0;z-index:20;flex-wrap:wrap;
}
.brand{display:flex;align-items:center;gap:9px;font-weight:700;color:var(--ink);}
/* The logo tile is per workspace, set from the database at runtime, because two clients want
   opposite things here. Essence Automations' mark is orange neon on a near-black circuit
   background baked into the PNG, whose left edge is only ~69% opaque: without a tile in its
   own colour the white page fringes straight through the artwork. Best in Auto's mark is
   black and yellow drawn for white, and a dark tile round it would look broken. Hence a
   variable defaulting to transparent, not a colour hardcoded here.
   Recolouring either mark was never an option: at that point it stops being the logo the
   client actually has. */
.logo{height:34px;border-radius:7px;display:block;}
.gate-logo,.logo{background:var(--logo-bg,transparent);}
.tabs{display:flex;gap:2px;}
.tab{
  background:none;border:none;padding:7px 13px;border-radius:8px;font:inherit;font-weight:600;
  color:var(--muted);cursor:pointer;
}
.tab:hover{background:#f4f2ea;color:var(--ink);}
/* A link out to another app, styled as a tab but deliberately NOT class "tab": the nav
   handler binds every .tab and reads data-view off it, so an anchor with no data-view would
   set the view to undefined and hide every panel, leaving a blank page behind the new tab. */
.tablink{
  display:flex;align-items:center;padding:7px 13px;border-radius:8px;font:inherit;font-weight:600;
  color:var(--muted);text-decoration:none;white-space:nowrap;
}
.tablink:hover{background:#f4f2ea;color:var(--ink);}
.tab.active{background:var(--brand-soft);color:var(--ink);box-shadow:inset 0 -2px 0 var(--brand);}
.topright{margin-left:auto;display:flex;align-items:center;gap:10px;}
.me{font-size:12.5px;color:var(--muted);}
/* Reps see the board only. The client sees the money but not the settings, the team,
   or anything that would let them edit the terms of the fee. */
body.role-rep .admin-only,
body.role-client .admin-only{display:none;}
body.role-rep .fees-only{display:none;}
/* Workspaces with no success-fee arrangement never see the apparatus that hangs off it. The
   API 404s these routes as well; this only keeps the screen honest. */
body.no-fees .fees-only{display:none;}
/* Agency-only chrome is hidden by default and revealed for the agency owner, so a client
   who somehow lands on the markup never even sees that other subaccounts exist. The API
   returns 403 regardless; this just keeps the screen honest. */
.agency-only{display:none;}
body.is-agency .agency-only{display:block;}
body.is-agency .tab.agency-only{display:inline-block;}

/* ---- subaccount switcher ---- */
.wsbrand{position:relative;}
.wsbtn{
  display:flex;align-items:center;gap:7px;background:none;border:none;padding:5px 9px;
  border-radius:8px;font:inherit;font-weight:700;color:var(--ink);cursor:pointer;max-width:230px;
}
.wsbtn:hover{background:#f4f2ea;}
/* Pinned to one client's hostname: the switcher becomes plain text. Not just disabled —
   a greyed-out control still tells the client there is something else to switch to. */
body.pinned .wsbtn{cursor:default;padding-left:0;}
body.pinned .wsbtn:hover{background:none;}
body.pinned .wsbtn svg{display:none;}
.wsbtn span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.wsbtn svg{flex:0 0 auto;color:var(--muted);}
.wsmenu{
  position:absolute;top:calc(100% + 6px);left:0;min-width:260px;max-height:70vh;overflow:auto;
  background:#fff;border:1px solid var(--line);border-radius:12px;
  box-shadow:0 12px 30px rgba(0,0,0,.13);z-index:40;padding:6px;
}
.wsmenu-head{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);padding:7px 9px 5px;}
.wsmenu-list{display:flex;flex-direction:column;}
.wsitem{
  display:flex;align-items:center;gap:8px;width:100%;text-align:left;background:none;border:none;
  padding:9px 10px;border-radius:8px;font:inherit;color:var(--ink);cursor:pointer;
}
.wsitem:hover{background:#f4f2ea;}
.wsitem.on{background:var(--brand-soft);font-weight:700;}
.wsitem-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.wsmenu-foot{
  width:100%;margin-top:4px;border-top:1px solid var(--line);background:none;border-left:none;
  border-right:none;border-bottom:none;padding:10px;font:inherit;font-weight:600;
  color:var(--muted);cursor:pointer;text-align:left;border-radius:0 0 8px 8px;
}
.wsmenu-foot:hover{background:#f4f2ea;color:var(--ink);}

/* ---- subaccounts screen ---- */
.panel.wide{grid-column:1 / -1;}
.wstable{display:flex;flex-direction:column;gap:8px;}
.wsrow{
  display:flex;align-items:center;gap:12px;padding:11px 13px;border:1px solid var(--line);
  border-radius:10px;background:#fff;flex-wrap:wrap;
}
.wsrow.on{border-color:var(--brand-line);background:var(--brand-soft);}
.wsrow-main{flex:1;min-width:180px;}
.wsrow-actions{display:flex;gap:6px;flex-wrap:wrap;}
/* AI spend, read from the inbox Worker over the service binding. min-width:0 on the row main
   above keeps this from widening the card on a phone. */
.wsrow-ai{margin-top:3px;}
.wsrow-link{
  display:flex;align-items:center;gap:6px;margin-top:6px;color:var(--muted);flex-wrap:wrap;
}
.wsrow-link select{flex:1 1 150px;min-width:0;max-width:240px;padding:4px 7px;font-size:12.5px;}
/* Conversation AI setup drawer. The snippet scrolls inside its own box on purpose: a code
   snippet that wraps gets copied wrong. */
.snip{
  background:#f4f2ea;padding:10px;border-radius:8px;overflow-x:auto;min-width:0;
  font-size:12.5px;margin:8px 0;white-space:pre;
}
.tryout{
  margin-top:10px;padding:11px;border:1px solid var(--brand-line);background:var(--brand-soft);
  border-radius:8px;font-size:14px;white-space:pre-wrap;overflow-wrap:anywhere;
}
.tryout .verdict{margin-top:8px;font-size:12.5px;font-weight:650;padding:4px 8px;border-radius:6px;display:inline-block;}
.tryout .verdict.over{background:#e7f6ee;color:#0f8a4d;}
.tryout .verdict.ans{background:#fff;color:var(--ink);}
/* align-items:flex-start plus min-width:0 on the text. A flex item defaults to
   min-width:auto and will not shrink below its content, so at 320 the label overflowed its
   own row instead of wrapping. Wrap labels, never clip them. */
.chk{display:flex;align-items:flex-start;gap:8px;margin:12px 0 2px;}
.chk input{width:auto;margin:2px 0 0;flex:0 0 auto;}
.chk b{min-width:0;overflow-wrap:anywhere;}

main{padding:18px 20px 60px;max-width:1500px;margin:0 auto;}

/* ---- toolbar ---- */
.toolbar{display:flex;gap:10px;align-items:center;margin-bottom:14px;flex-wrap:wrap;}
.toolbar input[type=search]{width:260px;margin:0;}
.toolbar select{width:auto;margin:0;}
.check{display:flex;align-items:center;gap:6px;margin:0;font-weight:600;color:var(--body);}
.check input{width:auto;margin:0;}

/* ---- board ---- */
/* `stretch`, not `flex-start`. With flex-start each column is only as tall as its own
   cards, so an empty column is barely taller than its header and everything below it is
   dead space that swallows a drop. The column you can see is now the column you can drop
   on, top to bottom. */
.board{display:flex;gap:12px;overflow-x:auto;padding-bottom:14px;align-items:stretch;}
.col{background:#efece2;border-radius:var(--radius);min-width:270px;width:270px;flex:0 0 auto;padding:10px;min-height:180px;}
.col.dragover{outline:2px dashed var(--brand-deep);background:var(--brand-soft);}
.col-head{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:9px;padding:0 2px;}
.col-head b{color:var(--ink);font-size:13px;}
.col-head .v{font-size:11.5px;color:var(--muted);}
.card{
  background:var(--card);border:1px solid var(--line);border-radius:9px;padding:10px 11px;margin-bottom:8px;
  cursor:pointer;box-shadow:var(--shadow);
  /* Vertical scrolling stays the browser's; sideways movement on a card is a drag and is ours.
     Without this a touch drag is cancelled the moment the finger moves, because the browser has
     already claimed the gesture for the board's own sideways scroll. */
  touch-action:pan-y;
}
.card:hover{border-color:var(--brand-deep);}
.card.dragging{opacity:.45;}
/* The card that follows the pointer. pointer-events:none is load-bearing: the drop target is
   found with elementFromPoint, and a ghost that answered hit tests would be the only thing ever
   found under the cursor. */
.card.ghost{
  position:fixed;z-index:55;pointer-events:none;margin:0;opacity:.96;
  transform:rotate(1.5deg);box-shadow:0 12px 28px rgba(0,0,0,.18);
}
.card .co{font-weight:700;color:var(--ink);margin-bottom:2px;}
.card .who{font-size:12px;color:var(--muted);margin-bottom:6px;}
.card .meta{display:flex;gap:6px;flex-wrap:wrap;align-items:center;}
.pill{font-size:10.5px;padding:2px 7px;border-radius:20px;background:#f2efe4;color:var(--body);border:1px solid var(--line);white-space:nowrap;}
.pill.src{background:var(--brand-soft);border-color:var(--brand-line);color:#8a3a05;}
.pill.val{background:var(--green-soft);border-color:#cfe6d8;color:var(--green);font-weight:700;}
.pill.warn{background:var(--red-soft);border-color:#eacfc6;color:var(--red);}
/* Meetings follow the workspace brand, not a fixed blue. Green, red and amber stay put
   because they MEAN something (won, needs attention, opened). Blue meant nothing here except
   "appointment", so on an orange-branded workspace it just read as a foreign colour. */
.pill.svc{background:#eef3f9;border-color:#cfdcea;color:var(--blue);font-weight:600;}
.pill.appt{background:var(--brand-soft);border-color:var(--brand-line);color:var(--brand-deep);font-weight:600;}
.pill.open{background:#fdf5e5;border-color:#eddcb8;color:var(--amber);}
.empty{color:var(--muted);font-size:11.5px;text-align:center;padding:16px 8px;line-height:1.4;}
/* First-run / nothing-here states: say what to do next, never just "no data". */
.firstrun{
  background:var(--card);border:1px dashed var(--line);border-radius:var(--radius);
  padding:26px 28px;max-width:60ch;box-shadow:var(--shadow);
}
.firstrun h3{margin-bottom:7px;font-size:16px;}
.firstrun p{margin:0 0 10px;color:var(--body);}
.firstrun p:last-child{margin-bottom:0;}
/* ---- Help accordion ----
   HOUSE RULE (CATALOG-STANDARDS, learned on Iman): a <summary> must stay display:block.
   Putting flex on it silently breaks native <details> toggling in mobile WebKit, so the
   flex row lives on an inner wrapper and the toggle is driven from JS as well. */
.faq-list{max-width:78ch;}
.faq{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
     margin-bottom:9px;box-shadow:var(--shadow);}
.faq summary{display:block;cursor:pointer;list-style:none;padding:13px 16px;border-radius:var(--radius);}
.faq summary::-webkit-details-marker{display:none;}
.faq summary:hover{background:var(--brand-soft);}
.faq summary:focus-visible{outline:2px solid var(--brand-deep);outline-offset:-2px;}
.faq-row{display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0;}
/* min-width:0 on the flex CHILD, not the row: a flex item defaults to min-width:auto and
   will not shrink below its longest word, which pushed the summary 2px past the card at 320. */
.faq-q{font-family:Georgia,"Times New Roman",serif;font-weight:700;color:var(--ink);font-size:15px;min-width:0;overflow-wrap:anywhere;}
.faq-chev{width:9px;height:9px;flex:0 0 auto;margin-top:-4px;
          border-right:2px solid var(--brand-deep);border-bottom:2px solid var(--brand-deep);
          transform:rotate(45deg);transition:transform .18s ease;}
.faq[open] .faq-chev{transform:rotate(-135deg);margin-top:3px;}
.faq[open] summary{border-bottom:1px solid var(--line);border-radius:var(--radius) var(--radius) 0 0;}
.faq-body{padding:12px 16px 14px;}
.faq-body p{margin:0 0 9px;max-width:64ch;}
.faq-body p:last-child{margin-bottom:0;}

/* ---- dashboard ---- */
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(155px,1fr));gap:12px;margin-bottom:16px;}
.kpi{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:14px 16px;box-shadow:var(--shadow);}
.kpi[data-drill]{cursor:pointer;}
.kpi[data-drill]:hover{border-color:var(--brand-deep);background:var(--brand-soft);}
.kpi[data-drill]:focus-visible{outline:2px solid var(--brand-deep);outline-offset:2px;}
.kpi .n{font-size:26px;font-weight:700;color:var(--ink);line-height:1.1;}
.kpi .l{font-size:11.5px;color:var(--muted);margin-top:4px;}
.kpi.alert .n{color:var(--red);}
.kpi.good .n{color:var(--green);}
.panels{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:12px;}
/* min-width:0 so a wide child (the source table) scrolls inside its own box instead of
   stretching the grid track and making the whole PAGE scroll sideways. A grid item defaults
   to min-width:auto, which refuses to shrink below its content. */
.panel{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:15px 17px;box-shadow:var(--shadow);min-width:0;}
.panel h3{display:flex;gap:7px;align-items:baseline;}
.panel-wide{grid-column:1/-1;}
.panel-wide #userForm{max-width:420px;}
.bar-row{display:grid;grid-template-columns:140px 1fr 44px;gap:9px;align-items:center;margin-bottom:7px;font-size:12.5px;}
/* Wrap rather than ellipsise. The source name IS the chart: truncating it to
   "WhatsApp mark..." loses the only thing the row is telling you. */
.bar-row .lbl{color:var(--body);white-space:normal;overflow-wrap:anywhere;min-width:0;}
.bar-track{display:block;background:#f0ede3;border-radius:5px;height:9px;overflow:hidden;}
.bar-fill{display:block;background:var(--brand);height:100%;border-radius:5px;min-width:4px;}
.bar-row .n{text-align:right;font-weight:700;color:var(--ink);}
.stat-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;}
.stat-grid div{background:#faf9f4;border-radius:8px;padding:10px 12px;}
.stat-grid .n{font-size:19px;font-weight:700;color:var(--ink);}
.stat-grid .l{font-size:11.5px;color:var(--muted);}
.list-row{display:flex;justify-content:space-between;gap:10px;padding:7px 0;border-bottom:1px solid var(--line);font-size:12.5px;cursor:pointer;}
.list-row:last-child{border-bottom:none;}
.list-row:hover{color:var(--ink);}
.list-row b{color:var(--ink);}

/* ---- commission ---- */
.acct{border:1px solid var(--line);border-radius:9px;padding:11px 13px;margin-bottom:9px;background:#fdfcf7;}
.acct-head{display:flex;gap:9px;align-items:baseline;margin-bottom:5px;flex-wrap:wrap;}
.acct-head b{color:var(--ink);}


.feedbox{background:var(--brand-soft);border:1px solid var(--brand-line);border-radius:var(--radius);
  padding:14px 16px;margin-bottom:14px;}
.feedbox b{color:var(--ink);}
.feedbox p{margin:5px 0 0;}
.feed-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;margin:9px 0;}
.feed-row input{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:12px;}

/* ---- meetings calendar ----
   Two columns on desktop; on a phone the day panel stays hidden until a date is tapped, so
   only one decision is on screen at a time. One class does the reveal, no per-element JS. */
.booker{display:grid;grid-template-columns:minmax(0,340px) minmax(0,1fr);gap:18px;align-items:start;}
.bk-left{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:14px;box-shadow:var(--shadow);}
.cal-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:10px;}
.cal-title{font-family:Georgia,serif;font-weight:700;font-size:15px;color:var(--ink);}
.cal-nav{width:30px;height:30px;border-radius:8px;border:1px solid var(--line);background:#fff;
  cursor:pointer;font-size:16px;line-height:1;color:var(--ink);}
.cal-nav:hover:not(:disabled){border-color:var(--brand-deep);background:var(--brand-soft);}
.cal-nav:disabled{opacity:.35;cursor:default;}
/* seven equal columns divide the container, so the grid cannot overflow a phone */
.cal-dow{display:grid;grid-template-columns:repeat(7,1fr);gap:3px;margin-bottom:4px;}
.cal-dow span{text-align:center;font-size:10.5px;color:var(--muted);font-weight:600;}
.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:3px;}
/* Wider than tall on purpose. A square cell is 42px of box around a 13px number, which reads
   as a sparse, drifting grid; the eye wants the dates closer together vertically. The cell
   stays comfortably past the 44px tap target horizontally, and the height still clears the
   number plus the "something booked" dot. */
.cal-day{aspect-ratio:1/0.74;min-height:30px;border:1px solid transparent;border-radius:8px;
  background:transparent;cursor:pointer;font-size:13px;color:var(--ink);position:relative;
  display:flex;align-items:center;justify-content:center;font-family:"Segoe UI",sans-serif;}
.cal-day:hover{background:var(--brand-soft);}
.cal-day.blank{visibility:hidden;pointer-events:none;}
.cal-day.past{color:var(--muted-soft);opacity:.55;}
.cal-day.today{box-shadow:inset 0 0 0 2px var(--brand-deep);font-weight:700;}
.cal-day.sel{background:var(--brand);color:#fff;font-weight:700;}
.cal-day .dot{position:absolute;bottom:3px;left:50%;transform:translateX(-50%);
  width:5px;height:5px;border-radius:50%;background:var(--brand-deep);}
.cal-day.sel .dot{background:#fff;}
.cal-hint{margin:10px 2px 0;}

/* "Did that meeting happen?" Sits above the calendar, in the brand tint rather than a warning
   colour: it is a question, not a problem. */
.askbox{background:var(--brand-soft);border:1px solid var(--brand-line);border-radius:var(--radius);
  padding:13px 15px;margin-bottom:14px;}
.askbox > b{color:var(--ink);}
.askbox p{margin:2px 0 9px;}
.askrow{display:flex;align-items:center;gap:12px;flex-wrap:wrap;background:var(--card);
  border:1px solid var(--line);border-radius:9px;padding:9px 12px;margin-top:7px;}
.askrow-main{flex:1;min-width:180px;}
.askrow-acts{display:flex;gap:6px;flex-wrap:wrap;}
.bk-right{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:16px 18px;box-shadow:var(--shadow);}
.bk-right h3{margin-bottom:10px;}
/* the list scrolls inside its panel so the page length never depends on meeting count */
.bk-right .appt-list{max-height:520px;overflow-y:auto;scrollbar-width:thin;}
@media (max-width:760px){
  .booker{grid-template-columns:1fr;}
  .bk-right{display:none;}
  body.has-picked .bk-right{display:block;}
  body.has-picked .cal-hint{display:none;}
  .bk-right .appt-list{max-height:none;}
}

/* ---- appointments ---- */
.appt-list{display:grid;gap:9px;}
.appt{background:var(--card);border:1px solid var(--line);border-left:4px solid var(--brand);border-radius:var(--radius);padding:12px 15px;display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:14px;align-items:center;box-shadow:var(--shadow);}
.appt .when{min-width:64px;font-weight:700;color:var(--ink);font-size:13px;}
.appt .who{min-width:0;}
.appt .who b{color:var(--ink);overflow-wrap:anywhere;}
.appt .acts{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end;}
/* The two action buttons are an `auto` track, so they take ~163px and starve the company
   name down to 59px whenever the right-hand panel is narrow (a tablet, or a half-width
   window). Keyed to the CONTAINER, not the viewport, because the panel's width depends on the
   booker split rather than the screen. Placed before the mobile media block on purpose, so
   the phone layout below still wins there. */
.appt-list{container-type:inline-size;}
@container (max-width:430px){
  .appt{grid-template-columns:auto minmax(0,1fr);}
  .appt .acts{grid-column:1/-1;justify-content:flex-start;}
}
/* The zone sits under the time, small, on every single meeting. It is the one label that
   stops a Dubai owner and a Nairobi caller reading the same row an hour apart. */
.appt .when .tz{display:block;font-weight:600;font-size:11.5px;color:var(--muted);letter-spacing:.02em;}
.appt .outcome{margin-top:4px;color:var(--body);border-left:2px solid var(--brand-line);padding-left:8px;}

/* wrap-up form: what happened, and what happens next, in the same action */
.wrapup{grid-column:1/-1;margin-top:10px;padding-top:10px;border-top:1px dashed var(--line);display:grid;gap:7px;}
.wrapup b{color:var(--ink);font-size:13px;}
.wrapup textarea,.wrapup input,.wrapup select{width:100%;}
.wrap-row{display:flex;gap:8px;flex-wrap:wrap;}
.wrap-row.end{justify-content:flex-end;}
.wrap-row > input{flex:1 1 160px;min-width:0;}

/* Two controls side by side that stack themselves when there is not room for both.
   A datetime-local box has a big intrinsic width and was crushing the channel dropdown next
   to it down to 33px on a 320px phone: "Phone call / Video call / On site" unreadable, on the
   form whose whole job is booking the meeting. flex-basis is the breakpoint, so no media
   query has to know which pair of fields is in the row. */
.field-row{display:flex;gap:8px;flex-wrap:wrap;}
.field-row > *{flex:1 1 180px;min-width:0;}

/* ---- orders with a payment ledger ---- */
.order{border:1px solid var(--line);border-radius:var(--radius);padding:10px 12px;margin-bottom:9px;background:var(--card);}
.order-head{display:flex;gap:9px;align-items:center;flex-wrap:wrap;}
.order-head .subj{flex:1 1 140px;min-width:0;color:var(--ink);font-weight:600;}
.order-pay{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:7px;}
.order-ledger{margin:8px 0 4px;border-left:2px solid var(--brand-line);padding-left:9px;}
.ledger-row{display:flex;justify-content:space-between;gap:10px;font-size:12px;color:var(--muted);padding:2px 0;}
.ledger-row b{color:var(--ink);}
.ledger-row .btn{padding:0 6px;line-height:1.4;margin-left:6px;}
.paybox{margin-top:9px;padding-top:9px;border-top:1px dashed var(--line);display:grid;gap:7px;}

/* ---- source conversion table ---- */
/* Wide content scrolls inside its own box; the page body must never scroll sideways. */
.tbl-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;}
.tbl{width:100%;border-collapse:collapse;font-size:13px;min-width:520px;}
.tbl th{text-align:left;font-weight:600;color:var(--muted);font-size:11.5px;text-transform:uppercase;
        letter-spacing:.04em;padding:0 10px 7px 0;border-bottom:1px solid var(--line);white-space:nowrap;}
.tbl td{padding:8px 10px 8px 0;border-bottom:1px solid var(--line);color:var(--body);white-space:nowrap;}
.tbl tbody tr:last-child td{border-bottom:0;}
.tbl td b{color:var(--ink);}

/* ---- drawer / modal ---- */
.drawer{position:fixed;inset:0;z-index:40;}
.drawer-bg{position:absolute;inset:0;background:rgba(20,20,20,.35);}
.drawer-panel{
  position:absolute;top:0;right:0;bottom:0;width:min(560px,100%);background:var(--bg);
  overflow-y:auto;padding:22px 24px 60px;box-shadow:-4px 0 24px rgba(0,0,0,.12);
}
.modal-panel{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:min(680px,94%);
  max-height:92vh;overflow-y:auto;background:var(--bg);border-radius:14px;padding:24px;
}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:0 14px;}
.row-full{grid-column:1/-1;}
.actions{display:flex;gap:9px;justify-content:flex-end;margin-top:8px;}
.drawer-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:6px;}
.drawer-head h2{margin-bottom:2px;}
.sec{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:14px 16px;margin-top:12px;}
.sec h3{margin-bottom:9px;}
.kv{display:grid;grid-template-columns:100px 1fr;gap:5px 10px;font-size:13px;}
.kv dt{color:var(--muted);} .kv dd{margin:0;color:var(--ink);}
.stack{display:grid;gap:8px;}
.stack input,.stack select,.stack textarea{margin:0;}
.stack label{margin:0;}
.formhead{margin:2px 0 2px;font-size:13px;color:var(--ink);font-family:Georgia,serif;}
/* Browser autofill paints its own background; keep the field readable and on-brand. */
input:-webkit-autofill{-webkit-text-fill-color:var(--ink);box-shadow:0 0 0 30px #fff8f3 inset;}
.note{border-bottom:1px solid var(--line);padding:9px 0;font-size:13px;}
.note:last-child{border-bottom:none;}
.note .h{display:flex;gap:7px;align-items:center;margin-bottom:3px;font-size:11.5px;color:var(--muted);}
.tl{font-size:12.5px;color:var(--body);padding:5px 0 5px 14px;border-left:2px solid var(--line);margin-left:3px;}
.tl b{color:var(--ink);}
.seg{display:flex;gap:4px;flex-wrap:wrap;margin-bottom:9px;}
.seg button{padding:5px 10px;border:1px solid var(--line);background:#fff;border-radius:20px;font:inherit;font-size:12px;cursor:pointer;color:var(--muted);}
.seg button.on{background:var(--brand-soft);border-color:var(--brand-deep);color:var(--ink);font-weight:600;}
.email-row{display:flex;gap:9px;align-items:center;padding:8px 0;border-bottom:1px solid var(--line);font-size:12.5px;}
.email-row:last-child{border-bottom:none;}
.email-row .subj{flex:1;color:var(--ink);}
.tracked{background:#faf9f4;border:1px dashed var(--line);border-radius:8px;padding:9px 11px;font-family:ui-monospace,Consolas,monospace;font-size:11px;word-break:break-all;color:var(--body);margin-top:7px;}

/* ---- toast ---- */
.toast{
  position:fixed;bottom:22px;left:50%;transform:translateX(-50%);background:var(--ink);color:#fff;
  padding:10px 18px;border-radius:22px;font-size:13px;z-index:60;box-shadow:0 4px 14px rgba(0,0,0,.2);
}

@media (max-width:760px){
  .topbar{gap:8px;padding:8px 12px;}
  .brand{font-size:15px;}
  .logo{height:28px;}
  .topright{gap:7px;}
  .me{display:none;}                     /* you know who you are signed in as */
  /* The switcher keeps its full width on a phone: which client you are in is the one thing
     that must never be truncated to an ellipsis you cannot read. */
  .wsbtn{max-width:44vw;padding:4px 6px;}
  .wsmenu{min-width:min(300px,88vw);max-width:88vw;}
  /* Every nav item must be visible without sideways scrolling: wrap onto as many rows
     as it takes. A hidden tab is a feature the user never finds. */
  .tabs{order:3;width:100%;flex-wrap:wrap;gap:4px;overflow:visible;}
  .tab{white-space:nowrap;flex:0 0 auto;padding:6px 11px;font-size:13px;}
  .demobar{padding:7px 12px;font-size:11.5px;text-align:left;}
  main{padding:14px 12px 60px;}
  .grid2{grid-template-columns:1fr;}
  .toolbar input[type=search]{width:100%;}
  .toolbar select{flex:1 1 40%;}
  /* One column at a time, with a peek of the next so the sideways scroll is obvious. */
  .col{min-width:86vw;width:86vw;}
  .kpis{grid-template-columns:repeat(2,1fr);gap:9px;}
  .kpi{padding:12px 13px;}
  .kpi .n{font-size:22px;}
  .panels{grid-template-columns:1fr;}
  /* Stack the bar under its label on a phone. Squeezing the name into a 96px column
     ellipsised the very thing the chart is about: "WhatsApp marketing" read "WhatsApp mark...".
     Name and count on one line, full-width bar beneath, nothing truncated. */
  .bar-row{grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"lbl n" "bar bar";gap:2px 8px;margin-bottom:11px;}
  .bar-row .lbl{grid-area:lbl;white-space:normal;overflow:visible;overflow-wrap:anywhere;}
  .bar-row .n{grid-area:n;}
  .bar-row .bar-track{grid-area:bar;}
  .drawer-panel{width:100%;padding:18px 16px 60px;}
  .modal-panel{width:94%;padding:18px 16px;}
  .kv{grid-template-columns:88px 1fr;}
  .kv dd{overflow-wrap:anywhere;}        /* long emails must not run off the edge */
  .appt{grid-template-columns:1fr;}
  .appt .acts{justify-content:flex-start;}
  .email-row{flex-wrap:wrap;}
  .acct-head{font-size:13px;}
}

/* ---- business card scanner ---- */
.scanbar{display:flex;flex-wrap:wrap;align-items:center;gap:9px;margin:0 0 14px;padding:11px 13px;
         background:var(--brand-soft);border:1px solid var(--brand-line);border-radius:var(--radius);}
.scanbar .muted{flex:1 1 200px;min-width:0;}
.scanbar #scanMsg{flex:1 1 100%;min-width:0;}
.scanbar .ok{color:var(--good,#2e7d52);font-weight:600;}
.scanbar button[disabled]{opacity:.6;cursor:default;}

/* ---- WhatsApp outreach ---- */
/* One column of cards, not a table. A table would put the message in a cell and the message
   is the point of this screen, so it gets the full width at every size. */
.wa-list{display:flex;flex-direction:column;gap:12px;}
/* One message for a whole campaign, and the area headers that let a day be routed
   geographically. --brand only: this fork is white-labelled and --yellow does not exist. */
.wa-campaign{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  margin-bottom:12px;}
.wa-campaign>summary{cursor:pointer;padding:11px 13px;font-weight:600;}
.wa-campaign-body{padding:0 13px 13px;display:flex;flex-direction:column;gap:9px;min-width:0;}
.wa-campaign-body textarea{width:100%;min-width:0;}
.wa-campaign-actions{display:flex;flex-wrap:wrap;align-items:center;gap:9px;}
.wa-area{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px;margin:16px 0 2px;
  padding-bottom:5px;border-bottom:2px solid var(--brand);}
.wa-area h3{margin:0;font-size:1rem;}
.wa-area .left{color:var(--muted);font-size:.82rem;}
.wa-today{display:inline-block;padding:3px 9px;border-radius:999px;background:var(--brand-soft);
  border:1px solid var(--brand-line);font-size:.8rem;font-weight:600;}
.wa-today.hit{background:var(--brand);}
.wa-card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
         padding:13px 14px;box-shadow:var(--shadow);}
.wa-head{display:flex;flex-wrap:wrap;align-items:flex-start;gap:9px;margin-bottom:9px;}
/* min-width:0 or a long company name stops the row shrinking and the page scrolls sideways. */
.wa-who{flex:1 1 220px;min-width:0;}
.wa-who b{color:var(--ink);}
.wa-who .sm{word-break:break-word;}
.wa-tags{display:flex;flex-wrap:wrap;gap:5px;flex:0 1 auto;}
.wa-msg{width:100%;padding:9px 11px;border:1px solid var(--line);border-radius:8px;
        font:inherit;font-size:13px;color:var(--ink);background:#fff;resize:vertical;line-height:1.5;}
.wa-msg:focus{outline:2px solid var(--brand-line);outline-offset:-1px;}
.wa-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:9px;}
/* Fourteen days of "did I do my ten". Gold is a day that hit the target, faint is a
   day nobody was contacted. */
.wa-rate-strip{display:flex;flex-wrap:wrap;gap:5px;margin:0 0 6px;}
.wa-day{display:flex;flex-direction:column;align-items:center;gap:1px;min-width:44px;
  padding:5px 6px;border:1px solid var(--line);border-radius:var(--radius);
  font-size:.72rem;color:var(--muted);}
.wa-day b{font-size:.95rem;color:var(--ink);}
.wa-day.hit{background:var(--brand-soft);border-color:var(--brand);}
.wa-day.hit b{color:var(--brand-deep,var(--ink));}
.wa-day.none{opacity:.55;}
.wa-tick{display:inline-flex;align-items:center;gap:6px;font-weight:600;cursor:pointer;
  padding:5px 9px;border:1px solid var(--line);border-radius:var(--radius);}
.wa-tick input{width:17px;height:17px;accent-color:var(--brand);}
.wa-tick-none{color:var(--muted);font-weight:500;}
.wa-card-open{color:var(--muted);}
.wa-card-open:hover{color:var(--ink);}
#waIntro{margin:0 0 13px;}

@media (max-width:760px){
  .wa-actions .grow{display:none;}          /* let the link sit next to the buttons, not a row down */
  .wa-tags{width:100%;}
}

/* ---- edit a prospect (drawer) ---- */
/* Behind a disclosure so the card still reads as a summary first. Until this existed a
   mistyped phone number could only be fixed through the API. */
.edit-details > summary{
  cursor:pointer;font-size:12.5px;font-weight:600;color:var(--ink);
  padding:7px 10px;border:1px solid var(--line);border-radius:8px;background:#faf9f4;
  list-style:none;
}
.edit-details > summary::-webkit-details-marker{display:none;}
.edit-details > summary::after{content:" ▾";color:var(--muted);}
.edit-details[open] > summary::after{content:" ▴";}
.edit-details > summary:hover{background:#f2efe4;}
/* A tag is a person's own label, so it reads differently from the classifying fields. */
.pill.tag{background:#f0ecf7;border-color:#ddd4ea;color:#5b4a7d;}
