UI: kolumna dostępności 6–13.02, sekcja Archiwum, nowy termin w nagłówkach
porownanie.html: - nowa kolumna „Dostępność 6–13.02” z pola `dostepnosc_6_13_02_2027`, skrócona do emoji + werdyktu (✅ DOSTĘPNE / 🔍 do sprawdzenia / ❌ BRAK (zweryf.)), pełna notatka w atrybucie title - sortowanie kolumny układa decyzyjnie (wolne → do sprawdzenia → brak), nie alfabetycznie po emoji - wiersz Glemm Lodge na czerwono i z przekreśloną nazwą: zweryfikowany brak miejsc bije kolor statusu ceny (reguła CSS niżej wygrywa) - karty `priorytet: ARCHIWALNA` wypadają z tabeli i z bilansu do osobnej sekcji „Archiwum” na dole strony - legenda i bilans statusów pod tabelą Termin wyjazdu wyjechał do stałych TERM_LABEL/TERM_SHORT/TERM_NOTE: nagłówki wszystkich stron (BUNDLE_NAME, też w gen_viz.py), lead start.html, opis kafla porównania i raport braków biorą go stąd. Zmiana terminu = zmiana stałych i regeneracja. Raport braków czyta teraz dostępność z pola frontmattera zamiast zgadywać z nagłówków w body, i pomija karty archiwalne. Wypis po regeneracji podaje bilans ✅/🔍/❌. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
de10b94bd9
commit
06ab1b24aa
200
gen_pages.py
200
gen_pages.py
|
|
@ -9,9 +9,11 @@ przez pole `resource` (patrz gen_viz.py).
|
||||||
Poza kartą na koncept skrypt generuje trzy strony zbiorcze:
|
Poza kartą na koncept skrypt generuje trzy strony zbiorcze:
|
||||||
|
|
||||||
pages/index.html spis wszystkich kart, pogrupowany katalogami
|
pages/index.html spis wszystkich kart, pogrupowany katalogami
|
||||||
pages/porownanie.html jedna tabela WSZYSTKICH ofert (nie regionów),
|
pages/porownanie.html jedna tabela WSZYSTKICH aktualnych ofert (nie
|
||||||
sortowalna klikiem, złożona z samych frontmatterów;
|
regionów), sortowalna klikiem, złożona z samych
|
||||||
na górze podsumowanie per region z `wyjazd.md`
|
frontmatterów; na górze podsumowanie per region
|
||||||
|
z `wyjazd.md`, na dole sekcja „Archiwum” z kartami
|
||||||
|
`priorytet: ARCHIWALNA` (riscercz na poprzedni termin)
|
||||||
pages/start.html landing: trzy kafle (porównanie / analiza / graf)
|
pages/start.html landing: trzy kafle (porównanie / analiza / graf)
|
||||||
plus linki do kart czterech regionów
|
plus linki do kart czterech regionów
|
||||||
|
|
||||||
|
|
@ -51,7 +53,12 @@ import yaml
|
||||||
BUNDLE_ROOT = Path(__file__).resolve().parent
|
BUNDLE_ROOT = Path(__file__).resolve().parent
|
||||||
PAGES_DIRNAME = "pages"
|
PAGES_DIRNAME = "pages"
|
||||||
PAGES_DIR = BUNDLE_ROOT / PAGES_DIRNAME
|
PAGES_DIR = BUNDLE_ROOT / PAGES_DIRNAME
|
||||||
BUNDLE_NAME = "Ski 2027 — Skicircus Saalbach"
|
BUNDLE_NAME = "Ski 2027 — wyjazd 6–13.02.2027"
|
||||||
|
# Termin wyjazdu w jednym miejscu: leci do nagłówków stron i do raportu
|
||||||
|
# braków. Zmiana terminu = zmiana tych dwóch stałych i regeneracja.
|
||||||
|
TERM_LABEL = "6–13.02.2027"
|
||||||
|
TERM_SHORT = "6–13.02" # nagłówek kolumny w tabeli porównawczej
|
||||||
|
TERM_NOTE = "tydzień Fasching, szczyt sezonu"
|
||||||
RESERVED = {"index.md", "log.md"}
|
RESERVED = {"index.md", "log.md"}
|
||||||
|
|
||||||
# Publiczny adres wystawki — jedyne miejsce, w którym siedzi domena. Używa go
|
# Publiczny adres wystawki — jedyne miejsce, w którym siedzi domena. Używa go
|
||||||
|
|
@ -420,11 +427,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
@ -870,6 +885,7 @@ def parse_conclusions(text: str) -> list[str]:
|
||||||
# (nagłówek, pole frontmattera / klucz specjalny, czy sortować liczbowo)
|
# (nagłówek, pole frontmattera / klucz specjalny, czy sortować liczbowo)
|
||||||
COLUMNS: list[tuple[str, str, bool]] = [
|
COLUMNS: list[tuple[str, str, bool]] = [
|
||||||
("Oferta", "_nazwa", False),
|
("Oferta", "_nazwa", False),
|
||||||
|
(f"Dostępność {TERM_SHORT}", "_dostepnosc", False),
|
||||||
("Priorytet", "priorytet", False),
|
("Priorytet", "priorytet", False),
|
||||||
("Region", "_region", False),
|
("Region", "_region", False),
|
||||||
("Miejscowość", "miejscowosc", False),
|
("Miejscowość", "miejscowosc", False),
|
||||||
|
|
@ -895,6 +911,56 @@ def is_offer(concept: Concept) -> bool:
|
||||||
return str(concept.frontmatter.get("type", "")).startswith("oferta")
|
return str(concept.frontmatter.get("type", "")).startswith("oferta")
|
||||||
|
|
||||||
|
|
||||||
|
# --- dostępność terminu (pole `dostepnosc_6_13_02_2027`) ---------------
|
||||||
|
|
||||||
|
AVAILABILITY_FIELD = "dostepnosc_6_13_02_2027"
|
||||||
|
|
||||||
|
# (emoji z legendy, skrót do komórki, klucz sortowania). Kolejność kluczy
|
||||||
|
# układa kolumnę decyzyjnie: potwierdzone wolne → do sprawdzenia → brak.
|
||||||
|
AVAILABILITY_MARKS = (
|
||||||
|
("✅", "✅ DOSTĘPNE", "1"),
|
||||||
|
("🔍", "🔍 do sprawdzenia", "2"),
|
||||||
|
("❌", "❌ BRAK (zweryf.)", "3"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def availability(concept: Concept) -> str:
|
||||||
|
return str(concept.frontmatter.get(AVAILABILITY_FIELD) or "").strip()
|
||||||
|
|
||||||
|
|
||||||
|
def availability_mark(value: str) -> tuple[str, str, str] | None:
|
||||||
|
for mark in AVAILABILITY_MARKS:
|
||||||
|
if value.startswith(mark[0]):
|
||||||
|
return mark
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _availability_cell(value: str) -> str:
|
||||||
|
"""Komórka dostępności: emoji + jedno słowo, pełna treść w `title`.
|
||||||
|
|
||||||
|
Wartości z frontmattera są zdaniami („🔍 BRAK DANYCH — silnik online
|
||||||
|
pokaże od ręki”), a tabela ma się skanować wzrokiem — więc w komórce
|
||||||
|
zostaje sam werdykt, a uzasadnienie czeka pod kursorem.
|
||||||
|
"""
|
||||||
|
if not value:
|
||||||
|
return '<td class="avail" data-key="9">—</td>'
|
||||||
|
mark = availability_mark(value)
|
||||||
|
if not mark:
|
||||||
|
return _cell(value, False)
|
||||||
|
_, short, key = mark
|
||||||
|
return (
|
||||||
|
f'<td class="avail" data-key="{key}" '
|
||||||
|
f'title="{html.escape(value, quote=True)}">{html.escape(short)}</td>'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def is_archived(concept: Concept) -> bool:
|
||||||
|
"""Karty z riserczu na poprzedni termin — poza tabelą i statusami."""
|
||||||
|
return str(concept.frontmatter.get("priorytet") or "").upper().startswith(
|
||||||
|
"ARCHIWALNA"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _shorten(value: str) -> str:
|
def _shorten(value: str) -> str:
|
||||||
"""Sam rdzeń wartości; doprecyzowanie w nawiasie/po myślniku idzie do title.
|
"""Sam rdzeń wartości; doprecyzowanie w nawiasie/po myślniku idzie do title.
|
||||||
|
|
||||||
|
|
@ -929,29 +995,22 @@ def _cell(value: str, numeric: bool, suffix: str = "", short: bool = True) -> st
|
||||||
return f"<td{attrs}>{html.escape(shown + suffix)}</td>"
|
return f"<td{attrs}>{html.escape(shown + suffix)}</td>"
|
||||||
|
|
||||||
|
|
||||||
def render_comparison(concepts: list[Concept], regions: list[Region]) -> str:
|
def _offer_rows(offers: list[Concept], by_dir: dict[str, Region]) -> str:
|
||||||
"""Jedna tabela wszystkich ofert bundle'a, prosto z frontmatterów."""
|
"""Wiersze tabeli porównawczej dla podanych ofert."""
|
||||||
by_dir = {r.dirname: r for r in regions}
|
|
||||||
offers = [c for c in concepts if is_offer(c)]
|
|
||||||
# Domyślna kolejność: najtańsza rodzina 2+2 na górze — pierwsze pytanie,
|
|
||||||
# które grupa zadaje. Resztę porządków daje sortowanie klikiem.
|
|
||||||
offers.sort(
|
|
||||||
key=lambda c: (
|
|
||||||
sort_number(str(c.frontmatter.get("koszt_rodzina_2p2") or "")) or 1e9,
|
|
||||||
c.title,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
rows = []
|
rows = []
|
||||||
for concept in offers:
|
for concept in offers:
|
||||||
frontmatter = concept.frontmatter
|
frontmatter = concept.frontmatter
|
||||||
status = str(frontmatter.get("status_ceny") or "")
|
status = str(frontmatter.get("status_ceny") or "")
|
||||||
upper = status.upper()
|
upper = status.upper()
|
||||||
css_row = (
|
classes = [
|
||||||
"verified" if "ZWERYFIKOWANE" in upper
|
"verified" if "ZWERYFIKOWANE" in upper
|
||||||
else "estimate" if "SZACUNEK" in upper
|
else "estimate" if "SZACUNEK" in upper
|
||||||
else ""
|
else ""
|
||||||
)
|
]
|
||||||
|
# Zweryfikowany brak miejsc to najmocniejszy komunikat w wierszu —
|
||||||
|
# ważniejszy niż to, czy cena jest pewna.
|
||||||
|
if availability(concept).startswith("❌"):
|
||||||
|
classes.append("unavailable")
|
||||||
dirname = posixpath.dirname(posixpath.dirname(concept.id))
|
dirname = posixpath.dirname(posixpath.dirname(concept.id))
|
||||||
region = by_dir.get(dirname)
|
region = by_dir.get(dirname)
|
||||||
region_label = region.label if region else (dirname or "—")
|
region_label = region.label if region else (dirname or "—")
|
||||||
|
|
@ -984,6 +1043,8 @@ def render_comparison(concepts: list[Concept], regions: list[Region]) -> str:
|
||||||
cells.append(
|
cells.append(
|
||||||
f'<td data-key="{html.escape(region_label, quote=True)}">{shown}</td>'
|
f'<td data-key="{html.escape(region_label, quote=True)}">{shown}</td>'
|
||||||
)
|
)
|
||||||
|
elif field == "_dostepnosc":
|
||||||
|
cells.append(_availability_cell(availability(concept)))
|
||||||
elif field == "www":
|
elif field == "www":
|
||||||
url = str(frontmatter.get("www") or "").strip()
|
url = str(frontmatter.get("www") or "").strip()
|
||||||
if url:
|
if url:
|
||||||
|
|
@ -1006,18 +1067,66 @@ def render_comparison(concepts: list[Concept], regions: list[Region]) -> str:
|
||||||
cells.append(
|
cells.append(
|
||||||
_cell(value, numeric, suffix, short=field not in NO_SHORTEN)
|
_cell(value, numeric, suffix, short=field not in NO_SHORTEN)
|
||||||
)
|
)
|
||||||
|
css_row = " ".join(c for c in classes if c)
|
||||||
klass = f' class="{css_row}"' if css_row else ""
|
klass = f' class="{css_row}"' if css_row else ""
|
||||||
rows.append(f"<tr{klass}>{''.join(cells)}</tr>")
|
rows.append(f"<tr{klass}>{''.join(cells)}</tr>")
|
||||||
|
return "".join(rows)
|
||||||
|
|
||||||
|
|
||||||
|
def _comparison_table(offers: list[Concept], by_dir: dict[str, Region]) -> str:
|
||||||
head = '<th data-key="">Zdjęcie</th>' + "".join(
|
head = '<th data-key="">Zdjęcie</th>' + "".join(
|
||||||
f'<th scope="col" aria-sort="none">{html.escape(title)}</th>'
|
f'<th scope="col" aria-sort="none">{html.escape(title)}</th>'
|
||||||
for title, _, _ in COLUMNS
|
for title, _, _ in COLUMNS
|
||||||
)
|
)
|
||||||
table = (
|
return (
|
||||||
'<div class="table-wrap"><table class="sortable"><thead><tr>'
|
'<div class="table-wrap"><table class="sortable"><thead><tr>'
|
||||||
f"{head}</tr></thead><tbody>{''.join(rows)}</tbody></table></div>"
|
f"{head}</tr></thead><tbody>{_offer_rows(offers, by_dir)}</tbody>"
|
||||||
|
"</table></div>"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _by_price(concept: Concept) -> tuple[float, str]:
|
||||||
|
# Domyślna kolejność: najtańsza rodzina 2+2 na górze — pierwsze pytanie,
|
||||||
|
# które grupa zadaje. Resztę porządków daje sortowanie klikiem.
|
||||||
|
return (
|
||||||
|
sort_number(str(concept.frontmatter.get("koszt_rodzina_2p2") or "")) or 1e9,
|
||||||
|
concept.title,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def render_comparison(concepts: list[Concept], regions: list[Region]) -> str:
|
||||||
|
"""Jedna tabela wszystkich aktualnych ofert bundle'a, prosto z frontmatterów.
|
||||||
|
|
||||||
|
Karty archiwalne (riscercz na poprzedni termin) idą do osobnej tabeli
|
||||||
|
na dole strony — nie mieszają się do porównania ani do statusów
|
||||||
|
dostępności, ale nie znikają z bazy.
|
||||||
|
"""
|
||||||
|
by_dir = {r.dirname: r for r in regions}
|
||||||
|
offers = sorted((c for c in concepts if is_offer(c)), key=_by_price)
|
||||||
|
active = [c for c in offers if not is_archived(c)]
|
||||||
|
archived = [c for c in offers if is_archived(c)]
|
||||||
|
|
||||||
|
table = _comparison_table(active, by_dir)
|
||||||
|
|
||||||
|
counts: dict[str, int] = {}
|
||||||
|
for concept in active:
|
||||||
|
mark = availability_mark(availability(concept))
|
||||||
|
counts[mark[1] if mark else "—"] = counts.get(mark[1] if mark else "—", 0) + 1
|
||||||
|
tally = " · ".join(f"{label}: {n}" for label, n in sorted(counts.items()))
|
||||||
|
|
||||||
|
archive = ""
|
||||||
|
if archived:
|
||||||
|
archive = (
|
||||||
|
'<section class="archive">\n'
|
||||||
|
"<h2>Archiwum — poza paczką riserczową 08.2026</h2>\n"
|
||||||
|
f'<p class="lead">Karty z riserczu na poprzedni termin '
|
||||||
|
f"(16–23.01.2027). Ceny i dostępność nie były weryfikowane na "
|
||||||
|
f"{html.escape(TERM_LABEL)} — nie wchodzą do porównania wyżej ani "
|
||||||
|
"do statusów dostępności. Zostają, bo tropy są nadal dobre.</p>\n"
|
||||||
|
f"{_comparison_table(archived, by_dir)}\n"
|
||||||
|
"</section>"
|
||||||
|
)
|
||||||
|
|
||||||
summary = ""
|
summary = ""
|
||||||
if regions:
|
if regions:
|
||||||
items = []
|
items = []
|
||||||
|
|
@ -1042,14 +1151,22 @@ def render_comparison(concepts: list[Concept], regions: list[Region]) -> str:
|
||||||
|
|
||||||
content = (
|
content = (
|
||||||
"<h1>Porównanie ofert</h1>\n"
|
"<h1>Porównanie ofert</h1>\n"
|
||||||
f'<p class="lead">Wszystkie {len(offers)} rozważanych noclegów w jednej '
|
f'<p class="lead">Wszystkie {len(active)} rozważanych noclegów na termin '
|
||||||
"tabeli — dane prosto z frontmatterów kart. Kliknij nagłówek, żeby "
|
f"<strong>{html.escape(TERM_LABEL)}</strong> ({html.escape(TERM_NOTE)}) "
|
||||||
"posortować; domyślnie od najtańszej rodziny 2+2.</p>\n"
|
"w jednej tabeli — dane prosto z frontmatterów kart. Kliknij nagłówek, "
|
||||||
|
"żeby posortować; domyślnie od najtańszej rodziny 2+2.</p>\n"
|
||||||
f"{summary}\n"
|
f"{summary}\n"
|
||||||
"<h2>Wszystkie oferty</h2>\n"
|
"<h2>Wszystkie oferty</h2>\n"
|
||||||
f"{table}\n"
|
f"{table}\n"
|
||||||
'<p class="legend"><span class="box v"></span>cena zweryfikowana '
|
'<p class="legend"><span class="box v"></span>cena zweryfikowana '
|
||||||
' <span class="box e"></span>szacunek do potwierdzenia</p>'
|
' <span class="box e"></span>szacunek do potwierdzenia '
|
||||||
|
' <span class="box u"></span>zweryfikowany brak miejsc<br>'
|
||||||
|
f"Dostępność {html.escape(TERM_SHORT)}: ✅ DOSTĘPNE (zweryfikowane) · "
|
||||||
|
"🔍 do sprawdzenia (obiekt nie publikuje kalendarza) · "
|
||||||
|
"❌ BRAK (zweryfikowane). "
|
||||||
|
f"Bilans: {html.escape(tally)}. Najedź na komórkę, żeby zobaczyć "
|
||||||
|
"pełną notatkę.</p>\n"
|
||||||
|
f"{archive}"
|
||||||
)
|
)
|
||||||
return _page_shell(
|
return _page_shell(
|
||||||
"Porównanie ofert", 0, content, body_class="wide", script=SORT_JS
|
"Porównanie ofert", 0, content, body_class="wide", script=SORT_JS
|
||||||
|
|
@ -1062,8 +1179,8 @@ def render_comparison(concepts: list[Concept], regions: list[Region]) -> str:
|
||||||
# tylko ścieżki root-absolutne działają pod obiema (patrz docstring modułu).
|
# tylko ścieżki root-absolutne działają pod obiema (patrz docstring modułu).
|
||||||
TILES = [
|
TILES = [
|
||||||
("/pages/porownanie.html", "Porównanie ofert",
|
("/pages/porownanie.html", "Porównanie ofert",
|
||||||
"Wszystkie noclegi w jednej sortowalnej tabeli: ceny, status ceny, "
|
"Wszystkie noclegi w jednej sortowalnej tabeli: dostępność na "
|
||||||
"priorytet, odległość od wyciągu."),
|
f"{TERM_SHORT}, ceny, status ceny, priorytet, odległość od wyciągu."),
|
||||||
("/pages/wyjazd.html", "Analiza wariantów",
|
("/pages/wyjazd.html", "Analiza wariantów",
|
||||||
"Cztery regiony obok siebie: skipassy, dojazd, budżet całkowity grupy "
|
"Cztery regiony obok siebie: skipassy, dojazd, budżet całkowity grupy "
|
||||||
"i wnioski przekrojowe."),
|
"i wnioski przekrojowe."),
|
||||||
|
|
@ -1111,7 +1228,8 @@ def render_start(concepts: list[Concept], regions: list[Region]) -> str:
|
||||||
|
|
||||||
content = (
|
content = (
|
||||||
f"<h1>{html.escape(BUNDLE_NAME)}</h1>\n"
|
f"<h1>{html.escape(BUNDLE_NAME)}</h1>\n"
|
||||||
'<p class="lead">16–23.01.2027, 4 rodziny / 14 osób, wyjazd z Warszawy. '
|
f'<p class="lead"><strong>{html.escape(TERM_LABEL)}</strong> '
|
||||||
|
f"({html.escape(TERM_NOTE)}), 4 rodziny / 14 osób, wyjazd z Warszawy. "
|
||||||
"Od czego zacząć:</p>\n"
|
"Od czego zacząć:</p>\n"
|
||||||
f'<ul class="tiles">{tiles}</ul>\n'
|
f'<ul class="tiles">{tiles}</ul>\n'
|
||||||
"<h2>Regiony</h2>\n"
|
"<h2>Regiony</h2>\n"
|
||||||
|
|
@ -1383,7 +1501,7 @@ def missing_data(concepts: list[Concept]) -> list[tuple[str, list[str]]]:
|
||||||
"""Czego brakuje w ofertach — bez zgadywania, tylko z tego, co jest."""
|
"""Czego brakuje w ofertach — bez zgadywania, tylko z tego, co jest."""
|
||||||
report = []
|
report = []
|
||||||
for concept in concepts:
|
for concept in concepts:
|
||||||
if not str(concept.frontmatter.get("type", "")).startswith("oferta"):
|
if not is_offer(concept) or is_archived(concept):
|
||||||
continue
|
continue
|
||||||
gaps = []
|
gaps = []
|
||||||
status = str(concept.frontmatter.get("status_ceny") or "")
|
status = str(concept.frontmatter.get("status_ceny") or "")
|
||||||
|
|
@ -1391,10 +1509,13 @@ def missing_data(concepts: list[Concept]) -> list[tuple[str, list[str]]]:
|
||||||
gaps.append("brak pola `status_ceny`")
|
gaps.append("brak pola `status_ceny`")
|
||||||
elif "SZACUNEK" in status.upper():
|
elif "SZACUNEK" in status.upper():
|
||||||
gaps.append(f"cena niepotwierdzona ({status})")
|
gaps.append(f"cena niepotwierdzona ({status})")
|
||||||
# Danymi o dostępności jest osobna sekcja (jak w glemm-lodge), a nie
|
# Dostępność czytamy z pola frontmattera, nie z nagłówka w tekście —
|
||||||
# samo słowo w tekście — "duża dostępność" w opisie się nie liczy.
|
# werdykt ✅/❌/🔍 jest danymi, a nie tym, czy ktoś napisał sekcję.
|
||||||
if not re.search(r"^#+\s*.*dostępnoś", concept.body, re.IGNORECASE | re.M):
|
value = availability(concept)
|
||||||
gaps.append("brak danych o dostępności terminu 16–23.01.2027")
|
if not value:
|
||||||
|
gaps.append(f"brak pola `{AVAILABILITY_FIELD}`")
|
||||||
|
elif value.startswith("🔍"):
|
||||||
|
gaps.append(f"dostępność {TERM_LABEL} do weryfikacji ({_shorten(value)})")
|
||||||
open_todos = len(re.findall(r"^\s*[-*]\s+\[ \]", concept.body, re.M))
|
open_todos = len(re.findall(r"^\s*[-*]\s+\[ \]", concept.body, re.M))
|
||||||
if open_todos:
|
if open_todos:
|
||||||
gaps.append(f"otwartych pozycji „Do zrobienia”: {open_todos}")
|
gaps.append(f"otwartych pozycji „Do zrobienia”: {open_todos}")
|
||||||
|
|
@ -1458,10 +1579,21 @@ def main() -> int:
|
||||||
f"Regiony z wyjazd.md: {len(regions)} "
|
f"Regiony z wyjazd.md: {len(regions)} "
|
||||||
f"({', '.join(r.label for r in regions) or '—'})"
|
f"({', '.join(r.label for r in regions) or '—'})"
|
||||||
)
|
)
|
||||||
|
active = [c for c in offers if not is_archived(c)]
|
||||||
print(
|
print(
|
||||||
f"Oferty w tabeli porównawczej: {len(offers)}, "
|
f"Oferty w tabeli porównawczej: {len(active)} "
|
||||||
|
f"(+{len(offers) - len(active)} archiwalnych w osobnej sekcji), "
|
||||||
f"ze zdjęciami: {len(with_photos)} (zdjęcia dokłada gen_images.py)"
|
f"ze zdjęciami: {len(with_photos)} (zdjęcia dokłada gen_images.py)"
|
||||||
)
|
)
|
||||||
|
marks = [availability_mark(availability(c)) for c in active]
|
||||||
|
print(
|
||||||
|
f"Dostępność {TERM_LABEL}: "
|
||||||
|
+ " · ".join(
|
||||||
|
f"{label}: {sum(1 for m in marks if m and m[1] == label)}"
|
||||||
|
for _, label, _ in AVAILABILITY_MARKS
|
||||||
|
)
|
||||||
|
+ f" · bez pola: {sum(1 for m in marks if m is None)}"
|
||||||
|
)
|
||||||
|
|
||||||
gaps = missing_data(concepts)
|
gaps = missing_data(concepts)
|
||||||
print()
|
print()
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ from urllib.parse import urlsplit, urlunsplit
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
BUNDLE_ROOT = Path(__file__).resolve().parent
|
BUNDLE_ROOT = Path(__file__).resolve().parent
|
||||||
BUNDLE_NAME = "Ski 2027 — Skicircus Saalbach"
|
BUNDLE_NAME = "Ski 2027 — wyjazd 6–13.02.2027"
|
||||||
CATALOG = Path(os.environ.get("KNOWLEDGE_CATALOG", "/tmp/knowledge-catalog"))
|
CATALOG = Path(os.environ.get("KNOWLEDGE_CATALOG", "/tmp/knowledge-catalog"))
|
||||||
|
|
||||||
sys.path.insert(0, str(CATALOG / "okf" / "src"))
|
sys.path.insert(0, str(CATALOG / "okf" / "src"))
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Karty — Ski 2027 — Skicircus Saalbach</title>
|
<title>Karty — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
@ -149,7 +157,7 @@ td.thumb .placeholder { display: flex; width: 120px; height: 80px; border-radius
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav><a href="start.html">← Start</a> · <a href="index.html">Wszystkie karty</a> · <a href="porownanie.html">Porównanie ofert</a> · <a href="linki.html">Linki</a> · <a href="../viz.html">Graf</a></nav>
|
<nav><a href="start.html">← Start</a> · <a href="index.html">Wszystkie karty</a> · <a href="porownanie.html">Porównanie ofert</a> · <a href="linki.html">Linki</a> · <a href="../viz.html">Graf</a></nav>
|
||||||
<h1>Ski 2027 — Skicircus Saalbach</h1>
|
<h1>Ski 2027 — wyjazd 6–13.02.2027</h1>
|
||||||
<p class="lead">Karty konceptów bundle'a — pełna treść każdego dokumentu (ceny, dostępność, plusy/minusy). Struktura powiązań: <a href="../viz.html">graf</a>.</p>
|
<p class="lead">Karty konceptów bundle'a — pełna treść każdego dokumentu (ceny, dostępność, plusy/minusy). Struktura powiązań: <a href="../viz.html">graf</a>.</p>
|
||||||
<h2>Wyjazd i wiedza ogólna</h2>
|
<h2>Wyjazd i wiedza ogólna</h2>
|
||||||
<ul class="cards"><li><a href="szablon-maila.html">Szablon zapytania grupowego (EN)</a> <span class="chip">narzedzie</span><p>Gotowy angielski mail o 4 apartamenty dla 14 osób w terminie 6–13.02.2027, z pytaniem o najbliższy wolny tydzień i notatkami negocjacyjnymi na rynek Fasching.</p></li><li><a href="wyjazd.html">Ski 2027 — cztery warianty na termin 6–13.02.2027</a> <span class="chip">Trip</span><p>Wyjazd narciarski 4 rodzin (14 osób) z Warszawy w tygodniu Fasching: porównanie czterech regionów, statusy dostępności noclegów i wnioski przekrojowe.</p></li></ul>
|
<ul class="cards"><li><a href="szablon-maila.html">Szablon zapytania grupowego (EN)</a> <span class="chip">narzedzie</span><p>Gotowy angielski mail o 4 apartamenty dla 14 osób w terminie 6–13.02.2027, z pytaniem o najbliższy wolny tydzień i notatkami negocjacyjnymi na rynek Fasching.</p></li><li><a href="wyjazd.html">Ski 2027 — cztery warianty na termin 6–13.02.2027</a> <span class="chip">Trip</span><p>Wyjazd narciarski 4 rodzin (14 osób) z Warszawy w tygodniu Fasching: porównanie czterech regionów, statusy dostępności noclegów i wnioski przekrojowe.</p></li></ul>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Apartment Brandau (Kappl) — Ski 2027 — Skicircus Saalbach</title>
|
<title>Apartment Brandau (Kappl) — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Apartments Kappl — Ski 2027 — Skicircus Saalbach</title>
|
<title>Apartments Kappl — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Ischgl / Silvretta Arena + dolina Paznaun — Ski 2027 — Skicircus Saalbach</title>
|
<title>Ischgl / Silvretta Arena + dolina Paznaun — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Häuslerhof (Valdaora) — Ski 2027 — Skicircus Saalbach</title>
|
<title>Häuslerhof (Valdaora) — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Residence Corones (Valdaora) — Ski 2027 — Skicircus Saalbach</title>
|
<title>Residence Corones (Valdaora) — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Kronplatz / Plan de Corones (Południowy Tyrol) — Ski 2027 — Skicircus Saalbach</title>
|
<title>Kronplatz / Plan de Corones (Południowy Tyrol) — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Linki — Ski 2027 — Skicircus Saalbach</title>
|
<title>Linki — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>AlpenParks Apartments Rehrenberg — Ski 2027 — Skicircus Saalbach</title>
|
<title>AlpenParks Apartments Rehrenberg — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>AlpenParks Hotel & Apartment Sonnleiten — Ski 2027 — Skicircus Saalbach</title>
|
<title>AlpenParks Hotel & Apartment Sonnleiten — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Duży dom wakacyjny 12–14 os. (do wyszukania) — Ski 2027 — Skicircus Saalbach</title>
|
<title>Duży dom wakacyjny 12–14 os. (do wyszukania) — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Glemm Lodge Apartments ⭐⭐⭐⭐ — Ski 2027 — Skicircus Saalbach</title>
|
<title>Glemm Lodge Apartments ⭐⭐⭐⭐ — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Appartementhaus Kristall at SchattbergXpress — Ski 2027 — Skicircus Saalbach</title>
|
<title>Appartementhaus Kristall at SchattbergXpress — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Sportchalet Viehhofen — Ski 2027 — Skicircus Saalbach</title>
|
<title>Sportchalet Viehhofen — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Skicircus Saalbach-Hinterglemm-Leogang-Fieberbrunn — Ski 2027 — Skicircus Saalbach</title>
|
<title>Skicircus Saalbach-Hinterglemm-Leogang-Fieberbrunn — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Apart Ideal (Serfaus) — Ski 2027 — Skicircus Saalbach</title>
|
<title>Apart Ideal (Serfaus) — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Haus Central (Apart Central), Ladis — Ski 2027 — Skicircus Saalbach</title>
|
<title>Haus Central (Apart Central), Ladis — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Serfaus-Fiss-Ladis (SFL) — Ski 2027 — Skicircus Saalbach</title>
|
<title>Serfaus-Fiss-Ladis (SFL) — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Start — Ski 2027 — Skicircus Saalbach</title>
|
<title>Start — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
@ -149,9 +157,9 @@ td.thumb .placeholder { display: flex; width: 120px; height: 80px; border-radius
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav><a href="/pages/index.html">Wszystkie karty</a> · <a href="/pages/porownanie.html">Porównanie ofert</a> · <a href="/pages/linki.html">Linki</a> · <a href="/viz.html">Graf</a></nav>
|
<nav><a href="/pages/index.html">Wszystkie karty</a> · <a href="/pages/porownanie.html">Porównanie ofert</a> · <a href="/pages/linki.html">Linki</a> · <a href="/viz.html">Graf</a></nav>
|
||||||
<h1>Ski 2027 — Skicircus Saalbach</h1>
|
<h1>Ski 2027 — wyjazd 6–13.02.2027</h1>
|
||||||
<p class="lead">16–23.01.2027, 4 rodziny / 14 osób, wyjazd z Warszawy. Od czego zacząć:</p>
|
<p class="lead"><strong>6–13.02.2027</strong> (tydzień Fasching, szczyt sezonu), 4 rodziny / 14 osób, wyjazd z Warszawy. Od czego zacząć:</p>
|
||||||
<ul class="tiles"><li><a href="/pages/porownanie.html">Porównanie ofert<small>Wszystkie noclegi w jednej sortowalnej tabeli: ceny, status ceny, priorytet, odległość od wyciągu.</small></a></li><li><a href="/pages/wyjazd.html">Analiza wariantów<small>Cztery regiony obok siebie: skipassy, dojazd, budżet całkowity grupy i wnioski przekrojowe.</small></a></li><li><a href="/viz.html">Graf powiązań<small>Struktura bazy wiedzy — koncepty, linki między nimi i adresy zewnętrzne. Załącznik, nie punkt wejścia.</small></a></li><li><a href="/pages/linki.html">Wszystkie linki<small>Pełne adresy wszystkich stron wystawki, z przyciskiem „kopiuj” — do wrzucenia grupie.</small></a></li></ul>
|
<ul class="tiles"><li><a href="/pages/porownanie.html">Porównanie ofert<small>Wszystkie noclegi w jednej sortowalnej tabeli: dostępność na 6–13.02, ceny, status ceny, priorytet, odległość od wyciągu.</small></a></li><li><a href="/pages/wyjazd.html">Analiza wariantów<small>Cztery regiony obok siebie: skipassy, dojazd, budżet całkowity grupy i wnioski przekrojowe.</small></a></li><li><a href="/viz.html">Graf powiązań<small>Struktura bazy wiedzy — koncepty, linki między nimi i adresy zewnętrzne. Załącznik, nie punkt wejścia.</small></a></li><li><a href="/pages/linki.html">Wszystkie linki<small>Pełne adresy wszystkich stron wystawki, z przyciskiem „kopiuj” — do wrzucenia grupie.</small></a></li></ul>
|
||||||
<h2>Regiony</h2>
|
<h2>Regiony</h2>
|
||||||
<p class="lead">Karta regionu = skipassy, dojazd, terminy, koszty życia i budżet całkowity.</p>
|
<p class="lead">Karta regionu = skipassy, dojazd, terminy, koszty życia i budżet całkowity.</p>
|
||||||
<ul class="regions"><li><a href="/pages/saalbach/region.html" class="hero" style="background-image:linear-gradient(rgba(15,23,42,.62),rgba(15,23,42,.72)),url('/pages/img/alpenparks-sonnleiten/01.jpg')">Saalbach<small>Budżet grupy: ~16 200–19 500 €</small></a></li><li><a href="/pages/ischgl/region.html" class="hero" style="background-image:linear-gradient(rgba(15,23,42,.62),rgba(15,23,42,.72)),url('/pages/img/apartment-brandau-kappl/01.jpg')">Ischgl/Paznaun<small>Budżet grupy: ~14 200–17 000 €</small></a></li><li><a href="/pages/kronplatz/region.html" class="hero" style="background-image:linear-gradient(rgba(15,23,42,.62),rgba(15,23,42,.72)),url('/pages/img/haeuslerhof-valdaora/01.jpg')">Kronplatz<small>Budżet grupy: ~14 500–17 700 €</small></a></li><li><a href="/pages/sfl/region.html" class="hero" style="background-image:linear-gradient(rgba(15,23,42,.62),rgba(15,23,42,.72)),url('/pages/img/haus-central-ladis/01.jpg')">SFL<small>Budżet grupy: ~14 500–17 900 €</small></a></li></ul>
|
<ul class="regions"><li><a href="/pages/saalbach/region.html" class="hero" style="background-image:linear-gradient(rgba(15,23,42,.62),rgba(15,23,42,.72)),url('/pages/img/alpenparks-sonnleiten/01.jpg')">Saalbach<small>Budżet grupy: ~16 200–19 500 €</small></a></li><li><a href="/pages/ischgl/region.html" class="hero" style="background-image:linear-gradient(rgba(15,23,42,.62),rgba(15,23,42,.72)),url('/pages/img/apartment-brandau-kappl/01.jpg')">Ischgl/Paznaun<small>Budżet grupy: ~14 200–17 000 €</small></a></li><li><a href="/pages/kronplatz/region.html" class="hero" style="background-image:linear-gradient(rgba(15,23,42,.62),rgba(15,23,42,.72)),url('/pages/img/haeuslerhof-valdaora/01.jpg')">Kronplatz<small>Budżet grupy: ~14 500–17 700 €</small></a></li><li><a href="/pages/sfl/region.html" class="hero" style="background-image:linear-gradient(rgba(15,23,42,.62),rgba(15,23,42,.72)),url('/pages/img/haus-central-ladis/01.jpg')">SFL<small>Budżet grupy: ~14 500–17 900 €</small></a></li></ul>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Szablon zapytania grupowego (EN) — Ski 2027 — Skicircus Saalbach</title>
|
<title>Szablon zapytania grupowego (EN) — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Ski 2027 — cztery warianty na termin 6–13.02.2027 — Ski 2027 — Skicircus Saalbach</title>
|
<title>Ski 2027 — cztery warianty na termin 6–13.02.2027 — Ski 2027 — wyjazd 6–13.02.2027</title>
|
||||||
<style>
|
<style>
|
||||||
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
:root { color-scheme: light dark; --fg:#0f172a; --muted:#64748b; --bg:#ffffff;
|
||||||
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
--line:#e2e8f0; --accent:#0d9488; --chip:#f1f5f9; --quote:#f8fafc; }
|
||||||
|
|
@ -95,11 +95,19 @@ table.sortable .name { font-weight: 600; }
|
||||||
tr.verified td { background: rgba(13, 148, 136, .14); }
|
tr.verified td { background: rgba(13, 148, 136, .14); }
|
||||||
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
tr.estimate td { background: rgba(100, 116, 139, .10); color: var(--muted); }
|
||||||
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
tr.estimate td.name a, tr.verified td.name a { color: var(--accent); }
|
||||||
|
/* zweryfikowany BRAK miejsc bije kolor statusu ceny — reguła niżej wygrywa */
|
||||||
|
tr.unavailable td { background: rgba(220, 38, 38, .16); }
|
||||||
|
tr.unavailable td.name a { text-decoration: line-through; }
|
||||||
|
td.avail { white-space: nowrap; font-weight: 600; }
|
||||||
|
.archive { margin-top: 2.5rem; }
|
||||||
|
.archive h2 { margin-bottom: .2rem; }
|
||||||
|
.archive .lead { font-size: .88rem; margin-top: .2rem; }
|
||||||
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
.legend { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
|
||||||
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
.legend .box { display: inline-block; width: .8em; height: .8em; border-radius: 3px;
|
||||||
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
border: 1px solid var(--line); vertical-align: -.05em; margin-right: .25em; }
|
||||||
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
.legend .box.v { background: rgba(13, 148, 136, .35); }
|
||||||
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
.legend .box.e { background: rgba(100, 116, 139, .25); }
|
||||||
|
.legend .box.u { background: rgba(220, 38, 38, .35); }
|
||||||
|
|
||||||
/* miniatury w tabeli */
|
/* miniatury w tabeli */
|
||||||
td.thumb { padding: .25rem; width: 128px; }
|
td.thumb { padding: .25rem; width: 128px; }
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue