/*
 * Bitakore — global stylesheet.
 * Dark-only design system (no light theme / no toggle by design). Everything here is driven by
 * CSS custom properties so the palette, spacing, and radii stay consistent across every page —
 * pages themselves stay unstyled semantic HTML/kotlinx.html, this file does all the work via
 * tag selectors plus a small number of classes introduced on Layout.kt and LoginPage.kt.
 */

:root {
  /* Tells the browser to render native controls (date/datetime-local pickers, scrollbars, ...) in
   * dark mode — without this the calendar-picker icon on input[type="date"/"datetime-local"]
   * renders in its light-mode colors and is nearly invisible against --color-surface-inset. */
  color-scheme: dark;

  /* Background: a dark navy → slate → charcoal gradient (mood reference: legacy prototype). */
  --bg-gradient:
    radial-gradient(1100px 700px at 15% -10%, rgba(60, 110, 150, 0.35) 0%, transparent 60%),
    linear-gradient(160deg, #001c2c 0%, #1c3550 42%, #001c2c 75%, #2a2a2a 100%);

  /* Surfaces */
  --color-bg: #071722;
  --color-surface: #101f2c;
  --color-surface-raised: #16283a;
  --color-surface-inset: #0b1620;

  /* Borders */
  --color-border: #24384a;
  --color-border-strong: #35506a;

  /* Text */
  --color-text: #edf2f7;
  --color-text-muted: #92a6b9;

  /* Accent */
  --color-accent: #4c8dff;
  --color-accent-hover: #6fa3ff;
  --color-accent-contrast: #051222;

  /* Status */
  --color-danger: #ff9a9a;
  --color-danger-bg: rgba(255, 99, 99, 0.12);
  --color-danger-border: rgba(255, 99, 99, 0.35);
  --color-info-bg: rgba(148, 178, 204, 0.10);
  --color-info-border: rgba(148, 178, 204, 0.28);
  --color-success: #22c55e;
  --color-success-hover: #3fdc76;
  --color-success-contrast: #052e14;
  --color-danger-solid: #ef4444;
  --color-danger-solid-hover: #f87171;
  --color-danger-contrast: #2e0505;

  /* Radii */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 18px;

  /* Spacing scale */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;

  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  /* Display face for the landing page only (HomePage.kt) -- an old-style serif that echoes the
     wedge-serif "BITAKORE" wordmark and the ledger/logbook idea behind "bitácora", set only on a
     few large headings so it reads as a deliberate accent rather than the whole app's voice. */
  --font-display: "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;
  --max-content-width: 640px;
}

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

html,
body {
  height: 100%;
  margin: 0;
}

body {
  min-height: 100vh;
  background: var(--bg-gradient) fixed;
  background-repeat: no-repeat;
  background-color: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

#app {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

h1,
h2,
h3 {
  font-weight: 600;
  line-height: 1.25;
  margin: 0 0 var(--space-4);
}

h1 {
  font-size: 1.75rem;
  margin-bottom: var(--space-5);
}

h2 {
  font-size: 1.15rem;
}

p {
  margin: 0 0 var(--space-3);
  color: var(--color-text);
}

a {
  color: var(--color-accent);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

/* ---------------------------------------------------------------------- */
/* Top nav (Layout.kt)                                                     */
/* ---------------------------------------------------------------------- */

.site-nav {
  background: rgba(10, 20, 30, 0.7);
  border-bottom: 1px solid var(--color-border);
  position: sticky;
  top: 0;
  z-index: 10;
}

.site-nav-inner {
  /* 25% taller than the base spacing scale (--space-3/--space-5) -- scoped here rather than
     bumping those shared vars, which are used by unrelated components elsewhere on the page. */
  padding: 15px 30px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.brand {
  display: flex;
  align-items: center;
}

.brand-logo {
  display: block;
  height: 35px;
  width: auto;
}

.brand:hover {
  text-decoration: none;
  opacity: 0.85;
}

.brand:focus-visible {
  outline: none;
  opacity: 0.85;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 20px;
}

.nav-links a {
  color: var(--color-text-muted);
  font-size: 1.125rem;
}

.nav-links a:hover {
  color: var(--color-text);
  text-decoration: none;
}

/* Groups .nav-links and .nav-account together against the right edge (rather than letting
   .nav-links float centered between the logo and the account/language icons) -- restores a
   layout that briefly existed only as uncommitted WIP (see buglog bug-312). */
.nav-end {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex: 1;
  min-width: 0;
  gap: 30px;
}

.nav-account {
  display: flex;
  align-items: center;
  gap: 15px;
}

/* Account/communication/settings menus + language picker (Layout.kt) -- each a
   relatively-positioned toggle (.nav-dropdown) with an absolutely-positioned panel
   (.nav-dropdown-menu) shown on :hover, pure CSS (no JS open/close). The ::after pseudo-element
   is a transparent bridge spanning the gap between the toggle and the panel. It only widens to
   the panel's full footprint (wider than the toggle, overhanging to the left) while its own
   toggle is hovered -- staying narrow the rest of the time so it doesn't sit on top of an
   *adjacent* dropdown (only 15px away via .nav-account's gap) and steal that dropdown's hover. */
.nav-dropdown {
  position: relative;
  display: flex;
  align-items: center;
}

.nav-dropdown::after {
  content: "";
  position: absolute;
  top: 100%;
  right: 0;
  left: auto;
  width: 100%;
  height: var(--space-2);
}

.nav-dropdown:hover::after {
  width: max(100%, 220px);
}

.nav-dropdown:hover .nav-dropdown-menu {
  display: flex;
}

.user-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--color-surface-inset);
  border: 1px solid var(--color-border-strong);
  color: var(--color-text);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.9375rem;
  font-weight: 600;
  cursor: pointer;
  overflow: hidden;
}

.user-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.nav-dropdown > button {
  background: transparent;
  padding: 5px 10px;
  line-height: 1;
  display: flex;
  align-items: center;
  color: var(--color-text);
}

.nav-dropdown > button:hover {
  background: var(--color-surface-inset);
  color: var(--color-accent);
}

.nav-dropdown > button .ui-icon {
  width: 22px;
  height: 22px;
}

.nav-dropdown-menu {
  display: none;
  position: absolute;
  top: calc(100% + var(--space-2));
  right: 0;
  z-index: 30;
  flex-direction: column;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  min-width: 160px;
  padding: var(--space-2);
  gap: var(--space-1);
}

.nav-dropdown-menu a {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--color-text);
  font-size: 0.9rem;
  font-weight: 400;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  white-space: nowrap;
}

.nav-item-icon {
  flex: none;
  width: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Inline SVG icon set (Icons.kt) — colored via `stroke="currentColor"` in the markup itself, so
   this just fixes a sensible default size; contexts that need a different size (the nav triggers,
   the table row-action buttons) override width/height explicitly. */
.ui-icon {
  width: 18px;
  height: 18px;
  flex: none;
  display: block;
}

.nav-dropdown-menu a:hover {
  background: var(--color-surface-inset);
  text-decoration: none;
}

/* Non-interactive "Incoming"/"Outgoing" group headings inside .comm-dropdown-menu. */
.nav-dropdown-section-label {
  color: var(--color-text-muted);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: var(--space-2) var(--space-3) 0;
}

.nav-dropdown-section-label:first-child {
  padding-top: 0;
}

.lang-option {
  color: var(--color-text);
  font-size: 0.9rem;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  cursor: pointer;
  white-space: nowrap;
}

.lang-option:hover {
  background: var(--color-surface-inset);
}

/* ---------------------------------------------------------------------- */
/* Floating "add log entry" shortcut (Layout.kt) — fixed just under the    */
/* nav's language dropdown on the right, a round "+" badge that expands    */
/* into a labeled pill on hover/focus. Sized 25% larger than the original  */
/* 48px badge (60px).                                                      */
/* ---------------------------------------------------------------------- */

.add-log-fab {
  position: fixed;
  top: 86px;
  right: var(--space-5);
  z-index: 20;
  display: flex;
  align-items: center;
  height: 60px;
  min-width: 60px;
  border-radius: 30px;
  background: var(--color-success);
  color: var(--color-success-contrast);
  overflow: hidden;
  white-space: nowrap;
  text-decoration: none;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
  transition: min-width 0.25s ease, background-color 0.2s ease, box-shadow 0.2s ease;
}

.add-log-fab:hover,
.add-log-fab:focus-visible {
  min-width: 238px;
  background: var(--color-success-hover);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.45);
  text-decoration: none;
}

.add-log-fab-icon {
  flex: 0 0 60px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.875rem;
  font-weight: 600;
  line-height: 1;
}

.add-log-fab-label {
  max-width: 0;
  opacity: 0;
  overflow: hidden;
  font-size: 1.125rem;
  font-weight: 600;
  white-space: nowrap;
  transition: max-width 0.25s ease, opacity 0.2s ease, padding-right 0.25s ease;
}

.add-log-fab:hover .add-log-fab-label,
.add-log-fab:focus-visible .add-log-fab-label {
  max-width: 200px;
  opacity: 1;
  padding-right: var(--space-4);
}

/* ---------------------------------------------------------------------- */
/* Page shell — centered, readable-width content column                   */
/* ---------------------------------------------------------------------- */

.page-shell {
  flex: 1;
  width: 100%;
  max-width: var(--max-content-width);
  margin: 0 auto;
  padding: var(--space-7) var(--space-4);
}

.page-shell-wide {
  max-width: 1200px;
}

.page-shell-listing {
  max-width: none;
  width: 80vw;
  min-width: 600px;
}

/* ---------------------------------------------------------------------- */
/* Site footer — legal links, sticks to the bottom via #app's flex column */
/* ---------------------------------------------------------------------- */

.site-footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--space-4);
  font-size: 0.85rem;
  color: var(--color-text-muted);
  border-top: 1px solid var(--color-border);
}

