/* Festival theme overrides for Bootstrap 5.3 */
:root {
	/* contrast-checked (WCAG AA 4.5:1): white on primary/secondary,
	   secondary text and danger hints on the page background */
	--bs-primary: #c94a24;
	--bs-primary-rgb: 201, 74, 36;
	--bs-primary-text-emphasis: #a33b1c;
	--bs-primary-border-emphasis: #f09179;
	--bs-secondary: #1f756b;
	--bs-secondary-rgb: 31, 117, 107;
	--bs-secondary-text-emphasis: #175a52;
	--bs-secondary-border-emphasis: #23857a;
	--bs-secondary-color: #5e5b68;
	--bs-secondary-color-rgb: 94, 91, 104;
	--bs-danger: #b02a37;
	--bs-danger-rgb: 176, 42, 55;
	--bs-body-bg: #e8e3e3;
	--bs-body-bg-rgb: 232, 227, 227;
	--bs-body-color: #2b2a33;
	--bs-body-color-rgb: 43, 42, 51;
	--karta-transition: 0.4s cubic-bezier(0.4, 0, 0.2, 1);
	--arrow-offset: 0.6rem;
}

/* .btn-primary/.btn-secondary hardcode their colors, so point them at the
   festival palette through the component variables */
.btn-primary {
	--bs-btn-color: #fff;
	--bs-btn-bg: var(--bs-primary);
	--bs-btn-border-color: var(--bs-primary);
	--bs-btn-hover-color: #fff;
	--bs-btn-hover-bg: var(--bs-primary-text-emphasis);
	--bs-btn-hover-border-color: var(--bs-primary-text-emphasis);
	--bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
	--bs-btn-active-color: #fff;
	--bs-btn-active-bg: var(--bs-primary-text-emphasis);
	--bs-btn-active-border-color: var(--bs-primary-text-emphasis);
	--bs-btn-disabled-bg: var(--bs-primary);
	--bs-btn-disabled-border-color: var(--bs-primary);
}

.btn-secondary {
	--bs-btn-color: #fff;
	--bs-btn-bg: var(--bs-secondary);
	--bs-btn-border-color: var(--bs-secondary);
	--bs-btn-hover-color: #fff;
	--bs-btn-hover-bg: var(--bs-secondary-text-emphasis);
	--bs-btn-hover-border-color: var(--bs-secondary-text-emphasis);
	--bs-btn-focus-shadow-rgb: var(--bs-secondary-rgb);
	--bs-btn-active-color: #fff;
	--bs-btn-active-bg: var(--bs-secondary-text-emphasis);
	--bs-btn-active-border-color: var(--bs-secondary-text-emphasis);
	--bs-btn-disabled-bg: var(--bs-secondary);
	--bs-btn-disabled-border-color: var(--bs-secondary);
}

body {
	overflow: hidden;
}

/* --- dev outlines (used by base/test pages) ---------------------------- */
.out-r {
	outline: 5px solid red;
}

.out-g {
	outline: 5px solid lime;
}

.out-b {
	outline: 5px solid blue;
}

.scrollable {
	overflow-y: scroll;
	overflow-x: hidden;
}

/* ============================== KARTA ================================== */
.karta {
	position: fixed;
	inset: 0;
	/* leaves room for the terms bar while it is shown (consent.js) */
	bottom: var(--consent-bar-height, 0px);
	overflow: hidden;
	background: var(--bs-body-bg);
	/* labels, headings and hints are UI, not selectable text — a touch
	   drag that starts on a card (or misses it) must never begin
	   selecting the page's text. Typing fields re-enable it below. */
	user-select: none;
	-webkit-user-select: none;
	-webkit-touch-callout: none;
}

.karta-page {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	padding: 1.5rem clamp(1rem, 12vw, 10rem) 5rem;
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
}

.karta-page.active,
.karta-page.leaving {
	opacity: 1;
	visibility: visible;
}

.karta-page.active {
	z-index: 2;
	pointer-events: auto;
}

.karta-page.leaving {
	z-index: 1;
}

.karta-page.from-right {
	animation: page-in-right var(--karta-transition);
}

.karta-page.from-left {
	animation: page-in-left var(--karta-transition);
}

.karta-page.from-bottom {
	animation: page-in-bottom var(--karta-transition);
}

.karta-page.from-top {
	animation: page-in-top var(--karta-transition);
}

.karta-page.to-left {
	animation: page-out-left var(--karta-transition);
}

.karta-page.to-right {
	animation: page-out-right var(--karta-transition);
}

.karta-page.to-top {
	animation: page-out-top var(--karta-transition);
}

.karta-page.to-bottom {
	animation: page-out-bottom var(--karta-transition);
}

@keyframes page-in-right {
	from {
		transform: translateX(100%);
	}
}

@keyframes page-in-left {
	from {
		transform: translateX(-100%);
	}
}

@keyframes page-in-bottom {
	from {
		transform: translateY(100%);
	}
}

@keyframes page-in-top {
	from {
		transform: translateY(-100%);
	}
}

@keyframes page-out-left {
	to {
		transform: translateX(-100%);
	}
}

@keyframes page-out-right {
	to {
		transform: translateX(100%);
	}
}

@keyframes page-out-top {
	to {
		transform: translateY(-100%);
	}
}

@keyframes page-out-bottom {
	to {
		transform: translateY(100%);
	}
}

/* --- intro page ---------------------------------------------------------- */
.intro-track {
	flex: 1 1 auto;
	min-height: 0;
	transition: transform 0.7s cubic-bezier(0.65, 0, 0.35, 1);
}

