/* ==========================================================================
   Small Wallet CSS
   ========================================================================== */

/* ==========================================================================
   1. Color Palette
   ========================================================================== */

/* Display face: Playfair Display (self-hosted variable, Latin + Latin-Ext) */
@font-face { font-family: 'Playfair Display'; font-style: normal; font-weight: 400 900; font-display: swap; src: url("../fonts/PlayfairDisplay-latin-ext.319e6b2aad48.woff2") format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Playfair Display'; font-style: normal; font-weight: 400 900; font-display: swap; src: url("../fonts/PlayfairDisplay-latin.ef05b30d6e5c.woff2") format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

:root {
  /* ================= Ligne 1 — an 80s transit map ==================
     One palette. Four lines do all the signalling, the way a
     network map does it: a colour means a line, never decoration. Money
     that grows rides the green line, money that drains rides the red,
     caution is the platform yellow, and the blue is the trunk — links,
     buttons, everything the interface offers you. There is deliberately
     no orange: it is the one hue that cannot be told from the yellow at
     a glance, and a fifth voice would only make the four harder to read.
     That holds for the page as it ships. An accent chosen in Settings ›
     Display (syndicus's eight, below) repaints only what the interface
     offers, and may be any of them, green and orange included: it is that
     browser's own choice, and the figures keep their lines.

     Everything else is paper, ink and rule: plain white, so the four
     lines are printed on nothing at all and each one carries its full
     strength. Flat — a map has no shadows.

     Still the one rule that matters: no colour is hardcoded anywhere
     else in the app. Every value lives here, which is what lets a
     single line below repaint the whole interface. */

  /* ---- Paper & ink: the sheet the map is printed on ----
     White, and the greys off it neutral: a warm cream next to white reads
     as a stain rather than as paper, so the secondary surfaces and the
     rules are the same sheet a shade down. */
  --paper: #FFFFFF;
  --paper-2: #F2F2F0;
  --ink: #14161A;
  --ink-soft: #3E434D;
  --ink-faint: #6B7280;
  --rule: #BFBFBC;
  --rule-soft: #E0E0DC;

  /* Panels that sit on the page rather than being the page (form
     fields, the nav pill). The same white as the paper in daylight —
     their border is what sets them apart there — and kept a separate
     name so the night cut can lift them off the dark page. */
  --surface: #FFFFFF;

  /* ---- The four lines ---- */
  --color-blue: #0B3DA8;      /* trunk line: links, actions, the offer   */
  --color-green: #00782A;     /* the green line: money kept, under budget*/
  --color-red: #C8102E;       /* the red line: overspending, danger      */
  --color-yellow: #F5C400;    /* platform stripe: a fill, never a word   */
  --color-yellow-ink: #7A5B00;/* the same yellow, dark enough to read    */

  /* The accent is the blue line: it is what the interface offers you.
     A browser may pick another from Settings › Display (smallwallet/
     themes.py, `data-accent` on <html>): one of the colours below — the
     same eight syndicus offers. Each is repainted in the night cut like
     the four lines. */
  --accent: var(--color-blue);
  --accent-hover: #08307F;
  --accent-glow: color-mix(in srgb, var(--accent) 18%, transparent);
  --color-brown: #8B5A2B;
  --color-olive: #5B6B12;
  --color-ochre: #A85D00;
  --color-emerald: #046C4E;
  --color-teal: #0B6573;
  --color-cobalt: #1D4ED8;
  --color-indigo: #3730A3;
  --color-plum: #6B21A8;

  /* The page is the paper itself, white. The accent touches only what the
     interface offers you and the wash behind a message. */
  --accent-wash: color-mix(in srgb, var(--accent) 8%, var(--surface));

  /* A highlighter over a figure — the yellow doing what yellow does. */
  --highlight: color-mix(in srgb, var(--color-yellow) 42%, transparent);

  /* Text that sits ON a filled swatch. Each is the far end of its own
     colour: white on the deep blue and red, and on the yellow the ink
     itself — the only way a yellow lozenge is ever legible. */
  --on-accent: #FFFFFF;
  --on-error: #FFFFFF;
  --on-warning: #FFFFFF;
  --on-success: #FFFFFF;

  /* ---- What each line means ---- */
  --color-error: var(--color-red);
  --color-success: var(--color-green);
  --color-warning: var(--color-yellow-ink);
  --color-info: var(--color-blue);
  --color-primary: var(--accent);

  /* ---- Neutrals ---- */
  --color-text: var(--ink);
  --color-text-muted: var(--ink-soft);
  --color-text-light: var(--ink-faint);
  --color-text-inactive: #96968F;
  --color-border: var(--rule);
  --color-border-light: var(--rule-soft);
  --color-bg-light: var(--paper-2);
  --color-bg-highlight: #E7E7E3;

  /* Display font (the ledger "book" face) — the romance is in the type,
     set against signage colour. */
  --font-display: "Playfair Display", "Iowan Old Style", "Palatino Linotype", "Times New Roman", serif;

  /* ---- Notices: a borderless wash behind plain ink, so it is never the
     colour that has to be read. An ordinary message takes the accent's
     wash, so it follows the theme; a warning or an error keeps its own
     line's, since that colour is the signal. ---- */
  --color-alert-success-bg: var(--accent-wash);
  --color-alert-success-text: var(--ink);
  --color-alert-warning-bg: color-mix(in srgb, var(--color-yellow) 18%, var(--surface));
  --color-alert-warning-text: var(--ink);
  --color-alert-danger-bg: color-mix(in srgb, var(--color-red) 8%, var(--surface));
  --color-alert-danger-text: var(--ink);
  --color-alert-info-bg: var(--accent-wash);
  --color-alert-info-text: var(--ink);
  --color-alert-secondary-bg: var(--accent-wash);
  --color-alert-secondary-text: var(--ink-soft);
}

/* The same map at night. The lines keep their identity and are brightened
   just enough to hold on a dark platform; the yellow, already bright,
   barely moves. Unless this browser chose a theme in Settings › Display,
   the device asks and the page answers, on the first frame, with no
   script and no flash. A chosen theme is a `data-theme` on <html>, put
   there by the server: Light keeps the day whatever the device says, and
   Dark is the same cut repeated under its own selector below — a copy,
   since CSS cannot name a block twice. Change one, change both. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #0F1114;
    --paper-2: #191C21;
    --ink: #F2F0E8;
    --ink-soft: #C0C4CC;
    --ink-faint: #878D98;
    --rule: #3A3F47;
    --rule-soft: #2A2E34;
    --surface: #171A1F;

    --color-blue: #5B9BFF;
    --color-green: #4CD07A;
    --color-red: #FF5A5A;
    --color-yellow: #FFD400;
    --color-yellow-ink: #F0C400;

    --color-brown: #C9935F;
    --color-olive: #B5C45A;
    --color-ochre: #F0A33A;
    --color-emerald: #34C38F;
    --color-teal: #3FB6C4;
    --color-cobalt: #6B93FF;
    --color-indigo: #8B8CF5;
    --color-plum: #B98CF0;

    --accent-hover: #8FBBFF;

    /* On a brightened line, the legible word is the dark one. */
    --on-accent: #0B1220;
    --on-error: #1A0505;
    --on-warning: #1A1400;
    --on-success: #05170B;

    --color-text-inactive: #6B7078;
    --color-bg-highlight: #22262C;
  }
}

