/* ============================================================
   Quraysh tree — visual system
   ============================================================ */

:root {
  /* Page surfaces */
  --bg:        #15171c;
  --bg2:       #1b1e25;
  --halo:      #20242c;          /* radial-gradient apex on <body> */

  /* Frames + borders */
  --frame:     rgba(255,255,255,.11);
  --frame-fill:rgba(255,255,255,.018);

  /* Cards */
  --card:      #232830;
  --card-hover:#272d36;
  --card-bd:   rgba(255,255,255,.09);
  --card-bd2:  rgba(255,255,255,.16);
  --card-shadow: none;

  /* Text */
  --txt:       #e8eaee;
  --muted:     #99a1ad;
  --faint:     #6d7480;

  /* Lines & connectors */
  --line:      rgba(200,206,216,.22);
  --link:      rgba(220,226,236,.62);    /* SVG connector stroke */
  --link-on:   rgba(245,248,252,.95);    /* focused connector */
  --arrow:     rgba(220,226,236,.9);

  /* UI panels (toolbar, dropdowns, minimap, tray) */
  --bar:       rgba(18,20,25,.92);
  --panel:     #1e222a;
  --hint-bg:   rgba(22,24,29,.78);
  --olab-bg:   rgba(20,22,27,.92);
  --focus-bg:  #2a2f38;

  /* Inputs & buttons */
  --btn:       rgba(255,255,255,.06);
  --btn-hover: rgba(255,255,255,.13);
  --input:     #20242b;
  --hover-bg:  rgba(255,255,255,.05);

  /* Overlays */
  --overlay:   rgba(10,11,14,.85);
  --whub:      #20242c;

  /* Root card gradient */
  --root-grad: linear-gradient(160deg, #2c333d, #222831);
  --olab-root-grad: linear-gradient(160deg, #2c333d, #1e222a);

  /* clan accents — soft, low-saturation pastels designed for the
     dark page. They read as accents against the navy background
     without overpowering the cards. */
  --hashim:    #6db3a3;
  --abdshams:  #dd9085;
  --nawfal:    #82b2d0;
  --muttalib:  #ad9ed6;
  --abddar:    #d9b97a;
  --asad:      #8aa6e0;
  --zuhra:     #d492b4;
  --taym:      #93c79a;
  --makhzum:   #d09f6e;
  --adi:       #bbbd83;
  --sahm:      #79c3cf;
  --jumah:     #c79bcf;
  --amir:      #d4b37f;
  --sama:      #9aa0a8;
  --fihri:     #9aa0a8;
  --spine:     #cbb68c;

  /* Foreground text drawn on top of a clan-colored fill (badges,
     wheel labels, .btn.on highlight). Dark in dark mode (because
     clan colors are pastel light), white in light mode (because
     clan colors there are deep). */
  --clan-fg:   #13161b;
}

/* ----------------------------------------------------------------
   LIGHT MODE
   Cool, modern, app-like surface. The background is a soft cool
   gray-blue so the saturated clan accents pop — every clan reads
   as a distinct color at a glance, even between neighbours that
   share a hue family (e.g. Nawfal blue vs Asad indigo, Hashim
   teal vs Sahm cyan vs Taym forest green).

   Each clan accent is tuned to ~32-40% lightness with 55-75%
   saturation, intentionally diverging from its hue-neighbours by
   ≥30 degrees of hue OR ≥15 percentage points of saturation so
   no two clans visually collide.
   ---------------------------------------------------------------- */
body.light {
  /* Page surfaces — cool light gray-blue with a brighter halo at
     the top so the radial gradient reads as gentle "page light." */
  --bg:        #eef0f4;
  --bg2:       #dde0e8;
  --halo:      #fbfcfd;

  /* Frame outlines for clan boundaries — visible slate at this
     opacity so each clan box is traced without overpowering its
     contents. */
  --frame:     rgba(28,38,55,.32);
  --frame-fill:rgba(28,38,55,.025);

  /* Cards — pure white surface, layered soft shadows, hairline
     dark border for crispness. */
  --card:      #ffffff;
  --card-hover:#f6f8fb;
  --card-bd:   rgba(28,38,55,.14);
  --card-bd2:  rgba(28,38,55,.34);
  --card-shadow:
    0 1px 2px rgba(20,30,40,.06),
    0 2px 6px rgba(20,30,40,.05),
    0 6px 18px rgba(20,30,40,.06);

  /* Type — near-black navy for strong reading contrast. */
  --txt:       #0d1320;
  --muted:     #3a4254;
  --faint:     #6c7484;

  /* Connectors — confident slate strokes that read at every zoom. */
  --line:      rgba(36,48,70,.42);
  --link:      rgba(32,46,72,.72);
  --link-on:   rgba(8,16,38,.96);
  --arrow:     rgba(32,46,72,.92);

  /* Toolbar / panels — translucent cool surface with a clear
     bottom edge. */
  --bar:       rgba(244,246,250,.92);
  --panel:     #ffffff;
  --hint-bg:   rgba(244,246,250,.88);
  --olab-bg:   rgba(251,252,254,.96);
  --focus-bg:  #ffffff;

  /* Inputs & buttons. */
  --btn:       rgba(28,38,55,.07);
  --btn-hover: rgba(28,38,55,.14);
  --input:     #ffffff;
  --hover-bg:  rgba(28,38,55,.05);

  /* Overlays. */
  --overlay:   rgba(18,24,38,.50);
  --whub:      #ffffff;

  /* Subtle cool gradient on the root card + root label. */
  --root-grad: linear-gradient(160deg, #ffffff 0%, #e1e8f1 100%);
  --olab-root-grad: linear-gradient(160deg, #ffffff 0%, #e1e8f1 100%);

  /* ──────────────────────────────────────────────────────────
     Clan accents — light mode palette tuned for distinctness.

     Within each hue family we pull each clan toward a different
     part of the spectrum so siblings don't blur together:

       Teal/cyan/green band  : Hashim (teal) – Sahm (clear cyan)
                               – Taym (forest green) – Adi (olive)
       Blue band             : Nawfal (medium blue) – Asad (navy)
       Purple/magenta band   : Muttalib (violet) – Jumah (magenta)
                               – Zuhra (rose)
       Warm band             : Abdshams (terracotta) – Makhzum
                               (rust orange) – Abddar (yellow amber)
                               – Amir (warm brown) – Spine (bronze)
       Neutral band          : Sama (cool slate) – Fihri (warm taupe)

     White (`--clan-fg`) reads cleanly on every one of them.
     ────────────────────────────────────────────────────────── */
  --hashim:    #0d7a73;   /* teal — green-cyan side of the family */
  --abdshams:  #c43a26;   /* vivid red-terracotta */
  --nawfal:    #2369a3;   /* medium clear blue */
  --muttalib:  #5b3ea1;   /* violet — blue-purple side */
  --abddar:    #b8870c;   /* yellow-amber (clearly the "yellow" clan) */
  --asad:      #2e4197;   /* navy indigo (darker, bluer than nawfal) */
  --zuhra:     #b13160;   /* rose — pink-red side of the magenta family */
  --taym:      #287f3a;   /* forest green (clearly green, not teal) */
  --makhzum:   #b25212;   /* orange rust (more orange than abdshams) */
  --adi:       #7a7a16;   /* yellow-olive (greenish gold) */
  --sahm:      #0f87a0;   /* clear cyan (bluer than hashim) */
  --jumah:     #8a288a;   /* magenta — red-purple side */
  --amir:      #885014;   /* warm brown (darker than abddar) */
  --sama:      #525968;   /* cool slate */
  --fihri:     #6f6448;   /* warm taupe — distinct from sama */
  --spine:     #6b541a;   /* bronze (darker than amir) */

  /* White text on the rich clan fills. */
  --clan-fg:   #ffffff;
}

/* Light-mode extras that don't fit cleanly into variable swaps. */
body.light .bar {
  /* A whisper of warmth under the toolbar — separates it from the
     tree without a hard line. */
  box-shadow: 0 1px 0 rgba(28,38,55,.05), 0 8px 24px rgba(28,38,55,.04);
}
body.light .nd.root,
body.light .olab-root {
  /* Cool blue-tinted rim around the root card so it reads as the
     "frontispiece" of the tree without clashing with the gray-blue
     background. */
  box-shadow:
    0 1px 2px rgba(20,30,40,.08),
    0 6px 22px rgba(35,105,163,.12);
}
body.light .nd:hover {
  box-shadow:
    0 1px 2px rgba(20,30,40,.08),
    0 4px 12px rgba(20,30,40,.10),
    0 10px 28px rgba(20,30,40,.10);
}
body.light .mini,
body.light .zoomctl button,
body.light .savemenu,
body.light .cmptray {
  /* Distinct, more confident shadow than the dark-mode equivalents
     (where the dark backdrop alone provides separation). */
  box-shadow:
    0 1px 2px rgba(20,30,40,.06),
    0 8px 28px rgba(20,30,40,.10);
}
body.light .results {
  box-shadow:
    0 4px 12px rgba(20,30,40,.08),
    0 16px 40px rgba(20,30,40,.12);
}
body.light .modal .mcard {
  box-shadow: 0 22px 60px rgba(20,30,40,.22);
}
/* Soften the title for light mode — the heavy white-on-dark
   weight is overpowering on a cream page. */
body.light .ttl {
  color: var(--txt);
  letter-spacing: 0;
}
/* Search input in light mode benefits from a soft inner highlight
   to read as a sunken field rather than a flat box. */
body.light .search input {
  box-shadow: inset 0 1px 2px rgba(20,30,40,.04);
}
body.light .search input:focus {
  box-shadow: inset 0 1px 2px rgba(20,30,40,.05),
              0 0 0 3px rgba(35,105,163,.20);
  border-color: rgba(35,105,163,.5);
}

* { box-sizing: border-box; }
html, body {
  margin: 0; padding: 0; height: 100%;
  overflow: hidden;
  background: var(--bg);
}
body {
  font-family: 'Amiri', Tahoma, serif;
  color: var(--txt);
  background: radial-gradient(1200px 700px at 50% -8%, var(--halo), var(--bg) 60%);
  transition: background-color .2s, color .2s;
}

/* ---------- top bar ---------- */
.bar {
  position: fixed; top: 0; inset-inline: 0; z-index: 40;
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  padding: 9px 14px;
  background: var(--bar);
  border-bottom: 1px solid var(--card-bd);
  backdrop-filter: blur(8px);
}
/* Brand block — site logo on the right (RTL start of toolbar) with
   the current tree name beside it in a quieter weight. The brand
   takes the auto-margin so the search/buttons cluster on the left. */
.brand {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-inline-end: auto;
  white-space: nowrap;
}
.logo {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: 'Reem Kufi', sans-serif;
  font-weight: 700;
  font-size: clamp(1rem, 3vw, 1.35rem);
  color: var(--txt);
  letter-spacing: .015em;
  text-decoration: none;
  padding: 2px 8px;
  margin-inline-start: -8px;  /* counter the padding so visual edge stays put */
  border-radius: 8px;
  transition: color .15s, background-color .15s;
}
.logo-text { line-height: 1; }
.logo:hover {
  background: var(--btn);
}
.logo:hover .logo-text { color: var(--spine); }
.logo:focus-visible {
  outline: 2px solid var(--spine);
  outline-offset: 2px;
}

/* Logo mark — the genealogy tree icon. Tinted gold so the brand
   identity carries the warm-accent thread that runs through the
   rest of the UI. A whisper of rotation on hover gives the icon
   a moment of life without being distracting. */
.logo-mark {
  width: clamp(26px, 4vw, 32px);
  height: clamp(26px, 4vw, 32px);
  color: var(--spine);
  flex-shrink: 0;
  transition: transform .25s cubic-bezier(.4, 0, .2, 1);
}
.logo:hover .logo-mark {
  transform: rotate(-4deg) scale(1.05);
}
.tree-name {
  font-family: 'Reem Kufi', sans-serif;
  font-weight: 500;
  font-size: clamp(.72rem, 2vw, .82rem);
  color: var(--muted);
  letter-spacing: .01em;
}
/* Subtle separator dot/slash before the tree name. */
.tree-name::before {
  content: "—";
  color: var(--faint);
  margin-inline-end: 4px;
  font-weight: 400;
}
.search {
  position: relative; flex: 1 1 220px; max-width: 340px; min-width: 150px;
}
.search input {
  width: 100%; font-family: 'Amiri', serif; font-size: .96rem;
  color: var(--txt);
  background: var(--input); border: 1px solid var(--card-bd2);
  border-radius: 10px; padding: 9px 34px 9px 12px; outline: none;
  transition: background-color .2s, border-color .2s;
}
.search input:focus { border-color: var(--hashim); }
.search svg {
  position: absolute; inset-inline-start: 11px; top: 50%;
  transform: translateY(-50%); opacity: .5;
}
.results {
  position: absolute; top: 46px; inset-inline: 0;
  background: var(--panel); border: 1px solid var(--card-bd2);
  border-radius: 11px; box-shadow: 0 16px 40px rgba(0,0,0,.35);
  overflow: hidden auto; max-height: 52vh; display: none; z-index: 50;
}
.results.show { display: block; }
.results button {
  display: flex; width: 100%; gap: 8px;
  justify-content: space-between; align-items: center;
  background: none; border: 0; border-bottom: 1px solid var(--card-bd);
  padding: 9px 12px; cursor: pointer; text-align: right;
  font-family: 'Amiri', serif; color: var(--txt);
}
.results button:hover { background: var(--hover-bg); }
.results .rn { font-weight: 700; }
.results .rc {
  font-family: 'Reem Kufi', sans-serif; font-size: .66rem;
  color: var(--clan-fg); padding: 1px 9px; border-radius: 12px; white-space: nowrap;
}
.results .empty {
  padding: 13px; text-align: center; color: var(--muted);
  font-family: 'Reem Kufi', sans-serif; font-size: .84rem;
}
.btn {
  font-family: 'Reem Kufi', sans-serif; font-size: .76rem;
  cursor: pointer; color: var(--txt);
  background: var(--btn);
  border: 1px solid var(--card-bd2);
  border-radius: 9px; padding: 9px 12px;
  transition: background .15s, border-color .15s; white-space: nowrap;
}
.btn:hover { background: var(--btn-hover); }
.btn.on   { background: var(--hashim); color: var(--clan-fg); border-color: transparent; font-weight: 600; }

/* Theme toggle — single glyph (sun in dark mode, moon in light) so
   the icon shows the OUTCOME of clicking. Slightly wider padding
   than a text button so the icon doesn't feel cramped. */
.btn.btn-theme {
  font-size: 1rem;
  line-height: 1;
  padding: 7px 11px;
  min-width: 38px;
}

/* ────────────────────────────────────────────────────────────────
   FONT SCALE
   `--font-scale` multiplies both the rem-based font sizes AND the
   px-based card dimensions inside the tree (paddings, max-width).
   It's fixed at 1.20 — the formerly-"large" setting — for clear
   reading. 1.20 keeps the 160-px list card at 192 px, still safely
   inside XGAP=200 so no neighbour columns collide. The toolbar/UI
   is not affected — only nodes in the tree scale.
   ──────────────────────────────────────────────────────────────── */
body { --font-scale: 1.20; }

/* ---------- canvas ----------
   direction: ltr is critical here. The tree is laid out in numeric
   pixel coordinates from a fixed origin, so the canvas subtree must
   use left-to-right CSS positioning even though the surrounding UI
   text is RTL. Without this, RTL flips empty absolutely-positioned
   elements to the right edge of their containing block. */
#canvas { position: fixed; inset: 0; overflow: hidden; cursor: grab; touch-action: none; direction: ltr; }
#canvas.grabbing { cursor: grabbing; }
#world   { position: absolute; top: 0; left: 0; transform-origin: 0 0; }
#world.grab .nd, #world.grab .frame { pointer-events: none; }

#links   { position: absolute; top: 0; left: 0; overflow: visible; }
/* Connectors render at a constant light-grey, regardless of clan
   color. The per-clan accent is preserved on focused lines only —
   see #world.dim ... .on rule below — so the macro view stays
   legible against the dark background. */
#links path {
  fill: none;
  stroke: var(--link);
  stroke-width: 2.5;
  /* Keep stroke at a constant on-screen width regardless of zoom. */
  vector-effect: non-scaling-stroke;
  stroke-linecap: square;
  stroke-linejoin: miter;
}
#links path.on {
  stroke: var(--link-on);
  stroke-width: 3;
}
#links #arrowhead path { fill: var(--arrow); stroke: none; }
#frames  { position: absolute; top: 0; left: 0; }
#nodes   { position: absolute; top: 0; left: 0; }

/* ---------- clan frames ---------- */
.frame {
  position: absolute;
  border: 1px solid var(--frame);
  background: var(--frame-fill);
  border-radius: 18px;
  cursor: pointer;
  transition: border-color .18s, background .18s;
}
.frame:hover {
  border-color: var(--fc);
  background: var(--fcb);
}
/* Inline labels left for fallback / printing — hidden because the
   overlay layer renders them at a constant readable size. */
.frame .flab, .frame .fcount { display: none; }

/* ---------- frame label overlay ----------
   Lives outside the scaled #world, so labels stay legible regardless
   of zoom. Tags follow their clan box by being positioned in screen
   coords every frame. */
#overlayLabels {
  position: absolute; inset: 0;
  pointer-events: none;
  font-family: 'Reem Kufi', sans-serif;
}
.olab {
  position: absolute;
  display: flex; align-items: center; gap: 8px;
  pointer-events: auto; cursor: pointer;
  background: var(--olab-bg);
  border: 1px solid var(--frame);
  border-radius: 12px;
  padding: 4px 12px;
  transform: translate(-50%, -50%);
  white-space: nowrap;
  transition: background .15s, border-color .15s, transform .12s;
  box-shadow: 0 4px 14px rgba(0,0,0,.25);
}
.olab:hover {
  background: var(--olab-bg);
  filter: brightness(1.08);
  border-color: var(--fc);
  transform: translate(-50%, -50%) scale(1.04);
}
.olab .olname {
  font-size: 1rem; font-weight: 700; color: var(--fc); line-height: 1;
}
.olab .olcount {
  font-size: .7rem; color: var(--faint); line-height: 1;
}
.olab-root {
  background: var(--olab-root-grad);
  border-color: var(--spine);
}
.olab-root .olname { font-size: 1.15rem; }
.olab-root .olcount { color: var(--spine); }
/* Compact form: shown when the canvas viewport is small. */
@media (max-width: 720px) {
  .olab .olname { font-size: .9rem; }
  .olab .olcount { display: none; }
}

/* ---------- node cards ---------- */
.nd {
  position: absolute;
  transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center;
  text-align: center;
  background: var(--card);
  border: 1px solid var(--card-bd);
  border-radius: 12px;
  padding: calc(6px * var(--font-scale)) calc(11px * var(--font-scale));
  max-width: calc(110px * var(--font-scale));
  min-width:  calc(52px  * var(--font-scale));
  cursor: pointer;
  transition: border-color .15s, background .15s, opacity .3s, box-shadow .2s;
  border-top: 3px solid var(--ac);
  box-shadow: var(--card-shadow);
  /* Restore RTL text inside each card so Arabic renders correctly. */
  direction: rtl;
}
.frame { direction: rtl; }
.nd:hover {
  border-color: var(--card-bd2);
  background: var(--card-hover);
}
.nd .nm { font-weight: 700; font-size: calc(1rem * var(--font-scale)); line-height: 1.28; color: var(--txt); }
.nd .rl {
  font-family: 'Reem Kufi', sans-serif; font-size: calc(.62rem * var(--font-scale));
  color: var(--muted); margin-top: 2px; line-height: 1.25;
}
.nd .bdg {
  font-family: 'Reem Kufi', sans-serif; font-size: calc(.56rem * var(--font-scale));
  color: var(--clan-fg); border-radius: 10px; padding: 0 7px; margin-top: 4px;
}
.nd.root {
  background: var(--root-grad);
  border-top: 3px solid var(--spine);
  padding: calc(11px * var(--font-scale)) calc(18px * var(--font-scale));
  max-width: none;
}
.nd.root .nm { font-size: calc(1.3rem * var(--font-scale)); }
.nd.root .rl { color: #cbb68c; }
.nd.eponym         { background: var(--card-hover); }
.nd.eponym .nm     { font-size: 1.06rem; color: var(--ac); }
.nd.tag-prophet    { box-shadow: 0 0 0 2px rgba(109,179,163,.4); }
.nd .era {
  position: absolute; top: -7px; inset-inline-end: -6px;
  font-size: .62rem; color: #13161b;
  background: var(--spine);
  border-radius: 50%; width: 15px; height: 15px; line-height: 15px;
  display: none;
}
body.era .nd.is-era .era { display: block; }

/* ---------- list card (bullet-collapsed siblings) ----------
   max-width stays below XGAP (200 in tree.js) by a comfortable margin
   so adjacent list cards don't bleed into each other. Within each
   item, name + dot + badge + era sit on row 1; the role drops to its
   own line on row 2 so long names get the full row width. Wrapping is
   enabled — names that still overflow flow onto a second line rather
   than being clipped with an ellipsis. */
.nd.list {
  text-align: right;
  align-items: stretch;
  /* Explicit width so the grid inside has a known canvas to allocate
     col-2 (the name column) into. Without it, the card shrink-wraps to
     min-content and Arabic word-break crushes names down to single
     characters. The width scales with --font-scale; at "large" (1.20)
     the card is 192 px — still inside XGAP=200 in tree.js. */
  width:     calc(160px * var(--font-scale));
  max-width: calc(160px * var(--font-scale));
  min-width: calc(160px * var(--font-scale));
  padding: calc(6px * var(--font-scale)) calc(8px * var(--font-scale));
  border-top: 3px solid var(--ac);
  background: var(--card);
}
.nd.list .lbody { display: flex; flex-direction: column; gap: 6px; }
/* Each item is a 3-col grid:
     col 1 = dot, col 2 = name/role (1fr), col 3 = era / badge.
   Row 1: dot | name | era   — name gets the full col-2 width so it
   rarely wraps. Row 2: . | role | badge — the secondary info drops
   beneath the name on its own line. */
.nd.list .li {
  display: grid;
  grid-template-columns: auto 1fr auto;
  column-gap: 6px;
  row-gap: 1px;
  align-items: center;
  font-family: 'Amiri', serif; font-size: .9rem; color: var(--txt);
  padding: 3px 4px; border-radius: 7px;
  line-height: 1.3;
  position: relative;
}
.nd.list .li:hover { background: var(--hover-bg); }
.nd.list .li.hit  { background: rgba(203,182,140,.18); }
.nd.list .ldot {
  grid-column: 1; grid-row: 1;
  width: 6px; height: 6px; border-radius: 50%;
}
.nd.list .ln {
  grid-column: 2; grid-row: 1;
  font-size: calc(.82rem * var(--font-scale));
  font-weight: 700;
  white-space: normal;
  overflow-wrap: break-word;
  line-height: 1.25;
}
.nd.list .lr {
  grid-column: 2; grid-row: 2;
  font-family: 'Reem Kufi', sans-serif; font-size: calc(.56rem * var(--font-scale));
  color: var(--muted);
  white-space: normal;
  line-height: 1.3;
}
.nd.list .lbdg {
  grid-column: 3; grid-row: 2;
  font-family: 'Reem Kufi', sans-serif; font-size: calc(.5rem * var(--font-scale));
  color: var(--clan-fg); padding: 0 5px; border-radius: 8px;
  justify-self: end;
}
.nd.list .lera {
  grid-column: 3; grid-row: 1;
  font-size: .58rem; color: #cbb68c;
  display: none;
  justify-self: end;
}
body.era .nd.list .li.is-era .lera { display: inline; }

/* ---------- focus / dim ---------- */
#world.dim .nd:not(.on)         { opacity: .12; }
#world.dim .frame:not(.on)      { opacity: .18; }
#world.dim #links path:not(.on) { opacity: .06; }

.nd.flash { animation: fl 1.1s ease 2; }
@keyframes fl {
  0%, 100% { box-shadow: 0 0 0 2px var(--spine); }
  50%      { box-shadow: 0 0 0 9px rgba(203,182,140,.45); }
}

/* ---------- zoom controls + minimap + hint ---------- */
.zoomctl {
  position: fixed; bottom: 16px; inset-inline-start: 14px;
  z-index: 35; display: flex; flex-direction: column; gap: 6px;
}
.zoomctl button {
  width: 40px; height: 40px; font-size: 1.2rem; border-radius: 11px;
  border: 1px solid var(--card-bd2);
  background: var(--bar); color: var(--txt);
  cursor: pointer; font-family: 'Reem Kufi', sans-serif;
  backdrop-filter: blur(6px);
}
.zoomctl button:hover { background: var(--btn-hover); }
.zoomctl .fit { font-size: .62rem; height: auto; padding: 7px 3px; line-height: 1.15; }

.mini {
  position: fixed; bottom: 16px; inset-inline-end: 14px; z-index: 35;
  width: 220px; height: 130px;
  background: var(--bar);
  border: 1px solid var(--card-bd2);
  border-radius: 12px;
  padding: 6px; cursor: crosshair;
  box-shadow: 0 10px 28px rgba(0,0,0,.25);
  backdrop-filter: blur(6px);
}
.mini svg { width: 100%; height: 100%; display: block; }
/* vector-effect lets us use real pixel stroke widths regardless
   of the SVG's non-uniform scaling. */
.mini .mf       { transition: opacity .15s; cursor: pointer; vector-effect: non-scaling-stroke; }
.mini .mf:hover { opacity: .85; stroke: #fff; stroke-width: 1.5; }
.mini #miniVp {
  fill: rgba(203,182,140,.18);
  stroke: rgba(203,182,140,.9);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}

.hint {
  position: fixed; bottom: 158px; inset-inline-end: 14px; z-index: 35;
  font-family: 'Reem Kufi', sans-serif; font-size: .7rem;
  color: var(--muted);
  background: var(--hint-bg);
  border: 1px solid var(--card-bd);
  border-radius: 10px;
  padding: 7px 12px; max-width: 240px; line-height: 1.6;
  backdrop-filter: blur(6px);
}

.focusban {
  position: fixed; top: 56px; inset-inline: 0; z-index: 34;
  display: none; justify-content: center; pointer-events: none;
}
.focusban.show { display: flex; }
.focusban span {
  pointer-events: auto;
  background: var(--focus-bg); color: var(--txt);
  border: 1px solid var(--card-bd2);
  font-family: 'Reem Kufi', sans-serif; font-size: .8rem;
  padding: 6px 8px 6px 14px; border-radius: 18px;
  box-shadow: 0 8px 22px rgba(0,0,0,.25);
  display: flex; gap: 10px; align-items: center;
}
.focusban b {
  cursor: pointer; color: #13161b;
  background: var(--spine);
  padding: 3px 11px; border-radius: 14px; font-weight: 600;
}

/* ---------- wheel overlay ---------- */
.overlay {
  position: fixed; inset: 0; z-index: 60;
  background: var(--overlay);
  display: none; align-items: center; justify-content: center;
  flex-direction: column; padding: 66px 14px 18px;
  backdrop-filter: blur(10px);
}
.overlay.show { display: flex; animation: fade .3s ease both; }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
.overlay h2 {
  font-family: 'Reem Kufi', sans-serif; font-weight: 700;
  color: var(--txt); margin: 0 0 3px;
  font-size: clamp(1.1rem, 3.5vw, 1.6rem);
}
.overlay p {
  font-family: 'Reem Kufi', sans-serif; color: var(--muted);
  font-size: .8rem; margin: 0 0 8px;
}
#wheelSvg { width: min(86vw, 540px); height: auto; max-height: 64vh; overflow: visible; }
.wedge { cursor: pointer; }
.wedge:hover .seg { filter: brightness(1.12); }
.wedge:hover text { fill: #fff; }
.seg   { stroke: var(--bg); stroke-width: 1.5; }
.wlab  { fill: var(--clan-fg); font-family: 'Reem Kufi', sans-serif; font-weight: 600; text-anchor: middle; dominant-baseline: middle; pointer-events: none; }
.wsub  { fill: var(--clan-fg); opacity: .75; font-family: 'Reem Kufi', sans-serif; text-anchor: middle; pointer-events: none; }
.whub  { fill: var(--whub); stroke: var(--card-bd2); stroke-width: 2; }
.whubt { fill: var(--txt); font-family: 'Reem Kufi', sans-serif; font-weight: 700; text-anchor: middle; dominant-baseline: middle; }
.ov-close {
  position: absolute; top: 70px; inset-inline-end: 18px;
  background: var(--btn); color: var(--txt);
  border: 1px solid var(--card-bd2); border-radius: 10px;
  padding: 8px 14px; cursor: pointer; font-family: 'Reem Kufi', sans-serif;
}
.ov-close:hover { background: var(--btn-hover); }

/* ---------- pre-Fihr modal ---------- */
.modal {
  position: fixed; inset: 0; z-index: 70;
  background: var(--overlay);
  display: none; align-items: center; justify-content: center;
  padding: 20px;
  backdrop-filter: blur(8px);
}
.modal.show { display: flex; }
.mcard {
  background: var(--panel); border: 1px solid var(--card-bd2);
  border-radius: 16px; max-width: 360px; width: 100%;
  padding: 22px; text-align: center;
  box-shadow: 0 20px 50px rgba(0,0,0,.4);
  max-height: 84vh; overflow: auto;
}
.mcard h3 {
  font-family: 'Reem Kufi', sans-serif; font-weight: 700;
  margin: 0 0 2px; font-size: 1.3rem;
}
.mcard p {
  font-family: 'Reem Kufi', sans-serif; color: var(--muted);
  font-size: .76rem; margin: 0 0 14px;
}
.chain { list-style: none; margin: 0; padding: 0; }
.chain li {
  font-weight: 700; font-size: 1.02rem;
  padding: 7px 0; border-bottom: 1px dashed var(--card-bd);
  color: var(--txt);
}
.chain li:last-child { border: 0; color: var(--spine); }
.chain li small {
  display: block; font-family: 'Reem Kufi', sans-serif;
  font-size: .58rem; color: var(--faint); font-weight: 400;
}
.mclose {
  margin-top: 14px; background: var(--spine); color: #15171c;
  border: 0; border-radius: 10px; padding: 9px 18px;
  cursor: pointer; font-family: 'Reem Kufi', sans-serif; font-weight: 600;
}

/* Pulse on Fihr at first load to invite exploration. */
@keyframes pulseRoot {
  0%, 100% { box-shadow: 0 0 0 0 rgba(203,182,140,.55); }
  50%      { box-shadow: 0 0 0 10px rgba(203,182,140,0); }
}
.nd.root { animation: pulseRoot 2.2s ease-in-out 2; }

/* ============================================================
   COMPARE MODE
   The "compare" feature hides everything not on a selected lineage
   and color-codes each pick's path-to-Fihr. State lives on
   <body class="comparing"> + per-element classes `cmp-on` (visible)
   and `cmp-hide` (display:none).
   ============================================================ */

/* The chip tray under the top bar — lists current selections with
   a colored swatch and an × to remove. Hidden until compare mode
   is on. */
.cmptray {
  position: fixed;
  top: 56px;
  inset-inline: 14px;
  z-index: 36;
  display: none;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  background: var(--bar);
  border: 1px solid var(--card-bd2);
  border-radius: 14px;
  padding: 8px 12px;
  box-shadow: 0 10px 28px rgba(0,0,0,.25);
  backdrop-filter: blur(8px);
  max-width: 920px;
  margin: 0 auto;
}
.cmptray.show { display: flex; }
.cmptray .cmp-label {
  font-family: 'Reem Kufi', sans-serif;
  font-size: .78rem;
  color: var(--muted);
  margin-inline-end: 4px;
}
.cmptray .cmp-hint {
  font-family: 'Reem Kufi', sans-serif;
  font-size: .8rem;
  color: var(--muted);
  flex: 1;
}
.cmp-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--hover-bg);
  border: 1px solid var(--c);
  border-radius: 14px;
  padding: 3px 4px 3px 11px;
  font-family: 'Amiri', serif;
  font-size: .9rem;
  color: var(--txt);
}
.cmp-chip-sw {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--c);
  flex: 0 0 10px;
}
.cmp-chip-x {
  background: var(--btn);
  border: 0;
  color: var(--txt);
  width: 20px; height: 20px;
  border-radius: 50%;
  cursor: pointer;
  font-size: 14px;
  line-height: 18px;
  padding: 0;
}
.cmp-chip-x:hover { background: var(--btn-hover); }
.cmp-clear {
  font-family: 'Reem Kufi', sans-serif;
  font-size: .72rem;
  background: rgba(220, 90, 90, 0.15);
  border: 1px solid rgba(220, 90, 90, 0.35);
  color: #d8a8a8;
  border-radius: 10px;
  padding: 5px 10px;
  cursor: pointer;
  margin-inline-start: auto;
}
.cmp-clear:hover { background: rgba(220, 90, 90, 0.25); }

