/**
 * Wizarding Family Tree - Public Styles
 * "Astral" UI — dark parchment + starlight, RTL-first.
 */

/**
 * Wizarding Family Tree - Public Styles
 * "Astral" UI — dark parchment + starlight, RTL-first.
 */

/* ============================================================
   1. Tokens
   ============================================================ */
.wft-container {
    --wft-bg: #08070f;
    --wft-bg-2: #0e0c1c;
    --wft-panel: #141126;
    --wft-panel-2: #1b1733;
    --wft-line: rgba(150, 130, 220, 0.16);
    --wft-line-strong: rgba(160, 140, 230, 0.32);

    --wft-ink: #ece9f7;
    --wft-ink-2: #a9a2c8;
    --wft-ink-3: #6f688f;

    --wft-primary: #9b7bf0;
    --wft-primary-2: #c3a6ff;
    --wft-gold: #e0b64a;
    --wft-gold-2: #f6d989;

    --wft-canon-main: #b48bff;
    --wft-canon-legacy: #3fbf87;
    --wft-canon-mystery: #ef8f45;

    --wft-r-sm: 8px;
    --wft-r-md: 12px;
    --wft-r-lg: 18px;

    --wft-shadow: 0 18px 50px rgba(0, 0, 0, .55);
    --wft-ring: 0 0 0 1px var(--wft-line);
}

/* ============================================================
   1b. Light scheme
   ------------------------------------------------------------
   Applied by JS (.wft-light) when the host page reads as light. Only tokens and
   the few surfaces that cannot be expressed as tokens are redefined, so the rest
   of the stylesheet is scheme-agnostic.
   ============================================================ */
.wft-container.wft-light {
    --wft-bg: #f4f2fa;
    --wft-bg-2: #ffffff;
    --wft-panel: #ffffff;
    --wft-panel-2: #f2eefb;
    --wft-line: rgba(78, 56, 140, .18);
    --wft-line-strong: rgba(78, 56, 140, .34);

    --wft-ink: #1b1730;
    --wft-ink-2: #4f4870;
    --wft-ink-3: #837ba3;

    --wft-primary: #6d45cf;
    --wft-primary-2: #5733b4;
    --wft-gold: #9a7415;
    --wft-gold-2: #7d5d0c;

    --wft-canon-main: #6d45cf;
    --wft-canon-legacy: #1c8b5e;
    --wft-canon-mystery: #b4600f;

    --wft-shadow: 0 14px 40px rgba(40, 24, 90, .14);

    background:
        radial-gradient(1200px 500px at 80% -10%, rgba(120, 80, 220, .10), transparent 60%),
        radial-gradient(900px 420px at 10% 110%, rgba(200, 150, 40, .08), transparent 60%),
        var(--wft-bg);
}

.wft-light .wft-toolbar {
    background: linear-gradient(180deg, rgba(255, 255, 255, .95), rgba(246, 243, 253, .95));
}

