/* PlayPulse Booking Portal — public storefront design tokens (design-agent conventions)
 *
 * Palette/type lifted 1:1 from the Flutter app's own design tokens
 * (lib/theme/app_theme.dart's AppColors — the Claude Design "nocturne"
 * system: dark navy-violet surface, violet accent, Inter) so a visitor
 * who's used the app doesn't land on a differently-colored, differently-
 * shaped website. Every color/radius/shadow below flows from these same
 * ~10 custom properties into every page (search, complex.php, account,
 * booking flow) — nothing is hardcoded per-page — so this one edit is
 * what re-skins the whole storefront.
 */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Cairo:wght@400;600;700&display=swap');

:root {
  /* AppColors.bg / .surface, one step lighter for -hover/-input so
     inputs and hover states are still visibly distinct on a page that
     (unlike the app) has no separate Scaffold vs. Card elevation cue. */
  --bg-base: #161826;
  --bg-surface: #1b1d2c;
  --bg-card: #232532;
  --bg-hover: #2b2e40;
  --bg-input: #1c1e2c;

  /* AppColors.text / .textMuted / .textFaint (text @ 70% / 60%) */
  --text-primary: #e9e9ed;
  --text-secondary: rgba(233, 233, 237, 0.7);
  --text-muted: rgba(233, 233, 237, 0.6);

  /* AppColors.divider (text @ 16%) / .accent */
  --border: rgba(233, 233, 237, 0.16);
  --border-focus: #9184d9;

  /* AppColors.accent / .accent2 / accentSoft (accent @ 14%) */
  --accent: #9184d9;
  --accent-light: #a7a1db;
  --accent-glow: rgba(145, 132, 217, 0.18);

  /* --yellow/--red now match AppColors.warning/.danger exactly (the app's
     "pending"/error tag colors); --green/--blue/--purple/--orange are
     status/accent colors the app doesn't define its own equivalent for,
     kept close to their originals — still legible against the new
     darker violet-tinted background, just not literally lifted from
     AppColors like the rest of this palette. */
  --green: #34d399; --green-bg: rgba(52,211,153,0.14);
  --yellow: #cc9a3b; --yellow-bg: rgba(204, 154, 59, 0.14);
  --red: #b5484e; --red-bg: rgba(181, 72, 78, 0.14);
  --blue: #7aa8ff; --blue-bg: rgba(122, 168, 255, 0.12);
  --purple: #a7a1db; --purple-bg: rgba(167, 161, 219, 0.14);
  --orange: #fb923c; --orange-bg: rgba(251,146,60,0.14);

  /* App buttons/cards/inputs all round to a consistent 12px; chips/hero
     panels get a slightly larger 16px, same relationship as the app's
     12px controls vs. its 16-18px card containers. */
  --radius: 12px;
  --radius-lg: 16px;
  --shadow: 0 10px 30px rgba(0,0,0,0.35);
  --shadow-sm: 0 2px 8px rgba(0,0,0,0.25);
  --header-h: 68px;
  --pad: 1.25rem;
}

/* The app is dark-only (no light theme) — the storefront now follows
   suit instead of flipping to a light palette the app has no equivalent
   for, so "prefers-color-scheme: light" visitors still see the same
   nocturne look the app always shows them. */

* { box-sizing: border-box; }
body {
  margin: 0; background: var(--bg-base); color: var(--text-primary);
  font-family: 'Inter', system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}
body.lang-ar { font-family: 'Cairo', system-ui, sans-serif; direction: rtl; }

a { color: inherit; text-decoration: none; }
.pw { max-width: 1280px; margin: 0 auto; padding: 0 var(--pad); }
.section-pad { padding: 3.5rem 0; }

header.site-header {
  position: sticky; top: 0; z-index: 40; height: var(--header-h);
  background: var(--bg-surface); border-bottom: 1px solid var(--border);
  display: flex; align-items: center;
}
header.site-header .pw { display: flex; align-items: center; justify-content: space-between; width: 100%; }
.logo { display: flex; align-items: center; gap: 0.5rem; font-weight: 800; font-size: 1.15rem; letter-spacing: -0.02em; }
.logo .accent { color: var(--accent); }
.logo.active { color: var(--accent); }
.logo-icon { height: 34px; width: 34px; object-fit: contain; flex-shrink: 0; }

