/* =========================================================
   Postzilla — Components
   Shared UI pieces. Breakpoint-specific overrides live in
   breakpoints.css, not here.
   ========================================================= */

/* ---- Icons ---- */
.pz-icon {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
}
.pz-icon--sm { width: 18px; height: 18px; }

/* Fluid, matching the type scale rather than fighting it. The
   fixed 32px read correctly on an SE and undersized everywhere
   above it, because every other size in this system grows with
   the viewport and this one did not. Floors at the old 32px, so
   the smallest screens are unchanged. */
.pz-icon--lg {
  width: clamp(32px, 2.6vw + 24px, 44px);
  height: clamp(32px, 2.6vw + 24px, 44px);
}

/* ---- Header / nav ---- */
.pz-header {
  position: sticky;
  top: 0;
  z-index: 40;
  /* min-height, not height. A fixed height clipped the mobile
     drawer inside the 72px bar: the toggle worked, the class
     landed, and nothing was visible. */
  min-height: var(--pz-header-h);
  display: flex;
  flex-direction: column;
  justify-content: center;
  background: color-mix(in srgb, var(--pz-bg) 85%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--pz-border);
  transition: box-shadow var(--pz-fast) var(--pz-ease);
}

/* Toggled by scroll position in theme.js. The header already has
   a border at rest; this adds the shadow on top once the page is
   no longer at scrollTop 0, so the bar visibly lifts off the
   content instead of reading identical at every scroll depth. */
.pz-header.is-scrolled {
  box-shadow: var(--pz-shadow);
}

.pz-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--pz-space-4);
  width: 100%;
  min-height: var(--pz-header-h);
}

.pz-brand {
  display: flex;
  align-items: center;
  gap: var(--pz-space-2);
  font-family: var(--pz-font-display);
  font-weight: 700;
  /* Grows with the mark so the wordmark and the Z stay in
     proportion instead of the text drifting ahead of it. */
  font-size: clamp(1.05rem, 0.6vw + 0.95rem, 1.35rem);
  letter-spacing: -0.02em;
  /* Allowed to shrink before the controls do. A flex child will
     not go below its content width without this. */
  min-width: 0;
  overflow: hidden;
}

.pz-brand .pz-icon { color: var(--pz-accent); }

/* The footer brand carries a bare .pz-icon rather than
   .pz-icon--lg, so the fluid sizing on that modifier never
   reached it and the mark sat at 24px while the header's grew.
   Scoping to .pz-brand catches the brand mark wherever it
   appears, header or footer, without touching every other icon.

   The clamp deliberately matches .pz-icon--lg exactly. This
   selector is more specific (0,2,0 against 0,1,0), so it wins
   inside .pz-brand either way: if the values disagreed, adding
   this rule would silently shrink the header logo it was meant
   to leave alone. */
.pz-brand .pz-icon {
  width: clamp(32px, 2.6vw + 24px, 44px);
  height: clamp(32px, 2.6vw + 24px, 44px);
}


.pz-nav {
  display: none;
  align-items: center;
  gap: var(--pz-space-6);
}

.pz-nav a {
  position: relative;
  color: var(--pz-text-muted);
  font-size: var(--pz-text-sm);
  transition: color var(--pz-fast) var(--pz-ease);
}
.pz-nav a:hover { color: var(--pz-text); }

/* Underline grows from the left on hover instead of the link just
   changing color. Sits on ::after so it never affects layout or
   the link's own baseline. No accent token to reach for here, so
   currentColor keeps it tied to whatever the text does. */
.pz-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -4px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--pz-fast) var(--pz-ease);
}
.pz-nav a:hover::after { transform: scaleX(1); }

.pz-header__actions {
  display: flex;
  align-items: center;
  gap: var(--pz-space-2);
  /* Never shrink: whatever else gives way, the theme toggle and
     the menu button must stay reachable. */
  flex: none;
}

/* Call-to-action buttons live in the mobile drawer below the
   breakpoint, where they already appear. Keeping them in the bar
   as well pushed the row past 375px on an iPhone SE, and since
   the page no longer scrolls sideways the overflow had nowhere
   to go: the menu button was simply clipped out of sight. Same
   pattern as .pz-nav, which is hidden here and shown at 744px. */
.pz-header__actions .pz-btn {
  display: none;
}

