/*
Theme Name: AZ Valley Website Designs
Description: Block theme for azvalleywebdesigns.com, carrying all eleven sections of the approved homepage mockup v001 byte for byte. Section wrappers carry id=<sections.yaml id> so `azv qa parity` locates them unchanged. Proven at 1440 and 390 in clients/az-valley-wordpress-lab before being brought here; the production divergences from the approved design are D006 (footer logo aspect ratio) and D008 (no footer social row).
Version: 1.1.2
Requires at least: 6.4
Text Domain: azvalley
*/

/* =========================================================
   Design System v2 — carried over from the approved mockup's
   :root block verbatim (mockup/design-tokens.json is derived
   from the same source). theme.json exposes the same values
   as presets for the editor; these custom properties keep the
   mockup's own CSS usable with minimal rewriting.
   ========================================================= */
:root{
  --night:       #0a0e1a;
  --night-2:     #0f1524;
  --night-3:     #141b2c;
  --night-line:  #232c40;

  --blue:        #4a9eff;
  --blue-dark:   #2f7dd8;
  --blue-text:   #1c56bd;
  --blue-deep:   #123566;
  --blue-mid:    #1a4ea8;

  --gold:        #f2b134;
  --green:       #4f9a56;

  --paper:       #ffffff;
  --ink:         #14181f;
  --ink-soft:    #5a6472;
  --line:        #e3e7ee;

  --on-dark:     #ffffff;
  --on-dark-soft:#aab0bd;

  --font-display: 'Anton', system-ui, sans-serif;
  --font-body:    'Inter', system-ui, sans-serif;

  --fs-xs:   clamp(.78rem, .75rem + .1vw, .85rem);
  --fs-sm:   clamp(.9rem, .87rem + .15vw, .98rem);
  --fs-base: clamp(1rem, .96rem + .2vw, 1.08rem);
  --fs-lg:   clamp(1.15rem, 1.05rem + .5vw, 1.35rem);
  --fs-xl:   clamp(1.6rem, 1.35rem + 1.2vw, 2.1rem);
  --fs-2xl:  clamp(2.1rem, 1.6rem + 2.4vw, 3.1rem);
  --fs-3xl:  clamp(2.6rem, 1.8rem + 3.8vw, 4.4rem);

  --space-1: .4rem; --space-2: .8rem; --space-3: 1.2rem; --space-4: 1.8rem;
  --space-5: 2.6rem; --space-6: 3.6rem; --space-7: 5.2rem; --space-8: 7.2rem;

  --radius-sm: 6px; --radius-md: 12px; --radius-lg: 22px; --radius-pill: 999px;
  --shadow-sm: 0 4px 14px -6px rgba(0,0,0,.45);
  --shadow-md: 0 20px 45px -18px rgba(0,0,0,.6);
  --container: 1180px;
  --dur: .2s; --ease: cubic-bezier(.4,0,.2,1);
}

/* ---- base (mockup lines 86-131, minus what theme.json already sets) ---- */
/* The mockup's own reset (its line 86). WordPress core border-boxes the blocks
   it ships but not arbitrary markup, so without this any element the design
   sizes explicitly *and* gives a border grows by the border: the offer icon's
   56px box came out 58px (session 5). */
*,*::before,*::after{ box-sizing:border-box; }
html{ scroll-behavior:smooth; }
@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{ animation-duration:.001ms !important; animation-iteration-count:1 !important; transition-duration:.001ms !important; scroll-behavior:auto !important; }
}
body{ -webkit-font-smoothing:antialiased; }
img{ max-width:100%; display:block; }
.accent{ color:var(--blue); }

/* `margin-bottom` is the mockup's own, restored (session 6). Sessions 2 and 5
   left it off and simulated it with a `margin-block-start` on the heading that
   follows. That simulation is exact only while the eyebrow's ::before rule is
   present: the eyebrow is `inline-flex`, so its baseline is its first flex
   item's, and with the rule there its own descent dominates the line box. The
   centred head variant hides the rule, the strut's descent takes over, and the
   simulated gap came out 1.14px too tall. The real rule has no such dependency,
   so the compensations on `.hero h1`, offer.php and how-it-works.php went with it. */
.eyebrow{
  display:inline-flex; align-items:center; gap:.5em; font-family:var(--font-body); font-weight:700;
  font-size:var(--fs-xs); letter-spacing:.14em; text-transform:uppercase;
  color:var(--blue); margin-bottom:var(--space-2);
}
.eyebrow::before{ content:""; width:22px; height:2px; background:var(--blue); display:inline-block; }
/* …and the other half of the mockup's rule: `h1,h2,h3,h4{ margin:0 0 …}`, i.e.
   the heading contributes no top margin — the eyebrow above it owns the gap.
   theme.json declares that same zero, but a flow layout's
   `:root :where(.is-layout-flow) > *{ margin-block-start:<blockGap> }` (0,1,0)
   ties with it and wins on order, putting the global 1.2rem back. This is
   (0,1,1), so it does not. */
