/* ==========================================================================
   Arco Outdoors — shared interior-page components
   Loaded *after* style.css on every page except the homepage. It adds only the
   patterns interior pages need; it never redefines a homepage component.
   All values come from the tokens declared in style.css.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Page banner — the interior-page counterpart to the homepage hero.
   Shorter, always carries exactly one H1, optionally backed by a photograph.
   -------------------------------------------------------------------------- */
.page-hero {
  position: relative;
  overflow: hidden;
  background-color: var(--ink-800);
  color: var(--cream);
}
.page-hero__media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.page-hero__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
    rgba(20, 16, 10, .86) 0%,
    rgba(20, 16, 10, .68) 55%,
    rgba(20, 16, 10, .42) 100%);
}
.page-hero__inner {
  position: relative;
  padding-block: 88px;
  max-width: 820px;
}
.page-hero h1 {
  font-weight: 600;
  font-size: clamp(36px, 4.6vw, 62px);
  line-height: 1.06;
  letter-spacing: -.01em;
  margin: 0 0 20px;
  color: var(--cream);
}
.page-hero h1 em { font-style: italic; color: var(--gold-light); }
.page-hero__lead {
  font-size: 17.5px;
  line-height: 1.7;
  color: rgba(253, 250, 243, .82);
  max-width: 620px;
  margin: 0;
}
.page-hero__actions { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 32px; }

/* Plain variant for legal / utility pages — no imagery, sand ground. */
.page-hero--plain { background: var(--sand-100); color: var(--ink); }
.page-hero--plain .page-hero__inner { padding-block: 64px; }
.page-hero--plain h1 { color: var(--ink); }
.page-hero--plain .page-hero__lead { color: var(--body); }

/* --------------------------------------------------------------------------
   2. Breadcrumbs — sits directly under the header, above the banner.
   -------------------------------------------------------------------------- */
.breadcrumb { background: var(--sand-100); border-bottom: 1px solid var(--hairline); }
.breadcrumb ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding-block: 14px;
  font-size: 12.5px;
  letter-spacing: .04em;
  color: var(--muted);
}
.breadcrumb li { display: flex; align-items: center; gap: 8px; }
.breadcrumb li + li::before {
  content: "/";
  color: var(--gold-deep);
  font-size: 12px;
}
.breadcrumb a { color: var(--body); }
.breadcrumb a:hover { color: var(--gold-link); }
.breadcrumb [aria-current="page"] { color: var(--ink); font-weight: 600; }

/* --------------------------------------------------------------------------
   3. Prose — long-form body copy (service detail, legal pages, articles).
   -------------------------------------------------------------------------- */
.prose { max-width: 74ch; color: var(--body); font-size: 17px; line-height: 1.8; }
.prose > * + * { margin-top: 22px; }
.prose h2 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(28px, 3vw, 40px);
  line-height: 1.14;
  color: var(--ink);
  margin-top: 52px;
}
.prose h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 24px;
  line-height: 1.25;
  color: var(--ink);
  margin-top: 38px;
}
.prose h4 {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--gold-link);
  margin-top: 32px;
}
.prose strong { color: var(--ink); font-weight: 700; }
.prose a { text-decoration: underline; text-underline-offset: 3px; }
.prose ul, .prose ol { padding-left: 0; }
.prose ul li, .prose ol li {
  position: relative;
  padding-left: 26px;
  margin-top: 12px;
}
.prose ul li::before {
  content: "✦";
  position: absolute;
  left: 0;
  top: -1px;
  color: var(--gold-deep);
  font-family: var(--font-display);
  font-size: 15px;
}
.prose ol { counter-reset: prose-list; }
.prose ol li { counter-increment: prose-list; }
.prose ol li::before {
  content: counter(prose-list) ".";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--gold-link);
  font-weight: 700;
  font-size: 15px;
}
.prose blockquote {
  margin: 32px 0;
  padding: 4px 0 4px 26px;
  border-left: 2px solid var(--gold-deep);
  font-family: var(--font-display);
  font-style: italic;
  font-size: 21px;
  line-height: 1.55;
  color: #332b20;
}
.prose figure { margin: 32px 0; }
.prose figure img { width: 100%; height: auto; }
.prose figcaption { margin-top: 10px; font-size: 13.5px; color: var(--muted); }
.prose hr { border: 0; border-top: 1px solid var(--hairline); margin: 44px 0; }