nav.main-nav { display: flex; gap: 1.5rem; align-items: center; }
nav.main-nav a { color: var(--text-secondary); font-weight: 500; position: relative; padding: 0.25rem 0; }
nav.main-nav a:hover { color: var(--text-primary); }
/* Current page — a distinct color plus an underline so it isn't color
   alone carrying the signal (contrast/accessibility). */
nav.main-nav a.active { color: var(--accent); font-weight: 700; }
nav.main-nav a.active::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: var(--accent); border-radius: 2px;
}

/* Notification bell — the nav link itself already inherits the plain a/
   a:hover/a.active rules above; this only styles the dot. */
.nav-notif-link { font-size: 1.05rem; line-height: 1; padding: 0.25rem 0.1rem; }
.notif-badge {
  position: absolute; top: -2px; right: -4px; width: 8px; height: 8px;
  border-radius: 50%; background: var(--danger, #e05656); border: 1.5px solid var(--bg-base);
}

/* Hamburger toggle — hidden on desktop, shown only under the same
   breakpoint where the nav collapses (see the nav.main-nav rules in the
   mobile media query below). Three <span> bars animate into an X via
   .is-open, set by App.initMobileNav() in assets/js/app.js. */
.nav-toggle {
  display: none; flex-direction: column; justify-content: center; gap: 5px;
  width: 40px; height: 40px; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--bg-hover); cursor: pointer; padding: 0;
}
.nav-toggle span {
  display: block; width: 18px; height: 2px; margin: 0 auto; background: var(--text-primary);
  border-radius: 2px; transition: transform .2s ease, opacity .2s ease;
}
.nav-toggle.is-open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle.is-open span:nth-child(2) { opacity: 0; }
.nav-toggle.is-open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Animated hero slider — admin-managed slides (booking-admin > Storefront
   > Hero Slides). Slides are stacked absolutely and cross-faded by
   toggling .is-active (see assets/js/app.js is not involved here; the
   slider's own small script lives inline in index.php next to its
   markup, same convention as every other page-specific script). Falls
   back to the plain static hero text/search bar when no slides are
   configured yet, so a fresh install never shows an empty box. */
.hero { position: relative; padding: 4.5rem 0 3rem; text-align: center; overflow: hidden; }
.hero-slider { position: absolute; inset: 0; z-index: 0; }
.hero-slide {
  position: absolute; inset: 0; background-size: cover; background-position: center;
  opacity: 0; transition: opacity 1.1s ease; pointer-events: none;
}
.hero-slide.is-active { opacity: 1; }
.hero-slider::after {
  content: ''; position: absolute; inset: 0;
  /* Matches --bg-base (#161826) now that the site no longer flips to a
     light gradient here — see the :root comment above on why. */
  background: linear-gradient(180deg, rgba(22,24,38,0.55) 0%, rgba(22,24,38,0.85) 100%);
}
.hero-slider-dots { position: absolute; z-index: 2; bottom: 1.1rem; left: 50%; transform: translateX(-50%); display: flex; gap: 0.4rem; }
.hero-slider-dots button {
  width: 8px; height: 8px; border-radius: 999px; border: none; background: rgba(255,255,255,0.4);
  cursor: pointer; padding: 0; transition: background .2s, width .2s;
}
.hero-slider-dots button.is-active { background: #fff; width: 22px; }
.hero > .pw { position: relative; z-index: 1; }
.hero h1 { font-size: clamp(2rem, 4vw, 3rem); font-weight: 800; letter-spacing: -0.02em; margin: 0 0 0.75rem; }
.hero p { color: var(--text-secondary); font-size: 1.1rem; max-width: 640px; margin: 0 auto 2rem; }
.hero.has-slider h1, .hero.has-slider p { color: #fff; text-shadow: 0 2px 12px rgba(0,0,0,0.35); }
.hero.has-slider p { color: rgba(255,255,255,0.85); }

.search-bar {
  display: flex; gap: 0.5rem; background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: 0.5rem; box-shadow: var(--shadow-sm); max-width: 720px; margin: 0 auto;
  flex-wrap: wrap;
}
.search-bar input, .search-bar select {
  flex: 1; min-width: 140px; border: none; background: transparent; color: var(--text-primary);
  padding: 0.75rem 1rem; font-size: 0.95rem; outline: none;
}

.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1.25rem; }
.card {
  /* position:relative added so .distance/.featured-ribbon/.offer-badge
     (all position:absolute) anchor to the CARD's own box — without this
     they'd fall back to the nearest positioned ancestor further up the
     page (or the viewport, with nothing else positioned), which is not
     where any of them are meant to sit. */
  position: relative;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-lg);
  overflow: hidden; box-shadow: var(--shadow-sm); transition: transform .15s ease, box-shadow .15s ease;
}
.card:hover { transform: translateY(-2px); box-shadow: var(--shadow); }
/* Featured — a highlighted/promoted complex (booking-admin > Tenants >
   Featured), styled like a restrained "Sponsored" tag rather than a loud
   takeover: a corner ribbon plus a subtle accent border/glow on the whole
   card, nothing that fights with the cover image or the offer badge. */
