/*
Theme Name: GnocchiApps
Theme URI: https://gnocchiapps.eu
Author: Flavio Trillo
Description: Ruhiges, technisches Block-Theme für GnocchiApps: iPhone-Apps, Screenshots, Support und Feedback.
Version: 1.1.0
Requires at least: 6.6
Requires PHP: 8.1
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: gnocchiapps
*/

/* ---------------------------------------------------------------- base */
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; font-variant-numeric: tabular-nums; }
h1, h2, h3, h4, .wp-block-site-title { text-wrap: balance; }
p, li { text-wrap: pretty; }

:where(a):focus-visible, :where(button):focus-visible, :where(input, textarea, select):focus-visible {
	outline: 3px solid var(--wp--preset--color--ink);
	outline-offset: 3px;
	border-radius: 4px;
}
::selection { background: var(--wp--preset--color--line); color: var(--wp--preset--color--ink); }

/* ---------------------------------------------------------------- header */
.gna-header { padding-block: var(--wp--preset--spacing--40); }
.gna-header .gna-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1.6rem; margin: 0; }
.gna-bar > * { margin: 0; }
.gna-bar .gna-nav { margin-left: auto; }
/* Logo (brand brief 02b, "active capsule"): iOS-style page indicator above the wordmark, all sizes relative to --f.
   Built in HTML/CSS so the wordmark stays real text and follows the light/dark tokens. */
:root { --gna-dot: #CFCBC2; }
.gna-wordmark { --f: 24px; display: inline-flex; flex-direction: column; align-items: flex-start; gap: max(5px, calc(var(--f) * .267)); text-decoration: none; color: var(--wp--preset--color--ink); }
.gna-wordmark__dots { display: flex; gap: calc(var(--f) * .133); }
.gna-wordmark__dots i { width: calc(var(--f) * .2); height: calc(var(--f) * .2); border-radius: 999px; background: var(--gna-dot); transition: width .25s ease, background-color .25s ease; }
.gna-wordmark__dots i:first-child { width: calc(var(--f) * .6); background: var(--wp--preset--color--accent); }
/* hover: the active capsule pages one position to the right */
.gna-wordmark:hover .gna-wordmark__dots i:first-child, .gna-wordmark:focus-visible .gna-wordmark__dots i:first-child { width: calc(var(--f) * .2); background: var(--gna-dot); }
.gna-wordmark:hover .gna-wordmark__dots i:nth-child(2), .gna-wordmark:focus-visible .gna-wordmark__dots i:nth-child(2) { width: calc(var(--f) * .6); background: var(--wp--preset--color--accent); }
@media (prefers-reduced-motion: reduce) { .gna-wordmark__dots i { transition: none; } }
.gna-wordmark__word { font-family: var(--wp--preset--font-family--wordmark); font-weight: 600; font-size: var(--f); line-height: 1; letter-spacing: -.03em; }
.gna-wordmark__word span { font-weight: 400; color: var(--wp--preset--color--muted); }
.gna-nav { display: flex; flex-wrap: wrap; align-items: center; gap: .25rem 1.6rem; }
.gna-nav ul { display: flex; flex-wrap: wrap; gap: 0.25rem 1.6rem; list-style: none; margin: 0; padding: 0; }
.gna-nav a { color: var(--wp--preset--color--muted); font-size: 0.95rem; font-weight: 500; text-decoration: none; padding-block: 0.4rem; background: linear-gradient(var(--wp--preset--color--accent), var(--wp--preset--color--accent)) left bottom / 0 2px no-repeat; transition: color .2s ease, background-size .25s ease; }
.gna-nav a:hover { color: var(--wp--preset--color--ink); background-size: 100% 2px; }
.gna-nav a[aria-current="page"] { color: var(--wp--preset--color--ink); background-size: 100% 2px; }
@media (prefers-reduced-motion: reduce) { .gna-nav a { transition: none; } }
.gna-lang { display: flex; gap: .9rem; list-style: none; margin: 0; padding: 0 0 0 1.6rem; border-left: 1px solid var(--wp--preset--color--line); }
.gna-lang a { color: var(--wp--preset--color--muted); font-size: .85rem; letter-spacing: .02em; text-decoration: none; padding-block: .4rem; }
.gna-lang a:hover, .gna-lang a[aria-current] { color: var(--wp--preset--color--ink); }
.gna-lang a[aria-current] { font-weight: 600; }

/* ---------------------------------------------------------------- footer */
.wp-site-blocks > main { padding-block-end: var(--wp--preset--spacing--60); }
.wp-site-blocks > .gna-footer { margin-block-start: 0; }
.gna-footer { background: var(--wp--preset--color--surface); border-top: 1px solid var(--wp--preset--color--accent-line); padding-block: var(--wp--preset--spacing--60) var(--wp--preset--spacing--50); }
.gna-footer__grid { display: grid; gap: var(--wp--preset--spacing--50); grid-template-columns: 1fr; margin: 0; }
@media (min-width: 760px) { .gna-footer__grid { grid-template-columns: 1.4fr 1fr 1fr; } }
.gna-footer__grid > * { margin: 0; }
.gna-footer h2 { font-size: var(--wp--preset--font-size--base); font-weight: 600; letter-spacing: -0.01em; margin-block-end: 0.75rem; }
.gna-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.4rem; }
.gna-footer a { color: var(--wp--preset--color--ink); }
.gna-footer p { color: var(--wp--preset--color--muted); margin: 0; }
.gna-footer .gna-footer__tagline { margin-block-start: 1rem; max-width: 22rem; }
/* The link columns are groups; keep the heading's top margin the earlier plain-HTML columns had (#90). */
.gna-footer .gna-footer__grid h2 { margin-block-start: 0.83em; }
.gna-footer .gna-footer__legal { margin-block-start: var(--wp--preset--spacing--50); font-size: var(--wp--preset--font-size--small); }

