/*
Theme Name: Newsky
Theme URI: https://hedlajner.sk
Author: Hedlajner
Description: Vlastná bloková (FSE) téma pre spravodajský web Hedlajner. Postavená na firemných farbách loga a prehľadnom rozložení zameranom na čítanie článkov a titulkov.
Version: 1.0.0
Requires at least: 6.4
Tested up to: 6.7
Requires PHP: 7.4
Text Domain: newsky
*/

.newsky-card-meta .taxonomy-category a {
	text-decoration: none;
}

/* Jemny tien okolo videa a vsetkych obrazkov (karty, hlavny obrazok clanku,
   obrazky v texte clanku). */
.newsky-intro-video,
.wp-block-post-featured-image img,
.wp-block-post-content img {
	box-shadow: 0 4px 14px rgba(0, 0, 0, 0.12);
}

/* Jemna svetlomodra ziara za nadpismi clankov (karty aj samotny clanok). */
.wp-block-post-title,
.wp-block-post-title a {
	text-shadow: 0 0 10px rgba(120, 180, 255, 0.45);
}

/* Logo v hlavnom paneli jemne "dycha" (pomaly pulzuje) a ma jemnu svetlomodru
   ziaru (drop-shadow sleduje tvar loga, nie hranaty box). Filter a animovany
   transform su zamerne na dvoch roznych elementoch (rodic / dieta): predtym
   boli oba na tom istom <img>, co Firefox rendruje zle - pri kazdom frame
   animacie musel prepocitat masku tiena na hlavnom vlakne namiesto GPU
   vrstvy (sekanie; v Chrome to vidno nebolo). Ked je filter na needitovanom
   rodicovi a animuje sa len transform na diecati, filter sa prepocita raz
   (nie 60x za sekundu) a animacia zostava lacny GPU transform - hladke vo
   vsetkych prehliadacoch, vizualne identicke s povodnym vzhladom. */
.wp-block-site-logo {
	filter: drop-shadow(0 0 8px rgba(120, 180, 255, 0.55));
}

.wp-block-site-logo img {
	animation: newsky-logo-breathe 4s ease-in-out infinite;
	will-change: transform;
	backface-visibility: hidden;
}

@keyframes newsky-logo-breathe {
	0%, 100% {
		transform: scale(1);
	}
	50% {
		transform: scale(1.05);
	}
}

@media (prefers-reduced-motion: reduce) {
	.wp-block-site-logo img {
		animation: none;
	}
}

/* Vo Firefoxe su vsetky animacie na stranke (logo, ikonky, plavajuce pozadie,
   patickovy text...) vypnute rovno globalne, nech uz nezalezi na tom, ako
   presne Gecko kompozituje jednotlive kombinacie filter/transform/pozadie.
   -moz-appearance je vlastnost, ktoru pozna len Gecko (Firefox) - ostatne
   prehliadace o nej nevedia, takze tento @supports blok sa aplikuje
   spolahlivo len tam. Nejde o UA sniffing, len o bezne pouzivany
   feature-query trik. Univerzalny selektor pokryje aj buduce animacie,
   netreba ich sem prideravat jednu po druhej. */
@supports (-moz-appearance: none) {
	*,
	*::before,
	*::after {
		animation: none !important;
	}
}

/* Core's own .wp-block-social-link{display:block} (and, more specifically,
   ".wp-block-social-links .wp-block-social-link.wp-social-link{display:
   inline-block}") centers its <a> by text-metrics (line-height +
   vertical-align), which never quite lines up with the search/theme-toggle
   icons' flex-centered boxes next to it in the header - flex +
   align-items:center centers it exactly instead, matching them pixel for
   pixel regardless of font metrics. !important: that inline-block rule above
   has 3 classes (0,3,0), more specific than this rule's 2 (0,2,0). */
.newsky-social-links .wp-social-link {
	display: flex !important;
	align-items: center;
}

/* YouTube a Facebook ikonky sa striedavo "nadychuju" - ked jedna pulzuje,
   druha je v pokoji, a naopak (posunute o polovicu cyklu). */
.newsky-social-links li:nth-child(1) a {
	display: inline-flex;
	animation: newsky-icon-breathe 3s ease-in-out infinite;
}

.newsky-social-links li:nth-child(2) a {
	display: inline-flex;
	animation: newsky-icon-breathe 3s ease-in-out infinite;
	animation-delay: 1.5s;
}

@keyframes newsky-icon-breathe {
	0%, 100% {
		transform: scale(1);
	}
	50% {
		transform: scale(1.18);
	}
}

@media (prefers-reduced-motion: reduce) {
	.newsky-social-links li a {
		animation: none;
	}
}

/* Decent, plynulo animovane pozadie: priesvitne stupajuce bubliny + jemne
   "dychajuci" gradient, bez JS. Gradient je vo fixed vrstve #dynamic-bg, ktora
   presne prekryva cely viewport (spravne aj na tablete/velkych obrazovkach -
   na "body" by sa velkost gradientu pocitala z celej vysky stranky a
   opakovala by sa po useekoch). "Dychanie" je animovane cez transform
   (GPU/compositor), nie cez background-position (to vynucovalo prekreslenie
   celej vrstvy kazdy frame a sposobovalo sekane scrollovanie na mobile). */
body {
	background: transparent !important;
	overflow-x: hidden;
}

.wp-site-blocks {
	position: relative;
	z-index: 1;
}

#dynamic-bg {
	position: fixed;
	inset: 0;
	z-index: -1;
	pointer-events: none;
	overflow: hidden;
	background: transparent;
}

