/*
Theme Name: JatekZseb
Theme URI:  https://gitlab.com/stas.karm/ai-wordpress-website-generator
Description: Starter theme for AI Theme Builder plugin.
Version:     1.0.0
Requires at least: 6.0
Requires PHP:      8.0
Author:      Stanislav Perepelytsia
License:     GPL v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: atb-jatekzseb-a0e3
*/

/* ═══════════════════════════════════════════════════════════════
   BASELINE + TOKEN BRIDGE.

   Two jobs, and only two:

   1. Make an unstyled site readable. The design lives in
      assets/css/main.css, written per site by the generator
      against the same class hooks.

   2. Carry the authored palette into Bootstrap's chrome. The
      design declares eight custom properties; everything the
      navbar, pagination, breadcrumb, buttons and form controls
      need is derived from them below, so the authored stylesheet
      never has to know a --bs-* name exists.

   Rule for editing this file: if a declaration expresses taste
   rather than legibility, it belongs in the authored stylesheet,
   not here. Every width, grid, colour scheme and spacing rhythm
   asserted here about a SECTION is one the design then has to
   override. Chrome is the exception — it is Bootstrap's, and the
   design only skins it.
   ═══════════════════════════════════════════════════════════════ */

/* ── The token contract ─────────────────────────────────────────
   These eight names are the entire interface between the authored
   stylesheet and the theme. The design overrides them in :root;
   the values here are the fallback that keeps an ungenerated site
   from looking broken.
   ─────────────────────────────────────────────────────────────── */

:root {
	--atb-color-primary: #16161a;
	--atb-color-secondary: #4a4a55;
	--atb-color-accent: #4a4a55;
	--atb-color-background: #121212;
	--atb-color-surface: #1e1e1e;
	--atb-color-text: #eeeeee;
	--atb-color-text-muted: #aaaaaa;
	--atb-color-border: #333333;
	--atb-color-success: #2e7d32;
	--atb-color-warning: #f57c00;
	--atb-color-error: #c62828;
	--atb-font-heading: "Manrope", system-ui, sans-serif;
	--atb-font-body: "Manrope", system-ui, sans-serif;
	--atb-font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
	--atb-size-base: 1rem;
	--atb-leading: 1.6;
	--atb-space-xs: 0.25rem;
	--atb-space-sm: 0.5rem;
	--atb-space-md: 1rem;
	--atb-space-lg: 1.5rem;
	--atb-space-xl: 2rem;
	--atb-space-2xl: 3rem;
	--atb-width-max: 1140px;
	--atb-width-content: 760px;
	--atb-width-sidebar: 300px;
	--atb-gutter: 1.5rem;
	--atb-measure: 72ch;
	--atb-radius-sm: 4px;
	--atb-radius-md: 8px;
	--atb-radius-lg: 16px;
	--atb-radius-full: 9999px;
	--atb-shadow-sm: 0 1px 3px rgba(0,0,0,.08);
	--atb-shadow-md: 0 4px 12px rgba(0,0,0,.10);
	--atb-shadow-lg: 0 8px 24px rgba(0,0,0,.12);
	--atb-duration-fast: 150ms;
	--atb-duration-normal: 250ms;
	--atb-duration-slow: 400ms;
	--atb-easing: cubic-bezier(.4,0,.2,1);
	--bs-primary: #16161a;
	--bs-secondary: #4a4a55;
	--bs-body-bg: #121212;
	--bs-body-color: #eeeeee;
	--bs-border-color: #333333;
	--bs-border-radius: 8px;
	--bs-font-sans-serif: "Manrope", system-ui, sans-serif;
	--bs-body-font-family: "Manrope", system-ui, sans-serif;
	--bs-link-color: #16161a;
	--bs-link-hover-color: #4a4a55;
}

/* ── Bootstrap bridge: globals ──────────────────────────────────
   Only the variables Bootstrap genuinely reads from :root. The
   component-scoped ones follow further down, and they have to:
   Bootstrap declares --bs-navbar-*, --bs-btn-* and friends ON the
   component, so a :root value for them is simply never consulted.
   This is the single most common way a Bootstrap theme ends up
   with a correctly coloured page and a default-blue navbar.
   ─────────────────────────────────────────────────────────────── */

:root {
	--atb-color-primary: #16161a;
	--atb-color-secondary: #4a4a55;
	--atb-color-accent: #4a4a55;
	--atb-color-background: #121212;
	--atb-color-surface: #1e1e1e;
	--atb-color-text: #eeeeee;
	--atb-color-text-muted: #aaaaaa;
	--atb-color-border: #333333;
	--atb-color-success: #2e7d32;
	--atb-color-warning: #f57c00;
	--atb-color-error: #c62828;
	--atb-font-heading: "Manrope", system-ui, sans-serif;
	--atb-font-body: "Manrope", system-ui, sans-serif;
	--atb-font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
	--atb-size-base: 1rem;
	--atb-leading: 1.6;
	--atb-space-xs: 0.25rem;
	--atb-space-sm: 0.5rem;
	--atb-space-md: 1rem;
	--atb-space-lg: 1.5rem;
	--atb-space-xl: 2rem;
	--atb-space-2xl: 3rem;
	--atb-width-max: 1140px;
	--atb-width-content: 760px;
	--atb-width-sidebar: 300px;
	--atb-gutter: 1.5rem;
	--atb-measure: 72ch;
	--atb-radius-sm: 4px;
	--atb-radius-md: 8px;
	--atb-radius-lg: 16px;
	--atb-radius-full: 9999px;
	--atb-shadow-sm: 0 1px 3px rgba(0,0,0,.08);
	--atb-shadow-md: 0 4px 12px rgba(0,0,0,.10);
	--atb-shadow-lg: 0 8px 24px rgba(0,0,0,.12);
	--atb-duration-fast: 150ms;
	--atb-duration-normal: 250ms;
	--atb-duration-slow: 400ms;
	--atb-easing: cubic-bezier(.4,0,.2,1);
	--bs-primary: #16161a;
	--bs-secondary: #4a4a55;
	--bs-body-bg: #121212;
	--bs-body-color: #eeeeee;
	--bs-border-color: #333333;
	--bs-border-radius: 8px;
	--bs-font-sans-serif: "Manrope", system-ui, sans-serif;
	--bs-body-font-family: "Manrope", system-ui, sans-serif;
	--bs-link-color: #16161a;
	--bs-link-hover-color: #4a4a55;
}

/* ── Reset ──────────────────────────────────────────────────── */

*,
*::before,
*::after {
	box-sizing: border-box;
}

body,
h1, h2, h3, h4,
p, figure, blockquote, dl, dd, ol, ul {
	margin: 0;
	padding: 0;
}

/* Scoped rather than global. v1 stripped list markers from every ul and ol
   on the site, which also stripped them from generated article bodies, where
   a bulleted list is meant to look like one. Only the theme's own structural
   lists lose their markers, and they are named rather than matched by a
   pattern so that adding a section type is a deliberate edit here. */
.site-nav__list,
.site-footer__list,
.post-list,
.s-offering__list,
.s-steps__list,
.s-stats__list,
.s-gallery__list,
.s-testimonials__list,
.s-pricing__list,
.s-checklist__list,
.s-timeline__list,
.s-team__list,
.s-clients__list,
.s-cards__list,
.s-documents__list,
.s-lettering__words,
.s-panorama__words,
.s-fragments__parts {
	list-style: none;
}

/* ── Legibility defaults ────────────────────────────────────── */

html {
	-webkit-text-size-adjust: 100%;
}

body {
	font-family: var(--atb-font-body);
	line-height: 1.6;
	color: var(--atb-color-text);
	background: var(--atb-color-background);
	/* Authored stylesheets are encouraged to break elements out of the
	   flow; clip rather than scroll keeps that from producing a
	   horizontal scrollbar on a phone. */
	overflow-x: clip;
}

h1, h2, h3, h4 {
	font-family: var(--atb-font-heading);
	line-height: 1.15;
	text-wrap: balance;
}

/* A word longer than its column wraps instead of widening the column.
   An email address, a URL or a store package id ("com.studio.game") is one
   unbreakable word, and authored sheets lay sections out as grids of `1fr`,
   whose minimum is the longest word inside. An audited site had one such
   word in a heading and the whole section — title, cards, text — grew to
   760px on a 390px phone, the right half cut off by the overflow-x: clip
   above. `anywhere` (not `break-word`) is the one that also lowers that
   minimum, so the column keeps its width and only the long word breaks.
   Inherited, so every span and link inside picks it up. */
.site-main,
.site-footer {
	overflow-wrap: anywhere;
}