.intro-track.revealed {
	transform: translateY(-100%);
}

.intro-panel {
	height: 100%;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 3rem;
}

.intro-title {
	margin: 0;
	font-size: clamp(3rem, 11vw, 6.5rem);
	line-height: 1.05;
	letter-spacing: -0.02em;
}

/* --- terms bar --------------------------------------------------------- */
.consent-bar {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 1040; /* above the karta, below Bootstrap modals (1055) */
	background: var(--bs-body-bg);
	border-top: 1px solid var(--bs-border-color);
	box-shadow: 0 -0.25rem 1rem rgba(0, 0, 0, 0.08);
}

.consent-bar-inner {
	display: flex;
	align-items: center;
	gap: 1rem 1.5rem;
	max-width: 60rem;
	margin: 0 auto;
	padding: 0.75rem 1rem;
}

.consent-bar-text {
	margin: 0;
	font-size: 0.8rem;
	color: var(--bs-secondary-color);
	max-height: 30vh;
	overflow-y: auto;
}

.consent-bar-text strong {
	display: block;
	margin-bottom: 0.2rem;
	font-size: 0.9rem;
	color: var(--bs-body-color);
}

#consent-accept {
	flex-shrink: 0;
}

@media (max-width: 575.98px) {
	.consent-bar-inner {
		flex-direction: column;
		align-items: stretch;
	}
}

.pdf-ai-note {
	max-width: 26rem;
}

.modal .podminky h2 {
	font-size: 1.15rem;
	margin: 0 0 1rem;
}

.modal .podminky h2 + h3,
.modal .podminky p + h2,
.modal .podminky ul + h2 {
	margin-top: 1.5rem;
}

.modal .podminky h3 {
	font-size: 1rem;
	margin: 1.25rem 0 0.5rem;
}

.intro-scroll {
	font-size: clamp(3.5rem, 9vw, 6rem);
	line-height: 1;
	color: var(--bs-primary);
	background: none;
	border: none;
	animation: bounce 1.4s infinite;
}

.intro-scroll:hover {
	color: var(--bs-primary-text-emphasis);
}

@keyframes bounce {
	0%,
	100% {
		transform: translateY(0);
	}

	50% {
		transform: translateY(0.35em);
	}
}

/* --- item cards (subjects + interests) ----------------------------------- */
/* interests has more items than Bootstrap's row-cols utility supports
   (it only defines 1-6; row-cols-7+ are not real classes and silently
   no-op, which is what caused an earlier collapsed-to-12px layout bug)
   -- plain grid-template-columns has no such ceiling. A FIXED column
   count per breakpoint (not auto-fill/auto-fit) is deliberate: auto-fill
   packs in more same-size columns as the viewport widens, so boxes never
   grow on bigger screens - fixed count lets each column (and so each
   square box, since .item-card is 100% of it) grow with the viewport. */
#interests-grid {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	/* slightly tighter than the row's own g-2 (0.5rem) -- reclaims a
	   few px per column. NOTE: one column fewer (4 at base) was tried and
	   reverted - even at zero container margin it made the grid tall
	   enough that the last box visually overlapped the star-zone's
	   drop-chips tray (position:absolute, outside the flex/grid budget
	   this layout otherwise fits against) on common phone sizes
	   (360x640, 390x700), not just extreme outliers. 5 columns is the
	   largest box size that is actually safe. */
	--bs-gutter-x: 0.25rem;
	/* headroom inside the scrolling container so the top row's hover lift
	   (translateY -4px) doesn't clip the info buttons at the top edge */
	padding-top: 0.4rem;
}

@media (min-width: 576px) {
	#interests-grid {
		grid-template-columns: repeat(6, 1fr);
	}
}

@media (min-width: 768px) {
	#interests-grid {
		grid-template-columns: repeat(7, 1fr);
	}
}

@media (min-width: 992px) {
	#interests-grid {
		grid-template-columns: repeat(8, 1fr);
	}
}

/* the card box itself is Bootstrap's .card + utilities; these rules only
   cover what Bootstrap has no utility for */
.karta input,
.karta textarea {
	user-select: text;
	-webkit-user-select: text;
}

.item-card {
	cursor: grab;
	user-select: none;
	/* a swipe that starts on a card scrolls the page; on touch screens a
	   drag starts only after a short hold (engine.js attachDrag) */
	touch-action: pan-y;
	-webkit-touch-callout: none;
	/* a fixed, deliberately small square -- NOT "100% of the grid column",
	   which on a 2-column mobile grid forces a huge box and pushes the
	   13-23 item grid past viewport height. box.png is a square frame,
	   so the box must square (1:1), not stretched to fit the column. */
	/* fills its grid column exactly -- the column count per breakpoint
	   (school.html/interests.html) is chosen as the minimum that keeps
	   the whole grid on-screen without scrolling, so "100% of the column"
	   is already the biggest safe square, not an independent guess */
	width: 100%;
	aspect-ratio: 1;
	margin-inline: auto;
	overflow: hidden;
	/* school's box ends up a different size than interests' (fewer items,
	   fewer columns needed -> wider column -> bigger box) -- icon/padding/
	   font below are sized in cqw (% of THIS box's own width) so they
	   scale correctly on both instead of being tuned for one fixed size */
	container-type: inline-size;
	background-color: transparent !important;
	background-image: url("../img/box.png");
	background-size: 100% 100%;
	background-repeat: no-repeat;
	box-shadow: none !important;
	transition: transform 0.2s;
}

