/* ============================================================
   Familix — Variant 8 "Geode"
   Variant 7 (Quartz, light) and variant 6 (Obsidian, dark) as one
   build with a switch between them.

     :root                     Quartz   — light  ← DEFAULT
     :root[data-theme="dark"]  Obsidian — dark

   Light sits on plain :root deliberately: it is what renders with no
   JavaScript and no stored preference. Dark is opt-in.

   `components.css` and `app.css` contain NO colour literals — every
   colour resolves through a token declared here. Switching theme
   therefore never touches component CSS, and adding a third theme
   is one more block in this file and nothing else.
   ============================================================ */

/* ------------------------------------------------------------
   QUARTZ — light · the default
   ------------------------------------------------------------ */
:root {
  color-scheme: light;

  /* Brand — the deep end carries text and icons on a light ground */
  --brand-400: #3a4cc4;
  --brand-500: #5468e0;
  --brand-600: #7488fa;
  --brand-700: #8fa0fc;
  --teal-400: #0c7d78;
  --teal-600: #5fd8d0;

  /* Ground */
  --bg: #f6f7fb;
  --bg-2: #eef0f7;
  --panel: #ffffff;

  /* Surfaces — raised means lighter in BOTH themes. That is why these
     are two token sets and not one inversion filter. */
  --glass: #ffffff;
  --glass-2: #f2f4fb;
  --row-hover: #f4f6fd;
  --sunken: rgba(19, 26, 46, 0.035);
  --sunken-2: #f7f9fd;
  --sunken-3: rgba(19, 26, 46, 0.04);
  --tint: rgba(19, 26, 46, 0.025);
  --tint-2: rgba(19, 26, 46, 0.03);
  --window-bg: linear-gradient(165deg, #ffffff, #fbfcfe);
  --footer-bg: #eef0f7;
  --nav-bg: rgba(246, 247, 251, 0.82);
  --backdrop: rgba(19, 26, 46, 0.45);

  /* Lines */
  --stroke: rgba(19, 26, 46, 0.12);
  --stroke-2: rgba(19, 26, 46, 0.22);
  --hairline: rgba(19, 26, 46, 0.07);
  --grid-line: rgba(19, 26, 46, 0.035);

  /* Controls */
  --input-bg: #ffffff;
  --input-bg-focus: #ffffff;
  --track: rgba(19, 26, 46, 0.12);
  --focus-ring: 0 0 0 3px rgba(92, 114, 245, 0.22);

  /* Text */
  --text: #131a2e;
  --text-muted: #515c7a;
  --text-dim: #5a6379;
  --on-accent: #ffffff;   /* sits on a gradient chip */
  --on-brand: #ffffff;    /* sits on the brand button */
  --on-danger: #ffffff;

  /* Semantic — never the brand hue */
  --success: #0a7048;  --success-bg: rgba(15, 157, 99, 0.11);
  --warning: #8f4207;  --warning-bg: rgba(180, 83, 9, 0.10);
  /* Text sitting ON `--warning-bg`, not on the page ground. `--warning` clears
     4.5:1 against white but only 4.35:1 once the amber wash is behind it, so a
     warning chip needs the darker step. v1's `.badge--warn` used this same
     amber-800 for the same reason. */
  --warning-strong: #92400e;
  --danger:  #dc2626;  --danger-bg:  rgba(220, 38, 38, 0.09);
  --danger-hover: #b91c1c;
  --danger-border: rgba(220, 38, 38, 0.40);
  --danger-ring: 0 0 0 3px rgba(220, 38, 38, 0.16);
  --success-border: rgba(15, 157, 99, 0.28);
  --info-bg: rgba(92, 114, 245, 0.11);
  --info-border: rgba(92, 114, 245, 0.30);
  --violet: #6d4aff;

  /* Gradients — brand runs deep→deeper so the white label survives */
  --grad-brand:  linear-gradient(135deg, #5468e0, #4054d8);
  --grad-mark:   linear-gradient(140deg, #4054d8, #0f9e97);
  --grad-text:   linear-gradient(110deg, #4054d8 15%, #0f9e97 85%);
  --grad-rule:   linear-gradient(90deg, #4054d8, #0f9e97);
  --grad-active: linear-gradient(120deg, rgba(92, 114, 245, 0.30), rgba(47, 212, 200, 0.10));
  --grad-active-border: rgba(92, 114, 245, 0.42);
  --grad-cta:    linear-gradient(120deg, rgba(92, 114, 245, 0.14), rgba(47, 212, 200, 0.06));
  --grad-quote:  linear-gradient(140deg, rgba(92, 114, 245, 0.16), rgba(47, 212, 200, 0.06));
  --grad-quote-border: rgba(92, 114, 245, 0.28);

  /* Ambient field — alpha baked in, ~40% of the dark theme's strength.
     A saturated blur at the dark opacity tints body text on paper. */
  --field-1: rgba(92, 114, 245, 0.18);
  --field-2: rgba(95, 216, 208, 0.10);
  --field-3: rgba(143, 160, 252, 0.12);

  /* ---- Companion role badges (request 131 §6) ----
     One hue per role. Each pair is a tint background with a same-hue
     foreground, and every one is measured at 11.5px — normal text, so 4.5:1
     applies to all eight. Light: pale tint, ink-dark text. */
  --role-friend-bg:    #e6eafc;  --role-friend-fg:    #2f41bd;
  --role-family-bg:    #d9f3f0;  --role-family-fg:    #0d5f5a;
  --role-colleague-bg: #fbeed2;  --role-colleague-fg: #7a4e00;
  --role-partner-bg:   #fbe4ed;  --role-partner-fg:   #98204f;
  --role-coach-bg:     #ddf1e0;  --role-coach-fg:     #1d6127;
  --role-guide-bg:     #dcecf9;  --role-guide-fg:     #10556f;
  --role-customer-bg:  #eee3fa;  --role-customer-fg:  #61329b;
  --role-other-bg:     #e8eaf1;  --role-other-fg:     #434a61;
  /* "you are" (request 139). Orange is the one hue the eight roles leave free —
     blue, teal, amber, pink, green, sky, purple and grey are all taken — so the
     badge reads as a different KIND of label, not a ninth role. */
  --role-self-bg:      #ffe1cf;  --role-self-fg:      #8f3410;

  /* Elevation — on paper, depth reads through opacity, not black */
  --shadow-sm: 0 1px 2px rgba(19, 26, 46, 0.07);
  --shadow-md: 0 8px 24px rgba(19, 26, 46, 0.09);
  --shadow-lg: 0 24px 56px rgba(19, 26, 46, 0.14);
  --glow: 0 8px 24px rgba(92, 114, 245, 0.28);
  --glow-hover: 0 10px 28px rgba(92, 114, 245, 0.34);

  /* ---- Navigation rail ----
     Inked in BOTH themes. Under Quartz it is a slab that stops the
     white rail and the white content column merging into each other;
     under Obsidian it becomes glass over the page. */
  --rail: #151c33;
  /* Opaque twin of the rail, for the mobile drawer, which floats over content
     where glass is unreadable (bug 0018). */
  --rail-solid: #151c33;
  --rail-2: #1d2645;
  --rail-border: transparent;
  --rail-text: #e6e9f5;
  --rail-muted: #a2abc6;
  --rail-dim: #79829e;
  --rail-stroke: rgba(255, 255, 255, 0.10);
  --rail-stroke-2: rgba(255, 255, 255, 0.18);
  --rail-hover: rgba(255, 255, 255, 0.07);
  --rail-active: linear-gradient(120deg, rgba(92, 114, 245, 0.55), rgba(15, 158, 151, 0.28));
  --rail-active-border: rgba(128, 147, 255, 0.55);
  --rail-active-text: #ffffff;
  --rail-active-icon: #7ee8e0;
  --rail-av: linear-gradient(135deg, #8093ff, #2fd4c8);
  --rail-av-fg: #0d1220;
  --rail-focus: #7ee8e0;

  /* ---- Non-colour: identical in both themes ---- */
  --r-xs: 4px;
  --r-sm: 6px;
  --r-md: 8px;
  --r-lg: 12px;
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
    Arial, "Noto Sans Hebrew", sans-serif;
  --mono: "SF Mono", "Cascadia Mono", Consolas, "Liberation Mono", monospace;
  --container: 1240px;
}

/* ------------------------------------------------------------
   OBSIDIAN — dark · opt-in
   Only colour is redeclared. Radii, type and layout are inherited
   from the block above, which keeps the two modes in step.
   ------------------------------------------------------------ */
:root[data-theme="dark"] {
  color-scheme: dark;

  /* Same hues; ramp reversed so the light end carries text on ink */
  --brand-400: #adb9ff;
  --brand-500: #5c72f5;
  --brand-600: #4356d6;
  --brand-700: #3543b4;
  --teal-400: #2fd4c8;
  --teal-600: #14a8a0;

  --bg: #0a0e1c;
  --bg-2: #0e1428;
  --panel: #121a30;

  --glass: rgba(255, 255, 255, 0.04);
  --glass-2: rgba(255, 255, 255, 0.07);
  --row-hover: rgba(255, 255, 255, 0.04);
  --sunken: rgba(0, 0, 0, 0.18);
  --sunken-2: rgba(0, 0, 0, 0.16);
  --sunken-3: rgba(0, 0, 0, 0.24);
  --tint: rgba(255, 255, 255, 0.02);
  --tint-2: rgba(255, 255, 255, 0.03);
  --window-bg: linear-gradient(165deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02));
  --footer-bg: rgba(0, 0, 0, 0.3);
  --nav-bg: rgba(10, 14, 28, 0.78);
  --backdrop: rgba(4, 6, 16, 0.74);

  --stroke: rgba(255, 255, 255, 0.09);
  --stroke-2: rgba(255, 255, 255, 0.17);
  --hairline: rgba(255, 255, 255, 0.05);
  --grid-line: rgba(255, 255, 255, 0.025);

  --input-bg: rgba(0, 0, 0, 0.24);
  --input-bg-focus: rgba(0, 0, 0, 0.34);
  --track: rgba(255, 255, 255, 0.1);

  --text: #e8ecf7;
  --text-muted: #c3cbe1;
  --text-dim: #a3aed0;
  --on-accent: #0a0e1c;
  /* Dark flips the brand ramp light, so the label on a brand surface must go
     dark too — white on --brand-400 measures 2.78:1 (task 0161a). */
  --on-brand: #0a0e1c;
  --on-danger: #24070a;

  --success: #34d399;  --success-bg: rgba(52, 211, 153, 0.13);
  --warning: #fbbf24;  --warning-bg: rgba(251, 191, 36, 0.13);
  /* On ink the light amber is already the readable end of the ramp (6.08:1 on
     the chip), so the strong step stays where it is rather than going darker. */
  --warning-strong: #fbbf24;
  --danger:  #f87171;  --danger-bg:  rgba(248, 113, 113, 0.13);
  --danger-hover: #fb8a8a;
  --danger-border: rgba(248, 113, 113, 0.45);
  --danger-ring: 0 0 0 3px rgba(248, 113, 113, 0.18);
  --success-border: rgba(52, 211, 153, 0.28);
  --info-bg: rgba(92, 114, 245, 0.15);
  --info-border: rgba(92, 114, 245, 0.30);
  --violet: #a78bfa;

  --grad-brand:  linear-gradient(135deg, #96a5ff, #8093ff);
  --grad-mark:   linear-gradient(140deg, #8093ff, #2fd4c8);
  --grad-text:   linear-gradient(110deg, #8093ff 15%, #2fd4c8 85%);
  --grad-rule:   linear-gradient(90deg, #8093ff, #2fd4c8);
  --grad-active: linear-gradient(120deg, rgba(92, 114, 245, 0.32), rgba(47, 212, 200, 0.12));
  --grad-active-border: rgba(92, 114, 245, 0.4);
  --grad-cta:    linear-gradient(120deg, rgba(92, 114, 245, 0.18), rgba(47, 212, 200, 0.07));
  --grad-quote:  linear-gradient(140deg, rgba(92, 114, 245, 0.24), rgba(47, 212, 200, 0.08));
  --grad-quote-border: rgba(92, 114, 245, 0.32);

  --field-1: rgba(92, 114, 245, 0.30);
  --field-2: rgba(20, 168, 160, 0.16);
  --field-3: rgba(53, 67, 180, 0.22);

  /* Role badges on ink: the tint goes translucent so it sits on the page
     instead of glowing, and the text lightens to carry the contrast. */
  --role-friend-bg:    rgba(128, 147, 255, 0.18); --role-friend-fg:    #aeb9ff;
  --role-family-bg:    rgba(47, 212, 200, 0.16);  --role-family-fg:    #6fded4;
  --role-colleague-bg: rgba(240, 180, 70, 0.16);  --role-colleague-fg: #f0c473;
  --role-partner-bg:   rgba(244, 114, 160, 0.16); --role-partner-fg:   #f79cba;
  --role-coach-bg:     rgba(90, 200, 110, 0.16);  --role-coach-fg:     #89dd9a;
  --role-guide-bg:     rgba(90, 180, 235, 0.16);  --role-guide-fg:     #8fcdf2;
  --role-customer-bg:  rgba(180, 130, 240, 0.16); --role-customer-fg:  #cba9f7;
  --role-other-bg:     rgba(255, 255, 255, 0.10); --role-other-fg:     #c4ccdf;
  --role-self-bg:      rgba(255, 146, 84, 0.18);  --role-self-fg:      #ffb689;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.4);
  --shadow-lg: 0 24px 56px rgba(0, 0, 0, 0.55);
  --glow: 0 0 32px rgba(92, 114, 245, 0.35);
  --glow-hover: 0 0 44px rgba(92, 114, 245, 0.5);

  /* Glass here rather than a slab: the page is already dark, so the
     rail no longer has to hold its own edge. */
  --rail: rgba(0, 0, 0, 0.28);
  /* The same colour the desktop rail resolves to over the page, made opaque so
     the drawer covers what is behind it (bug 0018). */
  --rail-solid: #070a14;
  --rail-2: rgba(255, 255, 255, 0.04);
  --rail-border: var(--stroke);
  --rail-text: var(--text);
  /* NOT var(--text-muted) (task 0149b). In dark the rail is glass —
     rgba(0,0,0,0.28) over the page — so it composites LIGHTER than the light
     theme's solid #151c33 rail, and the page's muted colour loses the contrast
     it has everywhere else. Sampled from the painted pixels: #9aa5c4 on the
     composited rail is 3.67:1, under AA for the 10.5px group titles that were
     already using it and for the brand suffix added here. #b3bcd4 measures
     4.92:1 and still reads a step below --rail-text. */
  --rail-muted: #b3bcd4;
  --rail-dim: var(--text-dim);
  --rail-stroke: var(--stroke);
  --rail-stroke-2: var(--stroke-2);
  --rail-hover: var(--glass);
  --rail-active: var(--grad-active);
  --rail-active-border: rgba(92, 114, 245, 0.42);
  --rail-active-text: var(--text);
  --rail-active-icon: var(--teal-400);
  --rail-av: var(--grad-mark);
  --rail-av-fg: var(--on-accent);
  --rail-focus: var(--teal-400);
}

/* Cross-fade only after load, so switching animates but the first
   paint does not. theme.js adds .theme-ready on DOMContentLoaded. */
.theme-ready body,
.theme-ready .nav,
.theme-ready .topbar,
.theme-ready .side,
.theme-ready .panel,
.theme-ready .stat,
.theme-ready .trip,
.theme-ready .auth-card,
.theme-ready .window {
  transition: background-color 0.22s ease, border-color 0.22s ease, color 0.22s ease;
}
@media (prefers-reduced-motion: reduce) {
  .theme-ready * { transition: none !important; }
}

/* ============================================================================
   Contrast preferences (task 0162a)

   Two conditional layers *beneath* the product palette — they never run unless
   the user has already told their operating system what they need. There is no
   UI for either, and nothing here changes the default look.

   Dark is expressed only as `:root[data-theme="dark"]`, never via
   `prefers-color-scheme` (a deliberate product decision — see the head of this
   file), so each preference needs exactly two blocks, not three.
   ========================================================================== */

/* ---- prefers-contrast: more ---------------------------------------------
   Legibility outranks hierarchy here: the muted/dim steps are pulled close to
   body text (all >7:1, AAA territory) and the near-invisible hairline borders
   are raised past 3:1 so card and field edges are unmistakable. Measured
   against the surfaces each token actually lands on. */
@media (prefers-contrast: more) {
  :root {
    --text-muted: #2f3847;   /* 11.81:1 on white, 10.38:1 on --bg-2 */
    --text-dim:   #36404f;   /* 10.48:1 on white,  9.21:1 on --bg-2 */

    --stroke:     #7b8496;   /* 3.76:1 on white — was rgba(19,26,46,.12) */
    --stroke-2:   #5d6678;   /* 5.77:1 on white */
    --hairline:   rgba(19, 26, 46, 0.38);
    --grid-line:  rgba(19, 26, 46, 0.20);
    --track:      rgba(19, 26, 46, 0.45);

    --focus-ring: 0 0 0 3px rgba(58, 79, 208, 0.85);
  }

  :root[data-theme="dark"] {
    --text-muted: #e0e5f2;   /* 15.25:1 on --bg, 13.70:1 on --panel */
    --text-dim:   #d7dcec;   /* 14.04:1 on --bg, 12.61:1 on --panel */

    --stroke:     #7d86a0;   /* 5.30:1 on --bg */
    --stroke-2:   #8d96b0;   /* 6.52:1 on --bg */
    --hairline:   rgba(255, 255, 255, 0.34);
    --grid-line:  rgba(255, 255, 255, 0.18);
    --track:      rgba(255, 255, 255, 0.42);

    --focus-ring: 0 0 0 3px rgba(173, 185, 255, 0.9);
  }
}

/* ---- forced-colors: active (Windows High Contrast) ----------------------
   The job is to stop fighting the user's palette, not to restyle for it.
   Backgrounds and text are replaced by the system automatically; three things
   are NOT, and each would otherwise lose meaning:

     1. `background-image` survives forced-colors, so a gradient button keeps
        its fill while its text is forced to a system colour — which is how a
        primary button becomes unreadable. Drop the image, take a border.
     2. `box-shadow` is discarded, so any affordance carried only by a shadow
        (our focus ring included) needs an `outline` to survive.
     3. Purely decorative colour washes have nothing to say once recoloured. */
@media (forced-colors: active) {
  .btn,
  .btn-primary,
  .btn-quiet,
  .btn-outline,
  .chip,
  .pillstat,
  .trip-mark,
  .mark {
    background-image: none;
    border: 1px solid currentColor;
  }

  /* A shadow-only focus ring disappears here; an outline does not. */
  :focus-visible {
    outline: 3px solid Highlight;
    outline-offset: 2px;
  }

  /* Decorative only — recoloured it is noise, not information. */
  .aurora,
  .grid-bg {
    display: none;
  }

  /* The switch reads as two states by knob position; give it an edge so the
     track and knob stay distinguishable once both take system colours. */
  .theme-switch { border: 1px solid currentColor; }
  .theme-switch .ts-knob { border: 1px solid currentColor; }
}

/* ============================================================================
   Monochrome (task 0162c)

   A palette, not a stylesheet. `data-mono` composes with `data-theme`, so one
   set of overrides yields both directions:

       data-mono                       -> black on white
       data-mono + data-theme="dark"   -> white on black

   It also composes with `prefers-contrast: more` above, which only touches
   text/border steps and so simply lands on top.

   (No relation to the `--mono` token, which is the monospace font stack.)

   Every colour-bearing token is neutralised here. Hue that carried meaning —
   success/warning/danger — collapses to ink, so the rules at the end give those
   components a border: what was a colour difference has to become a shape
   difference, or the mode would trade one colour-only signal for another.
   ========================================================================== */
:root[data-mono] {
  color-scheme: light;

  --brand-400: #000000;  --brand-500: #000000;
  --brand-600: #000000;  --brand-700: #000000;
  --teal-400:  #000000;  --teal-600:  #000000;
  --violet:    #000000;

  --bg: #ffffff;  --bg-2: #ffffff;  --panel: #ffffff;
  --glass: #ffffff;  --glass-2: #f2f2f2;
  --row-hover: #e8e8e8;
  --sunken: #f0f0f0;  --sunken-2: #f7f7f7;  --sunken-3: #f0f0f0;
  --tint: #f4f4f4;  --tint-2: #ececec;
  --window-bg: #ffffff;  --footer-bg: #ffffff;  --nav-bg: #ffffff;
  --backdrop: rgba(0, 0, 0, 0.7);

  --stroke: #000000;  --stroke-2: #000000;
  --hairline: #000000;  --grid-line: #767676;
  --track: #000000;

  --text: #000000;  --text-muted: #000000;  --text-dim: #1f1f1f;
  --on-accent: #ffffff;  --on-brand: #ffffff;  --on-danger: #ffffff;

  --success: #000000;  --success-bg: #ffffff;  --success-border: #000000;
  --warning: #000000;  --warning-strong: #000000;  --warning-bg: #ffffff;
  --danger: #000000;   --danger-bg: #ffffff;  --danger-border: #000000;
  --danger-hover: #000000;  --danger-ring: rgba(0, 0, 0, 0.35);
  --info-bg: #ffffff;  --info-border: #000000;

  --input-bg: #ffffff;  --input-bg-focus: #ffffff;
  --field-1: rgba(0, 0, 0, 0.3);  --field-2: rgba(0, 0, 0, 0.2);  --field-3: rgba(0, 0, 0, 0.1);

  /* Thicker than the themed ring: without hue it has only weight to separate
     itself from an ordinary black border. */
  --focus-ring: 0 0 0 4px #000000;
  --glow: none;  --glow-hover: none;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.25);
  --shadow-md: 0 2px 6px rgba(0, 0, 0, 0.3);
  --shadow-lg: 0 6px 18px rgba(0, 0, 0, 0.35);

  /* A gradient that survives into monochrome is the bug this mode removes. */
  --grad-brand:  linear-gradient(135deg, #000000, #000000);
  --grad-cta:    linear-gradient(135deg, #000000, #000000);
  --grad-mark:   linear-gradient(140deg, #000000, #000000);
  --grad-text:   linear-gradient(110deg, #000000, #000000);
  --grad-rule:   linear-gradient(90deg, #000000, #000000);
  --grad-quote:  linear-gradient(135deg, #ffffff, #ffffff);
  --grad-quote-border: #000000;
  --grad-active: #e8e8e8;  --grad-active-border: #000000;

  --rail: #ffffff;  --rail-2: #ffffff;  --rail-solid: #ffffff;
  --rail-text: #000000;  --rail-muted: #000000;  --rail-dim: #1f1f1f;
  --rail-border: #000000;  --rail-stroke: #000000;  --rail-stroke-2: #000000;
  --rail-hover: #e8e8e8;
  --rail-active: #000000;  --rail-active-text: #ffffff;
  --rail-active-icon: #ffffff;  --rail-active-border: #000000;
  --rail-focus: #000000;
  --rail-av: linear-gradient(135deg, #000000, #000000);  --rail-av-fg: #ffffff;

  --role-self-bg: #ffffff;      --role-self-fg: #000000;
  --role-family-bg: #ffffff;    --role-family-fg: #000000;
  --role-friend-bg: #ffffff;    --role-friend-fg: #000000;
  --role-partner-bg: #ffffff;   --role-partner-fg: #000000;
  --role-colleague-bg: #ffffff; --role-colleague-fg: #000000;
  --role-customer-bg: #ffffff;  --role-customer-fg: #000000;
  --role-coach-bg: #ffffff;     --role-coach-fg: #000000;
  --role-guide-bg: #ffffff;     --role-guide-fg: #000000;
  --role-other-bg: #ffffff;     --role-other-fg: #000000;
}

/* Same palette, inverted. */
:root[data-mono][data-theme="dark"] {
  color-scheme: dark;

  --brand-400: #ffffff;  --brand-500: #ffffff;
  --brand-600: #ffffff;  --brand-700: #ffffff;
  --teal-400:  #ffffff;  --teal-600:  #ffffff;
  --violet:    #ffffff;

  --bg: #000000;  --bg-2: #000000;  --panel: #000000;
  --glass: #000000;  --glass-2: #0d0d0d;
  --row-hover: #1c1c1c;
  --sunken: #0f0f0f;  --sunken-2: #080808;  --sunken-3: #0f0f0f;
  --tint: #0b0b0b;  --tint-2: #131313;
  --window-bg: #000000;  --footer-bg: #000000;  --nav-bg: #000000;
  --backdrop: rgba(0, 0, 0, 0.85);

  --stroke: #ffffff;  --stroke-2: #ffffff;
  --hairline: #ffffff;  --grid-line: #9a9a9a;
  --track: #ffffff;

  --text: #ffffff;  --text-muted: #ffffff;  --text-dim: #e4e4e4;
  --on-accent: #000000;  --on-brand: #000000;  --on-danger: #000000;

  --success: #ffffff;  --success-bg: #000000;  --success-border: #ffffff;
  --warning: #ffffff;  --warning-strong: #ffffff;  --warning-bg: #000000;
  --danger: #ffffff;   --danger-bg: #000000;  --danger-border: #ffffff;
  --danger-hover: #ffffff;  --danger-ring: rgba(255, 255, 255, 0.4);
  --info-bg: #000000;  --info-border: #ffffff;

  --input-bg: #000000;  --input-bg-focus: #000000;
  --field-1: rgba(255, 255, 255, 0.35);  --field-2: rgba(255, 255, 255, 0.25);  --field-3: rgba(255, 255, 255, 0.15);

  --focus-ring: 0 0 0 4px #ffffff;
  --glow: none;  --glow-hover: none;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.8);
  --shadow-md: 0 2px 6px rgba(0, 0, 0, 0.85);
  --shadow-lg: 0 6px 18px rgba(0, 0, 0, 0.9);

  --grad-brand:  linear-gradient(135deg, #ffffff, #ffffff);
  --grad-cta:    linear-gradient(135deg, #ffffff, #ffffff);
  --grad-mark:   linear-gradient(140deg, #ffffff, #ffffff);
  --grad-text:   linear-gradient(110deg, #ffffff, #ffffff);
  --grad-rule:   linear-gradient(90deg, #ffffff, #ffffff);
  --grad-quote:  linear-gradient(135deg, #000000, #000000);
  --grad-quote-border: #ffffff;
  --grad-active: #1c1c1c;  --grad-active-border: #ffffff;

  --rail: #000000;  --rail-2: #000000;  --rail-solid: #000000;
  --rail-text: #ffffff;  --rail-muted: #ffffff;  --rail-dim: #e4e4e4;
  --rail-border: #ffffff;  --rail-stroke: #ffffff;  --rail-stroke-2: #ffffff;
  --rail-hover: #1c1c1c;
  --rail-active: #ffffff;  --rail-active-text: #000000;
  --rail-active-icon: #000000;  --rail-active-border: #ffffff;
  --rail-focus: #ffffff;
  --rail-av: linear-gradient(135deg, #ffffff, #ffffff);  --rail-av-fg: #000000;

  --role-self-bg: #000000;      --role-self-fg: #ffffff;
  --role-family-bg: #000000;    --role-family-fg: #ffffff;
  --role-friend-bg: #000000;    --role-friend-fg: #ffffff;
  --role-partner-bg: #000000;   --role-partner-fg: #ffffff;
  --role-colleague-bg: #000000; --role-colleague-fg: #ffffff;
  --role-customer-bg: #000000;  --role-customer-fg: #ffffff;
  --role-coach-bg: #000000;     --role-coach-fg: #ffffff;
  --role-guide-bg: #000000;     --role-guide-fg: #ffffff;
  --role-other-bg: #000000;     --role-other-fg: #ffffff;
}

/* ---- monochrome: the parts a token cannot reach --------------------------
   Two categories, and they need opposite treatments.

   (a) Inline colour that is DATA. Expense rows are tinted from
       `expense_categories`, written straight into a `style` attribute, so no
       token touches them. They cannot be greyscaled either: greyscale
       preserves lightness, and a user who picked a dark navy would keep a dark
       row with black text on it. The background is replaced outright, with the
       alternation kept so rows still group. Nothing is lost — since request 155
       the group header names the category in text.

   (b) Inline colour that is DECORATION. The dashboard pie is
       `aria-hidden="true"` with a text legend carrying every label and
       percentage, and each status dot is followed by its own word. Those can
       simply be desaturated. */
:root[data-mono] .exp-table tbody tr[style] {
  background: #ffffff !important;
  --cat: #ffffff !important;
  --cat-fg: #000000 !important;
}
:root[data-mono] .exp-table tbody tr[style]:nth-child(even) {
  background: #ededed !important;
  --cat: #ededed !important;
}
:root[data-mono][data-theme="dark"] .exp-table tbody tr[style] {
  background: #000000 !important;
  --cat: #000000 !important;
  --cat-fg: #ffffff !important;
}
:root[data-mono][data-theme="dark"] .exp-table tbody tr[style]:nth-child(even) {
  background: #191919 !important;
  --cat: #191919 !important;
}

:root[data-mono] .dash-pie__chart,
:root[data-mono] .dash-pie__swatch,
:root[data-mono] .dash-total__dot {
  filter: grayscale(1) contrast(1.4);
}
/* Desaturated, two swatches can land on the same grey — an outline keeps them
   readable as distinct marks. */
:root[data-mono] .dash-pie__swatch,
:root[data-mono] .dash-total__dot {
  border: 1px solid var(--text);
}

/* ---- monochrome: hue that carried meaning becomes shape ------------------
   success / warning / danger are all ink here, so a status that read as
   "the green one" now needs an edge. Each of these already carries a text
   label; the border restores the second, non-textual cue. */
:root[data-mono] .pillstat,
:root[data-mono] .chip,
:root[data-mono] .badge,
:root[data-mono] .role-badge,
:root[data-mono] .btn,
:root[data-mono] .trip-mark,
:root[data-mono] .mark {
  border: 1px solid currentColor;
}
/* The destructive action must not look identical to a neutral one. */
:root[data-mono] .btn--danger,
:root[data-mono] .btn-danger {
  border-width: 3px;
  font-weight: 700;
}

/* Remaining inline colour, each written per element by a view and therefore
   beyond the token layer. Custom properties accept !important, which is what
   lets a stylesheet beat a `style` attribute here.

     --badge      career funnel stages and status badges (career/dashboard.php,
                  listings/_status_badge.php, travel/dashboard.php)
     .pay-status  the paid/due glyphs, coloured from app/config/travel.php
     .plan-day    the day cell, tinted with that day's category colour */
:root[data-mono] [style*="--badge"] { --badge: var(--text) !important; }
:root[data-mono] .pay-status { color: var(--text) !important; }
:root[data-mono] .plan-day[style] {
  background: var(--sunken) !important;
  --cat: var(--sunken) !important;
}
/* The status dots sit beside their own words, so one ink colour loses nothing.
   (The pie keeps `filter: grayscale()` instead: its slices must stay correlated
   with the legend swatches, and a single flat colour would erase that.) */
:root[data-mono] .dash-total__dot { background: var(--text) !important; }
