/* ===========================================================================
   Design system.
   Operate mode (impeccable docs/craft/impeccable/reference/operate.md).

   Use scene, which is what picks light over dark: one accountant, indoors,
   a full working day, dense tabular data. Light is primary; a dark preference
   is honoured, not offered as a theme toggle nobody asked for.

   Hand-written rather than a framework - no build step, and the craft floor
   requires theming the browser's own surfaces from the palette, which a
   utility framework does not do for you.
   =========================================================================== */

:root {
  /* -- Neutrals. Slightly cool, so secondary text tints from that hue
        rather than going gray (craft floor: never gray on a tinted surface). */
  --bg: #ffffff;
  --surface: #f6f7f9;        /* second neutral layer: sidebar, toolbar, thead */
  --surface-2: #eceef1;
  --border: #d9dde2;
  --border-strong: #b7bec6;

  --text: #14181c;           /* 17:1 on --bg */
  --text-2: #5a646e;         /* 5.6:1 - safe for body and placeholders */
  --text-3: #6b747d;         /* 4.6:1 - the floor, nothing lighter for text */

  /* -- Accent. Primary actions, current selection and state only.
        Never decoration (operate.md). */
  --accent: #0b57a4;
  --accent-hover: #09488a;
  --accent-weak: #e8f0fa;
  --accent-border: #b6d0ec;
  --on-accent: #ffffff;

  --danger: #a32218;
  --danger-weak: #fdeceb;
  --danger-border: #f2c4c0;

  /* -- Status. A total partition (SPEC.md §4), so every plot gets exactly one.
        Always rendered with its label - colour never carries meaning alone. */
  --st-not-for-sale-bg: #eceef0;  --st-not-for-sale-fg: #49545f;  --st-not-for-sale-bd: #d2d7dc;
  --st-available-bg:    #e3f4e8;  --st-available-fg:    #1b6a32;  --st-available-bd:    #b6e1c1;
  --st-held-bg:         #fdf0d8;  --st-held-fg:         #7a4d06;  --st-held-bd:         #f2d8a2;
  --st-booked-bg:       #e2eefb;  --st-booked-fg:       #194e8e;  --st-booked-bd:       #bad5f1;
  --st-partially-bg:    #ddf0f4;  --st-partially-fg:    #0d5663;  --st-partially-bd:   #aadbe4;
  --st-fully-bg:        #d7efe9;  --st-fully-fg:        #0e5c51;  --st-fully-bd:        #a7dbd0;
  --st-registered-bg:   #ece3f7;  --st-registered-fg:   #502590;  --st-registered-bd:   #d1bdee;

  /* -- Type. One family. Fixed rem scale, never fluid: a clamp-sized heading
        that shrinks inside a sidebar looks worse, not better (operate.md).
        Ratio ~1.14. */
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
          Arial, "Noto Sans", sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --fs-micro: 0.75rem;    /* 12 - table meta, captions */
  --fs-dense: 0.8125rem;  /* 13 - table body, the workhorse */
  --fs-body:  0.875rem;   /* 14 - forms, prose */
  --fs-md:    1rem;       /* 16 */
  --fs-lg:    1.125rem;   /* 18 */
  --fs-xl:    1.3125rem;  /* 21 */
  --fs-2xl:   1.5rem;     /* 24 */

  --lh-tight: 1.25;
  --lh-body: 1.55;

  /* -- Spacing, 4px base. */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 32px; --s7: 48px;

  --radius: 5px;
  --radius-sm: 3px;

  /* -- Depth. Offset plus soft blur; a zero-offset halo is decoration. */
  --shadow-1: 0 1px 2px rgba(20, 24, 28, 0.07), 0 1px 1px rgba(20, 24, 28, 0.04);
  --shadow-2: 0 2px 8px rgba(20, 24, 28, 0.09), 0 1px 2px rgba(20, 24, 28, 0.06);

  /* -- Motion. 150-250ms. State only: change, feedback, loading, reveal.
        No page-load choreography - the accountant is loading into a task. */
  --t: 160ms ease-out;

  --nav-w: 208px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #15181c;
    --surface: #1c2024;
    --surface-2: #24292e;
    --border: #32383f;
    --border-strong: #48505a;
    --text: #e9ecef;
    --text-2: #a3adb8;
    --text-3: #8e98a3;
    --accent: #5fa8ef;
    --accent-hover: #7cbaf4;
    --accent-weak: #16304a;
    --accent-border: #2a547f;
    --on-accent: #0b1b2b;
    --danger: #f08a80;
    --danger-weak: #3a1a17;
    --danger-border: #6b2a24;
    --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.5);
    --shadow-2: 0 2px 10px rgba(0, 0, 0, 0.55);

    --st-not-for-sale-bg: #262b30; --st-not-for-sale-fg: #a9b3bd; --st-not-for-sale-bd: #39414a;
    --st-available-bg:    #16301f; --st-available-fg:    #7ed69a; --st-available-bd:    #285035;
    --st-held-bg:         #33260c; --st-held-fg:         #e6bb66; --st-held-bd:         #54401a;
    --st-booked-bg:       #152c45; --st-booked-fg:       #86bdf2; --st-booked-bd:       #27486e;
    --st-partially-bg:    #12333a; --st-partially-fg:    #7fcdda; --st-partially-bd:    #1f525d;
    --st-fully-bg:        #10332e; --st-fully-fg:        #76cfbd; --st-fully-bd:        #1d524a;
    --st-registered-bg:   #281a3d; --st-registered-fg:   #c0a2ee; --st-registered-bd:   #432c63;
  }
}

