/* Modal windows: one dialog host in the layout, content fetched per popup. */
dialog.modal {
  border: 0;
  padding: 0;
  background: transparent;
  max-width: none;
  width: 100%;
  height: 100%;
  max-height: none;
  display: none;
  place-items: center;
  overflow: auto;
}

dialog.modal[open] {
  display: grid;
}

dialog.modal::backdrop {
  background: rgba(10,12,18,.45);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.modal-box {
  width: min(800px,calc(100% - 32px));
  background: var(--card);
  color: var(--text);
  border-radius: 24px;
  padding: 24px;
  box-shadow: var(--shadow);
  margin: 24px 0;
}

/* Opening: the box fades in and rises a few pixels, the backdrop fades in.
   Short and soft, so it reads as a light appearance rather than a pop. */
@keyframes modal-in {
  from {
    opacity: 0;
    transform: translateY(8px) scale(.985);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes backdrop-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

dialog.modal[open] .modal-box {
  animation: modal-in .22s cubic-bezier(.2,.7,.2,1) both;
}

dialog.modal[open]::backdrop {
  animation: backdrop-in .22s ease-out both;
}

/* The universal rule in base.css cannot reach ::backdrop, so it is named here. */
@media (prefers-reduced-motion: reduce) {
  dialog.modal[open]::backdrop {
    animation: none;
  }
}

/* A fragment whose first element carries data-box="wide" gets the wider box,
   e.g. the invoice with four footer buttons. app.js copies the value here. */
.modal-box.wide {
  width: min(960px,calc(100% - 32px));
}

/* The search palette: a slim box, aligned near the top like a command bar. */
.modal-box.palette {
  width: min(720px,calc(100% - 32px));
  padding: 8px;
  border-radius: 22px;
  align-self: start;
  margin-top: 12vh;
}

/* Every popup has the same skeleton: a header bar with the title and the X,
   the content, and a footer bar holding the buttons. Both bars bleed to the
   box edge through negative margins, so fragments need no extra wrapper. */
.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: -24px -24px 20px;
  padding: 24px;
  border-bottom: 1px solid var(--line);
}

.modal-title {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -.02em;
  margin: 0;
  line-height: 1;
}

.modal-close {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--ink-text);
  display: grid;
  place-items: center;
  flex: none;
  padding: 0;
}

.modal-close svg {
  display: block;
}

.modal-text {
  margin: 0;
  font-size: 14px;
  line-height: 1.5;
}

/* A titled section in a popup: the same breathing room above each one, and
   a fixed gap between the small caps label and its content. */
.msec {
  margin-top: 20px;
}

.msec > .slabel {
  display: block;
  margin-bottom: 8px;
}

/* A section shown as a card, like the date cards above it. Inside it the
   hover rows and inputs go white so they still stand out. */
.msec.boxed {
  padding: 12px 14px 14px;
  border-radius: 14px;
  background: var(--card2);
}

.msec.boxed .check-item:hover {
  background: var(--card);
}


.modal-foot {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 8px;
  margin: 20px -24px -24px;
  padding: 20px 24px;
  border-top: 1px solid var(--line);
  background: var(--card2);
  border-radius: 0 0 24px 24px;
}

.modal-error {
  margin: 0 0 12px;
  padding: 10px 12px;
  border-radius: 12px;
  background: var(--red-bg);
  color: var(--red-ink);
  font-size: 12px;
}

.modal .form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

/* Three info cards at the top of a task. */
.mcards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
  margin-top: 0;
}

.mcard {
  background: var(--card2);
  border-radius: 14px;
  padding: 10px 12px;
}

.mcard .label {
  font-size: 11px;
  color: var(--muted);
  font-weight: 500;
  margin-bottom: 4px;
}

.mcard .value {
  font-size: 14px;
  font-weight: 600;
}

.mcard.red {
  background: var(--red-bg);
}

.mcard.red .label,
.mcard.red .value {
  color: var(--red-ink);
}

.mcard.green {
  background: var(--green-bg);
}

.mcard.green .label,
.mcard.green .value {
  color: var(--green-ink);
}

/* Attached files. */
.file-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 6px;
}

.file {
  display: grid;
  grid-template-columns: 44px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 12px;
  background: var(--card2);
}

.file:hover {
  background: var(--hover);
}

