/* DS-05 -- section layouts.
 *
 * Grid tracks are minmax(0, 1fr) everywhere. A bare 1fr has min-width: auto,
 * so one long service name pushes its track past its share and overflows the
 * document at 320px, which is the most common way these builds fail the
 * responsive gate.
 *
 * Nothing here draws a card. A card is a raised rectangle with a shadow and
 * this design has neither; the equivalent unit is a region of the plane
 * separated from the next by a single metallic hairline.
 */

.grid { display: grid; gap: var(--s5); margin: 0; padding: 0; list-style: none; }

.ratio { position: relative; }
.ratio img { display: block; width: 100%; height: auto; }

/* ---- hero: one static low-key plate ----------------------------------- */
/*
 * Source order is text, then plate, at every width -- section 6 requires the
 * H1, the proposition, Book and the secondary link inside the first viewport,
 * and a photograph placed above them on a 320x568 screen pushes the actions
 * off it.
 *
 * At 1024 the two stack into ONE grid area and the copy sits in the bottom
 * left of the photograph, over a scrim. That is the only arrangement in which
 * the plate is both the first thing painted and the LCP element the
 * specification names. The scrim is opaque enough that the worst case -- a
 * blown-out white region of the photograph directly behind the lede -- still
 * measures over 5:1 for the muted text and over 13:1 for the ink.
 */

.hero { padding-block: var(--s7) var(--s8); }

.hero__wrap { display: grid; gap: var(--s6); }

.hero__eyebrow {
  font-size: .8125rem;
  line-height: 1.35;
  letter-spacing: .3em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--muted);
  margin: 0 0 var(--s5);
}

/* MATERIAL DISTINCTNESS: sparse asymmetric planes, never a dark card stack. */
@media (min-width: 1100px) {
  body.p-index main { display:grid; grid-template-columns:repeat(12,minmax(0,1fr)); align-items:start; background:var(--bg); }
  body.p-index main > .sec { min-width:0; margin:0; border:0; }
  body.p-index main > .sec > .wrap { width:auto; max-width:none; }
  body.p-index .hero { grid-column:1/-1; min-height:100svh; }
  body.p-index .svcp { grid-column:2/8; padding-block:12rem; }
  body.p-index .appr { grid-column:8/12; margin-top:20rem; padding-block:7rem; border-top:1px solid var(--gold); }
  body.p-index .galp { grid-column:1/-1; padding-block:14rem; }
  body.p-index .galp__list { grid-template-columns:2fr 1fr; align-items:end; }
  body.p-index .galp__item:first-child { grid-row:span 2; }
  body.p-index .stfp { grid-column:3/11; padding-block:14rem; }
  body.p-index .revp { grid-column:1/7; padding-block:12rem; }
  body.p-index .faqp { grid-column:8/-1; margin-top:12rem; padding-block:10rem; }
  body.p-index .cta { grid-column:1/-1; min-height:70svh; display:grid; align-items:center; }
}

.hero__lede {
  max-width: var(--measure);
  font-size: 1.125rem;
  color: var(--ink);
  margin: var(--s5) 0 var(--s6);
}

.hero__acts { display: flex; flex-wrap: wrap; gap: var(--s4); align-items: center; }

/* Two actions share a row only while each keeps 148px. Below that they stack
   on the flex gap, with no media query needed to say so. */
.hero__acts .btn { min-width: 148px; }

.hero__second {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: .9375rem;
}

.hero__fig { position: relative; margin: 0; }

.hero__plate {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  /* The hairline frame is an inset shadow, so it takes no layout space and
     the `sizes` promise in the markup stays exactly true. */
  box-shadow: inset 0 0 0 1px var(--ruleg);
  aspect-ratio: 4 / 3;
  background: var(--plane);
}

.hero__plate img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* ---- the soft spotlight ----------------------------------------------- */
/*
 * The signature effect, and the only animation in the build: one 600ms fade
 * of a radial gradient over the plate, played once on load. It moves nothing,
 * so it cannot shift layout, and section 4's animation-off state -- "spotlight
 * remains a static gradient" -- is reached by not playing it rather than by
 * removing it.
 */

.hero__glow {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(62% 58% at 26% 22%,
      rgba(255, 255, 255, .58) 0%,
      rgba(255, 255, 255, .22) 42%,
      rgba(255, 255, 255, 0) 72%),
    radial-gradient(90% 90% at 78% 96%,
      rgba(26, 24, 37, .34) 0%,
      rgba(26, 24, 37, 0) 68%);
  animation: ac-spot var(--t-long) ease-out both;
}

