/* ═══════════════════════════════════════════════════════════════════════════
   DESIGN TOKENS — Nafhan Family Tree
   Palette matched to Mockup/nafhan_family_tree_ULTIMATE_9.html (slate + amber
   glass aesthetic). Every variable NAME below is unchanged from before this
   pass — only the values changed — so nothing in JS or the rest of the CSS
   needed to be touched to pick this up.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Fonts (self-hosted, not a CDN request) ───────────────────────────────
   Inter + Plus Jakarta Sans, the mockup's own font pairing. Self-hosted
   (assets/fonts/) rather than loaded from Google Fonts, specifically so an
   installed PWA still renders the correct typeface offline — a CDN font
   request would silently fail with no network and fall back to a system
   font until reconnected. Both files are Google's own variable-weight
   latin-subset WOFF2 (the same files real Chrome/Edge/Safari get from
   fonts.googleapis.com), so one file each covers the whole weight range
   used below instead of needing one file per weight. */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('../fonts/inter-var-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 500 800;
  font-display: swap;
  src: url('../fonts/plus-jakarta-sans-var-latin.woff2') format('woff2');
}

:root {
  /* ── Brand ─────────────────────────────────────────────────────────────── */
  --navy-deep:    #0f172a;   /* slate-900 */
  --navy-royal:   #0f172a;   /* slate-900 */
  --blue-ocean:   #334155;   /* slate-700 — only used as a gradient stop today */
  --gold:         #f59e0b;   /* amber-500 — mockup's brand accent */
  --gold-bright:  #fbbf24;   /* amber-400 */
  --gold-deep:    #b45309;   /* amber-700 */
  /* Fixed, NOT redeclared in the light block below — unlike --gold (which
     light mode darkens to amber-700 so gold TEXT stays legible on a white
     card), the mockup's Guardian card border/photo-ring/focus-ring is the
     same amber-500 in both themes. Reusing the darkened --gold for those
     decorative accents was what made the Guardian card border look dull
     and muddy in light mode instead of the mockup's clean, saturated
     amber outline. */
  --accent-amber: #f59e0b;

  /* ── Semantic surfaces ─────────────────────────────────────────────────── */
  --bg:            #020617;   /* slate-950 — matches the mockup's dark --tree-bg */
  --bg-elevated:   #0f172a;   /* slate-900 */
  --surface:       #0f172a;   /* slate-900 */
  --surface-2:     #1e293b;   /* slate-800 */
  --surface-3:     #334155;   /* slate-700 */
  /* Outer stop matches --bg exactly — anything that fades toward --bg (the
     bottom-nav fade, the login screen's own edges) needs to land on the
     same colour the gradient has already settled into by the time it gets
     there, or the "fade" ends at a visibly different shade and reads as a
     hard-edged solid box instead of a smooth blend. */
  --stage-bg:      radial-gradient(circle at 50% 35%, #1e293b 0%, #0f172a 55%, var(--bg) 100%);

  /* ── Text ──────────────────────────────────────────────────────────────── */
  --text:          #f8fafc;   /* slate-50 */
  --text-muted:    #94a3b8;   /* slate-400 */
  --text-dim:      #64748b;   /* slate-500 */
  --text-on-gold:  #0f172a;   /* matches the mockup's own text-on-amber pairing */
  /* The mockup's primary-button colour actually INVERTS per theme — solid
     amber in dark mode, solid dark-slate in light mode — rather than just
     swapping shades of gold like the old button did. Kept as its own token
     pair (not reusing --gold) since it needs a genuinely different colour
     in light mode, not just a darker one. */
  --btn-primary-bg:       var(--gold);
  --btn-primary-bg-hover: var(--gold-bright);
  --btn-primary-text:     var(--text-on-gold);

  /* ── Lines & borders ───────────────────────────────────────────────────── */
  --line:          #334155;   /* slate-700 */
  --line-soft:     #1e293b;   /* slate-800 */
  --line-strong:   #475569;   /* slate-600 */

  /* ── Status ────────────────────────────────────────────────────────────── */
  --ok:            #10b981;   /* emerald-500 */
  --ok-soft:       rgba(16, 185, 129, .16);
  --warn:          #f59e0b;   /* amber-500 */
  --warn-soft:     rgba(245, 158, 11, .16);
  --danger:        #f43f5e;   /* rose-500 */
  --danger-soft:   rgba(244, 63, 94, .16);
  --info:          #0ea5e9;   /* sky-500 */
  --info-soft:     rgba(14, 165, 233, .16);
  /* Terracotta/burnt-orange — distinct from the rank amber, so a Ghost
     card doesn't read as "must be a Guardian" at a glance. Per the user's
     own hand-picked palette file (gemini-code-1787148691232.html). */
  --ghost:         #fb923c;   /* orange-400, dark-mode value (this is the dark :root default) */
  --ghost-soft:    rgba(251, 146, 60, .16);
  --divorced:      #64748b;   /* slate-500, dark-mode value */
  --divorced-soft: rgba(100, 116, 139, .16);

  /* ── Tree geometry ─────────────────────────────────────────────────────────
     Card dimensions taken directly from the mockup's own size presets
     (.size-standard / .size-compact / .size-large in
     nafhan_family_tree_ULTIMATE_9.html), not invented here:
        compact   180 × 75   (a horizontal row card — avatar left, text right)
        standard  188 × 224
        large     240 × 286
     --node-gap-x / --row-gap are this app's own layout-engine spacing (the
     mockup uses a different connector engine, so those don't transfer) and
     are tuned per preset to suit the card height above. */
  --node-w:        188px;
  --node-h:        224px;
  --node-photo:    72px;
  --node-gap-x:    36px;
  --row-gap:       106px;

  /* ── Radii ─────────────────────────────────────────────────────────────── */
  --r-sm:  10px;
  --r-md:  14px;   /* matches the mockup's form-input radius exactly */
  --r-lg:  20px;
  --r-xl:  28px;   /* matches the mockup's modal/panel radius */
  --r-pill: 999px;

  /* ── Elevation ─────────────────────────────────────────────────────────── */
  --sh-1: 0 2px 6px rgba(0,0,0,.25);
  --sh-2: 0 8px 24px rgba(0,0,0,.30);
  --sh-3: 0 20px 40px rgba(0,0,0,.40);
  --sh-4: 0 44px 80px rgba(0,0,0,.55);
  --glow-gold: 0 0 0 3px rgba(245,158,11,.25), 0 10px 30px rgba(245,158,11,.28);
  /* The mockup's glass tree-card has a faint inner highlight ring baked
     into its box-shadow, on top of the drop shadow — kept as its own
     token since it needs a different tint per theme (a hint of white on
     dark glass, a stronger white on light glass) and only the tree card
     uses it. */
  --node-inset: inset 0 0 0 1px rgba(255,255,255,.03);

  /* ── Type ──────────────────────────────────────────────────────────────── */
  --font: 'Inter', "Segoe UI", -apple-system, BlinkMacSystemFont, system-ui, Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-display: 'Plus Jakarta Sans', "Segoe UI Semibold", var(--font);
  /* The mockup always pairs --font-display with tight tracking on headings,
     names, and numeric metrics — one token instead of repeating the value
     at every call site. */
  --tracking-display: -0.02em;
  --fs-xs:   11px;
  --fs-sm:   13px;
  --fs-base: 15px;
  --fs-md:   17px;
  --fs-lg:   21px;
  --fs-xl:   27px;
  --fs-2xl:  34px;

  /* ── Motion ────────────────────────────────────────────────────────────── */
  /* The mockup's signature "lift" easing — used everywhere a card/panel
     settles into place (hover, focus, sheet/modal open). Replaces the old
     curve of the same name; every rule that already referenced --ease-out
     picks this up automatically. */
  --ease-out:  cubic-bezier(.16, 1, .3, 1);
  --ease-soft: cubic-bezier(.4, 0, .2, 1);
  --t-fast:   150ms;
  --t-base:   380ms;   /* was 240ms — matches the mockup's 0.4s card transition */
  --t-move:   500ms;   /* the documented ripple re-centre duration */

  /* ── Layers ────────────────────────────────────────────────────────────────
     One explicit stacking order, back to front — everything on screen has a
     documented home instead of a guessed number:
       1    the pan/zoom stage itself
       4    tree main connector lines   (.link--parent, .link--sibling)
       5    marriage / relation lines   (.link--spouse)
       6    ghost (pending) link lines  (.link--ghost)
       7    member cards                (.node, .nodes)
       8    header, bottom nav, floating zoom/share controls
       8.5  the selected / centred card, and any card mid-hover — just proud
            of the header so it never gets clipped at the top edge
       9    dropdowns & popovers (profile menu, notifications, search)
       10   full-detail popups (member card modal, add/edit forms, confirms)
       11   toasts — must stay visible even while a popup is open
       12   full-screen boot/login cover                                      */
  --z-canvas:        1;
  --z-tree-line:     4;
  --z-marriage-line: 5;
  --z-ghost-line:    6;
  --z-node:          7;
  --z-controls:      8;
  --z-topbar:        8;
  --z-node-selected: 8.5;
  --z-menu:          9;
  --z-sheet:         10;
  --z-modal:         10;
  --z-toast:         11;
  --z-screen:        12;

  /* ── Layout rhythm ─────────────────────────────────────────────────────── */
  --topbar-h:    58px;
  /* Gap between the floating topbar/bottom-dock and the screen edge — the
     mockup floats the header on desktop too, not just mobile, so this is
     no longer a mobile-only value (see layout.css's mobile query for the
     slightly tighter override). */
  --float-gap:   14px;
  --crumb-h:     40px;
  --bottomnav-h: 62px;
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-t: env(safe-area-inset-top, 0px);
}

/* ── Light theme ─────────────────────────────────────────────────────────── */
:root[data-theme="light"] {
  --bg:          #f8fafc;   /* slate-50 — mockup's light --tree-bg */
  --bg-elevated: #ffffff;
  --surface:     #ffffff;
  --surface-2:   #f1f5f9;   /* slate-100 */
  --surface-3:   #e2e8f0;   /* slate-200 */
  --stage-bg:    radial-gradient(circle at 50% 30%, #ffffff 0%, #f1f5f9 55%, var(--bg) 100%);
  --text:        #0f172a;   /* slate-900 */
  --text-muted:  #475569;   /* slate-600 */
  --text-dim:    #94a3b8;   /* slate-400 */
  --line:        #e2e8f0;   /* slate-200 — mockup's light card-border */
  --line-soft:   #f1f5f9;
  --line-strong: #cbd5e1;   /* slate-300 */
  --gold:        #d97706;   /* amber-600 — matches the mockup's own light-mode text-amber-600 (guardian name, relation text, etc.); the earlier amber-700 was darker than the mockup ever actually uses and read as dull. */
  --gold-bright: #f59e0b;   /* amber-500 */
  --btn-primary-bg:       #0f172a;   /* slate-900 — mockup's light-mode primary is dark, not amber */
  --btn-primary-bg-hover: #1e293b;   /* slate-800 */
  --btn-primary-text:     #ffffff;
  --sh-1: 0 2px 6px rgba(15,23,42,.06);
  --sh-2: 0 10px 40px rgba(15,23,42,.08);
  --sh-3: 0 20px 40px rgba(15,23,42,.12);
  --sh-4: 0 32px 70px rgba(15,23,42,.18);
  --glow-gold: 0 0 0 3px rgba(180,83,9,.18), 0 10px 26px rgba(180,83,9,.20);
  --node-inset: inset 0 0 0 1px rgba(255,255,255,.5);
  --ghost:      #ea580c;   /* orange-600 — deeper than dark mode's orange-400 for contrast on white */
  --ghost-soft: rgba(234, 88, 12, .14);
  --divorced:      #94a3b8;   /* slate-400 — lighter than dark mode's slate-500 for contrast on white */
  --divorced-soft: rgba(148, 163, 184, .16);
}

/* ── Compact / large node presets (admin "Node size" setting) ────────────── */
:root[data-nodesize="compact"] { --node-w: 160px; --node-h: 196px; --node-photo: 80px; --row-gap: 92px; }
:root[data-nodesize="large"]   { --node-w: 212px; --node-h: 254px; --node-photo: 110px; --row-gap: 122px; }

/* Only shrinks the default/"standard" size on mobile — compact and large
   each keep their own values above (a plain `:root` rule here has the same
   specificity as the base standard rule, so without :not() it would win by
   source order alone and shrink standard BELOW compact's protected value,
   which is exactly the bug this guards against). */
@media (max-width: 720px) {
  :root:not([data-nodesize="compact"]):not([data-nodesize="large"]) {
    --node-w: 172px; --node-h: 210px; --node-photo: 88px; --node-gap-x: 22px; --row-gap: 88px;
  }
}