/* ---------------------------------------------------------------------------
   Browser surfaces. The parts nobody draws still carry the design, and this is
   the check models skip most reliably (craft floor).
   --------------------------------------------------------------------------- */

* { box-sizing: border-box; }

html {
  caret-color: var(--accent);
  accent-color: var(--accent);          /* checkboxes, radios, range */
  scrollbar-color: var(--border-strong) transparent;
  scrollbar-width: thin;
}

::selection { background: var(--accent-weak); color: var(--text); }

::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: 6px;
  border: 3px solid var(--bg);
}
::-webkit-scrollbar-thumb:hover { background: var(--text-3); }

::placeholder { color: var(--text-2); opacity: 1; }   /* --text-2 clears 4.5:1 */

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Money and quantities. Tabular figures are measurement, not costume. */
.num {
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   Base
   --------------------------------------------------------------------------- */

body {
  margin: 0;
  font-family: var(--font);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  line-height: var(--lh-tight);
  text-wrap: balance;
  margin: var(--s6) 0 var(--s3);   /* more space above than below */
  font-weight: 600;
  letter-spacing: -0.01em;
}
h1 { font-size: var(--fs-2xl); margin-top: 0; }
h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-lg); }

p { margin: 0 0 var(--s3); max-width: 70ch; }   /* prose 65-75ch */

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 0.17em; }
a:hover { color: var(--accent-hover); }

code, .mono { font-family: var(--font-mono); font-size: 0.95em; }

.skip-link {
  position: absolute; left: var(--s3); top: -3rem;
  background: var(--bg); color: var(--text);
  padding: var(--s2) var(--s3); border: 1px solid var(--border);
  border-radius: var(--radius); z-index: 10; transition: top var(--t);
}
.skip-link:focus { top: var(--s3); }

/* ---------------------------------------------------------------------------
   Shell: top bar plus side nav. A permitted standard pattern (operate.md).
   --------------------------------------------------------------------------- */

.topbar {
  display: flex; align-items: center; gap: var(--s4);
  height: 48px; padding: 0 var(--s4);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 5;
}
.topbar__brand { font-weight: 650; font-size: var(--fs-md); letter-spacing: -0.015em; }
.topbar__sub { color: var(--text-2); font-size: var(--fs-micro); }
.topbar__right { margin-left: auto; display: flex; align-items: center; gap: var(--s3); font-size: var(--fs-micro); color: var(--text-2); }

.topbar__inbox {
  display: inline-flex; align-items: center; gap: var(--s2);
  color: var(--text-2); text-decoration: none;
  padding: var(--s1) var(--s2); border-radius: var(--radius-sm);
}
.topbar__inbox:hover { color: var(--text-1); background: var(--surface-2); }
.topbar__inbox:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.topbar__inbox[aria-current] { color: var(--accent); font-weight: 600; }
/* The count is the state, so it carries the accent the rest of the bar does not. */
.topbar__unread {
  font-variant-numeric: tabular-nums; font-weight: 650;
  min-width: 1.25rem; padding: 0 0.3em; text-align: center;
  background: var(--accent); color: var(--on-accent);
  border-radius: 999px; line-height: 1.45;
}