.wft-light .wft-tree-wrapper {
    background:
        radial-gradient(1000px 620px at 50% 38%, rgba(232, 226, 248, .9), transparent 70%),
        linear-gradient(180deg, #fbfaff, #eeebf8);
}

/* Starlight belongs to the night sky only. */
.wft-light .wft-stars {
    display: none;
}

.wft-light .wft-tree-wrapper::after {
    background:
        linear-gradient(to bottom, rgba(244, 242, 250, .9), transparent 9%, transparent 91%, rgba(244, 242, 250, .9)),
        linear-gradient(to right, rgba(244, 242, 250, .8), transparent 6%, transparent 94%, rgba(244, 242, 250, .8));
}

.wft-light .wft-band rect {
    fill: rgba(60, 40, 130, .035);
}

.wft-light .wft-band-line {
    stroke: rgba(60, 40, 130, .09);
}

.wft-light .wft-band-label {
    fill: rgba(70, 55, 130, .38);
}

/* Cards: white surface, family colour carried by the border and accent. */
.wft-light .wft-card-plate {
    fill: #ffffff;
    stroke-opacity: .65;
}

.wft-light .wft-node:hover .wft-card-plate {
    fill: #fbf9ff;
}

.wft-light .wft-card-shadow {
    fill: #2a1d5c;
    opacity: .13;
}

/* The palette is tuned for dark ground, so darken it for text on white. */
.wft-light .wft-card-sub {
    fill: color-mix(in srgb, var(--fam-color, #6d45cf) 72%, #191430);
    opacity: 1;
}

.wft-light .wft-link {
    opacity: .62;
}

.wft-light .wft-family-frame-label {
    fill: color-mix(in srgb, var(--fam-color, #6d45cf) 72%, #100c22);
    opacity: .85;
}

.wft-light .wft-trunk {
    opacity: .62;
}

.wft-light .wft-anc-chip-bg {
    fill: #ffffff;
    stroke-opacity: .6;
}

.wft-light .wft-anc-band-bg {
    fill: rgba(154, 116, 21, .05);
    stroke: rgba(154, 116, 21, .18);
}

.wft-light .wft-toggle-bg {
    fill: #ffffff;
    stroke-opacity: .55;
}

.wft-light .wft-toggle-text {
    fill: var(--wft-ink-2);
}

.wft-light .wft-bond-knot,
.wft-light .wft-marriage-mark {
    fill: #ffffff;
}

.wft-light .wft-bond,
.wft-light .wft-marriage {
    opacity: .65;
}

/* Avatars keep their colour but need a light rim to sit on white. */
.wft-light .wft-avatar-star {
    fill: #fff;
    opacity: .75;
}

.wft-light .wft-search-results,
.wft-light .wft-minimap,
.wft-light .wft-hud {
    background: rgba(255, 255, 255, .97);
}

.wft-light .wft-minimap svg {
    background: rgba(60, 40, 130, .05);
}

.wft-light .wft-tool,
.wft-light .wft-search-box,
.wft-light .wft-pill,
.wft-light .wft-chip,
.wft-light .wft-stat,
.wft-light .wft-rel {
    background: rgba(60, 40, 130, .04) !important;
}

.wft-light .wft-tool:hover {
    background: rgba(109, 69, 207, .16) !important;
    color: var(--wft-primary-2) !important;
}

.wft-light .wft-modal-content {
    background: linear-gradient(160deg, #ffffff 0%, #faf8ff 55%, #f4f1fc 100%);
}

.wft-light .wft-modal-overlay {
    background: rgba(30, 20, 60, .45);
}

.wft-light .wft-modal-close {
    background: rgba(60, 40, 130, .08) !important;
}

.wft-light .wft-mh-name {
    color: var(--wft-ink);
}

.wft-light .wft-badge-family {
    color: color-mix(in srgb, var(--fam-color, #6d45cf) 70%, #171232);
}

.wft-light .wft-loading-indicator {
    background: rgba(244, 242, 250, .7);
}

.wft-light .wft-toggle:hover .wft-toggle-text {
    fill: #fff;
}

/* ============================================================
   2. Shell
   ============================================================ */
.wft-container {
    /* Set by applyBleed() to cancel the padding of the theme wrapper. */
    --wft-bleed: 0px;
    --wft-bleed-top: 0px;
    margin-inline: calc(-1 * var(--wft-bleed));
    margin-block-start: calc(-1 * var(--wft-bleed-top));
    direction: rtl;
    text-align: right;
    font-family: 'Estedad', 'IRANSans', 'Vazirmatn', 'Vazir', system-ui, sans-serif;
    background:
        radial-gradient(1200px 500px at 80% -10%, rgba(155, 123, 240, .16), transparent 60%),
        radial-gradient(900px 420px at 10% 110%, rgba(224, 182, 74, .09), transparent 60%),
        var(--wft-bg);
    border: 1px solid var(--wft-line);
    border-radius: var(--wft-r-lg);
    box-shadow: var(--wft-shadow);
    position: relative;
    overflow: hidden;
    isolation: isolate;
    -webkit-font-smoothing: antialiased;
}

.wft-container *,
.wft-container *::before,
.wft-container *::after {
    box-sizing: border-box;
}

/* Fullscreen — body lock lives outside .wft-container, so it is a root rule */
body.wft-noscroll {
    overflow: hidden !important;
}

/* Fills the page, not the screen: the browser keeps its chrome and this covers
   everything under it. `inset` alone decides the size — 100vw/100vh would be
   wrong on both axes, overshooting by the scrollbar's width and by the mobile
   URL bar's height, which would push the toolbar off the bottom. */
.wft-container.wft-is-fullscreen {
    position: fixed;
    inset: 0;
    z-index: 99998;
    /* The toolbar takes the height it needs — which changes with how many rows of
       houses wrap — and the canvas takes the rest. */
    display: flex;
    flex-direction: column;
    border-radius: 0;
    border: none;
    margin: 0;
    max-width: none;
    /* None of the page shows through, so the panel supplies its own ground
       instead of borrowing the article's. */
    background: var(--wft-bg, #0e0c1c);
}

/* ============================================================
   3. Toolbar
   ============================================================ */
.wft-toolbar {
    position: relative;
    z-index: 60;
    background: linear-gradient(180deg, rgba(26, 22, 48, .92), rgba(16, 13, 33, .92));
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--wft-line);
}

.wft-bar {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 11px 16px;
    flex-wrap: wrap;
}

.wft-bar-main {
    justify-content: space-between;
}

.wft-bar-spacer {
    flex: 1 1 auto;
}

/* --- Search --- */
.wft-search-wrapper {
    position: relative;
    z-index: 200;
    flex: 0 1 280px;
    min-width: 200px;
}

.wft-search-box {
    display: flex;
    align-items: center;
    gap: 8px;
    background: rgba(255, 255, 255, .045);
    border: 1px solid var(--wft-line);
    border-radius: 999px;
    padding: 7px 14px;
    transition: border-color .2s, box-shadow .2s, background .2s;
}

.wft-search-box:focus-within {
    border-color: var(--wft-primary);
    background: rgba(155, 123, 240, .10);
    box-shadow: 0 0 0 4px rgba(155, 123, 240, .13);
}

.wft-search-icon {
    color: var(--wft-ink-3);
    flex: none;
}

.wft-search-input {
    flex: 1 1 auto;
    min-width: 0;
    background: transparent !important;
    border: none !important;
    outline: none !important;
    box-shadow: none !important;
    color: var(--wft-ink) !important;
    font: inherit !important;
    font-size: 14px !important;
    padding: 2px 0 !important;
    margin: 0 !important;
    height: auto !important;
}

.wft-search-input::placeholder {
    color: var(--wft-ink-3);
}

.wft-search-kbd {
    flex: none;
    font-size: 10px;
    color: var(--wft-ink-3);
    border: 1px solid var(--wft-line);
    border-radius: 5px;
    padding: 1px 5px;
    line-height: 1.5;
}

/* Scoped past the theme's .entry-content button rule (see the chip block). */
.wft-container .wft-search-box .wft-search-clear {
    flex: none;
    min-height: 0;
    background: none;
    border: none;
    border-radius: 0;
    box-shadow: none;
    color: var(--wft-ink-3);
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    padding: 0 2px;
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s, color .2s;
}

.wft-container .wft-search-wrapper.has-value .wft-search-clear {
    opacity: 1;
    pointer-events: auto;
}

.wft-search-wrapper.has-value .wft-search-kbd {
    display: none;
}

.wft-container .wft-search-box .wft-search-clear:hover {
    color: var(--wft-primary-2);
    background: none;
    box-shadow: none;
}

/* Results */
.wft-search-results {
    position: absolute;
    top: calc(100% + 8px);
    inset-inline: 0;
    background: rgba(20, 17, 38, .98);
    backdrop-filter: blur(16px);
    border: 1px solid var(--wft-line-strong);
    border-radius: var(--wft-r-md);
    max-height: 320px;
    overflow-y: auto;
    z-index: 300;
    display: none;
    box-shadow: var(--wft-shadow);
    padding: 5px;
}

.wft-search-results.active {
    display: block;
    animation: wft-pop .16s ease;
}

@keyframes wft-pop {
    from { opacity: 0; transform: translateY(-6px) }
    to   { opacity: 1; transform: none }
}

.wft-search-result-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-radius: var(--wft-r-sm);
    cursor: pointer;
    transition: background .15s;
}

.wft-search-result-item:hover,
.wft-search-result-item.is-active {
    background: rgba(155, 123, 240, .16);
}

.wft-search-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    flex: none;
    box-shadow: 0 0 8px currentColor;
}

.wft-search-result-name {
    color: var(--wft-ink);
    font-size: 13.5px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.wft-search-result-meta {
    margin-inline-start: auto;
    font-size: 11px;
    color: var(--wft-ink-3);
    flex: none;
}

.wft-search-no-results {
    padding: 18px;
    text-align: center;
    color: var(--wft-ink-3);
    font-size: 13px;
}

/* --- Source pills --- */
.wft-sources {
    display: flex;
    align-items: center;
    gap: 7px;
    flex-wrap: wrap;
}

.wft-sources-label,
.wft-families-label {
    font-size: 11.5px;
    font-weight: 700;
    color: var(--wft-ink-3);
    letter-spacing: .02em;
    flex: none;
}

.wft-pill {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 5px 12px 5px 10px;
    border-radius: 999px;
    border: 1px solid var(--wft-line);
    background: rgba(255, 255, 255, .03);
    color: var(--wft-ink-2);
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    user-select: none;
    transition: all .18s ease;
    white-space: nowrap;
}

.wft-pill input {
    display: none;
}

.wft-pill-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: currentColor;
    opacity: .35;
    transition: opacity .18s, box-shadow .18s;
    flex: none;
}

.wft-pill.is-on {
    color: var(--wft-ink);
    border-color: color-mix(in srgb, var(--pill-color, var(--wft-primary)) 55%, transparent);
    background: color-mix(in srgb, var(--pill-color, var(--wft-primary)) 16%, transparent);
}

.wft-pill.is-on .wft-pill-dot {
    background: var(--pill-color, var(--wft-primary));
    opacity: 1;
    box-shadow: 0 0 10px var(--pill-color, var(--wft-primary));
}

.wft-pill:hover:not(.is-locked) {
    border-color: var(--wft-line-strong);
    transform: translateY(-1px);
}

.wft-pill.is-locked {
    cursor: default;
    opacity: .95;
}

/* --- Tools --- */
.wft-tools {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: none;
}

.wft-tool {
    width: 34px;
    height: 34px;
    flex: none;
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    border-radius: 10px !important;
    border: 1px solid var(--wft-line) !important;
    background: rgba(255, 255, 255, .04) !important;
    color: var(--wft-ink-2) !important;
    cursor: pointer;
    padding: 0 !important;
    transition: all .18s ease;
    box-shadow: none !important;
}

.wft-tool svg {
    width: 17px;
    height: 17px;
    display: block;
}

.wft-tool:hover {
    background: rgba(155, 123, 240, .22) !important;
    border-color: var(--wft-primary) !important;
    color: #fff !important;
    transform: translateY(-1px);
}

.wft-tool:active {
    transform: translateY(0) scale(.95);
}

.wft-tool.is-on {
    background: rgba(155, 123, 240, .28) !important;
    border-color: var(--wft-primary) !important;
    color: #fff !important;
}

.wft-zoom-level {
    min-width: 46px;
    text-align: center;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
    color: var(--wft-ink-2);
    font-weight: 600;
    user-select: none;
    cursor: pointer;
}

.wft-tool-sep {
    width: 1px;
    height: 22px;
    background: var(--wft-line);
    margin: 0 3px;
    flex: none;
}

/* --- Family chips row --- */
.wft-bar-families {
    padding-top: 0;
    padding-bottom: 10px;
    gap: 10px;
    flex-wrap: nowrap;
    align-items: center;
}

/* Single scrollable row with an explicit next button.
   Wrapping made every house reachable but cost too much vertical space, and a
   bare horizontal scroller is unreachable with a mouse wheel — hence the
   button beside it. */
.wft-family-chips {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: 7px;
    padding: 2px 0;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-behavior: smooth;
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.wft-family-chips::-webkit-scrollbar {
    display: none;
}

/* Nudges the row along; hidden when everything already fits. */
.wft-container .wft-bar-families .wft-chip-nav {
    flex: none;
    min-height: 0;
    width: 28px;
    height: 28px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    border: 1px solid var(--wft-line);
    background: rgba(255, 255, 255, .05);
    color: var(--wft-ink-2);
    cursor: pointer;
    box-shadow: none;
    transition: background .18s, color .18s, border-color .18s;
}

.wft-container .wft-bar-families .wft-chip-nav:hover {
    background: rgba(155, 123, 240, .22);
    border-color: var(--wft-primary);
    color: #fff;
}

.wft-container .wft-bar-families .wft-chip-nav[hidden] {
    display: none;
}

.wft-chip-nav svg {
    width: 15px;
    height: 15px;
}
.wft-bar-families .wft-family-chips {
    flex: 1 1 auto;
    min-width: 0;
}

/* Control sizing.
   ------------------------------------------------------------------
   The theme gives every button and input inside .entry-content
   `min-height: 44px` plus its own padding, which inflated the 34px tool
   buttons to 44px and the search field to 64px. Scoped past it (0-3-0). */
.wft-container .wft-toolbar .wft-tool {
    min-height: 0;
    height: 32px;
    width: 32px;
    padding: 0;
    line-height: 1;
}

.wft-container .wft-toolbar .wft-search-box {
    min-height: 0;
    padding: 5px 12px;
}

.wft-container .wft-toolbar .wft-search-input {
    min-height: 0 !important;
    height: auto !important;
    line-height: 1.5 !important;
    padding: 1px 0 !important;
}

.wft-container .wft-toolbar .wft-zoom-level {
    min-height: 0;
    line-height: 32px;
}

/* An empty paragraph sits between the page content and the shortcode and its
   margin adds ~21px of dead space above the tree. */
p:empty:has(+ .wft-container) {
    display: none;
}

/* House picker chips.
   ------------------------------------------------------------------
   The site theme paints every <button> inside .entry-content with a magenta
   gradient at specificity 0-2-2:

       body.page-template-default .entry-content button { ... }

   A bare `.wft-chip` (0-1-0) loses to that, which is why every chip rendered
   as the same unreadable magenta pill with no active state. These rules are
   scoped through two ancestors (0-3-0) so they win on specificity without
   resorting to !important. */
.wft-container .wft-family-chips .wft-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex: none;
    min-height: 0;
    padding: 6px 13px;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--chip-color, var(--wft-primary)) 34%, transparent);
    background: rgba(255, 255, 255, .035);
    color: var(--wft-ink-2);
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1.5;
    cursor: pointer;
    white-space: nowrap;
    box-shadow: none;
    transition: border-color .18s ease, background .18s ease, color .18s ease, transform .18s ease;
}

.wft-container .wft-family-chips .wft-chip:hover {
    border-color: color-mix(in srgb, var(--chip-color, var(--wft-primary)) 70%, transparent);
    background: color-mix(in srgb, var(--chip-color, var(--wft-primary)) 10%, transparent);
    color: var(--wft-ink);
    transform: translateY(-1px);
    box-shadow: none;
}

.wft-container .wft-family-chips .wft-chip.is-active {
    color: #fff;
    border-color: var(--chip-color, var(--wft-primary));
    background: color-mix(in srgb, var(--chip-color, var(--wft-primary)) 20%, transparent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--chip-color, var(--wft-primary)) 15%, transparent);
}

.wft-container .wft-family-chips .wft-chip-swatch {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--chip-color, var(--wft-primary));
    flex: none;
    transition: box-shadow .18s ease;
}

.wft-container .wft-family-chips .wft-chip.is-active .wft-chip-swatch {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--chip-color, var(--wft-primary)) 30%, transparent);
}

