/* ═══════════════════════════════════════════════════════════════════════════
   KleinVet design tokens — the ONE definition of the palette.

   WHY THIS FILE EXISTS
   Three surfaces once rendered three different brand colours. styles.css used a
   deep teal (--accent-700 #0f6d65), owner.css declared its own --brand #0a7d68,
   and consultation-room.css declared --accent #3bd2aa, a green. Worse than the
   wrong values: `--accent` meant a different colour depending on which file you
   were reading.

   The cause was structural, not carelessness. owner.html and
   consultation-room.html never loaded styles.css, so they could not inherit its
   tokens and each had to invent a palette. Fixing the values alone would have
   drifted again the moment anyone touched either file, so the loading is fixed
   too: every page links this file FIRST, then its own stylesheet.

   RULES
   1. Brand, grey, surface and ink colours are defined here and nowhere else.
      A surface stylesheet referencing a brand hex literal is a bug, and
      test_frontend_contract.py fails on it.
   2. Light values live in bare `:root`. Dark values are redefined under BOTH
      the prefers-color-scheme media query AND :root[data-theme="dark"], so the
      in-app toggle wins in both directions. A colour defined only inside a
      media query cannot be overridden by the toggle.
   3. Semantic colours that carry SAFETY meaning — amber for the emergency
      notice, red for urgent clinical signs — are deliberately NOT derived from
      the brand ramp. They must stay distinguishable from "a KleinVet button" at
      a glance, because they exist to interrupt someone whose pet is bleeding.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Neutrals. Warm-tinted rather than pure grey: the product sits on cream,
        and a blue-grey scale reads as dirty against it. ─────────────────── */
  --gray-25:  #fffefa;
  --gray-50:  #faf8f2;
  --gray-100: #f2efe6;
  --gray-150: #e9e5dc;
  --gray-200: #ded9cf;
  --gray-300: #c7c1b7;
  --gray-350: #a0a7ab;
  --gray-400: #8b9296;
  --gray-450: #939a9e;
  --gray-500: #657079;
  --gray-600: #455364;
  --gray-700: #2b3d54;
  --gray-800: #172d49;
  --gray-900: #0c2140;
  --gray-950: #06172f;

  /* ── Brand. --accent-700 is the primary action colour; the ramp exists so a
        subtle fill (50/100) and a pressed state (800) come from the same hue
        rather than being eyeballed per surface. ─────────────────────────── */
  --accent-50:  #edf8f5;
  --accent-100: #d7eee8;
  --accent-200: #afe0d5;
  --accent-300: #7dcbbe;
  --accent-400: #4cb2a3;
  --accent-500: #268f83;
  --accent-600: #167c72;
  --accent-700: #0f6d65;
  --accent-800: #115750;
  --accent-900: #123f3c;

  /* ── Named brand constants used by chrome and marketing surfaces. ────── */
  --navy:       #0b2242;
  --navy-deep:  #06172f;
  --cream:      #f4f1e8;
  /* --coral is 2.93:1 on --cream and 2.98:1 on --coral-soft: fills and
     borders only, never text. test_frontend_contract greps for it. */
  --coral:        #d86f5c;
  --coral-soft:   #fff0ec;
  --coral-border: #f1bbb1;

  /* ── Surfaces and ink. ────────────────────────────────────────────────── */
  --bg:        #f4f1e8;
  --surface:   #fffdf8;
  --surface-2: #f8f6ef;
  --ink:       #10243d;
  --ink-2:     #34475b;
  /* --ink-3 and --muted are body-size text roles: each must reach 4.5:1 on
     --bg, --surface and --surface-2 in BOTH themes (WCAG 1.4.3). The old
     values (#66727c / #879095) were 4.36:1 and 2.88:1 on --bg;
     test_frontend_contract pins the ratios now. */
  --ink-3:     #5f6b75;
  --muted:     #5d666b;

  --border:   rgba(11, 34, 66, .09);
  --border-2: rgba(11, 34, 66, .15);
  --border-3: rgba(11, 34, 66, .24);

  --header-bg: rgba(6, 23, 47, .96);
}

/* Dark, via system preference. Guarded with :not([data-theme="light"]) so an
   explicit light choice still wins here. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:        var(--gray-950);
    --surface:   var(--gray-900);
    --surface-2: var(--gray-800);
    --ink:       var(--gray-50);
    --ink-2:     var(--gray-300);
    --ink-3:     var(--gray-350);
    --muted:     var(--gray-450);

    --border:   rgba(255, 255, 255, .06);
    --border-2: rgba(255, 255, 255, .1);
    --border-3: rgba(255, 255, 255, .14);

    --header-bg: rgba(15, 23, 42, .72);
  }
}

/* Dark, via the in-app toggle. Repeated deliberately: the media query above
   cannot serve this case, and a toggle that only worked on machines already set
   to dark would be worse than no toggle. */