/* --------------------------------------------------------------------------
   4. Split layout — copy beside a supporting image or panel.
   -------------------------------------------------------------------------- */
.split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 64px;
  align-items: center;
}
.split--top { align-items: start; }
.split__media { margin: 0; position: relative; }
.split__media img {
  width: 100%;
  height: 460px;
  object-fit: cover;
  background: var(--sand-200);
  box-shadow: var(--sh-image);
}
.split--reverse .split__media { order: -1; }

/* Article body with a sticky rail (service pages, blog posts). */
.with-rail {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 330px;
  gap: 64px;
  align-items: start;
}
.rail { position: sticky; top: 150px; display: flex; flex-direction: column; gap: 24px; }
.rail__card {
  background: var(--sand-100);
  border: 1px solid var(--hairline);
  padding: 30px 28px;
}
.rail__card h2, .rail__card h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 22px;
  color: var(--ink);
  margin: 0 0 14px;
}
.rail__card p { font-size: 14.5px; line-height: 1.7; color: var(--body); margin: 0 0 20px; }
.rail__card--dark { background: var(--ink); border-color: transparent; color: var(--cream); }
.rail__card--dark h2, .rail__card--dark h3 { color: var(--gold-light); }
.rail__card--dark p { color: rgba(253, 250, 243, .75); }

/* --------------------------------------------------------------------------
   5. Feature list — numbered process steps or capability blocks.
   -------------------------------------------------------------------------- */
.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 40px;
  counter-reset: step;
}
/* The homepage process is eight steps and has to read as two even rows of four.
   auto-fit alone would give five-and-three on a wide viewport, so the column
   count is pinned once there is room for four. */
@media (min-width: 1000px) {
  .steps { grid-template-columns: repeat(4, 1fr); }
}
.steps > li {
  counter-increment: step;
  border-top: 1px solid var(--gold-deep);
  padding-top: 24px;
}
.steps > li::before {
  content: "0" counter(step);
  display: block;
  font-family: var(--font-display);
  font-size: 34px;
  font-weight: 600;
  /* Large text still needs 3:1. --gold-deep manages only 2.14:1 on sand; this
     is the same gold at the lightness that clears it (see PROJECT-SPEC §15). */
  color: var(--gold-figure);
  line-height: 1;
  margin-bottom: 14px;
}
.steps h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 23px;
  color: var(--ink);
  margin: 0 0 10px;
}
.steps p { font-size: 14.5px; line-height: 1.7; color: var(--body); margin: 0; }

/* --------------------------------------------------------------------------
   6. FAQ — native disclosure, no JavaScript required.
   -------------------------------------------------------------------------- */
.faq { border-top: 1px solid var(--hairline); max-width: 860px; }
.faq details { border-bottom: 1px solid var(--hairline); }
.faq summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  padding: 24px 0;
  font-family: var(--font-display);
  font-size: 21px;
  font-weight: 600;
  color: var(--ink);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+";
  flex: none;
  font-family: var(--font-body);
  font-size: 22px;
  font-weight: 400;
  color: var(--gold-link);
  line-height: 1.1;
  transition: transform var(--dur) var(--ease);
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq details > *:not(summary) {
  font-size: 15.5px;
  line-height: 1.8;
  color: var(--body);
  margin: 0 0 24px;
  max-width: 72ch;
}

/* --------------------------------------------------------------------------
   7. Location / link index — service-area and services hub pages.
   -------------------------------------------------------------------------- */
.link-index {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 18px;
}
.link-index a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 22px 24px;
  background: var(--sand-50);
  border: 1px solid var(--hairline);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 21px;
  font-weight: 600;
  transition: box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.link-index a::after {
  content: "→";
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--gold-link);
  transition: transform var(--dur) var(--ease);
}
.link-index a:hover, .link-index a:focus-visible {
  box-shadow: var(--sh-card-hover);
  border-color: rgba(198, 151, 73, .5);
}
.link-index a:hover::after { transform: translateX(5px); }
.link-index span {
  display: block;
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 400;
  color: var(--body);
  margin-top: 5px;
}

