/* ============================================================
   CRONAH — styles.css
   Token system: deep-space dark theme. The page sits on top of the
   3D earth rendered by globe.js into #globe-canvas. The hero and the
   map section are transparent so the globe shows through sharp.

   GLASS CONTRACT (landing page only — body.glass-page, see the GLASS
   THEME block at the end of this file): every other landing section
   is translucent glass over the globe. That is affordable because
   globe.js treats those sections as "soft" windows: it renders at
   half resolution and a capped frame rate while only glass is on
   screen — invisible through a 26px blur. The base rules below keep
   the original opaque surfaces, which is what every page other than
   index.html still uses, and what the landing page falls back to
   when backdrop-filter is unsupported.

   The sage green and cream from the original brand palette survive
   as the light-on-dark roles: sage for structure and accents, cream
   for filled CTAs. Three type roles.
   Modes: body[data-mode="b2b"] / body[data-mode="b2c"]
   ============================================================ */

:root {
  /* Tells the browser to render its own chrome (scrollbars, date
     pickers, autofill, select dropdowns) dark. Set here rather than
     per-page so admin.html, profile.html and event.html get it too. */
  color-scheme: dark;

  /* --- Space substrate: what everything is layered on --- */
  --space-0: #070a12;  /* deepest black-blue — matches globe.js clear color. Nudged a touch lighter than pure black so the sky doesn't read as flat void; stars still sit far above this in brightness. */
  --space-1: #0b101c;  /* panel base */
  --space-2: #121a29;  /* raised panel (cards, inputs, modals) */

  /* Color tokens */
  --ink:   #e9eee4;  /* primary text — warm off-white with a green cast */
  --pine:  #ccd5ae;  /* sage green — accents, headings, data highlights */
  --leaf:  #e0e5b6;  /* lighter sage-yellow — hover borders, emphasis */
  --moss:  #9aab9c;  /* muted secondary text (7.9:1 on --space-1) */
  --mist:  rgba(204, 213, 174, 0.07);  /* faint sage wash over space */
  --paper: rgba(10, 15, 24, 0.76);     /* translucent panel surface */
  --line:  rgba(204, 213, 174, 0.20);  /* hairline borders */

  /* Text/icon color for anything sitting ON a filled accent surface.
     --ink is light now, so filled buttons need their own inverse. */
  --ink-invert: #0a1018;

  /* Pale sage-green accent — reserved for buttons and filled interactive
     elements. Kept light enough that --ink-invert (dark) text on top
     still has strong contrast. */
  --sage-accent:        #e3f0d6;
  --sage-accent-bright: #eef7e4;

  /* Per-mode accent (JS-free: driven by attribute selectors below) */
  --accent: var(--sage-accent);

  /* Type roles */
  --font-display: "Fraunces", Georgia, serif;
  --font-body: "Public Sans", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, monospace;

  --radius: 14px;
  --maxw: 1120px;
}

body[data-mode="b2c"] { --accent: var(--sage-accent); }

/* ---------- Reset & base ---------- */
*, *::before, *::after { box-sizing: border-box; }
/* The hidden attribute must ALWAYS win, no matter what display
   value any other rule sets. Fixes modals/images appearing when
   they shouldn't. */
[hidden] { display: none !important; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: var(--font-body);
  color: var(--ink);
  /* The gradient is the fallback sky: if WebGL, Three.js or globe.js
     is unavailable the canvas stays empty and this is what shows.
     When the globe IS running it paints over this. */
  background:
    radial-gradient(1200px 800px at 78% 8%, rgba(38, 62, 104, 0.32), transparent 62%),
    radial-gradient(900px 700px at 12% 82%, rgba(58, 78, 60, 0.22), transparent 60%),
    var(--space-0);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* ---------- 3D earth background (globe.js) ----------
   Fixed behind everything, never interactive. All page content is
   lifted onto its own stacking context above it. */
#globe-canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  display: block;
  pointer-events: none;
  /* Fades in once globe.js has a first frame, so there's no flash of
     an unpainted black canvas over the gradient. */
  opacity: 0;
  transition: opacity 1.2s ease;
}
.globe-on #globe-canvas { opacity: 1; }

/* Only static, in-flow content needs lifting: a positioned element with
   z-index 0 (the canvas) paints above non-positioned block content, so
   <main> and <footer> would otherwise disappear behind the globe.

   Do NOT add the fixed overlays (.back-to-top, .cookie-bar,
   .modal-backdrop) to this list. `body > .thing` outranks `.thing`, so
   it overrode their own `position: fixed` with `relative` — which
   dropped the back-to-top into the flow after the footer (leaving a gap
   below it) and would have rendered the modals in-flow, behind the
   header, instead of as overlays. They are all already fixed with a
   z-index far above the canvas and need nothing from here.

   .site-header is likewise absent on purpose: it sets its own
   `position: sticky` and z-index, and a rule here would fight it. */
body > main,
body > footer { position: relative; z-index: 1; }
img { max-width: 100%; display: block; }
a { color: var(--ink); font-weight: 600; text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.12;
  margin: 0 0 0.5em;
  letter-spacing: -0.01em;
}
h1 { font-size: clamp(2.2rem, 5vw, 3.6rem); }
h2 { font-size: clamp(1.7rem, 3.4vw, 2.4rem); }
h3 { font-size: 1.2rem; }

.eyebrow {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--moss);
  margin: 0 0 1rem;
}

/* Mode visibility — the whole switch mechanic in two rules */
body[data-mode="b2b"] [data-only="b2c"] { display: none !important; }
body[data-mode="b2c"] [data-only="b2b"] { display: none !important; }

/* Content cross-fade on mode change (added/removed by JS) */
main { transition: opacity 0.18s ease; }
main.is-switching { opacity: 0; }