/* Header CTAs are desktop-only. They carry white-space: nowrap
   and so cannot shrink: on a 375px screen they pushed the menu
   button clean off the edge, which is why the drawer looked
   unopenable. Every one of them is repeated inside the drawer,
   so nothing is lost by hiding them here. Shown again at the
   744px breakpoint, alongside the full nav. */
.pz-header__actions .pz-btn { display: none; }

/* The two controls that must survive at any width. Fixed and
   equal so the row cannot collapse them unevenly. */
.pz-theme-toggle,
.pz-menu-btn {
  flex: none;
  width: 40px;
  height: 40px;
}

/* The wordmark yields before the controls do. On the narrowest
   phones the mark alone still identifies the site, and losing a
   few letters is far better than losing the menu button. */
.pz-brand {
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
}

/* ---- Theme toggle ---- */
.pz-theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--pz-radius-pill);
  border: 1px solid var(--pz-border);
  background: var(--pz-surface);
  transition: background var(--pz-fast) var(--pz-ease), transform var(--pz-fast) var(--pz-ease);
}
.pz-theme-toggle:hover { transform: translateY(-1px); }
.pz-theme-toggle .pz-icon { color: var(--pz-text); }

/* ---- Buttons ---- */
.pz-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--pz-space-2);
  padding: 0.75rem 1.375rem;
  border-radius: var(--pz-radius-pill);
  font-size: var(--pz-text-sm);
  font-weight: 600;
  white-space: nowrap;
  transition: transform var(--pz-fast) var(--pz-ease), box-shadow var(--pz-fast) var(--pz-ease), background var(--pz-fast) var(--pz-ease);
}
.pz-btn:hover { transform: translateY(-1px); }
.pz-btn:active { transform: translateY(0); }

.pz-btn--primary {
  background: var(--pz-accent);
  color: var(--pz-accent-contrast);
  box-shadow: var(--pz-shadow);
}

.pz-btn--ghost {
  background: var(--pz-surface);
  color: var(--pz-text);
  border: 1px solid var(--pz-border);
}

.pz-btn--block { width: 100%; }

/* ---- Hero ---- */
.pz-hero {
  padding-block: var(--pz-space-8) var(--pz-space-7);
  text-align: center;
}

.pz-hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--pz-space-2);
  padding: 0.4rem 0.9rem;
  border-radius: var(--pz-radius-pill);
  background: var(--pz-surface);
  border: 1px solid var(--pz-border);
  color: var(--pz-accent);
  font-size: var(--pz-text-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  margin-bottom: var(--pz-space-5);
}

.pz-hero h1 {
  max-width: 18ch;
  margin-inline: auto;
}

.pz-hero__sub {
  max-width: 52ch;
  margin: var(--pz-space-4) auto var(--pz-space-6);
  font-size: var(--pz-text-lg);
}

.pz-hero__actions {
  display: flex;
  flex-direction: column;
  gap: var(--pz-space-3);
  align-items: center;
  justify-content: center;
}

/* ---- Sections ---- */
.pz-section {
  padding-block: var(--pz-space-8);
  border-top: 1px solid var(--pz-border);
}

.pz-section__head {
  text-align: center;
  max-width: 42ch;
  margin-inline: auto;
  margin-bottom: var(--pz-space-7);
}

.pz-eyebrow {
  color: var(--pz-accent);
  font-size: var(--pz-text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* ---- Cards / grid ---- */
.pz-grid {
  display: grid;
  gap: var(--pz-space-5);
  grid-template-columns: 1fr;
}

.pz-card {
  background: var(--pz-surface);
  border: 1px solid var(--pz-border);
  border-radius: var(--pz-radius-lg);
  padding: var(--pz-space-6);
  box-shadow: var(--pz-shadow);
  transition: transform var(--pz-fast) var(--pz-ease), box-shadow var(--pz-fast) var(--pz-ease);
}
.pz-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--pz-shadow-hover);
}

.pz-card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: var(--pz-radius-md);
  background: color-mix(in srgb, var(--pz-accent) 14%, transparent);
  color: var(--pz-accent);
  margin-bottom: var(--pz-space-4);
}

.pz-card h3 { margin-bottom: var(--pz-space-2); }
.pz-card p { margin-bottom: 0; }