.shell { display: flex; min-height: calc(100vh - 48px); }

.nav {
  width: var(--nav-w); flex: 0 0 var(--nav-w);
  background: var(--surface);
  border-right: 1px solid var(--border);
  padding: var(--s4) var(--s2);
}
.nav__group { margin-bottom: var(--s5); }
.nav__label {
  font-size: var(--fs-micro); font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--text-3);
  padding: 0 var(--s2) var(--s2);
}
.nav a {
  display: block; padding: var(--s2) var(--s2);
  border-radius: var(--radius); color: var(--text);
  text-decoration: none; font-size: var(--fs-body);
  transition: background-color var(--t), color var(--t);
}
.nav a:hover { background: var(--surface-2); }
.nav a[aria-current="page"] {
  background: var(--accent-weak); color: var(--accent); font-weight: 550;
}

.main { flex: 1 1 auto; min-width: 0; padding: var(--s5) var(--s5) var(--s7); }

/* ---------------------------------------------------------------------------
   Tables. Density is a product permission; many rows is the point.
   --------------------------------------------------------------------------- */

.table-wrap {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: auto;              /* overlays must not live in here - see base.html */
  background: var(--bg);
  /* Makes this the containing block for absolutely positioned descendants.
     Without it, a `.sr-only` label inside a table wider than the viewport is
     positioned against the initial containing block instead, escapes this
     clip, and scrolls the whole page sideways on a phone. */
  position: relative;
}

table.data {
  width: 100%; border-collapse: separate; border-spacing: 0;
  font-size: var(--fs-dense);
}
table.data th, table.data td {
  padding: var(--s2) var(--s3);
  border-bottom: 1px solid var(--border);
  text-align: left; vertical-align: middle;
}
/* Numbers, badges and headers must not break; free text may wrap, or long
   owner and facing values push a 10-column register into horizontal scroll
   at 1440px. */
table.data th, table.data td.num, table.data td .badge { white-space: nowrap; }
table.data thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--surface);
  font-size: var(--fs-micro); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--text-2);
  border-bottom: 1px solid var(--border-strong);
}
table.data thead th a { color: inherit; text-decoration: none; display: inline-flex; gap: var(--s1); align-items: center; }
table.data thead th a:hover { color: var(--text); }
table.data thead th[aria-sort] { color: var(--text); }
table.data tbody tr { transition: background-color var(--t); }
table.data tbody tr:hover { background: var(--surface); }
table.data tbody tr:last-child td { border-bottom: 0; }
table.data tfoot td {
  background: var(--surface); font-weight: 600;
  border-top: 1px solid var(--border-strong); border-bottom: 0;
}
.sort-arrow { font-size: 0.8em; color: var(--accent); }

/* ---------------------------------------------------------------------------
   Status badge. Colour plus label, never colour alone.
   --------------------------------------------------------------------------- */

.badge {
  display: inline-block; padding: 1px var(--s2);
  border-radius: 999px; border: 1px solid transparent;
  font-size: var(--fs-micro); font-weight: 550; white-space: nowrap;
}
.badge--not_for_sale   { background: var(--st-not-for-sale-bg); color: var(--st-not-for-sale-fg); border-color: var(--st-not-for-sale-bd); }
.badge--available      { background: var(--st-available-bg);    color: var(--st-available-fg);    border-color: var(--st-available-bd); }
.badge--held           { background: var(--st-held-bg);         color: var(--st-held-fg);         border-color: var(--st-held-bd); }
.badge--booked         { background: var(--st-booked-bg);       color: var(--st-booked-fg);       border-color: var(--st-booked-bd); }
.badge--partially_paid { background: var(--st-partially-bg);    color: var(--st-partially-fg);    border-color: var(--st-partially-bd); }
.badge--fully_paid     { background: var(--st-fully-bg);        color: var(--st-fully-fg);        border-color: var(--st-fully-bd); }
.badge--registered     { background: var(--st-registered-bg);   color: var(--st-registered-fg);   border-color: var(--st-registered-bd); }

.flag {
  display: inline-block; font-size: var(--fs-micro); font-weight: 550;
  color: var(--danger); background: var(--danger-weak);
  border: 1px solid var(--danger-border);
  border-radius: var(--radius-sm); padding: 0 var(--s1);
}

/* ---------------------------------------------------------------------------
   Controls. Every interactive component ships all seven states.
   --------------------------------------------------------------------------- */

