/* The hero demo is a mock of a real device screen, so it always renders the app's Material 3
   *light* theme (seed #E85D75) — regardless of whether the marketing site itself is in dark
   mode. Every color the demo needs is defined here as a local custom property, scoped to
   `.gd`, instead of reusing the site's `--bg`/`--surface`/etc. tokens (those flip under
   `prefers-color-scheme: dark` in the site stylesheet, which would make the "device" go dark too).
   Values are the exact Material 3 light roles measured from the app: see the feature spec. */
.gd {
  --app-bg: #fff8f7;                 /* colorScheme.surface */
  --app-surface-variant: #f0dedf;    /* colorScheme.surfaceContainerHighest */
  --app-primary: #8f4953;
  --app-on-primary: #ffffff;
  --app-tabbar-bg: #fceaea;
  --app-on-surface: #22191a;
  --app-on-surface-variant: #534345;
  color-scheme: light;
  position: relative;
  height: 100%;
  /* The top padding clears the phone mock's status bar, which the page draws over this area
     from outside the demo; --gd-top lets it match that bar's height. */
  padding: 0 10px 10px;
  padding-top: var(--gd-top, 56px);
  display: flex;
  flex-direction: column;
  font-family: var(--font-body, inherit);
  background: var(--app-bg);
  color: var(--app-on-surface);
}

/* ---------- View switching ---------- */
/* Both the tabs and chat "screens" (and the grid / swipe panes) are always in the DOM (see demo.js)
   and toggled with the `hidden` attribute rather than one replacing the other — that's what lets
   focus restore, after the chat's back button, find the very button that opened it: rebuilding
   the grid on every chat open would destroy and recreate its buttons, so the reference kept for
   focus restore would always point at a detached node. `[hidden]` already computes to `display:none`
   in the UA stylesheet, which removes the inactive view from layout, hit-testing AND the
   accessibility tree; the rule below just keeps that from being overridden by the `display:flex`
   these need while visible (same specificity, so source order would otherwise decide it). */
.gd-view-tabs, .gd-view-chat, .gd-pane { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.gd-view-tabs[hidden], .gd-view-chat[hidden], .gd-pane[hidden] { display: none; }

/* ---------- Discovery grid ---------- */
/* flex: 1 (not an explicit height) makes .gd-grid fill whatever vertical space is left in the
   .gd column after the tab bar/caption below take theirs. Grid's default `align-content` for
   auto-sized tracks resolves to "stretch", so the (implicit) rows then stretch evenly to fill
   that height — and each .gd-card, as a grid item with no explicit height, stretches with its
   row (same default). This is what keeps 6 two-column cards fitting the phone screen without
   overflow/scrolling, however tall the screen mock ends up being: the photo/action-row split
   inside each card only divides an already-bounded row height, it never adds to it. Do not
   give `.gd-grid` or `.gd-photo` a fixed/aspect-ratio height — that reintroduces overflow. */
.gd-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; flex: 1; min-height: 0; }

/* Stacking-context guard: .gd-card must establish its OWN stacking context (position + a
   non-auto z-index — 0 is enough) so its z-index:1 children are contained inside it and
   compared only against each other. Without this the match dialog (z-index below) can end up
   painted under a card's content. If you touch z-index anywhere in this file, keep this
   containment intact and keep .gd-match's z-index above .gd-card's. */
.gd-card {
  position: relative; z-index: 0;
  display: flex; flex-direction: column; min-height: 0;
  border-radius: 20px; overflow: hidden;
  background: #2a2326;
  transition: transform 320ms var(--ease), opacity 320ms var(--ease);
  animation: gd-in 320ms var(--ease);
}
.gd-card.is-leaving { transform: scale(0.85); opacity: 0; }

