/* =====================================================================
   Vyom Invoice — application stylesheet
   No external fonts or CDNs: works fully offline.
   ===================================================================== */

/* Palette taken from logovyom.svg:
   #E53935 wordmark red · #D00000 / #FF0002 mark reds
   #1A1817 wordmark dark · #016536 / #039939 / #31B05C leaf greens */
:root{
  --bg:          #f6f5f4;
  --surface:     #ffffff;
  --surface-2:   #faf9f8;
  --border:      #e7e3e1;
  --border-2:    #d9d3d0;
  --text:        #1a1817;
  --text-2:      #6b625e;
  --text-3:      #98908c;
  --brand:       #c62828;
  --brand-dark:  #a81e1e;
  --brand-mid:   #e53935;
  --brand-soft:  #fdecec;
  --accent:      #016536;
  --accent-soft: #e8f3ed;
  --danger:      #c0392b;
  --danger-soft: #fdeceb;
  --danger-line: #e8b4ae;
  --info:        #016536;
  --info-soft:   #e8f3ed;
  --info-line:   #bcd9c9;
  /* A warning is not an error. The palette had no amber, so warn notices
     borrowed green fills with amber borders and brown text; these give the
     three states — info / warn / danger — each their own colour. */
  --warn:        #8a5a10;
  --warn-soft:   #fdf4e3;
  --warn-line:   #eddcb4;
  --blue:        #1c4c80;
  --blue-soft:   #eaf1f9;
  --blue-line:   #c5daf0;
  --sidebar:     #faf8f6;   /* off-white — lets the logo sit on it untinted */
  --sidebar-2:   #efeae7;   /* hover / chip fill */
  --sidebar-tx:  #4c4441;
  --sidebar-tx2: #7d736e;   /* section labels, muted meta */
  --sidebar-line:#e4dedb;
  --radius:      10px;
  --radius-sm:   7px;
  --shadow:      0 1px 2px rgba(20,30,45,.06), 0 4px 14px rgba(20,30,45,.06);
  --shadow-lg:   0 10px 40px rgba(20,30,45,.18);
  --mono: ui-monospace, "Cascadia Mono", "Consolas", "SFMono-Regular", monospace;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

*,*::before,*::after{ box-sizing:border-box; }
html,body{ height:100%; }
body{
  margin:0; background:var(--bg); color:var(--text);
  font-family:var(--sans); font-size:14px; line-height:1.5;
  -webkit-font-smoothing:antialiased;
}
a{ color:inherit; text-decoration:none; }
h1,h2,h3,h4{ margin:0; font-weight:650; letter-spacing:-.01em; }
input,select,textarea,button{ font:inherit; color:inherit; }
[hidden]{ display:none !important; }

/* ------------------------------ Login ------------------------------ */
.login-screen{
  min-height:100vh; display:grid; place-items:center; padding:24px;
  background:
    radial-gradient(1100px 500px at 15% -10%, #234a35 0%, transparent 60%),
    radial-gradient(900px 500px at 100% 110%, #1d3f5f 0%, transparent 55%),
    #101a16;
}
.login-card{
  width:100%; max-width:390px; background:var(--surface);
  border-radius:16px; padding:32px; box-shadow:var(--shadow-lg);
}
.login-brand{ display:flex; flex-direction:column; gap:14px; margin-bottom:26px; }
.login-logo{ width:172px; height:auto; }
.login-brand h1{ font-size:19px; }
.login-brand p{ margin:2px 0 0; font-size:12.5px; color:var(--text-3); }
.login-error{
  background:var(--danger-soft); color:var(--danger); border:1px solid var(--danger-line);
  padding:9px 12px; border-radius:var(--radius-sm); font-size:12.5px; margin-bottom:14px;
}

/* ------------------------------ Fields ------------------------------ */
.field{ display:block; margin-bottom:15px; }
.field > span,.lbl{
  display:block; font-size:11.5px; font-weight:600; color:var(--text-2);
  margin-bottom:5px; letter-spacing:.02em;
}
.field.req > span::after{ content:" *"; color:var(--danger); }
/* Every text-like control gets one look.
   Written as an exclusion, not a list of types: most inputs in this app are
   written as a bare <input>, which defaults to text but is NOT matched by
   input[type=text] — that mismatch left ~60 fields unstyled. Excluding the
   handful of controls that must stay native also means a new type (tel, url,
   time…) is styled the day it is used. */
input:not([type=checkbox]):not([type=radio]):not([type=file]):not([type=hidden]):not([type=submit]):not([type=button]):not([type=reset]):not([type=range]):not([type=color]),
select,
textarea{
  width:100%; padding:8px 11px; border:1px solid var(--border-2);
  border-radius:var(--radius-sm); background:#fff; color:var(--text);
  font-size:14px; line-height:1.4; outline:none;
  transition:border-color .12s, box-shadow .12s, background .12s;
}
input:focus,select:focus,textarea:focus{
  border-color:var(--brand); box-shadow:0 0 0 3px rgba(198,40,40,.13);
}
input:hover:not(:focus):not([readonly]):not([disabled]),
select:hover:not(:focus):not([disabled]),
textarea:hover:not(:focus):not([readonly]){ border-color:var(--text-3); }

::placeholder{ color:var(--text-3); opacity:1; }

input[readonly],textarea[readonly]{ background:var(--surface-2); color:var(--text-2); }
input[disabled],select[disabled],textarea[disabled]{
  background:var(--surface-2); color:var(--text-3); cursor:not-allowed;
}
input.num,td input.num{ text-align:right; font-variant-numeric:tabular-nums; }

/* A select must not look like a different species from the box beside it:
   the native chrome is replaced with the same caret used elsewhere. */
select{
  appearance:none; -webkit-appearance:none; -moz-appearance:none;
  padding-right:32px; cursor:pointer;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath fill='none' stroke='%236b625e' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round' d='M1 1l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 11px center;
}
select::-ms-expand{ display:none; }

/* Date fields keep the same height and the picker icon is tinted to match. */
input[type=date]::-webkit-calendar-picker-indicator{ opacity:.5; cursor:pointer; }
input[type=date]:hover::-webkit-calendar-picker-indicator{ opacity:.8; }
input[type=search]::-webkit-search-decoration,
input[type=search]::-webkit-search-cancel-button{ -webkit-appearance:none; }

/* File input — the native button is unstyleable across browsers, so only the
   well around it is drawn, matching the other fields. */
input[type=file]{
  width:100%; padding:7px 11px; border:1px dashed var(--border-2);
  border-radius:var(--radius-sm); background:var(--surface-2);
  font-size:13px; color:var(--text-2); cursor:pointer;
  transition:border-color .12s, background .12s;
}
input[type=file]:hover{ border-color:var(--brand); background:var(--brand-soft); }
input[type=file]:focus{ outline:none; border-color:var(--brand); box-shadow:0 0 0 3px rgba(198,40,40,.13); }
input[type=file]::file-selector-button{
  margin-right:11px; padding:5px 11px; border-radius:6px;
  border:1px solid var(--border-2); background:#fff; color:var(--text);
  font:inherit; font-size:12.5px; font-weight:550; cursor:pointer;
}
input[type=file]::file-selector-button:hover{ background:var(--surface-2); border-color:var(--text-3); }

/* Show / hide password. The button sits inside the box, so the field keeps
   the same footprint as every other one — see public/js/pwtoggle.js. */
.pw-field{ position:relative; display:block; }
.pw-field input{ padding-right:40px; }
.pw-toggle{
  position:absolute; top:1px; right:1px; bottom:1px; width:38px;
  display:grid; place-items:center; padding:0;
  border:0; background:transparent; color:var(--text-3); cursor:pointer;
  border-radius:0 var(--radius-sm) var(--radius-sm) 0;
}
.pw-toggle:hover{ color:var(--brand); background:var(--surface-2); }
.pw-toggle:focus-visible{ outline:2px solid var(--brand); outline-offset:-2px; }
.pw-toggle svg{ width:17px; height:17px; display:block; }
.pw-toggle .icon-off{ display:none; }
.pw-field.shown .pw-toggle{ color:var(--brand); }
.pw-field.shown .pw-toggle .icon-on{ display:none; }
.pw-field.shown .pw-toggle .icon-off{ display:block; }

/* Checkboxes and radios stay native but take the brand colour. */
input[type=checkbox],input[type=radio]{
  width:15px; height:15px; accent-color:var(--brand);
  cursor:pointer; flex:none; margin:0;
}

/* No spinner arrows anywhere — quantity and rate are plain boxes */
input[type=number]{ -moz-appearance:textfield; appearance:textfield; }
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button{ -webkit-appearance:none; margin:0; }
textarea{ resize:vertical; min-height:64px; }
.hint{ font-size:11.5px; color:var(--text-3); margin-top:4px; }
.grid{ display:grid; gap:15px; }
.grid.c2{ grid-template-columns:repeat(2,1fr); }
.grid.c3{ grid-template-columns:repeat(3,1fr); }
.grid.c4{ grid-template-columns:repeat(4,1fr); }
@media (max-width:1100px){ .grid.c4{ grid-template-columns:repeat(2,1fr); } }
@media (max-width:820px){ .grid.c2,.grid.c3,.grid.c4{ grid-template-columns:1fr; } }

/* ------------------------------ Buttons ------------------------------ */
.btn{
  display:inline-flex; align-items:center; gap:7px; justify-content:center;
  padding:8px 15px; border-radius:var(--radius-sm); border:1px solid var(--border-2);
  background:#fff; cursor:pointer; font-size:13.5px; font-weight:550;
  transition:background .12s, border-color .12s, transform .06s; white-space:nowrap;
}
.btn:hover{ background:var(--surface-2); border-color:var(--text-3); }
.btn:active{ transform:translateY(1px); }
.btn-primary{ background:var(--brand); border-color:var(--brand); color:#fff; }
.btn-primary:hover{ background:var(--brand-dark); border-color:var(--brand-dark); }
.btn-danger{ background:#fff; border-color:#e8b4ae; color:var(--danger); }
.btn-danger:hover{ background:var(--danger-soft); border-color:var(--danger); }
.btn-ghost{ background:transparent; border-color:transparent; color:var(--text-2); }
.btn-ghost:hover{ background:rgba(26,24,23,.06); color:var(--text); }
.btn-sm{ padding:5px 10px; font-size:12.5px; }
.btn-block{ width:100%; }
.icon-btn{
  width:32px; height:32px; border-radius:var(--radius-sm); border:1px solid transparent;
  background:transparent; cursor:pointer; display:grid; place-items:center; font-size:15px;
}
.icon-btn:hover{ background:var(--surface-2); border-color:var(--border); }

/* ------------------------------ Layout ------------------------------ */
.app{ display:flex; min-height:100vh; }
.sidebar{
  width:236px; flex:none; background:var(--sidebar); color:var(--sidebar-tx);
  display:flex; flex-direction:column; position:sticky; top:0; height:100vh;
  border-right:1px solid var(--sidebar-line);
}
/* The logo is the whole header now — the wordmark and company name that sat
   under it were removed, so the padding closes up around it. */
.sidebar-head{
  display:flex; align-items:center; padding:18px 16px;
  border-bottom:1px solid var(--sidebar-line);
}
/* No chip behind the logo — the off-white sidebar is the logo's backdrop, so
   the mark reads as printed on the panel rather than pasted onto a card. */
.brand-chip{ display:flex; align-items:center; justify-content:flex-start; }
.brand-chip img{ width:100%; max-width:150px; height:auto; display:block; }
.nav{ flex:1; overflow-y:auto; padding:10px 9px 20px; }
.nav-label{
  font-size:10px; text-transform:uppercase; letter-spacing:.09em;
  color:var(--sidebar-tx2); padding:16px 9px 6px; font-weight:650;
}
.nav-item{
  display:flex; align-items:center; gap:10px; width:100%; text-align:left;
  padding:8px 10px; border-radius:var(--radius-sm); color:var(--sidebar-tx);
  font-size:13.3px; cursor:pointer; border:0; background:transparent;
  margin-bottom:1px;
}
.nav-item:hover{ background:var(--sidebar-2); color:var(--text); }
.nav-item.active{ background:var(--brand); color:#fff; font-weight:600; }
.nav-item.active .ico{ opacity:1; }
.nav-item .ico{ width:16px; text-align:center; opacity:.65; font-size:13px; }
.nav-item.sub{ padding-left:36px; font-size:12.8px; }
.sidebar-foot{
  padding:12px; border-top:1px solid var(--sidebar-line);
  display:flex; align-items:center; gap:8px; justify-content:space-between;
}
.fx-chip{
  display:flex; gap:6px; align-items:center; font-size:11.5px; color:var(--sidebar-tx2);
  background:var(--sidebar-2); padding:5px 9px; border-radius:20px;
}
.fx-chip b{ color:var(--text); font-variant-numeric:tabular-nums; }

.main{ flex:1; min-width:0; display:flex; flex-direction:column; }
.topbar{
  height:57px; flex:none; background:var(--surface); border-bottom:1px solid var(--border);
  display:flex; align-items:center; gap:14px; padding:0 20px;
  position:sticky; top:0; z-index:40;
}
.crumbs{ font-size:14px; font-weight:600; flex:1; min-width:0; }
.crumbs small{ font-weight:400; color:var(--text-3); font-size:12.5px; }
.topbar-right{ display:flex; align-items:center; gap:12px; }
.only-mobile{ display:none; }
@media (max-width:900px){
  .only-mobile{ display:grid; }
  .sidebar{ position:fixed; z-index:60; transform:translateX(-100%); transition:transform .2s; }
  .sidebar.open{ transform:none; }
}

.view{ padding:22px; flex:1; }

/* ------------------------------ Cards ------------------------------ */
.card{
  background:var(--surface); border:1px solid var(--border);
  border-radius:var(--radius); box-shadow:var(--shadow); margin-bottom:18px;
}
.card-head{
  display:flex; align-items:center; gap:12px; padding:14px 17px;
  border-bottom:1px solid var(--border);
}
.card-head h3{ font-size:14.5px; flex:1; }
.card-head p{ margin:2px 0 0; font-size:12px; color:var(--text-3); font-weight:400; }
.card-body{ padding:17px; }
.card-body.tight{ padding:0; }
.card-foot{
  padding:13px 17px; border-top:1px solid var(--border); background:var(--surface-2);
  display:flex; gap:9px; justify-content:flex-end; border-radius:0 0 var(--radius) var(--radius);
}

.page-head{ display:flex; align-items:flex-end; gap:14px; margin-bottom:18px; flex-wrap:wrap; }
.page-head h2{ font-size:20px; }
.page-head p{ margin:3px 0 0; color:var(--text-3); font-size:13px; }
.page-head .spacer{ flex:1; }

/* ------------------------------ Stats ------------------------------ */
.stats{ display:grid; grid-template-columns:repeat(4,1fr); gap:14px; margin-bottom:18px; }
@media (max-width:980px){ .stats{ grid-template-columns:repeat(2,1fr); } }
.stat{
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius);
  padding:15px 17px; box-shadow:var(--shadow);
}
.stat .k{ font-size:11.5px; color:var(--text-3); font-weight:600; letter-spacing:.02em; }
.stat .v{ font-size:23px; font-weight:700; margin-top:5px; font-variant-numeric:tabular-nums; }
.stat .s{ font-size:11.5px; color:var(--text-3); margin-top:2px; }
.stat.accent .v{ color:var(--brand); }

/* ------------------------------ Tables ------------------------------ */
.tbl-wrap{ overflow-x:auto; }
table.tbl{ width:100%; border-collapse:collapse; font-size:13px; }
table.tbl th{
  text-align:left; padding:10px 13px; background:var(--surface-2);
  border-bottom:1px solid var(--border); font-size:11.3px; font-weight:650;
  color:var(--text-2); text-transform:uppercase; letter-spacing:.04em; white-space:nowrap;
}
table.tbl td{ padding:10px 13px; border-bottom:1px solid var(--border); vertical-align:middle; }
table.tbl tbody tr:hover{ background:var(--surface-2); }
table.tbl tbody tr:last-child td{ border-bottom:0; }
table.tbl td.num,table.tbl th.num{ text-align:right; font-variant-numeric:tabular-nums; }
table.tbl td.mono{ font-family:var(--mono); font-size:12.3px; }
.row-actions{ display:flex; gap:5px; justify-content:flex-end; }
.empty{ padding:46px 20px; text-align:center; color:var(--text-3); }
.empty .big{ font-size:32px; opacity:.35; margin-bottom:10px; }
.empty p{ margin:0 0 14px; }

/* items grid (line-item editor) */
table.items{ width:100%; border-collapse:collapse; font-size:12.8px; }
/* The column header sticks BELOW the sticky topbar and the sticky card header,
   not at the top of the viewport — at top:0 it slid underneath them and
   disappeared. syncStickyOffsets() in core.js measures both and publishes the
   sum, because the card header's height changes with its description text. */
table.items th{
  padding:8px 8px; background:var(--surface-2); border-bottom:1px solid var(--border);
  font-size:10.8px; font-weight:650; color:var(--text-2); text-transform:uppercase;
  letter-spacing:.03em; text-align:left; white-space:nowrap;
  position:sticky; top:var(--items-th-top, 57px); z-index:2;
}

/* A products list runs to dozens of rows. The card header carries the
   "＋ Add product" button, so it travels with you — you can add a line from
   anywhere in the list instead of scrolling back to find the button. */
.items-card > .card-head{
  position:sticky; top:var(--topbar-h, 57px); z-index:32;
  background:var(--surface);
  border-radius:var(--radius) var(--radius) 0 0;
}

/* Bring a row clear of both sticky headers when it is scrolled into view. */
table.items tbody tr{ scroll-margin-top:calc(var(--items-th-top, 57px) + 44px); }

/* Blank room after the last card in an editor.
   Without it the final product row sits hard against the bottom of the
   document: the page cannot scroll any further, so that row can never reach
   the middle of the screen and its product list has nowhere to drop open.
   Roughly half a viewport is what centring the last row needs. */
.scroll-tail{ height:45vh; pointer-events:none; }
@media (max-width:900px){ .scroll-tail{ height:55vh; } }
@media print{ .scroll-tail{ display:none; } }

@media (max-width:900px){
  /* the topbar stops being sticky on mobile, so neither of these should be */
  .items-card > .card-head{ position:static; }
  table.items th{ top:0; }
}
table.items td{ padding:4px 6px; border-bottom:1px solid var(--border); }
table.items td input,table.items td select{ padding:6px 8px; font-size:12.8px; }
/* the caret needs its room back at this density */
table.items td select{ padding-right:26px; background-position:right 8px center; }
table.items tfoot td{ background:var(--surface-2); font-weight:650; border-top:1px solid var(--border-2); }
/* The row number doubles as the drag handle — it is the one cell with no
   input in it, so grabbing there can never fight with editing a field. */
table.items .drag{
  cursor:grab; color:var(--text-3); text-align:center; width:26px;
  user-select:none; -webkit-user-select:none;
}
table.items .drag:hover{ color:var(--brand); background:var(--brand-soft); }
table.items .drag:active{ cursor:grabbing; }
table.items tr.dragging{ opacity:.4; background:var(--brand-soft); }

/* A rate box holding the converted figure rather than what was typed. It is
   still editable — typing in it moves the pricing to that currency. */
table.items td input.derived,
td.derived{ color:var(--text-3); font-style:italic; }
table.items td input.derived{ background:var(--surface-2); border-style:dashed; }
table.items td input.derived:focus{ font-style:normal; color:var(--text); background:#fff; }

/* Inline checkbox that sits in a card header next to the buttons */
.inline-check{
  display:flex; align-items:center; gap:7px; font-size:12.5px; color:var(--text-2);
  white-space:nowrap; cursor:pointer;
}
.inline-check input{ width:auto; margin:0; }

/* ------------------------------ Autosave pill ------------------------------ */
.save-state{
  display:inline-flex; align-items:center; gap:8px; padding:7px 13px; border-radius:20px;
  font-size:12.5px; font-weight:550; white-space:nowrap;
  background:var(--accent-soft); color:var(--accent); border:1px solid transparent;
}
.save-state::before{
  content:''; width:7px; height:7px; border-radius:50%; background:currentColor; flex:none;
}
.save-state[data-state="pending"]{ background:var(--surface-2); color:var(--text-3); border-color:var(--border); }
.save-state[data-state="error"]{ background:var(--danger-soft); color:var(--danger); border-color:var(--danger-line); }

/* ------------------------------ Badges ------------------------------ */
.badge{
  display:inline-block; padding:2.5px 8px; border-radius:20px; font-size:11px;
  font-weight:650; letter-spacing:.02em; white-space:nowrap;
}
/* One badge colour per document type — Proforma, Commercial and Tax sit in
   the same list and have to be told apart at a glance. They previously
   resolved to red, green and green. */
.badge.gray { background:#eef1f5;            color:var(--text-2); }
.badge.green{ background:var(--accent-soft); color:var(--accent); }
.badge.amber{ background:var(--warn-soft);   color:var(--warn); }
.badge.blue { background:var(--blue-soft);   color:var(--blue); }
.badge.red  { background:var(--danger-soft); color:var(--danger); }

/* ------------------------------ Filters ------------------------------ */
.filters{
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius);
  padding:13px 15px; margin-bottom:16px; box-shadow:var(--shadow);
}
.filter-row{ display:flex; gap:11px; align-items:flex-end; flex-wrap:wrap; }
.filter-row .field{ margin:0; min-width:150px; }
.filter-row .field.grow{ flex:1; min-width:210px; }
.tabs{ display:flex; gap:4px; background:#eef1f5; padding:3px; border-radius:9px; }
.tabs button{
  border:0; background:transparent; padding:6px 14px; border-radius:7px;
  cursor:pointer; font-size:13px; font-weight:550; color:var(--text-2);
}
.tabs button.active{ background:#fff; color:var(--text); box-shadow:var(--shadow); }

/* ------------------------------ Searchable select ------------------------------ */
.ss{ position:relative; }
.ss-input{ width:100%; }
.ss-list{
  position:absolute; left:0; right:0; top:calc(100% + 4px); background:#fff;
  border:1px solid var(--border-2); border-radius:var(--radius-sm);
  box-shadow:var(--shadow-lg); max-height:264px; overflow-y:auto; z-index:80; padding:4px;
}
/* Inside a modal the body scrolls, which would clip a list opening downwards.
   searchableSelect() measures the room available and flips the list above the
   field when there is more space there. */
.ss-list.up{ top:auto; bottom:calc(100% + 4px); }
.ss-list .opt{ padding:7px 10px; border-radius:6px; cursor:pointer; }
.ss-list .opt:hover,.ss-list .opt.hi{ background:var(--brand-soft); }
.ss-list .opt b{ display:block; font-size:13px; font-weight:600; }
.ss-list .opt small{ font-size:11.4px; color:var(--text-3); }
.ss-list .opt mark{ background:#fdf0c4; color:inherit; padding:0 1px; border-radius:2px; }
.ss-list .none{ padding:12px; text-align:center; color:var(--text-3); font-size:12.5px; }

/* ------------------------------ Modal ------------------------------ */
.modal-root{
  position:fixed; inset:0; background:rgba(16,26,22,.5); z-index:200;
  display:grid; place-items:center; padding:22px; overflow-y:auto;
}
.modal{
  background:#fff; border-radius:13px; box-shadow:var(--shadow-lg);
  width:100%; max-width:520px; margin:auto;
}
.modal.wide{ max-width:880px; }
.modal-head{ padding:17px 20px; border-bottom:1px solid var(--border); display:flex; gap:12px; align-items:center; }
.modal-head h3{ font-size:16px; flex:1; }
.modal-head p{ margin:3px 0 0; font-size:12.4px; color:var(--text-3); font-weight:400; }
.modal-body{ padding:20px; max-height:66vh; overflow-y:auto; }
.modal-foot{ padding:14px 20px; border-top:1px solid var(--border); display:flex; gap:9px; justify-content:flex-end; background:var(--surface-2); border-radius:0 0 13px 13px; }

/* Fields sit flush inside a modal: the modal's own padding is the margin. */
.modal-body > .field:last-child,
.modal-body > .grid:last-child > .field{ margin-bottom:0; }
.modal-body .notice:last-child{ margin-bottom:0; }

/* fx prompt */
.fx-box{
  background:var(--accent-soft); border:1px solid var(--info-line); border-radius:var(--radius);
  padding:15px; margin-bottom:16px;
}
.fx-box .fx-eq{
  display:flex; align-items:center; gap:10px; font-size:16px; font-weight:600; margin-top:8px;
}
.fx-box .fx-eq input{ width:135px; font-size:16px; font-weight:650; text-align:right; }

/* ------------------------------ Toast ------------------------------ */
.toast-root{ position:fixed; right:18px; bottom:18px; z-index:300; display:flex; flex-direction:column; gap:8px; }
.toast{
  background:#1a2233; color:#fff; padding:11px 15px; border-radius:9px;
  box-shadow:var(--shadow-lg); font-size:13px; max-width:340px;
  animation:slideIn .18s ease-out;
}
.toast.ok{ background:var(--brand-dark); }
.toast.err{ background:var(--danger); }
@keyframes slideIn{ from{ opacity:0; transform:translateY(8px); } }

/* ------------------------------ Misc ------------------------------ */
/* Notices took their background from one palette and their border and text
   from another — a blue rule and blue text on a green fill. Both now come
   from the same pair. */
/* Notices took their background from one palette and their border and text
   from another — a blue rule and blue text on a green fill. Each state now
   draws all three from one set. */
.notice{
  background:var(--info-soft); border:1px solid var(--info-line); color:#14512c;
  padding:11px 14px; border-radius:var(--radius-sm); font-size:12.8px; margin-bottom:16px;
}
.notice.warn { background:var(--warn-soft);   border-color:var(--warn-line);   color:var(--warn); }
.notice.error{ background:var(--danger-soft); border-color:var(--danger-line); color:var(--danger); }
.doc-links{ display:flex; gap:7px; flex-wrap:wrap; }
.doc-pill{
  display:inline-flex; align-items:center; gap:6px; padding:5px 11px; border-radius:20px;
  border:1px dashed var(--border-2); font-size:12px; color:var(--text-3); cursor:pointer;
  background:#fff;
}
.doc-pill:hover{ border-color:var(--brand); color:var(--brand); }
.doc-pill.has{ border-style:solid; border-color:var(--brand); background:var(--brand-soft); color:var(--brand-dark); font-weight:600; }
.kv{ display:grid; grid-template-columns:auto 1fr; gap:5px 14px; font-size:13px; }
.kv dt{ color:var(--text-3); }
.kv dd{ margin:0; font-weight:550; }
.split{ display:grid; grid-template-columns:1fr 340px; gap:18px; align-items:start; }
@media (max-width:1150px){ .split{ grid-template-columns:1fr; } }
.sticky-actions{ position:sticky; top:74px; }

/* --------------------------------------------------------------------
   Save pill — the state of the write to MySQL, shown in the topbar.
   Distinct from each editor's own #saveState, which reports local
   validation ("Not saved — select a buyer").
   -------------------------------------------------------------------- */
.save-pill{
  display:inline-flex; align-items:center; gap:6px;
  padding:4px 10px; border-radius:999px;
  font-size:12px; font-weight:600; letter-spacing:.01em;
  border:1px solid transparent; white-space:nowrap;
}
/* Palette variables, not one-off hex fallbacks, so the pill tracks a theme
   change with everything else. */
.save-pill.saving{ background:var(--surface-2);   color:var(--text-2);    border-color:var(--border-2); }
.save-pill.saved { background:var(--accent-soft); color:var(--accent);    border-color:var(--info-line); }
.save-pill.error { background:var(--danger-soft); color:var(--danger);    border-color:var(--danger-line); }