:root[data-theme="dark"] {
  --paper: #0F1114;
  --paper-2: #191C21;
  --ink: #F2F0E8;
  --ink-soft: #C0C4CC;
  --ink-faint: #878D98;
  --rule: #3A3F47;
  --rule-soft: #2A2E34;
  --surface: #171A1F;

  --color-blue: #5B9BFF;
  --color-green: #4CD07A;
  --color-red: #FF5A5A;
  --color-yellow: #FFD400;
  --color-yellow-ink: #F0C400;

  --color-brown: #C9935F;
  --color-olive: #B5C45A;
  --color-ochre: #F0A33A;
  --color-emerald: #34C38F;
  --color-teal: #3FB6C4;
  --color-cobalt: #6B93FF;
  --color-indigo: #8B8CF5;
  --color-plum: #B98CF0;

  --accent-hover: #8FBBFF;

  --on-accent: #0B1220;
  --on-error: #1A0505;
  --on-warning: #1A1400;
  --on-success: #05170B;

  --color-text-inactive: #6B7078;
  --color-bg-highlight: #22262C;
}

/* The browser's own parts — scrollbars, the date picker, a select's
   list — follow the theme too, chosen or not. */
:root { color-scheme: light dark; }
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

/* A chosen accent. No :root in the selector, so the same rule colours its
   swatch in Settings › Display. It names a line declared above, which the
   night cut has already repainted, so one rule serves day and night. */
