/* ==========================================================================
   HOT admin console
   --------------------------------------------------------------------------
   Built for one person doing the same thing two hundred times a day: look at a
   listing, decide, move on. Every choice below serves that loop.

   E11 — the tokens now come from the design at ../Hot-CRM, which was itself
   extracted from the mobile app's Figma. So the console, the prototype and the
   phone finally agree on one yellow, one ink and one type scale.

   THE ONE RULE THAT SURVIVED THE RESKIN.
   On the light side of the app, YELLOW ONLY EVER MEANS "YOUR MOVE" — a row
   awaiting a decision, a queue that has waited too long, the primary action.
   Never decoration.

   The dark rail is the exception, and it is a deliberate one: there, yellow is
   also the ACTIVE page, exactly as the prototype has it. The two do not collide
   because they cannot both be read as a call to act — one is where you are, and
   it moves as you navigate. A count that is genuinely due still fills yellow
   against the rail's grey pills, so the signal survives on both sides.
   ========================================================================== */

/* Self-hosted, latin subset only.
   The prototype `@import`s these from Google. A console that fetches a
   stylesheet from a third party on every load has put a third party in the
   request path of the back office — and the fonts stop arriving the first time
   somebody runs it on a restricted network. 249 KB, once, from our own host. */
@font-face{font-family:Outfit;src:url(fonts/Outfit-300.woff2) format('woff2');font-weight:300;font-display:swap}
@font-face{font-family:Outfit;src:url(fonts/Outfit-400.woff2) format('woff2');font-weight:400;font-display:swap}
@font-face{font-family:Outfit;src:url(fonts/Outfit-500.woff2) format('woff2');font-weight:500;font-display:swap}
@font-face{font-family:Outfit;src:url(fonts/Outfit-600.woff2) format('woff2');font-weight:600;font-display:swap}
@font-face{font-family:Outfit;src:url(fonts/Outfit-700.woff2) format('woff2');font-weight:700;font-display:swap}
@font-face{font-family:Poppins;src:url(fonts/Poppins-400.woff2) format('woff2');font-weight:400;font-display:swap}
@font-face{font-family:Poppins;src:url(fonts/Poppins-500.woff2) format('woff2');font-weight:500;font-display:swap}
@font-face{font-family:Poppins;src:url(fonts/Poppins-600.woff2) format('woff2');font-weight:600;font-display:swap}
@font-face{font-family:Montserrat;src:url(fonts/Montserrat-700.woff2) format('woff2');font-weight:700;font-display:swap}
@font-face{font-family:Montserrat;src:url(fonts/Montserrat-800.woff2) format('woff2');font-weight:800;font-display:swap}

:root{
  --paper:#FFFFFF;
  --ground:#FAFAFA;
  --sunk:#F6F6F6;
  --cream:#FFFDE6;

  --ink:#141414;
  --ink-2:#616161;
  --ink-3:#888888;
  --ink-4:#BFBFBF;

  --rule:#E9E9E9;
  --rule-soft:#F1F1F1;

  --mark:#FFEB00;
  --mark-deep:#F0DE06;
  --mark-soft:#FFF797;
  --mark-edge:#E4D400;
  --mark-wash:#FFFDE6;

  /* The rail. Dark, because the prototype is, and because it puts a hard edge
     between "where I am in the product" and "the thing I am working on". */
  --rail-bg:#141414;
  --rail-ink:#FFFFFF;
  --rail-ink-2:#9B9B9B;
  --rail-ink-3:#6E6E6E;
  --rail-rule:#242424;
  --rail-sunk:#1E1E1E;

  --live:#2E9E5B;  --live-wash:#E8F6EE;
  --wait:#9A6B00;  --wait-wash:#FBF2DF;
  --stop:#E5484D;  --stop-wash:#FCEDEE;
  --info:#2B5CE0;  --info-wash:#EAEFFC;

  --sans:Outfit,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  --alt:Poppins,var(--sans);
  --logo:Montserrat,var(--sans);
  --mono:ui-monospace,"SF Mono",Menlo,Consolas,monospace;

  --rail-w:264px;
  --r:10px;
  --r-md:14px;
  --r-lg:22px;
  --shadow:0 1px 2px rgba(20,20,20,.05),0 10px 30px -18px rgba(20,20,20,.18);
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--ground);color:var(--ink);
  font:400 15px/1.5 var(--sans);
  -webkit-font-smoothing:antialiased;
  font-variant-numeric:tabular-nums;   /* times and counts must align in columns */
}
a{color:inherit}
:focus-visible{outline:2px solid var(--info);outline-offset:2px;border-radius:3px}

/* ---------- shell ---------- */
.shell{display:flex;min-height:100vh;align-items:stretch}

/* ---------- the rail ---------- */
.rail{
  width:var(--rail-w);flex:0 0 var(--rail-w);
  background:var(--rail-bg);color:var(--rail-ink);
  display:flex;flex-direction:column;position:sticky;top:0;height:100vh;
}
.rail__brand{display:flex;align-items:center;gap:12px;padding:20px 20px 18px;border-bottom:1px solid var(--rail-rule)}
.rail__mark{
  width:46px;height:46px;border-radius:var(--r-md);background:var(--mark);flex:none;
  display:grid;place-items:center;color:var(--ink);
  font:800 17px/1 var(--logo);letter-spacing:-.5px;
  box-shadow:inset 0 -3px 0 rgba(20,20,20,.14);
}
.rail__name{font:700 21px/1.1 var(--logo);letter-spacing:.5px}
.rail__sub{font:400 11px/1.4 var(--alt);color:var(--rail-ink-3);letter-spacing:.4px;margin-top:1px}

.rail__nav{padding:14px 14px 20px;overflow-y:auto;flex:1}
.rail__nav::-webkit-scrollbar{width:6px}
.rail__nav::-webkit-scrollbar-thumb{background:var(--rail-rule);border-radius:99px}
.rail__group{
  font:600 10.5px/1 var(--sans);letter-spacing:.14em;color:var(--rail-ink-3);
  text-transform:uppercase;padding:18px 10px 8px;
}
.rail__group:first-child{padding-top:4px}

.navlink{
  display:flex;align-items:center;gap:11px;
  padding:10px 12px;border-radius:var(--r);color:var(--rail-ink-2);
  text-decoration:none;font-size:14.5px;font-weight:400;margin-bottom:2px;
}
.navlink:hover{background:var(--rail-sunk);color:var(--rail-ink)}
.navlink__icon{width:18px;height:18px;flex:none;stroke-width:1.8}
.navlink__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Where you are. Yellow, as the prototype has it — and the only place on the
   rail where yellow is not "your move". It moves as you navigate, so it cannot
   be mistaken for something waiting to be done. */
.navlink[aria-current=page]{background:var(--mark);color:var(--ink);font-weight:600}

.navlink__count{
  font:500 11.5px/1 var(--sans);color:var(--rail-ink-2);
  background:var(--rail-sunk);border-radius:99px;padding:4px 9px;
  font-variant-numeric:tabular-nums;
}
.navlink[aria-current=page] .navlink__count{background:rgba(20,20,20,.12);color:var(--ink)}
/* And here it still means "your move": a due count fills yellow against the
   grey pills either side of it, on the active row as well as an inactive one. */