.file .ext {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--muted);
}

.file .fname {
  font-size: 12px;
  font-weight: 500;
}

.file .fsize {
  font-size: 12px;
  color: var(--muted);
}

/* Five-way status switch: the chosen one is an ink pill with a ringed dot. */
.status-switch {
  display: grid;
  grid-template-columns: repeat(5,minmax(0,1fr));
  gap: 6px;
  margin-top: 24px;
}

.status-switch button {
  height: 36px;
  border-radius: 999px;
  background: var(--card2);
  color: var(--text);
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

/* The mark takes the column's colour, the same as everywhere else. */
.status-switch button .statemark {
  color: var(--c,var(--muted));
}

.status-switch button.on {
  background: var(--ink);
  color: var(--ink-text);
}

/* On the chosen pill the ink ground swallows the grey mark of "Идеи", so that
   one is lifted to the pill's own text colour. The rest keep their hue, which
   reads fine on ink; "Готови" especially, since its mark is a filled disc with
   a white tick and would lose the tick if it turned white too. */
.status-switch button.on[data-status="idea"] .statemark {
  color: var(--ink-text);
}

/* Type select with the "Важна" flag chip beside it, in the task form. */
.type-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.type-row select {
  flex: 1;
  min-width: 0;
}

.type-row .bug-chip {
  flex: none;
  height: 44px;
  cursor: pointer;
}

.type-row .bug-chip svg {
  color: var(--red);
}

/* "Таксува се отделно" row with the amount beside it. */
/* Tall enough for the amount field from the start, so showing it does not
   change the row's height. */
.bill-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 58px;
  padding: 10px 12px;
  border-radius: 14px;
  background: var(--card2);
  margin-bottom: 14px;
}

.bill-check {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  cursor: pointer;
  color: var(--text);
}

.bill-check b {
  display: block;
  font-size: 14px;
  font-weight: 600;
}

.bill-check small {
  display: block;
  font-size: 11px;
  color: var(--muted);
}

/* Amount field: a white input group with the currency as a prepended
   segment inside the same border. */
.amount-wrap {
  display: flex;
  align-items: stretch;
  height: 36px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--card);
  overflow: hidden;
}

/* The box around the currency mark and the amount is the field here, so it
   takes the outline the input inside it would otherwise draw. */
.amount-wrap:focus-within {
  outline: 1.5px solid var(--text);
  outline-offset: 0;
}

.amount-wrap .cur {
  display: grid;
  place-items: center;
  padding: 0 10px;
  background: var(--card2);
  color: var(--muted);
  border-right: 1px solid var(--line);
  font-size: 12px;
}

.amount-wrap input {
  width: 96px;
  height: auto;
  padding: 0 10px;
  border: 0;
  border-radius: 0;
  background: transparent;
}

/* Attach files: a dashed zone (as in the prototype) that is both a click
   target for the file picker and a drop target for files dragged onto it. */
/* The file drop zone: one tall dashed panel with the cloud in the middle.
   --attach-bg is the ground the cut-out arrow in the icon is painted with, so
   the zone keeps the same background in every state and only its edge and its
   ink react. */
.attach {
  --attach-bg: var(--card2);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 26px 16px;
  border-radius: 16px;
  border: 1px dashed var(--line);
  background: var(--attach-bg);
  color: var(--muted);
  text-align: center;
  cursor: pointer;
  margin: 14px 0 ;
  transition: border-color .15s, color .15s;
}

.attach:hover {
  border-color: var(--muted);
}

/* A file is over the zone, or the hidden input has keyboard focus. */
.attach.over,
.attach:focus-within {
  border-color: var(--blue);
  color: var(--text);
}

.attach.over .attach-ico,
.attach:focus-within .attach-ico {
  color: var(--blue);
}

.attach-ico {
  display: block;
  margin-bottom: 6px;
  color: var(--text);
  transition: color .15s;
}

.attach-ico svg {
  display: block;
}

.attach-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}

.attach-hint {
  font-size: 12px;
}

/* The names of the chosen files, if any; empty it takes no room at all. */
.attach-names {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
  font-weight: 500;
  color: var(--text);
}

.attach-names:not(:empty) {
  margin-top: 8px;
}