.btn {
  display: inline-flex; align-items: center; gap: var(--s2);
  font: inherit; font-size: var(--fs-body); font-weight: 550;
  padding: var(--s2) var(--s3);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  background: var(--bg); color: var(--text);
  cursor: pointer;
  transition: background-color var(--t), border-color var(--t), color var(--t);
}
.btn:hover { background: var(--surface-2); border-color: var(--text-3); }
/* A button label never wraps. "Retire it" broke across two lines the first
   time one sat in a table column competing with a wide neighbour. */
.btn { white-space: nowrap; }
.btn:active { background: var(--border); }
.btn[disabled], .btn[aria-disabled="true"] {
  opacity: 0.55; cursor: not-allowed; background: var(--surface);
}
.btn[disabled]:hover { background: var(--surface); border-color: var(--border-strong); }
.btn--primary {
  background: var(--accent); border-color: var(--accent); color: var(--on-accent);
}
.btn--primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn--primary:active { background: var(--accent-hover); }
.btn[aria-busy="true"] { color: transparent; position: relative; }
.btn[aria-busy="true"]::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  width: 13px; height: 13px; border-radius: 50%;
  border: 2px solid currentColor; border-top-color: transparent;
  color: var(--text-2);
  animation: spin 600ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

input[type="text"], input[type="search"], input[type="number"],
input[type="date"], select, textarea {
  font: inherit; font-size: var(--fs-body);
  padding: var(--s2) var(--s3);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  background: var(--bg); color: var(--text);
  transition: border-color var(--t), box-shadow var(--t);
  max-width: 100%;
}
input:hover, select:hover { border-color: var(--text-3); }
input:disabled, select:disabled {
  background: var(--surface); color: var(--text-2); cursor: not-allowed;
}
input[aria-invalid="true"] { border-color: var(--danger); }

label { font-size: var(--fs-micro); font-weight: 600; color: var(--text-2); }

/* ---------------------------------------------------------------------------
   Toolbar, summary, empty state, notices
   --------------------------------------------------------------------------- */

.page-head { display: flex; align-items: baseline; gap: var(--s3); flex-wrap: wrap; margin-bottom: var(--s4); }
.page-head h1 { margin: 0; }
.page-head__count { color: var(--text-2); font-size: var(--fs-body); }
.page-head__actions { margin-left: auto; display: flex; gap: var(--s2); }

.toolbar {
  display: flex; gap: var(--s3); flex-wrap: wrap; align-items: flex-end;
  padding: var(--s3); margin-bottom: var(--s4);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius);
}
.field { display: flex; flex-direction: column; gap: var(--s1); }

.summary {
  display: flex; flex-wrap: wrap; gap: var(--s5);
  padding: var(--s3) 0 var(--s4);
  font-size: var(--fs-dense);
}
.summary div { display: flex; flex-direction: column; gap: 2px; }
.summary dt, .summary .k {
  font-size: var(--fs-micro); text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--text-3); font-weight: 600;
}
.summary .v { font-size: var(--fs-lg); font-weight: 600; font-variant-numeric: tabular-nums; }

.empty {
  padding: var(--s7) var(--s5); text-align: center;
  color: var(--text-2);
}
.empty strong { display: block; color: var(--text); font-size: var(--fs-md); margin-bottom: var(--s2); }

.notice {
  padding: var(--s3); border-radius: var(--radius);
  border: 1px solid var(--accent-border); background: var(--accent-weak);
  font-size: var(--fs-dense); margin-bottom: var(--s4);
}
.notice--warn { border-color: var(--danger-border); background: var(--danger-weak); }
.notice strong { font-weight: 650; }

.dl { display: grid; grid-template-columns: max-content 1fr; gap: var(--s2) var(--s5); font-size: var(--fs-dense); margin: 0; }
.dl dt { color: var(--text-3); font-weight: 600; font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: 0.04em; align-self: center; }
.dl dd { margin: 0; }

.muted { color: var(--text-2); }
.micro { font-size: var(--fs-micro); }

/* ---------------------------------------------------------------------------
   Responsive: structural, not fluid type. Collapse the nav, let the table
   scroll (operate.md).
   --------------------------------------------------------------------------- */