[data-accent="brown"] { --accent: var(--color-brown); }
[data-accent="olive"] { --accent: var(--color-olive); }
[data-accent="ochre"] { --accent: var(--color-ochre); }
[data-accent="emerald"] { --accent: var(--color-emerald); }
[data-accent="teal"] { --accent: var(--color-teal); }
[data-accent="cobalt"] { --accent: var(--color-cobalt); }
[data-accent="indigo"] { --accent: var(--color-indigo); }
[data-accent="plum"] { --accent: var(--color-plum); }
/* Hover darkens it by day and lightens it at night: the ink is the far
   end in both. After the night cut, which sets the default blue's own. */
:root[data-accent] { --accent-hover: color-mix(in srgb, var(--accent) 72%, var(--ink)); }

/* ==========================================================================
   2. Reset & Base Styles
   ========================================================================== */

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  background: var(--paper);
}

body {
  margin: 0 auto;
  max-width: 600px;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  /* syndicus's type: Noto Serif first — installed on Linux, absent from
     macOS and Windows, which keep Georgia — at the size the browser is set
     to (16px unless its owner chose bigger), never a pinned pixel size that
     would ignore that choice. */
  font-family: "Noto Serif", Georgia, "Times New Roman", Times, serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
  line-height: 1.5;
  padding: 1.5em 2em;
  font-size: 100%;
  color: var(--color-text);
  background-color: var(--paper);
}

/* ==========================================================================
   3. Typography
   ========================================================================== */

h1, h2, h3, h4, h5, h6 {
  margin-bottom: 1rem;
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.3;
  color: var(--ink);
}

h1, h2 {
  font-variant: small-caps;
}

h1 { font-size: 1.5rem; }
h2 { font-size: 1.75rem; }
h3 { font-size: 1.5rem; }
h4 { font-size: 1.25rem; }
h5 { font-size: 1.1rem; }
h6 { font-size: 1rem; }

p { margin-bottom: 1rem; }

ul, ol {
  margin-bottom: 1rem;
  padding-left: 1.5em;
}

a {
  color: var(--color-primary);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

small {
  font-size: 0.875rem;
}

/* ==========================================================================
   4. Layout
   ========================================================================== */

.container {
  width: 100%;
  max-width: 600px;
  margin: 0 auto;
  padding: 0 1rem;
}

.row {
  display: flex;
  flex-wrap: wrap;
}

.col { flex: 1 0 0%; }
.col-4 { flex: 0 0 33.333333%; max-width: 33.333333%; }
.col-6 { flex: 0 0 50%; max-width: 50%; }
.col-8 { flex: 0 0 66.666667%; max-width: 66.666667%; }
.col-12 { flex: 0 0 100%; max-width: 100%; }

.hide-mobile { }

@media (max-width: 768px) {
  .hide-mobile { display: none; }
  .col-4, .col-6, .col-8 {
    flex: 0 0 100%;
    max-width: 100%;
  }
  .row {
    flex-direction: column;
  }
}

/* Budget Page Layout */

/* ==========================================================================
   5. Navigation (element styles only)
   ========================================================================== */

/* No rule under the nav: the page opens on bare paper, and the colour is
   left to the figures that mean something. These rules are scoped to the
   site nav by id — a `nav` element elsewhere on a page (the savings page's
   view tabs) is its own thing and must not inherit the header's layout. */
/* Exactly one ledger row tall (2.3em), so the page below it starts on the
   ledger's beat. Left to itself the bar takes the height of the wordmark's
   line box — 25.2px in Playfair — and every row under it is off the beat by
   that much. (The beat itself is ≈36.8px at 16px, not a whole pixel: the 1.3
   line is syndicus's, kept on purpose.) The
   min-height only ever grows the bar, so a wrapped breadcrumb still fits. */
#main-nav {
  min-height: 2.3em;
  margin-bottom: 1em;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1em;
}

#main-nav .nav-left { display: inline-flex; align-items: baseline; gap: 1em; }

#main-nav a, #main-nav ul a {
  color: var(--color-text);
}

#main-nav ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  align-items: center;
  gap: 1em;
}

#main-nav li {
  display: inline;
}

#main-nav a {
  text-decoration: none;
}

#main-nav .nav-crumb { color: var(--color-text-inactive); }
#main-nav .nav-crumb a { color: var(--color-text); }

#main-nav .logo-text { display: inline-flex; align-items: center; gap: 0.3em; }
#main-nav .logo-link { display: inline-flex; align-items: center; gap: 0.3em; padding: 0.3em 0.7em; border: 1px solid var(--color-border); border-radius: 6px; background: var(--surface); }
#main-nav .logo-link:hover { background: var(--color-bg-light); }