/* --------------------------------------------------------------------------
   8. Fact table — specification and comparison data.
   -------------------------------------------------------------------------- */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
/* The container scrolls, so it carries tabindex="0" and needs a focus ring. */
.table-wrap:focus-visible { outline: 3px solid var(--gold-link); outline-offset: 3px; }
.table-wrap table {
  width: 100%;
  min-width: 520px;
  border-collapse: collapse;
  font-size: 15px;
}
.table-wrap caption {
  text-align: left;
  font-size: 13px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
  padding-bottom: 12px;
}
.table-wrap th, .table-wrap td {
  text-align: left;
  padding: 15px 18px;
  border-bottom: 1px solid var(--hairline);
  vertical-align: top;
}
.table-wrap thead th {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--body);
  background: var(--sand-100);
}
.table-wrap tbody th { font-weight: 700; color: var(--ink); }

/* --------------------------------------------------------------------------
   9. Inline CTA band — mid-page conversion prompt.
   -------------------------------------------------------------------------- */
/* A prose link inside the dark band must not inherit --gold-link, which is
   tuned for sand grounds and drops to 2.98:1 on ink. Same treatment as
   .section--ink a. Buttons are excluded: they carry their own grounds. */
.cta-band a:not(.btn) { color: var(--gold-light); }
.cta-band a:not(.btn):hover,
.cta-band a:not(.btn):focus-visible { color: var(--cream); }
.rail__card--dark a:not(.btn) { color: var(--gold-light); }

.cta-band {
  background: var(--ink);
  color: var(--cream);
  padding: 44px 40px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 28px;
}
.cta-band h2, .cta-band h3 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(24px, 2.6vw, 32px);
  line-height: 1.2;
  color: var(--cream);
  margin: 0;
  max-width: 30ch;
}
.cta-band p { font-size: 15px; line-height: 1.7; color: rgba(253, 250, 243, .75); margin: 10px 0 0; max-width: 46ch; }
.cta-band__actions { display: flex; flex-wrap: wrap; gap: 14px; }

/* --------------------------------------------------------------------------
   10. Pagination — blog index.
   -------------------------------------------------------------------------- */
.pagination {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  justify-content: center;
  margin-top: 56px;
}
.pagination a, .pagination span {
  min-width: 44px;
  padding: 12px 16px;
  text-align: center;
  border: 1px solid var(--hairline-2);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .08em;
  color: var(--ink);
}
.pagination a:hover { background: var(--ink); color: var(--sand-50); border-color: var(--ink); }
.pagination [aria-current="page"] { background: var(--gold); border-color: var(--gold); }

/* --------------------------------------------------------------------------
   11. Article meta — byline / date row for journal entries.
   -------------------------------------------------------------------------- */
.article-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 18px;
  font-size: 12.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 26px;
}
.article-meta .dot { width: 4px; height: 4px; border-radius: 50%; background: var(--gold-deep); }

/* --------------------------------------------------------------------------
   12. Utility
   -------------------------------------------------------------------------- */
.text-center { text-align: center; }
.stack-sm > * + * { margin-top: 14px; }
.stack-md > * + * { margin-top: 26px; }
.stack-lg > * + * { margin-top: 44px; }

/* --------------------------------------------------------------------------
   13. Responsive
   -------------------------------------------------------------------------- */
@media (max-width: 1024px) {
  .with-rail { grid-template-columns: 1fr; gap: 48px; }
  .rail { position: static; }
}

@media (max-width: 860px) {
  .page-hero__inner { padding-block: 56px; }
  .page-hero--plain .page-hero__inner { padding-block: 40px; }
  .split { gap: 40px; }
  .split__media img { height: 320px; }
  .split--reverse .split__media { order: 0; }
  .steps { gap: 30px; }
  .cta-band { padding: 32px 22px; }
  .prose { font-size: 16.5px; }
}

/* --------------------------------------------------------------------------
   14. Service-page components (added for /services/)
   -------------------------------------------------------------------------- */

/* Left-aligned section header — the hub's category bands read as a stack of
   labelled groups rather than a run of centred announcements. */