#dynamic-bg::before {
	content: "";
	position: absolute;
	inset: -15%;
	background: linear-gradient(165deg, #ffffff 0%, #f4f8fc 38%, #e8eef6 72%, #f7fafc 100%);
	animation: newsky-bg-shift 28s ease-in-out infinite alternate;
	will-change: transform;
}

#dynamic-bg::after {
	content: "";
	position: absolute;
	inset: 0;
	background: radial-gradient(ellipse at 18% 12%, rgba(149, 12, 22, 0.035), transparent 42%),
		radial-gradient(ellipse at 88% 78%, rgba(149, 12, 22, 0.025), transparent 46%);
	pointer-events: none;
}

@keyframes newsky-bg-shift {
	0% {
		transform: translate3d(-2%, -1%, 0) scale(1.1);
	}
	100% {
		transform: translate3d(2%, 3%, 0) scale(1.1);
	}
}

#dynamic-bg span {
	position: absolute;
	bottom: -140px;
	border-radius: 50%;
	background: radial-gradient(
		circle at 32% 28%,
		rgba(255, 255, 255, 0.92),
		rgba(150, 190, 228, 0.34) 58%,
		rgba(130, 175, 220, 0.1)
	);
	box-shadow: 0 0 32px rgba(120, 170, 220, 0.22);
	animation: newsky-bg-rise linear infinite, newsky-bg-sway ease-in-out infinite;
	will-change: transform, opacity;
	/* #dynamic-bg itself stays pointer-events:none (see above) so the empty
	   space between bubbles keeps clicking straight through to real page
	   content - only the circle itself (clip-path, not the invisible square
	   bounding box around it) becomes an actual click target. */
	pointer-events: auto;
	cursor: pointer;
	clip-path: circle(50%);
}

/* One-shot "pop" on click (see newsky_bubble_pop_js in functions.php),
   overriding the ambient rise/sway animation - !important is deliberate
   here: it's the only way to beat the #dynamic-bg span:nth-child(N) rules'
   equal-specificity animation-duration/-delay overrides below, so the pop
   actually plays instead of instantly finishing in 0s (see the dark-mode
   version of this exact trap, documented further down). Removing the class
   afterwards lets rise/sway restart clean from the bottom - a "new" bubble. */
#dynamic-bg span.is-popping {
	animation: newsky-bubble-pop 0.35s ease-out forwards !important;
	pointer-events: none;
}

@keyframes newsky-bubble-pop {
	0% {
		transform: scale(1);
		opacity: 1;
	}
	35% {
		transform: scale(1.3);
		opacity: 1;
	}
	100% {
		transform: scale(0.05);
		opacity: 0;
	}
}

/* Expanding ring + flying droplets, spawned as short-lived siblings inside
   #dynamic-bg (same fixed/viewport coordinate space as the bubbles) at the
   clicked bubble's on-screen position, then removed on animationend. */
.newsky-bubble-ring {
	position: absolute;
	/* Darker on the light background (default) so it actually shows up -
	   white-on-white was invisible; dark mode restores the white version
	   below, since white-on-dark already looked right. */
	border: 2px solid rgba(55, 105, 155, 0.75);
	border-radius: 50%;
	pointer-events: none;
	animation: newsky-bubble-ring 0.4s ease-out forwards;
}

.is-dark-mode .newsky-bubble-ring {
	border-color: rgba(255, 255, 255, 0.85);
}

@keyframes newsky-bubble-ring {
	0% {
		transform: scale(0.7);
		opacity: 0.9;
	}
	100% {
		transform: scale(2.4);
		opacity: 0;
	}
}

.newsky-bubble-droplet {
	position: absolute;
	width: 7px;
	height: 7px;
	margin: -3.5px 0 0 -3.5px;
	border-radius: 50%;
	background: radial-gradient(circle at 30% 30%, rgba(90, 145, 190, 0.95), rgba(45, 90, 135, 0.55));
	pointer-events: none;
	animation: newsky-bubble-droplet 0.45s ease-out forwards;
}

.is-dark-mode .newsky-bubble-droplet {
	background: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.95), rgba(170, 200, 228, 0.35));
}

@keyframes newsky-bubble-droplet {
	0% {
		transform: translate(0, 0) scale(1);
		opacity: 1;
	}
	100% {
		transform: translate(var(--dx), var(--dy)) scale(0.15);
		opacity: 0;
	}
}

@keyframes newsky-bg-rise {
	0% {
		transform: translateY(0) scale(1);
		opacity: 0;
	}
	10% {
		opacity: 0.65;
	}
	90% {
		opacity: 0.4;
	}
	100% {
		transform: translateY(-115vh) scale(1.12);
		opacity: 0;
	}
}

@keyframes newsky-bg-sway {
	0%, 100% {
		margin-left: 0;
	}
	50% {
		margin-left: 40px;
	}
}