.gd-photo { position: relative; flex: 1; min-height: 0; overflow: hidden; }
.gd-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gd-scrim-top, .gd-scrim-bottom { position: absolute; left: 0; right: 0; z-index: 1; padding: 8px; pointer-events: none; }
.gd-scrim-top { top: 0; padding-bottom: 16px; background: linear-gradient(rgb(0 0 0 / 0.6), transparent); }
/* The photo fills the whole card; the reaction buttons float over its lower edge (.gd-actions
   below), so the name block sits above them and the dark gradient reaches down behind them. */
.gd-scrim-bottom { bottom: 0; padding: 36px 8px 46px; background: linear-gradient(transparent, rgb(0 0 0 / 0.4) 40%, rgb(0 0 0 / 0.72)); display: grid; gap: 2px; }
.gd-distance { color: rgb(255 255 255 / 0.9); font-size: 0.68rem; font-weight: 600; }
.gd-name { color: #fff; font-size: 0.78rem; font-weight: 700; display: inline-flex; align-items: center; gap: 3px; }
.gd-city { color: rgb(255 255 255 / 0.9); font-size: 0.65rem; }
.gd-verified-icon { color: var(--app-primary); flex: none; }

.gd-actions { position: absolute; z-index: 2; left: 0; right: 0; bottom: 0; display: flex; justify-content: center; padding: 0 8px 9px; }
/* Two small round buttons centred under the name: the photo stays the card. */
.gd-reactions { display: flex; gap: 24px; }
.gd-reactions button {
  display: grid; place-items: center; width: 32px; height: 32px; padding: 0; border: 0; border-radius: 50%;
  cursor: pointer; transition: transform 150ms;
}
.gd-reactions button svg { width: var(--gd-pass-icon, 23px); height: var(--gd-pass-icon, 23px); }
.gd-reactions button:active { transform: scale(0.9); }
.gd-reactions button:disabled { opacity: 0.6; cursor: default; }
/* Frosted white over the photo, so ✕ reads on any picture without a solid frame. */
.gd-pass { background: rgb(255 255 255 / 0.85); color: var(--app-on-surface); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); }
.gd-like { background: var(--app-primary); color: var(--app-on-primary); box-shadow: 0 4px 10px -3px rgb(0 0 0 / 0.5); }
/* The like is the Siamora mark itself: the logo's own shape, painted white through a mask. */
.gd-like svg { display: none; }
.gd-like::before {
  content: ''; width: var(--gd-like-mark, 18px); height: var(--gd-like-mark, 18px); background: currentColor;
  -webkit-mask: url(/assets/img/logo-64.webp) center / contain no-repeat;
  mask: url(/assets/img/logo-64.webp) center / contain no-repeat;
}

.gd-message {
  display: inline-flex; align-items: center; justify-content: center; gap: 5px; height: 32px; padding: 0 14px;
  border: 0; border-radius: 999px; background: var(--app-primary); color: var(--app-on-primary);
  font: inherit; font-weight: 700; font-size: 0.74rem; cursor: pointer; transition: transform 150ms;
  box-shadow: 0 4px 10px -3px rgb(0 0 0 / 0.5);
  animation: gd-pop 220ms var(--ease);
}
.gd-message svg { width: 15px; height: 15px; }
.gd-message:active { transform: scale(0.97); }

/* ---------- Bottom tab bar: Grid and Swipe are real tabs, Likes / Chats / Profile decorative ---------- */
.gd-tabbar { display: flex; align-items: stretch; gap: 2px; margin-top: 8px; padding: 6px 4px; border-radius: 16px; background: var(--app-tabbar-bg); }
/* Five equal columns (a 256 px card leaves ~46 px each): icon over a small caption, like the app's
   bottom bar. Long Russian / Thai captions are cut with an ellipsis rather than wrapped. */
.gd-tab { display: flex; flex: 1 1 0; min-width: 0; flex-direction: column; align-items: center; gap: 1px; padding: 3px 0; border-radius: 10px; color: var(--app-on-surface-variant); }
.gd-tab-label { max-width: 100%; padding: 0 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.55rem; line-height: 1.2; }
button.gd-tab { border: 0; padding: 3px 0; background: transparent; font: inherit; cursor: pointer; }
button.gd-tab:focus-visible { outline: 2px solid var(--app-primary); outline-offset: 2px; }
.gd-tab.is-active { color: var(--app-primary); background: rgb(143 73 83 / 0.12); }