/* Long words in narrow columns — four steps side by side, a card title —
   break at a syllable with a hyphen rather than at an arbitrary letter.
   The limit keeps short words whole. Needs the page's lang, which
   language_attributes() writes. */
:where(h1, h2, h3, h4) {
	hyphens: auto;
	hyphenate-limit-chars: 10 4 4;
}

/* The same failure from the grid's side: a grid item's automatic minimum
   is its content, so anything that cannot shrink (a nowrap button, a wide
   table) still widens the whole section. Zero lets the track stay at the
   width it was given. :where(), so a design that needs a minimum states it. */
:where(.s) > * {
	min-inline-size: 0;
}

p {
	text-wrap: pretty;
}

a {
	color: inherit;
}

img,
picture,
svg,
video {
	display: block;
	max-width: 100%;
	height: auto;
}

/* Bare buttons only. .btn beats this on specificity, so Bootstrap's button
   component is untouched. */
button {
	font: inherit;
	color: inherit;
	background: none;
	border: 0;
	cursor: pointer;
}

summary {
	cursor: pointer;
}

/* Spacing so an unstyled page is readable rather than a single block.
   Deliberately uniform: rhythm is a design decision.

   Every rule here is wrapped in :where() and they have to be. Written plainly,
   `.s + .s` and `.s > * + *` are each two compound selectors, so they outrank
   the authored sheet's own `.s { padding: … }` on the property they set. An
   audited site carried 100px of section padding from its design AND this 2rem
   on top of it, on every section boundary of every page, because the design
   had no reason to write a margin rule it did not know it was fighting. At
   zero specificity they are what they claim to be — a floor under an
   ungenerated site — and the first thing the design says about rhythm
   replaces them.

   PADDING, not the margin between siblings this used to be. The margin was
   invisible on a banded design: a section carrying a ground of its own got
   2rem of the PAGE's colour above it and none of its own inside it, so an
   --alt band read as a tight stripe of text rather than a band. Padding is
   also what an authored `.s { padding-block: … }` actually replaces, which
   the margin was not — a design that spoke about rhythm left this in place
   underneath it. An audited site shipped with every section at exactly
   padding: 0 because the design stage never got as far as writing one: the
   whole page was a single undifferentiated column of text, and nothing in
   the baseline said otherwise. */

:where(.s) {
	padding-block: clamp(2.5rem, 5vw, 4.5rem);
}

:where(.s > * + *) {
	margin-block-start: 1rem;
}

/* The reading column, for the path where no framework lays the sections out.
   The section box itself stays full width so a ground painted on it still
   reaches both edges; only its CONTENT is brought into the centre column.
   The Bootstrap path has the same floor with the row's gutter folded into
   it — see :where(.atb-section-grid) .s further down. */
:where(.s) {
	padding-inline: max(1.25rem, calc((100% - var(--atb-width-section, 1280px)) / 2));
}

/* The measure: no line of running text wider than --atb-measure.
   The section column is 1280px, and a lead or a caption given the whole of
   it is a line nobody can read — an audited home page set its panorama's
   keyword line 1344px wide and a hero lead ran to 1184px, on a brief that
   asked for paragraphs of 650–760px. max-inline-size rather than max-width
   so an authored `max-width: none` does not undo it, at zero specificity so
   an authored max-inline-size does. The column variants are left out: their
   whole point is a body wider than one measure, set in columns. */
:where(.s) :where(
	.s-hero__lead, .s-hero__caption, .s-moment__body, .s-inset__text, .s-duo__text,
	.s-fragments__text, .s-cta__text, .s-panorama__caption, .s-panorama__words,
	.s-contact__text, .s-booking__intro, .s-booking__note, [class*="__intro"]
),
:where(.s:not(.s-story--columns):not(.s-prose--columns)) :where(.s-story__body, .s-prose__body) {
	max-inline-size: var(--atb-measure, 72ch);
}

.s-offering__list,
.s-steps__list,
.s-stats__list,
.s-gallery__list,
.s-testimonials__list,
.s-pricing__list,
.s-checklist__list,
.s-timeline__list,
.s-team__list,
.s-clients__list,
.s-cards__list,
.s-documents__list {
	display: grid;
	gap: 1rem;
}

/* ── Editorial moments: the floor under six compositions ────────
   The six editorial types (moment, lettering, inset, panorama,
   duo, fragments) are the ones whose whole point is a shape, and
   therefore the ones with the most to lose when the authored
   stylesheet misses them: an offering with no CSS is still a list
   of headings, but a duo with no CSS is two photographs and a
   floating sentence with no relationship between them.

   So each gets the least that keeps it legible — a run of words
   that reads as a run of words, a pair that reads as a pair — and
   nothing that competes with a real composition. Everything here
   is in :where(), so it contributes no specificity and the first
   thing the design says about any of these replaces it whole.

   Single column throughout. Every one of these types is composed
   across a wide screen and stacked on a narrow one, and the
   stacked form is the floor: at 390px the baseline already gives
   each block one column, the section gutter and images capped to
   the width of their container, so nothing here can overflow.
   ─────────────────────────────────────────────────────────────── */

/* One line of words, wrapping to several when the screen is
   narrow. `baseline` rather than `center` because the design's
   whole job in .s-lettering is to set these at different sizes,
   and words of two sizes centred on each other read as an
   accident. */
:where(.s-lettering__words, .s-panorama__words) {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.5rem 1.25rem;
}

:where(.s-fragments__parts, .s-duo__media) {
	display: grid;
	gap: 1.5rem;
}

/* The pair, from the tablet up. Below that they are two pictures
   one above the other, which is what "opposite corners" becomes
   on a phone — the diagonal is a wide-screen composition and
   forcing it into 390px is how a heading ends up on top of a
   photograph. */
@media (min-width: 48rem) {
	:where(.s-duo__media) {
		grid-template-columns: 1fr 1fr;
		align-items: center;
	}
}

/* An inset is defined by not spanning the page. The site plan
   says so properly through `width: narrow` (.s--narrow) and the
   design styles that; this is the floor for the case where the
   plan said nothing, so the block is still held in rather than
   rendering as one more full-width band with a picture in it. */
:where(.s-inset) {
	max-width: 46rem;
	margin-inline: auto;
}

/* The enquiry form. Controls are the one part of a generated page
   that looks broken rather than plain when nothing styles them:
   an input at its UA default width sits at about 20 characters in
   the middle of a designed page, and the label beside it rather
   than above it. Bootstrap's .form-control covers both where
   Bootstrap is loaded — this is the same floor for the native
   build, and it is scoped to our own hooks so it cannot reach a
   form some plugin rendered. */
:where(.s-booking__fields) {
	display: grid;
	gap: 1rem;
}

:where(.s-booking__label) {
	display: block;
}

:where(.s-booking__input) {
	display: block;
	width: 100%;
	padding: 0.6rem 0.75rem;
	font: inherit;
	color: inherit;
	background: transparent;
	border: 1px solid currentColor;
	border-radius: 0;
}

/* ── Action rows ────────────────────────────────────────────────
   A run of buttons is a row with air between them, and that is
   mechanism rather than taste — the same reason .brand is laid out
   here rather than left to the design.

   It is here because leaving it to the design failed the same way
   on both frameworks. A .btn is inline-block, so an actions row
   left at display:block puts its buttons in an inline run: two
   audited sites wrote `gap` on the row and nothing else, and gap
   means nothing outside a flex or grid container. One shipped the
   two hero buttons edge to edge with no space between them at all;
   the other, whose buttons happened not to fit on one line, shipped
   them touching vertically with the second indented by the sibling
   margin it had used instead. Neither is visible in the CSS — both
   sheets read as if they had spaced their buttons.

   One class of specificity, so a design that genuinely wants a
   different arrangement (a stacked column, a split row) still says
   so and wins. What it can no longer do is get an inline run by
   omission. --atb-actions-gap lets a design retune the air without
   restating the display.
   ─────────────────────────────────────────────────────────────── */

[class*="__actions"] {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--atb-actions-gap, 0.75rem 1rem);
}

/* ── Sections under Bootstrap's grid ────────────────────────────
   Present only when .atb-section-grid is on the body, i.e. Bootstrap
   is loaded AND the theme has not had its section grid switched off.
   See inc/grid.php for which columns each section gets and why.

   Everything here is mechanism the row needs in order to work, not
   taste. The authored stylesheet still owns colour, type, surface
   and rhythm, and still owns the composition of the sections that
   are not lists.
   ─────────────────────────────────────────────────────────────── */