/* ==========================================================================
   6. Forms
   ========================================================================== */

form {
  margin-bottom: 1rem;
}

.form-group {
  margin-bottom: 1rem;
}

label {
  display: block;
  margin-bottom: 0.5rem;
  font-weight: 500;
}

input,
textarea,
select,
button {
  box-sizing: border-box;
  font: inherit;
  color: inherit;
  margin: 0;
  padding: 0.5em;
  border: 1px solid var(--color-border);
  background-color: var(--surface);
  line-height: 1.2;
  border-radius: 4px;
}

input[type="text"],
input[type="number"],
input[type="date"],
input[type="email"],
input[type="password"],
select {
  padding: 0.5em;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  box-sizing: border-box;
}

.form-control {
  display: block;
  width: 100%;
  padding: 0.375rem 0.75rem;
  font-size: 1rem;
  line-height: 1.5;
  color: var(--color-text);
  background-color: var(--surface);
  border: 1px solid var(--color-border-light);
  border-radius: 0.25rem;
}

.form-select {
  display: block;
  width: 100%;
  padding: 0.375rem 0.75rem;
  font-size: 1rem;
  line-height: 1.5;
  color: var(--color-text);
  background-color: var(--surface);
  border: 1px solid var(--color-border-light);
  border-radius: 0.25rem;
}

.form-check {
  display: block;
  min-height: 1.5rem;
  margin-bottom: 0.5rem;
}

.form-check-input {
  margin-right: 0.5rem;
}

.form-check-label {
  display: inline-block;
}

.form-label {
  display: block;
  margin-bottom: 0.5rem;
  font-weight: 500;
}

.form-text {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.875rem;
  color: var(--color-text-muted);
}

.form-switch .form-check-input {
  appearance: none;
  width: 2em;
  height: 1em;
  background-color: var(--color-border);
  border-radius: 1em;
  position: relative;
  cursor: pointer;
  border: none;
  padding: 0;
  vertical-align: middle;
}

.form-switch .form-check-input::before {
  content: "";
  position: absolute;
  top: 0.1em;
  left: 0.1em;
  width: 0.8em;
  height: 0.8em;
  background-color: var(--surface);
  border-radius: 50%;
  transition: transform 0.15s ease-in-out;
}

.form-switch .form-check-input:checked {
  background-color: var(--color-primary);
}

.form-switch .form-check-input:checked::before {
  transform: translateX(1em);
}

/* Focusing a radio or a checkbox draws a dotted box around its label —
   the choice reads as a whole line, not a lone control. */
input[type="checkbox"]:focus-visible + label,
input[type="radio"]:focus-visible + label,
label:has(input[type="checkbox"]:focus-visible),
label:has(input[type="radio"]:focus-visible) {
  outline: 1px dotted currentColor;
  outline-offset: 2px;
}

/* The label carries the ring, so the control itself doesn't repeat it. */
input[type="checkbox"]:focus-visible:has(+ label),
input[type="radio"]:focus-visible:has(+ label),
label input[type="checkbox"]:focus-visible,
label input[type="radio"]:focus-visible {
  outline: none;
}

/* A switch is its own visible control — the pill keeps the ring. */
.form-switch .form-check-input:focus-visible {
  outline: 1px dotted currentColor;
  outline-offset: 2px;
}

.form-switch .form-check-input:focus-visible + .form-check-label {
  outline: none;
}

/* Settings › Display: one swatch per accent, in the shade of the theme in
   force. The default one shows the blue line, not whatever --accent is now. */
.display-heading { margin-top: 2em; }
.display-form fieldset { border: 0; }
.swatches { display: flex; flex-wrap: wrap; gap: 0 1.2em; }
.swatch-choice {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  min-height: 44px;
  margin: 0;
  font-weight: normal;
  cursor: pointer;
}
.swatch {
  width: 1.2em;
  height: 1.2em;
  border-radius: 50%;
  background: var(--accent);
}
.swatch:not([data-accent]) { background: var(--color-blue); }

/* ==========================================================================
   7. Buttons
   ========================================================================== */

button {
  cursor: pointer;
}

.btn {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 600;
  text-align: center;
  vertical-align: middle;
  cursor: pointer;
  padding: 0.4rem 0.85rem;
  font-size: 0.95rem;
  line-height: 1.5;
  border-radius: 2px;
  transition: transform 0.05s ease, background-color 0.15s ease;
  text-decoration: none;
}