.pz-step-num {
  font-family: var(--pz-font-display);
  font-size: var(--pz-text-xs);
  font-weight: 700;
  color: var(--pz-text-muted);
  margin-bottom: var(--pz-space-2);
}

/* ---- Platform icon row ---- */
.pz-platform-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pz-space-3);
  justify-content: center;
}

.pz-platform-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--pz-space-2);
  padding: 0.6rem 1rem;
  border-radius: var(--pz-radius-pill);
  background: var(--pz-surface);
  border: 1px solid var(--pz-border);
  font-size: var(--pz-text-sm);
  font-weight: 600;
}

.pz-platform-chip--highlight { border-color: var(--pz-accent); color: var(--pz-accent); }
.pz-platform-chip .pz-icon { color: var(--pz-text); }

/* ---- Tier table ---- */
.pz-tiers {
  display: grid;
  gap: var(--pz-space-5);
  grid-template-columns: 1fr;
}

.pz-tier {
  background: var(--pz-surface);
  border: 1px solid var(--pz-border);
  border-radius: var(--pz-radius-lg);
  padding: var(--pz-space-6);
  transition: transform var(--pz-fast) var(--pz-ease), box-shadow var(--pz-fast) var(--pz-ease);
}
.pz-tier:hover {
  transform: translateY(-2px);
  box-shadow: var(--pz-shadow-hover);
}

.pz-tier--pro {
  border-color: var(--pz-accent);
  box-shadow: 0 0 0 1px var(--pz-accent), var(--pz-shadow);
  position: relative;
}
/* Keeps the accent ring intact on hover instead of the plain
   .pz-tier:hover rule replacing it with an unringed shadow. */
.pz-tier--pro:hover {
  box-shadow: 0 0 0 1px var(--pz-accent), var(--pz-shadow-hover);
}

.pz-tier__badge {
  position: absolute;
  top: -12px;
  right: var(--pz-space-5);
  background: var(--pz-accent);
  color: var(--pz-accent-contrast);
  font-size: var(--pz-text-xs);
  font-weight: 700;
  padding: 0.25rem 0.75rem;
  border-radius: var(--pz-radius-pill);
}

.pz-tier__price {
  font-family: var(--pz-font-display);
  font-size: var(--pz-text-2xl);
  font-weight: 700;
  margin: var(--pz-space-2) 0 var(--pz-space-5);
}
.pz-tier__price span {
  font-size: var(--pz-text-sm);
  color: var(--pz-text-muted);
  font-weight: 500;
}

.pz-tier__list {
  display: flex;
  flex-direction: column;
  gap: var(--pz-space-3);
  margin-bottom: var(--pz-space-6);
}

.pz-tier__list li {
  display: flex;
  align-items: flex-start;
  gap: var(--pz-space-2);
  font-size: var(--pz-text-sm);
  color: var(--pz-text-muted);
}

.pz-tier__list .pz-icon { color: var(--pz-accent); margin-top: 2px; }

/* ---- Footer ---- */
.pz-footer {
  border-top: 1px solid var(--pz-border);
  padding-block: var(--pz-space-6);
}

.pz-footer__inner {
  display: flex;
  flex-direction: column;
  gap: var(--pz-space-4);
  align-items: center;
  text-align: center;
}

.pz-footer__links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--pz-space-4);
  font-size: var(--pz-text-sm);
  color: var(--pz-text-muted);
}
.pz-footer__links a:hover { color: var(--pz-text); }

.pz-footer small {
  color: var(--pz-text-muted);
  font-size: var(--pz-text-xs);
}

.pz-footer__social {
  display: flex;
  align-items: center;
  gap: var(--pz-space-4);
}
.pz-footer__social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  color: var(--pz-text-muted);
  transition: color var(--pz-fast) var(--pz-ease), transform var(--pz-fast) var(--pz-ease);
}
.pz-footer__social a:hover {
  color: var(--pz-accent);
  transform: translateY(-1px);
}

/* ---- Team page: member avatar + role ---- */
.pz-team-avatar {
  width: 112px;
  height: 112px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--pz-surface);
  border: 1px solid var(--pz-border);
  margin-bottom: var(--pz-space-4);
}
.pz-team-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.pz-team-social {
  display: flex;
  align-items: center;
  gap: var(--pz-space-3);
  margin-top: var(--pz-space-2);
}
.pz-team-social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--pz-text-muted);
  transition: color var(--pz-fast) var(--pz-ease), transform var(--pz-fast) var(--pz-ease);
}
.pz-team-social a:hover {
  color: var(--pz-accent);
  transform: translateY(-1px);
}

