/* ============================================================
   SITE.CSS
   UpLoft PLLC — public marketing site (uploft.org rebuild)

   Layout/shell for a scrolling, responsive marketing page.
   Reuses variables.css tokens and library.css's .prose /
   .quick-guide / .qg-* components directly (same visual system
   as the Library packets) rather than template.css's fixed-width
   print .sheet shell, which doesn't fit a page meant to scroll.

   Load order: variables.css → ../library/css/library.css (for
   h1 + .prose/.quick-guide/.qg-*) → THIS FILE.
   ============================================================ */

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

/* Bumps library.css's .prose p / .qg-card p / .qg-step-body p sizes up
   slightly for this scrolling site — they read a little small/dense on a
   page meant to be read at length rather than a fixed 5in print page.
   Scoped to site.css (loaded after library.css, same selector specificity,
   so this wins) rather than touching the shared library.css rules, which
   still need to fit the Library packets' print constraints. Same +1.5px/
   +0.05 line-height bump applied consistently across all three. */
.prose p { font-size: 15px; line-height: 1.5; }
.qg-card p { font-size: 13px; line-height: 1.4; }
.qg-step-body p { font-size: 13.5px; line-height: 1.4; }

body {
  margin              : 0;
  background-color    : var(--paper);
  background-image    : radial-gradient(circle, rgba(20, 17, 15, 0.06) 1px, transparent 1px);
  background-size     : 8px 8px;
  background-position : 0 0;
  color      : var(--ink);
  font-family: var(--font-body);
}

a { color: inherit; }

/* ------------------------------------------------------------
   ACCESSIBILITY — keyboard focus + reduced motion
   Backs specific claims made on /accessibility — keep this in sync
   if either page changes.
   ------------------------------------------------------------ */

/* Visible on every link/button, keyboard-only (not mouse clicks) via
   :focus-visible. --accent reads well against the site's light
   (--paper/--bone) surfaces; the dark-surface override below swaps
   in --brand-sage-lt, since --accent measures ~2.5:1 against --ink
   (fails AA) while sage-lt measures ~15:1 — same reasoning as the
   .charge-word and active-nav-state fixes elsewhere in this project. */
a:focus-visible,
button:focus-visible,
.btn-cta:focus-visible,
.spwidget-button:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
}

.band-dark :focus-visible,
.site-header :focus-visible,
.site-footer :focus-visible {
  outline-color: var(--brand-sage-lt);
}

/* Hover states animate briefly by default (see .btn-cta, .spwidget-button,
   .site-nav-links a) — suppressed entirely for anyone whose OS is set to
   reduce motion, per the /accessibility page's claim. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

.container {
  max-width: 760px;
  margin   : 0 auto;
  padding  : 0 var(--space-xl);
}

/* ------------------------------------------------------------
   NAV
   ------------------------------------------------------------ */

.site-header {
  background-color: var(--ink);
  background-image: radial-gradient(circle, rgba(245, 241, 231, 0.05) 1px, transparent 1px);
  background-size: 8px 8px;
  border-bottom: var(--border-thick);
}

/* Wider than the page's 760px reading column on purpose — the header
   is chrome, not content, and 960px left a visibly boxed-in bar with
   large empty margins on wide/external monitors (1600px+). Capped at
   1400px rather than left unconstrained, so it doesn't stretch logo
   and nav absurdly far apart on ultrawide displays either. */
.site-header .container {
  display        : flex;
  align-items    : center;
  justify-content: space-between;
  flex-wrap      : wrap;
  gap            : var(--space-md);
  padding-top    : var(--space-md);
  padding-bottom : var(--space-md);
  max-width      : 1400px;
}