.btn:hover {
  text-decoration: none;
}

.btn:active {
  transform: translateY(1px);
}

.btn-primary {
  background-color: var(--color-primary);
  border: 1px solid var(--ink);
  color: var(--on-accent);
}

.btn-primary:hover {
  background-color: var(--accent-hover);
}

.btn-outline {
  background-color: transparent;
  border: 1px solid var(--color-border-light);
}

.btn-outline:hover {
  background-color: var(--color-bg-light);
}

.btn-sm {
  padding: 0.25rem 0.5rem;
  font-size: 0.875rem;
}

.btn-lg {
  padding: 0.5rem 1rem;
  font-size: 1.125rem;
}

.btn-danger {
  background-color: var(--color-error);
  border: 1px solid var(--color-error);
  color: var(--on-error);
}

.btn-warning {
  background-color: var(--color-warning);
  border: 1px solid var(--color-warning);
  color: var(--on-warning);
}

.btn-outline-primary {
  background-color: transparent;
  border: 1px solid var(--color-primary);
  color: var(--color-primary);
}

.btn-outline-primary:hover {
  background-color: var(--color-primary);
  color: var(--on-accent);
}

.btn-outline-secondary {
  background-color: transparent;
  border: 1px solid var(--color-border);
  color: var(--color-text-muted);
}

.btn-outline-secondary:hover {
  background-color: var(--color-bg-light);
  color: var(--color-text);
}

.btn-outline-danger {
  background-color: transparent;
  border: 1px solid var(--color-error);
  color: var(--color-error);
}

.btn-outline-danger:hover {
  background-color: var(--color-error);
  color: var(--on-error);
}

.btn-outline-success {
  background-color: transparent;
  border: 1px solid var(--color-success);
  color: var(--color-success);
}

.btn-outline-success:hover {
  background-color: var(--color-success);
  color: var(--on-success);
}

.btn-block {
  display: block;
  width: 100%;
}

.btn-group {
  display: inline-flex;
}

.btn-group .btn {
  border-radius: 0;
}

.btn-group .btn:first-child {
  border-radius: 0.25rem 0 0 0.25rem;
}

.btn-group .btn:last-child {
  border-radius: 0 0.25rem 0.25rem 0;
}

/* ==========================================================================
   8. Lists
   ========================================================================== */

.list-unstyled {
  list-style: none;
  padding-left: 0;
}

.list-group {
  display: flex;
  flex-direction: column;
  padding: 0;
  margin-bottom: 1rem;
  border: 1px solid var(--color-border-light);
  border-radius: 0.25rem;
}

.list-group-flush {
  border: none;
  border-radius: 0;
}

.list-group-item {
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--color-border-light);
  list-style: none;
}

.list-group-item:last-child {
  border-bottom: 0;
}

.list-group-flush .list-group-item {
  border-left: 0;
  border-right: 0;
  border-radius: 0;
}

.list-group-item-action {
  color: var(--color-text);
  text-decoration: none;
}

.list-group-item-action:hover {
  background-color: var(--color-bg-light);
}

/* ==========================================================================
   9. Tables
   ========================================================================== */

.table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 1rem;
}

.table th,
.table td {
  padding: 0.75rem;
  border-top: 1px solid var(--color-border-light);
  text-align: left;
}

.table thead th {
  border-bottom: 2px solid var(--color-border);
  border-top: none;
}

.table-hover tbody tr:hover {
  background-color: var(--color-bg-light);
}

.table-responsive {
  display: block;
  width: 100%;
  overflow-x: auto;
}

/* ==========================================================================
   10. Alerts
   ========================================================================== */

/* A notice is a wash of colour behind plain ink, with no border: the wash
   alone sets it off the white page. */
.alert {
  padding: 0.75rem 1.25rem;
  margin-bottom: 1rem;
  border: 0;
  border-radius: 0.25rem;
}

.alert-success {
  color: var(--color-alert-success-text);
  background-color: var(--color-alert-success-bg);
}

.alert-warning {
  color: var(--color-alert-warning-text);
  background-color: var(--color-alert-warning-bg);
}

.alert-danger {
  color: var(--color-alert-danger-text);
  background-color: var(--color-alert-danger-bg);
}

.alert-info {
  color: var(--color-alert-info-text);
  background-color: var(--color-alert-info-bg);
}

.alert-secondary {
  color: var(--color-alert-secondary-text);
  background-color: var(--color-alert-secondary-bg);
}

.alert-heading {
  margin-bottom: 0.5rem;
  font-weight: 600;
}

