/* ============================================================================
   PAGES.CSS — the components the rebuild needed that the homepage never had.

   site.css is the homepage's design system, extracted byte-for-byte so the
   homepage can be proven not to have moved. This file is the small additive
   layer on top of it: components every rebuilt page wanted and none of them
   should invent privately, because a per-page <style> block is exactly how
   the site ended up with three competing design systems in the first place.

   Everything here is built from site.css's tokens. No new colours, no new
   radii, no second typeface, no sixth shadow — see DESIGN.md.

   LOAD ORDER: site.css → pages.css → protect-images.css → chrome.css.
   chrome.css stays last because it deliberately overrides both.
   ============================================================================ */


/* ============================================================================
   PER-PAGE HERO PHOTOGRAPHY

   The homepage's .hero hardcodes its own photograph. Every other page needs
   its own — law 6 of the rebuild brief: "different hero photo, no two pages
   may share a layout." Adding .hero-photo lets a page set the picture from
   four custom properties in one place, and inherits every other hero rule
   (type scale, form, proof bar, mobile stacking) unchanged.

       <section class="hero hero-photo" style="
         --hero-image:   image-set(url('…avif') type('image/avif'), …);
         --hero-image-m: image-set(url('…avif') type('image/avif'), …);">

   .hero.hero-photo (0,2,0) outranks .hero (0,1,0) at every width, including
   inside the max-width:979px block below, which is why the mobile override
   must repeat the compound selector rather than reuse .hero.
   ============================================================================ */
.hero.hero-photo {
  /* the ground under the photograph, for the moment before it decodes */
  background-color: var(--ink);
  background-image:
    /* Denser and held further right than the homepage's, because an interior
       hero's copy column is 640px wide rather than 580px and the sub-headline
       was landing on a floodlit gable. Still clear by 72%, so the half of the
       photograph people came to look at stays vibrant. */
    var(--hero-scrim,
      linear-gradient(90deg,
        rgba(7,16,42,0.93) 0%,
        rgba(7,16,42,0.88) 28%,
        rgba(7,16,42,0.72) 43%,
        rgba(7,16,42,0.44) 54%,
        rgba(7,16,42,0.14) 64%,
        rgba(7,16,42,0.00) 72%,
        rgba(7,16,42,0.00) 100%)),
    var(--hero-image);
  background-size: cover;
  background-position: var(--hero-position, center right);
  background-repeat: no-repeat;
}

@media (max-width: 979px) {
  .hero.hero-photo {
    /* Mobile puts the copy ON the photo rather than beside it, so the scrim
       runs top-to-bottom instead of left-to-right. --hero-image-m falls back
       to the desktop image when a page only supplies one. */
    background-image:
      var(--hero-scrim-m,
        linear-gradient(180deg,
          rgba(7,16,42,0.90) 0%,
          rgba(7,16,42,0.80) 38%,
          rgba(7,16,42,0.62) 62%,
          rgba(7,16,42,0.55) 100%)),
      var(--hero-image-m, var(--hero-image));
    background-position: var(--hero-position-m, center center);
  }
}


/* Hero credential chips — a row of short proofs under the form on pages where
   the four-up .hero-proof bar would be too heavy. Reads as one line on
   desktop, wraps to two on a phone. */
.hero-chips {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-top: 18px;
  justify-content: center;
}
@media (min-width: 980px) { .hero-chips { justify-content: flex-start; } }

.hero-chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 13px; border-radius: var(--r-pill);
  background: rgba(7,16,42,0.55);
  border: 1px solid rgba(255,255,255,0.18);
  color: rgba(255,255,255,0.94);
  font-size: 13px; font-weight: 600; letter-spacing: -0.005em;
  text-shadow: 0 1px 4px rgba(0,0,0,0.5);
}

.hero-chip svg { width: 15px; height: 15px; color: var(--brand-teal); flex-shrink: 0; }


/* ============================================================================
   SPLIT BAND — photograph on one side, the point on the other.

   This is the workhorse that replaces a prose column. A claim that used to be
   a paragraph becomes a heading, three ticks and the photograph that proves
   it. .split-reverse flips the media to the right; alternating them down a
   page is what gives the scroll its rhythm.
   ============================================================================ */
.split {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(28px, 4vw, 56px);
  align-items: center;
}
@media (min-width: 900px) {
  .split { grid-template-columns: 1fr 1fr; }
  .split-reverse .split-media { order: 2; }
}

/* Two columns of TEXT should start on the same line. .split centres its
   children, which is right when one side is a photograph — it sits level with
   the middle of the copy — but wrong for copy beside copy: the shorter column
   floated to the vertical middle and its heading sat well below the other's. */
.split-top { align-items: start; }

.split-media { margin: 0; position: relative; }

.split-media img {
  display: block; width: 100%; height: auto;
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
}

.split-media figcaption {
  margin-top: 12px;
  font-size: var(--fs-sm); color: var(--ink-muted); line-height: 1.5;
}

/* Two photographs stacked inside one media slot — the day/night pair. The
   second sits slightly over the first so the pair reads as one object. */
.split-media-pair { display: grid; gap: 14px; }

.split-media-pair img { border-radius: var(--r-lg); box-shadow: var(--shadow-md); }

/* Stacked, the pair has to stay SHORT. At their native ratio the two channel
   photos are square, so the media column ran 1,124px against 716px of copy —
   half a screen of scrolling before the text beside them was even finished
   (Ryan, 2026-08-27). A landscape crop puts the column back in step with the
   copy and keeps both photos in view at once; the subjects are centre-weighted
   (a corner detail, a fan of swatches) so nothing that matters is lost. */
@media (min-width: 900px) {
  .split-media-pair img { aspect-ratio: 16 / 9; object-fit: cover; }
}

/* Side by side ONLY while the split itself is still one column and the media
   slot is the full container. Once the split splits, its media column is half
   the width and a side-by-side pair drops each photo to ~256px — too small to
   read the very detail it was put there to show. */
@media (min-width: 520px) and (max-width: 899px) {
  .split-media-pair { grid-template-columns: 1fr 1fr; }
  /* Only in that side-by-side row do the cells have to match: the two
     photographs are 16:9 and 4:3, and a row of unequal cells is exactly the
     failure DESIGN.md's equal-cells rule exists to prevent. Stacked, each
     keeps its own frame. */
  .split-media-pair img { aspect-ratio: 4 / 3; object-fit: cover; }
}

