/*
   Виртуален счетоводител — интерфейс

   Типографията е PT Sans и PT Mono на ParaType — семейство, проектирано за печат
   на кирилски държавни документи. Кодовете на колоните (02-11, 03-41) са писани с
   моноширинния шрифт навсякъде: това е речникът, на който счетоводителите говорят
   с НАП, и в този продукт е първокласен обект, а не украса.

   Цветовете идват от артефактите на предметната област: хартия, черно мастило и
   синьо-виолетовото на печат върху документ.
*/

@font-face {
  font-family: "PT Sans";
  src: url("/static/fonts/PTSans-Regular.ttf") format("truetype");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "PT Sans";
  src: url("/static/fonts/PTSans-Bold.ttf") format("truetype");
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: "PT Mono";
  src: url("/static/fonts/PTMono-Regular.ttf") format("truetype");
  font-weight: 400;
  font-display: swap;
}

:root {
  --paper: #faf9f6;
  --paper-raised: #ffffff;
  --ink: #16181c;
  --ink-soft: #5c6068;
  --ink-faint: #8b9098;
  --stamp: #2b3a8f;
  --stamp-soft: #edeff9;
  --stamp-edge: #c3c9e8;
  --pending: #a8681a;
  --pending-soft: #faf1e2;
  --cleared: #2c6a4e;
  --cleared-soft: #e8f1ec;
  --alarm: #a32c28;
  --alarm-soft: #fbebea;
  --rule: #e2dfd8;
  --rule-strong: #cbc7bd;

  --step-down: 0.8125rem;
  --step-0: 0.9375rem;
  --step-1: 1.125rem;
  --step-2: 1.5rem;
  --step-3: 2.125rem;
  --step-4: 3rem;

  --sans: "PT Sans", system-ui, sans-serif;
  --mono: "PT Mono", ui-monospace, "SF Mono", monospace;
}

*,
*::before,
*::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 var(--step-0)/1.55 var(--sans);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--stamp); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { text-decoration-thickness: 2px; }
:focus-visible { outline: 2px solid var(--stamp); outline-offset: 2px; }

/* ---------------------------------------------------------------- масштаб */

h1, h2, h3 { margin: 0; font-weight: 700; letter-spacing: -0.015em; line-height: 1.15; }
h1 { font-size: var(--step-3); }
h2 { font-size: var(--step-2); }
h3 { font-size: var(--step-1); }
p { margin: 0 0 0.75rem; }

