/* Sections — per-section page layout. CSS Grid for page layout, Flexbox for internals. */

section {
  padding-block: var(--space-3xl);
}

.section__head {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-sm);
  margin-block-end: var(--space-2xl);
  max-width: 46rem;
}

.section--panel {
  background: var(--color-paper-2);
  border-block: 1px solid var(--color-rule-2);
}

/* =========================================================================
   HERO — full-bleed photographic fold. Content lower-third, left-biased.
   ========================================================================= */

.hero {
  position: relative;
  min-height: calc(100vh - var(--nav-height));
  min-height: calc(100dvh - var(--nav-height));
  display: grid;
  align-items: end;
  padding-block: var(--space-2xl) var(--space-3xl);
  overflow: hidden;
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: var(--z-base);
}

.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 38%;
  filter: brightness(0.62) saturate(0.92);
}

.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: var(--z-raised);
  background:
    linear-gradient(180deg, var(--color-scrim-soft) 0%, transparent 30%, var(--color-overlay-scrim) 100%),
    linear-gradient(90deg, var(--color-scrim-side) 0%, transparent 55%);
}

.hero__content {
  position: relative;
  z-index: var(--z-dropdown);
  max-width: 40rem;
  display: grid;
  gap: var(--space-lg);
  opacity: 0;
  transform: translateY(var(--space-md));
  animation: hero-rise var(--dur-long) var(--ease-out) 100ms forwards;
}

@keyframes hero-rise {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.hero h1 {
  font-size: var(--text-display);
  line-height: var(--lh-tight);
  color: var(--color-ink);
  text-wrap: balance;
}

.hero .lede {
  max-width: 34ch;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-md);
}

@media (max-width: 26rem) {
  /* At the narrowest phones, verbatim CTA copy ("Text us a photo of your
     wall") needs the full row width and a smaller type size to stay one
     line — never truncated, never wrapped to two lines (gate 49). */
  .hero__actions {
    flex-direction: column;
    align-items: stretch;
  }
  .hero__actions .btn {
    width: 100%;
  }
}

.hero__note {
  font-size: var(--text-sm);
  color: var(--color-muted);
  font-style: italic;
}

@media (prefers-reduced-motion: reduce) {
  .hero__content {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

@media (max-width: 40rem) {
  .hero h1 {
    font-size: var(--text-display-s);
  }
}

/* =========================================================================
   TRUST — a thin strip directly under the fold. Rules above and below, no
   card chrome; it should read as a caption to the hero, not a feature band.
   ========================================================================= */

.trust {
  padding-block: var(--space-lg);
  background: var(--color-paper-2);
  border-block: 1px solid var(--color-rule-2);
}

.trust__list {
  display: grid;
  gap: var(--space-md);
}

@media (min-width: 48rem) {
  .trust__list {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-lg);
    align-items: center;
  }

  /* Left-aligning all three inside equal columns left the last item ending
     wherever its text happened to stop, well short of the container edge and
     visibly out of line with the gallery beneath it. Pinning the last item to
     the end and centring the middle spreads the row edge to edge — the same
     .container padding the gallery grid uses, so the right edges agree. */
  .trust__item:nth-child(2) {
    justify-self: center;
  }

  .trust__item:nth-child(3) {
    justify-self: end;
  }
}

/* =========================================================================
   COMPARE — one wall, before and after the install. Both frames are real
   photographs of the same room; the before shot was registered onto the
   after's geometry (affine, from the door-casing edges) so the doorway,
   crown moulding and baseboard stay put as the wipe crosses them.
   ========================================================================= */

.compare__frame {
  --compare-pos: 55%;
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-rule-2);
  background: var(--color-paper-2);
  touch-action: pan-y;
}

.compare__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 45%;
}

/* clip-path (not an overflow wrapper) so the overlay image stays sized to the
   frame rather than to the revealed sliver. */
.compare__clip {
  position: absolute;
  inset: 0;
  clip-path: inset(0 calc(100% - var(--compare-pos)) 0 0);
}

.compare__divider {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--compare-pos);
  width: 2px;
  margin-inline-start: -1px;
  background: var(--color-accent);
  pointer-events: none;
}

.compare__divider::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 2.75rem;
  height: 2.75rem;
  transform: translate(-50%, -50%);
  border: 2px solid var(--color-accent);
  border-radius: 50%;
  background: var(--color-overlay-scrim);
}

.compare__tag {
  position: absolute;
  bottom: var(--space-md);
  z-index: var(--z-raised);
  padding: var(--space-2xs) var(--space-sm);
  border-radius: var(--radius-sm);
  background: var(--color-scrim-strong);
  color: var(--color-ink);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  pointer-events: none;
}