.footer-bar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.footer-logo {
  display: block;
  height: 22px;
  width: auto;
  opacity: 0.85;
}

.footer-copyright {
  color: var(--color-text-muted);
}

/* Collapsed by default -- only the logo + copyright bar shows. Hovering (or focusing a link
   inside, for keyboard users) grows the footer to reveal the Terms/Privacy/Contact row. */
.footer-links {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  margin-top: 0;
  transition: max-height 0.25s ease, opacity 0.2s ease, margin-top 0.25s ease;
}

.site-footer:hover .footer-links,
.site-footer:focus-within .footer-links {
  max-height: 2.5rem;
  opacity: 1;
  margin-top: var(--space-3);
}

.site-footer a {
  color: inherit;
}

.consent-notice {
  margin-top: var(--space-4);
  font-size: 0.85rem;
  color: var(--color-text-muted);
  text-align: center;
}

.legal-updated {
  color: var(--color-text-muted);
  font-size: 0.9rem;
}

.listing-search-form {
  margin-bottom: var(--space-5);
}

/* Groups the query input and country picker into one row (e.g. AdminCompaniesPage.kt) so the
   country filter sits next to the text search instead of stacking under it — each field's
   width:100% (see the global `input` rule above) resolves against this flex item's own basis,
   not the whole form's. */
.search-fields-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.search-fields-row > * {
  flex: 1 1 200px;
}

/* A boolean display filter (e.g. "Show inactive") living inside .search-fields-row alongside a
   text search input and/or country picker — sized to its label instead of stretching to match
   them, and themed rather than left as a bare unstyled checkbox. */
.filter-toggle {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex: 0 0 auto;
  color: var(--color-text-muted);
  font-size: 0.9rem;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
}

.filter-toggle:hover {
  color: var(--color-text);
}

/* Restyled as an actual toggle switch (pill track + sliding knob) rather than a native checkbox
   square — still a real <input type="checkbox"> underneath, so keyboard/screen-reader behavior is
   unchanged, only the visual is replaced. */
.filter-toggle input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  flex: none;
  width: 34px;
  height: 20px;
  margin: 0;
  border-radius: 999px;
  background: var(--color-surface-inset);
  border: 1px solid var(--color-border-strong);
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.filter-toggle input[type="checkbox"]::before {
  content: "";
  position: absolute;
  top: 1px;
  left: 1px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--color-text-muted);
  transition: transform 0.15s ease, background-color 0.15s ease;
}

.filter-toggle input[type="checkbox"]:checked {
  background: var(--color-accent);
  border-color: var(--color-accent);
}

.filter-toggle input[type="checkbox"]:checked::before {
  transform: translateX(14px);
  background: var(--color-accent-contrast);
}

