/* Brick Books - design system
   Colours lifted from the blog theme so the two look like siblings. */

:root {
  --ink: #060608;
  --surface: #0e0e13;
  --surface-2: #16161d;
  --surface-3: #1e1e28;
  --line: rgba(255, 255, 255, .10);
  --line-strong: rgba(255, 255, 255, .18);
  --white: #fff;
  --text: #ececf1;
  --muted: #9a9aa7;
  --muted-2: #6f6f7c;

  --c-blue: #2e7de0;
  --c-cyan: #16c6c9;
  --c-green: #74ce3c;
  --c-gold: #ffc61a;
  --c-orange: #ff7a1f;
  --c-red: #ee2b37;
  --c-pink: #ec1e8c;
  /* Violet is not in the rainbow motif - it exists so the fee categories have a
     colour of their own. Gold is reserved for "needs attention" (the CHECK ME
     badge, unverified rates), so no category may use it. */
  --c-violet: #a78bfa;
  --brand-blue: #1f63cf;
  --brand-blue-deep: #0e3a82;

  --rainbow: linear-gradient(90deg, var(--c-blue) 0%, var(--c-cyan) 17%, var(--c-green) 33%,
      var(--c-gold) 50%, var(--c-orange) 67%, var(--c-red) 83%, var(--c-pink) 100%);

  --font-display: "Fraunces", Georgia, "Times New Roman", serif;
  --font-ui: "Space Grotesk", "Segoe UI", system-ui, sans-serif;
  --font-body: "Hanken Grotesk", "Segoe UI", system-ui, sans-serif;

  --radius: 12px;
  --radius-sm: 8px;
  --sidebar: 232px;
  --shadow: 0 8px 30px rgba(0, 0, 0, .45);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--ink);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { font-family: var(--font-display); color: var(--white); margin: 0; font-weight: 600; letter-spacing: -.01em; }
h1 { font-size: 30px; line-height: 1.1; }
h2 { font-size: 21px; }
h3 { font-size: 16px; }
a { color: var(--c-cyan); text-decoration: none; }
a:hover { text-decoration: underline; }
code, .mono { font-family: "Cascadia Mono", Consolas, monospace; font-size: .92em; }

/* ---------- layout ---------- */
#app { display: grid; grid-template-columns: var(--sidebar) 1fr; min-height: 100vh; }

.sidebar {
  background: var(--surface);
  border-right: 1px solid var(--line);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
  /* The column itself never scrolls. Only the list of screens does, and only
     when it has to - see .nav below. Scrolling the whole column meant the logo
     and the footer slid away, and it meant every screen added to the program
     was a layout problem to be solved again with a few pixels of padding. */
  overflow: hidden;
}
/* The logo carries the wordmark, so the sidebar head is just the image.
   It is keyed to transparency, which is why it sits happily on the panel
   colour rather than on a black square of its own. */
/* The sidebar is a flex column. Anything with a fixed height in it needs
   flex-shrink: 0, or a short window squashes it - the rainbow rule was being
   crushed to nothing once the logo made the column overflow. */
.brand { display: block; padding: 18px 22px 14px; flex: 0 0 auto; }
.brand img { display: block; width: 100%; max-width: 172px; height: auto; margin: 0 auto; }
.brand:hover { text-decoration: none; }
.brand:hover img { opacity: .92; }
.rainbow-line { flex: 0 0 3px; height: 3px; background: var(--rainbow); }
.sidebar-foot { flex: 0 0 auto; }

.nav {
  padding: 14px 10px;
  /* Takes the space that is left, and scrolls inside itself if the screens do
     not fit. min-height:0 is what actually allows a flex child to shrink -
     without it the list refuses to get smaller and pushes the footer off. */
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
}
.nav-group-label { font-family: var(--font-ui); font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--muted-2); padding: 14px 10px 6px; }
.nav a {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--font-ui); font-size: 13.5px; font-weight: 500;
  color: var(--muted); padding: 9px 10px; border-radius: var(--radius-sm);
  text-decoration: none; position: relative; border-left: 2px solid transparent;
}
.nav a:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
.nav a.active { background: var(--surface-2); color: var(--white); border-left-color: var(--accent, var(--c-cyan)); }
.nav a .ico { width: 16px; text-align: center; opacity: .85; }
.nav a .badge { margin-left: auto; }

.sidebar-foot { padding: 12px 16px 18px; border-top: 1px solid var(--line); font-family: var(--font-ui); font-size: 11px; color: var(--muted-2); }

.main { min-width: 0; display: flex; flex-direction: column; }
.topbar {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 26px; border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--ink) 82%, transparent);
  backdrop-filter: blur(8px); position: sticky; top: 0; z-index: 20;
}
.topbar .spacer { flex: 1; }
.page { padding: 24px 26px 60px; max-width: 1500px; width: 100%; }
.page-head { margin-bottom: 20px; }
.page-head p.dek { color: var(--muted); margin: 6px 0 0; max-width: 74ch; }