.item-card:hover {
	transform: translateY(-4px);
}

/* icon = real image over an emoji fallback (shows while the icon is missing) */
/* school intro popup: the demo video box keeps the clip's shape and
   never overflows the dialog */
.school-intro-video-wrap {
	margin: 0 auto;
	border-radius: 0.75rem;
	overflow: hidden;
	background: #000;
	aspect-ratio: 1600 / 900;
	max-height: 55vh;
}

#school-intro-video {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}

/* "you still have an unrated smiley" message on the skills page */
.skills-missing {
	margin-top: 0.4rem;
	font-weight: 700;
	color: var(--bs-danger);
}

.skills-missing[hidden] {
	display: none;
}

/* "how many to pick" hint under a page's instruction */
.topic-hint {
	margin-top: 0.3rem;
	font-size: 0.9rem;
	font-weight: 600;
	color: var(--bs-primary);
}

.card-icon {
	position: relative;
	display: block;
	width: clamp(1.9rem, 6vw, 2.6rem); /* fallback: no container-query support */
	width: 36cqw;
	aspect-ratio: 1;
}

.card-icon::before {
	content: attr(data-emoji);
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	font-size: 70%;
}

/* once a real icon image has loaded, the emoji fallback behind it must not
   show through the image's own transparent margins -- drop it entirely
   rather than just relying on paint order (see the onload handlers that
   add this class in school.html/interests.html/engine.js) */
.card-icon.has-icon::before {
	content: none;
}

.card-icon img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: contain;
	/* the card handles the drag itself; never let the browser lift the
	   picture out with its native image drag */
	-webkit-user-drag: none;
	user-select: none;
	pointer-events: none;
}

/* the box is a fixed square now, not "as tall as the label needs" -- the
   label text must shrink with it and never push past the box's own
   height, so cap it at two lines and shrink the font in step with the
   box's own clamp() instead of Bootstrap's fixed .small size */
.item-card .card-body {
	padding: 0.3rem !important; /* fallback: no container-query support */
	padding: 5cqw !important;
	gap: 0.25rem !important; /* fallback */
	gap: 3cqw !important;
}

.item-card .card-body > span:last-child {
	font-size: clamp(0.7rem, 1.8vw, 0.85rem); /* fallback */
	font-size: 13cqw;
	line-height: 1.05;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.item-card.selected::after {
	content: "✓";
	position: absolute;
	top: 0.3rem;
	right: 0.5rem;
	width: 1.35rem;
	height: 1.35rem;
	display: grid;
	place-items: center;
	font-size: 0.8rem;
	color: #fff;
	background: var(--bs-secondary);
	border-radius: 50%;
}

/* interests: slightly bigger icons inside the same box (the box size
   is unchanged, so the grid still fits without scrolling); the label
   (max 2 lines at 13cqw) still fits below */
#interests-grid .card-icon {
	width: 56cqw;
}

/* tighter padding/gap to make room for the bigger icon */
#interests-grid .item-card .card-body {
	padding: 4cqw !important;
	gap: 1cqw !important;
}

/* interests: the "i" info button sits in the card's top-right corner,
   so the selected check moves to the top-left there */
.interest-cell {
	position: relative;
	/* lets the info button size itself to the card (cqw) */
	container-type: inline-size;
}

#interests-grid .item-card.selected::after {
	right: auto;
	left: max(0.4rem, 7cqw);
	top: max(0.35rem, 6cqw);
	width: min(1.35rem, 18cqw);
	height: min(1.35rem, 18cqw);
	font-size: min(0.8rem, 11cqw);
}

.info-btn {
	position: absolute;
	top: max(0.1rem, 2cqw);
	right: max(0.1rem, 2cqw);
	z-index: 2;
	width: min(1.35rem, 18cqw);
	aspect-ratio: 1;
	padding: 0;
	display: grid;
	place-items: center;
	border: 0;
	border-radius: 50%;
	background: var(--bs-primary);
	color: #fff;
	font: italic 700 min(0.85rem, 12cqw) / 1 Georgia, serif;
	box-shadow: 0 1px 3px rgb(0 0 0 / 0.25);
	cursor: pointer;
	transition: transform 0.2s;
}

/* follow the card's hover lift */
.interest-cell:hover .info-btn {
	transform: translateY(-4px);
}

/* invisible larger tap area for small phone cards */
.info-btn::before {
	content: "";
	position: absolute;
	inset: -0.4rem;
}

.info-btn:hover {
	filter: brightness(1.1);
}

.info-btn:focus-visible {
	outline: 2px solid var(--bs-primary);
	outline-offset: 2px;
}

/* touch: the hold that arms a drag lifts the card a little */
.item-card.drag-armed {
	transform: scale(1.06);
	transition: transform 0.15s ease-out;
}

.item-card.dragging {
	opacity: 0.35;
}

.drag-ghost {
	position: fixed;
	z-index: 1080;
	margin: 0;
	pointer-events: none;
	transform: translate(-50%, -50%) scale(1.08);
	opacity: 0.95;
}

/* --- drop zones (bag / star) --------------------------------------------- */
/* the zone is exactly as wide as its target, and the chips are positioned
   outside the flow — so the icon never moves as selections accumulate */
.drop-zone {
	position: absolute;
	z-index: 10;
	bottom: 0.6rem;
	right: 0.6rem;
}