/* Toolbar Save button — only visible in compare mode. Carries the
   spine-gold tint so it stands out as the export action. */
.btn.btn-save {
  background: rgba(203,182,140,.18);
  border-color: rgba(203,182,140,.55);
  color: var(--spine);
  font-weight: 600;
}
.btn.btn-save:hover { background: rgba(203,182,140,.3); }
/* When not in compare mode the save button stays in flex flow but
   is invisible (visibility:hidden) — so toggling compare mode does
   NOT resize the search bar or shift any other toolbar button. The
   slot is always reserved at the far-left end of the bar (last
   child = leftmost in the RTL row). */
.btn.btn-save[hidden] {
  display: inline-block;
  visibility: hidden;
  pointer-events: none;
}
.btn.btn-save.busy { opacity: .55; cursor: wait; pointer-events: none; }

/* Dropdown menu shown beneath the Save button. Positioned with
   inline left/top set by JS at open time so it always anchors below
   the live button bounds (the toolbar can wrap on narrow screens). */
.savemenu {
  position: fixed;
  display: none;
  flex-direction: column;
  min-width: 170px;
  background: var(--bar);
  border: 1px solid var(--card-bd2);
  border-radius: 12px;
  padding: 5px;
  z-index: 60;
  box-shadow: 0 14px 36px rgba(0,0,0,.35);
  backdrop-filter: blur(10px);
}
.savemenu.show { display: flex; }
.savemenu-item {
  background: none;
  border: 0;
  color: var(--txt);
  font-family: 'Reem Kufi', sans-serif;
  font-size: .85rem;
  padding: 9px 14px;
  cursor: pointer;
  text-align: right;
  border-radius: 8px;
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: flex-end;
}
.savemenu-item:hover { background: rgba(203,182,140,.18); color: var(--spine); }
.savemenu-item:disabled,
.savemenu-item.busy {
  opacity: .55;
  cursor: wait;
}