.compare__tag--start { left: var(--space-md); }
.compare__tag--end   { right: var(--space-md); }

/* The range input is the whole drag surface — invisible track, invisible
   thumb, so the divider knob reads as the handle. Keyboard support is free. */
.compare__range {
  position: absolute;
  inset: 0;
  z-index: var(--z-dropdown);
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  cursor: ew-resize;
}

.compare__range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  background: transparent;
  cursor: ew-resize;
}

.compare__range::-moz-range-thumb {
  width: 3rem;
  height: 3rem;
  border: none;
  border-radius: 50%;
  background: transparent;
  cursor: ew-resize;
}

.compare__range:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 3px;
}

/* The before/after pair is exported at 4:3, so the frame keeps that ratio at
   every width -- a wider desktop frame would crop the doorway that makes the
   two halves read as the same room. */

/* =========================================================================
   Swatches — photographed finish samples, grouped by material. Small on
   purpose: these are phone shots of physical samples, kept as colour and
   texture reference rather than blown up as hero imagery.
   ========================================================================= */

/* Fixed column counts, not auto-fill. There are exactly 20 swatches, and
   20 divides by 4, 5 and 10 — so every row is full and no row is a stub with
   dead space beside it, at every breakpoint. auto-fill left 12 on one row and
   5 on the next. */
/* Row gap is deliberately much larger than the caption's own offset. With
   even gaps a name floats midway between its own tile and the row below and
   reads as a heading for the wrong row — which is exactly how it came across
   the first time. Tight above, loose below, so each name attaches upward. */
.swatches {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  column-gap: var(--space-xs);
  row-gap: var(--space-xl);
  margin-block-start: var(--space-xl);
}

.swatch__name {
  display: block;
  margin-block-start: var(--space-2xs);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-xs);
  line-height: var(--lh-snug);
  color: var(--color-ink-2);
}

@media (min-width: 40rem) {
  .swatches {
    grid-template-columns: repeat(5, minmax(0, 1fr));
    column-gap: var(--space-sm);
  }
}

@media (min-width: 60rem) {
  .swatches {
    grid-template-columns: repeat(10, minmax(0, 1fr));
  }
}

.swatch img {
  display: block;
  width: 100%;
  /* height:auto is load-bearing. The width/height attributes on <img> map to
     the CSS width/height properties as presentational hints, so without this
     the element keeps its literal 560px attribute height and aspect-ratio is
     ignored entirely — aspect-ratio only sizes the box when height is auto. */
  height: auto;
  aspect-ratio: 5 / 7;
  object-fit: cover;
  border-radius: var(--radius-sm);
}

.swatches__note {
  margin-block-start: var(--space-lg);
  font-size: var(--text-sm);
  color: var(--color-muted);
}

@media (min-width: 40rem) {
  .swatches__grid {
    grid-template-columns: repeat(auto-fill, minmax(5.5rem, 1fr));
    gap: var(--space-sm);
  }
}

/* =========================================================================
   Duo — a static two-up. Used for the day/night pair, which shows ambience
   rather than a transformation and so does not earn a second drag slider.
   ========================================================================= */

/* =========================================================================
   LAMP — one frame showing the same wall lit two ways, with a switch. The
   two photographs are 1.149 and 1.054 wide-to-tall; 11/10 sits between them
   so each is trimmed by roughly 4% and neither jumps as they crossfade.
   ========================================================================= */

.lamp {
  display: grid;
  gap: var(--space-xl);
  justify-items: center;
}

.lamp__frame {
  position: relative;
  width: 100%;
  aspect-ratio: 11 / 10;
  overflow: hidden;
  border-radius: var(--radius-md);
  background: var(--color-paper-2);
}

.lamp__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.lamp__img--on {
  opacity: 0;
  transition: opacity var(--dur-med) var(--ease-in-out);
}

.lamp.is-on .lamp__img--on {
  opacity: 1;
}

/* A big physical toggle: recessed track, weighted knob carrying the bulb, and
   the whole plate warming when the light comes on. */
.lamp__switch {
  padding: 0;
  border-radius: 3.5rem;
}

.lamp__switch:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 6px;
  border-radius: 3.5rem;
}

.lamp__track {
  position: relative;
  display: block;
  width: 13rem;
  height: 5.75rem;
  border-radius: 3rem;
  background: var(--color-paper);
  border: 1px solid var(--color-rule);
  box-shadow: inset 0 3px 10px rgb(0 0 0 / 0.55);
  transition: background-color var(--dur-med) var(--ease-out),
              border-color var(--dur-med) var(--ease-out),
              box-shadow var(--dur-med) var(--ease-out);
}