/* PORTRAIT PAIR — two tall photographs whose subject runs top-to-bottom (a
   roofline jump, a channel drop below a gutter). The landscape crops above
   amputate exactly what these exist to show — the bird box's above-and-below
   was cut clean off (Ryan, 2026-08-29) — so this variant sits side by side at
   every width and keeps a 3:4 frame. Declared after both media queries so it
   wins at equal specificity. */
.split-media-pair-portrait { grid-template-columns: 1fr 1fr; }
.split-media-pair-portrait img { aspect-ratio: 3 / 4; object-fit: cover; }

/* A photograph whose SUBJECT is small inside a lot of empty frame — the swatch
   fan on its grey worktop, a part held in the hand. Filling the media column
   with it makes the picture tower over the two paragraphs beside it and reads
   as a mistake rather than emphasis (Ryan, 2026-08-27: "make this image
   smaller"). Same failure the pair-crop above was written for; this is the
   single-photo version. Capped and centred in its slot instead of filling it,
   caption tracking the image so the two stay one object. */
.split-media-sm img,
.split-media-sm figcaption { max-width: 430px; margin-inline: auto; }

.split-copy h2 {
  font-size: var(--fs-3xl); color: var(--ink);
  letter-spacing: -0.025em; line-height: 1.08;
  margin: 14px 0 16px;
}

.split-copy > p {
  font-size: var(--fs-lg); color: var(--ink-soft); line-height: 1.6;
  margin-bottom: 20px;
}

.split-copy > p:last-child { margin-bottom: 0; }

/* On a dark band the same block has to invert. */
.split-dark .split-copy h2 { color: white; }
.split-dark .split-copy > p { color: rgba(255,255,255,0.78); }
.split-dark .split-media figcaption { color: rgba(255,255,255,0.6); }
.split-dark .tick-list li { color: rgba(255,255,255,0.86); }
.split-dark .tick-list li strong { color: white; }


/* ============================================================================
   TICK LIST — the standard way a claim gets its evidence inside a split.
   The mark sits beside the line, never on a plate above it (DESIGN.md).
   ============================================================================ */
.tick-list { list-style: none; display: grid; gap: 13px; margin: 0 0 22px; }

/* The mark is positioned, NOT a grid column. A grid <li> makes EVERY element
   child its own grid item, so the <strong> at the start of each line was
   blockified into its own row and the trailing text was forced into the 22px
   mark column — one four-item list rendered 1,510px tall. */
.tick-list li {
  position: relative;
  padding-left: 34px;
  font-size: var(--fs-base); color: var(--ink-soft); line-height: 1.55;
}

.tick-list li strong { color: var(--ink); font-weight: 700; }

.tick-list li::before {
  content: "";
  position: absolute; left: 0; top: 2px;
  width: 22px; height: 22px;
  border-radius: 50%;
  background:
    /* the checkmark, drawn rather than an icon font or an emoji */
    url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230b7db3' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12l5 5L20 7'/%3E%3C/svg%3E")
    center / 14px 14px no-repeat,
    rgba(11,125,179,0.10);
}

.split-dark .tick-list li::before {
  background:
    url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2352cbbe' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12l5 5L20 7'/%3E%3C/svg%3E")
    center / 14px 14px no-repeat,
    rgba(82,203,190,0.14);
}


/* ============================================================================
   AUDIENCE CARDS — "is this for me?", answered as four people rather than
   four bullet points. Equal cells, one control height (Ryan's standard).
   ============================================================================ */
.audience-grid { display: grid; grid-template-columns: 1fr; gap: 18px; }
@media (min-width: 640px)  { .audience-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1060px) { .audience-grid { grid-template-columns: repeat(4, 1fr); } }

.audience-card {
  display: flex; flex-direction: column;
  background: white;
  border: 1px solid var(--hairline);
  border-radius: var(--r-xl);
  padding: 28px 24px 26px;
  box-shadow: var(--shadow-sm);
  transition: transform 0.3s var(--ease-swift), box-shadow 0.3s var(--ease-swift);
}

.audience-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }

.audience-card-mark { color: var(--brand-blue); margin-bottom: 16px; }

.audience-card-mark svg { width: 30px; height: 30px; display: block; }

.audience-card h3 {
  font-size: var(--fs-xl); color: var(--ink);
  letter-spacing: -0.02em; line-height: 1.2; margin-bottom: 9px;
}

.audience-card p {
  font-size: var(--fs-base); color: var(--ink-soft); line-height: 1.55;
  margin-bottom: 14px;
}

/* The card's last line is the reason to keep reading, and it must sit on the
   same baseline across all four cards however long the copy above it runs. */
.audience-card-note {
  margin-top: auto; padding-top: 14px;
  border-top: 1px solid var(--hairline);
  font-size: var(--fs-sm); font-weight: 700; color: var(--brand-blue);
}


/* ============================================================================
   NEUTRAL COMPARISON — the same table as .compare-table, minus the verdict.

   .compare-table's red/teal columns mean "them" and "us". When both columns
   are ours, that colouring would be telling the visitor their cheaper option
   is the wrong one, so this modifier neutralises it and lets .is-pick mark
   whichever column the row favours — with a word, never colour alone.
   ============================================================================ */
.compare-neutral .compare-cell-them,
.compare-neutral .compare-cell-us {
  background: white;
  color: var(--ink-soft);
}

.compare-neutral .compare-head .compare-cell-them,
.compare-neutral .compare-head .compare-cell-us {
  background: var(--surface-tinted);
  color: var(--ink);
}

/* No column tint. Tinting one side is a verdict, and on this table the tinted
   column was the MORE expensive product on the cheaper product's own page. */
.compare-neutral .compare-text-muted,
.compare-neutral .compare-text-win { color: var(--ink-soft); font-weight: 600; }

/* Its own line, always — as an inline-flex it ran straight on from the end of
   the sentence ("…cut into the fascia✓ SMARTCLIP WINS"). */
.compare-pick {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  margin-top: 8px;
  font-size: 11px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--brand-blue);
}

.compare-pick::before {
  content: ""; width: 13px; height: 13px; flex-shrink: 0;
  background: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230b7db3' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12l5 5L20 7'/%3E%3C/svg%3E") center / contain no-repeat;
}


/* ============================================================================
   PRICE BAND — a published range, stated once, at the size of a headline.
   Ranges only; never an exact price (DESIGN.md, product law).
   ============================================================================ */
.price-band {
  display: grid; grid-template-columns: 1fr; gap: clamp(24px, 3vw, 44px);
  align-items: center;
  background: var(--surface-tinted);
  border: 1px solid var(--hairline);
  border-radius: var(--r-xl);
  padding: clamp(28px, 4vw, 44px);
}
@media (min-width: 860px) { .price-band { grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); } }

