:root{
  --red:#A02020; --cta:#B72828; --red-d:#7F1D1D; --red-l:#F7E7E7;
  --ink:#1F2933; --ink-2:#52616B; --ink-3:#8A96A3;
  --bg:#F6F7F9; --panel:#FFFFFF; --line:#D9DEE5; --line-2:#EDF0F3;
  --ok:#2E7D32; --warn:#F9A825; --warn-d:#8a5b00; --err:#C62828;
  --sans:"Inter","Segoe UI",Roboto,-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif;
  --mono:ui-monospace,"SF Mono",Menlo,Consolas,monospace;
  --sh-1:0 1px 2px rgba(31,41,51,.06); --sh-2:0 4px 16px rgba(31,41,51,.08); --sh-3:0 12px 40px rgba(127,29,29,.14);
  --r:12px; --nav-w:230px;
}
*{box-sizing:border-box}
html,body{margin:0;height:100%}
/* text-size-adjust:100% disables Android WebView "font boosting", which otherwise inflates text in
   wide blocks and makes the whole app look oversized on a phone. */
html{-webkit-text-size-adjust:100%;text-size-adjust:100%}
body{font-family:var(--sans);color:var(--ink);background:var(--bg);font-size:14.5px;line-height:1.5;-webkit-font-smoothing:antialiased}
a{color:var(--red);text-decoration:none}
h1,h2,h3{margin:0;font-weight:800;letter-spacing:-.01em}
button{font-family:inherit}
.hidden{display:none!important}
.tnum{font-variant-numeric:tabular-nums;font-family:var(--mono)}

