/* =========================================================================
   Feedler — website shared styles
   Palette mirrors the app's built-in Dark theme (PredefinedThemes.swift).
   Reused across every page (cover, FAQ, contact, privacy).
   ========================================================================= */

:root {
  /* The site is dark by design. Declaring the scheme makes the browser render
     UA bits (scrollbars, form controls) dark and signals the dark theme to
     well-behaved tools. */
  color-scheme: dark;

  /* Dark theme tokens (1:1 with the app) */
  --bg:              #202020;
  --bg-secondary:    #363636;
  --bg-tertiary:     #444444;
  --text-primary:    #E1E1E1;
  --text-body:       #C0C0C0;  /* readable body copy (matches the app reader) */
  --text-secondary:  #888888;
  --text-tertiary:   #555555;
  --accent:          #F1745E;
  --separator:       #444444;

  /* Derived */
  --accent-glow:     rgba(241, 116, 94, 0.18);
  --card:            rgba(54, 54, 54, 0.55);
  --border:          rgba(255, 255, 255, 0.08);

  --font: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text",
          "Helvetica Neue", Helvetica, Arial, sans-serif;

  --maxw: 760px;
  --radius: 18px;
}

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

html {
  -webkit-text-size-adjust: 100%;
  background-color: var(--bg); /* avoids a flash during page transitions */
}

body {
  margin: 0;
  min-height: 100vh;   /* fallback */
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  font-family: var(--font);
  color: var(--text-primary);
  background-color: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  line-height: 1.6;
}



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

/* ---- Page transitions --------------------------------------------------- */
/* Reliable cross-browser transition (JS-driven, see site.js): the page blurs
   in on load and blurs out before navigating to another internal page. Works
   in every browser, unlike the View Transitions API. */
@media (prefers-reduced-motion: no-preference) {
  body { animation: page-enter 0.5s cubic-bezier(0.16, 1, 0.3, 1) both; }
  body.is-leaving { animation: page-leave 0.24s ease both; }

  /* Inner pages (those with <main class="page">) don't blur-fade as a whole;
     instead their content slides slightly up and fades in. The homepage
     (<main class="cover">) keeps the page-enter blur-fade above untouched. */
  body:has(main.page) { animation: none; }
  body:has(main.page).is-leaving { animation: page-leave 0.24s ease both; }
  /* Fade only — NO transform. A transform (even a transient/animating one) on
     `.page` makes it the containing block for `position: fixed` descendants (the
     screenshot lightbox), so the lightbox would size/centre against the page
     column + document height instead of the viewport — badly broken when the
     page is scrolled. Opacity doesn't create a containing block, so the entry
     fade is safe. (Was `page-rise` with a translateY that broke this.) */
  body:has(main.page) .page {
    animation: page-fade 0.5s cubic-bezier(0.16, 1, 0.3, 1) backwards;
  }
}
@keyframes page-enter {
  from { opacity: 0; filter: blur(7px); }
  to   { opacity: 1; filter: blur(0); }
}
@keyframes page-leave {
  from { opacity: 1; filter: blur(0); transform: translateY(0); }
  to   { opacity: 0; filter: blur(5px); transform: translateY(-8px); }
}
@keyframes page-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ---- Cover / hero ------------------------------------------------------- */

.cover {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 48px 24px;
  gap: 0;
}

.cover__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.logo {
  width: 140px;
  height: auto;
  animation:
    rise 0.7s cubic-bezier(0.2, 0.7, 0.2, 1) both,
    logo-float 4.5s ease-in-out 0.9s infinite;
}

@keyframes logo-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-8px); }
}

@media (prefers-reduced-motion: reduce) {
  .logo { animation: rise 0.7s cubic-bezier(0.2, 0.7, 0.2, 1) both; }
}

.wordmark {
  margin: 26px 0 0;
  font-size: clamp(2.4rem, 6vw, 3.4rem);
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--text-primary);
  animation: rise 0.7s cubic-bezier(0.2, 0.7, 0.2, 1) 0.12s both;
}

.tagline {
  margin: 10px 0 0;
  font-size: clamp(0.85rem, 2.2vw, 1rem);
  font-weight: 400;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-secondary);
  animation: rise 0.7s cubic-bezier(0.2, 0.7, 0.2, 1) 0.24s both;
}