/* Note the :where() on every rule the design may legitimately overrule. It
   contributes no specificity, so these land at one class and the authored
   sheet — which loads later — still wins. Without it `.atb-section-grid .s`
   would be two classes and would beat the design's own `.s { padding: … }`,
   clamping every section on the site to the gutter below. The two rules that
   are mechanism rather than taste keep their weight on purpose. */

:where(.atb-section-grid) .s {
	/* A .row pulls itself outward with negative side margins and expects a
	   padded parent to sit in — that is what .container-fluid would normally
	   provide. With it, a card's edge lines up exactly with the section title
	   at any padding the design chooses, because the column's own half-gutter
	   puts it back. Without it the cards hang half a gutter outside the title
	   and the page overflows; body's overflow-x: clip above is the backstop
	   for a full-bleed section that sets padding to zero.

	   The max() is the reading column. The gutter alone is a floor of about
	   12px, which on a 1440px viewport is a line of body text 1416px wide —
	   correct as mechanism and unreadable as a page. Whichever of the two is
	   larger wins, so the gutter still governs every viewport narrower than
	   the content column and the column governs everything above it. */
	padding-inline: max(
		calc(var(--bs-gutter-x, 1.5rem) * .5),
		calc((100% - var(--atb-width-section, 1280px)) / 2)
	);
}

.atb-section-grid .s .row {
	/* Mechanism. The baseline's own grid, twenty lines up, would otherwise
	   still be in force on these same lists: display:grid turns the columns
	   into grid items whose flex widths are ignored. column-gap is the same
	   class of failure from the other side — any horizontal gap stacks on top
	   of Bootstrap's padding gutters and pushes three 33.3% columns past 100%,
	   so the last card wraps to a row of its own. Neither is ever a thing the
	   design should be able to reintroduce, by accident or otherwise.

	   --bs-gutter-y goes to zero so that vertical space between wrapped rows
	   has exactly ONE source, the row-gap below. Bootstrap spends its vertical
	   gutter as a margin-top on every cell, which does not merge with a
	   row-gap — it adds to it. A design asking for 1.6rem between the rows of
	   a card grid was getting 1.6rem plus the 1.5rem gutter, so every list on
	   the site came out at roughly double the rhythm it was written for. */
	display: flex;
	column-gap: 0;
	--bs-gutter-y: 0;
}

:where(.atb-section-grid .s) .row {
	/* The default vertical rhythm, and the one the gutter token in the plan is
	   already saying: g-4 means 1.5rem of air, on both axes. Zero specificity,
	   so a design that wants a different figure between the rows says row-gap
	   and REPLACES this rather than adding to it. */
	row-gap: var(--bs-gutter-x);
}

/* ── Chrome: width ──────────────────────────────────────────────
   .container-fluid is deliberate — Bootstrap's .container steps
   through fixed max-widths per breakpoint, which would not line up
   with whatever rhythm the design chose for its sections. One
   token drives both instead.
   ─────────────────────────────────────────────────────────────── */

.site-header__inner,
.site-footer__inner {
	max-width: var(--atb-width-max);
	margin-inline: auto;
}

/* The floor under every header arrangement.
   An auto margin is free space and nothing else, so in a full bar there is
   none left, the arrangement's margin resolves to zero and whatever follows
   the lockup comes to rest against it. This is what keeps the brand its own
   air — and, on .site-nav, the CTA off the last menu item — when the bar has
   run out of room to place anything.
   column-gap only: at mobile the collapse wraps onto its own row and a
   row-gap here would double the padding the menu already has; the collapse
   itself is a block there, where a gap means nothing.
   Tighter at 992px than at 1400px on purpose — the narrowest expanded bar is
   the one that needs the room — and written EXACTLY as
   ATB_Header_Fit::HEADER_GAP writes it, which is how the breakpoint was
   chosen. bin/self-check.php holds the two together. */
.site-header__inner,
.site-nav {
	column-gap: clamp(1rem, 4vw - 1.25rem, 2.75rem);
}

/* ── Chrome: arrangements ───────────────────────────────────────
   The floor for the header/footer layouts chosen under Theme
   System. Structure only — whether the masthead is centred is the
   arrangement's job, what it looks like is the design's. Every rule
   here is one the authored sheet may restyle.

   Note what is NOT here: nothing touches .navbar, .navbar-collapse
   or their flex context, on any arrangement, which is what keeps
   the mobile collapse identical across all four.
   ─────────────────────────────────────────────────────────────── */

/* `stack` — the brand in the middle of the bar, three menu items on
   each side of it, no CTA.

   The brand is printed twice (header.php): .site-header__brand-bar in
   the bar beside the burger, .site-header__masthead inside the
   collapse between .site-nav__list--start and --end. Exactly one of
   them shows at any width, switched on the same navbar-expand-* class
   and at the same widths Bootstrap expands the navbar at — and back
   again in header-fit.js's collapsed form.

   The two lists take equal shares of the row (flex-basis 0, grow 1)
   and lean in towards the brand, so it sits on the centre line even
   when one side's labels are longer than the other's. */
.site-header--stack .site-nav > .site-header__masthead {
	flex: none;
	margin-inline: 0;
}

@media (max-width: 991.98px) {
	.site-header--stack .site-nav > .site-header__masthead {
		display: none;
	}
}

@media (max-width: 1199.98px) {
	.site-header--stack :is(.navbar-expand-xl, .navbar-expand-xxl) .site-nav > .site-header__masthead {
		display: none;
	}
}

@media (max-width: 1399.98px) {
	.site-header--stack .navbar-expand-xxl .site-nav > .site-header__masthead {
		display: none;
	}
}

.site-header--stack.site-header--collapsed .site-nav > .site-header__masthead,
.site-header--stack .site-header__bar:not([class*="navbar-expand"]) .site-nav > .site-header__masthead {
	display: none;
}

@media (min-width: 992px) {
	.site-header--stack:not(.site-header--collapsed) .navbar-expand-lg .site-header__brand-bar {
		display: none;
	}

	.site-header--stack:not(.site-header--collapsed) .navbar-expand-lg .site-nav {
		flex: 1 1 auto;
		align-items: center;
	}

	.site-header--stack:not(.site-header--collapsed) .navbar-expand-lg .site-nav__list--start {
		flex: 1 1 0;
		justify-content: flex-end;
	}

	.site-header--stack:not(.site-header--collapsed) .navbar-expand-lg .site-nav__list--end {
		flex: 1 1 0;
		justify-content: flex-start;
	}
}

@media (min-width: 1200px) {
	.site-header--stack:not(.site-header--collapsed) .navbar-expand-xl .site-header__brand-bar {
		display: none;
	}

	.site-header--stack:not(.site-header--collapsed) .navbar-expand-xl .site-nav {
		flex: 1 1 auto;
		align-items: center;
	}

	.site-header--stack:not(.site-header--collapsed) .navbar-expand-xl .site-nav__list--start {
		flex: 1 1 0;
		justify-content: flex-end;
	}

	.site-header--stack:not(.site-header--collapsed) .navbar-expand-xl .site-nav__list--end {
		flex: 1 1 0;
		justify-content: flex-start;
	}
}

@media (min-width: 1400px) {
	.site-header--stack:not(.site-header--collapsed) .navbar-expand-xxl .site-header__brand-bar {
		display: none;
	}

	.site-header--stack:not(.site-header--collapsed) .navbar-expand-xxl .site-nav {
		flex: 1 1 auto;
		align-items: center;
	}

	.site-header--stack:not(.site-header--collapsed) .navbar-expand-xxl .site-nav__list--start {
		flex: 1 1 0;
		justify-content: flex-end;
	}

	.site-header--stack:not(.site-header--collapsed) .navbar-expand-xxl .site-nav__list--end {
		flex: 1 1 0;
		justify-content: flex-start;
	}
}

/* Where the arrangements are NOT expressed: .site-header__inner cannot place
   anything, because the .navbar-collapse inside it carries Bootstrap's
   flex-grow: 1 and leaves the row with no free space to justify. `stack` used
   to centre its menu from here and rendered hard left for it. Placement is
   done with -lg- auto-margin utilities on the collapse's own children, in
   header.php — see the note there — and for `stack` by the flex shares
   above. */

.site-footer__block {
	margin-block-end: 1.5rem;
}

/* Legibility, not skin. The footer is the one place on the page that usually
   carries a background of its own, and a link there taking --atb-color-primary
   is a brand colour chosen to read on the page's background, not on the
   footer's — an audited site put dark red on dark green. Inheriting means the
   link reads on whatever the footer turns out to be, and the design overrides
   it with a single low-specificity rule the moment it wants something else. */
.site-footer__link {
	color: inherit;
}

.site-footer--center {
	text-align: center;
}

