/* ==========================================================================
   DARK MODE — the second axis. Opt-in, off by default.
   ==========================================================================

   Two independent choices, not four themes:

       data-skin  = classic | advanced   (flat, or soft-extruded)
       data-mode  = light   | dark

   They compose. Dark is a palette; the skin is a surface treatment. This file
   only redefines colour tokens, so it works under either skin, and the
   advanced skin only has to say how a shadow behaves in the dark (the block
   at the bottom). That is why there are three stylesheets rather than four.

   WHAT MADE THIS POSSIBLE. Until 2026-09-21 a card's colour was the literal
   string `#fff`, written out in 99 places across portal.css, draw.css and
   three pages' inline styles. No token could reach them, so no dark mode
   could exist. Those are now --surface and the --chip-* pairs, with their
   light values in style.css unchanged from the hexes they replaced — light
   mode did not shift a pixel when they moved. This file is the only place
   that gives them different values.

   WHAT DARK MODE IS NOT. It is not the light palette inverted. Pure white
   text on pure black is what people mean when they say dark mode hurts their
   eyes: the contrast is so high the letters bloom. The ink here is #eef2ec
   on #141a15, which is 13.7:1 — well past AA, well short of the 21:1 that
   causes halation. The greens and reds are also LIGHTENED, not reused: the
   light theme's --ok (#276a2a) on a dark card measures about 1.5:1, which is
   not a dim green, it is an invisible one.

   scripts/test-mode-dark.mjs measures every pair here, in both skins.
   ========================================================================== */

html[data-mode="dark"] {
  color-scheme: dark; /* so the browser's own scrollbars and form chrome follow */

  /* ---- the page and what sits on it ---------------------------------- */
  --bg: #10150f;         /* the room: a green-black, not a neutral one */
  --bg-alt: #171d18;     /* the tinted band in a table */
  --surface: #262f27;    /* a raised card, a table, an input */
  --card-bone: #262f27;  /* the flat theme's "bone" card — same thing here */
  --surface-edit: #332f1c; /* a price cell somebody typed over: warm, not white */
  --cost-tint: #2b332c;  /* the wash behind internal-only cost cells */

  /* The forest bar has to stay distinguishable from a page that is now also
     dark green. Lifted a little rather than darkened — a header darker than
     the page reads as a hole. */
  --brand: #22342a;
  --brand-soft: #2d483b;
  /* EVERY LINK IN DARK MODE WAS 1.3:1, on both looks, and had been since dark
     shipped. `a { color: var(--brand-soft) }` and dark never lifted pine — so
     a customer's name in the results table was dark green on a dark card: not
     dim, unreadable. It measured 1.29:1 on Original and 1.36:1 on Advanced.
     Found while compositing the real background behind that link (the row is a
     2.4%-white stripe over a card over the page, so reading any single layer's
     computed style answers the wrong question). Pine, lifted until it clears:
     6.6:1 on a striped row, 8.4:1 on the page. */
  --link: #8ec79c;
  --brand-deep: #132018; /* still the ink ON amber, so it does not move */
  --on-brand: #e8efe9;
  --border-ondark: rgba(255, 255, 255, 0.10);
  --highlight-ondark: rgba(255, 255, 255, 0.05);

  --line: #333d34;   /* a divider between rows — quiet on purpose */
  --edge: #737f74;   /* the EDGE OF A CONTROL — 3.30:1, see the block below */

  /* ---- text ----------------------------------------------------------- */
  --ink: #eef2ec;    /* 12.2:1 on a card. Not #fff: see the note above. */
  --body: #cbd3c9;
  --muted: #a4aea3;  /* 6.0:1 on a card, 7.7:1 on the page */

  /* ---- the colours that carry meaning ---------------------------------
     Every one of these is LIGHTER than its light-mode value. They are read
     as text on a dark surface, and the light-theme versions are all roughly
     1.5:1 there — the failure mode is not "dim", it is "gone". */
  --accent: #d99e2b;      /* still a SURFACE: the amber button keeps dark text */
  --accent-hover: #e8ad3d;
  --accent-ink: #e8b544;  /* amber as a LETTER: 8.22:1 on a card */
  --ok: #7fc98a;
  --leaf: #7cc06a;
  --leaf-hover: #8fcd7e;
  --warn: #e0b661;
  --danger: #f08a8a;

  /* Chips: a dark tint with a light ink, each pair measured together. */
  --chip-ok-bg: #1f3a24;   --chip-ok-ink: #8fd69a;
  --chip-warn-bg: #3a2e14; --chip-warn-ink: #e8be5c;
  --chip-bad-bg: #3d1f1f;  --chip-bad-ink: #f3a0a0;
  --chip-info-bg: #262046; --chip-info-ink: #b9aef0;

  /* The soft tints, inverted. Every one of these was a pale wash with dark
     ink on it; in the dark it becomes a deep wash with light ink, each pair
     measured together in test-mode-dark.mjs. Leaving any of them alone would
     put a lit rectangle on an otherwise dark screen — which is precisely the
     thing that makes a half-done dark mode worse than none. */
  --tint-amber-bg: #3a2e14;  --tint-amber-ink: #e8be5c;  --tint-amber-ink2: #dcb457;
  --tint-red-bg: #3d2320;    --tint-red-ink: #f0a293;
  --tint-red2-bg: #3d2420;   --tint-red2-ink: #f0a596;
  --tint-orange-bg: #3d2a1a; --tint-orange-ink: #e8a765;
  --tint-rose-bg: #382a2a;   --tint-rose-ink: #dfb3b3;
  --tint-sand-bg: #2e2c26;   --tint-sand-ink: #cfc8b4;
  --tint-mat-bg: #3a3120;    --tint-mat-ink: #e0cb92;
  --wash-danger: #3d2020;    --wash-danger-edge: #6b3a3a;
  --notice-bg: #382d18; --notice-ink: #e6c583; --notice-line: #6a5730;
  --note-amber-bg: #352c18;
  --panel-soft: #2a322b;
  --tint-green-bg: #1d3320;  --tint-green-ink: #8ed39a;
  --tint-green2-bg: #1c3524; --tint-green2-ink: #86d1a0;
  --tint-sage-bg: #22322a;   --tint-sage-ink: #a9d3b3; --tint-sage-line: #4e6a56;
  --tint-grey-bg: #2b2f2c;   --tint-grey-ink: #c2c8c3;
  --tint-ash-bg: #2c2e2e;    --tint-ash-ink: #c4c8c6;
  --tint-lilac-bg: #262640;  --tint-lilac-ink: #b6b6da;
  --tint-parch-bg: #2f2c22;  --tint-parch-ink: #d5cdb6; --tint-parch-line: #565040;
  --tint-parch2-bg: #2f2c22;
  --tint-work-bg: #1e3a27;   --tint-work-ink: #9ad2a8;
  --check-a: #3a423b; --check-b: #262d27;
  /* Warm bone, so the logo sits on roughly the ground it was drawn for. */
  --logo-plate: #f2efe6;
  --logo-plate-pad: 0.6rem 0.9rem;
  --art-ink: #9fb3a6;

  /* A shadow does almost nothing on a dark ground — there is no light for it
     to take away. Depth in the dark comes from the surface being lighter than
     the page, so the shadows shrink to a hairline that just stops a card's
     edge from vanishing. */
  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.5);
  --shadow-2: 0 8px 20px rgba(0, 0, 0, 0.45);
  --shadow-3: 0 18px 40px rgba(0, 0, 0, 0.55);
}

