/* ============================================================================
   KINSCROLL — design tokens  ·  direction: "Register"
   ----------------------------------------------------------------------------
   Drop-in replacement for the :root block in index.html.

   Rule of the system: the interface chrome carries NO hue. Every chromatic
   pixel means something in the data — who a person is, whose line you are on,
   what is selected, what is wrong. Neutrals do all the structural work.

   Neutral hue  OKLCH 255  (barely-cool mineral grey — never cream, never black)
   Accent hue   OKLCH 152  Cedar — a dark, grey-cast green
   Person A     OKLCH 248  Lapis  (male-coded)
   Person B     OKLCH  71  Ochre  (female-coded)
   Danger       OKLCH  27  Madder red

   Every colour below was generated in OKLCH, gamut-clipped by chroma, and
   checked for WCAG contrast + protan/deutan/tritan separation. Ratios are in
   docs/design-system.md; do not hand-edit a value without re-checking it.

   FONTS — put this in <head>, replacing the current Crimson Pro link:

   <link rel="preconnect" href="https://fonts.googleapis.com">
   <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
   <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Amiri:wght@400;700&family=IBM+Plex+Mono:wght@400;500;600&family=IBM+Plex+Sans+Arabic:wght@400;500;600&family=IBM+Plex+Sans+Devanagari:wght@400;500;600&display=swap">

   The Arabic and Devanagari families cost one extra entry in a single
   stylesheet request and ZERO font bytes until a document actually renders
   those scripts — Google serves them behind unicode-range.
   CJK is deliberately NOT linked (megabytes); it falls through to the system
   faces listed in --font-ui.
   ========================================================================== */