.card.is-featured { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-glow); }
.featured-ribbon {
  position: absolute; top: 0.6rem; left: 0.6rem; z-index: 2;
  background: var(--accent); color: #fff; font-size: 0.7rem; font-weight: 700;
  padding: 0.2rem 0.6rem; border-radius: 999px; letter-spacing: 0.02em;
}
/* Offer/promo badge — independent of featured, so it gets its own corner
   (bottom-left) rather than competing with the featured ribbon (top-left)
   or the distance badge (top-right) for the same spot. */
.offer-badge {
  position: absolute; bottom: 0.6rem; left: 0.6rem; z-index: 2;
  background: var(--orange); color: #1a0f00; font-size: 0.7rem; font-weight: 700;
  padding: 0.2rem 0.6rem; border-radius: 999px;
}
/* complex.php's own offers panel — the fuller title+description version
   of the same offers the search-result card only teases via .offer-badge. */
.offers-panel { display: flex; flex-direction: column; gap: 0.6rem; }
.offer-card {
  background: var(--orange-bg); border: 1px solid var(--orange); border-radius: var(--radius);
  padding: 0.75rem 1rem;
}
.offer-badge-inline {
  display: inline-block; background: var(--orange); color: #1a0f00; font-size: 0.7rem; font-weight: 700;
  padding: 0.15rem 0.55rem; border-radius: 999px; margin-bottom: 0.35rem;
}
/* .cover is used both inside a search-result .card AND standalone at the
   top of complex.php (id="complex-root" > .cover, no .card ancestor at
   all) — these rules used to be scoped ".card .cover", which meant the
   height/overflow constraints simply never applied on complex.php: its
   logo <img> rendered at full native resolution with nothing clipping
   it, which is exactly the huge image bleeding over the court cards and
   footer that got reported. Unscoped from .card so both spots are
   contained the same way; overflow:hidden is the actual safety net here
   (height alone doesn't stop a big native image from overflowing its box). */
.cover { height: 160px; overflow: hidden; background: var(--bg-hover) center/cover no-repeat; position: relative; }
/* Logo cover: a complex's logo (booking-admin > Tenants > Logo URL) is
   shown letterboxed on a soft tinted panel rather than stretched/cropped
   like a photo would be — object-fit:contain keeps the actual logo
   proportions intact. Falls back to the wide cover_photo_url as a
   background-image (set inline per-card) when no logo is set. */
.cover.has-logo { background: linear-gradient(135deg, var(--bg-hover), var(--bg-card)); display: flex; align-items: center; justify-content: center; padding: 1.25rem; }
/* Was max-width/max-height:100% + object-fit:contain — a plain
   letterboxed rectangle, inconsistent with the circular .cover-badge
   treatment used when there's also a cover photo (below), and with the
   circular logo avatar the Flutter app shows on this same page. Fixed
   circular size instead, matching that badge's shape (just bigger, since
   this is the ONLY thing in the panel rather than an overlay on a photo);
   object-fit:cover crops a non-square logo to fill the circle rather
   than letterboxing it — standard "logo in a circle" treatment. */