/* The centred footer reads as one column, so its link lists run
   horizontally instead of stacking into a narrow ribbon. */
.site-footer--center .site-footer__list {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 0.5rem 1.5rem;
}

.site-footer--rows .site-footer__main {
	padding-block-start: 1.5rem;
}

/* ── Chrome: optional slots ─────────────────────────────────────
   Four positions the pipeline can fill from the Custom Prompt. None
   of them render unless they hold text, so these rules are dead
   weight on most sites — but the baseline still has to make a
   filled slot legible, because the design stage may have been
   skipped and main.css may not exist at all.
   Deliberately plain: this is a floor, not a look. The authored
   stylesheet restyles them like any other hook.
   ─────────────────────────────────────────────────────────────── */

.site-topbar,
.site-prefooter {
	background: var(--atb-color-surface);
	border-block-end: 1px solid var(--atb-color-border);
	font-size: 0.875rem;
}

.site-prefooter {
	border-block: 1px solid var(--atb-color-border);
	border-block-end: 0;
}

.site-topbar__inner,
.site-prefooter__inner {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 0.5rem 1rem;
	max-width: var(--atb-width-max);
	margin-inline: auto;
	padding: 0.5rem var(--atb-gutter, 1.5rem);
}

.site-prefooter__inner {
	padding-block: 1.25rem;
}

.site-topbar__text,
.site-prefooter__text {
	margin: 0;
}

.site-topbar__link,
.site-prefooter__link {
	color: var(--atb-color-primary);
	font-weight: 600;
}

/* Bottom-right rather than centred: the corner is the one place a fixed
   element does not cover copy at 390px. */
.site-floating {
	position: fixed;
	inset-block-end: 1rem;
	inset-inline-end: 1rem;
	z-index: 50;
	display: inline-flex;
	align-items: center;
	padding: 0.75rem 1.25rem;
	border-radius: 999px;
	background: var(--atb-color-primary);
	color: var(--atb-color-background);
	font-size: 0.9375rem;
	font-weight: 600;
	text-decoration: none;
	box-shadow: 0 6px 20px rgb(0 0 0 / 18%);
}

.site-floating:hover,
.site-floating:focus-visible {
	color: var(--atb-color-background);
	opacity: 0.9;
}

/* ── Native framework chrome ───────────────────────────────────
   Used when Theme System selects Native CSS. Content sections keep their
   semantic hooks and are composed by main.css on every page; these rules
   provide resilient navigation/footer behaviour without Bootstrap assets.
   ─────────────────────────────────────────────────────────────── */

/* row-gap only on the bar and the collapse: the column gaps are the shared
   ones above, which is what the breakpoint was chosen against. The list's
   column gap is that same gap plus the 0.5rem each side Bootstrap pads a
   .nav-link with — the links here carry no padding of their own, and the
   estimate counts it either way. */
.atb-no-bootstrap .site-header__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	row-gap: 1.5rem;
	padding: 1rem var(--atb-gutter, 1.5rem);
}

.atb-no-bootstrap .site-nav,
.atb-no-bootstrap .site-nav__list {
	display: flex;
	align-items: center;
	row-gap: 1rem;
}

.atb-no-bootstrap .site-nav__list {
	column-gap: calc(1rem + clamp(0.25rem, 2.5vw - 1.25rem, 1.25rem));
}

.atb-no-bootstrap .site-header--compact .site-nav__list {
	column-gap: 1.25rem;
}

/* Bootstrap's .navbar-brand carries nowrap; without Bootstrap the lockup is
   a flex item like any other and its name would wrap instead. Restated so the
   brand measures the same on both paths. */
.atb-no-bootstrap .navbar-brand {
	white-space: nowrap;
}

/*
 * Tailwind ships a `.collapse { visibility: collapse; }` utility. The shared
 * Bootstrap-compatible header markup intentionally keeps that class on
 * #site-nav, so non-Bootstrap modes must neutralise the utility as well as
 * supplying their own display behaviour.
 */
.atb-no-bootstrap .site-nav {
	visibility: visible;
}

/* The button itself, not just its icon. `.navbar-toggler` is what gives the
   control its padding, its border and a transparent background under
   Bootstrap; without it the browser's own button chrome shows through — a
   grey slab in a designed header — and the colour no longer follows the
   palette, so the bars drawn in currentColor can come out invisible against
   it. Restated here for the frameworks that do not load Bootstrap. */
.atb-no-bootstrap .site-nav__toggle {
	display: none;
	padding: 0.5rem 0.75rem;
	color: var(--atb-color-text);
	background: transparent;
	border: 1px solid var(--atb-color-border);
	border-radius: var(--atb-radius-sm, 0.25rem);
	cursor: pointer;
}

.atb-no-bootstrap .site-nav__item--parent {
	position: relative;
}

.atb-no-bootstrap .site-nav__list--sub {
	display: none;
	position: absolute;
	z-index: 20;
	min-width: 14rem;
	padding: 0.75rem;
	background: var(--atb-color-background);
	border: 1px solid var(--atb-color-border);
}

.atb-no-bootstrap .site-nav__list--sub.show {
	display: grid;
}

/* The footer bands. One track per block that actually rendered, and the count
   is read off the markup rather than guessed.

   The previous rule was repeat(auto-fit, minmax(min(16rem, 100%), 1fr)) on the
   reasoning that auto-fit collapses the track a missing block would leave
   empty. It does — but auto-fit decides the count from the WIDTH, not from the
   children, and the two disagree at ordinary desktop sizes. An audited site
   rendered all four blocks at 1440px: the available 1104px fits three 256px
   tracks and two gaps but misses four by sixteen pixels, so auto-fit laid three
   and the contacts block wrapped onto a second row under the brand — a
   full-width hole across the right half of the footer. The count is not a
   function of the viewport, it is a property of the footer, and footer.php
   already knows it, so it states it in data-blocks and this reads it.

   THE STEPS ARE MIN-WIDTH, unlike everything else in this block, and they have
   to be. A per-count rule carries an attribute selector, so it outranks the
   plain one whatever media query the plain one sits in — a `max-width` step
   saying "two columns on a tablet" would simply lose to [data-blocks="4"] and
   never apply. Written mobile-first the cascade runs the right way round: one
   column is the floor, and each step up is stated at a specificity no lower
   than the step it replaces.

   The default of 1 is for markup written before the attribute existed: a
   stacked footer is plain, not broken. */
.atb-no-bootstrap .site-footer__inner > .row {
	display: grid;
	grid-template-columns: repeat(var(--atb-footer-cols, 1), minmax(0, 1fr));
	gap: 2rem;
	padding: 3rem var(--atb-gutter, 1.5rem);
}

/* Two-up from the tablet: four blocks in a single stack is a very long footer
   and the blocks themselves are short. */
@media (min-width: 36rem) {
	.atb-no-bootstrap .site-footer__inner > .row { --atb-footer-cols: 2; }
	.atb-no-bootstrap .site-footer__inner > .row[data-blocks="1"] { --atb-footer-cols: 1; }
}

@media (min-width: 62rem) {
	.atb-no-bootstrap .site-footer__inner > .row[data-blocks="1"] { --atb-footer-cols: 1; }
	.atb-no-bootstrap .site-footer__inner > .row[data-blocks="2"] { --atb-footer-cols: 2; }
	.atb-no-bootstrap .site-footer__inner > .row[data-blocks="3"] { --atb-footer-cols: 3; }
	.atb-no-bootstrap .site-footer__inner > .row[data-blocks="4"] { --atb-footer-cols: 4; }

	/* The one arrangement that is not equal tracks — the same split Bootstrap's
	   col-md-6 makes on the other path, restated as tracks: half the band to
	   the brand, the remaining blocks sharing the other half. */
	.atb-no-bootstrap .site-footer--brand-wide .site-footer__inner > .row[data-blocks="3"] {
		grid-template-columns: 2fr 1fr 1fr;
	}

	.atb-no-bootstrap .site-footer--brand-wide .site-footer__inner > .row[data-blocks="4"] {
		grid-template-columns: 3fr 1fr 1fr 1fr;
	}
}

/* `center` is one column at every width, so it stands outside the steps and
   after them: it ties with the per-count rules on specificity and wins on
   order. */
.atb-no-bootstrap .site-footer--center .site-footer__inner > .row {
	grid-template-columns: minmax(0, 1fr);
}

