/* The brand palette, from the asset pack:
     Navy #062B55 · Blue #0864DE · Slate #506079 · White #FFFFFF
   Four colours cannot dress a whole application, so everything blue, grey or
   near-black is derived from them: the surfaces below are those four mixed
   into white, not a borrowed grey ramp. Every text-on-surface pair here clears
   WCAG AA — the weakest is blue on a computed cell at 4.89:1, and body navy on
   white is 14.15:1.

   The semantic colours are NOT brand colours and are deliberately left alone.
   This is a ledger: red and green mean money lost and money made, and amber
   means look at this. Repainting them brand blue would take the meaning out of
   the only thing a bookkeeper reads the colour for. */
:root {
  /* brand */
  --navy: #062B55;
  --blue: #0864DE;
  --slate: #506079;
  --white: #FFFFFF;

  /* chrome, derived from the brand */
  --blue-dark: var(--navy);          /* the header gradient runs navy -> blue */
  --bg: #F7F8F9;                     /* slate at 4.5% */
  --card: var(--white);
  --border: #CACFD7;                 /* slate at 30% */
  --border-light: #EAECEF;           /* slate at 12% */
  --text: #041F3D;                   /* navy 28% toward black: body ink sits BELOW
                                        the accent tier, as it did before */
  --muted: var(--slate);
  --calc-bg: #EEF4FD;                /* blue at 7%: a cell the app worked out */

  /* The tint ladder. Precomputed rather than color-mix()'d: this file had no
     color-mix before and the repo states no browser floor, and a dropped
     declaration takes a selected row or a modal scrim with it silently.
     Each step is the brand colour mixed into white at the stated percent. */
  --blue-12: #E1ECFB;
  --blue-14: #DCE9FA;
  --blue-18: #D3E3F9;
  --blue-30: #B5D0F5;
  --slate-10: #EEEFF2;

  /* semantic — meaning, not branding */
  --green: #047857;
  --red: #b91c1c;
  --amber-bg: #fffbeb;
  --amber-ink: #92400e;              /* the readable pair for --amber-bg, 8.1:1 */
  --amber-line: #fcd34d;             /* its hairline, dark enough to read as a border */
  --amber-strong: #fef3c7;           /* one step down from --amber-bg: a row that needs looking at */
  --violet-bg: #f5f3ff;              /* §14 tax adjustment: deliberate and authorised, not a warning */
  --violet-ink: #5b21b6;             /* the readable pair for --violet-bg */
}

* { box-sizing: border-box; }
body {
  margin: 0;
  font-family: 'Suwannaphum', 'Khmer OS System', serif;
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
}
:lang(km), .kh { font-family: 'Suwannaphum', 'Khmer OS System', serif; }

/* ---------- Top bar ---------- */
/* A white bar, so the full-colour lockup can be itself. The gradient it
   replaced carried the brand; now the logo does, and everything else in here
   is ink on white rather than white on ink. The hairline is --border, not the
   lighter one: the bar and the page behind it are 1.06:1 apart, so this line
   is the only thing separating them as content scrolls under it. */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  background: var(--card); border-bottom: 1px solid var(--border);
  color: var(--text); padding: 10px 20px; position: sticky; top: 0; z-index: 50;
}
.topbar h1 { margin: 0; font-size: 17px; font-weight: 700; }
.topbar h1 span { font-weight: 400; color: var(--muted); font-size: 13px; margin-left: 8px; }
.brand-sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
.actions { display: flex; align-items: center; gap: 10px; }
.btn {
  border: none; border-radius: 8px; padding: 8px 16px; font-size: 13px;
  font-weight: 600; cursor: pointer; font-family: inherit;
}
/* Blue tints are mixed into white at 12% / 18% / 30%, keeping the ladder the
   old indigos had, so resting, hover and picked never collapse into one shade.
   --calc-bg sits below them at 7%, which is why a hover always reads darker
   than a cell the app worked out. */