@media (max-width:640px) {
  .modal .form-row,
  .mcards {
    grid-template-columns: 1fr 1fr;
  }
  .status-switch {
    grid-template-columns: repeat(3,minmax(0,1fr));
  }
  .modal-box {
    padding: 18px;
  }
  .modal-head {
    margin: -18px -18px 16px;
    padding: 14px 18px;
  }
  .modal-foot {
    margin: 16px -18px -18px;
    padding: 12px 18px;
  }
}

/* Client card: four stats, a small list, a two-column info grid and key/values. */
.mcards.four {
  grid-template-columns: repeat(4,minmax(0,1fr));
}

.mlist {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 6px;
}

.mrow {
  display: grid;
  grid-template-columns: 24px minmax(0,1fr) auto auto 80px;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 12px;
  background: var(--card2);
}

.mrow .mname {
  font-size: 12px;
  font-weight: 600;
}

.mgrid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 16px;
}

.mgrid .label {
  font-size: 11px;
  color: var(--muted);
  font-weight: 500;
}

.mgrid .value {
  font-size: 14px;
  font-weight: 500;
}

.mkv {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 6px;
  font-size: 12px;
}

.modal-head .sub {
  font-size: 12px;
  color: var(--muted);
}

@media (max-width:640px) {
  .mcards.four {
    grid-template-columns: 1fr 1fr;
  }
  .mgrid {
    grid-template-columns: 1fr;
  }
}

/* ------------------------------------------------ invoice / receipt modal */
/* The payment is shown as the document itself: a white sheet with fixed ink
   colours, so it reads the same in the dark theme. */
.paper {
  background: #fff;
  color: #111114;
  border-radius: 16px;
  padding: 20px;
  font-size: 12px;
  box-shadow: 0 0 0 1px rgba(17,17,20,.1);
}

/* The receipt is a real document a client is given, so its own text has to
   clear AA too: the issuer's VAT number and IBAN and the "Получател /
   Проект / Начин на плащане" labels were 4.17:1 and 3.54:1 on the sheet. */
.paper-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 14px;
  border-bottom: 1px solid rgba(17,17,20,.1);
}

.paper-issuer {
  font-weight: 600;
  font-size: 14px;
  letter-spacing: -.02em;
}

.paper-doc {
  text-align: right;
}

.paper-docno {
  font-weight: 600;
  font-size: 12px;
}

.paper-dim {
  color: rgba(17,17,20,.66); /* 6.09:1 on the sheet, was 4.17:1 */
  font-size: 12px;
  line-height: 1.5;
}

.paper-late {
  color: #c4102f;
  font-size: 12px;
}

.paper-pill {
  display: inline-block;
  margin-top: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.paper-pill.red {
  background: #ffe9ed;
  color: #c4102f;
}

.paper-pill.orange {
  background: #fff1e6;
  color: #9a4a08; /* 5.65:1, was 4.21:1 at 11px */
}

.paper-pill.green {
  background: #e9f8f1;
  color: #00803a;
}

.paper-meta {
  display: flex;
  gap: 24px;
  flex-wrap: wrap;
  padding: 14px 0;
  border-bottom: 1px solid rgba(17,17,20,.1);
}

.paper-label {
  color: rgba(17,17,20,.66); /* 6.09:1 on the sheet, was 3.54:1 */
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .06em;
}

.paper-strong {
  font-weight: 600;
  font-size: 14px;
}

.paper-mid {
  font-weight: 500;
  font-size: 14px;
}

.paper-line {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 0;
  border-bottom: 1px solid rgba(17,17,20,.1);
}

.paper-amt {
  font-weight: 500;
  white-space: nowrap;
}

.paper-total {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding-top: 12px;
  align-items: baseline;
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -.02em;
}

.btn:disabled {
  opacity: .45;
  cursor: not-allowed;
  box-shadow: none;
}

/* The most-pressed confirming button in the app ("Да", "Да, платено е") had
   the worst text contrast in it: white on --green is 2.79:1 light, 2.11:1
   dark, at 12px bold caps. --green-fill / --on-fill is 5.06:1 and 8.94:1. */
.btn.green {
  background: var(--green-fill);
  color: var(--on-fill);
  border-color: transparent;
}

/* Footer with two groups: document actions on the left, close and the main
   action on the right. When there is no room the right group drops to its
   own line, still right-aligned. */
.modal-foot.spread {
  display: flex;
  justify-content: space-between;
  gap: 8px 16px;
  flex-wrap: wrap;
  align-items: center;
}

.modal-foot.spread .foot-group {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}

.modal-foot.spread .foot-group.end {
  margin-left: auto;
  justify-content: flex-end;
}

.modal-foot.spread form {
  display: contents;
}


/* ------------------------------------------------------------ shared bits */
.modal-title .count {
  font-size: 14px;
  color: var(--muted);
  font-weight: 400;
  margin-left: 4px;
}

.modal-hint {
  margin: 12px 0 0;
  font-size: 12px;
  color: var(--muted);
}

.modal .gap-8 {
  gap: 8px;
}

.modal .mb-4 {
  margin-bottom: 4px;
}

/* Radio pills: one row of equal options, the chosen one in ink. */
.pill-group {
  display: grid;
  gap: 6px;
}

.pill-group.two {
  grid-template-columns: 1fr 1fr;
}

.pill-group.three {
  grid-template-columns: 1fr 1fr 1fr;
}

.pill-opt {
  position: relative;
  display: inline-grid;
  place-items: center;
  height: 40px;
  padding: 0 6px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--text);
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  margin: 0;
}