.filter-toggle input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* A two-sided variant of .filter-toggle (e.g. DiscoverPage's "Mine"/"All" activity-type filter)
   with a label flanking each end of the switch instead of one trailing label -- the active side
   is emphasized so the switch reads at a glance without needing to check which way the knob sits. */
.mine-all-toggle span {
  transition: color 0.15s ease, font-weight 0.15s ease;
}

.mine-all-toggle:not(:has(input:checked)) span:first-child,
.mine-all-toggle:has(input:checked) span:last-child {
  color: var(--color-text);
  font-weight: 600;
}

/* DiscoverPage's activity-type filter -- unlike .mine-all-toggle above, this shows only the
   currently active side (as its own label) rather than both ends of a switch; tapping it flips to
   the other value. */
.mine-all-toggle-button {
  flex: 0 0 auto;
  /* Bottom-aligns with the dropdown it sits beside (same fix as #bitacoraFilterForm's trailing
     button) instead of stretching to match .search-fields-row's tallest sibling -- the
     activity-type label's own text sits above its select, which this button has no equivalent
     of. */
  align-self: flex-end;
  /* Both labels below are grid-stacked onto the same cell (1/1) instead of laid out one after the
     other -- an auto grid track sizes to its widest occupant, so the button's own width is always
     the wider of "Mine"/"All" (in whatever language) regardless of which one is currently visible.
     Without this, tapping the button visibly resized it every time, since the two labels are rarely
     the same width. */
  display: grid;
  /* Matches the shared input/select vertical padding (--space-3) so its height lines up with the
     dropdown instead of reading shorter. */
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border-strong);
  /* Transparent at rest -- var(--color-surface-inset) is also every input/select's fill color, so
     using it here read as "disabled-looking form field" rather than "button". */
  background: transparent;
  color: var(--color-text);
  /* Matches the activity-type label's font-size (which the select inherits via `font: inherit`) --
     a mismatched font-size here was the actual cause of the button reading shorter than the
     dropdown despite identical padding/border, since it changes the rendered line-height. */
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

/* The two label spans (Mine/All) both live in the button's single grid cell -- see the sizing note
   above. */
.mine-all-toggle-button > span {
  grid-area: 1 / 1;
}

/* Kept in normal flow (unlike `display: none`/the `hidden` attribute) so it still contributes to
   the grid track's width calculation above -- only its paint is suppressed. */
.mine-all-toggle-button-label-inactive {
  visibility: hidden;
}

.mine-all-toggle-button:hover:not(:disabled) {
  background: var(--color-surface-inset);
  border-color: var(--color-accent);
}

.mine-all-toggle-button[aria-pressed="true"] {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-accent-contrast);
}

.mine-all-toggle-button:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* The login page's spinning cubes flank the form all the way to the viewport edge instead of
   inside the shared 1200px reading-width column other wide pages use. */
.page-shell-wide:has(.auth-layout) {
  max-width: none;
}

/* ---------------------------------------------------------------------- */
/* Register tabs (RegisterTabs.kt) — cross-links the practitioner and      */
/* company registration flows.                                            */
/* ---------------------------------------------------------------------- */

.register-tabs {
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-5);
  border-bottom: 1px solid var(--color-border);
}

.register-tab {
  padding: var(--space-2) var(--space-4);
  color: var(--color-text-muted);
  font-weight: 600;
  border-bottom: 2px solid transparent;
}

.register-tab:hover {
  color: var(--color-text);
  text-decoration: none;
}

.register-tab.active {
  color: var(--color-text);
  border-bottom-color: var(--color-accent);
}

/* ---------------------------------------------------------------------- */
/* Forms — shared across every page                                       */
/* ---------------------------------------------------------------------- */

form {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

label {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--color-text-muted);
}

input:not([type="radio"]):not([type="checkbox"]):not([type="file"]):not([type="hidden"]),
select,
textarea {
  width: 100%;
  font: inherit;
  color: var(--color-text);
  background: var(--color-surface-inset);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-3);
}

input[type="file"] {
  color: var(--color-text-muted);
  font-size: 0.9rem;
}

input[type="date"]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator {
  cursor: pointer;
  border-radius: var(--radius-sm);
}

input[type="date"]::-webkit-calendar-picker-indicator:hover,
input[type="datetime-local"]::-webkit-calendar-picker-indicator:hover {
  background: var(--color-surface-raised);
}

input[type="radio"] {
  margin-right: var(--space-2);
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible,
button:focus-visible,
a:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* My Bitácora's filter form — activity/from/to fields plus the submit button read better in one
 * row than stacked, wrapping on narrow viewports instead of forcing a fixed row. */
#bitacoraFilterForm {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: flex-end;
}

#bitacoraFilterForm label {
  flex: 1 1 180px;
}

#bitacoraFilterForm button {
  flex: 0 0 auto;
}

/* Log-activity forms carry far more fields than a typical page -- the standard 640px reading
 * column leaves every input cramped. Widen the page shell ~30% and lay fields out 2-up. */
.page-shell:has(#logActivityForm),
.page-shell:has(#logCenterActivityForm) {
  max-width: calc(640px * 1.3);
}

#logActivityForm,
#logCenterActivityForm,
.field-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4) var(--space-5);
  font-size: 1.2rem;
}

/* Every field is wrapped in a <label> -- headings, paragraphs, the notes textarea's own wrapping
 * label, the submit button, and status divs are the only other direct children, and all of those
 * should still span the full row rather than fight for a column. */
#logActivityForm > *:not(label),
#logCenterActivityForm > *:not(label),
.field-grid > *:not(label) {
  grid-column: 1 / -1;
}

/* ---------------------------------------------------------------------- */
/* Buttons                                                                 */
/* ---------------------------------------------------------------------- */

button {
  font: inherit;
  cursor: pointer;
  border: none;
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  transition: background-color 0.15s ease, border-color 0.15s ease, transform 0.05s ease;
}

button:active {
  transform: translateY(1px);
}

/* Primary, filled button — the default look for any submit button in the app (register,
   profile, accept-invitation forms all get this for free with no per-page markup changes). */
button[type="submit"],
.btn-primary {
  width: 100%;
  background: var(--color-accent);
  color: var(--color-accent-contrast);
  font-weight: 600;
}

button[type="submit"]:hover,
.btn-primary:hover {
  background: var(--color-accent-hover);
}