/* the backpack pulses (see .bag-zone .drop-target's animation below) -
   scale() grows it in every direction from its own center, and the
   shared 0.6rem edge offset above didn't leave enough room on real
   devices (OS gesture bars/home indicators overlap that corner without
   showing up in a plain viewport-size check). Lifted well clear of it;
   .drop-chips is positioned bottom:0 *relative to this zone*, not the
   viewport, so it rides up along with the backpack automatically. */
.bag-zone {
	bottom: 2.5rem;
	right: 1.5rem;
}

@media (min-width: 992px) {
	/* both drop targets sit at the top-right corner; the bottom-right
	   corner is left for the green next-page arrow */
	.star-zone {
		top: 0.6rem;
		bottom: auto;
	}

	.bag-zone {
		top: 1.5rem;
		bottom: auto;
	}

	/* the school grid is wider (6 columns) than the interests grid, so
	   on desktop its top row would sit under the top-right backpack and
	   its hint — push the grid down into the empty space below it */
	#page-school > .container {
		margin-top: 6rem !important;
		margin-bottom: auto !important;
	}
}

/* chips hang off the zone: above the bag, below the star (top corner) */
.drop-chips {
	position: absolute;
	right: 0;
	bottom: 100%;
	margin-bottom: 0.5rem;
	display: flex;
  flex-direction: row-reverse;
	flex-wrap: wrap;
	justify-content: flex-start;
  align-items: flex-start;
	background-color: #dddad4;
	box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.5);
	margin-right: 0.5rem;
	bottom: 0;
	right: 100%;
	height: calc(min(150%, 6.5rem));
	width: 75vw;
}

@media (min-width: 992px) {
	.bag-zone .drop-chips,
	.star-zone .drop-chips {
		bottom: auto;
		right: 0;
		top: 100%;
		margin-top: 0.5rem;
		margin-right: 0;
		height: 70vh;
		width: 100%;
	}
}

.drop-chips .chip {
	font-size: 2rem;
	padding: 0.25rem;
	border: 0;
	border-radius: 0.5rem;
	background: var(--bs-body-bg);
	box-shadow: var(--bs-box-shadow-sm);
	cursor: pointer;
	line-height: 0;
}

.drop-chips .card-icon {
	width: 2rem;
}

.drop-target {
	position: relative;
	width: clamp(4.5rem, 10vw, 6.5rem);
	aspect-ratio: 1;
	background: var(--bs-body-bg);
	transition:
		transform var(--karta-transition),
		background-color var(--karta-transition);
}

.drop-target .card-icon {
	position: absolute;
	inset: 15%;
	width: auto;
	height: auto;
}

.drop-target .card-icon::before {
	font-size: clamp(2rem, 4vw, 2.6rem);
}

.drop-count {
	position: absolute;
	bottom: 0;
	right: 0;
	transform: translate(25%, 25%);
}

/* backpack only (not the star): bigger than the base drop-target, plus a
   slow continuous pulse - unlike the next arrow's idle-triggered hop,
   there's no natural "idle" moment for a drag target, so this just runs
   the whole time the page is open to say "drag subjects here". Paused
   on hover so the drop-hover scale below reads cleanly instead of
   fighting the pulse. */
.bag-zone .drop-target {
	width: clamp(5.5rem, 13vw, 8rem);
	animation: bag-pulse 2.6s ease-in-out infinite;
}

@keyframes bag-pulse {
	0%,
	100% {
		transform: scale(1);
	}

	50% {
		transform: scale(1.08);
	}
}

.drop-zone.drop-hover .drop-target {
	transform: scale(1.15);
	background: #fff3ec;
	animation-play-state: paused;
}

.drop-zone.drop-flash .drop-target {
	animation: drop-flash 0.45s;
}

/* hand-drawn arrows pointing at each page's drop target — decorative,
   siblings of .drop-zone (not nested in it), positioned in the same
   .karta-page-relative coordinate space; never intercept clicks meant
   for the target underneath */
.drop-point-arrow {
	position: absolute;
	z-index: 11;
	width: clamp(3rem, 8vw, 5rem);
	height: auto;
	pointer-events: none;
	user-select: none;
}

.bag-arrow {
	/* .bag-zone moved by (2.5rem - 0.6rem) up and (1.5rem - 0.6rem)
	   left; shift the arrow pointing at it by the same amounts so the
	   gap between them stays the same */
	bottom: 7.9rem;
	right: 6.4rem;
}

.star-arrow {
	bottom: 6rem;
	right: 5.5rem;
}

@media (min-width: 992px) {
	.star-arrow {
		top: 6rem;
		bottom: auto;
		right: 5.5rem;
	}

	/* arrow3 points down by default; at the top-corner backpack it must
	   point up, so flip it vertically */
	.bag-arrow {
		top: 7.5rem;
		bottom: auto;
		right: 6.4rem;
		transform: scaleY(-1);
	}
}

/* short instruction to the left of each drop page's arrow */
.drop-hint {
	position: absolute;
	z-index: 11;
	max-width: min(14rem, 40vw);
	margin: 0;
	font-size: clamp(0.9rem, 1.4vw, 1.1rem);
	font-weight: 600;
	line-height: 1.25;
	text-align: right;
	text-wrap: balance;
	color: var(--bs-primary-text-emphasis);
	pointer-events: none;
	user-select: none;
}

/* star: bottom corner on small screens, top corner from lg up */
.star-hint {
	bottom: 7rem;
	right: calc(5.5rem + clamp(3rem, 8vw, 5rem) + 0.25rem);
}

