/**
 * Shinnova site stylesheet — the shared half of every builder page.
 *
 * WHY THIS IS A FILE AND NOT INLINE IN EACH PAGE
 * Measured on the first converted page: moving inline styles to classes makes a SINGLE
 * page 2.3KB LARGER gzipped (14.0 -> 16.3KB), because the Design prototypes repeat the
 * same inline style strings hundreds of times and gzip eats that almost for free. So
 * per-page class extraction, on its own, is a regression. The win is only in sharing:
 *
 *   inline:  20 pages x 16,298 gz          = 325,960 bytes
 *   shared:  9,064 once + 20 x 7,709       = 163,244 bytes   (50% less)
 *
 * and a visitor's second page drops from 16.3KB to 7.7KB. Anyone who benchmarks one
 * page in isolation will conclude this was a mistake; it is only correct across a site
 * someone browses, which is the point.
 *
 * EVERY VALUE HERE IS MEASURED, not chosen, from the Claude Design prototypes rendered
 * at 1440px with the real TBJ Norguba face loaded. Verify changes with
 * page-kit/tools/measure-baseline.js before committing them. The acceptance test is an
 * empty diff against the prototype, EXCEPT for the deliberate mobile and footer-logo
 * divergences listed in that file's header — read those before concluding a change
 * regressed something.
 *
 * WHAT A PAGE STILL OWNS: the per-product --accent / --ink / --accent-card-ink triple,
 * and its own hero background-image. Nothing else should appear in a page's <style>.
 * If a rule shows up on two pages it belongs in here.
 *
 * THE HANDLE MUST STAY ON THE FIREWALL ALLOWLIST. Shin_Assets dequeues every style
 * handle it does not recognise, including ones this plugin enqueues itself, and it
 * fails silently — the page renders completely unstyled with no error anywhere.
 */

/* ==================================================================== tokens */
#shinnova-page {
  /* --accent, --ink and --accent-card-ink are NOT set here. Each page declares its
     own product triple in its <style> block; this file only consumes them. */
  --folder:      var(--accent);
  --charcoal:    #2d2d2d;
  --heading:     rgb(51,51,51);
  --body:        #757575;   /* passes on white only */
  --body-alt:    #63676D;   /* on #f7f7f7 grounds */
  --ground:      #f7f7f7;
  --hairline:    rgba(51,51,51,0.14);
  --cta-green:   #00ff01;
  --cta-green-bd:#00f300;
  --cta-green-hv:#01b601;

  --h1: 85px;  --h1-ls: 4.4px;
  --h2: 65px;  --h2-ls: 1.5px;
  --h3: 32px;
  --lede: 24px;

  --cols-2: 1fr 1fr;
  --cols-3: repeat(3, 1fr);
  --cols-4: repeat(4, 1fr);
  /* NOT `1fr 1fr`: 1fr means minmax(auto,1fr), and the 85px headline's longest word
     squeezed the survey card to 254px. */
  --hero-cols: minmax(0, 1fr) minmax(0, 1fr);
  --hero-form-cols: 1fr 1fr;

  --folder-wall: 6px;
  --folder-radius: 22px;
  /* --folder-inset IS DELIBERATELY NOT APPLIED. The prototypes declare it (14px, 6px
     under 768) and set `margin: 0 0 var(--folder-inset)` on the folder — and it
     renders NOTHING, because there the folder's bottom margin collapses up through
     two plain divs and out of the document. Measured: prototype and page both end
     the folder at the same pixel, both with a computed 14px bottom margin, and the
     prototype's document is 14px shorter.

     It cannot collapse on our page: #shinnova-page carries `overflow-x: clip`, which
     establishes a block formatting context and traps the margin as a real gap below
     the footer. So applying it reproduces a number the prototype declares but never
     shows. This was added on 2026-09-11 and reverted the same day once measured;
     leaving the token out entirely is what stops it being "fixed" again. */
  --sheet-radius: 12px;
  --tab-drop: 12px;

  /* The Get Inspired gallery has its OWN column token, not --cols-4. They agree down
     to 900px and then part: the gallery stays two-up at 768 where --cols-4 drops to
     one. Collapsing them puts one photo per row on a phone. */
  --gal-cols: repeat(4, 1fr);
  --gal-rows: repeat(2, 1fr);

  /* The hub community list is CSS COLUMNS, not a grid — a plain count, not a track
     list. It drops to two under 900px and stays there. */
  --city-cols: 4;

  /* The site heroes' sub-headline. Only the 13 site pages use it; it is declared here
     rather than on .shin-folder--site because a token that resolves to nothing fails
     silently — the text simply renders at the inherited size and nothing says why. */
  --hero-sub: 24px;

  --nav-display: flex;
  --burger-display: none;
  --cta-phone-display: inline-flex;
  --cta-phone-pad: 10px 20px;
  --cta-phone-fs: 14px;
  --nav-pad: 0 28px;
  --head-pad: 0px;
  --bar-display: flex;
  --sticky-bar: none;
  --sticky-pad: 0px;
  --hero-y: 100px;
  /* Gutter between the Local Intro photo and its copy. The split grid itself has
     gap: 0, so this padding IS the gutter, and it collapses to 0 on mobile. */
  --split-pad: 50px;

  --font-display: 'TBJ Norguba', Oswald, sans-serif;
  --font-body: Poppins, sans-serif;
  /* CARD HEADINGS ARE POPPINS. The Design package set .shin-h3 and its siblings in
     Roboto, inline, on ~985 headings across 121 pages. The owner confirmed that was
     a design miss (2026-09-14): Poppins is the body face and these are body-side
     headings. Roboto stays in the stack as a genuine fallback and is NO LONGER
     SELF-HOSTED, which is the point — see the note where its @font-face used to be. */
  --font-card: Poppins, Roboto, sans-serif;
}
@media (max-width: 1400px) { #shinnova-page { --nav-pad: 0 18px; } }
@media (max-width: 1200px) {
  #shinnova-page {
    --nav-display: none; --burger-display: inline-flex; --head-pad: 5px;
    --cta-phone-pad: 8px 14px; --cta-phone-fs: 13px; --hero-y: 80px;
  }
}
@media (max-width: 900px) {
  #shinnova-page {
    --bar-display: none; --sticky-bar: grid; --sticky-pad: 76px;
    --h1: 70px; --h1-ls: 2.5px; --h2: 60px; --h2-ls: 2.5px; --h3: 28px; --lede: 14px;
    --hero-cols: 1fr; --cols-2: 1fr; --cols-3: 1fr; --cols-4: repeat(2, 1fr);
    --gal-cols: repeat(2, 1fr); --gal-rows: auto; --city-cols: 2;
    --hero-y: 50px; --split-pad: 0px; --hero-sub: 14px;
  }
}
@media (max-width: 768px) {
  #shinnova-page {
    --h1: 48px; --h1-ls: 1.5px; --h2: 40px; --h2-ls: 1.5px;
    --folder-wall: 4px; --folder-radius: 14px; --sheet-radius: 8px;
    --tab-drop: 8px; --cols-4: 1fr; --hero-form-cols: 1fr;
    /* The phone pill drops out and the header gains breathing room instead; the
       sticky bottom bar is carrying the call CTA by this width. */
    --cta-phone-display: none; --head-pad: 20px;
    --hero-y: 30px;
  }
}

/* The self-hosted display face. Served same-origin in production; note it has no
   CORS headers, so any off-domain preview falls back to Oswald, which runs about 8%
   shorter. That is a preview artifact, not a bug to fix. */
@font-face {
  font-family: 'TBJ Norguba';
  src: url('/wp-content/uploads/2026/03/tbj-norguba.regular.otf') format('opentype');
  font-weight: 400;
  font-display: swap;
}

/* === GENERATED FONTS — build_fonts.py — DO NOT EDIT BY HAND === */
/* Poppins, Roboto and Oswald, self-hosted. SIL Open Font License 1.1.
   Regenerate with page-kit/tools/build_fonts.py; do not hand-edit.

   These were a THIRD-PARTY, RENDER-BLOCKING stylesheet whose font files could
   not even be discovered until it had been fetched and parsed — 750 ms on the
   critical path, with the LCP text waiting at the end of it. Served from this
   stylesheet they cost no extra connection and no extra round trip.

   unicode-range IS LOAD-BEARING: it is what stops every visitor downloading
   subsets they cannot read. Only latin and latin-ext are hosted, so a page in
   Greek or Cyrillic falls back to the system face rather than loading one that
   is not here. That is deliberate for an English-language site. */