/* Shell */
.shell{display:grid;grid-template-columns:var(--nav-w) 1fr;min-height:100%}
.side{background:var(--panel);border-right:1px solid var(--line);display:flex;flex-direction:column;position:sticky;top:0;height:100vh}
.brand{display:flex;align-items:center;gap:11px;padding:18px 18px 14px}
.brand .mark{width:34px;height:34px;border-radius:8px;background:var(--red);color:#fff;display:grid;place-items:center;font-weight:800;font-size:15px}
.brand .nm{font-weight:800;letter-spacing:.2em;font-size:13px;color:var(--red);text-transform:uppercase;line-height:1.1}
.brand .sub{font-size:9px;letter-spacing:.22em;color:var(--ink-3);text-transform:uppercase}
.nav{padding:8px;display:flex;flex-direction:column;gap:2px;overflow:auto}
.nav a{display:flex;align-items:center;gap:11px;padding:10px 12px;border-radius:9px;color:var(--ink-2);font-weight:600;font-size:14px;cursor:pointer}
.nav a .ic{width:18px;text-align:center;opacity:.9}
.nav a:hover{background:var(--line-2);color:var(--ink)}
.nav a.active{background:var(--red);color:#fff;box-shadow:var(--sh-1)}
.nav .sec{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);font-weight:700;padding:14px 12px 5px}
.side .foot{margin-top:auto;padding:12px 14px;border-top:1px solid var(--line-2);font-size:11px;color:var(--ink-3)}
.rolepill{display:inline-flex;align-items:center;gap:6px;background:var(--red-l);color:var(--red-d);font-weight:700;font-size:11px;padding:4px 9px;border-radius:999px}
.foot .link{background:none;border:0;color:var(--red);cursor:pointer;padding:0;font-weight:700;font-size:11px;margin-top:8px}
/* Connectivity + sync status (sidebar footer). Green = online, amber = offline. */
.dot-online,.dot-offline{width:8px;height:8px;border-radius:50%;display:inline-block;flex:none}
.dot-online{background:#16a34a}
.dot-offline{background:#d97706}
.syncrow{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:8px}
.syncmsg{color:var(--ink-3)}
.foot .link:disabled{color:var(--ink-3);cursor:default;opacity:.6}

.main{min-width:0;display:flex;flex-direction:column}
.topbar{display:none}
/* Mobile status chip in the top bar: tap to sync. Green online, amber offline, shows the pending count. */
.syncchip{border:1px solid var(--line);background:var(--panel);border-radius:999px;font-size:12px;font-weight:800;padding:4px 10px;cursor:pointer;color:#16a34a}
.syncchip.off{color:#d97706}
.syncchip:disabled{cursor:default;opacity:.75}
.content{padding:24px 30px 90px;max-width:1400px;width:100%;margin:0 auto}
.page-h{display:flex;align-items:center;gap:14px;margin-bottom:20px;flex-wrap:wrap}
.page-h h1{font-size:23px}
.page-h .desc{color:var(--ink-3);font-size:13px}
.page-h .sp{flex:1}

/* Buttons */
.btn{appearance:none;border:1px solid transparent;border-radius:10px;font-weight:700;font-size:14px;cursor:pointer;padding:10px 16px;display:inline-flex;align-items:center;justify-content:center;gap:8px;transition:filter .15s,background .15s,border-color .15s;text-decoration:none}
.btn:disabled{opacity:.5;cursor:not-allowed}
.btn[aria-disabled="true"]{opacity:.5;cursor:not-allowed;pointer-events:none}
.btn.primary{background:var(--cta);color:#fff}
.btn.primary:hover:not(:disabled){filter:brightness(1.07)}
.btn.dark{background:var(--red-d);color:#fff}
.btn.ghost{background:#fff;border-color:var(--line);color:var(--ink)}
.btn.ghost:hover{background:var(--line-2)}
.btn.soft{background:var(--red-l);color:var(--red-d)}
.btn.soft:hover{filter:brightness(.98)}
.btn.wa{background:#25D366;color:#063}
.btn.sm{padding:7px 12px;font-size:13px;border-radius:9px}
.btn.icon{padding:8px 10px}
.btn.block{width:100%}

/* Cards / grid */
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--sh-1)}
.card .hd{padding:14px 18px;border-bottom:1px solid var(--line-2);display:flex;align-items:center;gap:10px}
.card .hd h2{font-size:13px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-2)}
.card .bd{padding:18px}
.grid{display:grid;gap:16px}
.stats{grid-template-columns:repeat(4,1fr)}
.stat{padding:16px 18px}
.stat .k{font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);font-weight:700}
.stat .v{font-size:30px;font-weight:800;margin-top:6px;color:var(--ink)}
.stat .v.red{color:var(--red)}

/* Forms */
.form{display:grid;gap:14px}
.row{display:grid;gap:14px;grid-template-columns:1fr 1fr}
.row.three{grid-template-columns:1fr 1fr 1fr}
label.fld{display:flex;flex-direction:column;gap:6px;font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3);font-weight:700}
label.fld input,label.fld select,label.fld textarea{font-family:inherit;font-size:14.5px;color:var(--ink);font-weight:500;letter-spacing:0;text-transform:none;border:1px solid var(--line);border-radius:10px;padding:10px 12px;background:#fff;width:100%}
label.fld textarea{min-height:70px;resize:vertical}
input:focus,select:focus,textarea:focus{outline:0;border-color:var(--cta);box-shadow:0 0 0 3px rgba(183,40,40,.14)}

/* Searchable select (SearchSelect.razor) - mirrors the mockup's .ssel/.ssel-menu rules */
.ssel{position:relative}
.ssel input{font-family:inherit;font-size:14.5px;color:var(--ink);font-weight:500;border:1px solid var(--line);border-radius:10px;padding:10px 12px;background:#fff;width:100%}
.ssel.disabled input{background:var(--line-2);color:var(--ink-3);cursor:not-allowed}
.ssel-menu{position:fixed;z-index:9999;background:#fff;border:1px solid var(--line);border-radius:10px;box-shadow:var(--sh-2);max-height:280px;overflow:auto}
.ssel-menu .opt{padding:10px 12px;cursor:pointer;font-size:14px;border-bottom:1px solid var(--line-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ssel-menu .opt:hover,.ssel-menu .opt.hi{background:var(--red-l)}
.ssel-menu .opt small{color:var(--ink-3)}
.ssel-menu .opt.create{color:var(--cta);font-weight:700;position:sticky;top:0;background:#fff}

/* Password requirements checklist (PasswordRules.razor) - ticks off live as the user types. */
.pwrules{list-style:none;margin:-4px 0 4px;padding:0;display:grid;gap:3px}
.pwrules li{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--ink-3)}
.pwrules li.ok{color:#1a7f45}
.pwrules .tick{width:1em;text-align:center;font-weight:700}
.ssel-menu .empty{padding:10px 12px;color:var(--ink-3);font-size:13px}

/* Tables */
.tbl{width:100%;border-collapse:collapse}
.tbl th{text-align:left;font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3);font-weight:700;padding:10px 10px;border-bottom:1px solid var(--line);white-space:nowrap}
.tbl th.num,.tbl td.num{text-align:right;font-variant-numeric:tabular-nums;font-family:var(--mono)}
.tbl td{padding:10px 10px;border-bottom:1px solid var(--line-2);vertical-align:middle}
.tbl tr:hover td{background:#fbfcfd}
.tbl.clickable tbody tr{cursor:pointer}
.badge{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:700;padding:3px 9px;border-radius:999px;text-transform:capitalize}
.badge.draft{background:#eef1f4;color:var(--ink-2)}
.badge.sent{background:#e7f2e8;color:var(--ok)}
.badge.accepted{background:#e2f0ff;color:#1a63b8}
.badge.declined{background:#fdeaea;color:var(--err)}
.badge.expired{background:#fbf1dd;color:var(--warn-d)}
.badge.active{background:#e7f2e8;color:var(--ok)}
.badge.inactive{background:#fdeaea;color:var(--err)}

/* Quote editor */
.qwrap{display:grid;grid-template-columns:1fr 320px;gap:20px;align-items:start}
/* Grid children default to min-width:auto, which lets the wide line-items table (min-width:920px)
   stretch the whole editor past the screen on a phone - pushing the right-aligned summary values,
   total and buttons off-screen. min-width:0 lets the column shrink so the table scrolls inside its
   own .qgrid-scroll container instead, and the summary stays full-width and readable. */
.qwrap>*{min-width:0}
.qgrid-scroll{overflow-x:auto}
.qgrid{width:100%;min-width:920px;border-collapse:collapse}
.qgrid th{background:#fff;font-size:10px;letter-spacing:.07em;text-transform:uppercase;color:var(--ink-3);font-weight:700;text-align:left;padding:9px 8px;border-bottom:1px solid var(--line);white-space:nowrap}
.qgrid th.num{text-align:right}
.qgrid td{padding:5px 6px;border-bottom:1px solid var(--line-2);vertical-align:middle}
.qgrid td.num{text-align:right;font-variant-numeric:tabular-nums;font-family:var(--mono);font-size:13px}
.qgrid tr.warn td{background:#fffaf0}
.qgrid input,.qgrid select{border:1px solid transparent;background:transparent;border-radius:7px;padding:7px 6px;font-size:13.5px;width:100%;font-family:inherit;color:var(--ink)}
.qgrid input:hover,.qgrid select:hover{border-color:var(--line)}
.qgrid td.idx{color:var(--ink-3);text-align:center;width:26px;font-family:var(--mono)}
.qgrid td.cat{min-width:140px}.qgrid td.prod{min-width:210px}
.qgrid td.dim input{width:64px;text-align:right}.qgrid td.qty input{width:44px;text-align:center}
.qgrid td.ex{min-width:150px}.qgrid td.pc input{width:48px;text-align:center}
.qgrid td.ex .badge{margin:1px 4px 1px 0;gap:5px}
.qgrid td.ex .ex-x{border:0;background:transparent;color:inherit;cursor:pointer;font-size:11px;padding:0;line-height:1}
.qgrid td.ex .ex-add{padding:3px 8px}
.round{display:block;font-size:10px;color:var(--ink-3);font-family:var(--mono);text-align:right;min-height:11px}
.lt{font-weight:700;color:var(--red-d)}
.rm{border:0;background:transparent;color:var(--ink-3);cursor:pointer;font-size:15px;padding:4px 7px;border-radius:7px}
.rm:hover{background:var(--red-l);color:var(--red)}
.qmsg{font-size:11.5px;padding:1px 8px 8px 34px}
.qmsg.warn{color:var(--warn-d)}.qmsg.err{color:var(--err)}
.sdot{display:inline-block;width:8px;height:8px;border-radius:50%}
.sdot.ok{background:var(--ok)}.sdot.warn{background:var(--warn)}.sdot.err{background:var(--err)}.sdot.idle{background:var(--line)}

.summary{position:sticky;top:20px}
.summary .srow{display:flex;justify-content:space-between;align-items:baseline;padding:9px 0;border-bottom:1px dashed var(--line-2)}
.summary .srow .k{color:var(--ink-2)}
.summary .srow .v{font-family:var(--mono);font-variant-numeric:tabular-nums}
.summary .srow.total{border:0;background:var(--red-d);color:#fff;border-radius:10px;padding:14px 16px;margin-top:8px}
.summary .srow.total .k{color:#fff;font-weight:800;letter-spacing:.1em;text-transform:uppercase;font-size:12px}
.summary .srow.total .v{color:#fff;font-size:22px;font-weight:800}
.warnbar{background:#fbf1dd;color:var(--warn-d);border:1px solid #f0dcae;border-radius:10px;padding:10px 12px;font-size:12.5px;font-weight:600;margin-top:10px}

/* Preview doc */
.doc{background:#fff;border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--sh-2);max-width:820px;margin:0 auto;overflow:hidden}
.doc .dh{display:flex;align-items:center;gap:16px;padding:26px 30px;border-bottom:3px solid var(--red)}
.doc .dh img{height:52px}
.doc .dh .nm{font-weight:800;letter-spacing:.28em;color:var(--red);text-transform:uppercase;font-size:19px}
.doc .dh .sub{font-size:10px;letter-spacing:.18em;color:var(--ink-3);text-transform:uppercase}
.doc .meta{margin-left:auto;text-align:right;font-size:12px;color:var(--ink-2)}
.doc .bd{padding:24px 30px}
.doc table{width:100%;border-collapse:collapse;font-size:12.5px;margin-top:6px}
.doc th{background:var(--red-l);color:var(--red-d);text-align:left;padding:8px 8px}
.doc th.num,.doc td.num{text-align:right;font-variant-numeric:tabular-nums}
.doc td{padding:8px 8px;border-bottom:1px solid var(--line-2)}
.doc .tot{margin-left:auto;width:290px;margin-top:16px}
.doc .tot .r{display:flex;justify-content:space-between;padding:7px 0;border-bottom:1px solid var(--line-2)}
.doc .tot .r.big{background:var(--red-d);color:#fff;border:0;border-radius:8px;padding:12px 14px;margin-top:8px}
.doc .tot .r.big b{font-size:18px}
.doc .terms{margin-top:24px;font-size:10.5px;color:var(--ink-3);border-top:1px solid var(--line-2);padding-top:12px;white-space:pre-wrap}

/* Auth */
.auth{min-height:100vh;display:grid;place-items:center;padding:1rem}
.auth .card{max-width:380px;width:100%;padding:2rem;border-top:5px solid var(--red)}
.auth .brandbig{font-weight:800;letter-spacing:.06em;font-size:1.5rem;color:var(--red)}
.auth .brandbig span{color:var(--ink)}
.auth .sub{color:var(--ink-3);margin:.2rem 0 1.4rem;letter-spacing:.05em}

/* MFA (MfaEnrol.razor, MfaChallenge.razor). The setup key and the recovery codes are user-select:all so a
   tap selects the whole thing - on a phone that is how they get into the authenticator app, since the QR
   is on the same screen as the app and cannot be scanned. */
.auth .card.wide{max-width:440px}
.mfa-qr{display:block;margin:0 auto;width:196px;height:196px;image-rendering:pixelated;background:#fff;border:1px solid var(--line);border-radius:10px;padding:6px}
/* Groups of 4 are laid out with a gap, not with spaces in the text, so selecting/copying the key yields
   the raw secret an authenticator app will accept. */
.mfa-secret{display:flex;flex-wrap:wrap;gap:4px 12px;font-family:var(--mono);font-size:15px;letter-spacing:.06em;word-break:break-all;-webkit-user-select:all;user-select:all;color:var(--ink);text-transform:none;background:var(--line-2);border:1px solid var(--line);border-radius:10px;padding:10px 12px}
.mfa-codes{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:6px 14px;font-family:var(--mono);font-size:13.5px;-webkit-user-select:all;user-select:all;background:var(--line-2);border:1px solid var(--line);border-radius:10px;padding:12px}
.mfa-check{display:flex;align-items:flex-start;gap:8px;font-size:13px;color:var(--ink-2);font-weight:600}
.mfa-check input{width:auto;margin-top:2px}

.empty-state{text-align:center;padding:50px 20px;color:var(--ink-3)}
.empty-state .big{font-size:16px;color:var(--ink-2);font-weight:700;margin-bottom:6px}
.searchbar{display:flex;gap:10px;align-items:center;margin-bottom:14px;flex-wrap:wrap}
.searchbar input{flex:1;min-width:200px;border:1px solid var(--line);border-radius:10px;padding:10px 12px;font-size:14px}
.msg{margin-top:1rem;padding:.8rem 1rem;background:#fff;border-left:4px solid var(--red);border-radius:6px}
.kv{display:grid;grid-template-columns:130px 1fr;gap:6px 12px;font-size:13.5px}
.kv .k{color:var(--ink-3);font-weight:600}

/* Modal / toast (ModalDialog.razor) - mirrors the mockup's .scrim/.modal/#toasts */
.scrim{position:fixed;inset:0;background:rgba(31,41,51,.5);display:flex;align-items:center;justify-content:center;z-index:80;padding:18px}
.modal{background:#fff;border-radius:14px;box-shadow:var(--sh-3);max-width:560px;width:100%;max-height:90vh;overflow:auto}
.modal .mh{display:flex;align-items:center;padding:16px 20px;border-bottom:1px solid var(--line-2)}
.modal .mh h3{font-size:16px}.modal .mh .x{margin-left:auto;border:0;background:transparent;font-size:20px;cursor:pointer;color:var(--ink-3)}
.modal .mb{padding:20px}
.modal .mf{padding:14px 20px;border-top:1px solid var(--line-2);display:flex;gap:10px;justify-content:flex-end}
#toasts{position:fixed;right:18px;bottom:18px;z-index:90;display:flex;flex-direction:column;gap:8px}
.toast{background:var(--ink);color:#fff;padding:11px 15px;border-radius:10px;box-shadow:var(--sh-2);font-weight:600;font-size:13.5px;animation:pop .2s ease}
.toast.ok{background:var(--ok)}.toast.err{background:var(--err)}.toast.warn{background:var(--warn-d)}
@keyframes pop{from{transform:translateY(8px);opacity:0}to{transform:none;opacity:1}}
.err{color:var(--cta);margin-top:.8rem;font-size:.9rem}
.mono-help{font-size:12px;color:var(--ink-3)}

/* mobile */
.mobnav{display:none}
/* Phone layout (portrait AND landscape). 960px so a phone held sideways (~915px wide) still gets the
   single-column app chrome + bottom nav rather than a cramped desktop sidebar. */
@media (max-width:960px){
  .shell{grid-template-columns:1fr}
  .side{display:none}
  /* Safe-area insets: pad the sticky top bar below the status bar (clock) and the fixed bottom nav
     above the gesture/navigation bar, so the header (Sign out) and bottom nav are never hidden under
     the system bars on a phone. env(...) resolves to 0 in desktop browsers, so the web is unaffected. */
  .topbar{display:flex;align-items:center;gap:12px;padding:10px 14px;padding-top:calc(10px + env(safe-area-inset-top));padding-left:calc(14px + env(safe-area-inset-left));padding-right:calc(14px + env(safe-area-inset-right));background:var(--panel);border-bottom:1px solid var(--line);position:sticky;top:0;z-index:40}
  .topbar .nm{font-weight:800;letter-spacing:.16em;color:var(--red);text-transform:uppercase;font-size:13px}
  .topbar .sp{flex:1}
  .content{padding:14px 12px;padding-bottom:calc(88px + env(safe-area-inset-bottom))}
  .qwrap{grid-template-columns:1fr}
  /* On a phone the summary/total flows BELOW the line items (natural order: add blinds, then see the
     total) instead of the desktop right-hand sidebar. */
  .summary{position:static}
  .stats{grid-template-columns:1fr 1fr;gap:10px}
  .row,.row.three{grid-template-columns:1fr}
  /* Dial the mockup's desktop-sized type/padding down so it fits a phone screen. */
  .page-h{margin-bottom:14px;gap:10px}
  .page-h h1{font-size:19px}
  .card .bd{padding:14px}
  .card .hd{padding:12px 14px}
  .stat{padding:12px 14px}
  .stat .v{font-size:22px;margin-top:2px}
  .btn{padding:9px 13px;font-size:13px}
  .btn.primary{padding:10px 15px}
  .tbl th,.tbl td{padding:9px 10px}
  /* A table cannot shrink below its content, and th is nowrap, so five columns of real client data
     (a company name, an unbreakable email) rendered 610px wide inside a 364px card and dragged the
     whole page 233px off-screen - the total and the email ran off the side. Two defences:
     1. .stack restacks each row into its own card, reading down instead of across.
     2. Any table NOT restacked (the admin screens) scrolls inside its own card, so the page itself
        never scrolls sideways however wide the content is. */
  .card .bd{overflow-x:auto}
  .tbl.stack{display:block}
  .tbl.stack thead{display:none}
  .tbl.stack tbody,.tbl.stack tr,.tbl.stack td{display:block;width:auto}
  .tbl.stack tr{border:1px solid var(--line-2);border-radius:12px;padding:12px 14px;margin:0 0 10px}
  .tbl.stack tr:last-child{margin-bottom:0}
  .tbl.stack tr:hover td{background:transparent}
  /* Long values (emails, addresses) break rather than push the row wider than the screen. */
  .tbl.stack td{border:0;padding:3px 0;display:flex;gap:10px;align-items:baseline;overflow-wrap:anywhere}
  .tbl.stack td::before{content:attr(data-label);flex:0 0 76px;font-size:10.5px;letter-spacing:.08em;
    text-transform:uppercase;color:var(--ink-3);font-weight:700;line-height:1.7}
  /* The first cell is the row's heading (client name, quote number): no caption, and it carries the
     weight the removed table header used to. */
  .tbl.stack td:first-child{font-size:15px;padding:0 0 6px;border-bottom:1px solid var(--line-2);margin-bottom:6px}
  .tbl.stack td:first-child::before{display:none}
  /* Money and counts read left-aligned beside their caption here, not flushed to a far edge. */
  .tbl.stack td.num{text-align:left}
  /* An empty cell would otherwise show a caption with nothing after it. */
  .tbl.stack td:empty{display:none}
  .mobnav{display:flex;position:fixed;bottom:0;left:0;right:0;background:#fff;border-top:1px solid var(--line);z-index:50;padding:5px 4px;padding-bottom:calc(5px + env(safe-area-inset-bottom));justify-content:space-around}
  .mobnav a{display:flex;flex-direction:column;align-items:center;gap:2px;font-size:10px;font-weight:700;color:var(--ink-3);padding:5px 10px;border-radius:9px;cursor:pointer}
  .mobnav a.active{color:var(--red);background:var(--red-l)}
  .mobnav a .ic{font-size:16px}
}
/* Landscape phones are short: reclaim vertical space and keep 4 stats in a row where it fits. */
@media (max-width:960px) and (orientation:landscape){
  .content{padding:12px 16px;padding-bottom:calc(84px + env(safe-area-inset-bottom))}
  .stats{grid-template-columns:repeat(4,1fr)}
  .page-h{margin-bottom:10px}
}

#blazor-error-ui{background:#b32121;color:#fff;bottom:0;box-shadow:0 -1px 2px rgba(0,0,0,.2);display:none;left:0;padding:.6rem 1.25rem;position:fixed;width:100%;z-index:1000}
#blazor-error-ui .dismiss{cursor:pointer;position:absolute;right:.75rem;top:.5rem}