:root {
  color-scheme: light dark;

  /* ---------------------------------------------------------------- type -- */
  /* ONE face carries the register. The old stack gave headings, body and
     numerals three different personalities, and a typewriter face on every
     microcap is most of what made a family register read as a code editor.
     Display and mono both resolve to the UI face. There was a --font-quote here,
     a real serif kept "for the hadith" — but the shipped design sets a hadith
     upright in the UI face on both the site and in the app, and the token was
     referenced nowhere. A face nothing uses is a comment that lies. */
  --font-ui:
    Inter, "IBM Plex Sans Arabic", "IBM Plex Sans Devanagari",
    "Segoe UI", Roboto, "Noto Sans", "Hiragino Sans", "Yu Gothic UI",
    "Microsoft YaHei", "PingFang SC", "Malgun Gothic", system-ui, sans-serif;
  --font-display: var(--font-ui);
  --font-mono:    var(--font-ui);
  /* for the rare place that genuinely wants a typewriter — nothing today */
  --font-mono-true:
    "IBM Plex Mono", ui-monospace, "SF Mono", Consolas, monospace;
  --font-arabic:  Amiri, "IBM Plex Sans Arabic", "Noto Naskh Arabic", serif;

  --serif: var(--font-display);
  --mono:  var(--font-mono);

  /* Anek Latin width axis. Apply with:
       font-variation-settings: "wdth" var(--wd-display);
     Narrow for the wordmark and headings, normal for running display text,
     wide for the small uppercase eyebrows. */
  --wd-narrow:  88;
  --wd-display: 96;
  --wd-normal: 100;
  --wd-wide:   112;

  --fw-regular:  400;
  --fw-medium:   500;
  --fw-semibold: 600;
  --fw-bold:     700;

  --fs-micro: 9.5px;
  --fs-2xs:  10.5px;
  --fs-xs:     11px;
  --fs-sm:     12px;
  --fs-base:   13px;   /* app body size — unchanged from today */
  --fs-md:     14px;
  --fs-lg:     16px;
  --fs-xl:     19px;
  --fs-2xl:    23px;
  --fs-3xl:    29px;
  --fs-4xl:    38px;
  --fs-5xl:    50px;

  --lh-flat:   1;
  --lh-tight:  1.12;
  --lh-snug:   1.3;
  --lh-normal: 1.5;
  --lh-loose:  1.7;

  --ls-tight:  -0.02em;
  --ls-snug:   -0.008em;
  --ls-normal: 0;
  --ls-wide:   0.06em;
  --ls-caps:   0.10em;   /* small uppercase labels */
  --ls-eyebrow:0.16em;   /* the widest tracking used anywhere */

  /* Numerals. Data columns, years, counts, IDs must not shimmy. */
  --num-tabular: "tnum" 1, "lnum" 1;
  --num-prose:   "pnum" 1, "onum" 0;

  /* --------------------------------------------------------------- space -- */
  --sp-0:   0;
  --sp-05:  2px;
  --sp-1:   4px;
  --sp-15:  6px;
  --sp-2:   8px;
  --sp-25: 10px;
  --sp-3:  12px;
  --sp-35: 14px;
  --sp-4:  16px;
  --sp-5:  20px;
  --sp-6:  24px;
  --sp-7:  28px;
  --sp-8:  32px;
  --sp-10: 40px;
  --sp-12: 48px;
  --sp-16: 64px;

  /* -------------------------------------------------------------- radius -- */
  --r-xs:    3px;
  --r-sm:    5px;
  --r-md:    8px;
  --r-lg:   12px;
  --r-xl:   18px;
  --r-full: 999px;

  /* -------------------------------------------------------------- motion -- */
  --dur-1:  90ms;   /* colour / opacity on a control        */
  --dur-2: 140ms;   /* hover, focus, small transforms       */
  --dur-3: 220ms;   /* panels opening, chips appearing      */
  --dur-4: 380ms;   /* view changes, camera settles         */
  --dur-5: 620ms;   /* the constellation reveal             */
  --ease-out:    cubic-bezier(0.20, 0.80, 0.28, 1);
  --ease-in-out: cubic-bezier(0.65, 0.00, 0.35, 1);
  --ease-spring: cubic-bezier(0.34, 1.42, 0.50, 1);
  --stagger: 90ms;  /* per-generation delay in the dots intro */

  /* ------------------------------------------------------------- z-index -- */
  --z-canvas:  0;   /* pan/zoom world                       */
  --z-wire:    1;   /* SVG ties beneath the cards           */
  --z-card:    2;   /* person cards / dots                  */
  --z-hud:    10;   /* zoom control, minimap, legend        */
  --z-header: 20;   /* app bar                              */
  --z-rail:   30;   /* generation rail, side panels         */
  --z-pop:    60;   /* dropdown panels, tooltips            */
  --z-sheet:  80;   /* bottom sheet / editor                */
  --z-toast:  90;
  --z-modal: 100;   /* scrim + dialog                       */

  /* ================================ COLOUR — LIGHT ======================== */

  /* ground */
  --bg:            #f3efe4;   /* page / world                          */
  --bg-sunk:       #e9e4d6;   /* recessed wells, inputs, empty states  */
  --surface:       #fbf8f0;   /* raised: header, panels, cards         */
  --surface-alt:   #f5f1e6;   /* zebra rows, hovered surface           */

  /* structure */
  --line:          #e2dccb;   /* default 1px border                    */
  --line-soft:     #ede8db;   /* internal dividers                     */
  --line-strong:   #bcb4a0;   /* emphasised edge, table head rule      */

  /* text */
  --text:          #262320;   /* 13.60:1 on --bg                      */
  --text-dim:      #544f43;   /* 7.09:1                               */
  --text-muted:    #736d5f;   /* 4.48:1 — the floor for any real text */
  --ink:           #f5f2ea;   /* text ON a dark/coloured fill          */
  --ink-soft:      #b9b3a4;   /* dimmed text on a dark fill            */

  /* accent — sea glass. Interaction, "your line", selection. Gold is the departed now. */
  --accent:        #37655a;   /* 5.76:1 — links, active state         */
  --accent-strong: #27514a;   /* 7.74:1 — hover, wordmark, series 3   */
  --accent-dim:    #4f7365;   /* 4.60:1 — accent text, still AA       */
  --accent-line:   #9dbaa3;   /*  1.91:1 — accent-tinted border only   */
  --accent-wash:   #e4ece5;   /* flat accent fill behind text          */

  /* person categories — load-bearing semantics */
  --male:          #44597a;   /* 6.18:1  Slate blue                   */
  --female:        #5b4c87;   /* 6.46:1  Violet                       */
  --neutral:       #736d5f;   /* 4.48:1  unknown / both               */
  --male-soft:     #b5bfd0;   /* gradient top, avatar wash             */
  --female-soft:   #c3bbd8;
  --neutral-soft:  #cbc5b6;
  --departed:      #8a6a2e;   /* 4.37:1  the closed rule under a departed name*/

  /* state */
  --danger:        #b3402e;   /*  5.40:1                               */
  --danger-wash:   #f4e2dc;
  --sel:           var(--accent-strong);  /* selected node, minimap box */

  /* rgb triplets, for rgb(... / alpha) composition */
  --rgb-bg: 242 239 230;
  --rgb-surface: 251 248 240;
  --rgb-text: 38 35 32;
  --rgb-accent: 55 101 90;
  --rgb-male: 68 89 122;
  --rgb-female: 91 76 135;
  --rgb-neutral: 125 120 105;

  /* accent tints — row hover, chip fill, focus halo */
  --wash-1: rgb(var(--rgb-accent) / .05);
  --wash-2: rgb(var(--rgb-accent) / .09);
  --wash-3: rgb(var(--rgb-accent) / .14);
  /* the ground the register is drawn on — warm paper, never the accent */
  --ground-a: rgb(138 106 46 / .075);
  --ground-b: rgb(138 106 46 / .05);
  --wash-4: rgb(var(--rgb-accent) / .22);

  /* neutral tints — dividers over imagery, pressed states */
  --tint-1: rgb(var(--rgb-text) / .04);
  --tint-2: rgb(var(--rgb-text) / .07);
  --tint-3: rgb(var(--rgb-text) / .12);

  /* the tree's SVG ties.
     --wire is for bulk strokes: thousands of them composite, so it is
     deliberately light. --wire-strong is for a single isolated or hovered
     tie, which must read on its own at 200%. */
  --wire:          rgb(var(--rgb-text) / .22);
  --wire-strong:   rgb(var(--rgb-text) / .40);
  --wire-hi:       var(--accent);          /* the lit kinship road */

  /* translucent chrome floating over the world */
  --glass:         rgb(var(--rgb-surface) / .92);
  --glass-heavy:   rgb(var(--rgb-surface) / .97);
  --scrim:         rgb(var(--rgb-text) / .38);

  /* shadow — tinted with the neutral hue, never pure black */
  --shadow-1: 0 1px 2px rgb(var(--rgb-text) / .06);
  --shadow-2: 0 2px 6px rgb(var(--rgb-text) / .08), 0 1px 2px rgb(var(--rgb-text) / .05);
  --shadow-3: 0 8px 20px rgb(var(--rgb-text) / .10), 0 2px 6px rgb(var(--rgb-text) / .06);
  --shadow-4: 0 20px 48px rgb(var(--rgb-text) / .14), 0 4px 12px rgb(var(--rgb-text) / .08);
  --edge-top: inset 0 1px 0 rgb(255 255 255 / .70);
  /* shadow colour for bespoke geometry the ramp above cannot express */
  --shadow-color:      transparent;
  --shadow-color-soft: transparent;

  /* focus — one ring, everywhere, never removed */
  --ring-color: var(--accent);
  --ring:       0 0 0 2px var(--bg), 0 0 0 4px var(--ring-color);
  --ring-inset: inset 0 0 0 2px var(--ring-color);

  /* the four user-selectable accents (keys must stay brass/jade/rose/sky —
     index.html persists them in localStorage under kinscroll.prefs) */
  --acc-brass:        #96722f;  --acc-brass-bright: #7f6024;  --acc-brass-dim: #a8935f;
  --acc-jade:         #37655a;  --acc-jade-bright:  #27514a;  --acc-jade-dim:  #5d8270;
  --acc-rose:         #8c3f52;  --acc-rose-bright:  #6b2f3f;  --acc-rose-dim:  #a06377;
  --acc-sky:          #48586b;  --acc-sky-bright:   #2c3946;  --acc-sky-dim:   #6b7b8e;
  --acc-brass-rgb: 150 114 47;   --acc-jade-rgb: 55 101 90;
  --acc-rose-rgb:  140 63 82;  --acc-sky-rgb:  72 88 107;
}