@keyframes ac-spot {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.hero__cap {
  margin-top: var(--s4);
  font-size: .8125rem;
  color: var(--muted);
}

@media (min-width: 768px) { .hero__plate { aspect-ratio: 3 / 2; } }

@media (min-width: 1024px) {
  .hero__wrap { grid-template-areas: "plate"; }
  .hero__text, .hero__fig { grid-area: plate; }

  .hero__plate { aspect-ratio: 16 / 9; }

  /* the scrim, applied only where the copy actually sits on the plate */
  .hero__plate::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(to top,
      rgba(10, 12, 14, .64) 0%,
      rgba(10, 12, 14, .40) 38%,
      rgba(10, 12, 14, .22) 64%,
      rgba(10, 12, 14, .02) 100%);
  }

  .hero__text {
    position: relative;
    z-index: 2;
    align-self: end;
    max-width: 42rem;
    padding: var(--s8);
  }

  .hero__cap {
    position: absolute;
    z-index: 2;
    inset-block-end: var(--s6);
    inset-inline-end: var(--s7);
    margin: 0;
    max-width: 18rem;
    text-align: right;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero__glow { animation: none; opacity: 1; }
}

/* ---- page heads ------------------------------------------------------- */

.phead { padding-block: var(--s8) var(--s7); }
.phead__lede { font-size: 1.125rem; color: var(--muted); margin: var(--s5) 0 0; }

/* ---- service preview and the six priced services ---------------------- */

.svcp__intro, .galp__intro, .stfp__intro {
  max-width: var(--measure);
  color: var(--muted);
  margin: var(--s5) 0 var(--s7);
}

.svcp__list { grid-template-columns: minmax(0, 1fr); }

/* A region of the plane, not a card: a hairline above it and nothing else. */
.svcp__item { padding-block: var(--s5); border-top: 1px solid var(--rule); }
.svcp__p { margin: var(--s3) 0; color: var(--muted); }
.svcp__link { display: inline-flex; align-items: center; min-height: 44px; font-weight: 700; }

/* A price here is often a sentence ("fee disclosed in consultation"), not a
   figure. At a flat 1.75rem that string is ~380px wide and pushed index.html
   7px past a 320px viewport, so the size is fluid and the string wraps. */
/* ---- services: the concierge folio ------------------------------------- */
/* A contents rail beside the mandates, not a list on its own. The rail is
   plain anchor navigation into six anchored records, so the page is complete
   with scripting disabled; the current record is marked through :target, so
   the marker needs no script either. */

.price__v { font-size: clamp(1.125rem, 4vw, 1.75rem); color: var(--act); }

.svc__folio { display: grid; gap: var(--s7); align-items: start; }

.svc__railin { border-top: 1px solid var(--act); padding-top: var(--s5); }

.svc__railh {
  margin: 0 0 var(--s4);
  font-size: .6875rem;
  line-height: 1.7;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
}

.svc__raillist { margin: 0; padding: 0; list-style: none; }
.svc__railitem { border-top: 1px solid var(--rule); }
.svc__railitem:first-child { border-top: 0; }

.svc__raillink {
  display: grid;
  grid-template-columns: 2.25rem minmax(0, 1fr);
  align-items: baseline;
  gap: var(--s1) var(--s3);
  min-height: 44px;
  padding-block: var(--s3);
  text-decoration: none;
}

.svc__raillink:hover .svc__railname,
.svc__raillink:focus-visible .svc__railname { text-decoration: underline; }

.svc__railno {
  grid-row: 1 / 3;
  font-family: var(--font-h);
  font-size: 1rem;
  color: var(--act);
}

.svc__railname { color: var(--ink); }

.svc__railmeta {
  grid-column: 2;
  font-size: .6875rem;
  line-height: 1.7;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
}

/* the current record, marked without script */
body:has(#service-1:target) .svc__raillink[href="#service-1"] .svc__railname,
body:has(#service-2:target) .svc__raillink[href="#service-2"] .svc__railname,
body:has(#service-3:target) .svc__raillink[href="#service-3"] .svc__railname,
body:has(#service-4:target) .svc__raillink[href="#service-4"] .svc__railname,
body:has(#service-5:target) .svc__raillink[href="#service-5"] .svc__railname,
body:has(#service-6:target) .svc__raillink[href="#service-6"] .svc__railname {
  color: var(--gold-l);
  text-decoration: underline;
  text-underline-offset: 4px;
}

.svc__railp {
  margin: var(--s5) 0 0;
  padding-top: var(--s4);
  border-top: 1px solid var(--rule);
  color: var(--muted);
  font-size: .8125rem;
}

.svc__railfig { margin: var(--s6) 0 0; border-radius: var(--radius); overflow: hidden; }
.svc__railfig img { display: block; width: 100%; height: auto; }

.svc__railcap {
  margin: var(--s3) 0 0;
  font-size: .8125rem;
  color: var(--muted);
}

/* the featured mandate */
.svc__feat {
  display: grid;
  gap: var(--s6);
  padding-bottom: var(--s8);
  border-bottom: 1px solid var(--rule);
  scroll-margin-top: var(--s6);
}

.svc__featkick {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
  margin: 0 0 var(--s4);
  font-size: .6875rem;
  line-height: 1.7;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
}

.svc__name--feat { font-size: clamp(1.75rem, 6vw, 2.75rem); margin: 0; }

.svc__featfig {
  margin: 0;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--ruleg);
}

.svc__featfig img { display: block; width: 100%; height: auto; }

.svc__listh {
  margin: var(--s8) 0 0;
  font-size: .6875rem;
  line-height: 1.7;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
}

.svc__list { display: grid; gap: 0; margin: 0; padding: 0; list-style: none; }

.svc__row {
  display: grid;
  gap: var(--s5);
  padding: var(--band-pad) var(--s5);
  border-top: 1px solid var(--rule);
  scroll-margin-top: var(--s6);
}

.svc__row:nth-child(even) {
  background: var(--plane);
  border-radius: var(--radius);
  box-shadow: inset 0 0 0 1px var(--ruleg);
}

.svc__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s3) var(--s5); }

.svc__no {
  margin: 0;
  font-family: var(--font-h);
  font-size: 1.5rem;
  line-height: 1;
  color: var(--act);
}

.svc__scope { color: var(--muted); margin: 0; }

.svc__fit { margin: var(--s4) 0 0; }

.svc__fitlabel {
  display: inline-block;
  margin-inline-end: var(--s2);
  font-size: .6875rem;
  line-height: 1.7;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--act);
}

/* the three record fields: what is in, what is not, and how long */
.svc__terms {
  display: grid;
  gap: var(--s5);
  margin: var(--s5) 0 0;
  padding-top: var(--s5);
  border-top: 1px solid var(--rule);
}

.svc__termh {
  margin: 0 0 var(--s2);
  font-size: .6875rem;
  line-height: 1.7;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
}

.svc__incl { margin: 0; padding: 0; list-style: none; }

.svc__incl li {
  position: relative;
  padding-inline-start: var(--s5);
  margin-bottom: var(--s2);
  font-size: .9375rem;
}

.svc__incl li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  top: .7em;
  width: 10px;
  height: 1px;
  background: var(--act);
}

.svc__bound, .svc__timing { margin: 0; font-size: .9375rem; color: var(--muted); }

.svc__link { display: inline-flex; align-items: center; min-height: 44px; margin-top: var(--s5); font-weight: 700; }

/* ---- gallery ---------------------------------------------------------- */

.galp__list, .gal__list { grid-template-columns: minmax(0, 1fr); }
.gal__list { display: grid; gap: var(--s5); margin: 0; padding: 0; list-style: none; }

.gal__group + .gal__group { margin-top: var(--s9); }

.gal__grouph {
  display: flex;
  align-items: baseline;
  gap: var(--s4);
  margin: 0 0 var(--s3);
  font-size: 1.5rem;
  line-height: 1.2;
}

.gal__groupno {
  font-family: var(--font-b);
  font-size: .6875rem;
  letter-spacing: .18em;
  color: var(--act);
  flex: none;
}

.gal__groupnote {
  max-width: var(--measure-s);
  margin: 0 0 var(--s5);
  font-size: .875rem;
  line-height: 1.7;
  color: var(--muted);
}

.galp__fig, .gal__fig { margin: 0; }

.gal__frame, .galp__fig {
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--ruleg);
}