/* Secondary/quiet submit buttons (login page's password + magic-link forms). Combined selector
   keeps specificity above the bare `button[type="submit"]` rule above so the override sticks. */
button[type="submit"].btn-secondary {
  width: auto;
  background: transparent;
  color: var(--color-text);
  border: 1px solid var(--color-border-strong);
  font-weight: 500;
  font-size: 0.9rem;
  padding: var(--space-2) var(--space-4);
}

button[type="submit"].btn-secondary:hover {
  background: var(--color-surface-raised);
}

/* OAuth "continue with" buttons — not submit buttons, so no specificity fight with the rules
   above. */
.btn-oauth {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font-weight: 600;
  font-size: 0.95rem;
}

.btn-oauth-google {
  background: #ffffff;
  color: #3c4043;
  border: 1px solid #d0d5da;
}

.btn-oauth-google:hover {
  background: #f3f4f5;
}

.btn-oauth-facebook {
  background: #1877f2;
  color: #ffffff;
}

.btn-oauth-facebook:hover {
  background: #2b88ff;
}

/* Small, non-full-width accent button -- section-header "+ Add X" triggers that open a modal
   (CertificationTypesPage.kt). */
.btn-add {
  width: auto;
  background: var(--color-accent);
  color: var(--color-accent-contrast);
  font-weight: 600;
  font-size: 0.9rem;
  padding: var(--space-2) var(--space-4);
}

.btn-add:hover {
  background: var(--color-accent-hover);
}

/* Quiet, bordered button for a modal's secondary/dismiss action -- not tied to `[type="submit"]`
   the way .btn-secondary is, since Cancel buttons are `type="button"`. */
.btn-outline {
  width: auto;
  background: transparent;
  color: var(--color-text);
  border: 1px solid var(--color-border-strong);
  font-weight: 500;
}

.btn-outline:hover {
  background: var(--color-surface-inset);
}

/* ---------------------------------------------------------------------- */
/* Status / error messages — plain divs whose id ends in Error/Status     */
/* across every page (passwordLoginError, formError, magicLinkStatus,     */
/* displayNameStatus, avatarStatus, oauthError, ...).                     */
/* ---------------------------------------------------------------------- */

div[id$="Error"]:not(:empty),
div[id$="Status"]:not(:empty) {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
  margin-bottom: var(--space-1);
}

div[id$="Error"] {
  background: var(--color-danger-bg);
  border: 1px solid var(--color-danger-border);
  color: var(--color-danger);
}

div[id$="Status"] {
  background: var(--color-info-bg);
  border: 1px solid var(--color-info-border);
  color: var(--color-text-muted);
}

div[id$="Error"]:empty,
div[id$="Status"]:empty {
  display: none;
}

/* Applied via HTMLElement.showError() (StatusMessages.kt) wherever a status/message element that
   normally shows neutral or success text is instead showing an error — overrides the neutral
   div[id$="Status"] styling above, and also covers plain unstyled <p> error messages appended
   into freshly-cleared containers (page load/list-fetch failures) that don't use the Status/Error
   id convention at all. */
.status-error {
  color: var(--color-danger);
}

div[id$="Status"].status-error {
  background: var(--color-danger-bg);
  border: 1px solid var(--color-danger-border);
  color: var(--color-danger);
}

/* ---------------------------------------------------------------------- */
/* Inline info tooltip — used by the passkey explainer on auth forms       */
/* ---------------------------------------------------------------------- */

.info-tooltip {
  position: relative;
  display: inline-block;
  margin-left: var(--space-1);
  cursor: help;
  color: var(--color-text-muted);
}

.info-tooltip-text {
  visibility: hidden;
  opacity: 0;
  position: absolute;
  z-index: 10;
  bottom: 125%;
  left: 50%;
  transform: translateX(-50%);
  width: 260px;
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  color: var(--color-text);
  font-size: 0.8rem;
  font-weight: normal;
  line-height: 1.4;
  transition: opacity 0.15s ease;
}

.info-tooltip:hover .info-tooltip-text,
.info-tooltip:focus .info-tooltip-text,
.info-tooltip:focus-visible .info-tooltip-text {
  visibility: visible;
  opacity: 1;
}

/* ---------------------------------------------------------------------- */
/* Auth method picker (AuthMethodPicker.kt) — passkey vs. password choice, */
/* shown as two selectable cards on every registration/invitation/setup   */
/* form.                                                                   */
/* ---------------------------------------------------------------------- */

.auth-method-options {
  display: flex;
  gap: var(--space-3);
}

.auth-method-option {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-1);
  text-align: left;
  background: var(--color-surface-inset);
  border: 1px solid var(--color-border);
  color: var(--color-text);
}

.auth-method-option:hover {
  border-color: var(--color-border-strong);
}

.auth-method-option.active {
  border-color: var(--color-accent);
  background: var(--color-surface-raised);
}

.auth-method-option-title {
  font-size: 1.1rem;
  font-weight: 700;
}

.auth-method-option-desc {
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--color-text-muted);
  white-space: normal;
}

.auth-password-fields {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin-top: var(--space-2);
}

.password-field-row {
  display: flex;
  gap: var(--space-2);
  align-items: stretch;
}

.password-field-row input {
  flex: 1 1 auto;
}

.password-visibility-toggle {
  flex: 0 0 auto;
  width: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--color-border-strong);
  color: var(--color-text-muted);
  padding: var(--space-2) var(--space-3);
}

.password-visibility-toggle:hover {
  background: var(--color-surface-inset);
  color: var(--color-text);
}

.field-warning {
  font-size: 0.8rem;
  color: var(--color-danger);
}

.field-warning:empty {
  display: none;
}

/* ---------------------------------------------------------------------- */
/* Login page                                                              */
/* ---------------------------------------------------------------------- */

.auth-layout {
  display: flex;
  align-items: stretch;
  gap: var(--space-6);
}

.auth-form-col {
  flex: 1 1 420px;
  min-width: 0;
}

/* Spinning 3D photo cubes flanking the login form — two per side, each continuously cycling
   through six sport photos on its faces. Pure CSS: transform-style preserve-3d plus one shared
   keyframe timeline, phase-shifted per cube via animation-delay/direction for variety. */
.auth-cubes {
  --cube-size: clamp(200px, 18vw, 280px);
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
  gap: calc(var(--cube-size) / 3);
  width: var(--cube-size);
  perspective: clamp(900px, 60vw, 1400px);
  position: fixed;
  top: 210px;
}