/* The collapsed header, without Bootstrap to provide it.

   Bootstrap switches on the navbar-expand-* class; this has to do the same,
   because that class is no longer always -lg (see atb_header_breakpoint()).
   So the one collapsed state is written four times, once per scope, and the
   four blocks must stay identical apart from the scope:

     below 992px    every header — all of them are burgers there
     below 1200px   a header that expands at xl or xxl
     below 1400px   a header that expands at xxl
     at any width   a header with no expand class at all, and one
                    header-fit.js has put in its collapsed form

   The last one repeats `display` with !important on the open panel: the
   collapsed form in the chrome block below is written for Bootstrap, whose
   expanded collapse is display:flex !important, and it opens the panel as a
   block. Here the open panel is the same column it is on a phone. */
@media (max-width: 991.98px) {
	.atb-no-bootstrap .site-nav__toggle {
		display: inline-flex;
	}

	.atb-no-bootstrap .site-header__inner {
		flex-wrap: wrap;
	}

	.atb-no-bootstrap .site-nav {
		display: none;
		flex-basis: 100%;
	}

	.atb-no-bootstrap .site-nav.show,
	.atb-no-bootstrap .site-nav__list {
		display: flex;
		flex-direction: column;
		align-items: stretch;
	}

	.atb-no-bootstrap .site-nav__list--sub {
		position: static;
	}
}

@media (max-width: 1199.98px) {
	.atb-no-bootstrap :is(.navbar-expand-xl, .navbar-expand-xxl) .site-nav__toggle {
		display: inline-flex;
	}

	.atb-no-bootstrap :is(.navbar-expand-xl, .navbar-expand-xxl) .site-header__inner {
		flex-wrap: wrap;
	}

	.atb-no-bootstrap :is(.navbar-expand-xl, .navbar-expand-xxl) .site-nav {
		display: none;
		flex-basis: 100%;
	}

	.atb-no-bootstrap :is(.navbar-expand-xl, .navbar-expand-xxl) .site-nav.show,
	.atb-no-bootstrap :is(.navbar-expand-xl, .navbar-expand-xxl) .site-nav__list {
		display: flex;
		flex-direction: column;
		align-items: stretch;
	}

	.atb-no-bootstrap :is(.navbar-expand-xl, .navbar-expand-xxl) .site-nav__list--sub {
		position: static;
	}
}

@media (max-width: 1399.98px) {
	.atb-no-bootstrap .navbar-expand-xxl .site-nav__toggle {
		display: inline-flex;
	}

	.atb-no-bootstrap .navbar-expand-xxl .site-header__inner {
		flex-wrap: wrap;
	}

	.atb-no-bootstrap .navbar-expand-xxl .site-nav {
		display: none;
		flex-basis: 100%;
	}

	.atb-no-bootstrap .navbar-expand-xxl .site-nav.show,
	.atb-no-bootstrap .navbar-expand-xxl .site-nav__list {
		display: flex;
		flex-direction: column;
		align-items: stretch;
	}

	.atb-no-bootstrap .navbar-expand-xxl .site-nav__list--sub {
		position: static;
	}
}

.atb-no-bootstrap :is(.site-header--collapsed .site-header__bar, .site-header__bar:not([class*="navbar-expand"])) .site-nav__toggle {
	display: inline-flex;
}

.atb-no-bootstrap :is(.site-header--collapsed .site-header__bar, .site-header__bar:not([class*="navbar-expand"])) .site-header__inner {
	flex-wrap: wrap;
}

.atb-no-bootstrap :is(.site-header--collapsed .site-header__bar, .site-header__bar:not([class*="navbar-expand"])) .site-nav {
	display: none;
	flex-basis: 100%;
}

.atb-no-bootstrap :is(.site-header--collapsed .site-header__bar, .site-header__bar:not([class*="navbar-expand"])) .site-nav.show,
.atb-no-bootstrap :is(.site-header--collapsed .site-header__bar, .site-header__bar:not([class*="navbar-expand"])) .site-nav__list {
	display: flex;
	flex-direction: column;
	align-items: stretch;
}

.atb-no-bootstrap .site-header--collapsed .site-header__bar .site-nav.show {
	display: flex !important;
}

.atb-no-bootstrap :is(.site-header--collapsed .site-header__bar, .site-header__bar:not([class*="navbar-expand"])) .site-nav__list--sub {
	position: static;
}

/* ── Chrome: the brand ──────────────────────────────────────────
   Layout, not skin, so it lives here rather than in the authored
   sheet. The three children are flat siblings inside one <a> — a
   mark, a name and an optional tagline — and Bootstrap's
   .navbar-brand leaves them as inline boxes, so `gap` on .brand
   does nothing and the tagline runs on after the name. Two columns
   with every child placed explicitly: the mark spans whatever rows
   exist, so the block is correct with a tagline and without one.
   The authored sheet still owns colour, size and type here.

   THE TEXT COLUMN'S FLOOR IS ITS TEXT. It was minmax(0, 1fr), and a
   zero floor is a zero min-content width: the lockup told the flex
   row it could shrink to the width of the mark alone, the row took
   it at its word, and Bootstrap's nowrap name ran out of its own box
   and over the first menu item — .navbar-brand 290px wide holding a
   282px name that started 56px in. Plain 1fr is minmax(auto, 1fr):
   the column can still take any spare width, but never less than
   the name needs.
   ─────────────────────────────────────────────────────────────── */

.brand {
	display: grid;
	grid-template-columns: auto 1fr;
	align-items: center;
	column-gap: 0.7rem;
}

.brand__mark {
	grid-column: 1;
	grid-row: 1 / -1;
}

/* justify-self keeps both from stretching to the column: a grid item is
   blockified, so without it the name fills whatever width the tagline
   claimed and its hover target runs far past the word. */
.brand__name {
	grid-column: 2;
	grid-row: 1;
	justify-self: start;
}

.brand__tagline {
	grid-column: 2;
	grid-row: 2;
	justify-self: start;
}

/* A logo is a picture of unknown proportions, not a monogram. The authored
   sheet styles .brand__mark for the one-letter <span> — a square with a
   radius — and that same rule reaches the <img> and squashes it. Qualifying
   by element outranks a bare .brand__mark whatever order the sheets load in.
   The height is definite rather than a max: with both axes auto, a logo that
   has not decoded yet has no intrinsic size to be capped and collapses to
   nothing. Fixing the height and letting the width follow the ratio keeps a
   sane box either way. */
img.brand__mark {
	inline-size: auto;
	max-inline-size: 12rem;
	block-size: 2.75rem;
	aspect-ratio: auto;
	object-fit: contain;
	border-radius: 0;
}

/* The three properties above that a logo cannot survive losing, restated one
   class higher.

   Qualifying by element is not enough on its own: an authored sheet can write
   `img.brand__mark` too, and at equal specificity the later sheet wins. One
   did — it gave both marks a clamped square and object-fit: cover, which is
   right for the monogram and crops a 3:2 logo into a square with its ends cut
   off. Only the shape is pinned here. The height stays on the rule above, at a
   specificity the design still beats, because how big the logo should be IS a
   design decision — how much of it you can see is not. */
.brand img.brand__mark {
	inline-size: auto;
	aspect-ratio: auto;
	object-fit: contain;
}

/* ── Chrome: header spacing and hit targets ─────────────────────
   Baselines, not decisions — all of it is low-specificity and the
   authored sheet can override any of it. Bootstrap's .navbar-nav
   carries no gap, so without this the nav items are separated only
   by .nav-link's own padding and read as one run-on word. The CTA
   and the toggler get a 2.75rem floor because a 32px control is
   under every touch-target guideline and the authored sheet sets
   the font size, not the box.
   ─────────────────────────────────────────────────────────────── */

/* Written as ATB_Header_Fit::MENU_GAP writes it. The floor is low and the
   slope steep: at 992px, the narrowest expanded bar, it is nearly nothing and
   .nav-link's own padding does the separating; by 1600px it is the full
   1.25rem. */
.site-nav__list {
	column-gap: clamp(0.25rem, 2.5vw - 1.25rem, 1.25rem);
}

/* ── Chrome: nothing in the bar shrinks, clips or wraps ─────────
   Layout, not skin. The header is a flex row, and a flex row that
   runs out of room shrinks its items — so the brand gave up its
   width, its nowrap name ran on over the first menu item, the
   labels broke onto two lines and the CTA grew to two lines and
   74px tall. Every one of those hides the collision instead of
   resolving it. So nothing here may shrink: when the row does not
   fit, it overflows, header-fit.js sees that, and the header goes
   to its compact and then its burger form instead. The breakpoint
   it expands at was already chosen to fit (ATB_Header_Fit).

   One class of specificity, like the rest of the chrome: the
   authored sheet is told these are the theme's, and the CSS gate
   refuses a sheet that sets flex-shrink, overflow, a width cap or
   white-space on them. The safety net pins them back if one ships
   anyway.

   nowrap from 992px only. Below that every header is a burger, and
   there a label is one line of a vertical list that may wrap on a
   320px phone rather than run off it. Between 992px and a wider
   expand breakpoint the bar is still a burger, but with at least
   940px of it — nothing there has a reason to wrap either.
   ─────────────────────────────────────────────────────────────── */

