diff --git a/README.md b/README.md
deleted file mode 100644
index 9a7490b..0000000
--- a/README.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# Røsstad Familietre
-
-**Nettsiden finner du her:** [https://funnyeivske.github.io/Roesstad/](https://funnyeivske.github.io/Roesstad/)
-
-## Om Nettsiden
-Dette er et digitalt samlingspunkt for Røsstad-familietreet. Nettsiden er designet for å bevare og visualisere familiens historie på en moderne og interaktiv måte.
-
-## Hvordan den fungerer
-
-### 1. Familietre (Hovedvisning)
-Her ser du selve slektstreet.
-- **Navigering:** Du kan dra i bakgrunnen for å flytte deg rundt, og zoome ut/inn.
-- **Personkort:** Klikk på en person for å sette dem i fokus.
-- **Legg til:** Bruk den store grønne knappen nede til høyre for å legge til nye familiemedlemmer.
-
-### 2. Kart
-Se hvor familien har sine røtter.
-- Når du legger til en person, kan du skrive inn et sted (f.eks. "Grimstad").
-- Personen vil da dukke opp som en markør på kartet.
-
-### 3. Tidslinje
-En kronologisk oversikt over familiens historie.
-- Her listes alle fødsler og dødsfall opp automatisk basert på informasjonen i familietreet.
-
----
-*Laget med ❤️ for Røsstad-familien.*
diff --git a/Script.js b/Script.js
deleted file mode 100644
index d695afa..0000000
--- a/Script.js
+++ /dev/null
@@ -1,559 +0,0 @@
-import { initializeApp } from "https://www.gstatic.com/firebasejs/10.14.1/firebase-app.js";
-import { getAuth, onAuthStateChanged, signOut } from "https://www.gstatic.com/firebasejs/10.14.1/firebase-auth.js";
-import { getFirestore, collection, addDoc, updateDoc, doc, onSnapshot, query } from "https://www.gstatic.com/firebasejs/10.14.1/firebase-firestore.js";
-import { firebaseConfig } from "./config.js";
-
-// --- INITIALIZATION ---
-const app = initializeApp(firebaseConfig);
-const auth = getAuth(app);
-const db = getFirestore(app);
-
-// --- STATE ---
-const state = {
- user: null,
- people: [],
- focusId: null,
- scale: 1.0,
- modal: {
- action: null, // 'add-child', 'add-parent-m', etc.
- mode: 'new' // 'new' or 'existing'
- },
- map: null
-};
-
-// --- IMMEDIATE SETUP (UI Handlers) ---
-// This ensures buttons work even if Auth is slow
-// --- IMMEDIATE SETUP (UI Handlers) ---
-// This ensures buttons work even if Auth is slow
-document.addEventListener('DOMContentLoaded', () => {
- setupTabs();
- setupZoom();
- setupModal();
- setupHelp();
- setupFAB();
-});
-
-// --- AUTHENTICATION ---
-onAuthStateChanged(auth, (user) => {
- if (user) {
- state.user = user;
- startDataListener();
- } else {
- // Redirect to login if not authenticated
- // Note: In local development with file://, this might trigger unexpectedly.
- // For now, we assume index.html is the login page.
- if (!window.location.pathname.endsWith('index.html') && !window.location.pathname.endsWith('/')) {
- window.location.href = "index.html";
- }
- }
-});
-
-document.getElementById('btn-logout')?.addEventListener('click', () => {
- signOut(auth).then(() => window.location.href = "index.html");
-});
-
-// --- DATA LISTENER ---
-function startDataListener() {
- const q = query(collection(db, 'familyMembers'));
- onSnapshot(q, (snapshot) => {
- state.people = snapshot.docs.map(d => ({ id: d.id, ...d.data() }));
-
- // Set initial focus if needed
- if (!state.focusId && state.people.length > 0) {
- const me = state.people.find(p => p.name && (p.name.toLowerCase().includes('eivind') || p.name.toLowerCase() === 'meg'));
- state.focusId = me ? me.id : state.people[0].id;
- }
-
- renderAll();
- });
-}
-
-function renderAll() {
- renderTree();
- renderMap();
- renderTimeline();
-}
-
-// --- TAB NAVIGATION ---
-function setupTabs() {
- document.querySelectorAll('.nav-tab[data-view]').forEach(btn => {
- btn.addEventListener('click', () => {
- // Update Active Tab
- document.querySelectorAll('.nav-tab[data-view]').forEach(b => b.classList.remove('active'));
- btn.classList.add('active');
-
- // Show View
- document.querySelectorAll('.view-section').forEach(v => v.classList.add('hidden'));
- const viewId = `view-${btn.dataset.view}`;
- const viewEl = document.getElementById(viewId);
- if (viewEl) viewEl.classList.remove('hidden');
-
- // Special handling for Map resize
- if (btn.dataset.view === 'map' && state.map) {
- setTimeout(() => state.map.invalidateSize(), 100);
- }
- });
- });
-}
-
-// --- TREE RENDERER ---
-// --- TREE RENDERER (GLOBAL) ---
-function renderTree() {
- const grid = document.getElementById('tree-grid');
- const svg = document.getElementById('tree-svg');
- if (!grid || !svg) return;
-
- grid.innerHTML = '';
- svg.innerHTML = ''; // Clear lines
-
- if (state.people.length === 0) {
- grid.innerHTML = `
-
Ingen personer i treet ennå.
-
Klikk på nede til høyre for å starte!
-
`;
- return;
- }
-
- const visited = new Set();
- const roots = findRoots();
-
- roots.forEach(root => {
- if (!visited.has(root.id)) {
- const treeNode = buildTreeNode(root, visited);
- grid.appendChild(treeNode);
- }
- });
-
- // Draw lines after layout is computed
- setTimeout(drawConnections, 100);
- window.addEventListener('resize', drawConnections);
-}
-
-function findRoots() {
- // A root is someone whose parents are NOT in the current list
- return state.people.filter(p => {
- const father = state.people.find(parent => parent.id === p.fatherId);
- const mother = state.people.find(parent => parent.id === p.motherId);
- return !father && !mother;
- });
-}
-
-function buildTreeNode(person, visited) {
- visited.add(person.id);
-
- // Container
- const container = document.createElement('div');
- container.className = 'node-container';
-
- // 1. Couple Wrapper
- const coupleWrapper = document.createElement('div');
- coupleWrapper.className = 'couple-wrapper';
-
- // Person Card
- const pCard = createCard(person);
- pCard.onclick = () => setFocus(person.id); // Keep focus logic for editing
- coupleWrapper.appendChild(pCard);
-
- // Partner Card
- if (person.partnerId) {
- const partner = state.people.find(p => p.id === person.partnerId);
- if (partner && !visited.has(partner.id)) {
- visited.add(partner.id);
- const partCard = createCard(partner);
- partCard.onclick = () => setFocus(partner.id);
- coupleWrapper.appendChild(partCard);
- }
- }
- container.appendChild(coupleWrapper);
-
- // 2. Children
- // Find children where this person (or partner) is a parent
- const children = state.people.filter(p =>
- p.fatherId === person.id || p.motherId === person.id ||
- (person.partnerId && (p.fatherId === person.partnerId || p.motherId === person.partnerId))
- );
-
- if (children.length > 0) {
- const childrenContainer = document.createElement('div');
- childrenContainer.className = 'children-container';
-
- // Sort children by birth date
- children.sort((a, b) => (a.birthDate || '9999') > (b.birthDate || '9999') ? 1 : -1);
-
- children.forEach(child => {
- if (!visited.has(child.id)) {
- const childNode = buildTreeNode(child, visited);
- childrenContainer.appendChild(childNode);
- }
- });
- container.appendChild(childrenContainer);
- }
-
- return container;
-}
-function drawConnections() {
- const svg = document.getElementById('tree-svg');
- const grid = document.getElementById('tree-grid');
- if (!svg || !grid) return;
-
- svg.innerHTML = '';
- const svgRect = svg.getBoundingClientRect();
-
- // Map all visible cards by ID
- const cardMap = new Map();
- document.querySelectorAll('.card').forEach(card => {
- if (card.dataset.id) cardMap.set(card.dataset.id, card);
- });
-
- const drawnPartners = new Set();
-
- // Helper for coordinates
- const getCenter = (el) => {
- const rect = el.getBoundingClientRect();
- return {
- x: rect.left + rect.width / 2 - svgRect.left,
- y: rect.top + rect.height / 2 - svgRect.top,
- bottom: rect.bottom - svgRect.top,
- top: rect.top - svgRect.top
- };
- };
-
- state.people.forEach(p => {
- const pCard = cardMap.get(p.id);
- if (!pCard) return;
-
- const pCenter = getCenter(pCard);
-
- // 1. Parent Connections
- [p.fatherId, p.motherId].forEach(parentId => {
- if (parentId) {
- const parentCard = cardMap.get(parentId);
- if (parentCard) {
- const parCenter = getCenter(parentCard);
- // Draw Curved Line
- // From Parent Bottom to Child Top
- const path = `M ${parCenter.x} ${parCenter.bottom}
- C ${parCenter.x} ${parCenter.bottom + 50},
- ${pCenter.x} ${pCenter.top - 50},
- ${pCenter.x} ${pCenter.top}`;
- createPath(svg, path);
- }
- }
- });
-
- // 2. Partner Connection
- if (p.partnerId) {
- const partnerCard = cardMap.get(p.partnerId);
- if (partnerCard) {
- // Avoid drawing twice
- const pairId = [p.id, p.partnerId].sort().join('-');
- if (!drawnPartners.has(pairId)) {
- drawnPartners.add(pairId);
- const partCenter = getCenter(partnerCard);
- createPath(svg, `M ${pCenter.x} ${pCenter.y} L ${partCenter.x} ${partCenter.y}`);
- }
- }
- }
- });
-}
-
-function createPath(svg, d) {
- const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
- path.setAttribute("d", d);
- path.setAttribute("class", "connector");
- svg.appendChild(path);
-}
-
-function setFocus(id) {
- state.focusId = id;
- document.querySelectorAll('.card').forEach(c => c.classList.remove('focus'));
- renderTree();
-}
-
-function createCard(person) {
- const isFocus = (person.id === state.focusId);
- const el = document.createElement('div');
- el.className = `card ${isFocus ? 'focus' : ''} ${person.gender === 'F' ? 'female' : 'male'}`;
- el.dataset.id = person.id; // Crucial for connections
-
- const year = person.birthDate ? new Date(person.birthDate).getFullYear() : '';
- const dead = person.deathDate ? '✝ ' : '';
- const loc = person.location ? person.location.split(',')[0] : '';
-
- el.innerHTML = `
-
- ${person.name}
- ${dead}${year}
- ${loc ? ` ${loc}
` : ''}
- `;
-
- // Always show actions if focused
- if (isFocus) {
- const actions = document.createElement('div');
- actions.className = 'mini-actions';
-
- // Add Child Button
- const btnChild = document.createElement('button');
- btnChild.className = 'btn-mini btn-add-child';
- btnChild.innerHTML = '';
- btnChild.title = "Legg til barn";
- btnChild.onclick = (e) => { e.stopPropagation(); window.openModal('add-child'); };
- actions.appendChild(btnChild);
-
- // Add Partner Button (if none)
- if (!person.partnerId) {
- const btnPartner = document.createElement('button');
- btnPartner.className = 'btn-mini btn-add-partner';
- btnPartner.innerHTML = '';
- btnPartner.title = "Legg til partner";
- btnPartner.onclick = (e) => { e.stopPropagation(); window.openModal('add-partner'); };
- actions.appendChild(btnPartner);
- }
- el.appendChild(actions);
- }
- return el;
-}
-
-function createSlot(person, label, action) {
- // Deprecated in global view, but kept if needed for other views
- return document.createElement('div');
-}
-
-
-// --- MAP RENDERER ---
-function renderMap() {
- if (!state.map) {
- const mapContainer = document.getElementById('map-container');
- if (!mapContainer) return;
-
- state.map = L.map('map-container').setView([65.0, 13.0], 5);
- L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
- attribution: '© OpenStreetMap © CARTO',
- subdomains: 'abcd',
- maxZoom: 19
- }).addTo(state.map);
- }
-
- // Clear existing markers
- state.map.eachLayer(layer => {
- if (layer instanceof L.Marker) state.map.removeLayer(layer);
- });
-
- // Add markers
- state.people.forEach(p => {
- if (p.location) {
- // Simple geocoding simulation for demo
- let lat = 0, lng = 0;
- if (p.location.includes(',')) {
- const parts = p.location.split(',');
- lat = parseFloat(parts[0]);
- lng = parseFloat(parts[1]);
- } else if (p.location.toLowerCase().includes('grimstad')) {
- lat = 58.34 + (Math.random() * 0.02); lng = 8.59 + (Math.random() * 0.02);
- } else if (p.location.toLowerCase().includes('oslo')) {
- lat = 59.91; lng = 10.75;
- }
-
- if (lat && lng) {
- L.marker([lat, lng]).addTo(state.map)
- .bindPopup(`${p.name}
${p.location}`);
- }
- }
- });
-}
-
-// --- TIMELINE RENDERER ---
-function renderTimeline() {
- const container = document.getElementById('timeline-list');
- if (!container) return;
-
- container.innerHTML = '';
- const events = [];
-
- state.people.forEach(p => {
- if (p.birthDate) events.push({ date: p.birthDate, type: 'Født', person: p.name, desc: p.description });
- if (p.deathDate) events.push({ date: p.deathDate, type: 'Død', person: p.name });
- });
-
- events.sort((a, b) => new Date(a.date) - new Date(b.date));
-
- events.forEach(ev => {
- const div = document.createElement('div');
- div.className = 'timeline-event';
- const dateStr = new Date(ev.date).toLocaleDateString('no-NO', { year: 'numeric', month: 'long', day: 'numeric' });
-
- div.innerHTML = `
- ${dateStr}
-
-
${ev.person} ${ev.type.toLowerCase()}
- ${ev.desc ? `
${ev.desc}
` : ''}
-
- `;
- container.appendChild(div);
- });
-}
-
-// --- MODAL LOGIC ---
-function setupModal() {
- window.openModal = (action) => {
- state.modal.action = action;
- const overlay = document.getElementById('modal-overlay');
- if (overlay) overlay.classList.remove('hidden');
-
- // Reset Form
- document.querySelectorAll('.input-field').forEach(i => i.value = '');
-
- // Set Title
- const title = document.getElementById('modal-title');
- if (title) {
- if (action === 'add-parent-m') title.textContent = "Legg til Far";
- else if (action === 'add-parent-f') title.textContent = "Legg til Mor";
- else if (action === 'add-child') title.textContent = "Legg til Barn";
- else if (action === 'add-partner') title.textContent = "Legg til Partner";
- else title.textContent = "Legg til Person";
- }
-
- // Default Mode
- window.setModalMode('new');
- renderExistingList();
- };
-
- window.setModalMode = (mode) => {
- state.modal.mode = mode;
- document.getElementById('tab-new').classList.toggle('active', mode === 'new');
- document.getElementById('tab-existing').classList.toggle('active', mode === 'existing');
- document.getElementById('form-new').classList.toggle('hidden', mode !== 'new');
- document.getElementById('form-existing').classList.toggle('hidden', mode !== 'existing');
- };
-
- const closeBtn = document.getElementById('btn-close-modal');
- if (closeBtn) closeBtn.onclick = () => {
- document.getElementById('modal-overlay').classList.add('hidden');
- };
-
- const saveBtn = document.getElementById('btn-save');
- if (saveBtn) saveBtn.onclick = async () => {
- const focusP = state.people.find(p => p.id === state.focusId);
- let targetId = null;
-
- if (state.modal.mode === 'new') {
- const newPerson = {
- name: document.getElementById('inp-name').value,
- birthDate: document.getElementById('inp-birth').value,
- deathDate: document.getElementById('inp-death').value,
- location: document.getElementById('inp-location').value,
- description: document.getElementById('inp-desc').value,
- gender: document.querySelector('input[name="gender"]:checked').value,
- fatherId: null, motherId: null, partnerId: null
- };
-
- // Auto-link logic
- if (state.modal.action === 'add-child' && focusP) {
- if (focusP.gender === 'M') newPerson.fatherId = focusP.id;
- else newPerson.motherId = focusP.id;
-
- if (focusP.partnerId) {
- const part = state.people.find(p => p.id === focusP.partnerId);
- if (part) {
- if (part.gender === 'M') newPerson.fatherId = part.id;
- else newPerson.motherId = part.id;
- }
- }
- }
-
- const docRef = await addDoc(collection(db, 'familyMembers'), newPerson);
- targetId = docRef.id;
-
- // If creating first person or using generic add
- if (state.modal.action === 'create-first' || !state.focusId) {
- state.focusId = targetId;
- }
-
- } else {
- targetId = document.getElementById('selected-existing-id').value;
- }
-
- // Link Relations
- if (focusP && targetId && state.modal.action !== 'create-first' && state.modal.action !== 'add-generic') {
- const col = collection(db, 'familyMembers');
- const updates = [];
-
- if (state.modal.action === 'add-parent-m') updates.push(updateDoc(doc(col, state.focusId), { fatherId: targetId }));
- else if (state.modal.action === 'add-parent-f') updates.push(updateDoc(doc(col, state.focusId), { motherId: targetId }));
- else if (state.modal.action === 'add-partner') {
- updates.push(updateDoc(doc(col, state.focusId), { partnerId: targetId }));
- updates.push(updateDoc(doc(col, targetId), { partnerId: state.focusId }));
- } else if (state.modal.action === 'add-child' && state.modal.mode === 'existing') {
- const upd = {};
- if (focusP.gender === 'M') upd.fatherId = focusP.id; else upd.motherId = focusP.id;
- updates.push(updateDoc(doc(col, targetId), upd));
- }
- await Promise.all(updates);
- }
-
- document.getElementById('modal-overlay').classList.add('hidden');
- };
-}
-
-function renderExistingList() {
- const list = document.getElementById('existing-list');
- if (!list) return;
- list.innerHTML = '';
- state.people.filter(p => p.id !== state.focusId).forEach(p => {
- const div = document.createElement('div');
- div.style.padding = '0.5rem';
- div.style.borderBottom = '1px solid #f1f5f9';
- div.style.cursor = 'pointer';
- div.textContent = p.name;
- div.onclick = () => {
- document.getElementById('selected-existing-id').value = p.id;
- div.style.background = '#f0fdf4';
- };
- list.appendChild(div);
- });
-}
-
-// --- ZOOM ---
-function setupZoom() {
- const grid = document.getElementById('tree-grid');
- const display = document.getElementById('zoom-display');
-
- const btnIn = document.getElementById('btn-zoom-in');
- if (btnIn) btnIn.onclick = () => {
- state.scale += 0.1;
- updateZoom();
- };
-
- const btnOut = document.getElementById('btn-zoom-out');
- if (btnOut) btnOut.onclick = () => {
- if (state.scale > 0.4) state.scale -= 0.1;
- updateZoom();
- };
-
- function updateZoom() {
- if (grid) grid.style.transform = `scale(${state.scale})`;
- if (display) display.textContent = Math.round(state.scale * 100) + '%';
- }
-}
-
-// --- HELP ---
-function setupHelp() {
- const btn = document.getElementById('btn-help');
- const modal = document.getElementById('modal-help');
- const close = document.getElementById('btn-close-help');
-
- if (btn && modal) {
- btn.onclick = () => modal.classList.remove('hidden');
- }
- if (close && modal) {
- close.onclick = () => modal.classList.add('hidden');
- }
-}
-
-// --- FAB ---
-function setupFAB() {
- const fab = document.getElementById('fab-add');
- if (fab) {
- fab.onclick = () => window.openModal('add-generic');
- }
-}
diff --git a/app.html b/app.html
deleted file mode 100644
index c0a0e67..0000000
--- a/app.html
+++ /dev/null
@@ -1,166 +0,0 @@
-
-
-
-
-
-
- Røsstad Familietre
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Velkommen til Røsstad Familietre!
-
- - Legg til person: Klikk på den store grønne pluss-knappen nede til høyre, eller
- bruk de små knappene på kortene.
- - Navigasjon: Bruk fanene øverst for å bytte mellom Tre, Kart og Tidslinje.
- - Zoom: Bruk pluss/minus knappene oppe til høyre for å zoome i treet.
- - Flytt treet: Du kan dra og slippe treet for å bevege deg rundt.
-
-
Tips: Legg til et sted (f.eks. "Grimstad") for å se personen på kartet!
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/config.js b/config.js
deleted file mode 100644
index bf7e3d6..0000000
--- a/config.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// --- FIREBASE CONFIGURATION ---
-export const firebaseConfig = {
- apiKey: "AIzaSyD-E58BdRwFCHDmsgRG9-PEWzMaQoheJ-0",
- authDomain: "roesstad-9fd48.firebaseapp.com",
- projectId: "roesstad-9fd48",
- storageBucket: "roesstad-9fd48.firebasestorage.app",
- messagingSenderId: "704119736902",
- appId: "1:704119736902:web:bc47f2b6a1383de0479847"
-};
diff --git a/index.html b/index.html
deleted file mode 100644
index dc1705d..0000000
--- a/index.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
-
-
- Logg Inn - Røsstad Arkivet
-
-
-
-
-
-
-
-
-
-
-
-
Røsstad Arkivet
-
Logg inn for å utforske familiens historie
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/login.js b/login.js
deleted file mode 100644
index 62e1da6..0000000
--- a/login.js
+++ /dev/null
@@ -1,92 +0,0 @@
-import { initializeApp } from "https://www.gstatic.com/firebasejs/10.14.1/firebase-app.js";
-import { getAuth, signInWithEmailAndPassword } from "https://www.gstatic.com/firebasejs/10.14.1/firebase-auth.js";
-import { firebaseConfig } from "./config.js";
-
-// --- INIT ---
-const app = initializeApp(firebaseConfig);
-const auth = getAuth(app);
-
-// --- DOM ELEMENTS ---
-const form = document.getElementById('login-form');
-const emailInput = document.getElementById('inp-email');
-const passwordInput = document.getElementById('inp-password');
-const loginBtn = document.getElementById('btn-login');
-const errorMsg = document.getElementById('error-msg');
-
-// --- LOGIN LOGIC ---
-if (form) {
- form.addEventListener('submit', async (e) => {
- e.preventDefault();
-
- const email = emailInput.value.trim();
- const password = passwordInput.value;
-
- if (!email || !password) {
- showError("Vennligst fyll ut både e-post og passord.");
- return;
- }
-
- setLoading(true);
-
- try {
- await signInWithEmailAndPassword(auth, email, password);
- // Redirect on success
- window.location.href = "app.html";
- } catch (error) {
- console.error("Login error:", error);
- handleError(error);
- setLoading(false);
- }
- });
-}
-
-function setLoading(isLoading) {
- if (isLoading) {
- loginBtn.textContent = "Logger inn...";
- loginBtn.disabled = true;
- errorMsg.textContent = "";
- } else {
- loginBtn.textContent = "Logg Inn";
- loginBtn.disabled = false;
- }
-}
-
-function handleError(error) {
- let message = "En ukjent feil oppstod.";
-
- switch (error.code) {
- case 'auth/invalid-credential':
- case 'auth/user-not-found':
- case 'auth/wrong-password':
- message = "Feil e-post eller passord.";
- break;
- case 'auth/too-many-requests':
- message = "For mange forsøk. Vennligst vent litt og prøv igjen.";
- break;
- case 'auth/invalid-email':
- message = "Ugyldig e-postadresse.";
- break;
- }
-
- showError(message);
-}
-
-function showError(msg) {
- errorMsg.textContent = msg;
- // Shake animation effect
- const container = document.querySelector('.login-container');
- container.style.animation = 'none';
- container.offsetHeight; /* trigger reflow */
- container.style.animation = 'shake 0.5s';
-}
-
-// Add shake keyframes dynamically
-const style = document.createElement('style');
-style.innerHTML = `
-@keyframes shake {
- 0%, 100% { transform: translateX(0); }
- 10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
- 20%, 40%, 60%, 80% { transform: translateX(5px); }
-}
-`;
-document.head.appendChild(style);
diff --git a/style.css b/style.css
index 417af22..55e4f05 100644
--- a/style.css
+++ b/style.css
@@ -1,6 +1,6 @@
/* --- RØSSTAD DESIGN SYSTEM --- */
@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap');
-@import url('tree.css');
+
:root {
/* --- PALETTE: Røsstad Green --- */
@@ -27,492 +27,4 @@
--color-text-muted: #64748b;
/* Slate 500 */
- max-width: 400px;
- text-align: center;
- color: white;
- border: 1px solid rgba(255, 255, 255, 0.2);
- box-shadow: var(--shadow-lg);
-}
-
-.login-logo {
- font-size: 4rem;
- color: var(--color-primary-light);
- margin-bottom: 1rem;
-}
-
-.login-title {
- font-size: 1.5rem;
- font-weight: 700;
- margin: 0 0 0.5rem 0;
-}
-
-.login-subtitle {
- font-size: 0.9rem;
- opacity: 0.8;
- margin-bottom: 2rem;
- font-weight: 300;
-}
-
-.input-field {
- width: 100%;
- padding: 1rem;
- margin-bottom: 1rem;
- border: none;
- border-radius: var(--radius-md);
- background: rgba(255, 255, 255, 0.95);
- font-family: inherit;
- font-size: 1rem;
- transition: box-shadow 0.2s;
-}
-
-.input-field:focus {
- outline: none;
- box-shadow: 0 0 0 3px rgba(45, 212, 191, 0.5);
-}
-
-.btn-primary {
- width: 100%;
- padding: 1rem;
- border: none;
- border-radius: var(--radius-md);
- background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark));
- color: white;
- font-weight: 600;
- font-size: 1rem;
- cursor: pointer;
- transition: transform 0.2s, box-shadow 0.2s;
-}
-
-.btn-primary:hover {
- transform: translateY(-2px);
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
-}
-
-.error-message {
- color: #fda4af;
- margin-top: 1rem;
- font-size: 0.9rem;
- min-height: 1.2em;
-}
-
-/* --- MAIN APP LAYOUT --- */
-#app-root {
- display: flex;
- flex-direction: column;
- height: 100vh;
-}
-
-/* Header */
-.app-header {
- background: var(--color-surface-glass);
- backdrop-filter: blur(10px);
- padding: 0.8rem 2rem;
- display: flex;
- justify-content: space-between;
- align-items: center;
- border-bottom: 1px solid rgba(0, 0, 0, 0.05);
- z-index: 100;
-}
-
-.brand-logo {
- display: flex;
- align-items: center;
- gap: 0.8rem;
- font-size: 1.2rem;
- font-weight: 700;
- color: var(--color-primary-dark);
-}
-
-.brand-logo i {
- color: var(--color-primary);
- font-size: 1.5rem;
-}
-
-/* Navigation Tabs */
-.nav-tabs {
- display: flex;
- gap: 0.5rem;
- background: rgba(0, 0, 0, 0.05);
- padding: 0.3rem;
- border-radius: var(--radius-md);
-}
-
-.nav-tab {
- padding: 0.5rem 1.2rem;
- border: none;
- background: transparent;
- border-radius: var(--radius-sm);
- color: var(--color-text-muted);
- font-weight: 600;
- cursor: pointer;
- transition: all 0.2s;
-}
-
-.nav-tab.active {
- background: white;
- color: var(--color-primary);
- box-shadow: var(--shadow-sm);
-}
-
-.nav-tab:hover:not(.active) {
- color: var(--color-primary);
- background: rgba(255, 255, 255, 0.5);
-}
-
-/* Controls */
-.header-controls {
- display: flex;
- align-items: center;
- gap: 1rem;
-}
-
-.icon-btn {
- background: none;
- border: none;
- font-size: 1.5rem;
- color: var(--color-text-muted);
- cursor: pointer;
- transition: color 0.2s;
- display: flex;
-}
-
-.icon-btn:hover {
- color: var(--color-primary);
-}
-
-.btn-logout {
- font-size: 0.9rem;
- padding: 0.4rem 1rem;
- border: 1px solid var(--color-primary);
- color: var(--color-primary);
- background: transparent;
- border-radius: var(--radius-sm);
- cursor: pointer;
- font-weight: 600;
-}
-
-.btn-logout:hover {
- background: var(--color-primary);
- color: white;
-}
-
-/* --- VIEW SECTIONS --- */
-.view-section {
- flex: 1;
- overflow: hidden;
- position: relative;
-}
-
-/* Tree View */
-#tree-container {
- width: 100%;
- height: 100%;
- overflow: auto;
- display: flex;
- justify-content: center;
- align-items: center;
- padding: 4rem;
- cursor: grab;
-}
-
-#tree-container:active {
- cursor: grabbing;
-}
-
-.tree-grid {
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 5rem;
- transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
-}
-
-.tree-row {
- display: flex;
- justify-content: center;
- gap: 3rem;
-}
-
-.tree-row.children {
- gap: 2rem;
- flex-wrap: wrap;
-}
-
-/* Person Card */
-.card {
- width: 200px;
- min-height: 130px;
- background: var(--color-surface-glass);
- border: 1px solid white;
- border-radius: var(--radius-md);
- padding: 1.2rem;
- display: flex;
- flex-direction: column;
- align-items: center;
- box-shadow: var(--shadow-md);
- cursor: pointer;
- transition: all 0.3s;
- position: relative;
-}
-
-.card:hover {
- transform: translateY(-5px);
- box-shadow: var(--shadow-lg);
- border-color: var(--color-primary-light);
-}
-
-.card.focus {
- transform: scale(1.15);
- z-index: 10;
- border: 2px solid var(--color-primary);
- background: white;
- box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
-}
-
-.card-avatar {
- font-size: 2rem;
- padding: 0.5rem;
- border-radius: 50%;
- margin-bottom: 0.5rem;
-}
-
-.card.male .card-avatar {
- color: var(--color-male);
- background: #e0f2fe;
-}
-
-.card.female .card-avatar {
- color: var(--color-female);
- background: #ffe4e6;
-}
-
-.card-name {
- font-size: 1rem;
- font-weight: 700;
- margin: 0.2rem 0;
- text-align: center;
-}
-
-.card-dates {
- font-size: 0.8rem;
- color: var(--color-text-muted);
- font-family: monospace;
-}
-
-.card-location {
- font-size: 0.7rem;
- margin-top: 0.5rem;
- padding: 2px 8px;
- background: rgba(45, 212, 191, 0.15);
- color: var(--color-primary-dark);
- border-radius: 10px;
- display: flex;
- align-items: center;
- gap: 4px;
-}
-
-/* Add Buttons (Mini) */
-.mini-actions {
- position: absolute;
- inset: 0;
- pointer-events: none;
-}
-
-.btn-mini {
- pointer-events: auto;
- position: absolute;
- width: 32px;
- height: 32px;
- border-radius: 50%;
- background: var(--color-primary);
- color: white;
- border: none;
- display: flex;
- justify-content: center;
- align-items: center;
- cursor: pointer;
- box-shadow: var(--shadow-md);
- transition: transform 0.2s;
-}
-
-.btn-mini:hover {
- transform: scale(1.2);
- background: var(--color-primary-dark);
-}
-
-.btn-add-child {
- bottom: -16px;
- left: 50%;
- transform: translateX(-50%);
-}
-
-.btn-add-partner {
- top: 50%;
- right: -16px;
- transform: translateY(-50%);
-}
-
-/* Empty Slot */
-.slot {
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 0.5rem;
-}
-
-.slot-label {
- font-size: 0.7rem;
- font-weight: 700;
- text-transform: uppercase;
- color: var(--color-text-muted);
- opacity: 0.7;
-}
-
-.btn-slot {
- width: 50px;
- height: 50px;
- border-radius: 50%;
- border: 2px dashed #cbd5e1;
- background: rgba(255, 255, 255, 0.5);
- color: #94a3b8;
- display: flex;
- justify-content: center;
- align-items: center;
- font-size: 1.5rem;
- cursor: pointer;
- transition: all 0.2s;
-}
-
-.btn-slot:hover {
- border-color: var(--color-primary);
- overflow-y: auto;
- height: 100%;
-}
-
-.timeline-event {
- position: relative;
- padding-left: 2rem;
- margin-bottom: 2rem;
- border-left: 2px solid var(--color-primary-light);
-}
-
-.timeline-event::before {
- content: '';
- position: absolute;
- left: -6px;
- top: 0;
- width: 10px;
- height: 10px;
- border-radius: 50%;
- background: var(--color-primary);
-}
-
-.event-date {
- font-weight: 700;
- color: var(--color-primary);
- font-size: 0.9rem;
-}
-
-.event-card {
- background: white;
- padding: 1rem;
- border-radius: var(--radius-md);
- box-shadow: var(--shadow-sm);
- margin-top: 0.5rem;
-}
-
-/* --- MODAL --- */
-.modal-overlay {
- position: fixed;
- inset: 0;
- background: rgba(15, 47, 36, 0.6);
- backdrop-filter: blur(4px);
- z-index: 1000;
- display: flex;
- justify-content: center;
- align-items: center;
- opacity: 0;
- animation: fadeIn 0.2s forwards;
-}
-
-@keyframes fadeIn {
- to {
- opacity: 1;
- }
-}
-
-.modal-content {
- background: white;
- width: 90%;
- max-width: 500px;
- border-radius: var(--radius-lg);
- padding: 2rem;
- box-shadow: var(--shadow-lg);
- transform: scale(0.95);
- animation: popIn 0.3s forwards;
-}
-
-@keyframes popIn {
- to {
- transform: scale(1);
- }
-}
-
-.modal-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 1.5rem;
- border-bottom: 1px solid #f1f5f9;
- padding-bottom: 1rem;
-}
-
-.modal-title {
- font-size: 1.4rem;
- font-weight: 700;
- color: var(--color-primary-dark);
- margin: 0;
-}
-
-.form-group {
- margin-bottom: 1rem;
-}
-
-
-.form-label {
- display: block;
- font-size: 0.85rem;
- font-weight: 700;
- margin-bottom: 0.4rem;
-}
-
-.form-row {
- display: flex;
- gap: 1rem;
-}
-
-/* --- FAB (Floating Action Button) --- */
-.fab-btn {
- position: fixed;
- bottom: 2rem;
- right: 2rem;
- width: 64px;
- height: 64px;
- border-radius: 50%;
- background: var(--color-primary);
- color: white;
- border: none;
- box-shadow: var(--shadow-lg);
- display: flex;
- justify-content: center;
- align-items: center;
- font-size: 2rem;
- cursor: pointer;
- z-index: 500;
- transition: transform 0.2s, background 0.2s;
-}
-
-.fab-btn:hover {
- transform: scale(1.1) rotate(90deg);
- background: var(--color-primary-dark);
}
\ No newline at end of file