/* The count is secondary: a quiet number, not a second badge. */
.wft-container .wft-family-chips .wft-chip-count {
    font-size: 11px;
    font-variant-numeric: tabular-nums;
    color: var(--wft-ink-3);
    background: none;
    border: 0;
    padding: 0;
    line-height: inherit;
    opacity: .85;
}

.wft-container .wft-family-chips .wft-chip.is-active .wft-chip-count {
    color: rgba(255, 255, 255, .8);
    background: none;
}

.wft-chip-all .wft-chip-swatch {
    background: linear-gradient(135deg, #ef5f6b, #4aa6ea 45%, #4fc07d);
}

/* ============================================================
   4. Canvas
   ============================================================ */
.wft-tree-wrapper {
    position: relative;
    min-height: 380px;
    overflow: hidden;
    background:
        radial-gradient(1000px 620px at 50% 38%, rgba(38, 30, 74, .85), transparent 70%),
        linear-gradient(180deg, var(--wft-bg-2), var(--wft-bg));
    touch-action: none;
}

/* Starfield */
.wft-stars {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 1;
    opacity: .55;
    background-image:
        radial-gradient(1.4px 1.4px at 12% 22%, rgba(255, 255, 255, .75), transparent),
        radial-gradient(1.2px 1.2px at 68% 12%, rgba(220, 210, 255, .65), transparent),
        radial-gradient(1.6px 1.6px at 84% 62%, rgba(255, 246, 214, .55), transparent),
        radial-gradient(1.1px 1.1px at 32% 78%, rgba(255, 255, 255, .55), transparent),
        radial-gradient(1.3px 1.3px at 52% 48%, rgba(200, 190, 255, .5), transparent),
        radial-gradient(1px 1px at 8% 62%, rgba(255, 255, 255, .45), transparent),
        radial-gradient(1.5px 1.5px at 92% 28%, rgba(255, 255, 255, .5), transparent),
        radial-gradient(1px 1px at 44% 8%, rgba(255, 255, 255, .4), transparent),
        radial-gradient(1.2px 1.2px at 24% 44%, rgba(255, 236, 190, .45), transparent),
        radial-gradient(1px 1px at 76% 88%, rgba(255, 255, 255, .4), transparent);
    background-size: 100% 100%;
    animation: wft-twinkle 7s ease-in-out infinite;
}

@keyframes wft-twinkle {
    0%, 100% { opacity: .38 }
    50%      { opacity: .68 }
}

.wft-tree-background {
    position: absolute;
    inset: -24px;
    background-size: cover;
    background-position: center;
    opacity: var(--wft-bg-opacity, .15);
    filter: blur(var(--wft-bg-blur, 5px)) grayscale(35%);
    pointer-events: none;
    z-index: 0;
}

/* Edge vignette so the tree fades instead of getting clipped hard */
.wft-tree-wrapper::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 20;
    background:
        linear-gradient(to bottom, rgba(8, 7, 15, .85), transparent 9%, transparent 91%, rgba(8, 7, 15, .85)),
        linear-gradient(to right, rgba(8, 7, 15, .7), transparent 6%, transparent 94%, rgba(8, 7, 15, .7));
}

.wft-tree-svg {
    position: relative;
    z-index: 10;
    width: 100%;
    height: 100%;
    display: block;
    cursor: grab;
    touch-action: none;
}

.wft-tree-svg:active {
    cursor: grabbing;
}

.wft-tree-svg.is-panning {
    cursor: grabbing;
}

/* ============================================================
   5. Tree graphics
   ============================================================ */

/* Generation bands */
.wft-band rect {
    fill: rgba(255, 255, 255, .022);
}

.wft-band-line {
    stroke: rgba(255, 255, 255, .05);
    stroke-width: 1;
}

/* No letter-spacing: this is Persian, and spacing a cursive script pulls its
   joined letters apart. Safari goes further and lays the spaced run out in
   logical order, printing the word backwards. See .wft-family-frame-label. */
/* Backstop for the rule above: nothing drawn in the tree may be letter-spaced.
   Every label in here is Persian, and it took four attempts to find that this was
   what broke them on Safari — so it is enforced once, centrally, rather than
   relied on being left out of each new rule. */