/* ---- Coming soon + App Store badge ------------------------------------- */

.coming-soon {
  margin-top: 52px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  animation: rise 0.7s cubic-bezier(0.2, 0.7, 0.2, 1) 0.38s both;
}

.coming-soon__eyebrow {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent);
}

/* App Store badge — styled like Apple's pill, marked "Coming soon". */
.appstore-badge {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 12px 20px;
  border-radius: 14px;
  background: #000;
  border: 1px solid rgba(255, 255, 255, 0.22);
  color: #fff;
  cursor: default;
  user-select: none;
}

.appstore-badge__apple { width: 26px; height: 26px; flex: none; fill: #fff; }

.appstore-badge__text { display: flex; flex-direction: column; line-height: 1.1; text-align: left; }
.appstore-badge__small { font-size: 0.62rem; letter-spacing: 0.02em; opacity: 0.85; }
.appstore-badge__big   { font-size: 1.25rem; font-weight: 600; letter-spacing: -0.01em; }

/* ---- Header (content pages) -------------------------------------------- */

.site-header {
  display: flex;
  align-items: center;
  padding: 18px 24px;
  border-bottom: 1px solid var(--border);
}

.site-header__brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--text-primary);
  font-weight: 500;
  font-size: 1.05rem;
}
.site-header__brand:hover { text-decoration: none; opacity: 0.85; }
.site-header__brand img {
  width: 30px;
  height: auto;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.4));
}

/* ---- Content page (FAQ / Contact / Privacy) ---------------------------- */

.page {
  flex: 1 0 auto;
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 48px 24px 32px;
}

.page h1 {
  margin: 0 0 6px;
  font-size: clamp(1.9rem, 5vw, 2.6rem);
  font-weight: 600;
  letter-spacing: -0.01em;
}

.page__updated {
  margin: 0 0 36px;
  font-size: 0.9rem;
  color: var(--text-secondary);
}

.page h2 {
  margin: 38px 0 10px;
  font-size: 1.2rem;
  font-weight: 600;
  color: var(--text-primary);
}

.page p,
.page li {
  font-size: 1rem;
  line-height: 1.75;
  color: var(--text-body);
}

.page ul { padding-left: 22px; margin: 10px 0; }
.page li { margin: 6px 0; }
.page strong { color: var(--text-primary); font-weight: 600; }

/* ---- FAQ accordion ------------------------------------------------------ */

/* ── FAQ search — prominent pill that filters questions by the typed words ── */
.faq-search {
  position: relative;
  margin: 26px 0 36px; /* extra breathing room below so it reads as its own block */
}
.faq-search__icon {
  position: absolute;
  left: 20px; top: 50%;
  transform: translateY(-50%);
  width: 19px; height: 19px;
  color: var(--text-secondary);
  pointer-events: none;
  transition: color 0.18s ease;
}
.faq-search:focus-within .faq-search__icon { color: var(--accent); }
.faq-search__input {
  width: 100%;
  box-sizing: border-box;
  padding: 16px 52px;
  font: inherit;
  font-size: 1.05rem;
  color: var(--text-primary);
  /* Lighter fill than the cards + a soft elevation shadow so the bar floats
     above the list and clearly stands out. */
  background: var(--bg-tertiary);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 999px; /* fully rounded pill */
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.3);
  -webkit-appearance: none;
  appearance: none;
  transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
}
.faq-search__input::placeholder { color: var(--text-secondary); }
.faq-search__input:focus {
  outline: none;
  border-color: var(--accent);
  background: #4d4d4d;
  box-shadow: 0 0 0 4px var(--accent-glow), 0 12px 30px rgba(0, 0, 0, 0.34);
}
.faq-search__input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.faq-search__clear {
  position: absolute;
  right: 10px; top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center; justify-content: center;
  width: 34px; height: 34px;
  border: none; border-radius: 50%;
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  transition: color 0.15s ease, background 0.15s ease;
}
.faq-search__clear svg { width: 18px; height: 18px; }
.faq-search__clear:hover { color: var(--text-primary); background: rgba(255, 255, 255, 0.08); }
/* `display: inline-flex` above would otherwise override the [hidden] attribute. */
.faq-search__clear[hidden] { display: none; }
/* Hidden state set by JS AFTER the collapse animation finishes. */
.faq__item.is-filtered-out { display: none; }
.faq-noresults {
  text-align: center;
  color: var(--text-secondary);
  margin: 6px 0 0;
  padding: 22px 0;
}
.faq__q mark {
  background: var(--accent-glow);
  color: var(--text-primary);
  border-radius: 3px;
  padding: 0 2px;
}