@media (max-width: 900px) {
  .shell { flex-direction: column; }
  .nav {
    width: auto; flex: none; border-right: 0;
    border-bottom: 1px solid var(--border);
    padding: var(--s2);
    display: flex; gap: var(--s2); overflow-x: auto;
    /* A flex item defaults to min-width:auto, which refuses to shrink below
       its content — so overflow-x never engages and the strip pushes the
       whole page sideways instead of scrolling itself. */
    min-width: 0;
  }
  .nav__group { margin: 0; display: flex; gap: var(--s2); }
  .nav__label { display: none; }
  .nav a { white-space: nowrap; }
  .main { padding: var(--s4) var(--s3) var(--s6); }
  .page-head__actions { margin-left: 0; width: 100%; }

  /* The bar is a fixed 48px, so it cannot wrap. At 390px the brand, the
     location, Notifications, the username and Sign out do not fit, and the
     location is the one that carries nothing: this is a single-project
     system and it is named in the brand beside it. */
  .topbar { gap: var(--s3); }
  .topbar__sub { display: none; }
  .topbar__right { min-width: 0; }
  .topbar__right > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}

/* Print: its own surface, not a screenshot of the screen. */
@media print {
  .topbar, .nav, .toolbar, .page-head__actions, .skip-link { display: none !important; }
  .shell { display: block; }
  .main { padding: 0; }
  .table-wrap { border: 0; overflow: visible; }
  table.data { font-size: 9pt; }
  table.data thead th { position: static; }
  body { background: #fff; color: #000; }
}

/* ---------------------------------------------------------------------------
   Fixes from the first inspection round.
   --------------------------------------------------------------------------- */

/* `.num` lost to `table.data td` on specificity, so money columns were not
   actually right-aligned. Read the computed value, not the intention. */
table.data td.num, table.data th.num { text-align: right; }

/* In a definition list the value sits next to its term; right-aligning it
   throws it to the far edge of the grid column. Tabular figures still apply. */
.dl dd.num { text-align: left; }

/* A button that happens to be a link must not carry a link underline. */
.btn { text-decoration: none; }

/* Announce sort direction without printing it in the header. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

@media (max-width: 900px) {
  .summary { gap: var(--s4); }
}

/* ---------------------------------------------------------------------------
   Printed documents: the customer statement and the receipt.

   Print is its own surface, not a screenshot of the screen. The shell is
   hidden, so a printed page needs its own letterhead or it arrives with no
   indication of who issued it.
   --------------------------------------------------------------------------- */

/* !important because the next rule along sets `display` on an element that may
   also carry this class, and same-specificity-later-wins would reveal it on
   screen. It cost one wrongly-visible letterhead to find out. */
.print-only { display: none !important; }

.doc-head {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: var(--s5); padding-bottom: var(--s3); margin-bottom: var(--s4);
  border-bottom: 1px solid var(--border-strong);
}
.doc-head__title { font-size: var(--fs-xl); font-weight: 650; margin: 0; }
.doc-head__meta { text-align: right; font-size: var(--fs-micro); color: var(--text-2); }

.receipt {
  max-width: 46rem;
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  padding: var(--s5); background: var(--bg); box-shadow: var(--shadow-1);
}
.receipt__amount {
  display: flex; align-items: baseline; gap: var(--s3);
  padding: var(--s3) 0; margin: var(--s4) 0;
  border-top: 1px solid var(--border); border-bottom: 1px solid var(--border);
}
.receipt__figure { font-size: var(--fs-2xl); font-weight: 650; font-variant-numeric: tabular-nums; }
.receipt__words { font-size: var(--fs-dense); color: var(--text-2); font-style: italic; }
.receipt__sign {
  margin-top: var(--s7); padding-top: var(--s2);
  border-top: 1px solid var(--text-3); width: 14rem;
  font-size: var(--fs-micro); color: var(--text-2);
}

.ledger-running { font-weight: 600; }

@page { margin: 16mm; }

@media print {
  .print-only { display: block !important; }
  .no-print { display: none !important; }
  .receipt { border: 0; box-shadow: none; padding: 0; max-width: none; }
  .doc-head { border-bottom: 1pt solid #000; }
  table.data tbody tr:hover { background: transparent; }
  a { color: #000; text-decoration: none; }
  h2 { page-break-after: avoid; }
  table { page-break-inside: auto; }
  tr { page-break-inside: avoid; }
}

/* ---------------------------------------------------------------------------
   Forms: the registration screen.
   --------------------------------------------------------------------------- */

.stack { display: grid; gap: var(--s5); max-width: 60rem; }
/* Same trap as the mobile nav: a grid item defaults to min-width:auto, so a
   panel holding the min-width:34rem allocation table refused to shrink and
   pushed the whole phone page 202px sideways instead of letting .table-wrap
   scroll itself. */
.stack > * { min-width: 0; }

.panel {
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--s4); background: var(--bg);
}
.panel > h2 { margin: 0 0 var(--s4); font-size: var(--fs-lg); }

.field-grid {
  display: grid; gap: var(--s4);
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}
.field--wide { grid-column: 1 / -1; }
.field input, .field select { width: 100%; }
.field input[type="checkbox"] { width: auto; }

.field-error { color: var(--danger); font-weight: 600; }
.field-error::before { content: "— "; }

.actions { display: flex; gap: var(--s2); }

/* A select inside a dense table should not force the column wide. */
table.data td select { max-width: 24rem; }

/* A checkbox sits beside its label, not above it in a column. */
.field--check { flex-direction: row; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.field--check label { font-size: var(--fs-body); font-weight: 500; color: var(--text); }
.field--check .micro { flex-basis: 100%; }

/* Opt-in, not inherited by every table in a panel: the allocation table has
   two columns and full width leaves a canyon between the plot and its amount,
   but a seven-column table in a panel wants the whole width. */
table.data--narrow { width: auto; min-width: 34rem; }

/* ---------------------------------------------------------------------------
   Dashboard. SPEC.md §8.
   --------------------------------------------------------------------------- */

/* Three or four readings side by side at desk width, stacked on a phone.
   Breakpoint-driven columns, not fluid type. */
.band {
  display: grid; gap: var(--s5); margin: var(--s4) 0 var(--s6);
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  align-items: start;
}
.band > section > h3 { margin: 0 0 var(--s1); }
.band > section > p { margin: 0 0 var(--s3); }

/* The §8 Band 2 grid: 183 plots coloured by status. The one surface in this
   product where colour IS the information, which is why it earns the full
   status palette while everything else stays restrained. Each cell still
   carries its number and a spoken status - colour never carries meaning
   alone. */
.plot-grid {
  display: grid; gap: var(--s1);
  grid-template-columns: repeat(auto-fill, minmax(3.25rem, 1fr));
  margin-bottom: var(--s6);
}
.plot-cell {
  display: flex; align-items: center; justify-content: center;
  min-height: 2.25rem; padding: var(--s1);
  border: 1px solid transparent; border-radius: var(--radius-sm);
  font-size: var(--fs-micro); font-weight: 550;
  font-variant-numeric: tabular-nums;
  text-decoration: none;
  transition: box-shadow var(--t), transform var(--t);
}
.plot-cell:hover {
  box-shadow: var(--shadow-1);
  transform: translateY(-1px);
}

.legend {
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4);
  list-style: none; padding: 0; margin: 0 0 var(--s3);
  font-size: var(--fs-micro);
}
.legend li { display: flex; align-items: center; gap: var(--s2); }
.legend__swatch { min-width: 2rem; text-align: center; }
.legend__label { color: var(--text-2); }

@media (prefers-reduced-motion: reduce) {
  .plot-cell:hover { transform: none; }
}

/* ---------------------------------------------------------------------------
   Administration: settings, audit log, notes. SPEC.md §3.9, §7, §19.
   --------------------------------------------------------------------------- */

/* A form living inside a table cell: controls on one line, baseline-aligned
   with the row rather than stacked into it. */
.row-form {
  display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap;
}
.row-form input[type="text"] { width: auto; }
.row-form .field--check { margin: 0; gap: var(--s1); }

.notes { list-style: none; padding: 0; margin: var(--s4) 0 0; }
.notes li {
  padding: var(--s3) 0;
  border-top: 1px solid var(--border);
}
.notes li:first-child { border-top: 0; }
.notes li p { margin: 0 0 var(--s1); }
.notes li:target { background: var(--accent-weak); }

.pager {
  display: flex; gap: var(--s3); align-items: center;
  margin-top: var(--s4);
}

/* The shared input rule above already styles textareas; these two are the
   only properties a multi-line box needs on top of it. */
textarea { width: 100%; resize: vertical; }

/* ---------------------------------------------------------------------------
   The settle-a-discrepancy sheet. A real modal, and it earns one: the
   accountant is partway down a list of two hundred, and losing their place
   on every answer would make the screen unusable. Native <dialog>, so it
   lives in the top layer and no scroll container can clip it.
   --------------------------------------------------------------------------- */

dialog.sheet {
  width: min(44rem, calc(100vw - 2 * var(--s4)));
  max-height: calc(100vh - 2 * var(--s5));
  overflow: auto;
  padding: var(--s5);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--bg); color: var(--text);
  box-shadow: 0 8px 28px rgba(20, 24, 28, 0.18), 0 2px 6px rgba(20, 24, 28, 0.10);
}
dialog.sheet::backdrop { background: rgba(20, 24, 28, 0.45); }
dialog.sheet > h2 { margin: 0 0 var(--s1); }
dialog.sheet > p.micro { margin: 0 0 var(--s4); }

.sheet__dismiss { float: right; margin-left: var(--s4); }

/* The explanation is the point of the sheet, so it reads as prose rather than
   as a caption: full body size, a measure that does not run past 70ch. */
.sheet__detail {
  max-width: 68ch;
  margin-bottom: var(--s5);
  padding: var(--s4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.sheet__detail p { margin: 0 0 var(--s3); }
.sheet__detail p:last-child { margin-bottom: 0; }

.sheet__dismissal { margin-top: var(--s5); border-top: 1px solid var(--border); padding-top: var(--s4); }
.sheet__dismissal summary { cursor: pointer; color: var(--text-2); }
.sheet__dismissal summary:hover { color: var(--text); }
.sheet__dismissal .toolbar { margin-top: var(--s3); margin-bottom: 0; }

@media (max-width: 900px) {
  dialog.sheet { width: calc(100vw - 2 * var(--s3)); padding: var(--s4); }
}

/* ---------------------------------------------------------------------------
   The shareable price card. SPEC.md §7 — the one artefact a buyer sees, so
   Persuade mode. The restraint IS the persuasion: somebody deciding on ₹58
   lakh of land wants the figure legible and the facts checkable, not a
   brochure. One family, one accent, generous air around the number.
   --------------------------------------------------------------------------- */

.card {
  max-width: 34rem; margin: 0 auto;
  padding: var(--s6) var(--s5) var(--s5);
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--bg); box-shadow: var(--shadow-1);
}
.card__head { text-align: center; padding-bottom: var(--s5); }
.card__project {
  margin: 0; font-size: var(--fs-micro); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-2);
}
.card__plot { margin: var(--s2) 0 var(--s3); font-size: 2rem; letter-spacing: -0.02em; }
.card__status {
  display: inline-block; margin: 0; padding: 2px var(--s3);
  border-radius: 999px; font-size: var(--fs-micro); font-weight: 600;
  background: var(--st-available-bg); color: var(--st-available-fg);
  border: 1px solid var(--st-available-bd);
}
.card__status--held { background: var(--st-held-bg); color: var(--st-held-fg); border-color: var(--st-held-bd); }
.card__status--gone { background: var(--surface-2); color: var(--text-2); border-color: var(--border); }

.card__facts {
  display: grid; gap: var(--s2) var(--s5); margin: 0;
  padding: var(--s4) 0; border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-dense);
}
.card__facts > div { display: flex; justify-content: space-between; gap: var(--s4); }
.card__facts dt { color: var(--text-2); }
.card__facts dd { margin: 0; font-weight: 550; font-variant-numeric: tabular-nums; }