#dynamic-bg span:nth-child(1) { left: 4%; width: 22px; height: 22px; animation-duration: 26s, 11s; animation-delay: -3s, -1s; }
#dynamic-bg span:nth-child(2) { left: 12%; width: 54px; height: 54px; animation-duration: 34s, 14s; animation-delay: -12s, -4s; }
#dynamic-bg span:nth-child(3) { left: 19%; width: 16px; height: 16px; animation-duration: 21s, 9s; animation-delay: -7s, -2s; }
#dynamic-bg span:nth-child(4) { left: 27%; width: 78px; height: 78px; animation-duration: 41s, 16s; animation-delay: -18s, -6s; }
#dynamic-bg span:nth-child(5) { left: 36%; width: 28px; height: 28px; animation-duration: 24s, 10s; animation-delay: -5s, -3s; }
#dynamic-bg span:nth-child(6) { left: 44%; width: 96px; height: 96px; animation-duration: 46s, 18s; animation-delay: -22s, -8s; }
#dynamic-bg span:nth-child(7) { left: 53%; width: 18px; height: 18px; animation-duration: 19s, 8s; animation-delay: -9s, -1s; }
#dynamic-bg span:nth-child(8) { left: 61%; width: 42px; height: 42px; animation-duration: 29s, 13s; animation-delay: -14s, -5s; }
#dynamic-bg span:nth-child(9) { left: 68%; width: 64px; height: 64px; animation-duration: 37s, 15s; animation-delay: -11s, -7s; }
#dynamic-bg span:nth-child(10) { left: 74%; width: 24px; height: 24px; animation-duration: 23s, 10s; animation-delay: -16s, -2s; }
#dynamic-bg span:nth-child(11) { left: 81%; width: 88px; height: 88px; animation-duration: 44s, 17s; animation-delay: -25s, -9s; }
#dynamic-bg span:nth-child(12) { left: 88%; width: 20px; height: 20px; animation-duration: 20s, 9s; animation-delay: -4s, -3s; }
#dynamic-bg span:nth-child(13) { left: 8%; width: 36px; height: 36px; animation-duration: 31s, 12s; animation-delay: -20s, -6s; }
#dynamic-bg span:nth-child(14) { left: 48%; width: 14px; height: 14px; animation-duration: 17s, 7s; animation-delay: -8s, -2s; }
#dynamic-bg span:nth-child(15) { left: 92%; width: 50px; height: 50px; animation-duration: 33s, 14s; animation-delay: -13s, -4s; }
#dynamic-bg span:nth-child(16) { left: 31%; width: 70px; height: 70px; animation-duration: 39s, 16s; animation-delay: -27s, -10s; }

@media (prefers-reduced-motion: reduce) {
	#dynamic-bg::before,
	#dynamic-bg span {
		animation: none !important;
	}

	/* Popping a bubble should still work with reduced motion - it just
	   disappears instantly instead of animating, and no ring/droplets spawn
	   (the click handler itself checks the same media query before creating
	   them at all). */
	#dynamic-bg span.is-popping {
		opacity: 0 !important;
	}

	.newsky-bubble-ring,
	.newsky-bubble-droplet {
		display: none !important;
	}
}

/* Dark-mode analog of the animated background above: same shift/rise/sway
   animations (untouched), just dark tones instead of the light gradient -
   body's own background is transparent!important either way, so this is
   what actually needs to change for the page to read as "dark". */
.is-dark-mode #dynamic-bg::before {
	background: linear-gradient(165deg, #16181d 0%, #1b1e24 38%, #202329 72%, #17191e 100%);
}

.is-dark-mode #dynamic-bg::after {
	background: radial-gradient(ellipse at 18% 12%, rgba(255, 138, 138, 0.05), transparent 42%),
		radial-gradient(ellipse at 88% 78%, rgba(255, 138, 138, 0.035), transparent 46%);
}

.is-dark-mode #dynamic-bg span {
	background: radial-gradient(
		circle at 32% 28%,
		rgba(255, 255, 255, 0.18),
		rgba(145, 165, 195, 0.09) 58%,
		rgba(125, 145, 175, 0.028)
	);
	box-shadow: 0 0 24px rgba(0, 0, 0, 0.4);
	/* animation-name only (not the "animation" shorthand): the shorthand
	   would reset animation-duration/-delay to their 0s defaults, clobbering
	   the per-bubble timing set by the #dynamic-bg span:nth-child(N) rules
	   below (same specificity, but those come first in the file) - which is
	   exactly what made every bubble instantly invisible in dark mode. */
	animation-name: newsky-bg-rise-dark, newsky-bg-sway-dark;
}

@keyframes newsky-bg-rise-dark {
	0% {
		transform: translateY(0) scale(1);
		opacity: 0;
	}
	10% {
		opacity: 0.48;
	}
	90% {
		opacity: 0.27;
	}
	100% {
		transform: translateY(-115vh) scale(1.12);
		opacity: 0;
	}
}

@keyframes newsky-bg-sway-dark {
	0%, 100% {
		margin-left: 0;
	}
	50% {
		margin-left: 22px;
	}
}

/* Small side padding on the page content in portrait/mobile, so text and
   cards don't sit flush against the screen edges. */
@media (max-width: 600px) {
	.wp-site-blocks > main {
		padding-left: 4px;
		padding-right: 4px;
	}
}

/* Article card excerpt: up to 4 lines on narrow/portrait screens (single
   column, more room to breathe), tightened to 3 lines on wider grid
   layouts. The JS clamp script adds a real "..." only when text is
   actually cut off, based on whichever max-height applies here. */
.newsky-card .wp-block-post-excerpt {
	max-height: 6.6em;
	line-height: 1.65;
	overflow: hidden;
}

/* Article cards (homepage + category grids): keep title/excerpt/category
   aligned across a row regardless of how long each one's text is.
   Only applied from 601px up - on narrow/portrait screens the grid is a
   single column anyway, so the full title can just show. */
@media (min-width: 601px) {
	.newsky-card {
		display: flex;
		flex-direction: column;
		height: 100%;
	}

	.newsky-card .wp-block-post-title {
		max-height: 2.4em;
		line-height: 1.2;
		overflow: hidden;
	}

	.newsky-card .wp-block-post-excerpt {
		max-height: 4.95em;
	}

	.newsky-card-meta {
		width: 100%;
		align-items: center;
	}
}

/* "Ilustračný obrázok" caption under the article's featured image - only
   makes sense when there actually is a featured image to caption. */
.newsky-image-caption {
	margin-top: 0.5rem;
	margin-bottom: 1rem;
}

