/* ==========================================================================
   brand.css - UPDATED 2026-10-02 (Postgres + Option A, phase 6 of 6) - NEW FILE.

   THE SINGLE PLACE THE LOOK OF THIS APP IS DEFINED.

   Why this file exists at all, and why the colours are NOT in config.ini:
   static/index.html is served straight off disk by GET / (a FileResponse),
   so it can never read config.ini - a browser gets the file, not a rendered
   template. Meanwhile GET /auth/activate, GET /auth/reset-password,
   GET /reference and GET /diagrams are built in Python and COULD read
   config.ini. Putting the palette in config.ini would therefore have given
   two sources of truth that drift apart the first time one is edited: the
   chat page green and the activation page green would stop matching.

   A stylesheet both sides link to is the one place that works for both:
     - static/index.html            <link> in its <head>
     - auth_pages.py                (activation / reset pages)
     - project_reference.py         PAGE_CSS consumers: /reference, /diagrams
   Change a value here once and all five screens follow. This is the same
   "one shared config drives everything" rule config.ini already follows for
   application settings - presentation simply has its own natural home.

   TEXT (product name, tagline, logo path and alt text) is different: it IS
   in config.ini under [branding], because Python needs it as strings and
   index.html picks the same values up from GET /auth/config. See
   config.ini's [branding] section.

   PALETTE SOURCE: read from the live https://www.andalusia.systems/ on
   2026-10-02 by reading the computed styles of the rendered page, not by
   eye:
     #0d652d  deep green  - headings, hero band, primary surfaces (57 uses)
     #ccebd6  pale green  - section tint
     #f6f7eb  cream       - alternate section background
     #fffc31  bright yellow - call-to-action buttons ONLY. Deliberately NOT
                             used here: in this app the accent colour is also
                             the focus-ring and link colour, and yellow on
                             white fails every contrast threshold for that.
                             If you ever want the site's yellow CTA look on
                             the Sign in button, add a --cta pair rather than
                             changing --accent.

   DARK MODE: #0d652d is a DARK green, so it cannot also serve as the accent
   on a dark background - it scores 2.4:1 against the dark surface, well
   under the 4.5:1 minimum. The dark theme therefore uses a lightened green
   of the same hue (#57c98a, 8.0:1) with a near-black green ink, exactly the
   pattern the original blue theme already used (#2b57c9 -> #6e93f0).
   ========================================================================== */

/* This stylesheet has to stand ON ITS OWN for the pages auth_pages.py
   builds: those load brand.css and nothing else. static/index.html and the
   /reference + /diagrams pages each already declare this, so it is a no-op
   there - but without it here, `.auth-card input { width: 100% }` plus the
   card's own padding made every field overflow the card's right edge on the
   activation and password-reset pages. Found by looking at the rendered
   page, not by reading the CSS. */
*, *::before, *::after { box-sizing: border-box; }