/* Hidden from the eye, not from the keyboard: display:none took the radio out
   of the Tab order and out of the accessibility tree, so "Вид", "Към",
   "Статус" and "Тип" could not be changed without a mouse. The control stays
   in the label's top-left corner at 1px, and base.css rings the pill around
   it when it takes focus. */
.pill-opt input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  pointer-events: none;
}

.pill-opt.on {
  background: var(--ink);
  color: var(--ink-text);
  border-color: var(--ink);
}

/* The amount field stretched to its column. */
.amount-wrap.full {
  width: 100%;
  height: 44px;
  border-radius: 8px;
}

.amount-wrap.full input {
  flex: 1;
  width: auto;
  min-width: 0;
}

/* Сума · Дата · Метод in one row. */
.modal .form-row.amount-date-method {
  grid-template-columns: 130px 1fr 1fr;
}

/* Payment form: the line under the project select with value / paid / left,
   and the button that fills the whole remainder into the amount. */
.pay-info {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: -6px 0 14px;
  padding: 10px 12px;
  border-radius: 12px;
  background: var(--card2);
  font-size: 12px;
  color: var(--muted);
}

.pay-info b {
  color: var(--text);
  font-weight: 600;
}

/* ------------------------------------------------------------ project form */
.pform {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 22px;
}

.pform-side {
  background: var(--card2);
  border-radius: 18px;
  padding: 16px;
}

/* Inputs inside the tinted panel sit on white, so they stay visible. */
.pform-side input:where(:not([type=checkbox]):not([type=radio])),
.pform-side select,
.pform-side .amount-wrap {
  background-color: var(--card);
}

.pform-side .pill-opt {
  background: var(--card);
}

.pform-side .pill-opt.on {
  background: var(--ink);
}

.logo-row {
  display: flex;
  gap: 14px;
  align-items: center;
  margin-bottom: 14px;
}

/* The colour field takes all the room beside the logo, so the swatches can
   spread out in rows instead of stacking in a column as wide as the label. */
.logo-row > .field {
  flex: 1;
  min-width: 0;
}

.logo-pick {
  position: relative;
  width: 80px;
  height: 80px;
  border-radius: 30%;
  background: var(--c,var(--orange));
  color: #fff;
  display: grid;
  place-items: center;
  font-weight: 500;
  font-size: 30px;
  line-height: 1;
  letter-spacing: -.02em;
  flex: none;
  cursor: pointer;
  overflow: hidden;
  margin: 0;
}

.logo-pick input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  pointer-events: none;
}

.logo-pick img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
  display: block;
}

/* Same computed ink as the small project badge (see the note in rows.css):
   30px white on the yellow or mint swatch is 1.70:1 / 1.85:1. This repeats
   the declaration because modal.css loads after rows.css and the plain
   .logo-pick rule above would otherwise win. */