/* Keyboard focus */
:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.95rem;
  padding: 0.72rem 1.4rem;
  border-radius: 999px;
  border: 1.5px solid transparent;
  cursor: pointer;
  transition: transform 0.12s ease, background 0.15s ease, color 0.15s ease;
}
.btn:hover { text-decoration: none; transform: translateY(-1px); }
.btn-primary { background: var(--accent); color: var(--ink-invert); }
.btn-primary:hover { background: var(--sage-accent-bright); }
.btn-ghost { background: rgba(255, 255, 255, 0.04); color: var(--ink); border-color: var(--line); }
.btn-ghost:hover { border-color: var(--accent); background: rgba(255, 255, 255, 0.08); }
.btn-outline { background: rgba(255, 255, 255, 0.04); color: var(--ink); border-color: var(--line); }
.btn-outline:hover { border-color: var(--accent); color: var(--ink); background: rgba(255, 255, 255, 0.08); }
.btn-wide { width: 100%; }

/* ---------- Header ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 1200;
  /* Solid, not translucent+blurred. A backdrop-filter here would make
     the browser re-blur a full-width strip of an animating WebGL canvas
     on every single frame — it was one of the main causes of scroll
     jank. The globe shows through the hero above it instead. */
  background: #060a11;
  border-bottom: 1px solid var(--line);
}
.header-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0.7rem 1.25rem;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
}
.brand { display: flex; align-items: center; gap: 0.55rem; color: var(--ink); }
.brand:hover { text-decoration: none; }
.brand-mark {
  width: 26px; height: 26px;
  border-radius: 50% 50% 50% 4px;   /* leaf-shaped dot */
  background: linear-gradient(135deg, var(--leaf), var(--pine));
}
.brand-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.25rem;
  letter-spacing: 0.01em;
}

/* The B2B/B2C switch */
.mode-switch {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr; /* equal halves — the thumb is 50%, so they always align */
  background: var(--mist);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px;
  margin-inline: auto;
}
.mode-btn {
  position: relative;
  z-index: 2;
  border: 0;
  background: transparent;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.88rem;
  padding: 0.45rem 1.2rem;
  border-radius: 999px;
  color: var(--moss);
  cursor: pointer;
  text-align: center;
  white-space: nowrap;
  transition: color 0.2s ease;
}
.mode-btn[aria-selected="true"] { color: var(--ink-invert); }
.mode-thumb {
  position: absolute;
  z-index: 1;
  top: 4px; bottom: 4px; left: 4px;
  width: calc(50% - 4px);
  background: var(--accent);
  border-radius: 999px;
  transition: transform 0.25s cubic-bezier(0.35, 0, 0.2, 1), background 0.25s ease;
}
body[data-mode="b2c"] .mode-thumb { transform: translateX(100%); }

.header-nav { display: flex; align-items: center; gap: 1.1rem; }
.header-nav > a { color: var(--ink); font-weight: 500; font-size: 0.92rem; }
.header-nav > a:hover { text-decoration: none; }
/* .header-nav > a above is more specific than .btn-primary alone (an
   extra element selector beats the class-only rule), so it was
   silently overriding the Admin link's text color with --ink — cream
   text on the cream .btn-primary fill, unreadable. Restore the
   inverted color for any filled button that lives in the nav. */
.header-nav > a.btn-primary { color: var(--ink-invert); }

/* ---------- Account dropdown ----------
   Anchored to the account button. Signed out the button opens the auth
   modal; signed in it toggles this menu, so reaching the dashboard is a
   deliberate second click rather than something that happens by
   accident. [hidden] wins over display:grid via the global rule. */
/* ---------- Language switch ----------
   Same pill shell as the B2B/B2C switch so they read as a family, but
   smaller and with circular flags instead of labels. The inactive flag
   is desaturated and dimmed rather than hidden, so it's obvious it can
   be clicked. */
.lang-switch {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  background: var(--mist);
  border: 1px solid var(--line);
  border-radius: 999px;
  flex-shrink: 0;
  position: relative;
  /* Extra breathing room on top of the nav's own gap, so this reads as
     its own group rather than crowding whatever sits right before it
     (Sign out / Account). */
  margin-left: 0.5rem;
}
/* Thin divider to the left, echoing the one already used between
   header-nav links, so the language switch reads as a separate
   control rather than another nav item. */
.header-nav > .lang-switch::before {
  content: "";
  position: absolute;
  left: -0.75rem;
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: 1.2rem;
  background: var(--line);
}
.lang-btn {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  cursor: pointer;
  line-height: 0;
  opacity: 0.42;
  filter: saturate(0.35);
  transition: opacity 0.18s ease, filter 0.18s ease, transform 0.15s ease;
}
.lang-btn:hover { opacity: 0.8; filter: saturate(0.8); }
.lang-btn[aria-pressed="true"] {
  opacity: 1;
  filter: none;
  box-shadow: 0 0 0 2px var(--accent);
}
.lang-btn:active { transform: scale(0.92); }
.lang-btn .flag {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: block;
}
/* The white band of the Bulgarian flag would vanish into a light
   surface; a hairline keeps the disc readable on any background. */
.lang-btn .flag circle,
.lang-btn .flag { box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.25); }

@media (max-width: 640px) {
  .lang-btn { width: 24px; height: 24px; }
  .lang-btn .flag { width: 18px; height: 18px; }
}
@media (prefers-reduced-motion: reduce) {
  .lang-btn { transition: none; }
}

.account-menu { position: relative; }

#account-btn[aria-haspopup="menu"]::after {
  content: "";
  display: inline-block;
  width: 0.4em;
  height: 0.4em;
  margin-left: 0.5em;
  vertical-align: 0.12em;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translate(-0.06em, -0.06em);
  transition: transform 0.18s ease;
}
#account-btn[aria-expanded="true"]::after {
  transform: rotate(-135deg) translate(-0.12em, -0.12em);
}

.account-dropdown {
  position: absolute;
  top: calc(100% + 0.55rem);
  right: 0;
  z-index: 1300;
  min-width: 11.5rem;
  display: grid;
  gap: 0.15rem;
  padding: 0.4rem;
  background: var(--space-2);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.6);
  animation: account-menu-in 0.16s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes account-menu-in {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: none; }
}