.faq {
  display: flex;
  flex-direction: column;
  /* No flex `gap` — per-item margin instead, so the JS can animate it to 0 as an
     item collapses out of the filter (gap can't be animated per item). */
  margin-top: 8px;
}
.faq__item { margin-bottom: 10px; }
.faq__item:last-child { margin-bottom: 0; }

.faq__item {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--card);
  overflow: hidden;
  transition: border-color 0.35s ease;
}
/* The open card frames itself in faint coral so it stands out from the rest. */
.faq__item--open { border-color: rgba(241, 116, 94, 0.4); }

.faq__item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 16px 18px;
  cursor: pointer;
  font-size: 1.02rem;
  font-weight: 500;
  color: var(--text-primary);
  list-style: none;
  /* Don't let a click/double-click select the question text. */
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 0.25s ease;
}
.faq__item summary::-webkit-details-marker { display: none; }
/* Subtle hover — the row just lightens (no moving text). Disabled once the item
   is open: the coral title + border are the highlight then. */
.faq__item:not(.faq__item--open) summary:hover { background-color: rgba(255, 255, 255, 0.045); }

.faq__q {
  flex: 1;
  transition: color 0.35s ease;
}
/* Open question fades to the coral accent (animated, not an ON/OFF switch) to
   highlight which answer is showing. */
.faq__item--open .faq__q { color: var(--accent); }

/* Leave breathing room (and clear any future sticky header) when a deep-linked
   question is scrolled to the top via ?q=<slug>. */
.faq__item { scroll-margin-top: 84px; }

/* Discreet "copy link to this question" button, injected by JS into each
   header. Faint by default; on hover-capable devices it only appears when the
   row is hovered, so it never competes with the question. On touch (no hover)
   it stays gently visible so it's still discoverable. */
.faq__copy {
  flex: none;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  margin: -6px 0;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--text-secondary);
  opacity: 0.55;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: opacity 0.2s ease, color 0.2s ease, background-color 0.2s ease,
    transform 0.2s ease;
}
.faq__copy svg { width: 16px; height: 16px; display: block; }
.faq__copy:hover { color: var(--accent); background: rgba(241, 116, 94, 0.12); }
.faq__copy:active { transform: scale(0.9); }
/* Copied confirmation — checkmark flips to coral briefly. */
.faq__copy--done { color: var(--accent); opacity: 1; }
@media (hover: hover) {
  .faq__copy { opacity: 0; }
  .faq__item summary:hover .faq__copy,
  .faq__copy:focus-visible,
  .faq__copy--done { opacity: 0.7; }
  .faq__item summary:hover .faq__copy:hover { opacity: 1; }
}

/* Brief highlight pulse on the question opened via a shared ?q=<slug> link, so
   it's instantly clear which one the link pointed to. */
@keyframes faqFlash {
  0%   { box-shadow: 0 0 0 0 rgba(241, 116, 94, 0); }
  18%  { box-shadow: 0 0 0 4px rgba(241, 116, 94, 0.35); }
  100% { box-shadow: 0 0 0 0 rgba(241, 116, 94, 0); }
}
.faq__item--flash { animation: faqFlash 1.5s ease-out; }

@media (prefers-reduced-motion: reduce) {
  .faq__item,
  .faq__item summary,
  .faq__q { transition: none; }
  .faq__copy { transition: none; }
  .faq__item--flash { animation: none; }
}