/* ==========================================================================
   CONTROLS need a brighter edge than a divider does.
   --line is a row separator and is quiet by design; at 1.37:1 it is nowhere
   near the 3:1 the boundary of a control has to clear. So every control gets
   --edge instead. Without this block a dark input is a dark rectangle on a
   dark card with nothing to say where it starts.
   ========================================================================== */
html[data-mode="dark"] input[type="text"],
html[data-mode="dark"] input[type="search"],
html[data-mode="dark"] input[type="email"],
html[data-mode="dark"] input[type="tel"],
html[data-mode="dark"] input[type="number"],
html[data-mode="dark"] input[type="password"],
html[data-mode="dark"] input[type="time"],
html[data-mode="dark"] input[type="date"],
html[data-mode="dark"] textarea,
html[data-mode="dark"] select,
html[data-mode="dark"] .btn-sm,
html[data-mode="dark"] .hist-filters button,
html[data-mode="dark"] .app-side-foot button,
html[data-mode="dark"] .pin-buttons button,
html[data-mode="dark"] .q-zoom-bar button,
html[data-mode="dark"] .details-btn {
  border-color: var(--edge);
  color: var(--ink);
}

/* An image has its own colours and does not get to keep a white mat in the
   dark; a photo of a yard floating on a white card is the one thing that
   ruins a dark screen at night. */
html[data-mode="dark"] .q-photos.one .q-photo img { background: var(--bg-alt); }

/* Checkboxes, radios, date pickers and the like are painted by the browser.
   accent-color plus the color-scheme above is what stops them rendering as
   light-mode widgets punched into a dark page. */
html[data-mode="dark"] input[type="checkbox"],
html[data-mode="dark"] input[type="radio"],
html[data-mode="dark"] input[type="range"] { accent-color: var(--accent); }