.account-menu-item {
  display: block;
  width: 100%;
  margin: 0;
  padding: 0.55rem 0.7rem;
  border: 0;
  border-radius: 8px;
  background: none;
  font: inherit;
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
}
.account-menu-item:hover {
  background: rgba(204, 213, 174, 0.10);
  text-decoration: none;
}
.account-menu-signout { color: #ff9b8a; }
.account-menu-signout:hover { background: rgba(255, 155, 138, 0.12); }

@media (max-width: 640px) {
  .account-dropdown { min-width: 10rem; }
}

@media (prefers-reduced-motion: reduce) {
  .account-dropdown { animation: none; }
  #account-btn::after { transition: none; }
}

/* ---------- Hero ----------
   Deliberately transparent: this is where the globe is at its
   furthest and the starfield is fully visible, so nothing sits
   between the visitor and it except the text itself. The text gets
   its own local scrim instead of a full-width panel. */
.hero {
  background: transparent;
  border-bottom: 0;
  min-height: 88vh;
  display: flex;
  align-items: center;
}
.hero-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 5.5rem 1.25rem 4.5rem;
  width: 100%;
}
.hero h1 {
  max-width: 17ch;
  text-shadow: 0 2px 30px rgba(4, 6, 12, 0.9), 0 1px 3px rgba(4, 6, 12, 0.8);
}
.hero-lead {
  max-width: 56ch;
  font-size: 1.08rem;
  color: #c3cec4;
  text-shadow: 0 1px 16px rgba(4, 6, 12, 0.95);
}
.hero .eyebrow { text-shadow: 0 1px 12px rgba(4, 6, 12, 0.9); }
.hero-actions { display: flex; gap: 0.8rem; flex-wrap: wrap; margin-top: 1.6rem; }

/* ---------- Impact strip ---------- */
.impact {
  background:
    linear-gradient(180deg, rgba(204, 213, 174, 0.09), rgba(204, 213, 174, 0.02)),
    #070c14;
  color: var(--ink);
  border-block: 1px solid var(--line);
}
.impact-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 2.2rem 1.25rem;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;
}
.impact-num {
  display: block;
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 700;
  color: var(--pine);
}
.impact-label { font-size: 0.88rem; color: var(--moss); }

/* ---------- Sections ----------
   Text-heavy sections get a translucent scrim so copy stays readable
   over the earth; the map section deliberately doesn't, because
   that's where the globe has flown in and should be seen. */
.section {
  padding: 4.5rem 0;
  /* Opaque base. Non-landing pages keep this; the landing page
     overrides it with glass in the GLASS THEME block at the end of
     this file, paired with globe.js rendering at half resolution
     behind the blur. */
  background: #060a11;
  border-block: 1px solid rgba(204, 213, 174, 0.08);
}
.section-tinted { background: #0a1019; border-block: 1px solid var(--line); }
.section-inner { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem; }
.section-lead { max-width: 58ch; color: var(--moss); }

/* The About section is the one deliberate exception to the opaque rule.
   Fully solid sections back to back made the middle of the page feel
   stiff, so this one lets the earth through as a soft shape behind the
   copy. The trick to keeping it readable is doing the darkening inside
   the filter — brightness() crushes the planet's highlights (ice and
   cloud tops are the bright bits that would otherwise wash out text)
   before the overlay goes on, rather than relying on opacity alone.
   Measured worst case (a pure-white polar-ice pixel sitting directly
   behind a paragraph, before the blur averages it down): 6.0:1 for
   body text, 12.7:1 for headings. Comfortably past WCAG AA, so the
   earth can be left brighter than a first guess would allow.

   globe.js knows about this section: it keeps rendering while #about is
   on screen, but at half resolution, which nobody can tell through a
   40px blur. */
#about.section-tinted {
  background: rgba(6, 10, 17, 0.70);
  backdrop-filter: blur(40px) brightness(0.45) saturate(1.7);
  -webkit-backdrop-filter: blur(40px) brightness(0.45) saturate(1.7);
}
/* No backdrop-filter support: stay opaque rather than unreadable. */
@supports not (backdrop-filter: blur(1px)) {
  #about.section-tinted { background: #0a1019; }
}

/* The map section is the destination of the globe's flight — let it
   show through around the map panel instead of covering it up. */
#map.section {
  background:
    linear-gradient(180deg, #060a11 0%, rgba(6, 10, 17, 0.30) 26%,
                            rgba(6, 10, 17, 0.30) 74%, #060a11 100%);
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.25rem;
  margin-top: 2rem;
}
.card {
  background: var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.5rem;
  contain: layout paint;
  transition: border-color 0.15s ease, transform 0.15s ease, background 0.15s ease;
}
.card:hover { border-color: var(--leaf); transform: translateY(-2px); background: #131c2b; }
.card p { margin-bottom: 0; color: var(--moss); font-size: 0.95rem; }

.steps {
  list-style: none;
  counter-reset: step;
  padding: 0;
  margin: 2rem 0 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.25rem;
}
.step { counter-increment: step; position: relative; padding-top: 2.4rem; }
.step::before {
  content: counter(step, decimal-leading-zero);
  position: absolute;
  top: 0; left: 0;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--pine);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.15rem 0.6rem;
  background: var(--space-2);
}
.step p { color: var(--moss); font-size: 0.95rem; }

/* ---------- Heatmap placeholder ----------
   Sits directly in front of the globe once it has flown in over
   Bulgaria, so it carries a ring of light to separate the two. */
.heatmap {
  position: relative;
  margin-top: 2rem;
  height: 420px;
  border-radius: var(--radius);
  border: 1px solid rgba(204, 213, 174, 0.35);
  overflow: hidden;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(4, 6, 12, 0.6);
  background:
    radial-gradient(circle, rgba(204, 213, 174, 0.16) 1.2px, transparent 1.6px) 0 0 / 22px 22px,
    linear-gradient(180deg, #0d1420, #101a29);
}
.heatmap-badge {
  position: absolute;
  top: 12px; left: 12px;
  z-index: 3;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  color: var(--ink);
  background: rgba(8, 13, 22, 0.88);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0.3rem 0.6rem;
}
.hm-marker {
  position: absolute;
  transform: translate(-50%, -50%);
  z-index: 2;
}
.hm-dot {
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--leaf);
  box-shadow: 0 0 0 6px rgba(224, 229, 182, 0.45);
  animation: pulse 2.4s ease-out infinite;
}
.hm-marker[data-intensity="high"] .hm-dot { background: var(--pine); box-shadow: 0 0 0 9px rgba(204, 213, 174, 0.40); }
.hm-label {
  position: absolute;
  top: 100%; left: 50%;
  transform: translateX(-50%);
  margin-top: 8px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--ink);
  background: rgba(8, 13, 22, 0.85);
  border-radius: 4px;
  padding: 0 0.35rem;
  white-space: nowrap;
}
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(184, 90, 32, 0.35); }
  70%  { box-shadow: 0 0 0 16px rgba(184, 90, 32, 0); }
  100% { box-shadow: 0 0 0 0 rgba(184, 90, 32, 0); }
}
.heatmap-legend {
  list-style: none;
  display: flex;
  gap: 1.5rem;
  flex-wrap: wrap;
  padding: 0;
  margin: 1rem 0 0;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--moss);
}
.heatmap-legend .swatch {
  display: inline-block;
  width: 10px; height: 10px;
  border-radius: 50%;
  margin-right: 0.4rem;
}