.cover.has-logo img {
  width: 140px; height: 140px; border-radius: 50%; object-fit: cover;
  background: var(--bg-card); border: 3px solid var(--bg-card); box-shadow: var(--shadow-sm);
}
/* Small logo badge overlaid on an actual cover photo (complex.php, when a
   tenant has both a cover_photo_url and a logo_url) — deliberately kept
   INSIDE .cover's own box (bottom offset, not negative) rather than
   hanging half off the edge, so .cover's overflow:hidden can never clip
   it and it can never repeat the oversized/unclipped-image bug this box
   already had once. */
.cover .cover-badge {
  position: absolute; left: 1rem; bottom: 1rem; width: 56px; height: 56px; padding: 6px;
  border-radius: 50%; object-fit: contain; background: var(--bg-card); border: 2px solid var(--bg-card);
  box-shadow: var(--shadow-sm);
}
.card .distance { position: absolute; top: 0.6rem; right: 0.6rem; background: rgba(22,24,38,0.65); color: #fff; font-size: 0.72rem; font-weight: 600; padding: 0.2rem 0.55rem; border-radius: 999px; backdrop-filter: blur(2px); }
body.lang-ar .card .distance { right: auto; left: 0.6rem; }
.card .body { padding: 1rem 1.1rem 1.2rem; }
.card h3 { margin: 0 0 0.25rem; font-size: 1.05rem; }
.card .meta { color: var(--text-secondary); font-size: 0.85rem; margin-bottom: 0.5rem; }
.card .price { font-weight: 700; color: var(--accent-light); }

/* Filter bar — sport, distance radius, "near me" toggle. Shared by the
   homepage's search box and search.php's fuller filter row. */
.filter-bar {
  display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: 0.9rem 1.1rem; margin-bottom: 1.5rem;
}
.filter-bar .filter-group { display: flex; align-items: center; gap: 0.4rem; }
.filter-bar label { font-size: 0.8rem; color: var(--text-secondary); font-weight: 600; white-space: nowrap; }
.filter-bar select, .filter-bar input[type="text"] {
  border: 1px solid var(--border); background: var(--bg-input); color: var(--text-primary);
  border-radius: var(--radius); padding: 0.5rem 0.75rem; font-size: 0.88rem; outline: none;
}
.filter-bar select:focus, .filter-bar input:focus { border-color: var(--border-focus); }
.filter-chip {
  display: inline-flex; align-items: center; gap: 0.35rem; border-radius: 999px; padding: 0.45rem 0.9rem;
  font-size: 0.85rem; font-weight: 600; border: 1px solid var(--border); background: var(--bg-hover);
  color: var(--text-secondary); cursor: pointer; transition: background .15s, color .15s, border-color .15s;
}
.filter-chip.is-active { background: var(--accent-glow); border-color: var(--accent); color: var(--accent-light); }
.filter-bar .spacer { flex: 1; }
.location-note { font-size: 0.8rem; color: var(--text-muted); }

/* Sport filter row — a circular icon + label per sport, scrolling
   horizontally, matching the Flutter app's own Sports row (SportBadge in
   lib/widgets/sport_chip.dart) exactly instead of the plain <select>
   dropdown this used to be. Populated live from GET /api/sports.php
   (App.renderSportChips() in assets/js/app.js) — the same admin-managed
   catalog (booking-admin > Sports) the app itself reads, so a sport added
   there shows up here too, not just in the app. */
.sport-chip-row {
  display: flex; gap: 0.9rem; overflow-x: auto; padding: 0.2rem 0.1rem 0.6rem;
  margin-bottom: 0.25rem; -webkit-overflow-scrolling: touch; scrollbar-width: thin;
}
.sport-chip {
  display: flex; flex-direction: column; align-items: center; gap: 0.4rem;
  flex: 0 0 auto; width: 64px; background: none; border: none; padding: 0; cursor: pointer;
  color: var(--text-muted); font-family: inherit;
}
.sport-chip .icon {
  width: 48px; height: 48px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  font-size: 1.3rem; background: var(--bg-card); border: 1px solid var(--border);
  transition: background .15s, border-color .15s;
}
.sport-chip .label {
  font-size: 0.72rem; font-weight: 600; white-space: nowrap; max-width: 64px;
  overflow: hidden; text-overflow: ellipsis;
}
.sport-chip.is-active { color: var(--accent-light); }
.sport-chip.is-active .icon { background: var(--accent-glow); border-color: var(--accent); }

/* Ad placements — admin-managed images that link out, styled to look
   like content rather than an intrusive banner. */
.ad-slot { margin: 2rem 0; }
.ad-slot a { display: block; border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-sm); }
.ad-slot img { width: 100%; display: block; }
.ad-slot .ad-label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); margin-bottom: 0.4rem; }
.ad-sidebar { display: flex; flex-direction: column; gap: 1rem; }