.eyebrow + :is(h1,h2,h3){ margin-block-start:0; }
.lede{ font-size:var(--fs-lg); color:var(--on-dark-soft); font-family:var(--font-body); }
/* The mockup's section head is a left-aligned 44rem block. Putting that
   max-width on the head *block* does not work: a constrained layout positions
   every child with `margin-left:auto !important; margin-right:auto !important`
   (its own `:not(.alignleft):not(.alignright):not(.alignfull)` escape hatches all
   float or full-bleed instead), so a narrowed head is centred — 209px right of
   the mockup's — and overriding the margins to 0 loses the same auto margins'
   other job, centring the content column itself, dropping the head to the root
   padding edge (session 5, both measured).
   So the head keeps core's `contentSize` width and the 44rem cap moves to its
   children, which sit in a flow layout core does not horizontally align. The
   head's box is invisible — no fill, no border — so the text wraps and starts
   exactly where the mockup's does. */
.section-head > *{ max-width:44rem; }

/* Focus visibility — the mockup's rule, now restored in full. Sessions 2-7 kept
   only the two selectors the page actually had (`a`, `button`) and dropped the
   rest as dead weight. The FAQ made `summary` live, and the omission was not
   cosmetic: a focused summary fell back to Chromium's own ring — `1px auto
   rgb(16,16,16)`, near-black on a --night-2 band — so keyboard focus was
   effectively invisible on the page's first interactive control (session 8,
   caught by the focus-ring probe, not by geometry: every box matched). The
   form-control selectors come back with it rather than waiting to be
   rediscovered by the contact form the same way. */
a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible,
select:focus-visible, summary:focus-visible, [tabindex="0"]:focus-visible{
  outline:3px solid var(--blue); outline-offset:3px; border-radius:4px;
}

/* ---- Buttons — bracket corners (mockup lines 144-171) -------------------
   The Button block puts `className` on its wrapper div and the styled
   element is the inner link, so every mockup `.btn` rule is re-targeted to
   `.wp-block-button.btn > .wp-block-button__link`. The core button reset is
   `:root :where(.wp-block-button__link)` (0,1,0); these are (0,2,0). */