.auth-cubes-left {
  left: 8vw;
}

.auth-cubes-right {
  right: 8vw;
}

.cube {
  position: relative;
  width: var(--cube-size);
  height: var(--cube-size);
  transform-style: preserve-3d;
  animation-name: cube-spin;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
}

.cube-face {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  border-radius: var(--radius-sm);
  backface-visibility: hidden;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
}

.cube-face-front { transform: translateZ(calc(var(--cube-size) / 2)); }
.cube-face-back { transform: rotateY(180deg) translateZ(calc(var(--cube-size) / 2)); }
.cube-face-left { transform: rotateY(-90deg) translateZ(calc(var(--cube-size) / 2)); }
.cube-face-right { transform: rotateY(90deg) translateZ(calc(var(--cube-size) / 2)); }
.cube-face-top { transform: rotateX(90deg) translateZ(calc(var(--cube-size) / 2)); }
.cube-face-bottom { transform: rotateX(-90deg) translateZ(calc(var(--cube-size) / 2)); }

@keyframes cube-spin {
  0%, 12% { transform: rotateX(0deg) rotateY(0deg); }
  16%, 29% { transform: rotateY(180deg); }
  33%, 46% { transform: rotateX(90deg); }
  50%, 62% { transform: rotateY(90deg); }
  66%, 79% { transform: rotateX(-90deg); }
  83%, 96% { transform: rotateY(-90deg); }
  100% { transform: rotateX(0deg) rotateY(0deg); }
}

.cube-spin-1 { animation-duration: 40s; }
.cube-spin-2 { animation-duration: 55s; animation-delay: -8s; animation-direction: reverse; }
.cube-spin-3 { animation-duration: 48s; animation-delay: -15s; }
.cube-spin-4 { animation-duration: 62s; animation-delay: -25s; animation-direction: reverse; }

@media (max-width: 1050px) {
  .auth-cubes {
    display: none;
  }
}

.auth-title {
  max-width: 420px;
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}

.auth-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.35);
  max-width: 420px;
  margin: 0 auto;
}

.auth-primary h2 {
  margin-bottom: var(--space-1);
}

.auth-hint {
  color: var(--color-text-muted);
  font-size: 0.85rem;
  margin-bottom: var(--space-4);
}

.auth-divider {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: var(--space-5) 0;
  color: var(--color-text-muted);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.auth-divider::before,
.auth-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--color-border);
}

.oauth-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.auth-secondary {
  border-top: 1px solid var(--color-border);
  padding-top: var(--space-5);
  margin-top: var(--space-2);
}

.auth-secondary + .auth-secondary {
  border-top: none;
  padding-top: 0;
  margin-top: var(--space-4);
}

.auth-secondary-heading {
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
  margin-bottom: var(--space-2);
}

/* ---------------------------------------------------------------------- */
/* Activity selection — searchable, collapsible category cards of icon +  */
/* label tiles (ActivitySelectionPage.kt, also reused read-only elsewhere) */
/* ---------------------------------------------------------------------- */

.activity-search {
  margin-bottom: var(--space-4);
}

.activity-category-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  margin-bottom: var(--space-3);
}

.activity-category-card summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--color-text);
  list-style: revert;
}

.activity-category-card summary::marker {
  color: var(--color-text-muted);
}

.activity-category-card[open] summary {
  margin-bottom: var(--space-3);
}

.activity-category-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--space-2);
}

/* Overrides the generic column-stacking `label` rule -- an icon + name tile, not a form field. */
.activity-option {
  flex-direction: row;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.9rem;
  font-weight: 400;
  color: var(--color-text);
  background: var(--color-surface-inset);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.activity-option:hover {
  border-color: var(--color-border-strong);
}

.activity-option:has(.activity-option-checkbox:checked) {
  background: rgba(76, 141, 255, 0.14);
  border-color: var(--color-accent);
  color: var(--color-text);
}

.activity-option:has(.activity-option-checkbox:focus-visible) {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* Visually hidden but still focusable/checkable -- the label + icon carry the visible state. */
.activity-option-checkbox {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.activity-option-icon {
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
  color: var(--color-text-muted);
}

.activity-option:has(.activity-option-checkbox:checked) .activity-option-icon {
  color: var(--color-accent);
}

.activity-option-label {
  flex: 1;
  overflow: hidden;
  white-space: normal;
}

/* ---------------------------------------------------------------------- */
/* Bitácora — log/approve/list pages                                      */
/* ---------------------------------------------------------------------- */

.hidden {
  display: none !important;
}

.map-container {
  width: 100%;
  height: 300px;
  border-radius: var(--radius-md);
  margin-top: var(--space-2);
}

.entry-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  margin-bottom: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.entry-card h3 {
  margin: 0;
  font-size: 1rem;
  text-transform: capitalize;
}

.entry-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-2);
}

.entry-actions button {
  width: auto;
  font-weight: 600;
}

.btn-approve {
  background: var(--color-success);
  color: var(--color-success-contrast);
  border: 1px solid var(--color-success);
}

.btn-approve:hover {
  background: var(--color-success-hover);
}

.btn-reject {
  background: var(--color-danger-solid);
  color: var(--color-danger-contrast);
  border: 1px solid var(--color-danger-solid);
}

.btn-reject:hover {
  background: var(--color-danger-solid-hover);
}

/* Compact icon action buttons — table row actions (AdminUsersPage.kt, AdminCompaniesPage.kt,
   IssuingAuthoritiesPage.kt, CertificationTypesPage.kt) sit tightly together as small square
   icon buttons instead of full-width text buttons, so the Actions column stays narrow. Separate
   from .entry-actions, which stays a space-between text-button layout for card contexts
   (PendingApprovalsPage.kt). Applied to both the header `th` and the row `td` (rather than just
   `:last-child`) so the column shrinks to the buttons' own width instead of stretching to share
   the table's `width: 100%` with the other columns -- `width: 1%` plus `white-space: nowrap` is
   the standard trick for that under `table-layout: auto`. */
.table-row-actions {
  display: flex;
  gap: var(--space-1);
}

th.table-row-actions,
td.table-row-actions {
  width: 1%;
  white-space: nowrap;
}

.icon-button {
  width: 32px;
  height: 32px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--color-border-strong);
  color: var(--color-text);
}