/* Checkbox affordance on search results when compare mode is on. */
.cmp-check {
  width: 18px; height: 18px;
  border: 1.5px solid var(--card-bd2);
  border-radius: 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  color: var(--bg);
  background: var(--hover-bg);
  flex: 0 0 18px;
}
.cmp-check.on {
  background: var(--spine);
  border-color: var(--spine);
}

/* Visibility rules — only apply when body.comparing AND the tree
   actually has selections. Outside compare mode all cmp-* classes
   are ignored so they don't accidentally hide things. */
body.comparing #nodes .nd.cmp-hide,
body.comparing #frames .frame.cmp-hide,
body.comparing #overlayLabels .olab.cmp-hide,
body.comparing #links path.cmp-hide {
  display: none !important;
}

/* Visible cards get an outline in their selection's color. Cards on
   multiple paths fall back to the neutral spine color. The card's
   own clan border-top is preserved underneath. */
body.comparing #nodes .nd.cmp-on {
  box-shadow: 0 0 0 2px var(--cmp-color, rgba(203,182,140,.7));
}
body.comparing #frames .frame.cmp-on {
  border-color: var(--cmp-color, var(--fc));
}
body.comparing #overlayLabels .olab.cmp-on {
  border-color: var(--cmp-color, var(--fc));
}
body.comparing #links path.cmp-on {
  stroke-width: 3;
}