/* ================================= COLOUR — DARK ==========================
   Not an inversion. The dark theme is a slate theme: the ground is lifted
   well off black (L 0.208) because the tree draws thousands of hairlines and
   pure black both eats thin dark strokes and halates around bright ones.
   Chroma rises slightly at low lightness so the greys read as stone, not as
   dead grey. All chromatic tokens are re-picked for a dark ground, not
   lightened algorithmically.
   ======================================================================== */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:            #141414;
    --bg-sunk:       #0e0e0e;
    --surface:       #1f1f1f;
    --surface-alt:   #1a1a1a;

    --line:          #343434;
    --line-soft:     #262626;
    --line-strong:   #4a4a4a;

    --text:          #e7e5e1;   /* 14.49:1 on --bg */
    --text-dim:      #a3a09a;   /*  7.61:1 */
    --text-muted:    #757169;   /*  4.71:1 */
    --ink:           #1a1917;
    --ink-soft:      #57544d;

    --accent:        #8fbcb0;   /* 8.76:1  */
    --accent-strong: #a8ccc2;   /* 10.60:1 */
    --accent-dim:    #6f9a8f;   /* 5.87:1  */
    --accent-line:   #3c5a52;
    --accent-wash:   #1d2b27;

    --male:          #7f96b8;   /* 6.10:1  */
    --female:        #a493d6;   /* 6.78:1  */
    --neutral:       #8a8681;   /*  4.71:1 */
    --male-soft:     #333f52;
    --female-soft:   #443b5c;
    --neutral-soft:  #3a3936;
    --departed:      #c9a45e;

    --danger:        #d0604a;   /*  6.74:1 */
    --danger-wash:   #3a211c;

    --rgb-bg: 20 20 20;
    --rgb-surface: 31 31 31;
    --rgb-text: 231 229 225;
    --rgb-accent: 143 188 176;
    --rgb-male: 127 150 184;
    --rgb-female: 164 147 214;
    --rgb-neutral: 138 134 129;

    --wash-1: rgb(var(--rgb-accent) / .06);
    --wash-2: rgb(var(--rgb-accent) / .10);
    --wash-3: rgb(var(--rgb-accent) / .16);
    --ground-a: rgb(201 164 94 / .055);
    --ground-b: rgb(201 164 94 / .04);
    --wash-4: rgb(var(--rgb-accent) / .24);

    --tint-1: rgb(var(--rgb-text) / .04);
    --tint-2: rgb(var(--rgb-text) / .08);
    --tint-3: rgb(var(--rgb-text) / .14);

    --wire:        rgb(var(--rgb-text) / .20);
    --wire-strong: rgb(var(--rgb-text) / .34);

    --glass:       rgb(var(--rgb-surface) / .90);
    --glass-heavy: rgb(var(--rgb-surface) / .96);
    --scrim:       rgb(0 0 0 / .60);

    --shadow-1: 0 1px 2px rgb(0 0 0 / .40);
    --shadow-2: 0 2px 8px rgb(0 0 0 / .48), 0 1px 2px rgb(0 0 0 / .36);
    --shadow-3: 0 10px 28px rgb(0 0 0 / .56), 0 2px 8px rgb(0 0 0 / .40);
    --shadow-4: 0 24px 60px rgb(0 0 0 / .66), 0 6px 16px rgb(0 0 0 / .46);
    --edge-top: inset 0 1px 0 rgb(255 255 255 / .05);
    --shadow-color:      transparent;
    --shadow-color-soft: transparent;

    --acc-brass:        #c9a45e;  --acc-brass-bright: #d9b978;  --acc-brass-dim: #9a7f4b;
    --acc-jade:         #8fbcb0;  --acc-jade-bright:  #a8ccc2;  --acc-jade-dim:  #6f9a8f;
    --acc-rose:         #b98090;  --acc-rose-bright:  #d1a0ad;  --acc-rose-dim:  #976976;
    --acc-sky:          #8fa3b8;  --acc-sky-bright:   #adbfd1;  --acc-sky-dim:   #74869a;
    --acc-brass-rgb: 201 164 94; --acc-jade-rgb: 143 188 176;
    --acc-rose-rgb:  185 128 144; --acc-sky-rgb:  143 163 184;
  }
}