.wp-block-button.btn > .wp-block-button__link{
  position:relative; display:inline-flex; align-items:center; justify-content:center; gap:.6em;
  font-family:var(--font-body); font-weight:700; font-size:var(--fs-sm); letter-spacing:.04em; text-transform:uppercase;
  line-height:1.6;
  padding:1em 1.5em; border-radius:var(--radius-sm); border:1.5px solid transparent;
  cursor:pointer; text-decoration:none; transition:transform var(--dur) var(--ease), background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease);
  white-space:nowrap; margin:6px;
  /* The mockup's .btn is an inline-flex box that shrink-wraps its label. Inside
     the Button block it is the child of `.wp-block-button`, which is itself a
     flex item already sized to the label PLUS this 6px margin — and Chromium
     then lays the link out against that wrapper's border box without taking the
     margin back off, so every button rendered 12px wider than the design and
     its right-hand bracket sat 6px outside where it belongs. `fit-content` is
     the width the mockup's own box resolves to. `.btn-block` below restates
     `width` for the header's full-width CTA and, coming later, still wins. */
  width:fit-content;
}
.wp-block-button.btn > .wp-block-button__link::before,
.wp-block-button.btn > .wp-block-button__link::after{
  content:""; position:absolute; width:13px; height:13px; border-color:var(--on-dark); border-style:solid; opacity:.9;
}
.wp-block-button.btn > .wp-block-button__link::before{ top:-6px; right:-6px; border-width:2px 2px 0 0; }
.wp-block-button.btn > .wp-block-button__link::after{ bottom:-6px; left:-6px; border-width:0 0 2px 2px; }
.wp-block-button.btn > .wp-block-button__link:hover{ transform:translateY(-2px); }
.wp-block-button.btn > .wp-block-button__link:active{ transform:translateY(0); }
.wp-block-button.btn-primary > .wp-block-button__link{ background:var(--blue); color:var(--night); border-color:var(--blue); }
.wp-block-button.btn-primary > .wp-block-button__link:hover{ background:#6cb0ff; border-color:#6cb0ff; color:var(--night); }
.wp-block-button.btn-outline > .wp-block-button__link{ background:transparent; color:var(--on-dark); border-color:var(--night-line); }
.wp-block-button.btn-outline > .wp-block-button__link:hover{ border-color:var(--blue); color:var(--blue); }
.wp-block-button.btn-block{ width:100%; }
.wp-block-button.btn-block > .wp-block-button__link{ width:calc(100% - 12px); }

/* ---- Header (mockup lines 173-215) -------------------------------------
   Group (sticky) › Group.nav-row (flex) › Image.brand + Navigation.primary-nav
   + Buttons.nav-actions. */
.site-header{
  z-index:100; background:rgba(10,14,26,.92);
  border-bottom:1px solid var(--night-line);
}
/* The mockup puts backdrop-filter on the header itself. That property makes
   the header the containing block for fixed descendants, and the Navigation
   block's open overlay is position:fixed — it was trapped inside the 67px
   bar. The blur lives on a pseudo-element instead: same look, free overlay. */
.site-header::before{
  content:""; position:absolute; inset:0; z-index:-1; backdrop-filter:blur(6px); pointer-events:none;
}
.site-header .nav-row{ padding-block:.7rem; gap:var(--space-4); }
.wp-block-image.brand{ margin:0; flex-shrink:0; }
.wp-block-image.brand > a{ display:block; }
.wp-block-image.brand img{ height:42px; width:auto; max-width:none; }

.primary-nav .wp-block-navigation__container{ gap:var(--space-4); }
.primary-nav .wp-block-navigation-item__content{
  text-decoration:none; color:var(--on-dark-soft); font-weight:600; font-size:var(--fs-sm); white-space:nowrap;
  padding:.4rem .1rem; border-bottom:2px solid transparent; transition:color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.primary-nav .wp-block-navigation-item__content:hover{ color:var(--on-dark); }
.primary-nav .current-menu-item > .wp-block-navigation-item__content{ color:var(--blue); border-color:var(--blue); }

/* The Navigation block's hamburger, styled as the mockup's .menu-toggle */
.primary-nav .wp-block-navigation__responsive-container-open{
  display:inline-flex; align-items:center; justify-content:center; width:44px; height:44px;
  background:transparent; border:1px solid var(--night-line); border-radius:var(--radius-sm); color:var(--on-dark);
  cursor:pointer; padding:0;
}
.primary-nav .wp-block-navigation__responsive-container-open svg{ width:22px; height:22px; }
.primary-nav .wp-block-navigation__responsive-container-close{ color:var(--on-dark); }

/* Below 900px: logo left, hamburger right, CTA hidden (mockup hides .nav-cta
   and .primary-nav there). Core switches at 600px; this moves the seam. */
.wp-block-buttons.nav-actions{ display:none; }
@media (max-width:899px){
  .primary-nav .wp-block-navigation__responsive-container-open:not(.always-shown){ display:inline-flex; }
  .primary-nav .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open){ display:none; }
}
@media (min-width:900px){
  .wp-block-buttons.nav-actions{ display:flex; }
  .primary-nav .wp-block-navigation__responsive-container-open:not(.always-shown){ display:none; }
}
/* Open overlay: the mockup's mobile-nav rows (night-3 fill comes from the
   block's overlayBackgroundColor). The mockup's mobile nav also carries the
   primary CTA as a full-width button; the Navigation block cannot hold a
   Buttons block, so it is a navigation-link styled as .btn-primary.btn-block
   that exists only inside the overlay. */
.primary-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content{
  color:var(--on-dark); font-weight:600; padding:.85rem .3rem; border-bottom:1px solid var(--night-line); font-size:var(--fs-base);
}
.primary-nav .wp-block-navigation-item.nav-overlay-cta{ display:none; }
.primary-nav .is-menu-open .wp-block-navigation-item.nav-overlay-cta{ display:block; margin-top:var(--space-3); margin-inline:6px; }
.primary-nav .is-menu-open .nav-overlay-cta > .wp-block-navigation-item__content{
  position:relative; display:flex; align-items:center; justify-content:center; width:100%;
  font-weight:700; font-size:var(--fs-sm); letter-spacing:.04em; text-transform:uppercase;
  padding:1em 1.5em; border-radius:var(--radius-sm); border:1.5px solid var(--blue);
  background:var(--blue); color:var(--night);
}
.primary-nav .is-menu-open .nav-overlay-cta > .wp-block-navigation-item__content::before,
.primary-nav .is-menu-open .nav-overlay-cta > .wp-block-navigation-item__content::after{
  content:""; position:absolute; width:13px; height:13px; border-color:var(--on-dark); border-style:solid; opacity:.9;
}
.primary-nav .is-menu-open .nav-overlay-cta > .wp-block-navigation-item__content::before{ top:-6px; right:-6px; border-width:2px 2px 0 0; }
.primary-nav .is-menu-open .nav-overlay-cta > .wp-block-navigation-item__content::after{ bottom:-6px; left:-6px; border-width:0 0 2px 2px; }

/* ---- Hero (mockup lines 217-240) ----------------------------------------
   Group.hero › Columns.hero-grid (60/40) › eyebrow · H1 · lede · Buttons ·
   badges (HTML block) | hero-art (HTML block, inline SVG). */
.hero{
  position:relative; background:
    radial-gradient(ellipse at 20% -10%, rgba(74,158,255,.14), transparent 55%),
    var(--night);
  color:var(--on-dark); overflow:hidden;
  padding-block: var(--space-8) var(--space-7);
}
.hero .hero-grid{ gap:var(--space-6); margin:0; position:relative; z-index:2; }
.hero h1{ color:var(--on-dark); }
.hero .lede{ max-width:34rem; }
.hero .hero-actions{ margin-block-start:var(--space-5); margin-inline:-6px; gap:var(--space-3); }
.hero-art{ position:relative; }
.hero-scene{ width:100%; height:auto; filter:drop-shadow(0 30px 60px rgba(0,0,0,.5)); }
.hero .hero-badges{ display:flex; flex-wrap:wrap; gap:var(--space-3); margin-block-start:var(--space-5); }
.hero-badge{
  display:flex; align-items:center; gap:.6rem; font-size:var(--fs-xs); color:var(--on-dark-soft);
  border:1px solid var(--night-line); border-radius:var(--radius-pill); padding:.55rem 1rem;
}
.hero-badge svg{ width:16px; height:16px; flex-shrink:0; color:var(--blue); }

/* The mockup stacks the hero below 860px (`@media (min-width:860px)` on
   .hero-grid); core's Columns block stacks at a fixed 782px with !important
   rules. From 782 to 859px re-assert the stacked state with the same weight so
   the WordPress hero follows the design's seam, not the block's. */
@media (max-width:859px){
  .hero .wp-block-columns.hero-grid{ flex-wrap:wrap !important; }
  .hero .wp-block-columns.hero-grid > .wp-block-column{ flex-basis:100% !important; }
}

/* ---- Stat bar (mockup lines 242-260) ------------------------------------
   Group.stat-bar (full width) > Group.stat-bar__grid (core grid layout) >
   three Group.stat-bar__item > ghost (HTML block) - number - label
   (Paragraphs). Colour, font family, size, the three columns and the item
   padding all come from block attributes and theme.json presets; only what a
   block cannot express is here. */
.stat-bar{
  border-top:1px solid var(--night-line); border-bottom:1px solid var(--night-line);
  background:var(--night-2);
}
.stat-bar .stat-bar__item{
  text-align:center; position:relative; overflow:hidden;
  border-bottom:1px solid var(--night-line);
}
/* Core's grid layout holds `columnCount` at every width. The mockup is one
   column below 700px - its own seam, not the header's 900 or the hero's 860. */
@media (max-width:699px){
  .stat-bar .stat-bar__grid{ grid-template-columns:1fr; }
}
@media (min-width:700px){
  .stat-bar .stat-bar__item{ border-bottom:none; border-right:1px solid var(--night-line); }
  .stat-bar .stat-bar__item:last-child{ border-right:none; }
}
.stat-bar__ghost{
  position:absolute; inset:0; margin:0; display:flex; align-items:center; justify-content:center;
  font-family:var(--font-display); font-size:6rem; color:var(--on-dark); opacity:.05; letter-spacing:0;
  pointer-events:none; user-select:none;
}
/* The mockup's paragraph margins (`0 0 var(--space-3)` plus the label's .3rem
   top, which collapses against the number's 1.2rem). WordPress's flow layout
   moves the gap to a top margin and zeroes the last child's bottom margin, so
   both are restated; the layout rules are `:where()`-wrapped and lose. */
.stat-bar .stat-bar__num{ position:relative; margin:0 0 var(--space-3); }
.stat-bar .stat-bar__label{ position:relative; margin:.3rem 0 var(--space-3); }

/* ---- Offer (mockup lines 262-281, 534-564) ------------------------------
   Group (anchor "offer", night background, --space-7 block padding) >
   Group.section-head > eyebrow / H2 / lede, then Group.grid-3 in core's grid
   layout > three Group.feature-card > icon (HTML) / H3 / Paragraph / card link
   (HTML). Background, padding, the three columns, the 2.6rem gap, the card
   padding and all card typography are block attributes reading theme.json
   presets; what is left below is what a block cannot express. The classes are
   the mockup's own, so these rules are its rules, re-scoped only where the
   block wrapper differs. */
.feature-card .icon{
  width:56px; height:56px; border-radius:var(--radius-sm); background:rgba(74,158,255,.08);
  border:1.5px solid var(--blue); display:flex; align-items:center; justify-content:center;
  margin-bottom:var(--space-3); color:var(--blue);
}
.feature-card .icon svg{ width:26px; height:26px; }
.feature-card .card-link{ display:inline-flex; align-items:center; gap:.4em; margin-top:var(--space-3); color:var(--blue); text-decoration:none; font-weight:700; font-size:var(--fs-sm); }
.feature-card .card-link svg{ width:15px; height:15px; transition:transform var(--dur) var(--ease); }
.feature-card .card-link:hover svg{ transform:translateX(3px); }
.feature-card .card-link:hover{ color:#6cb0ff; }
/* Core's grid layout holds `columnCount` at every width (session 4, #16). The
   mockup's services grid is one column below 640px — its own seam, distinct
   from the stat bar's 700, the hero's 860 and the header's 900. */
@media (max-width:639px){
  .wp-block-group.grid-3{ grid-template-columns:1fr; }
}

/* ---- How it works (mockup lines 283-294, 566-593) -----------------------
   Group (anchor "how-it-works", night-2 background) > Group.section-head
   .section-head--center > eyebrow / H2 / lede, then Group.steps in core's grid
   layout > four Group.step > H3 / Paragraph. Surface, padding, the four
   columns, the 1.8rem gap, the step padding and all typography are block
   attributes; only the centred head variant and the counter medallion are
   here, because neither is expressible as a block. */
.section-head--center{ text-align:center; }
.section-head--center > *{ margin-inline:auto; }
.section-head--center .eyebrow::before{ display:none; }

.steps{ counter-reset: step; }
.step::before{
  counter-increment: step; content: counter(step);
  display:flex; align-items:center; justify-content:center; width:40px; height:40px;
  border-radius:50%; border:1.5px solid var(--blue); color:var(--blue); font-family:var(--font-display);
  font-size:1.1rem; margin-bottom:var(--space-3);
}
/* Core's grid layout holds `columnCount` at every width (session 4, #16). This
   section stacks below 760px — its own seam again: not the offer's 640, the
   stat bar's 700, the hero's 860 or the header's 900. */
@media (max-width:759px){
  .wp-block-group.steps{ grid-template-columns:1fr; }
}

/* ---- Recent work (mockup lines 296-315, 595-639) ------------------------
   Group (anchor "work", night background) > Group.section-head, then
   Group.work-grid in core's grid layout > three Group `article`.work-card >
   Image.work-card__media / Group.work-card__body (core's vertical FLEX layout)
   > tag or status pill / H3 / Paragraph / card link (HTML). Surface, radius,
   padding, the crop box, object-fit, every colour and every type step are
   block attributes; what is below is what a block cannot express. */
.work-card{
  overflow:hidden; box-shadow:var(--shadow-md);
  display:flex; flex-direction:column; height:100%;
}
/* The Image block is a <figure>; the mockup's crop box is a plain div. Zero its
   margin and let it fill the card. `object-position` is the one thing the
   block's Aspect-ratio/Scale controls do not cover. */
.work-card__media{ margin:0; background:var(--night-2); }
.work-card__media img{ width:100%; object-position:top; }
/* Core's vertical flex layout aligns children to `flex-start`; the mockup's
   card body is a default `stretch`, and `flex:1` on the body and its paragraph
   is what pins the card link to the bottom of an uneven row. */
.work-card__body{ flex:1; align-items:stretch; }
.work-card__body p{ flex:1; }
/* The mockup's pill is a <span>, so `.work-card__body p` — the rule that gives
   the tag its size, colour and `flex:1` — misses it. Here it is a Paragraph, so
   `flex` is restored to the span's own `0 1 auto`; without it the pill stretches. */
/* Unused in production: the approved mockup's only status pill, on the AZ Free
   Estimates card, became a tag because that is a completed client project
   (D013). Kept so a future status pill needs no new CSS. */
.work-card__body .status-pill{ display:inline-flex; align-items:center; width:fit-content; flex:0 1 auto; }
/* Core's flex layout zeroes its children's margins at the same (0,1,0) weight as
   a plain class, and wins on order — which dropped the link's .4rem, the half of
   its spacing that sits *on top of* the .5rem flex gap. (0,2,0) keeps it. */
.work-card__body .work-card__link{
  font-weight:700; font-size:var(--fs-sm); color:var(--blue-text); text-decoration:none;
  display:inline-flex; align-items:center; gap:.4em; margin-top:.4rem;
}
.work-card__body .work-card__link svg{ width:16px; height:16px; transition:transform var(--dur) var(--ease); }
.work-card__body .work-card__link:hover svg{ transform:translateX(3px); }
/* Core's grid layout holds `columnCount` at every width (session 4, #16). This
   section stacks below 760px — the same seam as the steps above it, and the
   first time two sections have shared one. */
@media (max-width:759px){
  .wp-block-group.work-grid{ grid-template-columns:1fr; }
}

/* ---- Why local businesses work with us (mockup lines 262-281, 641-671) ---
   Group (anchor "why", night-2 background) > Group.section-head > eyebrow / H2
   — no lede — then Group.grid-4 in core's grid layout > four Group.feature-card
   > icon (HTML) / H3 / Paragraph. The card rules are the offer's, unchanged and
   not restated: the mockup gives both grids the same `.feature-card` class, so
   session 5's block already styles this section's cards.

   What is new is the grid. Core's grid layout holds `columnCount` at every
   width (session 4, #16), and `.grid-4` is the first section with TWO seams
   rather than one: one column below 640px, two from 640, four from 960. The
   640 is shared with the offer's `.grid-3`; the 960 is this section's own, and
   is the widest seam on the page — wider than the header's 900. */
@media (max-width:639px){
  .wp-block-group.grid-4{ grid-template-columns:1fr; }
}
@media (min-width:640px) and (max-width:959px){
  .wp-block-group.grid-4{ grid-template-columns:repeat(2,1fr); }
}

/* ---- Pricing (mockup lines 391-397, 673-693) ----------------------------
   Group (anchor "pricing", night background) > Group.split in core's grid
   layout > a flow Group (eyebrow / H2 / lede / Buttons) beside Group.grid in
   core's grid layout > two Group.panel > H3 / Paragraph.

   The panel is entirely block attributes — fill, 1px border, 22px radius and
   --space-4 padding are all things a Group can say — so nothing about it is
   here. What is here is the split, which a block cannot say: core's grid
   layout emits `grid-template-columns` and the gap, and nothing else. */
.split{ align-items:center; }
/* Core's grid layout holds `columnCount` at every width (session 4, #16). The
   split becomes one column below 860px — the hero's seam, the second time two
   sections have shared one (the work grid took the steps' 760). */
@media (max-width:859px){
  .wp-block-group.split{ grid-template-columns:1fr; }
}

/* ---- FAQ accordion (mockup lines 701-716) -------------------------------
   Group (anchor "faq", night-2 background) > Group.section-head > eyebrow / H2,
   then Group.faq (flow, blockGap 0) > four core/details `.faq-item` >
   summary / Paragraph.

   The behaviour is the `<details>` element's own and none of it is here: no
   script, no ARIA, no state class. What is here is the styling the mockup put
   on markup a block cannot carry.

   The mockup's `.faq{ max-width:46rem }` moves to the children for the reason
   `.section-head > *` gives above — a constrained layout centres any block
   narrower than `contentSize` and offers no way to left-align it — and the
   result is identical, because each item's border-bottom is what the 46rem was
   sizing. */
.faq > *{ max-width:46rem; }
.faq-item{ border-bottom:1px solid var(--night-line); }
.faq-item > summary{
  cursor:pointer; list-style:none; display:flex; align-items:center; justify-content:space-between; gap:var(--space-3);
  padding:var(--space-3) 0; font-family:var(--font-body); font-weight:700; font-size:var(--fs-base); color:var(--on-dark);
  position:relative;
}
.faq-item > summary::-webkit-details-marker{ display:none; }

/* The mockup's `<span class="plus" aria-hidden="true">` in three boxes — circle,
   horizontal bar, vertical bar — rebuilt as two pseudo-elements, because the
   Details block parses its summary back out of the `<summary>` element and a
   classed span in there is markup it cannot round-trip (faq.php explains the
   choice). The circle and the horizontal bar are one box: the bar is a
   background gradient, centred, 11x2 like the span's ::before. `flex-shrink:0`
   and the 26px box are the span's own. */
.faq-item > summary::after{
  content:""; flex-shrink:0; width:26px; height:26px; border-radius:50%;
  border:1.5px solid var(--night-line);
  background-image:linear-gradient(currentColor,currentColor);
  background-size:11px 2px; background-position:center; background-repeat:no-repeat;
  color:var(--blue);
}
/* The vertical bar. It is `position:absolute` so it is not a third flex item:
   the summary is `space-between`, so a third item would sit between the text
   and the circle instead of on top of it. Pinned to the circle's centre —
   26px box at the content edge, so 13px in, less half the bar's 2px.
   `calc(50% - 5.5px)` and NOT `top:50%; transform:translateY(-50%)`: both put
   the bar's box in the same place, but a transformed box rasterises on its own
   compositing path and the two end rows of the 11px bar came out with different
   antialiasing coverage than the mockup's flex-centred one — 16 pixels across
   the four items, the only thing separating the closed states (session 8).
   Laying it out arithmetically leaves the closed state transform-free, exactly
   as the mockup's is, and the difference goes to zero. */
.faq-item > summary::before{
  content:""; position:absolute; right:12px; top:calc(50% - 5.5px);
  width:2px; height:11px; background:var(--blue);
  transition:transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
/* The mockup's open state, unchanged: the vertical bar turns into the
   horizontal one and fades, leaving a minus. Motion is emulated away in every
   capture (render.REDUCED_MOTION), so only the end state is ever evidence. */
.faq-item[open] > summary::before{ transform:rotate(90deg); opacity:0; }

/* The answer. The mockup styles it as `.faq-item p` — a descendant rule, no
   class — so it stays a rule rather than becoming Paragraph attributes: a
   fifth question added in the editor then needs nothing said about it. */
.faq-item > p{ padding-bottom:var(--space-3); color:var(--on-dark-soft); margin-block:0; }

/* ---- Final CTA band (mockup lines 718-724) ------------------------------
   Group (anchor "final-cta", night background) > Group.cta-band > H2 /
   Paragraph.lede / Buttons.

   The band's fill, border, radius and padding are all block attributes — the
   gradient via theme.json's `cta-band` preset (final-cta.php explains why it is
   a preset and not a rule here). What is left is the three things a block
   cannot say. */

/* `text-align` has to reach the H2, the lede and the button, and a Group block
   has no attribute that sets alignment for its descendants. */
.cta-band{ text-align:center; }

/* Translucent white — an alpha colour, so not a palette entry and not
   expressible as a `textColor`. The mockup's own value. */
.cta-band .lede{ color:rgba(255,255,255,.92); margin-inline:auto; }

/* The button inverts inside the band: white fill, band-blue label. Re-targeted
   to the inner link for the reason the shared `.btn` rules give — the Button
   block puts `className` on the wrapper and styles the `<a>` inside it. */
.cta-band .wp-block-button.btn-primary > .wp-block-button__link{
  background:#fff; border-color:#fff; color:var(--blue-deep);
}
.cta-band .wp-block-button.btn-primary > .wp-block-button__link:hover{
  background:#e8f1ff; border-color:#e8f1ff;
}

/* ---- Footer (mockup lines 726-760) --------------------------------------
   Group (tagName footer, anchor "footer", night-2, on-dark-soft, 1px top
   border) > Group.footer-grid (core grid layout) > Group.footer-brand +
   three Paragraph.footer-heading / List.footer-list columns, then
   Group.footer-bottom (flex, space-between).

   Fill, text colour, border, padding and the flex row are all block
   attributes. What is here is the three things a block cannot say. */

/* 1. The column ratio. Core's grid layout emits `repeat(4, minmax(0,1fr))` —
      four EQUAL columns — where the design's first column is wider, and it
      holds `columnCount` at every width (session 4, #16), so the single-column
      stack is a query of its own. 760px is the steps/work grid's seam, shared
      for the third time. */
.wp-block-group.footer-grid{ grid-template-columns:1fr; }
@media (min-width:760px){
  .wp-block-group.footer-grid{ grid-template-columns:1.3fr 1fr 1fr 1fr; }
}

/* 2. The list reset — the mockup's global `ul{ margin:0; padding:0;
      list-style:none }`, scoped. Global would also reach the header's
      Navigation block, which styles its own list. */
.footer-list{ margin:0; padding:0; list-style:none; }
.footer-list li{ margin-bottom:.6rem; }

/* 3. Link sizing. `font-size` is on the ANCHOR, exactly as the mockup has it,
      not on the list — which is why "Serving the Phoenix Valley, AZ", the one
      Contact item that is not a link, renders a step larger than the two above
      it. That is the approved design and it is left alone. */
.footer-list a{ text-decoration:none; font-size:var(--fs-sm); color:var(--on-dark-soft); transition:color var(--dur) var(--ease); }
.footer-list a:hover{ color:var(--blue); }

/* No `.footer-brand img` rule: the Image block's own `width:auto; height:40px`
   says it, the way the header's does.

   This is the one place the implementation deliberately does NOT match the
   mockup's pixels. The mockup's header rule is
   `.brand img{ height:42px; width:auto }`; its footer rule is
   `.footer-brand img{ height:40px }` — the same author, the same PNG, and
   `width:auto` simply missing. Without it the `width="150"` attribute survives
   as the used width, so the mockup renders this logo 150x40 against a natural
   773x384: the hexagon becomes an oval and the wordmark stretches to 86% wider
   than its true proportions. The header, three screens up in the same approved
   file, renders the same asset undistorted at 84.55x42.
   A design that contradicts itself is not stating an intent, and stretching a
   brand mark is not one a build guide should carry to client sites, so the
   footer logo keeps its aspect ratio at 80.52x40 and the divergence is
   declared: sections.yaml `footer.locked`, Q004, and
   clients/az-valley-wordpress-lab/docs/discovery.md session 9 (D006). It costs
   ~2440 differing pixels at 1440 and ~2375 at 390, and reverting is one
   `width:150px` if the owner decides otherwise. */
.footer-brand p{ font-size:var(--fs-sm); max-width:26rem; }

/* `margin-bottom` is the mockup's own and has to be stated, not left to the
   root blockGap. The two look interchangeable — both are --space-3 — but the
   list reset three rules up sets `margin:0`, and that also cancels the
   `margin-block-start` core's flow layout would have put on the list. With the
   heading's margin dropped, every footer list sat 19.19px too high while the
   headings above them stayed put (session 9). A gap needs an owner; here the
   mockup already named one. */
.footer-heading{ font-family:var(--font-body); font-weight:700; color:var(--on-dark); font-size:var(--fs-sm); letter-spacing:.04em; text-transform:uppercase; margin-bottom:var(--space-3); }

/* The social row's circles. NOTHING MATCHES THESE THREE RULES IN PRODUCTION:
   D008 removed the `.footer-social` Group and its two anchors from
   patterns/footer.php, because no real AZ Valley account URL exists (Q003).
   They are kept, unused, so that restoring the row when the accounts exist is
   one edit to the pattern and nothing else — the markup is in
   mockup/history/v001/ and in the lab theme.

   For whoever restores it: the two anchors are HTML blocks — an inline SVG in
   a labelled link is not a native block, and core's Social Icons block ships
   different artwork (footer.php says why) — so they are styled here the way
   the offer's and why's icon boxes are. */
.footer-social a{
  width:38px; height:38px; border-radius:50%; border:1px solid var(--night-line);
  display:flex; align-items:center; justify-content:center;
  color:var(--on-dark-soft); transition:border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.footer-social a:hover{ border-color:var(--blue); color:var(--blue); }
.footer-social svg{ width:17px; height:17px; }

.footer-bottom a{ text-decoration:underline; color:var(--on-dark-soft); }

/* =========================================================
   Inner pages — /portfolio/, /pricing/, /about/, /contact/
   (D017). None of these has a mockup; they are composed from
   the homepage's approved system — section heads, eyebrows,
   panels, feature cards, bracket buttons, the CTA band — and
   only what that system did not already say is below.
   ========================================================= */

/* The sticky header would cover every in-page anchor target
   (#michelyns-decorations, #quote, …). It is 67px below 900px and 93-94px from
   900px up, where the nav CTA button makes the row taller — 90px alone left the
   target 3-4px under the header on desktop (pre-launch audit, 2026-09-13). */
[id]{ scroll-margin-top:90px; }
@media (min-width:900px){ [id]{ scroll-margin-top:116px; } }

/* Page hero: the homepage hero's surface and glow, without its art. */
.page-hero{
  background:
    radial-gradient(ellipse at 20% -10%, rgba(74,158,255,.14), transparent 55%),
    var(--night);
  color:var(--on-dark);
}
.page-hero h1{ color:var(--on-dark); font-size:var(--fs-3xl); }
.page-hero .lede{ max-width:40rem; }

/* Long-form text keeps the section head's measure. */
.prose > *{ max-width:44rem; }

/* Check lists (portfolio "What we built", pricing inclusions). The list reset
   is the footer's, scoped the same way. */
.check-list{ margin:0; padding:0; list-style:none; }
.check-list li{ display:flex; gap:.7rem; align-items:flex-start; margin-bottom:.7rem; color:var(--on-dark-soft); }
.check-list li svg{ width:18px; height:18px; flex-shrink:0; margin-top:.25em; color:var(--blue); }
.project__subhead{
  font-family:var(--font-body); font-weight:700; font-size:var(--fs-sm); letter-spacing:.04em;
  text-transform:uppercase; color:var(--on-dark); margin-block:var(--space-4) var(--space-3);
  line-height:1.3;
}

/* ---- Portfolio ----------------------------------------------------------- */
.project{ display:grid; grid-template-columns:1fr; gap:var(--space-5); align-items:start; }
@media (min-width:860px){
  .project{ grid-template-columns:minmax(0,1.15fr) minmax(0,1fr); gap:var(--space-6); }
  .project--compact{ grid-template-columns:minmax(0,.8fr) minmax(0,1fr); align-items:center; }
}
.project__body > .eyebrow + h2{ margin-block-start:0; }
.project-shot{ margin:0; }
.project-shot__frame{
  height:560px; overflow-y:auto; overscroll-behavior:contain;
  border:1px solid var(--night-line); border-radius:var(--radius-lg);
  background:var(--paper); box-shadow:var(--shadow-md);
}
.project-shot__frame img{ width:100%; height:auto; }
.project-shot figcaption{ margin-top:var(--space-2); font-size:var(--fs-xs); color:var(--on-dark-soft); }
@media (max-width:859px){ .project-shot__frame{ height:420px; } }
.project-compact__media{ margin:0; border-radius:var(--radius-lg); overflow:hidden; box-shadow:var(--shadow-md); }
.project-compact__media img{ width:100%; object-position:top; }
.project-list > .project--compact{
  border-top:1px solid var(--night-line); padding-top:var(--space-7);
}

/* ---- Pricing --------------------------------------------------------------- */
.model-grid{ align-items:stretch; }
@media (max-width:859px){ .wp-block-group.model-grid{ grid-template-columns:1fr; } }
.model > .eyebrow + h2{ margin-block-start:0; }
/* Only the inline and bottom margins are reset: the top one is the panel's flow
   gap, and zeroing it put the pills flush under the paragraph above. */
.model-terms{ margin-inline:0; margin-block-end:0; padding:0; list-style:none; display:flex; flex-wrap:wrap; gap:var(--space-2); }
/* 1.25rem rather than the pill radius: identical on one line, and a rounded box
   instead of a lozenge when the long term wraps on a narrow phone. */
.model-terms li{
  border:1px solid var(--night-line); border-radius:1.25rem; padding:.45rem .95rem;
  font-size:var(--fs-sm); color:var(--on-dark-soft);
}
.model-terms strong{ color:var(--on-dark); }

/* ---- About ----------------------------------------------------------------- */
@media (min-width:860px){
  .wp-block-group.about-founder:has(> figure){ grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr); }
}

/* ---- Contact --------------------------------------------------------------- */
@media (max-width:759px){ .wp-block-group.contact-grid{ grid-template-columns:1fr; } }
.contact-card__value{ font-size:var(--fs-xl); font-weight:700; line-height:1.3; overflow-wrap:anywhere; }
/* A phone number never breaks ("(623) 755-" / "0046" at 320px). */
.contact-card__value a[href^="tel:"]{ white-space:nowrap; }
/* An email address is one long word. It is a step smaller, on the paragraph so the
   line box shrinks with it, and the pattern offers a <wbr> before the "@", so
   when it must wrap it breaks there rather than mid-name; `anywhere` above is only
   the last resort. */
.contact-card__value--email{ font-size:var(--fs-lg); }
@media (max-width:379px){
  .contact-card__value{ font-size:var(--fs-lg); }
  .contact-card__value--email{ font-size:var(--fs-base); }
}
.contact-card__value a{ color:var(--on-dark); text-decoration:none; }
.contact-card__value a:hover{ color:var(--blue); }
.contact-card__actions{ margin-inline:-6px; margin-block-start:var(--space-3); gap:var(--space-2); }
.contact-area{ margin-block-start:var(--space-4); }