.pz-team-role-row {
  display: flex;
  align-items: center;
  gap: var(--pz-space-3);
  margin-bottom: var(--pz-space-2);
}

.pz-team-role-row .pz-team-role {
  margin-bottom: 0;
}

.pz-team-role-row .pz-team-social {
  margin-top: 0;
}

/* ---- Jobs page: role search ---- */
.pz-role-search {
  display: flex;
  flex-direction: column;
  gap: var(--pz-space-4);
  margin-bottom: var(--pz-space-6);
}

.pz-role-search__input {
  width: 100%;
  padding: 0.85rem 1.1rem;
  border-radius: var(--pz-radius-md);
  border: 1px solid var(--pz-border);
  background: var(--pz-surface);
  color: var(--pz-text);
  font-size: var(--pz-text-base);
  font-family: inherit;
}
.pz-role-search__input::placeholder { color: var(--pz-text-muted); }
.pz-role-search__input:focus {
  outline: none;
  border-color: var(--pz-accent);
}

.pz-role-filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pz-space-2);
}

.pz-role-filter {
  padding: 0.5rem 1rem;
  border-radius: var(--pz-radius-pill);
  border: 1px solid var(--pz-border);
  background: var(--pz-surface);
  color: var(--pz-text-muted);
  font-size: var(--pz-text-sm);
  font-weight: 600;
  transition: background var(--pz-fast) var(--pz-ease), color var(--pz-fast) var(--pz-ease), border-color var(--pz-fast) var(--pz-ease), transform var(--pz-fast) var(--pz-ease);
}
.pz-role-filter:hover { color: var(--pz-text); transform: translateY(-1px); }
.pz-role-filter.is-active {
  background: var(--pz-accent);
  border-color: var(--pz-accent);
  color: var(--pz-accent-contrast);
}

.pz-role-list {
  display: grid;
  gap: var(--pz-space-5);
}

.pz-role-card h3 { margin-bottom: var(--pz-space-2); }
.pz-role-card p { margin-bottom: var(--pz-space-4); }

.pz-role-empty {
  text-align: center;
  color: var(--pz-text-muted);
  padding: var(--pz-space-6) 0;
  grid-column: 1 / -1;
}
.pz-role-empty a { color: var(--pz-text); text-decoration: underline; }

/* ---- Mobile nav drawer ---- */
.pz-menu-btn {
  display: inline-flex;
  width: 40px;
  height: 40px;
  align-items: center;
  justify-content: center;
  border-radius: var(--pz-radius-sm);
  border: 1px solid var(--pz-border);
}

/* Always flex now instead of display:none/flex, so max-height can
   actually transition — display can't be animated, which is why
   the drawer used to snap open/closed with no in-between frame.
   Collapsed to 0 height and clipped, so it takes no space and
   isn't tab-reachable while closed. The breakpoints.css override
   that forces this off entirely above the drawer's breakpoint
   still applies unchanged, display:none there wins regardless. */
.pz-mobile-nav {
  display: flex;
  width: 100%;
  flex-direction: column;
  gap: var(--pz-space-1);
  padding-inline: var(--pz-space-4);
  padding-block: 0;
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  border-top: 0 solid var(--pz-border);
  background: var(--pz-bg);
  transition: max-height var(--pz-slow) var(--pz-ease),
              padding-block var(--pz-slow) var(--pz-ease),
              border-top-width var(--pz-slow) var(--pz-ease),
              opacity var(--pz-fast) var(--pz-ease);
}
.pz-mobile-nav.is-open {
  /* Generous ceiling above the tallest real drawer content (five
     links + the CTA). Only the true content height ever shows,
     since overflow is clipped — this just has to clear it. */
  max-height: 480px;
  padding-block: var(--pz-space-4);
  border-top-width: 1px;
  opacity: 1;
}
.pz-mobile-nav a {
  padding: var(--pz-space-3) var(--pz-space-2);
  border-radius: var(--pz-radius-sm);
  color: var(--pz-text);
  font-size: var(--pz-text-base);
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity var(--pz-fast) var(--pz-ease), transform var(--pz-fast) var(--pz-ease), background var(--pz-fast) var(--pz-ease);
}
.pz-mobile-nav a:hover { background: var(--pz-surface); }