/* section 17 asks the eight photographs to read as one graded set. They were
   taken by eight different people in eight buildings, so the only honest way
   to do that is to grade them together. Done here rather than baked into 24
   files: the shipped bytes then still match what ASSET_SOURCES.md says was
   done to the originals, which is a crop and a re-encode. */
.gal__frame img { filter: saturate(.92) contrast(1.04); }

.gal__cap, .galp__cap {
  display: flex;
  gap: var(--s3);
  margin-top: var(--s4);
  line-height: 1.5;
  color: var(--muted);
}

.galp__cap { font-size: .875rem; }
/* section 17: 13px captions */
.gal__cap { font-size: .8125rem; max-width: var(--measure-s); }
.gal__item--wide .gal__cap { max-width: var(--measure); }

.gal__no { font-size: .8125rem; color: var(--act); flex: none; }
.galp__cap .gal__no { font-size: .875rem; }

/* ---- staff ------------------------------------------------------------ */

.stf__notice {
  max-width: var(--measure);
  margin: 0 0 var(--s7);
  padding: var(--s5);
  border-inline-start: 1px solid var(--act);
  color: var(--muted);
  font-size: .9375rem;
}

.stf__list, .stfp__list { grid-template-columns: minmax(0, 1fr); }

.stf__card {
  height: 100%;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--ruleg);
  background: var(--bg);
}