@media (min-width: 992px) {
	.star-hint {
		top: 8rem;
		bottom: auto;
	}

	.bag-hint {
		top: 9.5rem;
		bottom: auto;
		right: calc(6.4rem + clamp(3rem, 8vw, 5rem) + 0.25rem);
	}
}

/* bag: always the bottom corner, beside its arrow */
.bag-hint {
	bottom: 10.5rem;
	right: calc(6.4rem + clamp(3rem, 8vw, 5rem) + 0.25rem);
}

/* the faded "you can drag here" demo card (dragDemo() in engine.js) */
.drag-demo {
	position: fixed;
	z-index: 1070;
	margin: 0;
	pointer-events: none;
	opacity: 0;
}

/* --- decorative faces + question marks (school / interests pages) -------- */
/* same "scattered, aria-hidden, non-interactive" pattern as .hint-emoji,
   just paired with a small question-mark badge; capped at 3 per page and
   placed away from the corners the logo/nav-arrows/drop-target already own */
.hint-face-group {
	position: absolute;
	opacity: 0.4;
	pointer-events: none;
	user-select: none;
}

.hint-face-group .hint-face {
	display: block;
	width: clamp(2.5rem, 7vw, 4rem);
	height: auto;
}

.hint-face-group .hint-face-q {
	position: absolute;
	top: -0.5rem;
	right: -0.7rem;
	width: clamp(1rem, 3vw, 1.5rem);
	height: auto;
}

.hint-face-group:nth-child(1) {
	top: 36%;
	left: 4%;
	transform: rotate(-9deg);
}

.hint-face-group:nth-child(2) {
	bottom: 9%;
	left: 6%;
	transform: rotate(8deg) scale(0.9);
}

.hint-face-group:nth-child(3) {
	top: 44%;
	right: 4%;
	transform: rotate(6deg) scale(1.1);
}

@media (min-width: 992px) {
	/* on large screens the bag/star drop-chips tray becomes a fixed
	   ~6.5rem-wide column pinned to the right edge, so the %-based
	   offset above would drift right under it - switch to a rem offset
	   that clears the column instead */
	.hint-face-group:nth-child(3) {
		right: 9rem;
	}
}

@keyframes drop-flash {
	0% {
		transform: scale(1);
	}

	40% {
		transform: scale(1.3);
	}

	100% {
		transform: scale(1);
	}
}

/* --- skills page (faces carousel) ------------------------------------------ */
/* the face IS the emoji glyph — the gray state is a filter + opacity, so the
   same glyph never shifts between the unselected and selected states
   (research §6) */
.face-btn {
	background: none;
	border: none;
	padding: 0;
	width: clamp(2.1rem, 3vw + 1.5rem, 3rem);
	aspect-ratio: 1;
	cursor: pointer;
	user-select: none;
	touch-action: manipulation;
	-webkit-tap-highlight-color: transparent;
	filter: grayscale(1);
	opacity: 0.5;
	transition:
		filter var(--karta-transition),
		opacity var(--karta-transition),
		transform var(--karta-transition);
}

.face-btn img {
	width: 100%;
	height: 100%;
	object-fit: contain;
}

.face-btn.selected {
	filter: none;
	opacity: 1;
	transform: scale(1.15);
}

/* the slides are absolutely positioned, so the carousel has no intrinsic
   height — let it fill the page's remaining space and center each slide's
   rows, so the one-row last slide matches the five-row slides */
#skills-carousel {
	display: flex;
	flex-flow: row wrap;
	justify-content: center;
	flex: 1 1 auto;
	min-height: 0;
}

/* small phones: the rows scroll — while more is hidden below, fade the
   carousel's bottom edge and offer a "more questions" pill
   (pages/skills.js). The page's bottom padding (5rem) is where the
   carousel ends. */
.skills-more-wrap {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 5rem;
	height: 3.5rem;
	display: flex;
	align-items: flex-end;
	justify-content: center;
	background: linear-gradient(to bottom, transparent, var(--bs-body-bg) 85%);
	pointer-events: none;
	z-index: 2;
}

.skills-more-wrap[hidden] {
	display: none;
}

.skills-more {
	pointer-events: auto;
	padding: 0.35rem 0.9rem;
	border: none;
	border-radius: 999px;
	background: var(--bs-body-bg);
	color: var(--bs-primary);
	font-weight: 600;
	font-size: 0.9rem;
	box-shadow: 0 0.2rem 0.8rem rgba(0, 0, 0, 0.15);
	animation: bounce 1.4s infinite;
}

/* scroll slider: a visible, draggable scrollbar beside a page's scrolling
   area (phones hide native scrollbars); built and positioned by
   static/js/karta/scrollbar.js */
.karta-scrollbar {
	position: absolute;
	width: 0.5rem;
	border-radius: 999px;
	background: rgba(0, 0, 0, 0.08);
	z-index: 2;
	touch-action: none;
	cursor: pointer;
}

.karta-scrollbar[hidden] {
	display: none;
}

/* a wider invisible hit area so a finger can grab the thin bar */
.karta-scrollbar::before {
	content: "";
	position: absolute;
	inset: 0 -0.75rem;
}

.karta-scrollbar-thumb {
	position: absolute;
	left: 0;
	right: 0;
	border-radius: 999px;
	background: var(--bs-primary);
	min-height: 2rem;
}

/* an unanswered question, flagged red until it is rated (skills.js) */
.skill-row.unrated {
	border-radius: 0.75rem;
	background: rgba(214, 69, 69, 0.12);
	box-shadow: inset 0 0 0 2px rgba(214, 69, 69, 0.55);
}