.eyebrow {
  font: 400 var(--step-down)/1 var(--mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.muted { color: var(--ink-soft); }
.faint { color: var(--ink-faint); }
.small { font-size: var(--step-down); }
.mono { font-family: var(--mono); }
.num { font-family: var(--mono); font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }

/* ------------------------------------------------------------------ рамка */

.masthead {
  background: var(--ink);
  color: var(--paper);
  padding: 0.7rem 1.5rem;
  display: flex;
  align-items: baseline;
  gap: 1.25rem;
  flex-wrap: wrap;
}
.masthead a { color: var(--paper); text-decoration: none; }
.masthead .brand { font-weight: 700; letter-spacing: -0.02em; }
.masthead .firm { font-size: var(--step-down); color: #a9adb8; }
.masthead .spacer { flex: 1; }
.masthead .who { font-size: var(--step-down); color: #a9adb8; }

.wrap { max-width: 1180px; margin: 0 auto; padding: 1.75rem 1.5rem 5rem; }
.wrap-wide { max-width: 1440px; }

.crumbs { font-size: var(--step-down); color: var(--ink-faint); margin-bottom: 1rem; }
.crumbs a { color: var(--ink-soft); }

.page-head { display: flex; gap: 1.5rem; align-items: flex-start; flex-wrap: wrap; margin-bottom: 1.5rem; }
.page-head .grow { flex: 1 1 22rem; }

/* --------------------------------------------------------------- дедлайн */

.deadline {
  border: 1px solid var(--rule-strong);
  background: var(--paper-raised);
  padding: 0.6rem 0.9rem;
  min-width: 12rem;
}
.deadline .days { font: 400 var(--step-3)/1 var(--mono); letter-spacing: -0.03em; }
.deadline.urgent { border-color: var(--pending); background: var(--pending-soft); }
.deadline.urgent .days { color: var(--pending); }
.deadline.late { border-color: var(--alarm); background: var(--alarm-soft); }
.deadline.late .days { color: var(--alarm); }
.deadline.settled { border-color: var(--rule-strong); background: var(--paper-raised); }
.deadline.settled .days { color: var(--ink-faint); }
.deadline.settled.done { border-color: var(--cleared); background: var(--cleared-soft); }
.deadline.settled.done .days { color: var(--cleared); }

/* --------------------------------------------------------------- таблици */

table { width: 100%; border-collapse: collapse; }
thead th {
  font: 400 var(--step-down)/1.2 var(--mono);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--stamp);
  background: var(--stamp-soft);
  text-align: left;
  padding: 0.5rem 0.7rem;
  border-bottom: 1px solid var(--stamp-edge);
  white-space: nowrap;
}
thead th.num { text-align: right; }
tbody td { padding: 0.6rem 0.7rem; border-bottom: 1px solid var(--rule); vertical-align: top; }
tbody tr:hover { background: var(--paper-raised); }
tfoot td { padding: 0.6rem 0.7rem; border-top: 2px solid var(--ink); font-weight: 700; }

.table-scroll { overflow-x: auto; border: 1px solid var(--rule); background: var(--paper-raised); }

/* ----------------------------------------------------------------- бадж */

.tag {
  display: inline-block;
  font: 400 var(--step-down)/1.4 var(--mono);
  padding: 0.05rem 0.4rem;
  border: 1px solid currentColor;
  white-space: nowrap;
}
.tag-code { color: var(--stamp); background: var(--stamp-soft); border-color: var(--stamp-edge); }
.tag-pending { color: var(--pending); background: var(--pending-soft); }
.tag-cleared { color: var(--cleared); background: var(--cleared-soft); }
.tag-alarm { color: var(--alarm); background: var(--alarm-soft); }
.tag-quiet { color: var(--ink-soft); background: var(--paper-raised); border-color: var(--rule-strong); }

/* A tag inside a link is a control. Without this it read as decoration that
   happened to sit in a clickable cell. */
a .tag { transition: border-color 140ms ease, filter 140ms ease; }
a:hover .tag, a:focus-visible .tag { border-color: currentColor; filter: brightness(0.94); }

/* --------------------------------------------------- ЛЕНТА НА КОЛОНИТЕ

   Подписът на този интерфейс. Всеки документ се показва като миниатюра на реда,
   който заема в дневника: кои от номерираните колони е попълнил. Съпоставянето
   документ → колона е цялата работа, която този продукт върши вместо човека, и
   тук тя се вижда с един поглед, вместо да се чете.
*/

.tape { display: flex; gap: 2px; align-items: stretch; }
.tape-cell {
  width: 0.42rem;
  min-height: 1.6rem;
  background: var(--rule);
  border-radius: 1px;
}
.tape-cell.filled { background: var(--stamp); }
.tape-cell.filled.negative { background: var(--alarm); }
.tape-legend { font: 400 var(--step-down)/1 var(--mono); color: var(--ink-faint); }

/* ---------------------------------------------------------------- карти */

.card {
  border: 1px solid var(--rule);
  background: var(--paper-raised);
  padding: 1rem 1.1rem;
}
.card + .card { margin-top: 0.9rem; }
.card-head { display: flex; justify-content: space-between; gap: 1rem; align-items: baseline; margin-bottom: 0.6rem; }

.grid { display: grid; gap: 0.9rem; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(21rem, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); }

.split { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 1.25rem; }
@media (max-width: 62rem) { .split { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------- въпроси */

.question {
  border: 1px solid var(--rule-strong);
  border-left: 3px solid var(--pending);
  background: var(--paper-raised);
  padding: 0.9rem 1rem;
}
.question.blocking { border-left-color: var(--alarm); }
.question.info { border-left-color: var(--stamp); }
.question.resolved { border-left-color: var(--cleared); opacity: 0.72; }
.question + .question { margin-top: 0.7rem; }
.question h3 { font-size: var(--step-0); margin-bottom: 0.3rem; }
.question .basis { font: 400 var(--step-down)/1.4 var(--mono); color: var(--stamp); }

/* -------------------------------------------------------------- бутони */

.btn {
  display: inline-block;
  font: 700 var(--step-0)/1.2 var(--sans);
  padding: 0.5rem 0.9rem;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--paper);
  cursor: pointer;
  text-decoration: none;
}
.btn:hover { background: #2c2f36; }
.btn-quiet { background: transparent; color: var(--ink); }
.btn-quiet:hover { background: var(--rule); }
.btn-small { font-size: var(--step-down); padding: 0.3rem 0.6rem; }
.btn-row { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }

/* The two decisions on a document. Accepting is the ordinary move and carries
   the weight; rejecting is outlined until you are on it, because a filled red
   button beside a filled green one turns a routine screen into an alarm. */
.btn-accept { background: var(--cleared); border-color: var(--cleared); color: #fff; }
.btn-accept:hover { background: #24583f; border-color: #24583f; }
.btn-reject { background: transparent; border-color: var(--alarm); color: var(--alarm); }
.btn-reject:hover { background: var(--alarm); color: #fff; }

/* A status standing among the buttons that change it. The plain .tag is set for
   running text — barely half a button tall — so in that row it read as a label
   somebody had dropped there rather than part of the group. */
.btn-row .tag {
  display: inline-flex;
  align-items: center;
  padding: 0.3rem 0.6rem;
  min-height: 1.85rem;
}

input[type="text"], textarea, select {
  font: 400 var(--step-0)/1.4 var(--sans);
  padding: 0.4rem 0.5rem;
  border: 1px solid var(--rule-strong);
  background: var(--paper-raised);
  color: var(--ink);
}

/* ------------------------------------------------------------- документ */

.preview {
  border: 1px solid var(--rule-strong);
  background: var(--paper-raised);
  width: 100%;
  /* Scrolls rather than shrinks. A portrait page in a short, wide box is
     limited by its height, so `contain` drew an A4 invoice at about half the
     column width — small enough that checking a figure against the reading
     meant opening the file. Full width and scroll makes the paper readable
     where it sits. */
  max-height: 84vh;
  overflow: auto;
}
.preview img { display: block; width: 100%; height: auto; }

.fields { width: 100%; }
.fields th { text-align: left; font-weight: 400; color: var(--ink-soft); padding: 0.3rem 0.6rem 0.3rem 0; white-space: nowrap; }
.fields td { padding: 0.3rem 0; border-bottom: 1px solid var(--rule); }

.confidence { display: inline-block; width: 3.2rem; height: 0.4rem; background: var(--rule); vertical-align: middle; }
.confidence span { display: block; height: 100%; background: var(--cleared); }
.confidence.low span { background: var(--pending); }
.confidence.bad span { background: var(--alarm); }

/* ----------------------------------------------------------- деклaрация */

.decl-row { display: grid; grid-template-columns: 4.5rem 1fr 8rem; gap: 0.8rem; align-items: baseline;
            padding: 0.4rem 0; border-bottom: 1px solid var(--rule); }
.decl-row.total { border-top: 2px solid var(--ink); border-bottom: none; font-weight: 700; padding-top: 0.6rem; }
.decl-row .code { font: 400 var(--step-down)/1.6 var(--mono); color: var(--stamp); }
.decl-row details summary { cursor: pointer; }

.record-map { font-family: var(--mono); font-size: var(--step-down); }
.record-map .slot { white-space: pre; }
.record-map .slot:nth-child(odd) { background: var(--stamp-soft); }

@media (prefers-reduced-motion: no-preference) {
  .card, .question { transition: border-color 120ms ease; }
}

/* ---------------------------------------------------------------- печат

   Счетоводителят разпечатва резултата, за да го подпише или подаде на клиента.
   Отделен генератор на отчет би бил втори източник на същите числа; страницата
   просто се държи прилично на хартия.
*/

@media print {
  :root { --paper: #fff; --paper-raised: #fff; }

  .masthead,
  .crumbs,
  .btn,
  .btn-row,
  form { display: none !important; }

  body { font-size: 10pt; }
  .wrap { max-width: none; padding: 0; }

  h1 { font-size: 18pt; }
  h2 { font-size: 13pt; }

  .split { grid-template-columns: 1fr; gap: 0.6rem; }
  .card { border: 1px solid #999; break-inside: avoid; }
  .question { break-inside: avoid; }
  .decl-row { break-inside: avoid; }

  /* Разгъни всички разбивки: на хартия няма кой да ги отвори. */
  details { display: block; }
  details > summary { list-style: none; font-weight: 700; }
  details[open] > *,
  details > * { display: revert; }
  details:not([open]) > *:not(summary) { display: block !important; }

  a { color: inherit; text-decoration: none; }
  a[href]::after { content: ""; }

  thead { display: table-header-group; }
  thead th { background: #eee !important; color: #000 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }

  .tag { border: 1px solid #666 !important; color: #000 !important; background: #fff !important; }
}

/* --------------------------------------------------------- качване на файлове

   The browser's own file control arrives with a grey bevelled button and the
   words "No file chosen" — it sat in a row of styled buttons announcing that
   nobody had looked at this screen. The control keeps its behaviour; only the
   button it draws is restyled. */

input[type="file"] {
  font: inherit;
  font-size: var(--step-down);
  color: var(--ink-soft);
  max-width: 18rem;
}

input[type="file"]::file-selector-button {
  font: inherit;
  font-size: var(--step-down);
  padding: 0.34rem 0.7rem;
  margin-right: 0.6rem;
  color: var(--ink);
  background: var(--paper-raised);
  border: 1px solid var(--rule-strong);
  border-radius: 2px;
  cursor: pointer;
}

input[type="file"]::file-selector-button:hover {
  border-color: var(--stamp);
  color: var(--stamp);
}

/* A client's name is the way into their month, so it has to look like one.
   Bold black text in a table reads as a label, and the row that most needs
   opening — a new client with nothing in it yet — is the one nobody clicks. */
.client-link {
  color: var(--stamp);
  text-decoration: none;
  border-bottom: 1px solid var(--stamp-edge);
}

.client-link:hover {
  border-bottom-color: var(--stamp);
}

/* A button that has to read as a link: it acts on this page rather than going
   anywhere, but the eye looks for a link where an action sits inline in text. */
.linklike {
  font: inherit;
  color: var(--stamp);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
}

dialog::backdrop { background: rgba(20, 23, 30, 0.55); }

/* ------------------------------------------------------------ трите числа

   The month in three figures. Each is the way to what it counts — the documents,
   the questions, the declaration — so each is a link rather than a card with a
   link buried in it, and the whole target is clickable.

   Centred, because the figure is the content and everything else is a caption
   for it. The accent rail appears on hover rather than sitting there: three
   coloured bars competing above a table is noise, one under the cursor is an
   answer. */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: 1rem;
  margin-bottom: 1.5rem;
}

.stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  padding: 1.15rem 1rem 1.05rem;
  text-align: center;
  text-decoration: none;
  color: inherit;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 3px;
  position: relative;
  overflow: hidden;
  transition: border-color 140ms ease, box-shadow 140ms ease, transform 140ms ease;
}

/* The rail grows from the middle out — it belongs to the figure above it. */
.stat::after {
  content: "";
  position: absolute;
  left: 50%;
  right: 50%;
  bottom: 0;
  height: 2px;
  background: var(--stamp);
  transition: left 160ms ease, right 160ms ease;
}

.stat.pending::after { background: var(--pending); }

.stat:hover,
.stat:focus-visible {
  border-color: var(--rule-strong);
  box-shadow: 0 2px 10px rgba(20, 23, 30, 0.07);
  transform: translateY(-1px);
}

.stat:hover::after,
.stat:focus-visible::after { left: 0; right: 0; }

.stat-label {
  font: 400 var(--step-down)/1 var(--mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.stat-figure {
  font: 400 var(--step-3)/1.05 var(--mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.stat.pending .stat-figure { color: var(--pending); }

.stat-note {
  font-size: var(--step-down);
  color: var(--ink-soft);
  max-width: 20rem;
}

.stat:hover .stat-note { color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .stat, .stat::after { transition: none; }
  .stat:hover, .stat:focus-visible { transform: none; }
}

.period-pick select {
  font: inherit;
  font-size: var(--step-down);
  padding: 0.3rem 0.45rem;
  border: 1px solid var(--rule-strong);
  border-radius: 2px;
  background: var(--paper-raised);
  color: var(--ink);
  cursor: pointer;
}

.period-pick select:hover { border-color: var(--stamp); }

/* Signing out sits beside the name it signs out, on every page. Small, because
   it is not what anyone came to do — and unmistakable, because looking for the
   way out and not finding it is its own kind of alarming. */

.signout-form { display: inline-flex; margin-left: 0.75rem; }

.signout {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.55rem;
  height: 1.55rem;
  padding: 0;
  font: 400 0.8rem/1 var(--sans);
  color: rgba(255, 255, 255, 0.55);
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 50%;
  cursor: pointer;
  transition: color 140ms ease, border-color 140ms ease, background 140ms ease;
}

.signout:hover,
.signout:focus-visible {
  color: #fff;
  border-color: rgba(255, 255, 255, 0.6);
  background: rgba(255, 255, 255, 0.1);
}

@media (prefers-reduced-motion: reduce) { .signout { transition: none; } }

/* ------------------------------------------------------------- годината

   A client's months, when the one on screen is empty and the others are not.
   Shown as the thing to act on rather than as a line of links under an
   apology — the documents exist, they are simply somewhere else. */

.months {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: 0.6rem;
  margin-top: 1rem;
}

.month {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.7rem 0.8rem;
  text-decoration: none;
  color: inherit;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 3px;
  transition: border-color 140ms ease, background 140ms ease, transform 140ms ease;
}

.month:hover,
.month:focus-visible {
  border-color: var(--stamp);
  background: var(--paper-raised);
  transform: translateY(-1px);
}

.month-name { font-weight: 700; }
.month-year { font: 400 var(--step-down)/1 var(--mono); color: var(--ink-faint); }
.month-count { font-size: var(--step-down); color: var(--ink-soft); margin-top: 0.2rem; }

@media (prefers-reduced-motion: reduce) {
  .month { transition: none; }
  .month:hover, .month:focus-visible { transform: none; }
}

/* ---------------------------------------------------------------- диалози

   Scrolling the page behind an open dialog moved the thing you were looking at
   out from under the dialog you opened about it. `showModal` does not stop it
   on its own. */

.modal-open, .modal-open body { overflow: hidden; }

dialog::backdrop { background: rgba(17, 19, 24, 0.45); }

dialog { position: relative; }

.dialog-close {
  position: absolute;
  top: 0.45rem;
  right: 0.5rem;
  z-index: 1;
  width: 1.8rem;
  height: 1.8rem;
  display: grid;
  place-items: center;
  font: 400 1rem/1 var(--sans);
  color: var(--ink-soft);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 3px;
  cursor: pointer;
}

.dialog-close:hover,
.dialog-close:focus-visible {
  color: var(--ink);
  background: var(--rule);
  border-color: var(--rule-strong);
}

/* ------------------------------------------------------- какво липсва */

.gap {
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--rule);
}
.gap:last-child { border-bottom: none; }

.gap-head {
  display: flex;
  gap: 0.8rem;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 0.2rem;
}

.letter {
  border: 1px solid var(--rule-strong);
  background: var(--paper-raised);
  padding: 0.9rem 1rem;
}

.letter-line {
  display: flex;
  gap: 0.6rem;
  align-items: baseline;
  font-size: var(--step-down);
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 0.35rem;
}

.letter-body {
  margin: 0.6rem 0 0;
  font: 400 var(--step-down)/1.55 var(--mono);
  white-space: pre-wrap;
  overflow-x: auto;
}

/* ------------------------------------------------ годишно приключване */

.unknowns {
  margin-top: 1rem;
  padding: 0.7rem 0.9rem;
  border-left: 3px solid var(--pending);
  background: var(--pending-soft);
}
.unknowns ul { margin: 0.4rem 0 0; padding-left: 1.1rem; }
.unknowns li { font-size: var(--step-down); color: var(--ink-soft); padding: 0.12rem 0; }

/* The two things a client is, side by side, when it is both. */
.period-kinds { display: flex; gap: 0.4rem; margin-bottom: 1rem; }
.period-kinds a {
  padding: 0.35rem 0.8rem;
  font-size: var(--step-down);
  text-decoration: none;
  color: var(--ink-soft);
  border: 1px solid var(--rule-strong);
  border-radius: 3px;
  background: var(--paper-raised);
}
.period-kinds a.on { background: var(--ink); border-color: var(--ink); color: var(--paper); font-weight: 700; }
.period-kinds a:hover:not(.on) { border-color: var(--stamp); color: var(--ink); }

/* --------------------------------------------------- моите клиенти

   The person signed in has their own clients somewhere in a list of the whole
   practice's. A stripe rather than a colour wash: the row still has to be read
   as a row, and the numbers in it must not change meaning because of who is
   looking. */

tbody tr.mine td:first-child { box-shadow: inset 3px 0 0 var(--stamp); }
tbody tr.mine td { background: var(--stamp-soft); }