/* ---------- cards ---------- */
.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 18px; position: relative; overflow: hidden;
}
/* The rainbow trim is on every card. It used to appear only on cards marked "accent" (a connection
   that was not set up yet), which looked random. */
.card::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 2px; background: var(--rainbow); }
/* The one box without it: the Dashboard's list of things worth a look. */
.card.no-trim::before { display: none; }
.card h3 { font-family: var(--font-ui); font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); font-weight: 600; margin-bottom: 12px; }
.grid { display: grid; gap: 16px; }
.g2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.g3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.g4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.g-2-1 { grid-template-columns: 2fr 1fr; }
.g-1-2 { grid-template-columns: 1fr 2fr; }
@media (max-width: 1200px) { .g4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } .g-2-1, .g-1-2 { grid-template-columns: 1fr; } }
@media (max-width: 900px) { .g2, .g3 { grid-template-columns: 1fr; } #app { grid-template-columns: 1fr; } .sidebar { position: static; height: auto; } }

/* ---------- the menu on a narrow screen ----------
   Stacked, the sidebar put fifteen navigation items above the content, so a
   phone opened on a wall of links and you had to scroll past the whole menu to
   reach the screen you came for. Here the same list becomes one horizontally
   scrolling strip: the logo stays where it belongs, and the actual program is
   visible without scrolling at all. */
@media (max-width: 900px) {
  /* A grid or flex child will not shrink below its content unless it is told
     it may, and the scrolling strip below is very wide content. Without these
     the whole PAGE grew wider than the phone, which pushed the fixed demo
     banner off the right-hand edge. */
  #app, .sidebar, .nav, .main { min-width: 0; }
  .sidebar { border-right: 0; border-bottom: 1px solid var(--line); }
  .nav {
    display: flex; gap: 4px; padding: 8px 10px;
    /* flex:0 0 auto, or the strip inherits the column's leftover height and
       stretches every item down the screen. */
    flex: 0 0 auto; align-items: center;
    overflow-x: auto; overflow-y: hidden;
    /* Momentum scrolling on iOS, and no scrollbar eating a row of pixels. */
    -webkit-overflow-scrolling: touch; scrollbar-width: none;
  }
  .nav::-webkit-scrollbar { display: none; }
  /* The group headings only make sense in a column. */
  .nav-group-label { display: none; }
  .nav a {
    flex: 0 0 auto; white-space: nowrap;
    border-left: 0; border-bottom: 2px solid transparent;
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  }
  .nav a.active { border-left-color: transparent; border-bottom-color: var(--accent, var(--c-cyan)); }
}

/* ---------- stat tiles ---------- */
.stat { display: flex; flex-direction: column; gap: 4px; }
.stat .label { font-family: var(--font-ui); font-size: 11px; letter-spacing: .09em; text-transform: uppercase; color: var(--muted); }
.stat .value { font-family: var(--font-ui); font-size: 27px; font-weight: 700; color: var(--white); letter-spacing: -.02em; line-height: 1.1; font-variant-numeric: tabular-nums; }
.stat .value.sm { font-size: 21px; }
.stat .sub { font-size: 12.5px; color: var(--muted); }
.pos { color: var(--c-green) !important; }
.neg { color: var(--c-red) !important; }
.warnc { color: var(--c-gold) !important; }

/* ---------- buttons ---------- */
button, .btn {
  font-family: var(--font-ui); font-size: 13px; font-weight: 600;
  border-radius: var(--radius-sm); padding: 9px 15px; cursor: pointer;
  border: 1px solid var(--line-strong); background: var(--surface-2); color: var(--text);
  transition: background .12s, border-color .12s, transform .06s;
}
button:hover, .btn:hover { background: var(--surface-3); border-color: var(--muted-2); text-decoration: none; }
button:active { transform: translateY(1px); }
button:disabled { opacity: .45; cursor: not-allowed; }
.btn-primary { background: var(--c-blue); border-color: var(--c-blue); color: #fff; }
.btn-primary:hover { background: #3d8bea; border-color: #3d8bea; }
.btn-good { background: var(--c-green); border-color: var(--c-green); color: #06210a; }
.btn-danger { background: transparent; border-color: color-mix(in srgb, var(--c-red) 60%, transparent); color: var(--c-red); }
.btn-danger:hover { background: color-mix(in srgb, var(--c-red) 14%, transparent); }
.btn-sm { padding: 5px 10px; font-size: 12px; }
/* A link that is meant to look and act like a button. */
a.btn { display: inline-block; text-decoration: none; }
.btn-ghost { background: transparent; border-color: var(--line); color: var(--muted); }
.btn-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/* ---------- forms ---------- */
label { display: block; font-family: var(--font-ui); font-size: 12px; font-weight: 600; color: var(--muted); margin-bottom: 5px; letter-spacing: .02em; }
input, select, textarea {
  width: 100%; background: var(--ink); border: 1px solid var(--line-strong);
  color: var(--text); font-family: var(--font-ui); font-size: 14px;
  padding: 9px 11px; border-radius: var(--radius-sm); line-height: 1.4;
}
/* An <input type=date>, an <input type=number> and a <select> all work out a
   slightly different intrinsic height from the same padding and font. Left
   alone that puts neighbouring boxes a couple of pixels out of line, which is
   exactly the sort of thing you notice and cannot unsee. Pin them. */
input:not([type="checkbox"]):not([type="radio"]), select { height: 40px; }
textarea { height: auto; min-height: 40px; }
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--c-cyan); box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-cyan) 18%, transparent); }
input[type="checkbox"] { width: auto; accent-color: var(--c-cyan); }
.field { margin-bottom: 14px; }
.field .hint { font-size: 12px; color: var(--muted-2); margin-top: 5px; line-height: 1.45; }
/* A row of fields that must line up.

   Two things break this if you let them:
     1. A hint under one field makes that field taller. With the row aligned to
        the bottom, the field WITH the hint gets pushed up and its input no
        longer sits level with the others. So hints are taken out of the flow
        and the row reserves space for them instead.
     2. A <select> sizes itself to its longest option, so flex:1 with an auto
        basis gives it more room than its neighbours. flex-basis 0 makes every
        column share the width evenly regardless of content. */