@supports (color: rgb(from white calc(pow(r / 255, 2.2) * 255) g b)) {
  .logo-pick {
    --code-ink: rgb(from var(--c,var(--orange))
      calc((pow(r / 255,2.2) * .2126 + pow(g / 255,2.2) * .7152 + pow(b / 255,2.2) * .0722 - .179) * -100000)
      calc((pow(r / 255,2.2) * .2126 + pow(g / 255,2.2) * .7152 + pow(b / 255,2.2) * .0722 - .179) * -100000)
      calc((pow(r / 255,2.2) * .2126 + pow(g / 255,2.2) * .7152 + pow(b / 255,2.2) * .0722 - .179) * -100000));
    color: color-mix(in srgb,var(--code-ink) 90%,var(--c,var(--orange)));
  }
}

/* The X at the badge's top-right corner clears the logo. */
.logo-wrap {
  position: relative;
  flex: none;
}

/* 22px badge, 26px target (WCAG 2.5.8 asks 24). It has to be ::before, the
   way .check does it in base.css: these controls carry data-tip, and the
   tooltip capsule is drawn in ::after. Claiming ::after here overwrote the
   capsule's content and its placement, so the tooltip surfaced as a black
   disc over the button instead of a labelled capsule under it. */
.logo-x::before,
.swatch::before,
.check-del::before {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: inherit;
}

.logo-x {
  position: absolute;
  top: -6px;
  right: -6px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--ink-text);
  border: 2px solid var(--card);
  display: grid;
  place-items: center;
  padding: 0;
}

/* The generic button:hover ring in base.css would draw a second circle just
   outside the 2px --card edge. The badge is already a solid disc, so it says
   "delete" the way .check-del does: it turns red instead of gaining a ring. */
.logo-x:hover {
  box-shadow: none;
  background: var(--red);
  color: var(--ink-text);
}

.swatches {
  display: grid;
  grid-template-columns: repeat(auto-fill,20px);
  gap: 8px 10px;
}

.swatch {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--c);
  outline: 2px solid transparent;
  outline-offset: 2px;
  cursor: pointer;
  margin: 0;
  position: relative;
}

.swatch input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  pointer-events: none;
}

.swatch:has(input:checked) {
  outline-color: var(--text);
}

/* Tabbing into the colours lands on the picked swatch, whose ring is already
   drawn: the focus shows as that ring in the text colour. */
.swatch:has(input:focus-visible) {
  outline-color: var(--text);
}

