/* ============================================================
   DFI Remodeling, design system

   Structural direction. Three brand values only, taken straight
   from the logo artwork: near black, white, and the azure
   #2795D4 sampled from the REMODELING LLC wordmark and the
   house window squares.

   Neutrals are cool steel so they sit in the same hue family as
   the azure. The previous palette mixed warm neutrals with a
   cool accent, which is what made it read as slightly off.

   Type carries personality through role contrast: Archivo on its
   width axis for display, Archivo normal for body, IBM Plex Mono
   for labels and measurements.
   ============================================================ */

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }
img, picture, video, canvas, svg { display: block; max-width: 100%; }

/* Images carry width/height attributes so the browser can reserve space
   and avoid layout shift. Those attributes also act as presentational
   height hints, which override any aspect-ratio set in CSS. height:auto
   hands control back to the stylesheet. */
img { height: auto; }
input, button, textarea, select { font: inherit; color: inherit; }
p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }

/* ---------- Tokens ---------- */
:root {
  /* Ink and paper. The ink matches the logo field so the artwork
     sits on its own background in the header and footer. */
  --ink:          #0d0f12;
  --ink-soft:     #2c333b;
  --ink-muted:    #5a636e;
  --paper:        #fafbfc;
  --paper-raised: #ffffff;

  /* Cool steel neutrals, one family only, tuned to the azure hue */
  --steel-100: #f2f4f6;
  --steel-200: #e4e7eb;
  --steel-300: #cdd3da;
  --steel-400: #9ba5b1;

  /* The one accent. Sampled directly from logo.png, hue 202 at 82%
     saturation. Kept at full strength: it is the only colour on the
     site and desaturating it is what made the old palette generic.
     --accent-ink is the same hue darkened to clear WCAG AA (4.5:1)
     for body-size text and links on white. */
  --accent:       #2795d4;
  --accent-ink:   #10618f;
  --accent-hover: #1c7cb5;
  --accent-lift:  #58b0e2;   /* button hover, lighter so dark text stays legible */
  --accent-tint:  #eaf4fb;

  /* Shadows tinted to the ink hue, never neutral black */
  --shadow-sm: 0 1px 2px rgba(13, 15, 18, 0.06);
  --shadow-md: 0 8px 24px -10px rgba(13, 15, 18, 0.16);
  --shadow-lg: 0 24px 48px -20px rgba(13, 15, 18, 0.22);

  /* Fluid type scale */
  --step--1: clamp(0.87rem, 0.84rem + 0.14vw, 0.94rem);
  --step-0:  clamp(1.00rem, 0.96rem + 0.20vw, 1.13rem);
  --step-1:  clamp(1.25rem, 1.17rem + 0.38vw, 1.50rem);
  --step-2:  clamp(1.56rem, 1.42rem + 0.71vw, 2.03rem);
  --step-3:  clamp(1.95rem, 1.71rem + 1.20vw, 2.75rem);
  --step-4:  clamp(2.44rem, 2.03rem + 1.95vw, 3.71rem);

  /* Spacing */
  --space-2xs: 0.5rem;
  --space-xs:  0.75rem;
  --space-s:   1rem;
  --space-m:   1.5rem;
  --space-l:   2.5rem;
  --space-xl:  4rem;
  --space-2xl: 6rem;
  --space-3xl: 9rem;

  /* Tight radii. Soft pill corners read generic, and this is a
     company that builds square things to a measurement. */
  --radius:    4px;
  --radius-lg: 8px;

  --measure: 65ch;
  --shell:   1400px;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --dur:  0.32s;

  /* Three type roles. Display and body are the same family on
     different width axes, which keeps one webfont doing two jobs
     while still giving headlines a distinct voice. */
  --font: "Archivo", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* ---------- Base ---------- */
body {
  font-family: var(--font);
  font-size: var(--step-0);
  line-height: 1.65;
  color: var(--ink-soft);
  background: var(--paper);
}

h1, h2, h3, h4 {
  color: var(--ink);
  font-weight: 700;
  letter-spacing: -0.022em;
  line-height: 1.08;
  text-wrap: balance;
}

/* Display treatment. h1 is the only uppercase level, set on the wide
   end of the Archivo width axis to echo the mass of the italic DFI
   mark. h2 borrows the width but keeps sentence case, so the page has
   one shouting level rather than several. */
/* The clamp floor is lower than --step-4 because these headings are uppercase
   and set on the wide end of the width axis, so each character takes far more
   room than the scale assumes. At the old floor a single long word such as
   CONSTRUCTION was wider than a 390px phone. */
h1 {
  font-size: clamp(1.95rem, 1.35rem + 2.6vw, 3.71rem);
  font-stretch: 118%;
  text-transform: uppercase;
  letter-spacing: -0.012em;
  line-height: 0.98;
}
h2 { font-size: var(--step-3); font-stretch: 110%; }
h3 { font-size: var(--step-1); letter-spacing: -0.012em; line-height: 1.25; }
h4 { font-size: var(--step-0); letter-spacing: 0; line-height: 1.35; }

p { max-width: var(--measure); }

/* The reset zeroes every margin, so consecutive paragraphs need their
   spacing back or they run together as one block. */
p + p { margin-top: 1em; }

/* --accent-ink, not --accent: the full strength azure is 2.9:1 on
   white and fails AA for body-size text. */
a { color: var(--accent-ink); text-decoration-thickness: 1px; text-underline-offset: 3px; }

/* ---------- Layout ---------- */
.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 5vw, 4rem);
}