/* ---------------------------------------------------------------- hero: the apps lead */
.gna-hero { padding-block: var(--wp--preset--spacing--60); overflow-x: clip; }
.gna-hero__grid { display: grid; grid-template-columns: 1fr; gap: var(--wp--preset--spacing--50); align-items: center; }
.gna-hero__grid > * { margin: 0; }
.gna-hero h1 { margin: 0 0 1.25rem; max-width: 10ch; }
.gna-hero__lead { color: var(--wp--preset--color--muted); max-width: 26rem; margin: 0 0 2rem; }

/* Stacked (one device above the other) below 900px, same breakpoint as .gna-hero__grid itself switching from a
   single column to text-beside-devices — below it, each device gets real width instead of two cramped slivers;
   the side-by-side pair only makes sense once the hero has room for it. One portrait (Precious), one landscape
   (ShotTimer, whose own screen reads like a stopwatch face and suits being shown turned on its side) — wider
   than the old matched-portrait-pair container, since the landscape device wants more width to read clearly.
   Restored to this exact side-by-side sizing (vs. the equal-longest-side overlap tried afterwards, which read
   as too small) — see #40's history for that attempt. */
.gna-devices { display: grid; grid-template-columns: 1fr; align-items: center; gap: var(--wp--preset--spacing--40); width: 100%; max-width: clamp(13rem, 70vw, 18rem); justify-self: center; }
.gna-devices > * { margin: 0 auto; }
@media (min-width: 900px) {
	.gna-hero__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
	.gna-devices { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(1rem, 2.6vw, 2rem); max-width: 36rem; }
}
/* the one motion: devices rise into place once */
.gna-devices .gna-phone { animation: gna-rise .8s cubic-bezier(.2, .8, .2, 1) both; }
.gna-devices .gna-phone:nth-child(2) { animation-delay: .12s; }
@keyframes gna-rise { from { transform: translateY(28px); opacity: 0; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .gna-devices .gna-phone { animation: none; } }

/* Pre-composited pair (hero.php uses this instead of the CSS-framed pair below when hero-devices-{lang}.png
   exists): a single image with real device bezels/shadows baked in, both phones already at true matching scale
   (one landscape in front of one portrait) — so it just needs sizing as a plain image, overriding the grid
   layout above that the two-separate-frame version needs. */
.gna-devices--composite { display: block; max-width: clamp(16rem, 78vw, 30rem); }
.gna-devices--composite img { display: block; width: 100%; height: auto; }
@media (min-width: 900px) { .gna-devices--composite { max-width: 30rem; } }

/* Device frame (CSS-framed fallback pair). */
.gna-phone { width: 100%; max-width: 17rem; aspect-ratio: 9 / 19.5; margin: 0; padding: .45rem; border-radius: 2.4rem; background: #0e0f11; box-shadow: 0 0 0 1px rgb(255 255 255 / .1) inset, 0 28px 44px -26px rgb(22 23 26 / .6); }
.gna-phone__screen { position: relative; width: 100%; height: 100%; border-radius: 2rem; overflow: hidden; background: linear-gradient(170deg, #34363b, #17181b); display: grid; place-items: center; }
.gna-phone__screen::before { content: ""; position: absolute; top: .65rem; left: 50%; translate: -50% 0; width: 30%; height: 1rem; border-radius: 999px; background: #000; z-index: 1; }
.gna-phone__screen img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* Landscape variant (ShotTimer): the frame itself turns sideways (aspect-ratio inverted, notch moves from the
   top edge to the left edge). */
.gna-phone--landscape { aspect-ratio: 19.5 / 9; }
.gna-phone--landscape .gna-phone__screen::before { top: 50%; left: .65rem; translate: 0 -50%; width: 1rem; height: 30%; }

/* Fallback only: used for a locale that has no genuine landscape capture yet (hero.php picks this modifier
   when shottimer-shot-landscape-{lang}.jpg doesn't exist, falling back to the portrait idle capture every other
   screen uses). The image gets rotated into the frame with CSS rather than stretched/cropped into it.
   container-type:size on the screen lets the rotated image size itself in terms of the frame's own box (100cqw
   = the frame's width) rather than the viewport, so after the 90° turn its visual width exactly matches the
   frame width with the source's own aspect ratio intact — no stretching, no gap. Drop this whole rule (and the
   hero.php branch that applies it) once every locale has a real landscape screenshot. */
.gna-phone--landscape-rotated .gna-phone__screen { container-type: size; }
.gna-phone--landscape-rotated .gna-phone__screen img {
	/* Scaled past 100cqw on purpose: at an exact fit the rotated image's short ends are the screenshot's own
	   status bar and tab bar, rotated sideways into illegible slivers. Oversizing pushes both outside the frame
	   (clipped by the screen's own overflow:hidden), leaving just the main content — the digital readout and
	   START button — centred and legible. */
	position: absolute; top: 50%; left: 50%; width: auto; height: 132cqw; aspect-ratio: 9 / 19.5;
	transform: translate(-50%, -50%) rotate(90deg);
}

/* ---------------------------------------------------------------- home: compact two-column app overview
   (full-bleed tinted band — outer .gna-apps-band carries the colour, inner .gna-apps the grid, see apps.php) */
.gna-apps-band { background: var(--wp--preset--color--accent-wash); border-top: 1px solid var(--wp--preset--color--accent-line); border-bottom: 1px solid var(--wp--preset--color--accent-line); padding-block: var(--wp--preset--spacing--60); }
.gna-apps { display: grid; grid-template-columns: 1fr; gap: var(--wp--preset--spacing--60) clamp(3rem, 8vw, 6rem); }
.gna-apps > * { margin: 0; }
@media (min-width: 860px) { .gna-apps { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.gna-appcol > * { margin-block: 0; }
.gna-app__icon { display: block; width: 4.5rem; height: auto; aspect-ratio: 1; margin: 0 0 1.5rem; border-radius: 22.4%; box-shadow: 0 0 0 1px rgb(22 23 26 / .1), 0 10px 22px -12px rgb(22 23 26 / .6); }
.gna-appcol h2 { margin: 0 0 .75rem; }
.gna-app__tagline { font-size: var(--wp--preset--font-size--medium); font-weight: 500; line-height: 1.35; letter-spacing: -0.015em; margin: 0 0 1rem; }
.gna-appcol > p { max-width: 32rem; }
.gna-appcol > p:not(.gna-app__tagline) { color: var(--wp--preset--color--muted); }
.gna-specs { margin: 1.75rem 0 1.75rem; max-width: 34rem; }
.gna-specs > div { display: grid; grid-template-columns: 7rem 1fr; gap: 1rem; padding-block: .7rem; border-top: 1px solid var(--wp--preset--color--line); }
.gna-specs > div:last-child { border-bottom: 1px solid var(--wp--preset--color--line); }
.gna-specs dt { color: var(--wp--preset--color--muted); font-size: var(--wp--preset--font-size--small); padding-top: .1rem; }
.gna-specs dd { margin: 0; }
.gna-app__soon { display: inline-block; margin: 1.25rem 0 0; padding: .3rem .8rem; border: 1px solid var(--wp--preset--color--accent-line); border-radius: .5rem; color: var(--wp--preset--color--accent-text); font-size: var(--wp--preset--font-size--small); }

/* ---------------------------------------------------------------- misc */
.gna-page-title { margin-block: var(--wp--preset--spacing--60) var(--wp--preset--spacing--40); }
.wp-block-button__link { transition: background-color .2s ease, color .2s ease; }
.wp-block-button.is-style-outline .wp-block-button__link { background: transparent; color: var(--wp--preset--color--ink); border: 1.5px solid var(--wp--preset--color--ink); padding-block: calc(.8rem - 1.5px); }
.wp-block-button.is-style-outline .wp-block-button__link:hover { background: var(--wp--preset--color--ink); color: var(--wp--preset--color--paper); }
.wp-block-separator { border-color: var(--wp--preset--color--line); }

/* ---------------------------------------------------------------- dark mode: same neutral tokens, swapped */
@media (prefers-color-scheme: dark) {
	html body {
		--wp--preset--color--paper: #1C1B22;
		--wp--preset--color--surface: #24232B;
		--wp--preset--color--ink: #F6F5F2;
		--wp--preset--color--muted: #A9A6AF;
		--wp--preset--color--line: #34323B;
		--wp--preset--color--accent: #8FA68B;
		--gna-dot: #5E5C66;
		--wp--preset--color--accent-fill: var(--wp--preset--color--accent);
		/* Custom properties substitute their var() references using the element where THEY are declared, not
		   where they're later consumed — theme.json declares these once at :root, so without redeclaring the
		   same formulas here they'd stay locked to their light-mode result even under this override. */
		--wp--preset--color--accent-wash: color-mix(in srgb, var(--wp--preset--color--accent) 8%, var(--wp--preset--color--paper));
		--wp--preset--color--accent-line: color-mix(in srgb, var(--wp--preset--color--accent) 32%, var(--wp--preset--color--line));
		--wp--preset--color--accent-text: color-mix(in srgb, var(--wp--preset--color--accent) 70%, var(--wp--preset--color--ink));
		--wp--preset--color--on-accent-muted: color-mix(in srgb, var(--wp--preset--color--paper) 88%, var(--wp--preset--color--accent-fill));
		--wp--preset--color--on-accent-line: color-mix(in srgb, var(--wp--preset--color--paper) 25%, var(--wp--preset--color--accent-fill));
		/* --accent is brightened for dark mode (header/button contrast), so ink (now light) no longer contrasts
		   with it; paper (now near-black) does — swap which one .gna-ask's text uses, per theme. */
		--wp--preset--color--on-accent: var(--wp--preset--color--paper);
	}
	.gna-phone { box-shadow: 0 0 0 1px rgb(255 255 255 / .14) inset, 0 28px 44px -26px rgb(0 0 0 / .9); }
	.gna-app__icon { box-shadow: 0 0 0 1px rgb(255 255 255 / .12), 0 10px 22px -12px rgb(0 0 0 / .9); }
}

/* ---------------------------------------------------------------- screenshots (issue #11)
   Use a core Image block with the class "gna-shot" for a framed screenshot, and wrap several in a group
   with the class "gna-shots" for the gallery (3 columns; a swipeable row on small screens). */
.gna-shots { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(1rem, 3vw, 2rem); align-items: start; }
.gna-shots > * { margin: 0; }
@media (max-width: 720px) {
	.gna-shots { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; gap: 1rem; padding-bottom: .75rem; margin-inline: calc(-1 * var(--wp--preset--spacing--40)); padding-inline: var(--wp--preset--spacing--40); }
	.gna-shots > * { flex: 0 0 62%; scroll-snap-align: center; }
}
.wp-block-image.gna-shot { position: relative; margin: 0; padding: .45rem; border-radius: 2.4rem; background: #0e0f11; box-shadow: 0 0 0 1px rgb(255 255 255 / .1) inset, 0 28px 44px -26px rgb(22 23 26 / .6); }
.wp-block-image.gna-shot img { display: block; width: 100%; height: auto; aspect-ratio: 1170 / 2532; object-fit: cover; border-radius: 2rem; }
.wp-block-image.gna-shot::after { content: ""; position: absolute; top: 1.1rem; left: 50%; translate: -50% 0; width: 28%; height: .9rem; border-radius: 999px; background: #000; }
/* Unused for now (both apps capture content-only, no real system chrome baked in — confirmed with both app
   sessions), kept as an escape hatch: if a screenshot ever DOES show the device's own Dynamic Island baked into
   the pixels, drawing this CSS pill on top of it stacks two slightly-misaligned black capsules into one
   oversized blob. gna-shot--real-notch (set per app in app_page(), see build-content.py) drops the synthetic
   one so the real captured chrome would be the only pill shown. */
.wp-block-image.gna-shot.gna-shot--real-notch::after { content: none; }
@media (prefers-color-scheme: dark) { .wp-block-image.gna-shot { box-shadow: 0 0 0 1px rgb(255 255 255 / .14) inset, 0 28px 44px -26px rgb(0 0 0 / .9); } }

/* ---------------------------------------------------------------- app pages (issues #8-#10) */
.gna-apphero { padding-block: var(--wp--preset--spacing--60) var(--wp--preset--spacing--40); }
.gna-apphero > * { margin-block: 0; }
.wp-block-image.gna-appicon { margin: 0 0 1.5rem; }
.wp-block-image.gna-appicon img { display: block; width: 5.5rem; height: auto; aspect-ratio: 1; border-radius: 22.4%; box-shadow: 0 0 0 1px rgb(22 23 26 / .1), 0 12px 26px -14px rgb(22 23 26 / .6); }
@media (prefers-color-scheme: dark) { .wp-block-image.gna-appicon img { box-shadow: 0 0 0 1px rgb(255 255 255 / .12), 0 12px 26px -14px rgb(0 0 0 / .9); } }
.gna-apphero h1 { margin: 0 0 .75rem; }
.gna-apphero .gna-apphero__tagline { font-size: var(--wp--preset--font-size--medium); font-weight: 500; letter-spacing: -0.015em; line-height: 1.35; margin: 0 0 1rem; max-width: 34rem; }
.gna-apphero .gna-apphero__lead { color: var(--wp--preset--color--muted); max-width: 34rem; margin: 0 0 1.5rem; }
.gna-apphero .wp-block-buttons { margin-top: 1.25rem; }
.gna-section { padding-block: var(--wp--preset--spacing--60); }
.gna-section > * { margin-block: 0; }
.gna-section > h2 { margin-block-end: var(--wp--preset--spacing--50); }
.gna-features { display: grid; grid-template-columns: 1fr; gap: 0 clamp(2rem, 6vw, 4.5rem); }
@media (min-width: 760px) { .gna-features { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.gna-features > * { margin: 0; }
.gna-feature { padding-block: 1.25rem 1.5rem; border-top: 1px solid var(--wp--preset--color--line); }
.gna-feature > * { margin: 0; }
.gna-feature h3 { font-size: var(--wp--preset--font-size--medium); font-weight: 600; letter-spacing: -0.015em; margin-block-end: .4rem; }
.gna-feature p { color: var(--wp--preset--color--muted); }
.gna-steps { margin: 0; padding-left: 1.25rem; max-width: 40rem; display: grid; gap: 1rem; }
.gna-steps li::marker { color: var(--wp--preset--color--muted); font-weight: 600; }
.gna-note { color: var(--wp--preset--color--muted); font-size: var(--wp--preset--font-size--small); max-width: 40rem; margin-block-start: var(--wp--preset--spacing--40); }
/* Quiet link line to an app's own privacy/terms pages (issue #41) — same size/colour as .gna-note, but the
   links themselves stay full-contrast so they still read as links, not muted-into-invisibility. */
.gna-legal-line { color: var(--wp--preset--color--muted); font-size: var(--wp--preset--font-size--small); margin-block-start: var(--wp--preset--spacing--50); }
.gna-legal-line a { color: var(--wp--preset--color--ink); }
.gna-section p.gna-about { max-width: 34rem; font-size: var(--wp--preset--font-size--medium); line-height: 1.5; letter-spacing: -0.01em; }

/* ---------------------------------------------------------------- "ask" band (contact prompt): full accent, no tint —
   the one section per page meant to read as a solid block of colour, not just a wash. Text uses --on-accent (ink in
   light mode, paper in dark mode — whichever is actually the dark one) rather than the sitewide ink/link colours,
   since --accent is deliberately brightened in dark mode and plain ink would no longer contrast with it there. */
.gna-ask { background: var(--wp--preset--color--accent-fill); color: var(--wp--preset--color--on-accent); padding-block: var(--wp--preset--spacing--60); }
.gna-ask > * { margin-block: 0; }
.gna-ask h2 { margin-block-end: var(--wp--preset--spacing--40); color: var(--wp--preset--color--paper); }
.gna-ask p, .gna-ask a { color: var(--wp--preset--color--paper); }

/* ---------------------------------------------------------------- sticky header (issue #24)
   The template-part wrapper is the sticky element (its parent .wp-site-blocks spans the whole page, so it can stick).
   It is already full width; the side padding comes from the inner .gna-header group. */
.wp-site-blocks > .gna-site-header {
	position: sticky; top: 0; z-index: 50;
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
	border-bottom: 1px solid var(--wp--preset--color--line);
}
@supports (backdrop-filter: blur(1px)) and (background: color-mix(in srgb, red, blue)) {
	/* translucent page colour, so content scrolling underneath stays faintly visible; text stays ink (AA either way) */
	.wp-site-blocks > .gna-site-header { background: color-mix(in srgb, var(--wp--preset--color--paper) 86%, transparent); backdrop-filter: blur(12px) saturate(1.2); -webkit-backdrop-filter: blur(12px) saturate(1.2); }
}
.admin-bar .wp-site-blocks > .gna-site-header { top: 32px; }
@media (max-width: 782px) { .admin-bar .wp-site-blocks > .gna-site-header { top: 46px; } }
html { scroll-padding-top: 6rem; }
.gna-header { padding-block: 1rem; }

/* ---------------------------------------------------------------- touch targets and short viewports (issue #25)
   WCAG 2.2 AA 2.5.8 wants >= 24px targets; primary controls here are >= 40px. */
.gna-nav a { display: inline-block; padding-block: .55rem; }
.gna-lang { gap: .15rem; }
.gna-lang a { display: inline-block; padding: .6rem .5rem; }
.gna-footer ul { gap: 0; }
.gna-footer li a { display: inline-block; padding-block: .4rem; }
/* A sticky bar eats too much of a landscape phone: let it scroll away there. */
@media (max-height: 500px) { .wp-site-blocks > .gna-site-header { position: static; } }

/* footer line: copyright left, "Made with ❤️ in Berlin" right; stacks on phones (issue #26) */
.gna-footer .gna-footer__legal { display: flex; flex-wrap: wrap; justify-content: space-between; gap: .35rem 2rem; }
.gna-footer__made { white-space: nowrap; }

/* ---------------------------------------------------------------- phone menu (issue #27)
   Up to 700px the link row is replaced by a "Menü" button (a <details>, no JavaScript) that drops a full-width panel
   with large tap targets under the sticky bar. Above 700px the normal link row is shown. */
.gna-menu { display: none; }
@media (max-width: 700px) {
	html { scroll-padding-top: 4.5rem; }
	.gna-header { padding-block: .4rem; }
	.gna-header .gna-bar { flex-wrap: nowrap; gap: 0 .5rem; }
	.gna-wordmark { order: 1; }
	.gna-wordmark { --f: 20px; }
	.gna-bar .gna-nav { display: none; }
	.gna-lang { order: 2; margin: 0 0 0 auto; padding: 0; border-left: 0; gap: .1rem; }
	.gna-menu { display: block; order: 3; }
	.gna-menu > summary { display: flex; align-items: center; gap: .55rem; min-height: 2.75rem; padding: 0 .5rem 0 .75rem; border-radius: .6rem; cursor: pointer; list-style: none; font-weight: 550; -webkit-tap-highlight-color: transparent; }
	.gna-menu > summary::-webkit-details-marker { display: none; }
	.gna-menu__icon { position: relative; display: block; width: 1.25rem; height: 2px; background: currentColor; border-radius: 2px; box-shadow: 0 -6px 0 currentColor, 0 6px 0 currentColor; transition: box-shadow .2s ease, background-color .2s ease, transform .2s ease; }
	.gna-menu[open] .gna-menu__icon { background: transparent; box-shadow: none; }
	.gna-menu[open] .gna-menu__icon::before, .gna-menu[open] .gna-menu__icon::after { content: ""; position: absolute; inset: 0; background: currentColor; border-radius: 2px; }
	.gna-menu[open] .gna-menu__icon::before { transform: rotate(45deg); }
	.gna-menu[open] .gna-menu__icon::after { transform: rotate(-45deg); }
	.gna-menu__panel { position: absolute; left: 0; right: 0; top: 100%; padding: .25rem var(--wp--style--root--padding-left, 1rem) 1.25rem; background: var(--wp--preset--color--paper); border-bottom: 1px solid var(--wp--preset--color--line); box-shadow: 0 24px 32px -24px rgb(28 27 34 / .35); }
	.gna-menu__panel ul { list-style: none; margin: 0; padding: 0; }
	.gna-menu__panel li + li { border-top: 1px solid var(--wp--preset--color--line); }
	.gna-menu__panel a { display: flex; align-items: center; min-height: 3.5rem; color: var(--wp--preset--color--ink); font-size: 1.125rem; font-weight: 500; letter-spacing: -0.01em; text-decoration: none; }
	.gna-menu__panel a[aria-current] { font-weight: 700; }
}
@media (max-width: 700px) and (prefers-color-scheme: dark) { .gna-menu__panel { box-shadow: 0 24px 32px -24px rgb(0 0 0 / .8); } }
@media (max-width: 700px) and (prefers-reduced-motion: reduce) { .gna-menu__icon { transition: none; } }
@media (max-width: 600px) { .gna-footer li a { display: inline-flex; align-items: center; min-height: 2.75rem; padding-block: 0; } }

/* ---------------------------------------------------------------- contact form (issues #13, #14; one form since #85)
   Contact Form 7 markup, styled here. Controls are >= 16px (no iOS zoom on focus) and >= 44px tall. */
.gna-formpage { padding-block: var(--wp--preset--spacing--60); }
.gna-formpage > * { margin-block: 0; }
.gna-formpage h1 { margin-block-end: .75rem; }
.gna-formpage .gna-formpage__intro { color: var(--wp--preset--color--muted); max-width: 34rem; margin-block-end: var(--wp--preset--spacing--50); }
.gna-formpage .wpcf7 { max-width: 36rem; }
.gna-form-fields { display: grid; gap: 1.25rem; }
.gna-form-fields > *, .gna-field-row > * { margin: 0; }
.gna-form-note { color: var(--wp--preset--color--muted); font-size: var(--wp--preset--font-size--small); }
.gna-field-row { display: grid; grid-template-columns: 1fr; gap: 1.25rem; }
@media (min-width: 560px) { .gna-field-row { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.gna-field label { display: grid; gap: .4rem; }
.gna-label { font-weight: 550; }
.gna-optional { color: var(--wp--preset--color--muted); font-weight: 400; }
.gna-field .wpcf7-form-control-wrap { display: block; }
.gna-form-fields :where(input[type="text"], input[type="email"], select, textarea) {
	display: block; width: 100%; box-sizing: border-box; min-height: 2.75rem; padding: .6rem .8rem;
	font: inherit; font-size: 1rem; line-height: 1.4; color: var(--wp--preset--color--ink);
	background: var(--wp--preset--color--surface); border: 1.5px solid var(--wp--preset--color--muted); border-radius: .5rem;
}
.gna-form-fields textarea { min-height: 10rem; resize: vertical; }
@media (prefers-color-scheme: dark) { .gna-form-fields :where(input[type="text"], input[type="email"], select, textarea) { background: var(--wp--preset--color--surface); } }
.gna-form-fields .wpcf7-not-valid { border-color: var(--wp--preset--color--ink); border-width: 2px; }
.gna-form-fields .wpcf7-not-valid-tip { display: block; margin-top: .35rem; color: var(--wp--preset--color--ink); font-size: var(--wp--preset--font-size--small); font-weight: 550; }
.gna-form-fields .wpcf7-not-valid-tip::before { content: "\26A0\FE0E\00a0"; }
/* consent checkbox: whole label is the target */
.gna-consent .wpcf7-list-item { display: block; margin: 0; }
.gna-consent label { display: flex; align-items: flex-start; gap: .75rem; min-height: 2.75rem; padding-block: .35rem; font-size: var(--wp--preset--font-size--small); }
.gna-consent input[type="checkbox"] { flex: none; width: 1.6rem; height: 1.6rem; margin: .1rem 0 0; accent-color: var(--wp--preset--color--ink); }
.gna-consent a { color: inherit; }
.gna-submit .wpcf7-submit {
	min-height: 2.75rem; padding: .8rem 1.4rem; font: inherit; font-weight: 550; cursor: pointer; border: 0; border-radius: .7rem;
	background: var(--wp--preset--color--ink); color: var(--wp--preset--color--paper); transition: background-color .2s ease;
}
.gna-submit .wpcf7-submit:hover { background: var(--wp--preset--color--muted); }
.gna-submit .wpcf7-submit:disabled { opacity: .55; cursor: progress; }
.gna-submit { display: flex; align-items: center; gap: .75rem; }
.gna-submit .wpcf7-spinner { margin: 0; }
/* honeypot: out of sight for people and assistive tech, still present in the DOM for bots */
.gna-hp { position: absolute; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden; }
/* result box below the form (Contact Form 7 toggles its state classes) */
.gna-formpage .wpcf7 form .wpcf7-response-output { margin: 1.25rem 0 0; padding: .9rem 1.1rem; border: 1.5px solid var(--wp--preset--color--ink); border-radius: .5rem; background: var(--wp--preset--color--surface); font-weight: 550; }
.gna-formpage .wpcf7 form.sent .wpcf7-response-output { border-left-width: 6px; }
.gna-formpage .screen-reader-response { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; margin: -1px; padding: 0; border: 0; }
.gna-formpage .screen-reader-response ul { display: none; }

/* ---------------------------------------------------------------- Complianz cookie policy (issue #21)
   The plugin paints service rows translucent light grey and the expanded cookie tables white/#f7f7f7, with ID
   selectors. In dark mode that puts light text on light grounds (contrast failure, tables nearly unreadable), and
   the per-service consent checkbox is 13px (below the 24px target size). :is() matches the plugin's specificity. */
:is(#cmplz-document, #cmplz-cookies-overview) .cmplz-dropdown { background-color: var(--wp--preset--color--surface); }
:is(#cmplz-document, #cmplz-cookies-overview) .cmplz-dropdown summary { background-color: var(--wp--preset--color--line); color: var(--wp--preset--color--ink); }
:is(#cmplz-document, #cmplz-cookies-overview) .cmplz-dropdown .cookies-per-purpose { border-color: var(--wp--preset--color--line); background-color: var(--wp--preset--color--line); }
:is(#cmplz-document, #cmplz-cookies-overview) .cmplz-dropdown .cookies-per-purpose div:nth-child(n) { background-color: var(--wp--preset--color--paper); color: var(--wp--preset--color--ink); }
#cmplz-manage-consent-container.cmplz-manage-consent-container .cmplz-categories .cmplz-category { background-color: var(--wp--preset--color--surface); }
#cmplz-manage-consent-container.cmplz-manage-consent-container .cmplz-categories .cmplz-category .cmplz-category-header { background-color: var(--wp--preset--color--line); color: var(--wp--preset--color--ink); }
#cmplz-manage-consent-container.cmplz-manage-consent-container .cmplz-categories .cmplz-category .cmplz-category-header .cmplz-always-active { color: var(--wp--preset--color--ink); }
.cmplz-document .cmplz-accept-service { width: 1.6rem; height: 1.6rem; accent-color: var(--wp--preset--color--ink); }
@media (prefers-color-scheme: dark) { :is(#cmplz-document, #cmplz-cookies-overview) .cmplz-dropdown summary div::after { filter: invert(1); } }

/* ---------------------------------------------------------------- Complianz consent banner, phone landscape (issue #68)
   Below 400px viewport height Complianz shrinks the banner with zoom (.6, buttons/links .5) and stretches it to the
   full viewport height, which leaves a blank area and 17px buttons. Undo that: normal size, height from content
   (capped to the viewport), message scrolls, the three buttons sit in one row at full touch size. */
@media (max-height: 400px) {
	body .cmplz-cookiebanner { display: flex !important; flex-direction: column; zoom: 1 !important; height: auto !important; max-height: calc(100dvh - 16px) !important; padding: 10px 16px !important; gap: 6px !important; }
	body .cmplz-cookiebanner .cmplz-header { max-height: none !important; margin-bottom: 0 !important; }
	body .cmplz-cookiebanner .cmplz-close { zoom: 1 !important; }
	body .cmplz-cookiebanner .cmplz-body { flex: 0 1 auto !important; min-height: 0; overflow-y: auto; margin-top: 0 !important; }
	body .cmplz-cookiebanner > :not(.cmplz-body) { flex-shrink: 0; }
	body .cmplz-cookiebanner .cmplz-message { font-size: var(--wp--preset--font-size--small); }
	body .cmplz-cookiebanner .cmplz-buttons { flex-direction: row !important; gap: 8px !important; }
	body .cmplz-cookiebanner .cmplz-buttons .cmplz-btn { zoom: 1 !important; flex: 1 1 0; height: auto !important; min-height: 2.75rem !important; padding: 0 .5rem !important; font-size: var(--wp--preset--font-size--small) !important; line-height: 1.2 !important; white-space: normal !important; }
	body .cmplz-cookiebanner .cmplz-documents, body .cmplz-cookiebanner .cmplz-information { zoom: 1 !important; }
}
/* Banner links (Dienste verwalten, Cookie Policy, Datenschutz, Impressum) and the inline consent form's checkboxes on
   the cookie policy are 13-16px tall at every width; bring them to the 24px target size. */
body .cmplz-cookiebanner a.cmplz-link { padding-block: 4px; line-height: 16px; }
#cmplz-manage-consent-container input.cmplz-consent-checkbox { width: 1.6rem; height: 1.6rem; accent-color: var(--wp--preset--color--ink); }