:root {
  /* Layout neutrals - unchanged from index.html's original palette. */
  /* UPDATED 2026-10-02 (green page background) - was #edf0f4, a neutral cool
     grey. His request: carry the Sign-In page's green across the whole app.
     NOT the Sign-In page's own #ccebd6, and the reason is measured rather
     than aesthetic: --muted text on #ccebd6 is 4.49:1, just under the 4.5:1
     AA minimum. Keycloak gets away with #ccebd6 because its muted text sits
     on a white card; in this app --muted sits directly on the page (the gate
     tagline, the form hints, /reference's lead paragraphs). #ddeee4 is the
     same hue, one step lighter, and clears AA on every text colour:
       --ink 13.46:1   --muted 4.77:1   --accent 5.97:1
       --note 5.27:1   --error 5.45:1
     It also separates white cards from the page BETTER than a lighter tint
     would (1.21:1 against #ffffff, versus 1.13:1 for #e9f4ee) - which matters
     most on /reference, where the page is almost entirely cards. */
  --bg: #ddeee4;
  --surface: #ffffff;
  /* UPDATED 2026-10-02 (green page background) - NEW. The background of a
     thing you TYPE INTO: the auth inputs and the chat composer.
     These used --bg, which was invisible as a problem while the page was a
     neutral grey, and became one the moment the page turned green: every text
     box would have turned green with it. One token was doing two jobs - the
     same shape of mistake as phase 6's page-wide `form { display: flex }`,
     which was correct until a second form appeared.
     White here, and in dark mode the OLD --bg value, so dark mode's recessed
     field look is preserved exactly rather than quietly changed. */
  --field: #ffffff;
  --ink: #18212d;
  --muted: #5b6778;
  --line: #d5dbe3;
  --code-bg: #f3f5f8;
  --error: #b42318;
  /* UPDATED 2026-10-02 (signup-form polish, round 2) - NEW. An informational
     note: something the reader must take in before filling a form, but not an
     error and not the brand accent. His request was specifically blue.
     This is the app's OWN former blue, the one the whole UI used before the
     Andalusia rebrand, so it is a colour this project already owned rather
     than a new one invented for one line. 6.35:1 on --surface - passes AA.
     NOTE for whoever re-runs phase 6's test suite: one of its 90 server
     checks asserted "no leftover blue #2b57c9/#6e93f0 anywhere", which was
     about leftovers from the rebrand. This is a deliberate reintroduction,
     so that check now needs to allow --note's definition. */
  --note: #2b57c9;

  /* Andalusia Systems brand. */
  --accent: #0d652d;        /* 7.1:1 on white - passes AA and AAA for text */
  --accent-ink: #ffffff;    /* 7.1:1 on --accent - text ON an accent button  */
  --accent-soft: #ccebd6;   /* pale green, for tinted panels and hovers      */

  /* Callout/warning colours, used by /reference and /diagrams. */
  --warn-bg: #fdf3e7;
  --warn-ink: #7a4a05;
  --warn-line: #eccb8f;

  /* Typography - UNCHANGED (his instruction: keep the existing font). The
     site itself uses Inter; this app stays on IBM Plex. */
  --sans: "IBM Plex Sans", "Segoe UI", system-ui, -apple-system, sans-serif;
  --mono: "IBM Plex Mono", Consolas, "SFMono-Regular", monospace;

  /* The logo's rendered height. Natural size is 226x70, so the width follows
     at the same 3.23:1 ratio and never has to be stated. */
  --logo-height: 30px;
}

@media (prefers-color-scheme: dark) {
  :root {
    /* UPDATED 2026-10-02 (green page background) - was #10151c, a neutral
       near-black. Tinted very slightly green so dark mode belongs to the same
       brand as the light theme. The shift is deliberately tiny: every text
       colour measures within 0.02 of its old ratio (--ink 15.32:1,
       --muted 7.18:1, --accent 8.85:1), so this is a hue change and not a
       legibility change. */
    --bg: #0f1613;
    --surface: #19202a;
    /* The old --bg value, kept exactly: dark fields stay darker than the
       card they sit on, which is what gave them their recessed look. */
    --field: #10151c;
    --ink: #e6ebf2;
    --muted: #97a3b4;
    --line: #2a3340;
    --code-bg: #121820;
    --error: #f97066;
    /* 5.54:1 on --surface - passes AA. Same pairing the old theme used. */
    --note: #6e93f0;

    --accent: #57c98a;      /* same hue as #0d652d, lightened: 8.0:1 on --surface */
    --accent-ink: #07160d;  /* 9.0:1 on --accent */
    --accent-soft: #15301f;

    --warn-bg: #2a2114;
    --warn-ink: #e8c288;
    --warn-line: #5c4620;
  }
}

/* ==========================================================================
   The brand bar: logo top-left, on every page.
   Used by index.html's <header>, auth_pages.py's pages, and the /reference
   and /diagrams headers.
   ========================================================================== */

.brand-logo {
  height: var(--logo-height);
  width: auto;
  display: block;
  flex: none;
}