/* a skipped question the page scrolled back to */
.skill-row.needs-rating {
	border-radius: 0.75rem;
	animation: needs-rating 1.6s ease-out;
}

@keyframes needs-rating {
	0%,
	60% {
		background: rgba(var(--bs-primary-rgb), 0.14);
	}
	100% {
		background: transparent;
	}
}

#skills-carousel .carousel-controls {
	display: flex;
	width: 50%;
	justify-content: space-around;
	position: fixed;
	bottom: 0.6rem;
}

#skills-carousel .carousel-controls button {
	width: 3rem;
	height: 3rem;
	z-index: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
}

/* --- free-text pages (hobby / dreams) --------------------------------------- */
/* decorative hint emojis: scattered around the page edges (never the center,
   where the input sits), legible but clearly behind the content, and
   non-interactive (pointer-events off — FR-026). Percentage offsets + a
   vw-clamped size keep every glyph inside the box at 320px (Constitution IV) */
.hint-emoji {
	position: absolute;
	width: clamp(2.5rem, 7vw, 4.5rem);
	height: auto;
	opacity: 0.45;
	pointer-events: none;
	user-select: none;
}

.hint-emoji:nth-child(1) {
	top: 18%;
	left: 10%;
	transform: rotate(-12deg) scale(0.85);
}

.hint-emoji:nth-child(2) {
	top: 24%;
	right: 9%;
	transform: rotate(9deg) scale(1.2);
}

.hint-emoji:nth-child(3) {
	bottom: 20%;
	left: 13%;
	transform: rotate(7deg) scale(1.05);
}

.hint-emoji:nth-child(4) {
	bottom: 16%;
	right: 11%;
	transform: rotate(-10deg) scale(0.75);
}

.hint-emoji:nth-child(5) {
	top: 48%;
	left: 6%;
	transform: rotate(-5deg) scale(1.35);
}

.hint-emoji:nth-child(6) {
	top: 40%;
	right: 7%;
	transform: rotate(13deg) scale(0.95);
}

/* the free-text pill: cap its width so it doesn't stretch edge-to-edge on
   wide screens, and lift it above the scattered hint emojis (the emojis are
   position:absolute and would otherwise paint over the field). Bootstrap's
   .form-control fills with var(--bs-body-bg) and borders with
   var(--bs-border-color) - both were barely distinguishable from the page
   background once --bs-body-bg changed to a similarly light gray, so the
   field's own boundary needs an explicit background/border here instead
   of inheriting the (now near-invisible) defaults. */
.karta-page input.form-control,
#interest-modal input.form-control {
	position: relative;
	z-index: 1;
	max-width: min(24rem, 100%);
	background-color: #fff;
	border-color: rgba(43, 42, 51, 0.35);
	box-shadow: 0 1px 4px rgba(43, 42, 51, 0.12);
}

.karta-page input.form-control:focus,
#interest-modal input.form-control:focus {
	background-color: #fff;
	border-color: var(--bs-primary);
}

/* --- navigation arrows ----------------------------------------------------- */
/* fixed width/height + flex centering (not aspect-ratio + padding around the
   glyph) so the circle stays a circle on every device — shrink-to-fit sizing
   around a bare "→"/"←" character varies with the glyph's advance width in
   whatever font the OS/browser substitutes, which can render it as a narrow
   oval instead of a circle */
.next-arrow {
	position: absolute;
	z-index: 10;
	bottom: var(--arrow-offset);
	right: var(--arrow-offset);
	width: 5.2rem;
	height: 5.2rem;
	display: flex;
	align-items: center;
	justify-content: center;
	background: none;
	border: none;
	padding: 0;
	opacity: 0;
	transform: scale(0.5);
	pointer-events: none;
	/* hidden = also out of the tab order (opacity alone keeps it focusable) */
	visibility: hidden;
	transition:
		opacity var(--karta-transition),
		transform var(--karta-transition),
		visibility var(--karta-transition);
}

.next-arrow img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.25));
}

.next-arrow.visible {
	opacity: 1;
	transform: scale(1);
	pointer-events: auto;
	visibility: visible;
}

/* idle nudge: if the visitor sits on a page without acting, engine.js
   (see scheduleAttention) adds this class after a delay so the arrow
   hops to catch the eye - a friendly "look here", not an error/warning
   shake. Removed again on animationend, then rescheduled if still idle
   (see wireNextArrowAttention), so it repeats every few seconds rather
   than nagging continuously.

   Two variants, same shape, different amplitude: most pages anchor the
   arrow at the BOTTOM, with the whole page height above it, so the hop
   can be big. school/interests anchor it at the TOP with only
   --arrow-offset (0.6rem) of headroom before .karta's overflow:hidden
   clips it - 0.6rem / 5.2rem size =~ 11.5%, so that variant stays well
   under that regardless of arrow size. */
@keyframes next-arrow-attention {
	0%,
	100% {
		transform: scale(1) translateY(0);
	}

	18% {
		transform: scale(1.18) translateY(-42%);
	}
	32% {
		transform: scale(1) translateY(0);
	}
	50% {
		transform: scale(1.1) translateY(-22%);
	}
	64% {
		transform: scale(1) translateY(0);
	}
}