.card__prices { display: grid; gap: var(--s4); padding: var(--s5) 0 var(--s4); }
.card__price { text-align: center; }
.card__price-label {
  display: block; font-size: var(--fs-micro); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-2);
}
.card__price-value {
  display: block; margin: var(--s1) 0;
  font-size: 2.25rem; font-weight: 650; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.card__price-rate { display: block; font-size: var(--fs-dense); color: var(--text-2); }
.card__price--otp .card__price-value { font-size: 1.75rem; color: var(--accent); }

.card__foot { padding-top: var(--s4); border-top: 1px solid var(--border); text-align: center; }
.card__foot .micro { max-width: 40ch; margin: 0 auto var(--s4); }

@media (max-width: 900px) {
  .card { padding: var(--s5) var(--s4); border: 0; box-shadow: none; }
  .card__plot { font-size: 1.75rem; }
  .card__price-value { font-size: 2rem; }
}

/* The inbox. §10 — in-app only, so this is the whole notification surface. */
.inbox { list-style: none; padding: 0; margin: 0; }
.inbox__item {
  display: flex; gap: var(--s4); align-items: flex-start;
  justify-content: space-between;
  padding: var(--s4);
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--bg); margin-bottom: var(--s2);
}
/* Unread carries weight, a lighter surface and a dot — never a coloured
   border-left, which reads as decoration stuck to the edge of the row. */