.faq__chevron {
  flex: none;
  width: 18px;
  height: 18px;
  color: var(--accent);
  /* Bouncy rotate (ease-out-back overshoot) to match the expand. */
  transition: transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.faq__item--open .faq__chevron { transform: rotate(180deg); }

/* Outer wrapper is what JS animates (height 0 ↔ content), so it clips. */
.faq__answer { overflow: hidden; }

.faq__answer-inner {
  padding: 4px 18px 18px;
  color: var(--text-body);
  line-height: 1.75;
}
.faq__answer-inner a { color: var(--accent); }

/* Inline app-navigation path, e.g. "Settings › Article". Styled like the
   reader's inline <code> token: a neutral tinted box with a hairline
   border and monospace type, so a path reads as a distinct UI string that
   stands clearly apart from the prose — without a loud coloured fill.
   Left on the default `box-decoration-break: slice` (as the reader's
   <code> is) so a long path that wraps reads as one continuous box across
   the break rather than two stacked chips. Never breaks mid-label: every
   space that could break is a real space only *after* each separator,
   while labels and the "label ›" pair are glued with &nbsp; — so the sole
   wrap opportunity is right after a ›. On full-width screens the path
   stays on one line (`nowrap` suppresses those spaces); the mobile block
   below (≤700px) drops the nowrap so a path too wide for the narrow flex
   column breaks cleanly after a › (never inside "Manage Account") instead
   of overflowing. (A real space is used rather than <wbr>, which some
   engines still break at under `nowrap`.) Reusable: wrap the path in
   `.path`, write each separator as `&nbsp;<span>›</span> ` (nbsp before,
   real space after), and join multi-word labels with &nbsp;. */
.path {
  padding: 1px 6px;
  border-radius: 6px;
  background: var(--bg-tertiary);
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: var(--text-primary);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.85em;
  font-style: normal;
  white-space: nowrap;
}
.path > span {
  color: var(--text-secondary);
}

/* Real, airy lists (e.g. the providers) with coral markers. */
.faq__answer-inner ul {
  margin: 14px 0 4px;
  padding-left: 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.faq__answer-inner li { margin: 0; }
.faq__answer-inner li::marker { color: var(--accent); }

/* Group labels (e.g. Web-hosted / Self-hosted) above each services list. */
.faq__services-label {
  margin: 18px 0 8px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent);
}
.faq__services-label + ul { margin-top: 0; }

/* A sub-question heading inside an answer (e.g. "Why isn't Feedly supported?"). */
.faq__subq {
  margin: 22px 0 6px;
  font-weight: 600;
  color: var(--text-primary);
}

/* "Why choose Feedler?" — an icon list (more striking than plain bullets). */
.faq__answer-inner .why {
  list-style: none;
  padding-left: 0;
  margin: 20px 0 8px;
  gap: 16px;
}
.faq__answer-inner .why > li {
  display: flex;
  gap: 14px;
  align-items: center;
  margin: 0;
}
.why__icon {
  flex: none;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(241, 116, 94, 0.13);
  color: var(--accent);
}
.why__icon svg { width: 21px; height: 21px; display: block; }
.why__body strong { color: var(--text-primary); }
/* Two-way sub-list inside a "why" step (e.g. the OPML import options). The step
   gets taller, so top-align its icon instead of centring it. */
.why__ways { margin: 8px 0 4px; padding-left: 18px; list-style-type: disc; }
.why__ways li { margin: 4px 0; }
.faq__answer-inner .why > li:has(.why__ways) { align-items: flex-start; }
/* Closing line under the list — same breathing room as above the list. */
.faq__answer-inner .why__outro { margin: 20px 0 0; }

/* Provider list — official logo (in brand colours) in front of each name. */
.faq__answer-inner .providers {
  list-style: none;
  padding-left: 14px;
  margin: 12px 0 4px;
  gap: 11px;
}
.faq__answer-inner .providers > li { margin: 0; }
.faq__answer-inner .providers a {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  color: var(--text-primary);   /* white name, not the link accent */
}
.faq__answer-inner .providers a:hover { text-decoration: none; }
.provider-logo {
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 5px;
}

/* Provider name: same sliding underline as the footer menu links. */
.provider-name { position: relative; }
.provider-name::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -3px;
  height: 1.5px;
  border-radius: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.32s cubic-bezier(0.16, 1, 0.3, 1);
}
.providers a:hover .provider-name::after { transform: scaleX(1); }

/* ---- FAQ screenshots + CSS-only lightbox (tap to zoom) ------------------ */

/* A row of tappable phone screenshots inside an answer. Wraps on narrow
   screens; the whole thing is pure CSS — a hidden checkbox per shot drives
   the lightbox, so open/close animate with no JavaScript. */