@keyframes next-arrow-attention-safe {
	0%,
	100% {
		transform: scale(1) translateY(0);
	}

	/* scale() also expands the box upward from its own center, so the
	   budget here is translateY% PLUS half of scale's growth, not
	   translateY alone - e.g. scale(1.08) + translateY(-9%) effectively
	   reaches ~13% upward (4% from the scale half + 9% translate), which
	   clipped by ~2px in testing despite looking under the ~11.5% ceiling
	   at a glance. */
	20% {
		transform: scale(1.04) translateY(-7%);
	}
	35% {
		transform: scale(1) translateY(0);
	}
	50% {
		transform: scale(1.02) translateY(-3%);
	}
	65% {
		transform: scale(1) translateY(0);
	}
}

/* loops while the pupil is idle on the page, so the way forward keeps
   drawing the eye until they tap it (engine removes .attention on any
   interaction) */
.next-arrow.attention {
	animation: next-arrow-attention 1.1s ease-in-out infinite;
}

.karta[data-page="school"] .next-arrow.attention,
.karta[data-page="interests"] .next-arrow.attention {
	animation-name: next-arrow-attention-safe;
}

/* both drop targets park in a corner, so the next-page arrow takes the
   opposite one. On phones/tablets the targets are bottom-right, so the
   arrow is top-right; from lg up both targets move to the top-right, so
   the arrow drops to the bottom-right. */
.karta[data-page="school"] #next-arrow,
.karta[data-page="interests"] #next-arrow {
	top: var(--arrow-offset);
	bottom: auto;
}

@media (min-width: 992px) {
	.karta[data-page="school"] #next-arrow,
	.karta[data-page="interests"] #next-arrow {
		top: auto;
		bottom: var(--arrow-offset);
	}
}

/* brand mark, fixed top-left on every page; the back arrow parks below it
   so the two never overlap. Also a "go to start" button (engine.js). */
.top-left-logo {
	position: absolute;
	z-index: 5;
	top: 0.5rem;
	left: 0.5rem;
	height: clamp(3rem, 8vw, 4.25rem);
	background: none;
	border: none;
	padding: 0;
	cursor: pointer;
	user-select: none;
}

.top-left-logo img {
	height: 100%;
	width: auto;
	display: block;
}

.back-arrow {
	position: absolute;
	z-index: 10;
	/* parks below the logo - keep this calc's clamp() in sync with
	   .top-left-logo's height above so the two never overlap */
	top: calc(0.5rem + clamp(3rem, 8vw, 4.25rem) + 0.4rem);
	left: var(--arrow-offset);
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	font-size: 1rem;
	font-weight: 600;
	line-height: 1;
	padding: 0.45rem 0.9rem;
	opacity: 0;
	pointer-events: none;
	visibility: hidden;
	transition:
		opacity var(--karta-transition),
		visibility var(--karta-transition);
}

.back-arrow.visible {
	opacity: 1;
	pointer-events: auto;
	visibility: visible;
}

/* --- modal ------------------------------------------------------------------- */
#interest-modal .card-icon,
#school-modal .card-icon {
	width: 4.5rem;
	margin: 0 auto 0.75rem;
}

#interest-modal input.form-control,
#school-modal input.form-control {
	max-width: 100%;
	font-size: 1.1rem;
	padding: 0.6rem 0.9rem;
}

/* free-text pages: the same rectangular field as the "jiné" modal */
.karta-page input.form-control {
	max-width: min(28rem, 100%);
	font-size: 1.1rem;
	padding: 0.6rem 0.9rem;
}

#school-modal .form-label,
#interest-modal .form-label {
	color: var(--bs-emphasis-color);
	font-size: 1.05rem;
}

#interest-modal .card-icon::before,
#school-modal .card-icon::before {
	font-size: 3rem;
}

/* shared confirm-only gate popup (skills advice):
   rounded dialog with a pop-in on show — Bootstrap's fade covers the
   backdrop, this keyframe animates the dialog itself (research §7) */
#gate-popup .modal-content {
	border-radius: 1.75rem;
}

@keyframes gate-pop {
	from {
		transform: scale(0.85);
	}
}

#gate-popup.show .modal-dialog {
	animation: gate-pop var(--karta-transition);
}

/* --- school page intro popup (pages/school-intro.js) ------------------- */
#school-intro-popup .modal-content {
	border-radius: 1.75rem;
}

#school-intro-popup.show .modal-dialog {
	animation: gate-pop var(--karta-transition);
}

.school-intro-video-wrap {
	border-radius: 1rem;
	overflow: hidden;
	background: #f4f4f4;
	box-shadow: 0 0.25rem 1rem rgba(0, 0, 0, 0.12);
}

.school-intro-video-wrap video {
	display: block;
	width: 100%;
	height: auto;
	max-height: 55vh;
	object-fit: contain;
}

#school-intro-confirm {
	font-weight: 700;
	font-size: 1.15rem;
	padding: 0.75rem;
}


/* --- done page: the PDF download is the main action -------------------- */
.pdf-download {
	display: inline-flex;
	align-items: center;
	gap: 0.6rem;
	padding: 0.9rem 2.2rem;
	font-size: 1.35rem;
	font-weight: 700;
	transition: transform 0.2s, box-shadow 0.2s;
}

/* "Stahování..." while the PDF is being built: the dots get a fixed
   width so the label doesn't shift as they grow (pages/done.js) */
.pdf-download .loading-dots {
	display: inline-block;
	width: 1.4em;
	text-align: left;
}

.pdf-download:disabled {
	opacity: 0.85;
}

.pdf-download:hover:not(:disabled) {
	transform: translateY(-2px) scale(1.03);
}

.reset-link {
	font-size: 1rem;
	text-decoration: underline;
	opacity: 0.8;
}

.reset-link:hover {
	opacity: 1;
}