.price-band-figures { display: grid; gap: 18px; }

.price-band-figure {
  display: flex; flex-direction: column; gap: 3px;
}

.price-band-label {
  font-size: 12px; font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--brand-blue);
}

.price-band-value {
  font-size: var(--fs-4xl); font-weight: 700; color: var(--ink);
  letter-spacing: -0.03em; line-height: 1.05;
}

.price-band-value small { font-size: 0.45em; font-weight: 600; color: var(--ink-muted); letter-spacing: -0.01em; }

.price-band-copy h3 {
  font-size: var(--fs-2xl); color: var(--ink);
  letter-spacing: -0.02em; line-height: 1.15; margin-bottom: 12px;
}

.price-band-copy p { font-size: var(--fs-base); color: var(--ink-soft); line-height: 1.6; margin-bottom: 14px; }

.price-band-copy p:last-of-type { margin-bottom: 20px; }

.price-band-actions { display: flex; flex-wrap: wrap; gap: 12px; }


/* ============================================================================
   DEMO BAND — the live myLights handset, with the reason to tap it beside it.
   Dark ground because a phone screen only looks like a phone screen at night.
   ============================================================================ */
.demo-band {
  background:
    radial-gradient(ellipse 70% 90% at 78% 40%, rgba(11,125,179,0.30) 0%, transparent 62%),
    radial-gradient(ellipse 60% 80% at 12% 90%, rgba(82,203,190,0.14) 0%, transparent 58%),
    var(--brand-dark-900);
  color: white;
}

.demo-band .section-head h2 { color: white; }
.demo-band .section-head p { color: rgba(255,255,255,0.76); }

.demo-grid {
  display: grid; grid-template-columns: 1fr; gap: clamp(32px, 4vw, 64px);
  align-items: center; justify-items: center;
}
@media (min-width: 900px) {
  .demo-grid { grid-template-columns: minmax(0, 1fr) 320px; justify-items: stretch; }
}

.demo-copy h3 {
  font-size: var(--fs-3xl); color: white;
  letter-spacing: -0.025em; line-height: 1.1; margin: 14px 0 16px;
}

.demo-copy > p { font-size: var(--fs-lg); color: rgba(255,255,255,0.78); line-height: 1.6; margin-bottom: 22px; }

.demo-copy .eyebrow { color: var(--brand-teal); }

.demo-copy .tick-list li { color: rgba(255,255,255,0.86); }
.demo-copy .tick-list li strong { color: white; }
.demo-copy .tick-list li::before {
  background:
    url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2352cbbe' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12l5 5L20 7'/%3E%3C/svg%3E")
    center / 14px 14px no-repeat,
    rgba(82,203,190,0.14);
}

.demo-hint {
  display: inline-flex; align-items: center; gap: 9px;
  font-size: var(--fs-sm); font-weight: 600; color: var(--brand-teal);
}

.demo-hint svg { width: 17px; height: 17px; }

.demo-under {
  margin-top: 16px; text-align: center;
  font-size: var(--fs-sm);
}

.demo-under a { color: var(--brand-teal); font-weight: 700; }


/* ============================================================================
   MOAT PANEL — a single claim big enough to be the whole section.
   Used where the point is one sentence and evidence, not a list of features.
   ============================================================================ */
.moat {
  position: relative;
  border-radius: var(--r-xl);
  overflow: hidden;
  background: var(--ink);
  color: white;
  padding: clamp(34px, 5vw, 64px);
}

.moat::after {
  /* one soft blue sweep, not a decorative gradient wash */
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(ellipse 55% 120% at 88% 0%, rgba(11,125,179,0.42) 0%, transparent 60%);
}

.moat > * { position: relative; z-index: 1; }

.moat .eyebrow { color: var(--brand-teal); }

.moat h2 {
  font-size: var(--fs-4xl); color: white;
  letter-spacing: -0.03em; line-height: 1.05;
  margin: 16px 0 20px;
  max-width: 26ch;
}

.moat > p {
  font-size: var(--fs-lg); color: rgba(255,255,255,0.80); line-height: 1.6;
  max-width: 62ch; margin-bottom: 28px;
}

.moat-facts {
  display: grid; grid-template-columns: 1fr; gap: 1px;
  background: rgba(255,255,255,0.13);
  border: 1px solid rgba(255,255,255,0.13);
  border-radius: var(--r-md);
  overflow: hidden;
}
@media (min-width: 820px) { .moat-facts { grid-template-columns: repeat(3, 1fr); } }

.moat-fact { background: var(--ink); padding: 24px 22px; }

.moat-fact-num {
  font-size: 12px; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--brand-teal);
  margin-bottom: 10px; display: block;
}

.moat-fact h3 { font-size: var(--fs-lg); color: white; letter-spacing: -0.015em; margin-bottom: 7px; }

.moat-fact p { font-size: var(--fs-sm); color: rgba(255,255,255,0.72); line-height: 1.55; }


/* ============================================================================
   INTERIOR HERO TYPE

   The homepage's h1 is two words per line ("Your Lights." / "Your Way.") and
   is set at clamp(60px, 8vw, 96px) to suit them. Interior headlines carry more
   words, and at that size they filled the entire fold on their own — which
   pushed the capture form below it and broke law 1 of the rebuild brief
   (photograph, headline AND a call to action, all without scrolling).

   So a photo hero takes a smaller step, tunable per page via --hero-h1, and
   gets a slightly wider copy column. The homepage carries no .hero-photo
   class, so nothing here can reach it.
   ============================================================================ */
.hero-photo h1 {
  font-size: var(--hero-h1, clamp(38px, 4.2vw + 6px, 60px));
  font-weight: 800;
  -webkit-text-stroke: 0.3px currentColor;
  margin-bottom: 12px;
}

.hero-photo .hero-sub { font-size: var(--fs-base); margin-bottom: 22px; }

@media (min-width: 980px) {
  .hero-photo .hero-copy { max-width: var(--hero-copy-max, 640px); }
}


/* ============================================================================
   LINKS INSIDE THE NEW COMPONENTS

   site.css styles links per-component, so a link dropped into a split, a price
   band or the moat panel inherited body colour and read as plain text — the
   internal silo links were invisible.
   ============================================================================ */
.split-copy a,
.price-band-copy a,
.audience-card a {
  color: var(--brand-blue); font-weight: 700;
  text-decoration: underline; text-underline-offset: 2px;
  text-decoration-thickness: 1px;
  text-decoration-color: rgba(11,125,179,0.35);
  transition: text-decoration-color 0.2s var(--ease-smooth);
}