.swatch.custom {
  background: conic-gradient(#ff3b5c,#f5b000,#00b341,#00b4f0,#7b1fe8,#ff3b5c);
}

.swatch.custom input[type=color] {
  display: block;
  position: absolute;
  inset: 0;
  opacity: 0;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  cursor: pointer;
}

/* Project information: the client as one tinted row that opens the card.
   The margin gives air between the client row, the fact cards and the
   description; the six cards sit in two rows of three whatever the base
   .mcards grid does. */
.info-client {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 16px;
  background: var(--card2);
  color: var(--text);
  cursor: pointer;
  margin-bottom: 14px;
}

.mcards.info-cards {
  grid-template-columns: repeat(3,minmax(0,1fr));
  margin-bottom: 4px;
}

.info-client .glyph {
  flex: none;
}

.info-client .min0 {
  flex: 1;
}

.info-client-name {
  display: block;
  font-size: 14px;
  font-weight: 600;
}

.info-client-sub {
  display: block;
  font-size: 12px;
  color: var(--muted);
}

/* ----------------------------------------------------- cards, blocks, lines */
.mcard .value.big {
  font-size: 18px;
}

.mcard .hint {
  font-size: 11px;
  color: var(--muted);
  margin-top: 2px;
}

.mblock {
  margin-top: 16px;
}

.mblock .slabel {
  display: block;
  margin-bottom: 6px;
}

.mtext {
  font-size: 14px;
  line-height: 1.5;
}

/* A compact line: date, what, state, amount. Opens the document it names. */
.mline {
  display: grid;
  grid-template-columns: 52px minmax(0,1fr) auto auto;
  gap: 12px;
  align-items: center;
  padding: 9px 12px;
  border-radius: 12px;
  background: var(--card2);
  font-size: 12px;
  color: var(--text);
  cursor: pointer;
}

.mline .num {
  min-width: 64px;
}

.tag.outline {
  background: var(--card);
  border: 1px solid var(--line);
  color: var(--text);
}

/* --------------------------------------------------------- project payments */
.prog {
  margin: 4px 0 14px;
}

.prog-head {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  margin-bottom: 6px;
}

.prog-bar {
  height: 10px;
  border-radius: 999px;
  background: var(--card2);
  overflow: hidden;
}

.prog-bar i {
  display: block;
  width: var(--w,0%);
  height: 100%;
  background: var(--green);
}

.add-pay {
  border-top: 1px solid var(--line);
  padding-top: 14px;
  margin-top: 14px;
}

.add-pay .slabel {
  display: block;
  margin-bottom: 10px;
}

.pay-grid {
  display: grid;
  grid-template-columns: 110px 1fr 150px 1fr;
  gap: 8px;
}

/* ------------------------------------------------------------------ notes */
.note-add {
  display: flex;
  gap: 8px;
  align-items: flex-end;
  margin-bottom: 14px;
}

.note-add textarea {
  flex: 1;
  border-radius: 16px;
}

.note-add .btn {
  height: 44px;
  flex: none;
}

/* The code gate in front of the notes: the same panel whether it asks for a
   new code or for the one already set. */
.vault-gate {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 10px;
  padding: 26px 18px;
  border-radius: 16px;
  background: var(--card2);
}

.vault-ico {
  display: block;
  color: var(--muted);
}

.vault-text {
  margin: 0;
  font-size: 14px;
  font-weight: 500;
}

.vault-warn {
  margin: 0;
  font-size: 12px;
  color: var(--red-ink);
}

.vault-hint {
  margin: 0;
  font-size: 12px;
  color: var(--muted);
}

.vault-form {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 2px;
}

/* Four digits, so the field is only as wide as they are and the characters
   sit apart far enough to be counted at a glance. */
.vault-code {
  width: 92px;
  text-align: center;
  font-size: 20px;
  font-weight: 600;
  letter-spacing: .3em;
  text-indent: .3em;
}

.note-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.note-item {
  background: var(--card2);
  border-radius: 16px;
  padding: 12px 14px;
  display: flex;
  gap: 12px;
  align-items: flex-start;
}

.note-body {
  flex: 1;
  min-width: 0;
  font-size: 14px;
  line-height: 1.45;
}

.note-side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
  flex: none;
}

.note-x {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--text);
  display: grid;
  place-items: center;
  padding: 0;
}

/* --------------------------------------------------------- project chips */
.chip-pick {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  min-height: 36px;
}

.pick-chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 12px 6px 8px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--text);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  margin: 0;
}

.pick-chip input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  pointer-events: none;
}

.pick-chip .code {
  width: 20px;
  height: 20px;
  border-radius: 30%;
  font-size: 9px;
}

.pick-chip.on {
  background: var(--card2);
  border-color: var(--ink);
}

/* ----------------------------------------------------------------- search */
.search-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
  color: var(--muted);
}

.search-head .search-input {
  flex: 1;
  min-width: 0;
  height: auto;
  border: 0;
  border-radius: 0;
  background: transparent;
  padding: 0;
  font-size: 16px;
  color: var(--text);
}

/* The palette focuses this field the moment it opens and there is nothing
   else in the box to move to, so a focus mark here says nothing. */
.search-head .search-input:focus {
  outline: none;
}

.kbd {
  font-size: 11px;
  font-family: inherit;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 2px 6px;
  flex: none;
  cursor: pointer;
}

.search-results {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 8px 4px 8px;
}

.search-group {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* The heading of a group of results: the section's own mark, and in ink
   rather than grey, so it reads as a title and not as a caption. */
.search-group .slabel {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px 10px 4px;
  color: var(--text);
}

.search-group .slabel svg {
  flex: none;
}

.search-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 10px;
  border-radius: 12px;
  color: var(--text);
  cursor: pointer;
}

.search-item:hover {
  background: var(--hover);
}

.search-title {
  display: block;
  font-size: 14px;
  font-weight: 500;
}

.search-sub {
  display: block;
  font-size: 12px;
  color: var(--muted);
}

.search-empty {
  padding: 10px 12px 6px;
  font-size: 12px;
  margin: 0;
}