.lamp.is-on .lamp__track {
  background: color-mix(in oklab, var(--color-accent) 20%, var(--color-paper));
  border-color: var(--color-accent);
  box-shadow: inset 0 3px 10px rgb(0 0 0 / 0.3),
              0 0 2.5rem color-mix(in oklab, var(--color-accent) 45%, transparent);
}

.lamp__legend {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  transition: opacity var(--dur-short) var(--ease-out);
}

.lamp__legend--off {
  right: 1.75rem;
  color: var(--color-muted);
}

.lamp__legend--on {
  left: 1.875rem;
  color: var(--color-accent);
  opacity: 0;
}

.lamp.is-on .lamp__legend--off { opacity: 0; }
.lamp.is-on .lamp__legend--on  { opacity: 1; }

.lamp__knob {
  position: absolute;
  top: 0.5rem;
  left: 0.5rem;
  display: grid;
  place-items: center;
  width: 4.5rem;
  height: 4.5rem;
  border-radius: 50%;
  background: var(--color-paper-3);
  box-shadow: 0 3px 12px rgb(0 0 0 / 0.6);
  transition: transform var(--dur-med) var(--ease-spring),
              background-color var(--dur-med) var(--ease-out);
}

/* 13rem track − 4.5rem knob − 0.5rem inset each side = 7.5rem of travel. */
.lamp.is-on .lamp__knob {
  transform: translateX(7.5rem);
  background: var(--color-accent);
}

.lamp__bulb {
  width: 2rem;
  height: 2rem;
  color: var(--color-muted);
  transition: color var(--dur-med) var(--ease-out);
}

.lamp.is-on .lamp__bulb {
  color: var(--color-accent-ink);
}

.lamp__caption {
  margin: 0;
  font-size: var(--text-sm);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-muted);
}

/* =========================================================================
   BENEFITS — icon cards. Copy is verbatim from the What It Does list.
   ========================================================================= */

.benefits {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-md);
}

@media (min-width: 40rem) {
  .benefits {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 68rem) {
  .benefits {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

/* =========================================================================
   MOCKUP — copy-led. No imagery; type carries it, offset right-biased.
   ========================================================================= */

.mockup .container {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-2xl);
  align-items: center;
}

/* The illustration only appears once there is a genuinely empty column to put
   it in. Below 60rem the text uses the full width and the art would just be
   pushing the CTA further down the page. */
.mockup__art {
  display: none;
}

.mockup__art svg {
  width: 100%;
  max-width: 26rem;
  height: auto;
  color: var(--color-muted);   /* the dashed "before" frame — visible, not loud */
}

.mockup__art-after {
  color: var(--color-ink-2);
}

.mockup__art-slats {
  color: var(--color-accent);
}

.mockup__art-arrow,
.mockup__art-arrow-back {
  color: var(--color-accent);
}

.mockup__art-arrow-back {
  opacity: 0.45;
}

.mockup__inner {
  max-width: 40rem;
  display: grid;
  gap: var(--space-lg);
  padding-inline-start: var(--space-lg);
  border-inline-start: 2px solid var(--color-accent);
}

.mockup h2 {
  font-size: var(--text-2xl);
}

@media (min-width: 60rem) {
  .mockup .container {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }

  .mockup__art {
    display: grid;
    justify-items: center;
  }

  .mockup__inner {
    max-width: 34rem;
  }
}

@media (max-width: 26rem) {
  .mockup__inner {
    padding-inline-start: var(--space-sm);
  }
}

/* =========================================================================
   GALLERY — a uniform portrait grid at every width. Every install photo is a
   vertical phone frame of a vertical wall, so spanning tiles across two
   columns would crop the wall off at both ends, and uneven spans leave orphan
   cells whenever the photo count is not a multiple of the span pattern. A
   plain grid keeps the crops honest, stays gapless at any count, and adds no
   horizontal scroll surface to overflow the viewport on a phone.
   ========================================================================= */

.gallery__head {
  margin-block-end: var(--space-xl);
}

.gallery__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-xs);
}

.gallery__grid .gallery__figure {
  aspect-ratio: 4 / 5;
}

@media (min-width: 40rem) {
  .gallery__grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-sm);
  }
}

@media (min-width: 60rem) {
  .gallery__grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-md);
  }
}

/* =========================================================================
   MATERIALS — two-column comparison, text-only.
   ========================================================================= */

.materials__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-lg);
}

@media (min-width: 40rem) {
  .materials__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.materials__note {
  margin-block-start: var(--space-xl);
  color: var(--color-ink-2);
}

/* =========================================================================
   FINISHES — typographic chip set.
   ========================================================================= */

.finishes__inner {
  display: grid;
  gap: var(--space-xl);
}

/* =========================================================================
   WHAT IT DOES — asymmetric split, list left, single detail photo right.
   ========================================================================= */

.does {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-2xl);
  align-items: center;
}

