Offers, tabelka z uslugami
This commit is contained in:
124
src/content/internet-swiatlowodowy/offers.yaml
Normal file
124
src/content/internet-swiatlowodowy/offers.yaml
Normal file
@@ -0,0 +1,124 @@
|
||||
przelaczniki:
|
||||
- id: "budynek"
|
||||
etykieta: "Rodzaj budynku"
|
||||
domyslny: "jednorodzinny"
|
||||
opcje:
|
||||
- id: "jednorodzinny"
|
||||
nazwa: "Jednorodzinny"
|
||||
- id: "wielorodzinny"
|
||||
nazwa: "Wielorodzinny"
|
||||
|
||||
- id: "umowa"
|
||||
etykieta: "Okres umowy"
|
||||
domyslny: "24m"
|
||||
opcje:
|
||||
- id: "24m"
|
||||
nazwa: "24 miesiące"
|
||||
- id: "bezterminowa"
|
||||
nazwa: "Bezterminowa"
|
||||
|
||||
# WIERSZE TABELI
|
||||
funkcje:
|
||||
- id: "pobieranie"
|
||||
etykieta: "Prędkość pobierania"
|
||||
- id: "wysylanie"
|
||||
etykieta: "Prędkość wysyłania"
|
||||
- id: "router"
|
||||
etykieta: "Router Wi-Fi"
|
||||
# - id: "tv"
|
||||
# etykieta: "Pakiet TV"
|
||||
- id: "umowa_info"
|
||||
etykieta: "Umowa"
|
||||
- id: "instalacja"
|
||||
etykieta: "Aktywacja"
|
||||
- id: "adres_ip"
|
||||
etykieta: "Adres IP"
|
||||
|
||||
# PLANY – jedna lista, ceny zależą od kombinacji przełączników
|
||||
plany:
|
||||
- id: "fiber100"
|
||||
nazwa: "FIBER 100"
|
||||
predkosc: "100 Mb/s"
|
||||
popularny: false
|
||||
ceny:
|
||||
jednorodzinny:
|
||||
# 12m: "59 zł/mies."
|
||||
24m: "64 zł/mies."
|
||||
bezterminowa: "84 zł/mies."
|
||||
wielorodzinny:
|
||||
# 12m: "55 zł/mies."
|
||||
24m: "54 zł/mies."
|
||||
bezterminowa: "74 zł/mies."
|
||||
funkcje:
|
||||
pobieranie: "do 100 Mb/s"
|
||||
wysylanie: "do 50 Mb/s"
|
||||
router: true
|
||||
adres_ip: "Dynamiczny"
|
||||
tv: false
|
||||
umowa_info: "12 / 24 / bez umowy"
|
||||
instalacja: "149 zł"
|
||||
|
||||
- id: "fiber300"
|
||||
nazwa: "FIBER 300"
|
||||
predkosc: "300 Mb/s"
|
||||
popularny: true
|
||||
ceny:
|
||||
jednorodzinny:
|
||||
# 12m: "79 zł/mies."
|
||||
24m: "75 zł/mies."
|
||||
bezterminowa: "95 zł/mies."
|
||||
wielorodzinny:
|
||||
# 12m: "69 zł/mies."
|
||||
24m: "65 zł/mies."
|
||||
bezterminowa: "85 zł/mies."
|
||||
funkcje:
|
||||
pobieranie: "do 300 Mb/s"
|
||||
wysylanie: "do 150 Mb/s"
|
||||
router: true
|
||||
umowa_info: "12 / 24 / bez umowy"
|
||||
instalacja: "149,00 zł"
|
||||
adres_ip: "Dynamiczny"
|
||||
|
||||
- id: "fiber600"
|
||||
nazwa: "FIBER 600"
|
||||
predkosc: "600 Mb/s"
|
||||
popularny: false
|
||||
ceny:
|
||||
jednorodzinny:
|
||||
24m: "85 zł/mies."
|
||||
bezterminowa: "105 zł/mies."
|
||||
wielorodzinny:
|
||||
24m: "75 zł/mies."
|
||||
bezterminowa: "95 zł/mies."
|
||||
funkcje:
|
||||
pobieranie: "do 600 Mb/s"
|
||||
wysylanie: "do 300 Mb/s"
|
||||
router: true
|
||||
umowa_info: "24 / bez umowy"
|
||||
instalacja: "149 zł"
|
||||
adres_ip: "Dynamiczny"
|
||||
|
||||
uslugi_dodatkowe:
|
||||
- id: "public_ip"
|
||||
nazwa: "Publiczny adres IP"
|
||||
cena: "18,45 zł miesięcznie."
|
||||
opis: |
|
||||
Otrzymujesz unikalny, publiczny adres przypisany na stałe do Twojego łącza, który pozwala na:
|
||||
- Monitoring domu
|
||||
- Dostęp zdalny do urządzeń
|
||||
- Hostowanie serwera lub aplikacji
|
||||
|
||||
Jest to przydatne dla firm, graczy i zaawansowanych użytkowników, którzy potrzebują stabilnej identyfikacji swojej sieci w internecie.
|
||||
|
||||
- id: telefon
|
||||
nazwa: Telefon
|
||||
cena: od wybranej opcji
|
||||
opis: |
|
||||
Profesjonalna telefonia VoIP jako dodatek do internetu
|
||||
- Niższe koszty połączeń - szczególnie na komórki i za granicę
|
||||
- Zachowaj dotychczasowy numer lub otrzymaj nowy lokalny
|
||||
- Bez dodatkowych kabli - działa przez internet
|
||||
- Jeden numer dostępny na wielu urządzeniach jednocześnie
|
||||
- Krystalicznie czysty dźwięk HD
|
||||
|
||||
[Poznaj szczegóły oferty telefonii →](/telefon)
|
||||
@@ -18,4 +18,11 @@ paragraphs:
|
||||
|
||||
Sprawdź naszą pełną ofertę i wybierz rozwiązanie dopasowane do Twoich potrzeb.
|
||||
|
||||
- title:
|
||||
content:
|
||||
Router WiFi AC1200 w cenie instalacji, zapewnia jeszcze większą moc, szybkość, zasięg i bezpieczeństwo dla Twoich stale rosnących potrzeb sieciowych.
|
||||
|
||||
Dzięki funkcji sieci gościnnej Twoi goście mają dostęp do internetu, a Twoje urządzenia i dane pozostają bezpieczne.
|
||||
|
||||
Technologia dwuzakresowa eliminuje zakłócenia i gwarantuje płynne działanie sieci dla całej rodziny.
|
||||
# Kolejne sekcje mozna dodawać poja wiać się bedą pod tabela produktów
|
||||
6
src/helpers/getActiveLabel.js
Normal file
6
src/helpers/getActiveLabel.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export function getActiveLabel(switches, selected, switchId) {
|
||||
const sw = switches.find((s) => s.id === switchId);
|
||||
if (!sw) return "";
|
||||
const opt = sw.opcje.find((o) => o.id === selected[switchId]);
|
||||
return opt?.nazwa ?? "";
|
||||
}
|
||||
16
src/helpers/getPrice.js
Normal file
16
src/helpers/getPrice.js
Normal file
@@ -0,0 +1,16 @@
|
||||
export function getPrice(plan, switches, selected) {
|
||||
try {
|
||||
if (plan.cena) return plan.cena;
|
||||
if (!switches.length) return plan.ceny || "-";
|
||||
|
||||
let v = plan.ceny;
|
||||
for (const sw of switches) {
|
||||
const key = selected[sw.id];
|
||||
if (!v || !(key in v)) return "-";
|
||||
v = v[key];
|
||||
}
|
||||
return v;
|
||||
} catch {
|
||||
return "-";
|
||||
}
|
||||
}
|
||||
54
src/islands/Offers/OffersExtraServices.jsx
Normal file
54
src/islands/Offers/OffersExtraServices.jsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import FuzMarkdown from "../Markdown.jsx";
|
||||
import "../../styles/offers/offers-extra.css";
|
||||
|
||||
|
||||
export default function OffersExtraServices({
|
||||
extraServices,
|
||||
openId,
|
||||
toggle,
|
||||
}) {
|
||||
if (!extraServices.length) return null;
|
||||
|
||||
return (
|
||||
<div class="fuz-extra-services">
|
||||
<h3 class="fuz-title-small">Usługi dodatkowe</h3>
|
||||
|
||||
<div class="fuz-table-wrapper">
|
||||
<table class="fuz-table">
|
||||
<thead class="fuz-table-head">
|
||||
<tr>
|
||||
<th class="fuz-table-heading">Usługa</th>
|
||||
<th class="fuz-table-heading center">Cena</th>
|
||||
<th class="fuz-table-heading center w-32">Szczegóły</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{extraServices.map((srv, i) => (
|
||||
<>
|
||||
<tr class={i % 2 === 0 ? "fuz-row-even" : "fuz-row-odd"}>
|
||||
<td class="fuz-feature-name">{srv.nazwa}</td>
|
||||
<td class="fuz-feature-cell center">{srv.cena}</td>
|
||||
<td class="fuz-feature-cell-btn center">
|
||||
<button class="btn-link" onClick={() => toggle(srv.id)}>
|
||||
{openId === srv.id ? "Zwiń" : "Szczegóły"}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{openId === srv.id && (
|
||||
<tr>
|
||||
<td colSpan={3} class="fuz-expand-details">
|
||||
<FuzMarkdown text={srv.opis} ctx={{ kanaly: srv.kanaly }} />
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
27
src/islands/Offers/OffersSwitches.jsx
Normal file
27
src/islands/Offers/OffersSwitches.jsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import "../../styles/offers/offers-switches.css";
|
||||
|
||||
export default function OffersSwitches({ switches, selected, onSwitch }) {
|
||||
if (!switches.length) return null;
|
||||
|
||||
return (
|
||||
<div class="fuz-switches-wrapper">
|
||||
{switches.map((sw) => (
|
||||
<div class="fuz-switch-block">
|
||||
<div class="fuz-switch-group">
|
||||
{sw.opcje.map((op) => (
|
||||
<button
|
||||
type="button"
|
||||
class={`fuz-switch ${
|
||||
selected[sw.id] === op.id ? "active" : ""
|
||||
}`}
|
||||
onClick={() => onSwitch(sw.id, op.id)}
|
||||
>
|
||||
{op.nazwa}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
88
src/islands/Offers/OffersTable.jsx
Normal file
88
src/islands/Offers/OffersTable.jsx
Normal file
@@ -0,0 +1,88 @@
|
||||
import { getPrice } from "../../helpers/getPrice";
|
||||
import { getActiveLabel } from "../../helpers/getActiveLabel";
|
||||
import "../../styles/offers/offers-table.css";
|
||||
|
||||
|
||||
export default function OffersTable({ switches, selected, plans, features }) {
|
||||
return (
|
||||
<div class="fuz-table-wrapper">
|
||||
<table class="fuz-table">
|
||||
<thead class="fuz-table-head">
|
||||
<tr>
|
||||
<th class="fuz-table-heading">Parametr</th>
|
||||
|
||||
{plans.map((plan) => (
|
||||
<th
|
||||
class={`fuz-plan-heading ${
|
||||
plan.popularny ? "is-popular fuz-popular-top" : ""
|
||||
}`}
|
||||
>
|
||||
<div class="fuz-plan-title">{plan.nazwa}</div>
|
||||
<div class="fuz-plan-price">
|
||||
{getPrice(plan, switches, selected)}
|
||||
</div>
|
||||
<div class="fuz-plan-speed">{plan.predkosc}</div>
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{features.map((f, rowIndex) => (
|
||||
<tr class={rowIndex % 2 === 0 ? "fuz-row-even" : "fuz-row-odd"}>
|
||||
<td class="fuz-feature-name">{f.etykieta}</td>
|
||||
|
||||
{plans.map((plan) => {
|
||||
const isPopular = plan.popularny;
|
||||
const isLastRow = rowIndex === features.length - 1;
|
||||
|
||||
if (f.id === "umowa_info") {
|
||||
return (
|
||||
<td
|
||||
class={`fuz-feature-cell ${
|
||||
isPopular
|
||||
? `is-popular ${
|
||||
isLastRow ? "fuz-popular-bottom" : ""
|
||||
}`
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
{getActiveLabel(switches, selected, "umowa")}
|
||||
</td>
|
||||
);
|
||||
}
|
||||
|
||||
const val = plan.funkcje?.[f.id];
|
||||
|
||||
const baseClass =
|
||||
val === true
|
||||
? "fuz-feature-yes"
|
||||
: val === false || val == null
|
||||
? "fuz-feature-no"
|
||||
: "fuz-feature-cell";
|
||||
|
||||
return (
|
||||
<td
|
||||
class={`${baseClass} ${
|
||||
isPopular
|
||||
? `is-popular ${
|
||||
isLastRow ? "fuz-popular-bottom" : ""
|
||||
}`
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
{val === true
|
||||
? "✓"
|
||||
: val === false || val == null
|
||||
? "✕"
|
||||
: val}
|
||||
</td>
|
||||
);
|
||||
})}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
65
src/islands/OffersIsland.jsx
Normal file
65
src/islands/OffersIsland.jsx
Normal file
@@ -0,0 +1,65 @@
|
||||
import { useState } from "preact/hooks";
|
||||
import FuzMarkdown from "./Markdown.jsx";
|
||||
|
||||
import OffersSwitches from "./Offers/OffersSwitches.jsx";
|
||||
import OffersTable from "./Offers/OffersTable.jsx";
|
||||
import OffersExtraServices from "./Offers/OffersExtraServices.jsx";
|
||||
import "../styles/offers/offers-main.css";
|
||||
|
||||
export default function InternetOffersIsland({ data }) {
|
||||
const switches = data.przelaczniki ?? [];
|
||||
const features = data.funkcje ?? [];
|
||||
const plans = data.plany ?? [];
|
||||
const extraServices = data.uslugi_dodatkowe ?? [];
|
||||
|
||||
const initialSelected = {};
|
||||
switches.forEach((sw) => {
|
||||
initialSelected[sw.id] = sw.domyslny;
|
||||
});
|
||||
|
||||
const [selected, setSelected] = useState(initialSelected);
|
||||
const [openServiceId, setOpenServiceId] = useState(null);
|
||||
|
||||
const toggleService = (id) =>
|
||||
setOpenServiceId((prev) => (prev === id ? null : id));
|
||||
|
||||
const handleSwitchClick = (switchId, optionId) =>
|
||||
setSelected((prev) => ({ ...prev, [switchId]: optionId }));
|
||||
|
||||
return (
|
||||
<section class="fuz-offers-section">
|
||||
<div class="fuz-offers-container">
|
||||
{data.opis_gorny && (
|
||||
<div class="fuz-offers-description">
|
||||
<FuzMarkdown text={data.opis_gorny} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<OffersSwitches
|
||||
switches={switches}
|
||||
selected={selected}
|
||||
onSwitch={handleSwitchClick}
|
||||
/>
|
||||
|
||||
<OffersTable
|
||||
switches={switches}
|
||||
selected={selected}
|
||||
plans={plans}
|
||||
features={features}
|
||||
/>
|
||||
|
||||
<OffersExtraServices
|
||||
extraServices={extraServices}
|
||||
openId={openServiceId}
|
||||
toggle={toggleService}
|
||||
/>
|
||||
|
||||
{data.opis_dolny && (
|
||||
<div class="fuz-offers-description">
|
||||
<FuzMarkdown text={data.opis_dolny} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import DefaultLayout from "../../layouts/DefaultLayout.astro";
|
||||
import Hero from "../../components/hero/Hero.astro";
|
||||
import SectionRenderer from "../../components/sections/SectionRenderer.astro";
|
||||
import Markdown from "../../islands/Markdown.jsx";
|
||||
import OffersIsland from "../../islands/OffersIsland.jsx";
|
||||
|
||||
import yaml from "js-yaml";
|
||||
import fs from "fs";
|
||||
@@ -17,7 +18,16 @@ const page = yaml.load(
|
||||
fs.readFileSync("./src/content/internet-swiatlowodowy/page.yaml", "utf8"),
|
||||
);
|
||||
|
||||
type Paragraph = {
|
||||
title?: string;
|
||||
content: string;
|
||||
};
|
||||
|
||||
const data = yaml.load(
|
||||
fs.readFileSync("./src/content/internet-swiatlowodowy/offers.yaml", "utf8"),
|
||||
);
|
||||
const first = page.paragraphs[0];
|
||||
const rest = page.paragraphs.slice(1);
|
||||
---
|
||||
|
||||
<DefaultLayout seo={seo}>
|
||||
@@ -26,28 +36,21 @@ const first = page.paragraphs[0];
|
||||
<section class="fuz-section text-center">
|
||||
<div class="fuz-section-grid md:grid-cols-1">
|
||||
{page.title.map((line: any) => <h1 class="fuz-section-title">{line}</h1>)}
|
||||
|
||||
{first.title && <h3>{first.title}</h3>}
|
||||
<Markdown text={first.content} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{
|
||||
page.paragraphs.slice(1).map((p: { title: string; content: string }) => (
|
||||
<OffersIsland client:load data={data} />
|
||||
|
||||
{rest.map((p: Paragraph) => (
|
||||
<section class="fuz-section text-center">
|
||||
<div class="fuz-section-grid md:grid-cols-1">
|
||||
{p.title && <h3 class="fuz-section-title">{p.title}</h3>}
|
||||
|
||||
{p.content
|
||||
.trim()
|
||||
.split(/\n\n+/)
|
||||
.map((par: string) => (
|
||||
<Markdown text={par} />
|
||||
))}
|
||||
<Markdown text={p.content.replace(/\n/g, "\n\n")} />
|
||||
</div>
|
||||
</section>
|
||||
))
|
||||
}
|
||||
))}
|
||||
|
||||
<SectionRenderer src="./src/content/internet-swiatlowodowy/section.yaml" />
|
||||
<!-- <section class="fuz-section">
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
}
|
||||
|
||||
.fuz-markdown ul {
|
||||
@apply list-disc pl-6 mb-4;
|
||||
@apply list-disc pl-10 mb-4;
|
||||
}
|
||||
|
||||
.fuz-markdown ol {
|
||||
@@ -32,6 +32,14 @@
|
||||
@apply mb-1;
|
||||
}
|
||||
|
||||
.fuz-markdown ul li::marker {
|
||||
color: var(--fuz-accent);
|
||||
}
|
||||
|
||||
.dark .fuz-markdown ul li::marker {
|
||||
color: var(--fuz-accent);
|
||||
}
|
||||
|
||||
.fuz-markdown a {
|
||||
@apply text-blue-600 dark:text-blue-400 underline hover:no-underline;
|
||||
}
|
||||
|
||||
27
src/styles/offers/offers-extra.css
Normal file
27
src/styles/offers/offers-extra.css
Normal file
@@ -0,0 +1,27 @@
|
||||
.fuz-extra-services {
|
||||
@apply mt-16;
|
||||
color: var(--fuz-text);
|
||||
}
|
||||
|
||||
.fuz-title-small {
|
||||
@apply text-xl font-semibold mb-4;
|
||||
color: var(--fuz-text);
|
||||
}
|
||||
|
||||
.fuz-expand-details {
|
||||
@apply px-4 py-4;
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
:root.dark .fuz-expand-details {
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
}
|
||||
|
||||
.btn-link {
|
||||
@apply underline cursor-pointer;
|
||||
color: var(--fuz-accent);
|
||||
}
|
||||
|
||||
.btn-link:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
14
src/styles/offers/offers-main.css
Normal file
14
src/styles/offers/offers-main.css
Normal file
@@ -0,0 +1,14 @@
|
||||
.fuz-offers-section {
|
||||
@apply py-12;
|
||||
background: var(--fuz-bg);
|
||||
color: var(--fuz-text);
|
||||
}
|
||||
|
||||
.fuz-offers-container {
|
||||
@apply max-w-7xl mx-auto px-6;
|
||||
}
|
||||
|
||||
.fuz-offers-description {
|
||||
@apply mb-10 text-base leading-relaxed;
|
||||
color: var(--fuz-text);
|
||||
}
|
||||
31
src/styles/offers/offers-switches.css
Normal file
31
src/styles/offers/offers-switches.css
Normal file
@@ -0,0 +1,31 @@
|
||||
.fuz-switches-wrapper {
|
||||
@apply flex flex-wrap justify-center gap-6 mb-12;
|
||||
}
|
||||
|
||||
.fuz-switch-group {
|
||||
@apply inline-flex rounded-full overflow-hidden relative;
|
||||
background: rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
:root.dark .fuz-switch-group {
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
}
|
||||
|
||||
|
||||
|
||||
.fuz-switch {
|
||||
@apply px-6 py-2 text-sm font-semibold cursor-pointer select-none transition-all;
|
||||
color: var(--fuz-text);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.fuz-switch:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.fuz-switch.active {
|
||||
background: var(--fuz-accent);
|
||||
color: var(--btn-text);
|
||||
opacity: 1;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.18);
|
||||
}
|
||||
212
src/styles/offers/offers-table.css
Normal file
212
src/styles/offers/offers-table.css
Normal file
@@ -0,0 +1,212 @@
|
||||
/* =========================================
|
||||
TABELA — KONTENER
|
||||
========================================= */
|
||||
|
||||
.fuz-table-wrapper {
|
||||
@apply overflow-x-auto rounded-3xl shadow-lg mb-0;
|
||||
background: var(--fuz-bg);
|
||||
border: 1px solid rgba(0,0,0,0.07);
|
||||
}
|
||||
|
||||
:root.dark .fuz-table-wrapper {
|
||||
border: 1px solid rgba(255,255,255,0.12);
|
||||
}
|
||||
|
||||
.fuz-table {
|
||||
@apply min-w-full border-collapse;
|
||||
color: var(--fuz-text);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* =========================================
|
||||
NAGŁÓWEK
|
||||
========================================= */
|
||||
|
||||
.fuz-table-head {
|
||||
background: color-mix(in srgb, var(--fuz-text) 6%, transparent);
|
||||
}
|
||||
|
||||
:root.dark .fuz-table-head {
|
||||
background: color-mix(in srgb, var(--fuz-text) 12%, transparent);
|
||||
}
|
||||
|
||||
.fuz-table-heading {
|
||||
@apply text-center font-semibold py-4 px-4 text-lg;
|
||||
color: var(--fuz-text);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* =========================================
|
||||
NAGŁÓWEK PLANU
|
||||
========================================= */
|
||||
|
||||
.fuz-plan-heading {
|
||||
@apply text-center py-4 px-4 align-bottom;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fuz-plan-title {
|
||||
@apply text-lg font-semibold mb-1;
|
||||
color: var(--fuz-text);
|
||||
}
|
||||
|
||||
.fuz-plan-price {
|
||||
@apply text-2xl font-extrabold mb-1;
|
||||
color: var(--fuz-accent);
|
||||
}
|
||||
|
||||
.fuz-plan-speed {
|
||||
@apply text-xs;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
|
||||
/* Badge popularności – jeśli używasz */
|
||||
.fuz-plan-badge {
|
||||
@apply text-[10px] px-2 py-0.5 rounded-full uppercase tracking-wide inline-block mb-2;
|
||||
background: var(--fuz-accent);
|
||||
color: var(--fuz-accent-text);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* =========================================
|
||||
WIERSZE
|
||||
========================================= */
|
||||
|
||||
.fuz-row-even {
|
||||
background: color-mix(in srgb, var(--fuz-text) 4%, transparent);
|
||||
}
|
||||
|
||||
:root.dark .fuz-row-even {
|
||||
background: color-mix(in srgb, var(--fuz-text) 10%, transparent);
|
||||
}
|
||||
|
||||
.fuz-row-odd {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.fuz-feature-name {
|
||||
@apply py-3 px-4 text-lg font-medium;
|
||||
color: var(--fuz-text);
|
||||
border-top: 1px solid rgba(0,0,0,0.07);
|
||||
}
|
||||
|
||||
:root.dark .fuz-feature-name {
|
||||
border-top: 1px solid rgba(255,255,255,0.12);
|
||||
}
|
||||
|
||||
.fuz-feature-cell {
|
||||
@apply py-3 px-4 text-center text-lg;
|
||||
color: var(--fuz-text);
|
||||
border-top: 1px solid rgba(0,0,0,0.07);
|
||||
}
|
||||
|
||||
:root.dark .fuz-feature-cell {
|
||||
border-top: 1px solid rgba(255,255,255,0.12);
|
||||
}
|
||||
|
||||
.fuz-feature-cell-btn {
|
||||
@apply py-3 px-4 text-center text-sm;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* =========================================
|
||||
CHECKMARKS
|
||||
========================================= */
|
||||
|
||||
/* ✔ = kolor accent */
|
||||
.fuz-feature-yes {
|
||||
@apply py-3 px-4 text-center font-bold text-base;
|
||||
color: var(--fuz-accent);
|
||||
border-top: 1px solid rgba(0,0,0,0.07);
|
||||
}
|
||||
|
||||
:root.dark .fuz-feature-yes {
|
||||
border-top: 1px solid rgba(255,255,255,0.12);
|
||||
}
|
||||
|
||||
/* ✕ = szary / low opacity */
|
||||
.fuz-feature-no {
|
||||
@apply py-3 px-4 text-center font-bold text-base;
|
||||
opacity: 0.45;
|
||||
border-top: 1px solid rgba(0,0,0,0.07);
|
||||
}
|
||||
|
||||
:root.dark .fuz-feature-no {
|
||||
border-top: 1px solid rgba(255,255,255,0.12);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* =========================================
|
||||
POPULARNY PLAN — WARIANT C (MOCNY)
|
||||
========================================= */
|
||||
|
||||
/* pełne tło pastel na ACCENT (mocniejsze – C) */
|
||||
.is-popular,
|
||||
.fuz-popular-col {
|
||||
background: color-mix(in srgb, var(--fuz-accent) 22%, transparent) !important;
|
||||
border-left: 2px solid var(--fuz-accent);
|
||||
border-right: 2px solid var(--fuz-accent);
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
:root.dark .is-popular,
|
||||
:root.dark .fuz-popular-col {
|
||||
background: color-mix(in srgb, var(--fuz-accent) 32%, transparent) !important;
|
||||
}
|
||||
|
||||
/* górny border */
|
||||
.fuz-popular-top {
|
||||
border-top: 2px solid var(--fuz-accent);
|
||||
}
|
||||
|
||||
/* dolny border */
|
||||
.fuz-popular-bottom {
|
||||
border-bottom: 2px solid var(--fuz-accent);
|
||||
}
|
||||
|
||||
/* zbijamy border wewnątrz popularnych */
|
||||
.fuz-popular-col.fuz-feature-cell,
|
||||
.fuz-popular-col.fuz-feature-yes,
|
||||
.fuz-popular-col.fuz-feature-no {
|
||||
border-top: none !important;
|
||||
}
|
||||
|
||||
/* USŁUGI DODATKOWE */
|
||||
/* Górny border pierwszego wiersza sekcji */
|
||||
.fuz-extra-services table tbody tr:first-child td {
|
||||
border-top: 1px solid rgba(0,0,0,0.07);
|
||||
}
|
||||
:root.dark .fuz-extra-services table tbody tr:first-child td {
|
||||
border-top: 1px solid rgba(255,255,255,0.15);
|
||||
}
|
||||
|
||||
/* Wiersz "Szczegóły" (opis) — zawsze pełny border-top */
|
||||
.fuz-expand-details {
|
||||
border-top: 0px solid rgba(0,0,0,0.1);
|
||||
}
|
||||
:root.dark .fuz-expand-details {
|
||||
border-top: 1px solid rgba(255,255,255,0.15);
|
||||
}
|
||||
|
||||
/* I zawsze ładny border-bottom na końcu sekcji */
|
||||
.fuz-extra-services table tbody tr:last-child td {
|
||||
border-bottom: 1px solid rgba(0,0,0,0.1);
|
||||
}
|
||||
:root.dark .fuz-extra-services table tbody tr:last-child td {
|
||||
border-bottom: 1px solid rgba(255,255,255,0.15);
|
||||
}
|
||||
|
||||
/* Usunięcie "pustych" borderów kolumny szczegóły */
|
||||
.fuz-feature-cell-btn {
|
||||
border-top: 1px solid rgba(0,0,0,0.07);
|
||||
}
|
||||
:root.dark .fuz-feature-cell-btn {
|
||||
border-top: 1px solid rgba(255,255,255,0.12);
|
||||
}
|
||||
Reference in New Issue
Block a user