.navbar-brand {
	flex-shrink: 0;
	min-inline-size: max-content;
}

@media (min-width: 992px) {
	.site-nav__list .nav-link,
	.site-header__cta {
		white-space: nowrap;
	}
}

.site-header__cta,
.site-nav__toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-block-size: 2.75rem;
}

/* A dropdown item is a link in a panel: it needs room to be hit and a
   focus state, since a keyboard user never triggers :hover. */
.dropdown-item {
	min-block-size: 2.5rem;
	display: flex;
	align-items: center;
}

/* ── Chrome: the dropdown indicator ─────────────────────────────
   A parent item has to look like a parent before it is clicked. Bootstrap
   draws a caret on .dropdown-toggle itself, but that sheet is not loaded on
   Native CSS / Tailwind / Bulma — there the parent renders identical to an
   ordinary link and the submenu is simply not discoverable. Drawn here so
   all four framework paths get the same mark, in currentColor so it follows
   whatever colour the design gave the link.

   `border: 0` comes first and is load-bearing on the Bootstrap path: its
   caret is a solid triangle built from four borders, and without wiping it
   the triangle and the chevron below stack into one filled arrow.

   Physical border-right / border-bottom rather than the logical pair — the
   shape is a chevron pointing DOWN, and it has to keep pointing down on the
   RTL locales. Logical edges mirror with the direction and would swing it a
   quarter turn to point sideways.

   The open state is keyed to aria-expanded, which both paths already
   maintain (Bootstrap's dropdown plugin writes it; so does the hand-rolled
   toggle in assets/js/main.js), so it costs no markup and no script. The
   transition is dropped by the reduced-motion block at the end of this file.
   ─────────────────────────────────────────────────────────────── */

.site-nav .dropdown-toggle::after {
	content: "";
	display: inline-block;
	inline-size: 0.4em;
	block-size: 0.4em;
	margin-inline-start: 0.45em;
	/* Stated, not inherited: Bootstrap gives its own caret vertical-align:
	   .255em, and that value survives the border reset below — the mark would
	   ride high on Bootstrap and sit level everywhere else. */
	vertical-align: middle;
	border: 0;
	border-right: 0.1em solid currentColor;
	border-bottom: 0.1em solid currentColor;
	transform: translateY(-0.12em) rotate(45deg);
	transform-origin: center;
	transition: transform 0.15s ease-in-out;
}

.site-nav .dropdown-toggle[aria-expanded="true"]::after {
	transform: translateY(0.06em) rotate(-135deg);
}

/* ── Chrome: when the tagline shows ─────────────────────────────
   The tagline is the one part of the row that is decorative, so it
   is the first thing to go when the row is short of room — and it is
   never the reason the header becomes a burger.

   It used to be dropped below 1200px on the assumption that the bar
   expanded at 992 and ran out of room somewhere in between. Both
   halves of that are decided per site now: the header states on
   data-tagline-from the width from which ATB_Header_Fit found the
   tagline fits beside everything else — lg, xl, xxl, or none — and
   header-fit.js drops it again (.site-header--compact) if the real
   fonts disagree.

   Below 992px it is never shown: every header is a burger there, and
   a phone header has no room for a second line under the name.
   ─────────────────────────────────────────────────────────────── */

@media (max-width: 991.98px) {
	.brand__tagline {
		display: none;
	}
}

@media (max-width: 1199.98px) {
	[data-tagline-from="xl"] .site-header__bar .brand__tagline {
		display: none;
	}
}

@media (max-width: 1399.98px) {
	[data-tagline-from="xxl"] .site-header__bar .brand__tagline {
		display: none;
	}
}

[data-tagline-from="none"] .site-header__bar .brand__tagline,
.site-header--compact .site-header__bar .brand__tagline {
	display: none;
}

/* ── Chrome: the two forms header-fit.js can put the header in ──
   The breakpoint was chosen from an estimate, and the estimate does
   not know the typeface. header-fit.js measures the real row before
   the first paint and, only while the navbar is expanded and only if
   the row does not fit, steps down:

   1. .site-header--compact — the tagline goes (above) and the gaps
      close up to their floor. Nothing is hidden that a visitor needs.
   2. .site-header--wide — the bar drops the design's width cap and
      uses the viewport, less the gutters.
   3. .site-header--collapsed — if that was not enough, the burger,
      at a width where the navbar would otherwise be expanded.

   It takes both off again as soon as the row fits, re-measuring from
   scratch each time, so the header never sticks in a form it has
   outgrown.

   The collapsed form is Bootstrap's own collapsed navbar restated at
   a higher specificity than navbar-expand-* — toggler shown, collapse
   hidden until .show, the menu a column — so the toggle, the collapse
   plugin and the keyboard handling in main.js are the ones a phone
   already uses. !important only where Bootstrap's own rule has it:
   the collapse's display and the placement utilities (order-*-last,
   m*-*-auto), which would otherwise carry `end`'s brand to the far
   side of the burger.

   Nothing here touches .navbar itself — see the note at the top of
   header.php. The wrap is on .site-header__inner, which is where
   Bootstrap inherits it to.
   ─────────────────────────────────────────────────────────────── */

.site-header--compact .site-header__inner,
.site-header--compact .site-nav {
	column-gap: 1rem;
}

.site-header--compact .site-nav__list {
	column-gap: 0.25rem;
}

/* .site-header--wide — the row still does not fit inside the design's
   width cap, so the bar takes the viewport instead. Three classes, so an
   authored `.site-header__inner { max-width: … }` does not put the cap
   back; the gutters are the bar's own padding and stay. */
.site-header.site-header--wide .site-header__inner {
	max-width: none;
	max-inline-size: none;
}

.site-header--collapsed .site-header__bar .site-header__inner {
	flex-wrap: wrap;
}

.site-header--collapsed .site-header__bar .navbar-toggler {
	display: inline-flex;
}

.site-header--collapsed .site-header__bar .navbar-brand {
	order: 0 !important;
	margin-inline: 0 !important;
}

.site-header--collapsed .site-header__bar .navbar-collapse {
	flex-basis: 100%;
}

.site-header--collapsed .site-header__bar .navbar-collapse.collapse:not(.show) {
	display: none !important;
}

.site-header--collapsed .site-header__bar .navbar-collapse:is(.show, .collapsing) {
	display: block !important;
}

.site-header--collapsed .site-header__bar .navbar-nav {
	flex-direction: column;
}

.site-header--collapsed .site-header__bar .navbar-nav .nav-link {
	padding-inline: var(--bs-nav-link-padding-x, 0);
}

.site-header--collapsed .site-header__bar .navbar-nav .dropdown-menu {
	position: static;
}

/* ── Bootstrap bridge: navbar ─────────────────────────────────── */

.site-header__bar {
	--bs-navbar-color:                var(--atb-color-text);
	--bs-navbar-hover-color:          var(--atb-color-primary);
	--bs-navbar-active-color:         var(--atb-color-primary);
	--bs-navbar-brand-color:          var(--atb-color-text);
	--bs-navbar-brand-hover-color:    var(--atb-color-primary);
	--bs-navbar-disabled-color:       var(--atb-color-border);
	--bs-navbar-toggler-border-color: var(--atb-color-border);
	--bs-navbar-toggler-focus-width:  2px;

	/* Bootstrap parks the lockup's air on its trailing edge. That is the
	   wrong edge for the `end` arrangement, where the brand comes last and
	   the margin would hold it off the right edge instead of away from the
	   menu. The gap is set on .site-header__inner as a column-gap instead —
	   symmetric, order-independent, and it applies between the toggler and
	   the brand on mobile too. Zeroed here so the two do not stack. */
	--bs-navbar-brand-margin-end: 0;
}

/* Bootstrap's toggler icon is an SVG data URI with the stroke colour baked
   in, so it turns invisible the moment a design picks a dark header. Redrawn
   here in currentColor, which cannot get that wrong whatever palette the
   model chooses.

   THE BOX IS OURS TOO, and it has to be. <span class="navbar-toggler-icon">
   is an empty inline element: everything below draws on a box that Bootstrap
   supplies, and on Native CSS / Tailwind / Bulma Bootstrap is not loaded. The
   span then computes to 0x0, the three bars have nothing to paint on, and the
   button renders as an empty outlined rectangle in the corner of every phone
   header — with no other way to open the menu. The four properties here are
   byte-for-byte what Bootstrap declares, so restating them changes nothing on
   the Bootstrap path and is the whole control on the other three. */