main:not(:has(.wp-block-post-featured-image)) .newsky-image-caption {
	display: none;
}

/* Site tagline shown above the homepage intro video, in a script/cursive font */
.newsky-tagline {
	font-family: "Dancing Script", cursive;
	font-weight: 700;
	margin: 0.5rem 0;
}

/* Red scrollbar (Firefox + WebKit browsers) */
html {
	scrollbar-color: var(--wp--preset--color--primary-red) #f0f0f0;
}

::-webkit-scrollbar {
	width: 14px;
}

::-webkit-scrollbar-track {
	background: #f0f0f0;
}

::-webkit-scrollbar-thumb {
	background-color: var(--wp--preset--color--primary-red);
	border-radius: 7px;
	border: 3px solid #f0f0f0;
}

::-webkit-scrollbar-thumb:hover {
	background-color: var(--wp--preset--color--navy);
}

.wp-block-post-content h1 {
	font-size: var(--wp--preset--font-size--xx-large);
}

.wp-block-post-content h2 {
	font-size: var(--wp--preset--font-size--x-large);
}

.wp-block-post-content h3 {
	font-size: var(--wp--preset--font-size--large);
}

.wp-block-post-content h4 {
	font-size: var(--wp--preset--font-size--medium);
	color: var(--wp--preset--color--primary-red);
}

.wp-block-post-content h5,
.wp-block-post-content h6 {
	font-size: var(--wp--preset--font-size--medium);
}

/* Embedded videos in article content (YouTube etc.) + self-hosted <video>:
   rounded corners with a soft drop shadow, matching the 12px radius used
   elsewhere on the site (e.g. .newsky-intro-video). Radius on the wrapper
   (with overflow hidden) actually clips the embed; radius on the iframe/
   video itself is a fallback for embeds with no wrapper. */
.wp-block-post-content .wp-block-embed__wrapper,
.wp-block-post-content .wp-embed-aspect-16-9 {
	border-radius: 12px;
	overflow: hidden;
	box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}

.wp-block-post-content iframe,
.wp-block-post-content video {
	border-radius: 12px;
	box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}

/* Video description: My AI Writer emits this as a plain centered italic
   paragraph right after the embed (not a figcaption - see
   ai_writer_videos_to_embed_blocks()), so target it as the embed's
   immediate next sibling. Pulled closer to the video, smaller and muted
   gray instead of the article's normal paragraph size/spacing/color. */
.wp-block-post-content .wp-block-embed + p {
	margin-top: 0.4em;
	font-size: 0.8rem;
	color: #646970;
}

/* Pagination: page numbers as rounded buttons - gray by default, red text
   for the active page (prev/next "Novšie"/"Staršie" text links removed
   from the templates, numbers-only now). */
.wp-block-query-pagination-numbers .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 2.2rem;
	height: 2.2rem;
	padding: 0 0.6rem;
	border: 1px solid #dcdcde;
	border-radius: 8px;
	color: #646970;
	font-weight: 600;
	text-decoration: none;
}

.wp-block-query-pagination-numbers .page-numbers:hover {
	border-color: var(--wp--preset--color--navy);
	color: var(--wp--preset--color--navy);
}

.wp-block-query-pagination-numbers .page-numbers.current {
	color: var(--wp--preset--color--primary-red);
	border-color: var(--wp--preset--color--primary-red);
}

/* Footer brand row: keep "HEDLAJNER" and "© 2026" on the same text baseline */
.newsky-footer-brand {
	align-items: baseline;
}

.newsky-footer-brand .wp-block-site-title,
.newsky-footer-brand p {
	margin: 0;
	line-height: 1;
}

/* Footer 3-column layout: force equal columns side by side instead of the
   blocks' default constrained content width, which was wide enough to make
   the 3rd column wrap onto its own row. */
.newsky-footer-columns {
	display: grid !important;
	grid-template-columns: repeat(3, 1fr);
	align-items: start;
}

.newsky-footer-col {
	max-width: none !important;
	width: 100%;
}

@media (max-width: 780px) {
	.newsky-footer-columns {
		grid-template-columns: 1fr;
	}
}

/* Middle footer column (company info) centered, desktop only. */
@media (min-width: 781px) {
	.newsky-footer-columns > .newsky-footer-col:nth-child(2) {
		text-align: center;
	}
}

/* Soft white glow on "HEDLAJNER" and the company name in the footer. */
.newsky-footer-columns > .newsky-footer-col:nth-child(1) > p,
.newsky-footer-columns > .newsky-footer-col:nth-child(2) strong {
	text-shadow: 0 0 3px rgba(255, 255, 255, 0.3);
}

/* Full-bleed red bar at the very bottom of the footer: escapes the footer's
   own side padding and the constrained-layout content width, spanning the
   entire viewport regardless of parent padding. */
.newsky-footer-bottombar {
	box-sizing: border-box;
	max-width: none !important;
	width: 100vw !important;
	margin-left: calc(50% - 50vw) !important;
	margin-right: calc(50% - 50vw) !important;
	padding: 0.6rem 1.5rem;
	margin-top: 1.5rem;
}

.newsky-footer-bottombar p {
	margin: 0;
	display: inline-block;
	animation: newsky-footer-text-sway 5s ease-in-out infinite alternate;
}

@keyframes newsky-footer-text-sway {
	0% {
		transform: translateX(-18px);
	}
	100% {
		transform: translateX(18px);
	}
}

@media (prefers-reduced-motion: reduce) {
	.newsky-footer-bottombar p {
		animation: none;
	}
}

/* Article headings (post titles) stay dark blue even when linked - the global
   link color would otherwise override the heading color on linked titles. */