.section-head--left {
  text-align: left;
  max-width: 62ch;
  margin: 0 0 44px;
}
.section-head--left .eyebrow { justify-content: flex-start; }
.section-head--left .eyebrow::after { content: none; }
.section-head--left p.lead { margin-top: 16px; }

/* Callout — climate notes, scope caveats, anything the reader should not skim. */
.note {
  border-left: 3px solid var(--gold-deep);
  background: var(--sand-100);
  padding: 26px 30px;
  max-width: 74ch;
}
.note > * + * { margin-top: 14px; }
.note h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 21px;
  color: var(--ink);
  margin: 0;
}
.note p { font-size: 15.5px; line-height: 1.8; color: var(--body); margin: 0; }
.note--onDark {
  background: rgba(255, 255, 255, .04);
  border-left-color: var(--gold);
}
.note--onDark h3 { color: var(--gold-light); }
.note--onDark p { color: rgba(253, 250, 243, .78); }

/* Category card grid — the homepage `.card` frame, with a compact media box. */
.card--service .card__media img { height: 200px; }
.card--service .card__body { padding: 26px 26px 30px; }
.card--service .card__title { font-size: 24px; }

/* Feature card — one service given the full width of the grid. */
.card--feature {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: 0;
  align-items: stretch;
}
.card--feature .card__media img { height: 100%; min-height: 320px; }
.card--feature .card__body { padding: 44px 46px; justify-content: center; }
.card--feature .card__title { font-size: 32px; margin-bottom: 16px; }
.card--feature .card__text { font-size: 16px; flex: none; }

/* Two-column definition list for material / option comparisons. */
.spec-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 30px 40px;
}
.spec-grid > div { border-top: 1px solid var(--hairline-2); padding-top: 20px; }
.spec-grid h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 21px;
  color: var(--ink);
  margin: 0 0 10px;
}
.spec-grid p { font-size: 14.5px; line-height: 1.75; color: var(--body); margin: 0; }

/* Compact eight-market strip — the "Areas we serve" block on service pages.
   Constrained so the eight priority markets read as two rows of four rather
   than one long row with two orphans. */
.areas-grid--compact { max-width: 800px; }

/* Anchor row — jump links to the sections of a long service page. */
.jumpbar { background: var(--sand-100); border-bottom: 1px solid var(--hairline); }
.jumpbar ul {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 26px;
  padding-block: 16px;
}
.jumpbar a {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--body);
}
.jumpbar a:hover, .jumpbar a:focus-visible { color: var(--gold-link); }

@media (max-width: 860px) {
  .card--feature { grid-template-columns: 1fr; }
  .card--feature .card__media img { min-height: 220px; height: 220px; }
  .card--feature .card__body { padding: 30px 26px 34px; }
  .card--feature .card__title { font-size: 27px; }
  .note { padding: 22px 22px; }
  .section-head--left { margin-bottom: 32px; }
}

/* --------------------------------------------------------------------------
   15. Project index (added for /projects/)

   Three components, all reusable:

     .section--ink   a dark band without the .why texture image, for sections
                     that need contrast but have no photograph to carry it
     .filterbar      a chip row that filters a following grid by tag
     .work-card      a text-forward record card — deliberately not a photo
                     card, because /projects/ documents work and /gallery/
                     shows it, and the two must not look interchangeable

   The filter bar is hidden until main.js adds `.filter-on` to <html>. That is
   the same gate `.reveal-on` uses (§18 of style.css) and it exists for the
   same reason: if the script fails to load, every card stays visible and the
   page degrades to a plain list rather than to a dead control.
   -------------------------------------------------------------------------- */

.section--ink { background: var(--ink); color: var(--cream); }
.section--ink .section-head--left p.lead,
.lead--onDark { color: rgba(253, 250, 243, .74); }
.section--ink a { color: var(--gold-light); }
.section--ink a:hover, .section--ink a:focus-visible { color: var(--cream); }
/* Components dropped into a dark band keep their structure and swap ink for
   cream. Without this a .spec-grid renders --ink text on --ink ground. */
.section--ink .spec-grid > div { border-top-color: rgba(224, 169, 78, .38); }
.section--ink .spec-grid h3 { color: var(--gold-light); }
.section--ink .spec-grid p,
.section--ink .prose p { color: rgba(253, 250, 243, .74); }