/* Aligns the logo's left edge with the page content's left edge (the
   760px .container below the header) even though the header itself
   deliberately stays wider (1400px, so nav has breathing room on wide
   monitors — see .site-header .container above). The gap between the
   two containers' left edges isn't constant: it's 0 on narrow viewports
   (neither container is width-capped, both just fill the viewport, and
   below 640px .site-header .container centers everything anyway — see
   that media query) and only converges to a fixed 320px once BOTH
   containers are pinned at their max-width. calc() with nested max()
   replicates each container's own centering formula and takes the
   difference, so this is exact at both ends instead of just the
   wide-desktop case. The two magic numbers (760px, 1400px) must match
   .container's and .site-header .container's max-width values — if
   either changes, update both here.

   Known imprecision: uses 100vw, which includes the scrollbar's width;
   real layout width doesn't, since block-level centering (.container's
   own margin:auto) resolves against the containing block, not the
   viewport. That mismatch leaves a real few-px error in the middle of
   the transition range (measured ~7-8px at 1000px viewport, roughly
   half the scrollbar's width, converging to exactly 0 at both extremes).
   Tried fixing it with a --scrollbar-width custom property
   (calc(100vw - 100%)) — doesn't work: unregistered custom properties
   don't resolve percentages at declaration time, only wherever they're
   finally substituted, so that 100% ended up meaning something
   different than intended. A DOM-based fix (nest a real .container
   inside the header for pixel-perfect alignment via the browser's own
   box model, no vw involved) would need position:absolute layering that
   conflicts with the mobile nav-wrap fix elsewhere in this file — not
   worth that risk for a few px. Left as known, small, bounded
   imprecision rather than chasing it further. */
.brand {
  /* Text styling is a fallback only — nav.js replaces the contents
     with the logo image on load. Kept in case JS is slow/blocked. */
  font-family   : var(--font-display);
  font-size     : 26px;
  letter-spacing: 1px;
  color         : var(--bone);
  text-decoration: none;
  display       : block;
  margin-left   : calc(max(0px, (100vw - 760px) / 2) - max(0px, (100vw - 1400px) / 2));
}

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

/* No margin here on purpose — the brand cluster is left-aligned (no
   centering needed) and .footer-cluster > * + * (site.css, near
   .footer-top) already adds the gap before the next sibling. A margin
   declared here previously silently lost to that reset rule anyway,
   same specificity + later in the file — don't re-add one without
   moving this block after it. */
.footer-logo {
  display: block;
  height : 20px;
  width  : auto;
}

.site-nav-links {
  display    : flex;
  flex-wrap  : wrap;
  align-items: center;
  gap        : var(--space-lg);
  list-style : none;
  margin     : 0;
  padding    : 0;
}

/* white-space: nowrap is load-bearing on mobile — without it, a flex item
   under space pressure shrinks below its content width and the browser
   wraps the label's own text mid-phrase ("Groups & Events" broke into
   three stacked lines) instead of the whole link dropping to the next row,
   which is what flex-wrap above is actually for. Found 2026-08-01 checking
   the deployed site at mobile width — not visible at desktop width at all. */
.site-nav-links a {
  font-family    : var(--font-label);
  font-size      : 12px;
  letter-spacing : 1.5px;
  text-transform : uppercase;
  color          : var(--bone);
  text-decoration: none;
  opacity        : 0.8;
  white-space    : nowrap;
  transition     : opacity 0.15s;
}

.site-nav-links a:hover { opacity: 1; text-decoration: underline; }

/* Color-as-text rule (adopted 2026-08-01, see README/CLAUDE.md):
   --accent/--brand-* are background/border/accent only, never text.
   "You are here" now reads as an accent underline under --bone text,
   not colored text — was --accent-lt before (kept for reference: that
   was itself already a contrast-driven swap off plain --accent, since
   violet-on-ink measures ~2.5:1/fails AA vs. the tint's ~15:1). */
.site-nav-links a.site-nav__active {
  opacity      : 1;
  color        : var(--bone);
  border-bottom: 2px solid var(--accent-lt);
  padding-bottom: 2px;
}

.site-nav-links .btn-cta {
  opacity: 1;
}