@media (max-width:640px) {
  .pform {
    grid-template-columns: 1fr;
  }
  .modal .form-row.amount-date-method,
  .pay-grid {
    grid-template-columns: 1fr 1fr;
  }
  .modal-box.palette {
    margin-top: 16px;
  }
  /* A popup is about 343px wide on a phone: three fact cards in a row leave
     around 100px each, and the five fixed cells of a subscription line do not
     fit at all, so it becomes a wrapping row instead of a grid. */
  .mcards.info-cards {
    grid-template-columns: repeat(2,minmax(0,1fr));
  }
  .mrow {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
  }
}

@media (max-width:420px) {
  .mcards,
  .mcards.four,
  .mcards.info-cards {
    grid-template-columns: 1fr;
  }
}

/* ------------------------------------------------------------ confirm dialog */
/* The small popup for secondary confirmations (task done, payment received,
   deletions). Sits centred above everything, including an open modal. */
dialog.confirm {
  border: 0;
  padding: 0;
  background: transparent;
  max-width: none;
  width: 100%;
  height: 100%;
  max-height: none;
  display: none;
}

dialog.confirm[open] {
  display: grid;
  place-items: center;
}

dialog.confirm::backdrop {
  background: rgba(10,12,18,.35);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}

.confirm-box {
  width: min(400px,calc(100% - 32px));
  margin: 0;
  padding: 22px 22px 18px;
  border-radius: 20px;
  background: var(--card);
  color: var(--text);
  box-shadow: var(--shadow);
}

/* The subject of the question: an icon tile, the title, and the details
   (client · project · amount) underneath, so it is clear what is confirmed. */
.confirm-subject {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 12px;
  margin: 0 0 14px;
  padding: 4px 0 14px;
  border-bottom: 1px solid var(--line);
}

.confirm-ico {
  width: 56px;
  height: 56px;
  border-radius: 18px;
  background: var(--card2);
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}

/* Title with an optional tag beside it, e.g. the month of a subscription charge. */
.confirm-title-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
}

.confirm-tags {
  display: inline-flex;
  gap: 6px;
}

.confirm-tags:empty {
  display: none;
}

/* The plan's rhythm: outlined, muted, clearly not the month tag. */
.confirm-period {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px dashed var(--line);
  color: var(--muted);
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
}

.confirm-amount {
  display: block;
  margin-top: 8px;
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -.02em;
}

.confirm-title {
  display: block;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.3;
}

.confirm-meta {
  display: block;
  margin-top: 3px;
  font-size: 12px;
  color: var(--muted);
}

.confirm-q {
  margin: 0 0 16px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.4;
  text-align: center;
}

dialog.confirm.green .confirm-q {
  color: var(--green-ink);
}

dialog.confirm.red .confirm-q {
  color: var(--red-ink);
}

/* An optional pick above the buttons, e.g. the payment method. */
.confirm-choice {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin: -4px 0 16px;
}

.confirm-choice-label {
  font-size: 12px;
  color: var(--muted);
}

/* An optional date under the pick, e.g. when the money actually arrived. */
.confirm-date {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  margin: -4px 0 16px;
}

.confirm-date input {
  width: auto;
  min-width: 160px;
}

.confirm-actions {
  display: flex;
  justify-content: center;
  gap: 8px;
}

/* ------------------------------------------------------------- checklist */
/* Rows as in KanbanFlow: tick, text, and a ⋮ menu that appears on hover.
   Text is edited in place, so the editing state must look like the text. */
.checklist {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* Items align to the top, so on a wrapped item the tick sits beside the
   first line; the 2px nudge centres the 16px box on that 19.6px line. */
.check-item {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 0 -8px;
  padding: 4px 8px;
  border-radius: 8px;
}

.check-item > input[type=checkbox] {
  margin-top: 2px;
}

/* The × is centred on the whole row, however many lines the text takes. */
.check-item > .check-del,
.check-item > .check-delete-form {
  align-self: center;
  margin: -4px 0;
}

.check-delete-form {
  display: contents;
}

.check-item:hover {
  background: var(--card);
}

.check-item input[type=checkbox],
.checklist input[type=checkbox] {
  flex: none;
}

.check-text {
  flex: 1;
  min-width: 0;
  font-size: 14px;
  line-height: 1.4;
  padding: 2px 4px;
  margin: -2px -4px;
  border-radius: 6px;
  overflow-wrap: anywhere;
  cursor: text;
}

.check-text[contenteditable="true"] {
  background: transparent;
}

.check-item.done .check-text {
  color: var(--muted);
}

.check-item.done .check-text[contenteditable="true"] {
  text-decoration: none;
  color: var(--text);
}

/* 19px glyph, 25px target through the shared ::before above (::after carries the data-tip capsule). */
.check-del {
  position: relative;
  width: 19px;
  height: 19px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--ink);
  color: var(--ink-text);
  opacity: 0;
  transition: opacity .12s;
  flex: none;
  padding: 0;
}