.inline { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; }
.inline > * { flex: 1 1 0; min-width: 130px; }
.inline > .narrow { flex: 0 0 130px; min-width: 0; }

.inline .field { margin-bottom: 0; position: relative; min-width: 0; }
.inline .field .hint {
  position: absolute; top: calc(100% + 5px); left: 0; right: 0; margin-top: 0;
}
/* Reserve the space the absolutely-positioned hint would have taken. */
.inline:has(.hint) { margin-bottom: 30px; }
/* The fixed gap above only fits a one-line hint. A longer hint wraps past it and runs
   into the label of the next row. So in a row with hints, and no bare control like a
   Save button, the hints sit in the normal flow and the fields line up along the top:
   a longer hint then pushes the row below down instead of overlapping it, and every
   input still sits level because every field in these rows has a label. */
.inline:has(.hint):not(:has(> .btn-row)) { align-items: flex-start; margin-bottom: 14px; }
.inline:has(.hint):not(:has(> .btn-row)) .field .hint { position: static; margin-top: 5px; }
/* A button straight after a note needs air above it. */
.note + button, .note + .btn-row, .note + .card, .note + .check-row { margin-top: 14px; }
/* A row of fields followed by its buttons, and a note after buttons or a fold-out, were
   stacking with no space between them on several screens. */
.inline + .btn-row { margin-top: 12px; }
.btn-row + .note, .explainer + .note { margin-top: 14px; }
/* Bare controls in a row (a Save button with no label) sit level with the
   inputs, which is what flex-end already gives us. */
.inline > .btn-row { flex: 0 0 auto; }
.check-row { display: flex; align-items: center; gap: 9px; }
.check-row label { margin: 0; }

/* ---------- tables ---------- */
.table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); }
table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
th {
  font-family: var(--font-ui); font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); text-align: left; padding: 11px 12px; background: var(--surface-2);
  border-bottom: 1px solid var(--line); white-space: nowrap; position: sticky; top: 0; z-index: 2;
}
td { padding: 9px 12px; border-bottom: 1px solid var(--line); vertical-align: middle; }
tbody tr:hover { background: var(--surface-2); }
tbody tr:last-child td { border-bottom: none; }
.num { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--font-ui); white-space: nowrap; }
.t-clip { max-width: 340px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- misc ---------- */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--font-ui); font-size: 10.5px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; padding: 3px 7px; border-radius: 5px;
  background: var(--surface-3); color: var(--muted);
}
.badge.warn { background: color-mix(in srgb, var(--c-gold) 18%, transparent); color: var(--c-gold); }
.badge.good { background: color-mix(in srgb, var(--c-green) 16%, transparent); color: var(--c-green); }
.badge.bad { background: color-mix(in srgb, var(--c-red) 16%, transparent); color: var(--c-red); }
.badge.info { background: color-mix(in srgb, var(--c-cyan) 16%, transparent); color: var(--c-cyan); }

.pill { display: inline-block; padding: 2px 8px; border-radius: 20px; font-family: var(--font-ui); font-size: 11px; font-weight: 600; }
.dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }

.note {
  border-left: 3px solid var(--c-cyan); background: var(--surface-2);
  padding: 12px 14px; border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: 13.5px; color: var(--text); line-height: 1.6;
}
.note.warn { border-left-color: var(--c-gold); }
.note.danger { border-left-color: var(--c-red); }
.note.good { border-left-color: var(--c-green); }
.note strong { color: var(--white); }
.note + .note { margin-top: 10px; }

.explain {
  font-size: 13px; color: var(--muted); line-height: 1.6;
  background: var(--surface-2); border: 1px dashed var(--line-strong);
  padding: 11px 13px; border-radius: var(--radius-sm); margin-top: 10px;
}
.explain b { color: var(--text); font-weight: 600; }