.steps--onDark > li { border-top-color: rgba(224, 169, 78, .38); }
.steps--onDark > li::before { color: var(--gold); }
.steps--onDark h3 { color: var(--gold-light); }
.steps--onDark p { color: rgba(253, 250, 243, .74); }

/* --- Filter bar ----------------------------------------------------------- */
.filterbar { display: none; }
.filter-on .filterbar {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 22px;
}
.filterbar__chip {
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--body);
  background: transparent;
  border: 1px solid var(--hairline-2);
  border-radius: var(--r-pill);
  padding: 9px 17px;
  cursor: pointer;
  transition: background .18s ease, border-color .18s ease, color .18s ease;
}
.filterbar__chip:hover { border-color: var(--gold-deep); color: var(--ink); }
.filterbar__chip[aria-pressed="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--sand-50);
}
.filterbar__n { opacity: .6; margin-left: 4px; font-variant-numeric: tabular-nums; }

.filter-status {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--body);
  margin: 0 0 34px;
  min-height: 1em;
}
.filter-empty { font-size: 15.5px; color: var(--body); margin-top: 28px; }
.linklike {
  font: inherit;
  color: var(--gold-link);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.linklike:hover, .linklike:focus-visible { color: var(--ink); }

/* --- Work cards ----------------------------------------------------------- */
.work-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(310px, 1fr));
  gap: 26px;
}
.work-card {
  display: flex;
  flex-direction: column;
  background: var(--cream);
  border: 1px solid var(--hairline-2);
  border-radius: var(--r-sm);
  padding: 28px 28px 26px;
}
/* `hidden` must beat `display:flex`. */
.work-card[hidden] { display: none; }
.work-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 0 16px;
}
.work-card__tag {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--gold-link);
  border: 1px solid var(--hairline-2);
  border-radius: 3px;
  padding: 4px 8px;
}
.work-card h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 22px;
  line-height: 1.25;
  color: var(--ink);
  margin: 0 0 12px;
}
.work-card > p { font-size: 14.5px; line-height: 1.75; color: var(--body); margin: 0; }
.work-card__link { margin-top: auto; padding-top: 20px; }
.work-card__link a {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--gold-link);
}
.work-card__link a:hover, .work-card__link a:focus-visible {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 4px;
}

/* --- The empty-record panel ----------------------------------------------- */
.record-empty {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 34px;
  align-items: start;
  background: var(--cream);
  border: 1px solid var(--hairline-2);
  border-left: 3px solid var(--gold-deep);
  padding: 36px 40px;
  max-width: 900px;
}
.record-empty__count {
  font-family: var(--font-display);
  font-size: 82px;
  font-weight: 600;
  line-height: .9;
  color: var(--gold-figure);
  /* Cormorant Garamond defaults to old-style figures, which renders this as an
     x-height "o" rather than a full-height zero. */
  font-variant-numeric: lining-nums;
  font-feature-settings: "lnum" 1;
}
.record-empty__body h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 23px;
  color: var(--ink);
  margin: 0 0 14px;
}
.record-empty__body p { font-size: 15.5px; line-height: 1.8; color: var(--body); margin: 0; }
.record-empty__body p + p { margin-top: 14px; }

@media (max-width: 640px) {
  .record-empty { grid-template-columns: 1fr; gap: 14px; padding: 28px 24px; }
  .record-empty__count { font-size: 58px; }
  .work-card { padding: 24px 22px; }
  .filter-on .filterbar { gap: 8px; }
  .filterbar__chip { font-size: 12px; padding: 8px 14px; }
}

/* --------------------------------------------------------------------------
   16. Photo grid (added for /gallery/)

   Captions sit BELOW the image rather than overlaid on it. The homepage
   `.gallery-item` overlays them, which looks better and reads worse: white
   text on an arbitrary photograph has no guaranteed contrast, and the caption
   is the part of this page that has to be legible, because it is the part
   making a claim about what you are looking at.

   Uniform 4:3 boxes, so the grid does not reflow when the filter changes.
   -------------------------------------------------------------------------- */

.photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
  gap: 28px;
}
.photo {
  margin: 0;
  display: flex;
  flex-direction: column;
  background: var(--cream);
  border: 1px solid var(--hairline-2);
}
/* `hidden` must beat `display:flex` for the filter. */
.photo[hidden] { display: none; }
.photo img {
  width: 100%;
  aspect-ratio: 4 / 3;
  height: auto;
  object-fit: cover;
  background: var(--sand-200);
}
.photo figcaption { padding: 18px 20px 20px; }
.photo__name {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 19px;
  line-height: 1.3;
  color: var(--ink);
}
.photo__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 12px;
}
.photo__tag {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--gold-link);
  border: 1px solid var(--hairline-2);
  border-radius: 3px;
  padding: 4px 7px;
}

@media (max-width: 640px) {
  .photo-grid { grid-template-columns: 1fr; gap: 20px; }
  .photo figcaption { padding: 16px 16px 18px; }
}

/* --------------------------------------------------------------------------
   17. Review components (added for /reviews/)

   `.review-card` is built and documented but NOT rendered anywhere yet: no
   review in this repository is verified, so publishing one would be
   fabrication. See PROJECT-SPEC.md §11.2. The component exists so that real
   reviews drop straight in without a design pass, and so the standard for
   what a published review must carry is written down alongside its markup.
   -------------------------------------------------------------------------- */

.review-card {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
  background: var(--cream);
  border: 1px solid var(--hairline-2);
  border-radius: var(--r-sm);
  padding: 30px 30px 26px;
}
.review-card blockquote {
  margin: 0;
  font-size: 16px;
  line-height: 1.75;
  color: var(--body-2);
}
.review-card figcaption {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-top: auto;
  padding-top: 6px;
}
.review-card__name { font-weight: 700; font-size: 14px; color: var(--ink); }
.review-card__meta { font-size: 12.5px; color: var(--muted); }

/* Checklist used on /reviews/ — a practice beside a plain yes or never.
   The shared `.table-wrap thead th` ground is --sand-100, which disappears
   inside a .section--sand band, so this variant carries its own. */
.claim-table { min-width: 460px; }
.claim-table thead th { background: var(--ink); color: var(--cream); }
.claim-table td:last-child { width: 1%; white-space: nowrap; }
.claim-yes, .claim-no {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
}
/* Both pass 4.5:1 on the cream and sand grounds this table sits on. */
.claim-yes { color: #2f6b3d; }
.claim-no  { color: #8c3a2b; }

/* --------------------------------------------------------------------------
   18. Contact and quote pages (added for /contact-us/ and /get-a-quote/)
   -------------------------------------------------------------------------- */

/* A phone number, email address or address block given the display face, so
   the details people came for read as the largest thing in their block.
   `.spec-grid p` sets 14.5px with a higher specificity than a bare class, so
   the grid context is named explicitly rather than fought with !important. */
.contact-line,
.spec-grid p.contact-line {
  display: block;
  font-family: var(--font-display);
  font-size: 25px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--gold-link);
  margin: 0 0 10px;
}
a.contact-line:hover, a.contact-line:focus-visible {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 4px;
}
/* Address and hours are facts rather than links, so they lose the link colour
   and drop a step in size — three lines at the full size would out-shout the
   phone number, which is the thing most visitors came for. */
.contact-line__plain {
  display: block;
  color: var(--ink);
  font-size: 20px;
  line-height: 1.45;
}

/* Marks an optional control without shouting; the required ones carry *. */
.field-optional {
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--muted);
}

/* Radio and checkbox groups inside a form panel. A fieldset is used so the
   group has a programmatic name; the legend is styled to match a field label. */
.field-group { border: 0; margin: 0 0 16px; padding: 0; }
.field-group legend {
  display: block;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--body-2);
  margin-bottom: 10px;
  padding: 0;
}
.field-choices { display: flex; flex-wrap: wrap; gap: 8px 20px; }
.field-choices label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 14.5px;
  color: var(--body-2);
  cursor: pointer;
}
.field-choices input { accent-color: var(--gold-deep); }

/* The quote page runs the form beside a supporting column rather than inside
   a narrow card, so the panel is allowed more room than the homepage one. */
.quote-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: 56px;
  align-items: start;
}
@media (max-width: 1024px) {
  .quote-layout { grid-template-columns: 1fr; gap: 44px; }
}
@media (max-width: 860px) {
  .contact-line { font-size: 22px; }
}