/* The logo is a transparent PNG whose wordmark is bright green, so it reads
   correctly on both the light and the dark surface with no filter applied -
   nothing to do per theme.

   .brand-link is the anchor around it. Without these two rules a MISSING
   image file falls back to the browser's broken-image box plus the alt text
   styled as a link: blue and underlined. That is not hypothetical - the PNG
   is not in Git, so any copy of this project that has not had it downloaded
   into static/ yet will render exactly that, including a Kubernetes image
   built before the file was added. Styled this way it degrades to a plain
   wordmark instead. */
.brand-link { text-decoration: none; color: var(--ink); font-weight: 600; }
.brand-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.brand-mark {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  min-width: 0;
}

/* The chat page's header is already busy (sign-in status, two buttons and
   the tool picker), so the brand text has to give way rather than squeeze
   everything else. It is allowed to wrap - an earlier attempt at
   white-space: nowrap + ellipsis truncated the product name to
   "Andalusia Sy..." at 1180px wide, which looks like a bug rather than a
   design. The logo itself already carries the company name, so hiding the
   text on a narrow window loses nothing. */
.brand-mark .brand-text { min-width: 0; }
.brand-mark .brand-text h1 {
  font-size: 1rem;
  font-weight: 600;
  margin: 0;
  color: var(--ink);
  line-height: 1.3;
}
.brand-mark .brand-text p {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--muted);
  line-height: 1.3;
}

@media (max-width: 1100px) {
  /* Logo only - it is the wordmark, so nothing is actually lost. */
  body > header .brand-mark .brand-text { display: none; }
}

/* ==========================================================================
   Shared form styling for the standalone pages built in Python
   (auth_pages.py) AND the two in-page panels in index.html, so the signup
   form on the chat page and the reset form that arrives from an email look
   like one product rather than two.
   ========================================================================== */

.auth-card {
  /* Stated explicitly so the card keeps its block layout wherever it is
     used: static/index.html styles its composer form, and a page-wide
     `form { display: flex }` would otherwise lay these fields out in a row.
     A class selector wins over an element selector, so this holds
     regardless of which stylesheet is linked last. */
  display: block;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 1.6rem 1.5rem;
  max-width: 26rem;
  width: 100%;
  box-shadow: 0 1px 2px rgba(16, 24, 40, 0.04), 0 8px 24px rgba(16, 24, 40, 0.06);
}

.auth-card h2 {
  margin: 0 0 0.3rem;
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--ink);
}

.auth-card .sub {
  margin: 0 0 1.1rem;
  font-size: 0.875rem;
  color: var(--muted);
  line-height: 1.5;
}

/* UPDATED 2026-10-02 (signup-form polish): a .sub that states RULES rather
   than describing the panel, so the username rule and the password length
   read as requirements instead of small print. Used by #signup-hint in
   static/index.html.
   UPDATED 2026-10-02 (round 2): this was the --error red for one round; he
   asked for BLUE, so it now uses --note (see the token at the top of this
   file). The red is still what marks the required FIELDS - so the panel now
   says two different things with two colours: blue "read this", red "you
   must fill this in", which is the more useful split. */
.auth-card .sub.required-note {
  color: var(--note);
}

.auth-card label {
  display: block;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--ink);
  margin: 0.85rem 0 0.3rem;
}

.auth-card label .optional {
  font-weight: 400;
  color: var(--muted);
}

/* UPDATED 2026-10-02 (signup-form polish): NEW - the asterisk that marks a
   required field, e.g. *Email. His request. Same --error red as the hint
   above, so "red = you must" is one idea on the panel and not two.
   The asterisk carries aria-hidden="true" in the markup because the input's
   own `required` attribute is what a screen reader announces - a spoken
   "star" would be noise, and leaving `required` off to "explain" it in text
   would lose the browser's built-in empty-submit block (tested in phase 6).
   The two NAME asterisks are toggled by markRequiredNames() from what
   GET /auth/config reports, exactly like the (optional) hints they replace,
   so config.ini [signup] require_name = false still relaxes the whole form
   rather than leaving a red star on an optional box. */
.auth-card label .req {
  color: var(--error);
  font-weight: 700;
  margin-right: 0.15rem;
}

