/* Ultimate Naturabuy — the design system, from the 2026 brandbook.
 *
 * Three colour families, because the brand has three:
 *   generic  browns  — the brand speaking as itself
 *   chasse   greens  — hunting
 *   peche    blues   — fishing
 *
 * An app picks one with THEME and everything follows. The hex values are the
 * brandbook's own; do not invent new ones — the book gives Pantone, CMYK, RGB
 * and RAL for each, and a fourth value that only exists in CSS would be the one
 * that is wrong on a printed poster.
 *
 * Public Sans is the brand typeface. It is served from static/fonts as a
 * @font-face rather than from Google's CDN: these apps sit behind an
 * authenticating ingress, and a webfont request that leaves the network leaks
 * which app an authenticated user is looking at.
 */

:root {
  /* Générique — brown. The default. */
  --generic-deep:  #281e1e;
  --generic-mid:   #3c3228;
  --generic-light: #bdbaad;

  /* Chasse — green. */
  --chasse-deep:   #002B1B;
  --chasse-mid:    #183f33;
  --chasse-light:  #a3c4ae;

  /* Pêche — blue. */
  --peche-deep:    #0D2140;
  --peche-mid:     #1f314e;
  --peche-light:   #b1cddd;

  /* Semantic colours are separate from the brand families on purpose: "this
   * failed" must not change meaning because an app switched theme. */
  --ok:    #1f7a4d;
  --warn:  #9a6b12;
  --bad:   #a03027;

  /* Spacing and radius, on a scale rather than ad hoc. */
  --s1: .25rem; --s2: .5rem; --s3: .75rem; --s4: 1rem;
  --s5: 1.5rem; --s6: 2rem; --s7: 3rem;
  --r:  10px; --r-sm: 6px; --r-pill: 999px;
}

/* The theme maps a family onto roles. Every component below reads the roles,
 * never a family directly — which is what makes a theme a one-line change. */
:root, [data-theme="generic"] {
  --deep: var(--generic-deep);  --mid: var(--generic-mid);
  --tint: var(--generic-light);
  --paper: #faf9f7;  --surface: #ffffff;  --line: #e5e1da;
  --ink: var(--generic-deep);  --ink-soft: #6b6156;
  --accent: var(--generic-mid); --accent-ink: #ffffff;
}
[data-theme="chasse"] {
  --deep: var(--chasse-deep);   --mid: var(--chasse-mid);
  --tint: var(--chasse-light);
  --paper: #f7faf8;  --surface: #ffffff;  --line: #dee8e1;
  --ink: var(--chasse-deep);   --ink-soft: #4a5f55;
  --accent: var(--chasse-mid);  --accent-ink: #ffffff;
}
[data-theme="peche"] {
  --deep: var(--peche-deep);    --mid: var(--peche-mid);
  --tint: var(--peche-light);
  --paper: #f7f9fb;  --surface: #ffffff;  --line: #dde5ec;
  --ink: var(--peche-deep);    --ink-soft: #4a5768;
  --accent: var(--peche-mid);   --accent-ink: #ffffff;
}

/* Dark: the deep brand colour becomes the ground and the light tint becomes the
 * ink, so the palette stays the brand's rather than becoming grey. Handles all
 * three viewer states — explicit light, explicit dark, and the default where
 * only prefers-color-scheme speaks. */
@media (prefers-color-scheme: dark) {
  :root:not([data-mode="light"]) {
    --paper: var(--deep);
    --surface: color-mix(in srgb, var(--deep) 88%, white);
    --line: color-mix(in srgb, var(--deep) 72%, white);
    --ink: #f4f2ee;
    --ink-soft: var(--tint);
    --accent: var(--tint);
    --accent-ink: var(--deep);
  }
}
[data-mode="dark"] {
  --paper: var(--deep);
  --surface: color-mix(in srgb, var(--deep) 88%, white);
  --line: color-mix(in srgb, var(--deep) 72%, white);
  --ink: #f4f2ee;
  --ink-soft: var(--tint);
  --accent: var(--tint);
  --accent-ink: var(--deep);
}

/* ── Type ─────────────────────────────────────────────────────────────────── */
@font-face {
  font-family: "Public Sans";
  /* The variable TTF straight from Google Fonts' OFL release, served from here
   * rather than from their CDN. It is ~100 KB and compresses again over the
   * wire; a woff2 would be smaller, so if you have woff2_compress to hand,
   * convert it and add the url() above this one. */
  src: url("/static/fonts/PublicSans-Variable.ttf") format("truetype-variations");
  font-weight: 100 900;
  font-display: swap;
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: "Public Sans", system-ui, -apple-system, "Segoe UI", Arial, sans-serif;
  font-size: 16px; line-height: 1.55;
  font-variant-numeric: tabular-nums;
}
h1, h2, h3 { margin: 0 0 var(--s2); line-height: 1.2; letter-spacing: -.015em;
             font-weight: 620; text-wrap: balance; }