/* section 17's black-and-bronze panel: a 4:5 crop out of the 3:4 source, a
   bronze hairline and a black foot so the panel meets the body instead of
   stopping at it. The intrinsic width/height stay on the img, so the crop
   costs no layout shift. */
.stf__fig {
  position: relative;
  margin: 0;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--panel-stf);
}

.stf__fig img { width: 100%; height: 100%; object-fit: cover; }

.stf__fig::after {
  content: "";
  position: absolute;
  inset: 0;
  box-shadow: inset 0 -1px 0 0 var(--act);
  background: linear-gradient(180deg, rgba(10,12,14,.02) 52%, rgba(10,12,14,.64) 100%);
  pointer-events: none;
}

/* the authored house monogram, once, on the lead sheet */
.stf__mono {
  position: absolute;
  left: var(--s5);
  bottom: var(--s5);
  z-index: 1;
  display: block;
  width: 64px;
  height: 64px;
}

.stf__mono svg { display: block; width: 64px; height: 64px; max-width: none; }
.mo__c, .mo__a { fill: none; stroke: var(--gold-l); stroke-width: 3; }
.mo__c { stroke-linecap: round; }

.stf__body { padding: var(--s5); }

.stf__kicker {
  margin: 0 0 var(--s3);
  font-size: .6875rem;
  line-height: 1.7;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
}

.stf__name { font-size: 1.25rem; }
.stf__role { color: var(--act); font-weight: 600; margin: var(--s2) 0; }
.stf__scope { margin: 0 0 var(--s4); font-size: 1.0625rem; }
.stf__bio { margin: 0; color: var(--muted); }

.stf__cue {
  margin: var(--s5) 0 0;
  padding-top: var(--s4);
  border-top: 1px solid var(--rule);
  font-size: .9375rem;
}

.stf__cuelabel {
  display: block;
  margin-bottom: var(--s1);
  font-size: .6875rem;
  line-height: 1.7;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--act);
}

.stf__svcs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s3);
  margin: var(--s4) 0 0;
  padding: 0;
  list-style: none;
}

.stf__svcs a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: var(--s4);
  border: 1px solid var(--rule);
  border-radius: 999px;
  font-size: .8125rem;
  text-decoration: none;
}

.stf__svcs a:hover, .stf__svcs a:focus-visible { border-color: var(--act); }

/* ---- the responsibility matrix ---------------------------------------- */
/* One definition list. Below 768 it is exactly what S5 asks for at mobile -
   a labelled definition list - and from 768 up the same markup lays out as a
   two-column matrix. There is no second copy of the content to drift. */

.mtx__dl { margin: var(--s6) 0 0; }

.mtx__row { padding-block: var(--s5); border-top: 1px solid var(--rule); }
.mtx__row:last-child { border-bottom: 1px solid var(--rule); }

.mtx__dt {
  font-size: .6875rem;
  line-height: 1.7;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
}

.mtx__dd { margin: var(--s2) 0 0; }
.mtx__role { display: block; color: var(--act); font-weight: 700; }
.mtx__what { display: block; margin-top: var(--s1); color: var(--muted); font-size: .9375rem; }

/* ---- about ------------------------------------------------------------ */

.abt__cols { display: grid; gap: var(--s6); }
.abt__p { margin: 0 0 var(--s5); }
.prin__list { grid-template-columns: minmax(0, 1fr); }
.prin__p { margin: var(--s3) 0 0; color: var(--muted); }

.place__fig { max-width: 1134px; margin-inline: auto; }

.place__frame {
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--ruleg);
}

.place__cap { margin-top: var(--s4); font-size: .8125rem; color: var(--muted); }

/* ---- reviews: R5 private client letter folio -------------------------- */
/* A correspondence folio, not a card grid. One letter opens the page at full
   size beside a narrow rail that indexes the other five; each of those five
   is a real anchored letter printed in full further down, so the rail is
   ordinary anchor navigation and needs no script at all. */

.revp__list { grid-template-columns: minmax(0, 1fr); }

.rev__folio { display: grid; gap: var(--s7); }

.rev__card {
  padding: var(--s6);
  border-radius: var(--radius);
  box-shadow: inset 0 0 0 1px var(--ruleg);
  background: var(--bg);
  /* the rail links land here; the header is not sticky, but a letter that
     opens flush against the viewport edge reads as a clipped one */
  scroll-margin-top: var(--s6);
}

/* the lead letter is distinguished by scale, a gold frame and the seal -
   not by a second background colour, which would fight the section plane */
.rev__card--lead { box-shadow: inset 0 0 0 1px var(--act); }

.rev__no { font-size: 1rem; color: var(--act); margin: 0 0 var(--s5); }

.rev__head { display: flex; align-items: center; gap: var(--s5); margin-bottom: var(--s5); }

