/* ==========================================================================
   Shared components: glass button, nav (mobile + desktop), footer,
   case-page overlay shell, cookie consent banner
   ========================================================================== */

/* ---------- CTA headline (used on every page's pre-footer CTA section) ----------
   Matches .pg-headline's font/size exactly (same weight, stroke, tracking) so the
   CTA headline reads as the same "page headline" treatment, just on the accent
   section. Desktop size is bumped per page below, mirroring that page's own
   .pg-headline desktop override. */
.pg-cta-head {
  font-family: var(--font-ui);
  font-weight: 400;
  -webkit-text-stroke: 0.048em currentColor;
  font-size: min(2.4rem, 8.8cqw, 4dvh);
  line-height: 1.1;
  letter-spacing: calc(0.029em + 0.2pt);
  text-transform: uppercase;
  color: var(--colour-bg);
  text-wrap: balance;
}

/* ---------- Glass button (the ONLY button style site-wide) ---------- */
/* .pg-btn[hidden] restores the native hidden-attribute behaviour -- .pg-btn's
   own `display: flex` below is an author-stylesheet rule, which otherwise
   silently overrides the browser's built-in `[hidden] { display: none }` UA
   rule (author styles always win over UA styles, regardless of specificity
   or source order), so a `hidden` .pg-btn stayed visible instead of hiding.
   Bit by this in the questionnaire's step nav (Back/Continue/Submit), where
   toggling `hidden` on/off per step had no visible effect. */
.pg-btn[hidden] { display: none; }
.pg-btn {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: center;
  gap: 0.35em;
  padding: min(16px, 1.5dvh) 12px;
  border-radius: var(--radius-button);
  border: none;
  background: var(--colour-accent-40);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  box-shadow: var(--shadow-glass);
  color: var(--colour-ink);
  font-family: var(--font-ui);
  font-size: var(--size-button);
  font-weight: 400;
  -webkit-text-stroke: 0.018em currentColor;
  text-align: center;
  transition: filter 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
}

.pg-btn:hover {
  filter: brightness(1.05);
  transform: translateY(-1px);
  box-shadow: var(--shadow-glass-hover);
}

.pg-btn:active {
  filter: brightness(1.05);
  transform: translateY(1px);
  box-shadow: inset 0 2px 6px rgba(58, 63, 67, 0.18);
}

.pg-btn--auto { width: auto; padding-left: 28px; padding-right: 28px; }

.pg-btn:disabled { opacity: 0.6; cursor: default; pointer-events: none; }

@media (min-width: 760px) {
  .pg-btn { font-size: min(12pt, 2.4dvh); }
}

/* ---------- Shared inline form-validation/submit error (Phase 5: Forms) ----------
   Used by the Inquiry (Section 7), Contact, and Acquire purchase forms. Always
   occupies its layout box (reserved for up to two lines of text) so that the
   submit button below it never jumps/shifts when a message appears — only
   opacity toggles via .is-visible once JS has a message to display. */