h1 { font-size: clamp(1.5rem, 3.2vw, 2rem); }
h2 { font-size: 1.15rem; }
h3 { font-size: 1rem; }
p  { margin: 0 0 var(--s4); max-width: 68ch; }
a  { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
code, .mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .88em; }
.muted { color: var(--ink-soft); }
.small { font-size: .85rem; }
.eyebrow { font-size: .7rem; letter-spacing: .12em; text-transform: uppercase;
           color: var(--ink-soft); font-weight: 600; }

/* ── Chrome ───────────────────────────────────────────────────────────────── */
.topbar {
  background: var(--deep); color: #fff;
  padding: var(--s3) var(--s4);
  display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap;
}
.topbar a { color: #fff; text-decoration: none; opacity: .82; font-size: .92rem; }
.topbar a:hover, .topbar a.on { opacity: 1; }
.topbar .brand { font-weight: 700; letter-spacing: -.01em; opacity: 1; }
.topbar .spacer { margin-left: auto; }
.shell { max-width: 72rem; margin: 0 auto; padding: var(--s5) var(--s4) var(--s7); }

/* ── Components ───────────────────────────────────────────────────────────── */
.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); padding: var(--s4);
}
.stack { display: flex; flex-direction: column; gap: var(--s3); }
.row   { display: flex; gap: var(--s3); align-items: center; flex-wrap: wrap; }
.grid  { display: grid; gap: var(--s3);
         grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr)); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: 44px; padding: var(--s2) var(--s4);
  background: var(--accent); color: var(--accent-ink);
  border: 1px solid transparent; border-radius: var(--r-sm);
  font: inherit; font-weight: 600; font-size: .95rem;
  cursor: pointer; text-decoration: none;
}
.btn:hover { filter: brightness(1.08); }
.btn.ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn.wide  { width: 100%; }
.btn[disabled] { opacity: .5; cursor: default; }

label { display: block; font-size: .85rem; color: var(--ink-soft);
        margin-bottom: var(--s1); font-weight: 500; }
input[type=text], input[type=email], input[type=password], input[type=number],
select, textarea {
  width: 100%; min-height: 44px; padding: var(--s2) var(--s3);
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  /* 16px so iOS does not zoom the page on focus. */
  font: inherit; font-size: 16px;
}
input:focus-visible, select:focus-visible, textarea:focus-visible, .btn:focus-visible,
a:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
/* The login code: wide, spaced, and big enough to read back while typing. */
.code-input {
  font-family: ui-monospace, Menlo, monospace;
  font-size: 1.6rem; letter-spacing: .35em; text-align: center;
  padding: var(--s3); min-height: 56px;
}

.pill { display: inline-block; font-size: .72rem; padding: .12rem .5rem;
        border-radius: var(--r-pill); border: 1px solid var(--line);
        color: var(--ink-soft); }
.pill.ok   { color: var(--ok);   border-color: color-mix(in srgb, var(--ok) 40%, transparent); }
.pill.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
.pill.bad  { color: var(--bad);  border-color: color-mix(in srgb, var(--bad) 40%, transparent); }

.flash { padding: var(--s3) var(--s4); border-radius: var(--r-sm);
         border-left: 3px solid var(--accent); background: var(--surface);
         margin-bottom: var(--s3); font-size: .92rem; }
.flash.error { border-left-color: var(--bad); }
.flash.ok    { border-left-color: var(--ok); }

/* A standing banner, not a flash. A flash says what just happened and goes away
 * on the next request; a banner says something true about the whole app, so it
 * is rendered by base.html rather than by get_flashed_messages() and there is
 * nothing to dismiss.
 *
 * The tone is a semantic colour rather than a brand one, and for the reason
 * those exist at all: "not finished yet" must not change meaning because an app
 * switched theme. Modifier classes, like .pill and .flash above. */
.banner {
  padding: var(--s2) var(--s4);
  display: flex; flex-wrap: wrap; gap: var(--s2);
  align-items: baseline; justify-content: center; text-align: center;
  font-size: .88rem;
}
.banner b { font-weight: 650; }
.banner.warn { background: color-mix(in srgb, var(--warn) 14%, var(--surface));
               border-bottom: 1px solid color-mix(in srgb, var(--warn) 45%, transparent); }
.banner.ok   { background: color-mix(in srgb, var(--ok) 12%, var(--surface));
               border-bottom: 1px solid color-mix(in srgb, var(--ok) 40%, transparent); }

.scroller { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table { border-collapse: collapse; width: 100%; font-size: .9rem; }
th, td { text-align: left; padding: var(--s2) var(--s3);
         border-bottom: 1px solid var(--line); }
th { font-size: .72rem; text-transform: uppercase; letter-spacing: .06em;
     color: var(--ink-soft); font-weight: 600; }
td.num, th.num { text-align: right; }

/* The topographic pattern is part of the brand's graphic territory; used here
 * as a restrained texture on the sign-in panel only. */
.auth-wrap { min-height: 80vh; display: grid; place-items: center; padding: var(--s4); }
.auth-card { width: 100%; max-width: 25rem; }
.auth-mark { height: 2.25rem; margin-bottom: var(--s4); color: var(--accent); }

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