.split-copy a:hover,
.price-band-copy a:hover,
.audience-card a:hover { text-decoration-color: var(--brand-blue); }

.moat a, .split-dark .split-copy a, .demo-copy a {
  color: var(--brand-teal); font-weight: 700;
  text-decoration: underline; text-underline-offset: 2px;
  text-decoration-color: rgba(82,203,190,0.4);
}


/* ============================================================================
   HEADLINE BALANCE

   Every one of these headings left a one-word last line ("offer.", "live.").
   text-wrap: balance evens the lines and degrades to normal wrapping where it
   is not supported.
   ============================================================================ */
.split-copy h2,
.demo-copy h3,
.moat h2,
.price-band-copy h3 { text-wrap: balance; }


/* ============================================================================
   NEUTRAL COMPARISON ON MOBILE — the labels have to change too.

   Under 720px site.css collapses each row into a stacked card and stamps the
   two value cells with "TYPICAL:" in red and "SPARKLED:" in teal. On a neutral
   table that is not a style detail, it is FALSE: the SmartClip column was
   labelled "Typical" in the red reserved for competitors, on SmartClip's own
   page, and Permanent was labelled "Sparkled" as though the other one wasn't.

   The column names come from the page, via two custom properties on the table:

       <div class="compare-table compare-neutral"
            style="--compare-them-label:'SmartClip: ';
                   --compare-us-label:'Permanent: '">
   ============================================================================ */
@media (max-width: 720px) {
  .compare-neutral .compare-cell-them::before {
    content: var(--compare-them-label, "Option A: ");
    color: var(--brand-blue);
  }
  .compare-neutral .compare-cell-us::before {
    content: var(--compare-us-label, "Option B: ");
    color: var(--brand-blue);
  }
  /* the stacked cells are left-aligned, so the verdict pill is too */
  .compare-neutral .compare-pick { justify-content: flex-start; }
}

/* site.css leaves the footnote's links at footnote colour, and those links are
   the internal silo — they have to look clickable. */
.compare-footnote a {
  color: var(--brand-blue); font-weight: 700; font-style: normal;
  text-decoration: underline; text-underline-offset: 2px;
  text-decoration-color: rgba(11,125,179,0.35);
}

.compare-footnote a:hover { text-decoration-color: var(--brand-blue); }


/* ============================================================================
   HERO ON A PHONE

   Mobile puts the copy ON the photograph rather than beside it, so the form
   sits directly over the lit house. A left-to-right scrim does nothing there
   and the glass fields washed out against the glow — hence a heavier
   top-to-bottom one, and chips that become equal full-width cells instead of
   three pills of three different widths stacked raggedly down the middle
   ("wrapped button rows read as thrown together" — Ryan).
   ============================================================================ */
@media (max-width: 979px) {
  .hero.hero-photo {
    background-image:
      /* LIGHTER, because the photograph IS the pitch (Ryan, 2026-08-27: "each
         hero on mobile needs to be adjusted so the money shot is in view").
         The previous ramp sat at 0.80-0.93 the whole way down and flattened
         every hero into a dark rectangle — the lit house, the only thing no
         competitor can copy, was invisible on a phone. It stays dense behind
         the headline at the top, then opens up: the form inputs carry their
         own glass background and border, so they hold up over the picture. */
      var(--hero-scrim-m,
        linear-gradient(180deg,
          rgba(7,16,42,0.88) 0%,
          rgba(7,16,42,0.78) 22%,
          rgba(7,16,42,0.58) 46%,
          rgba(7,16,42,0.50) 72%,
          rgba(7,16,42,0.62) 100%)),
      var(--hero-image-m, var(--hero-image));
  }
}

@media (max-width: 560px) {
  .hero-chips {
    display: grid; grid-template-columns: 1fr;
    gap: 8px; justify-items: stretch;
    max-width: 320px; margin-inline: auto;
  }
  .hero-chip { justify-content: flex-start; }
}


/* ============================================================================
   HERO ACCENT WORD

   `?angle=` on the Permanent pillar rewrites the whole h1 to
   `lead + <span class="accent">…</span>`, so the default markup has to use the
   same shape — no .h1-line spans there, or the ad variants would render
   differently from the page they replace.
   ============================================================================ */
.hero-photo h1 .accent { color: var(--brand-teal); }


/* ============================================================================
   TIER CARDS — scope or price, three ways, as cards rather than a table.

   Two shapes share one component: Permanent's tiers carry a published RANGE
   and a feature list; Christmas's carry a photograph of the same house at each
   scope. `.tier-card` stretches so all three end level whatever the copy does,
   and the CTA is pinned to the bottom by margin-top:auto — the alternative is
   three buttons on three different baselines, which is the "thrown together"
   Ryan calls out.
   ============================================================================ */
.tier-grid { display: grid; grid-template-columns: 1fr; gap: 22px; }
@media (min-width: 760px)  { .tier-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .tier-grid { grid-template-columns: repeat(3, 1fr); } }

.tier-card {
  display: flex; flex-direction: column;
  background: white;
  border: 1px solid var(--hairline);
  border-radius: var(--r-xl);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: transform 0.3s var(--ease-swift), box-shadow 0.3s var(--ease-swift);
}

.tier-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }

/* The middle tier is the one most people pick, and saying so is information,
   not decoration — so it gets the blue outline and nothing else does. */
.tier-card-popular {
  border-color: var(--brand-blue);
  box-shadow: 0 0 0 1px var(--brand-blue), var(--shadow-md);
}

.tier-card-media { position: relative; margin: 0; line-height: 0; background: var(--surface-sunken); }

.tier-card-media img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; }

.tier-flag {
  position: absolute; top: 14px; left: 14px;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: var(--r-pill);
  background: var(--brand-blue); color: white;
  font-size: 11px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase;
  line-height: 1;
}

.tier-card-body { display: flex; flex-direction: column; flex: 1; padding: 26px 24px 24px; }

.tier-label {
  font-size: 12px; font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--brand-blue); margin-bottom: 10px;
}

.tier-card h3 {
  font-size: var(--fs-2xl); color: var(--ink);
  letter-spacing: -0.02em; line-height: 1.15; margin-bottom: 6px;
}

.tier-sub { font-size: var(--fs-sm); color: var(--ink-muted); line-height: 1.5; margin-bottom: 18px; }

.tier-price {
  padding: 16px 0; margin-bottom: 18px;
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}

.tier-price-value {
  display: block;
  font-size: clamp(28px, 2.4vw + 18px, 40px); font-weight: 700;
  color: var(--ink); letter-spacing: -0.03em; line-height: 1.05;
}