.gd-caption { margin: 8px 0 0; text-align: center; font-size: 0.62rem; color: var(--app-on-surface-variant); }

/* ---------- Match overlay (mirrors discovery_match_overlay.dart) ---------- */
.gd-match {
  position: absolute; inset: 0; z-index: 2; display: grid; place-items: center; padding: 24px;
  background: rgb(0 0 0 / 0.54); animation: gd-fade 200ms var(--ease);
}
.gd-match-card {
  width: 100%; max-width: 240px; text-align: center; background: var(--app-bg); color: var(--app-on-surface);
  border-radius: 24px; padding: 26px 20px 20px; animation: gd-pop 320ms var(--ease);
}
.gd-match-heart { color: var(--app-primary); margin-bottom: 12px; }
.gd-match-card h3 { margin: 0 0 8px; font-size: 1.2rem; font-weight: 800; }
.gd-match-card p { margin: 0 0 18px; font-size: 0.82rem; line-height: 1.4; color: var(--app-on-surface-variant); }
.gd-match-send, .gd-match-keep {
  width: 100%; display: flex; align-items: center; justify-content: center; gap: 6px;
  border: 0; border-radius: 14px; padding: 10px 0; font: inherit; font-weight: 700; font-size: 0.85rem; cursor: pointer;
}
.gd-match-send { background: var(--app-primary); color: var(--app-on-primary); }
.gd-match-keep { background: transparent; color: var(--app-primary); margin-top: 6px; }

/* ---------- Chat screen (mirrors chat_screen.dart / chat_message_bubble.dart / chat_composer_bar.dart) ---------- */
/* A normal flex child of .gd-view-chat, NOT position:absolute — .gd's own top padding
   clears the phone mock's status bar, and an absolutely inset:0 child would ignore that
   padding and slide up underneath it. */