.wp-block-post-title,
.wp-block-post-title a {
	color: var(--wp--preset--color--navy) !important;
}

.wp-block-post-title a:hover {
	color: var(--wp--preset--color--primary-red) !important;
}

.newsky-meta {
	display: flex;
	gap: 0.75rem;
	align-items: center;
	flex-wrap: wrap;
}

/* Footer always stuck to the bottom of the viewport, even on short pages */
html {
	height: 100%;
}

.wp-site-blocks {
	display: flex;
	flex-direction: column;
	min-height: 100vh;
}

.wp-site-blocks > main {
	flex: 1 0 auto;
}

.wp-site-blocks > footer {
	flex-shrink: 0;
}

footer .wp-block-site-title a:hover,
footer .wp-block-site-title a:focus {
	color: var(--wp--preset--color--primary-red);
}

/* Sticky, translucent + blurred top header with a centered category menu */
/* WordPress wraps the header template part in its own <header class="wp-block-template-part">
   element that hugs the content height exactly. Sticky positioning has to live on THAT wrapper
   (whose parent, .wp-site-blocks, spans the full page) - putting it on the inner content div
   only gives it ~1 header-height of scroll room before it unsticks. */
.wp-site-blocks > header.wp-block-template-part {
	position: sticky;
	top: 0;
	z-index: 100;
	background-color: rgba(255, 255, 255, 0.7);
	-webkit-backdrop-filter: blur(10px);
	backdrop-filter: blur(10px);
	box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
}

.admin-bar .wp-site-blocks > header.wp-block-template-part {
	top: 32px;
}

@media screen and (max-width: 782px) {
	.admin-bar .wp-site-blocks > header.wp-block-template-part {
		top: 46px;
	}
}

.newsky-header-grid {
	display: flex;
	align-items: center;
	gap: 1rem;
	min-height: 44px;
}

.newsky-main-nav.wp-block-navigation {
	flex: 1 1 auto;
	justify-content: center;
}

.newsky-main-nav .wp-block-navigation-item__content,
.newsky-main-nav a.wp-block-navigation-item__content {
	color: #000000 !important;
}

.newsky-current-nav-item .wp-block-navigation-item__content,
.newsky-current-nav-item a.wp-block-navigation-item__content {
	color: var(--wp--preset--color--primary-red) !important;
}

.newsky-main-nav .wp-block-navigation-item__content:hover {
	color: var(--wp--preset--color--primary-red) !important;
}

@media (max-width: 600px) {
	.newsky-header-grid {
		flex-direction: column;
		gap: 0.5rem;
	}

	.newsky-main-nav.wp-block-navigation {
		margin-top: 0.75rem;
		/* .newsky-header-grid switches to flex-direction:column just above,
		   making width the cross axis - a flex item's cross size should
		   stretch to the container's own width by default, but this nav is
		   itself a flex formatting context whose row children (nowrap, see
		   below) push it back to their own content width instead of
		   respecting that stretch. Pinning width explicitly is what actually
		   keeps it from overflowing .newsky-header-grid; min-width:0 alone
		   (the usual flex-shrink fix) isn't enough here since the container
		   isn't shrinking it along the main axis anymore. */
		width: 100%;
		max-width: 100%;
		min-width: 0;
	}

	/* Keep the category menu on one line - !important overrides WordPress's
	   own auto-generated layout class, which otherwise wins the cascade and
	   forces flex-wrap:wrap. No horizontal scroll workaround needed anymore
	   now that only Domov/Svet/Menu (3 short items) show directly - that
	   used to be required for all 6 categories, but it would also clip the
	   "Menu" dropdown below (see .newsky-nav-more-menu), so it's gone. */
	.newsky-main-nav .wp-block-navigation__container {
		flex-wrap: nowrap !important;
		justify-content: center !important;
	}
}

/* Menu dropdown in the main nav (Tech/Drive/Haluze/War, collapsed behind a
   hamburger-icon toggle placed before Domov/Svet - see
   hedlajner_split_main_nav_overflow()). Same on desktop and mobile/portrait
   for now. */
.newsky-nav-more {
	position: relative;
}

.newsky-nav-more-toggle {
	color: #000000;
	background: none;
	border: none;
	padding: 0;
	margin: 0;
	cursor: pointer;
	display: inline-flex;
	align-items: center;
}

.newsky-nav-more-toggle:hover {
	color: var(--wp--preset--color--primary-red);
}

.newsky-nav-more-menu {
	display: none;
	position: absolute;
	top: 100%;
	left: 0;
	margin: 10px 0 0;
	background: #fff;
	border: 1px solid #dcdcde;
	border-radius: 8px;
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
	/* Guarantees the corners actually clip round even if a child (an item's
	   hover highlight, say) paints a square background flush to the edge -
	   overflow:hidden only clips this element's own CONTENT, not its own
	   box-shadow, which is drawn outside the border regardless. */
	overflow: hidden;
	padding: 0;
	width: max-content;
	z-index: 30;
	text-transform: uppercase;
}

.newsky-nav-more.is-open .newsky-nav-more-menu {
	display: block;
}

.newsky-nav-more-menu li {
	/* !important: undoes core's own .wp-block-navigation-item rule (higher
	   specificity than a single class here) that sets display:flex - meant
	   for the horizontal bar, but as a flex box each item kept extra
	   phantom width beyond its own link text here, leaving a gap before the
	   dropdown's right edge. Plain block items shrink to exactly the
	   content's width instead. */
	display: block !important;
	list-style: none;
}

.newsky-nav-more-menu a {
	display: block;
	width: auto;
	padding: 8px 16px;
	white-space: nowrap;
	color: #000000 !important;
	text-decoration: none;
}