.does ul {
  display: grid;
  gap: var(--space-md);
}

.does li {
  position: relative;
  padding-inline-start: var(--space-lg);
  font-size: var(--text-md);
  color: var(--color-ink-2);
  line-height: var(--lh-snug);
}

.does li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.5em;
  width: 0.75rem;
  height: 1px;
  background: var(--color-accent);
}

.does__media {
  aspect-ratio: 4 / 3;
  overflow: hidden;
}

.does__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 70%;
}

@media (min-width: 60rem) {
  .does {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
  .does__media {
    order: 2;
  }
}

/* =========================================================================
   HOW IT WORKS — step sequence + one process photo.
   ========================================================================= */

.how {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-2xl);
}

.how__media {
  aspect-ratio: 3 / 4;
  overflow: hidden;
  max-width: 26rem;
}

.how__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 30%;
}

.how__note {
  margin-block-start: var(--space-xl);
  color: var(--color-muted);
  font-size: var(--text-sm);
  max-width: 40ch;
}

@media (min-width: 60rem) {
  .how {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
    align-items: stretch;
  }

  /* The photo used to keep a fixed 3/4 and float taller than the steps beside
     it, matching neither the top nor the bottom of that column.
     The image is taken out of flow so its intrinsic height cannot size the
     row — otherwise `height: 100%` resolves against a row the image itself is
     inflating, and it stays taller than the text regardless. With it absolute,
     the steps column alone sets the height and both edges square off. */
  .how__media {
    position: relative;
    aspect-ratio: auto;
    max-width: none;
    height: 100%;
    min-height: 24rem;
  }

  .how__media img {
    position: absolute;
    inset: 0;
  }
}

/* =========================================================================
   PRICE — fast read, no imagery, offset column.
   ========================================================================= */

.price__inner {
  max-width: 34rem;
  display: grid;
  gap: var(--space-lg);
}

/* (A `.price h2` rule used to sit here. It never matched anything — the
   section is `#price` — and `.price-about h2` below now sizes both headings.) */

.price__figure {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--text-3xl);
  color: var(--color-accent);
  font-variant-numeric: tabular-nums;
}

/* =========================================================================
   ABOUT — quiet, text-only.
   ========================================================================= */

.about__inner {
  max-width: 38rem;
  display: grid;
  gap: var(--space-lg);   /* same as .price__inner so both columns share a rhythm */
  align-content: start;
}

/* Price and about share one row from 60rem up. Below that they stack, which
   is the same reading order either way. */
.price-about {
  display: grid;
  gap: var(--space-2xl);
}

@media (min-width: 60rem) {
  .price-about {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-3xl);
    align-items: start;
  }
}

/* Both headings, one size, so they sit on the same line across the band.
   They were mismatched because the old `.price h2` rule never applied — the
   section is `#price`, and nothing on the page carries a `price` class — so
   the price heading silently fell back to the base size while the about
   heading had an explicit override. */
.price-about h2 {
  font-size: var(--text-xl);
}

/* =========================================================================
   FINAL CTA — full-bleed darkened room photo, contact block on top.
   ========================================================================= */

.final-cta {
  position: relative;
  overflow: hidden;
  padding-block: var(--space-3xl);
}

.final-cta__media {
  position: absolute;
  inset: 0;
  z-index: var(--z-base);
}

.final-cta__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 30%;
  filter: brightness(0.4) saturate(0.85);
}

.final-cta__scrim {
  position: absolute;
  inset: 0;
  z-index: var(--z-raised);
  background: linear-gradient(180deg, var(--color-overlay-scrim) 0%, var(--color-scrim-strong) 100%);
}

.final-cta__content {
  position: relative;
  z-index: var(--z-dropdown);
  max-width: 34rem;
  display: grid;
  gap: var(--space-lg);
}

.final-cta h2 {
  font-size: var(--text-2xl);
}

.final-cta__actions {
  display: grid;
  gap: var(--space-md);
}

.final-cta__email {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-md);
  color: var(--color-ink);
  border-bottom: 1px solid var(--color-rule);
  width: fit-content;
}

.final-cta__email:hover {
  color: var(--color-accent);
  border-color: var(--color-accent);
}

@media (min-width: 40rem) {
  .final-cta__actions {
    grid-auto-flow: column;
    grid-auto-columns: max-content;
    justify-content: start;
  }
}

/* =========================================================================
   Generic responsive container safety
   ========================================================================= */

@media (max-width: 40rem) {
  section {
    padding-block: var(--space-2xl);
  }
}
