/* ==========================================================================
   CLEAN N CLEAR — design system
   Layer Nine Media · staged comp built from wireframe-04-approved

   TYPE STRATEGY
   -------------
   Three families, each owning one job, chosen to flow rather than clash:

     Hammersmith One  display   The logo font. HERO H1 AND PAGE H1 ONLY.
                                Never a subhead, never body, never a button.
     Archivo          headings  Grotesque. Shares Hammersmith's squarish
                                bowls and low stroke contrast, but has a
                                full weight range Hammersmith lacks (it is
                                single-weight). Subheads, nav, pills, labels.
     Source Sans 3    body      Humanist. Taller x-height and more open
                                apertures than Archivo, which is what keeps
                                body copy legible at 65% opacity.

   OPACITY LADDER  (client rule — hold to it)
     Hero / page H1 ....... 100%
     Subheads (h2/h3) ......  80%
     Body & subtext ........  65%

   COLOUR
     Hero H1 and all pills are GREEN. Page background is the warm off-white.
     Light green tint is 1.53:1 — DECORATIVE ONLY, never put text on it.
   ========================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Hammersmith+One&family=Archivo:wght@400;500;600;700;800&family=Source+Sans+3:ital,wght@0,400;0,600;1,400&display=swap');

/* ---------- tokens ---------- */
:root{
  /* brand */
  --green:      #2E6417;
  --green-deep: #234E11;   /* hover / pressed */
  --green-tint: #EDF1E7;   /* decorative wash only — fails contrast */
  --cream:      #EBDEBC;
  /* Warm-neutral ladder. Kept as three distinct steps on purpose — the page
     has to stay lighter than the placeholder/band cream, or photo slots and
     the cream sections blend into it. Warmed as a set on 23 Jul 2026: the old
     page (#F7F4EC) was so close to white it read as white.
       page  #F4EDDD  L* 93.9   whole page
       soft  #ECE3CB  L* 90.4   photo placeholders, .band-cream
       cream #EBDEBC  L* 88.7   brand cream (locked — do not touch)  */
  --cream-soft: #ECE3CB;

  /* surface */
  --bg-rgb:    244 237 221;              /* page bg channels — hero scrim, header
                                            and nav all derive from this, so the
                                            page warms in ONE place */
  --bg:        rgb(var(--bg-rgb));       /* #F4EDDD — whole page */
  --surface:   #FFFFFF;
  --line:      #E3DCC9;
  --line-soft: #EEE8D9;

  /* ink — one colour, three strengths */
  --ink-rgb: 25 27 20;
  --ink:     rgb(var(--ink-rgb));            /* 100% — H1 only (when not green) */
  --ink-80:  rgb(var(--ink-rgb) / .80);      /* subheads */
  --ink-65:  rgb(var(--ink-rgb) / .65);      /* body, subtext — the floor for real copy */
  --ink-50:  rgb(var(--ink-rgb) / .50);      /* 2.9:1 — NON-CONTENT ONLY (input
                                                placeholders, photo-slot labels).
                                                Never a sentence a visitor must read. */

  /* type */
  --f-display: 'Hammersmith One', 'Trebuchet MS', system-ui, sans-serif;
  --f-head:    'Archivo', 'Segoe UI', -apple-system, sans-serif;
  --f-body:    'Source Sans 3', 'Segoe UI', -apple-system, sans-serif;

  /* rhythm */
  --wrap: 1140px;
  --gut:  clamp(20px, 5vw, 40px);
  --sec:  clamp(56px, 8vw, 104px);
  --r:    14px;   /* card radius */
  --promo-h: 40px;   /* season-pass bar height in the sticky header */
}

/* ---------- reset ---------- */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;scroll-padding-top:88px}
body{
  margin:0;
  background:var(--bg);
  color:var(--ink-65);
  font-family:var(--f-body);
  font-size:17px;
  line-height:1.65;
  /* Inherited everywhere. Only bites when a single token genuinely cannot
     fit — a pasted URL, an email address, a long town name in a narrow cell —
     and stops it setting the page width and scrolling the whole site
     sideways. Normal prose is unaffected. */
  overflow-wrap:break-word;
  -webkit-font-smoothing:antialiased;
}
img,svg{max-width:100%;display:block}
a{color:var(--green);text-decoration:none}
a:hover{text-decoration:underline}
:focus-visible{outline:2.5px solid var(--green);outline-offset:3px;border-radius:4px}

/* ---------- layout ---------- */
.wrap{width:100%;max-width:var(--wrap);margin-inline:auto;padding-inline:var(--gut)}
.wrap--narrow{max-width:760px}
section{padding-block:var(--sec)}
.band{background:var(--surface)}
.band-cream{background:var(--cream-soft)}
.center{text-align:center}
.center .lede{margin-inline:auto}

/* ---------- type ---------- */
h1,h2,h3,h4{margin:0;text-wrap:balance}
p{margin:0}
p + p{margin-top:1em}

/* H1 — Archivo 800, green, full strength. Client's chosen header font (Oct 2026),
   replacing Hammersmith One; Hammersmith now lives only in the logo mark art. */
.h-hero,
.h-page{
  font-family:var(--f-head);
  font-weight:800;
  color:var(--green);
  line-height:1.02;
  letter-spacing:-.012em;
  opacity:1;
}
/* nowrap keeps the hero's two intended lines (break only at the <br>) so Archivo,
   wider than the old logo font, doesn't stack "Window" over "Washing". */
.h-hero{font-size:clamp(2.7rem, 6vw, 4.35rem);white-space:nowrap}
.h-page{font-size:clamp(2.15rem, 4.4vw, 3.2rem);line-height:1.06}

/* H2 / H3 — Archivo at 80% */
.h-sec{
  font-family:var(--f-head);font-weight:600;
  font-size:clamp(1.6rem, 2.9vw, 2.2rem);
  line-height:1.18;letter-spacing:-.011em;
  color:var(--ink-80);
}
.h-sub{
  font-family:var(--f-head);font-weight:600;
  font-size:1.16rem;line-height:1.3;letter-spacing:-.006em;
  color:var(--ink-80);
}
.h-mini{
  font-family:var(--f-head);font-weight:600;
  font-size:.98rem;line-height:1.35;
  color:var(--ink-80);
}

/* eyebrow */
.eyebrow{
  font-family:var(--f-head);font-weight:600;
  font-size:.715rem;letter-spacing:.17em;text-transform:uppercase;
  color:var(--green);
  display:flex;align-items:center;gap:.6rem;
}
.eyebrow::before{content:"";width:22px;height:2px;background:var(--green);border-radius:2px;flex:0 0 auto}
.center .eyebrow{justify-content:center}

/* body copy at 65% */
.lede{font-size:clamp(1.06rem, 1.5vw, 1.2rem);line-height:1.6;color:var(--ink-65);max-width:62ch}
.body{color:var(--ink-65)}
.meta{font-size:.85rem;color:var(--ink-65);font-family:var(--f-head);font-weight:500;letter-spacing:.01em}