.icon-button .ui-icon {
  width: 16px;
  height: 16px;
}

.icon-button:hover {
  background: var(--color-surface-inset);
  color: var(--color-accent);
}

.icon-button-danger:hover {
  background: var(--color-danger-bg);
  border-color: var(--color-danger-border);
  color: var(--color-danger);
}

.badge {
  display: inline-block;
  width: fit-content;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
}

.badge-pending {
  background: var(--color-info-bg);
  border: 1px solid var(--color-info-border);
  color: var(--color-text-muted);
}

.badge-verified {
  background: rgba(120, 220, 150, 0.12);
  border: 1px solid rgba(120, 220, 150, 0.35);
  color: #8ee6a8;
}

.badge-rejected {
  background: var(--color-danger-bg);
  border: 1px solid var(--color-danger-border);
  color: var(--color-danger);
}

.badge-role {
  background: rgba(76, 141, 255, 0.12);
  border: 1px solid rgba(76, 141, 255, 0.35);
  color: var(--color-accent-hover);
  margin-right: var(--space-1);
}

/* ---------------------------------------------------------------------- */
/* Country picker (CountryCatalog.kt) — a custom dark-theme dropdown       */
/* instead of a native <input list>/<datalist>, whose popup can't be       */
/* themed and reads as invisible against this app's dark background.      */
/* ---------------------------------------------------------------------- */

.country-picker {
  position: relative;
}

.country-picker::after {
  content: "▾";
  position: absolute;
  top: 50%;
  right: var(--space-3);
  transform: translateY(-50%);
  color: var(--color-text-muted);
  pointer-events: none;
}

.country-picker input {
  padding-right: var(--space-6);
}

.country-picker-options {
  display: none;
  position: absolute;
  top: calc(100% + var(--space-1));
  left: 0;
  right: 0;
  z-index: 20;
  max-height: 240px;
  overflow-y: auto;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  padding: var(--space-1);
}

.country-picker-options.open {
  display: block;
}

.country-picker-option {
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
  color: var(--color-text);
  cursor: pointer;
}

.country-picker-option:hover {
  background: var(--color-surface-inset);
}

/* ---------------------------------------------------------------------- */
/* Listing tables (AdminUsersPage.kt, AdminCompaniesPage.kt) — paginated   */
/* admin tables: a solid-colored header row and alternating row shading.   */
/* ---------------------------------------------------------------------- */

.listing-table {
  width: 100%;
  border-collapse: collapse;
}

.listing-table th,
.listing-table td {
  padding: var(--space-2) var(--space-3);
  text-align: left;
}

.listing-table-head-row th {
  background: var(--color-surface-raised);
  color: var(--color-text);
  border-bottom: 1px solid var(--color-border-strong);
}

.listing-table tr:not(.listing-table-head-row):nth-child(odd) {
  background: var(--color-surface);
}

.listing-table tr:not(.listing-table-head-row):nth-child(even) {
  background: var(--color-surface-inset);
}

/* ---------------------------------------------------------------------- */
/* Pagination control (Pagination.kt) — kept visually detached from the    */
/* results table above it (own top border + spacing) since it's a         */
/* sibling element, not part of the table.                                */
/* ---------------------------------------------------------------------- */

.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
}

.pagination-nav {
  width: 100px;
}

.pagination-label {
  color: var(--color-text-muted);
  font-size: 0.9rem;
}

/* ---------------------------------------------------------------------- */
/* Section headings paired with an "+ Add X" trigger button (e.g.          */
/* CertificationTypesPage.kt's issuing-authorities/certification-types    */
/* listings), and the <dialog> modals those buttons open.                 */
/* ---------------------------------------------------------------------- */

.page-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

.page-header-row h1,
.page-header-row h2 {
  margin: 0;
}

.page-header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

dialog.modal {
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
  background: var(--color-surface-raised);
  color: var(--color-text);
  padding: var(--space-6);
  width: 90vw;
  max-width: 560px;
  max-height: 85vh;
  overflow-y: auto;
}

dialog.modal::backdrop {
  background: rgba(0, 0, 0, 0.6);
}

dialog.modal h3 {
  margin-top: 0;
}

.modal-actions {
  display: flex;
  gap: var(--space-3);
  margin-top: var(--space-2);
}

.modal-actions button[type="submit"] {
  width: auto;
  flex: 1;
}

/* ---------------------------------------------------------------------- */
/* Discover page (DiscoverPage.kt) — map-first layout: a 20% left column   */
/* showing nearby activity photos, a 60%-wide map, and a 20% right column  */
/* showing marketer ads (both via AdCarousel.kt, split by photo source --  */
/* a fixed pick per search, no auto-rotation). The search form itself      */
/* lives in a <dialog class="modal"> opened by the lens button floated     */
/* over the map.                                                          */
/* ---------------------------------------------------------------------- */

/* 50% wider than the shared dialog.modal's 560px cap -- this form packs an activity-type select,
   the Mine/All toggle, a full location-search widget (with its own confirm-map) and a radius
   input, so it needs more breathing room than a plain confirmation dialog. Selector must be at
   least as specific as "dialog.modal" (element + class) for the override to actually win. */
dialog.discover-search-modal {
  max-width: 840px;
}

.discover-layout {
  display: grid;
  grid-template-columns: 20% 60% 20%;
  gap: var(--space-4);
  margin-top: var(--space-4);
}

.discover-map-col {
  position: relative;
}

.discover-map {
  height: 70vh;
  margin-top: 0;
}

/* Fits the whole Discover page into one viewport with no vertical scrollbar -- scoped to this one
   page (toggled by DiscoverPage.wireDiscoverPage/Router.onNavigateAway) rather than changed on
   #app/.page-shell-listing globally, since other listing pages (admin tables, etc.) are meant to
   scroll when their content runs long. #app's usual `min-height: 100vh` only stops it from being
   *shorter* than the viewport; it doesn't stop taller content (like the old fixed 70vh map) from
   pushing it past 100vh, which is what forced the scrollbar. Capping #app's height here and
   flex-sizing everything below it to fill exactly what's left (map/side columns included) is what
   actually removes the scroll instead of just changing which element happens to overflow. */
body.discover-fit-viewport #app {
  height: 100vh;
  overflow: hidden;
}