#flash-messages {
  position: fixed;
  top: 0.5em;
  left: 50%;
  transform: translateX(-50%);
  width: calc(100% - 4em);
  max-width: calc(600px - 4em);
  z-index: 1000;
}

.flash-message {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.5rem;
}

.flash-close {
  background: none;
  border: none;
  padding: 0 0 0 1rem;
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
  opacity: 0.5;
  border-radius: 0;
  flex-shrink: 0;
}

.flash-close:hover {
  opacity: 1;
}

/* Inline warning box */
.warning-box {
  background-color: var(--color-alert-warning-bg);
  border-radius: 0.25rem;
  padding: 1em;
  margin-bottom: 1em;
}

.warning-box h3 {
  margin-top: 0;
}

/* ==========================================================================
   11. Badges
   ========================================================================== */

.badge {
  display: inline-block;
  padding: 0.25em 0.5em;
  font-size: 0.75rem;
  font-weight: 600;
  border-radius: 0.25rem;
}

.bg-light {
  background-color: var(--color-bg-light);
}

.bg-secondary {
  background-color: var(--color-text-muted);
  color: var(--paper);
}

.bg-success {
  background-color: var(--color-success);
  color: var(--on-success);
}

.bg-danger {
  background-color: var(--color-error);
  color: var(--on-error);
}

/* ==========================================================================
   12. Status Indicators
   ========================================================================== */

.status-on-track {
  color: var(--color-success);
}

.status-slightly-behind {
  color: var(--color-warning);
}

.status-behind {
  color: var(--color-error);
}

/* ==========================================================================
   13. Footer
   ========================================================================== */

footer {
  margin-top: auto;
  padding-top: 1em;
  font-size: 0.8rem;
}

/* ==========================================================================
   14. Utility Classes
   ========================================================================== */

/* Text Alignment */
.text-center { text-align: center; }
.text-right { text-align: right; }
.text-end { text-align: right; }

/* Text Colors */
.text-success { color: var(--color-success); }
.text-danger { color: var(--color-error); }
.text-warning { color: var(--color-warning); }
.text-info { color: var(--color-info); }
.text-muted { color: var(--color-text-muted); }
.text-dark { color: var(--color-text); }
.text-inactive { color: var(--color-text-inactive); }

/* Display */
.d-flex { display: flex; }
.d-grid { display: grid; }
.d-block { display: block; }
.d-inline { display: inline; }
.d-inline-block { display: inline-block; }
.d-none { display: none; }

/* Flexbox */
.justify-content-between { justify-content: space-between; }
.justify-content-center { justify-content: center; }
.align-items-center { align-items: center; }
.flex-wrap { flex-wrap: wrap; }
.gap-1 { gap: 0.25rem; }
.gap-2 { gap: 0.5rem; }
.gap-3 { gap: 1rem; }

/* Margins */
.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: 0.25rem; }
.mb-2 { margin-bottom: 0.5rem; }
.mb-3 { margin-bottom: 1rem; }
.mb-4 { margin-bottom: 1.5rem; }
.mb-5 { margin-bottom: 3rem; }

.mt-0 { margin-top: 0; }
.mt-1 { margin-top: 0.25rem; }
.mt-2 { margin-top: 0.5rem; }
.mt-3 { margin-top: 1rem; }
.mt-4 { margin-top: 1.5rem; }
.mt-5 { margin-top: 3rem; }

.me-1 { margin-right: 0.25rem; }
.me-2 { margin-right: 0.5rem; }
.me-3 { margin-right: 1rem; }

.ms-1 { margin-left: 0.25rem; }
.ms-2 { margin-left: 0.5rem; }
.ms-3 { margin-left: 1rem; }

/* Padding */
.p-0 { padding: 0; }
.p-1 { padding: 0.25rem; }
.p-2 { padding: 0.5rem; }
.p-3 { padding: 1rem; }

.py-1 { padding-top: 0.25rem; padding-bottom: 0.25rem; }
.py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; }
.py-3 { padding-top: 1rem; padding-bottom: 1rem; }

.px-1 { padding-left: 0.25rem; padding-right: 0.25rem; }
.px-2 { padding-left: 0.5rem; padding-right: 0.5rem; }
.pb-4 { padding-bottom: 1.5rem; }
.pt-4 { padding-top: 1.5rem; }
.py-4 { padding-top: 1.5rem; padding-bottom: 1.5rem; }

.px-3 { padding-left: 1rem; padding-right: 1rem; }

/* Width */
.w-100 { width: 100%; }

