/* ============================================================
   GTBNPS FINANCE — REGISTER
   The spreadsheet, on the web.

   The bursar has been working in this exact grid for a long time, so
   the rules here are conservative on purpose: same headers, same
   column order, same colour key (green = paid in full, yellow =
   part-paid, red = outstanding), same top-right stats box. What is
   new is only what a spreadsheet could not do — a sticky name
   column, a cell that saves itself, and a row that recalculates as
   you leave it.
   ============================================================ */

.reg {
  display: flex; flex-direction: column;
  height: 100%; min-height: 0; background: var(--surface);
}

/* ── Toolbar ──────────────────────────────────────────────── */
.reg__bar {
  flex: none;
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s5);
  border-bottom: 1px solid var(--border);
  background: var(--surface); z-index: 20;
  flex-wrap: wrap;
}
.reg__class {
  height: 36px; min-width: 190px; padding: 0 34px 0 var(--s3);
  font-weight: var(--w-semi); font-size: var(--t-base);
  background-color: var(--surface);
  border: 1px solid var(--border-strong); border-radius: var(--r-sm);
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%231B2D5E' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center;
}
.reg__search {
  height: 36px; width: 210px; padding: 0 var(--s3) 0 32px;
  border: 1px solid var(--border-strong); border-radius: var(--r-sm);
  background: var(--surface-alt) no-repeat left 10px center;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='%238B93AD' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-3.5-3.5'/%3E%3C/svg%3E");
  font-size: var(--t-sm);
}
.reg__search:focus { outline: none; border-color: var(--navy-soft); background-color: var(--surface); }