/* Explicit override wins in both directions, so the in-app toggle works
   whatever the OS says. Duplicated rather than @import-ed on purpose: one
   file, no build step, same as the app. */
:root[data-theme="dark"] {
  --bg:            #141414;
  --bg-sunk:       #0e0e0e;
  --surface:       #1f1f1f;
  --surface-alt:   #1a1a1a;

  --line:          #343434;
  --line-soft:     #262626;
  --line-strong:   #4a4a4a;

  --text:          #e7e5e1;
  --text-dim:      #a3a09a;
  --text-muted:    #757169;
  --ink:           #1a1917;
  --ink-soft:      #57544d;

  --accent:        #8fbcb0;
  --accent-strong: #a8ccc2;
  --accent-dim:    #6f9a8f;
  --accent-line:   #3c5a52;
  --accent-wash:   #1d2b27;

  --male:          #7f96b8;
  --female:        #a493d6;
  --neutral:       #8a8681;
  --male-soft:     #333f52;
  --female-soft:   #443b5c;
  --neutral-soft:  #3a3936;
  --departed:      #c9a45e;

  --danger:        #d0604a;
  --danger-wash:   #3a211c;

  --rgb-bg: 20 20 20;
  --rgb-surface: 31 31 31;
  --rgb-text: 231 229 225;
  --rgb-accent: 143 188 176;
  --rgb-male: 127 150 184;
  --rgb-female: 164 147 214;
  --rgb-neutral: 138 134 129;

  --wash-1: rgb(var(--rgb-accent) / .06);
  --wash-2: rgb(var(--rgb-accent) / .10);
  --wash-3: rgb(var(--rgb-accent) / .16);
  --wash-4: rgb(var(--rgb-accent) / .24);

  --tint-1: rgb(var(--rgb-text) / .04);
  --tint-2: rgb(var(--rgb-text) / .08);
  --tint-3: rgb(var(--rgb-text) / .14);

  --wire:        rgb(var(--rgb-text) / .20);
  --wire-strong: rgb(var(--rgb-text) / .34);

  --glass:       rgb(var(--rgb-surface) / .90);
  --glass-heavy: rgb(var(--rgb-surface) / .96);
  --scrim:       rgb(0 0 0 / .60);

  --shadow-1: 0 1px 2px rgb(0 0 0 / .40);
  --shadow-2: 0 2px 8px rgb(0 0 0 / .48), 0 1px 2px rgb(0 0 0 / .36);
  --shadow-3: 0 10px 28px rgb(0 0 0 / .56), 0 2px 8px rgb(0 0 0 / .40);
  --shadow-4: 0 24px 60px rgb(0 0 0 / .66), 0 6px 16px rgb(0 0 0 / .46);
  --edge-top: inset 0 1px 0 rgb(255 255 255 / .05);
  --shadow-color:      transparent;
  --shadow-color-soft: transparent;

  --acc-brass:        #c9a45e;  --acc-brass-bright: #d9b978;  --acc-brass-dim: #9a7f4b;
  --acc-jade:         #8fbcb0;  --acc-jade-bright:  #a8ccc2;  --acc-jade-dim:  #6f9a8f;
  --acc-rose:         #b98090;  --acc-rose-bright:  #d1a0ad;  --acc-rose-dim:  #976976;
  --acc-sky:          #8fa3b8;  --acc-sky-bright:   #adbfd1;  --acc-sky-dim:   #74869a;
  --acc-brass-rgb: 201 164 94; --acc-jade-rgb: 143 188 176;
  --acc-rose-rgb:  185 128 144; --acc-sky-rgb:  143 163 184;
}