/* List card behaviour in compare mode:
   - When the list card is selected as a whole (cmp-allitems), every
     bullet shows.
   - When specific items are selected, only those `.li.cmp-item-on`
     bullets show; others collapse.
   - Selected bullets get a thin outline in their color so multi-
     pick lists are readable. */
body.comparing #nodes .nd.list.cmp-on:not(.cmp-allitems) .li:not(.cmp-item-on) {
  display: none;
}
body.comparing #nodes .nd.list .li.cmp-item-on {
  background: rgba(255,255,255,.05);
  box-shadow: inset 0 0 0 1.5px var(--cmp-color);
}

/* Hint banner: when compare mode is on but nothing's selected, the
   tray prompts the user. */
body.comparing #focusban { display: none; }

/* ---------- small-screen tweaks ---------- */
@media (max-width: 720px) {
  .mini { width: 150px; height: 96px; }
  .hint { display: none; }
  .ttl  { font-size: 1rem; }
  .ttl small { display: none; }
  .bar  { padding: 7px 10px; gap: 6px; }
  .btn  { padding: 7px 9px; font-size: .7rem; }
  .search { max-width: none; }
  .olab { padding: 3px 9px; }
  .olab .olname { font-size: .85rem; }
}

/* ============================================================
   HOME PAGE
   Landing surface that lists the available trees. Shares the
   theme palette + toolbar/.brand styles with the tree pages so
   the visual identity is consistent.
   ============================================================ */