.faq__answer-inner .shots {
  display: flex;
  justify-content: center;
  /* Two-shot rows (e.g. the Activity Log pair) sit side by side and
     share the width; the gap keeps single-shot blocks untouched. */
  gap: 14px;
  margin: 18px 0 22px;
}
.faq__answer-inner .shots .shot {
  margin: 0;
  width: 100%;
  max-width: 320px;
  display: flex;
  flex-direction: column;
  gap: 11px;
}
.shot figcaption {
  font-size: 0.82rem;
  line-height: 1.4;
  text-align: center;
  color: var(--text-secondary);
}

/* Thumbnail — a framed card that lifts on hover, with a zoom badge. It's an
   <a> (opens the GLightbox viewer), so kill the link underline/colour. */
.shot__thumb {
  position: relative;
  display: block;
  cursor: zoom-in;
  text-decoration: none;
  /* Fixed frame → identical height for every shot. Since all the screenshots
     share one width (always an iPhone), the image fills the width at its NATURAL
     scale (no zoom) and the frame simply crops the bottom. The lightbox shows
     the whole, uncropped screenshot. */
  aspect-ratio: 7 / 8;
  border-radius: 18px;
  overflow: hidden;
  border: 1px solid var(--border);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.28);
  transition: transform 0.25s cubic-bezier(0.2, 0.8, 0.25, 1), box-shadow 0.25s ease;
}
.shot__thumb img { display: block; width: 100%; height: auto; }
/* A landscape (shorter) screenshot: the fixed 7/8 portrait frame would leave
   empty space below it. Match the frame to the image's own aspect instead, so it
   fills exactly — no gap, no crop, and the space stays reserved (no lazy-load
   layout shift). Set to each wide image's ratio. */
.shot__thumb--wide { aspect-ratio: 1206 / 903; }
.shot__thumb--square { aspect-ratio: 1 / 1; }
/* Soft fade where the bottom is cropped, so the cut dissolves into the dark
   instead of ending on a hard edge. */
.shot__thumb::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 30%;
  background: linear-gradient(to bottom, rgba(32, 32, 32, 0), var(--bg));
  pointer-events: none;
}
/* Hover affordances ONLY for real pointing devices. On touch, a :hover rule
   makes the FIRST tap paint the hover state instead of firing the click (iOS
   "sticky hover") → the user has to tap twice to open. Gating with
   `@media (hover: hover)` keeps the lift/reveal on desktop and makes the first
   tap open on mobile. */
@media (hover: hover) {
  .shot__thumb:hover { transform: translateY(-4px); box-shadow: 0 16px 38px rgba(0, 0, 0, 0.42); }
}
/* Frosted-glass circular zoom badge on the thumbnail. Low-alpha fill so what's
   behind blurs through, plus a hairline highlight border — like the app's glass
   controls, not a flat disc. */
.shot__zoom {
  display: grid;
  place-items: center;
  border-radius: 50%;
  color: #fff;
  background: rgba(40, 40, 42, 0.35);
  backdrop-filter: blur(18px) saturate(180%);
  -webkit-backdrop-filter: blur(18px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.18);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.22);
}

/* Zoom badge — bottom-right of the thumbnail, revealed on hover. */
.shot__zoom {
  position: absolute;
  right: 10px;
  bottom: 10px;
  z-index: 2;                     /* above the bottom fade */
  width: 34px;
  height: 34px;
  opacity: 0;
  transform: scale(0.8);
  transition: opacity 0.25s ease, transform 0.25s ease;
}
@media (hover: hover) {
  .shot__thumb:hover .shot__zoom { opacity: 1; transform: scale(1); }
}
/* Touch: no hover to reveal it → show the badge permanently as the tap affordance. */
@media (hover: none) {
  .shot__zoom { opacity: 1; transform: scale(1); }
}
.shot__zoom svg { width: 17px; height: 17px; }

@media (prefers-reduced-motion: reduce) {
  .shot__thumb,
  .shot__zoom { transition: none; }
}

/* ---- Contact cards ------------------------------------------------------ */

.contact-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin: 30px 0 8px;
}

.contact-card {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 18px 20px;
  border: 1px solid var(--border);
  border-radius: 16px;
  background: var(--card);
  color: var(--text-primary);
  transition:
    transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1),
    border-color 0.2s ease,
    background 0.2s ease;
}
.contact-card:hover {
  text-decoration: none;
  transform: translateY(-3px);
  border-color: rgba(241, 116, 94, 0.45);
  background: rgba(54, 54, 54, 0.72);
}