.wft-tree-group text {
    letter-spacing: normal;
}

.wft-band-label {
    fill: rgba(200, 190, 240, .30);
    font-size: 13px;
    font-weight: 700;
    direction: rtl;
    text-anchor: start;
    pointer-events: none;
    user-select: none;
}

/* Ancestral row — ancient figures above the first known generation */
.wft-anc-band-bg {
    fill: rgba(224, 182, 74, .045);
    stroke: rgba(224, 182, 74, .14);
    stroke-width: 1;
    stroke-dasharray: 4 8;
}

.wft-anc-chip {
    cursor: pointer;
}

.wft-anc-chip-bg {
    fill: rgba(24, 20, 46, .95);
    stroke: var(--fam-color, #e0b64a);
    stroke-width: 1.1;
    stroke-opacity: .5;
    transition: stroke-opacity .2s, fill .2s;
}

.wft-anc-chip:hover .wft-anc-chip-bg {
    fill: rgba(38, 32, 70, .98);
    stroke-opacity: 1;
}

.wft-anc-chip-name {
    fill: var(--wft-ink-2);
    font-size: 11.5px;
    font-weight: 600;
    direction: rtl;
    text-anchor: start;
    pointer-events: none;
}

.wft-anc-chip:hover .wft-anc-chip-name {
    fill: var(--wft-ink);
}

.wft-anc-chip-dot {
    pointer-events: none;
}

.wft-anc-link {
    fill: none;
    stroke: var(--wft-gold);
    stroke-width: 1.2;
    stroke-dasharray: 2 7;
    stroke-linecap: round;
    opacity: .4;
    pointer-events: none;
}

/* Card marks */
.wft-mark-sibling {
    fill: var(--wft-primary-2);
    font-size: 11px;
    text-anchor: middle;
    dominant-baseline: central;
    opacity: .75;
    pointer-events: none;
}

.wft-mark-ancestor {
    fill: var(--wft-gold);
    font-size: 10px;
    text-anchor: middle;
    dominant-baseline: central;
    opacity: .85;
    pointer-events: none;
}

.wft-badge-ancestor {
    color: var(--wft-gold-2);
    border-color: color-mix(in srgb, var(--wft-gold) 45%, transparent);
    background: color-mix(in srgb, var(--wft-gold) 15%, transparent);
}

/* Family frames — one soft rectangle per top-level family block */
.wft-family-frame-bg {
    fill: color-mix(in srgb, var(--fam-color, #9b7bf0) 6%, transparent);
    stroke: color-mix(in srgb, var(--fam-color, #9b7bf0) 26%, transparent);
    stroke-width: 1;
    stroke-dasharray: 5 9;
}

/* The caption is two elements, each holding one script — see scaleMapLabels.
   text-anchor is start on both rather than end, matching every label here that has
   always rendered correctly, and scaleMapLabels does the aligning arithmetic.

   Critically, no letter-spacing. Persian is cursive: spacing it breaks the joins
   between letters, which is why this caption alone came out as loose, unconnected
   glyphs. Safari compounds that by laying the spaced right-to-left run out in
   logical order, so the house name printed backwards — مالفوی as ىفلام. This was
   the whole bug; it was never the digits or the separator. */
.wft-family-frame-label {
    fill: color-mix(in srgb, var(--fam-color, #9b7bf0) 78%, #ffffff);
    font-size: 13px;
    font-weight: 800;
    direction: rtl;
    text-anchor: start;
    pointer-events: none;
    user-select: none;
    opacity: .75;
    dominant-baseline: auto;
}

.wft-family-frame-count {
    fill: color-mix(in srgb, var(--fam-color, #9b7bf0) 62%, #ffffff);
    font-size: 13px;
    font-weight: 700;
    direction: ltr;
    text-anchor: start;
    pointer-events: none;
    user-select: none;
    opacity: .6;
    dominant-baseline: auto;
}

/* Zoomed out the caption sits over its own block rather than above it, so it has
   to hold up against the cards behind it: brighter, centred on its line, and
   outlined so it stays legible over any house colour. */
.wft-family-frame-label.is-map-label,
.wft-family-frame-count.is-map-label {
    fill: color-mix(in srgb, var(--fam-color, #9b7bf0) 42%, #ffffff);
    opacity: .95;
    dominant-baseline: central;
    paint-order: stroke fill;
    stroke: rgba(8, 7, 15, .72);
    stroke-width: .18em;
    stroke-linejoin: round;
}

.wft-light .wft-family-frame-label.is-map-label,
.wft-light .wft-family-frame-count.is-map-label {
    fill: color-mix(in srgb, var(--fam-color, #9b7bf0) 82%, #000000);
    stroke: rgba(255, 255, 255, .78);
}

/* Shared trunk: one orthogonal connector per household */
.wft-trunk {
    fill: none;
    stroke: var(--link-color, #6f5ea8);
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: .5;
    pointer-events: none;
}

/* Soft links: real relationships that must not move anyone in the layout.
   Each is dashed and curved so it never reads as a parent line. */
.wft-soft {
    fill: none;
    stroke-width: 1.6;
    pointer-events: none;
}

/* Adoption — child stays under the blood parent, tethered to the other family */
.wft-soft-adoptive {
    stroke: #4aa6ea;
    stroke-dasharray: 10 6;
    opacity: .7;
}

/* Siblings with no known parent: joined to each other, not to a fabricated source */
.wft-soft-sibling {
    stroke: var(--wft-primary-2);
    stroke-dasharray: 2 7;
    opacity: .65;
}

/* --- Jump portals ------------------------------------------------------
   What a tie too long to draw turns into: a pill under the card naming the
   person on the far side, in their house colour, that flies you to them. It
   replaces a line that crossed the whole page and landed off screen. */
.wft-portal {
    cursor: pointer;
}

.wft-portal-stem {
    fill: none;
    stroke: var(--fam-color, #9b7bf0);
    stroke-width: 1.4;
    stroke-dasharray: 3 3;
    opacity: .55;
}

.wft-portal-pill {
    fill: color-mix(in srgb, var(--fam-color, #9b7bf0) 16%, #100d21);
    stroke: color-mix(in srgb, var(--fam-color, #9b7bf0) 58%, transparent);
    stroke-width: 1;
    transition: fill .16s, stroke .16s;
}

.wft-portal-dot {
    fill: var(--fam-color, #9b7bf0);
}

/* start, not middle: this holds a Persian name, and Safari renders Arabic script
   backwards under middle and end. drawPortals centres it by arithmetic instead. */
.wft-portal-label {
    fill: var(--wft-ink-2);
    font: 600 11px Estedad, IRANSans, Vazirmatn, system-ui, sans-serif;
    text-anchor: start;
    direction: rtl;
    dominant-baseline: central;
    pointer-events: none;
    user-select: none;
}

.wft-portal-chev {
    fill: none;
    stroke: var(--fam-color, #9b7bf0);
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.wft-portal:hover .wft-portal-pill,
.wft-portal:focus-visible .wft-portal-pill {
    fill: color-mix(in srgb, var(--fam-color, #9b7bf0) 34%, #100d21);
    stroke: var(--fam-color, #9b7bf0);
}

.wft-portal:hover .wft-portal-label,
.wft-portal:focus-visible .wft-portal-label {
    fill: #fff;
}

.wft-portal:focus-visible {
    outline: none;
}

.wft-portal:focus-visible .wft-portal-pill {
    stroke-width: 2;
}

.wft-light .wft-portal-pill {
    fill: color-mix(in srgb, var(--fam-color, #9b7bf0) 12%, #ffffff);
}

.wft-light .wft-portal-label {
    fill: #1b1830;
}

/* Spatial hint only */
.wft-soft-near {
    stroke: var(--wft-ink-3);
    stroke-dasharray: 1 8;
    stroke-linecap: round;
    opacity: .6;
}

.wft-mark-near {
    fill: var(--wft-ink-3);
    font-size: 12px;
    font-weight: 800;
    text-anchor: middle;
    dominant-baseline: central;
    opacity: .8;
    pointer-events: none;
}

/* Links */
.wft-link {
    fill: none;
    stroke: var(--link-color, #6f5ea8);
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: .5;
    transition: opacity .25s, stroke-width .25s;
}

/* Ancestral link (نیا): the person above is an ancestor, not a direct parent.
   Gold and clearly dashed so it reads as "generations unknown in between"
   rather than looking like a faint ordinary parent line. */
.wft-link-indirect {
    stroke: var(--wft-gold) !important;
    stroke-width: 2;
    stroke-dasharray: 9 7;
    opacity: .85;
}

/* Connected through a sibling rather than a recorded parent */
.wft-link-sibling {
    stroke-dasharray: 2 7;
    stroke-width: 1.8;
    opacity: .7;
}

.wft-link.is-lit {
    opacity: 1;
    stroke-width: 3;
    filter: drop-shadow(0 0 6px var(--link-color, #6f5ea8));
}

/* Marriage links between distant cousins */
.wft-marriage {
    fill: none;
    stroke: var(--wft-gold);
    stroke-width: 1.2;
    stroke-dasharray: 4 7;
    opacity: .4;
}

.wft-marriage-mark {
    fill: var(--wft-bg-2);
    stroke: var(--wft-gold);
    stroke-width: 1;
    stroke-opacity: .6;
    pointer-events: none;
}

/* Household bond (adjacent couple) */
.wft-bond {
    stroke: var(--wft-gold);
    stroke-width: 1.3;
    opacity: .45;
}

/* A diamond, not a disc: circles read as people here, so the union marker uses a
   different shape and a lighter weight rather than competing with the portraits. */
.wft-bond-knot {
    fill: var(--wft-bg-2);
    stroke: var(--wft-gold);
    stroke-width: 1;
    stroke-opacity: .7;
}

/* --- Person card --- */
.wft-node {
    cursor: pointer;
    transition: opacity .3s ease;
}

.wft-card-plate {
    fill: rgba(19, 16, 39, .94);
    stroke: var(--fam-color, #9b7bf0);
    stroke-width: 1.25;
    stroke-opacity: .40;
    transition: stroke-opacity .2s, fill .2s;
}

.wft-card-accent {
    fill: var(--fam-color, #9b7bf0);
    opacity: .72;
}

.wft-card-shadow {
    fill: #000;
    opacity: .38;
}

.wft-node:hover .wft-card-plate {
    fill: rgba(32, 27, 62, .98);
    stroke-opacity: 1;
}

.wft-card-name {
    fill: var(--wft-ink);
    font-size: 15px;
    font-weight: 700;
    direction: rtl;
    text-anchor: start;
    pointer-events: none;
    dominant-baseline: alphabetic;
}

.wft-card-sub {
    font-size: 11px;
    font-weight: 600;
    direction: rtl;
    text-anchor: start;
    pointer-events: none;
    fill: var(--fam-color, #9b7bf0);
    opacity: .95;
}

.wft-card-sub tspan.wft-dim-text {
    fill: var(--wft-ink-3);
}

/* Avatar */
.wft-avatar-ring {
    fill: none;
    stroke: var(--fam-color, #9b7bf0);
    stroke-width: 1.5;
    opacity: .8;
}

.wft-avatar-initial {
    font-size: 21px;
    font-weight: 800;
    text-anchor: middle;
    dominant-baseline: central;
    pointer-events: none;
    fill: #fff;
    fill-opacity: .94;
}

.wft-avatar-star {
    fill: #fff;
    opacity: .55;
}

.wft-avatar-img {
    transition: filter .3s ease;
}

.wft-bw-mode .wft-avatar-img {
    filter: grayscale(100%);
}

.wft-bw-mode .wft-node:hover .wft-avatar-img {
    filter: grayscale(0%);
}

/* Toggle pill (child count) */
.wft-toggle {
    cursor: pointer;
}

.wft-toggle-bg {
    fill: rgba(17, 14, 34, .96);
    stroke: var(--fam-color, #9b7bf0);
    stroke-width: 1;
    stroke-opacity: .38;
    transition: fill .18s, stroke-opacity .18s;
}

.wft-toggle:hover .wft-toggle-bg {
    fill: var(--fam-color, #9b7bf0);
    stroke-opacity: 1;
}

.wft-toggle-text {
    fill: var(--wft-ink-2);
    font-size: 10.5px;
    font-weight: 700;
    text-anchor: middle;
    dominant-baseline: central;
    pointer-events: none;
    font-variant-numeric: tabular-nums;
    /* "+۵" is a symbol plus a numeral, not prose — pin the order so bidi
       reordering cannot flip the sign to the far side of the digits. */
    direction: ltr;
    transition: fill .18s;
}

.wft-toggle:hover .wft-toggle-text {
    fill: #100d20;
}

/* Marks */
.wft-mark-indirect {
    fill: var(--wft-gold);
    font-size: 11px;
    text-anchor: middle;
    dominant-baseline: central;
    opacity: .8;
    pointer-events: none;
}

/* --- Focus / dim states --- */
.wft-tree-group.has-focus .wft-node:not(.is-lit) {
    opacity: .16;
}

.wft-tree-group.has-focus .wft-link:not(.is-lit),
.wft-tree-group.has-focus .wft-bond:not(.is-lit),
.wft-tree-group.has-focus .wft-marriage {
    opacity: .08;
}

.wft-tree-group.has-focus .wft-portal:not(.is-lit) {
    opacity: .18;
}

.wft-node.is-lit .wft-card-plate {
    stroke-opacity: .95;
    stroke-width: 1.6;
}

.wft-node.is-origin .wft-card-plate {
    stroke: var(--wft-gold);
    stroke-width: 1.8;
    stroke-opacity: 1;
}

/* Search hit */
.wft-node.is-found .wft-card-plate {
    stroke: var(--wft-gold-2);
    stroke-width: 3;
    stroke-opacity: 1;
}

.wft-node.is-found .wft-card-halo {
    opacity: 1;
    animation: wft-halo 1.6s ease-in-out infinite;
}

.wft-card-halo {
    fill: none;
    stroke: var(--wft-gold-2);
    stroke-width: 2;
    opacity: 0;
    pointer-events: none;
}

@keyframes wft-halo {
    0%, 100% { opacity: .55; transform: scale(1) }
    50%      { opacity: .12; transform: scale(1.035) }
}

/* Level of detail */
.wft-tree-group.lod-far .wft-card-name,
.wft-tree-group.lod-far .wft-card-sub,
.wft-tree-group.lod-far .wft-toggle-text,
.wft-tree-group.lod-far .wft-avatar-initial {
    display: none;
}

/* The far view is a map of houses; a field of name pills is not part of it. */
.wft-tree-group.lod-far .wft-layer-portals {
    display: none;
}

.wft-tree-group.lod-far .wft-card-plate {
    fill: var(--fam-color, #9b7bf0);
    fill-opacity: .55;
    stroke-opacity: .9;
}

.wft-tree-group.lod-mid .wft-card-sub {
    display: none;
}

.wft-tree-group.lod-mid .wft-card-name {
    font-size: 16px;
}

/* Compact cards on narrow viewports (must match applyMetrics in wft-tree.js) */
.wft-compact .wft-card-name {
    font-size: 13px;
}

.wft-compact .wft-card-sub {
    font-size: 10px;
}

.wft-compact .wft-avatar-initial {
    font-size: 17px;
}

/* ============================================================
   6. Minimap
   ============================================================ */
.wft-minimap {
    position: absolute;
    inset-inline-start: 14px;
    inset-block-end: 14px;
    width: 214px;
    z-index: 40;
    background: rgba(14, 12, 28, .88);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid var(--wft-line);
    border-radius: var(--wft-r-md);
    padding: 7px;
    box-shadow: 0 12px 30px rgba(0, 0, 0, .5);
    transition: opacity .25s, transform .25s;
}

.wft-minimap.is-hidden {
    opacity: 0;
    pointer-events: none;
    transform: translateY(10px);
}

.wft-minimap svg {
    display: block;
    width: 100%;
    height: 128px;
    cursor: crosshair;
    border-radius: 6px;
    background: rgba(0, 0, 0, .25);
}

.wft-minimap-node {
    rx: 1.5;
}

.wft-minimap-view {
    fill: rgba(224, 182, 74, .12);
    stroke: var(--wft-gold);
    stroke-width: 1.2;
    rx: 3;
    pointer-events: none;
}

/* ============================================================
   7. HUD (lineage breadcrumb)
   ============================================================ */
.wft-hud {
    position: absolute;
    inset-block-end: 14px;
    inset-inline-end: 14px;
    z-index: 40;
    max-width: min(60%, 620px);
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    justify-content: flex-end;
    background: rgba(14, 12, 28, .9);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid var(--wft-line);
    border-radius: 999px;
    padding: 7px 14px;
    box-shadow: 0 12px 30px rgba(0, 0, 0, .5);
    opacity: 0;
    transform: translateY(8px);
    pointer-events: none;
    transition: opacity .2s, transform .2s;
}

.wft-hud.is-on {
    opacity: 1;
    transform: none;
    pointer-events: auto;
}

.wft-hud-crumb {
    font-size: 12px;
    font-weight: 600;
    color: var(--wft-ink-2);
    cursor: pointer;
    white-space: nowrap;
    transition: color .15s;
}

.wft-hud-crumb:hover {
    color: var(--wft-primary-2);
}

.wft-hud-crumb.is-last {
    color: var(--wft-gold-2);
    font-weight: 800;
}

.wft-hud-sep {
    color: var(--wft-ink-3);
    font-size: 11px;
}

/* ============================================================
   8. Loading / empty
   ============================================================ */
.wft-loading-indicator {
    position: absolute;
    inset: 0;
    z-index: 45;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 18px;
    color: var(--wft-ink-2);
    background: rgba(8, 7, 15, .55);
    backdrop-filter: blur(3px);
    font-size: 13.5px;
    transition: opacity .3s;
}

.wft-loading-indicator.hidden {
    opacity: 0;
    pointer-events: none;
}

.wft-rune {
    width: 62px;
    height: 62px;
    position: relative;
}

.wft-rune::before,
.wft-rune::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 2px solid transparent;
}

.wft-rune::before {
    border-top-color: var(--wft-primary);
    border-right-color: var(--wft-primary);
    animation: wft-spin 1.15s cubic-bezier(.55, .15, .45, .85) infinite;
}

.wft-rune::after {
    inset: 11px;
    border-bottom-color: var(--wft-gold);
    border-left-color: var(--wft-gold);
    animation: wft-spin 1.7s cubic-bezier(.55, .15, .45, .85) infinite reverse;
}

@keyframes wft-spin {
    to { transform: rotate(360deg) }
}

.wft-empty-state {
    position: absolute;
    inset: 0;
    z-index: 30;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 14px;
    color: var(--wft-ink-3);
    text-align: center;
    padding: 40px;
}

.wft-empty-state svg {
    width: 66px;
    height: 66px;
    opacity: .4;
}

.wft-empty-state p {
    margin: 0;
    font-size: 14px;
}

/* ============================================================
   9. Modal
   ============================================================ */
.wft-modal {
    position: fixed;
    inset: 0;
    z-index: 99999;
    display: none;
}

.wft-modal.active {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}

.wft-modal-overlay {
    position: absolute;
    inset: 0;
    background: rgba(4, 3, 9, .82);
    backdrop-filter: blur(7px);
    -webkit-backdrop-filter: blur(7px);
    animation: wft-fade .25s ease;
}

@keyframes wft-fade {
    from { opacity: 0 }
    to   { opacity: 1 }
}

.wft-modal-content {
    position: relative;
    display: flex;
    flex-direction: column;
    width: min(760px, 100%);
    max-height: min(88vh, 820px);
    /* The box itself must not scroll: the close button is pinned to it and the
       gradient is painted on it, so only .wft-modal-body scrolls (below). If this
       scrolled, the button and the header backdrop would slide up with content. */
    overflow: hidden;
    direction: rtl;
    text-align: right;
    font-family: 'Estedad', 'IRANSans', 'Vazirmatn', 'Vazir', system-ui, sans-serif;
    background: linear-gradient(160deg, #1a1636 0%, #100d21 55%, #0b0917 100%);
    border: 1px solid var(--wft-line-strong);
    border-radius: 22px;
    box-shadow: 0 30px 90px rgba(0, 0, 0, .7), 0 0 0 1px rgba(255, 255, 255, .03) inset;
    animation: wft-rise .3s cubic-bezier(.2, .8, .3, 1);
    color: var(--wft-ink);
}

@keyframes wft-rise {
    from { opacity: 0; transform: translateY(26px) scale(.97) }
    to   { opacity: 1; transform: none }
}

.wft-modal-close {
    position: absolute;
    top: 14px;
    inset-inline-start: 14px;
    z-index: 5;
    box-sizing: border-box !important;
    width: 30px !important;
    height: 30px !important;
    min-width: 0 !important;
    min-height: 0 !important;
    border: 1px solid var(--wft-line) !important;
    background: rgba(255, 255, 255, .07) !important;
    color: var(--wft-ink-2) !important;
    font-size: 17px !important;
    line-height: 1 !important;
    border-radius: 8px !important;
    cursor: pointer;
    display: flex !important;
    align-items: center;
    justify-content: center;
    padding: 0 !important;
    transition: all .18s;
}

.wft-modal-close:hover {
    background: rgba(255, 255, 255, .16) !important;
    color: #fff !important;
}

.wft-modal-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 0;
}

/* Hero */
.wft-mh {
    position: relative;
    display: flex;
    align-items: center;
    gap: 20px;
    padding: 30px 30px 24px;
    border-bottom: 1px solid var(--wft-line);
    overflow: hidden;
}

.wft-mh::before {
    content: '';
    position: absolute;
    inset: 0;
    background: radial-gradient(520px 200px at 88% -30%, var(--fam-color, #9b7bf0), transparent 70%);
    opacity: .28;
    pointer-events: none;
}

.wft-mh-avatar {
    position: relative;
    width: 104px;
    height: 104px;
    flex: none;
    border-radius: 50%;
    overflow: hidden;
    border: 2px solid var(--fam-color, #9b7bf0);
    box-shadow: 0 0 0 6px color-mix(in srgb, var(--fam-color, #9b7bf0) 14%, transparent);
}

.wft-mh-avatar img,
.wft-mh-avatar svg {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: cover;
}

.wft-mh-text {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
}

.wft-mh-name {
    margin: 0 0 3px;
    font-size: 27px;
    line-height: 1.25;
    font-weight: 800;
    color: #fff;
}

.wft-mh-latin {
    font-size: 13.5px;
    color: var(--wft-ink-3);
    margin-bottom: 12px;
    letter-spacing: .02em;
    direction: ltr;
    text-align: right;
}

.wft-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
}

.wft-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 11px;
    border-radius: 999px;
    font-size: 11.5px;
    font-weight: 700;
    border: 1px solid transparent;
}

.wft-badge-family {
    color: #fff;
    border-color: color-mix(in srgb, var(--fam-color, #9b7bf0) 60%, transparent);
    background: color-mix(in srgb, var(--fam-color, #9b7bf0) 22%, transparent);
}

.wft-badge-canon {
    color: var(--wft-canon-main);
    border-color: color-mix(in srgb, var(--wft-canon-main) 45%, transparent);
    background: color-mix(in srgb, var(--wft-canon-main) 14%, transparent);
}

.wft-badge-canon.src-hogwarts_legacy {
    color: var(--wft-canon-legacy);
    border-color: color-mix(in srgb, var(--wft-canon-legacy) 45%, transparent);
    background: color-mix(in srgb, var(--wft-canon-legacy) 14%, transparent);
}

.wft-badge-canon.src-hogwarts_mystery {
    color: var(--wft-canon-mystery);
    border-color: color-mix(in srgb, var(--wft-canon-mystery) 45%, transparent);
    background: color-mix(in srgb, var(--wft-canon-mystery) 14%, transparent);
}

.wft-badge-neutral {
    color: var(--wft-ink-2);
    border-color: var(--wft-line);
    background: rgba(255, 255, 255, .04);
}

/* Sections */
.wft-ms {
    padding: 22px 30px;
    border-bottom: 1px solid var(--wft-line);
}

.wft-ms:last-child {
    border-bottom: none;
}

.wft-ms-title {
    font-size: 11.5px;
    font-weight: 800;
    letter-spacing: .08em;
    color: var(--wft-ink-3);
    margin: 0 0 12px;
    text-transform: uppercase;
}

.wft-ms-text {
    margin: 0;
    line-height: 1.95;
    font-size: 14px;
    color: var(--wft-ink-2);
}

/* Stats */
.wft-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 10px;
}

.wft-stat {
    background: rgba(255, 255, 255, .035);
    border: 1px solid var(--wft-line);
    border-radius: var(--wft-r-md);
    padding: 12px 14px;
}

.wft-stat-label {
    display: block;
    font-size: 11px;
    color: var(--wft-ink-3);
    margin-bottom: 4px;
}

.wft-stat-value {
    display: block;
    font-size: 16px;
    font-weight: 800;
    color: var(--wft-ink);
    font-variant-numeric: tabular-nums;
}

/* Relation chips */
.wft-rels {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* Scoped past the theme's .entry-content button rule (see the chip block). */
.wft-container .wft-modal .wft-rel {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 0;
    padding: 6px 13px 6px 11px;
    border-radius: 999px;
    border: 1px solid var(--wft-line);
    background: rgba(255, 255, 255, .035);
    color: var(--wft-ink);
    font-size: 13px;
    font-weight: 600;
    line-height: 1.5;
    cursor: pointer;
    box-shadow: none;
    transition: border-color .18s, background .18s, transform .18s;
}

.wft-container .wft-modal .wft-rel:hover {
    transform: translateY(-1px);
    border-color: color-mix(in srgb, var(--rel-color, #9b7bf0) 70%, transparent);
    background: color-mix(in srgb, var(--rel-color, #9b7bf0) 16%, transparent);
    box-shadow: none;
}

.wft-rel-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--rel-color, #9b7bf0);
    box-shadow: 0 0 8px var(--rel-color, #9b7bf0);
    flex: none;
}

/* Lineage path */
.wft-lineage {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 7px;
}

.wft-lineage-sep {
    color: var(--wft-ink-3);
    font-size: 12px;
}

.wft-modal-error {
    padding: 40px;
    text-align: center;
    color: var(--wft-ink-3);
}

/* ============================================================
   10. Responsive
   ============================================================ */
@media screen and (max-width: 900px) {
    /* The minimap is hidden here, so its toggle would be a control that does nothing.
       .wft-tool sets display:inline-flex !important, so this has to match it. */
    .wft-minimap { display: none }
    .wft-toggle-minimap { display: none !important }
    .wft-hud { max-width: calc(100% - 28px) }
}

/* Phones: the toolbar was eating a third of the screen, so labels go and
   everything tightens up. The tree, not the chrome, should own the viewport. */
@media screen and (max-width: 560px) {
    .wft-bar { padding: 8px 10px; gap: 8px }
    .wft-bar-families { padding-bottom: 7px }

    .wft-sources-label,
    .wft-families-label { display: none }

    .wft-search-box { padding: 6px 11px }
    .wft-search-input { font-size: 13px !important }
    .wft-search-kbd { display: none }

    .wft-pill { padding: 4px 9px; font-size: 11.5px; gap: 5px }
    .wft-pill-dot { width: 7px; height: 7px }

    .wft-chip { padding: 4px 9px; font-size: 11.5px; gap: 5px }
    .wft-chip-swatch { width: 8px; height: 8px }
    .wft-chip-count { font-size: 10px; padding: 0 5px; line-height: 15px }

    .wft-tool { width: 30px; height: 30px; border-radius: 9px !important }
    .wft-tool svg { width: 15px; height: 15px }
    .wft-tools { gap: 4px }
    .wft-tool-sep { height: 18px; margin: 0 1px }
    .wft-zoom-level { min-width: 38px; font-size: 11px }

    .wft-hud { display: none }
}

@media screen and (max-width: 782px) {
    .wft-bar { gap: 10px; padding: 10px 12px }
    .wft-search-wrapper { flex: 1 1 100%; min-width: 0 }
    .wft-sources { order: 3; width: 100% }
    .wft-bar-spacer { display: none }
    .wft-tools { order: 2; margin-inline-start: auto }
    .wft-mh { flex-direction: column; text-align: center; padding: 26px 20px 20px }
    .wft-mh-latin { text-align: center }
    .wft-badges, .wft-rels, .wft-lineage { justify-content: center }
    .wft-ms { padding: 18px 20px }
    .wft-mh-name { font-size: 22px }
    .wft-modal.active { padding: 12px }
}

@media (prefers-reduced-motion: reduce) {
    .wft-container *,
    .wft-container *::before,
    .wft-container *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
}

/* Print */
@media print {
    .wft-toolbar, .wft-minimap, .wft-hud { display: none }
    .wft-tree-wrapper { background: #fff !important }
    .wft-tree-wrapper::after, .wft-stars { display: none }
    .wft-card-plate { fill: #fff !important; stroke: #333 !important }
    .wft-card-name, .wft-card-sub { fill: #111 !important }
    .wft-link { stroke: #555 !important; opacity: 1 !important }
}

/* ============================================================
   14. Focus and pointer ergonomics
   ============================================================ */

/* The controls are all custom-painted, so the UA focus ring either does not show
   against them or is overridden by the theme. Every interactive element needs a
   ring of its own or the tree is unusable without a mouse. */
.wft-container :is(button, input, [tabindex]):focus-visible,
.wft-container .wft-node:focus-visible {
    outline: 2px solid var(--wft-primary-2, #c3a6ff);
    outline-offset: 2px;
    border-radius: 8px;
}

/* An SVG group takes no outline in every engine; give the focused card the same
   treatment its hover state gets, so the ring is not the only signal. */
.wft-node:focus-visible .wft-card-plate {
    stroke: var(--wft-primary-2, #c3a6ff);
    stroke-width: 2.5;
}

.wft-node:focus {
    outline: none;
}

.wft-node:focus-visible {
    outline: 2px solid var(--wft-primary-2, #c3a6ff);
    outline-offset: 3px;
}

/* Jump past 136 focusable cards instead of tabbing through all of them. */
.wft-skip {
    position: absolute;
    inset-inline-start: 12px;
    top: 8px;
    z-index: 300;
    padding: 9px 16px;
    border-radius: 10px;
    background: var(--wft-primary-2, #c3a6ff);
    color: #fff;
    font-size: 13px;
    font-weight: 700;
    text-decoration: none;
    transform: translateY(-180%);
    transition: transform .16s ease;
}

.wft-skip:focus {
    transform: translateY(0);
}

/* Touch pointers cannot hit a 28px control reliably. Grow the hit area without
   changing the painted size, so the visual density of the bar is preserved. */
@media (pointer: coarse) {
    .wft-container :is(.wft-tool, .wft-chip-nav, .wft-search-clear, .wft-modal-close) {
        position: relative;
    }

    .wft-container :is(.wft-tool, .wft-chip-nav, .wft-search-clear, .wft-modal-close)::after {
        content: "";
        position: absolute;
        inset: 50% auto auto 50%;
        width: 44px;
        height: 44px;
        transform: translate(-50%, -50%);
    }

    /* Matches the specificity of the theme-override rule this file already carries
       for chips; anything lower loses to it. */
    .wft-container .wft-family-chips .wft-chip {
        min-height: 40px;
    }
}

/* ============================================================
   15. User guide
   ============================================================ */

/* Sits under the canvas as part of the page, not as another panel floating over
   it — so it is quieter than the tree and never competes for attention. */
.wft-guide {
    margin: 18px 0 0;
    padding: 20px 22px 22px;
    border: 1px solid var(--wft-line);
    border-radius: var(--wft-r-lg);
    background: linear-gradient(180deg, rgba(26, 22, 48, .5), rgba(16, 13, 33, .5));
    color: var(--wft-ink-2);
    font-size: 13px;
    line-height: 1.7;
    direction: rtl;
    text-align: right;
}

.wft-container.wft-is-fullscreen .wft-toolbar {
    flex: 0 0 auto;
}

.wft-container.wft-is-fullscreen .wft-tree-wrapper {
    flex: 1 1 auto;
    min-height: 0;   /* or the canvas refuses to shrink below its content */
    border-radius: 0;
}

/* In fullscreen the container is the window; the guide would sit below the fold
   with no way to scroll to it. */
.wft-is-fullscreen .wft-guide {
    display: none;
}

/* The theme styles `.entry-content` headings and lists at 0-2-2, which beats a
   plain class. Everything the guide draws is therefore reset at 0-3-0 or higher,
   or it inherits article typography and the block triples in height. */
.wft-container .wft-guide .wft-guide-title {
    margin: 0 0 14px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--wft-ink);
    font-size: 15px;
    line-height: 1.5;
    font-weight: 800;
    letter-spacing: .01em;
}

.wft-container .wft-guide .wft-guide-sub {
    margin: 18px 0 8px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--wft-primary-2);
    font-size: 12.5px;
    line-height: 1.5;
    font-weight: 800;
}

.wft-container .wft-guide .wft-guide-grid > .wft-guide-sub:first-child {
    margin-top: 0;
}

/* Columns rather than a grid: the four sections are very different heights, and
   a grid would size every row to its tallest cell. Flowing them balances the
   block instead, which is what keeps a reference this long down to a glance. */
.wft-guide-grid {
    columns: 3 260px;
    column-gap: 34px;
    orphans: 2;
    widows: 2;
}

/* Nothing may be split across a column break — not a list item mid-sentence, and
   not a heading left stranded at the foot of a column. */
.wft-container .wft-guide .wft-guide-grid :is(li, h3) {
    break-inside: avoid;
}

.wft-container .wft-guide .wft-guide-sub {
    break-after: avoid;
}

/* 0-3-1, so it outweighs the theme's 0-2-2 `.entry-content ul`; anything lower
   loses and the lists come back as bordered cards with article margins. The theme
   also paints its own bullet as `li::before`, which lands inside the icon chips
   and the line swatches, so that is cleared here and re-drawn only where this
   guide asks for one. */
.wft-container .wft-guide .wft-guide-grid :is(ul, ol, li)::before {
    content: none;
}

.wft-container .wft-guide .wft-guide-grid :is(ul, ol, li) {
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    list-style: none;
    font-size: inherit;
}

.wft-container .wft-guide .wft-guide-list li {
    position: relative;
    padding-inline-start: 15px;
    margin-bottom: 5px;
}

.wft-container .wft-guide .wft-guide-grid .wft-guide-list li::before {
    content: "";
    position: absolute;
    inset-inline-start: 0;
    top: .78em;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--wft-primary);
    opacity: .6;
}

/* --- line legend --- */
.wft-container .wft-guide .wft-guide-legend li {
    display: flex;
    align-items: baseline;
    gap: 10px;
    padding-inline-start: 0;
}

.wft-container .wft-guide .wft-guide-legend li::before {
    display: none;
}

.wft-guide-line {
    flex: 0 0 30px;
    height: 0;
    margin-top: .82em;
    border-top: 2px solid var(--wft-primary);
}

.wft-guide-line.is-dashed {
    border-top-style: dashed;
    border-color: var(--wft-ink-3);
}

.wft-guide-line.is-adoptive {
    border-top-style: dashed;
    border-color: #6aa9f0;
}

/* Not a line at all: the jump portal is a pill, so its swatch is one too. */
.wft-guide-line.is-portal {
    height: 13px;
    margin-top: .34em;
    border: 1px solid color-mix(in srgb, var(--wft-primary-2) 58%, transparent);
    border-radius: 7px;
    background: color-mix(in srgb, var(--wft-primary-2) 18%, transparent);
}

/* --- toolbar reference --- */
.wft-container .wft-guide .wft-guide-tools li {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    margin-bottom: 9px;
}

.wft-guide-icon {
    flex: 0 0 30px;
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border: 1px solid var(--wft-line);
    border-radius: var(--wft-r-sm);
    background: rgba(255, 255, 255, .035);
    color: var(--wft-ink-2);
}

.wft-guide-icon svg {
    width: 16px;
    height: 16px;
}

.wft-guide-tool-text strong {
    display: block;
    color: var(--wft-ink);
    font-weight: 700;
}

/* --- keyboard shortcuts --- */
.wft-container .wft-guide .wft-guide-keys li {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 7px;
    margin-bottom: 5px;
}

.wft-container .wft-guide .wft-guide-keys kbd {
    min-width: 24px;
    padding: 1px 7px;
    border: 1px solid var(--wft-line-strong);
    border-bottom-width: 2px;
    border-radius: 6px;
    background: rgba(255, 255, 255, .05);
    color: var(--wft-ink);
    font-family: inherit;
    font-size: 11.5px;
    font-weight: 700;
    text-align: center;
}

/* Coarse pointers have no keyboard and no hover, so two of these sections are
   advice the reader cannot act on. */
@media (pointer: coarse) {
    .wft-guide-keys,
    .wft-guide-sub:has(+ .wft-guide-keys) {
        display: none;
    }
}

@media (max-width: 600px) {
    .wft-guide {
        padding: 16px 16px 18px;
        font-size: 12.5px;
    }
}

/* ============================================================
   16. Page header on phones
   ------------------------------------------------------------
   Not the plugin's own chrome, but the theme's header above it. The theme's
   script sizes a `third_header_height` masthead to `innerHeight / 1.5` — 541px
   of cover art on a 812px phone, so the tree starts two thirds of the way down
   a screen it has to share. The common room already solved this for its own
   pages; this is the same treatment, scoped to pages carrying the tree.
   ============================================================ */

@media screen and (max-width: 768px) {

    /* `!important` because the height is written inline by the theme's script,
       on load and again on every resize.

       A fixed length rather than `auto` or `min-height`: `#masthead::before`
       paints the cover at `height: 100%`, and a percentage only resolves
       against an ancestor with a definite height. Both the header and the
       table wrapper inside it need it — the wrapper carries its own height, so
       capping only the header leaves the child at full size. */
    body.wft-has-tree .site-header,
    body.wft-has-tree .site-brand-main {
        height: clamp(170px, 26vh, 220px) !important;
    }

    /* Deliberately asymmetric. `#masthead` starts at y=0, underneath the fixed
       navbar, so its top rows are never seen. `.site-branding` is a table cell
       centring its content in its own box, and symmetric padding would centre
       the title in the whole box — half a navbar too high in the part the
       reader can actually see. Centring in the visible region needs exactly
       one thing: padding-top − padding-bottom = the navbar's height.

       The 14px on both sides is slack, not alignment: it keeps that difference
       intact while holding the title off the header's edge. Longhand, so the
       theme's horizontal padding survives.

       The script measures the bar and writes `--wft-navbar-h`; the fallback here
       is only for when it has not run yet. Its declared min-height would be the
       wrong number to use — the tools inside the bar are taller than it. */
    body.wft-has-tree .site-brand-main .site-branding {
        padding-top: calc(var(--wft-navbar-h, 62px) + 14px);
        padding-bottom: 14px;
    }

    /* The cell centres everything it holds, so while this arrow is in there the
       title is not what ends up in the middle — it sits a whole arrow's height
       high. It is a hint to scroll past a full-screen cover, which is exactly
       what this header is no longer, and the theme already drops it on phones. */
    body.wft-has-tree .site-brand-main .scrollDown {
        display: none;
    }
}