/* The global `html, body { overflow: hidden }` rule above is for the
   tree app, where the canvas drives all pan/zoom. On the home page
   we need the document to flow and scroll normally, so we also
   release the html element (it's marked `class="home"` on the home
   page). */
html.home,
html.home body.home {
  height: auto;
  min-height: 100%;
  overflow: auto;
}
body.home .bar { position: sticky; top: 0; }

.home-main {
  max-width: 900px;
  margin: 0 auto;
  padding: 56px 24px 80px;
  position: relative;
  z-index: 1;  /* sit above the background pattern */
}

/* Background flourish — very subtle dot grid that calls back to the
   logo's node points. Sits behind everything on the home page. */
body.home::before {
  content: "";
  position: fixed;
  inset: 0;
  background-image:
    radial-gradient(circle, var(--card-bd) 1px, transparent 1.4px);
  background-size: 36px 36px;
  background-position: 18px 18px;
  opacity: .55;
  pointer-events: none;
  z-index: 0;
  mask-image: radial-gradient(ellipse 70% 50% at 50% 35%, #000 30%, transparent 75%);
          -webkit-mask-image: radial-gradient(ellipse 70% 50% at 50% 35%, #000 30%, transparent 75%);
}

.home-header {
  text-align: center;
  margin-bottom: 56px;
}

/* Hero mark — the ceremonial big version of the logo. Gentle
   entrance: fades up + scales in on first paint. */
.hero-mark {
  width: clamp(110px, 18vw, 168px);
  height: clamp(110px, 18vw, 168px);
  display: block;
  margin: 0 auto 18px;
  color: var(--spine);
  animation: heroMarkIn .9s cubic-bezier(.2, .8, .2, 1) both;
}
@keyframes heroMarkIn {
  from { opacity: 0; transform: scale(0.9) translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

.home-title {
  font-family: 'Reem Kufi', sans-serif;
  font-weight: 700;
  font-size: clamp(2.6rem, 7vw, 4rem);
  color: var(--txt);
  margin: 0 0 14px;
  letter-spacing: .02em;
  /* Subtle warm-gold accent on the title — present in both themes. */
  background: linear-gradient(180deg, var(--txt) 0%, var(--spine) 130%);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: titleIn .9s .15s cubic-bezier(.2, .8, .2, 1) both;
}
@keyframes titleIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

/* Ornament — Arabic-manuscript inspired divider rule between the
   title and the subtitle. Carries the spine-gold accent at low
   opacity so it sits below the title in weight. */
.home-ornament {
  display: block;
  margin: 0 auto 18px;
  width: clamp(140px, 32vw, 240px);
  height: 14px;
  color: var(--spine);
  opacity: .65;
  animation: titleIn .9s .25s cubic-bezier(.2, .8, .2, 1) both;
}

.home-subtitle {
  font-family: 'Reem Kufi', sans-serif;
  font-size: clamp(.95rem, 2.5vw, 1.1rem);
  color: var(--muted);
  margin: 0;
  line-height: 1.6;
  animation: titleIn .9s .35s cubic-bezier(.2, .8, .2, 1) both;
}

/* Tree card grid — grows from 1 column on mobile to multiple
   on wider screens as more trees are added. */
.trees-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 20px;
}

.tree-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: var(--card);
  border: 1px solid var(--card-bd);
  border-radius: 16px;
  padding: 28px 26px;
  text-decoration: none;
  color: var(--txt);
  box-shadow: var(--card-shadow);
  transition: transform .18s, box-shadow .18s, border-color .18s;
  position: relative;
  overflow: hidden;
  border-top: 3px solid var(--spine);
}
.tree-card::before {
  /* Subtle warm glow in the corner — adds depth without weight. */
  content: "";
  position: absolute;
  inset-inline-end: -40px;
  top: -40px;
  width: 160px;
  height: 160px;
  background: radial-gradient(circle, var(--spine) 0%, transparent 70%);
  opacity: .08;
  pointer-events: none;
}
.tree-card:hover {
  transform: translateY(-3px);
  border-color: var(--card-bd2);
  box-shadow:
    0 4px 14px rgba(20,30,40,.12),
    0 14px 36px rgba(20,30,40,.14);
}
.tree-card:focus-visible {
  outline: 2px solid var(--spine);
  outline-offset: 3px;
}

.tree-card-eyebrow {
  font-family: 'Reem Kufi', sans-serif;
  font-size: .72rem;
  font-weight: 500;
  color: var(--spine);
  letter-spacing: .12em;
  text-transform: uppercase;
}
.tree-card-name {
  font-family: 'Reem Kufi', sans-serif;
  font-weight: 700;
  font-size: 1.6rem;
  color: var(--txt);
  margin: 2px 0 4px;
  letter-spacing: .01em;
}
.tree-card-desc {
  font-family: 'Amiri', serif;
  font-size: 1rem;
  color: var(--muted);
  line-height: 1.65;
  margin: 0;
}
.tree-card-cta {
  font-family: 'Reem Kufi', sans-serif;
  font-size: .82rem;
  color: var(--spine);
  margin-top: 14px;
  font-weight: 600;
  transition: gap .15s;
}
.tree-card:hover .tree-card-cta {
  letter-spacing: .03em;
}

/* Home toolbar tweaks — no search bar on home, so the brand sits
   alone on the right with the theme toggle on the left. */
body.home .bar { gap: 12px; }

@media (max-width: 720px) {
  .home-main { padding: 40px 16px 40px; }
  .home-header { margin-bottom: 32px; }
  .tree-card { padding: 22px 20px; }
  .tree-card-name { font-size: 1.35rem; }
  .tree-card-desc { font-size: .92rem; }
}