.check-item:hover .check-del,
.check-del:focus-visible {
  opacity: 1;
}

.check-del:hover {
  box-shadow: none;
  background: var(--red);
  color: var(--ink-text);
}

/* The standing "add" line: plain grey text until typed in; as soon as there
   is text, an empty tick box appears in front, so the line looks like the item
   it is about to become. No background of its own. */
.check-add {
  position: relative;
  min-height: 24px;
  margin: 2px -8px 0;
  padding: 4px 8px 4px 34px;
  border-radius: 8px;
  font-size: 14px;
  line-height: 1.4;
  cursor: text;
}

/* The placeholder stays until something is typed. */
.check-add:empty::before {
  content: attr(data-placeholder);
  color: var(--muted);
  pointer-events: none;
}

/* The tick box is always drawn, so the line reads as the item it is about to
   become before anything is typed. At rest it sits at half opacity: present
   enough to say "this is a checklist line", quiet enough not to compete with
   the real items above it. */
.check-add::after {
  content: "";
  position: absolute;
  left: 8px;
  top: 50%;
  width: 16px;
  height: 16px;
  margin-top: -8px;
  border-radius: 4px;
  border: 1.5px solid var(--muted);
  background: var(--card);
  opacity: .5;
  transition: opacity .12s;
}

/* Clicked into, or already carrying text: the same full-strength box the line
   showed before, unchanged. */
.check-add:focus::after,
.check-add:not(:empty)::after {
  opacity: 1;
}

/* ----------------------------------------------------------- image previews */
.thumbs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 10px;
}

.thumb {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  color: var(--muted);
  font-size: 11px;
}

.thumb img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 12px;
  background: var(--card2);
  border: 1px solid var(--line);
}

.thumb:hover img {
  border-color: var(--hover-ring);
}

.thumb-name {
  display: block;
}

.thumbs + .file-list {
  margin-top: 10px;
}

/* Delete control: the logo picker's × pinned to the thumbnail's corner, and
   a small × at the end of a file row. */
.thumb-wrap {
  position: relative;
  min-width: 0;
}

/* This one sits on the card, not on an ink tile, so the glyph cannot keep
   --ink-text: that is white in the light theme (white on white) and near-black
   in the dark one (near-black on the dark card). A control drawn on --card
   takes --text, as every other one on that surface does. */
.file-row .check-del {
  background: var(--card);
  color: var(--text);
  box-shadow: 0 1px 4px rgba(0,0,0,.18);
}

.file-row:hover .check-del {
  opacity: 1;
}

.file-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.file-row .file {
  flex: 1;
  min-width: 0;
}

/* Full-size picture over everything, dark backdrop, click anywhere to close. */
dialog.lightbox {
  border: 0;
  padding: 0;
  background: transparent;
  max-width: none;
  max-height: none;
  width: 100%;
  height: 100%;
  display: none;
}

dialog.lightbox[open] {
  display: grid;
  place-items: center;
}

dialog.lightbox::backdrop {
  background: rgba(10, 12, 18, .82);
}

dialog.lightbox img {
  max-width: min(92vw, 1400px);
  max-height: 90vh;
  border-radius: 12px;
  box-shadow: var(--shadow);
}

.lightbox-close {
  position: fixed;
  top: 18px;
  right: 18px;
}

/* ------------------------------------------------- checklist in the form */
/* The form reuses the preview's rows; its text is an input dressed as text. */
.check-item input.check-text {
  height: auto;
  width: auto;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 14px;
  line-height: 1.4;
  padding: 2px 4px;
  margin: -2px -4px;
  border-radius: 6px;
}

.check-item input.check-text:focus {
  background: transparent;
}

.check-item.done input.check-text {
  color: var(--muted);
}