/* --------------------------------------------------------------------------
   19. Legal pages (added for /privacy-policy/, /cookie-policy/, /accessibility/)
   -------------------------------------------------------------------------- */

/* `kbd` and `code` appear only in the accessibility statement, where naming a
   key or an element precisely is clearer than describing it. Styled so they
   read as part of the page rather than as browser-default monospace. */
.prose kbd,
.spec-grid kbd {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .85em;
  padding: 2px 7px;
  border: 1px solid var(--hairline-2);
  border-bottom-width: 2px;
  border-radius: 3px;
  background: var(--white);
  color: var(--ink);
  white-space: nowrap;
}
.prose code,
.spec-grid code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .88em;
  color: var(--ink);
  background: rgba(36, 29, 21, .05);
  padding: 1px 5px;
  border-radius: 3px;
}

/* The legal pages open on a plain banner rather than photography — there is no
   image that honestly illustrates a privacy notice — so the eyebrow and lead
   carry the page on their own and want a little more breathing room. */
.page-hero--plain .page-hero__lead { max-width: 62ch; }


/* --------------------------------------------------------------------------
   20. Project gallery (added for /projects/)

   Client photography arrives from ImageKit at unknown proportions — portrait
   phone shots beside landscape ones — so the grid is CSS multi-column rather
   than a row grid. Columns let every photograph keep its natural aspect ratio
   with no cropping at all, which a fixed-ratio grid cannot do without either
   letterboxing or cutting the subject out of frame.

   Hidden items carry the `hidden` attribute, so they are out of flow entirely
   and reserve no space until Load More reveals them.
   -------------------------------------------------------------------------- */

.pgallery {
  columns: 3;
  column-gap: 24px;
}
.pgallery__item {
  margin: 0 0 24px;
  /* Never split a photograph across a column boundary. */
  break-inside: avoid;
  page-break-inside: avoid;
  background: var(--sand-200);
}
.pgallery__item[hidden] { display: none; }

.pgallery__link {
  display: block;
  position: relative;
  overflow: hidden;
  background: var(--sand-200);
}
.pgallery__link img {
  display: block;
  width: 100%;
  height: auto;
  transition: transform .5s var(--ease);
}
.pgallery__link:hover img,
.pgallery__link:focus-visible img { transform: scale(1.03); }
.pgallery__link:focus-visible { outline: 3px solid var(--gold-link); outline-offset: 3px; }

/* A thin inset rule on hover rather than a heavier overlay. */
.pgallery__link::after {
  content: "";
  position: absolute;
  inset: 10px;
  border: 1px solid rgba(253, 250, 243, .55);
  opacity: 0;
  transition: opacity .3s var(--ease);
  pointer-events: none;
}
.pgallery__link:hover::after,
.pgallery__link:focus-visible::after { opacity: 1; }

/* Real proportions are unknown until each photograph arrives, so reserve a
   plausible box and release it on load. Gated on `.js` because only the script
   removes it — without JavaScript the images simply size themselves. Caps
   layout shift without ever cropping or distorting a photograph. */
.js .pgallery__item:not(.is-loaded) { min-height: 220px; }

.pgallery__more {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  margin-top: 44px;
}
.pgallery__count {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
  min-height: 1em;
}

@media (max-width: 1024px) {
  .pgallery { columns: 2; column-gap: 20px; }
  .pgallery__item { margin-bottom: 20px; }
}
@media (max-width: 560px) {
  .pgallery { columns: 1; }
}