details.advanced { margin-top: 18px; }
details.advanced > summary {
  cursor: pointer; font-family: var(--font-ui); font-size: 12px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted); font-weight: 600; padding: 6px 0;
}
details.advanced[open] > summary { margin-bottom: 4px; }
details.explainer { margin-top: 10px; }
details.explainer > summary {
  cursor: pointer; font-family: var(--font-ui); font-size: 12.5px; font-weight: 600;
  color: var(--c-cyan); list-style: none; display: inline-flex; align-items: center; gap: 6px;
}
details.explainer > summary::before { content: "?"; display: inline-flex; align-items: center; justify-content: center; width: 15px; height: 15px; border-radius: 50%; border: 1px solid currentColor; font-size: 10px; font-weight: 700; }
details.explainer[open] > summary { margin-bottom: 8px; }

.empty { text-align: center; padding: 40px 20px; color: var(--muted-2); font-size: 14px; }
.spinner { display: inline-block; width: 15px; height: 15px; border: 2px solid var(--line-strong); border-top-color: var(--c-cyan); border-radius: 50%; animation: spin .7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

.toast-host { position: fixed; right: 20px; bottom: 20px; display: flex; flex-direction: column; gap: 9px; z-index: 200; max-width: 420px; }
.toast {
  background: var(--surface-3); border: 1px solid var(--line-strong); border-left: 3px solid var(--c-cyan);
  padding: 11px 15px; border-radius: var(--radius-sm); font-size: 13.5px;
  box-shadow: var(--shadow); animation: slide .2s ease-out;
}
.toast.bad { border-left-color: var(--c-red); display: flex; align-items: flex-start; gap: 12px; }
.toast .toast-text { flex: 1; min-width: 0; }
.toast .toast-close {
  flex: none; background: transparent; border: 0; color: var(--text-dim, inherit); cursor: pointer;
  font-size: 20px; line-height: 1; padding: 0 2px; margin: -2px -4px 0 0;
}
.toast .toast-close:hover { color: var(--text, inherit); }
.toast.good { border-left-color: var(--c-green); }
@keyframes slide { from { transform: translateX(20px); opacity: 0; } }

.modal-host { position: fixed; inset: 0; background: rgba(0, 0, 0, .72); display: flex; align-items: flex-start; justify-content: center; padding: 5vh 20px; z-index: 150; overflow-y: auto; }
.modal { background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--radius); width: 100%; max-width: 720px; box-shadow: var(--shadow); }
.modal.wide { max-width: 1080px; }
.modal-head { padding: 18px 20px 14px; border-bottom: 1px solid var(--line); display: flex; align-items: center; gap: 12px; }
.modal-body { padding: 20px; }
.modal-foot { padding: 14px 20px; border-top: 1px solid var(--line); display: flex; gap: 9px; justify-content: flex-end; }

.progress { height: 7px; background: var(--surface-3); border-radius: 5px; overflow: hidden; }
.progress > div { height: 100%; border-radius: 5px; transition: width .35s ease; }

.tabs { display: flex; gap: 3px; border-bottom: 1px solid var(--line); margin-bottom: 18px; flex-wrap: wrap; }
.tabs button { background: none; border: none; border-bottom: 2px solid transparent; border-radius: 0; color: var(--muted); padding: 9px 14px; }
.tabs button.active { color: var(--white); border-bottom-color: var(--c-cyan); background: none; }

.dropzone {
  border: 2px dashed var(--line-strong); border-radius: var(--radius); padding: 34px 20px;
  text-align: center; color: var(--muted); transition: all .15s; cursor: pointer;
}
.dropzone.over { border-color: var(--c-green); background: color-mix(in srgb, var(--c-green) 8%, transparent); color: var(--c-green); }

svg.chart { display: block; width: 100%; overflow: visible; }
/* Radial charts must not stretch to the column width or they balloon. */
svg.chart-fixed { width: auto; max-width: 100%; height: auto; flex: 0 0 auto; }
svg text { font-family: var(--font-ui); fill: var(--muted); }
.legend { display: flex; flex-wrap: wrap; gap: 5px 16px; margin-top: 12px; font-family: var(--font-ui); font-size: 12px; }
.legend span { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); }

.kv { display: grid; grid-template-columns: auto 1fr; gap: 6px 18px; font-size: 13.5px; }
.kv dt { color: var(--muted); }
.kv dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; font-family: var(--font-ui); }
.kv dd.total { font-weight: 700; color: var(--white); border-top: 1px solid var(--line); padding-top: 6px; margin-top: 4px; }
.kv dt.total { font-weight: 700; color: var(--white); border-top: 1px solid var(--line); padding-top: 6px; margin-top: 4px; }

.scroll-y { max-height: 420px; overflow-y: auto; }
.hr { height: 1px; background: var(--line); margin: 22px 0; border: 0; }
.muted { color: var(--muted); }
.small { font-size: 12.5px; }
.right { text-align: right; }
.nowrap { white-space: nowrap; }
.mt { margin-top: 16px; }
.mb { margin-bottom: 16px; }


