Stylizacja, zmiana mapy zasięgu

This commit is contained in:
dm
2025-11-26 14:37:07 +01:00
parent 8bf578e6d9
commit a0f4e8fbab
29 changed files with 339 additions and 557 deletions

View File

@@ -9,7 +9,6 @@ const {
ctas = [] ctas = []
} = Astro.props; } = Astro.props;
// Automatyczne wczytanie wszystkich obrazów hero
const images = import.meta.glob<{ default: ImageMetadata }>('/src/assets/hero/*.{png,jpg,jpeg,webp,avif}', { const images = import.meta.glob<{ default: ImageMetadata }>('/src/assets/hero/*.{png,jpg,jpeg,webp,avif}', {
eager: true eager: true
}); });
@@ -44,7 +43,6 @@ const isLCP = true;
)} )}
<div class="f-hero-inner"> <div class="f-hero-inner">
{Array.isArray(title) {Array.isArray(title)
? title.map(line => ( ? title.map(line => (
<h1>{line}</h1> <h1>{line}</h1>

View File

@@ -7,7 +7,7 @@ const links = [
{ name: "INTERNET I TELEWIZJA", href: "/internet-telewizja" }, { name: "INTERNET I TELEWIZJA", href: "/internet-telewizja" },
{ name: "TELEFON", href: "/telefon" }, { name: "TELEFON", href: "/telefon" },
{ name: "ZASIĘG SIECI", href: "/mapa-zasiegu" }, { name: "ZASIĘG SIECI", href: "/mapa-zasiegu" },
{ name: "KONTAKT", href: "/#contact" }, { name: "KONTAKT", href: "/kontakt" },
{ {
name: "BOK", name: "BOK",
href: "https://panel.fuz.pl/userpanel/auth", href: "https://panel.fuz.pl/userpanel/auth",

View File

@@ -1,12 +1,10 @@
--- ---
const { cities = [] } = Astro.props; const { cities = [] } = Astro.props;
// sortujemy alfabetycznie
const sorted = cities.sort((a: string, b: any) => a.localeCompare(b, "pl")); const sorted = cities.sort((a: string, b: any) => a.localeCompare(b, "pl"));
--- ---
<div class="fuz-cities-box"> <div class="fuz-cities-box">
<h4 class="fuz-cities-title">Miejscowości w zasięgu sieci światłowodowej i radiowej</h4> <h4 class="fuz-cities-title">Miejscowości w zasięgu sieci światłowodowej</h4>
<div class="fuz-cities-grid"> <div class="fuz-cities-grid">
{sorted.map((city: unknown) => ( {sorted.map((city: unknown) => (
@@ -20,7 +18,6 @@ const sorted = cities.sort((a: string, b: any) => a.localeCompare(b, "pl"));
background: var(--f-background); background: var(--f-background);
color: var(--f-text); color: var(--f-text);
padding: 16px; padding: 16px;
} }

View File

@@ -13,7 +13,7 @@ const {
description = "", description = "",
showMarker = false, showMarker = false,
mode = "full", mode = "full",
mapStyleId = "8e0a97af9476f2d3" // Google DEMO mapId (legalne, bez warningów) mapStyleId = "8e0a97af9476f2d3"
} = Astro.props; } = Astro.props;
/** ID kontenera w DOM */ /** ID kontenera w DOM */
@@ -119,9 +119,11 @@ const domId = `fuz-map-${Math.random().toString(36).slice(2)}`;
if (title || desc) { if (title || desc) {
const info = new InfoWindow({ const info = new InfoWindow({
content: ` content: `
<div class="fuz-map-infowindow"> <div class="f-info-window">
<strong>${title}</strong><br/> <div class="f-info-header">
${desc} <div class="f-info-city">${title}</div>
<div class="f-info-street">${desc}</div>
</div>
</div> </div>
` `
}); });

View File

@@ -1,15 +0,0 @@
---
const { id, label } = Astro.props;
---
<label class="flex items-center gap-2 cursor-pointer select-none text-sm">
<input
id={id}
type="checkbox"
class="h-4 w-4 rounded border-gray-400"
onchange={id === "fiber-toggle"
? "fiberRangeShow()"
: "radioRangeShow()"}
/>
<span>{label}</span>
</label>

View File

@@ -1,184 +1,125 @@
--- ---
import yaml from "js-yaml"; import yaml from "js-yaml";
import fs from "fs"; import fs from "fs";
import MapGoogle from "../maps/MapGoogle.astro"; import MapGoogle from "../../components/maps/MapGoogle.astro";
// import "../../styles/contact.css";
const data = yaml.load( const data = yaml.load(
fs.readFileSync("./src/content/contact/contact.yaml", "utf8"), fs.readFileSync("./src/content/contact/contact.yaml", "utf8")
); );
const apiKey = import.meta.env.PUBLIC_GOOGLE_MAPS_KEY; const apiKey = import.meta.env.PUBLIC_GOOGLE_MAPS_KEY;
const form = data.form; const form = data.form;
--- ---
<section id="contact" class="f-section"> <section id="kontakt" class="f-section">
<div class="f-contact-grid"> <div class="f-contact-grid">
<!-- Lewa kolumna --> <!-- Kolumna lewa -->
<div class="f-contact-col-1"> <div class="f-contact-col-1">
<h2>{data.title}</h2> <h2>{data.title}</h2>
<div class="f-contact-item" set:html={data.description} /> <div class="f-contact-item" set:html={data.description}></div>
</div>
<!-- Formularz -->
<div class="f-contact-col-2">
<h2>{data.contactFormTitle}</h2>
<form id="contactForm" class="f-contact-form">
<div class="f-contact-form-inner">
<input
type="text"
name="firstName"
placeholder={form.firstName.placeholder}
class="f-input"
required
/>
<input
type="text"
name="lastName"
placeholder={form.lastName.placeholder}
class="f-input"
required
/>
</div>
<div class="grid grid-cols-2 gap-4">
<input
type="email"
name="email"
placeholder={form.email.placeholder}
class="f-input"
required
autocomplete="email"
/>
<input
type="tel"
name="phone"
placeholder={form.phone.placeholder}
class="f-input"
required
autocomplete="tel"
/>
</div>
<input
type="text"
name="subject"
placeholder={form.subject.placeholder}
class="f-input"
required
/>
<textarea
name="message"
rows={form.message.rows}
placeholder={form.message.placeholder}
class="f-input"
required></textarea>
<label class="f-rodo">
<input type="checkbox" name="rodo" required />
<span>
{form.rodo.label}
<a
href={form.rodo.policyLink}
title={form.rodo.policyTitle}
>{form.rodo.policyText}</a
>.
</span>
</label>
<button title={form.submit.title}>
{form.submit.label}
</button>
</form>
</div>
</div> </div>
<div class="f-contact-map"> <div class="f-contact-col-2">
<MapGoogle <h2>{data.contactFormTitle}</h2>
apiKey={apiKey} <form id="contactForm" class="f-contact-form">
lat={data.lat} <div class="f-contact-form-inner">
lon={data.lng} <input type="text" name="firstName" placeholder={form.firstName.placeholder} class="f-input" required />
zoom={16} <input type="text" name="lastName" placeholder={form.lastName.placeholder} class="f-input" required />
title={data.markerTitle} </div>
description={data.markerAddress}
showMarker={true} <div class="grid grid-cols-2 gap-4">
mode="contact" <input type="email" name="email" placeholder={form.email.placeholder} class="f-input" required autocomplete="email" />
mapStyleId={data.maps.mapId} <input type="tel" name="phone" placeholder={form.phone.placeholder} class="f-input" required autocomplete="tel" />
/> </div>
<input type="text" name="subject" placeholder={form.subject.placeholder} class="f-input" required />
<textarea name="message" rows={form.message.rows} placeholder={form.message.placeholder} class="f-input" required></textarea>
<label class="f-rodo">
<input type="checkbox" name="rodo" required />
<span>
{form.rodo.label}
<a href={form.rodo.policyLink} title={form.rodo.policyTitle}>{form.rodo.policyText}</a>.
</span>
</label>
<button title={form.submit.title}>{form.submit.label}</button>
</form>
</div> </div>
<!-- TODO: Poprawić obslugę błedu wysyłania wiadomości by pojawiał sie toast i ulozyć css --> </div>
<div id="toast" class="f-toast"></div>
<div class="f-contact-map">
<MapGoogle
apiKey={apiKey}
lat={data.lat}
lon={data.lng}
zoom={16}
title={data.markerTitle}
description={data.markerAddress}
showMarker={true}
mode="contact"
mapStyleId={data.maps.mapId}
/>
</div>
<div id="toast" class="f-toast"></div>
</section> </section>
<!-- ReCaptcha --> <!-- ReCaptcha v3 -->
<script <script is:inline define:vars={{ siteKey: import.meta.env.PUBLIC_RECAPTCHA_SITE_KEY }}>
is:inline window.FUZ_RECAPTCHA_KEY = siteKey;
define:vars={{ siteKey: import.meta.env.PUBLIC_RECAPTCHA_SITE_KEY }}
>
window.FUZ_RECAPTCHA_KEY = siteKey;
const recaptchaScript = document.createElement("script"); const s = document.createElement("script");
recaptchaScript.src = s.src = "https://www.google.com/recaptcha/api.js?render=" + siteKey;
"https://www.google.com/recaptcha/api.js?render=" + siteKey; s.async = true;
document.head.appendChild(recaptchaScript); document.head.appendChild(s);
</script> </script>
<script <script
is:inline is:inline
define:vars={{ define:vars={{
successMsg: JSON.stringify(form.submit.successMessage), successMsg: form.successMessage,
errorMsg: JSON.stringify(form.submit.errorMessage), errorMsg: form.errorMessage
}} }}
> >
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
const form = document.getElementById("contactForm"); const form = document.getElementById("contactForm");
const toast = document.getElementById("toast"); const toast = document.getElementById("toast");
if (!form) return; if (!form) return;
form.addEventListener("submit", async (e) => { form.addEventListener("submit", async (e) => {
if (!form.reportValidity()) return; if (!form.reportValidity()) return;
e.preventDefault();
e.preventDefault(); const data = Object.fromEntries(new FormData(form).entries());
data.rodo = form.rodo.checked;
const formData = new FormData(form); const token = await grecaptcha.execute(window.FUZ_RECAPTCHA_KEY, { action: "submit" });
data.recaptcha = token;
const payload = Object.fromEntries(formData.entries()); const resp = await fetch("/api/contact", {
payload.rodo = formData.get("rodo") === "on"; method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data)
});
const token = await grecaptcha.execute(window.FUZ_RECAPTCHA_KEY, { const json = await resp.json();
action: "submit",
});
payload.recaptcha = token;
const resp = await fetch("/api/contact", { showToast(json.ok ? successMsg : errorMsg, json.ok ? "success" : "error");
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
const json = await resp.json(); if (json.ok) form.reset();
showToast(
json.ok ? JSON.parse(successMsg) : JSON.parse(errorMsg),
json.ok ? "success" : "error",
);
if (json.ok) form.reset();
});
function showToast(message, type = "success") {
toast.innerHTML = `
<div class="fuz-toast-msg ${type}">
${message}
</div>
`;
toast.classList.remove("visible");
void toast.offsetWidth;
toast.classList.add("visible");
setTimeout(() => {
toast.classList.remove("visible");
}, 3000);
}
}); });
function showToast(msg, type) {
toast.innerHTML = `<div class="f-toast-msg ${type}">${msg}</div>`;
toast.classList.remove("visible");
void toast.offsetWidth;
toast.classList.add("visible");
setTimeout(() => toast.classList.remove("visible"), 3000);
}
});
</script> </script>

View File

@@ -1,12 +0,0 @@
przelaczniki:
- id: "zasieg"
etykieta: "Rodzaj zasiegu"
domyslny: "none"
title: "Zmień rodzaj"
opcje:
- id: "swiatlowodowy"
nazwa: "Światłowodowy"
- id: "radiowy"
nazwa: "Radiowy"
- id: "none"
nazwa: "Ukryj zasięgi"

View File

@@ -1,5 +1,5 @@
site: site:
name: "FUZ Internet światłowodowy i radiowy w Wyszkowie" name: "FUZ Internet światłowodowy w Wyszkowie"
description: "Stabilny i szybki internet" description: "Stabilny i szybki internet"
url: "https://www.fuz.pl" url: "https://www.fuz.pl"
lang: "pl" lang: "pl"

View File

@@ -1,33 +0,0 @@
import { useState } from "preact/hooks";
import "../styles/offers/offers-switches.css";
export default function MapRangeSwitch() {
const [selected, setSelected] = useState("none");
const options = [
{ id: "swiatlowodowy", nazwa: "Światłowodowy" },
{ id: "radiowy", nazwa: "Radiowy" },
{ id: "none", nazwa: "Ukryj" }
];
const update = (id) => {
setSelected(id);
window?.handleMapSwitch?.(id);
};
return (
<div class="map-range-switch fuz-switches-wrapper">
<div class="fuz-switch-group flex sm:flex-row flex-col w-full">
{options.map((op) => (
<button
type="button"
class={`fuz-switch ${selected === op.id ? "active" : ""} w-full sm:w-auto`}
onClick={() => update(op.id)}
>
{op.nazwa}
</button>
))}
</div>
</div>
);
}

View File

@@ -22,9 +22,6 @@ export default function RangeForm() {
let timeoutCity = null; let timeoutCity = null;
let timeoutStreet = null; let timeoutStreet = null;
// =====================================================
// AUTOCOMPLETE MIASTO
// =====================================================
async function fetchCitySuggestions(q) { async function fetchCitySuggestions(q) {
const res = await fetch(`/api/cities-autocomplete?q=${encodeURIComponent(q)}`); const res = await fetch(`/api/cities-autocomplete?q=${encodeURIComponent(q)}`);
setCitySuggest(await res.json()); setCitySuggest(await res.json());
@@ -80,9 +77,6 @@ export default function RangeForm() {
cityListRef.current.children[highlightIndex]?.scrollIntoView({ block: "nearest" }); cityListRef.current.children[highlightIndex]?.scrollIntoView({ block: "nearest" });
}, [highlightIndex]); }, [highlightIndex]);
// =====================================================
// AUTO-MATCH MIASTO — NOWE!
// =====================================================
useEffect(() => { useEffect(() => {
if (!citySuggest.length) return; if (!citySuggest.length) return;
@@ -98,9 +92,6 @@ export default function RangeForm() {
} }
}, [city, citySuggest]); }, [city, citySuggest]);
// =====================================================
// DOSTĘPNOŚĆ ULIC
// =====================================================
async function updateStreetAvailability(currentCity) { async function updateStreetAvailability(currentCity) {
if (!currentCity) { if (!currentCity) {
setStreetDisabled(true); setStreetDisabled(true);
@@ -133,9 +124,6 @@ export default function RangeForm() {
updateStreetAvailability(city); updateStreetAvailability(city);
}, [city]); }, [city]);
// =====================================================
// AUTOCOMPLETE ULICA
// =====================================================
async function fetchStreetSuggestions(q, c) { async function fetchStreetSuggestions(q, c) {
const res = await fetch( const res = await fetch(
`/api/streets-autocomplete?city=${encodeURIComponent(c)}&q=${encodeURIComponent(q)}` `/api/streets-autocomplete?city=${encodeURIComponent(c)}&q=${encodeURIComponent(q)}`
@@ -194,9 +182,6 @@ export default function RangeForm() {
streetListRef.current.children[streetHighlightIndex]?.scrollIntoView({ block: "nearest" }); streetListRef.current.children[streetHighlightIndex]?.scrollIntoView({ block: "nearest" });
}, [streetHighlightIndex]); }, [streetHighlightIndex]);
// =====================================================
// AUTO-MATCH ULICA — NOWE!
// =====================================================
useEffect(() => { useEffect(() => {
if (!streetSuggest.length) return; if (!streetSuggest.length) return;
@@ -211,9 +196,6 @@ export default function RangeForm() {
} }
}, [street, streetSuggest]); }, [street, streetSuggest]);
// =====================================================
// SUBMIT
// =====================================================
async function onSubmit(e) { async function onSubmit(e) {
e.preventDefault(); e.preventDefault();
setError(""); setError("");
@@ -248,17 +230,13 @@ export default function RangeForm() {
setLoading(false); setLoading(false);
} }
// =====================================================
// RENDER
// =====================================================
return ( return (
<form class="flex flex-col gap-2" onSubmit={onSubmit} autocomplete="off"> <form class="flex flex-col gap-2" onSubmit={onSubmit} autocomplete="off">
{/* CITY */} {/* CITY */}
<div class="autocomplete-wrapper"> <div class="autocomplete-wrapper">
<input <input
class={`f-input ${citySuggest.length ? "autocomplete-open" : ""}`} class={`f-input ${citySuggest.length ? "autocomplete-open" : ""}`}
name="formCity"
placeholder="Wpisz miejscowość..." placeholder="Wpisz miejscowość..."
value={city} value={city}
onInput={onCityInput} onInput={onCityInput}
@@ -295,6 +273,7 @@ export default function RangeForm() {
? "W tej miejscowości nie występują" ? "W tej miejscowości nie występują"
: "Wpisz ulicę..." : "Wpisz ulicę..."
} }
name="formStreet"
value={street} value={street}
readOnly={streetDisabled} readOnly={streetDisabled}
onInput={streetDisabled ? undefined : onStreetInput} onInput={streetDisabled ? undefined : onStreetInput}
@@ -323,24 +302,23 @@ export default function RangeForm() {
{/* NUMBER */} {/* NUMBER */}
<input <input
class="f-input" class="f-input"
name="formNumber"
placeholder="np. 1A" placeholder="np. 1A"
value={number} value={number}
onInput={(e) => setNumber(e.target.value)} onInput={(e) => setNumber(e.target.value)}
required required
/> />
{/* ERROR */}
{error && ( {error && (
<p class="text-red-600 dark:text-red-400 text-sm">{error}</p> <p class="text-red-600text-lg">{error}</p>
)} )}
{/* BUTTON */}
<button <button
class="btn btn-outline" class="btn btn-outline"
disabled={loading} disabled={loading}
> >
{loading ? ( {loading ? (
<span class="w-5 h-5 border-2 border-[var(--fuz-accent)] border-t-transparent rounded-full animate-spin"></span> <span class="w-5 h-5 border-2 border-[var(--f-text)] border-t-transparent rounded-full animate-spin"></span>
) : ( ) : (
"Sprawdź dostępność →" "Sprawdź dostępność →"
)} )}

View File

@@ -8,14 +8,12 @@ export const POST: APIRoute = async ({ request }) => {
const transporter = nodemailer.createTransport({ const transporter = nodemailer.createTransport({
host: import.meta.env.SMTP_HOST, host: import.meta.env.SMTP_HOST,
port: Number(import.meta.env.SMTP_PORT), port: Number(import.meta.env.SMTP_PORT),
secure: true, // 465 = SSL secure: true,
auth: { auth: {
user: import.meta.env.SMTP_USER, user: import.meta.env.SMTP_USER,
pass: import.meta.env.SMTP_PASS, pass: import.meta.env.SMTP_PASS,
}, },
tls: { tls: { rejectUnauthorized: false }
rejectUnauthorized: false, // wymagane przez Webio
}
}); });
await transporter.sendMail({ await transporter.sendMail({
@@ -31,7 +29,7 @@ Temat: ${form.subject}
Wiadomość: Wiadomość:
${form.message} ${form.message}
`.trim() `.trim(),
}); });
return new Response(JSON.stringify({ ok: true }), { status: 200 }); return new Response(JSON.stringify({ ok: true }), { status: 200 });

View File

@@ -14,5 +14,5 @@ const hero = yaml.load(fs.readFileSync("./src/content/home/hero.yaml", "utf8"));
<DefaultLayout seo={seo}> <DefaultLayout seo={seo}>
<Hero {...hero} /> <Hero {...hero} />
<SectionRenderer src="./src/content/site/site.section.yaml" /> <SectionRenderer src="./src/content/site/site.section.yaml" />
<SectionContact /> <!-- <SectionContact /> -->
</DefaultLayout> </DefaultLayout>

View File

@@ -1,5 +1,6 @@
--- ---
import DefaultLayout from "../../layouts/DefaultLayout.astro"; import DefaultLayout from "../../layouts/DefaultLayout.astro";
import SectionContact from "../../components/sections/SectionContact.astro";
const seo = { const seo = {
title: "Kontakt FUZ", title: "Kontakt FUZ",
@@ -9,12 +10,5 @@ const seo = {
--- ---
<DefaultLayout seo={seo}> <DefaultLayout seo={seo}>
<section class="fuz-section"> <SectionContact />
<div class="fuz-container">
<h1 class="fuz-hero-title">Kontakt FUZ</h1>
<p class="mt-4 text-gray-600 dark:text-gray-300">
Ta podstrona jest na razie szkieletem. Możemy tu później wczytać treść z YAML.
</p>
</div>
</section>
</DefaultLayout> </DefaultLayout>

View File

@@ -1,9 +1,7 @@
--- ---
import DefaultLayout from "../../layouts/DefaultLayout.astro"; import DefaultLayout from "../../layouts/DefaultLayout.astro";
import MapGoogle from "../../components/maps/MapGoogle.astro"; import MapGoogle from "../../components/maps/MapGoogle.astro";
import MapRangeSwitch from "../../islands/MapRangeSwitch.jsx";
import RangeForm from "../../islands/RangeForm.jsx"; import RangeForm from "../../islands/RangeForm.jsx";
//import CitiesList from "../../components/maps/CitiesList.astro";
import "../../styles/map-google.css"; import "../../styles/map-google.css";
@@ -11,49 +9,40 @@ const apiKey = import.meta.env.PUBLIC_GOOGLE_MAPS_KEY;
const lat = 52.597388; const lat = 52.597388;
const lon = 21.456797; const lon = 21.456797;
const mapStyleId = "8e0a97af9476f2d3"; const mapStyleId = "8e0a97af9476f2d3";
// const res = await fetch(new URL("/api/all-cities", Astro.site));
// const cities = await res.json();
--- ---
<script> <script>
declare global { declare global {
interface Window { interface Window {
handleMapSwitch?: (mode: string) => void;
showAddressOnMap?: (result: any) => void; showAddressOnMap?: (result: any) => void;
fuzMaps?: any; fuzMaps?: any;
} }
} }
</script> </script>
<DefaultLayout title="FUZ Mapa zasięgu sieci"> <DefaultLayout title="FUZ Mapa zasięgu sieci światłowodowej">
<section class="flex flex-col md:flex-row h-full min-h-[80vh]"> <section class="flex flex-col md:flex-row h-full min-h-[80vh]">
<!-- PANEL --> <!-- PANEL LEWY -->
<aside <aside
class="w-full md:w-[340px] bg-[var(--f-background)] text-[var(--f-text)] class="w-full md:w-[340px] bg-[var(--f-background)] text-[var(--f-text)]
border-r border-gray-200 dark:border-slate-700 pt-6 px-6 pt-6 px-6 flex flex-col gap-6 overflow-y-auto z-40"
flex flex-col gap-6 overflow-y-auto z-40"
> >
<h3 class="text-3xl">Sprawdź dostępność usług</h3> <h3 class="text-3xl">Sprawdź dostępność usług</h3>
<p class="text-sm"> <p class="text-sm">
Wybierz swoją miejscowość i ulicę oraz numer budynku, aby sprawdzić dostępność naszych Wybierz swoją miejscowość i ulicę oraz numer budynku, aby sprawdzić
usług internetowych w Twojej okolicy. dostępność usług światłowodowych FUZ.
</p> </p>
<!-- 🔵 WYNIOSŁY FORMULARZ (ISLAND) -->
<RangeForm client:load /> <RangeForm client:load />
</aside> </aside>
<!-- MAPA --> <!-- MAPA -->
<div class="flex-1 relative min-h-[50vh] md:min-h-0"> <div class="flex-1 relative min-h-[50vh] md:min-h-0">
<div class="map-range-container">
<MapRangeSwitch client:load />
</div>
<MapGoogle <MapGoogle
apiKey={apiKey} apiKey={apiKey}
lat={lat} lat={lat}
lon={lon} lon={lon}
zoom={12} zoom={17}
showMarker={true} showMarker={true}
mode="full" mode="full"
mapStyleId={mapStyleId} mapStyleId={mapStyleId}
@@ -61,82 +50,45 @@ const mapStyleId = "8e0a97af9476f2d3";
</div> </div>
</section> </section>
<!-- <CitiesList cities={cities} /> -->
<!-- ===================================================== -->
<!-- WARSTWY KML -->
<!-- ===================================================== -->
<script is:inline> <script is:inline>
let fiberLayer = null; let fiberLayer = null;
let radioLayer = null;
window.getActiveMap = function () { window.getActiveMap = function () {
if (!window.fuzMaps) return null; if (!window.fuzMaps) return null;
return Object.values(window.fuzMaps)[0] || null; return Object.values(window.fuzMaps)[0] || null;
}; };
window.fiberRangeShow = function (show) { function enableFiberLayer() {
const map = window.getActiveMap(); const map = window.getActiveMap();
if (!map) return; if (!map) return;
if (!show && fiberLayer) { if (fiberLayer) {
fiberLayer.setMap(null); fiberLayer.setMap(null);
fiberLayer = null;
return;
} }
if (show && !fiberLayer) { fiberLayer = new google.maps.KmlLayer(
fiberLayer = new google.maps.KmlLayer( "https://www.google.com/maps/d/kml?mid=1Or8SF_9qx6QMdidS-99V_jqQuhF9de0&forcekml=1",
"https://www.google.com/maps/d/kml?mid=1Or8SF_9qx6QMdidS-99V_jqQuhF9de0&forcekml=1", { suppressInfoWindows: true, preserveViewport: false },
{ suppressInfoWindows: true, preserveViewport: false }, );
); fiberLayer.setMap(map);
fiberLayer.setMap(map); }
}
};
window.radioRangeShow = function (show) { // Czekamy aż mapa się załaduje
const int = setInterval(() => {
const map = window.getActiveMap(); const map = window.getActiveMap();
if (!map) return; if (map && window.google?.maps) {
clearInterval(int);
if (!show && radioLayer) { enableFiberLayer();
radioLayer.setMap(null);
radioLayer = null;
return;
} }
}, 100);
if (show && !radioLayer) {
radioLayer = new google.maps.KmlLayer(
"https://www.google.com/maps/d/kml?mid=1c08LxJ9uCbWWfCCyopJmAMLQI1rmTkA&forcekml=1",
{ suppressInfoWindows: true, preserveViewport: false },
);
radioLayer.setMap(map);
}
};
window.handleMapSwitch = function (mode) {
if (mode === "swiatlowodowy") {
window.fiberRangeShow(true);
window.radioRangeShow(false);
} else if (mode === "radiowy") {
window.fiberRangeShow(false);
window.radioRangeShow(true);
} else {
window.fiberRangeShow(false);
window.radioRangeShow(false);
}
};
</script> </script>
<!-- ===================================================== -->
<!-- FUNKCJA: POKAZYWANIE MARKERA NA MAPIE -->
<!-- ===================================================== -->
<script is:inline> <script is:inline>
window.showAddressOnMap = async function (result) { window.showAddressOnMap = async function (result) {
const map = window.getActiveMap(); const map = window.getActiveMap();
if (!map) return; if (!map) return;
// Jeśli API jeszcze się nie załadowało czekamy na Promise // Czekamy aż API będzie gotowe
if (!window.google?.maps?.importLibrary) { if (!window.google?.maps?.importLibrary) {
await new Promise((resolve) => { await new Promise((resolve) => {
const int = setInterval(() => { const int = setInterval(() => {
@@ -148,84 +100,71 @@ const mapStyleId = "8e0a97af9476f2d3";
}); });
} }
// NOWE LIBRARIES
const { AdvancedMarkerElement } = const { AdvancedMarkerElement } =
await google.maps.importLibrary("marker"); await google.maps.importLibrary("marker");
const { InfoWindow } = await google.maps.importLibrary("maps"); const { InfoWindow } = await google.maps.importLibrary("maps");
// Kasujemy stare
if (window._activeMarker) window._activeMarker.map = null; if (window._activeMarker) window._activeMarker.map = null;
if (window._activeInfo) window._activeInfo.close(); if (window._activeInfo) window._activeInfo.close();
const pos = { lat: result.lat, lng: result.lon }; const pos = { lat: result.lat, lng: result.lon };
// ★ Nowy marker const overlay = document.createElement("div");
overlay.className = "pulse-marker";
const projection = map.getProjection();
if (projection) {
const point = projection.fromLatLngToPoint(new google.maps.LatLng(pos));
overlay.style.left = point.x + "px";
overlay.style.top = point.y + "px";
}
setTimeout(() => {
overlay.remove();
}, 1500);
map.getDiv().appendChild(overlay);
map.panTo(pos);
let targetZoom = 16;
setTimeout(() => {
map.setZoom(targetZoom);
}, 250);
const marker = new AdvancedMarkerElement({ const marker = new AdvancedMarkerElement({
map, map,
position: pos, position: pos,
title: `${result.city} ${result.street ?? ""} ${result.number}`, title: `${result.city} ${result.street ?? ""} ${result.number}`,
className: "marker-bounce",
}); });
window._activeMarker = marker; window._activeMarker = marker;
// ★ Nowy infoWindow — działa tak samo, ale z importLibrary // InfoWindow
const html = ` const html = `
<div style="font-size:14px; line-height:1.5; padding:2px; color:#000;"> <div class="f-info-window">
<div style="margin-bottom:6px;"> <div class="f-info-header">
<strong>${result.city}</strong><br/> <div class="f-info-heading">
<strong>${result.street ?? ""} ${result.number}</strong> ${
</div> result.availableFiber
? `<span class="ok">✔</span> Internet światłowodowy dostępny`
<div> : `<span class="no">✖</span> Światłowód niedostępny`
${ }
result.availableFiber
? '✔ <span style="color:green;">Internet światłowodowy dostępny</span>'
: '✖ <span style="color:red;">Internet światłowodowy niedostępny</span>'
}<br/>
${
result.availableRadio
? '✔ <span style="color:green;">Internet radiowy dostępny</span>'
: '✖ <span style="color:red;">Internet radiowy niedostępny</span>'
}
</div>
<a href="/#kontakt"
style="display:block; margin-top:8px;
background:#00aaff; color:white;
padding:6px 8px; text-align:center;
text-decoration:none; border-radius:6px;"
title="Przejdź do formularza kontaktowego">
Przejdź do kontaktu →
</a>
</div> </div>
`; <div class="f-info-city">${result.city}</div>
<div class="f-info-street">${result.street ?? ""} ${result.number}</div>
</div>
</div>
<div class="w-full flex justify-center mb-4">
<a href="/kontakt" class="btn btn-outline">Przejdź do kontaktu →</a>
</div>
</div>
`;
const info = new InfoWindow({ content: html }); const info = new InfoWindow({ content: html });
window._activeInfo = info; window._activeInfo = info;
info.open({ info.open({ map, anchor: marker });
map,
anchor: marker,
});
map.setCenter(pos);
map.setZoom(16);
}; };
</script> </script>
</DefaultLayout> </DefaultLayout>
<style is:global>
.fade-in {
animation: fuzFadeIn 0.25s ease-out forwards;
}
@keyframes fuzFadeIn {
from {
opacity: 0;
transform: translateY(-6px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>

View File

@@ -15,7 +15,6 @@
@import "./offers/offers-main.css"; @import "./offers/offers-main.css";
@import "./offers/offers-switches.css"; @import "./offers/offers-switches.css";
html { html {
font-family: 'Nunito', sans-serif; font-family: 'Nunito', sans-serif;
/* font-family: "Lora", sans-serif; */ /* font-family: "Lora", sans-serif; */
@@ -24,10 +23,6 @@ html {
scroll-behavior: smooth; scroll-behavior: smooth;
} }
body {
/* @apply bg-white text-gray-900 dark:bg-slate-900 dark:text-gray-100 antialiased; */
}
.grecaptcha-badge { .grecaptcha-badge {
display: none !important; display: none !important;
} }

View File

@@ -3,46 +3,39 @@
} }
.btn-primary { .btn-primary {
@apply border-none; @apply border-none bg-[--btn-background] text-[--btn-text];
background: var(--btn-background);
color: var(--btn-text);
} }
.btn-primary:hover { .btn-primary:hover {
filter: brightness(0.95); @apply brightness-[0.95];
} }
.btn-outline { .btn-outline {
@apply border border-solid; @apply border border-solid border-[--btn-outline-border] text-[--btn-outline-text] bg-[--btn-outline-background];
border-color: var(--btn-outline-border);
color: var(--btn-outline-text);
background: var(--btn-outline-background);
} }
.btn-outline:hover { .btn-outline:hover {
background-color: var(--btn-outline-background-hover); @apply bg-[--btn-outline-background-hover] text-[--btn-outline-text-hover];
color: var(--btn-outline-text-hover);
} }
.btn-ghost { .btn-ghost {
background-color: transparent; @apply bg-transparent text-[--btn-ghost-text];
color: var(--btn-ghost-text);
} }
.btn-ghost:hover { .btn-ghost:hover {
background-color: var(--btn-ghost-hover-bg); @apply bg-[--btn-ghost-hover-bg];
} }
.f-input { .f-input {
@apply w-full py-3 px-4 rounded-xl border border-[var(--f-input-border)] bg-[var(--f-background)] text-[var(--f-text)] transition-all duration-200; @apply w-full py-3 px-4 rounded-xl border border-[--f-input-border] bg-[--f-background] text-[--f-text] transition-all duration-200;
} }
.f-input:hover { .f-input:hover {
@apply border-[var(--f-text)] opacity-[0.9]; @apply border-[--f-text] opacity-[0.9];
} }
.f-input:focus { .f-input:focus {
@apply outline-none border-[var(--f-header)]; @apply outline-none border-[--f-header];
box-shadow: 0 0 0 3px color-mix(in srgb, var(--f-header) 40%, transparent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--f-header) 40%, transparent);
} }
@@ -50,48 +43,31 @@
color: color-mix(in srgb, var(--f-text) 40%, transparent); color: color-mix(in srgb, var(--f-text) 40%, transparent);
} }
/* Error */
.fuz-input-error { .fuz-input-error {
border-color: #ff4d4f !important; border-color: #ff4d4f !important;
box-shadow: 0 0 0 3px rgba(255, 77, 79, 0.3) !important; box-shadow: 0 0 0 3px rgba(255, 77, 79, 0.3) !important;
} }
/* Disabled */
.fuz-input:disabled { .fuz-input:disabled {
opacity: 0.6; opacity: 0.6;
cursor: not-allowed; cursor: not-allowed;
background-color: color-mix(in srgb, var(--f-background) 80%, #888); background-color: color-mix(in srgb, var(--f-background) 80%, #888);
} }
/* Textarea */
/* textarea.fuz-input {
resize: none;
} */
/* .fuz-link {
color: var(--fuz-accent);
transition: color 0.2s ease;
} */
/* Kapsuła — input + dropdown jako jedna całość */
.autocomplete-wrapper { .autocomplete-wrapper {
position: relative; position: relative;
} }
/* Input (gdy dropdown otwarty) */
.autocomplete-open { .autocomplete-open {
border-bottom-left-radius: 0 !important; border-bottom-left-radius: 0 !important;
border-bottom-right-radius: 0 !important; border-bottom-right-radius: 0 !important;
border-bottom-width: 0 !important; border-bottom-width: 0 !important;
} }
/* Dropdown */
.autocomplete-list { .autocomplete-list {
@apply absolute left-0 right-0 z-50 bg-[var(--f-background)] text-[var(--f-text)] border border-gray-300 dark:border-slate-700 rounded-b-xl shadow-xl max-h-56 overflow-auto; @apply absolute left-0 right-0 z-50 bg-[--f-background] text-[--f-text] border border-gray-300 dark:border-slate-700 rounded-b-xl shadow-xl max-h-56 overflow-auto;
border-top: none; border-top: none;
/* ważne */
animation: fadeIn 0.12s ease-out; animation: fadeIn 0.12s ease-out;
} }
@@ -101,7 +77,7 @@
.autocomplete-list li:hover, .autocomplete-list li:hover,
.autocomplete-list li.active { .autocomplete-list li.active {
@apply bg-gray-100 dark:bg-slate-800; @apply bg-[--f-autocomplete-hover-bg] text-[--f-autocomplete-hover-text];
} }
@keyframes fadeIn { @keyframes fadeIn {

View File

@@ -15,7 +15,7 @@
} }
.f-contact-col-2 { .f-contact-col-2 {
@apply bg-[var(--f-background)] text-[var(--f-text)]; @apply bg-[--f-background] text-[--f-text];
h1, h1,
h2, h2,
@@ -32,11 +32,11 @@
h2, h2,
h3, h3,
h4 { h4 {
@apply text-2xl font-semibold text-[var(--f-text)] m-0; @apply text-2xl font-semibold text-[--f-text] m-0;
} }
p { p {
@apply text-xl mt-4 leading-relaxed text-[var(--f-text)]; @apply text-xl mt-4 leading-relaxed text-[--f-text];
} }
} }
@@ -49,14 +49,14 @@
} }
.f-rodo { .f-rodo {
@apply flex items-start gap-3 text-lg text-[var(--f-text)]; @apply flex items-start gap-3 text-lg text-[--f-text];
a { a {
@apply text-[var(--f-link-text)]; @apply text-[--f-link-text];
} }
a:hover { a:hover {
@apply text-[var(--fuz-link-hover)]; @apply text-[--fuz-link-hover];
} }
input { input {
@@ -73,8 +73,10 @@
@apply w-full max-w-7xl mx-auto mt-6; @apply w-full max-w-7xl mx-auto mt-6;
} }
.s-toast { .f-toast {
@apply fixed top-5 left-1/2 z-[9999] pointer-events-none; @apply fixed left-1/2 z-[999999] pointer-events-none;
top: calc(var(--nav-height, 80px) + 20px);
@apply opacity-0 -translate-y-3 -translate-x-1/2 transition-all duration-300 ease-out; @apply opacity-0 -translate-y-3 -translate-x-1/2 transition-all duration-300 ease-out;
} }
@@ -83,15 +85,13 @@
} }
.f-toast-msg { .f-toast-msg {
@apply px-5 py-3 rounded-xl shadow-lg text-sm; @apply px-5 py-3 rounded-xl shadow-lg text-lg bg-[--f-background-o] text-[--f-text];
background: var(--fuz-accent);
color: var(--fuz-accent-text);
} }
.f-toast-msg.success { .f-toast-msg.success {
background: var(--fuz-accent); @apply bg-green-900 text-white;
} }
.f-toast-msg.error { .f-toast-msg.error {
@apply bg-red-500 text-white; @apply bg-red-500 text-white;
} }

View File

@@ -1,9 +1,6 @@
@layer components { @layer components {
#cookie-banner { #cookie-banner {
@apply fixed bottom-0 left-0 w-full translate-y-full transition-transform duration-500 ease-in-out; @apply fixed bottom-0 left-0 w-full translate-y-full transition-transform duration-500 ease-in-out bg-[--f-cookie-background] text-[--f-cookie-text];
background: var(--f-cookie-background);
color: var(--f-cookie-text);
/* border-top: 1px solid rgba(0, 0, 0, 0.1); */
} }
.f-cookie-panel-inner { .f-cookie-panel-inner {
@@ -15,8 +12,7 @@
} }
.f-cookie-privacy-link { .f-cookie-privacy-link {
@apply ml-3; @apply ml-3 text-[--f-link-text];
color: var(--f-link-text);
} }
.f-cookie-accept, .f-cookie-accept,
@@ -25,12 +21,10 @@
} }
.f-cookie-accept { .f-cookie-accept {
background: var(--f-cookie-accept-background); @apply bg-[--f-cookie-accept-background] text-[--f-cookie-accept-text]
color: var(--f-cookie-accept-text);
} }
.f-cookie-reject { .f-cookie-reject {
background: var(--f-cookie-reject-background); @apply bg-[--f-cookie-reject-background] text-[--f-cookie-reject-text]
color: var(--f-cookie-reject-text);
} }
} }

View File

@@ -1,6 +1,6 @@
@layer components { @layer components {
.f-footer { .f-footer {
@apply mt-2 border-t border-[var(--f-input-border)] bg-[var(--f-background-o)] text-[var(--f-text)] pt-2; @apply mt-2 border-t border-[--f-input-border] bg-[--f-background-o] text-[--f-text] pt-2;
} }
.f-footer-inner { .f-footer-inner {
@@ -16,15 +16,15 @@
h4, h4,
h5, h5,
h6 { h6 {
@apply text-xl font-semibold text-[var(--f-header)]; @apply text-xl font-semibold text-[--f-header];
} }
a { a {
@apply text-[var(--f-link-text)]; @apply text-[--f-link-text];
} }
a:hover { a:hover {
@apply text-[var(--fuz-link-hover)]; @apply text-[--fuz-link-hover];
} }
p { p {
@@ -33,14 +33,14 @@
} }
.f-footer-copyright { .f-footer-copyright {
@apply text-center py-4 text-base text-[var(--f-text)]; @apply text-center py-4 text-base text-[--f-text];
} }
.f-footer-recaptcha { .f-footer-recaptcha {
@apply text-base; @apply text-base;
a { a {
@apply text-[var(--f-link-text)]; @apply text-[--f-link-text];
} }
} }
} }

View File

@@ -1,25 +1,20 @@
.f-hero { .f-hero {
@apply relative overflow-hidden text-center py-32 px-6; @apply relative overflow-hidden text-center py-28 px-6;
background: linear-gradient(to right,
var(--fuz-hero-from),
var(--fuz-hero-to));
color: var(--f-text);
} }
.f-hero-bg { .f-hero-bg {
@apply absolute top-0 left-0 w-full h-full object-cover opacity-[0.4]; @apply absolute top-0 left-0 w-full h-full object-cover opacity-[0.6];
} }
.f-hero-inner { .f-hero-inner {
@apply relative max-w-7xl mx-auto text-[var(--f-text)]; @apply relative max-w-7xl mx-auto text-[f-text];
h1 { h1 {
@apply text-5xl md:text-6xl font-extrabold leading-tight mb-6 text-[var(--f-header)]; @apply text-5xl md:text-6xl font-extrabold leading-tight mb-6 text-[--f-header];
} }
h2 { h2 {
@apply text-xl md:text-4xl font-semibold mb-2 opacity-0 text-[var(--f-header-2)]; @apply text-xl md:text-4xl font-semibold mb-2 opacity-0 text-[--f-header-2];
animation-name: fade-in; animation-name: fade-in;
animation-duration: 0.8s; animation-duration: 0.8s;
animation-timing-function: ease-out; animation-timing-function: ease-out;
@@ -27,13 +22,13 @@
} }
p { p {
@apply text-xl md:text-4xl font-semibold mb-2 opacity-0 text-[var(--f-header-items)]; @apply text-xl md:text-4xl font-semibold mb-2 opacity-0 text-[--f-header-items];
animation: fade-in 0.3s ease-out forwards; animation: fade-in 0.3s ease-out forwards;
animation-delay: calc(var(--delay) * 0.4s); animation-delay: calc(var(--delay) * 0.4s);
} }
p.description { p.description {
@apply max-w-6xl mx-auto text-lg md:text-xl my-6 leading-snug text-[var(--f-text)]; @apply max-w-6xl mx-auto text-lg md:text-xl my-6 leading-snug text-[--f-text];
} }
} }

View File

@@ -31,24 +31,92 @@
} }
.map-range-switch { /* Pulsująca obwódka budynku */
background: var(--f-background); .pulse-marker {
width: 22px;
height: 22px;
border-radius: 50%;
background: rgba(0, 170, 255, 0.55);
position: absolute;
transform: translate(-50%, -50%);
animation: pulseAnim 1.3s ease-out forwards;
} }
.map-range-switch .fuz-switch-group { @keyframes pulseAnim {
display: flex; 0% {
gap: 8px; transform: translate(-50%, -50%) scale(0.2);
opacity: 1;
}
80% {
transform: translate(-50%, -50%) scale(1.6);
opacity: 0.3;
}
100% {
opacity: 0;
}
} }
/* Mobile: pionowo */ /* Animacja markera */
@media (max-width: 640px) { .marker-bounce {
.map-range-switch .fuz-switch-group { animation: markerBounce 0.35s ease-out forwards;
flex-direction: column; }
width: 100%;
@keyframes markerBounce {
0% {
transform: translateY(-18px);
opacity: 0;
} }
.map-range-switch .fuz-switch { 100% {
width: 100%; transform: translateY(0);
text-align: center; opacity: 1;
} }
}
/* Info window */
.f-info-window {
@apply p-3;
}
/* HEADER */
.f-info-header {
margin-bottom: 10px;
}
.f-info-heading {
@apply text-lg uppercase;
.ok {
color: green;
}
.no {
color: #d00;
}
}
.f-info-city,
.f-info-street {
@apply text-xl ml-3;
}
.gm-style {
background: var(--f--background) !important;
}
.gm-style-iw-c {
background: var(--f-background) !important;
border-radius: 14px !important;
box-shadow: 0 4px 18px rgba(0,0,0,0.12) !important;
padding: 0 !important;
}
.gm-style-iw-d {
overflow: visible !important;
padding: 0 !important;
background: transparent !important;
} }

View File

@@ -33,21 +33,16 @@
} }
.fuz-markdown ul li::marker { .fuz-markdown ul li::marker {
color: var(--fuz-accent); @apply text-[--f-text];
} }
.dark .fuz-markdown ul li::marker {
color: var(--fuz-accent);
}
.fuz-markdown a { .fuz-markdown a {
@apply no-underline hover:no-underline text-[var(--f-link-text)]; @apply no-underline hover:no-underline text-[var(--f-link-text)];
} }
.fuz-markdown button.modal-link { .fuz-markdown button.modal-link {
@apply no-underline hover:no-underline mt-2; @apply no-underline hover:no-underline mt-2 bg-[--f-background] text-[--f-link-text];
background: var(--f-background);
color: var(--fuz-accent);
} }
.fuz-markdown blockquote { .fuz-markdown blockquote {
@apply border-l-4 border-gray-300 dark:border-gray-700 pl-4 italic mb-4; @apply border-l-4 border-gray-300 dark:border-gray-700 pl-4 italic mb-4;

View File

@@ -9,34 +9,25 @@
/* CLOSE BUTTON */ /* CLOSE BUTTON */
.fuz-modal-close { .fuz-modal-close {
@apply absolute top-4 right-6 text-3xl font-bold cursor-pointer transition-opacity; @apply absolute top-4 right-6 text-3xl font-bold cursor-pointer transition-opacity text-[--f-text] opacity-[0.7];
color: var(--f-text);
opacity: 0.7;
} }
.fuz-modal-close:hover { .fuz-modal-close:hover {
@apply opacity-100; @apply opacity-100;
} }
/* PANEL — FULLSCREEN PANEL */
.fuz-modal-panel { .fuz-modal-panel {
@apply w-full h-full overflow-y-auto; @apply w-full h-full overflow-y-auto px-6 py-8 md:px-12 md:py-12 bg-[--f-background] text-[--f-text];
@apply px-6 py-8 md:px-12 md:py-12;
background: var(--f-background);
color: var(--f-text);
} }
/* INNER LAYOUT */
.fuz-modal-inner { .fuz-modal-inner {
@apply max-w-4xl mx-auto; @apply max-w-4xl mx-auto;
} }
.fuz-modal-title { .fuz-modal-title {
@apply text-4xl font-bold mb-8 text-center; @apply text-4xl font-bold mb-8 text-center text-[--f-text];
color: var(--f-text);
} }
/* CONTENT STYLE */
.fuz-modal-content p { .fuz-modal-content p {
@apply leading-relaxed text-2xl text-center; @apply leading-relaxed text-2xl text-center;
} }
@@ -44,7 +35,6 @@
.fuz-modal-content p img { .fuz-modal-content p img {
@apply mt-2 leading-relaxed; @apply mt-2 leading-relaxed;
} }
/* ANIMATIONS */
@keyframes fadeIn { @keyframes fadeIn {
from { from {
@@ -52,6 +42,6 @@
} }
to { to {
opacity: 1; opacity: 2;
} }
} }

View File

@@ -1,5 +1,5 @@
.f-navbar { .f-navbar {
@apply w-full shadow-sm sticky top-0 z-50 bg-[var(--f-background)] text-[var(--f-text)]; @apply w-full shadow-sm sticky top-0 z-50 bg-[--f-background] text-[--f-text];
} }
.f-navbar-inner { .f-navbar-inner {
@@ -11,16 +11,16 @@
} }
.f-navbar-link{ .f-navbar-link{
@apply text-base hover:text-[var(--fuz-accent)] transition-colors; @apply text-base hover:text-[--fuz-accent] transition-colors;
} }
.f-mobile-toggle { .f-mobile-toggle {
@apply text-3xl p-2 text-[var(--f-text)]; @apply text-3xl p-2 text-[--f-text];
} }
.f-mobile-menu { .f-mobile-menu {
@apply fixed top-0 right-0 h-full w-64 bg-[var(--f-background)] shadow-lg transform translate-x-full transition-transform duration-300 flex flex-col gap-4 p-6; @apply fixed top-0 right-0 h-full w-64 bg-[--f-background] shadow-lg transform translate-x-full transition-transform duration-300 flex flex-col gap-4 p-6;
} }
.f-mobile-menu.open { .f-mobile-menu.open {
@@ -28,8 +28,7 @@
} }
.f-mobile-link { .f-mobile-link {
@apply text-lg py-2 border-b text-[var(--f-text)] hover:text-[var(--fuz-accent)]; @apply text-lg py-2 border-b text-[--f-text] hover:text-[--fuz-accent] border-[--f-border-color];
border-color: var(--f-border-color);
} }
.f-navbar-logo{ .f-navbar-logo{

View File

@@ -14,9 +14,9 @@
} }
.f-feature-link { .f-feature-link {
@apply underline cursor-pointer w-full h-full text-[var(--f-link-text)]; @apply cursor-pointer w-full h-full text-[--f-link-text] text-lg;
} }
.f-feature-link:hover { .f-feature-link:hover {
@apply text-[var(--f-link-text-hover)]; @apply text-[--f-link-text-hover];
} }

View File

@@ -3,7 +3,7 @@
} }
.f-switch-group { .f-switch-group {
@apply inline-flex overflow-hidden relative bg-[var(--f-background-switch)] mt-8; @apply inline-flex overflow-hidden relative bg-[--f-background-switch] mt-8;
} }
.f-switch { .f-switch {
@@ -11,7 +11,7 @@
} }
.f-switch.active { .f-switch.active {
@apply text-[var(--f-text-switcher)] bg-[var(--f-background-switcher)] ; @apply text-[--f-text-switcher] bg-[--f-background-switcher] ;
} }
.f-switch:hover { .f-switch:hover {

View File

@@ -1,5 +1,5 @@
.f-table-wrapper { .f-table-wrapper {
@apply overflow-x-auto rounded-3xl shadow-lg mb-0 border border-[var(--f-offers-border)]; @apply overflow-x-auto rounded-3xl shadow-lg mb-0 border border-[--f-offers-border];
} }
.f-table { .f-table {
@@ -23,7 +23,7 @@
} }
.f-plan-price { .f-plan-price {
@apply text-2xl font-extrabold mb-1 text-[var(--f-offers-price)]; @apply text-2xl font-extrabold mb-1 text-[--f-offers-price];
} }
/* Na ten moment ukryte */ /* Na ten moment ukryte */
@@ -74,13 +74,6 @@
border-bottom: 2px solid var(--f-offers-popular); border-bottom: 2px solid var(--f-offers-popular);
} }
/* .f-popular-col.f-feature-cell,
.f-popular-col.f-feature-yes,
.f-popular-col.f-feature-no {
border-top: none !important;
} */
.f-popular-badge { .f-popular-badge {
@apply bg-blue-500 text-white text-xs font-semibold px-3 py-1 rounded-full inline-block mb-2 uppercase tracking-wide; @apply bg-blue-500 text-white text-xs font-semibold px-3 py-1 rounded-full inline-block mb-2 uppercase tracking-wide;
/* background: #3b82f6; /* background: #3b82f6;

View File

@@ -1,7 +1,7 @@
@layer components { @layer components {
.f-section-header { .f-section-header {
@apply text-3xl md:text-4xl font-bold mb-6 text-[var(--f-header)]; @apply text-3xl md:text-4xl font-bold mb-6 text-[--f-header];
} }
.f-section { .f-section {
@@ -33,7 +33,7 @@
} }
.f-section-title { .f-section-title {
@apply text-4xl md:text-5xl font-bold mb-2 text-[var(--f-header)]; @apply text-4xl md:text-5xl font-bold mb-2 text-[--f-header];
} }
.f-section-nav { .f-section-nav {
@@ -42,34 +42,10 @@
} }
.f-section-channel { .f-section-channel {
@apply grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-8 gap-2; @apply grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-8 gap-2;
} }
.f-channel-box { .f-channel-box {
@apply flex flex-col items-center p-4 rounded-xl bg-[var(--f-background)] border border-[var(--f-offers-border)] shadow-sm hover:shadow-md transition @apply flex flex-col items-center p-4 rounded-xl bg-[--f-background] border border-[--f-offers-border] shadow-sm hover:shadow-md transition
} }
/* .fuz-iframe-box {
@apply bg-white dark:bg-slate-800 p-4 rounded-xl border border-gray-200 dark:border-slate-700 shadow;
}
.fuz-iframe-wrapper {
@apply w-full overflow-hidden border-0 shadow-none;
background: transparent !important;
aspect-ratio: 16/9;
}
.fuz-iframe {
@apply w-full h-full border-0 shadow-none;
background: transparent !important;
}
.dark .fuz-iframe-wrapper {
background: transparent !important;
}
.dark .fuz-iframe {
background: transparent !important;
} */

View File

@@ -33,6 +33,8 @@
:root { :root {
--f-background: var(--surface2-light); --f-background: var(--surface2-light);
--f-text: var(--text2-light);
--f-text-1: var(--text1-light);
--f-background-switch: var(--surface3-light); --f-background-switch: var(--surface3-light);
--f-text-switcher: var(--brand-dark); --f-text-switcher: var(--brand-dark);
@@ -42,8 +44,7 @@
--f-header-2: var(--text1-light); --f-header-2: var(--text1-light);
--f-header-items: (var(--text2-light)); --f-header-items: (var(--text2-light));
--f-text: var(--text2-light);
--f-text-1: var(--text1-light);
--f-link-text: var(--brand-dim); --f-link-text: var(--brand-dim);
@@ -75,10 +76,21 @@
--f-cookie-accept-background: green; --f-cookie-accept-background: green;
/* --f-cookie-accept-text: */ /* --f-cookie-accept-text: */
--f-cookie-reject-background: var(--text2-light); --f-cookie-reject-background: var(--text2-light);
--f-autocomplete-hover-bg: var(--surface4-light);
--f-autocomplete-hover-text: var(--surface2-light);
-fuz-hero-from: #3b82f6;
/* niebieski - kolor początkowy */
--fuz-hero-to: #8b5cf6;
/* fioletowy - kolor końcowy */
} }
:root.dark { :root.dark {
--f-background: var(--surface1-dark); --f-background: var(--surface1-dark);
--f-text: var(--text1-dark);
--f-text-1: var(--text1-dark);
--f-background-switch: var(--surface2-dark); --f-background-switch: var(--surface2-dark);
--f-background-switch: var(--surface3-dark); --f-background-switch: var(--surface3-dark);
@@ -89,8 +101,7 @@
--f-header-2: var(--text1-dark); --f-header-2: var(--text1-dark);
--f-header-items: (var(--text2-dark)); --f-header-items: (var(--text2-dark));
--f-text: var(--text1-dark);
--f-text-1: var(--text1-dark);
--f-link-text: var(--brand-dark); --f-link-text: var(--brand-dark);
--f-link-text-hover: var(--f-text2-dark); --f-link-text-hover: var(--f-text2-dark);
@@ -119,6 +130,9 @@
--f-cookie-accept-background: green; --f-cookie-accept-background: green;
/* --f-cookie-accept-text: */ /* --f-cookie-accept-text: */
--f-cookie-reject-background: var(--text2-light); --f-cookie-reject-background: var(--text2-light);
--f-autocomplete-hover-bg: var(--surface3-dark);
--f-autocomplete-hover-text: var(--text1-dark);
} }
/* Body */ /* Body */