.tier-price-note { display: block; margin-top: 5px; font-size: var(--fs-sm); color: var(--ink-muted); }

.tier-features { list-style: none; display: grid; gap: 10px; margin-bottom: 22px; }

.tier-features li {
  position: relative; padding-left: 28px;
  font-size: var(--fs-sm); color: var(--ink-soft); line-height: 1.5;
}

.tier-features li::before {
  content: ""; position: absolute; left: 0; top: 2px;
  width: 18px; height: 18px; border-radius: 50%;
  background:
    url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230b7db3' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12l5 5L20 7'/%3E%3C/svg%3E")
    center / 11px 11px no-repeat,
    rgba(11,125,179,0.10);
}

.tier-cta { margin-top: auto; }

.tier-cta .btn { width: 100%; justify-content: center; }

/* The note that sits under a set of tiers and explains what moves the number. */
.tier-note {
  max-width: 860px; margin: 32px auto 0; text-align: center;
  font-size: var(--fs-base); color: var(--ink-soft); line-height: 1.6;
}

.tier-note strong { color: var(--ink); }


/* ============================================================================
   SPEC TILES — the hardware, stated as numbers, on a dark ground because
   that is where a photograph of an LED puck can actually be seen.
   ============================================================================ */
.spec-band {
  background:
    radial-gradient(ellipse 60% 90% at 20% 10%, rgba(11,125,179,0.26) 0%, transparent 62%),
    var(--ink);
  color: white;
}

.spec-band .section-head h2 { color: white; }
.spec-band .section-head p { color: rgba(255,255,255,0.74); }
.spec-band .eyebrow { color: var(--brand-teal); }

.spec-grid {
  display: grid; grid-template-columns: 1fr; gap: clamp(28px, 4vw, 56px);
  align-items: center;
}
@media (min-width: 900px) { .spec-grid { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); } }

.spec-media { margin: 0; }

.spec-media img {
  display: block; width: 100%; height: auto;
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-xl);
}

.spec-media figcaption {
  margin-top: 12px; font-size: var(--fs-sm); color: rgba(255,255,255,0.6); line-height: 1.5;
}

.spec-tiles { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px;
  background: rgba(255,255,255,0.13);
  border: 1px solid rgba(255,255,255,0.13);
  border-radius: var(--r-md); overflow: hidden; }
@media (min-width: 640px) { .spec-tiles { grid-template-columns: repeat(3, 1fr); } }

.spec-tile { background: var(--ink); padding: 22px 20px; }

.spec-tile-value {
  display: block; font-size: var(--fs-2xl); font-weight: 700;
  color: white; letter-spacing: -0.02em; line-height: 1.1; margin-bottom: 6px;
}

.spec-tile-label { display: block; font-size: var(--fs-sm); color: rgba(255,255,255,0.68); line-height: 1.45; }


/* ============================================================================
   PATTERN TILES — the four bulb patterns, at the same price, so the card
   carries no price at all. The bulbs sit on a night ground because that is
   the only light they are ever seen in.
   ============================================================================ */
.pattern-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; }
@media (min-width: 900px) { .pattern-grid { grid-template-columns: repeat(4, 1fr); } }

.pattern-card {
  display: flex; flex-direction: column;
  background: white; border: 1px solid var(--hairline);
  border-radius: var(--r-lg); overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: transform 0.3s var(--ease-swift), box-shadow 0.3s var(--ease-swift);
}

.pattern-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }

.pattern-card-bulbs {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  padding: 30px 18px 26px;
  /* LIGHT, not night (Ryan, 2026-08-27). The reasoning for a dark ground was
     that bulbs are only ever seen lit — but these are product cut-outs, not
     photographs of a lit roofline, and the dark panel made four cards read as
     four black boxes in the middle of a white page. surface-sunken is one of
     the only two separation surfaces DESIGN.md allows, and the warm-white
     bulbs still read against it because each one is faceted and outlined. */
  background: var(--surface-sunken);
  border-bottom: 1px solid var(--hairline);
}

.pattern-card-bulbs img { display: block; width: 100%; height: auto; max-width: 190px; }

.pattern-card-body { padding: 18px 18px 20px; text-align: center; }

.pattern-card h3 { font-size: var(--fs-lg); color: var(--ink); letter-spacing: -0.015em; margin-bottom: 5px; }

.pattern-card p { font-size: var(--fs-sm); color: var(--ink-muted); line-height: 1.45; }

.pattern-flag {
  position: absolute; top: 12px; left: 12px;
  padding: 5px 10px; border-radius: var(--r-pill);
  background: var(--brand-blue); color: white;
  font-size: 10px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; line-height: 1;
}


/* ============================================================================
   PROMISE CARDS — five items, and five never divides into a tidy grid.

   Rather than leave a ragged last row, the umbrella promise (the all-inclusive
   one, which literally contains the other four) spans the full width and the
   four specifics sit in a 2x2 beneath it. Every cell is full; the composition
   says what the copy says.
   ============================================================================ */
.promise-grid { display: grid; grid-template-columns: 1fr; gap: 18px; }
@media (min-width: 720px) {
  .promise-grid { grid-template-columns: repeat(2, 1fr); }
  .promise-card-lead { grid-column: 1 / -1; }
}

.promise-card {
  display: flex; flex-direction: column;
  background: white; border: 1px solid var(--hairline);
  border-radius: var(--r-xl); padding: 26px 24px;
  box-shadow: var(--shadow-sm);
}

.promise-card-head { display: flex; align-items: flex-start; gap: 14px; margin-bottom: 10px; }

.promise-card-mark { color: var(--brand-blue); flex-shrink: 0; }

.promise-card-mark svg { width: 26px; height: 26px; display: block; }

.promise-card h3 { font-size: var(--fs-xl); color: var(--ink); letter-spacing: -0.02em; line-height: 1.25; }

.promise-card p { font-size: var(--fs-base); color: var(--ink-soft); line-height: 1.55; }

.promise-card-lead {
  background: var(--surface-tinted);
  border-color: rgba(11,125,179,0.22);
}

.promise-card-lead h3 { font-size: var(--fs-2xl); }


/* The demo band, mirrored. The Permanent pillar and the SmartClip pillar both
   have to show the same live handset; putting it on opposite sides is what
   stops two pages that share one component from reading as one page. */
@media (min-width: 900px) {
  .demo-grid-reverse { grid-template-columns: 320px minmax(0, 1fr); }
}

/* A plain row of city pills. site.css styles the pill itself but its only
   container, .more-cities, is a show/hide helper with no layout of its own. */