.newsky-nav-more-menu a:hover {
	background: var(--wp--preset--color--light-gray, #f4f5f7);
	color: var(--wp--preset--color--primary-red) !important;
}

/* "O nás" stands out from the category links (Drive/Haluze/War) above it in
   the same dropdown - theme red instead of black. The CSS class set on this
   nav item in the editor lands on the <li>, not the <a>, hence the descendant
   selector. */
.newsky-nav-more-menu li.newsky-nav-link-o-nas a {
	color: var(--wp--preset--color--primary-red) !important;
}

/* Container padding is 0 (first/last item flush with the top/bottom edge)
   so their own hover highlight needs the container's corner radius, or it'd
   square off past the rounded border on hover. */
.newsky-nav-more-menu li:first-child a {
	border-top-left-radius: 8px;
	border-top-right-radius: 8px;
}

.newsky-nav-more-menu li:last-child a {
	border-bottom-left-radius: 8px;
	border-bottom-right-radius: 8px;
}

/* Header search - a search icon (before the YouTube/Facebook icons) that
   toggles a small dropdown form, same interaction pattern as .newsky-nav-more
   above. Submits a normal GET to templates/search.html (?s=...), which
   already existed but had no way to reach it from the UI before this. */
.newsky-header-search {
	position: relative;
	display: inline-flex;
	align-items: center;
}

/* Wraps search+toggle+social-links (hedlajner_prepend_header_search()) into
   one flex row so they always sit on a single line, even when
   .newsky-header-grid itself stacks into a column on narrow/portrait
   screens (see the max-width:600px rule below). */
.newsky-header-icons {
	display: flex;
	align-items: center;
	gap: 1rem;
}

/* Unlike .newsky-header-grid, this wrapper isn't tagged with WordPress's own
   "is-layout-flex" class, so its auto-generated ".is-layout-flex > :is(*,
   div) { margin: 0 }" reset doesn't reach the social-links <ul> nested in
   here anymore - its default list margin was puffing up the whole header's
   height. Same reset, applied directly instead of relying on that class. */
.newsky-header-icons > * {
	margin: 0;
}

/* Same top-up as .newsky-theme-toggle's margin below - keeps the
   toggle-to-YouTube gap equal to the YouTube-to-Facebook gap (25px) instead
   of just .newsky-header-icons's own smaller 1rem gap. !important: core's own
   ".is-layout-flex > :is(*, div) { margin: 0 }" layout-support rule has
   higher specificity than a single class and would otherwise zero this out. */
.newsky-header-icons > .newsky-social-links {
	margin-left: calc(25px - 1rem) !important;
}

.newsky-header-search-toggle {
	color: #000000;
	background: none;
	border: none;
	padding: 0;
	margin: 0;
	cursor: pointer;
	display: inline-flex;
	align-items: center;
}

.newsky-header-search-toggle:hover {
	color: var(--wp--preset--color--primary-red);
}

.newsky-header-search-form {
	display: none;
	position: absolute;
	top: 100%;
	right: 0;
	margin-top: 10px;
	align-items: center;
	gap: 6px;
	background: #fff;
	border: 1px solid #dcdcde;
	border-radius: 8px;
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
	padding: 8px;
	z-index: 30;
}

.newsky-header-search.is-open .newsky-header-search-form {
	display: flex;
}

.newsky-header-search-form input[type="search"] {
	width: 170px;
	max-width: 50vw;
	padding: 6px 10px;
	border: 1px solid #dcdcde;
	border-radius: 6px;
	font-size: 0.9rem;
}

.newsky-header-search-form button[type="submit"] {
	flex-shrink: 0;
	display: flex;
	align-items: center;
	background: none;
	border: none;
	padding: 4px;
	color: var(--wp--preset--color--navy);
	cursor: pointer;
}

.newsky-header-search-form button[type="submit"]:hover {
	color: var(--wp--preset--color--primary-red);
}

/* Dark mode toggle - black circle, yellow crescent moon, left of the search
   icon (see hedlajner_dark_mode_toggle_html() in hedlajner-open-graph.php). */
.newsky-theme-toggle {
	width: 26px;
	height: 26px;
	flex-shrink: 0;
	border-radius: 50%;
	background: #000000;
	border: none;
	padding: 0;
	/* .newsky-header-grid's own flex "gap" (1rem) already puts 1rem between
	   every pair of icons here - topping it up to the social-links block's
	   own 25px gap (between YouTube/Facebook) so all 3 gaps read as equal,
	   instead of search-to-toggle and toggle-to-YouTube looking tighter.
	   !important: core's own ".is-layout-flex > :is(*, div) { margin: 0 }"
	   layout-support rule outranks a single class here (it matches via
	   :is(*, div), which counts as element-level specificity on top of its
	   own class) and would otherwise zero this margin back out. */
	margin: 0 0 0 calc(25px - 1rem) !important;
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

.newsky-theme-toggle:hover {
	background: #2a2a2a;
}

/* Dimmed while the visitor hasn't accepted cookies yet (hedlajner_dark_mode
   is a "Volitelny" cookie - see Zasady ochrany osobnych udajov) - the click
   is already a no-op via updateToggleAvailability()'s consent check, this
   just makes that visible instead of a button that silently does nothing. */
.newsky-theme-toggle.is-disabled {
	opacity: 0.35;
	cursor: not-allowed;
}

.newsky-theme-toggle.is-disabled:hover {
	background: #000000;
}

/* Only one of the 2 icons inside the button shows at a time: moon (light
   mode, offers to switch TO dark) or sun (dark mode, offers to switch TO
   light) - see hedlajner_dark_mode_toggle_html(). */
.newsky-theme-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

.newsky-theme-icon-moon,
.newsky-theme-icon-sun {
	align-items: center;
	justify-content: center;
}

/* display set separately per icon/mode below (not folded into the shared
   align-items rule above) - a previous version set display:inline-flex for
   both icons in one combined rule that happened to be declared AFTER
   .newsky-theme-icon-sun{display:none}, silently winning and showing both
   icons stacked together at once regardless of mode. */
.newsky-theme-icon-moon {
	display: inline-flex;
}

.newsky-theme-icon-sun {
	display: none;
}

.is-dark-mode .newsky-theme-icon-moon {
	display: none;
}

.is-dark-mode .newsky-theme-icon-sun {
	display: inline-flex;
}

.is-dark-mode .newsky-theme-toggle {
	background: #ffffff;
}

.is-dark-mode .newsky-theme-toggle:hover {
	background: #e5e7eb;
}

/* Dark mode - toggled by adding .is-dark-mode to <html> (JS on click, and
   PHP reads the same cookie server-side on every page load so there's no
   flash of light mode before JS runs - see hedlajner_add_dark_mode_html_class()).
   Overriding the theme's own color custom properties handles most of the
   site for free, since theme.json's global styles (body background/text,
   headings, links, category labels, dates...) already reference these
   variables instead of hardcoding colors. Only this stylesheet's OWN
   hardcoded #fff/#dcdcde backgrounds (dropdowns, cards, pagination) need
   their own explicit override below. */
:root.is-dark-mode {
	--wp--preset--color--base: #16181d;
	--wp--preset--color--contrast: #e5e7eb;
	--wp--preset--color--light-gray: #22252c;
	--wp--preset--color--mid-gray: #9aa3af;
	--wp--preset--color--navy: #8fb4ff;
	--wp--preset--color--primary-red: #ff8a8a;
}

/* The footer (navy background, white text, red bottom bar) already reads
   fine as-is in dark mode - it's the one section of the site that was
   already "dark". Re-declaring the 3 color variables it actually uses,
   scoped to the footer itself, cancels the :root.is-dark-mode redefinitions
   above for everything inside it (nearest custom-property definition wins),
   so has-navy-background-color/has-base-color/has-primary-red-background-color
   resolve back to their normal light-mode values here specifically. */
.is-dark-mode footer.has-navy-background-color {
	--wp--preset--color--navy: #162d4f;
	--wp--preset--color--base: #ffffff;
	--wp--preset--color--primary-red: #950c16;
}

.is-dark-mode .newsky-site-header {
	border-bottom-color: #2a2d34 !important;
}

.is-dark-mode .newsky-main-nav .wp-block-navigation-item__content,
.is-dark-mode .newsky-main-nav a.wp-block-navigation-item__content,
.is-dark-mode .newsky-nav-more-toggle,
.is-dark-mode .newsky-header-search-toggle {
	color: #e5e7eb !important;
}

.is-dark-mode .newsky-nav-more-menu,
.is-dark-mode .newsky-header-search-form {
	background: #1f2229;
	border-color: #33363e;
}

.is-dark-mode .newsky-nav-more-menu a {
	color: #e5e7eb !important;
}

/* "O nás" stays theme red in dark mode too, matching light mode - same
   reasoning as the light-mode rule above, just re-declared with higher
   specificity than .is-dark-mode .newsky-nav-more-menu a so it isn't
   swallowed by the generic dark-mode text color. */
.is-dark-mode .newsky-nav-more-menu li.newsky-nav-link-o-nas a {
	color: var(--wp--preset--color--primary-red) !important;
}

.is-dark-mode .newsky-nav-more-menu a:hover {
	background: #2a2d34;
}

.is-dark-mode .newsky-header-search-form input[type="search"] {
	background: #16181d;
	color: #e5e7eb;
	border-color: #33363e;
}

.is-dark-mode .newsky-related-articles {
	border-top-color: #2a2d34 !important;
}

.is-dark-mode .newsky-related-thumb {
	box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4);
}

.is-dark-mode .wp-block-query-pagination-numbers .page-numbers {
	border-color: #33363e;
	color: #9aa3af;
}

/* The rule above matches ".current"/":hover" too (equal specificity, same 3
   "parts", but declared later - so it was winning and hiding both the
   current-page highlight and the hover state). Restating them explicitly
   (now 4 parts, unambiguously more specific) brings back the red "current"
   and navy ":hover" - already dark-mode-adjusted via the color variables. */
.is-dark-mode .wp-block-query-pagination-numbers .page-numbers.current {
	color: var(--wp--preset--color--primary-red);
	border-color: var(--wp--preset--color--primary-red);
}

.is-dark-mode .wp-block-query-pagination-numbers .page-numbers:hover {
	color: var(--wp--preset--color--navy);
	border-color: var(--wp--preset--color--navy);
}

.is-dark-mode .my-post-footer-credit {
	border-top-color: #2a2d34 !important;
}

.is-dark-mode .my-post-footer-copy-link,
.is-dark-mode .my-post-footer-share-toggle {
	border-color: #33363e !important;
	color: #9aa3af !important;
}

.is-dark-mode .my-post-footer-share-menu {
	background: #1f2229 !important;
	border-color: #33363e !important;
}

.is-dark-mode .my-post-footer-share-menu a {
	color: #e5e7eb !important;
}

/* Sticky header bar (see "Sticky, translucent + blurred top header" rule
   above) - it paints its own translucent white fill independently of the
   page background, so it stayed light even with the rest of the page dark. */
.is-dark-mode .wp-site-blocks > header.wp-block-template-part {
	background-color: rgba(22, 24, 29, 0.8);
}

/* Cancel WordPress's default root-level block gap so main sits flush under the sticky header */
.newsky-main-content {
	margin-top: 0 !important;
}

/* Cancel the default block gap between the video and the content section below it,
   so the section's own padding-top is the only spacing (no doubling up). */
.newsky-content-section {
	margin-top: 0 !important;
}

/* Intro video sized to the page content width, right under the sticky header: autoplay/loop, not clickable */
.newsky-intro-video {
	margin: 0;
	line-height: 0;
	pointer-events: none;
	border-radius: 12px;
	overflow: hidden;
}

.newsky-intro-video video {
	display: block;
	width: 100%;
	max-height: 70vh;
	object-fit: cover;
	border-radius: 12px;
}

/* Homepage/archive H1 (site name + tagline): needed so the page has a real
   top-level heading for SEO/accessibility, but the visual design already
   communicates this via the logo, so it's kept off-screen instead of shown. */
.newsky-sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* "Suvisiace clanky" (hedlajner-related-articles.php), appended after the
   article content: 3 cards per row, matching the homepage/archive card
   look (rounded shadowed thumbnail, red category label, navy title). */
.newsky-related-articles {
	margin-top: 2rem;
	padding-top: 1.5rem;
	border-top: 1px solid #dcdcde;
}

/* Pager-style: each arrow click replaces the 3 cards with a freshly fetched
   page from the server (no client-side scrolling track needed). */
.newsky-related-carousel {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	margin-top: 1rem;
}

.newsky-related-grid {
	display: flex;
	gap: 1.5rem;
	flex: 1 1 auto;
	min-width: 0;
}

.newsky-related-card {
	flex: 0 0 calc((100% - 2 * 1.5rem) / 3);
	min-width: 0;
}

@media (max-width: 780px) {
	.newsky-related-card {
		flex-basis: 100%;
	}
}

/* Same square "pager" look as the category/archive pagination numbers
   (.wp-block-query-pagination-numbers .page-numbers) - fixed equal
   width/height (square, not a stretched rectangle), rounded corners, gray
   border by default, navy on hover. */
.newsky-related-arrow {
	flex: 0 0 auto;
	width: 2.2rem;
	height: 2.2rem;
	padding: 0;
	border: 1px solid #dcdcde;
	border-radius: 8px;
	background: #fff;
	color: #646970;
	font-weight: 600;
	font-size: 1.2rem;
	line-height: 1;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
}

.newsky-related-arrow:hover:not(:disabled) {
	border-color: var(--wp--preset--color--navy, #162d4f);
	color: var(--wp--preset--color--navy, #162d4f);
}

.newsky-related-arrow:disabled {
	opacity: 0.35;
	cursor: default;
}

/* Fixed 16:9 box (not the image's own aspect ratio) so all 3 thumbnails
   line up at the same size regardless of the source photo's dimensions. */
.newsky-related-thumb {
	display: block;
	overflow: hidden;
	border-radius: 6px;
	aspect-ratio: 16 / 9;
	box-shadow: 0 4px 14px rgba(0, 0, 0, 0.12);
}

.newsky-related-thumb img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.newsky-related-meta {
	display: flex;
	justify-content: space-between;
	margin-top: 0.5rem;
	font-size: 0.8rem;
	font-weight: 700;
}

.newsky-related-cat {
	color: var(--wp--preset--color--primary-red, #950c16);
}

.newsky-related-date {
	color: var(--wp--preset--color--mid-gray, #6b7280);
}

/* !important: theme.json sets a sitewide h3 font-size (elements.h3) that
   otherwise wins over this class on load order alone. */
.newsky-related-title {
	margin: 0.35rem 0 0;
	font-size: 0.95rem !important;
	line-height: 1.35;
}

.newsky-related-title a {
	font-size: inherit !important;
	color: var(--wp--preset--color--navy, #162d4f);
	text-decoration: none;
}

.newsky-related-title a:hover {
	color: var(--wp--preset--color--primary-red, #950c16);
}

/* The section heading itself ("Súvisiace články", h4) - forced smaller
   regardless of the tag's own default size, so it doesn't compete with the
   article's own in-body H2 subheadings above it. */
.newsky-related-articles > .wp-block-heading {
	font-size: 1.1rem !important;
	margin: 0;
	text-align: center;
}

/* "Next page" link used by the infinite-scroll script as its fetch target;
   styled as a small neutral-gray button (also a manual fallback for
   users who click it before the auto-load triggers). */
.newsky-infinite-pagination {
	margin-top: 1.5rem;
}

.newsky-infinite-pagination .wp-block-query-pagination-next {
	display: inline-block;
	padding: 0.45rem 1.25rem;
	background-color: #e2e2e2;
	color: #555555;
	font-size: 0.8rem;
	font-weight: 600;
	border-radius: 999px;
	border: 1px solid #b0b0b0;
	text-decoration: none;
	transition: background-color 0.2s ease;
}

.newsky-infinite-pagination .wp-block-query-pagination-next:hover {
	background-color: #cfcfcf;
}

/* While a page is being fetched, hide the label and show a small spinner
   in its place instead, so the button keeps its size and position. */
.newsky-infinite-pagination .wp-block-query-pagination-next.is-loading {
	position: relative;
	color: transparent;
	pointer-events: none;
}

.newsky-infinite-pagination .wp-block-query-pagination-next.is-loading::after {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 14px;
	height: 14px;
	margin: -7px 0 0 -7px;
	border: 2px solid #cfcfcf;
	border-top-color: #555555;
	border-radius: 50%;
	animation: newsky-spin 0.6s linear infinite;
}

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