.auth-card input[type="email"],
.auth-card input[type="password"],
.auth-card input[type="text"] {
  width: 100%;
  font: inherit;
  font-size: 0.9375rem;
  color: var(--ink);
  /* UPDATED 2026-10-02 (green page background): --bg -> --field. See the
     --field note at the top of this file: these boxes followed the page
     colour only because the two happened to share a value. */
  background: var(--field);
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 0.55rem 0.7rem;
}

.auth-card input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.auth-card .row2 { display: flex; gap: 0.6rem; }
.auth-card .row2 > div { flex: 1; min-width: 0; }

.btn-primary {
  width: 100%;
  margin-top: 1.1rem;
  background: var(--accent);
  color: var(--accent-ink);
  border: none;
  border-radius: 9px;
  padding: 0.65rem 1rem;
  font: inherit;
  font-weight: 500;
  cursor: pointer;
}
.btn-primary:hover { filter: brightness(1.08); }
.btn-primary:disabled { opacity: 0.55; cursor: not-allowed; filter: none; }
.btn-primary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.btn-link {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: 0.875rem;
  color: var(--accent);
  cursor: pointer;
  text-decoration: underline;
}
.btn-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The one line every form uses to report what the SERVER said. Never
   client-invented text: see index.html's submitSignup()/submitForgot() and
   the account-enumeration note there. */
.auth-msg {
  margin: 0.9rem 0 0;
  font-size: 0.875rem;
  line-height: 1.5;
  padding: 0.6rem 0.75rem;
  border-radius: 9px;
  display: none;
}
.auth-msg.show { display: block; }
/* UPDATED 2026-10-02 (signup-form polish): the success text itself is now
   the brand green (--accent) instead of --ink, at his request. The pale-green
   panel and green border were already here; only the words changed colour.
   Measured: #0d652d on #ccebd6 = 5.63:1 (light), #57c98a on #15301f = 6.87:1
   (dark) - both pass AA. NOTE this styling is shared: the forgot-password
   reply and the transient "Working…" line also use .ok, so they turn green
   too. That is consistent rather than accidental, but it is a real
   consequence of the change and easy to reverse by splitting the class. */
.auth-msg.ok { background: var(--accent-soft); color: var(--accent); font-weight: 600; border: 1px solid var(--accent); }
.auth-msg.bad { background: var(--warn-bg); color: var(--warn-ink); border: 1px solid var(--warn-line); }
/* UPDATED 2026-10-02 (signup-form polish): NEW - a message placed at the TOP
   of a card rather than under its button. .auth-msg's margin is top-only
   (0.9rem 0 0), which is right below a button and wrong above a heading, so
   this flips it to bottom-only. His request: the signup reply must appear
   above "Create an account", where it cannot be missed on a long form. */
.auth-msg.at-top {
  margin: 0 0 1.1rem;
}

.auth-foot {
  margin: 1.1rem 0 0;
  padding-top: 0.9rem;
  border-top: 1px solid var(--line);
  font-size: 0.875rem;
  color: var(--muted);
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
  justify-content: space-between;
}
.auth-foot a { color: var(--accent); }

/* ==========================================================================
   Standalone page frame - ONLY used by auth_pages.py (the activation and
   password-reset pages a person reaches from an email). index.html and the
   /reference and /diagrams pages bring their own layout and just use the
   tokens and the brand bar above.
   ========================================================================== */

body.auth-page {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.55 var(--sans);
  display: flex;
  flex-direction: column;
}

body.auth-page > header {
  display: flex;
  align-items: center;
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}

body.auth-page > main {
  flex: 1;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 3rem 1.25rem;
}

body.auth-page .result-icon {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.35rem;
  margin: 0 0 0.9rem;
  background: var(--accent-soft);
  color: var(--accent);
  border: 1px solid var(--accent);
}
body.auth-page .result-icon.bad {
  background: var(--warn-bg);
  color: var(--warn-ink);
  border-color: var(--warn-line);
}

@media (max-width: 560px) {
  body.auth-page > main { padding: 1.75rem 1rem; }
  .auth-card { padding: 1.25rem 1.1rem; }
  .auth-card .row2 { display: block; }
}