.pg-form-error {
  display: block;
  min-height: 2.6em;
  margin: 8px 0 0 0;
  font-family: var(--font-body);
  font-weight: 300;
  font-size: calc(min(1rem, 4.6cqw, 2.8dvh) - 2pt);
  line-height: 1.3;
  color: #B23B3B;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.pg-form-error.is-visible { opacity: 1; }

/* ---------- Shared honeypot field (Phase 6: Anti-Spam) ----------
   Off-screen (not display:none/type="hidden", which some bots skip) so real
   visitors never see or reach it via tab order, but bots that blindly fill
   every field in a form will populate it — a filled honeypot is treated as
   spam server-side (see is_spam_submission() in includes/form-helpers.php).
   Used by the Inquiry (Section 7), Contact, and Acquire purchase forms. */
.pg-hp {
  position: absolute;
  left: -9999px;
  top: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ---------- Nav: mobile three-dot trigger ---------- */
/* Plain 3-dot glyph, no circular glass backdrop — sits above the horizontal
   nav bar (.pg-nav-mobile) so it stays visible/tappable while the bar is open. */
.pg-nav-trigger {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 52;
  width: auto;
  height: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 10px;
  border: none;
  border-radius: 999px;
  background: none;
  cursor: pointer;
}

.pg-nav-trigger span {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--colour-ink);
  display: block;
}

@media (min-width: 760px) {
  .pg-nav-trigger { display: none; }
}

/* Hide the fixed-position trigger while the mobile nav bar is open — it sits
   above the bar (z-index 52 vs 50) so it stays tappable to toggle closed,
   but that also means it visually overlaps the last link. Once the bar is
   open, closing already happens via outside-tap/close-button/Escape, so the
   trigger dots have no further job to do until the bar closes again. */
.pg-nav-trigger.is-hidden {
  display: none;
}

/* Per-section mobile menu trigger (three dots), used on pages that repeat the
   trigger inside every section rather than a single global one. Same rule:
   mobile-only, hidden once the always-visible desktop nav takes over. */
@media (min-width: 760px) {
  .pg-menu-btn { display: none !important; }
}

/* ---------- Nav: mobile fixed overlay panel ---------- */
.pg-nav-mobile {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 50;
  display: none;
  background: rgba(123, 148, 175, 0.37);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  box-shadow: var(--shadow-glass);
}

.pg-nav-mobile.is-open { display: block; }

.pg-nav-mobile__panel {
  position: static;
  transform: none;
  width: 100%;
  max-width: none;
  height: auto;
  background: transparent;
  padding: 16px 20px;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: space-between;
  align-items: center;
  gap: 6px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.pg-nav-mobile__panel::-webkit-scrollbar { display: none; }

.pg-nav-mobile__panel a {
  flex: 0 0 auto;
  color: var(--colour-ink);
  font-family: var(--font-body);
  font-weight: 300;
  font-size: calc(min(0.74rem, 3.2dvh) + 1pt);
  letter-spacing: 0.01em;
  white-space: nowrap;
  transition: transform 0.2s ease, color 0.2s ease;
}

.pg-nav-mobile__panel a:hover { transform: translateX(5px); }

.pg-nav-mobile__close {
  display: none;
}

@media (min-width: 760px) {
  .pg-nav-mobile { display: none !important; }
}

/* ---------- Nav: desktop always-visible glass panel ----------
   Site-wide standard (originated on the homepage, now shared by every
   page): a floating pill-shaped horizontal bar centred over the top of the
   content column, not a top-right box. */
.pg-nav-desktop {
  display: none;
}

@media (min-width: 760px) {
  .pg-nav-desktop {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    position: fixed;
    top: 20px;
    margin-top: 0;
    /* left:50% alone centres against the true viewport width, but on pages
       whose own inner scroll container has a narrower clientWidth than the
       viewport (the homepage's #scroll-root), naive 50% centring sits half
       a scrollbar-width off from the actual content centre. nav.js measures
       that per-page gap and writes it to --sg-nav-shift; this subtracts
       half of it back out. On pages where <body> itself is the scroller,
       the gap is 0 and this is a no-op. */
    left: calc(50% - var(--sg-nav-shift, 0px));
    right: auto;
    transform: translateX(-50%);
    /* 100% of the desktop content column's own width (1200px-capped). */
    width: min(1200px, calc(100vw - 48px));
    max-width: none;
    z-index: 41;
    padding: calc(min(18px, 1.6dvh) - 5px) 40px;
    border-radius: 999px;
    background: rgba(123, 148, 175, 0.37);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    box-shadow: var(--shadow-glass);
    /* See .pg-nav-trigger: forces this fixed blurred panel onto its own
       compositor layer up front so Chrome isn't recomputing the blur
       backdrop from scratch on the first frames of every scroll. */
    will-change: backdrop-filter;
  }

  .pg-nav-desktop a {
    color: var(--colour-ink);
    font-family: var(--font-body);
    font-weight: 300;
    font-size: calc(var(--size-body) - 0.5pt);
    letter-spacing: 0.01em;
    line-height: calc(1.2em + 1pt);
    text-decoration: none;
    transition: color 0.2s ease;
  }

  /* Colour-only hover (no translateX) — consistent across every page. */
  .pg-nav-desktop a:hover { color: var(--colour-accent); }

  /* When the footer (accent-coloured background) is scrolled underneath the
     fixed nav bar, the default accent hover colour would be near-invisible
     against it — swap to the page background colour instead. .is-over-footer
     is toggled on <html> by an IntersectionObserver (nav.js) watching each
     page's own #the-footer. */
  html.is-over-footer .pg-nav-desktop a:hover {
    color: var(--colour-bg);
  }

  /* Self page link — shown instead of omitted, but inert/disabled so it
     reads as "you are here" without being clickable. */
  .pg-nav-desktop a.is-current,
  .pg-nav-mobile__panel a.is-current {
    opacity: 0.45;
    pointer-events: none;
    cursor: default;
  }
  .pg-nav-desktop a.is-current:hover { color: var(--colour-ink); }

  /* "Back to top" button — last item in every page's floating nav bar.
     Always visible but disabled (dim, non-interactive) until nav.js/home.js
     toggles .is-active on shortly after scrolling starts (a small px
     threshold, not a full screen height). Shared across all pages so every
     nav bar has the same set of items — this is what keeps the bar's
     height identical on the homepage and everywhere else. */
  .pg-nav-top-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    flex-shrink: 0;
    border: none;
    border-radius: 50%;
    background: none;
    color: var(--colour-ink);
    cursor: default;
    opacity: 0.35;
    pointer-events: none;
    transition: opacity 0.2s ease, color 0.2s ease;
  }
  .pg-nav-top-btn.is-active {
    opacity: 1;
    pointer-events: auto;
    cursor: pointer;
  }
  .pg-nav-top-btn:hover {
    color: var(--colour-accent);
  }
  html.is-over-footer .pg-nav-top-btn:hover {
    color: var(--colour-bg);
  }
}

/* Pages other than the homepage: shift all in-flow content down 30px
   (the fixed nav bar is unaffected since it's positioned relative to the
   viewport, not body flow). #scroll-root only exists on the homepage, so
   :not(:has(#scroll-root)) is the same "is this the homepage" check nav.js
   already uses in JS. */
body:not(:has(#scroll-root)) {
  padding-top: 30px;
}

.pg-nav-mobile__panel a.is-current {
  opacity: 0.45;
  pointer-events: none;
  cursor: default;
}
.pg-nav-mobile__panel a.is-current:hover { transform: none; }

/* ---------- Footer (two-zone: Navigate + Recent Thinking) ---------- */
/* Extra breathing room above the footer's first content (statement/CTA/
   footer-zones), on top of whatever top padding the page's own footer
   section rule already applies. */
#the-footer .pg-col { padding-top: 15px; }
.footer-statement { margin: min(8px, 1dvh) 0 0 0; font-family: var(--font-ui); font-weight: 400; -webkit-text-stroke: 0.048em currentColor; font-size: calc(min(2.1rem, 8cqw, 3.6dvh) + 4pt); line-height: calc(1.14em + 0.2pt); letter-spacing: calc(0.029em + 0.4pt); text-transform: uppercase; color: var(--colour-bg); }
.footer-zones { display: flex; flex-direction: column; gap: 25px; margin-top: min(24px, 3dvh); width: 100%; }
.footer-zone { display: flex; flex-direction: column; gap: min(10px, 1.2dvh); }
.footer-zone-label { font-family: var(--font-ui); font-weight: 500; font-size: calc(min(0.95rem, 4.2cqw, 2.4dvh) - 1.5pt); letter-spacing: 0.14em; color: rgba(246, 243, 238, 0.6); text-transform: uppercase; }
.footer-zone a { align-self: flex-start; font-family: var(--font-body); font-weight: 300; font-size: min(0.95rem, 4.2cqw, 2.4dvh); color: var(--colour-bg); transition: transform 0.2s ease, color 0.2s ease; }
.footer-zone a:hover { color: var(--colour-ink); transform: translateX(5px); }
.footer-thinking { display: flex; flex-direction: column; gap: min(16px, 1.9dvh); min-width: 0; }
.footer-thinking .footer-zone-label { margin-top: 10px; }
.footer-thinking a { align-self: flex-start; font-family: var(--font-body); font-weight: 300; font-size: calc(min(0.95rem, 4.2cqw, 2.4dvh) - 1pt); line-height: 1.25; color: var(--colour-bg); transition: transform 0.2s ease, color 0.2s ease; }
.footer-thinking a:hover { color: var(--colour-ink); transform: translateX(5px); }
.footer-divider { display: none; }
.footer-bottom { margin-top: 25px; padding-top: min(20px, 2.4dvh); display: flex; flex-direction: column; gap: 25px; border-top: 1px solid rgba(246, 243, 238, 0.25); }
.footer-social { display: flex; flex-wrap: wrap; gap: min(16px, 3.6cqw) min(14px, 3.1cqw); }
/* letter-spacing trimmed from 0.16em to 0.1em — at 0.16em the widest labels
   (DEVIANTART, INSTAGRAM) pushed the 8-link row just ~2px past the mobile
   content column's width, forcing an unwanted 3rd wrapped line instead of
   the intended 4+4 two-line layout. */
.footer-social a { font-family: var(--font-ui); font-weight: 400; font-size: calc(min(0.95rem, 4.2cqw, 2.4dvh) - 2pt); letter-spacing: 0.1em; color: var(--colour-bg); text-transform: uppercase; transition: transform 0.2s ease, color 0.2s ease; }
.footer-social a:hover { color: var(--colour-ink); transform: translateX(5px); }
.footer-copyright { margin: 0; font-family: var(--font-body); font-weight: 300; font-size: calc(min(0.68rem, 2.9cqw, 1.6dvh) + 1.5pt); line-height: 1.35; color: rgba(246, 243, 238, 0.7); }

/* Mobile only: tighten the gap between the footer statement/quote and the
   "Navigate" label by 20px — calc() on top of the existing min() keeps this
   a flat 20px reduction off whichever arm (px or dvh) is currently smaller,
   rather than guessing a fixed replacement value. !important is required
   because the spacer's height is set via an inline style in index.php. */
@media (max-width: 759px) {
  .footer-spacer { min-height: calc(min(100px, 8dvh) - 20px) !important; }
}

/* Mobile only: pull the footer quote (.footer-statement) upward 70px. Uses
   transform (not margin) so it layers on top of any page-specific
   margin-top override (e.g. home.css's +75px push on the homepage) without
   needing to know/replicate each page's own base value. */
@media (max-width: 759px) {
  .footer-statement { transform: translateY(-70px); }
}

/* ---------- Case-page overlay shell (mobile) ---------- */
.case-overlay {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(245, 245, 247, 0.9);
  backdrop-filter: blur(22px);
  -webkit-backdrop-filter: blur(22px);
  padding: 20px;
  box-sizing: border-box;
}

.case-overlay.is-open { display: flex; justify-content: center; }

.case-overlay__close {
  position: fixed;
  top: 20px;
  right: 20px;
  z-index: 61;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.3rem;
}

/* Prev/next/close icon buttons: shared by the case lightbox (mobile + desktop)
   and the testimonial overlay — hover slides the stroke to the dusty-blue accent. */
.case-mobile-actions button svg,
.case-desktop-actions button svg,
.t-card-head-actions button svg,
.acq-actions button svg {
  transition: stroke 0.2s ease;
}

.case-mobile-actions button:hover svg,
.case-desktop-actions button:hover svg,
.t-card-head-actions button:hover svg,
.acq-actions button:hover svg {
  stroke: var(--colour-accent);
}

/* ---------- Case-page desktop stacked-stage card ---------- */
.case-desktop {
  display: none;
}

@media (min-width: 760px) {
  .case-desktop {
    width: min(1160px, 95vw);
    height: auto;
    max-height: 94dvh;
    background: rgba(255, 255, 255, 0.50);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border-radius: 18px;
    box-shadow: 0 20px 50px rgba(58, 63, 67, 0.18);
    padding: 34px 52px;
    box-sizing: border-box;
    flex-direction: column;
    overflow-y: auto;
  }
}

/* ---------- Cookie consent card ----------
   A small, self-contained card floating bottom-centre (not a full-width
   bar) — title, short copy + a "manage" link, then Accept/Reject stacked
   full-width below. Frosted glass-morphism surface (translucent white +
   backdrop blur, same treatment as the case-page overlay) so the single
   shared .pg-btn glass style (calibrated for light backgrounds) still
   reads correctly here — no scoped colour override needed. Centred on
   mobile; parked at the far right of the viewport on wide screens (see
   the min-width:760px block) so it doesn't block centred page content. */
.pg-consent-bar {
  position: fixed;
  left: 50%;
  bottom: 16px;
  transform: translateX(-50%);
  width: calc(100% - 40px);
  max-width: min(360px, var(--mobile-content-width));
  z-index: 70;
  display: none;
  flex-direction: column;
  gap: 14px;
  padding: 24px 22px 22px;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.55);
  backdrop-filter: blur(22px);
  -webkit-backdrop-filter: blur(22px);
  box-shadow: 0 18px 44px rgba(58, 63, 67, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.6);
  text-align: left;
}

.pg-consent-bar.is-visible { display: flex; }

.pg-consent-bar__title {
  margin: 0;
  font-family: var(--font-ui);
  font-weight: 500;
  font-size: 1.05rem;
  letter-spacing: 0.02em;
  color: var(--colour-ink);
}

.pg-consent-bar__text {
  margin: 0;
  font-family: var(--font-body);
  font-weight: 300;
  font-size: 0.8rem;
  line-height: 1.4;
  color: var(--colour-ink);
}

.pg-consent-bar__link {
  color: var(--colour-ink);
  text-decoration: underline;
}

.pg-consent-bar__actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.pg-consent-bar__accept,
.pg-consent-bar__decline {
  width: 100%;
  padding: 13px 12px;
  font-size: 0.8rem;
}

@media (min-width: 760px) {
  .pg-consent-bar {
    left: auto;
    right: 24px;
    bottom: 24px;
    transform: none;
    max-width: 380px;
    padding: 28px 26px 24px;
    gap: 16px;
  }

  .pg-consent-bar__title { font-size: 1.15rem; }
  .pg-consent-bar__text { font-size: 0.85rem; }

  .pg-consent-bar__accept,
  .pg-consent-bar__decline {
    padding: 14px 16px;
    font-size: 0.85rem;
  }
}

/* ---------- Interaction prompt (global, used across all engagement prompts) ---------- */
.pg-prompt {
  font-family: var(--font-ui);
  font-weight: 400;
  font-size: var(--size-prompt);
  letter-spacing: 0.02em;
  color: var(--colour-accent);
  text-transform: none;
}

/* ---------- SVG asset protection (global, all pages) ----------
   Deters casual right-click "Save Image As" / drag-out-to-desktop on the
   real logo/mark SVG files (uploaded marks, testimonial client logos,
   acquire listings, success-story logos, monograms). Scoped to img[src$=".svg"]
   only, so case-study/portrait photography (jpg/png) is untouched.
   Pure CSS, no extra requests — zero load-time cost. Does not touch alt
   text, filenames, or markup crawlers read, so SEO is unaffected. Every
   clickable tile/card that contains one of these images (mk-tile, acq-tile,
   ss-card, pf-card) handles its own click/tap via the parent element, not
   the <img> itself, so removing pointer-events from the <img> does not
   break any existing interaction. */
img[src$=".svg"] {
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-user-drag: none;
  user-drag: none;
}

/* ---------- Mobile portrait lock (global, all pages) ----------
   Every section on this site is designed edge-to-edge for a tall,
   narrow viewport (100dvh scroll-snap sections, dvh-capped type). There
   is no landscape layout, so rather than let a rotated phone render a
   broken/overflowing version of the portrait design, cover the screen
   with a "please rotate back" message instead.

   Pure CSS, no markup or JS needed anywhere — this lives in
   components.css, already loaded on every single page, and the overlay
   itself is generated via body::before rather than a real element.

   Scoped to touch/coarse-pointer devices with a short viewport height
   (landscape phones are short — typically <= 500px tall; landscape
   tablets/laptops are much taller and are deliberately left alone,
   since their landscape use is normal, not a rotated phone). */
@media (orientation: landscape) and (max-height: 500px) and (pointer: coarse) {
  body::before {
    content: "Please rotate your device back to portrait to view this site.";
    position: fixed;
    inset: 0;
    z-index: 99999;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 0 15%;
    background: var(--colour-bg);
    color: var(--colour-ink);
    font-family: var(--font-ui);
    font-weight: 400;
    font-size: 1rem;
    line-height: 1.4;
    letter-spacing: 0.02em;
  }

  body { overflow: hidden; }
}
