/* ---------------------------------------------------------------------------
   Shared foundation: the typeface, the palette, the reset. Every page links
   this first; page stylesheets only add what is theirs.

   This is the one place the brand lives. Change --primary here and the table,
   the dashboard and everything after it move together.
   --------------------------------------------------------------------------- */
@font-face {
  font-family: "Chakra Petch";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/chakra-petch-400.woff2") format("woff2");
}

@font-face {
  font-family: "Chakra Petch";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/chakra-petch-600.woff2") format("woff2");
}

@font-face {
  font-family: "Chakra Petch";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/chakra-petch-700.woff2") format("woff2");
}

:root {
  --primary: #069494;

  --bg: #000000;              /* the page behind everything */
  --fg: #e9ecf1;
  --muted: #8b93a1;

  --surface: #0b0e14;         /* anything raised off the background */
  --surface-2: #131923;       /* raised again: controls, hover */
  --edge: #39424f;            /* every border on the site */

  /* Roles that used to be written as literals at their call sites. They exist
     so a theme can move them: a hairline that reads as a divider on black has
     to be darker than the page on white, and teal that passes as body text on
     one ground fails on the other. */
  --primary-ink: var(--primary);   /* --primary used as *text* */
  --on-primary: #04211f;           /* text on a --primary fill */
  --hairline: rgba(57, 66, 79, .45);   /* dividers inside a surface */
  --accent-wash: rgba(6, 148, 148, .07);  /* "this row is yours" */
  --hover-wash: rgba(255, 255, 255, .06); /* nav and control hover */
  --danger: #e0576b;               /* a negative number, a failed sign-in */
  --warn: #e0b83a;                 /* not wrong, not right */
  /* Four-colour deck. Spades take the text colour so they read as ink
     rather than as a fourth hue competing with the other three. */
  --suit-s: var(--fg);
  --suit-h: #f0576b;
  --suit-d: #4aa3e8;
  --suit-c: #35b46f;

  /* A card face, and the ink on it. Deliberately the same in both themes — a
     playing card is a light rectangle with dark ink on it, and making that
     follow the OS setting would make it stop looking like one. */
  --card-face: #f3f5f8;
  --card-edge: #b9c2cd;
  --card-s: #12181f;
  --card-h: #c0223a;
  --card-d: #1360a8;
  --card-c: #157a49;

  --font: "Chakra Petch", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* Native widgets, scrollbars and form controls follow the theme too. */
  color-scheme: dark;
}

/* Light mode.
   Dark is the default and stays on bare `:root` deliberately: **the table view
   is dark in both themes** — it is a fixed-aspect object with a felt gradient,
   card art and chip images, and it never sets `data-theme`, so it simply never
   reaches this block. Which also means light mode cannot be applied by a media
   query here; the pre-paint script in `base.html` reads the OS preference and
   sets the attribute, so only pages that opt in can turn light. */
html[data-theme="light"] {
  --bg: #eef1f5;
  --fg: #101720;
  --muted: #5a6472;

  --surface: #ffffff;
  --surface-2: #f2f5f8;
  --edge: #d2d9e1;

  /* Full-strength teal is only ~3.5:1 on white, which is fine for a fill and
     thin for small text — so text gets a darker cut of the same hue and the
     brand colour itself is left alone. */
  --primary-ink: #046b6b;
  --on-primary: #ffffff;
  --hairline: rgba(16, 23, 32, .1);
  --accent-wash: rgba(6, 148, 148, .08);
  --hover-wash: rgba(16, 23, 32, .05);
  --danger: #c3283f;
  --warn: #a1730a;
  --suit-s: var(--fg);
  --suit-h: #c3283f;
  --suit-d: #1668b0;
  --suit-c: #17804d;

  color-scheme: light;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
}

/* ---------------------------------------------------------------------------
   Full-page loader — ported from the shell in ../ECI_NEXUS_v2
   (`templates/base.html`): a fixed curtain in the page colour with the square
   brand mark turning slowly in the middle, faded out and removed once the page
   is actually ready.

   The original inlined this in <head> to have it before first paint. It lives
   here instead because base.css is a render-blocking <link> on every page —
   applied before first paint already, which is the only thing inlining bought.
   And because the curtain is `var(--bg)`, one rule covers both themes where
   the original needed two.
   --------------------------------------------------------------------------- */
#page-loader {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: grid;
  place-items: center;
  background: var(--bg);
}

#page-loader img {
  width: 44px;
  height: 44px;
  animation: page-loader-spin 2.5s linear infinite;
}

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

/* The brand mark is a pure-white cut-out, so it needs a dark ground — on the
   light theme's curtain it would be invisible. Inverting a pure-white alpha
   mask gives a pure-black one, which is exactly the mark in reverse, so this
   costs no second asset. It would be wrong for a mark with colour in it. */
html[data-theme="light"] #page-loader img { filter: invert(1); }

#page-loader.is-going {
  opacity: 0;
  transition: opacity .4s ease;
}

/* The spin is the feedback, not decoration, so it stays — only the fade goes.
   `dismissLoader()` removes the node on a timer as well as on transitionend,
   which is what stops the curtain sticking when there is no transition to end. */
@media (prefers-reduced-motion: reduce) {
  #page-loader.is-going { transition: none; }
}