/* Height */
.h-100 { height: 100%; }

/* Borders */
.border { border: 1px solid var(--color-border-light); }
.border-top { border-top: 1px solid var(--color-border-light); }
.border-bottom { border-bottom: 1px solid var(--color-border-light); }
.border-secondary { border-color: var(--color-text-muted); }
.rounded { border-radius: 0.25rem; }

/* Visibility */
.visually-hidden,
.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;
}

/* Typography */
.small { font-size: 0.875rem; }

/* Spinners */
.spinner-border {
  display: inline-block;
  width: 2rem;
  height: 2rem;
  border: 0.25em solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: spin 0.75s linear infinite;
}

.spinner-border-sm {
  width: 1rem;
  height: 1rem;
  border-width: 0.2em;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.text-peach { color: var(--color-primary); }

/* ==========================================================================
   15. JS Toggle (Collapse)
   ========================================================================== */

.collapse {
  display: none;
}

.collapse.show {
  display: block;
}

/* ==========================================================================
   16. Paper chrome — wordmark, rubber stamps, dither rules
   ========================================================================== */

/* Wordmark in the ledger's display face */
#main-nav .logo-text,
#main-nav .logo-link {
  font-family: var(--font-display);
  font-variant: small-caps;
  font-size: 1.05em;
  font-weight: 700;
}

#main-nav .logo-link {
  border-color: var(--rule);
  background: var(--paper-2);
  padding: 0.3em 0.7em 0.5em;
  transition: background 0.12s ease;
}

#main-nav .logo-link:hover {
  background: var(--paper);
}

/* The squirrel beside the wordmark: the Noun Project drawing in
   img/squirrel.svg used as a mask over the wordmark's own ink, so it takes
   whatever colour the lettering has, night cut included, rather than the
   black baked into the file. It stays still on hover. */
#main-nav .logo-text .logo-squirrel,
#main-nav .logo-link .logo-squirrel {
  display: inline-block;
  width: 1.5em;
  height: 1.5em;
  background-color: currentColor;
  -webkit-mask: url("../img/squirrel.3b876648a708.svg") center / contain no-repeat;
  mask: url("../img/squirrel.3b876648a708.svg") center / contain no-repeat;
}

/* Dithered / inked horizontal rule — a halftone strip */
hr {
  height: 4px;
  border: 0;
  margin: 1em 0;
  background: repeating-conic-gradient(var(--ink-soft) 0 25%, transparent 0 50%) 0 0 / 4px 4px;
  opacity: 0.6;
}

/* Rubber stamps — bureaucratic status marks */
.stamp {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: 0.72em;
  line-height: 1;
  padding: 0.3em 0.55em;
  border: 2px solid currentColor;
  border-radius: 3px;
  color: var(--ink-soft);
  transform: rotate(-4deg);
  opacity: 0.9;
  box-shadow: inset 0 0 0 1px var(--paper);
  white-space: nowrap;
}

.stamp--ok     { color: var(--color-success); }
.stamp--warn   { color: var(--color-warning); }
.stamp--urgent { color: var(--color-red); transform: rotate(-7deg); }
.stamp--due    { color: var(--accent); }
.stamp--paid   { color: var(--color-success); }

/* Paper filing card (obligations, etc.) */
.owe-card {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1em;
  border: 1px solid var(--rule);
  background: var(--paper-2);
  padding: 0.9em 1em;
  margin-bottom: 0.6em;
}

.owe-card .owe-body { min-width: 0; }
.owe-card .owe-actions { font-size: 0.85em; white-space: nowrap; }



/* Site footer: the legal pages, kept quiet but always reachable. Nothing is
   drawn above them — the space alone is the separation, so the page ends
   rather than being closed off. No auto side margins either: they would stop
   the footer stretching in the body's flex column, shrink-wrapping it around
   the two links and pulling them off centre. Full width, centred contents. */
#site-footer {
  margin: 3em 0 1.5em;
  padding-top: 1em;
  text-align: center;
  font-size: 0.85em;
}

#site-footer a {
  color: var(--color-text-light);
  text-decoration: none;
  margin: 0 0.75em;
}

#site-footer a:hover,
#site-footer .lang-switch button:hover {
  color: var(--color-text);
  text-decoration: underline;
}

/* The language switcher: a POST form, since it changes a saved setting, whose
   button is dressed as one more footer link. It names the other language in
   that language. */
#site-footer .lang-switch {
  display: inline;
}