/* ------------------------------------------------------------
   BUTTONS
   ------------------------------------------------------------ */

/* Primary CTA — violet, not sage: sage is reserved for section-label
   badges (see .qg-label), violet is the site's "clickable/active" color.
   Text is --bone, not --ink: ink-on-accent measures ~2.5:1 (fails
   AA), bone-on-accent measures ~7:1. */
.btn-cta {
  display        : inline-block;
  font-family    : var(--font-label);
  font-size      : 13px;
  font-weight    : 600;
  letter-spacing : 1.5px;
  text-transform : uppercase;
  text-decoration: none;
  background     : var(--accent);
  color          : var(--bone);
  border         : 2.5px solid var(--panel-black);
  padding        : var(--space-sm) var(--space-lg);
  box-shadow     : 3px 3px 0 var(--panel-black);
  transition     : background-color 0.15s;
}

.btn-cta:hover { background: var(--accent-dk); }

/* Buttons sitting on a dark (--ink) surface — panel-black shadow reads
   as almost no shadow at all against --ink, so those get sage instead,
   which also plays off the violet button + sage "Loft" logo pairing. */
.btn-cta.on-dark { box-shadow: 3px 3px 0 var(--brand-sage); }

/* ------------------------------------------------------------
   HERO + CLOSING CTA — dark bands, bookend the page
   ------------------------------------------------------------ */

.band-dark {
  /* dark-surface halftone — --paper's RGB at low alpha, the dark-mode
     counterpart to body's light-mode formula above */
  background-color: var(--ink);
  background-image: radial-gradient(circle, rgba(245, 241, 231, 0.05) 1px, transparent 1px);
  background-size: 8px 8px;
  color     : var(--bone);
  padding   : 56px 0;
}

/* Headline stays --bone (cream), not an accent color — reserving
   color for interactive elements so it doesn't compete with the CTA
   button below it. .eyebrow (small kicker label) is --bone too now
   (was --brand-sage) — the color-as-text rule means label vs.
   headline distinction has to come from weight/spacing/size, which
   it already did (uppercase + letter-spacing + smaller size). */
.band-dark h1 {
  font-family   : var(--font-display);
  color         : var(--bone);
  font-size     : 44px;
  line-height   : 0.95;
  letter-spacing: 1px;
  margin        : 0 0 var(--space-md);
}

.eyebrow {
  font-family    : var(--font-label);
  font-size      : 12px;
  letter-spacing : 2px;
  text-transform : uppercase;
  color          : var(--bone);
  margin-bottom  : var(--space-sm);
}

.band-dark .lede {
  font-size    : 16px;
  line-height  : 1.5;
  max-width    : 46ch;
  color        : var(--bone);
  margin-bottom: var(--space-xl);
}

.band-dark.closing {
  text-align: center;
  padding: 48px 0;
}

.band-dark.closing h2 {
  font-family: var(--font-display);
  color: var(--bone);
  font-size: 32px;
  letter-spacing: 1px;
  margin-bottom: var(--space-sm);
}

.band-dark.closing p {
  color: var(--bone);
  opacity: 0.85;
  margin-bottom: var(--space-lg);
}

.call-line {
  display    : block;
  margin-top : var(--space-md);
  font-family: var(--font-label);
  font-size  : 12px;
  letter-spacing: 1px;
  color      : var(--bone);
  opacity    : 0.7;
}

/* ------------------------------------------------------------
   SECTIONS
   ------------------------------------------------------------ */

.section {
  padding: 48px 0;
}

.section + .section {
  border-top: 2px dotted var(--steel);
}

/* Big pull quote used for beliefs/blockquote-style lines outside .prose */
blockquote {
  border-left: 5px solid var(--accent);
  background : var(--bone);
  padding    : var(--space-md) var(--space-lg);
  margin     : var(--space-md) 0 0;
  font-style : italic;
  font-size  : 14px;
  line-height: 1.5;
}