/* stable 72px box at every width: base.css resets every svg to max-width:100%,
   which collapses a fixed mark inside anything allowed to shrink, so the mark
   takes its size from the span and opts out of the reset. */
.rev__av { display: block; flex: none; width: 72px; height: 72px; }
.rev__av svg { display: block; width: 72px; height: 72px; max-width: none; }
.av__ln { fill: none; stroke: var(--act); stroke-width: 1.4; }
.av__dot { fill: var(--act); }
.av__fill { fill: var(--act); opacity: .18; }

.rev__id { min-width: 0; }
.rev__by, .revp__by { font-weight: 700; margin: 0; }
.rev__meta {
  margin: var(--s1) 0 0;
  font-size: .6875rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
}

.rev__q, .revp__q { max-width: var(--measure-s); margin: 0; font-size: 1.0625rem; }
.rev__q p, .revp__q p { margin: 0; }
.rev__card--lead .rev__q { font-size: 1.1875rem; line-height: 1.75; }

.rev__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  margin-top: var(--s6);
  padding-top: var(--s5);
  border-top: 1px solid var(--rule);
}

.rev__svc { display: inline-flex; align-items: center; min-height: 44px; font-size: .875rem; }

/* the one seal-like authored mark on the page - the house crown, the same
   motif the footer closes on, used here as the endpoint of the lead letter */
.rev__seal { display: block; flex: none; width: 44px; height: 44px; opacity: .85; }
.rev__seal svg { display: block; width: 44px; height: 44px; max-width: none; }

/* ---- the index rail --------------------------------------------------- */

.rev__railh {
  margin: 0;
  font-family: var(--font-b);
  font-size: .6875rem;
  font-weight: 700;
  line-height: 1.7;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--act);
  padding-bottom: var(--s3);
  border-bottom: 1px solid var(--act);
}

.rev__railp { margin: var(--s4) 0 0; font-size: .875rem; color: var(--muted); }

.rev__raillist { list-style: none; margin: var(--s4) 0 0; padding: 0; }
.rev__railitem { border-bottom: 1px solid var(--rule); }

.rev__raillink {
  display: grid;
  grid-template-columns: 2.25rem minmax(0, 1fr);
  align-items: baseline;
  gap: 0 var(--s3);
  padding-block: var(--s4);
  min-height: 44px;
  text-decoration: none;
  color: var(--ink);
}

.rev__raillink:hover .rev__railname,
.rev__raillink:focus-visible .rev__railname {
  text-decoration: underline;
  text-underline-offset: .28em;
}

.rev__railno { font-family: var(--font-h); font-size: 1rem; color: var(--act); }
.rev__railname { font-weight: 700; }
.rev__railmeta {
  grid-column: 2;
  margin-top: var(--s1);
  font-size: .75rem;
  color: var(--muted);
}

/* ---- the correspondence stack ----------------------------------------- */

.rev__stackh {
  margin: var(--s9) 0 var(--s6);
  font-size: clamp(1.375rem, 2.6vw, 1.875rem);
}

.rev__stack { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s6); }
.rev__stackitem { min-width: 0; }

.revp__item { padding-block: var(--s6); border-top: 1px solid var(--rule); }

/* ---- faq -------------------------------------------------------------- */

.faqg__h { font-size: clamp(1.5rem, 3vw, 2.25rem); }
.faqg__sub { color: var(--muted); margin: var(--s2) 0 var(--s5); }

.faq__item { border-top: 1px solid var(--rule); }
.faq__item:last-of-type { border-bottom: 1px solid var(--rule); }

/* section 17 asks for a solid open state, so that an open row reads as a
   panel rather than as a gap between two hairlines. */
.faq__item[open] { background: var(--sel); }

.faq__q {
  display: flex;
  align-items: baseline;
  gap: var(--s4);
  min-height: 56px;            /* section 17: 56px rows */
  padding: var(--s4) var(--s7) var(--s4) var(--s4);
  font-family: var(--font-h);
  font-weight: 700;
  font-size: 1.125rem;
  line-height: 1.3;
  cursor: pointer;
  list-style: none;
  position: relative;
}

.faq__q::-webkit-details-marker { display: none; }

.faq__q:focus-visible { outline: 2px solid var(--act); outline-offset: -2px; }

/* section 17: gold index numbers, the same treatment the gallery already
   uses for a numeral. */
.faq__no {
  font-family: var(--font-b);
  font-size: .6875rem;
  letter-spacing: .18em;
  color: var(--act);
  flex: none;
}

.faq__qt { min-width: 0; }

.faq__q::after {
  content: "+";
  position: absolute;
  inset-inline-end: var(--s4);
  top: 50%;
  transform: translateY(-50%);
  font-size: 1.5rem;
  line-height: 1;
  color: var(--act);
}