#site-footer .lang-switch button {
  margin: 0 0.75em;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--color-text-light);
  cursor: pointer;
}

/* The home page's example journal, laid on the paper as a sheet of its own:
   the surface, edged with a rule — which, the surface and the page both
   being white by day, is what sets it off — and no shadow, since the
   palette is flat. It reaches an em out into the body's padding on each
   side, so the ledger inside keeps the width of the text around it. */
.home-sample {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 1.5em 1em 1em;
  margin: 0 -1em;
}

/* Receipts and obligations open and close, but nothing in the example leads
   anywhere: its links point at pages the visitor has no account for, and its
   spending rows have no transactions to open onto. */
.home-sample a,
.home-sample .cat-detail > summary {
  pointer-events: none;
}

/* ...and "Add an obligation", the one row that is nothing but a link, is left
   out of it. */
.home-sample [data-key="obligations"] > .ledger-row:last-child {
  display: none;
}

/* The spending arrows, red for more and green for less, sit centred astride
   the sheet's top edge: pulled down half their height over it, and the sheet
   opens with that much more room so they never cover the period's dates. */
.home-knobs {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: center;
  gap: 0.5em;
  margin-bottom: -1em;
}

.home-knobs button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2em;
  height: 2em;
  padding: 0;
  border: 0;
  border-radius: 3px;
  font: inherit;
  cursor: pointer;
}

.home-knobs .spend-more {
  background: var(--color-red);
  color: var(--on-error);
}

.home-knobs .spend-less {
  background: var(--color-green);
  color: var(--on-success);
}

.home-knobs button:hover {
  filter: brightness(1.1);
}

.home-knobs svg {
  width: 16px;
  height: 16px;
}

/* The home page's promise, set well above the site-wide h1: it is the first
   thing a visitor reads and the only headline the page has. */
.home-title {
  font-size: 2.2rem;
  line-height: 1.2;
}

/* The one-line pitch under it, given room on both sides so it reads as its
   own statement rather than a caption squeezed between title and example. */
.home-pitch {
  margin: 2em 0 0.75em;
}

.home-trust {
  margin: 0 0 3em;
}


/* ==========================================================================
   17. Touch — Apple's 44-point floor
   ========================================================================== */

/* Anything a finger can tap is at least 44 by 44 points, Apple's floor (a
   CSS pixel is a point on an iPhone). A mouse needs none of it, so only a
   coarse pointer pays, and the page a desktop sees does not move. The ledger's
   own rows and tools are in _reckoner_styles.html. */
@media (pointer: coarse) {
  /* At least Apple's default body size, 17pt, and more if the browser is
     set bigger. On the root, so what is sized in rem (buttons, fields)
     grows with it and the body's 100% follows. Every field stays at least
     16px, under which iOS Safari zooms the page in on focus, and the
     smallest text — the obligations' due stamps (.stamp, 0.72em, ~12px)
     and the badges (0.75rem, 12.75px) — is still over Apple's 11-point
     floor. */
  html { font-size: max(100%, 17px); }

  /* The nav keeps the ledger's beat, at least 44px on a touchscreen. */
  #main-nav { min-height: max(2.3em, 44px); align-items: center; }
  #main-nav .nav-left { align-items: center; }
  #main-nav a { display: inline-flex; align-items: center; min-height: 44px; }

  button,
  .btn,
  select,
  input:not([type="radio"]):not([type="checkbox"]):not([type="hidden"]) { min-height: 44px; }
  /* Taller, with the label still in the middle of it. */
  .btn { display: inline-flex; align-items: center; justify-content: center; }

  /* A radio or a checkbox is tapped through its label. */
  label:has(> input[type="radio"]),
  label:has(> input[type="checkbox"]) { display: flex; align-items: center; min-height: 44px; }

  #site-footer a,
  #site-footer .lang-switch button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    min-width: 44px;
  }

  .home-knobs button { width: 44px; height: 44px; }

  /* A link that is a paragraph of its own ("Forgot password?", a way back)
     answers 44px tall but takes no more room: the padding grows the box a
     finger hits, and the same margin taken back leaves its line where it
     was. CSS cannot tell such a paragraph from a sentence with one link in
     it, and this costs the sentence nothing either. */
  p > a:only-child:not(.btn) {
    display: inline-block;
    padding-block: 12px;
    margin-block: -12px;
  }

  /* A list of pages, one under the other, needs the room for real: hit areas
     stretched over each other would only split the same 24px between them. */
  .settings-menu a { display: inline-flex; align-items: center; min-height: 44px; }
}