.btn.primary { background: var(--white); color: var(--blue-dark); }
.btn.primary:hover { background: var(--blue-12); }
.btn.ghost { background: var(--bg); color: var(--text); border: 1px solid var(--border-light); }
.btn.ghost:hover { background: var(--border-light); border-color: var(--border); }
.btn.small { padding: 4px 10px; font-size: 12px; background: var(--blue); color: var(--white); border-radius: 6px; }
.btn.small.outline { background: var(--white); color: var(--blue-dark); border: 1px solid var(--blue); }
.btn.small.outline:hover { background: var(--calc-bg); }
.btn.small.red { background: var(--white); color: var(--red); border: 1px solid var(--red); }
.btn.small.red:hover { background: #fef2f2; }
.btn-group { display: flex; gap: 8px; flex-wrap: wrap; }
.btn.danger { background: transparent; color: var(--red); font-size: 15px; padding: 2px 6px; }
.save-status { font-size: 12px; color: var(--muted); }
/* Was #fde68a, which is 1.25:1 on white — it only ever read because the bar
   was dark. This amber is the one already used for warnings here, at 5.02:1. */
.save-status.dirty { color: #b45309; font-weight: 700; }

/* ---------- Tabs ---------- */
/* ---------- tab strip ----------
   admin.html ALSO uses class="tabs" (its #anav) and has no .shell wrapper, so
   this base rule is what that page gets. The company portal's sidebar lives
   under `.shell .tabs` below — scoping it there is what keeps the admin panel
   from turning into a full-height rail that pushes its own <main> off screen. */
.tabs {
  display: flex; gap: 4px; padding: 8px 16px 0; background: var(--card);
  border-bottom: 2px solid var(--border-light); overflow-x: auto;
  position: sticky; top: 52px; z-index: 40;
}
.tabs button {
  border: none; background: transparent; padding: 10px 14px; cursor: pointer;
  font-family: inherit; font-size: 13px; font-weight: 600; color: var(--muted);
  border-bottom: 3px solid transparent; white-space: nowrap;
}
.tabs button:hover { color: var(--blue); }
.tabs button.active { color: var(--blue-dark); border-bottom-color: var(--blue); }

/* LOAD-BEARING, on BOTH pages. applyModuleGating() (app.js) and applyNavPerms()
   (admin.js) both hide forbidden tabs with the hidden ATTRIBUTE, and the
   explicit display a sidebar row needs would override it — a user would see,
   and could open, sections their permissions do not grant. */
.tabs button[hidden] { display: none !important; }

/* ---------- company portal: the sections live in a left sidebar ----------
   Eleven tabs in a row scrolled sideways on anything but a wide desktop, and a
   horizontally scrolled tab strip hides its own contents. A column shows all
   eleven at once. Everything here is scoped to .shell, which only index.html has. */
.shell { display: grid; grid-template-columns: 228px minmax(0, 1fr); align-items: start; }

.shell .tabs {
  display: block; gap: 0; padding: 10px 8px 16px;
  border-bottom: 0; border-right: 1px solid var(--border-light); overflow-x: visible;
  /* min-height as well as max: without it the rail stops wherever the last tab
     lands and the page shows a white block that ends halfway down. */
  min-height: calc(100vh - 52px); max-height: calc(100vh - 52px); overflow-y: auto;
}
.shell .tabs button {
  display: block; width: 100%; text-align: left;
  border: none; border-bottom: 0; background: transparent; border-radius: 9px;
  padding: 9px 12px; margin-bottom: 2px;
  font-size: 13px; font-weight: 600; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: background .16s, color .16s;
}
.shell .tabs button:hover { background: var(--border-light); color: var(--blue-dark); }
.shell .tabs button.active { background: var(--blue); color: var(--white); border-bottom-color: transparent; }
.shell .tabs button.dragging { opacity: .45; }

/* ---- 📘 Books unfolds its sections in place ----
   Two levels and no more: the rail entry, then the bookkeeping groups with
   their sections. 0fr -> 1fr folds without measuring anything in JS, and the
   wrapper turns visibility:hidden with it — a folded list that is merely
   clipped is still in the tab order, which is a trap for a keyboard. */
.shell .tabs .subnav { display: grid; grid-template-rows: 1fr; transition: grid-template-rows .28s ease; }
.shell .tabs .subnav.closed { grid-template-rows: 0fr; }
.shell .tabs .subnav[hidden] { display: none; }
.shell .tabs .subnav-inner { overflow: hidden; }
.shell .tabs .subnav.closed > .subnav-inner,
.shell .tabs .subnav-group.closed .subnav-list > div { visibility: hidden; transition: visibility 0s .28s; }

/* The left rule is the nesting: these belong to the entry above them. */
.shell .tabs .subnav-group { margin: 0 0 2px 13px; padding-left: 7px; border-left: 1px solid var(--border-light); }
.shell .tabs .subnav-head {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  width: 100%; padding: 7px 8px 3px; margin: 0; border: 0; border-radius: 0; background: none;
  font-family: inherit; font-size: 10px; font-weight: 800; letter-spacing: .07em;
  text-transform: uppercase; color: var(--muted); cursor: pointer;
}
.shell .tabs .subnav-head:hover { background: none; color: var(--blue-dark); }
.shell .tabs .subnav-head svg { width: 13px; height: 13px; flex: none; transition: transform .25s ease; }
.shell .tabs .subnav-group.closed .subnav-head svg { transform: rotate(-90deg); }

.shell .tabs .subnav-list { display: grid; grid-template-rows: 1fr; transition: grid-template-rows .28s ease; }
.shell .tabs .subnav-group.closed .subnav-list { grid-template-rows: 0fr; }
.shell .tabs .subnav-list > div { overflow: hidden; }

.shell .tabs .subnav-item {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  padding: 7px 10px; margin-bottom: 2px; border: 0; border-radius: 9px; background: none;
  font-family: inherit; font-size: 12.5px; font-weight: 600; color: var(--text); cursor: pointer;
  transition: background .16s, color .16s;
}
.shell .tabs .subnav-item svg { width: 15px; height: 15px; flex: none; }

/* ---- 3D icons (public/icons3d, made in Canva) ----
   Images, not glyphs: emoji drew at a different weight on every platform, and
   the line icons were a second style beside them. Sized by where they sit,
   nudged down to centre on the label rather than its baseline, and decorative
   (alt="") — the label beside each one is its name. On a blue active row a
   navy-and-blue icon sinks into the fill (the paperclip, key and refresh
   arrows all but vanish), so there it sits on a small white tile. */
.ic3d { width: 1.35em; height: 1.35em; vertical-align: -0.33em; margin-right: .3em; object-fit: contain; flex: none; }
.shell .tabs button .ic3d { width: 20px; height: 20px; vertical-align: -5px; margin-right: 8px; }
.shell .tabs .subnav-item .ic3d { width: 18px; height: 18px; margin: 0; }
.card h2 .ic3d { width: 22px; height: 22px; vertical-align: -5px; }
.shell .tabs button.active .ic3d,
.shell .tabs .subnav.on-tab .subnav-item.on .ic3d {
  background: var(--white); border-radius: 6px; padding: 2px; box-sizing: border-box;
  box-shadow: 0 1px 2px rgba(6, 43, 85, .25);
}
.shell .tabs .subnav-item:hover { background: var(--border-light); color: var(--blue-dark); }
/* The current section, marked two ways: filled while Books is the open tab,
   and a quiet tint while another tab is — two solid blue entries in one rail
   read as two active places, and only one of them can be. */
.shell .tabs .subnav-item.on { background: var(--blue-12); color: var(--blue-dark); }
.shell .tabs .subnav.on-tab .subnav-item.on { background: var(--blue); color: var(--white); }
.shell .tabs .subnav.on-tab .subnav-item.on:hover { background: var(--blue-dark); color: var(--white); }

/* ---- Tax holds two kinds of entry, and they must not read as one ----
   Ten of them: two ledger sections, and eight whole tabs that moved in from the
   flat rail. A section redraws the Books card; a tab leaves it entirely. So the
   tabs sit below a hairline in their own block, keep the emoji the rail has
   always labelled them with instead of a section's line icon, and light up with
   the rail's filled pill — which is already what every other tab does, one
   level up. Nothing new to learn, and no new colour. */
.shell .tabs .subnav-tabs { margin-top: 5px; padding-top: 5px; border-top: 1px solid var(--border-light); }
.shell .tabs .subnav-tabs.alone { margin-top: 0; padding-top: 0; border-top: 0; }
.shell .tabs .subnav-tab {
  cursor: pointer;                   /* .tabs button says grab; these eight are
                                        deliberately undraggable, so they must not */
  padding: 7px 10px; font-size: 12.5px; color: var(--text);
  /* emoji grow the line box; without this the eight tabs drift out of step
     with the two sections directly above them and the group looks uneven. */
  line-height: 1.3;
}

/* Until the books are set up every section lands on the same setup screen. The
   flag is on <body> because books.js sets it from inside a card that is not an
   ancestor of this rail. The tax tabs are not the books and stay reachable. */
body.bk-unconfigured .shell .tabs .subnav-item { opacity: .45; pointer-events: none; }

/* The drawer chrome exists only on narrow screens, and only in the portal. */
.nav-toggle { display: none; }
.nav-backdrop { display: none; }

@media (max-width: 900px) {
  .shell { grid-template-columns: minmax(0, 1fr); }
  .nav-toggle {
    display: inline-flex; align-items: center; gap: 10px; margin: 10px 0 0 16px;
    padding: 8px 14px; border: 1px solid var(--border); border-radius: 9px;
    background: var(--card); color: var(--text); font-family: inherit;
    font-size: 13px; font-weight: 700; cursor: pointer;
  }
  .nav-toggle .bars { position: relative; display: inline-block; width: 16px; height: 12px; }
  .nav-toggle .bars i { position: absolute; left: 0; width: 100%; height: 2px; border-radius: 2px;
    background: currentColor; transition: transform .28s ease, opacity .2s ease; }
  .nav-toggle .bars i:nth-child(1) { top: 0; }
  .nav-toggle .bars i:nth-child(2) { top: 5px; }
  .nav-toggle .bars i:nth-child(3) { top: 10px; }
  body.nav-open .nav-toggle .bars i:nth-child(1) { transform: translateY(5px) rotate(45deg); }
  body.nav-open .nav-toggle .bars i:nth-child(2) { opacity: 0; }
  body.nav-open .nav-toggle .bars i:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

  .shell .tabs {
    position: fixed; top: 0; left: 0; bottom: 0; width: 252px; max-width: 84vw; z-index: 60;
    max-height: none; transform: translateX(-100%); transition: transform .28s ease;
    border-right: 1px solid var(--border); box-shadow: 0 10px 30px rgba(6, 43, 85, 0.18);
    padding-top: max(14px, env(safe-area-inset-top));
  }
  body.nav-open .shell .tabs { transform: none; }
  .nav-backdrop { display: block; position: fixed; inset: 0; z-index: 59;
    background: rgba(6, 43, 85, 0.45); opacity: 0; pointer-events: none; transition: opacity .28s ease; }
  body.nav-open .nav-backdrop { opacity: 1; pointer-events: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .shell .tabs, .nav-backdrop, .nav-toggle .bars i,
  .shell .tabs .subnav, .shell .tabs .subnav-list, .shell .tabs .subnav-head svg,
  .shell .tabs .subnav-inner, .shell .tabs .subnav-list > div { transition: none !important; }
}

main { padding: 20px; max-width: 1280px; margin: 0 auto; }

/* The company portal runs the full width of the shell.
   `margin: 0 auto` above is the real cap, not max-width. main is a grid item in
   .shell, and auto inline margins switch stretch OFF, so every tab sized itself
   to its own content and stopped: measured at a 1920px viewport, Company
   Information came out 877px, Staff 665px and the 16-column payroll sheet 1280px
   — three tabs of one portal disagreeing with each other, none of them using the
   1,692px the column was offering, and the payroll sheet scrolling sideways
   inside its own wrapper at 1,198px while 412px sat empty beside it.
   margin-inline puts the stretch back; max-width lets it keep going past a
   1508px viewport. BOTH are needed: max-width on its own measured as an exact
   no-op at every width from 1280 to 2560.
   Scoped to .shell because bare `main` also styles admin.html and firm.html,
   which have no .shell; for those two the rule above IS the page layout. */
.shell main { max-width: none; margin-inline: 0; }

/* The tables want the width. The FIELD grids do not: .grid.c3 is auto-fit
   minmax(200px, 1fr), so Company Information's nine fields went from 3 tracks to
   7 at 1920px and the Staff form from 2 to 7 — the fields got NARROWER as the
   page got wider, because more of them were crammed onto each row. 840px is the
   widest value that still holds three, which is the shape these forms were drawn
   for. Only c3 is capped: .grid.c2 in this portal wraps CARDS — the dashboard,
   the monthly workflow, the annual page — and those are meant to grow. */
.shell main .grid.c3 { max-width: 840px; }

/* And no single input needs to be half a metre wide. The full-address field sits
   alone in a .grid.c2 row, so uncapped it stretched to ~800px on a wide monitor.
   This binds on nothing else: a field inside a capped three-column grid is ~268px
   already, and the TRS 01 and letter forms live in .form-paper, which is capped
   at 900px and centred — verified unchanged at 1440, 1920 and 2560. */
.shell main .field { max-width: 520px; }
.loading { text-align: center; padding: 60px; color: var(--muted); }

/* ---------- Cards / sections ---------- */
.card {
  background: var(--card); border: 1px solid var(--border-light);
  border-radius: 12px; padding: 20px; margin-bottom: 18px;
  box-shadow: 0 1px 3px rgba(6, 43, 85, 0.05);
}
.card h2 {
  margin: 0 0 14px; font-size: 15px; color: var(--blue-dark);
  border-bottom: 2px solid var(--border-light); padding-bottom: 8px;
}
.grid { display: grid; gap: 12px 18px; }
.grid.c2 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grid.c3 { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.field label { display: block; font-size: 11.5px; font-weight: 600; color: var(--muted); margin-bottom: 3px; }
.field input, .field select {
  width: 100%; padding: 7px 10px; border: 1px solid var(--border);
  border-radius: 7px; font-family: inherit; font-size: 13.5px; background: var(--white);
}
.field input:focus, td input:focus { outline: 2px solid var(--blue); outline-offset: -1px; border-color: var(--blue); }

/* ---------- Stat tiles ---------- */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; margin-bottom: 18px; }
.stat {
  background: var(--card); border: 1px solid var(--border-light); border-radius: 12px;
  padding: 14px 16px; box-shadow: 0 1px 3px rgba(6, 43, 85, 0.05);
}
.stat .lbl { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.stat .val { font-size: 19px; font-weight: 700; margin-top: 4px; }
.stat .sub { font-size: 11.5px; color: var(--muted); margin-top: 2px; }
.stat.good .val { color: var(--green); }
.stat.bad .val { color: var(--red); }
.stat.blue .val { color: var(--blue-dark); }

/* ---------- Tables ---------- */
.tbl-wrap { overflow-x: auto; }
table.sheet { border-collapse: collapse; width: 100%; font-size: 12.5px; }
table.sheet th, table.sheet td { border: 1px solid var(--border); padding: 5px 7px; }
table.sheet thead th {
  background: var(--blue-dark); color: var(--white); font-weight: 600; font-size: 11.5px;
  text-align: center; vertical-align: middle;
}
table.sheet thead tr.sub th { background: var(--blue); font-weight: 500; }
table.sheet td.num, table.sheet th.num { text-align: right; font-variant-numeric: tabular-nums; }
table.sheet td.ctr { text-align: center; }
table.sheet td.calc { background: var(--calc-bg); font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; }
table.sheet tbody tr:nth-child(even) td:not(.calc) { background: var(--bg); }
table.sheet tbody tr:hover td { background: #fef9c3 !important; }
table.sheet tfoot td { background: var(--amber-bg); font-weight: 700; border-top: 2px solid var(--blue-dark); }
table.sheet td input {
  width: 100%; min-width: 52px; border: none; background: transparent; padding: 3px 2px;
  font-family: inherit; font-size: 12.5px; border-radius: 4px;
}
table.sheet td input.num { text-align: right; font-variant-numeric: tabular-nums; }
table.sheet td input:hover { background: #fff7d6; }
.tbl-actions { display: flex; justify-content: space-between; align-items: center; margin: 12px 0 4px; }
.row-count { font-size: 12px; color: var(--muted); }

/* ---------- Sales Tax Book ----------
   A generated book has two kinds of row that a typed one never had, and both
   have to be legible at a glance in a column of figures.

   A credit note is a real reversal of real turnover, so it is marked in red --
   the ledger meaning of the colour, not a warning about the row. A legacy row
   is turnover that has not been reconciled to a posted transaction yet; amber
   is "look at this", which is exactly its status. Neither uses a brand colour:
   these say what the number IS. */
table.sheet tbody tr.tb-credit td { color: var(--red); }
/* :not(.calc) matches the zebra rule above it selector for selector, so the
   amber wins on an even row too; the computed cells keep their own tint. */
table.sheet tbody tr.tb-legacy td:not(.calc) { background: var(--amber-bg); }
/* A legacy row that matches a sale posted in Books. It is still counted and its
   figures are still the declaration's, so the number is not repainted red as if
   it were wrong — what is wrong is that it may be here twice. A stronger amber
   and a left marker say "settle this one" without claiming the answer. */
table.sheet tbody tr.tb-dup td:not(.calc) { background: var(--amber-strong); }
table.sheet tbody tr.tb-dup td:first-child { box-shadow: inset 3px 0 0 var(--amber-line); }
/* §14's documented tax adjustments. Violet, not amber and not red: it is not a
   warning and it is not wrong — it is a deliberate, authorised, evidenced entry
   that is NOT a sale, and the point of colouring it at all is that a reader can
   never mistake one for a row that came out of Books. The same tint marks the
   adjustment line in the book's own totals and every row of the table below it. */
table.sheet tbody tr.tb-adjust td:not(.calc),
table.sheet tfoot tr.tb-adjust td { background: var(--violet-bg); }
table.sheet tfoot tr.tb-adjust td { font-style: italic; }
/* The invoice number is the transaction. It reads as a link because it is one. */
.tb-open { color: var(--blue); font-weight: 600; text-decoration: none; }
.tb-open:hover, .tb-open:focus { text-decoration: underline; }
@media print {
  .tb-open { color: inherit; font-weight: inherit; }
}

/* ---------- Official form (TRS01 / P101 / letter) ---------- */
.form-paper {
  background: var(--white); border: 1px solid var(--border); border-radius: 4px;
  max-width: 900px; margin: 0 auto 18px; padding: 36px 44px;
  box-shadow: 0 2px 10px rgba(6, 43, 85, 0.08);
  font-family: 'Suwannaphum', 'Khmer OS System', serif;
  line-height: 1.65;
}
.form-paper .en { font-family: 'Suwannaphum', serif; }
.fhead { display: flex; justify-content: space-between; font-size: 12.5px; text-align: center; }
.fhead .col b { display: block; }
.fhead .moto { font-size: 13px; font-weight: 700; }
.ftitle { text-align: center; margin: 14px 0; }
.ftitle .t1 { font-size: 17px; font-weight: 700; color: var(--blue-dark); }
.ftitle .t2 { font-size: 13px; color: var(--muted); }
.fnote { text-align: right; font-size: 12px; font-weight: 600; }
.boxes { display: inline-flex; gap: 3px; vertical-align: middle; }
.boxes span {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 26px; border: 1.5px solid var(--text); font-weight: 700;
  font-size: 13px; font-family: 'Suwannaphum', serif; background: var(--white);
}
.boxes span.dash { border: none; width: 10px; }
.frow { display: flex; flex-wrap: wrap; gap: 6px 24px; align-items: baseline; margin: 7px 0; font-size: 13px; }
.frow .lbl { font-weight: 600; }
.frow .fill {
  flex: 1; min-width: 120px; border-bottom: 1px dotted var(--muted);
  padding: 0 6px; font-weight: 600; color: var(--blue-dark);
}
table.form-tbl { border-collapse: collapse; width: 100%; font-size: 13px; margin: 10px 0; }
table.form-tbl th, table.form-tbl td { border: 1.4px solid var(--text); padding: 6px 9px; }
table.form-tbl th { background: var(--bg); text-align: center; }
table.form-tbl td.num { text-align: right; font-variant-numeric: tabular-nums; }
table.form-tbl td.calc { background: var(--calc-bg); font-weight: 700; text-align: right; }
table.form-tbl tr.total td { background: var(--amber-bg); font-weight: 700; }
.fsig { display: flex; justify-content: space-between; margin-top: 30px; font-size: 12.5px; text-align: center; }
.fsig .col { width: 45%; }
.fsig .line { margin-top: 56px; border-top: 1px dotted var(--text); }
.fdecl { font-size: 12px; color: var(--muted); margin: 12px 0; text-align: justify; }

/* letter */
.letter { font-size: 13.5px; }
.letter p { margin: 9px 0; }
.letter h3 { font-size: 14px; margin: 16px 0 6px; }
/* editable client-letter exchange rate (screen); a formatted copy prints instead */
.letter-rate { width: 84px; text-align: right; font: inherit; padding: 1px 5px; border: 1px solid var(--border); border-radius: 4px; background: var(--calc-bg); }
.letter-rate:focus { outline: none; border-color: var(--blue-dark); }
.letter-rate-print { display: none; }

.badge { display: inline-block; background: var(--calc-bg); color: var(--blue-dark); font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 99px; margin-left: 8px; }
.hint { font-size: 12px; color: var(--muted); margin: 6px 0; }

/* ---------- Print ---------- */
@media print {
  body { background: #fff; }
  .no-print, .tbl-actions, .btn { display: none !important; }
  /* the sidebar is .no-print, so collapse the grid or its column prints blank */
  .shell { display: block; }
  main { padding: 0; max-width: none; }
  .card, .form-paper { box-shadow: none; border: none; margin: 0; padding: 10px; }
  table.sheet thead th { background: #ddd !important; color: #000 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  td input { border: none !important; }
  .letter-rate-print { display: inline !important; }
}

/* ---------- TRS 01 official header (scoped, additive) ---------- */
.trs-head { display: flex; align-items: flex-start; gap: 14px; }
.trs-col { flex: 1; text-align: center; }
.trs-center { flex: 0 0 190px; }
.trs-logo { width: 175px; height: auto; }
.trs-kh { font-size: 13.5px; font-weight: 700; color: #1f6e63; line-height: 1.9; }
.trs-en { font-size: 11px; font-weight: 700; color: #1f6e63; letter-spacing: .4px; }
.trs-rule { border-bottom: 2.5px solid #e07b2f; padding-bottom: 4px; margin-bottom: 4px; }
.trs-sublbl { font-size: 11px; font-weight: 700; line-height: 1.3; text-align: left; }
.trs-sublbl i, .trs-lbl i, .trs-mbox i { font-style: normal; font-weight: 400; font-size: 9.5px; color: #444; }
.trs-box-fill {
  display: inline-flex; align-items: center; justify-content: center;
  border: 1.5px solid #333; background: #fff; min-width: 110px; min-height: 32px;
  padding: 2px 12px; font-size: 13px; font-weight: 600;
  box-shadow: 2px 2px 0 rgba(0,0,0,.18);
}
.trs-branch { display: flex; align-items: center; gap: 10px; justify-content: flex-start; margin-top: 8px; text-align: left; }
.trs-branch .trs-box-fill { flex: 1; }
.trs-form-panel { background: #dcdcdc; padding: 8px 10px 10px; margin-top: 8px; box-shadow: 2px 2px 0 rgba(0,0,0,.18); }
.trs-form-no { text-align: center; font-size: 12px; font-weight: 700; padding-bottom: 6px; }
.trs-form-month { display: flex; align-items: center; justify-content: center; gap: 6px; font-size: 11.5px; font-weight: 700; }
.trs-form-month .trs-mbox { display: inline-flex; flex-direction: column; align-items: flex-end; }
.trs-form-month .trs-box-fill { min-width: 74px; min-height: 28px; }
.trs-form-month .trs-mbox:last-child .trs-box-fill { min-width: 60px; }
.trs-title-row { display: flex; align-items: center; gap: 20px; margin: 14px 0 10px; }
.trs-title { flex: 1; text-align: center; margin-left: 190px; }
.trs-title .t1 { font-size: 15.5px; font-weight: 700; color: #1d3a6e; }
.trs-title .t1.sm { font-size: 12.5px; margin-top: 2px; }
.trs-title .t2 { font-size: 11px; font-weight: 700; color: #1d3a6e; letter-spacing: .5px; }
.trs-barcode {
  flex: 0 0 250px; border: 1.5px solid #333; min-height: 46px;
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; color: #777;
}
.trs-period-lbls {
  display: flex; justify-content: space-between; gap: 16px;
  font-size: 11px; font-weight: 700;
  border-top: 2.5px solid #e07b2f; padding: 6px 0 4px; margin-top: 6px;
}
.trs-en-inline { font-weight: 400; }
.trs-period-row { display: flex; align-items: center; justify-content: space-between; gap: 6px; flex-wrap: nowrap; margin-bottom: 10px; }
.trs-period-row .boxes { gap: 2px; }
.trs-period-row .trs-sublbl { font-size: 9.5px; }
.trs-period-row .trs-sublbl i { font-size: 8.5px; }
.trs-period-row .boxes span { width: 17px; height: 22px; font-size: 10.5px; }
.trs-info { display: flex; flex-direction: column; gap: 7px; }
.trs-row { display: flex; align-items: stretch; gap: 8px; }
.trs-lbl { flex: 0 0 auto; font-size: 11px; font-weight: 700; line-height: 1.3; align-self: center; }
.trs-lbl i { font-style: normal; }
.trs-val {
  display: flex; align-items: center; justify-content: center;
  border: 1.5px solid #333; background: #fff; min-height: 33px;
  padding: 3px 10px; font-size: 13px; font-weight: 600;
  box-shadow: 2px 2px 0 rgba(0,0,0,.18); text-align: center;
}
.trs-val.grow { flex: 1; }
@media print { .trs-form-panel { -webkit-print-color-adjust: exact; print-color-adjust: exact; } }

/* ---------- SaaS shell (additive) ---------- */
.user-chip { font-size: 12px; background: var(--bg); color: var(--muted); border: 1px solid var(--border-light);
             padding: 5px 12px; border-radius: 99px; white-space: nowrap; }
.sub-banner {
  background: #fef2f2; color: var(--red); border-bottom: 1px solid #fecaca;
  padding: 9px 20px; font-size: 13px; font-weight: 700; text-align: center;
}
.abadge { display: inline-block; font-size: 11px; font-weight: 700; padding: 2px 9px; border-radius: 99px; }
.abadge.ok { background: #d1fae5; color: var(--green); }
.abadge.bad { background: #fee2e2; color: var(--red); }
.abadge.mut { background: var(--border-light); color: var(--muted); }
.modgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 6px; }
.modchk { display: flex; align-items: center; gap: 8px; font-size: 12.5px; background: var(--bg);
  border: 1px solid var(--border-light); border-radius: 7px; padding: 7px 10px; cursor: pointer; }
.modtag { background: var(--calc-bg); color: var(--blue-dark); font-size: 11px; padding: 1px 7px; border-radius: 5px; }
a.btn { text-decoration: none; display: inline-block; }
.np-sel { padding: 5px 8px; border: 1px solid var(--border); border-radius: 6px; font-family: inherit; font-size: 12.5px; background: var(--white); }
#npYear { width: 90px; }
[hidden] { display: none !important; }
/* combined print: each tab starts on a new page */
.print-section { break-inside: auto; }
@media print {
  .print-section { page-break-after: always; }
  .print-section:last-child { page-break-after: auto; }
  .print-section .stats, .print-section .hint, .print-section .row-count,
  .print-section .sum-grid, .print-section .sum-section-title { display: none !important; }
}
/* combined print: day books rotate to A4 landscape, forms stay portrait */
@page { size: A4 portrait; }
@page landscape-sheet { size: A4 landscape; }
@media print {
  .print-landscape { page: landscape-sheet; }
}
@media print {
  /* day books: hide the delete-button column left empty in print */
  .print-landscape table.sheet th:last-child, .print-landscape table.sheet td:last-child { display: none; }
}
@media print {
  /* day books: balanced column widths so dates, invoices and Khmer text don't clip */
  .print-landscape table.sheet td:nth-child(2), .print-landscape table.sheet th:nth-child(2) { min-width: 82px; }
  .print-landscape table.sheet td:nth-child(3), .print-landscape table.sheet th:nth-child(3) { min-width: 95px; }
  .print-landscape table.sheet td:nth-child(5), .print-landscape table.sheet th:nth-child(5) { min-width: 150px; }
}

/* ---------- TRS 01: official-style tax calculation table + signature boxes ---------- */
.trs-calc-title { background: #d9c49c; border: 1px solid #b59663; padding: 4px 10px; font-weight: 700; font-size: 13px; margin-top: 14px; }
.trs-turnover { display: flex; align-items: center; gap: 10px; margin: 10px 0 6px; }
.trs-turnover .trs-A { font-size: 26px; font-weight: 700; font-family: 'Suwannaphum', serif; }
.trs-turnover .lbl { font-size: 11.5px; font-weight: 700; }
.trs-turnover .trs-K { border: 1.5px solid #333; background: #e7d9bd; padding: 2px 10px; font-weight: 700; box-shadow: 2px 2px 0 rgba(0,0,0,.15); }
.trs-turnover .trs-kval { flex: 1; max-width: 280px; border: 1.5px solid #333; padding: 3px 12px; text-align: right; font-weight: 700; box-shadow: 2px 2px 0 rgba(0,0,0,.15); }
table.trs-calc th, table.trs-calc td { border-color: #b45309; }
table.trs-calc th { background: #faf0dd; position: relative; padding-bottom: 18px; }
table.trs-calc .trs-abcd { position: absolute; left: 0; right: 0; bottom: 0; background: #f3dfba; border-top: 1px solid #b45309; font-weight: 700; }
table.trs-calc .trs-bcode { float: left; font-weight: 700; background: #f3dfba; border: 1px solid #b45309; font-size: 10.5px; padding: 0 5px; border-radius: 2px; }
table.trs-calc .trs-rate { background: #fdf6ea; font-weight: 700; }
table.trs-calc tr.total td { background: #f3dfba; }
.trs-en-sm { font-size: 10.5px; color: #555; }
.trs-decl-h { margin: 12px 0 2px; font-size: 13px; }
.trs-sign { display: flex; gap: 26px; margin-top: 12px; }
.trs-sigbox { flex: 1; border: 1.6px solid #b45309; padding: 8px 12px; }
.trs-sigbox .t { font-size: 11px; font-weight: 700; border-bottom: 1px solid #e3cba0; padding-bottom: 4px; margin-bottom: 8px; }
.trs-sigbox .r { display: flex; align-items: flex-start; gap: 10px; margin: 7px 0; }
.trs-sigarea { flex: 1; border: 1.4px solid #333; min-height: 64px; background: #fff; }
.trs-namearea { flex: 1; border: 1.4px solid #333; min-height: 26px; background: #fff; }
.trs-sigbox .boxes span { width: 20px; height: 24px; }

/* combined print: TRS 01 compact — whole form fits one A4 portrait page */
@media print {
  .print-trs01 .form-paper { padding: 8px 6px; line-height: 1.3; }
  .print-trs01 .trs-logo { width: 110px; }
  .print-trs01 .trs-kh { font-size: 11px; line-height: 1.55; }
  .print-trs01 .trs-en { font-size: 9px; }
  .print-trs01 .trs-box-fill { min-height: 22px; min-width: 84px; font-size: 10.5px; padding: 1px 8px; }
  .print-trs01 .trs-form-panel { padding: 4px 8px 6px; margin-top: 4px; }
  .print-trs01 .trs-form-no { font-size: 10px; padding-bottom: 3px; }
  .print-trs01 .trs-form-month { font-size: 9.5px; }
  .print-trs01 .trs-form-month .trs-box-fill { min-width: 56px; min-height: 20px; }
  .print-trs01 .trs-branch { margin-top: 4px; }
  .print-trs01 .trs-title-row { margin: 6px 0 4px; }
  .print-trs01 .trs-title .t1 { font-size: 12.5px; }
  .print-trs01 .trs-title .t1.sm { font-size: 10.5px; }
  .print-trs01 .trs-title .t2 { font-size: 9px; }
  .print-trs01 .trs-barcode { flex-basis: 190px; min-height: 32px; font-size: 8px; }
  .print-trs01 .trs-period-lbls { font-size: 8.5px; padding: 3px 0 2px; }
  .print-trs01 .trs-period-row { margin-bottom: 4px; }
  .print-trs01 .trs-period-row .boxes span { width: 14px; height: 17px; font-size: 8.5px; }
  .print-trs01 .trs-period-row .trs-sublbl { font-size: 8px; }
  .print-trs01 .trs-period-row .trs-sublbl i { font-size: 7px; }
  .print-trs01 .trs-info { gap: 3px; }
  .print-trs01 .trs-lbl { font-size: 8.5px; }
  .print-trs01 .trs-lbl i { font-size: 7.5px; }
  .print-trs01 .trs-val { min-height: 20px; font-size: 10.5px; padding: 1px 6px; }
  .print-trs01 .trs-calc-title { margin-top: 6px; font-size: 10.5px; padding: 2px 8px; }
  .print-trs01 .trs-turnover { margin: 5px 0 3px; }
  .print-trs01 .trs-turnover .trs-A { font-size: 18px; }
  .print-trs01 .trs-turnover .lbl { font-size: 9px; }
  .print-trs01 .trs-turnover .trs-kval, .print-trs01 .trs-turnover .trs-K { font-size: 10.5px; padding: 1px 8px; }
  .print-trs01 table.form-tbl { font-size: 9.5px; margin: 4px 0; }
  .print-trs01 table.form-tbl th, .print-trs01 table.form-tbl td { padding: 2px 6px; }
  .print-trs01 table.trs-calc th { padding-bottom: 14px; }
  .print-trs01 .trs-en-sm { font-size: 8px; }
  .print-trs01 .trs-bcode { font-size: 8.5px; }
  .print-trs01 .trs-decl-h { margin: 10px 0 3px; font-size: 10px; }
  .print-trs01 .fdecl { font-size: 7.8px; margin: 6px 0; line-height: 1.85; }
  .print-trs01 .trs-sign { margin-top: 14px; gap: 16px; }
  .print-trs01 .trs-sigbox { padding: 8px 10px; }
  .print-trs01 .trs-sigbox .t { font-size: 8.5px; margin-bottom: 8px; }
  .print-trs01 .trs-sigbox .r { margin: 9px 0; gap: 6px; }
  .print-trs01 .trs-sigbox .boxes span { width: 14px; height: 17px; font-size: 8.5px; }
  .print-trs01 .trs-sigarea { min-height: 56px; }
  .print-trs01 .trs-namearea { min-height: 26px; }
  .print-trs01 .trs-sublbl { font-size: 8px; }
  .print-trs01 .trs-sublbl i { font-size: 7px; }
}

/* combined print: client letter compact — fits one A4 portrait page */
@media print {
  .print-letter .form-paper { padding: 14px 24px; line-height: 1.35; }
  .print-letter .letter { font-size: 11.5px; }
  .print-letter .letter p { margin: 5px 0; }
  .print-letter .letter h3 { font-size: 12px; margin: 8px 0 3px; }
  .print-letter table.form-tbl { font-size: 11px; margin: 6px 0; }
  .print-letter table.form-tbl th, .print-letter table.form-tbl td { padding: 3px 8px; }
  .print-letter .fsig { margin-top: 16px; font-size: 10.5px; }
  .print-letter .fsig .line { margin-top: 34px; }
}

/* draggable tabs */
.tabs button { cursor: grab; }
.tabs button.dragging { opacity: .45; cursor: grabbing; background: var(--calc-bg); border-radius: 6px 6px 0 0; }

/* print tab-selector modal */
.modal-overlay { position: fixed; inset: 0; background: rgba(6, 43, 85, 0.5); display: flex;
  align-items: center; justify-content: center; z-index: 100; }
.modal { background: var(--white); border-radius: 12px; padding: 22px 24px; width: 100%; max-width: 380px;
  box-shadow: 0 12px 40px rgba(0,0,0,.3); }
.modal h3 { margin: 0 0 14px; font-size: 15px; color: var(--blue-dark); }
.modal-list { display: flex; flex-direction: column; gap: 7px; margin-bottom: 16px; }
.modal-actions { display: flex; align-items: center; gap: 8px; }
@media print { .modal-overlay { display: none !important; } }
.modal-sub { font-size: 12px; font-weight: 700; color: var(--blue-dark); margin: 4px 0 6px; }
.modsize { color: var(--muted); font-size: 11px; margin-left: auto; }
.modchk { justify-content: flex-start; }
/* rasterized attachment pages */
.print-attach { text-align: center; }
.print-attach img { width: 100%; height: auto; display: block; }
@media print {
  /* fit each rasterized page within the printable area (no overflow to a blank page) */
  .print-attach img { width: auto; height: auto; max-width: 100%; max-height: 252mm; margin: 0 auto; }
  .print-landscape.print-attach img { max-height: 180mm; }
}
.modal-hint { font-size: 11.5px; color: var(--muted); margin: -6px 0 12px; }
.modchk[draggable] { cursor: grab; }
.modchk.dragging { opacity: .45; background: var(--calc-bg); }
.draghandle { color: var(--muted); cursor: grab; user-select: none; font-size: 13px; }

/* ---------- summary cards (bottom of Selling/Buying) ---------- */
.sum-section-title { margin: 18px 0 8px; font-size: 13px; font-weight: 700; color: var(--blue-dark); }
.sum-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 14px; margin-top: 16px; }
.sum-card {
  display: flex; align-items: center; gap: 13px; padding: 14px 16px;
  background: var(--card); border: 1px solid var(--border-light); border-radius: 14px;
  box-shadow: 0 4px 14px rgba(6, 43, 85, 0.06); position: relative; overflow: hidden;
  transition: transform .15s ease, box-shadow .15s ease;
}
.sum-card:hover { transform: translateY(-2px); box-shadow: 0 8px 22px rgba(6, 43, 85, 0.12); }
.sum-card::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 5px; background: var(--accent, var(--blue)); }
.sum-card.span2 { grid-column: span 2; }
.sum-ic {
  flex: 0 0 auto; width: 44px; height: 44px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center; font-size: 22px;
  background: var(--accent-soft, var(--calc-bg));
}
.sum-body { min-width: 0; }
.sum-lbl { font-size: 11.5px; font-weight: 600; color: var(--muted); line-height: 1.3; }
.sum-val { font-size: 20px; font-weight: 800; color: var(--text); margin-top: 2px; font-variant-numeric: tabular-nums; }
.sum-val.sm { font-size: 16px; }
.sum-card.teal   { --accent: #0d9488; --accent-soft: #ccfbf1; }
.sum-card.violet { --accent: #7c3aed; --accent-soft: #ede9fe; }
.sum-card.blue   { --accent: var(--blue);  --accent-soft: var(--blue-18); }
.sum-card.amber  { --accent: #d97706; --accent-soft: #fef3c7; }
.sum-card.red    { --accent: #dc2626; --accent-soft: #fee2e2; }
.sum-card.green  { --accent: #059669; --accent-soft: #d1fae5; }
.sum-card.slate  { --accent: var(--slate); --accent-soft: var(--slate-10); }
.sum-card.red .sum-val { color: var(--red); }
.prevsal-row { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; text-align: left; padding: 10px 12px; border: 1px solid var(--border-light);
  background: var(--bg); border-radius: 8px; font-family: inherit; font-size: 13px; cursor: pointer; }
.prevsal-row:hover { background: var(--calc-bg); border-color: var(--blue); }

/* ---------- File Checking tab ---------- */
.modal-sub + .modgrid { margin-bottom: 10px; }
.fc-file { display: flex; align-items: center; gap: 6px; }
.fc-sel { flex: 1; min-width: 130px; max-width: 220px; padding: 2px 4px; border: 1px solid var(--border-light);
  border-radius: 5px; font-family: inherit; font-size: 11.5px; background: var(--white); color: var(--muted); }
.fc-sel:hover { border-color: var(--blue); color: var(--text); }
.fc-note { display: block; font-size: 10.5px; color: var(--red); margin-top: 2px; }
table.sheet td.fc-issues { font-size: 11.5px; color: var(--red); max-width: 340px; }
table.sheet td .abadge { cursor: help; }
.abadge.warn { background: #ede9fe; color: #6d28d9; }
.abadge.eye { border-bottom: 2px dotted currentColor; }
.fc-note.mut { color: var(--muted); }
table.sheet td.fc-issues .btn { margin-top: 4px; }

/* by-eye review window: scan on the left, typed figures on the right */
.modal.wide { max-width: 1180px; max-height: 94vh; overflow: auto; }
.fc-review { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(280px, 1fr); gap: 16px; }
.fc-page { display: flex; flex-direction: column; min-width: 0; }
.fc-page-bar { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; font-size: 12px; color: var(--muted); }
.fc-page-sel { max-width: 190px; font-size: 11.5px; padding: 3px 5px; color: var(--text); }
.fc-thumbs {
  display: flex; gap: 8px; overflow-x: auto; padding: 8px; margin-bottom: 8px;
  background: var(--bg); border: 1px solid var(--border-light); border-radius: 8px;
}
.fc-thumb {
  flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 5px; border: 2px solid transparent; border-radius: 8px; background: var(--white);
  cursor: pointer; font-family: inherit; transition: transform .12s ease, border-color .12s ease, box-shadow .12s ease;
}
.fc-thumb:hover { transform: translateY(-2px); box-shadow: 0 5px 14px rgba(6, 43, 85, 0.16); }
.fc-thumb.active { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(8, 100, 222, 0.18); }
.fc-thumb-img { display: block; width: 64px; height: 88px; background: var(--border-light); border-radius: 3px; overflow: hidden; }
.fc-thumb-img img { width: 100%; height: 100%; object-fit: cover; object-position: top; display: block; }
.fc-thumb-no { font-size: 10.5px; font-weight: 800; color: var(--muted); }
.fc-thumb.active .fc-thumb-no { color: var(--blue-dark); }
.btn.small.outline.on { background: var(--blue); color: var(--white); border-color: var(--blue); }
.fc-page-view { flex: 1; min-height: 300px; max-height: 56vh; overflow: auto; background: var(--bg);
  border: 1px solid var(--border-light); border-radius: 8px; padding: 8px; text-align: center; }
.fc-page-view canvas { max-width: none; box-shadow: 0 2px 10px rgba(6, 43, 85, 0.15); background: var(--white); }
.fc-fields { max-height: 76vh; overflow: auto; display: flex; flex-direction: column; gap: 8px; }
.fc-field { border: 1px solid var(--border-light); border-radius: 8px; padding: 8px 10px; background: var(--bg); }
.fc-field-lbl { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.fc-field-val { font-size: 16px; font-weight: 700; margin: 2px 0 6px; font-variant-numeric: tabular-nums; word-break: break-word; }
/* the per-field ✓ / ✗ toggles wear the same pill shape as the action buttons */
.fc-mark { border-radius: 999px; padding: 5px 13px; font-weight: 700; transition: transform .12s ease, box-shadow .12s ease; }
.fc-mark:hover { transform: translateY(-1px); box-shadow: 0 3px 9px rgba(6, 43, 85, 0.1); }
.fc-mark.on[data-mark="ok"] { background: var(--green); color: var(--white); border-color: var(--green); }
.fc-mark.on[data-mark="bad"] { background: var(--red); color: var(--white); border-color: var(--red); }
@media (max-width: 900px) { .fc-review { grid-template-columns: 1fr; } }

/* OCR of the shown page, under the image */
.fc-ocr { margin-top: 8px; }
.fc-ocr-bar { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); flex-wrap: wrap; }
.fc-ocr-bar .fc-sel { flex: 0 0 auto; min-width: 0; width: auto; }
.fc-ocr-state { font-size: 11.5px; color: var(--blue-dark); }
.fc-ocr-text {
  margin: 6px 0 0; padding: 8px 10px; max-height: 116px; overflow: auto; white-space: pre-wrap;
  background: var(--bg); border: 1px solid var(--border-light); border-radius: 8px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px; line-height: 1.5;
}
.fc-ocr-hint { font-size: 10.5px; font-weight: 600; color: var(--muted); }
.fc-ocr-fix { margin-top: 4px; font-size: 11px; font-weight: 600; color: #b45309; }
.fc-ocr-hint.ok { color: var(--green); }

/* blue highlight: the row's figure, shown where it sits on the page */
.fc-canvas-wrap { position: relative; display: inline-block; line-height: 0; }
.fc-canvas-wrap canvas { display: block; }
.fc-hl-layer { position: absolute; inset: 0; pointer-events: none; }
.fc-hl {
  position: absolute; border-radius: 3px;
  background: rgba(8, 100, 222, 0.26);
  border: 1.5px solid rgba(8, 100, 222, 0.85);
  box-shadow: 0 0 0 2px rgba(8, 100, 222, 0.12);
}
.fc-hl.flash { animation: fc-hl-flash 1.1s ease-out 2; }
@keyframes fc-hl-flash {
  0%, 100% { background: rgba(8, 100, 222, 0.26); }
  50% { background: rgba(8, 100, 222, 0.62); }
}
.fc-field-val.hit {
  background: var(--blue-18); color: var(--blue-dark); border-radius: 5px;
  padding: 1px 6px; margin-left: -6px; cursor: pointer; display: inline-block;
}
.fc-field-val.hit:hover { background: var(--blue-30); }
.fc-hit-tag { font-size: 10.5px; font-weight: 700; color: var(--blue); }

/* pick which day-book row this page belongs to */
.fc-rowpick { display: flex; align-items: center; gap: 8px; margin: -6px 0 8px; flex-wrap: wrap; }
.fc-rowpick label { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.fc-rowpick .fc-sel { flex: 1; min-width: 260px; max-width: 100%; font-size: 12px; padding: 4px 6px; color: var(--text); }

/* "already checked" — stamped across the page and repeated beside the figures */
.fc-stamp {
  position: absolute; left: 50%; top: 20%; transform: translate(-50%, -50%) rotate(-14deg);
  display: flex; flex-direction: column; align-items: center; gap: 8px; pointer-events: none;
  padding: 12px 28px; border: 4px solid rgba(5, 150, 105, .55); border-radius: 12px;
  background: rgba(209, 250, 229, .38); color: rgba(4, 120, 87, .85);
  font-weight: 900; letter-spacing: 1px; text-align: center; white-space: nowrap;
}
.fc-stamp b { font-size: clamp(16px, 3.4vw, 28px); line-height: 1.6; }
.fc-stamp span { font-size: 12px; font-weight: 700; letter-spacing: .3px; }
.fc-stamp.bad { border-color: rgba(180, 83, 9, .55); background: rgba(254, 243, 199, .42); color: rgba(146, 64, 14, .9); }
.fc-checked {
  font-size: 11.5px; font-weight: 600; line-height: 1.45; border-radius: 8px; padding: 7px 10px;
  background: #d1fae5; color: var(--green); border: 1px solid rgba(5, 150, 105, .35);
}
.fc-checked.bad { background: var(--amber-bg); color: #92400e; border-color: rgba(180, 83, 9, .35); }

/* choose several rows, then give them all the same PDF */
.fc-bulk {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 10px 0 2px; padding: 10px 12px; border-radius: 10px;
  background: var(--calc-bg); border: 1px solid rgba(8, 100, 222, 0.25);
}
.fc-bulk label { display: flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 600; color: var(--blue-dark); }
.fc-bulk-count { font-size: 12.5px; font-weight: 800; color: var(--blue-dark); }
.fc-bulk .fc-sel { color: var(--text); }
.fc-bulk-page { width: 74px; text-align: center; }
/* Blue at 14%, twice --calc-bg: a picked row paints over its own computed
   cells, and the old tint was so near them that picking a row showed nothing.
   It stays under the 18% the selected value wears, so the two selections in
   the review pane do not read as the same thing. */
table.sheet tbody tr.picked td { background: var(--blue-14) !important; }
table.sheet tbody tr.resumed td { animation: fc-resumed 2.4s ease-out 1; }
@keyframes fc-resumed { 0%, 60% { background: #fef9c3 !important; } 100% { background: transparent; } }
table.sheet td input[type=checkbox], table.sheet th input[type=checkbox] { width: 16px; height: 16px; cursor: pointer; }
.fc-sel.empty { border-color: var(--blue); background: var(--calc-bg); color: var(--blue-dark); font-weight: 700; }
.fc-sel.flash { animation: fc-sel-flash 1.4s ease-out 1; }
@keyframes fc-sel-flash {
  0%, 100% { box-shadow: none; }
  30% { box-shadow: 0 0 0 4px rgba(8, 100, 222, 0.35); }
}

/* review window actions: quick fills on top, the decisions underneath */
.fc-actions { margin-top: 14px; border-top: 1px solid var(--border-light); padding-top: 12px;
  display: flex; flex-direction: column; gap: 10px; }
.fc-actions-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.fc-actions-row.main { justify-content: flex-end; }
.fc-tickcount { margin-left: auto; font-size: 11.5px; font-weight: 700; color: var(--muted); white-space: nowrap; }
.fc-tickcount.done { color: var(--green); }

.fc-btn {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; cursor: pointer;
  padding: 9px 16px; border-radius: 999px; border: 1.5px solid transparent;
  font-family: inherit; font-size: 12.5px; font-weight: 700; line-height: 1;
  background: var(--white); color: var(--text);
  transition: transform .12s ease, box-shadow .12s ease, background .12s ease, border-color .12s ease;
}
.fc-btn:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(6, 43, 85, 0.12); }
.fc-btn:active { transform: translateY(0); box-shadow: none; }
.fc-btn:focus-visible { outline: 3px solid rgba(8, 100, 222, 0.35); outline-offset: 2px; }
.fc-btn-ic { font-size: 13px; line-height: 1; }

.fc-btn.ok { background: #ecfdf5; color: var(--green); border-color: rgba(5, 150, 105, .35); }
.fc-btn.ok:hover { background: #d1fae5; border-color: var(--green); }
.fc-btn.ocr { background: var(--calc-bg); color: var(--blue-dark); border-color: rgba(8, 100, 222, 0.3); }
.fc-btn.ocr:hover { background: var(--blue-18); border-color: var(--blue); }
.fc-btn.ghost { background: transparent; color: var(--muted); border-color: var(--border-light); }
.fc-btn.ghost:hover { background: var(--bg); color: var(--text); border-color: var(--border); }
.fc-btn.save { background: var(--white); color: var(--blue-dark); border-color: var(--blue); }
.fc-btn.save:hover { background: var(--calc-bg); }
.fc-btn.primary {
  background: linear-gradient(135deg, var(--blue-dark), var(--blue)); color: var(--white);
  border-color: transparent; padding: 10px 20px; font-size: 13px;
  box-shadow: 0 3px 10px rgba(8, 100, 222, 0.3);
}
.fc-btn.primary:hover { box-shadow: 0 7px 18px rgba(8, 100, 222, 0.38); }
@media (max-width: 640px) {
  .fc-actions-row.main { justify-content: stretch; }
  .fc-actions-row.main .fc-btn { flex: 1; justify-content: center; }
}

/* ===================== Bookkeeping module =====================
   Scoped under .bk / .bk-* so nothing here can reach the tax declaration
   screens. Additive only — no existing rule is modified. */
/* The heading row carries the currency badge and, at the far end, the one
   control the old sidebar footer held. The button sits BESIDE the h2 rather
   than inside it: inside, its label would be read out as part of the heading. */
.bk-head { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px;
  border-bottom: 2px solid var(--border-light); padding-bottom: 8px; margin-bottom: 14px; }
.bk-head h2 { flex: 1; margin: 0; border-bottom: 0; padding-bottom: 0; }
.bk-refresh { padding: 6px 12px; border: 1px solid transparent; border-radius: 9px;
  background: var(--calc-bg); color: var(--blue-dark); font-family: inherit; font-size: 11.5px;
  font-weight: 700; cursor: pointer; transition: background .18s; }
.bk-refresh:hover { background: var(--blue-18); }

.bk-msg { border-radius: 8px; padding: 8px 12px; font-size: 12.5px; margin: 8px 0; }
.bk-msg.ok { background: #ecfdf5; color: #065f46; border: 1px solid #a7f3d0; }
.bk-msg.err { background: #fef2f2; color: var(--red); border: 1px solid #fecaca; }
/* Not an error: something to settle. Amber is the ledger's "look at this", and
   the suspected double-count is exactly that — nothing has gone wrong, and
   nothing has been changed, but a person has to decide. */
.bk-msg.warn { background: var(--amber-bg); color: var(--amber-ink); border: 1px solid var(--amber-line); }
.bk-h { font-size: 13.5px; color: var(--blue-dark); margin: 18px 0 6px; }
.bk-bar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin: 10px 0; }
.bk-bar label { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.bk-bar input[type=month], .bk-bar input[type=date] { border: 1px solid var(--border); border-radius: 6px;
  padding: 5px 8px; font-family: inherit; font-size: 12.5px; }
.bk-reports { gap: 6px; }
.bk-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin: 12px 0; }
.bk-kpi { background: var(--calc-bg); border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; }
.bk-kpi .k { font-size: 11px; color: var(--muted); font-weight: 600; }
.bk-kpi .v { font-size: 18px; font-weight: 700; color: var(--blue-dark); margin-top: 2px; }
.bk-kpi .s { font-size: 11px; color: var(--muted); margin-top: 2px; }
table.bk-t { width: 100%; border-collapse: collapse; font-size: 12.5px; margin: 6px 0 14px; }
table.bk-t th { background: var(--blue-dark); color: var(--white); font-weight: 700; text-align: left;
  padding: 6px 8px; font-size: 11.5px; }
table.bk-t td { border-bottom: 1px solid var(--border); padding: 5px 8px; vertical-align: top; }
table.bk-t tbody tr:nth-child(even) td { background: var(--bg); }
table.bk-t td.r, table.bk-t th.r { text-align: right; font-variant-numeric: tabular-nums; }
table.bk-t tr.tot td { font-weight: 700; background: var(--calc-bg) !important; border-top: 2px solid var(--blue); }
table.bk-t .s { font-size: 11px; color: var(--muted); }
table.bk-t input, table.bk-t select { border: 1px solid var(--border); border-radius: 5px; padding: 3px 5px;
  font-family: inherit; font-size: 12px; width: 100%; box-sizing: border-box; }
.bk-lines td { padding: 3px 4px; }
.bk-form { background: var(--bg); border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px; margin: 10px 0 16px; }
.bk-ok { color: #047857; font-weight: 700; }
.bk-bad { color: var(--red); font-weight: 700; }
.bk-draft { color: var(--muted); font-weight: 700; }
/* A reversed tax adjustment (§14/§20). It is KEPT — nothing here is ever deleted — so it is
   shown struck through rather than removed, and the last cell keeps its own styling so the
   word "reversed" and the reason for it stay readable. */
.bk-void td { opacity: .62; text-decoration: line-through; }
.bk-void td:last-child { text-decoration: none; opacity: 1; }
.bk-link { color: var(--blue); text-decoration: none; border-bottom: 1px dotted currentColor; }
.bk-link:hover { border-bottom-style: solid; }
.bk-pill { background: var(--calc-bg); border-radius: 99px; padding: 3px 10px; font-size: 11.5px; font-weight: 600; }
.bk-json { background: var(--navy); color: var(--border-light); padding: 12px; border-radius: 8px; font-size: 11.5px; overflow: auto; max-height: 420px; }

/* ---------- dashboard ---------- */
.dash-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-top: 4px; }
.dash-kpi { background: var(--calc-bg); border: 1px solid var(--border-light); border-radius: 10px; padding: 12px 14px; }
.dash-kpi .k { font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.dash-kpi .v { font-size: 20px; font-weight: 700; color: var(--blue-dark); margin-top: 4px; }
.dash-kpi .s { font-size: 11px; color: var(--muted); margin-top: 2px; }
.dash-na { color: var(--muted); font-weight: 400; }
.dash-rows th { text-align: left; font-weight: 600; color: var(--muted); font-size: 12.5px; width: 52%; }
.dash-rows td { font-size: 12.5px; }
.dash-chip { display: inline-block; font-size: 11px; font-weight: 700; padding: 2px 9px; border-radius: 99px; }
.dash-chip.ok { background: #d1fae5; color: var(--green); }
.dash-chip.warn { background: var(--amber-strong); color: var(--amber-ink); }
/* .bad was missing, so every red status rendered as unstyled bold text — the
   one colour that most needed to stand out was the only one that did not. */
.dash-chip.bad { background: #fee2e2; color: var(--red); }
/* a reason, not a zero: an empty card must say why it is empty */
.dash-empty { padding: 14px; border: 1px dashed var(--border); border-radius: 10px;
  color: var(--muted); font-size: 12.5px; background: var(--card); }
@media (max-width: 760px) { .dash-kpi .v { font-size: 17px; } }

/* ---------- document classification ---------- */
.doc-sel { font-family: inherit; font-size: 12px; padding: 4px 6px; border-radius: 6px;
  border: 1px solid var(--border); background: var(--white); max-width: 170px; }
.doc-sel:disabled { opacity: .5; }
.doc-sel.doc-ok { background: #d1fae5; border-color: #a7f3d0; color: var(--green); font-weight: 700; }
.doc-sel.doc-warn { background: #fef3c7; border-color: #fde68a; color: #92400e; font-weight: 700; }
.doc-sel.doc-bad { background: #fee2e2; border-color: #fecaca; color: var(--red); font-weight: 700; }

/* ---------- monthly tax readiness ---------- */
.wf-bar { height: 10px; border-radius: 99px; background: var(--border-light); overflow: hidden; margin: 6px 0 10px; }
.wf-bar-fill { height: 100%; border-radius: 99px; background: linear-gradient(90deg, var(--blue), #22c55e);
  transition: width .5s ease; }
@media (prefers-reduced-motion: reduce) { .wf-bar-fill { transition: none; } }

/* ---------- books day-book rows ---------- */
.bk-row { cursor: pointer; }
.bk-row:hover { background: var(--calc-bg); }
.bk-warn { color: #92400e; font-weight: 700; font-size: 11px; }
.bk-tax { font-size: 11px; color: var(--muted); text-transform: capitalize; }

/* an empty day book should say so, not show a blank strip */
.bk-empty { text-align: center; padding: 22px; color: var(--muted); font-size: 12.5px; }

/* The day books want every pixel of that width. The quick-entry forms do not:
   .grid.c3 is auto-fit minmax(200px, 1fr), so the eight-field purchase form
   measured 3 tracks today, then 4 at 1512px, 6 at 1920px and 9 at 2560px — one
   row of nine fields. 840px is the widest value that still holds three, which
   is the shape the forms were drawn for (3 + 3 + 2) and the one they have now.
   .grid.c2 gets the same cap: its two uses here are prose beside fields, not
   cards, and a 1,000px-wide column of explanation is not an improvement. */
.bk .grid.c2, .bk .grid.c3 { max-width: 840px; }

/* Prose has no business running 2,000px wide. Block-level only — a `.hint`
   span inside a .bk-bar is inline, and a `.hint` td is an empty-state table
   cell; a max-width on either of those would be wrong. */
.bk div.hint, .bk p.hint { max-width: 680px; }

/* An eleven-column day book is wider than the panel below about 1100px, and
   nothing in books.js wraps a table in .tbl-wrap, so it painted out through the
   card's rounded corner and scrolled the whole PAGE sideways: measured 651px of
   content in a 500px window at 390px, and 1107px in 1024px. Scrolling the panel
   keeps it inside the card. The durable fix is a .tbl-wrap around each table,
   the way app.js does it in thirteen places. */
.bk #bkBody { overflow-x: auto; }

/* the transactions with nothing attached: a red edge, because an input-VAT
   claim with no invoice behind it is the first thing an inspection asks for */
.bk-missing { border-left: 3px solid var(--red); }
.bk-misslist { margin: 8px 0 0; padding-left: 18px; font-size: 12.5px; }
.bk-misslist li { margin-bottom: 3px; }
.bk-misslist .s { color: var(--muted); }
/* the row for the month being looked at, in the tax summary */
.bk-t tr.sel td { background: var(--calc-bg) !important; }

/* the bank account whose reconciliation is shown under the table */
.bk-row.sel { background: var(--calc-bg); box-shadow: inset 3px 0 0 var(--blue); }

/* quick-entry card header: title on the left, cancel on the right */
.bk-qhead { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 10px; }

/* ---------- Documents: category pills and the missing rows ---------- */
.doc-cats-h { margin: 14px 0 0; font-size: 12.5px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .04em; }
.doc-cats { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.doc-pill { border: 1px solid var(--border); background: var(--card); border-radius: 999px;
  padding: 5px 12px; font-family: inherit; font-size: 12px; font-weight: 600; color: var(--muted);
  cursor: pointer; transition: background .15s, color .15s, border-color .15s; }
.doc-pill:hover { border-color: var(--blue); color: var(--blue-dark); }
.doc-pill.on { background: var(--blue); border-color: var(--blue); color: var(--white); }
.doc-pill span { opacity: .65; margin-left: 4px; font-variant-numeric: tabular-nums; }
/* a transaction with no paperwork is not a file — it is a thing to chase */
tr.doc-missing td { background: #fff5f5; }

/* ---------- Settings: label/value rows ---------- */
.set-row { display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
  padding: 9px 0; border-bottom: 1px solid var(--border-light); }
.set-row:last-of-type { border-bottom: 0; }
.set-k { color: var(--muted); font-size: 13px; }
.set-note { font-size: 11.5px; color: var(--muted); opacity: .85; margin-top: 2px; max-width: 46ch; }
.set-v { font-weight: 700; color: var(--text); text-align: right; font-size: 13.5px; }

/* ---------- Header logo ---------- */
/* The full lockup, in colour, on the white bar. Colour because the bar is
   white: on the old navy gradient these same inks measured 1.00:1 at the
   worst point — BALANCE in brand blue against a brand blue background, i.e.
   invisible. The full lockup rather than the wordmark because it carries the
   tagline; at 56px that line renders around 9px, which is the floor the asset
   pack's README sets before it says to drop to the wordmark. */
.topbar h1.brand-mark {
  display: flex; align-items: center; gap: 10px;
  min-width: 0;                      /* let the console name ellipsize, not the logo */
}
.brand-logo {
  height: 56px; width: auto; display: block; flex: none;
}
.topbar h1.brand-mark span {
  margin-left: 0;                    /* the flex gap does this now */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* On a phone the console name is the first thing worth dropping: the logo
   already says which product this is, and the nav says which section. */
@media (max-width: 560px) {
  .brand-logo { height: 42px; }
  .topbar h1.brand-mark span { display: none; }
}

/* ---------- App footer ---------- */
/* Sits under the shell on every page, states the running build, and stays out
   of the way: muted, small, and never printed onto a tax document. */
.appfoot {
  padding: 14px 18px 20px;
  text-align: center;
  font-size: 11.5px;
  color: var(--muted);
  min-height: 20px;                 /* hold the space so the page does not jump when it fills */
}
.appfoot .ver { display: inline-flex; flex-wrap: wrap; gap: 6px; justify-content: center; align-items: center; }
.appfoot code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px; color: var(--muted);
  background: var(--border-light); border-radius: 4px; padding: 1px 5px;
}
.appfoot .dev {
  color: var(--red); font-weight: 600;
  background: #fef2f2; border-radius: 4px; padding: 1px 6px;
}