.faq__item[open] .faq__q::after { content: "\2212"; }

/* section 17: the answer is body copy, not a caption, so it takes the muted
   token at 8.32:1 rather than anything lighter. The 68ch cap comes from
   .measure. */
.faq__a { padding: 0 var(--s4) var(--s5); color: var(--muted); }
.faq__a p { margin: 0; }

.faq__escape {
  margin: var(--s6) 0 0;
  padding: var(--s5);
  border-radius: var(--radius);
  box-shadow: inset 0 0 0 1px var(--ruleg);
}

/* ---- contact ---------------------------------------------------------- */

.con__grid { display: grid; gap: var(--s8); }
/* the identity column is the narrow one, so its heading is sized for the
   column and not for a full-width band */
.cd__h { font-size: clamp(1.375rem, 2.4vw, 1.75rem); }
.cd__hh { font-size: 1.0625rem; margin: var(--s6) 0 0; }
.cd__addr { font-style: normal; margin: var(--s4) 0 0; }
.cd__mail { margin: var(--s2) 0 0; }
.cd__note { margin: var(--s5) 0 0; font-size: .9375rem; color: var(--muted); }
.cd__hours { margin: var(--s4) 0 0; }

/* label against value on one ruled row. A multi-column flow was tried first
   and split a dt from its own dd across the column break. */
.cd__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--s4);
  align-items: baseline;
  padding-block: var(--s3);
  border-top: 1px solid var(--rule);
}

.cd__hours dt {
  font-size: .75rem;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 700;
}

.cd__hours dd { margin: 0; }

/*
 * F5, the Concierge Conversation. Five visible steps in ONE semantic form -
 * a fieldset was tried first and a grid fieldset renders unreliably, so each
 * step is a role="group" labelled by its own heading. Nothing here depends on
 * JavaScript: with scripting off the five steps are five ruled blocks and the
 * form posts to /api/contact exactly as it does with scripting on.
 */
.cstep { padding-block: var(--s6); border-top: 1px solid var(--rule); }
.cstep:first-of-type { border-top: 0; padding-top: 0; }

.cstep__h {
  display: flex;
  align-items: baseline;
  gap: var(--s4);
  margin: 0;
  font-family: var(--font-h);
  font-weight: 700;
  font-size: 1.25rem;
  line-height: 1.25;
}

/* the same gold numeral the services folio and the FAQ accordion use. Gold
   stays on actions, numerals and rules and goes nowhere else. */
.cstep__no {
  font-family: var(--font-b);
  font-size: .6875rem;
  letter-spacing: .18em;
  color: var(--act);
  flex: none;
}

.cstep__why {
  margin: var(--s3) 0 var(--s5);
  max-width: var(--measure-s);
  font-size: .9375rem;
  line-height: 1.65;
  color: var(--muted);
}

/* section 17: 50px fields and 18px input text, which is a size a visitor
   reads back without leaning in. The 44px floor in design.css is the site
   minimum; this is the contact page spending more on the one form that
   carries the whole enquiry. */
.cform .field input, .cform .field select { min-height: 50px; }

.cform .field input, .cform .field select, .cform .field textarea {
  font-size: 1.125rem;
  padding: var(--s3) var(--s4);
}

/* 18px text in a 12px box measures 55px, so the single-line controls take
   the smaller vertical padding and land on section 17's 50px exactly. The
   textarea keeps the roomier box - it is holding a paragraph, not a line. */
.cform .field input, .cform .field select { padding-block: var(--s2); }

.field { margin-bottom: var(--s5); }
.field:last-child { margin-bottom: 0; }
.field__opt { font-size: .8125rem; color: var(--muted); font-weight: 400; }
.hint { margin: var(--s2) 0 0; font-size: .8125rem; color: var(--muted); }

/* the subdued privacy box sits between the last step and the one action, so
   the sentence about what not to send is the last thing read before send. */
.cform__privacy {
  margin: var(--s6) 0 0;
  padding: var(--s5);
  border-radius: var(--radius);
  background: var(--panel-rev);
  box-shadow: inset 0 0 0 1px var(--ruleg);
}

.cform__consent { margin: 0; font-size: .9375rem; line-height: 1.65; color: var(--muted); }
.cform__foot { margin: var(--s6) 0 0; }

/* section 17: a fixed 56px response region. It is reserved whether or not
   anything has been submitted, so a success or an error arrives without
   pushing the page under the reader's eye. */
.cform__status {
  margin: var(--s5) 0 0;
  min-height: 56px;
  font-size: .9375rem;
  line-height: 1.6;
}

/* base.css hides every idle status region that is still empty. Section 17
   asks this one page for the opposite - a response region held open at 56px
   so a success or an error does not move the button out from under the
   pointer that just pressed it. */
.cform__status[data-state="idle"]:empty { display: block; }

