/* Shed Index design system.
   Palette is cool slate with a deep timber-green accent -- chosen to read as
   survey/engineering reference rather than home-decor retail. */

:root {
  --ground:    #EDEEEA;
  --surface:   #F8F9F6;
  --ink:       #1B211F;
  --ink-soft:  #5A635F;
  --rule:      #CDD2CB;
  --accent:    #1F4D45;
  --flag:      #B04A18;
  --go:        #2C6539;

  --measure: 68ch;
  --step:    clamp(1rem, 0.9rem + 0.4vw, 1.125rem);

  /* Figures are the product here, so they get their own face. A system
     mono stack costs no request and no CSP allowance -- style-src is
     'self', which rules out a hosted webfont -- and tabular numerals are
     what stop a column of psf values from jittering as the digits change. */
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
          "Liberation Mono", monospace;

  /* Vertical rhythm. One scale, referenced everywhere, so section spacing
     is a decision made once rather than a number retyped per rule. */
  --gap-s: 0.75rem;
  --gap-m: 1.5rem;
  --gap-l: 2.75rem;

  /* Ground snow load ramp, five steps of the accent hue rather than a
     second accent colour. Snow load is a sequential quantity, so the ramp
     is sequential: pale is little, deep is a lot. */
  --band-1: #B3C3BC;
  --band-2: #8AA59B;
  --band-3: #628A7D;
  --band-4: #437063;
  --band-5: #1F4D45;
}

@media (prefers-color-scheme: dark) {
  :root {
    --ground:   #131817;
    --surface:  #1B211F;
    --ink:      #E7EAE5;
    --ink-soft: #9BA49F;
    --rule:     #2F3835;
    --accent:   #74C3B1;
    --flag:     #E58A55;
    --go:       #78BC85;

    /* The ramp inverts with the mode: on a dark ground the deep end has to
       be the bright one, or "a lot of snow" reads as "nearly invisible". */
    --band-1: #2E3A36;
    --band-2: #3F564D;
    --band-3: #527A6B;
    --band-4: #629E8A;
    --band-5: #74C3B1;
  }
}

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

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font: var(--step)/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: 62rem; margin: 0 auto; padding: 0 1.25rem; }

.site-header {
  display: flex; flex-wrap: wrap; gap: 1rem 1.5rem;
  align-items: baseline; justify-content: space-between;
  max-width: 62rem; margin: 0 auto; padding: 1.25rem;
  border-bottom: 1px solid var(--rule);
}

.wordmark { font-weight: 700; letter-spacing: -0.02em; text-decoration: none; color: var(--ink); }
.site-header nav { display: flex; gap: 1.25rem; flex-wrap: wrap; }
.site-header nav a { color: var(--ink-soft); text-decoration: none; }
.site-header nav a:hover { color: var(--accent); text-decoration: underline; }

h1 { font-size: clamp(1.75rem, 1.2rem + 2.2vw, 2.75rem); line-height: 1.1;
     letter-spacing: -0.02em; text-wrap: balance; margin: 2rem 0 0.75rem; }
h2 { font-size: clamp(1.25rem, 1rem + 1vw, 1.6rem); line-height: 1.2; margin: 2rem 0 0.5rem; }
p  { max-width: var(--measure); }
h3 { font-size: 1.05rem; line-height: 1.25; margin: 1.5rem 0 0.4rem; color: var(--ink); }

/* The standing pages (about, contact, privacy, terms) are the first prose
   on this site long enough to need list styling. Same measure as a
   paragraph, so a bulleted clause and the sentence above it stop at the
   same place. */
ul, ol { max-width: var(--measure); padding-left: 1.25rem; }
li { margin: 0.4rem 0; }
code { font-family: var(--mono); font-size: 0.9em; background: var(--surface);
       border: 1px solid var(--rule); border-radius: 3px; padding: 0.05em 0.35em; }

.contact-email { font-family: var(--mono); font-size: 1.15em; margin: 1.25rem 0 2rem; }
.lede { font-size: 1.15em; color: var(--ink-soft); }

a { color: var(--accent); text-underline-offset: 2px; }
a:focus-visible, button:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.cta {
  display: inline-block; padding: 0.7rem 1.2rem; border-radius: 3px;
  background: var(--accent); color: var(--ground);
  text-decoration: none; font-weight: 600;
}

/* The only motion on the site: a press that acknowledges the press. No
   scroll or entrance animation -- this is a page someone opens to check a
   structural figure, and movement it did not ask for is noise. Gated on
   prefers-reduced-motion regardless. */