/* ---------- monthly checklist grid ---------- */
table.checklist th:first-child,
table.checklist td.chk-label { text-align: left; min-width: 230px; }
table.checklist th { text-align: center; }
table.checklist td { padding: 5px 6px 8px; text-align: center; }
table.checklist tbody tr:hover { background: var(--surface-2); }

td.chk-cell {
  cursor: pointer; user-select: none; position: relative;
  min-width: 46px; transition: background .1s;
}
td.chk-cell:hover { background: var(--surface-3); }
td.chk-cell.chk-future { opacity: .45; }
td.chk-cell.chk-alert { box-shadow: inset 0 0 0 1px var(--c-gold); border-radius: 4px; }

.chk-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 5px; font-size: 12px; font-weight: 700;
  font-family: var(--font-ui); border: 1px solid transparent;
}
.chk-count {
  display: block; font-family: var(--font-ui); font-size: 9.5px;
  color: var(--muted-2); line-height: 1; margin-top: 4px;
}

/* ---------- detail / summary toggle ---------- */
.level-toggle { display: inline-flex; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); overflow: hidden; }
.level-toggle button {
  border: 0; border-radius: 0; background: transparent; color: var(--muted);
  padding: 5px 12px; font-size: 12px;
}
.level-toggle button.active { background: var(--surface-3); color: var(--white); }

.group-row { border-top: 1px solid var(--line); padding-top: 10px; margin-top: 10px; }
.group-row:first-child { border-top: 0; margin-top: 0; padding-top: 0; }
.group-head { display: flex; align-items: baseline; gap: 10px; font-family: var(--font-ui); }
.group-head .gname { font-weight: 600; color: var(--white); font-size: 13.5px; flex: 1; }
.group-head .gval { font-variant-numeric: tabular-nums; font-weight: 600; }
.group-children { margin: 6px 0 0 14px; font-size: 12.5px; color: var(--muted); }
.group-children div { display: flex; gap: 8px; align-items: baseline; padding: 1.5px 0; }
.group-children .cname { flex: 1; }
.group-children .cval { font-variant-numeric: tabular-nums; font-family: var(--font-ui); }


/* ---------- per-transaction tax hint ---------- */
.tax-hint {
  border-radius: var(--radius-sm); padding: 10px 13px; margin: 10px 0;
  font-family: var(--font-ui); border: 1px solid transparent;
}
.tax-hint.set-aside {
  background: color-mix(in srgb, var(--c-gold) 10%, transparent);
  border-color: color-mix(in srgb, var(--c-gold) 34%, transparent);
}
.tax-hint.saving {
  background: color-mix(in srgb, var(--c-green) 9%, transparent);
  border-color: color-mix(in srgb, var(--c-green) 30%, transparent);
}
.tax-hint.muted {
  background: var(--surface-2); border-color: var(--line);
  color: var(--muted); font-size: 12.5px;
}
.tax-hint .th-main { font-size: 15px; color: var(--text); }
.tax-hint.set-aside .th-main strong { color: var(--c-gold); font-size: 19px; font-variant-numeric: tabular-nums; }
.tax-hint.saving .th-main strong { color: var(--c-green); font-size: 19px; font-variant-numeric: tabular-nums; }
.tax-hint .th-keep { color: var(--muted); font-size: 12.5px; }
.tax-hint .th-parts {
  display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 5px;
  font-size: 11.5px; color: var(--muted);
}
.tax-hint .th-parts .th-why {
  margin-left: auto; opacity: .75; border-bottom: 1px dotted var(--muted-2); cursor: help;
}
.tax-hint.stock {
  background: color-mix(in srgb, var(--c-blue) 9%, transparent);
  border-color: color-mix(in srgb, var(--c-blue) 30%, transparent);
}
.tax-hint.stock .th-main strong { color: var(--c-blue); }

/* ---------- illustrated empty states ---------- */
.empty-illustrated {
  display: flex; align-items: center; gap: 26px; justify-content: center;
  padding: 26px 20px; flex-wrap: wrap; text-align: left;
}
.empty-illustrated .empty-words { max-width: 46ch; }
/* Without a picture the flex row has one child, so it centres a narrow column
   in a wide card. Left aligned and full width reads as a normal empty state
   rather than something whose image failed to load. */
.empty-illustrated.no-art { justify-content: flex-start; padding: 22px 20px; }
.empty-illustrated.no-art .empty-words { max-width: 62ch; }
.empty-illustrated .empty-words h3 {
  font-family: var(--font-display); font-size: 19px; color: var(--white);
  text-transform: none; letter-spacing: -.01em; margin: 0 0 8px;
}
.empty-illustrated .empty-words p { color: var(--muted); font-size: 14px; margin: 0 0 8px; line-height: 1.6; }
.empty-illustrated .empty-words p:last-child { margin-bottom: 0; }
@media (max-width: 700px) {
  .empty-illustrated { flex-direction: column; text-align: center; }
  .empty-illustrated .empty-words { text-align: center; }
}