.contact-card__icon {
  flex: none;
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(241, 116, 94, 0.14);
  color: var(--accent);
}
.contact-card__icon svg { width: 22px; height: 22px; }

.contact-card__text {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.contact-card__label {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.contact-card__value {
  font-size: 1.05rem;
  color: var(--text-primary);
  overflow-wrap: anywhere;
}

.contact-card__arrow {
  flex: none;
  color: var(--text-secondary);
  transition:
    transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1),
    color 0.2s ease;
}
.contact-card__arrow svg { width: 18px; height: 18px; display: block; }
.contact-card:hover .contact-card__arrow {
  transform: translateX(4px);
  color: var(--accent);
}

/* ---- Footer (shared) ---------------------------------------------------- */

.site-footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 36px 24px 44px;
  text-align: center;
  font-size: 0.9rem;
  color: var(--text-secondary);
}

.site-footer__nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px 24px;
  font-size: 0.95rem;
}
.site-footer__nav a {
  position: relative;
  color: var(--text-body);
  transition: color 0.2s ease;
}
/* Modern sliding underline that grows from the left on hover. */
.site-footer__nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -4px;
  height: 1.5px;
  border-radius: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.32s cubic-bezier(0.16, 1, 0.3, 1);
}
.site-footer__nav a:hover { color: var(--text-primary); text-decoration: none; }
.site-footer__nav a:hover::after { transform: scaleX(1); }

/* Social links (Bluesky, Mastodon) — discreet muted glyphs, side by side,
   tinting coral on hover. */
.site-footer__social {
  display: inline-flex;
  align-items: center;
  gap: 16px;
}
.site-footer__social a {
  display: inline-flex;
  color: var(--text-body);
  transition: color 0.2s ease;
}
.site-footer__social a:hover { color: var(--accent); }
.site-footer__social svg { width: 18px; height: 18px; }

.site-footer__copy { margin: 0; font-size: 0.85rem; color: var(--text-secondary); }

/* ---- Animations --------------------------------------------------------- */

@keyframes rise {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .logo, .wordmark, .tagline, .coming-soon, .site-footer { animation: none; }
}

/* ============================================================================
   GLightbox reskin → the old custom-lightbox look (frosted glass discs, rounded
   image, italic caption, "n / total" pill, Lucide chevrons, blurred backdrop).
   style.css loads AFTER glightbox.min.css, so these win at equal specificity.
   ============================================================================ */

/* Blurred, dark backdrop (0.86 alpha + blur 6, like the app's glass). */
.glightbox-container .goverlay {
  background: rgba(16, 16, 16, 0.86);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

/* Rounded image with a hairline outline + soft shadow. */
.glightbox-clean .gslide-image img {
  border-radius: 16px;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.06), 0 14px 40px rgba(0, 0, 0, 0.45);
}
/* Kill GLightbox's OWN drop-shadow on the media container — we shadow the image
   itself (above) — AND cap the container to the same width as the (capped) image.
   GLightbox sizes the container to the UN-capped fit (e.g. 868px for a landscape
   shot); left alone it shows a ghost shadow "outline" at that old width, and the
   invisible strip beside the narrower image still counts as the media so a tap
   there won't close the lightbox. Matching it to the image makes that strip
   backdrop again (tap-to-close works). Portrait shots are already this narrow. */
.glightbox-clean .gslide-media,
.glightbox-clean .gslide-image {
  box-shadow: none;
  max-width: min(100%, 560px) !important;
}
/* GLightbox's tap-to-close (closeOnOutsideClick) treats any click INSIDE
   `.ginner-container` as "keep open" — but it makes that container FULL-WIDTH, so
   the empty area beside a narrower image is a dead zone (tap doesn't close).
   Shrink it to wrap the media so ONLY the image itself keeps the lightbox open. */
.glightbox-clean .ginner-container {
  width: -moz-fit-content !important;
  width: fit-content !important;
  max-width: min(100%, 560px) !important;
}