/* ---------- Action split & forms ---------- */
.section-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 3rem;
  align-items: start;
}
.panel-form {
  background: var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 2rem;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.45);
}
.panel-form h3 { margin-bottom: 1.2rem; }
.panel-form label {
  display: block;
  font-weight: 600;
  font-size: 0.88rem;
  margin: 1rem 0 0.35rem;
}
.panel-form input,
.panel-form select,
.panel-form textarea,
#auth-form input {
  width: 100%;
  font: inherit;
  font-size: 0.95rem;
  color: var(--ink);
  background: #060a11;
  border: 1.5px solid var(--line);
  border-radius: 10px;
  padding: 0.65rem 0.8rem;
}
/* Native pickers (date, select) render their own chrome — force the
   dark scheme so they don't come back white on a dark form. */
.panel-form input,
.panel-form select,
.panel-form textarea,
#auth-form input { color-scheme: dark; }
.panel-form input::placeholder,
.panel-form textarea::placeholder { color: #6f7d71; }
.panel-form input:focus,
.panel-form select:focus,
.panel-form textarea:focus,
#auth-form input:focus {
  outline: none;
  border-color: var(--leaf);
  background: #08101a;
}
.panel-form .btn { margin-top: 1.4rem; }
.optional { font-weight: 400; color: var(--moss); }
.field-hint { font-size: 0.8rem; color: var(--moss); margin: 0.3rem 0 0; }

/* Honeypot — visually removed, still in the DOM for bots */
.hp {
  position: absolute !important;
  left: -9999px !important;
  width: 1px; height: 1px;
  opacity: 0;
}

.form-status { min-height: 1.2em; font-size: 0.88rem; margin: 0.8rem 0 0; }
.form-status.ok { color: var(--pine); font-weight: 600; }
.form-status.err { color: #ff9b8a; font-weight: 600; }

/* ---------- Footer ---------- */
.site-footer {
  background: #03050a;
  color: var(--ink);
  margin-top: 0;
  border-top: 1px solid var(--line);
}
.footer-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  /* The brand block gets the room it needs and no more; the two link
     columns are a fixed width so they sit next to each other on the
     right instead of drifting apart across a 2fr gap. */
  padding: 3.5rem 1.25rem 2.25rem;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  column-gap: 4rem;
  row-gap: 2.5rem;
  align-items: start;
}

.footer-brand { max-width: 34ch; }
.footer-brand .brand { margin-bottom: 0.9rem; }
.footer-tag { font-size: 0.92rem; color: var(--moss); margin: 0 0 0.6rem; }
.footer-place {
  font-family: var(--font-mono);
  font-size: 0.76rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--moss);
  margin: 0;
}

/* Both link columns share one layout so their baselines line up. */
.footer-col {
  display: grid;
  gap: 0.65rem;
  justify-items: start;
  min-width: 8.5rem;
}
.footer-heading {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--moss);
  margin: 0 0 0.15rem;
}
.footer-col a,
.footer-col .footer-legal-btn {
  color: var(--ink);
  font-size: 0.92rem;
  font-weight: 500;
  line-height: 1.3;
  white-space: nowrap;
}

/* Bottom bar — the copyright and strapline used to be jammed into the
   right-hand column, which is what made the legal links wrap raggedly. */
.footer-bar {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 1.25rem 1.25rem 2.25rem;
  border-top: 1px solid rgba(204, 213, 174, 0.10);
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 2rem;
  justify-content: space-between;
  align-items: baseline;
}
.footer-legal { font-size: 0.8rem; color: var(--moss); margin: 0; }