/* ---- Check my books ---- */
.check-items { margin: 10px 0 4px; display: flex; flex-direction: column; gap: 9px; }
.check-item {
  border-left: 2px solid var(--line); padding: 2px 0 2px 10px;
}
.check-item-head {
  display: flex; justify-content: space-between; gap: 10px; align-items: baseline;
}
.check-item-label { font-size: 13px; color: var(--white); }

/* ---- Scrollbars ----
   The default Windows scrollbar is a wide light-grey slab that cuts straight
   through a dark layout. These are thin, dark, and only really visible while
   there is something to scroll. Applies to the sidebar, tables, modals and
   the page itself. */
* { scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; }

*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--line-strong);
  border-radius: 8px;
  border: 3px solid transparent;   /* inset, so the bar reads as narrow */
  background-clip: content-box;
}
*::-webkit-scrollbar-thumb:hover { background: var(--muted-2); background-clip: content-box; }
*::-webkit-scrollbar-corner { background: transparent; }

/* Reclaim enough height that the sidebar stops scrolling at all on a normal
   screen - a scrollbar you never see beats a tidy one you do.
   Trimmed further in the 'Sidebar density' block near the end of this file,
   which is the one that wins - keep changes there rather than here. */
.nav { padding: 8px 10px; }
.nav-group-label { padding: 10px 10px 4px; }
.nav a { padding: 7.5px 10px; }

/* ---- attached documents ---- */
.attach-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.doc-link {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; color: var(--c-cyan); text-decoration: none;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 7px 11px; max-width: 100%; overflow-wrap: anywhere;
}
.doc-link:hover { background: var(--surface-2); text-decoration: none; }

/* ---- sortable table headers ---- */
th.sortable { cursor: pointer; user-select: none; white-space: nowrap; }
th.sortable:hover { color: var(--white); background: var(--surface-2); }
th.sortable.sorted { color: var(--white); }
.sort-arrow {
  display: inline-block; width: 10px; margin-left: 5px;
  color: var(--c-cyan); font-size: 11px;
}

/* ---- attachment marker in the list ---- */
.clip {
  margin-left: 8px; text-decoration: none; font-size: 12px;
  opacity: .55; cursor: pointer;
}
.clip:hover { opacity: 1; text-decoration: none; }

/* ---- Sidebar density ----
   The nav is 14 items across three groups. These trims keep the whole column
   inside a short window without a scrollbar, which is where most laptop
   screens land once browser chrome is taken off. In the demo the banner at
   the top takes a further slice, which is the tightest case there is.
   Override the earlier rules. */
.brand { padding: 10px 22px 8px; }
.brand img { max-width: 132px; }
.nav { padding: 6px 10px; }
.nav-group-label { padding: 7px 10px 2px; }
.nav a { padding: 5px 10px; font-size: 13px; }
.sidebar-foot { padding: 9px 16px 12px; }

/* ---- clickable findings on Check my books ---- */
.check-item-link { cursor: pointer; border-radius: var(--radius-sm); transition: background .12s; }
.check-item-link:hover { background: var(--surface-2); border-left-color: var(--c-cyan); }
.check-item-open { color: var(--c-cyan); opacity: 0; transition: opacity .12s; margin-top: 3px; }
.check-item-link:hover .check-item-open { opacity: 1; }

/* ---- editable category list ---- */
.category-row {
  cursor: pointer; border-radius: var(--radius-sm);
  padding: 1px 6px; margin-left: -6px; transition: background .12s;
}
.category-row:hover { background: var(--surface-2); color: var(--text); }

/* ---- dashboard items that take you somewhere ---- */
.note-link { cursor: pointer; transition: background .12s; }
.note-link:hover { background: var(--surface-2); }
.note-link-arrow { opacity: .5; }
.note-link:hover .note-link-arrow { opacity: 1; }

/* ---- clickable "things worth a look" ---- */
.note-link { cursor: pointer; transition: background .12s, border-color .12s; }
.note-link:hover { background: var(--surface-2); }
.note-link-arrow { color: var(--c-cyan); white-space: nowrap; font-weight: 600; }