:root[data-theme="dark"] {
  --bg:        var(--gray-950);
  --surface:   var(--gray-900);
  --surface-2: var(--gray-800);
  --ink:       var(--gray-50);
  --ink-2:     var(--gray-300);
  --ink-3:     var(--gray-350);
  --muted:     var(--gray-450);

  --border:   rgba(255, 255, 255, .06);
  --border-2: rgba(255, 255, 255, .1);
  --border-3: rgba(255, 255, 255, .14);

  --header-bg: rgba(15, 23, 42, .72);
}

/* ═══════════════════════════════════════════════════════════════════════════
   Owner app brand, LOCKED 2026-09-16 (docs/design/APP_MAP.md F-02).

   The owner app was re-based on the KV logo: navy #0F172A for surfaces and
   ink, cyan #22D3EE for actions and active states only, white cards on a cool
   #F8FAFC ground, slate muted text and borders. Amber and red stay reserved for
   clinical warnings (rule 3 above).

   Scoped to [data-brand="kv"] so the vanilla clinic shell and staff pages keep
   the cream/teal palette above until they are migrated. The Next.js owner app
   sets the attribute on its root. It redefines the same semantic names, so
   components written against --bg / --ink / --accent-* follow without edits.
   The locked designs are light-only, so this scope does not follow dark mode.
   The doubled attribute raises specificity above the dark-mode :root rules
   (0,2,0) so a system dark preference cannot flip the owner app to cream-dark.
   ═══════════════════════════════════════════════════════════════════════════ */
:root[data-brand="kv"][data-brand],
[data-brand="kv"][data-brand] {
  color-scheme: light;

  /* Slate neutrals, blue-biased to sit with navy rather than cream. */
  --gray-25:  #ffffff;
  --gray-50:  #f8fafc;
  --gray-100: #f1f5f9;
  --gray-150: #e8eef5;
  --gray-200: #e2e8f0;
  --gray-300: #cbd5e1;
  --gray-350: #b4c0cf;
  --gray-400: #94a3b8;
  --gray-450: #7b8aa0;
  --gray-500: #64748b;
  --gray-600: #475569;
  --gray-700: #334155;
  --gray-800: #1e293b;
  --gray-900: #0f172a;
  --gray-950: #020617;

  /* Cyan action ramp: 400 is the logo dot and the primary button fill. */
  --accent-50:  #ecfeff;
  --accent-100: #cffafe;
  --accent-200: #a5f3fc;
  --accent-300: #67e8f9;
  --accent-400: #22d3ee;
  --accent-500: #06b6d4;
  --accent-600: #0891b2;
  --accent-700: #22d3ee;
  --accent-800: #0e7490;
  --accent-900: #164e63;

  --navy:      #0f172a;
  --navy-deep: #020617;
  --cream:     #f8fafc;
  /* The owner brand has no coral; the unread badge uses cyan instead. */
  --coral:        #22d3ee;
  --coral-soft:   #ecfeff;
  --coral-border: #a5f3fc;

  --bg:        #f8fafc;
  --surface:   #ffffff;
  --surface-2: #f1f5f9;
  --ink:       #0f172a;
  --ink-2:     #334155;
  /* Muted text, one step darker than slate-500 (#64748b) by the owner's
     decision (2026-09-18): #64748b on the grey card (#f1f5f9) is 4.34:1, under
     WCAG AA; #5e6c82 is 4.86:1 there and keeps the same look. */
  --ink-3:     #5e6c82;
  --muted:     #5e6c82;
  --border:    #e2e8f0;
  --border-2:  #cbd5e1;
  --border-3:  #b4c0cf;
  --header-bg: rgba(248, 250, 252, .9);

  /* Safety fills for the locked skin-check screens (rule 3): red only for the
     urgent result (SC4-U), amber only for the "initial assessment, not a
     diagnosis" and "take care" notes (SC1, SC4). */
  --urgent:          #dc2626;
  --urgent-soft:     #fef2f2;
  --urgent-border:   #fecaca;
  --caution:         #b45309;
  --caution-soft:    #fffbeb;
  --caution-border:  #fcd34d;
}