/* Stat block for pricing */
.price-stats {
  display  : flex;
  gap      : var(--space-xl);
  flex-wrap: wrap;
  margin-bottom: var(--space-md);
}

.price-stat .amount {
  font-family: var(--font-display);
  font-size  : 34px;
  color      : var(--ink);
  line-height: 1;
}

.price-stat .label {
  font-family    : var(--font-label);
  font-size      : 11px;
  letter-spacing : 1px;
  text-transform : uppercase;
  color          : var(--steel);
}

/* ------------------------------------------------------------
   JOURNEY STEPPER — Approach page, six-phase horizontal timeline
   ------------------------------------------------------------ */

.journey-stepper {
  display       : flex;
  align-items   : flex-start;
  gap           : 0;
  overflow-x    : auto;
  padding       : var(--space-md) 0;
  margin-bottom : var(--space-md);
}

.journey-step {
  display       : flex;
  flex-direction: column;
  align-items   : center;
  text-align    : center;
  flex          : 1;
  min-width     : 110px;
  position      : relative;
}

.journey-step:not(:last-child)::after {
  content   : "";
  position  : absolute;
  top       : 13px;
  left      : calc(50% + 24px);
  right     : calc(-50% + 24px);
  height    : 2px;
  background: var(--steel);
  opacity   : 0.4;
}

.journey-step .node {
  width         : 26px;
  height        : 26px;
  border-radius : 50%;
  background    : var(--accent);
  border        : 2.5px solid var(--ink);
  margin-bottom : var(--space-sm);
  position      : relative;
  z-index       : 1;
}

.journey-step.optional .node { background: var(--paper); }

.journey-step .name {
  font-family    : var(--font-label);
  font-size      : 11.5px;
  letter-spacing : 0.5px;
  text-transform : uppercase;
  color          : var(--ink);
}

.journey-step.optional .name { color: var(--steel); font-style: italic; }

/* ------------------------------------------------------------
   CREDENTIALS LIST — Team page, Lawson's licensure block
   ------------------------------------------------------------ */

.credentials {
  list-style   : none;
  margin       : var(--space-md) 0 0;
  padding      : 0;
  border-left  : 5px solid var(--steel);
  background   : var(--paper);
  padding      : var(--space-sm) var(--space-md);
}

.credentials li {
  font-size    : 13px;
  line-height  : 1.4;
  margin-bottom: var(--space-xs);
}

.credentials li:last-child { margin-bottom: 0; }

/* ------------------------------------------------------------
   ENTRY CARD — Team member / Groups & Events list items
   ------------------------------------------------------------ */

.entry-card {
  border       : var(--border-mid);
  background   : var(--bone);
  box-shadow   : 4px 4px 0 var(--steel);
  padding      : var(--space-lg);
  margin-bottom: var(--space-lg);
}

.entry-card:last-child { margin-bottom: 0; }

.entry-card h3 {
  font-family   : var(--font-label);
  font-size     : 16px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color         : var(--ink);
  margin-bottom : var(--space-xs);
}

.entry-card .meta {
  font-family    : var(--font-label);
  font-size      : 11px;
  letter-spacing : 0.5px;
  text-transform : uppercase;
  color          : var(--steel);
  margin-bottom  : var(--space-sm);
}

.entry-card p { font-size: 13.5px; line-height: 1.45; }

.entry-card a.signup {
  display       : inline-block;
  margin-top    : var(--space-sm);
  font-family   : var(--font-label);
  font-size     : 11px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color         : var(--ink);
  /* No text-decoration override here — the browser default anchor
     underline is the link affordance now that color can't be, per
     the color-as-text rule. */
}

.entry-list-empty {
  font-size : 13.5px;
  color     : var(--steel);
  font-style: italic;
  padding   : var(--space-md) 0;
}

/* ------------------------------------------------------------
   FOOTER
   ------------------------------------------------------------ */