/* The zebra band on a table is a light-mode trick: darkening alternate rows
   on an already-dark card just makes them look broken. Lighten instead. */
html[data-mode="dark"] .data-table tbody tr:nth-child(even) {
  background: rgba(255, 255, 255, 0.025);
}

/* ==========================================================================
   DARK + ADVANCED — where the two axes actually have to talk to each other.

   Neumorphism in the dark is not the light formula with darker colours. The
   highlight is the whole effect, and a highlight has to be LIGHTER than the
   surface it sits on, so in the dark it is a lifted grey rather than white.
   Everything else — the real control borders, the solid amber primary, the
   contrast floors — carries over from skin-advanced.css unchanged.
   ========================================================================== */
html[data-mode="dark"][data-skin="advanced"] {
  /* The same recipe as the light skin, derived the same way from a dark base
     (2026-09-22). --nm-dark is the base darkened, --nm-light is it LIFTED
     rather than pushed to white — in the dark the highlight is a raised grey,
     because a white highlight on a near-black card is a glare, not a lit edge.
     Everything structural above — carved calendar grid, inset budget tracks,
     segmented controls, flat table rows, real control borders, solid amber
     primary — is written against these tokens and carries over untouched. */
  /* RELIEF IN THE DARK, chosen the same way and derived the same way: the
     ground drops, surfaces come up, and depth is a crisp lip plus three thin
     shadows rather than one wide glow.

     THE BEVEL IS THE PART THAT CHANGES. In the light skin it is a near-white
     line; here a near-white line at any real strength IS the glow, on a ground
     with nothing to absorb it. So it is white at 7% — just enough to say
     "this edge turns toward the light" and not enough to shine. The shadows
     go the other way: on a dark ground they can be near-black and still read
     as shadow rather than as ink. */
  --nm-page: #1b211c;
  --nm-base: #262f27;
  --nm-face: linear-gradient(#2a332b, #232b24);
  --nm-sunk: linear-gradient(#161b17, #1c221d);

  --nm-light: #313c32;
  --nm-dark: #0d110d;

  --nm-rim: #39443a;
  --nm-edge: #8a9689;   /* 4.23:1 on the lightest dark surface */

  --bg: var(--nm-page);
  --bg-alt: #202821;
  --card-bone: var(--nm-base);
  --surface: var(--nm-base);
  --line: #39443a;

  /* THE FIGURES' COST COLOURS, CHOSEN FOR THE DARK — not the light three
     lightened. A dark palette is its own set or it is a set that fails: each
     of these was validated against THIS base (#232b24) for the dark lightness
     band, the chroma floor, protanopia and deuteranopia separation, the
     normal-vision floor and 3:1 on the surface. Worst touching pair 16.3
     (deutan), 18.7 normal. css/figures.css holds the light three and the
     reason the order never changes. */
  --nm-slot-a: #3f9c68;   /* labour */
  --nm-slot-b: #5c85cc;   /* materials */
  --nm-slot-c: #bb8a22;   /* overhead */
}


/* ==========================================================================
   THE ESCAPE HATCHES, again.
   ========================================================================== */

/* Asked their OS for more contrast: give the ink and the edges more room.
   This deliberately goes past the "no halation" reasoning above — somebody
   who has set this preference has said which side of that trade they want. */
@media (prefers-contrast: more) {
  html[data-mode="dark"] {
    --ink: #ffffff;
    --body: #e6ece4;
    --muted: #c3ccc1;
    --line: #5a675b;
    --edge: #9aa79b;
  }
}

/* Paper is white whatever the screen is doing. A contract printed out of dark
   mode should not arrive as a black rectangle. */
@media print {
  html[data-mode="dark"] {
    --bg: #fff; --bg-alt: #fff; --surface: #fff; --card-bone: #fff;
    --surface-edit: #fffdf5; --cost-tint: #f3f0e6;
    --ink: #1c211d; --body: #565e57; --muted: #5f675f;
    --line: #e4e1d8; --edge: #7d7866;
    --ok: #276a2a; --danger: #a32020; --accent-ink: #8d6206; --warn: #b8860b;
    --chip-ok-bg: #dff0d8;   --chip-ok-ink: #2f6b2f;
    --chip-warn-bg: #fbe8c8; --chip-warn-ink: #8a5a12;
    --chip-bad-bg: #f7d3d3;  --chip-bad-ink: #a12727;
    --chip-info-bg: #e4e0f5; --chip-info-ink: #4b3d8f;
    --shadow-1: none; --shadow-2: none; --shadow-3: none;
  }
}