.inbox__item--unread { background: var(--surface); }
.inbox__item--unread .inbox__subject { font-weight: 600; }
.inbox__subject { margin: 0 0 var(--s1); display: flex; align-items: center; gap: var(--s2); }
.inbox__item--unread .inbox__subject::before {
  content: ""; flex: 0 0 auto;
  width: 7px; height: 7px; border-radius: 50%; background: var(--accent);
}
.inbox__body > p:last-child { margin-bottom: 0; }
.inbox__actions { display: flex; gap: var(--s2); flex-shrink: 0; }

@media (max-width: 900px) {
  .inbox__item { flex-direction: column; gap: var(--s3); }
  .inbox__actions { width: 100%; }
}

/* Error pages render outside the shell, so they carry their own measure. */
.errorpage { max-width: 60ch; padding-top: var(--s7); }
.errorpage h1 { margin-bottom: var(--s4); }
.errorpage p { margin: 0 0 var(--s4); color: var(--text-2); }

/* A <summary> styled as a button keeps the browser's disclosure triangle
   unless both of these are set — Chromium honours the pseudo-element, the
   rest honour list-style. Without them the control is a button with a wart. */
summary.btn { cursor: pointer; list-style: none; }
summary.btn::-webkit-details-marker { display: none; }
summary.btn::marker { content: ""; }