.gd-chat { flex: 1; min-height: 0; display: flex; flex-direction: column; background: var(--app-bg); animation: gd-fade 180ms var(--ease); }
.gd-chatbar { display: flex; align-items: center; gap: 12px; padding: 14px 12px; flex: none; }
.gd-chatbar-back {
  display: grid; place-items: center; width: 32px; height: 32px; flex: none; border: 0; border-radius: 50%;
  background: transparent; color: var(--app-on-surface); cursor: pointer;
}
.gd-chatbar-avatar { width: 36px; height: 36px; border-radius: 50%; object-fit: cover; flex: none; }
.gd-chatbar-name { flex: 1; min-width: 0; display: inline-flex; align-items: center; gap: 4px; font-weight: 700; font-size: 0.95rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gd-chatbar-more { display: grid; place-items: center; width: 28px; height: 28px; flex: none; color: var(--app-on-surface-variant); }

.gd-messages { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; padding: 8px 12px; }
.gd-bubble { max-width: 78%; padding: 10px 14px; border-radius: 16px; font-size: 0.85rem; line-height: 1.35; animation: gd-in 200ms var(--ease); }
.gd-bubble-theirs { align-self: flex-start; background: var(--app-surface-variant); color: var(--app-on-surface); border-bottom-left-radius: 4px; }
.gd-bubble-mine { align-self: flex-end; background: var(--app-primary); color: var(--app-on-primary); border-bottom-right-radius: 4px; }

.gd-composer-area { flex: none; }
.gd-sent-notice { margin: 0; padding: 0 12px 6px; font-size: 0.68rem; color: var(--app-on-surface-variant); text-align: center; }
.gd-composer { display: flex; align-items: center; gap: 8px; padding: 8px 8px 12px 12px; }
/* Decorative only (the demo never attaches files) — reduced opacity gives it the same "disabled
   affordance" look as a real inactive control, and pointer-events:none/cursor:default make sure
   it never LOOKS tappable (no hover cursor) even though, as a plain aria-hidden span, it was
   already unreachable by keyboard and inert to clicks (nothing listens for them). */
.gd-composer-attach {
  display: grid; place-items: center; width: 28px; height: 28px; flex: none;
  color: var(--app-on-surface-variant); opacity: 0.55; cursor: default; pointer-events: none;
}
.gd-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.gd-composer-input {
  flex: 1; min-width: 0; border: 0; border-radius: 24px; padding: 10px 16px; font: inherit; font-size: 0.85rem;
  background: var(--app-surface-variant); color: var(--app-on-surface);
}
.gd-composer-input::placeholder { color: var(--app-on-surface-variant); }
.gd-composer-input:disabled { opacity: 0.7; }
.gd-composer-send {
  display: grid; place-items: center; width: 44px; height: 44px; flex: none; border: 0; border-radius: 50%;
  background: var(--app-primary); color: var(--app-on-primary); cursor: pointer; transition: transform 150ms, opacity 150ms;
}
.gd-composer-send:active { transform: scale(0.94); }
.gd-composer-send:disabled { opacity: 0.45; cursor: default; }

/* ---------- Swipe deck (mirrors discovery_swipe_deck.dart / discovery_swipe_card.dart) ---------- */
/* Two absolutely stacked cards: the next one (scaled 0.94 → 1 as the top is dragged) and the top
   one (z-index 1). The transform transition animates both the spring-back and the 220 ms
   fly-off; .is-dragging turns it off so the card follows the pointer 1:1. */
.gd-deck { position: relative; z-index: 0; flex: 1; min-height: 0; }
.gd-deck-card {
  position: absolute; inset: 0; border-radius: 24px; overflow: hidden;
  background: var(--app-surface-variant);
  user-select: none; -webkit-user-select: none;
  transition: transform 220ms var(--ease);
}
.gd-deck-card.is-next { animation: gd-in 320ms var(--ease); }
.gd-deck-card.is-top { z-index: 1; cursor: grab; }
.gd-deck-card.is-top:focus-visible { outline: 3px solid var(--app-primary); outline-offset: 2px; }
.gd-deck-card.is-dragging { transition: none; cursor: grabbing; }
.gd-deck-photo { width: 100%; height: 100%; object-fit: cover; display: block; pointer-events: none; }
.gd-deck-info {
  position: absolute; left: 0; right: 0; bottom: 0; display: grid; gap: 4px;
  padding: 48px 76px 20px 20px; pointer-events: none;
  background: linear-gradient(transparent, rgb(0 0 0 / 0.75));
}
.gd-deck-name { color: #fff; font-size: 1.25rem; font-weight: 700; display: inline-flex; align-items: center; gap: 4px; }
.gd-deck-place { color: rgb(255 255 255 / 0.9); font-size: 0.8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gd-deck-hint {
  position: absolute; top: 20px; z-index: 1; display: grid; place-items: center;
  width: 58px; height: 58px; border-radius: 50%; background: rgb(0 0 0 / 0.35); color: #fff;
  pointer-events: none;
}
.gd-deck-hint.is-like { left: 20px; }
.gd-deck-hint.is-pass { right: 20px; }
.gd-deck-message {
  position: absolute; right: 16px; bottom: 18px; z-index: 1; display: grid; place-items: center;
  width: 52px; height: 52px; border: 0; border-radius: 50%; cursor: pointer;
  background: var(--app-primary); color: var(--app-on-primary);
  box-shadow: 0 2px 8px rgb(0 0 0 / 0.25); transition: transform 150ms;
}
.gd-deck-message:active { transform: scale(0.94); }

@media (prefers-reduced-motion: reduce) {
  .gd-deck-card { transition: none; animation: none; }
}

@keyframes gd-in { from { opacity: 0; transform: scale(0.92); } }
@keyframes gd-pop { from { opacity: 0; transform: scale(1.06); } }
@keyframes gd-fade { from { opacity: 0; } }