/* Frosted circular buttons — close + arrows (the app's glass-control recipe). */
.glightbox-clean .gclose,
.glightbox-clean .gnext,
.glightbox-clean .gprev {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: rgba(40, 40, 42, 0.35);
  -webkit-backdrop-filter: blur(18px) saturate(180%);
  backdrop-filter: blur(18px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.18);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.22);
  opacity: 1;
  transition: background-color 0.2s ease, transform 0.2s ease;
}
.glightbox-clean .gclose { top: 16px; right: 16px; }
.glightbox-clean .gclose:hover,
.glightbox-clean .gnext:hover,
.glightbox-clean .gprev:hover {
  background: rgba(62, 62, 64, 0.5);
  opacity: 1;
}
.glightbox-clean .gclose:active,
.glightbox-clean .gnext:active,
.glightbox-clean .gprev:active { transform: scale(0.9); }

/* Our opacity:1 above would otherwise reveal arrows GLightbox has disabled
   (a single-image answer, or an unreachable direction) as fully-opaque but dead
   buttons. Hide them outright instead. */
.glightbox-clean .gnext.disabled,
.glightbox-clean .gprev.disabled,
.glightbox-clean .glightbox-button-hidden { display: none !important; }

/* Our injected Lucide glyphs — stroked, centred. GLightbox ships
   `.glightbox-clean .gnext path { fill:#fff }`, which (CSS beats the SVG's own
   `fill="none"` presentation attr) fills our chevrons solid → must override the
   PATH, not just the svg. */
.glightbox-clean .gclose svg,
.glightbox-clean .gnext svg,
.glightbox-clean .gprev svg {
  width: 22px;
  height: 22px;
}
.glightbox-clean .gclose svg path,
.glightbox-clean .gnext svg path,
.glightbox-clean .gprev svg path {
  fill: none;
  stroke: #fff;
}

/* Caption: hide GLightbox's own in-flow description (white box, awkward layout)
   and render our OWN fixed italic caption above the counter pill (like the old
   lightbox) — updated in JS from the current slide. Cap the image height so it
   never reaches down into the caption + pill band. */
.glightbox-clean .gslide-description { display: none; }
/* GLightbox sizes the image with an INLINE `max-height: calc(100vh - Npx)` where
   N is its (now hidden) description's height = 0, so the image would fill the
   full height and sit under our caption + pill. !important beats that inline. */
.glightbox-clean .gslide-image img {
  max-height: calc(100vh - 150px) !important;
  /* Also cap the WIDTH so a landscape/short screenshot doesn't blow up on wide
     screens (its height cap never binds). Portrait shots are height-limited and
     stay far narrower than this, so they're unaffected. */
  max-width: min(100%, 560px) !important;
}
.feedler-caption {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 56px;
  padding: 0 20px;
  text-align: center;
  font-size: 0.85rem;
  font-style: italic;
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.72);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.55);
  pointer-events: none;
  z-index: 1000000;
}

/* "n / total" frosted pill, bottom-centre (injected in JS as .feedler-counter). */
.feedler-counter {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  padding: 5px 12px;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1.2;
  color: rgba(255, 255, 255, 0.92);
  background: rgba(40, 40, 42, 0.35);
  -webkit-backdrop-filter: blur(18px) saturate(180%);
  backdrop-filter: blur(18px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.18);
  z-index: 1000000;
  pointer-events: none;
}

/* Fade our caption + pill OUT with the close — otherwise they stay fully solid
   and then pop at the very END of the close (they aren't part of GLightbox's own
   fade). GLightbox adds `.glightbox-closing` to the container while closing (its
   fade is `gfade* 0.5s ease`). Transition-only (no keyframe animation, which left
   them stuck at opacity 0 on open); they show instantly with the content. */
.feedler-caption,
.feedler-counter { transition: opacity 0.4s ease; }
.glightbox-container.glightbox-closing .feedler-caption,
.glightbox-container.glightbox-closing .feedler-counter { opacity: 0; }

/* Phones: no gutter for side arrows over the image → hide; swipe + pill carry
   nav (exactly the old lightbox behaviour). */
@media (max-width: 700px) {
  .glightbox-clean .gnext,
  .glightbox-clean .gprev { display: none; }
}

/* Phones: let a path that can't fit the narrow flex column wrap at its
   separators (the <wbr> points) instead of overflowing. Labels stay glued
   by &nbsp;, so it only ever breaks at a ›, never mid-label. */
@media (max-width: 700px) {
  .path { white-space: normal; }
}