@media (prefers-reduced-motion: no-preference) {
  .cta, a.buy { transition: transform 0.12s cubic-bezier(0.16, 1, 0.3, 1), filter 0.12s; }
  .cta:active, a.buy:active { transform: translateY(1px); }
}

/* Verdict chips used by the snow load matcher. */
.verdict { display: inline-block; padding: 0.15rem 0.55rem; border: 1px solid currentColor;
           font-size: 0.8em; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; }
.verdict--pass     { color: var(--go); }
.verdict--marginal { color: var(--ink-soft); }
.verdict--fail     { color: var(--flag); }

.table-scroll { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; font-size: 0.95em; }
th, td { text-align: left; padding: 0.6rem 0.75rem; border-bottom: 1px solid var(--rule); }
th { font-size: 0.75em; text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-soft);
     font-weight: 600; border-bottom-color: var(--ink-soft); }
/* Figures share the readout's face, so a psf value reads the same whether
   it is the headline answer or a cell in a comparison. */
td.num { font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
tbody tr:last-child td { border-bottom: 0; }

/* The outbound Amazon link in the comparison table, styled as a button on
   request. It is deliberately a SMALLER button than the product page's
   .cta: one repeated down every row at full CTA weight would out-shout the
   snow-load ratings the table exists to compare, so it is compact, sized to
   its text, and never full width.

   nowrap keeps "Check price on Amazon" whole rather than breaking across
   three lines in a narrow cell, because a screen reader announces link text
   without its column header. */
a.buy {
  display: inline-block; white-space: nowrap;
  padding: 0.4rem 0.7rem; border-radius: 3px;
  background: var(--accent); color: var(--ground);
  font-size: 0.85em; font-weight: 600; text-decoration: none;
}
a.buy:hover, a.cta:hover { filter: brightness(1.12); }

/* Text for screen readers only. Clipped rather than display:none, which
   would remove it from the accessible tree along with everything else. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip: rect(0 0 0 0); clip-path: inset(50%);
  overflow: hidden; white-space: nowrap;
}

.site-footer { margin-top: 4rem; padding: 1.5rem 1.25rem;
               border-top: 1px solid var(--rule); color: var(--ink-soft); font-size: 0.9em; }
/* The standing pages, on every page. Mirrors the header nav rather than
   inventing a second link treatment. */
.site-footer__nav { display: flex; flex-wrap: wrap; gap: var(--gap-m); }
.site-footer__nav a { color: var(--ink-soft); text-decoration: none; }
.site-footer__nav a:hover { color: var(--accent); text-decoration: underline; }

.disclosure { font-size: 0.85em; color: var(--ink-soft); max-width: var(--measure);
              border-top: 1px solid var(--rule); padding-top: 0.9rem; margin-top: 2rem; }

.notice { border-left: 3px solid var(--flag); background: var(--surface);
          padding: 0.9rem 1.1rem; margin: 1.5rem 0; max-width: var(--measure); }

.zip-form { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: end;
            margin: 1.5rem 0; max-width: var(--measure); }
.zip-form label { display: block; font-size: 0.85em; color: var(--ink-soft); width: 100%; }
.zip-form input { flex: 1 1 12ch; padding: 0.65rem 0.75rem; font: inherit;
                  font-variant-numeric: tabular-nums;
                  background: var(--surface); color: var(--ink);
                  border: 1px solid var(--rule); border-radius: 3px; }
.zip-form button { border: 0; cursor: pointer; font: inherit; }

.provenance { font-size: 0.85em; color: var(--ink-soft); }

/* --- The answer ------------------------------------------------------ */
/* The visitor came for one number. It leads the page instead of sitting
   inside a sentence, and it is set in the figure face so it reads as a
   measurement rather than as copy. */
.readout {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--gap-s);
  margin: var(--gap-m) 0 var(--gap-l);
  padding-bottom: var(--gap-m);
  border-bottom: 1px solid var(--rule);
  max-width: var(--measure);
}
.readout__value {
  margin: 0; font-family: var(--mono); font-size: 1.15rem;
  color: var(--ink-soft); letter-spacing: -0.01em;
}
.readout__number {
  font-size: clamp(3rem, 2rem + 5vw, 5rem); line-height: 0.9; font-weight: 600;
  color: var(--ink); font-variant-numeric: tabular-nums; letter-spacing: -0.03em;
}
.readout__label { margin: 0; flex: 1 1 18ch; color: var(--ink-soft); font-size: 0.9em; }