/* one gold action, at the height of the fields above it */
.cform .btn--primary { min-height: 50px; }

.cform__status[data-state="error"] { color: var(--err); }
.cform__status[data-state="ok"] { color: var(--act); }

.alt__in { display: grid; gap: var(--s4); justify-items: start; }

/* ---- privacy ---------------------------------------------------------- */

.pv__date { margin: var(--s5) 0 0; font-weight: 700; }
.pv__sec { padding-block: var(--s6); border-top: 1px solid var(--rule); }
.pv__sec:first-child { border-top: 0; }
.pv__h { font-size: clamp(1.25rem, 2.5vw, 1.75rem); margin-bottom: var(--s4); }
.pv__sec p { color: var(--muted); }
.pv__sec p + p { margin-top: var(--s4); }

/* ---- cta and subscribe ------------------------------------------------ */

.cta__in { display: grid; gap: var(--s5); }
.cta__p { max-width: var(--measure); margin: 0; color: var(--muted); }
.cta__actions { display: flex; flex-wrap: wrap; gap: var(--s4); }
.cta__actions .btn { min-width: 148px; }


/* ---- 404 -------------------------------------------------------------- */

.nf { padding-block: var(--s9); }
.nf__code { font-size: .75rem; letter-spacing: .3em; text-transform: uppercase; color: var(--muted); }
.nf__p { color: var(--muted); }
.nf__links { display: flex; flex-wrap: wrap; gap: var(--s4); margin-top: var(--s6); }
.nf__links a { display: inline-flex; align-items: center; min-height: 44px; }

/* ---- breakpoints ------------------------------------------------------ */

/* 768px: the desktop identity begins. Two-column sections activate, the
   gallery goes to two, and the priced services split into a name column and
   a scope column. */
@media (min-width: 768px) {
  .svcp__list, .prin__list, .how__list, .proc__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .galp__list, .gal__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gal__item--wide { grid-column: 1 / -1; }
  .stf__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stfp__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* the lead sheet runs the full width of the folio and turns on its side:
     panel beside body, not above it */
  .stf__item--lead { grid-column: 1 / -1; }
  .stf__card--lead { display: grid; grid-template-columns: minmax(0, 20rem) minmax(0, 1fr); }
  .stf__card--lead .stf__fig { height: 100%; aspect-ratio: auto; }
  .stf__card--lead .stf__body { padding: var(--s7); align-self: center; }
  .mtx__row {
    display: grid;
    grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
    align-items: baseline;
    gap: var(--s5);
  }
  .mtx__dd { margin: 0; }
  .revp__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .abt__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s8); }
  .svc__feat { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--s7); align-items: start; }
  .svc__terms { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5) var(--s7); }
  .svc__feat .svc__terms { grid-template-columns: minmax(0, 1fr); }
  /* alternating detail sheets: the plane flips, and so does the side the
     numeral and name sit on. The row does not SPLIT here - see 1280 */
  .svc__row { gap: var(--s7); }
  .svc__row:nth-child(even) .svc__head { flex-direction: column; align-items: flex-end; text-align: end; }
  .svc__row:nth-child(odd) .svc__head { flex-direction: column; align-items: flex-start; }
}

/* 1024px: the planes reach full depth, the gallery goes to three columns and
   the staff row shows all four plates. */