/* Section rhythm.
   These pad top AND bottom, so two stacked sections add up. At the old flat
   6rem that meant 192px of dead space between every section on the page,
   which read as the page having fallen apart rather than as breathing room.
   Halved and made responsive, so short viewports tighten further. */
.section    { padding-block: clamp(2rem, 4vw, 3rem); }
.section-lg { padding-block: clamp(3rem, 6vw, 4.5rem); }

/* A band sitting directly against another section does not need both its own
   top padding and its neighbour's bottom padding. */
.section + .section { padding-top: clamp(1.5rem, 3vw, 2.25rem); }

/* Asymmetric split. Collapses hard to one column under 900px. */
/* align-items:start, never center. Centering a short text block
   beside a tall image splits the height difference into dead space
   above and below the text. */
.split {
  display: grid;
  gap: var(--space-xl);
  grid-template-columns: 1fr;
  align-items: start;
}
@media (min-width: 900px) {
  .split       { grid-template-columns: 1.15fr 1fr; gap: clamp(3rem, 6vw, 6rem); }
  .split--wide { grid-template-columns: 1.6fr 1fr; }
  .split--flip > :first-child { order: 2; }
}

/* Grids, never flexbox percentage math */
.grid-2 { display: grid; gap: var(--space-m); grid-template-columns: 1fr; }
.grid-3 { display: grid; gap: var(--space-m); grid-template-columns: 1fr; }
@media (min-width: 700px)  { .grid-2 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .grid-3 { grid-template-columns: repeat(3, 1fr); } }

/* ---------- Dimension rule ----------
   The site's signature device. On a framing drawing a dimension is a
   hairline terminated in ticks with the measurement sitting in a gap.
   Section labels are set that way here: a mono label, then the line,
   then the closing tick. It reads as a measurement rather than as
   decoration, which is true to a company that builds to plans. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-ink);
  margin-bottom: var(--space-s);
}

/* Opening tick */
.eyebrow::before {
  content: "";
  width: 1px;
  height: 10px;
  background: var(--accent);
  flex: none;
}

/* The line itself, with the closing tick as a right border */
.eyebrow::after {
  content: "";
  flex: 1;
  height: 10px;
  border-right: 1px solid var(--accent);
  background: linear-gradient(
    to bottom,
    transparent calc(50% - 0.5px),
    var(--steel-300) calc(50% - 0.5px),
    var(--steel-300) calc(50% + 0.5px),
    transparent calc(50% + 0.5px)
  );
}

/* On the black header band and any dark section */
.eyebrow--invert { color: var(--accent); }
.eyebrow--invert::after {
  background: linear-gradient(
    to bottom,
    transparent calc(50% - 0.5px),
    rgba(255, 255, 255, 0.22) calc(50% - 0.5px),
    rgba(255, 255, 255, 0.22) calc(50% + 0.5px),
    transparent calc(50% + 0.5px)
  );
}

.lede { font-size: var(--step-1); color: var(--ink-soft); line-height: 1.5; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  min-height: 52px;            /* comfortably above the 48px tap target floor */
  padding: 0 var(--space-m);
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-size: var(--step-0);
  font-weight: 600;
  letter-spacing: -0.005em;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              transform 0.12s var(--ease),
              box-shadow var(--dur) var(--ease);
}
.btn:active { transform: translateY(1px) scale(0.99); }

/* Ink on azure, not white on azure. White on the full strength accent is
   3.3:1 and fails AA for button text. Darkening the background to pass
   would have meant giving up the brand colour on the highest value
   element on the page, so the text darkens instead. Ink on azure is
   5.8:1, and hover goes lighter rather than darker to keep it there. */
.btn--primary {
  background: var(--accent);
  color: var(--ink);
  box-shadow: var(--shadow-sm);
}
.btn--primary:hover { background: var(--accent-lift); box-shadow: var(--shadow-md); }

.btn--ghost {
  background: transparent;
  border-color: var(--steel-300);
  color: var(--ink);
}
.btn--ghost:hover { border-color: var(--ink); background: var(--steel-100); }

/* ---------- Forms. Label above input, error below. ---------- */
.field { display: grid; gap: var(--space-2xs); margin-bottom: var(--space-m); }
.field label { font-size: var(--step--1); font-weight: 600; color: var(--ink); }
.field input,
.field select,
.field textarea {
  min-height: 52px;
  padding: 0.75rem var(--space-s);
  border: 1px solid var(--steel-300);
  border-radius: var(--radius);
  background: var(--paper-raised);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.field textarea { min-height: 130px; padding-top: var(--space-s); resize: vertical; }
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-tint);
}
.field .hint  { font-size: var(--step--1); color: var(--ink-muted); }
.field .error { font-size: var(--step--1); color: #9b2c2c; }
.field[data-invalid="true"] input,
.field[data-invalid="true"] select,
.field[data-invalid="true"] textarea { border-color: #9b2c2c; }

/* ---------- Focus ---------- */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 3px; }

/* ---------- Entrance cascade. Transform and opacity only. ---------- */
.reveal {
  opacity: 0;
  transform: translateY(14px);
  animation: reveal 0.7s var(--ease) forwards;
  animation-delay: calc(var(--i, 0) * 90ms);
}
@keyframes reveal { to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .reveal { opacity: 1; transform: none; }
}

/* ---------- Utilities ---------- */
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: var(--space-s); top: -100px;
  background: var(--accent); color: #fff;
  padding: var(--space-2xs) var(--space-s);
  border-radius: var(--radius); z-index: 100;
  transition: top var(--dur) var(--ease);
}
.skip-link:focus { top: var(--space-s); }