@font-face {
  /* OSWALD IS PUNCTUATION ONLY. It is not a text face here and must never become one
     again: `unicode-range` below is exactly the set of marks TBJ Norguba has no glyph
     for, so this file is fetched only by a heading that contains one of them.

     WHY. TBJ Norguba maps 70 codepoints - letters, digits, and `! & , . ?` and nothing
     else. Every other mark fell through to Oswald, and asking for one apostrophe
     downloaded the whole 28.5 KB latin face. 41 of 132 pages did exactly that, and on
     the mobile homepage it was the longest chain in the dependency tree at 719 ms.
     Copy can fix most of them, but not all: `O'Fallon` and `Lee's Summit` are city
     names, and ten product pages carry one in an H1.

     So Oswald is subset to the 47 marks it actually has to supply - 28,488 bytes ->
     6,884, a 76% cut - and the weight axis is kept, which is what lets ONE file serve
     every display weight. It used to be three files (300/400/500) that were BYTE
     IDENTICAL, because Google serves Oswald as a variable font and build_fonts.py
     saved the same download under three names; a page using two display weights
     downloaded the same 28.5 KB twice.

     The trade, stated plainly: if TBJ Norguba ever fails to load, headings fall to
     `sans-serif` and only their punctuation comes from Oswald. That is a mixed
     rendering, and it is accepted - TBJ is same-origin, preloaded and 7 KB. The old
     behaviour bought a tidier failure mode at 28.5 KB on every affected page.

     An accented character in a display heading falls to sans-serif too. There are none
     today (page-kit/tools/audit_display_glyphs.py checks) and adding the Latin-1
     letters back costs 8 KB, which is more than this whole file. */
  font-family: 'Oswald';
  font-style: normal;
  font-weight: 200 700;
  font-display: swap;
  src: url('../fonts/oswald-fallback.woff2') format('woff2');
  unicode-range: U+0022-0025, U+0027-002B, U+002D, U+002F, U+003A-003E, U+0040, U+005B-0060, U+007B-007E, U+00A0, U+00A9, U+00AE, U+00B0, U+00B7, U+00BC-00BE, U+00D7, U+00F7, U+2013-2014, U+2018-2019, U+201C-201D, U+2022, U+2026, U+20AC, U+2122;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('../fonts/poppins-300-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('../fonts/poppins-300-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/poppins-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/poppins-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/poppins-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/poppins-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/poppins-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/poppins-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* ROBOTO IS NOT SELF-HOSTED, AND MUST NOT BE ADDED BACK.
   It was six files, and like Oswald they were byte-identical in threes: Google serves
   Roboto as a variable font, so `:wght@500;600;700` returned one download saved under
   three names. A page using two weights fetched the same 42 KB twice — Lee's Summit
   Windows pulled roboto-500 AND roboto-600, 84 KB of a 122 KB font payload.

   And only one of those two was ours. Nothing in this stylesheet asks for Roboto 500;
   all three consumers specify 600. The local preview, which has no GTM, fetches only
   the 600. Staging, with GTM, fetches both — something Google Tag Manager injects asks
   for Roboto, which is Google's default UI face, and because we self-hosted it that
   widget got to pull 42 KB from our origin. Dropping the @font-face leaves it on the
   system sans, where it belongs, and costs us nothing.

   Roboto still appears in --font-card as a FALLBACK NAME only: if a visitor happens to
   have it installed it will be used should Poppins fail, and no file is ever fetched. */
/* === END GENERATED FONTS === */

/* ===================================================================== base */
#shinnova-page { background: #d9d9d9; overflow-x: clip; }  /* desk surface behind the folder */
#shinnova-page *, #shinnova-page *::before, #shinnova-page *::after { box-sizing: border-box; }
#shinnova-page img { max-width: 100%; }
/* THE COMPANION TO width/height ON <img>, AND IT IS NOT OPTIONAL.
   Those attributes are PRESENTATIONAL HINTS mapped to the CSS `width` and `height`
   properties — not merely a ratio. The moment the converter started stamping them, any
   image whose CSS set a width but no height took the attribute as a literal pixel
   height: the Current Offers row grew 923px -> 1566px, because six images sized by
   `aspect-ratio: 3/2` and `1/1` suddenly stood 604 and 652 pixels tall.

   `height: auto` hands the box back to the author CSS while leaving the browser the
   attribute-derived ratio to reserve space with, which is the entire point of adding
   them. Both halves are needed; neither works alone.

   SPECIFICITY ZERO IS THE LOAD-BEARING PART. A presentational hint loses to every
   author rule, even a (0,0,0) one, so this is strong enough to win — while `height`
   set by a class such as `.shin-simg--cover` (0,1,0) still beats it, which is what
   keeps the cover images filling their boxes. Written as `img[width][height]` outside
   :where() it would be (0,2,1) and would break exactly those. */
:where(#shinnova-page img[width][height]) { height: auto; }
/* THE ID IS INSIDE :where() AND MUST STAY THERE.
   The prototypes declare these at ELEMENT specificity — `a { color: #0b7fc9 }` — so
   every anchor that states its own colour (nav tabs, phone pills, hero CTAs, footer
   links: 107 of the 313 anchors in the package carry one inline) overrides it, and
   only a genuinely bare anchor renders blue.

   Writing them as `#shinnova-page a` instead raised them to ID specificity, which
   beats every class in this file. The result was the whole site's links forced to one
   blue: the nav tabs turned #0b7fc9-on-#099cf9 and stopped being readable at all, and
   the hero CTAs lost their white. :where() contributes ZERO specificity, so these
   land back at (0,0,1) and (0,1,1) — the prototypes' own cascade.

   Do not "simplify" the :where() away. It fails in the least visible direction: the
   page still renders, the geometry harness still measures exact, and only the colour
   is wrong. */
:where(#shinnova-page) a { color: #0b7fc9; text-decoration: none; }
/* :where(:hover) TOO, for the same reason one level down. At (0,1,1) this beat every
   SINGLE-class colour in the file — `.tab-windows`, `.shin-sticky-call`,
   `.shin-menu-phone` are all (0,1,0) — so hovering a nav tab turned it blue-on-blue
   again, which is the original bug with an extra step. In the prototypes the colour
   is inline and hover cannot touch it, so this belongs at (0,0,1): later in source
   than the rule above, which is what makes it win on a genuinely bare anchor and
   lose to everything else. */
:where(#shinnova-page) a:where(:hover) { color: #06639e; text-decoration: underline; }
/* The buttons, tabs and pills carry `text-decoration: none` INLINE in the prototypes,
   which beats the element-level `a:hover` underline above. A class rule does not beat
   it — (0,1,0) loses to (0,1,1) — so the button-shaped anchors restate it. Text links
   are deliberately NOT in this list: 206 of the 313 anchors have no inline
   text-decoration and DO underline on hover, which is the behaviour to keep.
   `:is()` takes the specificity of its most specific argument, so this lands at
   (0,2,1) and wins. */
:where(#shinnova-page) :is(
  .shin-logo, .shin-tabs a, .shin-menu a, .shin-phone-pill, .shin-hero-cta,
  .shin-btn-green, .shin-sticky a, .shin-sibling, .shin-svc-card, .shin-gallery a,
  .shin-footer-brand > a
):hover { text-decoration: none; }
#shinnova-page summary { list-style: none; cursor: pointer; }
#shinnova-page ::selection { background: var(--accent); color: var(--charcoal); }

/* The folder: a band of product color wrapping the page.
   THE BASE TYPOGRAPHY LIVES HERE AND IS LOAD-BEARING. Everything without an
   explicit line-height inherits 1.6 from this rule, so dropping it makes every
   eyebrow, label and bare text node 1.2px shorter and the page ends up ~100px
   short overall — small enough per element to look fine and still miss. */
.shin-folder {
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 300;
  line-height: 1.6;
  background: var(--folder);
  padding: 0 var(--folder-wall) var(--folder-wall);
  border-bottom-left-radius: var(--folder-radius);
  border-bottom-right-radius: var(--folder-radius);
  box-shadow: 0 18px 44px rgba(45,45,45,0.22);
}
/* Hubs and city pages STAY BORDERLESS (reference/TEMPLATE-location-product-page.md).
   That is three tokens, not one color: a neutral frame with no wall, no radius and no
   inset. Declared on the folder rather than on #shinnova-page so it survives the
   breakpoints above, which would otherwise put the wall back at 768px.

   The ACCENT IS NOT NEUTRALISED. These pages keep the windows pair for every eyebrow
   rule, icon and card border — only the frame goes grey. See render_location.py. */
.shin-folder--flat {
  --folder: #3a3a3a;
  --folder-wall: 0px;
  --folder-radius: 0px;
}
.shin-wrap { max-width: 1500px; margin: 0 auto; padding: 0 20px; }
.shin-narrow { max-width: 1040px; }

/* =================================================================== header */
.shin-header {
  position: sticky; top: 0; z-index: 60; background: transparent;
  /* Bleeds out over the folder wall so the tab strip spans the full width. */
  margin: 0 calc(var(--folder-wall) * -1);
}
/* The folder's top edge lives on THIS row, not on .shin-header — the header also
   contains the follow-along bar, and a border there slides down when the bar opens. */
.shin-header-row {
  background: var(--charcoal);
  border-bottom: var(--folder-wall) solid var(--folder);
}
.shin-header-inner {
  max-width: 1500px; margin: 0 auto; padding: var(--head-pad) 20px 0;
  display: flex; align-items: stretch; gap: 24px; min-height: 80px;
}
.shin-burger {
  display: var(--burger-display); align-items: center; gap: 10px;
  margin-bottom: var(--tab-drop); background: none; border: 0; color: #fff;
  font-family: var(--font-body); font-size: 14px; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.04em; cursor: pointer;
  padding: 0 4px; flex: 0 0 auto;
}
.shin-burger i { font-size: 20px; }
.shin-logo { display: flex; align-items: center; flex: 0 0 auto; padding: 14px 0 var(--tab-drop); }
.shin-logo img { height: 46px; width: auto; display: block; }
.shin-nav { display: flex; align-items: stretch; flex: 1 1 auto; justify-content: center; }
.shin-tabs {
  display: var(--nav-display); align-items: stretch; gap: 0; list-style: none;
  margin: 0; padding: 0; font-family: var(--font-body); font-size: 14px;
  font-weight: 500; letter-spacing: 0.04em; text-transform: uppercase;
}
.shin-tabs li { display: flex; }
/* The offset belongs on the li as margin-top. `align-items: flex-end` collapses
   every anchor to text height. */
.shin-tabs li.is-inactive { margin-top: var(--tab-drop); }
.shin-tabs a {
  display: flex; align-items: center; padding: var(--nav-pad);
  border-top-left-radius: 10px; border-top-right-radius: 10px;
  filter: saturate(0.7) brightness(0.82); transition: filter 0.2s ease;
}
.shin-tabs a:hover { filter: none; }
/* A GENERAL SITE PAGE HAS NO CURRENT PRODUCT, and its tabs are neither state: all
   five sit flush and undimmed, none pulled down and none merged into the sheet. The
   product HUBS are different again — they wear the full product-page treatment, own
   tab active and the other four dropped and dimmed. Three states, not two. */
.shin-tabs li.is-flush { margin-top: 0; }
.shin-tabs li.is-flush a { filter: none; }
/* Active tab: full height, larger radii, and it covers the folder wall so it merges
   into the white sheet below. */
.shin-tabs li.is-active { margin-top: 0; }
.shin-tabs li.is-active a {
  margin-bottom: calc(var(--folder-wall) * -1);
  border-top-left-radius: 12px; border-top-right-radius: 12px;
  position: relative; z-index: 2; filter: none;
}
.tab-windows { background: #099cf9; color: #06263f; }
.tab-doors   { background: #ff1042; color: #3d0210; }
.tab-siding  { background: #00ff01; color: #0b2b0b; }
.tab-roofing { background: #fec502; color: #3a2c00; }
.tab-decks   { background: #00f5d4; color: #003b34; }

.shin-header-cta { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; padding-bottom: var(--tab-drop); }
.shin-phone-pill {
  display: var(--cta-phone-display); align-items: center; gap: 8px;
  padding: var(--cta-phone-pad); border-radius: 40px;
  background: #099ffe; border: 1px solid #0093f2; color: #fff;
  font-family: var(--font-body); font-size: var(--cta-phone-fs); font-weight: 500;
  white-space: nowrap;
}
.shin-phone-pill:hover { background: #099cf9; color: #fff; }

/* Burger dropdown, which reproduces the tab language inside the menu. */
.shin-menu { display: none; background: var(--charcoal); padding: 0 20px 16px; }
.shin-menu.is-open { display: block; }
.shin-menu ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.shin-menu a {
  display: block; padding: 12px 16px; border-radius: 10px;
  font-family: var(--font-body); font-size: 14px; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.04em;
}
.shin-menu .shin-menu-phone { background: #099ffe; color: #fff; }

/* ================================================== follow-along survey bar */
/* Shown once the hero card scrolls out of view, and at >=901px only, where the
   sticky mobile bar takes over instead. */
.shin-bar { display: none; background: var(--charcoal); border-bottom: 1px solid rgba(255,255,255,0.1); }
.shin-bar.is-visible { display: var(--bar-display); }
.shin-bar-inner {
  max-width: 1500px; margin: 0 auto; padding: 10px 20px;
  display: flex; align-items: center; gap: 16px; width: 100%;
}
/* letter-spacing matches .shin-survey-title — same words, same face, and the two are
   on screen one after the other as the hero card scrolls out and this bar takes over. */
.shin-bar-label {
  flex: 0 0 auto; font-family: var(--font-display); font-size: 20px;
  text-transform: uppercase; color: #fff; letter-spacing: 0.04em;
}
.shin-bar-step { flex: 1 1 auto; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* WHITE FIELDS ON THE DARK BAR, matching `.shin-survey input` and the prototype.
   These were dark-on-dark (#3a3a3a on #262626), which read as disabled rather than as
   inputs. The prototype's bar declares `background: #fff; border: 1px solid #e0e0e0;
   color: #2d2d2d` inline — the same treatment the survey card already uses — so this is
   a correction back to the package, not a restyle. The placeholder override went with
   it: white-on-white is invisible, and the card gets on fine with the browser default. */
.shin-bar input {
  min-height: 40px; padding: 8px 14px; border: 1px solid #e0e0e0; border-radius: 12px;
  font-family: var(--font-body); font-size: 14px; color: var(--charcoal); background: #fff;
  flex: 1 1 130px; min-width: 0;
}
.shin-bar input:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(9,156,249,0.25);
}
.shin-bar .shin-btn-green { min-height: 40px; padding: 9px 22px; font-size: 14px; }

/* ==================================================================== sheet */
.shin-sheet {
  background: #fff;
  border-bottom-left-radius: var(--sheet-radius);
  border-bottom-right-radius: var(--sheet-radius);
  overflow: hidden;
}

/* ===================================================================== hero */
.shin-hero {
  position: relative;
  background-size: cover; background-position: center center; background-repeat: no-repeat;
}
.shin-hero-scrim {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(45,45,45,0.74) 0%, rgba(45,45,45,0.6) 100%);
}
/* Location and hub heroes use a FLAT scrim, not the product pages' gradient. */
.shin-hero-scrim--flat { background: rgba(46,46,46,0.63); }
.shin-hero-inner {
  position: relative; z-index: 2; max-width: 1500px; margin: 0 auto;
  padding: var(--hero-y) 20px; display: grid;
  grid-template-columns: var(--hero-cols); align-items: center; gap: 40px;
}
.shin-eyebrow-hero {
  margin: 0 0 14px; font-family: var(--font-body); font-size: 12px; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.3em; color: var(--accent);
}
.shin-h1 {
  margin: 0; font-family: var(--font-display); font-weight: 400;
  overflow-wrap: break-word; font-size: min(var(--h1), 5vw); line-height: 1;
  letter-spacing: var(--h1-ls); text-transform: uppercase; color: #fff;
  text-shadow: 0 2px 18px rgba(0,0,0,0.35); text-wrap: pretty;
}
.shin-hero-lede {
  margin: 24px 0 0; max-width: 46ch; font-family: var(--font-body);
  font-size: var(--lede); font-weight: 300; line-height: 1.5; color: rgba(255,255,255,0.92);
}
.shin-hero-trust {
  margin: 22px 0 0; font-family: var(--font-body); font-size: 14px;
  font-weight: 300; color: rgba(255,255,255,0.8);
}

/* =================================================================== survey */
.shin-survey { display: flex; align-items: flex-start; justify-content: center; height: 100%; padding: 40px 0; scroll-margin-top: 100px; }

/**
 * MOBILE PUTS THE FORM FIRST.
 *
 * Mobile is more than half of this site's traffic, and on a phone the hero copy pushed
 * the survey card's top to 451px and its Continue button to 938px — on a 667px
 * viewport the entire call to action sat below the fold, on pages whose only job is to
 * convert. The headline is worth less than the form it was standing in front of.
 *
 * `order` rather than reordered markup, deliberately. The DOM keeps copy-then-form, so
 * the H1 still precedes the form for a screen reader and a crawler, and desktop is
 * untouched. It also changes no element's height, which means the fidelity diff
 * against the Design prototype stays empty at every width — this is a visual-order
 * departure only, and a documented one (docs/ARCHITECTURE-site-rebuild.md).
 */
@media (max-width: 900px) {
  /* A COLUMN, so the scroll cue can sit under the card. Single-child everywhere else,
     so this changes nothing on a page without one. */
  .shin-survey { order: -1; padding: 0 0 28px; flex-direction: column; align-items: center; }
  .shin-hero-inner > div:not(.shin-survey) { order: 0; }

  /* A FLOOR ON THE GAP ABOVE THE CARD.
     `.shin-hero-inner` pays `var(--hero-y)` (30px at phone widths), which already
     clears the card's 20-24px side gutter. Some heroes are not that class: their grid
     is an inline-styled div, and the five site pages (home, about, contact, gallery,
     services) set `padding: 0 20px` on it because their copy column carries its own
     80px. On a phone the survey moves to the top of that grid and the card ended up
     flush against the header with no gap at all.
     THE PADDING GOES ON THE SURVEY, NOT THE GRID, because the grid's padding is an
     INLINE style and no stylesheet rule can outrank it. The survey carries no inline
     style, so this lands. 24px matches the widest side gutter, so the card sits in an
     even frame.
     Excluding `.shin-hero-inner` is what keeps the 120 location pages at 30px rather
     than 54: their grid already pays, and every pixel above the card pushes Continue
     closer to the fold, which is the thing the mobile work exists to protect. */
  :not(.shin-hero-inner) > .shin-survey { padding-top: 24px; }
}

/**
 * First and last name stay SIDE BY SIDE on phones.
 *
 * The prototype stacks them below 768px (`--hero-form-cols: 1fr`). That costs a whole
 * 48px field row plus its gap, and on a 375x667 phone those 60px are the difference
 * between the Continue button being above the fold and below it once the browser's own
 * chrome is accounted for. At 375px each field is still ~137px wide, which holds
 * "First name" comfortably.
 *
 * This is a layout departure from the prototype, not a content one: nothing is hidden
 * and nothing is reworded. See docs/ARCHITECTURE-site-rebuild.md for the measurements
 * and for what is still below the fold at that size.
 */
@media (max-width: 768px) {
  #shinnova-page { --hero-form-cols: 1fr 1fr; }
}

/**
 * "SEE MORE" — the mobile scroll cue.
 *
 * On a phone the survey card is moved to the top of the hero and fills most of the
 * screen, so on a short handset the page reads as if it ENDS at the Continue button:
 * the hero copy that follows is below the fold and there is no seam suggesting
 * anything comes after it. This is the affordance that says the page continues.
 *
 * Injected by shin-site.js, not authored into any page — it has to reach 130 pages,
 * and none of them would carry it. See that file for why it is inserted as a SIBLING
 * of the survey rather than inside it.
 *
 * `display: none` outside the query is the whole desktop story: a display:none element
 * is not a grid item at all, so the two-column hero is untouched, and the button is
 * neither focusable nor announced where it would make no sense.
 */
.shin-scroll-cue { display: none; }

@media (max-width: 900px) {
  .shin-scroll-cue {
    display: inline-flex; align-items: center; gap: 9px;
    /* NO `order` HERE. Inside the survey's column an order of -1 would put the cue
       ABOVE the card, which is the opposite of what it says. */
    margin: 10px 0 0; padding: 8px 14px;
    background: none; border: 0; cursor: pointer;
    font-family: var(--font-body); font-size: 12px; font-weight: 500;
    text-transform: uppercase; letter-spacing: 0.18em;
    color: rgba(255,255,255,0.85);
    -webkit-tap-highlight-color: transparent;
    /* `visibility 0s 0.25s`, NOT `visibility 0.25s`. Transitioning visibility over a
       DURATION animates a property the compositor cannot handle, so the whole thing
       falls back to the main thread every frame — Lighthouse reports it as "avoid
       non-composited animations", and it is main-thread time spent during the LCP
       window on a decoration. A zero-duration change DELAYED until the fade finishes
       gives exactly the same result: visible throughout the fade, then properly gone
       from the tab order and the accessibility tree, with only opacity animating. */
    opacity: 1; transition: opacity 0.25s ease, visibility 0s 0.25s;
  }
  /* Gone the moment they scroll — it has done its job and it is over the hero copy.
     `visibility` and not just `opacity`, so it leaves the tab order and the
     accessibility tree instead of lingering as an invisible target. */
  .shin-scroll-cue.is-gone { opacity: 0; visibility: hidden; }
  /* The companion [hidden] rule every display-setting class in this file needs — the
     UA sheet's `[hidden] { display: none }` is weaker than a class rule. */
  .shin-scroll-cue[hidden] { display: none; }
  .shin-scroll-cue:focus-visible { outline: 2px solid var(--cta-green); outline-offset: 3px; border-radius: 4px; }
  /* Two borders on a rotated box, so the chevron costs no icon, no mask and no glyph.
     build_icons.py emits only the 29 marks the pages actually use and it reads the
     stored HTML — a class injected at runtime would never reach it, and the generated
     block is not hand-editable. */
  .shin-scroll-cue__chev {
    width: 9px; height: 9px; margin-top: -4px;
    border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
    transform: rotate(45deg);
    animation: shin-cue-bob 1.8s ease-in-out infinite;
  }
}

/* translate() inside a rotated frame: (3px,3px) at 45deg resolves to straight down. */
@keyframes shin-cue-bob {
  0%, 100% { transform: rotate(45deg) translate(0, 0); }
  50%      { transform: rotate(45deg) translate(3px, 3px); }
}
@media (prefers-reduced-motion: reduce) {
  .shin-scroll-cue__chev { animation: none; }
}

/* ======================================================= conversion confetti
   Fires once, on the thank-you panel, after a lead is captured. Nothing here runs
   before that: the elements do not exist until shin-site.js builds them, so this
   costs nothing on load and cannot touch LCP — the one moment on this site where an
   animation is free is the moment after the form is done.

   NO LIBRARY. A confetti package is 10-30 KB for something that is twenty divs and a
   keyframe, and the builder plugin's asset firewall would have to allowlist it.

   The card is `overflow: hidden`, so the pieces are clipped to it rather than
   scattering over the page — deliberate: it reads as the card celebrating, and it
   cannot cause a scrollbar or shift anything around it. */
.shin-confetti {
  position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 3;
}
.shin-confetti i {
  position: absolute; top: -12px; width: 8px; height: 14px; opacity: 0;
  animation: shin-confetti-fall var(--dur, 2.4s) var(--delay, 0s) cubic-bezier(.25,.6,.4,1) forwards;
}
@keyframes shin-confetti-fall {
  0%   { opacity: 0; transform: translate3d(0, -20px, 0) rotate(0deg); }
  8%   { opacity: 1; }
  80%  { opacity: 1; }
  100% { opacity: 0; transform: translate3d(var(--dx, 0), var(--fall, 420px), 0) rotate(var(--spin, 540deg)); }
}
/* A celebration nobody asked to see is exactly what this setting is for. The panel
   still appears, it just appears without the pieces. */
@media (prefers-reduced-motion: reduce) {
  .shin-confetti { display: none; }
}

.shin-survey-card {
  position: relative; width: 100%; max-width: 460px; background: #fff;
  border-radius: 20px; box-shadow: 0 18px 44px rgba(0,0,0,0.32); overflow: hidden;
}
.shin-survey-head { padding: 20px 24px; background: var(--charcoal); }
.shin-survey-eyebrow {
  margin: 0 0 6px; font-family: var(--font-body); font-size: 12px; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.3em; color: var(--cta-green);
}
/* TRACKED, because the display face is not. TBJ Norguba sets uppercase very tight —
   at 30px "GET YOUR PROJECT PRICED" runs its R/O/J together and reads as one long
   word. The headings already compensate (--h1-ls is 4.4px at 85px, ~0.05em); this
   line had nothing. 0.04em is 1.2px here, the same order as the h1's, and it costs no
   wrap: the string still fits one line at the card's 460px down to 375px. Kept in step
   with .shin-bar-label, which is the same words in the same face. */
.shin-survey-title {
  margin: 0; font-family: var(--font-display); font-size: 30px; line-height: 1.05;
  text-transform: uppercase; letter-spacing: 0.04em; color: #fff;
}
/* THE OFFER LINE, AND IT COSTS NO VERTICAL SPACE ON PURPOSE.
   It takes the slot the "Free Estimate" eyebrow had rather than adding a band, because
   there is nowhere to add one: at 360x640 there are SEVENTEEN pixels between the
   Continue button and the fold, and section 6b spent real work buying those. A 30px
   banner would hand them straight back. ("Free estimate" moved into the footnote,
   which is below the button and below the fold on the two smallest phones anyway.)

   Tracking is 0.12em where the eyebrow ran 0.3em: at 0.3em this copy wraps to three
   lines in a 272px card. Two lines is the design — `--offer-lh` keeps the pair tight —
   and the whole line is measured below to confirm it never becomes three. */
.shin-survey-offer {
  margin: 0; font-family: var(--font-display); font-size: 26px; line-height: 1.08;
  text-transform: uppercase; letter-spacing: 0.04em; text-wrap: balance;
}
/* TWO SLOTS, NOT ONE ELEMENT WITH A <span> INSIDE IT. `data-edit` replaces an
   element's INNER CONTENT, so a nested span would be wiped the first time anyone
   edited this line in the visual editor — and it would take the two-colour treatment
   with it, silently, months later. A slot per colour keeps both halves editable and
   keeps the styling out of the copy. */
.shin-survey-offer__when { color: #fff; }
.shin-survey-offer__what { color: var(--cta-green); }
/* Short phones have the least room and the same words, so the tracking gives way
   before the type size does — it is the cheaper of the two and reads the same. */
/* 20px ON A SHORT PHONE, AND THAT IS A LINE COUNT, NOT A PREFERENCE. The display face
   is far more compact than Poppins: measured on the card, this copy sets on ONE line at
   20px down to a 360px viewport and wraps to two from 22px up. Two lines cost 26px of
   the headroom above the Continue button, and a 360x640 has the least of it. Big where
   there is room, single-line where there is not. */
@media (max-width: 900px) and (max-height: 700px) {
  .shin-survey-offer { font-size: 20px; }
}

.shin-survey-body { padding: 22px 24px 26px; }
.shin-progress { display: flex; align-items: center; gap: 12px; margin-bottom: 18px; }
/* The companion [hidden] rule, which every class in this file that sets `display`
   and is toggled from JS needs. Without it `progressRow.hidden = true` is inert —
   the UA sheet's `[hidden] { display: none }` is weaker than any class rule — and
   the progress bar sat above the confirmation after a successful submit. */
.shin-progress[hidden] { display: none; }
.shin-progress-track { flex: 1 1 auto; height: 6px; border-radius: 6px; background: rgba(45,45,45,0.12); overflow: hidden; }
.shin-progress-fill { height: 100%; border-radius: 6px; background: var(--accent); transition: width 0.3s ease; width: 50%; }
.shin-progress-label {
  flex: 0 0 auto; font-family: var(--font-body); font-size: 12px; font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--body);
}
.shin-step-hint { margin: -8px 0 14px; font-family: var(--font-body); font-size: 13px; font-weight: 300; color: var(--body); }
.shin-survey form { display: flex; flex-direction: column; gap: 12px; }
/**
 * THE STEP IS NOT A FLEX BOX AT RUNTIME, AND ITS `gap` WAS DEAD.
 *
 * funnel-engine.js `showStep()` writes `el.style.display = 'block'` on the active step
 * (and `'none'` on the rest). An inline declaration beats any class, so this container
 * was block-flow from the moment the engine ran — and `gap` does nothing in block
 * flow. The four fields rendered EDGE TO EDGE, 0px apart, with only their 1px borders
 * and 14px corner radii suggesting a seam. That is the "fields aren't properly sized"
 * the owner reported (2026-09-14), and it was never a taste call: the stylesheet asked
 * for 12px and got none of it.
 *
 * So state `block` — what actually renders — and space the children with margins,
 * which work the same either way. Do NOT put the gap back and do NOT reach for
 * `!important` to force flex: the engine hides an inactive step with an inline
 * `display: none`, and an `!important` class here would beat that and show every step
 * at once.
 *
 * Declaring `block` also removes a real flash. The class said `flex`, so between first
 * paint and the engine's first `showStep()` the submit button stretched full width and
 * then snapped to shrink-wrapped. Now both paints agree.
 *
 * `.shin-survey` prefixes these to clear `.shin-btn-green` and `.shin-consent`, which
 * set their own margin-top at the same specificity and are declared later in this file
 * — without it the button would keep 4px and lose its separation from the last field.
 */
.shin-step { display: block; }
.shin-step[hidden] { display: none; }
.shin-survey .shin-step > * + * { margin-top: 16px; }
/* The CTA gets the field rhythm plus the 4px .shin-btn-green already asked for. */
.shin-survey .shin-step > .shin-btn-green { margin-top: 20px; }
/* Consent hugs the button it is about, and is not part of the field rhythm. */
.shin-survey .shin-step > .shin-consent { margin-top: 4px; }
.shin-name-row { display: grid; grid-template-columns: var(--hero-form-cols); gap: 12px; }
.shin-survey input {
  width: 100%; min-height: 48px; padding: 12px 16px; border: 1px solid #e0e0e0;
  border-radius: 14px; font-family: var(--font-body); font-size: 15px;
  color: var(--charcoal); background: #fff;
}
.shin-survey input:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(9,156,249,0.25);
}
.shin-btn-green {
  min-height: 52px; margin-top: 4px; padding: 14px 32px; border-radius: 50px;
  background: var(--cta-green); border: 1px solid var(--cta-green-bd);
  box-shadow: 4px 4px 7px 0px rgba(51,51,51,0.28); color: rgb(51,51,51);
  font-family: var(--font-body); font-size: 17px; font-weight: 500; cursor: pointer;
}
.shin-btn-green:hover { background: var(--cta-green-hv); color: #fff; }
.shin-btn-green:disabled { opacity: 0.55; cursor: default; }
.shin-btn-green:disabled:hover { background: var(--cta-green); color: rgb(51,51,51); }
/* TCPA consent appears on the first keystroke in any step-1 field, not before. */
.shin-consent { margin: 2px 0 0; font-family: var(--font-body); font-size: 11px; font-weight: 300; line-height: 1.5; color: #999; }
.shin-consent[hidden] { display: none; }
.shin-consent a { color: var(--accent); }
.shin-tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.shin-tile {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; min-height: 88px; padding: 12px 6px; border-radius: 16px; cursor: pointer;
  font-family: var(--font-body); font-size: 13px; font-weight: 500;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  background: #fff; border: 2px solid #e0e0e0; color: var(--charcoal);
}
.shin-tile:hover { transform: translateY(-2px); }
.shin-tile i { font-size: 22px; }
.shin-tile[aria-pressed="true"] { box-shadow: 0 6px 16px rgba(51,51,51,0.16); }
.shin-tile[data-product="windows"][aria-pressed="true"] { background: #099cf9; border-color: #099cf9; color: #06263f; }
.shin-tile[data-product="doors"][aria-pressed="true"]   { background: #ff1042; border-color: #ff1042; color: #fff; }
.shin-tile[data-product="siding"][aria-pressed="true"]  { background: #00ff01; border-color: #00ff01; color: #0b2b0b; }
.shin-tile[data-product="roofing"][aria-pressed="true"] { background: #fec502; border-color: #fec502; color: #3a2c00; }
.shin-tile[data-product="decks"][aria-pressed="true"]   { background: #00f5d4; border-color: #00f5d4; color: #003b34; }
.shin-tile[data-product="unsure"][aria-pressed="true"]  { background: var(--charcoal); border-color: var(--charcoal); color: #fff; }
/* Confirmation replaces the form on a successful lead. It offers BOTH numbers, which
   is deliberate even on a localized page. */
.shin-thanks[hidden] { display: none; }
.shin-thanks-title { margin: 0 0 8px; font-family: var(--font-display); font-size: 26px; line-height: 1.1; text-transform: uppercase; color: var(--charcoal); }
.shin-thanks p { margin: 0; font-family: var(--font-body); font-size: 14px; font-weight: 300; color: var(--body); }
.shin-thanks a { font-weight: 500; }
/* Sits after the form, inside the card. */
.shin-survey-foot { margin: 16px 0 0; font-family: var(--font-body); font-size: 12px; font-weight: 300; color: var(--body-alt); }

/**
 * SHORT PHONES: drop the step hint.
 *
 * Keyed on viewport HEIGHT, not width, because height is the actual constraint. A
 * 390x844 phone has room to spare; a 375x667 or 360x640 does not, and width tells you
 * nothing about which is which.
 *
 * "Tell us how to reach you." is the most expendable thing in the card — every field
 * below it already carries a placeholder saying the same, so the line costs vertical
 * space on exactly the screens that have none to give.
 */
@media (max-width: 900px) and (max-height: 700px) {
  .shin-step-hint { display: none; }
  .shin-survey-body { padding: 16px 20px 20px; }
  .shin-survey-head { padding: 14px 20px; }
  /* 44px is Apple's documented minimum touch target, so this is the floor, not a
     preference — do not shave it further to win a few more pixels. */
  .shin-survey input { min-height: 44px; }
  /* THE FIELD SPACING IS PAID FOR OUT OF THE PROGRESS ROW, at the owner's direction
     (2026-09-14): the fields come first, and the progress row is where the slack is.
     Restoring the field gaps costs 48px of card height, which is most of the margin
     the "form first on mobile" work bought back. 12px between fields instead of 16,
     and 8px under the progress row instead of 12, returns 16px of that — on a 375x667
     phone the Continue button lands at 484px, comfortably above the ~553px Safari
     actually shows, where 500px was getting thin. */
  .shin-survey .shin-step > * + * { margin-top: 12px; }
  .shin-survey .shin-step > .shin-btn-green { margin-top: 16px; }
  .shin-progress { margin-bottom: 8px; }
}

/* ================================================================= sections */
.shin-section { background: #fff; }
.shin-section--ground { background: var(--ground); }
.pad-local-intro   { padding: 80px 0 0; }
.pad-product-value { padding: 80px 0 60px; }
.pad-why-local     { padding: 0 0 70px; }
.pad-features      { padding: 70px 0; }
.pad-process       { padding: 70px 0; }
.pad-reviews       { padding: 0 0 60px; }
.pad-faq           { padding: 70px 0; }
.pad-other         { padding: 70px 0 0; }
.pad-contact       { padding: 70px 0 80px; }

.shin-sec-head { text-align: center; margin-bottom: 40px; }
.shin-sec-head--tight { margin-bottom: 36px; }
.shin-eyebrow {
  margin: 0 0 10px; display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--font-body); font-size: 12px; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.3em; color: var(--ink);
}
.shin-eyebrow::before {
  content: ""; width: 18px; height: 3px; border-radius: 2px;
  background: var(--accent); flex: 0 0 auto;
}
.shin-h2 {
  margin: 0 0 20px; font-family: var(--font-display); font-weight: 400;
  font-size: var(--h2); line-height: 1; letter-spacing: var(--h2-ls);
  text-transform: uppercase; color: var(--heading); text-wrap: pretty;
}
.shin-h3 { margin: 0 0 12px; font-family: var(--font-card); font-weight: 600; font-size: var(--h3); line-height: 1.2; color: var(--charcoal); }
.shin-body { margin: 0; font-family: var(--font-body); font-size: 15px; font-weight: 300; line-height: 1.6; color: var(--body); }
/* On the #f7f7f7 grounds the body grey has to darken: #757575 only passes on white. */
.shin-section--ground .shin-body { color: var(--body-alt); }
.shin-body--stacked { margin: 0 0 16px; }

/* Local Intro: photo and copy, two up. The grid gap is ZERO and the gutter is
   --split-pad on the copy column, so the photo runs to the container edge. */
.shin-split { display: grid; grid-template-columns: var(--cols-2); gap: 0; align-items: center; }
.shin-split-copy { padding-left: var(--split-pad); }
.shin-split img { width: 100%; height: 100%; min-height: 320px; object-fit: cover; border-radius: 12px; display: block; }
/* Contact reuses the two-up shape but with a real gap and stretched cells, so the
   map matches the height of the NAP column beside it. */
.shin-split--gap { gap: 40px; align-items: stretch; }

/* Product Value: one narrow centred column, checkmark bullets left-aligned. */
.shin-center { text-align: center; }
.shin-pv-lede { margin: 0 auto 24px; max-width: 68ch; font-family: var(--font-body); font-size: 15px; font-weight: 300; line-height: 1.6; color: var(--body); }
.shin-checks { list-style: none; margin: 0 auto; padding: 0; display: flex; flex-direction: column; gap: 10px; max-width: 60ch; text-align: left; }
.shin-checks li { display: flex; align-items: flex-start; gap: 12px; font-family: var(--font-body); font-size: 15px; font-weight: 300; line-height: 1.6; color: var(--body); }
.shin-checks i { color: var(--accent); margin-top: 5px; flex: 0 0 auto; }

/* Card grids. */
.shin-grid-3 { display: grid; grid-template-columns: var(--cols-3); gap: 20px; }
.shin-grid-3--stretch { align-items: stretch; }
.shin-grid-3--start { align-items: start; }
.shin-grid-4 { display: grid; grid-template-columns: var(--cols-4); gap: 16px; }
.shin-card { background: #fff; border: 1px solid var(--hairline); border-radius: 12px; padding: 24px; }
/* The accent frame is the card default on this page type, not a variant: both the
   "why it matters" cards and the feature cards carry a 3px accent border. */
.shin-card--outlined { border: 3px solid var(--accent); }
/* The middle card is filled with the accent; its text is the hue-matched ink, not
   the sitewide charcoal, which fails contrast on several accents. */
.shin-card--filled { background: var(--accent); border: 3px solid var(--accent); }
.shin-card--filled .shin-h3, .shin-card--filled .shin-body { color: var(--accent-card-ink); }

/* Our Process: numbered steps. NOT cards — a plain flex column, no border or
   padding, spacing entirely from the gap. */
.shin-process-step { display: flex; flex-direction: column; gap: 12px; }
.shin-process-step .shin-h3 { margin: 0; }
.shin-process-step .shin-body { margin: 0; }
.shin-step-num { font-family: var(--font-display); font-size: 56px; line-height: 1; color: var(--ink); }
.shin-process-foot { margin: 40px 0 0; text-align: center; font-family: var(--font-body); font-size: var(--lede); font-weight: 300; color: var(--charcoal); }

/* Reviews. */
.shin-review { background: #fff; border: 1px solid var(--hairline); border-radius: 12px; padding: 24px; box-shadow: 0 6px 18px rgba(51,51,51,0.06); display: flex; flex-direction: column; gap: 14px; }
.shin-review-who { display: flex; align-items: center; gap: 12px; }
.shin-review-who .shin-google-g { width: 20px; height: 20px; display: block; flex: 0 0 auto; }
.shin-review-name { font-family: var(--font-body); font-size: 15px; font-weight: 600; color: var(--charcoal); }
.shin-stars { display: flex; gap: 3px; color: #fbbc04; font-size: 15px; }
.shin-review p { margin: 0; font-family: var(--font-body); font-size: 15px; font-weight: 300; line-height: 1.6; color: #555; }
.shin-rating { margin: 32px 0 0; text-align: center; font-family: var(--font-body); font-size: 14px; font-weight: 300; color: var(--body); }
.shin-rating strong { font-weight: 600; color: var(--charcoal); }

/* FAQ: native details/summary with the marker hidden and a real <i> plus glyph that
   rotates 45deg when open. A real element rather than ::after content, because the
   icon font's glyph is what the prototype uses and pseudo-element font shorthand is
   easy to get subtly wrong. */
.shin-faq { display: flex; flex-direction: column; gap: 12px; }
.shin-faq details { border: 1px solid rgba(51,51,51,0.18); border-radius: 8px; overflow: hidden; }
.shin-faq summary {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 18px 22px; cursor: pointer; list-style: none;
  background: rgba(51,51,51,0.05);
  font-family: var(--font-body); font-size: 16px; font-weight: 600; color: var(--charcoal);
}
.shin-faq summary::-webkit-details-marker { display: none; }
.shin-faq summary i { transition: transform 0.2s ease; flex: 0 0 auto; color: var(--accent); }
.shin-faq details[open] summary i { transform: rotate(45deg); }
.shin-faq .shin-body { margin: 0; padding: 20px 22px; color: var(--body-alt); }

/* Sibling link row. */
.shin-sibling {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 22px 24px; border-radius: 12px; border: 1px solid var(--hairline);
  background: #fff; font-family: var(--font-body); font-size: 17px; font-weight: 500;
  color: var(--charcoal); transition: box-shadow 0.2s ease, transform 0.2s ease;
}
.shin-sibling:hover { transform: translateY(-3px); box-shadow: 0 12px 24px rgba(51,51,51,0.12); color: var(--charcoal); }
/* One rule per product, and WINDOWS IS EASY TO FORGET. The first converted page was
   a windows page, and a page's sibling row lists the OTHER four products — so the
   windows card is the one card that reference page could not show. Its absence cost
   the card its accent border on all 64 non-windows pages, and it also made the card
   6px wider than the prototype, which was enough to stop "Windows in Maryland
   Heights" wrapping and left that section 27px short. */
.sib-windows { border-left: 6px solid #099cf9; } .sib-windows i { color: #099cf9; }
.sib-doors   { border-left: 6px solid #ff1042; } .sib-doors i   { color: #ff1042; }
.sib-siding  { border-left: 6px solid #00ff01; } .sib-siding i  { color: #00ff01; }
.sib-roofing { border-left: 6px solid #fec502; } .sib-roofing i { color: #fec502; }
.sib-decks   { border-left: 6px solid #00f5d4; } .sib-decks i   { color: #00f5d4; }
/* Two bare paragraphs with their own top margins, not a wrapped block: the second
   sits 12px under the first, and neither has a bottom margin. */
.shin-uplink { margin: 12px 0 0; text-align: center; font-family: var(--font-body); font-size: 15px; font-weight: 300; color: var(--body); }
.shin-uplink--first { margin-top: 28px; }
.shin-uplink a { font-weight: 500; }

/* Contact: NAP card and map. */
.shin-nap { display: flex; flex-direction: column; gap: 14px; padding: 24px; border-radius: 12px; background: var(--ground); }
.shin-nap-name { margin: 0; font-family: var(--font-body); font-size: 16px; font-weight: 600; color: var(--charcoal); }
.shin-nap-row { display: flex; align-items: flex-start; gap: 12px; }
.shin-nap-row i { color: var(--accent); width: 16px; margin-top: 4px; flex: 0 0 auto; }
.shin-nap-row a { font-family: var(--font-body); font-size: 15px; font-weight: 500; color: var(--ink); }
.shin-nap-row a:hover { text-decoration: underline; }
.shin-nap-row span { font-family: var(--font-body); font-size: 15px; color: var(--body-alt); }
.shin-map { min-height: 380px; border-radius: 12px; overflow: hidden; border: 1px solid var(--hairline); }
.shin-map iframe { width: 100%; height: 100%; min-height: 380px; border: 0; display: block; }
/* Two embeds, stacked. O'Fallon only — it is two cities, MO and IL, and the page is
   written around not confusing them. Each half gives up the 380px floor so the pair
   still matches the NAP column's height rather than doubling it. */
.shin-map-stack { min-height: 380px; display: grid; grid-template-rows: 1fr 1fr; gap: 12px; }
.shin-map--half { min-height: 0; }
.shin-map--half iframe { min-height: 184px; }

/* =================================================================== footer */
.shin-footer { background: var(--charcoal); padding: 64px 0 calc(40px + var(--sticky-pad)); }
.shin-footer-top { display: grid; grid-template-columns: var(--cols-4); gap: 48px; align-items: start; margin-bottom: 48px; }
.shin-footer-brand img { width: 180px; height: auto; display: block; }
.shin-footer-brand > a { display: inline-block; margin-bottom: 20px; }
.shin-footer-gbp { margin: 0 0 8px; font-family: var(--font-body); font-size: 14px; font-weight: 500; color: #fff; }
.shin-footer-copy { margin: 0; font-family: var(--font-body); font-size: 13px; font-weight: 300; color: rgba(255,255,255,0.6); }
.shin-footer-col { display: flex; flex-direction: column; gap: 12px; }
.shin-footer-h { margin: 0 0 4px; font-family: var(--font-body); font-size: 12px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.28em; color: var(--accent); }
.shin-footer-col a { font-family: var(--font-body); font-size: 14px; color: rgba(255,255,255,0.85); }
.shin-footer-col a:hover { color: var(--accent); }
/* A standalone 1px rule with its own bottom margin, not a border on the offices
   grid: the measured gap between the two blocks is 48 above and 40 below the rule. */
.shin-footer-rule { height: 1px; background: rgba(255,255,255,0.12); margin-bottom: 40px; }
/* Both offices appear on every page in every tier. That is deliberate, not a leak. */
.shin-offices { display: grid; grid-template-columns: var(--cols-2); gap: 48px; }
.shin-office > p { margin: 0 0 18px; font-family: var(--font-body); font-size: 15px; font-weight: 600; color: #fff; }
.shin-office-rows { display: flex; flex-direction: column; gap: 12px; }
.shin-office-row { display: flex; align-items: flex-start; gap: 12px; }
.shin-office-row i { color: var(--accent); width: 16px; margin-top: 4px; flex: 0 0 auto; }
.shin-office-row a { font-family: var(--font-body); font-size: 14px; color: rgba(255,255,255,0.85); }
.shin-office-row a:hover { color: var(--accent); }
.shin-office-row span { font-family: var(--font-body); font-size: 14px; color: rgba(255,255,255,0.7); }

/* ====================================================== sticky mobile bar */
/* The only always-visible CTA below 901px. Carries ONE metro number on a localized
   page; the non-localized pages carry both. */
.shin-sticky {
  display: var(--sticky-bar); position: fixed; left: 0; right: 0; bottom: 0; z-index: 70;
  grid-template-columns: 1fr 1fr; gap: 10px; padding: 10px;
  background: var(--charcoal); border-top: 1px solid rgba(255,255,255,0.12);
}
.shin-sticky a {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 48px; border-radius: 50px; font-family: var(--font-body);
  font-size: 15px; font-weight: 500;
}
.shin-sticky-call { background: #099ffe; border: 1px solid #0093f2; color: #fff; }
.shin-sticky-quote { background: var(--cta-green); border: 1px solid var(--cta-green-bd); color: rgb(51,51,51); }

/* ==================================== location and hub pages (not products)
   Every value below is MEASURED from the Claude Design prototypes at 1440px with
   the real TBJ face loaded, the same rule as the rest of this file: match the
   prototype, and a nicer number is a regression.

   These sections appear only on the pages named for a PLACE (the two metro hubs and
   the city pages). The product pages use none of them. Two sections on those pages —
   Service Cards and Get Inspired — are byte-identical across all nine and so are
   markup constants in render_location.py rather than data; Customer Reviews is
   identical too but stays data, because it is real published review text.

   THE HEADINGS ARE NOT THE SHARED .shin-h2. Four of these sections restyle it, and
   two of them make it BOLD. The shared rule is weight 400 with `margin: 0 0 20px`,
   which is right on the product pages and right for Cities We Serve and Contact
   here; the four overrides below are the prototype, not drift. */

/* --- Services Across <Place>: photo left, copy right.
   TOP-aligned, not centred: the copy column runs roughly twice the photo's height,
   and centring would leave the photo floating in the middle of the row. */
.pad-services-across { padding: 70px 0 0; }
.pad-services-across .shin-h2 { margin: 10px 0 0; }
.shin-split--top { align-items: start; }
/* This photo keeps its natural aspect instead of filling the cell, which is why the
   shared `.shin-split img` cover/min-height rule is undone here. */
.shin-split--top img { height: auto; min-height: 0; object-fit: contain; }
/* 16px is the DEFAULT and 20px is the exception, the same shape as .shin-uplink.
   An adjacent-sibling rule was the obvious way to write this and is wrong on the
   St. Louis pages: the <details> sits between the second and third paragraphs, so
   the third is nobody's next sibling and would silently take the first paragraph's
   20px. A class on the first one cannot be broken by what gets inserted after it. */
.shin-loc-body {
  margin: 16px 0 0; font-family: var(--font-body); font-size: 15px; font-weight: 300;
  line-height: 1.6; color: var(--heading); text-align: justify;
}
.shin-loc-body--first { margin-top: 20px; }
.shin-loc-body strong { font-weight: 700; }
.shin-loc-sub {
  margin: 28px 0 0; font-family: var(--font-display); font-size: var(--h3);
  font-weight: 400; line-height: 1.2; color: var(--heading);
}
.shin-loc-list {
  display: flex; flex-direction: column; gap: 6px; margin: 16px 0 28px;
  padding-left: 22px; font-family: var(--font-body); font-size: 15px;
  font-weight: 300; line-height: 1.8; color: var(--heading);
}

/* --- "Serving <City> Neighborhoods & Nearby Communities": a real <details>, closed
   on load, no JS. ST. LOUIS CITY PAGES ONLY — all seven have it, neither hub and no
   Kansas City page does.

   Deliberately NOT the FAQ's details styling, which is a different size at every
   value: 8px radius against 4px, an 18px/22px summary against 16px/20px, and a 5%
   ground against 12%. Reusing .shin-faq here would be four silent divergences. */
.shin-loc-nb {
  margin: 20px 0 0; border: 1px solid rgba(51,51,51,0.2); border-radius: 4px;
  overflow: hidden;
}
.shin-loc-nb summary {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 16px 20px; cursor: pointer; list-style: none;
  background: rgba(51,51,51,0.12);
  font-family: var(--font-body); font-size: 15px; font-weight: 600; color: var(--charcoal);
}
.shin-loc-nb summary::-webkit-details-marker { display: none; }
.shin-loc-nb summary i { transition: transform 0.2s ease; flex: 0 0 auto; }
.shin-loc-nb[open] summary i { transform: rotate(45deg); }
/* The body is a flex column with a gap, so its children carry NO margins of their
   own — which is why .shin-loc-body and .shin-loc-list are both reset here. */
.shin-loc-nb-body { padding: 20px; display: flex; flex-direction: column; gap: 14px; }
.shin-loc-nb-body .shin-loc-body { margin: 0; }
.shin-loc-nb-body .shin-loc-list { margin: 0; line-height: 1.6; }

/* --- High-Performance Windows: copy left, photo right, columns centred.
   Note the copy is --body here and --heading in the section above, and the heading is
   BOLD here and regular there. That is the prototype, not an oversight. */
.pad-hp-windows { padding: 80px 0; }
.pad-hp-windows .shin-h2 { margin: 0; font-weight: 700; }
/* As .shin-loc-body: 16px default, 20px on the first. Here it is the bullet list
   that breaks the adjacency chain rather than a disclosure. */
.shin-hp-body {
  margin: 16px 0 0; font-family: var(--font-body); font-size: 15px; font-weight: 300;
  line-height: 1.6; color: var(--body); text-align: justify;
}
.shin-hp-body--first { margin-top: 20px; }
.shin-hp-list {
  display: flex; flex-direction: column; gap: 6px; margin: 12px 0 0;
  padding-left: 22px; font-family: var(--font-body); font-size: 15px;
  font-weight: 300; line-height: 1.6; color: var(--body);
}
/* The second column holds the photo rather than copy, but wants the same gutter. */
.shin-split-pad { padding-left: var(--split-pad); }

/* --- Service Cards: four accent-filled cards, one per non-windows product.
   THE COLOURS BELOW ARE WRONG, AND KNOWINGLY SO. They reproduce the prototypes,
   which apply the brand palette POSITIONALLY (blue, red, yellow, teal) instead of
   matching each card to its product, skipping siding's green altogether:

       card      here      should be   (here is actually...)
       Doors     #099cf9   #ff1042     the windows blue
       Roofing   #ff1042   #fec502     the doors red
       Siding    #fec502   #00ff01     the roofing yellow
       Decks     #00ccb1   #00f5d4     nobody's colour

   Confirmed with the owner on 2026-09-11 as a Design miss: product colours are
   meant to be consistent sitewide, and they already are on the product pages'
   .sib-* cards. Design is correcting the prototypes; when the new ones land,
   change these four values to the canonical tokens and re-render.
   See HANDOFF-product-colors.md in the shinnova-site-source repo. */
.pad-service-cards { padding: 0 0 20px; }
.shin-svc-grid { display: grid; grid-template-columns: var(--cols-4); gap: 20px; align-items: stretch; }
.shin-svc-card {
  padding: 20px; border-radius: 12px; color: #0d0d0d;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.shin-svc-card:hover { transform: translateY(-4px); box-shadow: 0 12px 24px rgba(51,51,51,0.18); }
.shin-svc-card h3 {
  margin: 0 0 12px; font-family: var(--font-card); font-size: var(--h3);
  font-weight: 600; line-height: 1.2; color: #0d0d0d; text-align: center;
}
.shin-svc-card p {
  margin: 0 0 12px; font-family: var(--font-body); font-size: 15px;
  font-weight: 300; line-height: 1.6; color: #0d0d0d;
}
.shin-svc-card p:last-child { margin-bottom: 0; }
.shin-svc-card ul {
  display: flex; flex-direction: column; gap: 4px; margin: 0 0 12px;
  padding-left: 22px; font-family: var(--font-body); font-size: 15px;
  font-weight: 300; line-height: 1.6; color: #0d0d0d;
}
.svc-doors   { background: #099cf9; }
.svc-roofing { background: #ff1042; }
.svc-siding  { background: #fec502; }
.svc-decks   { background: #00ccb1; }

/* --- Cities We Serve: the hub-only community list.
   REDESIGNED 2026-09-11. This was a grid of cards naming the locations that have their
   own page; it is now the full approved community list for that side of the business —
   31 entries on Kansas City, 78 on St. Louis — because the metro hubs are the CATCHALL
   tier for every place without a micro-site of its own.

   The links are styled IDENTICALLY to the plain entries, which looks like an oversight
   and is not: it is so that no location is singled out at metro level. Do not give
   them the site link colour. Hover is the only tell. */
.pad-cities { padding: 70px 0 0; }
.pad-cities .shin-h2 { margin: 0 0 16px; }
.shin-cities-lede {
  margin: 0 auto; max-width: 68ch; font-family: var(--font-body); font-size: 15px;
  font-weight: 300; line-height: 1.6; color: var(--body);
}
/* Columns rather than a grid: the list flows down each column and balances itself, so
   a 78-entry list does not need a row count worked out per metro. */
.shin-city-list {
  margin: 0; padding: 0; list-style: none;
  columns: var(--city-cols, 4); column-gap: 32px; display: block;
}
.shin-city-list li {
  font-family: var(--font-body); font-size: 15px; font-weight: 300;
  line-height: 1.9; color: var(--body-alt);
}
.shin-city-list a { color: var(--body-alt); font-weight: 300; }
.shin-city-list a:hover { color: var(--charcoal); text-decoration: none; }
.shin-cities-foot {
  margin: 28px 0 0; text-align: center; font-family: var(--font-body);
  font-size: 15px; font-weight: 300; color: var(--body);
}
.shin-cities-foot a { font-weight: 500; }

/* Inline copy links are MEDIUM against the surrounding 300. Not cosmetic: the extra
   width wraps Olathe's contact paragraph a line earlier at 1200px, which is 24px of
   section height and nothing else on the page to explain it. */
.shin-loc-body a,
.shin-hp-body a,
.pad-loc-contact .shin-body a { font-weight: 500; }

/* --- Service Area & Contact. Same two-up as the product pages', but it is the LAST
   white section before the photo band rather than the last section on the page, so
   it carries no bottom padding of its own. */
.pad-loc-contact { padding: 70px 0 0; }

/* --- Get a Free Estimate: full-bleed photo behind a heavy scrim.
   The photo is a per-page CSS background, set in the page's own <style>. */
.pad-free-estimate {
  position: relative; margin-top: 60px;
  background-size: cover; background-position: center; background-repeat: no-repeat;
  background-attachment: fixed;
}
.shin-fe-scrim { background: rgba(46,46,46,0.83); }
.shin-fe-wrap {
  position: relative; z-index: 2; max-width: 1500px; margin: 0 auto;
  padding: 60px 20px 40px;
}
.shin-fe-inner { padding: 80px 0 50px; text-align: center; }
.shin-fe-inner .shin-h2 {
  margin: 0 0 10px; color: #fff; text-shadow: 4px 2px 7px rgba(51,51,51,0.22);
}
/* max-width is load-bearing: 90ch is roughly 1190px against the wrap's 1460px, so
   without it every line here wraps in a different place. */
.shin-fe-body {
  margin: 0 auto; max-width: 90ch; font-family: var(--font-body);
  font-size: var(--lede); font-weight: 300; line-height: 1.5; color: #fff;
  text-shadow: 4px 4px 7px rgba(0,86,199,0.25);
}
.shin-fe-body + .shin-fe-body { margin-top: 24px; }
.shin-fe-body strong { font-weight: 700; }
/* The paragraph AFTER the CTA — Chesterfield only. Six more pixels of air than the
   body paragraphs get, and its link is the CTA green underlined rather than the site
   blue, because it sits on the dark photo band where the blue does not pass. */
/* `.shin-fe-body + .shin-fe-tail`, not a bare `.shin-fe-tail`: the tail carries both
   classes, so the adjacent-sibling rule above outranks a single class and the 30px
   silently lost to 24px. Six pixels, and the only symptom was six pixels. */
.shin-fe-body + .shin-fe-tail { margin-top: 30px; }
.shin-fe-tail a { color: var(--cta-green); text-decoration: underline; }

/* --- Customer Reviews, location variant.
   The same six reviews as the product pages in a different frame: a TBJ display
   eyebrow instead of the Poppins-with-rule one, a bold and wider-spaced H2, a
   "Verified Google review" label beside the stars, and the section's padding on the
   WRAP rather than on the section. */
.pad-loc-reviews { padding: 0; background: #fff; }
.shin-loc-reviews-wrap { padding: 80px 20px 50px; }
.pad-loc-reviews .shin-h2 {
  margin: 10px 0 50px; font-weight: 700; text-align: center;
}
.shin-review-verified {
  margin-left: 6px; font-family: var(--font-body); font-size: 13px;
  font-weight: 300; color: #999;
}

/* --- Get Inspired: a four-column gallery whose first tile is a 2x2 hero. */
.pad-get-inspired { padding: 0 0 80px; }
/* Shared with Customer Reviews above, which uses the same display eyebrow. */
.shin-loc-eyebrow {
  margin: 0; font-family: var(--font-display); font-size: var(--h3); font-weight: 700;
  line-height: 1.2; color: var(--charcoal); text-align: center;
}
.shin-gal-head { margin: 10px 0; font-weight: 700; text-align: center; }
.shin-gal-lede {
  margin: 0 0 50px; font-family: var(--font-body); font-size: 15px; font-weight: 300;
  line-height: 1.6; color: #444; text-align: center;
}
.shin-gallery {
  display: grid; grid-template-columns: var(--gal-cols);
  grid-template-rows: var(--gal-rows); gap: 20px;
}
/* aspect-ratio, not a height: the tiles are square and the 2x2 hero is square too,
   so the row height comes from the tiles rather than from the grid. Without it the
   rows collapse to the images' own heights and the hero stops being square. */
.shin-gallery a { display: block; overflow: hidden; border-radius: 12px; aspect-ratio: 1 / 1; }
.shin-gallery a:first-child { grid-column: span 2; grid-row: span 2; }
.shin-gallery img { display: block; width: 100%; height: 100%; object-fit: cover; border-radius: 12px; }

/* THE 2x2 HERO TILE KEEPS ITS SPAN AT EVERY WIDTH. Dropping it back to a normal cell
   below 900px is the obvious-looking thing to do — it "consumes the whole row" — and
   the prototype does not do it: at two columns the tile spans both and stands 860px
   tall, which is 433px of section height. Nor does .shin-split-pad need zeroing here;
   --split-pad is already 0px below 900. */

/* ===================================================== site pages (13)
   THE SITE PAGES BREAK AT A DIFFERENT WIDTH, and it is one token pair. The location
   and product prototypes collapse --cols-2 and --cols-3 to a single column at 900px;
   the site prototypes hold them to 768px. Same property, same page furniture, two
   different breakpoints, and nothing about the markup says so — it cost 215px on the
   footer's two office blocks, which stacked here and stayed side by side there.

   Declared on the folder rather than on #shinnova-page so it cascades to the whole
   page and cannot be undone by the width rules further up this file. */
/* The column and hero breakpoints are NOT here. The twelve site pages do not share
   a table — at least four profiles among them — so each page carries its own, emitted
   into its <style> by carry_tokens() in render_site.py. A profile picked here would
   fit some of them and silently mis-stack the rest.

   What .shin-folder--site still carries is the chrome that IS uniform across the
   family: the logo padding below. */

/* The logo sits 6px higher on a site page that is NOT a product hub: 8px of top
   padding against the 14px used everywhere else. The split is exact but needs both
   classes to express — the five PRODUCT HUBS are site pages and use 14, while Olathe
   and the metro hubs are flat and also use 14. Only the pages that are both --site
   and --flat take 8.

   Only visible below 1200px, where the nav hides and the logo becomes the tallest
   thing in the header row and therefore sets its height. */
.shin-folder--site.shin-folder--flat .shin-logo { padding-top: 8px; }

/* The sticky bar carries THREE buttons on a site page — call Kansas City, call
   St. Louis, get a quote — against two on a location page, which belongs to one
   office. Three children in the two-column grid wrapped to a second row. */
.shin-sticky--3up { grid-template-columns: 1fr 1fr 1.1fr; }

/* ============================================= before / after comparison
   PORTED FROM THE LANDERS, where this has been live on production since the siding
   and windows localized landers shipped. Same component, same structure, same
   behaviour — only the prefix changes, from `sn-ba` to `shin-ba`, to match this
   stylesheet. The prototypes build the identical nesting, so converting one is a
   class swap; see replace_sliders() in render_site.py.

   The lander copy carries `width/height: 100% !important` on the images to out-weigh
   Beaver Builder's `img { height: auto }`. That is NOT needed here: the asset firewall
   dequeues the theme stylesheet on a raw page, and this file's only base rule is
   `max-width: 100%`. Reinstate it if a page ever renders with the divider hanging
   below the photo — that was the symptom. */
.shin-ba { position: relative; width: 100%; overflow: hidden; }
/* No aspect-ratio here on purpose: it genuinely differs per page — 16/9 on Siding,
   1/1 on Windows, 4/3 on Doors — and each page keeps its own inline. A default here
   would be overridden on every page that uses it and misleading on the one that
   does not. */
.shin-ba__img { position: relative; width: 100%; overflow: hidden; }
.shin-ba__img > img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* The "before" photo, revealed by clipping from the right. 50% is the rest state and
   the JS moves it; a page with the script blocked still shows a usable half-and-half
   rather than one photo on top of the other. */
.shin-ba__after {
  position: absolute; top: 0; left: 0; width: 100%; height: 100%;
  overflow: hidden; z-index: 2; clip-path: inset(0 50% 0 0);
}
.shin-ba__after img { width: 100%; height: 100%; object-fit: cover; object-position: center; display: block; }
.shin-ba__line {
  position: absolute; top: 0; left: 50%; width: 4px; height: 100%; background: #fff;
  z-index: 3; transform: translateX(-50%); box-shadow: 0 0 10px rgba(0,0,0,0.25);
}
.shin-ba__knob {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 64px; height: 64px; background: #fff; border-radius: 50%; z-index: 4;
  display: flex; align-items: center; justify-content: center;
  font-size: 28px; font-weight: 700; color: #111;
  box-shadow: 0 8px 24px rgba(0,0,0,0.2); pointer-events: none;
}
/* A real range input, transparent and covering the whole photo: it is the drag
   surface AND the keyboard control, so the comparison is operable without a mouse. */
.shin-ba__range {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; cursor: ew-resize; z-index: 5; margin: 0;
}

/* ======================================================== legal pages
   Privacy Policy and Terms of Use. Long-form prose, no survey form, and a flat
   charcoal hero band instead of a photo — the only two pages in the site with that
   shape. Every value is measured from the prototypes.

   These carry a class rather than staying inline because of VOLUME, not breadth:
   only two pages use them, but between them that is 67 identical paragraphs and 27
   identical headings. */
.pad-legal-hero { position: relative; background: var(--charcoal); }
.shin-legal-hero-wrap {
  position: relative; z-index: 2; max-width: 1040px; margin: 0 auto;
  padding: 72px 20px 64px;
}
/* The shared .shin-h1 carries a text-shadow for legibility over a hero PHOTO. There
   is no photo here, just a flat band, and the shadow only muddies the edge. */
.shin-h1--flat { text-shadow: none; }

.pad-legal-body { padding: 64px 0 80px; }
.shin-legal-wrap { max-width: 900px; margin: 0 auto; padding: 0 20px; }
/* Note 1.7, not the 1.6 the rest of the site uses: long legal prose is read in a
   narrower column and wants the extra leading. That is the prototype. */
.shin-legal-p {
  margin: 0 0 18px; font-family: var(--font-body); font-size: 15px;
  font-weight: 300; line-height: 1.7; color: #55585c;
}
/* The opening paragraph of each document, set a step heavier and darker. */
.shin-legal-lead {
  margin: 0 0 18px; font-family: var(--font-body); font-size: 15px;
  font-weight: 500; line-height: 1.7; color: var(--charcoal);
}
.shin-legal-h2 {
  margin: 44px 0 18px; font-family: var(--font-display); font-size: var(--h3);
  font-weight: 400; line-height: 1.15; letter-spacing: var(--h2-ls);
  text-transform: uppercase; color: var(--heading);
}
.shin-legal-h3 {
  margin: 28px 0 12px; font-family: var(--font-card); font-size: 18px;
  font-weight: 600; line-height: 1.3; color: var(--charcoal);
}


/* ==================================== site pages: the shared vocabulary
   Generated from a census of the twelve converted site pages, then reviewed. A shape
   earns a class here on VOLUME across pages, not on looking tidy: these 24 cover 574
   of the 1371 styled elements on those pages, and everything else stays inline, which
   is the agreed trade (owner, 2026-09-11).

   Three of the 24 are not here because they already exist and are reused as-is:
   .shin-wrap, .shin-nap-row and .shin-split-pad. Matching was done by comparing exact
   declaration sets against this file rather than by eye — a shape that merely looks
   like an existing class is not the same class.

   NOTE ON NAMING: the `-flush`, `-justify` and `-bold` variants are COMPLETE rule
   sets, not BEM modifiers. Each stands alone; applying two of them together is a
   mistake, which is why none uses `--`. */
/* GREEN, AND DELIBERATELY NOT WHAT THE DESIGN PACKAGE SAYS (owner, 2026-09-11).
   The package specifies `rgba(255,255,255,0.12)` with a white label — a glass pill over
   the hero video. Faithful, but nearly invisible against moving footage, and the Beaver
   Builder site it replaces used solid green. So these now wear the site's own CTA green,
   the same treatment as `.shin-btn-green` and the sticky bar's Free Quote button.

   The label is rgb(51,51,51), NOT white. BB used white on #00ff01, which is about a
   1.4:1 contrast ratio — unreadable. Dark on green is the same green and legible, and it
   is already the convention everywhere else on the site.

   This is the one place the site knowingly diverges from the package, so the fidelity
   harness will never justify it and a future pass must not "restore" the glass pill. */
.shin-hero-cta { align-items: center; background: var(--cta-green); border: 1px solid var(--cta-green-bd); border-radius: 40px; box-shadow: 4px 4px 7px 0px rgba(51,51,51,0.28); color: rgb(51,51,51); display: inline-flex; font-family: var(--font-body); font-size: 16px; font-weight: 500; gap: 10px; min-height: 48px; padding: 13px 28px; text-decoration: none; }
.shin-hero-cta:hover { background: var(--cta-green-hv); border-color: var(--cta-green-hv); color: #fff; }
.shin-icon-accent { color: #099cf9; margin-top: 4px; width: 16px; }
.shin-link-md { font-weight: 500; }
.shin-s15 { font-family: var(--font-body); font-size: 15px; }
.shin-scol-10 { display: flex; flex-direction: column; gap: 10px; }
.shin-sfaq { border: 1px solid rgba(51,51,51,0.2); border-radius: 4px; overflow: hidden; }
.shin-sfaq__body { color: var(--charcoal); font-family: var(--font-body); font-size: 15px; font-weight: 300; line-height: 1.6; padding: 20px 50px 20px 24px; }
.shin-sfaq__icon { flex: 0 0 auto; transition: transform 0.2s ease; }
.shin-sfaq__summary { align-items: center; background: rgba(51,51,51,0.12); color: var(--charcoal); display: flex; font-family: var(--font-body); font-size: 16px; font-weight: 500; gap: 20px; justify-content: space-between; padding: 18px 24px; }
.shin-sgrid-2 { align-items: center; display: grid; gap: 56px; grid-template-columns: var(--cols-2); margin: 0 auto; max-width: 1500px; padding: 0 20px; }
.shin-sh2 { color: var(--heading); font-family: var(--font-display); font-size: var(--h2); font-weight: 400; letter-spacing: var(--h2-ls); line-height: 1; margin: 10px 0 24px; text-transform: uppercase; }
.shin-sh2-bold { color: var(--heading); font-family: var(--font-display); font-size: var(--h2); font-weight: 700; letter-spacing: var(--h2-ls); line-height: 1; margin: 10px 0 0; text-transform: uppercase; text-wrap: pretty; }
.shin-sh3 { color: #333; font-family: var(--font-display); font-size: var(--h3); font-weight: 400; line-height: 1.1; margin: 0 0 12px; }
.shin-simg { border-radius: 12px; display: block; height: auto; width: 100%; }
.shin-simg--cover { display: block; height: 100%; object-fit: cover; width: 100%; }
.shin-sp { color: var(--body); font-family: var(--font-body); font-size: 15px; font-weight: 300; line-height: 1.6; margin: 0 0 16px; }
.shin-sp-flush { color: var(--body); font-family: var(--font-body); font-size: 15px; font-weight: 300; line-height: 1.6; margin: 0; }
.shin-sp-justify { color: var(--body); font-family: var(--font-body); font-size: 15px; font-weight: 300; line-height: 1.6; margin: 0; text-align: justify; }
.shin-sp-justify-top { color: var(--body); font-family: var(--font-body); font-size: 15px; font-weight: 300; line-height: 1.6; margin: 20px 0 0; text-align: justify; }
.shin-srow { align-items: center; display: flex; gap: 12px; }
.shin-strong { color: var(--charcoal); font-weight: 600; }

/* The gallery grid: 105 photos, so these two shapes are 210 of that page's elements
   on their own. One page rather than several, but by volume it is the single biggest
   duplication in the site set — the same test that earned the legal prose its classes. */
.shin-gal-figure {
  margin: 0; border-radius: 12px; overflow: hidden; background: var(--ground);
  border: 1px solid rgba(51,51,51,0.1);
}
.shin-gal-figure-img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }

/* ================================================= mobile hero stills
   THE HERO VIDEO IS 8.28 MB AND MOBILE SHOULD NOT PAY FOR IT. Measured by PageSpeed on
   a Moto G Power over Slow 4G: LCP 7.1s and a 10,758 KiB payload, essentially all of it
   this one file. The video element is 375x911 there — taller than the viewport — so it
   is also the largest paint, which is what made LCP so bad.

   Below 768px the video is replaced by three stills lifted from that same footage,
   cross-fading with a slow Ken Burns move: 198 KB for all three against 8,478 KB of
   video, a 97.7% cut, and the hero still moves rather than going flat.

   NO JAVASCRIPT DECIDES THIS, AND THAT IS THE POINT. `display: none` on the video means
   it has no box, an IntersectionObserver never reports it as intersecting, shin-site.js
   therefore never calls play(), and `preload="none"` means not one byte is fetched.
   Widen the window and the element gets a box, the observer fires, and the video plays.
   The bandwidth decision rides entirely on the media query.

   The stills sit BEFORE the video in the DOM so the sibling combinator below can reach
   it; they never overlap, because each is display:none exactly where the other shows. */
.shin-hero-stills { display: none; }

@media (max-width: 768px) {
  .shin-hero-stills {
    display: block; position: absolute; inset: 0; overflow: hidden; z-index: 0;
  }
  .shin-hero-stills ~ video[data-shin-autoplay] { display: none; }

  /* THE LCP ELEMENT DOES NOT ANIMATE UNTIL AFTER THE PAGE HAS LOADED.
     This still is the largest element in the mobile hero — 339,517 px2 against 20,104
     for the next candidate — so it IS the LCP, and an LCP element that is running an
     infinite opacity+transform animation from the first frame is a moving target for
     the measurement. PSI bore that out: with the network identical and fast in both
     (50 ms load delay, 20-60 ms transfer), element render delay came back as 110 ms on
     a 98 and 1,170 ms on a 74, alternating run to run.
     So the base state is a plain, static, fully opaque background — nothing to
     composite, nothing growing, nothing to re-attribute — and shin-site.js adds
     .shin-hero-stills--playing once `load` has fired. The animation then picks up at
     its -0.63s phase, which is opacity 1, so the handover is invisible. */
  .shin-hero-still {
    position: absolute; inset: 0;
    background-size: cover; background-position: center; background-repeat: no-repeat;
    opacity: 0;
  }
  .shin-hero-still:nth-child(1) { opacity: 1; }
  .shin-hero-stills--playing .shin-hero-still {
    animation: shin-hero-still 21s linear infinite;
  }
  /* One keyframe, three transform-origins: the zoom pushes away from a different
     corner each time, so the three moves read as different without three animations. */

  /* THE DELAYS ARE SHIFTED BACK BY 0.63s, AND THAT IS AN LCP FIX, NOT A DESIGN TWEAK.
     The keyframes fade in from opacity 0 to 1 across 3% of a 21s cycle — 630ms — so
     with a delay of 0s the first still, which IS the largest element in the mobile
     hero, was invisible at first paint. Chrome cannot count an invisible element as
     the LCP, so it settled on something smaller and then RE-ATTRIBUTED to the still as
     it faded in. That is why the homepage oscillated between 67 and 96 across runs
     while every other page sat above 90: the measurement was picking a different
     element each time.
     A NEGATIVE delay starts the animation already in progress — still 1 computes to
     the 3% keyframe, opacity 1, on the very first frame. All three shift by the same
     0.63s so the 7s spacing and the crossfade handoff are bit-for-bit what they were;
     only the phase moves. */
  .shin-hero-still:nth-child(1) { animation-delay: -0.63s; transform-origin: 50% 30%; }
  .shin-hero-still:nth-child(2) { animation-delay:  6.37s; transform-origin: 25% 70%; }
  .shin-hero-still:nth-child(3) { animation-delay: 13.37s; transform-origin: 75% 45%; }
}

@keyframes shin-hero-still {
  0%     { opacity: 0; transform: scale(1.02); }
  3%     { opacity: 1; }
  30%    { opacity: 1; }
  33.34% { opacity: 0; transform: scale(1.14); }
  /* Scale returns to its start across the two thirds of the cycle this still is
     invisible for, so the next loop begins from 1.02 with no visible snap. */
  100%   { opacity: 0; transform: scale(1.02); }
}

/* A slow pan is exactly what this setting is for. Hold the first still, still cropped
   and still correct, and animate nothing. */
@media (prefers-reduced-motion: reduce) {
  .shin-hero-still { animation: none; opacity: 0; transform: none; }
  .shin-hero-still:nth-child(1) { opacity: 1; }
}

/* =========================================================== parallax bands
   NOT FROM THE DESIGN PACKAGE. The Beaver Builder homepage this replaces ran its five
   service bands (Windows, Doors, Siding, Roofing, Decks) as `fl-row-bg-parallax`, and
   the owner asked for that back on 2026-09-11 — the prototypes have no equivalent, so
   the geometry harness will never ask for this and nothing else in the file implies it.

   BB implemented it as plain `background-attachment: fixed`, and reverted to `scroll`
   at 768px. Both halves are reproduced, because the second one is not optional: fixed
   backgrounds are janky-to-broken on iOS Safari and Android Chrome, which is where
   most of this site's traffic is.

   Safe to apply as a class because the five sections set background-image, -size,
   -position and -repeat as LONGHANDS inline, never the `background` shorthand — so
   there is no inline background-attachment for this to lose to. A future section that
   uses the shorthand would silently ignore this class.

   Note `cover` sizes a fixed background against the VIEWPORT rather than the element,
   so these bands crop wider than they do without it. That is what the old site did. */
.shin-parallax { background-attachment: fixed; }
@media (max-width: 768px) {
  .shin-parallax { background-attachment: scroll; }
}
@media (prefers-reduced-motion: reduce) {
  .shin-parallax { background-attachment: scroll; }
}

/* ======================================================= homepage offer cards
   NOT FROM THE DESIGN PACKAGE, in the same way .shin-parallax is not — applied by the
   converter from OFFER_CARDS in render_site.py, which IS the specification.

   The prototype lays the five Current Offers out as a bare image with a white heading
   and a white line of body copy under it, no card around any of it. That works in
   Design, where the section's background art is cropped so every caption lands on the
   cyan field. It does not survive the real page: the artwork is `cover` against a
   1500px column, so the top row of captions sits on the white part of it and THREE OF
   THE FIVE OFFERS WERE INVISIBLE — white on white — with the other two low-contrast
   over cyan. Reported by the owner 2026-09-14.

   So the copy gets a ground of its own. Charcoal is the same #2d2d2d the survey head
   and the dark sections already use, and the 2px product border is the same weight and
   the same five colours as .shin-tile, which is the other place on the page where a
   product is a coloured chip. Nothing here depends on the artwork behind it, which is
   the point: the offers stay legible whatever the background crops to.

   Radius 24 against the image's own inline 20 plus 14px of padding — near enough to
   concentric that the frame reads as one shape. */
.shin-offer {
  background: var(--charcoal);
  border: 2px solid #e0e0e0;
  border-radius: 24px;
  padding: 14px 14px 20px;
}
.shin-offer--windows { border-color: #099cf9; }
.shin-offer--doors   { border-color: #ff1042; }
.shin-offer--siding  { border-color: #00ff01; }
.shin-offer--roofing { border-color: #fec502; }
.shin-offer--decks   { border-color: #00f5d4; }

@media (prefers-reduced-motion: reduce) {
  #shinnova-page * { transition: none !important; }
}

/* === GENERATED ICONS — build_icons.py — DO NOT EDIT BY HAND === */
/* Font Awesome Free 5.15.4 glyphs, CC BY 4.0 — https://fontawesome.com/license/free
   Regenerate with page-kit/tools/build_icons.py; do not hand-edit the rules below.

   These are masks, not fonts: the element is painted in `currentColor` and the
   glyph cuts the shape out of it, so an icon still inherits its colour from
   whatever it sits in, exactly as the webfont did. */
/* Scoped to the page wrapper, NOT .shin-folder: the sticky mobile CTA bar is
   appended AFTER the folder closes and its three icons would have been missed.
   :where() keeps the id out of the specificity, so this stays at (0,2,0) and a
   later rule can still size or recolour an icon. */
:where(#shinnova-page) :is(.fas, .fab)[class*="fa-"] {
  display: inline-block; height: 1em; width: 1em;
  background-color: currentColor;
  vertical-align: -0.125em;
  -webkit-mask: var(--shin-icon) no-repeat center / contain;
          mask: var(--shin-icon) no-repeat center / contain;
}
.fa-arrow-right { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath d='M190.5 66.9l22.2-22.2c9.4-9.4 24.6-9.4 33.9 0L441 239c9.4 9.4 9.4 24.6 0 33.9L246.6 467.3c-9.4 9.4-24.6 9.4-33.9 0l-22.2-22.2c-9.5-9.5-9.3-25 .4-34.3L311.4 296H24c-13.3 0-24-10.7-24-24v-32c0-13.3 10.7-24 24-24h287.4L190.9 101.2c-9.8-9.3-10-24.8-.4-34.3z'/%3E%3C/svg%3E"); width: 0.875em; }
.fa-bars { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath d='M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z'/%3E%3C/svg%3E"); width: 0.875em; }
.fa-border-all { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath d='M416 32H32A32 32 0 0 0 0 64v384a32 32 0 0 0 32 32h384a32 32 0 0 0 32-32V64a32 32 0 0 0-32-32zm-32 64v128H256V96zm-192 0v128H64V96zM64 416V288h128v128zm192 0V288h128v128z'/%3E%3C/svg%3E"); width: 0.875em; }
.fa-check { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z'/%3E%3C/svg%3E"); }
.fa-clipboard-list { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Cpath d='M336 64h-80c0-35.3-28.7-64-64-64s-64 28.7-64 64H48C21.5 64 0 85.5 0 112v352c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V112c0-26.5-21.5-48-48-48zM96 424c-13.3 0-24-10.7-24-24s10.7-24 24-24 24 10.7 24 24-10.7 24-24 24zm0-96c-13.3 0-24-10.7-24-24s10.7-24 24-24 24 10.7 24 24-10.7 24-24 24zm0-96c-13.3 0-24-10.7-24-24s10.7-24 24-24 24 10.7 24 24-10.7 24-24 24zm96-192c13.3 0 24 10.7 24 24s-10.7 24-24 24-24-10.7-24-24 10.7-24 24-24zm128 368c0 4.4-3.6 8-8 8H168c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16zm0-96c0 4.4-3.6 8-8 8H168c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16zm0-96c0 4.4-3.6 8-8 8H168c-4.4 0-8-3.6-8-8v-16c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16z'/%3E%3C/svg%3E"); width: 0.75em; }
.fa-clock { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M256,8C119,8,8,119,8,256S119,504,256,504,504,393,504,256,393,8,256,8Zm92.49,313h0l-20,25a16,16,0,0,1-22.49,2.5h0l-67-49.72a40,40,0,0,1-15-31.23V112a16,16,0,0,1,16-16h32a16,16,0,0,1,16,16V256l58,42.5A16,16,0,0,1,348.49,321Z'/%3E%3C/svg%3E"); }
.fa-cloud-showers-heavy { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M183.9 370.1c-7.6-4.4-17.4-1.8-21.8 6l-64 112c-4.4 7.7-1.7 17.5 6 21.8 2.5 1.4 5.2 2.1 7.9 2.1 5.5 0 10.9-2.9 13.9-8.1l64-112c4.4-7.6 1.7-17.4-6-21.8zm96 0c-7.6-4.4-17.4-1.8-21.8 6l-64 112c-4.4 7.7-1.7 17.5 6 21.8 2.5 1.4 5.2 2.1 7.9 2.1 5.5 0 10.9-2.9 13.9-8.1l64-112c4.4-7.6 1.7-17.4-6-21.8zm-192 0c-7.6-4.4-17.4-1.8-21.8 6l-64 112c-4.4 7.7-1.7 17.5 6 21.8 2.5 1.4 5.2 2.1 7.9 2.1 5.5 0 10.9-2.9 13.9-8.1l64-112c4.4-7.6 1.7-17.4-6-21.8zm384 0c-7.6-4.4-17.4-1.8-21.8 6l-64 112c-4.4 7.7-1.7 17.5 6 21.8 2.5 1.4 5.2 2.1 7.9 2.1 5.5 0 10.9-2.9 13.9-8.1l64-112c4.4-7.6 1.7-17.4-6-21.8zm-96 0c-7.6-4.4-17.4-1.8-21.8 6l-64 112c-4.4 7.7-1.7 17.5 6 21.8 2.5 1.4 5.2 2.1 7.9 2.1 5.5 0 10.9-2.9 13.9-8.1l64-112c4.4-7.6 1.7-17.4-6-21.8zM416 128c-.6 0-1.1.2-1.6.2 1.1-5.2 1.6-10.6 1.6-16.2 0-44.2-35.8-80-80-80-24.6 0-46.3 11.3-61 28.8C256.4 24.8 219.3 0 176 0 114.2 0 64 50.1 64 112c0 7.3.8 14.3 2.1 21.2C27.8 145.8 0 181.5 0 224c0 53 43 96 96 96h320c53 0 96-43 96-96s-43-96-96-96z'/%3E%3C/svg%3E"); }
.fa-door-open { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 512'%3E%3Cpath d='M624 448h-80V113.45C544 86.19 522.47 64 496 64H384v64h96v384h144c8.84 0 16-7.16 16-16v-32c0-8.84-7.16-16-16-16zM312.24 1.01l-192 49.74C105.99 54.44 96 67.7 96 82.92V448H16c-8.84 0-16 7.16-16 16v32c0 8.84 7.16 16 16 16h336V33.18c0-21.58-19.56-37.41-39.76-32.17zM264 288c-13.25 0-24-14.33-24-32s10.75-32 24-32 24 14.33 24 32-10.75 32-24 32z'/%3E%3C/svg%3E"); width: 1.25em; }
.fa-drafting-compass { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M457.01 344.42c-25.05 20.33-52.63 37.18-82.54 49.05l54.38 94.19 53.95 23.04c9.81 4.19 20.89-2.21 22.17-12.8l7.02-58.25-54.98-95.23zm42.49-94.56c4.86-7.67 1.89-17.99-6.05-22.39l-28.07-15.57c-7.48-4.15-16.61-1.46-21.26 5.72C403.01 281.15 332.25 320 256 320c-23.93 0-47.23-4.25-69.41-11.53l67.36-116.68c.7.02 1.34.21 2.04.21s1.35-.19 2.04-.21l51.09 88.5c31.23-8.96 59.56-25.75 82.61-48.92l-51.79-89.71C347.39 128.03 352 112.63 352 96c0-53.02-42.98-96-96-96s-96 42.98-96 96c0 16.63 4.61 32.03 12.05 45.66l-68.3 118.31c-12.55-11.61-23.96-24.59-33.68-39-4.79-7.1-13.97-9.62-21.38-5.33l-27.75 16.07c-7.85 4.54-10.63 14.9-5.64 22.47 15.57 23.64 34.69 44.21 55.98 62.02L0 439.66l7.02 58.25c1.28 10.59 12.36 16.99 22.17 12.8l53.95-23.04 70.8-122.63C186.13 377.28 220.62 384 256 384c99.05 0 190.88-51.01 243.5-134.14zM256 64c17.67 0 32 14.33 32 32s-14.33 32-32 32-32-14.33-32-32 14.33-32 32-32z'/%3E%3C/svg%3E"); }
.fa-envelope { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M502.3 190.8c3.9-3.1 9.7-.2 9.7 4.7V400c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V195.6c0-5 5.7-7.8 9.7-4.7 22.4 17.4 52.1 39.5 154.1 113.6 21.1 15.4 56.7 47.8 92.2 47.6 35.7.3 72-32.8 92.3-47.6 102-74.1 131.6-96.3 154-113.7zM256 320c23.2.4 56.6-29.2 73.4-41.4 132.7-96.3 142.8-104.7 173.4-128.7 5.8-4.5 9.2-11.5 9.2-18.9v-19c0-26.5-21.5-48-48-48H48C21.5 64 0 85.5 0 112v19c0 7.4 3.4 14.3 9.2 18.9 30.6 23.9 40.7 32.4 173.4 128.7 16.8 12.2 50.2 41.8 73.4 41.4z'/%3E%3C/svg%3E"); }
.fa-hammer { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath d='M571.31 193.94l-22.63-22.63c-6.25-6.25-16.38-6.25-22.63 0l-11.31 11.31-28.9-28.9c5.63-21.31.36-44.9-16.35-61.61l-45.25-45.25c-62.48-62.48-163.79-62.48-226.28 0l90.51 45.25v18.75c0 16.97 6.74 33.25 18.75 45.25l49.14 49.14c16.71 16.71 40.3 21.98 61.61 16.35l28.9 28.9-11.31 11.31c-6.25 6.25-6.25 16.38 0 22.63l22.63 22.63c6.25 6.25 16.38 6.25 22.63 0l90.51-90.51c6.23-6.24 6.23-16.37-.02-22.62zm-286.72-15.2c-3.7-3.7-6.84-7.79-9.85-11.95L19.64 404.96c-25.57 23.88-26.26 64.19-1.53 88.93s65.05 24.05 88.93-1.53l238.13-255.07c-3.96-2.91-7.9-5.87-11.44-9.41l-49.14-49.14z'/%3E%3C/svg%3E"); width: 1.125em; }
.fa-home { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath d='M280.37 148.26L96 300.11V464a16 16 0 0 0 16 16l112.06-.29a16 16 0 0 0 15.92-16V368a16 16 0 0 1 16-16h64a16 16 0 0 1 16 16v95.64a16 16 0 0 0 16 16.05L464 480a16 16 0 0 0 16-16V300L295.67 148.26a12.19 12.19 0 0 0-15.3 0zM571.6 251.47L488 182.56V44.05a12 12 0 0 0-12-12h-56a12 12 0 0 0-12 12v72.61L318.47 43a48 48 0 0 0-61 0L4.34 251.47a12 12 0 0 0-1.6 16.9l25.5 31A12 12 0 0 0 45.15 301l235.22-193.74a12.19 12.19 0 0 1 15.3 0L530.9 301a12 12 0 0 0 16.9-1.6l25.5-31a12 12 0 0 0-1.7-16.93z'/%3E%3C/svg%3E"); width: 1.125em; }
.fa-hourglass-half { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Cpath d='M360 0H24C10.745 0 0 10.745 0 24v16c0 13.255 10.745 24 24 24 0 90.965 51.016 167.734 120.842 192C75.016 280.266 24 357.035 24 448c-13.255 0-24 10.745-24 24v16c0 13.255 10.745 24 24 24h336c13.255 0 24-10.745 24-24v-16c0-13.255-10.745-24-24-24 0-90.965-51.016-167.734-120.842-192C308.984 231.734 360 154.965 360 64c13.255 0 24-10.745 24-24V24c0-13.255-10.745-24-24-24zm-75.078 384H99.08c17.059-46.797 52.096-80 92.92-80 40.821 0 75.862 33.196 92.922 80zm.019-256H99.078C91.988 108.548 88 86.748 88 64h208c0 22.805-3.987 44.587-11.059 64z'/%3E%3C/svg%3E"); width: 0.75em; }
.fa-house-damage { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath d='M288 114.96L69.47 307.71c-1.62 1.46-3.69 2.14-5.47 3.35V496c0 8.84 7.16 16 16 16h149.23L192 439.19l104.11-64-60.16-119.22L384 392.75l-104.11 64L319.81 512H496c8.84 0 16-7.16 16-16V311.1c-1.7-1.16-3.72-1.82-5.26-3.2L288 114.96zm282.69 121.32L512 184.45V48c0-8.84-7.16-16-16-16h-64c-8.84 0-16 7.16-16 16v51.69L314.75 10.31C307.12 3.45 297.56.01 288 0s-19.1 3.41-26.7 10.27L5.31 236.28c-6.57 5.91-7.12 16.02-1.21 22.6l21.4 23.82c5.9 6.57 16.02 7.12 22.6 1.21L277.42 81.63c6.05-5.33 15.12-5.33 21.17 0L527.91 283.9c6.57 5.9 16.69 5.36 22.6-1.21l21.4-23.82c5.9-6.57 5.36-16.69-1.22-22.59z'/%3E%3C/svg%3E"); width: 1.125em; }
.fa-layer-group { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M12.41 148.02l232.94 105.67c6.8 3.09 14.49 3.09 21.29 0l232.94-105.67c16.55-7.51 16.55-32.52 0-40.03L266.65 2.31a25.607 25.607 0 0 0-21.29 0L12.41 107.98c-16.55 7.51-16.55 32.53 0 40.04zm487.18 88.28l-58.09-26.33-161.64 73.27c-7.56 3.43-15.59 5.17-23.86 5.17s-16.29-1.74-23.86-5.17L70.51 209.97l-58.1 26.33c-16.55 7.5-16.55 32.5 0 40l232.94 105.59c6.8 3.08 14.49 3.08 21.29 0L499.59 276.3c16.55-7.5 16.55-32.5 0-40zm0 127.8l-57.87-26.23-161.86 73.37c-7.56 3.43-15.59 5.17-23.86 5.17s-16.29-1.74-23.86-5.17L70.29 337.87 12.41 364.1c-16.55 7.5-16.55 32.5 0 40l232.94 105.59c6.8 3.08 14.49 3.08 21.29 0L499.59 404.1c16.55-7.5 16.55-32.5 0-40z'/%3E%3C/svg%3E"); }
.fa-leaf { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath d='M546.2 9.7c-5.6-12.5-21.6-13-28.3-1.2C486.9 62.4 431.4 96 368 96h-80C182 96 96 182 96 288c0 7 .8 13.7 1.5 20.5C161.3 262.8 253.4 224 384 224c8.8 0 16 7.2 16 16s-7.2 16-16 16C132.6 256 26 410.1 2.4 468c-6.6 16.3 1.2 34.9 17.5 41.6 16.4 6.8 35-1.1 41.8-17.3 1.5-3.6 20.9-47.9 71.9-90.6 32.4 43.9 94 85.8 174.9 77.2C465.5 467.5 576 326.7 576 154.3c0-50.2-10.8-102.2-29.8-144.6z'/%3E%3C/svg%3E"); width: 1.125em; }
.fa-lightbulb { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 352 512'%3E%3Cpath d='M96.06 454.35c.01 6.29 1.87 12.45 5.36 17.69l17.09 25.69a31.99 31.99 0 0 0 26.64 14.28h61.71a31.99 31.99 0 0 0 26.64-14.28l17.09-25.69a31.989 31.989 0 0 0 5.36-17.69l.04-38.35H96.01l.05 38.35zM0 176c0 44.37 16.45 84.85 43.56 115.78 16.52 18.85 42.36 58.23 52.21 91.45.04.26.07.52.11.78h160.24c.04-.26.07-.51.11-.78 9.85-33.22 35.69-72.6 52.21-91.45C335.55 260.85 352 220.37 352 176 352 78.61 272.91-.3 175.45 0 73.44.31 0 82.97 0 176zm176-80c-44.11 0-80 35.89-80 80 0 8.84-7.16 16-16 16s-16-7.16-16-16c0-61.76 50.24-112 112-112 8.84 0 16 7.16 16 16s-7.16 16-16 16z'/%3E%3C/svg%3E"); width: 0.6875em; }
.fa-long-arrow-alt-right { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath d='M313.941 216H12c-6.627 0-12 5.373-12 12v56c0 6.627 5.373 12 12 12h301.941v46.059c0 21.382 25.851 32.09 40.971 16.971l86.059-86.059c9.373-9.373 9.373-24.569 0-33.941l-86.059-86.059c-15.119-15.119-40.971-4.411-40.971 16.971V216z'/%3E%3C/svg%3E"); width: 0.875em; }
.fa-map-marker-alt { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Cpath d='M172.268 501.67C26.97 291.031 0 269.413 0 192 0 85.961 85.961 0 192 0s192 85.961 192 192c0 77.413-26.97 99.031-172.268 309.67-9.535 13.774-29.93 13.773-39.464 0zM192 272c44.183 0 80-35.817 80-80s-35.817-80-80-80-80 35.817-80 80 35.817 80 80 80z'/%3E%3C/svg%3E"); width: 0.75em; }
.fa-pen-square { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath d='M400 480H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48v352c0 26.5-21.5 48-48 48zM238.1 177.9L102.4 313.6l-6.3 57.1c-.8 7.6 5.6 14.1 13.3 13.3l57.1-6.3L302.2 242c2.3-2.3 2.3-6.1 0-8.5L246.7 178c-2.5-2.4-6.3-2.4-8.6-.1zM345 165.1L314.9 135c-9.4-9.4-24.6-9.4-33.9 0l-23.1 23.1c-2.3 2.3-2.3 6.1 0 8.5l55.5 55.5c2.3 2.3 6.1 2.3 8.5 0L345 199c9.3-9.3 9.3-24.5 0-33.9z'/%3E%3C/svg%3E"); width: 0.875em; }
.fa-phone-alt { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M497.39 361.8l-112-48a24 24 0 0 0-28 6.9l-49.6 60.6A370.66 370.66 0 0 1 130.6 204.11l60.6-49.6a23.94 23.94 0 0 0 6.9-28l-48-112A24.16 24.16 0 0 0 122.6.61l-104 24A24 24 0 0 0 0 48c0 256.5 207.9 464 464 464a24 24 0 0 0 23.4-18.6l24-104a24.29 24.29 0 0 0-14.01-27.6z'/%3E%3C/svg%3E"); }
.fa-plus { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath d='M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z'/%3E%3C/svg%3E"); width: 0.875em; }
.fa-question { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Cpath d='M202.021 0C122.202 0 70.503 32.703 29.914 91.026c-7.363 10.58-5.093 25.086 5.178 32.874l43.138 32.709c10.373 7.865 25.132 6.026 33.253-4.148 25.049-31.381 43.63-49.449 82.757-49.449 30.764 0 68.816 19.799 68.816 49.631 0 22.552-18.617 34.134-48.993 51.164-35.423 19.86-82.299 44.576-82.299 106.405V320c0 13.255 10.745 24 24 24h72.471c13.255 0 24-10.745 24-24v-5.773c0-42.86 125.268-44.645 125.268-160.627C377.504 66.256 286.902 0 202.021 0zM192 373.459c-38.196 0-69.271 31.075-69.271 69.271 0 38.195 31.075 69.27 69.271 69.27s69.271-31.075 69.271-69.271-31.075-69.27-69.271-69.27z'/%3E%3C/svg%3E"); width: 0.75em; }
.fa-shield-alt { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M466.5 83.7l-192-80a48.15 48.15 0 0 0-36.9 0l-192 80C27.7 91.1 16 108.6 16 128c0 198.5 114.5 335.7 221.5 380.3 11.8 4.9 25.1 4.9 36.9 0C360.1 472.6 496 349.3 496 128c0-19.4-11.7-36.9-29.5-44.3zM256.1 446.3l-.1-381 175.9 73.3c-3.3 151.4-82.1 261.1-175.8 307.7z'/%3E%3C/svg%3E"); }
.fa-star { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath d='M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z'/%3E%3C/svg%3E"); width: 1.125em; }
.fa-temperature-low { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M416 0c-52.9 0-96 43.1-96 96s43.1 96 96 96 96-43.1 96-96-43.1-96-96-96zm0 128c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm-160-16C256 50.1 205.9 0 144 0S32 50.1 32 112v166.5C12.3 303.2 0 334 0 368c0 79.5 64.5 144 144 144s144-64.5 144-144c0-34-12.3-64.9-32-89.5V112zM144 448c-44.1 0-80-35.9-80-80 0-25.5 12.2-48.9 32-63.8V112c0-26.5 21.5-48 48-48s48 21.5 48 48v192.2c19.8 14.8 32 38.3 32 63.8 0 44.1-35.9 80-80 80zm16-125.1V304c0-8.8-7.2-16-16-16s-16 7.2-16 16v18.9c-18.6 6.6-32 24.2-32 45.1 0 26.5 21.5 48 48 48s48-21.5 48-48c0-20.9-13.4-38.5-32-45.1z'/%3E%3C/svg%3E"); }
.fa-tint { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 352 512'%3E%3Cpath d='M205.22 22.09c-7.94-28.78-49.44-30.12-58.44 0C100.01 179.85 0 222.72 0 333.91 0 432.35 78.72 512 176 512s176-79.65 176-178.09c0-111.75-99.79-153.34-146.78-311.82zM176 448c-61.75 0-112-50.25-112-112 0-8.84 7.16-16 16-16s16 7.16 16 16c0 44.11 35.89 80 80 80 8.84 0 16 7.16 16 16s-7.16 16-16 16z'/%3E%3C/svg%3E"); width: 0.6875em; }
.fa-tools { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M501.1 395.7L384 278.6c-23.1-23.1-57.6-27.6-85.4-13.9L192 158.1V96L64 0 0 64l96 128h62.1l106.6 106.6c-13.6 27.8-9.2 62.3 13.9 85.4l117.1 117.1c14.6 14.6 38.2 14.6 52.7 0l52.7-52.7c14.5-14.6 14.5-38.2 0-52.7zM331.7 225c28.3 0 54.9 11 74.9 31l19.4 19.4c15.8-6.9 30.8-16.5 43.8-29.5 37.1-37.1 49.7-89.3 37.9-136.7-2.2-9-13.5-12.1-20.1-5.5l-74.4 74.4-67.9-11.3L334 98.9l74.4-74.4c6.6-6.6 3.4-17.9-5.7-20.2-47.4-11.7-99.6.9-136.6 37.9-28.5 28.5-41.9 66.1-41.2 103.6l82.1 82.1c8.1-1.9 16.5-2.9 24.7-2.9zm-103.9 82l-56.7-56.7L18.7 402.8c-25 25-25 65.5 0 90.5s65.5 25 90.5 0l123.6-123.6c-7.6-19.9-9.9-41.6-5-62.7zM64 472c-13.2 0-24-10.8-24-24 0-13.3 10.7-24 24-24s24 10.7 24 24c0 13.2-10.7 24-24 24z'/%3E%3C/svg%3E"); }
.fa-google { --shin-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 488 512'%3E%3Cpath d='M488 261.8C488 403.3 391.1 504 248 504 110.8 504 0 393.2 0 256S110.8 8 248 8c66.8 0 123 24.5 166.3 64.9l-67.5 64.9C258.5 52.6 94.3 116.6 94.3 256c0 86.5 69.1 156.6 153.7 156.6 98.2 0 135-70.4 140.8-106.9H248v-85.3h236.1c2.3 12.7 3.9 24.9 3.9 41.4z'/%3E%3C/svg%3E"); width: 0.9531em; }
/* === END GENERATED ICONS === */