.city-pill-row {
  display: flex; flex-wrap: wrap; gap: 8px;
  justify-content: center;
  max-width: 940px; margin-inline: auto;
}


/* NEARBY BAND — the cross-link row at the foot of city and service pages.
   These were one-line .compare-footnote paragraphs floating alone in a
   section-tight: tiny text, acres of white space (Ryan, 2026-08-28 —
   "way too small and way too much empty space", and he'd seen it on all of
   them). Now it's a real component: an eyebrow label over full-size city
   pills on a sunken card, using the same pill the county hubs use. */
.nearby-band {
  text-align: center;
  background: var(--surface-sunken);
  border: 1px solid var(--hairline);
  border-radius: var(--r-xl);
  padding: 30px clamp(18px, 4vw, 44px) 32px;
  max-width: 940px;
  margin-inline: auto;
}
.nearby-band .eyebrow { margin-bottom: 16px; }
.nearby-band .city-pill-row { gap: 10px; }
.nearby-band .city-pill {
  font-size: 14.5px;
  padding: 10px 18px;
  background: #fff;
  border-color: var(--hairline);
  box-shadow: var(--shadow-sm);
}
.nearby-band .city-pill:hover,
.nearby-band .city-pill:focus-visible {
  background: rgba(11,125,179,0.08);
  border-color: rgba(11,125,179,0.22);
}
/* A real review quoted inside a split section — born on the jump section,
   where a paraphrase of the customer's review was doing the quote's job
   (Ryan, 2026-08-29: include the actual snippet, link the reviews page). */
.split-quote {
  margin: 18px 0 0; padding: 14px 18px;
  border-left: 3px solid var(--brand-gold);
  background: var(--surface-sunken);
  border-radius: 0 var(--r-lg) var(--r-lg) 0;
}
.split-quote p {
  margin: 0; font-size: 15px; line-height: 1.6;
  color: var(--ink); font-style: italic;
}
.split-quote cite {
  display: block; margin-top: 8px;
  font-style: normal; font-size: 13.5px; color: var(--ink-muted);
}
.split-quote cite a { color: var(--brand-blue); }

.nearby-band-note {
  margin: 14px 0 0;
  font-size: 13.5px;
  color: var(--ink-muted);
}


/* Three tier cards, three different heading lengths — which put the price
   blocks on three different lines. Reserving two lines for the heading and one
   for the scope note lands every price on the same baseline, which is the
   whole point of a comparison set ("aligned baselines" — Ryan). */
/* OPT-IN, because the reserve is only right where the headings actually differ.
   On the Permanent pillar the tier names wrap to two lines and the price blocks
   landed on three different baselines without it; on the Christmas pillar all
   three names are one word and reserving the second line just opens a hole. */
@media (min-width: 760px) {
  .tier-grid-reserve .tier-card h3 { min-height: 2.3em; }
  .tier-grid-reserve .tier-sub { min-height: 3em; }
}

/* site.css leaves the spacing figure's caption at caption colour, links and
   all, so the cluster link inside it was invisible. */
.spacing-compare-caption a,
.tier-note a {
  color: var(--brand-blue); font-weight: 700;
  text-decoration: underline; text-underline-offset: 2px;
  text-decoration-color: rgba(11,125,179,0.35);
}

.spacing-compare-caption a:hover,
.tier-note a:hover { text-decoration-color: var(--brand-blue); }


/* The four pattern captions run one line, one line, one line, then two — an
   uneven bottom row on a set that exists to be compared. */
.pattern-card-body p { min-height: 2.9em; }


/* A six-step process in the homepage's four-column grid leaves two empty cells
   in the last row — the exact "thrown together" look the equal-cells rule
   exists to prevent. Three columns divides six evenly; two at tablet does too. */
@media (min-width: 1000px) {
  .process-grid-3 { grid-template-columns: repeat(3, 1fr); }
}


/* ============================================================================
   VIDEO FACADE — a poster and a play button; the player arrives on click.

   The site loads no third-party player on page load, and it should not start
   now: an embedded YouTube iframe pulls ~600KB and sets cookies before anyone
   has decided to watch. So each video is a LOCAL poster (downloaded from
   YouTube once, served from sparkled-assets like every other image) plus a
   button. Clicking swaps in a youtube-nocookie iframe with autoplay — one
   request, made because the visitor asked for it.

   The pattern is already on this site: the myLights demo boots on tap for the
   same reason. Behaviour lives in sparkled-assets/video.js.
   ============================================================================ */
.video-embed {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--r-xl);
  overflow: hidden;
  background: var(--ink);
  box-shadow: var(--shadow-lg);
  cursor: pointer;
  border: none; padding: 0; margin: 0;
  display: block; width: 100%;
}

.video-embed img,
.video-embed iframe {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; border: 0; display: block;
}

/* a soft floor so white caption text stays legible on a bright frame */
.video-embed::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, rgba(7,16,42,0.10) 0%, rgba(7,16,42,0.00) 38%, rgba(7,16,42,0.55) 100%);
  transition: opacity 0.3s var(--ease-smooth);
}

.video-embed.is-playing::after,
.video-embed.is-playing .video-play,
.video-embed.is-playing .video-label { display: none; }

.video-play {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: 74px; height: 74px; border-radius: 50%;
  background: rgba(255,255,255,0.94);
  box-shadow: var(--shadow-lg);
  display: flex; align-items: center; justify-content: center;
  transition: transform 0.28s var(--ease-spring), background-color 0.2s var(--ease-smooth);
}

.video-play svg { width: 30px; height: 30px; margin-left: 4px; color: var(--brand-blue); }

.video-embed:hover .video-play,
.video-embed:focus-visible .video-play { transform: translate(-50%, -50%) scale(1.08); background: white; }

.video-embed:focus-visible { outline: 3px solid var(--brand-blue); outline-offset: 3px; }

.video-label {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 18px 20px;
  color: white; font-weight: 700; font-size: var(--fs-base);
  letter-spacing: -0.01em; line-height: 1.3;
  text-align: left;
  text-shadow: 0 1px 6px rgba(0,0,0,0.55);
}

.video-duration {
  display: block; margin-top: 3px;
  font-size: var(--fs-sm); font-weight: 600; color: rgba(255,255,255,0.74);
  text-shadow: 0 1px 6px rgba(0,0,0,0.55);
}

/* A single feature video, centred and larger than the grid ones. */
.video-feature { max-width: 860px; margin-inline: auto; }

.video-grid { display: grid; grid-template-columns: 1fr; gap: 20px; }
@media (min-width: 700px)  { .video-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1060px) { .video-grid-3 { grid-template-columns: repeat(3, 1fr); } }