/* --- Locator map ----------------------------------------------------- */
/* Inline SVG, no tile service: the CSP allows no third-party image or
   script. See app/Support/UsMap.php. */
.snow-map-figure { margin: var(--gap-l) 0; max-width: 46rem; }
.snow-map {
  display: block; width: 100%; height: auto;
  background: var(--surface);
  border: 1px solid var(--rule); border-radius: 3px;
}
.snow-map__states path {
  fill: var(--ground); stroke: var(--ink-soft); stroke-width: 0.75;
  stroke-linejoin: round; vector-effect: non-scaling-stroke; opacity: 0.55;
}
/* Every dot carries a dark ring. Fill alone could not be relied on: the
   pale end of the ramp sits on pale land, and "under 10 psf" was
   effectively invisible against Florida. */
.snow-map__dot {
  stroke: var(--ink); stroke-width: 1.25; vector-effect: non-scaling-stroke;
}
.snow-map__dot--band1 { fill: var(--band-1); }
.snow-map__dot--band2 { fill: var(--band-2); }
.snow-map__dot--band3 { fill: var(--band-3); }
.snow-map__dot--band4 { fill: var(--band-4); }
.snow-map__dot--band5 { fill: var(--band-5); }

/* The county that was searched. --flag is already the palette's attention
   colour (the notice rule, the failing verdict), so "you are here" does not
   introduce a sixth hue. Colour alone would not carry it for a
   colour-blind reader, so it is also the largest dot and the only ringed
   one, and the SVG title names the county outright. */
.snow-map__dot--here { fill: var(--flag); stroke: var(--ink); stroke-width: 2; }

.snow-map-caption {
  display: flex; flex-wrap: wrap; gap: var(--gap-s) var(--gap-m);
  align-items: center; justify-content: space-between;
  margin-top: var(--gap-s); font-size: 0.8em; color: var(--ink-soft);
}
.snow-map-key { display: flex; flex-wrap: wrap; gap: 1px; font-family: var(--mono); }
.snow-map-key__step {
  padding: 0.25rem 0.5rem; color: var(--ground); font-size: 0.9em; white-space: nowrap;
}
.snow-map-key__step--band1 { background: var(--band-1); color: var(--ink); }
.snow-map-key__step--band2 { background: var(--band-2); color: var(--ink); }
.snow-map-key__step--band3 { background: var(--band-3); }
.snow-map-key__step--band4 { background: var(--band-4); }
.snow-map-key__step--band5 { background: var(--band-5); }
.snow-map-caption__note { flex: 1 1 16ch; }

@media (max-width: 34rem) {
  /* The five-step key stops being readable long before the map does. */
  .snow-map-key__step { padding: 0.25rem 0.35rem; font-size: 0.8em; }
}

/* --- Product imagery -------------------------------------------------- */
/* Self-hosted only: img-src is 'self' data:, and the Associates agreement
   allows product imagery through PA-API or SiteStripe, not lifted from a
   listing. See app/Support/ProductImage.php. */
.product-shot { margin: var(--gap-m) 0 var(--gap-l); max-width: 34rem; }
.product-shot img {
  display: block; width: 100%; height: auto;
  /* The markup declares a nominal 4:3 so space is reserved before the image
     loads. Real assets vary, so the box is fixed and the image is contained
     inside it rather than cropped: a shed photographed square must not have
     its roof trimmed to fit a layout decision. */
  aspect-ratio: 4 / 3; object-fit: contain;
  background: var(--surface);
  border: 1px solid var(--rule); border-radius: 3px;
}
.product-shot figcaption {
  margin-top: var(--gap-s); font-size: 0.8em; color: var(--ink-soft);
}

/* Thumbnail in the comparison table. Fixed box so rows keep an even
   height whether or not a product has an image yet. */
.product-thumb {
  float: left; width: 3.25rem; height: 3.25rem; margin: 0 0.65rem 0 0;
  object-fit: contain; background: var(--surface);
  border: 1px solid var(--rule); border-radius: 2px;
}

/* The ZIP list on a county page. Dense on purpose: it is a reference
   block, not a navigation menu, and there can be a couple of hundred. */
.zip-list { max-width: none; font-family: var(--mono); font-size: 0.85em; line-height: 2; }
.zip-list a { display: inline-block; padding: 0.1rem 0.4rem; border: 1px solid var(--rule);
              border-radius: 2px; text-decoration: none; }
.zip-list a:hover { border-color: var(--accent); }