/* search.php's two-column layout: results + a sidebar ad column. Stacks
   on narrow screens (sidebar ad drops below the results instead). */
.search-layout { display: grid; grid-template-columns: 1fr 260px; gap: 1.75rem; align-items: start; }
@media (max-width: 860px) {
  .search-layout { grid-template-columns: 1fr; }
}

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem;
  border-radius: var(--radius); padding: 0.7rem 1.3rem; font-weight: 600; font-size: 0.92rem;
  border: 1px solid var(--border); background: var(--bg-hover); color: var(--text-primary); cursor: pointer;
}
.btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn-primary:hover { background: var(--accent-light); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.badge { display: inline-block; padding: 0.2rem 0.6rem; border-radius: 999px; font-size: 0.75rem; font-weight: 600; }
.badge.green { background: var(--green-bg); color: var(--green); }
.badge.red { background: var(--red-bg); color: var(--red); }
.badge.yellow { background: var(--yellow-bg); color: var(--yellow); }
/* Added for complaint status (open/in_progress/resolved/closed) — reuses
   the existing --blue token (already defined above, just never had a
   .badge variant yet) plus a new neutral "grey" for a closed complaint,
   which isn't quite a failure (red) or a success (green). */
.badge.blue { background: var(--blue-bg); color: var(--blue); }
.badge.grey { background: var(--bg-hover); color: var(--text-secondary); }

.empty-state { text-align: center; padding: 3rem 1rem; color: var(--text-muted); }
.empty-state .icon { font-size: 2.5rem; margin-bottom: 0.75rem; }

.form-input {
  width: 100%; padding: 0.75rem 1rem; border-radius: var(--radius); border: 1px solid var(--border);
  background: var(--bg-input); color: var(--text-primary); font-size: 0.95rem; margin-bottom: 0.9rem;
}
.form-input:focus { outline: none; border-color: var(--border-focus); }

/* OAuth sign-in buttons (login.php/register.php) */
.oauth-buttons { display: flex; flex-direction: column; gap: 0.6rem; margin-bottom: 1.1rem; }
.btn-oauth {
  display: flex; align-items: center; justify-content: center; gap: 0.6rem; width: 100%;
  padding: 0.7rem 1rem; border-radius: var(--radius); border: 1px solid var(--border); background: var(--bg-card);
  color: var(--text-primary); font-weight: 600; font-size: 0.92rem; cursor: pointer; text-decoration: none;
}
.btn-oauth:hover { background: var(--bg-hover); }
.btn-oauth .swatch { width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; font-weight: 800; font-size: 0.8rem; border-radius: 4px; }
.btn-oauth.google .swatch { color: #4285F4; }
.btn-oauth.facebook .swatch { color: #1877F2; }
.oauth-divider { display: flex; align-items: center; gap: 0.75rem; color: var(--text-muted); font-size: 0.8rem; margin: 1.1rem 0; }
.oauth-divider::before, .oauth-divider::after { content: ''; flex: 1; height: 1px; background: var(--border); }

#toast-container { position: fixed; bottom: 1.5rem; right: 1.5rem; z-index: 100; display: flex; flex-direction: column; gap: 0.5rem; }
body.lang-ar #toast-container { right: auto; left: 1.5rem; }
.toast { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 0.8rem 1.2rem; box-shadow: var(--shadow); font-size: 0.9rem; }
.toast.error { border-color: var(--red); color: var(--red); }
.toast.success { border-color: var(--green); color: var(--green); }

/* Booking flow step indicator (complex.php) — Court -> Date & time ->
   Confirm, so the visitor always knows where they are in the process
   instead of a page that just grows taller as sections appear. */
.booking-steps { display: flex; align-items: center; gap: 0.5rem; margin: 1.75rem 0 1.5rem; }
.booking-step { display: flex; align-items: center; gap: 0.55rem; color: var(--text-muted); font-size: 0.88rem; font-weight: 600; }
.booking-step .num {
  width: 26px; height: 26px; border-radius: 999px; display: flex; align-items: center; justify-content: center;
  border: 2px solid var(--border); font-size: 0.8rem; transition: background .2s, border-color .2s, color .2s;
}
.booking-step.is-active { color: var(--text-primary); }
.booking-step.is-active .num { background: var(--accent); border-color: var(--accent); color: #fff; }
.booking-step.is-done .num { background: var(--green); border-color: var(--green); color: #fff; }
.booking-step.is-done { color: var(--text-secondary); }
.booking-step-line { flex: 1; height: 2px; background: var(--border); max-width: 60px; }
.court-card { cursor: pointer; transition: border-color .15s, transform .15s; border: 2px solid transparent; }
.court-card:hover { transform: translateY(-2px); }
.court-card.selected { border-color: var(--accent); }
.tier-card { cursor: pointer; border: 2px solid transparent; }
.tier-card.selected { border-color: var(--accent); background: var(--accent-glow); }
.slot-btn {
  border: 1px solid var(--border); background: var(--bg-hover); color: var(--text-primary);
  border-radius: var(--radius); padding: 0.65rem 0.5rem; font-size: 0.85rem; font-weight: 600; cursor: pointer;
  transition: background .15s, border-color .15s;
}
.slot-btn:hover { border-color: var(--accent); }
.slot-btn.selected { background: var(--accent); border-color: var(--accent); color: #fff; }
.slot-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 0.5rem; }
.booking-confirm-card {
  background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: 1.5rem; box-shadow: var(--shadow-sm);
}
.booking-success { text-align: center; padding: 2.5rem 1rem; }
.booking-success .icon { font-size: 3rem; margin-bottom: 1rem; }
.fade-in { animation: ppb-fade-in .25s ease; }
@keyframes ppb-fade-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }

footer.site-footer { border-top: 1px solid var(--border); padding: 2.5rem 0; color: var(--text-muted); text-align: center; font-size: 0.85rem; }
.footer-copy { margin-top: 0.5rem; }
/* "Get the app" section — collapses to nothing (App.renderAppLinksSection
   sets el.innerHTML = '') when the admin hasn't configured any download
   link yet, so it never leaves an empty gap above the copyright line. */
.app-links-section { margin-bottom: 0.25rem; }
.app-links-title { font-weight: 600; color: var(--text-secondary); margin-bottom: 0.6rem; }
.app-links-row { display: flex; justify-content: center; gap: 0.6rem; flex-wrap: wrap; }
.app-link-btn { font-size: 0.85rem; }
/* Footer's "File a complaint" / "Terms & Disclaimer" row — plain text
   links, not buttons, since this is quiet legal/support footer real
   estate, not a call to action. */
.footer-legal-row { margin-bottom: 0.75rem; }
.footer-legal-row a { color: var(--text-secondary); text-decoration: underline; }
.footer-legal-row a:hover { color: var(--text-primary); }
.footer-legal-sep { margin: 0 0.5rem; color: var(--text-muted); }
/* The short liability-disclaimer banner shown on complaint.php (both when
   filing and when browsing your own past complaints) and echoed at the
   top of terms.php — same box treatment as other inline notices on this
   site (a quiet bordered card, not an alarming red banner: it's routine
   legal boilerplate, not an error state). */
.disclaimer-note { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 1rem 1.25rem; font-size: 0.85rem; color: var(--text-secondary); line-height: 1.6; margin-bottom: 1.5rem; }
.disclaimer-note a { color: var(--accent-light); }

@media (max-width: 640px) {
  .nav-toggle { display: flex; }
  nav.main-nav {
    display: flex; flex-direction: column; align-items: stretch; gap: 0;
    position: absolute; top: var(--header-h); left: 0; right: 0;
    background: var(--bg-surface); border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow);
    max-height: 0; overflow: hidden; opacity: 0;
    transition: max-height .2s ease, opacity .2s ease;
  }
  nav.main-nav.is-open { max-height: 260px; opacity: 1; }
  nav.main-nav a {
    padding: 0.9rem var(--pad); border-bottom: 1px solid var(--border);
  }
  nav.main-nav a.active::after { display: none; } /* underline doesn't read well full-width; background tint instead */
  nav.main-nav a.active { background: var(--accent-glow); }
}