.navlink__count--due{background:var(--mark);color:var(--ink);font-weight:700}
.navlink[aria-current=page] .navlink__count--due{background:var(--ink);color:var(--mark)}

.rail__foot{
  padding:16px 20px;border-top:1px solid var(--rail-rule);
  display:flex;align-items:center;gap:12px;
}
.rail__avatar{
  width:38px;height:38px;border-radius:50%;background:var(--mark);flex:none;
  display:grid;place-items:center;color:var(--ink);font:700 13px/1 var(--sans);
}
.rail__who{min-width:0;flex:1}
.rail__whoname{font-size:14px;font-weight:600;color:var(--rail-ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rail__whorole{font-size:12px;color:var(--rail-ink-3);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rail__out{color:var(--rail-ink-3);font-size:12px;padding:0;background:none;border:0;cursor:pointer}
.rail__out:hover{color:var(--rail-ink)}

.main{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;background:var(--ground)}

/* ---------- the rail, collapsed ----------
   Icons only, at 72px. Labels and counts go, the brand keeps its mark, and the
   section headings go with them — a lone uppercase word over three icons is
   noise. Nothing is hidden with `display:none` that a keyboard needs: the links
   are still there, still focusable, still labelled by their title. */
.is-railed .rail{width:72px;flex:0 0 72px}
.is-railed .rail__brand{padding:20px 13px;justify-content:center}
 /* `> div` would take the HOT mark with the wordmark — they are siblings. */
.is-railed .rail__brand > div:not(.rail__mark),
.is-railed .rail__group,
.is-railed .navlink__label,
.is-railed .navlink__count,
.is-railed .rail__who,
.is-railed .rail__out{display:none}
.is-railed .navlink{justify-content:center;padding:11px 0}
.is-railed .rail__nav{padding:14px 10px}
.is-railed .rail__foot{justify-content:center;padding:16px 0}

/* ---------- topbar ---------- */
.top{
  position:sticky;top:0;z-index:20;background:var(--ground);
  padding:18px 28px 14px;
  display:flex;align-items:center;gap:16px;
}
.top__burger{
  width:40px;height:40px;border-radius:var(--r);background:var(--paper);
  border:1px solid var(--rule);display:grid;place-items:center;color:var(--ink);
  flex:none;cursor:pointer;
}
.top__burger:hover{background:var(--sunk)}
.top__title{font-size:24px;font-weight:600;letter-spacing:-.02em;margin:0;line-height:1.2}
.top__crumb{font:400 13px/1.4 var(--sans);color:var(--ink-3);margin-top:2px;order:2}
.top__heading{display:flex;flex-direction:column}
.top__actions{margin-left:auto;display:flex;gap:10px;align-items:center}

.top__search{position:relative;flex:0 1 420px;min-width:180px}
.top__search input{
  width:100%;font:400 14px/1.4 var(--sans);color:var(--ink);
  background:var(--paper);border:1px solid var(--rule);border-radius:99px;
  padding:10px 16px 10px 40px;
}
.top__search input::placeholder{color:var(--ink-3)}
.top__search input:focus{outline:none;border-color:var(--ink-4);box-shadow:0 0 0 3px rgba(20,20,20,.05)}
.top__search svg{position:absolute;left:14px;top:11px;width:16px;height:16px;color:var(--ink-3)}

.top__bell{
  width:40px;height:40px;border-radius:50%;background:var(--paper);border:1px solid var(--rule);
  display:grid;place-items:center;color:var(--ink);position:relative;flex:none;cursor:pointer;
}
.top__bell:hover{background:var(--sunk)}
.top__bell[data-unread]::after{
  content:"";position:absolute;top:9px;right:11px;width:7px;height:7px;border-radius:50%;
  background:var(--mark);border:1.5px solid var(--paper);
}

.page{padding:6px 28px 72px;max-width:1420px;width:100%}

/* ---------- type ---------- */
h2.sec{font-size:17px;font-weight:600;letter-spacing:-.015em;margin:0 0 12px}
.eyebrow{font:600 10.5px/1 var(--sans);letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);margin-bottom:9px}
.muted{color:var(--ink-2)}
.dim{color:var(--ink-3)}
.mono{font-family:var(--mono);font-size:.92em}
.num{font-family:var(--mono);font-variant-numeric:tabular-nums}

/* ---------- surfaces ---------- */
.panel{background:var(--paper);border:1px solid var(--rule);border-radius:var(--r-lg);box-shadow:var(--shadow)}
.panel__head{padding:18px 22px 14px;border-bottom:1px solid var(--rule-soft);display:flex;align-items:center;gap:12px}
.panel__body{padding:20px 22px}
.panel__foot{padding:14px 22px;border-top:1px solid var(--rule-soft);display:flex;align-items:center;gap:10px}

.grid{display:grid;gap:16px}
.grid--3{grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}
.grid--4{grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}
 /* Six across, as the design has it — twelve counts in two rows of six. An
    auto-fit would put seven on a wide screen and leave five stranded below,
    which reads as a list that ran out rather than a grid. */
.grid--6{grid-template-columns:repeat(6,minmax(0,1fr))}
@media (max-width:1240px){.grid--6{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media (max-width:820px){.grid--6{grid-template-columns:repeat(2,minmax(0,1fr))}}
.grid--2{grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
/* Two panels that are not equals. The bar chart carries eight months and the
   donut carries two numbers; an even split wastes the one that needs room. */
.grid--wide{grid-template-columns:1.35fr 1fr}
.grid--narrow{grid-template-columns:1fr 1.8fr}
@media (max-width:1100px){
  .grid--wide,.grid--narrow{grid-template-columns:1fr}
}

/* ---------- stat ---------- */
.stat{background:var(--paper);border:1px solid var(--rule);border-radius:var(--r-lg);padding:20px 22px;position:relative}
.stat__icon{width:40px;height:40px;border-radius:var(--r);background:var(--mark-wash);
  display:grid;place-items:center;color:var(--ink);margin-bottom:16px}
.stat__value{font-size:32px;font-weight:600;letter-spacing:-.03em;line-height:1.1;font-variant-numeric:tabular-nums}
.stat__label{font:400 14px/1.4 var(--sans);color:var(--ink-3);margin-top:2px}
.stat__note{font-size:13px;color:var(--ink-2);margin-top:4px}
.stat__delta{position:absolute;top:20px;right:22px;font:500 12px/1 var(--sans);
  background:var(--sunk);color:var(--ink-2);border-radius:99px;padding:6px 10px}

/* The one tile that is the headline. Inverted, like the prototype's first card. */
.stat--lead{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.stat--lead .stat__label{color:var(--ink-4)}
.stat--lead .stat__icon{background:rgba(255,255,255,.08);color:var(--mark)}
.stat--lead .stat__delta{background:var(--mark);color:var(--ink);font-weight:600}

/* Still "your move": a tile with work behind it. */
.stat--due{border-color:var(--mark-edge);background:var(--mark-wash)}

/* The small tiles under the headline row — a count and a dot, nothing else. */
.tile{background:var(--paper);border:1px solid var(--rule);border-radius:var(--r-md);padding:16px 18px}
.tile__value{font-size:22px;font-weight:600;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.tile__label{display:flex;align-items:center;gap:7px;font-size:13px;color:var(--ink-2);margin-top:3px}
.tile__dot{width:8px;height:8px;border-radius:50%;background:var(--ink-4);flex:none}
.tile__dot--mark{background:var(--mark)}
.tile__dot--ink{background:var(--ink)}

/* ---------- buttons ---------- */
.btn{
  appearance:none;border:1px solid var(--rule);background:var(--paper);color:var(--ink);
  font:500 14px/1 var(--sans);padding:11px 18px;border-radius:99px;cursor:pointer;
  display:inline-flex;align-items:center;gap:6px;white-space:nowrap;text-decoration:none;
  transition:background .12s ease,border-color .12s ease,transform .06s ease;
}
.btn:hover{background:var(--sunk);border-color:var(--ink-3)}
.btn:active{transform:translateY(.5px)}
.btn[disabled]{opacity:.45;cursor:not-allowed}
.btn--primary{background:var(--mark);border-color:var(--mark);font-weight:600}
.btn--primary:hover{background:var(--mark-deep);border-color:var(--mark-deep)}
.btn--go{background:var(--live);border-color:var(--live);color:#fff}
.btn--go:hover{background:#106A31;border-color:#106A31}
.btn--stop{background:var(--stop);border-color:var(--stop);color:#fff}
.btn--stop:hover{background:#A50019;border-color:#A50019}
/* Destructive actions sitting in a list are quiet. A row is not a warning, and
   red on every row competes with the yellow that means "your move". The colour
   is spent once — on the confirm button, where the damage actually happens. */
.btn--danger-quiet{background:var(--paper);border-color:var(--rule);color:var(--ink-2);font-weight:600}
.btn--danger-quiet:hover{background:var(--stop-wash);border-color:#F0B8C2;color:var(--stop)}
.btn--quiet{border-color:transparent;background:transparent;color:var(--ink-2)}
.btn--quiet:hover{background:var(--sunk);color:var(--ink)}
.btn--sm{padding:7px 13px;font-size:12.5px}
.btn__key{font:600 9.5px/1 var(--mono);border:1px solid currentColor;opacity:.5;border-radius:3px;padding:2px 4px}

/* ---------- inputs ---------- */
.field{display:flex;flex-direction:column;gap:5px}
.field__label{font:500 13px/1 var(--sans);color:var(--ink-2)}
.input,.select,.textarea{
  font:400 14px/1.4 var(--sans);color:var(--ink);background:var(--paper);
  border:1px solid var(--rule);border-radius:var(--r);padding:11px 14px;width:100%;
}
.input::placeholder{color:var(--ink-3)}
.input:focus,.select:focus,.textarea:focus{border-color:var(--ink);outline:none;box-shadow:0 0 0 3px rgba(20,20,20,.06)}
.textarea{min-height:84px;resize:vertical}
.field__hint{font-size:11.5px;color:var(--ink-3)}
.field__error{font-size:11.5px;color:var(--stop);font-weight:600}

/* ---------- tags ---------- */
.tag{display:inline-flex;align-items:center;gap:5px;font:600 11px/1 var(--sans);letter-spacing:.02em;
  padding:6px 11px;border-radius:99px;border:1px solid transparent;white-space:nowrap}
.tag--live{background:var(--live-wash);color:var(--live);border-color:#C6E4D0}
.tag--wait{background:var(--wait-wash);color:var(--wait);border-color:#EBD9AE}
.tag--stop{background:var(--stop-wash);color:var(--stop);border-color:#F3C9D1}
.tag--info{background:var(--info-wash);color:var(--info);border-color:#C9D6F7}
.tag--flat{background:var(--sunk);color:var(--ink-2);border-color:var(--rule)}
/* The design's two solid chips: yellow for a sale or an open home, ink for a
   rental, a private inspection or an off-market listing. They are categories
   rather than states, which is why neither is the "your move" yellow — that one
   is `.tag--due`, and it is filled with the same colour on purpose: a chip you
   must act on and a chip that merely says "rental" are told apart by WHERE they
   are, in a column of their own, every row carrying one. */
.tag--mark{background:var(--mark);color:var(--ink);border-color:var(--mark)}
.tag--ink{background:var(--ink);color:var(--paper);border-color:var(--ink)}

/* Listing photographs, at a size for checking rather than for admiring: a
   moderator is asking "is this the right property and is anything in shot that
   should not be", which needs a legible thumbnail, not a hero image. */
.thumb{width:132px;height:99px;object-fit:cover;border-radius:var(--r);border:1px solid var(--rule);background:var(--sunk);display:block}
.tag--due{background:var(--mark);color:var(--ink);border-color:var(--mark-edge)}

/* ---------- table (hand built — no datatables package) ---------- */
.tablewrap{background:var(--paper);border:1px solid var(--rule);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--shadow)}
.tablescroll{overflow-x:auto}
table.t{width:100%;border-collapse:collapse;font-size:14px}
table.t th{
  text-align:left;font:600 11px/1 var(--sans);letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink-3);padding:15px 20px;background:var(--paper);
  border-bottom:1px solid var(--rule);white-space:nowrap;
}
table.t th[aria-sort]{cursor:pointer;user-select:none}
table.t th[aria-sort]:hover{color:var(--ink)}
table.t th[aria-sort=ascending]::after{content:" ↑";color:var(--mark-edge)}
table.t th[aria-sort=descending]::after{content:" ↓";color:var(--mark-edge)}
table.t td{padding:16px 20px;border-bottom:1px solid var(--rule-soft);vertical-align:middle}
table.t tbody tr:last-child td{border-bottom:0}
table.t tbody tr:hover{background:var(--sunk)}
table.t tbody tr[data-due=true]{box-shadow:inset 3px 0 0 var(--mark)}
.t__primary{font-weight:600}
.t__sub{font-size:11.5px;color:var(--ink-3);margin-top:1px}
.t__actions{text-align:right;white-space:nowrap}

/* ---------- SIGNATURE: the wait bar --------------------------------------
   A queue is ordered by how long someone has been waiting, so the row's own
   underline carries that fact. Hairline at zero, yellow as it approaches the
   service target, red past it. The numeric age is still printed beside it —
   the bar is redundant encoding, which is what makes it safe.
   ------------------------------------------------------------------------ */
.wait{display:inline-flex;align-items:center;gap:9px}
.wait__num{font:600 11.5px/1 var(--mono);color:var(--ink-2);min-width:34px}
.wait__track{position:relative;flex:0 0 auto;width:72px;height:2px;background:var(--rule-soft);border-radius:2px;overflow:hidden}
.wait__fill{position:absolute;inset:0 auto 0 0;background:var(--rule);border-radius:2px}
.wait[data-state=near] .wait__fill{background:var(--mark-edge)}
.wait[data-state=near] .wait__num{color:var(--wait)}
.wait[data-state=over] .wait__fill{background:var(--stop)}
.wait[data-state=over] .wait__num{color:var(--stop);font-weight:700}

/* ---------- empty ---------- */
.empty{padding:44px 20px;text-align:center}
.empty__title{font-weight:700;font-size:14px}
.empty__body{color:var(--ink-2);font-size:13px;margin-top:4px;max-width:44ch;margin-inline:auto}
.empty__action{margin-top:14px}

/* ---------- toast (replaces alert) ---------- */
.toasts{position:fixed;right:18px;bottom:18px;z-index:60;display:flex;flex-direction:column;gap:8px;width:330px;max-width:calc(100vw - 36px)}
.toast{
  background:var(--paper);border:1px solid var(--rule);border-left:3px solid var(--ink-3);
  border-radius:var(--r);box-shadow:0 6px 20px rgba(10,10,10,.10);padding:11px 13px;
  display:flex;gap:10px;align-items:flex-start;
  animation:toast-in .16s cubic-bezier(.2,.7,.3,1);
}
.toast--go{border-left-color:var(--live)}
.toast--stop{border-left-color:var(--stop)}
.toast--due{border-left-color:var(--mark-edge)}
.toast__body{flex:1;min-width:0}
.toast__title{font-weight:700;font-size:12.5px}
.toast__text{font-size:12px;color:var(--ink-2);margin-top:1px;overflow-wrap:anywhere}
.toast__close{border:0;background:none;color:var(--ink-3);cursor:pointer;font-size:15px;line-height:1;padding:0 2px}
.toast__close:hover{color:var(--ink)}
.toast.is-leaving{animation:toast-out .14s ease forwards}
@keyframes toast-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
@keyframes toast-out{to{opacity:0;transform:translateY(4px)}}

/* ---------- modal (replaces confirm) ---------- */
dialog.modal{
  border:0;padding:0;background:transparent;max-width:min(94vw,460px);width:100%;
  color:var(--ink);
}
dialog.modal::backdrop{background:rgba(10,10,10,.34);backdrop-filter:blur(1.5px)}
.modal__card{background:var(--paper);border:1px solid var(--rule);border-radius:10px;
  box-shadow:0 16px 48px rgba(10,10,10,.18);overflow:hidden;
  animation:modal-in .15s cubic-bezier(.2,.7,.3,1)}
.modal__head{padding:15px 18px 0}
.modal__title{font-size:15px;font-weight:800;letter-spacing:-.015em;margin:0}
.modal__body{padding:8px 18px 16px;font-size:13px;color:var(--ink-2);white-space:pre-line}
/* A form modal stacks .field blocks; the body's pre-line is for prose, not for
   a control's whitespace, and two adjacent fields need air between them. */
.modal__body .field{white-space:normal}
.modal__body .field + .field{margin-top:12px}
.modal__foot{padding:12px 18px;background:var(--sunk);border-top:1px solid var(--rule-soft);
  display:flex;justify-content:flex-end;gap:8px}
@keyframes modal-in{from{opacity:0;transform:translateY(-6px) scale(.99)}to{opacity:1;transform:none}}

/* ---------- misc ---------- */
.row{display:flex;align-items:center;gap:8px}
.row--wrap{flex-wrap:wrap}
.spacer{flex:1}
.hr{height:1px;background:var(--rule-soft);border:0;margin:16px 0}
.chip{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--rule);background:var(--paper);
  border-radius:99px;padding:4px 10px;font-size:12px;cursor:pointer}
.chip:hover{background:var(--sunk)}
.chip[aria-pressed=true]{background:var(--mark);border-color:var(--mark-edge);font-weight:700}
.is-busy{opacity:.55;pointer-events:none}
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

@media (max-width:900px){
  .shell{flex-direction:column}
  .rail{width:100%;flex:none;height:auto;position:static;flex-direction:row;align-items:center;overflow-x:auto}
  .rail__nav{display:flex;gap:4px;padding:8px}
  .rail__group,.rail__foot{display:none}
  .page{padding:16px}
}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;transition-duration:.001ms!important}
}

/* ---------- settings ---------- */
.setting{display:flex;gap:20px;align-items:flex-start;padding:14px 16px;border-bottom:1px solid var(--rule-soft)}
.setting:last-child{border-bottom:0}
.setting__main{flex:1;min-width:0}
.setting__label{display:block;font-weight:650;font-size:13.5px;cursor:pointer}
.setting__desc{margin:3px 0 0;font-size:12.5px;color:var(--ink-2);line-height:1.5;max-width:62ch}
.setting__control{flex:0 0 268px;max-width:268px}
.setting__hint{margin:5px 0 0;font-size:11.5px;color:var(--ink-3)}

/* Toggle. A button with role=switch, so it is keyboard-operable without a
   checkbox we would then have to fight to restyle. */
.toggle{position:relative;width:42px;height:24px;border-radius:99px;border:1px solid var(--rule);
  background:var(--sunk);cursor:pointer;padding:0;transition:background .14s ease,border-color .14s ease}
.toggle__knob{position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;
  background:#fff;border:1px solid var(--rule);transition:transform .14s cubic-bezier(.2,.7,.3,1)}
.toggle[aria-checked=true]{background:var(--mark);border-color:var(--mark-edge)}
.toggle[aria-checked=true] .toggle__knob{transform:translateX(18px);border-color:var(--mark-edge)}

/* Simulation banner. Not dismissible on purpose — a simulated provider accepts
   a credential anyone can write, so it must never be quietly forgotten. */
.banner{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:11px 15px;
  border-radius:var(--r);margin-bottom:18px;font-size:13px}
.banner b{font-size:12.5px}
.banner--sim{background:var(--mark-wash);border:1px solid var(--mark-edge)}
.banner--sim a{margin-left:auto;font-weight:650;color:var(--ink)}

/* ---------- staff sign-in ---------- */
/* ---------- sign in ----------
   Built to ../Hot-CRM/index.html. The split is the design's: a yellow half
   carrying the product's promise and a white half carrying the form. It is the
   one console screen somebody sees before they are anybody, so it is the one
   that has to look like the product rather than like a tool. */

.login-shell{display:flex;min-height:100vh}

.login-hero{
  flex:1.05;background:var(--mark);position:relative;overflow:hidden;
  display:flex;flex-direction:column;justify-content:space-between;padding:56px;
}
/* Two rings, bled off opposite corners. Pseudo-elements rather than images:
   they scale to any viewport, cost nothing to load, and print as flat colour. */
.login-hero::before{
  content:"";position:absolute;top:-90px;left:-90px;width:280px;height:280px;
  border-radius:50%;border:44px solid rgba(255,255,255,.35);
}
.login-hero::after{
  content:"";position:absolute;inset:auto -140px -160px auto;width:460px;height:460px;
  border-radius:50%;border:56px solid rgba(20,20,20,.06);
}

.hero-tagline{position:relative;z-index:1}
.hero-kicker{font:500 15px/1 var(--logo);letter-spacing:2.5px;text-transform:uppercase;
  color:var(--ink);opacity:.75;margin:0}
.hero-logo{font:800 clamp(64px,9vw,104px)/1 var(--logo);letter-spacing:-2px;margin:10px 0 18px}
.hero-line{font:400 17px/1.5 var(--alt);max-width:340px;color:var(--ink-2);margin:0}

.hero-cards{position:relative;z-index:1;display:flex;gap:14px;flex-wrap:wrap}
.hero-chip{
  background:var(--paper);border-radius:999px;padding:10px 18px;font-size:13px;font-weight:500;
  box-shadow:0 8px 22px -12px rgba(20,20,20,.35);display:flex;align-items:center;gap:8px;
}
.hero-chip .dot{width:8px;height:8px;border-radius:50%;background:var(--ink)}

.login-panel{flex:1;display:flex;align-items:center;justify-content:center;
  padding:40px 24px;background:var(--paper)}
.login-card{width:100%;max-width:400px}
.login-card .brand{display:flex;align-items:center;gap:12px;margin-bottom:36px}
.brand-mark{
  width:46px;height:46px;border-radius:var(--r-md);background:var(--mark);flex:none;
  display:grid;place-items:center;color:var(--ink);
  font:800 17px/1 var(--logo);letter-spacing:-.5px;
  box-shadow:inset 0 -3px 0 rgba(20,20,20,.14);
}
.brand-name{font:700 21px/1.1 var(--logo);letter-spacing:.5px}
.brand-sub{font:400 11px/1.4 var(--alt);color:var(--ink-3);letter-spacing:.4px;margin-top:1px}

.login-title{font-size:27px;font-weight:600;letter-spacing:-.3px;margin:0}
.login-sub{font:400 13px/1.55 var(--alt);color:var(--ink-2);margin:6px 0 30px}

/* The asterisk is red and small — required is a fact about the field, not a
   warning about the person. */
.login-card .field__label em{color:var(--stop);font-style:normal;margin-left:1px}

.remember-row{display:flex;justify-content:space-between;align-items:center;
  margin:4px 0 24px;font-size:13px;color:var(--ink-2)}
.remember-row label{display:flex;gap:8px;align-items:center;cursor:pointer}
.remember-row input{accent-color:var(--ink);width:15px;height:15px}
.link{font-weight:500;color:var(--ink);border-bottom:1px solid var(--mark-deep);text-decoration:none}

.btn-block{width:100%;justify-content:center}

.otp-note{
  margin:22px 0 0;background:var(--mark-wash);border:1px solid var(--mark-soft);
  border-radius:var(--r-md);padding:12px 16px;font-size:12.5px;line-height:1.5;color:var(--ink-2);
  display:flex;gap:10px;align-items:flex-start;
}
.otp-note svg{flex:none;margin-top:2px}

.login-foot{margin:28px 0 0;font:400 12px/1.5 var(--alt);color:var(--ink-3);text-align:center}

.signin__error{margin:0 0 16px;padding:10px 13px;border-radius:var(--r);font-size:13px;
  background:var(--stop-wash);border:1px solid #F3C9D1;color:var(--stop)}

/* One column below the split's natural width: the hero is decoration, and a
   400px form squeezed beside a 200px stripe of yellow serves nobody. */
@media (max-width:860px){
  .login-shell{display:block}
  .login-hero{display:none}
  .login-panel{min-height:100vh}
}

/* Sticky save bar. The page reserves space for it, otherwise it covers the last
   rows of the form — which is exactly where the most consequential settings sit. */
.savebar{position:sticky;bottom:0;display:flex;align-items:center;gap:10px;
  padding:12px 16px;margin:0 -16px -44px;background:var(--paper);
  border-top:1px solid var(--rule);box-shadow:0 -6px 18px rgba(10,10,10,.05);z-index:10}
.savebar .dim{font-size:12.5px}
.page:has(.savebar){padding-bottom:96px}

/* ---------- user detail rows ---------- */
.urow{display:flex;gap:14px;align-items:baseline;padding:9px 16px;border-bottom:1px solid var(--rule-soft);font-size:13px}
.urow:last-child{border-bottom:0}
.urow__label{flex:0 0 116px;color:var(--ink-3);font-size:11.5px;text-transform:uppercase;letter-spacing:.06em;font-weight:700}
.urow__value{flex:1;min-width:0;overflow-wrap:anywhere}
.banner--stop{background:var(--stop-wash);border:1px solid #F3C9D1}
.banner--stop b{color:var(--stop)}
/* Laravel's paginator markup */
.panel__foot nav{display:flex;gap:6px;align-items:center;font-size:12.5px}
.panel__foot nav a,.panel__foot nav span{padding:4px 9px;border:1px solid var(--rule);border-radius:var(--r);text-decoration:none}
.panel__foot nav [aria-current]{background:var(--mark);border-color:var(--mark-edge);font-weight:700}

.t__link{color:inherit;text-decoration:none}
.t__link:hover{text-decoration:underline;text-underline-offset:2px;text-decoration-color:var(--mark-edge);text-decoration-thickness:2px}

/* ---------- keyboard hints -----------------------------------------------
   The review screen is the one place in this console where the keyboard is the
   primary interface — a moderator makes the same decision two hundred times a
   day, and reaching for the mouse between each one is most of the work. The
   hint has to be visible without competing with the decision it describes. */
kbd{
  font:600 10.5px/1 var(--mono);background:var(--sunk);border:1px solid var(--rule);
  border-bottom-width:2px;border-radius:4px;padding:2px 5px;color:var(--ink-2)
}
[aria-invalid=true]{border-color:var(--stop);box-shadow:0 0 0 3px var(--stop-wash)}

/* ---------- dashboard: charts, hand drawn ---------- */
/* No charting library. House rule, and the right call anyway: a stacked pair of
   rounded bars is thirty lines of markup, and a library would be 90 KB and a
   supply-chain dependency in the back office for one picture. */

.legend{display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--ink-2);margin-left:14px}
.legend__key{width:11px;height:11px;border-radius:3px;flex:none}
.legend__key--mark{background:var(--mark)}
.legend__key--ink{background:var(--ink)}

.bars{display:flex;align-items:flex-end;gap:10px;justify-content:space-between}
.bars__col{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;gap:8px}
.bars__stack{width:100%;max-width:46px;display:flex;flex-direction:column;justify-content:flex-end}
.bars__seg{width:100%;border-radius:8px;min-height:0}
/* The two segments meet, so only the outer corners are round — otherwise the
   join reads as two separate bars that happen to touch. */
.bars__seg--ink{background:var(--ink);border-radius:8px 8px 0 0}
.bars__seg--mark{background:var(--mark);border-radius:0 0 8px 8px}
.bars__seg--ink:only-child,.bars__seg--mark:only-child{border-radius:8px}
.bars__label{font-size:12.5px;color:var(--ink-3)}
.bars__total{font-size:12px;color:var(--ink-4);min-height:1em}

.donut{display:flex;align-items:center;gap:26px;flex-wrap:wrap}
.donut__n{font:600 26px var(--sans);fill:var(--ink)}
.donut__c{font:400 12px var(--sans);fill:var(--ink-3)}
.donut__keys{display:flex;flex-direction:column;gap:10px}
.donut__key{display:flex;align-items:center;gap:9px;font-size:14px;color:var(--ink-2)}
.donut__key b{margin-left:auto;color:var(--ink);font-weight:600}

.meter{display:grid;grid-template-columns:130px 1fr auto;align-items:center;gap:14px;margin-bottom:12px}
.meter:last-child{margin-bottom:0}
.meter__label{font-size:13.5px;color:var(--ink-2)}
.meter__track{height:10px;border-radius:99px;background:var(--sunk);overflow:hidden}
.meter__fill{height:100%;border-radius:99px;min-width:2px}
.meter__fill--mark{background:var(--mark)}
.meter__fill--ink{background:var(--ink)}
.meter__value{font-size:13px;color:var(--ink);font-weight:600}

.when{display:flex;align-items:center;gap:14px;padding:12px 0;border-bottom:1px solid var(--rule-soft)}
.when:last-child{border-bottom:0;padding-bottom:0}
.when:first-child{padding-top:0}
.when__chip{width:48px;height:48px;border-radius:var(--r);background:var(--mark-wash);
  display:grid;place-items:center;flex:none;line-height:1.1}
.when__day{font-size:16px;font-weight:600}
.when__mon{font:600 9.5px/1 var(--sans);letter-spacing:.1em;color:var(--ink-3)}
.when__what{flex:1;min-width:0}
.when__where{font-size:14.5px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.when__meta{font-size:12.5px;color:var(--ink-3);margin-top:2px}

/* ---------- long forms ----------
   The design's shape for a create screen: one card, numbered sections divided
   by a hairline, and a sticky-feeling footer carrying the two decisions. */

.formcard{background:var(--paper);border:1px solid var(--rule);border-radius:var(--r-lg);
  box-shadow:var(--shadow);padding:8px 30px 0;max-width:1180px}

.fsection{display:flex;align-items:flex-start;gap:14px;padding:30px 0 20px}
.fsection + .fgrid,.fsection + .chips{margin-bottom:4px}
.fsection__n{width:30px;height:30px;border-radius:9px;background:var(--mark);flex:none;
  display:grid;place-items:center;font:600 14px/1 var(--sans);color:var(--ink)}
.fsection__title{font-size:19px;font-weight:600;letter-spacing:-.015em;margin:2px 0 0}
.fsection__sub{margin:3px 0 0;font-size:13.5px;color:var(--ink-3)}
/* The divider belongs to the section that FOLLOWS, so the first one has none
   and the footer is not double-ruled. */
.fsection:not(:first-child){border-top:1px solid var(--rule-soft);margin-top:12px}

.fgrid{display:grid;grid-template-columns:1fr 1fr;gap:18px 24px;padding-bottom:8px}
.fgrid--3{grid-template-columns:repeat(3,1fr)}
.fgrid__full{grid-column:1/-1}
@media (max-width:820px){.fgrid,.fgrid--3{grid-template-columns:1fr}}

.formcard__foot{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  margin:26px -30px 0;padding:18px 30px;background:var(--sunk);
  border-top:1px solid var(--rule);border-radius:0 0 var(--r-lg) var(--r-lg)}

/* ---------- chips, segment, switch ---------- */
/* All three are radio/checkbox inputs with the box hidden and the label styled,
   so they arrive with the form, work without JavaScript, and are reachable by
   keyboard. `:focus-visible` is on the input and drawn on the label beside it. */
.chips{display:flex;gap:12px;flex-wrap:wrap}
.chip{position:relative;display:inline-flex;align-items:center;cursor:pointer}
.chip input{position:absolute;opacity:0;width:0;height:0}
.chip span{border:1px solid var(--rule);background:var(--paper);border-radius:999px;
  padding:11px 20px;font-size:14px;font-weight:500}
.chip input:checked + span{background:var(--mark);border-color:var(--mark);font-weight:600}
.chip input:focus-visible + span{box-shadow:0 0 0 3px rgba(20,20,20,.12)}

.segment{display:inline-flex;background:var(--sunk);border-radius:999px;padding:5px;gap:4px}
.segment__opt{position:relative;display:inline-flex;cursor:pointer;flex:1}
.segment__opt input{position:absolute;opacity:0;width:0;height:0}
.segment__opt span{flex:1;text-align:center;border-radius:999px;padding:9px 18px;
  font-size:14px;font-weight:500;color:var(--ink-2)}
.segment__opt input:checked + span{background:var(--ink);color:var(--mark);font-weight:600}
.segment__opt input:focus-visible + span{box-shadow:0 0 0 3px rgba(20,20,20,.12)}

.switch{display:flex;align-items:center;gap:14px;border:1px solid var(--rule);
  background:var(--paper);border-radius:var(--r-md);padding:16px 18px;cursor:pointer}
.switch__txt{flex:1;display:flex;flex-direction:column;gap:2px}
.switch__txt b{font-size:14.5px;font-weight:600}
.switch__txt span{font-size:12.5px;color:var(--ink-3)}
.switch input{position:absolute;opacity:0;width:0;height:0}
.switch__track{width:46px;height:26px;border-radius:999px;background:var(--ink-4);
  flex:none;padding:3px;transition:background .15s ease}
.switch__knob{display:block;width:20px;height:20px;border-radius:50%;background:var(--paper);
  transition:transform .15s ease}
.switch input:checked ~ .switch__track{background:var(--ink)}
.switch input:checked ~ .switch__track .switch__knob{transform:translateX(20px);background:var(--mark)}
.switch input:focus-visible ~ .switch__track{box-shadow:0 0 0 3px rgba(20,20,20,.12)}

/* ---------- upload ---------- */
.avatarrow{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.avatarrow__mark{width:64px;height:64px;border-radius:20px;background:var(--mark);flex:none;
  display:grid;place-items:center;font:700 20px/1 var(--sans);color:var(--ink);overflow:hidden}
.avatarrow__mark img{width:100%;height:100%;object-fit:cover}
.upload{flex:1;min-width:220px;display:flex;flex-direction:column;align-items:center;gap:6px;
  padding:18px 20px;border:1.5px dashed var(--mark-soft);border-radius:var(--r-md);
  background:var(--mark-wash);cursor:pointer;text-align:center}
.upload:hover{border-color:var(--mark-deep)}
.upload b{font-size:14.5px;font-weight:600}
.upload span:not(.upload__ico){font-size:12.5px;color:var(--ink-3)}
.upload__ico{width:42px;height:42px;border-radius:50%;background:var(--mark);
  display:grid;place-items:center;color:var(--ink)}
.upload:focus-within{outline:2px solid var(--ink);outline-offset:2px}

.rulenote{display:flex;gap:10px;align-items:flex-start;margin:18px 0 0;
  background:var(--mark-wash);border:1px solid var(--mark-soft);border-radius:var(--r-md);
  padding:14px 16px;font-size:13px;line-height:1.55;color:var(--ink-2)}
.rulenote svg{flex:none;margin-top:2px}

.field__hint{font-size:12.5px;color:var(--ink-3);line-height:1.45}

/* A one-line confirmation after a redirect. Not a toast: a toast belongs to an
   action that happened on the screen you are still looking at, and this one
   survives a navigation on purpose — the person is somewhere new and needs to
   know the last thing worked. */
.flash{margin:0 0 14px;padding:12px 16px;border-radius:var(--r-md);font-size:13.5px;
  background:var(--live-wash);border:1px solid #C6E4D0;color:var(--live)}

/* Fields that belong to one chip. `:has()` rather than a class toggled by
   script: the inputs are in the form whichever chip is chosen, so the page
   submits correctly before any JavaScript has run and keeps doing so without
   it. Hidden fields are also `disabled` by the same rule below, so a licence
   typed and then switched away from is not silently submitted. */
.agentonly{display:none}
.formcard:has(input[name="profile"][value="agent"]:checked) .agentonly{display:grid}

/* ---------- input group, typeahead, removable chips ---------- */
.inputgroup{display:flex;align-items:stretch}
.inputgroup__addon{display:flex;align-items:center;padding:0 14px;font-size:13.5px;color:var(--ink-3);
  background:var(--sunk);border:1px solid var(--rule);border-right:0;border-radius:var(--r) 0 0 var(--r)}
.inputgroup .input{border-radius:0 var(--r) var(--r) 0}

.typeahead-anchor{position:relative}
.typeahead{position:absolute;top:calc(100% + 4px);left:0;z-index:30;min-width:280px;
  max-height:260px;overflow:auto;
  background:var(--paper);border:1px solid var(--rule);border-radius:var(--r-md);box-shadow:var(--shadow)}
.typeahead__opt{display:block;width:100%;text-align:left;padding:10px 14px;font-size:13.5px;
  background:none;border:0;cursor:pointer;color:var(--ink)}
.typeahead__opt:hover,.typeahead__opt:focus-visible{background:var(--mark-wash);outline:none}
.typeahead__none{padding:12px 14px;font-size:13px;color:var(--ink-3)}
/* `.field` holds the label, the control and the hint, so anchoring a dropdown
   to it puts the dropdown at the FIELD's origin — above the input, over the
   label. `.typeahead-anchor` wraps just the input, which is the box the list
   should hang off. */

.chip--area span{display:inline-flex;align-items:center;gap:8px;background:var(--mark-wash);
  border-color:var(--mark-soft)}
.chip__x{border:0;background:none;cursor:pointer;color:var(--ink-3);font-size:12px;line-height:1;padding:0}
.chip__x:hover{color:var(--stop)}

/* ---------- listing form ---------- */
.inputgroup__addon--end{border-left:0;border-right:1px solid var(--rule);
  border-radius:0 var(--r) var(--r) 0}
.inputgroup:has(.inputgroup__addon--end) .input{border-radius:var(--r) 0 0 var(--r)}

.textarea{min-height:110px;resize:vertical;font-family:var(--sans)}

/* The count chips are narrower than the profile chips and read as one row. */
.chip--count span{padding:9px 16px;font:600 12px/1 var(--sans);letter-spacing:.03em}

.upload--wide{padding:34px 20px}
.upload--over{border-color:var(--ink);background:var(--mark-soft)}
.upload--full{opacity:.55;pointer-events:none}

.thumbs{display:flex;gap:12px;flex-wrap:wrap;margin:14px 0 4px}
.thumb{width:110px;height:82px;border-radius:var(--r);border:1px dashed var(--rule);
  background:var(--sunk);display:grid;place-items:center;font-size:11.5px;color:var(--ink-3);
  overflow:hidden;flex:none}
.thumb--has{border-style:solid;background:var(--paper)}
.thumb--has img{width:100%;height:100%;object-fit:cover}

/* ---------- fields that belong to an answer ----------
   Driven by `:has()` on the form, not by script: the controls are in the DOM
   whichever option is chosen, so the page is correct before any JavaScript has
   run and stays correct without it. Hidden fields still POST — the server
   clears what does not apply (a sale has no furnishing) rather than trusting
   the browser to have withheld it. */

.agencyonly,.rentalonly,.virtualonly{display:none}
.salesonly{display:inline}
#listingform:has(input[name="mode"][value="rental"]:checked) .salesonly{display:none}
#listingform:has(input[name="mode"][value="rental"]:checked) span.rentalonly{display:inline !important}

/* An agency belongs to an agent. A landlord has none. */
#listingform:has(input[name="listedByOwner"][value="0"]:checked) .agencyonly{display:flex}

/* Furnishing is a question about a rental. */
#listingform:has(input[name="mode"][value="rental"]:checked) .rentalonly{display:block}

/* A virtual inspection needs somewhere to attend. */
#listingform:has(input[name="inspectionType"][value="virtual"]:checked) .virtualonly{display:flex}

/* ---------- the Schedule Inspection form (S11.11) ----------
   Same `:has()` arrangement as the listing form, for the same reason: the
   controls are all in the DOM whichever type is chosen, so the page is right
   before any script has run and stays right without one. */

/* Three options do not fit on one line as pills at the deck's wording, so this
   segment wraps into a grid rather than squeezing "OFI / Open Home — public
   drop-in" into a chip nobody can read. */
.segment--3{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));width:100%;border-radius:var(--r)}
.segment--3 .segment__opt span{border-radius:calc(var(--r) - 3px);white-space:normal;line-height:1.3}

/* One note per type, and only the chosen one is shown. All three ship in the
   markup so the note is never a fetch, and never briefly absent. */
.rule-note{display:none;margin:0;padding:11px 13px;border-radius:var(--r);
  background:var(--mark-wash,#FFFCE8);border:1px solid var(--rule);
  font-size:12.5px;color:var(--ink-2)}
#slotform:has(input[name="kind"][value="public"]:checked)  .rule-note[data-for-kind="public"],
#slotform:has(input[name="kind"][value="private"]:checked) .rule-note[data-for-kind="private"],
#slotform:has(input[name="kind"][value="virtual"]:checked) .rule-note[data-for-kind="virtual"]{display:block}

/* A meeting link is a question about a virtual inspection, and ONLY about one.
   Shown for it, hidden otherwise — and the server still refuses a virtual slot
   without one, because a browser is not where a rule lives. */
#virtualfield{display:none}
#slotform:has(input[name="kind"][value="virtual"]:checked) #virtualfield{display:flex}

.formcard__note{margin:0;font-size:12.5px;color:var(--ink-3);flex:1;min-width:220px}

/* ---------- Property Visit Requests (S11.12) ----------
   The deck opens this screen with the workflow written across the top and
   closes the table with what each decision does. Both are the same idea: the
   screen is a promise to somebody who is waiting, and the person making the
   decision should not have to remember what it sets off. */
.flash--info{background:var(--info-wash);border-color:#C9D6F7;color:var(--ink)}
.tablewrap__foot{margin:0;padding:11px 16px;border-top:1px solid var(--rule);
  background:var(--sunk);font-size:12.5px;color:var(--ink-2);
  border-radius:0 0 var(--r-md) var(--r-md)}

/* ---------- CRM provider cards (S11.13) ----------
   The design draws one card per provider rather than a row per connection, and
   the difference is the point: a table answers "what is connected", a grid of
   cards answers "what could be, and what is wrong with what is". Four of the
   seven are Not connected on the client's own screen, and they are on it. */
.crmgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(420px,1fr));gap:16px}
.crmcard{border:1px solid var(--rule);border-radius:var(--r-md);background:var(--paper);
  padding:18px 20px;display:flex;flex-direction:column;gap:14px}
.crmcard[data-state="not_connected"]{background:var(--sunk)}
.crmcard__head{display:flex;align-items:center;gap:12px}
.crmcard__mark{width:38px;height:38px;border-radius:var(--r);background:var(--mark-wash);
  display:grid;place-items:center;flex:none;color:var(--ink)}
.crmcard__mark svg{width:19px;height:19px}
.crmcard__name{min-width:0;flex:1}
.crmcard__name b{font-size:15px;letter-spacing:-.01em}
.crmcard__kind{font-size:11.5px;color:var(--ink-3)}
.crmcard__facts{display:flex;gap:16px;flex-wrap:wrap;font-size:12px;color:var(--ink-2)}
.crmcard__facts b{color:var(--ink);font-weight:600}
.crmcard__switch{display:flex;align-items:center;justify-content:space-between;gap:14px;
  border:1px solid var(--rule);border-radius:var(--r-md);padding:14px 16px}
.crmcard__note{margin:0;font-size:12px;color:var(--wait)}
.crmcard__actions{display:flex;gap:8px;flex-wrap:wrap}

/* ---------- Location Management (S11.14) ----------
   The design puts the add-form beside the table rather than above it, and that
   is the right call for this screen: adding a place and judging which places to
   hide are the same task, and the live-listing counts are the evidence for the
   second one. Stacked on a narrow screen, form first. */
.locsplit{display:grid;grid-template-columns:minmax(300px,380px) minmax(0,1fr);gap:16px;align-items:start}
@media (max-width:1100px){.locsplit{grid-template-columns:1fr}}
.fgrid--one{grid-template-columns:1fr}
.chips--tight{gap:4px}
.chip--pick{position:relative;cursor:pointer}
.chip--pick input{position:absolute;opacity:0;width:0;height:0}
.chip--pick span{display:inline-block;border:1px solid var(--rule);background:var(--paper);
  color:var(--ink-2);border-radius:999px;padding:7px 13px;font:600 12px/1 var(--sans)}
.chip--pick input:checked + span{background:var(--ink);border-color:var(--ink);color:var(--mark)}
.chip--pick input:focus-visible + span{box-shadow:0 0 0 3px rgba(20,20,20,.12)}

/* ---------- Property Alerts (S11.15) ---------- */
.alertlist{display:flex;flex-direction:column;gap:10px}
.alertrow{display:flex;align-items:center;gap:14px;border:1px solid var(--rule);
  border-radius:var(--r-md);padding:14px 16px;background:var(--paper)}
.alertrow__what{flex:1;min-width:0}
.alertrow__what b{font-size:14.5px}
.soonbox{margin-top:14px;border:1px solid var(--rule);border-left:3px solid var(--wait);
  border-radius:var(--r);padding:12px 14px;background:var(--wait-wash);font-size:12.5px}
.soonbox ul{margin:6px 0 0;padding-left:18px}
.soonbox li{margin:3px 0}
.panel__foot{padding:11px 16px;border-top:1px solid var(--rule);background:var(--sunk);
  font-size:12.5px;color:var(--ink-2);border-radius:0 0 var(--r-md) var(--r-md)}

/* ---------- package cards (S11.17) ----------
   A package is an offer, and an offer is read by what it includes — which is
   why the design draws these as cards and not as table rows. */
.pkggrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:16px;margin-bottom:18px}
.pkgcard{border:1px solid var(--rule);border-radius:var(--r-md);background:var(--paper);
  padding:20px;display:flex;flex-direction:column;gap:10px}
.pkgcard--popular{border:2px solid var(--ink)}
.pkgcard__head{display:flex;align-items:center;justify-content:space-between;gap:10px}
.pkgcard__head b{font-size:15px;letter-spacing:-.01em}
.pkgcard__price b{font-size:26px;letter-spacing:-.03em}
.pkgcard__price span{font-size:12px;color:var(--ink-3)}
.pkgcard__meta{font-size:12.5px;color:var(--ink-2)}
.pkgcard__features{margin:4px 0 auto;padding:0;list-style:none;display:flex;flex-direction:column;gap:6px}
.pkgcard__features li{font-size:12.5px;color:var(--ink-2);padding-left:16px;position:relative}
.pkgcard__features li::before{content:"";position:absolute;left:0;top:6px;width:6px;height:6px;
  border-radius:50%;background:var(--mark)}

/* ---------- the app's vocabulary (S11.18) ---------- */
.vgroup{padding:0 0 18px;margin:0 0 18px;border-bottom:1px dashed var(--rule)}
.vgroup:last-child{border-bottom:0;margin-bottom:0;padding-bottom:0}
.vgroup__where{margin:0;font-size:12px;color:var(--ink-3)}
.vgroup__where code{font-family:var(--mono);font-size:.92em;color:var(--ink-2)}
.vgroup__drift{margin:6px 0 0;font-size:12px;color:var(--wait);
  background:var(--wait-wash);border:1px solid #EBD9AE;border-radius:var(--r);padding:8px 11px}

/* ---------------------------------------------------------------- roles ---
   Screen 22. The deck's role cards: an initialled mark, a blurb, a count.
   Three columns there and two here, so the cards size to content rather than
   to a fixed third — two thirds of a row with a gap is a layout that looks
   like something failed to load. */
.rolecard { flex: 1 1 280px; min-width: 260px; }
.rolecard__head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.rolecard__mark {
    width: 34px; height: 34px; border-radius: 12px;
    display: grid; place-items: center;
    background: var(--mark); color: var(--ink);
    font-size: 12px; font-weight: 700; letter-spacing: .02em;
}
.rolecard__blurb { font-size: 12.5px; line-height: 1.55; margin: 0 0 12px; }

/* A row for a module the design does not draw. Dimmed, not hidden: it is a
   place people can write, so it belongs on a permissions table.

   The table is `.t` like every other table in the console. It was `.table`
   first — a class this stylesheet has never had — so the matrix rendered with
   no width, no cell padding and no row rules: three columns crushed against
   the left of a full-width panel with the rest of it empty, reading as a
   broken layout rather than a table.

   The role columns share what is left after the module name, so two roles do
   not sit in the first third of the width. */
#matrix th:first-child, #matrix td:first-child { width: 34%; }
#matrix th:not(:first-child), #matrix td:not(:first-child) { width: 33%; }
#matrix .dim-row > td:first-child b { font-weight: 600; }

/* ------------------------------------------------------------- settings ---
   The design's numbered sections. The number is a yellow square with the
   figure in it, and it is the only thing that orders a long form somebody
   scrolls past — headings alone all look alike by section four. */
.setsec { margin-bottom: 16px; }
.setsec__head { display: flex; align-items: center; gap: 12px; }
.setsec__num {
    width: 28px; height: 28px; flex: 0 0 28px; border-radius: 9px;
    display: grid; place-items: center;
    background: var(--mark); color: var(--ink);
    font-size: 12.5px; font-weight: 700;
}
.setsec__head > a { margin-left: auto; }

/* The trailing control of a panel head — a link or a button — sits at the far
   right, which is where the design puts it and where the eye looks for it. The
   head is a flex row with no justification, so without this it lands hard up
   against the title and reads as part of the heading. */
.panel__head > .panel__act { margin-left: auto; }

/* A field the design draws as a control and this product states instead. The
   value reads as a fact rather than as a disabled input, because a greyed-out
   switch invites somebody to look for the permission that would enable it. */
.stated{display:flex;gap:20px;align-items:flex-start;padding:14px 16px;border-bottom:1px solid var(--rule-soft)}
.stated:last-child{border-bottom:0}
.stated__main{flex:1;min-width:0}
.stated__label{display:block;font-weight:650;font-size:13.5px}
.stated__why{margin:3px 0 0;font-size:12.5px;color:var(--ink-2);line-height:1.5;max-width:62ch}
.stated__control{flex:0 0 268px;max-width:268px}