body.discover-fit-viewport .page-shell-listing {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

body.discover-fit-viewport .discover-layout {
  flex: 1 1 auto;
  min-height: 0;
  grid-template-rows: minmax(0, 1fr);
}

body.discover-fit-viewport .discover-side-col,
body.discover-fit-viewport .discover-map-col {
  height: 100%;
  min-height: 0;
}

body.discover-fit-viewport .discover-map-col {
  display: flex;
  flex-direction: column;
}

body.discover-fit-viewport .discover-map {
  flex: 1 1 auto;
  min-height: 0;
  height: auto;
}

.discover-lens-button {
  position: absolute;
  top: var(--space-4);
  left: var(--space-4);
  z-index: 10;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface-raised);
  color: var(--color-text);
  font-size: 1.1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
  transition: none;
  /* Suppresses the browser's own default tap-highlight flash so only our own halo (below) shows. */
  -webkit-tap-highlight-color: transparent;
}

.discover-lens-button:active {
  transform: none;
}

.discover-lens-button:hover {
  background: var(--color-surface-inset);
  color: var(--color-accent);
}

.discover-lens-button:focus-visible {
  outline: none;
}

/* Yellow glow ring behind the lens button. A conic-gradient alone fills the *whole* disc with
   color at every angle -- it isn't a ring by itself, so a mask carves out the center, leaving
   only a genuine thin band (~3px) near the outer edge regardless of the button's own background/
   stacking. Covers most of the circle (300deg of 360, a small gap) rather than a short arc.
   Cycles: spin one full turn, freeze briefly, fade out, sit hidden for a long stretch, then snap
   its rotation back to 0 while still invisible (so the next spin never shows a jump) and fade
   back in. CSS has no per-cycle randomness (no random() support to rely on yet), so the "wait" is
   a long fixed dwell rather than a truly random one -- closest pure-CSS approximation. */
.discover-lens-button::before {
  content: "";
  position: absolute;
  inset: -5px;
  border-radius: 50%;
  /* Fades in over 25deg at the start, but a much longer 50deg taper at the end so it trails off
     gradually instead of disappearing abruptly. */
  background: conic-gradient(
    from 0deg,
    transparent 0deg,
    #ffd23f 25deg,
    #ffd23f 250deg,
    transparent 300deg,
    transparent 360deg
  );
  filter: blur(1px);
  /* Wider transition band than before -- the ring reads as thick where the arc is at full
     opacity (the middle) and thin where the color itself is already fading out (the taper). */
  -webkit-mask: radial-gradient(closest-side, transparent calc(100% - 6px), #000 calc(100% - 2px));
  mask: radial-gradient(closest-side, transparent calc(100% - 6px), #000 calc(100% - 2px));
  z-index: -1;
  pointer-events: none;
  opacity: 0;
  animation: discover-lens-halo-cycle 7s linear infinite;
}

@keyframes discover-lens-halo-cycle {
  0% {
    opacity: 1;
    transform: rotate(0deg);
  }
  25% {
    opacity: 1;
    transform: rotate(360deg);
  }
  30% {
    /* stop: frozen in place, still visible */
    opacity: 1;
    transform: rotate(360deg);
  }
  34% {
    /* hide */
    opacity: 0;
    transform: rotate(360deg);
  }
  96% {
    /* wait, hidden -- rotation reset happens here, unseen */
    opacity: 0;
    transform: rotate(0deg);
  }
  100% {
    opacity: 0;
    transform: rotate(0deg);
  }
}

/* Matches .discover-map's height so the photo/ad columns line up with the map rather than
   growing/shrinking to however many images happen to be shown. */
.discover-side-col {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  height: 70vh;
}

.photo-preview-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

.photo-preview-thumb {
  width: 96px;
  height: 96px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
}

.photo-preview-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
}

/* flex: 1 1 0 + min-height: 0 divides the column's fixed height evenly among however many slots
   are shown (1-4 photos, 1-3 ads) instead of stacking them at their natural aspect ratio and
   letting the column's total height drift away from the map's; object-fit crops rather than
   distorting to fill each share. */
.ad-carousel-image {
  width: 100%;
  object-fit: cover;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
}

/* Ads render as bare <img>s directly in the column (no slot wrapper -- they're never rotated
   slot-by-slot), so they carry the flex sizing themselves. */
#discoverAdsColumn .ad-carousel-image {
  flex: 1 1 0;
  min-height: 0;
}

/* Photos render one independently-rotating slot per visible photo (see AdCarousel.kt) -- the
   wrapper carries the flex sizing so a slot that's momentarily empty (an omitted rotation) still
   holds its share of the column's height instead of collapsing it. */
.ad-carousel-slot {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
}

#discoverPhotosColumn .ad-carousel-image {
  height: 100%;
}

/* Photos pop in (small -> full size) growing from the map's edge -- the photo column sits to the
   map's left, so transform-origin is its right edge (the side facing the map). Every rotation
   rebuilds these <img> elements from scratch (see AdCarousel.kt), so this replays each time the
   photo set changes, not just on first load. Ads are deliberately excluded (see
   #discoverAdsColumn below) -- they must never animate on their own. */
#discoverPhotosColumn .ad-carousel-image {
  transform-origin: right center;
  animation: photo-pop-in 0.5s ease-out;
}

/* Slides in from the right (the map's side) while growing, instead of just scaling in place --
   makes the map-ward origin actually readable instead of a subtle in-place grow. */
@keyframes photo-pop-in {
  from { opacity: 0; transform: scale(0.4) translateX(40px); }
  to { opacity: 1; transform: scale(1) translateX(0); }
}

#discoverAdsColumn .ad-carousel-image {
  animation: none;
}

/* ---------------------------------------------------------------------- */
/* Landing page (HomePage.kt) -- signed-out visitors only                 */
/* ---------------------------------------------------------------------- */

/* Full-bleed regardless of the page shell's own max-width (the 50%/50vw trick), so the hero and
   its flanking photo columns can run edge to edge while the sections below stay inside the normal
   wide (1200px) shell -- no changes needed to Layout.kt/renderWithLayout for this one section. */
.home-hero {
  position: relative;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  min-height: min(680px, 88vh);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding: var(--space-6) var(--space-5);
}

.home-hero-inner {
  position: relative;
  z-index: 2;
  max-width: 480px;
  margin: 0 auto;
  text-align: center;
}