/* ---------- Account modal ---------- */
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: rgba(2, 4, 8, 0.88);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
/* The hidden attribute must always win, even over display:flex above */
.modal-backdrop[hidden] { display: none; }
/* Lock page scroll only while the modal is open (class set by JS) */
body.modal-open { overflow: hidden; }
.modal {
  position: relative;
  background: var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 2rem;
  width: min(420px, 100%);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.7);
}
.modal-close {
  position: absolute;
  top: 0.8rem; right: 0.9rem;
  border: 0;
  background: transparent;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--moss);
  cursor: pointer;
}
.auth-tabs {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
}
.auth-tab {
  flex: 1;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.04);
  border-radius: 999px;
  padding: 0.5rem;
  font: inherit;
  font-weight: 600;
  font-size: 0.88rem;
  color: var(--moss);
  cursor: pointer;
}
.auth-tab.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--ink-invert);
}
#auth-form label {
  display: block;
  font-weight: 600;
  font-size: 0.88rem;
  margin: 1rem 0 0.35rem;
}
.role-choice {
  border: 0;
  padding: 0;
  margin: 0.4rem 0 0;
}
.role-choice legend {
  font-weight: 600;
  font-size: 0.88rem;
  padding: 0;
  margin-bottom: 0.4rem;
}
.role-options { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; }
.role-option { position: relative; display: block; cursor: pointer; margin: 0; }
.role-option input {
  position: absolute;
  opacity: 0;
  width: 100%; height: 100%;
  margin: 0;
  cursor: pointer;
}
.role-option span {
  display: block;
  border: 1.5px solid var(--line);
  border-radius: 10px;
  padding: 0.6rem 0.7rem;
  font-weight: 600;
  font-size: 0.88rem;
  text-align: center;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.role-option small {
  display: block;
  font-weight: 400;
  font-size: 0.72rem;
  color: var(--moss);
  margin-top: 0.15rem;
}
.role-option input:checked + span {
  border-color: var(--accent);
  background: var(--mist);
}
.role-option input:focus-visible + span {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
}
#auth-form .btn { margin-top: 1.4rem; }
.auth-divider {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin: 1.2rem 0;
  color: var(--moss);
  font-size: 0.8rem;
}
.auth-divider::before,
.auth-divider::after {
  content: "";
  flex: 1;
  border-top: 1px solid var(--line);
}
.btn-google {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  background: rgba(255, 255, 255, 0.05);
  color: var(--ink);
  border-color: var(--line);
}
.btn-google:hover { border-color: var(--accent); }

.auth-note { font-size: 0.8rem; color: var(--moss); margin-top: 1.2rem; }
.auth-note code { font-family: var(--font-mono); font-size: 0.78rem; }

/* ---------- Profile page ---------- */
.profile-page {
  max-width: 880px;
  margin: 0 auto;
  padding: 3rem 1.25rem 4rem;
}
.profile-state { text-align: center; padding: 4rem 0; }
.profile-state .btn { margin-top: 1rem; }
.profile-state .section-lead { margin-inline: auto; }
.profile-header-nav a { display: inline !important; } /* keep visible on mobile */
/* Only the "← Back to…" link is anchored next to the logo — everything
   else (Team admin, Sign out, language switch) is a right-aligned
   utility cluster. The nav stretches to fill the header, and auto
   margin on the back-link pushes the rest to the far right edge,
   regardless of which of those items happen to be [hidden]. */
.profile-header-nav { flex: 1; }
.profile-header-nav > a:first-child { margin-right: auto; }

.profile-heading { margin-bottom: 2rem; }
.profile-heading h1 { font-size: clamp(1.9rem, 4vw, 2.6rem); margin-bottom: 0; }

.profile-grid {
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: 1.5rem;
  align-items: start;
}
.profile-card {
  background: var(--mist);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 2rem;
}
.profile-card h2 { font-size: 1.25rem; }
.profile-identity { text-align: center; }

.avatar-wrap {
  width: 128px; height: 128px;
  margin: 0 auto 1rem;
  border-radius: 50%;
  overflow: hidden;
  border: 3px solid var(--space-2);
  box-shadow: 0 0 0 2px var(--line);
  background: var(--space-2);
  display: flex;
  align-items: center;
  justify-content: center;
}
.avatar-wrap img { width: 100%; height: 100%; object-fit: cover; }
.avatar-fallback {
  font-family: var(--font-display);
  font-size: 3rem;
  font-weight: 700;
  color: var(--pine);
}
.profile-email {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  color: var(--moss);
  margin: 0 0 0.6rem;
  word-break: break-all;
}
.role-badge {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  margin-bottom: 1.2rem;
  background: var(--pine);
  color: var(--ink-invert);
}
.role-badge[data-role="worker"] { background: var(--accent); color: var(--ink-invert); }
.role-badge:empty { display: none; }
.avatar-upload-label { display: inline-block; cursor: pointer; }

.profile-card form label {
  display: block;
  font-weight: 600;
  font-size: 0.88rem;
  margin: 1rem 0 0.35rem;
}
.profile-card form input,
.profile-card form textarea {
  width: 100%;
  font: inherit;
  font-size: 0.95rem;
  color: var(--ink);
  background: #060a11;
  color-scheme: dark;
  border: 1.5px solid var(--line);
  border-radius: 10px;
  padding: 0.65rem 0.8rem;
}
.profile-card form input:focus,
.profile-card form textarea:focus {
  outline: none;
  border-color: var(--leaf);
}
.profile-card form .btn { margin-top: 1.2rem; }
.profile-divider {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 2rem 0;
}

@media (max-width: 720px) {
  .profile-grid { grid-template-columns: 1fr; }
}

/* When Leaflet takes over the heatmap panel, drop the dot-grid bg */
.heatmap-live { background: #0b1018; }
.heatmap-live .heatmap-badge { z-index: 1000; }

/* OpenStreetMap only ships a light tile set. Rather than swap tile
   providers, invert the tile pane so the map sits in the dark theme
   without glaring against the globe behind it. The filter is scoped
   to the tiles only, so markers, popups and controls keep their own
   colors. */
.leaflet-tile-pane {
  filter: invert(1) hue-rotate(185deg) brightness(0.85);
}
.leaflet-container { background: #0b1018 !important; }
.leaflet-control-attribution {
  background: rgba(8, 13, 22, 0.85) !important;
  color: #9aab9c !important;
}
.leaflet-control-attribution a { color: #ccd5ae !important; }
.leaflet-bar a {
  background: #121a29 !important;
  color: #e9eee4 !important;
  border-bottom-color: rgba(204, 213, 174, 0.2) !important;
}
.leaflet-bar a:hover { background: #16202f !important; }
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
  background: #121a29 !important;
  color: #e9eee4 !important;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.6) !important;
}

/* CRITICAL: Leaflet uses internal z-indexes up to ~1000. Isolating
   each map's stacking context traps those values inside the panel,
   so maps can never float above the header, modal, or anything else. */
.heatmap, .event-map, .admin-map {
  position: relative;
  isolation: isolate;
  z-index: 0;
  contain: layout paint;
}
.hm-popup { font-family: var(--font-body); }
.hm-popup strong { display: block; margin-bottom: 0.2rem; }
.hm-popup-status {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--moss);
  margin-bottom: 0.3rem;
}
.hm-popup a { font-weight: 600; }

/* ---------- Event page ---------- */
.event-page {
  max-width: 760px;
  margin: 0 auto;
  padding: 3rem 1.25rem 4rem;
}
.event-meta { display: flex; gap: 0.6rem; flex-wrap: wrap; margin: 1rem 0 1.5rem; }
.event-chip {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.05em;
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  background: var(--pine);
  color: var(--ink-invert);
}
.event-chip-quiet { background: var(--mist); color: var(--ink); border: 1px solid var(--line); }
.event-description {
  font-size: 1.05rem;
  color: var(--moss);
  max-width: 60ch;
  margin-bottom: 2rem;
  white-space: pre-line; /* respects paragraph breaks the team types */
}
.event-map {
  height: 320px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  overflow: hidden;
  margin-top: 1.5rem;
  background: #0b1018;
}
.event-cta {
  margin-top: 2.5rem;
  background: var(--mist);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 2rem;
}
.event-cta h2 { font-size: 1.35rem; }
.event-cta .btn { margin-top: 0.6rem; }

/* ---------- Admin panel ---------- */
.admin-howto {
  background: var(--mist);
  border: 1px solid var(--line);
  border-left: 4px solid var(--leaf);
  border-radius: 10px;
  padding: 1.2rem 1.5rem;
  margin-bottom: 1.5rem;
  font-size: 0.92rem;
}
.admin-howto ol { margin: 0.5rem 0; padding-left: 1.3rem; }
.admin-howto li { margin: 0.25rem 0; }
.admin-howto p { margin: 0.5rem 0 0; color: var(--moss); }
.place-search-row { display: flex; gap: 0.5rem; }
.place-search-row input { flex: 1; }
.place-search-row .btn { flex-shrink: 0; }

.admin-page {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 3rem 1.25rem 4rem;
}
.admin-grid {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: 1.5rem;
  align-items: start;
}
.admin-map {
  height: 300px;
  border-radius: 10px;
  border: 1.5px solid var(--line);
  overflow: hidden;
  margin-top: 0.35rem;
  background: #0b1018;
  cursor: crosshair;
}
.coords-readout {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  color: var(--ink);
  margin: 0.5rem 0 0;
}
.coords-label { color: var(--moss); }
.check-row {
  display: flex !important;
  align-items: center;
  gap: 0.6rem;
  margin-top: 1.2rem !important;
  cursor: pointer;
}
.check-row input {
  width: auto !important;
  accent-color: var(--pine);
  transform: scale(1.2);
}
.admin-form-actions { display: flex; gap: 0.6rem; align-items: center; }
.btn-small { padding: 0.35rem 0.85rem; font-size: 0.82rem; }
.btn-danger { color: #ff9b8a; }
.btn-danger:hover { border-color: #ff9b8a; color: #ff9b8a; }

/* ---------- Admin dashboard: KPI cards + recent activity ---------- */
.dash-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
  margin-bottom: 1rem;
}
.dash-card {
  background: var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem 1.4rem;
  transition: border-color 0.15s ease, transform 0.2s ease;
}
.dash-card:hover { border-color: var(--leaf); transform: translateY(-2px); }
.dash-num {
  display: block;
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 700;
  color: var(--pine);
}
.dash-label { font-size: 0.82rem; color: var(--moss); }

.activity-list { list-style: none; padding: 0; margin: 1rem 0 0; }
.activity-item {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--line);
}
.activity-item.is-handled { opacity: 0.5; }
.activity-badge { flex-shrink: 0; }
.activity-info { flex: 1; display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }

@media (max-width: 720px) {
  .dash-grid { grid-template-columns: repeat(2, 1fr); }
  .activity-item { flex-wrap: wrap; }
}

.event-list { list-style: none; padding: 0; margin: 1rem 0 0; }
.event-list-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--line);
}
.event-list-item.is-inactive { opacity: 0.55; }
.event-list-meta {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--moss);
  margin-top: 0.15rem;
}
.event-list-actions { display: flex; gap: 0.4rem; flex-shrink: 0; }
.event-list-empty { color: var(--moss); padding: 1rem 0; }