/* A video and the notes that belong to it, as ONE grid instead of two stacked
   ones. Two grids read as pairs only while both happen to have the same column
   count, and they did not: on a phone each collapsed to a single column, so a
   visitor got all three videos and THEN all three sets of notes (Ryan,
   2026-08-27: "the written instructions need to go right after each video").
   Between 1000 and 1059px it was worse -- two columns of video above THREE
   columns of notes. DOM order is video, its notes, video, its notes, so the
   pairing cannot come apart at any width; the desktop rule below lifts the
   videos back into a row of their own, which is what the two grids looked like
   at full width all along. */
.step-pairs { display: grid; grid-template-columns: 1fr; gap: 20px; }

@media (min-width: 1060px) {
  .step-pairs {
    grid-template-columns: repeat(3, 1fr);
    row-gap: clamp(24px, 3vw, 36px);
  }
  /* Odd children are the videos, even children their notes. Placed explicitly
     rather than left to auto-flow, which would run video, notes, video across
     the first row. */
  .step-pairs > *:nth-child(odd)  { grid-row: 1; }
  .step-pairs > *:nth-child(even) { grid-row: 2; }
  .step-pairs > *:nth-child(1), .step-pairs > *:nth-child(2) { grid-column: 1; }
  .step-pairs > *:nth-child(3), .step-pairs > *:nth-child(4) { grid-column: 2; }
  .step-pairs > *:nth-child(5), .step-pairs > *:nth-child(6) { grid-column: 3; }
}

.video-note {
  max-width: 760px; margin: 18px auto 0; text-align: center;
  font-size: var(--fs-sm); color: var(--ink-muted); line-height: 1.55;
}

.video-note a { color: var(--brand-blue); font-weight: 700; text-decoration: underline; text-underline-offset: 2px; }


/* ============================================================================
   DOWNLOAD CARDS — the printable instructions and the presets file.
   ============================================================================ */
.download-grid { display: grid; grid-template-columns: 1fr; gap: 18px; }
@media (min-width: 760px) { .download-grid { grid-template-columns: repeat(2, 1fr); } }

.download-card {
  display: flex; align-items: flex-start; gap: 16px;
  background: white; border: 1px solid var(--hairline);
  border-radius: var(--r-xl); padding: 24px 22px;
  box-shadow: var(--shadow-sm);
  transition: transform 0.3s var(--ease-swift), box-shadow 0.3s var(--ease-swift), border-color 0.2s;
}

.download-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: rgba(11,125,179,0.3); }

.download-card-mark {
  flex-shrink: 0; width: 46px; height: 46px; border-radius: var(--r-md);
  background: rgba(11,125,179,0.10); color: var(--brand-blue);
  display: flex; align-items: center; justify-content: center;
}

.download-card-mark svg { width: 24px; height: 24px; }

.download-card h3 { font-size: var(--fs-lg); color: var(--ink); letter-spacing: -0.015em; margin-bottom: 5px; }

.download-card p { font-size: var(--fs-sm); color: var(--ink-soft); line-height: 1.5; }

.download-card-meta {
  display: inline-flex; align-items: center; gap: 6px;
  margin-top: 10px; font-size: 12px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--brand-blue);
}


/* ============================================================================
   STORY FURNITURE — a pull quote, a timeline and a signature.

   Our Story was a 22-paragraph prose column, which is precisely the shape the
   rebuild brief rejected. A story still has to READ as prose, though, so it
   does not get chopped into cards — it gets punctuation: a line lifted out at
   headline size, a dated rail for the part that is genuinely a sequence (three
   company names in three years), and a signed sign-off.
   ============================================================================ */
/* NO accent bar down the side. A thick coloured border on one edge is the
   single most recognisable generated-UI tell, and DESIGN.md's confirmed
   anti-reference is exactly that look. It was also doing no work: at --fs-3xl
   in full-strength ink, breaking out wider than the story column it
   interrupts, inside a sunken band, the quote already reads as lifted out.
   DESIGN.md's own instruction for this — "if a section needs distinction, use
   size, weight or space, not a new typeface" — applies to decoration too. */
.pullquote {
  max-width: 900px; margin: clamp(44px, 6vw, 76px) auto;
}

.pullquote p {
  font-size: var(--fs-3xl); font-weight: 700; color: var(--ink);
  letter-spacing: -0.025em; line-height: 1.18;
  text-wrap: balance;
  /* the opening quote mark hangs into the margin, the way a set quote does */
  text-indent: -0.42em;
}

.pullquote cite {
  display: block; margin-top: 14px;
  font-size: var(--fs-sm); font-style: normal; font-weight: 600;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-muted);
}

/* --- the naming journey ---------------------------------------------- */
.timeline { max-width: 780px; margin-inline: auto; list-style: none; }

.timeline li {
  position: relative;
  padding: 0 0 clamp(26px, 3vw, 38px) 46px;
}

.timeline li:last-child { padding-bottom: 0; }

.timeline li::before {
  content: ""; position: absolute; left: 8px; top: 6px;
  width: 13px; height: 13px; border-radius: 50%;
  background: var(--brand-blue);
  box-shadow: 0 0 0 4px rgba(11,125,179,0.14);
}

/* the rail, drawn between the dots rather than through them */
.timeline li:not(:last-child)::after {
  content: ""; position: absolute; left: 14px; top: 24px; bottom: 4px;
  width: 1px; background: var(--hairline-strong);
}

.timeline-when {
  display: block; font-size: 12px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--brand-blue);
  margin-bottom: 5px;
}

.timeline h3 { font-size: var(--fs-xl); color: var(--ink); letter-spacing: -0.02em; margin-bottom: 7px; }

.timeline p { font-size: var(--fs-base); color: var(--ink-soft); line-height: 1.6; }

/* --- the sign-off ----------------------------------------------------- */
.signature {
  max-width: 780px; margin-inline: auto;
  background: var(--surface-tinted);
  border: 1px solid rgba(11,125,179,0.2);
  border-radius: var(--r-xl);
  padding: clamp(28px, 4vw, 44px);
  text-align: center;
}

.signature p { font-size: var(--fs-lg); color: var(--ink-soft); line-height: 1.6; margin-bottom: 16px; }

.signature-name {
  font-size: var(--fs-2xl); font-weight: 700; color: var(--ink);
  letter-spacing: -0.02em; line-height: 1.2;
}

.signature-role { display: block; margin-top: 4px; font-size: var(--fs-sm); color: var(--ink-muted); font-weight: 600; }