.home-eyebrow {
  display: inline-block;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-accent);
  margin-bottom: var(--space-3);
}

.home-hero-title {
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 5.5vw, 3.75rem);
  line-height: 1.08;
  letter-spacing: -0.01em;
  margin: 0 0 var(--space-4);
}

.home-hero-subtitle {
  font-size: 1.05rem;
  color: var(--color-text-muted);
  margin: 0 0 var(--space-6);
}

.home-hero-ctas {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.home-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-sm);
  font-weight: 600;
  font-size: 1rem;
  transition: background-color 0.15s ease, border-color 0.15s ease, transform 0.05s ease;
}

.home-cta:hover {
  text-decoration: none;
}

.home-cta:active {
  transform: translateY(1px);
}

.home-cta-primary {
  background: var(--color-accent);
  color: var(--color-accent-contrast);
}

.home-cta-primary:hover {
  background: var(--color-accent-hover);
}

.home-cta-secondary {
  background: transparent;
  color: var(--color-text);
  border: 1px solid var(--color-border-strong);
}

.home-cta-secondary:hover {
  background: var(--color-surface-inset);
}

/* Four columns of real activity photos flanking the headline -- two per side, each scrolling
   opposite its neighbor at its own speed (same idea as .auth-cubes' phase-shifted spin, just a
   vertical strip of "log entries" instead of a rotating cube, to look like a distinct signature
   rather than reusing the login page's move outright). Purely decorative, so aria-hidden in
   HomePage.kt -- the headline carries the same meaning in text. */
.home-marquee {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
}

.home-marquee-col {
  position: absolute;
  top: 0;
  bottom: 0;
  width: clamp(120px, 10vw, 170px);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, transparent, black 15%, black 85%, transparent);
  mask-image: linear-gradient(to bottom, transparent, black 15%, black 85%, transparent);
}

.home-marquee-col-1 { left: 3vw; }
.home-marquee-col-2 { left: calc(3vw + clamp(120px, 10vw, 170px) + var(--space-4)); }
.home-marquee-col-3 { right: calc(3vw + clamp(120px, 10vw, 170px) + var(--space-4)); }
.home-marquee-col-4 { right: 3vw; }

.home-marquee-track {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  animation: home-marquee-up 46s linear infinite;
}

.home-marquee-track-down {
  animation-name: home-marquee-down;
}

.home-marquee-col-2 .home-marquee-track { animation-duration: 58s; }
.home-marquee-col-3 .home-marquee-track { animation-duration: 40s; }
.home-marquee-col-4 .home-marquee-track { animation-duration: 52s; }

@keyframes home-marquee-up {
  from { transform: translateY(0); }
  to { transform: translateY(-50%); }
}

@keyframes home-marquee-down {
  from { transform: translateY(-50%); }
  to { transform: translateY(0); }
}

.home-marquee-tile {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  flex-shrink: 0;
  border-radius: var(--radius-md);
  overflow: hidden;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
}

.home-marquee-tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.home-marquee-tile-badge {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--color-success);
  color: var(--color-success-contrast);
  display: flex;
  align-items: center;
  justify-content: center;
}

.home-marquee-tile-badge .ui-icon {
  width: 11px;
  height: 11px;
  color: inherit;
}

.home-marquee-tile-label {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: var(--space-2);
  background: linear-gradient(to top, rgba(7, 23, 34, 0.85), transparent);
  color: var(--color-text);
  font-size: 0.72rem;
  font-weight: 600;
}

@media (max-width: 1080px) {
  .home-marquee {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .home-marquee-track {
    animation: none;
  }
}

.home-section-heading {
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--color-text-muted);
  margin: 0 0 var(--space-6);
}

/* "How it works" -- a real 3-step sequence (log, then verify, then it counts toward your record),
   so numbering it is meaningful rather than decorative. */
.home-steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-6);
  margin: 0 0 var(--space-7);
}

.home-step-icon-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}

.home-step-number {
  font-family: var(--font-display);
  font-size: 2rem;
  line-height: 1;
  color: var(--color-accent);
}

.home-step-icon {
  width: 24px;
  height: 24px;
  color: var(--color-text-muted);
}

.home-step h2 {
  font-family: var(--font-display);
  font-size: 1.3rem;
  margin: 0 0 var(--space-2);
}

.home-step p {
  color: var(--color-text-muted);
  margin: 0;
}

.home-audiences {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-5);
  margin: 0 0 var(--space-7);
}

.home-audience-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
}

.home-audience-card h2 {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-display);
  font-size: 1.1rem;
  margin: 0 0 var(--space-2);
}

.home-audience-icon {
  width: 22px;
  height: 22px;
  color: var(--color-accent);
}

.home-audience-card p {
  color: var(--color-text-muted);
  font-size: 0.95rem;
  margin: 0;
}

.home-cta-band {
  text-align: center;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
  padding: var(--space-7) var(--space-5);
  margin: 0 0 var(--space-6);
}

.home-cta-band h2 {
  font-family: var(--font-display);
  font-size: 1.75rem;
  margin: 0 0 var(--space-2);
}

.home-cta-band p {
  color: var(--color-text-muted);
  margin: 0 0 var(--space-5);
}

/* ---------------------------------------------------------------------- */
/* Analytics consent banner (Analytics.kt / ConsentBanner.kt)             */
/* ---------------------------------------------------------------------- */

.analytics-consent-banner {
  position: fixed;
  left: var(--space-5);
  right: var(--space-5);
  bottom: var(--space-5);
  z-index: 40;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  max-width: 640px;
  margin: 0 auto;
  padding: var(--space-4) var(--space-5);
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.45);
}

.analytics-consent-banner p {
  flex: 1 1 320px;
  margin: 0;
  color: var(--color-text);
  font-size: 0.9rem;
}

.analytics-consent-actions {
  display: flex;
  gap: var(--space-3);
  flex: 0 0 auto;
}

.analytics-consent-actions button {
  width: auto;
}

.analytics-consent-actions button:not(.btn-primary) {
  background: transparent;
  color: var(--color-text-muted);
  border: 1px solid var(--color-border-strong);
}

.analytics-consent-actions button:not(.btn-primary):hover {
  background: var(--color-surface-inset);
}

@media (max-width: 1080px) {
  .home-steps,
  .home-audiences {
    grid-template-columns: 1fr;
  }
}