/* --------------------------------------------------------------------------
   21. Lightbox (added for /projects/)

   Vanilla, no library. Carries the `hidden` attribute so it stays out of the
   accessibility tree until it is opened.
   -------------------------------------------------------------------------- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 64px 24px;
}
.lightbox[hidden] { display: none; }
.lightbox__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(16, 12, 8, .93);
  animation: lb-fade .2s var(--ease);
}
.lightbox__figure {
  position: relative;
  margin: 0;
  max-width: min(1600px, 100%);
  max-height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.lightbox__img {
  max-width: 100%;
  max-height: calc(100vh - 128px);
  width: auto;
  height: auto;
  object-fit: contain;
  box-shadow: 0 40px 80px rgba(0, 0, 0, .5);
  animation: lb-in .24s var(--ease);
}

.lightbox__btn {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  /* 48px keeps every control at the touch-target minimum. */
  width: 48px;
  height: 48px;
  border: 1px solid rgba(253, 250, 243, .3);
  background: rgba(20, 16, 10, .6);
  color: var(--cream);
  cursor: pointer;
  transition: background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
}
.lightbox__btn:hover,
.lightbox__btn:focus-visible { background: var(--gold); border-color: var(--gold); color: var(--ink); }
.lightbox__btn:focus-visible { outline: 3px solid var(--cream); outline-offset: 3px; }
.lightbox__btn--close { top: 16px; right: 16px; }
.lightbox__btn--prev  { left: 16px;  top: 50%; transform: translateY(-50%); }
.lightbox__btn--next  { right: 16px; top: 50%; transform: translateY(-50%); }

.lightbox__counter {
  position: absolute;
  left: 0; right: 0; bottom: 20px;
  text-align: center;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: rgba(253, 250, 243, .7);
  margin: 0;
}

@keyframes lb-fade { from { opacity: 0 } to { opacity: 1 } }
@keyframes lb-in   { from { opacity: 0; transform: scale(.98) } to { opacity: 1; transform: none } }

@media (max-width: 640px) {
  .lightbox { padding: 72px 12px 76px; }
  .lightbox__img { max-height: calc(100vh - 148px); }
  .lightbox__btn { width: 46px; height: 46px; }
  .lightbox__btn--prev { left: 10px; top: auto; bottom: 16px; transform: none; }
  .lightbox__btn--next { right: 10px; top: auto; bottom: 16px; transform: none; }
  .lightbox__counter { bottom: 30px; }
}

@media (prefers-reduced-motion: reduce) {
  .pgallery__link img { transition: none; }
  .pgallery__link:hover img,
  .pgallery__link:focus-visible img { transform: none; }
  .lightbox__backdrop, .lightbox__img { animation: none; }
}


/* --------------------------------------------------------------------------
   Spacing utilities  (added pass 16)

   These replace 283 inline style attributes that had accumulated across the
   pages -- almost all one-line spacing tweaks repeated dozens of times
   (margin-top:0 alone appeared 98 times). A deliberately small, closed set of
   the patterns that actually recurred, not a general utility framework: a new
   spacing value belongs in its component's own rule, not here.

   Two things about the form of these selectors, both learned the hard way when
   the first attempt made every page taller:

   1. They live at the END of pages.css, the last stylesheet the page loads, so
      they win any specificity tie against a component rule.
   2. The class is doubled (.u-mt-0.u-mt-0) to raise specificity to (0,2,0).
      An inline style beats every selector; a single class does not, so
      .prose h2 { margin-top: 40px } (0,1,1) quietly swallowed the utility and
      the spacing it was supposed to remove came back. Doubling is the standard
      way to buy specificity without !important, which this codebase avoids.

   The point is not bytes -- inline styles are small and do not block rendering
   -- it is that one decision now lives in one place, and that the markup no
   longer needs 'unsafe-inline' in a style-src Content-Security-Policy. Forty-six
   genuinely one-off declarations were left inline on purpose.
   -------------------------------------------------------------------------- */
.u-mt-0.u-mt-0   { margin-top: 0; }
.u-mt-32.u-mt-32 { margin-top: 32px; }
.u-mt-36.u-mt-36 { margin-top: 36px; }
.u-mt-40.u-mt-40 { margin-top: 40px; }
.u-mt-44.u-mt-44 { margin-top: 44px; }
.u-mt-48.u-mt-48 { margin-top: 48px; }
.u-mt-52.u-mt-52 { margin-top: 52px; }
.u-mb-0.u-mb-0   { margin-bottom: 0; }
.u-m-0.u-m-0     { margin: 0; }
.u-mw-none.u-mw-none       { max-width: none; }
.u-gap-30.u-gap-30         { gap: 30px; }
.u-gap-56.u-gap-56         { gap: 56px; }
.u-pb-section.u-pb-section { padding-bottom: var(--section-y); }