/* Snoozing a queue item. §8 Band 5 — the thing you do when you cannot do the
   work, so it sits below the band, closed, and never competes with it. */
.snooze { margin: var(--s2) 0 var(--s5); }
.snooze > summary {
  cursor: pointer; color: var(--text-2); width: fit-content;
  padding: var(--s1) 0;
}
.snooze > summary:hover { color: var(--text-1); }
.snooze__form {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--s3);
  margin-top: var(--s3); padding: var(--s3);
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface);
}
.snooze__why { flex: 1 1 22rem; }
/* The tick column carries no heading text, so it must not claim width. The
   selector names .pick on both cells: `th:last-child` would have squeezed the
   last column of every table in the product, and did. */
table.data td.pick, table.data th.pick { width: 1%; white-space: nowrap; }
table.data td.pick input { margin: 0; }

/* Repricing. Closed by default: §5's rate change is rare and consequential,
   and an open form invites it to be read as a correction, which it is not. */
.reprice { margin: var(--s4) 0 var(--s5); }
.reprice > summary { width: fit-content; }
.reprice__form {
  margin-top: var(--s3); padding: var(--s4);
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); max-width: 60rem;
}

/* ---------------------------------------------------------------------------
   The opening position statement (§13). A document before it is a screen: it
   exists to be printed, walked with a pen and signed.
   --------------------------------------------------------------------------- */

/* The box somebody ticks. An <input type=checkbox> would print as a widget and
   some browsers drop it entirely; a drawn square always prints. */
.tickbox {
  display: inline-block; width: 11px; height: 11px;
  border: 1px solid var(--text-3); border-radius: 2px;
}

.signoff { margin-top: var(--s6); max-width: 60rem; }
.signoff__grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--s6);
  margin: var(--s6) 0 var(--s4);
}
.signoff__rule {
  display: block; border-bottom: 1px solid var(--text-3);
  height: var(--s6); margin-bottom: var(--s2);
}

@media print {
  /* 183 rows over several sheets of paper: the header has to repeat or the
     later pages are columns of numbers with no names on them. */
  table.opening thead { display: table-header-group; }
  table.opening tfoot { display: table-row-group; }
  table.opening { font-size: 8.5pt; }
  table.opening td, table.opening th { padding: 2pt 4pt; }

  /* Keep the signature block off a page of its own, and never split it. */
  .signoff { page-break-inside: avoid; margin-top: 12pt; }
  .tickbox { border-color: #000; }
}

/* The bulk settle table: one form row per discrepancy. The inputs carry the
   density, so they sit tighter than a form panel would. */
td.bulk-cell { vertical-align: top; }
td.bulk-cell input, td.bulk-cell select { width: 100%; min-width: 9rem; }
td.bulk-cell .field-error { display: block; margin-top: var(--s1); }