/* ============================ LEGACY ALIASES ==============================
   index.html uses the old parchment names in ~400 places. These aliases let
   the new palette land with a single :root swap; delete them once every call
   site has been migrated to the semantic names above.

   Note the old names lie: --parchment is the TEXT colour and --ink is the
   INVERTED text colour. The aliases preserve the old meaning, not the old
   word.
   ======================================================================== */
:root {
  --felt:          var(--bg);
  --felt-deep:     var(--bg-sunk);
  --felt-line:     var(--line);
  --chrome:        var(--surface);
  --parchment:     var(--text);
  --parchment-dim: var(--text-dim);
  /* --ink / --ink-soft / --male / --female / --neutral / --danger keep their
     names and are defined above. */
  --brass:         var(--accent);
  --brass-bright:  var(--accent-strong);
  --brass-dim:     var(--accent-dim);
}

/* ============================== BASE ======================================
   The minimum the tokens assume. Everything else stays in index.html.
   ======================================================================== */

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-ui);
  font-size: var(--fs-base);
  line-height: var(--lh-normal);
  font-feature-settings: var(--num-tabular);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Display face: Anek Latin, held narrow. Used for the wordmark, person names,
   kinship terms, and view titles — nothing else. */
.display,
.wordmark,
h1, h2, h3 {
  font-family: var(--font-display);
  font-variation-settings: "wdth" var(--wd-display);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-snug);
  line-height: var(--lh-tight);
}

/* The one uppercase treatment in the system: wide-set Anek, small, muted.
   Section eyebrows and legend labels only. */
.eyebrow {
  font-family: var(--font-display);
  font-variation-settings: "wdth" var(--wd-wide);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-medium);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Data: years, counts, IDs, coordinates, generation numbers. */
.num, .mono {
  font-family: var(--font-mono);
  font-feature-settings: var(--num-tabular);
  font-variant-numeric: tabular-nums lining-nums;
}

:where(a, button, select, input, textarea, [tabindex]):focus-visible {
  outline: none;
  box-shadow: var(--ring);
  border-radius: var(--r-sm);
}

::selection { background: var(--wash-4); color: var(--text); }

@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-1: 1ms; --dur-2: 1ms; --dur-3: 1ms; --dur-4: 1ms; --dur-5: 1ms;
    --stagger: 0ms;
  }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}

/* Forced-colours (Windows high contrast): let the OS win, but keep the
   person categories distinguishable by giving them a shape channel too. */
@media (forced-colors: active) {
  .card.m, .card.f { forced-color-adjust: none; }
}