@media (max-width: 900px) {
  .admin-grid { grid-template-columns: 1fr; }
}

/* ---------- Admin panel: mobile optimization ---------- */
@media (max-width: 640px) {
  .admin-page { padding: 1.6rem 0.9rem 3rem; }
  .admin-howto { padding: 1rem 1.1rem; font-size: 0.88rem; }
  .admin-page .profile-card { padding: 1.3rem; }
  .admin-map { height: 260px; }

  /* Event rows stack: name on top, action buttons in a row below */
  .event-list-item {
    flex-direction: column;
    align-items: stretch;
    gap: 0.7rem;
  }
  .event-list-actions {
    width: 100%;
    flex-wrap: wrap;
  }
  .event-list-actions .btn {
    flex: 1 1 calc(50% - 0.4rem);
    text-align: center;
  }

  /* Finger-sized touch targets */
  .btn-small { padding: 0.55rem 0.9rem; font-size: 0.88rem; }
  .admin-form-actions { flex-wrap: wrap; }
  .admin-form-actions .btn { flex: 1 1 auto; text-align: center; }
  .place-search-row .btn { padding-inline: 1rem; }
  .coords-readout { font-size: 0.78rem; }
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ---------- Responsive ---------- */
@media (max-width: 900px) {
  .section-split, .card-grid { grid-template-columns: 1fr; }
  .steps { grid-template-columns: repeat(2, 1fr); }
  .impact-inner { grid-template-columns: 1fr; gap: 1.2rem; }
  .footer-inner { grid-template-columns: 1fr 1fr; column-gap: 2rem; }
  .footer-brand { grid-column: 1 / -1; }
}
@media (max-width: 640px) {
  .header-inner { justify-content: space-between; }
  .mode-switch { order: 3; width: 100%; }
  /* Direct children only — the account dropdown is inside .header-nav
     and its links must stay visible. */
  .header-nav > a { display: none; }      /* keep only Account on tiny screens */
  .header-nav > a#admin-link:not([hidden]) { display: inline-block; } /* admins always see it */
  .steps { grid-template-columns: 1fr; }
  .heatmap { height: 340px; }
}

/* ---------- Cookie consent banner ---------- */
.cookie-bar {
  position: fixed;
  left: 1rem; right: 1rem; bottom: 1rem;
  z-index: 2500;
  max-width: 720px;
  margin: 0 auto;
  background: rgba(10, 15, 24, 0.96);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.1rem 1.3rem;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.7);
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
}
.cookie-bar p { margin: 0; font-size: 0.85rem; max-width: 46ch; color: var(--moss); }
.cookie-bar-actions { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.cookie-bar-link { color: var(--pine); font-size: 0.82rem; font-weight: 600; }
.cookie-bar .btn-small { padding: 0.5rem 1rem; font-size: 0.82rem; }
.cookie-bar .btn-outline { border-color: rgba(233, 238, 228, 0.35); color: var(--ink); }
.cookie-bar .btn-outline:hover { border-color: var(--leaf); color: var(--leaf); }
@media (max-width: 560px) {
  .cookie-bar { flex-direction: column; align-items: stretch; }
  .cookie-bar-actions { justify-content: flex-end; }
}

/* ---------- FAQ accordion (details/summary, no JS needed) ---------- */
.faq-list { display: grid; gap: 0.75rem; margin-top: 2rem; }
.faq-item {
  background: var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.3rem 1.25rem;
  /* Opening or hovering an item shouldn't force the browser to
     re-evaluate layout and paint for the whole FAQ list. */
  contain: layout paint;
}
.faq-item summary {
  cursor: pointer;
  list-style: none;
  padding: 1rem 0;
  font-weight: 600;
  font-size: 1rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "+";
  font-family: var(--font-mono);
  font-size: 1.2rem;
  color: var(--pine);
  flex-shrink: 0;
  transition: transform 0.15s ease;
}
.faq-item[open] summary::after { transform: rotate(45deg); }
.faq-item p { margin: 0 0 1.1rem; color: var(--moss); }

/* ---------- Legal modal: draft notice banner ---------- */
.legal-draft-notice {
  background: rgba(201, 130, 42, 0.12);
  border: 1px solid rgba(201, 130, 42, 0.35);
  border-left: 4px solid #d9933b;
  border-radius: 10px;
  padding: 1rem 1.25rem;
  margin-bottom: 2rem;
  font-size: 0.9rem;
  color: #e8c493;
}
.legal-draft-notice strong { display: block; margin-bottom: 0.2rem; }
/* Only shown to Bulgarian readers — the drafts themselves stay English
   until a lawyer produces the BG versions. */
.legal-lang-note { display: none; margin-top: 0.5rem; font-style: italic; }
html[lang="bg"] .legal-lang-note { display: block; }

/* ---------- Pricing hint on B2B service cards ---------- */
.pricing-note {
  display: block;
  margin-top: 0.7rem;
  font-family: var(--font-mono);
  font-size: 0.76rem;
  color: var(--moss);
}

/* ---------- GDPR consent row + forgot password link ---------- */
.consent-row { font-size: 0.82rem; align-items: flex-start !important; }
.consent-row span a { font-weight: 600; }
.auth-forgot {
  display: inline-block;
  margin-top: 0.5rem;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 0.82rem;
  color: var(--ink);
  cursor: pointer;
}
.auth-forgot:hover { text-decoration: underline; }

/* ---------- Footer legal row ---------- */
.footer-legal-btn {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  text-align: left;
  color: var(--ink);
  cursor: pointer;
}
.footer-legal-btn:hover { text-decoration: underline; }

/* Inline text-link-styled buttons (used where legal content opens as a
   popup instead of navigating — keeps the <a>-like look with a <button>
   semantics so it doesn't behave like a real link). */
.inline-link-btn {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  font-size: inherit;
  font-weight: 600;
  color: var(--pine);
  cursor: pointer;
  text-decoration: none;
}
.inline-link-btn:hover { text-decoration: underline; }

/* ---------- Legal popup modal ---------- */
.modal-legal { width: min(680px, 100%); max-height: 82vh; overflow-y: auto; }
.legal-modal-body h3 { font-size: 1.1rem; margin-top: 1.6rem; margin-bottom: 0.4rem; }
.legal-modal-body p, .legal-modal-body li { color: var(--moss); font-size: 0.95rem; }
.legal-modal-body ul { padding-left: 1.2rem; }
.legal-modal-body code { font-family: var(--font-mono); font-size: 0.85em; }

/* ============================================================
   ANIMATIONS & INTERACTIONS
   The .js-ready gate matters: .reveal only starts hidden once
   shared.js has confirmed it's running and will actually reveal
   it. Without JS, .reveal content is fully visible by default —
   no permanently-invisible sections if a script fails to load.
   ============================================================ */

/* Anchored sections shouldn't land partly under the sticky header */
section[id] { scroll-margin-top: 84px; }

/* ---------- Scroll reveal ---------- */
.js-ready .reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.6s ease, transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
.js-ready .reveal.reveal-visible {
  opacity: 1;
  transform: none;
}
/* Staggered children inside a reveal group get a small delay ladder */
.js-ready .reveal-group > * { transition-delay: calc(var(--reveal-index, 0) * 70ms); }

/* ---------- Header: shadow + shrink on scroll ---------- */
.site-header {
  transition: box-shadow 0.25s ease, background 0.25s ease;
}
.site-header.is-scrolled {
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.45);
  background: rgba(5, 8, 14, 0.9);
}