/* ---- demo mode ---- */
.demo-banner {
  position: fixed; top: 0; left: 0; right: 0; z-index: 400;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 9px 14px;
  background: linear-gradient(90deg, #2a1e00, #3a2a00);
  border-bottom: 1px solid var(--c-gold);
  color: #ffe9a8; font-family: var(--font-ui); font-size: 12.5px;
}
.demo-chip {
  background: var(--c-gold); color: #1a1200;
  font-weight: 800; letter-spacing: .12em; font-size: 10.5px;
  padding: 4px 10px; border-radius: 4px; flex: 0 0 auto;
  border: 0; cursor: pointer; font-family: var(--font-ui);
}
.demo-chip:hover { filter: brightness(1.1); }
.demo-words { flex: 1 1 240px; min-width: 0; }
.demo-reset { flex: 0 0 auto; }
.demo-hide {
  flex: 0 0 auto; background: none; border: 0; cursor: pointer;
  color: #ffe9a8; opacity: .6; font-size: 18px; line-height: 1;
  padding: 0 4px;
}
.demo-hide:hover { opacity: 1; }

/* Folded away: only the explanation goes. The chip stays, because nobody should
   be able to forget these are invented figures - and Reset stays, because it is
   the one control the person showing the demo actually needs. One line on a
   phone instead of three. */
.demo-banner.is-collapsed { padding: 5px 14px; gap: 10px; }
.demo-banner.is-collapsed .demo-words,
.demo-banner.is-collapsed .demo-hide { display: none; }
.demo-banner.is-collapsed .demo-reset {
  margin-left: auto; padding: 3px 9px; font-size: 11px;
}

/* Push the whole app down so the banner never covers the logo or the topbar.
   The height is measured in JS because the text wraps on a narrow window. */
body.is-demo #app { padding-top: var(--demo-banner-h, 40px); }
body.is-demo .sidebar {
  height: calc(100vh - var(--demo-banner-h, 40px));
  top: var(--demo-banner-h, 40px);
}
/* Stacked on a narrow screen the sidebar is a strip across the top, not a
   column beside the content, so pinning it to the viewport height left a
   screen-high hole between the menu and the program. This rule has to sit
   AFTER the one above rather than up with the other mobile styles, because
   that one carries no media query and would otherwise win. */
@media (max-width: 900px) {
  body.is-demo .sidebar { height: auto; top: auto; }
}


/* 'new' beside Licence & help when a version is waiting. Sits on the right of
   the sidebar entry, like the attention count on the dashboard, so it reads as
   part of the furniture rather than an alert. */
.nav a .update-dot {
  margin-left: auto; font-size: 10px; letter-spacing: .04em;
  text-transform: uppercase;
}

/* The website demo only. Sits under the navigation, in the space the real
   program leaves empty, and is styled to read as an aside rather than another
   menu item: a customer must never find an advert in their own sidebar, and
   this whole block is skipped when BRICKBOOKS_STATIC is undefined. */
.demo-aside {
  margin: 22px 14px 8px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: rgba(255, 255, 255, .02);
}
.demo-aside p {
  margin: 0 0 6px;
  font-size: 12px;
  color: var(--muted-2);
}
.demo-aside a {
  font-size: 13px;
  font-weight: 600;
  color: var(--c-cyan);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.demo-aside a:hover { color: var(--text); }

/* A card that folds away once it has been filled in. The header keeps the key
   figure visible, and the Edit / Close word is drawn here so the markup stays plain. */
details.fold > summary {
  cursor: pointer; list-style: none; display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
details.fold > summary::-webkit-details-marker { display: none; }
details.fold .fold-title {
  font-family: var(--font-ui); font-size: 12px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted); font-weight: 600;
}
details.fold .fold-value { color: var(--text); font-size: 14px; }
details.fold .fold-action {
  margin-left: auto; font-family: var(--font-ui); font-size: 12.5px; font-weight: 600; color: var(--c-cyan);
}
details.fold .fold-action::before { content: "Edit"; }
details.fold[open] .fold-action::before { content: "Close"; }
details.fold[open] > summary { margin-bottom: 14px; }

/* The small "i" in the corner of a box, and the explanation it opens. */
.card.has-info { padding-bottom: 40px; }
button.info-i {
  position: absolute; right: 12px; bottom: 10px; width: 20px; height: 20px; min-height: 0;
  padding: 0; margin: 0; border-radius: 50%; background: transparent;
  border: 1px solid var(--line-strong); color: var(--muted); box-shadow: none;
  font: italic 700 12px/1 Georgia, "Times New Roman", serif;
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
}
button.info-i:hover, button.info-i:focus-visible, button.info-i[aria-expanded="true"] {
  color: var(--c-cyan); border-color: var(--c-cyan); background: transparent;
}
.info-pop {
  position: fixed; z-index: 400; width: min(330px, calc(100vw - 16px));
  background: var(--surface-3); border: 1px solid var(--line-strong); border-radius: 10px;
  padding: 12px 14px; box-shadow: 0 10px 30px rgba(0, 0, 0, .55);
  font-size: 12.5px; line-height: 1.5; color: var(--text); text-transform: none; letter-spacing: 0;
}
.info-pop p { margin: 0 0 8px; }
.info-pop p:last-child { margin-bottom: 0; }

/* Spacing found by the screen-by-screen audit. */
/* Buttons side by side in a table cell (Edit and Delete, Save and Remove) touched. */
td button + button, td button + a, td a + button, td button + select, td select + button { margin-left: 6px; }
/* In a row of fields a field may shrink, but not until its text is cut off: below this it
   wraps onto the next line instead. Seen at half-screen width on Money in & out. */
.inline .field { min-width: 120px; }
.inline > .narrow .field { min-width: 0; }
/* A dropdown inside a table cell was squeezed to a sliver. Let the table scroll instead. */
.table-wrap select, .scroll-y select { width: auto; min-width: 150px; max-width: 460px; }

/* Two rows of fields one after the other (the trip form) had no space between them. */
.inline + .inline { margin-top: 12px; }

/* Type-ahead beside a category drop-down (categoryFinder in core.js) */
.cat-finder { display: flex; gap: 10px; align-items: flex-start; flex-wrap: wrap; }
.cat-finder > select { flex: 1 1 260px; min-width: 0; }
.cat-finder-find { position: relative; flex: 0 1 200px; min-width: 150px; }
.cat-finder-find input { width: 100%; font-family: var(--font-mono, monospace); }
.cat-finder-list {
  position: absolute; left: 0; top: calc(100% + 4px); z-index: 20; margin: 0; padding: 4px;
  list-style: none; min-width: 400px; max-width: 480px;
  background: var(--surface-2); border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm); box-shadow: var(--shadow);
}
.cat-finder-list[hidden] { display: none; }
.cat-finder-list li { display: flex; gap: 10px; align-items: baseline; padding: 7px 9px;
  border-radius: 6px; cursor: pointer; font-size: 13px; }
.cat-finder-list li.on, .cat-finder-list li:hover { background: var(--surface-3); }
.cat-finder-list .cat-code { flex: 0 0 140px; font-family: var(--font-mono, monospace);
  color: var(--c-cyan); font-size: 12px; }

/* An "i" beside a figure rather than in a box's corner. */
button.info-i.info-i-inline {
  position: static; margin-left: 6px; vertical-align: middle; width: 18px; height: 18px;
  font-size: 11px; flex: none;
}
.donut-wrap { position: relative; display: inline-block; line-height: 0; }
.donut-wrap button.info-i-inline {
  position: absolute; left: 50%; top: 50%; margin: 0; transform: translate(-50%, 28px);
}

/* Step-by-step connection guides (Settings & data, API keys) */
.guide-i {
  display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px;
  border: 1px solid var(--line-strong); border-radius: 50%; color: var(--muted);
  font: italic 700 11px/1 Georgia, "Times New Roman", serif;
}
button.guide-toggle {
  display: inline-flex; align-items: center; gap: 8px; min-height: 0; padding: 4px 0;
  margin: 0 0 10px; background: transparent; border: 0; box-shadow: none; color: var(--muted);
  font-size: 13px; cursor: pointer;
}
button.guide-toggle:hover, button.guide-toggle[aria-expanded="true"] { color: var(--c-cyan); }
button.guide-toggle:hover .guide-i, button.guide-toggle[aria-expanded="true"] .guide-i {
  color: var(--c-cyan); border-color: var(--c-cyan);
}
.guide-panel {
  font-size: 13px; line-height: 1.6; color: var(--text); background: var(--surface-2);
  border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 12px 16px;
  margin-bottom: 12px;
}
.guide-panel[hidden] { display: none; }
.guide-panel h4 { margin: 14px 0 6px; font-size: 13px; }
.guide-panel h4:first-child { margin-top: 0; }
.guide-panel p { margin: 0 0 8px; }
.guide-panel ol, .guide-panel ul { margin: 0 0 8px; padding-left: 22px; }
.guide-panel li { margin-bottom: 5px; }
.guide-panel .guide-note {
  border-left: 3px solid var(--c-gold); padding: 6px 10px; background: rgba(255, 198, 26, .07);
  border-radius: 0 6px 6px 0;
}

/* A document beside its form. Stacks when the window is narrow, instead of squeezing both. */
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
@media (max-width: 900px) { .two-col { grid-template-columns: 1fr; } }

/* The licence panel at the bottom of the sidebar, shown until a licence is active. */
.licence-panel { display: flex; flex-direction: column; gap: 7px; align-items: flex-start;
  margin-bottom: 12px; padding: 10px 12px; border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm); background: var(--surface-2); }
.licence-panel-line { font-weight: 600; color: var(--text); font-size: 12px; }
a.licence-panel-key { font-size: 11px; color: var(--c-cyan); }

/* The update offer's "What's New" and "Loose Bricks Tightened" blocks. */
.update-news { margin: 14px 0; padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface-2, transparent); }
.update-news h3 { margin: 0 0 8px; font-size: 15px; }
.update-news ul { margin: 0; padding-left: 20px; }
.update-news li + li { margin-top: 4px; }
.update-news p { margin: 0 0 6px; }
.update-news p:last-child { margin-bottom: 0; }

/* Splitting a purchase across categories (views/splitpurchase.js). */
.split-table { width: 100%; }
.split-table td { padding: 6px 8px; vertical-align: middle; }
.split-table input.num { width: 110px; text-align: right; }
.split-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin: 10px 0; }
.split-remaining { font-size: 14px; }
.good-text { color: var(--c-green); }
.bad-text { color: var(--c-red); }