/* Each link fades/slides in a little after the last, instead of
   the whole list appearing at once. Delays only apply while open;
   closing reverts everything on the same fast timing so it never
   feels sluggish to dismiss. */
.pz-mobile-nav.is-open a { opacity: 1; transform: translateY(0); }
.pz-mobile-nav.is-open a:nth-child(1) { transition-delay: 30ms; }
.pz-mobile-nav.is-open a:nth-child(2) { transition-delay: 60ms; }
.pz-mobile-nav.is-open a:nth-child(3) { transition-delay: 90ms; }
.pz-mobile-nav.is-open a:nth-child(4) { transition-delay: 120ms; }
.pz-mobile-nav.is-open a:nth-child(5) { transition-delay: 150ms; }
.pz-mobile-nav.is-open a:nth-child(6) { transition-delay: 180ms; }

/* The primary action inside the drawer. Without this it reads as
   one more link in a list, and the header button it replaced on
   mobile was the most prominent thing in the bar. */
.pz-mobile-nav__cta,
.pz-mobile-nav a[data-nav="product"] {
  margin-top: var(--pz-space-2);
  text-align: center;
  font-weight: 600;
  background: var(--pz-accent);
  color: var(--pz-accent-contrast);
  border-radius: var(--pz-radius-pill);
}

.pz-mobile-nav__cta:hover,
.pz-mobile-nav a[data-nav="product"]:hover {
  background: var(--pz-accent);
  color: var(--pz-accent-contrast);
}


/* ---- Scroll reveal ----
   theme.js adds the .pz-reveal class itself (progressive
   enhancement — nothing in markup depends on it) and observes the
   same elements, adding .is-visible the first time each scrolls
   into view. If JS never runs, elements never get .pz-reveal and
   stay at their normal opacity/position, so there's no no-JS
   fallback to write. prefers-reduced-motion already collapses the
   transition to ~0 globally, see base.css. */
.pz-reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--pz-slow) var(--pz-ease), transform var(--pz-slow) var(--pz-ease);
}
.pz-reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* ---- Horizontal scroll, on purpose ----
   For the cases where content genuinely is wider than the
   viewport and shrinking it would make it useless: a table, a
   row of tabs, a wide chart. The scrolling belongs to this box,
   never to the page.

   Wrap the wide thing:
     <div class="pz-scroll-x"><table>...</table></div>            */

.pz-scroll-x {
  overflow-x: auto;
  overflow-y: hidden;
  /* Momentum on iOS, and a scrollbar that only shows when it is
     actually needed. */
  -webkit-overflow-scrolling: touch;
  /* Stops a horizontal drag inside the box from turning into a
     browser back-navigation gesture halfway through. */
  overscroll-behavior-x: contain;
  /* Reserve the gutter so content does not shift the moment a
     scrollbar appears. */
  scrollbar-width: thin;
}

/* A cue that there is more to see. Without it a scroll box on a
   trackpad looks like a box that simply cuts content off. */
.pz-scroll-x--fade {
  /* An alpha mask, not a colour: only the opacity of each stop
     matters, so this works identically on either theme and needs
     no token. Written as rgb() rather than a hex to make that
     obvious to the next person reading it. */
  mask-image: linear-gradient(to right, rgb(0 0 0 / 1) 0, rgb(0 0 0 / 1) calc(100% - 24px), rgb(0 0 0 / 0) 100%);
  -webkit-mask-image: linear-gradient(to right, rgb(0 0 0 / 1) 0, rgb(0 0 0 / 1) calc(100% - 24px), rgb(0 0 0 / 0) 100%);
}

/* Tabs and chip rows: scroll, but never show a bar for what is
   obviously a swipeable strip. */
.pz-scroll-x--bare {
  scrollbar-width: none;
}

.pz-scroll-x--bare::-webkit-scrollbar {
  display: none;
}

/* A table inside a scroll box must be allowed its natural width,
   or it wraps into an unreadable mess instead of scrolling. */
.pz-scroll-x > table {
  min-width: max-content;
}