/* --- keyboard focus ------------------------------------------------------ */
/* one clear ring for every custom-styled control; :focus-visible keeps it
   off mouse/touch clicks and shows it only for keyboard navigation */
.item-card:focus-visible,
.face-btn:focus-visible,
.chip:focus-visible,
.next-arrow:focus-visible,
.back-arrow:focus-visible,
.top-left-logo:focus-visible,
.intro-scroll:focus-visible,
.carousel-controls .btn:focus-visible {
	outline: 3px solid var(--bs-primary);
	outline-offset: 2px;
	border-radius: 0.75rem;
}

/* the cards sit in a scroll container that would clip an outer ring */
.item-card:focus-visible {
	outline-offset: -5px;
	border-radius: 1rem;
}

/* ring only - colouring the face would make it look already selected */
.face-btn:focus-visible {
	border-radius: 50%;
}

/* headings receive focus programmatically on page change - no ring */
.karta-page [tabindex="-1"]:focus {
	outline: none;
}

/* ============================== PHONES & TABLETS ===========================
   Below lg the star and the bag both sit in the bottom-right corner. The
   bottom strip is laid out as one unit: target in the corner, the chosen-
   icons tray filling the rest of the row to its left (never off-screen),
   and the hint text + arrow just above the tray, pointing down at the
   target. The page reserves that strip (padding-bottom) so the card grid
   ends above it and scrolls inside its own container instead of sliding
   underneath. */
@media (max-width: 991.98px) {
	.star-zone {
		--zone-right: 0.6rem;
	}

	.bag-zone {
		--zone-right: 1.5rem;
	}

	/* tray: same bottom line as the target, from the left gutter to the
	   target (100% = the zone, i.e. the target's width) */
	.drop-chips {
		right: 100%;
		bottom: 0;
		margin-right: 0.5rem;
		height: 5.5rem;
		width: calc(100vw - 100% - var(--zone-right) - 0.5rem - 0.75rem);
	}

	/* arrows: a fixed size, sitting on top of the tray's right end */
	.drop-point-arrow {
		width: 3rem;
	}

	.bag-arrow {
		bottom: 7.9rem;
		right: 6.4rem;
	}

	/* arrow2 points up-right (at the desktop star in the top corner);
	   mirrored it points down-right, at the star below */
	.star-arrow {
		bottom: 6.3rem;
		right: 3.5rem;
		transform: scaleY(-1);
	}

	.star-hint {
		bottom: 7.5rem;
		right: calc(3.5rem + 3rem + 0.25rem);
	}

	.bag-hint {
		bottom: 9.4rem;
		right: calc(6.4rem + 3rem + 0.25rem);
	}

	/* keep the grid clear of the strip: star tray top 6.1rem, bag tray top
	   8rem, plus the two-line hint above each */
	#page-interests {
		padding-bottom: 10.5rem;
	}

	#page-school {
		padding-bottom: 12.5rem;
	}

	#page-interests > .container,
	#page-school > .container {
		min-height: 0;
		margin-block: 1rem !important;
	}

	/* the decorative faces would land on the cards or behind the tray */
	.hint-face-group {
		display: none;
	}

	/* interests: 4 columns so the boxes (and the cqw-sized icon and label
	   inside them) stay readable */
	#interests-grid {
		grid-template-columns: repeat(4, 1fr);
	}
}

/* tablets (portrait): the desktop side margins (12vw) waste a lot of a
   tablet's width, and the screen is tall enough for fewer, bigger boxes:
   school 13 items in 5 columns (3 rows), interests 21 in 5 (6 from 768px) */
@media (min-width: 576px) and (max-width: 991.98px) {
	.karta-page {
		padding-inline: 2rem;
	}

	#interests-grid {
		grid-template-columns: repeat(5, 1fr);
		--bs-gutter-x: 0.75rem;
		--bs-gutter-y: 0.75rem;
	}

	/* bigger chips in the tray to match the bigger boxes */
	.drop-chips .chip {
		font-size: 2.75rem;
	}

	.drop-chips .card-icon {
		width: 2.75rem;
	}

	.drop-chips {
		height: 6.5rem;
	}

	/* arrows and hints ride above the taller tray (star tray top 7.1rem,
	   bag tray top 9rem) */
	.drop-point-arrow {
		width: 3.5rem;
	}

	.star-arrow {
		bottom: 7.3rem;
	}

	.bag-arrow {
		bottom: 9.1rem;
	}

	.star-hint {
		bottom: 8.6rem;
		right: calc(3.5rem + 3.5rem + 0.25rem);
	}

	.bag-hint {
		bottom: 10.4rem;
		right: calc(6.4rem + 3.5rem + 0.25rem);
	}

	#page-interests {
		padding-bottom: 12rem;
	}

	#page-school {
		padding-bottom: 14rem;
	}
}

/* wider tablets: 21 interest cards fit in 4 rows of 6 */
@media (min-width: 768px) and (max-width: 991.98px) {
	#interests-grid {
		grid-template-columns: repeat(6, 1fr);
	}
}

/* box corners: the clip must scale with the box, a fixed 1rem radius
   bites into the frame drawn in box.png on small boxes */
.item-card {
	border-radius: 12% !important;
}

@media (max-width: 575.98px) {
	/* phones: narrow side margins buy noticeably bigger boxes */
	.karta-page {
		padding-inline: 0.75rem;
	}

	/* keep page headings clear of the round back button (top-left) */
	.karta-page > header {
		padding-inline: 3.25rem;
	}
}