/* ── Sticky stats box — the workbook's top-right panel ────── */
.reg__stats {
  flex: none;
  display: flex; gap: var(--s2); align-items: stretch;
  padding: var(--s3) var(--s5);
  border-bottom: 1px solid var(--border);
  background: var(--surface-alt);
  overflow-x: auto; scrollbar-width: none;
}
.reg__stats::-webkit-scrollbar { height: 0; }
.stat {
  flex: none; min-width: 112px;
  padding: 9px var(--s3);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-sm);
}
.stat__label {
  font-size: 9.5px; font-weight: var(--w-bold); letter-spacing: .055em;
  text-transform: uppercase; color: var(--text-3); white-space: nowrap;
}
.stat__value {
  font-size: var(--t-md); font-weight: var(--w-black); letter-spacing: -.02em;
  margin-top: 3px; font-variant-numeric: tabular-nums;
}
.stat--hero { background: var(--navy); border-color: var(--navy); }
.stat--hero .stat__label { color: rgba(255,255,255,.55); }
.stat--hero .stat__value { color: #fff; }
.stat__bar { height: 3px; border-radius: var(--r-full); background: var(--bg-sunken); margin-top: 6px; overflow: hidden; }
.stat__bar i { display: block; height: 100%; background: var(--green-mid); border-radius: var(--r-full); }
.stat__bar i.low { background: var(--red-mid); }
.stat__bar i.mid { background: var(--gold); }

/* ══════════════════════════════════════════════════════════
   THE GRID
   ══════════════════════════════════════════════════════════ */
.reg__scroll {
  flex: 1; min-height: 0;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  /* Snapping the scroll to whole cells would fight keyboard
     navigation, so it is deliberately off. */
}

.grid {
  border-collapse: separate; border-spacing: 0;
  font-size: var(--t-sm);
  font-variant-numeric: tabular-nums;
}

.grid th, .grid td {
  border-right: 1px solid var(--border-light);
  border-bottom: 1px solid var(--border-light);
  height: var(--cell-h);
  padding: 0;
}

/* ── Header ───────────────────────────────────────────────── */
.grid thead th {
  position: sticky; top: 0; z-index: 12;
  background: var(--bg-sunken);
  border-bottom: 2px solid var(--border-strong);
  font-size: var(--t-xs); font-weight: var(--w-bold);
  color: var(--navy); text-align: center;
  padding: 0 8px; white-space: nowrap;
  min-width: var(--cell-w); height: 40px;
}
.grid thead th .sub {
  display: block; font-size: 9.5px; font-weight: var(--w-semi);
  color: var(--text-3); letter-spacing: .03em;
}
.grid thead th.optional { color: var(--text-2); }
.grid thead th.optional .sub { color: var(--text-4); }

/* The two frozen columns. The z-index ladder matters: the header
   cells of the frozen columns have to sit above both the sticky
   header row and the sticky body cells, or they disappear under one
   of them while scrolling diagonally. */
.grid th.c-no,   .grid td.c-no   { position: sticky; left: 0; width: var(--col-no-w); min-width: var(--col-no-w); }
.grid th.c-name, .grid td.c-name { position: sticky; left: var(--col-no-w); width: var(--col-name-w); min-width: var(--col-name-w); }
.grid td.c-no, .grid td.c-name { background: var(--surface); z-index: 6; }
.grid thead th.c-no, .grid thead th.c-name { z-index: 14; background: var(--bg-sunken); }
.grid td.c-name { border-right: 1px solid var(--border-strong); }
.grid th.c-name { border-right: 1px solid var(--border-strong); }
.grid tbody tr:hover td.c-no, .grid tbody tr:hover td.c-name { background: #F7F9FD; }

.grid td.c-no {
  text-align: center; color: var(--text-3);
  font-size: var(--t-xs); font-weight: var(--w-semi);
}
.grid td.c-name { padding: 0 10px; }
.c-name__btn {
  display: flex; align-items: center; gap: 7px; width: 100%; height: 100%;
  font-size: var(--t-sm); font-weight: var(--w-semi); color: var(--text);
  text-align: left; overflow: hidden;
}
.c-name__txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.c-name__btn:hover .c-name__txt { color: var(--navy); text-decoration: underline; }
/* A quiet dot marks a child with no parent details yet — the one
   thing that stops a reminder letter being personal. */
.c-name__flag {
  width: 6px; height: 6px; border-radius: 50%; background: var(--amber-border); flex: none;
}

/* ── Editable money cells ─────────────────────────────────── */
.cell {
  display: block; width: 100%; height: 100%;
  padding: 0 9px; text-align: right;
  font-size: var(--t-sm); font-variant-numeric: tabular-nums;
  background: transparent; border: 0; color: var(--text);
  transition: background var(--fast);
}
.cell:hover { background: #F5F8FD; }
.cell:focus {
  outline: none; background: #fff;
  box-shadow: inset 0 0 0 2px var(--navy-soft);
  text-align: right; font-weight: var(--w-semi);
}
.cell[readonly] { cursor: default; }
.cell[readonly]:hover { background: transparent; }
.cell.empty { color: var(--text-4); }
/* Colour key, carried over from the workbook so nothing has to be
   re-learned: green = this fee is settled, amber = part-paid. */
.cell.full  { background: rgba(22,163,74,.075); color: var(--green); font-weight: var(--w-semi); }
.cell.part  { background: rgba(212,160,23,.10); color: #8A6A0C; font-weight: var(--w-medium); }
.cell.saving { background: rgba(37,99,235,.09); }
.cell.saved  { animation: cellSaved 1s ease-out; }
@keyframes cellSaved {
  0%   { background: rgba(22,163,74,.32); }
  100% { background: transparent; }
}
.cell.failed { background: rgba(220,38,38,.12); box-shadow: inset 0 0 0 1.5px var(--red-mid); }
.cell.queued { background: rgba(212,160,23,.13); }

td.has-cell { position: relative; }
/* Corner marker: a queued (offline) cell, and a cell carrying a
   second private figure. Both are deliberately small — the bursar
   needs to notice them, nobody looking over her shoulder does. */
td.q-mark::after, td.t-mark::after {
  content: ''; position: absolute; top: 2px; right: 2px;
  width: 0; height: 0; border-style: solid;
  border-width: 0 6px 6px 0;
}
td.q-mark::after { border-color: transparent var(--gold) transparent transparent; }
td.t-mark::after { border-color: transparent var(--purple) transparent transparent; }

/* Timestamp tooltip — the workbook's cell comment, kept. */
td.has-cell .cell-tip {
  position: absolute; bottom: calc(100% + 5px); right: 0; z-index: 30;
  background: var(--navy-deep); color: #fff;
  font-size: var(--t-xs); font-weight: var(--w-medium);
  padding: 5px 9px; border-radius: var(--r-xs);
  white-space: nowrap; box-shadow: var(--sh-md);
  opacity: 0; visibility: hidden; transform: translateY(3px);
  transition: opacity var(--fast), transform var(--fast), visibility var(--fast);
  pointer-events: none;
}
td.has-cell:hover .cell-tip { opacity: 1; visibility: visible; transform: none; }

/* ── Computed columns ─────────────────────────────────────── */
.grid td.c-calc {
  text-align: right; padding: 0 10px;
  background: var(--surface-alt);
  font-weight: var(--w-semi); color: var(--text-2);
  font-size: var(--t-sm);
}
.grid th.c-calc { background: #E7ECF6; }
.grid td.c-cum  { color: var(--navy); font-weight: var(--w-bold); }
.grid td.c-out.owing { color: var(--red); font-weight: var(--w-bold); }
.grid td.c-out.clear { color: var(--green); font-weight: var(--w-bold); }
.grid td.c-pct { font-weight: var(--w-bold); }
.pctpill {
  display: inline-block; min-width: 46px; padding: 2px 7px;
  border-radius: var(--r-full); font-size: var(--t-xs); font-weight: var(--w-bold);
}
.pctpill.hi  { background: var(--green-bg); color: var(--green); }
.pctpill.mid { background: var(--gold-pale); color: #8A6A0C; }
.pctpill.lo  { background: var(--red-bg);   color: var(--red); }

/* Freeze the three computed columns to the right edge on a wide
   screen. In the workbook these sat off to the right and you scrolled
   to reach them — but "how much does this child still owe" is the
   question the register exists to answer, so it stays on screen while
   the fee columns scroll under it.
   Only above 1100px: below that, five frozen columns would leave
   almost nothing scrolling between them. */
@media (min-width: 1100px) {
  .grid th.c-calc, .grid td.c-calc { position: sticky; z-index: 7; }
  .grid th.c-calc { z-index: 13; }
  .grid .c-cum { right: calc(var(--col-pct-w) + var(--col-out-w)); min-width: var(--col-cum-w); width: var(--col-cum-w); }
  .grid .c-out { right: var(--col-pct-w); min-width: var(--col-out-w); width: var(--col-out-w); }
  .grid .c-pct { right: 0; min-width: var(--col-pct-w); width: var(--col-pct-w); }
  /* A left edge on the first frozen column, so it reads as a pinned
     panel rather than as a cell that happens to overlap. */
  .grid .c-cum {
    border-left: 1px solid var(--border-strong);
    /* A soft shadow so it reads as a pinned panel with the fee
       columns sliding underneath, rather than as overlapping cells. */
    box-shadow: -6px 0 10px -6px rgba(15,30,66,.13);
  }
  .grid tfoot td.c-calc, .grid tfoot td.c-cum,
  .grid tfoot td.c-out, .grid tfoot td.c-pct { z-index: 11; }
}

.grid tbody tr:nth-child(even) td:not(.c-no):not(.c-name) { background: rgba(244,246,251,.5); }
.grid tbody tr:nth-child(even) td.c-calc { background: #F3F5FA; }
.grid tbody tr.active td { background: #EFF4FE !important; }
.grid tbody tr.active td.c-no, .grid tbody tr.active td.c-name { background: #E8F0FE !important; }

/* Totals row, frozen to the bottom of the scroller. */
.grid tfoot td {
  position: sticky; bottom: 0; z-index: 10;
  background: var(--bg-sunken);
  border-top: 2px solid var(--border-strong);
  font-weight: var(--w-bold); color: var(--navy);
  text-align: right; padding: 0 9px; height: 36px;
}
.grid tfoot td.c-no, .grid tfoot td.c-name { z-index: 11; text-align: left; padding-left: 10px; }

/* ── "+" add instalment column ────────────────────────────── */
.addcol {
  width: 26px; height: 26px; border-radius: var(--r-xs);
  display: inline-grid; place-items: center;
  background: var(--surface); border: 1px dashed var(--border-strong);
  color: var(--text-2); margin-left: 6px; vertical-align: middle;
  transition: all var(--fast);
}
.addcol:hover { background: var(--navy); border-color: var(--navy); color: #fff; border-style: solid; }
.addcol svg { width: 13px; height: 13px; stroke-width: 2.6; }

/* ── Floating add-student button ──────────────────────────────
   Hidden by default. Its layout lives entirely inside the mobile
   media query below, so without this it rendered on desktop as an
   unstyled button sitting in the flex column — visible, and sitting
   on top of the grid where it swallowed clicks. */
.reg__fab { display: none; }

.reg__add {
  position: sticky; bottom: var(--s4); margin-left: auto;
  display: inline-flex; align-items: center; gap: 7px;
  height: 40px; padding: 0 var(--s4); border-radius: var(--r-full);
  background: var(--navy); color: #fff;
  font-size: var(--t-sm); font-weight: var(--w-semi);
  box-shadow: var(--sh-md); z-index: 18;
}
.reg__add:hover { background: var(--navy-deep); }
.reg__add svg { width: 16px; height: 16px; stroke-width: 2.4; }

/* ── Keyboard hint strip ──────────────────────────────────── */
.reg__hint {
  flex: none;
  display: flex; align-items: center; gap: var(--s4);
  padding: 7px var(--s5);
  border-top: 1px solid var(--border);
  background: var(--surface-alt);
  font-size: var(--t-xs); color: var(--text-3);
}
kbd {
  display: inline-block; min-width: 18px; padding: 1px 5px;
  background: var(--surface); border: 1px solid var(--border-strong);
  border-bottom-width: 2px; border-radius: 4px;
  font-family: var(--font); font-size: 10.5px; font-weight: var(--w-bold);
  color: var(--text-2); text-align: center;
}

/* ══════════════════════════════════════════════════════════
   MOBILE — cards instead of a grid
   A 20-column spreadsheet on a 390px screen is not a spreadsheet,
   it is a puzzle. On a phone each child becomes a card and the fees
   become rows you tap, with a numeric keypad. Everything the
   desktop grid can do is reachable here, just shaped for a thumb.
   ══════════════════════════════════════════════════════════ */
.reg__cards { display: none; }

@media (max-width: 900px) {
  .reg__scroll { display: none; }
  .reg__hint { display: none; }
  .reg__cards {
    display: block; flex: 1; min-height: 0; overflow-y: auto;
    padding: var(--s3) var(--s3) calc(var(--bottomnav-h) + 90px + env(safe-area-inset-bottom));
    -webkit-overflow-scrolling: touch;
  }
  .reg__bar { padding: var(--s3) var(--s4); gap: var(--s2); }
  /* The class picker is the control that actually gets used on a
     phone, so it takes the width; search shrinks beside it. The
     toolbar's "Add student" button is hidden because the floating
     Add button already does that job — two of them side by side just
     pushed the toolbar onto a second row. */
  .reg__class { flex: 2 1 140px; min-width: 0; }
  .reg__search { flex: 1 1 90px; width: auto; min-width: 0; }
  .reg__bar #addBtn { display: none; }
  .reg__bar #exportBtn { flex: none; }
  .reg__stats { padding: var(--s3) var(--s4); }

  .scard {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--r-md); margin-bottom: var(--s2);
    overflow: hidden;
  }
  .scard__head {
    display: flex; align-items: center; gap: var(--s3);
    padding: var(--s3); width: 100%; text-align: left;
  }
  .scard__no {
    width: 26px; height: 26px; flex: none; border-radius: var(--r-xs);
    background: var(--bg-sunken); color: var(--text-3);
    font-size: var(--t-xs); font-weight: var(--w-bold);
    display: grid; place-items: center;
  }
  /* Every one of these is a <span>. Without display:block they flow
     inline and the name, the parent and the amount run together into
     one wrapped paragraph instead of stacking. */
  .scard__main { flex: 1; min-width: 0; display: block; }
  .scard__name {
    display: block;
    font-size: var(--t-base); font-weight: var(--w-semi);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .scard__meta {
    display: block; font-size: var(--t-xs); color: var(--text-3); margin-top: 1px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .scard__right { text-align: right; flex: none; display: block; }
  .scard__out { display: block; font-size: var(--t-base); font-weight: var(--w-bold); font-variant-numeric: tabular-nums; }
  .scard__out.owing { color: var(--red); }
  .scard__out.clear { color: var(--green); }
  .scard__pct { display: block; font-size: 10.5px; color: var(--text-3); margin-top: 1px; }
  .scard__bar { height: 3px; background: var(--bg-sunken); }
  .scard__bar i { display: block; height: 100%; background: var(--green-mid); }
  .scard__bar i.low { background: var(--red-mid); }
  .scard__bar i.mid { background: var(--gold); }

  .scard__body { display: none; border-top: 1px solid var(--border-light); padding: var(--s2) var(--s3) var(--s3); }
  .scard.open .scard__body { display: block; }

  .frow {
    display: flex; align-items: center; gap: var(--s3);
    padding: 9px 0; border-bottom: 1px solid var(--border-light);
  }
  .frow:last-child { border-bottom: 0; }
  .frow__label { flex: 1; min-width: 0; font-size: var(--t-sm); }
  .frow__label .opt { font-size: 10px; color: var(--text-4); margin-left: 5px; }
  .frow__date { font-size: 10.5px; color: var(--text-4); margin-top: 1px; }
  .frow__input {
    width: 114px; height: 38px; flex: none;
    text-align: right; padding: 0 10px;
    border: 1px solid var(--border-strong); border-radius: var(--r-sm);
    background: var(--surface-alt);
    font-size: var(--t-base); font-variant-numeric: tabular-nums; font-weight: var(--w-semi);
  }
  .frow__input:focus {
    outline: none; background: #fff; border-color: var(--navy-soft);
    box-shadow: 0 0 0 3px rgba(52,71,138,.13);
  }
  .frow__input.full { color: var(--green); background: rgba(22,163,74,.07); }
  .frow__input.part { color: #8A6A0C; background: rgba(212,160,23,.09); }

  .reg__fab {
    position: fixed; right: var(--s4);
    bottom: calc(var(--bottomnav-h) + var(--s4) + env(safe-area-inset-bottom));
    z-index: 42;
    height: 50px; padding: 0 var(--s5); border-radius: var(--r-full);
    background: var(--navy); color: #fff;
    display: inline-flex; align-items: center; gap: var(--s2);
    font-size: var(--t-base); font-weight: var(--w-semi);
    box-shadow: var(--sh-lg);
  }
  .reg__fab svg { width: 19px; height: 19px; stroke-width: 2.4; }
}