/* border-top reuses the same divider convention as .section + .section
   below — without it, the footer shares its dark background and has zero
   gap with .band-dark.closing right above it, so the two read as one
   continuous ~600px dark mass instead of two distinct zones. The internal
   3-cluster spacing was correct all along; this is what was actually
   making the whole thing still feel like "a full page of footer." */
.site-footer {
  background-color: var(--ink);
  background-image: radial-gradient(circle, rgba(245, 241, 231, 0.05) 1px, transparent 1px);
  background-size: 8px 8px;
  color     : var(--bone);
  padding   : var(--space-xl) var(--space-lg);
  border-top: 2px dotted var(--steel);
}

.site-footer a {
  color: var(--bone);
  text-decoration: none;
  transition: opacity 0.15s;
}

.site-footer a:hover { text-decoration: underline; }

/* Brand (left) and required notices (right) side by side instead of
   fully stacked — a centered single-column footer was burning a lot of
   vertical height on wide viewports for not much content. Constrained to
   the page's own 760px reading column (matching .container) rather than
   the full ~1233px header-width row, which is also most of why the old
   layout read as "a lot of empty space around short lines of text."
   Wraps to stacked (brand, then notices) under ~640px via flex-wrap. */
.footer-top {
  display        : flex;
  flex-wrap      : wrap;
  justify-content: space-between;
  align-items    : flex-start;
  gap            : var(--space-xl);
  max-width      : 760px;
  margin         : 0 auto;
  text-align     : left;
}

.footer-cluster--brand,
.footer-cluster--notices {
  flex: 1 1 260px;
}

/* Utility bar (legal links + copyright) is its own compact, centered
   closing row below footer-top — same convention a lot of footers use
   (content columns on top, one closing bar at the very bottom). */
.footer-cluster--utility {
  max-width : 760px;
  margin    : var(--space-lg) auto 0;
  text-align: center;
}

/* Tight spacing within a cluster (still applies inside each column) —
   this replaces the old model of every block carrying its own
   section-level margin, which is what made the footer read as ~9
   evenly-spaced blocks instead of a few groups. All margins on cluster
   children are reset to 0 here so spacing comes from exactly one place
   (no browser-default <p> margins or per-element margin-bottom to fight
   with). NOTE: this rule's specificity ties with any single-class rule
   on the same element (e.g. .footer-logo's own margin) — whichever is
   declared later in the file wins for the properties both set. Keep
   .footer-logo's margin declared after this block, not before, or its
   centering/spacing silently breaks again (this happened once already).
*/
.footer-cluster > * {
  margin: 0;
}

.footer-cluster > * + * {
  margin-top: var(--space-sm);
}

.footer-address {
  font-size  : 12.5px;
  line-height: 1.5;
  opacity    : 0.85;
}

.footer-contact {
  font-family: var(--font-label);
  font-size  : 12.5px;
  letter-spacing: 0.5px;
}

.footer-notice {
  font-size    : 11.5px;
  line-height  : 1.5;
  opacity      : 0.7;
}

.footer-notice--emergency {
  opacity     : 1;
  font-weight : 700;
  color       : var(--bone);
}

.footer-legal {
  font-family    : var(--font-label);
  font-size      : 10.5px;
  letter-spacing : 1px;
  text-transform : uppercase;
  opacity        : 0.7;
}

.footer-copyright {
  font-family    : var(--font-label);
  font-size      : 10px;
  letter-spacing : 1px;
  text-transform : uppercase;
  opacity        : 0.5;
}

/* ------------------------------------------------------------
   RESPONSIVE — stack the qg-grid on narrow viewports; library.css's
   3/2-col grid assumes print or desktop-width viewing
   ------------------------------------------------------------ */

@media (max-width: 640px) {
  .qg-grid, .qg-grid.cols-2 {
    grid-template-columns: 1fr;
  }

  .band-dark h1 { font-size: 32px; }

  .site-header .container { justify-content: center; text-align: center; }
}