/* ---------- Nav underline hover ---------- */
.header-nav > a, .footer-nav a {
  position: relative;
}
.header-nav > a::after {
  content: "";
  position: absolute;
  left: 0; right: 100%;
  bottom: -3px;
  height: 2px;
  background: var(--accent);
  border-radius: 2px;
  transition: right 0.2s ease;
}
.header-nav > a:hover::after { right: 0; }

/* ---------- Brand mark: gentle breathing pulse ---------- */
.js-ready .brand-mark {
  animation: brand-breathe 4.5s ease-in-out infinite;
}
@keyframes brand-breathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.08); }
}

/* ---------- Buttons: press feedback ---------- */
.btn:active { transform: translateY(0) scale(0.96); }
.mode-btn { transition: color 0.2s ease, transform 0.15s ease; }
.mode-btn:active { transform: scale(0.95); }

/* ---------- Cards: richer hover ---------- */
.card {
  transition: border-color 0.15s ease, transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}
.card:hover {
  transform: translateY(-3px);
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.5);
}

/* ---------- FAQ items: hover lift ---------- */
.faq-item { transition: border-color 0.15s ease, transform 0.15s ease; }
.faq-item:hover { border-color: var(--leaf); }

/* ---------- Modal: pop-in on open (CSS animations replay whenever
   an element goes from display:none to displayed, so no JS needed) ---------- */