.navbar-toggler-icon {
	display: inline-block;
	inline-size: 1.5em;
	block-size: 1.5em;
	vertical-align: middle;
	position: relative;
	background-image: linear-gradient(currentColor, currentColor);
	background-repeat: no-repeat;
	background-position: center;
	background-size: 100% 2px;
}

.navbar-toggler-icon::before,
.navbar-toggler-icon::after {
	content: "";
	position: absolute;
	inset-inline: 0;
	height: 2px;
	background: currentColor;
}

.navbar-toggler-icon::before {
	top: 15%;
}

.navbar-toggler-icon::after {
	bottom: 15%;
}

/* ── Bootstrap bridge: dropdown ───────────────────────────────── */

.site-nav .dropdown-menu {
	--bs-dropdown-bg:               var(--atb-color-background);
	--bs-dropdown-color:            var(--atb-color-text);
	--bs-dropdown-border-color:     var(--atb-color-border);
	--bs-dropdown-link-color:       var(--atb-color-text);
	--bs-dropdown-link-hover-bg:    var(--atb-color-surface);
	--bs-dropdown-link-hover-color: var(--atb-color-primary);
	--bs-dropdown-link-active-bg:   var(--atb-color-primary);
	--bs-dropdown-link-active-color: var(--atb-color-background);
}

/* ── Bootstrap bridge: buttons ────────────────────────────────── */

.btn {
	--bs-btn-color:              var(--atb-color-text);
	--bs-btn-border-color:       var(--atb-color-border);
	--bs-btn-hover-color:        var(--atb-color-primary);
	--bs-btn-hover-border-color: var(--atb-color-primary);
	--bs-btn-focus-shadow-rgb:   0, 0, 0;
}

.btn--primary {
	--bs-btn-color:              var(--atb-color-background);
	--bs-btn-bg:                 var(--atb-color-primary);
	--bs-btn-border-color:       var(--atb-color-primary);
	--bs-btn-hover-color:        var(--atb-color-background);
	--bs-btn-hover-bg:           var(--atb-color-accent);
	--bs-btn-hover-border-color: var(--atb-color-accent);
}

.btn--ghost {
	--bs-btn-color:              var(--atb-color-primary);
	--bs-btn-bg:                 transparent;
	--bs-btn-border-color:       var(--atb-color-primary);
	--bs-btn-hover-color:        var(--atb-color-background);
	--bs-btn-hover-bg:           var(--atb-color-primary);
	--bs-btn-hover-border-color: var(--atb-color-primary);
}

/* ── The platform mark ───────────────────────────────── */

/* Mechanism, and it HAS to be restated here: the reset above lays every svg
   out as `display: block` with `height: auto`, which is right for an image in
   a figure and wrong for a 1em glyph sitting inside a button — the mark would
   break onto its own line and take its height from the viewBox instead of from
   the type. This is the same failure .navbar-toggler-icon had at 0×0 in 1.3.3,
   and it is restated for the same reason: the element is emitted by the theme,
   so the theme owes it a box.

   The width and height are `em` on purpose. Together with fill="currentColor"
   on the element itself it means the mark takes the button's colour AND its
   type size, including whatever the authored sheet does on :hover or inside an
   inverted band — so a stylesheet that has never heard of platform marks still
   styles them correctly. `flex: none` is for the case where the design makes
   the button a flex row: a 1em glyph must not be the thing that shrinks.

   The GAP between the mark and the label is deliberately not set here. In
   inline flow the newline in the template is already a space; in a flex button
   it is the design's `gap` to choose. */
.platform-mark {
	display: inline-block;
	width: 1em;
	height: 1em;
	vertical-align: -0.125em;
	flex: none;
}

/* ── Bootstrap bridge: pagination, breadcrumb, forms ──────────── */

.pagination {
	--bs-pagination-color:               var(--atb-color-text);
	--bs-pagination-bg:                  var(--atb-color-background);
	--bs-pagination-border-color:        var(--atb-color-border);
	--bs-pagination-hover-color:         var(--atb-color-primary);
	--bs-pagination-hover-bg:            var(--atb-color-surface);
	--bs-pagination-hover-border-color:  var(--atb-color-border);
	--bs-pagination-focus-color:         var(--atb-color-primary);
	--bs-pagination-focus-bg:            var(--atb-color-surface);
	--bs-pagination-active-color:        var(--atb-color-background);
	--bs-pagination-active-bg:           var(--atb-color-primary);
	--bs-pagination-active-border-color: var(--atb-color-primary);
	--bs-pagination-disabled-color:      var(--atb-color-border);
	--bs-pagination-disabled-bg:         var(--atb-color-background);
	--bs-pagination-disabled-border-color: var(--atb-color-border);
}

/* ── Chrome: the breadcrumb trail ──────────────────────────────
   Laid out here, not skinned here, and NOT left to Bootstrap.

   The comment in atb_breadcrumbs() used to say Bootstrap's .breadcrumb draws
   the separators and handles the wrap. It does — on the Bootstrap path. On the
   other three frameworks nothing is loaded under it, and <ol class="breadcrumb">
   falls back to the reset above: margin and padding zeroed, so the markers sit
   outside the box and never paint, and the items stay list-items. The trail
   renders as "Home" and "About" on two lines, flush against the left edge of
   the viewport with no separator between them. That is what an audited site
   shipped on every inner page.

   The alignment is the second half of it, and it is wrong on BOTH paths:
   .atb-breadcrumbs is a direct child of <main> with nothing between it and the
   viewport edge, and Bootstrap's .breadcrumb carries no horizontal padding
   either. So the measure and the gutter are set here, from the same
   --atb-width-max the header and the footer use, and the trail lines up with
   the chrome above it instead of hugging the edge.

   Everything below is layout and legibility. Colour, type, size, the divider
   glyph and the spacing are the authored stylesheet's, through .atb-breadcrumbs,
   .breadcrumb and .breadcrumb-item.
   ─────────────────────────────────────────────────────────────── */

.atb-breadcrumbs {
	max-inline-size: var(--atb-width-max);
	margin-inline: auto;
	padding: 1rem var(--atb-gutter, 1.5rem) 0;
	font-size: 0.875rem;
}