.prose{max-width:68ch}
.prose p{color:var(--ink-65)}
.prose h2{margin-top:2.2em}
.prose h3{margin-top:1.8em}
.prose h2 + p,.prose h3 + p{margin-top:.65em}
.prose ul{margin:1.1em 0 0;padding-left:1.15rem;color:var(--ink-65)}
.prose li{margin-bottom:.5em}
.prose li::marker{color:var(--green)}

/* ---------- pills (all buttons are pills, all green) ---------- */
/* Pills never wrap — a button label broken across two lines stops reading as
   a button. So they shrink instead, and only once they need to.

   Padding goes first because it's the cheapest thing to give up, then a little
   type. Both are clamped: padding is at full 1.75rem above ~675px wide and
   type at full size above ~600px, so nothing changes on desktop — this only
   engages on phones and small tablets.

   max-width:100% is the actual guarantee. With nowrap a long label could
   otherwise make the pill wider than its container and set the page width,
   which is how the whole site ends up scrolling sideways. Note the honest
   limit: CSS can't shrink text to fit: if a label is ever long enough to
   still not fit at the floor, it's the label that's wrong, not the button. */
.pill{
  display:inline-flex;align-items:center;justify-content:center;gap:.55rem;
  font-family:var(--f-head);font-weight:600;letter-spacing:.005em;
  font-size:clamp(.86rem, .55rem + 1vw, .925rem);
  padding-block:.92rem;
  padding-inline:clamp(1.05rem, .4rem + 3.2vw, 1.75rem);
  max-width:100%;
  border-radius:999px;
  background:var(--green);color:#fff;border:1.5px solid var(--green);
  text-decoration:none;cursor:pointer;white-space:nowrap;
  transition:background .16s ease, border-color .16s ease, transform .16s ease;
}
.pill:hover{background:var(--green-deep);border-color:var(--green-deep);color:#fff;text-decoration:none;transform:translateY(-1px)}
.pill--ghost{background:transparent;color:var(--green)}
.pill--ghost:hover{background:var(--green);color:#fff}
.pill--onGreen{background:#fff;border-color:#fff;color:var(--green)}
.pill--onGreen:hover{background:var(--cream);border-color:var(--cream);color:var(--green)}
.pill--outlineLight{background:transparent;border-color:rgb(255 255 255 / .70);color:#fff}
.pill--outlineLight:hover{background:#fff;border-color:#fff;color:var(--green)}
/* Longhand, so it overrides the base pill's padding-inline clamp rather than
   half of it — `padding` shorthand here would reset both axes and silently
   undo the responsive inline padding above. */
.pill--sm{padding-block:.62rem;padding-inline:clamp(.85rem,.3rem + 2.4vw,1.25rem);font-size:.85rem}
.pill--full{width:100%}
.pill svg{width:17px;height:17px;fill:currentColor;flex:0 0 auto}

/* text link with arrow */
.tlink{
  font-family:var(--f-head);font-weight:600;font-size:.92rem;
  color:var(--green);display:inline-flex;align-items:center;gap:.4rem;
}
.tlink::after{content:"→";transition:transform .16s ease;display:inline-block}
.tlink:hover{text-decoration:none}
.tlink:hover::after{transform:translateX(4px)}

/* ---------- header / nav ---------- */
.site-head{
  position:sticky;top:0;z-index:60;
  background:rgb(var(--bg-rgb) / .88);
  backdrop-filter:saturate(140%) blur(12px);
  border-bottom:1px solid var(--line);
}
.site-head .wrap{display:flex;align-items:center;gap:2rem;min-height:76px}
.brand{display:flex;align-items:center;flex:0 0 auto}
.brand img{height:42px;width:auto}
.nav{margin-left:auto;display:flex;align-items:center;gap:1.9rem}
/* :not(.pill) throughout — same trap as the footer. `.nav a` is (0,1,1) and
   outranks `.pill` at (0,1,0), so without it the nav's link colour, size and
   weight all win over the button's: the green quote pills rendered near-black
   text on green instead of white. Excluding pills at the source keeps the next
   button dropped into the nav from inheriting the same problem. */
.nav a:not(.pill){
  font-family:var(--f-head);font-weight:500;font-size:.94rem;
  color:var(--ink-80);text-decoration:none;
}
.nav a:not(.pill):hover,.nav a:not(.pill)[aria-current="page"]{color:var(--green);text-decoration:none}
.nav a:not(.pill)[aria-current="page"]{font-weight:600}

/* Season Pass — a solid green pill matching the Free-quote pill so it stands out
   from the plain nav links. Desktop only; in the mobile menu it's a green,
   weighted row. */
.nav a.nav-pass{color:var(--green);font-weight:600}
@media(min-width:1001px){
  .nav a.nav-pass{background:var(--green);color:#fff;border:1.5px solid var(--green);
    padding:.4rem .85rem;border-radius:999px;line-height:1}
  .nav a.nav-pass:hover{background:var(--green-deep);border-color:var(--green-deep);color:#fff;text-decoration:none}
  .nav a.nav-pass[aria-current="page"]{background:var(--green-deep);border-color:var(--green-deep);color:#fff}
}

.menu{position:relative}
.menu > button{
  font-family:var(--f-head);font-weight:500;font-size:.94rem;color:var(--ink-80);
  background:none;border:0;padding:0;cursor:pointer;display:flex;align-items:center;gap:.32rem;
}
.menu > button::after{content:"";width:5px;height:5px;border-right:1.6px solid currentColor;border-bottom:1.6px solid currentColor;transform:rotate(45deg) translate(-1px,-1px)}
.menu:hover > button,.menu > button:focus-visible{color:var(--green)}
.menu-pop{
  position:absolute;top:calc(100% + 14px);left:50%;translate:-50% 0;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:0 18px 44px -18px rgb(25 27 20 / .22);
  padding:.55rem;min-width:264px;
  display:none;
}
/* Invisible bridge across the 14px gap between the button and the popup. Without
   it the pointer crosses a dead zone that belongs to neither, .menu:hover drops,
   and the popup closes before you reach the links — the "hover won't hold" loop.
   The bridge is part of .menu-pop, so hovering it keeps .menu:hover alive. */
.menu-pop::before{content:"";position:absolute;left:0;right:0;top:-16px;height:16px}
.menu:hover .menu-pop,.menu:focus-within .menu-pop{display:block}
.menu-pop a{display:block;padding:.62rem .8rem;border-radius:9px;font-size:.9rem;font-weight:500}
.menu-pop a:hover{background:var(--green-tint);color:var(--green)}
.menu-pop hr{border:0;border-top:1px solid var(--line-soft);margin:.4rem .8rem}

/* 44x44 — it was 39x42, under the minimum comfortable touch target, and it's
   the only control in the header on a phone. The bars stay 23px; the button
   grew around them, so nothing looks heavier. */
.navbtn{
  display:none;background:none;border:0;padding:0;cursor:pointer;
  width:44px;height:44px;border-radius:11px;
  flex-direction:column;align-items:center;justify-content:center;gap:5px;
}
.navbtn span{
  display:block;width:23px;height:2px;background:var(--ink-80);border-radius:2px;
  transition:transform .22s ease, opacity .14s ease;
}
/* Bars fold into an X while open. Without this the button looks identical in
   both states, so the only "menu is open" signal is the panel itself.
   Bar height 2 + gap 5 = 7px between centres, which is the travel each outer
   bar needs to meet in the middle. */
.navbtn[aria-expanded="true"] span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.navbtn[aria-expanded="true"] span:nth-child(2){opacity:0}
.navbtn[aria-expanded="true"] span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}
@media(prefers-reduced-motion:reduce){.navbtn span{transition:none}}


/* ---------- mobile menu ----------
   Built as a menu, not the desktop nav folded into a drawer. What changed and
   why, since it all reads as "styling" otherwise:

   * Full height, not a panel that stops mid-screen on a hairline. A drawer
     that ends halfway down looks like it failed to load.
   * Rows sized for a thumb — 1.14rem type on ~56px rows, against the .94rem
     desktop nav text that was being reused at 42px.
   * Services is a labelled group, not an always-open dropdown wearing its
     desktop border-left. Its button is inert here (see NAV_JS) so it's styled
     as the section label it actually is.
   * Ends on the two things a window-cleaning customer opens a menu to do:
     get a quote, or call. Those were absent — the quote pill was just another
     row in the list, and the phone number appeared nowhere in the menu at all.
*/
@media(max-width:1000px){
  /* height, not `bottom:0`. .site-head sets backdrop-filter, which makes it
     the containing block for its fixed-position descendants — so `bottom:0`
     resolves against the 76px header, not the viewport, and collapses the
     panel to ~40px. Viewport units sidestep the containing block entirely.
     (`top:76px` is measured from the header too, but the header is sticky at
     the top, so 76px below its top edge is where we want it either way.) */
  /* The panel opens by growing its height, and clips what hasn't arrived yet,
     so the menu is drawn down from under the header.

     It is NOT a translate. .site-head sets backdrop-filter and so is the
     containing block and stacking context for this fixed panel — a panel
     slid up out of view would still paint over the header on its way down,
     and it can't be clipped from inside that context. Growing the height
     clips against the panel's own box, which is exactly the drawer effect.

     Transition, not animation, and that matters: a transition that can't run
     lands on the final computed value, so the menu is simply open. A stalled
     animation holds a keyframe, which is how a fade-in can leave a menu
     invisible and unopenable. */
  .nav{
    position:fixed;inset:calc(76px + var(--promo-h)) 0 auto;background:var(--bg);
    display:flex;flex-direction:column;align-items:stretch;gap:0;
    padding-inline:var(--gut);
    overflow-y:auto;overscroll-behavior:contain;
    border-bottom:0;

    /* Vertical padding collapses with the height. box-sizing is border-box,
       and a border-box height can't go below its own padding — leaving it on
       floored the closed panel at 40px, so the drawer jumped that far the
       instant it opened. Padding is inside the 736px when open, so animating
       it costs nothing at the other end. */
    height:0;padding-block:0;
    opacity:0;visibility:hidden;box-shadow:none;
    transition:
      height .32s cubic-bezier(.4,0,.2,1),
      padding-top .32s cubic-bezier(.4,0,.2,1),
      padding-bottom .32s cubic-bezier(.4,0,.2,1),
      opacity .2s ease,
      visibility 0s linear .32s;      /* held visible until the close finishes */
  }
  .nav.is-open{
    height:calc(100dvh - 76px - var(--promo-h));
    padding-top:.75rem;
    padding-bottom:calc(1.75rem + env(safe-area-inset-bottom));
    opacity:1;visibility:visible;
    box-shadow:0 26px 50px -26px rgb(25 27 20 / .30);
    transition:
      height .32s cubic-bezier(.4,0,.2,1),
      padding-top .32s cubic-bezier(.4,0,.2,1),
      padding-bottom .32s cubic-bezier(.4,0,.2,1),
      opacity .16s ease,
      visibility 0s;
  }
  @media(prefers-reduced-motion:reduce){
    .nav,.nav.is-open{transition:none}
  }

  .nav > a:not(.pill){
    padding-block:1.05rem;
    font-size:1.14rem;font-weight:600;
    border-bottom:1px solid var(--line-soft);
  }

  /* Services group */
  .menu{padding-block:1.05rem;border-bottom:1px solid var(--line-soft)}
  .menu > button{
    width:100%;justify-content:flex-start;cursor:default;
    font-size:.72rem;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
    color:var(--green);
  }
  .menu > button::after{display:none}          /* no chevron — it doesn't open */
  .menu:hover > button{color:var(--green)}
  .menu-pop{
    position:static;translate:none;display:block;
    border:0;box-shadow:none;background:none;
    padding:.35rem 0 0;min-width:0;
  }
  .menu-pop hr{display:none}
  .menu-pop a{padding:.6rem 0;border-left:0;border-radius:0;font-size:1.05rem;font-weight:500}
  .menu-pop a:hover{background:none;color:var(--green)}

  /* No CTA in the drawer — the sticky mobile footer carries Call + Free quote. */
  .nav > .pill--sm{display:none}

  .navbtn{display:flex;margin-left:auto}
  /* The panel is fixed and scrolls itself; without this the page underneath
     scrolls too, which reads as the menu sliding away under your thumb. */
  body.nav-open{overflow:hidden}
}


/* ---------- hero ---------- */
.hero{padding-block:clamp(48px,7vw,86px) clamp(52px,7vw,92px)}
.hero-grid{display:grid;grid-template-columns:1.06fr .94fr;gap:clamp(32px,5vw,64px);align-items:center}
@media(max-width:900px){.hero-grid{grid-template-columns:1fr;gap:34px}}
/* About: on mobile the photo + detail card move up under the intro paragraph,
   above the prose (on desktop they sit in the right-hand column as normal). */
@media(max-width:900px){.about-grid .about-side{order:-1}}
.hero .h-hero{margin-top:1rem}
.hero .lede{margin-top:1.15rem}

/* Hero tagline. Archivo at 80%, per the type ladder — Hammersmith is the H1's
   alone, and the tagline sitting directly under it is exactly where that rule
   is easiest to break by accident. */
.hero-tag{
  font-family:var(--f-head);font-weight:600;
  font-size:clamp(1.25rem,2.1vw,1.6rem);
  line-height:1.3;letter-spacing:-.004em;
  color:var(--ink-80);
  margin-top:.85rem;
}

/* Full-bleed hero (home page).
   The photograph fills the section and sits behind all of the hero type. The
   frame is chosen with its subject on the RIGHT; the left is bleed — sky,
   siding, glass — and is only ever seen through the wash below.

   That wash is what makes this safe. It is the page's own off-white, near
   opaque over the type column and gone by the time it reaches the subject, so
   the locked palette holds: green H1, 80% subheads, 65% body, all sitting on
   effectively the same background they were contrast-checked against. Type is
   never laid straight onto photography — no photo can be trusted to hold a
   ratio, and this one has not been shot yet. */
/* Height: the hero is deliberately tall so more of the photo shows (client
   direction, 6 Sep 2026). Taller than the old fold-budgeted 660px ceiling, so on
   shorter screens the differentiator band below now sits a bit lower — an
   accepted trade for a bigger hero image. svh, not vh, so mobile browser chrome
   doesn't shove it off-screen. */
.hero--full{
  position:relative;isolation:isolate;overflow:hidden;
  display:flex;align-items:center;
  min-height:clamp(480px, calc(100svh - 180px), 720px);
  padding-block:clamp(40px,5vw,60px);
}
.hero-bg{position:absolute;inset:0;z-index:-2;background:var(--bg)}
/* Photo-right / text-left hero (client direction, 6 Sep 2026): `cover` fills the
   hero with no letterbox edge, so the left scrim in ::after can feather the image
   smoothly into the page-colour text ground with no hard seam mid-hero. The photo
   is a subject-right window-cleaning shot, so the face stays clear on the right
   while the headline sits on the faded left. `center 30%` keeps faces and action
   high as the wide hero crops top and bottom. */
.hero-bg img{width:100%;height:100%;object-fit:cover;object-position:center 62%}
/* The hero background layer is itself a .photopick. Without this, the picker's
   `position:relative` beats `.hero-bg`'s absolute (equal specificity, defined
   later) — the layer stops filling the hero, collapses to zero height, and the
   photo loads but never paints. Two classes = higher specificity, absolute
   wins back. background:none so no cream flash before the image loads. */
.hero-bg.photopick{position:absolute;background:var(--bg)}
/* Two layers, and the order matters — first listed paints on top.

   1. The bottom fade. Without it the photo is cut off with a hard horizontal
      edge, and because the horizontal scrim below is near-opaque on the left
      and gone on the right, that edge is a different colour at each end. The
      differentiator band underneath then reads far stronger on the right than
      the left — the band is uniform, what sits above it was not. Landing at
      full page colour by 100% means the hero hands off to exactly --bg across
      its whole width, so the band meets one colour.
   2. The horizontal scrim that keeps the type legible. */
.hero--full::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  /* Two scrims, stacked:
     1. Left-to-right fade — page colour on the left, gone by ~62%. This is the
        text's ground: the image is pinned right, so the left half is page colour
        already; this feathers the image's left edge into it so the headline
        reads cleanly with no visible box, at any width.
     2. Bottom fade — hands the photo off to the page colour so the
        differentiator band below meets one clean edge across its width. */
  background:
    linear-gradient(90deg,
      rgb(var(--bg-rgb) / 1)   0%,
      rgb(var(--bg-rgb) / .99) 18%,
      rgb(var(--bg-rgb) / .90) 30%,
      rgb(var(--bg-rgb) / .60) 44%,
      rgb(var(--bg-rgb) / .22) 56%,
      rgb(var(--bg-rgb) / 0)   70%),
    linear-gradient(180deg,
      rgb(var(--bg-rgb) / 0)   55%,
      rgb(var(--bg-rgb) / .08) 74%,
      rgb(var(--bg-rgb) / .35) 88%,
      rgb(var(--bg-rgb) / .75) 96%,
      rgb(var(--bg-rgb) / 1)   100%);
}

/* The text's own ground. A soft feathered wash anchored to the copy column, so
   wherever the column sits — narrow or ultrawide — the headline, tagline, CTAs
   and trust strip always have a readable surface under them while the rest of
   the photo stays fully visible. Feathered (fades to 0), not a hard card, so
   the full-bleed feel is kept. isolation:isolate puts it behind the text but
   above the photo. */
/* NO background patch behind the hero text — every attempt at one read as a
   visible shape (square/cloud) against the full-bleed photo. Readability is
   carried by a shadow on the text itself, so there is no box to see. Crisp, not
   a glow (client call, 6 Sep 2026): a 1px dark drop for definition plus a tight
   2px light edge that keeps the type legible where the photo runs light — the
   wide multi-ring bloom is gone. */
.hero-copy{position:relative}
.hero-copy .h-hero{
  text-shadow:0 1px 2px rgb(25 27 20 / .38), 0 0 2px rgb(var(--bg-rgb) / 1);
}
.hero-copy .hero-tag{
  text-shadow:0 1px 2px rgb(25 27 20 / .34), 0 0 2px rgb(var(--bg-rgb) / .95);
}
.hero-copy{max-width:min(52%,600px);margin-left:-40px}
/* Hero masthead left-aligned (client direction, 6 Sep 2026): the image is pinned
   right and the left is a page-colour ground, so the headline, tagline and CTAs
   all sit left on that ground. */
.hero-copy .h-hero,
.hero-copy .hero-tag{text-align:left}
.hero-copy .cta-row{justify-content:flex-start}

/* Phone: no left/right split to work with, so the wash goes flat and the crop
   pulls toward the subject. Roughly two thirds of visitors land here. */
@media(max-width:900px){
  .hero--full{min-height:0;padding-block:clamp(44px,9vw,72px)}
  .hero-copy{max-width:none;margin-left:0}
  .hero-bg img{object-position:66% 32%}
  /* One layer here, and it still lands on full page colour at the bottom for
     the same reason as desktop — the band below has to meet a single colour. */
  /* Mobile: no left/right split — the photo is full-width behind the stacked
     copy — so the veil is vertical. Light at the top to reveal the subject,
     moderate through the copy, stronger only at the very bottom to meet the
     band. Was a near-opaque .93–.96 flat wash that hid the photo entirely. */
  .hero--full::after{
    background:linear-gradient(180deg,
      rgb(var(--bg-rgb) / .34) 0%,
      rgb(var(--bg-rgb) / .48) 44%,
      rgb(var(--bg-rgb) / .58) 82%,
      rgb(var(--bg-rgb) / .82) 100%);
  }
}
.cta-row{display:flex;flex-wrap:wrap;gap:.75rem;margin-top:1.55rem}
/* Tight on purpose: this strip is the last thing in the hero, and every pixel
   it spends pushes the differentiator band below a 1080p fold. */
/* Secondary hero CTA sits on the photo, so the transparent ghost style was
   hard to read. Give it a solid light fill with green text — pairs with the
   solid green primary and stays legible over any frame. */
.pill--onphoto{background:#fff;border-color:#fff;color:var(--green)}
.pill--onphoto:hover{background:var(--cream);border-color:var(--cream);color:var(--green)}
.stars{color:#C9922B;letter-spacing:.08em;font-size:.95rem}

/* ---------- photo placeholder ---------- */
.ph{
  position:relative;border-radius:var(--r);overflow:hidden;
  background:var(--cream-soft);
  border:1px dashed #D6CBAC;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.55rem;
  text-align:center;padding:1.5rem;
  min-height:200px;
}
.ph::before{
  content:"";position:absolute;inset:0;
  background:url('../brand/mark-green.svg') center/38% no-repeat;
  opacity:.09;
}
.ph span{
  position:relative;
  font-family:var(--f-head);font-weight:600;font-size:.71rem;
  letter-spacing:.15em;text-transform:uppercase;color:#857544;
  max-width:24ch;line-height:1.6;
}
.ph--hero{min-height:clamp(300px,38vw,420px)}
.ph--tall{min-height:300px}
.ph--thumb{min-height:170px}

/* Full-bleed stand-in for the hero photograph. No border or radius — it is
   the section, not a slot inside it. The watermark sits at 74% across to mark
   where the subject goes, matching the object-position the real photo gets. */
.ph--bleed{
  height:100%;min-height:0;padding:0;border:0;border-radius:0;
  align-items:stretch;justify-content:stretch;
}
.ph--bleed::before{background-position:74% 50%;background-size:24%;opacity:.14}
@media(max-width:900px){
  .ph--bleed::before{background-position:70% 35%;background-size:38%}
}

/* ---------- photo picker (staging review aid) ----------
   Overlays a real <img> on the placeholder box and, in review, arrow controls
   to cycle options. .photopick keeps the "ph" class for sizing/crop hooks but
   resets the placeholder's dashed border and cream fill. At launch only the
   image and .photopick--static remain (the JS and controls aren't emitted). */
.photopick{position:relative;border:0;padding:0;overflow:hidden;background:var(--cream-soft)}
.photopick .photopick-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.photopick::before{display:none}          /* hide the watermark mark under a real photo */

.photopick-ctrl{
  position:absolute;left:50%;bottom:12px;translate:-50% 0;z-index:5;
  display:flex;align-items:center;gap:.1rem;
  background:rgb(25 27 20 / .55);backdrop-filter:blur(6px);
  border-radius:999px;padding:.18rem .28rem;
  opacity:.9;transition:opacity .15s ease;
}
.photopick:hover .photopick-ctrl,.hero-ctrl{opacity:1}
.pp-prev,.pp-next{
  width:32px;height:32px;flex:0 0 auto;border:0;border-radius:50%;
  background:transparent;color:#fff;font-size:1.15rem;line-height:1;cursor:pointer;
  display:flex;align-items:center;justify-content:center;
}
.pp-prev:hover,.pp-next:hover{background:rgb(255 255 255 / .22)}
.pp-count{
  color:#fff;font-family:var(--f-head);font-weight:600;font-size:.76rem;
  min-width:2.7em;text-align:center;letter-spacing:.02em;
}
/* Hero controls sit in the hero FOREGROUND (the bg layer is below the scrim). */
.hero-ctrl{position:absolute;left:50%;bottom:22px;translate:-50% 0;z-index:6}

.photopick-flag{
  position:absolute;top:10px;left:10px;z-index:5;max-width:80%;
  background:#FFF2CC;color:#7A5C00;box-shadow:inset 0 0 0 1px #F0DEA4;
  font-family:var(--f-head);font-weight:600;font-size:.68rem;line-height:1.3;
  padding:.28em .6em;border-radius:6px;
}

/* ---------- copy editor (staging, "copy" tool) ----------
   Any visitor text block becomes click-to-rewrite. Subtle until touched: a
   dashed hint on hover, a solid ring on focus, an amber tab once changed. */
.cc-edit{
  cursor:text;border-radius:5px;outline:none;
  transition:box-shadow .12s ease, background .12s ease;
}
.cc-edit:hover{box-shadow:0 0 0 2px rgb(46 100 23 / .28)}
.cc-edit:focus{box-shadow:0 0 0 2px var(--green);background:rgb(255 255 255 / .7)}
.cc-changed{box-shadow:0 0 0 2px rgb(224 185 58 / .75)}
.cc-changed:hover,.cc-changed:focus{box-shadow:0 0 0 2px var(--green)}

/* ---------- shared "Save my changes" bar + panel (photos + copy) ---------- */
.cc-savebar{position:fixed;left:16px;bottom:16px;z-index:80}
.cc-save{
  font-family:var(--f-head);font-weight:600;font-size:.85rem;
  background:var(--green);color:#fff;border:0;border-radius:999px;
  padding:.7rem 1.15rem;cursor:pointer;box-shadow:0 12px 28px -10px rgb(25 27 20 / .5);
}
.cc-save:hover{background:var(--green-deep)}
.cc-savebar.cc-has .cc-save{box-shadow:0 0 0 3px rgb(224 185 58 / .6), 0 12px 28px -10px rgb(25 27 20 / .5)}
@media(max-width:720px){.cc-savebar{left:12px;bottom:calc(12px + 74px)}}  /* clear the mobile call bar */
.cc-panel{position:fixed;inset:0;z-index:90;display:flex;align-items:center;justify-content:center;
  background:rgb(25 27 20 / .5);padding:20px}
.cc-panel[hidden]{display:none}
.cc-card{background:var(--surface);border-radius:16px;max-width:460px;width:100%;
  padding:22px;position:relative;box-shadow:0 30px 60px -20px rgb(25 27 20 / .5)}
.cc-card h3{font-family:var(--f-head);font-weight:700;color:var(--ink-80);margin:0 0 .3rem;font-size:1.2rem}
.cc-sub{font-size:.85rem;color:var(--ink-65);margin:0 0 .8rem;line-height:1.5}
.cc-list{background:var(--bg);border:1px solid var(--line);border-radius:10px;
  padding:.7rem .8rem;font-size:.8rem;white-space:pre-wrap;color:var(--ink-80);
  max-height:44vh;overflow:auto;font-family:var(--f-head);margin:0;line-height:1.5}
.cc-actions{display:flex;gap:.5rem;margin-top:.9rem;flex-wrap:wrap}
.cc-copy,.cc-link{font-family:var(--f-head);font-weight:600;font-size:.82rem;
  border-radius:999px;padding:.55rem 1rem;cursor:pointer;border:1.5px solid var(--green)}
.cc-copy{background:var(--green);color:#fff}
.cc-link{background:transparent;color:var(--green)}
.cc-close{position:absolute;top:8px;right:12px;background:none;border:0;
  font-size:1.6rem;line-height:1;color:var(--ink-65);cursor:pointer}

/* ---------- staging markers (stripped before launch) ---------- */
/* No white-space:nowrap. It was here to stop a short chip like "[4.9]" being
   split, but the reviews wrap whole sentences in .tbd — and an unbreakable
   407px sentence set the document width on a 375px phone, which is what was
   causing the whole page to scroll sideways. Chips wrap now; box-decoration-
   break keeps the amber background and its inset border drawn correctly on
   every line rather than only the first. */
.tbd{
  background:#FFF2CC;color:#7A5C00;
  font-family:var(--f-head);font-weight:600;font-size:.85em;
  padding:.05em .45em;border-radius:5px;
  box-shadow:inset 0 0 0 1px #F0DEA4;
  -webkit-box-decoration-break:clone;
  box-decoration-break:clone;
}
.stage-note{
  border-left:3px solid #E0B93A;background:#FFFAEC;
  border-radius:0 10px 10px 0;
  padding:.85rem 1.1rem;margin-top:1.4rem;
  font-size:.86rem;line-height:1.55;color:#6E5714;
}
.stage-note b{font-family:var(--f-head);font-weight:700}

/* ---------- cards / grids ---------- */
.grid{display:grid;gap:clamp(18px,2.4vw,28px)}
.g2{grid-template-columns:repeat(2,1fr)}
.g3{grid-template-columns:repeat(3,1fr)}
.g4{grid-template-columns:repeat(4,1fr)}
@media(max-width:940px){.g4{grid-template-columns:repeat(2,1fr)}.g3{grid-template-columns:repeat(2,1fr)}}
@media(max-width:640px){.g2,.g3,.g4{grid-template-columns:1fr}}

.card{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:clamp(20px,2.4vw,28px);
}
.card--link{transition:transform .18s ease, box-shadow .18s ease, border-color .18s ease;display:block;color:inherit}
.card--link:hover{transform:translateY(-3px);box-shadow:0 20px 40px -26px rgb(25 27 20 / .32);border-color:#D6CBAC;text-decoration:none}
.card .ph{margin:calc(-1 * clamp(20px,2.4vw,28px)) calc(-1 * clamp(20px,2.4vw,28px)) 1.15rem;border-radius:var(--r) var(--r) 0 0;border-width:0 0 1px}

/* Four differentiators — wireframe-04 proportions.
   The wireframe draws this as a shallow band, not four cards: a 38px circular
   outline mark, text beside it, vertically centred, one short line of support
   copy. Held to those dimensions so the strip stays a breath between the hero
   and the service rows rather than a second block of content. */
/* Not a solid white slab. Flat --surface against the off-white page put a hard
   edge directly under the hero photo, which read as a second section starting
   rather than the hero settling. It's a white that reaches full opacity only
   on the band's own horizontal centre line and falls away vertically in both
   directions, so the page colour carries through at the edges and the band
   never draws a border.

   The band no longer spans the full page. Its width is capped at the content
   wrap, and the tint moved onto a ::before so the ends can be masked without
   fading the icons and labels with them — a mask on the section itself would
   take its children too, and the outer two items would go pale.

   The horizontal mask is deliberately tight — 4% each end, about 46px at the
   1140px cap. Enough to kill the vertical edge, and short enough that the
   outermost icon still sits on fully opaque tint; at 7% the fade reached under
   it. The vertical fade is unchanged and still does the top/bottom work. */
.band--feats{
  position:relative;
  padding-block:clamp(20px,2.4vw,30px);
  background:none;
}
.band--feats::before{
  content:"";position:absolute;inset-block:0;left:50%;translate:-50% 0;
  width:min(calc(100% - var(--gut)), var(--wrap));
  pointer-events:none;
  /* Flat, defined surface (client call, 6 Sep 2026): a solid white panel rather
     than a feathered glow. Capped to the wrap and rounded so it reads as a
     contained card between the hero and the service rows, not a full-width slab
     with a hard horizontal edge under the hero photo. A hairline plus a soft
     shadow give it its own edge; no vertical fade, no end mask. */
  background:#fff;
  border-radius:var(--r);
  box-shadow:0 0 0 1px rgb(120 110 80 / .12), 0 6px 20px -12px rgb(80 72 45 / .28);
}
/* Positioned so it paints above ::before — without this the tint covers the
   content, since a positioned pseudo outranks static in-flow children. */
.band--feats > .wrap{position:relative}

/* Label only in this band — no supporting line — so each icon+label pair is
   centred in its column and sits on one horizontal centre line across all
   four. Scoped to the band: .feat is also used on the quote and contact
   sections, where it keeps its subtext and stays left-aligned. */
.band--feats .g4{gap:24px}
.band--feats .feat{justify-content:center;align-items:center}
.band--feats .feat .h-mini{font-size:1.02rem;line-height:1.2}

/* Phone: two-up, not a four-row tower.
   The global .g4 rule drops to one column here, which turned the band into a
   264px list — no longer a banner, and it broke the tint: a vertical fade over
   that height puts its only solid area across the middle two rows and leaves
   the outer two washed out. Two-up keeps it ~140px, so the fade spans the band
   the way it does on desktop and the whole thing still clears the fold on a
   375x812 phone.

   Left-aligned rather than centred, because centred pairs put every icon at a
   different x once a label wraps — with two columns the icons line up and the
   wrapped label reads down a straight edge.

   This block MUST stay below the rules above: media queries add no specificity,
   so at equal weight the later rule wins and these would lose if moved up. */
@media(max-width:640px){
  .band--feats .g4{grid-template-columns:repeat(2,1fr);gap:16px 12px}
  .band--feats .feat{justify-content:flex-start;gap:.6rem}
  .band--feats .feat-ico{width:32px;height:32px}
  .band--feats .feat-ico svg{width:16px;height:16px}
  .band--feats .feat .h-mini{font-size:.9rem;line-height:1.25}
}
.feat{display:flex;gap:.85rem;align-items:center}
.feat-ico{
  width:38px;height:38px;flex:0 0 auto;border-radius:50%;
  border:1.5px solid var(--green);background:transparent;
  display:flex;align-items:center;justify-content:center;
}
.feat-ico svg{width:18px;height:18px;fill:var(--green)}
.feat p{margin-top:.15rem;font-size:.875rem;line-height:1.45;color:var(--ink-65)}

/* ---------- zigzag service rows ---------- */
.zig{display:grid;grid-template-columns:1fr 1fr;gap:clamp(28px,4.5vw,60px);align-items:center;padding-block:clamp(30px,4vw,48px)}
.zig + .zig{border-top:1px solid var(--line)}
.zig:nth-of-type(even) .zig-media{order:-1}
@media(max-width:860px){
  .zig{grid-template-columns:1fr;gap:24px}
  .zig:nth-of-type(even) .zig-media{order:0}
}
.ticks{list-style:none;margin:1.15rem 0 0;padding:0}
.ticks li{display:flex;gap:.65rem;align-items:flex-start;padding:.3rem 0;font-size:.96rem;color:var(--ink-65)}
.ticks li::before{
  content:"";flex:0 0 auto;width:19px;height:19px;margin-top:.22rem;border-radius:50%;
  background:var(--green-tint) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%232E6417' d='M9.2 16.6 4.8 12.2l1.5-1.5 2.9 2.9 7.5-7.5 1.5 1.5z'/%3E%3C/svg%3E") center/13px no-repeat;
}

/* ---------- reviews ---------- */
.rev-head{
  display:flex;gap:1.1rem;align-items:center;flex-wrap:wrap;
  padding-bottom:1.3rem;border-bottom:1px solid var(--line);
}
.glogo{
  width:42px;height:42px;flex:0 0 auto;border-radius:50%;
  background:var(--bg);border:1px solid var(--line);
  display:flex;align-items:center;justify-content:center;
  font-family:var(--f-head);font-weight:700;font-size:1.05rem;color:var(--green);
}
.rev{display:flex;gap:1rem;padding-block:1.4rem}
.rev + .rev{border-top:1px solid var(--line-soft)}
.av{
  width:40px;height:40px;flex:0 0 auto;border-radius:50%;
  background:var(--cream);
  display:flex;align-items:center;justify-content:center;
  font-family:var(--f-head);font-weight:600;font-size:.95rem;color:var(--green);
}
.rev-meta{display:flex;flex-wrap:wrap;align-items:center;gap:.6rem}
.rev q{display:block;margin-top:.45rem;font-size:.98rem;color:var(--ink-65);quotes:none}

/* ---------- form ---------- */
.formcard{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:clamp(22px,2.8vw,32px);
  box-shadow:0 26px 56px -34px rgb(25 27 20 / .28);
}
.field{display:block;margin-bottom:1rem}
.field > span{
  display:block;font-family:var(--f-head);font-weight:600;font-size:.8rem;
  color:var(--ink-80);margin-bottom:.38rem;letter-spacing:.005em;
}
.field input,.field select,.field textarea{
  width:100%;font-family:var(--f-body);font-size:1rem;color:var(--ink);
  background:var(--bg);border:1px solid var(--line);border-radius:10px;
  padding:.78rem .9rem;
}
.field input:focus,.field select,.field textarea:focus{outline-offset:0}
.field textarea{min-height:104px;resize:vertical}
.field input::placeholder,.field textarea::placeholder{color:var(--ink-50)}
.consent{display:flex;gap:.6rem;align-items:flex-start;margin-top:1rem;font-size:.82rem;color:var(--ink-65);line-height:1.5}
.consent input{margin-top:.25rem;accent-color:var(--green);width:16px;height:16px;flex:0 0 auto}

/* ---------- FAQ ---------- */
.faq{border-top:1px solid var(--line)}
.faq details{border-bottom:1px solid var(--line)}
.faq summary{
  list-style:none;cursor:pointer;padding:1.2rem 2.5rem 1.2rem 0;position:relative;
  font-family:var(--f-head);font-weight:600;font-size:1.04rem;color:var(--ink-80);
}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{
  content:"";position:absolute;right:.35rem;top:50%;width:11px;height:11px;
  border-right:2px solid var(--green);border-bottom:2px solid var(--green);
  transform:translateY(-70%) rotate(45deg);transition:transform .2s ease;
}
.faq details[open] summary::after{transform:translateY(-30%) rotate(-135deg)}
.faq details > div{padding:0 2.5rem 1.4rem 0;font-size:.98rem;color:var(--ink-65)}

/* ---------- closing CTA ---------- */
.closer{background:var(--green);color:#fff;border-radius:0}
.closer .h-sec{color:#fff;opacity:1;font-size:clamp(1.9rem,3.6vw,2.7rem)}
.closer .lede{color:rgb(255 255 255 / .82)}
.closer .eyebrow{color:var(--cream)}
.closer .eyebrow::before{background:var(--cream)}

/* ---------- area chips ---------- */
.chips{display:flex;flex-wrap:wrap;gap:.55rem;margin-top:1.4rem}
.chip{
  font-family:var(--f-head);font-weight:500;font-size:.87rem;
  background:var(--surface);border:1px solid var(--line);border-radius:999px;
  padding:.45rem 1rem;color:var(--ink-65);text-decoration:none;
}
.chip:hover{border-color:var(--green);color:var(--green);text-decoration:none}

/* ---------- breadcrumb ---------- */
.crumb{font-family:var(--f-head);font-weight:500;font-size:.83rem;color:var(--ink-65);padding-top:1.6rem}
.crumb a{color:var(--ink-65)}
.crumb a:hover{color:var(--green)}
.crumb span{margin-inline:.45rem;opacity:.6}

/* page header block */
.pagehead{padding-block:clamp(34px,5vw,58px) clamp(30px,4vw,48px);border-bottom:1px solid var(--line)}
.pagehead .h-page{margin-top:.85rem}
.pagehead .lede{margin-top:1rem}

/* ---------- footer ---------- */
.site-foot{background:var(--green);color:rgb(255 255 255 / .72);padding-block:clamp(46px,6vw,72px) 0;font-size:.93rem}
/* :not(.pill) matters. `.site-foot a` is one class + one element (0,1,1) and
   beats `.pill--onGreen` (0,1,0), so without this the footer's white phone
   pill gets white text on a white pill and vanishes. Excluding pills here
   rather than patching the one button keeps the next pill dropped into the
   footer from hitting the same thing. */
.site-foot a:not(.pill){color:rgb(255 255 255 / .78);text-decoration:none}
.site-foot a:not(.pill):hover{color:#fff;text-decoration:underline}
.site-foot .h-mini{color:var(--cream);letter-spacing:.11em;text-transform:uppercase;font-size:.73rem;margin-bottom:1rem}
.site-foot img{height:46px;width:auto}
/* Three columns since the Areas list came out — brand, Services, Company. */
.foot-grid{display:grid;grid-template-columns:1.5fr 1fr 1fr;gap:clamp(24px,3vw,48px)}
@media(max-width:860px){.foot-grid{grid-template-columns:1fr 1fr}}
@media(max-width:520px){.foot-grid{grid-template-columns:1fr}}
.foot-list{list-style:none;margin:0;padding:0}
.foot-list li{margin-bottom:.55rem}
.foot-bar{
  margin-top:clamp(34px,4vw,54px);border-top:1px solid rgb(255 255 255 / .17);
  padding-block:1.35rem;display:flex;flex-wrap:wrap;gap:1rem;justify-content:space-between;
  font-size:.83rem;color:rgb(255 255 255 / .70);
}

/* ---------- mobile sticky call bar ---------- */
.stickybar{
  position:fixed;left:0;right:0;bottom:0;z-index:70;display:none;gap:.6rem;
  padding:.65rem var(--gut) calc(.65rem + env(safe-area-inset-bottom));
  background:rgb(var(--bg-rgb) / .95);backdrop-filter:blur(10px);
  border-top:1px solid var(--line);
}
.stickybar .pill{flex:1}
@media(max-width:720px){.stickybar{display:flex}body{padding-bottom:74px}}

/* ---------- season pass page ---------- */
/* A sales focal point styled like a ski/hockey season pass: a bold full-bleed
   green hero, then the tiers as a full-width lineup of cards (one featured), so
   the whole thing reads at a glance with no cramped table or horizontal scroll. */
/* The season-pass card render IS the hero — full-bleed, its own green fills the
   section edge to edge (no separate hero background, no overlaid buttons). The
   #2B5319 is only a fallback colour before the image loads. */
.pass-hero{background:#2B5319;padding:0;line-height:0;position:relative}
.pass-hero-img{display:block;width:100%;height:auto;margin:0}
/* Desktop-only scroll cue over the big season-pass hero: a subtle bobbing
   chevron at the bottom, hinting the pass picker sits below the fold. Hidden on
   mobile (the hero is short there) and for reduced-motion users. */
.pass-scroll{display:none}
@media(min-width:721px){
  /* Cap the hero to the first screen (minus the 77px sticky header) so the whole
     card shows AND the scroll cue stays on-screen — at 1080p the un-capped image
     was taller than the viewport and pushed the cue below the fold. contain +
     the matching green bg keeps it reading full-bleed. */
  .pass-hero{height:calc(100svh - 77px)}
  .pass-hero-img{height:100%;object-fit:contain}
  .pass-scroll{display:flex;align-items:center;justify-content:center;
    position:absolute;left:50%;bottom:26px;transform:translateX(-50%);
    width:46px;height:46px;border-radius:50%;z-index:2;line-height:0;color:var(--cream);
    background:rgb(235 222 188 / .10);border:1px solid rgb(235 222 188 / .45);
    animation:pass-bob 1.9s ease-in-out infinite;
    transition:background .16s ease,border-color .16s ease}
  .pass-scroll:hover{background:rgb(235 222 188 / .22);border-color:var(--cream)}
  .pass-scroll::after{content:"";width:12px;height:12px;margin-top:-4px;
    border-right:2.5px solid currentColor;border-bottom:2.5px solid currentColor;transform:rotate(45deg)}
}
@keyframes pass-bob{0%,100%{transform:translate(-50%,0)}50%{transform:translate(-50%,6px)}}
@media(prefers-reduced-motion:reduce){.pass-scroll{animation:none}}

/* (Hero-font A/B toggle removed at launch — client chose Archivo, now the
   permanent H1 font above. Staging tool CSS + candidate fonts are gone.) */

/* Gutters page sub-service image cards */
.subsvc-card{display:flex;flex-direction:column}
.subsvc-img{display:block;width:100%;aspect-ratio:3/2;object-fit:cover;border-radius:10px}

/* Season-pass "Get on a pass": under the selector on desktop, below the whole
   chart on mobile (where the columns stack). */
.pass-cta-mobile{display:none}
@media(max-width:820px){
  .pass-cta-desktop{display:none}
  .pass-cta-mobile{display:inline-flex;margin-top:1.3rem}
}

/* Home hero: the two CTA pills are redundant on mobile — the sticky footer
   already carries Call + Free quote — so drop them there. */
@media(max-width:720px){.hero-copy .cta-row{display:none}}
.pass-eyebrow{font-family:var(--f-head);font-weight:600;font-size:.78rem;
  letter-spacing:.18em;text-transform:uppercase;color:rgb(235 222 188 / .85)}
.pass-h1{color:var(--cream);margin-top:.8rem}
.pass-lede{color:rgb(235 222 188 / .9);margin:1.15rem auto 0;max-width:56ch}

/* Selector (left) + comparison chart (right), modeled on the Ikon Pass shop. */
.passshop-grid{display:grid;grid-template-columns:0.92fr 1.18fr;gap:26px;align-items:start;text-align:left}
@media(max-width:820px){.passshop-grid{grid-template-columns:1fr;gap:20px}}
.passpicks{display:grid;gap:12px}
.passpick{display:flex;gap:12px;align-items:flex-start;text-align:left;width:100%;
  background:#fff;border:1.5px solid var(--line);border-radius:12px;padding:1rem 1.1rem;cursor:pointer;font-family:inherit}
.passpick:hover{border-color:var(--green)}
.passpick[aria-pressed="true"]{border-color:var(--green);box-shadow:0 0 0 1px var(--green),0 18px 36px -24px rgb(35 78 17 / .5)}
.passpick-radio{flex:0 0 auto;width:18px;height:18px;border-radius:50%;border:2px solid #C7BE9F;margin-top:3px;position:relative}
.passpick[aria-pressed="true"] .passpick-radio{border-color:var(--green)}
.passpick[aria-pressed="true"] .passpick-radio::after{content:"";position:absolute;inset:3px;border-radius:50%;background:var(--green)}
.passpick-body{display:flex;flex-direction:column;gap:.14rem;flex:1;min-width:0}
.passpick-name{font-family:var(--f-head);font-weight:700;font-size:1.02rem;color:var(--ink);display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}
.passpick-badge{background:var(--green);color:var(--cream);font-size:.6rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;padding:.2rem .5rem;border-radius:999px}
.passpick-tag{font-size:.86rem;color:var(--ink-65)}
.passpick-rate{font-family:var(--f-head);font-weight:700;color:var(--green);margin-top:.35rem}
.passpick-rate em{font-style:normal;font-weight:500;color:var(--ink-65);font-size:.85rem}
.passchart-wrap{overflow-x:auto}
.passchart{border-collapse:collapse;width:100%;font-size:.9rem}
.passchart th,.passchart td{padding:.62rem .7rem;text-align:left;border-bottom:1px solid var(--line);vertical-align:top;line-height:1.35}
.passchart thead th{font-family:var(--f-head);font-weight:700;color:var(--ink-80);font-size:.84rem;white-space:nowrap;border-bottom:2px solid var(--line)}
/* Label column anchors each row — bolder, darker, tinted so it reads as a header
   column distinct from the values. */
.passchart tbody th{font-weight:700;color:var(--ink);font-size:.86rem;white-space:nowrap;background:var(--cream-soft)}
.passchart thead th:first-child{background:var(--cream-soft)}
.passchart td{color:var(--ink-80)}
.passchart .pc-sub{display:block;font-size:.78rem;color:var(--ink-65);font-weight:400}
.passchart .pc-col.is-sel{background:var(--green-tint)}
.passchart thead .pc-col.is-sel{color:var(--green);box-shadow:inset 0 -2px 0 var(--green)}
/* Mobile: show one tier at a time, but keep every tier's cell in the layout
   (non-selected ones visibility:hidden, not display:none) so each row is always
   as tall as its TALLEST tier. Switching passes swaps the text without the boxes
   changing size. Taken out of table layout onto a grid with a fixed label column
   so the value cells stay aligned and wrap identically whichever tier shows. */
@media(max-width:720px){
  .passchart,.passchart thead,.passchart tbody{display:block}
  .passchart tr{display:grid;grid-template-columns:9.5rem 1fr;width:100%}
  .passchart thead th:first-child{display:none}
  .passchart tbody tr>th[scope=row]{grid-column:1;grid-row:1}
  .passchart .pc-col{grid-column:2;grid-row:1}
  .passchart .pc-col:not(.is-sel){visibility:hidden}
}

/* ---------- season-pass announcement bar (in the sticky header) ---------- */
/* First child of .site-head, so it rides with the sticky header and stays visible
   on every page. Fixed height (--promo-h) so the mobile menu offset can account
   for it (header = bar + 76px nav row). */
.promo-bar{display:flex;align-items:center;justify-content:center;gap:.5rem;
  height:var(--promo-h);padding:0 1rem;background:var(--green);color:var(--cream);
  font-family:var(--f-head);font-weight:600;font-size:.9rem;line-height:1.2;
  text-align:center;text-decoration:none;white-space:nowrap;overflow:hidden}
.promo-bar:hover{background:var(--green-deep);color:var(--cream)}
.promo-bar .promo-go{display:inline-block;white-space:nowrap;transition:transform .15s ease}
.promo-bar:hover .promo-go{transform:translateX(3px)}
/* Season-pass page has no announcement bar, so drop the header-height token to 0
   (the mobile menu offset is 76px + var(--promo-h)). */
body.no-promo{--promo-h:0px}
@media(max-width:560px){.promo-bar{font-size:.76rem;gap:.35rem}}

/* ---------- utility ---------- */
.mt-1{margin-top:.5rem}.mt-2{margin-top:1rem}.mt-3{margin-top:1.6rem}.mt-4{margin-top:2.4rem}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