@media (min-width: 1024px) {
  /* the identity column is the NARROW one - 20rem against a 544px form here
     and an 800px form at 1280. It waits until 1024 because at 768 the same
     split left the form 248px, narrower than the column beside it. */
  .con__grid { grid-template-columns: minmax(0, 20rem) minmax(0, 1fr); }
  .svcp__list, .prin__list, .how__list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .galp__list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .stf__list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .proc__list { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .revp__list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .svc__folio { grid-template-columns: minmax(0, 17rem) minmax(0, 1fr); gap: var(--s8); }
  /* the rail is persistent from here up. Nothing in this design is sticky
     except this, and the header scrolls away, so there is nothing for it to
     collide with. */
  .svc__railin { position: sticky; top: var(--s6); }
  .svc__feat .svc__terms { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* the folio only splits when the lead letter can still hold a real
     measure beside the rail; at 768 a 360px "featured" letter is not one */
  .rev__folio { grid-template-columns: minmax(0, 1fr) minmax(0, 20rem); gap: var(--s8); }
  /* the band splits into lede and actions only once the lede keeps a
     real measure beside the buttons; at 768 the same rule left it about
     130px wide, which is four or five words a line */
  .cta__in { grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
}

/* 1280px: the detail sheets split. Same rule the reviews folio follows -
   the row only turns on its side once the body still has a real measure
   beside the head. The folio spends 17rem plus a --s8 gap on the rail, so
   at 1024 a 22rem head track leaves about 190px of body and the row runs
   three times its proper height; at 1280 it leaves 512px. */
@media (min-width: 1280px) {
  /* F5's left rail. Each step turns on its side and the reason the detail is
     asked for becomes a margin note beside the controls it explains. */
  .cstep { display: grid; grid-template-columns: minmax(0, 16rem) minmax(0, 1fr); gap: var(--s7); }
  .cstep__why { margin-bottom: 0; }
  .svc__row { grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); }
  .svc__row:nth-child(even) { grid-template-columns: minmax(0, 1fr) minmax(0, 22rem); }
  .svc__row:nth-child(even) .svc__head { grid-column: 2; grid-row: 1; }
  .svc__row:nth-child(even) .svc__body { grid-column: 1; grid-row: 1; }
  /* the head column is a stretched grid item, so its inner edge is a
     full-height rule for free. That is what holds the empty half of
     the spread together instead of leaving it as a blank plane. */
  .svc__row:nth-child(odd) .svc__head { border-inline-end: 1px solid var(--ruleg); padding-inline-end: var(--s7); }
  .svc__row:nth-child(even) .svc__head { border-inline-start: 1px solid var(--ruleg); padding-inline-start: var(--s7); }
}

/* 1600px: nothing changes. The content column is already centred at 1360px
   and every rendition is cut for that box; letting the gallery run to 1600
   gave it a 485px column against a 437px sizes promise, which is a soft
   photograph on the one screen wide enough to show it. */

/* ---- the light palette's two consequences ----------------------------- */
/*
 * Everything above this line is the base layout, untouched. These two blocks
 * are the only places where turning the ground from near-black to #F2F1F8
 * changes something other than a token.
 */

/* 1. The recommendation's media filter belongs to every photograph in the
      build, not only to the ones inside a gallery frame. */
.hero__plate img, .place__frame img, .stf__fig img, .svc__featfig img {
  filter: saturate(.92) contrast(1.04);
}

/* 2. From 1024 up the hero copy sits ON the plate, under the scrim, and the
      scrim is dark by design -- it is what keeps a headline legible over a
      photograph. The ink there is therefore white rather than the page ink:
      #FFFFFF on the .64 foot of the scrim measures 12.6:1, and the eyebrow,
      lede and caption at 86% white measure 9.6:1. Below 1024 the copy is on
      the page ground and keeps the ordinary ink. */
@media (min-width: 1024px) {
  /* This build's headline runs to five lines, so the hero copy is taller than
     a 16/9 plate at 1440: the action row and the caption fell off the bottom
     of the photograph onto the page ground, where this white overlay ink is
     invisible. The plate fills the row it shares with the copy and keeps 16/9
     as its floor, so the scrim is always behind the copy it was written for. */
  .hero__plate { min-height: 100%; }

  .hero__text h1 { color: #FFFFFF; }
  .hero__eyebrow,
  .hero__lede,
  .hero__cap { color: rgba(255, 255, 255, .86); }
  .hero__second { color: #FFFFFF; }
  .hero__second:hover { color: var(--sel); }
  .hero .btn--ghost { color: #FFFFFF; border-color: rgba(255, 255, 255, .5); }
  .hero__text :focus-visible { outline-color: #FFFFFF; }
}

/* ---- visual fix pass -------------------------------------------------- */
/*
 * Four corrections found by looking at the rendered pages rather than the
 * markup. None of them changes a token, a section's spacing, or the grid
 * the base build lays its planes on.
 */

/* The heading and the lede of the closing band are separate elements in one
   wrapper, both with margin 0 and no gap, so the display face's descenders
   sat on the paragraph's first line at every width. */
.cta__text { display: grid; gap: var(--s3); }

/* The 404 page has the same pairing and had the same collision. */
.nf__p { margin-top: var(--s4); }

/* The footer email is a single unbroken token inside an inline-flex link, so
   the flex item's automatic minimum is the width of the whole address. At
   768, where the footer runs three columns, it overflowed its column and was
   clipped by the one beside it. `break-word` cannot fix this -- by
   definition it does not affect the min-content contribution -- and
   `anywhere` is the value that does. */
.ft__addr, .ft__addr a { overflow-wrap: anywhere; }

/* From 1100 up the review plane is half the grid, and the three-column rule
   shared with the reviews page left each quote about 150px wide. One column
   inside that plane gives every quote the measure it was written for. */
@media (min-width: 1100px) {
  body.p-index .revp__list { grid-template-columns: minmax(0, 1fr); }
}

/* aajwebz-mailto-nowrap — an address is one token, never split across lines */
a[href^="mailto:"] {
  overflow-wrap: normal;
  word-break: normal;
  white-space: nowrap;
  display: inline-block;
  max-width: 100%;
}
@media (max-width: 380px) {
  a[href^="mailto:"] { font-size: 0.88em; }
}