.breadcrumb {
	--bs-breadcrumb-divider-color:     var(--atb-color-accent);
	--bs-breadcrumb-item-active-color: var(--atb-color-accent);

	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.25rem 0.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.breadcrumb-item {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
}

/* On the item rather than as a flex gap child: a wrapped trail must not begin
   a new line with an orphaned separator, and ::before travels with its item. */
.breadcrumb-item + .breadcrumb-item::before {
	content: var(--atb-breadcrumb-divider, "\203A");
	color: var(--atb-color-accent);

	/* Bootstrap floats its divider and pads it; the item is a flex box here
	   and a float inside one is ignored anyway, but the padding would show as
	   an uneven gap on one path only. Zeroed so both render alike. */
	float: none;
	padding: 0;
}

.breadcrumb-item.active {
	color: var(--atb-color-accent);
}

.form-control {
	--bs-body-bg:      var(--atb-color-background);
	--bs-border-color: var(--atb-color-border);

	color: var(--atb-color-text);
}

/* ── Chrome: the cookie consent banner ─────────────
   Mechanism, like the gate below it, and hidden by exactly the
   opposite move. The gate is rendered `hidden` and RAISED by a
   class rule that outranks the attribute; the banner is rendered
   `hidden` and stays that way until main.js takes the attribute
   off. So this file must never put a bare `display` on
   .consent-banner: a class selector beats the UA's [hidden] rule,
   and the bar would then be up permanently — including for every
   visitor who already answered, on a page whose buttons they have
   already used once.

   That is also the one thing the authored stylesheet can do here
   by accident, which is why the [hidden] rule below carries
   !important — the only declaration in this file that does,
   outside the reduced-motion block at the end. The baseline loads
   BEFORE main.css, so nothing weaker survives the design writing
   `.consent-banner { display: flex }` for its own layout. The CSS
   gate refuses that declaration as well; this is the half of the
   guard that does not depend on the gate having been run.

   Everything else is layout and legibility. The ground, the
   border, the type, the spacing and the two buttons are the
   design's, through .consent-banner, __inner, __text, __link,
   __actions and the shared .btn--primary / .btn--ghost. What it
   must NOT restate is position, inset, display or z-index — those
   are what put the bar at the bottom of the viewport and keep it
   above the page.
   ───────────────────────────────────────────────────────── */

.consent-banner {
	position: fixed;
	inset-block-end: 0;
	inset-inline: 0;
	z-index: 60;
	padding: 1rem var(--atb-gutter, 1.5rem);
	/* Capped and scrollable rather than allowed to grow: a translated
	   sentence on a 320px screen can otherwise take half the viewport,
	   and the page under a consent bar has to stay usable. */
	max-block-size: 60vh;
	overflow-y: auto;
	color: var(--atb-color-text);
	background: var(--atb-color-background);
	border-block-start: 1px solid var(--atb-color-border);
	box-shadow: 0 -6px 24px rgb(0 0 0 / 12%);
}

.consent-banner[hidden] {
	display: none !important;
}

.consent-banner__inner {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem 1.5rem;
	max-inline-size: var(--atb-width-max);
	margin-inline: auto;
}

.consent-banner__text {
	margin: 0;
	/* Measure, not width: the sentence is one line of prose and the
	   buttons take the rest of the row. */
	max-inline-size: 72ch;
	font-size: 0.9375rem;
}

/* The actions row is already a wrapping flex row — see the shared
   [class*="__actions"] rule above. Only the no-shrink is particular:
   without it the two buttons are the first thing the row squeezes,
   and a translated "Reject" wraps to three lines. */
.consent-banner__actions {
	flex: 0 0 auto;
}

/* Below Bootstrap's sm breakpoint the row has no room for a sentence
   and two buttons beside it, so the buttons take the full width
   underneath — sharing it equally, because Accept and Reject are the
   same decision and neither may end up the smaller target. */
@media (max-width: 575.98px) {
	.consent-banner__actions {
		inline-size: 100%;
	}

	.consent-banner__button {
		flex: 1 1 auto;
	}
}

/* The corner element is fixed in the bottom-right and the bar runs the
   full width, so the bar lands on top of it. Lifted for as long as the
   bar is up, by the height main.js measured. Keyed off the attribute
   rather than off the banner's own state because the two elements are
   siblings and CSS cannot look sideways. */
:root[data-atb-consent="pending"] .site-floating {
	inset-block-end: calc(1rem + var(--atb-consent-height, 5rem));
}

/* ── Chrome: the age gate ───────────────────────────────────────
   Mechanism, like the header. The dialog is rendered on every page and always
   carries `hidden`; what raises it is data-atb-age="pending" on <html>, set
   synchronously by the inline guard in the <head> before the first frame. So
   the visibility rule has to outrank the `hidden` attribute — a class selector
   beats the UA's [hidden] rule, which is why the display lives on .atb-agegate
   itself and not on the attribute.

   The scroll lock is on both html and body: one alone leaves the page
   scrollable behind the overlay on one platform or the other, and a gate you
   can scroll past is a picture of a gate.

   Everything below is layout. Colour, type, the panel's surface, its border
   and radius, the spacing and the buttons are the design's, through
   .atb-agegate, .atb-agegate__panel, __eyebrow, __title, __text, __actions and
   the shared .btn--primary / .btn--ghost. What the design must NOT restate is
   position, inset, display or z-index on .atb-agegate — those are what make it
   block, and the authored sheet loads last.
   ─────────────────────────────────────────────────────────────── */

.atb-agegate {
	display: none;
	position: fixed;
	inset: 0;
	z-index: 1000;
	align-items: center;
	justify-content: center;
	padding: 1.5rem;
	overflow-y: auto;
	/* Deliberately not a token: the scrim sits between the page and the panel,
	   and every --atb-color-* is either the page's ground or the panel's. A
	   design that wants its own scrim sets background on .atb-agegate. */
	background: rgb(0 0 0 / 72%);
}

:root[data-atb-age="pending"] .atb-agegate {
	display: flex;
}

:root[data-atb-age="pending"],
:root[data-atb-age="pending"] body {
	overflow: hidden;
}

.atb-agegate__panel {
	max-inline-size: 30rem;
	inline-size: 100%;
	padding: clamp(1.5rem, 5vw, 2.5rem);
	text-align: center;
	color: var(--atb-color-text);
	background: var(--atb-color-background);
	border: 1px solid var(--atb-color-border);
}

.atb-agegate__eyebrow {
	margin: 0 0 0.75rem;
	color: var(--atb-color-accent);
	font-size: 0.8rem;
	letter-spacing: 0.16em;
	text-transform: uppercase;
}

.atb-agegate__title {
	margin: 0 0 0.75rem;
	font-family: var(--atb-font-heading);
}

.atb-agegate__text {
	margin: 0 0 1.5rem;
	color: var(--atb-color-secondary);
}

/* The shared action-row rule above already gives this a wrapping flex row —
   which it needs, and shrinking is not an option: the two labels are
   translated per site and "Подтверждаю" next to "Мне ещё нет 18" does not fit
   a phone on one line. Only the centring is particular to the dialog. */
.atb-agegate__actions {
	justify-content: center;
}

/* ── The legal document ─────────────────────────────────────────
   Privacy, terms, cookies. The one part of a generated site that
   is finished here rather than by the per-site stylesheet, and the
   only place in this file where taste is deliberately being
   expressed — because the taste in question is "none".

   These pages used to render through the same .s-* hooks as
   everything else, so the design composed them like any other
   page. An audited privacy policy opened with a split hero and a
   call-to-action button, then a quoted-claim band, then three
   marketing cards on a contrasting ground, then the policy itself
   broken across three prose sections in alternating colours, one
   of them in two columns. Every one of those is a device for
   holding the attention of someone browsing. Nobody browses a
   privacy policy: they arrive with a question and leave when they
   have found the sentence that answers it.

   So the markup carries .atb-legal__* hooks instead, which are not
   in the contract the stylesheet author is shown and are not in
   its hook list — it cannot style them, by construction rather
   than by instruction. What the page keeps is what it inherits:
   the site's palette through the tokens above, the site's two
   typefaces, the header and the footer. What it loses is the
   composition, which is the whole intent.

   One class of specificity throughout, so a human editing a
   generated theme can still overrule any of it.
   ─────────────────────────────────────────────────────────────── */

.atb-legal {
	/* Prose measure, not the site's grid. Long enough to read without the
	   line-return becoming work, short enough that the eye finds the start of
	   the next line — the same reason --atb-width-content exists, stated in
	   characters because that is what the measure actually depends on. */
	max-inline-size: 68ch;
	margin-inline: auto;
	padding: clamp(2rem, 5vw, 3.5rem) var(--atb-gutter, 1.5rem) clamp(3rem, 7vw, 5rem);
}

.atb-legal__title {
	margin-block-end: clamp(1.5rem, 4vw, 2.5rem);
	font-size: clamp(1.75rem, 1.2vw + 1.4rem, 2.5rem);
	line-height: 1.15;
}

.atb-legal__heading {
	/* Asymmetric on purpose: a heading belongs to what follows it, and the
	   space above is what separates one clause of the document from the last. */
	margin-block: clamp(2rem, 4vw, 2.75rem) 0.6rem;
	font-size: clamp(1.15rem, 0.5vw + 1rem, 1.4rem);
	line-height: 1.25;
}

/* The whole body, not only our own paragraphs: an edited page renders through
   the_content() and its blocks need the same rhythm. */
.atb-legal__body > * + * {
	margin-block-start: 1rem;
}

/* After the rule above, which would otherwise put a paragraph's worth of
   space between a heading and the text it introduces and undo the asymmetry.
   Both hooks: ours, and the bare heading an edited page's blocks emit. */
.atb-legal__body :is(.atb-legal__heading, h2, h3, h4) + * {
	margin-block-start: 0.6rem;
}

.atb-legal :is(p, li) {
	line-height: 1.7;
}

.atb-legal :is(ul, ol) {
	padding-inline-start: 1.5rem;
}

.atb-legal li + li {
	margin-block-start: 0.4rem;
}

/* Underlined rather than coloured. A legal document is the one page where a
   link is a reference the reader may have to follow deliberately, and colour
   alone is not a reliable way to say so on whatever ground the site chose. */
.atb-legal a {
	color: var(--atb-color-primary);
	text-decoration: underline;
	text-underline-offset: 0.15em;
}

.atb-legal :is(table) {
	inline-size: 100%;
	border-collapse: collapse;
}

.atb-legal :is(th, td) {
	padding: 0.5rem 0.75rem;
	border: 1px solid var(--atb-color-border);
	text-align: start;
}

/* ── Accessibility ──────────────────────────────────────────── */

.skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	padding: 0.5rem 1rem;
	background: var(--atb-color-background);
	color: var(--atb-color-text);
	z-index: 100;
}

.skip-link:focus {
	left: 0;
}

:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}