.signature-note {
  margin-top: 22px; padding-top: 20px;
  border-top: 1px solid var(--hairline);
  font-size: var(--fs-sm); color: var(--ink-muted); line-height: 1.6;
}

/* --- prose that stays prose ------------------------------------------- */
/* Not every page should be cards. The story reads as writing, so it keeps a
   measured column — but centred, at a comfortable measure, with real spacing,
   rather than interior.css's cramped left-aligned 76ch block. */
.story { max-width: 700px; margin-inline: auto; }

.story p {
  font-size: var(--fs-lg); color: var(--ink-soft); line-height: 1.72;
  margin-bottom: 20px;
}

.story p:last-child { margin-bottom: 0; }

.story p strong { color: var(--ink); }

.story-lead { font-size: var(--fs-xl) !important; color: var(--ink) !important; font-weight: 500; }


/* ============================================================================
   OPEN POSITIONS — the careers page as a real job listing page.

   Careers used to be a hero, three paragraphs and a link that opened
   GoHighLevel in a new tab. Someone arriving from one of the Facebook job
   listings could not find out what the job paid, what the hours were or what
   the work actually involved without applying first (Ryan, 2026-08-28). Each
   role is published here in full instead, with the same facts as the listing
   it came from.

   Roles are STACKED, not carded side by side. Two long postings in a two-up
   grid give two columns of unequal height -- the "thrown together" look
   DESIGN.md's equal-cells rule exists to prevent -- and a job posting is read
   top to bottom, not compared across.
   ============================================================================ */
.job-list { display: grid; gap: clamp(20px, 3vw, 32px); }

.job {
  border: 1px solid var(--hairline);
  border-radius: var(--r-xl);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

.job-head {
  padding: clamp(22px, 3vw, 30px) clamp(20px, 3vw, 32px) 0;
}

.job-head h3 {
  font-size: var(--fs-2xl); color: var(--ink);
  letter-spacing: -0.022em; line-height: 1.14; margin: 0 0 14px;
}

/* The three facts someone decides on -- pay, hours, place -- before any prose. */
.job-facts { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 4px; }

.job-fact {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 13px; border-radius: var(--r-pill);
  background: var(--surface-sunken);
  border: 1px solid var(--hairline);
  font-size: 13.5px; font-weight: 650; color: var(--ink-soft);
  letter-spacing: -0.005em;
}

.job-fact svg { width: 15px; height: 15px; color: var(--brand-blue); flex-shrink: 0; }

/* Pay is the one fact people scan for, so it is the one that is not grey. */
.job-fact-pay {
  background: rgba(46, 160, 106, 0.10);
  border-color: rgba(46, 160, 106, 0.28);
  color: #1c6b45;
}
.job-fact-pay svg { color: #2ea06a; }

.job-body { padding: clamp(18px, 2.4vw, 24px) clamp(20px, 3vw, 32px) clamp(22px, 3vw, 30px); }

.job-body > p { color: var(--ink-soft); line-height: 1.62; margin: 0 0 16px; }

.job-section { margin-top: 22px; }

.job-section h4 {
  font-size: 12px; font-weight: 700; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--brand-blue);
  margin: 0 0 10px;
}

.job-section p { color: var(--ink-soft); line-height: 1.62; margin: 0 0 12px; }

.job-section ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }

.job-section li {
  position: relative; padding-left: 26px;
  color: var(--ink-soft); line-height: 1.55;
}

.job-section li::before {
  content: ""; position: absolute; left: 6px; top: 0.62em;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--brand-teal);
}

/* The standard paragraph on the installer posting is the part Ryan asks people
   to read twice, so it is pulled out of the run of prose rather than sitting in
   it as another block of grey text. */
.job-callout {
  margin-top: 22px; padding: 16px 18px;
  border-left: 3px solid var(--brand-teal);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  background: var(--surface-sunken);
}

.job-callout p { margin: 0 0 10px; color: var(--ink-soft); line-height: 1.6; }
.job-callout p:last-child { margin-bottom: 0; }
.job-callout strong { color: var(--ink); }

.job-foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
  padding: clamp(16px, 2vw, 20px) clamp(20px, 3vw, 32px);
  border-top: 1px solid var(--hairline);
  background: var(--surface-sunken);
}

.job-foot .apply-note { margin: 0; font-size: var(--fs-sm); color: var(--ink-muted); }


/* ============================================================================
   APPLY MODAL — the application in a popup, not a new tab. See apply.js for
   why the form inside it is still GoHighLevel's.
   ============================================================================ */
.apply-modal {
  display: none;
  position: fixed; inset: 0; z-index: 400;
  background: rgba(10,20,36,0.6);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  opacity: 0; transition: opacity 0.25s var(--ease-swift);
  padding: clamp(10px, 2vw, 24px);
}

.apply-modal.is-open { display: flex; opacity: 1; align-items: center; justify-content: center; }

/* The PANEL owns the height. The form inside scrolls; the page behind does not,
   and nothing depends on a pixel height guessed in advance. */
.apply-modal-panel {
  background: white;
  border-radius: var(--r-2xl);
  width: 100%; max-width: 720px;
  height: min(92vh, 960px);
  display: flex; flex-direction: column;
  overflow: hidden; position: relative;
  box-shadow: var(--shadow-xl);
  transform: scale(0.94) translateY(16px);
  transition: transform 0.32s var(--ease-spring);
}

.apply-modal.is-open .apply-modal-panel { transform: scale(1) translateY(0); }

.apply-modal-head {
  flex-shrink: 0;
  padding: 20px 60px 18px 26px;
  background: radial-gradient(ellipse 80% 140% at 100% 0%, rgba(82,203,190,0.25), transparent 60%),
              linear-gradient(135deg, #0b7db3 0%, #053b5d 100%);
  color: white; position: relative;
}

.apply-modal-head h2 {
  color: white; font-size: 21px; font-weight: 700;
  letter-spacing: -0.02em; line-height: 1.15; margin: 0 0 5px;
}

.apply-modal-head p { color: rgba(255,255,255,0.82); font-size: 14px; line-height: 1.5; margin: 0; }

.apply-modal-close {
  position: absolute; top: 14px; right: 14px;
  width: 36px; height: 36px; border-radius: 50%;
  background: rgba(255,255,255,0.15); color: white;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 22px; line-height: 1; font-weight: 300;
  transition: all 0.2s; backdrop-filter: blur(10px); cursor: pointer;
}

.apply-modal-close:hover { background: rgba(255,255,255,0.28); transform: rotate(90deg); }

.apply-modal-body { flex: 1; min-height: 0; background: #fff; }

.apply-modal-body iframe { display: block; width: 100%; height: 100%; border: 0; }