.modal-backdrop:not([hidden]) { animation: modal-fade 0.18s ease; }
.modal-backdrop:not([hidden]) .modal { animation: modal-pop 0.24s cubic-bezier(0.16, 1, 0.3, 1); }
@keyframes modal-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes modal-pop {
  from { opacity: 0; transform: translateY(12px) scale(0.97); }
  to { opacity: 1; transform: none; }
}

/* ---------- Cookie bar: slide up on entrance ---------- */
.cookie-bar { animation: cookie-slide-up 0.35s cubic-bezier(0.16, 1, 0.3, 1); }
@keyframes cookie-slide-up {
  from { opacity: 0; transform: translateY(24px); }
  to { opacity: 1; transform: none; }
}

/* ---------- Mode content cross-fade, upgraded ---------- */
main.is-switching { opacity: 0; transform: translateY(6px); }
main { transition: opacity 0.22s ease, transform 0.22s ease; }

/* ---------- Impact numbers: little pop when their count-up finishes ---------- */
.impact-num.is-counted { animation: count-pop 0.4s ease; }
@keyframes count-pop {
  0% { transform: scale(1); }
  40% { transform: scale(1.12); }
  100% { transform: scale(1); }
}

/* ---------- Back to top ---------- */
.back-to-top {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: rgba(14, 21, 34, 0.92);
  color: var(--ink);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.55);
  /* Always on screen, bottom right — it no longer fades in past a
     scroll threshold, so there is no .is-visible state any more and
     shared.js does not track scroll position for it. */
  opacity: 1;
  pointer-events: auto;
  display: grid;
  place-items: center;
  transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease;
  z-index: 40;
}
.back-to-top:hover {
  background: var(--accent);
  color: var(--ink-invert);
  transform: translateY(-2px);
}
.back-to-top:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
@media (max-width: 560px) {
  .back-to-top { right: 1rem; bottom: 1rem; width: 40px; height: 40px; }
}

/* ---------- Respect reduced motion: kill everything above ---------- */
@media (prefers-reduced-motion: reduce) {
  .js-ready .reveal { opacity: 1 !important; transform: none !important; }
  /* globe.js already renders a single still frame in this mode; make
     sure the canvas doesn't fade either. */
  #globe-canvas { transition: none !important; }
  .brand-mark { animation: none !important; }
  .modal-backdrop:not([hidden]),
  .modal-backdrop:not([hidden]) .modal,
  .cookie-bar,
  .impact-num.is-counted {
    animation: none !important;
  }
  .back-to-top { transition: background 0.15s ease !important; }
  .back-to-top:hover { transform: none; }
}

/* ============================================================
   GLASS THEME — landing page only (body.glass-page on index.html).
   Every major surface between the hero and the bottom of the footer
   becomes translucent glass so the globe shows through the whole
   page. Kept affordable by three rules:
   1. globe.js treats all glass sections as "soft" windows — half
      render resolution and a capped frame rate while only glass is
      on screen. Nobody can tell through the blur.
   2. Raised elements INSIDE a glass section (cards, forms, FAQ
      items) use plain rgba surfaces, never their own
      backdrop-filter — nested blurs multiply compositor cost for
      no visible gain.
   3. #map keeps its own mostly-transparent gradient (no blur):
      it's the destination of the globe's flight and must stay sharp.
   #about keeps its original, contrast-measured recipe — the rule
   below deliberately loses to #about.section-tinted on specificity.
   ============================================================ */

body.glass-page .site-header {
  background: rgba(6, 10, 17, 0.62);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  backdrop-filter: blur(14px) saturate(1.4);
}
body.glass-page .site-header.is-scrolled {
  background: rgba(5, 8, 14, 0.70);
}

body.glass-page #services,
body.glass-page #faq,
body.glass-page #action {
  background: rgba(6, 10, 17, 0.55);
  -webkit-backdrop-filter: blur(26px) brightness(0.52) saturate(1.5);
  backdrop-filter: blur(26px) brightness(0.52) saturate(1.5);
}

body.glass-page .impact {
  background:
    linear-gradient(180deg, rgba(204, 213, 174, 0.09), rgba(204, 213, 174, 0.02)),
    rgba(7, 12, 20, 0.50);
  -webkit-backdrop-filter: blur(26px) brightness(0.52) saturate(1.5);
  backdrop-filter: blur(26px) brightness(0.52) saturate(1.5);
}

body.glass-page .site-footer {
  background: rgba(3, 5, 10, 0.58);
  -webkit-backdrop-filter: blur(26px) brightness(0.48) saturate(1.5);
  backdrop-filter: blur(26px) brightness(0.48) saturate(1.5);
}

/* Raised surfaces inside glass sections: translucent, no blur. */
body.glass-page .card,
body.glass-page .faq-item { background: rgba(14, 21, 34, 0.55); }
body.glass-page .card:hover { background: rgba(19, 28, 43, 0.75); }
body.glass-page .step::before { background: rgba(14, 21, 34, 0.75); }
body.glass-page .panel-form { background: rgba(14, 21, 34, 0.62); }
body.glass-page .panel-form input,
body.glass-page .panel-form select,
body.glass-page .panel-form textarea {
  background: rgba(6, 10, 17, 0.72);
}
body.glass-page .panel-form input:focus,
body.glass-page .panel-form select:focus,
body.glass-page .panel-form textarea:focus {
  background: rgba(8, 16, 26, 0.88);
}

/* No backdrop-filter → glass would be unreadable noise. Fall back to
   the original opaque surfaces. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  body.glass-page .site-header,
  body.glass-page #services,
  body.glass-page #faq,
  body.glass-page #action { background: #060a11; }
  body.glass-page .impact {
    background:
      linear-gradient(180deg, rgba(204, 213, 174, 0.09), rgba(204, 213, 174, 0.02)),
      #070c14;
  }
  body.glass-page .site-footer { background: #03050a; }
}

/* Users who ask the OS for less transparency get the opaque look. */
@media (prefers-reduced-transparency: reduce) {
  body.glass-page .site-header,
  body.glass-page #services,
  body.glass-page #faq,
  body.glass-page #action {
    background: #060a11;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  body.glass-page .impact {
    background:
      linear-gradient(180deg, rgba(204, 213, 174, 0.09), rgba(204, 213, 174, 0.02)),
      #070c14;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  body.glass-page .site-footer {
    background: #03050a;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}
