/* DS-04 -- 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 single most common way these builds fail
 * the responsive gate.
 */

.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: overhead photograph with inset detail ---------------------- */

.hero { padding-block: var(--s7) var(--s8); }

.hero__in { display: grid; gap: var(--s6); }

.hero__eyebrow {
  font-size: .875rem;
  line-height: 1.35;
  letter-spacing: .2em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--acc);
  margin: 0 0 var(--s4);
}

/* MATERIAL DISTINCTNESS: one overhead workbench assembled from unequal zones. */
@media (min-width: 1100px) {
  body.p-index main { display:grid; grid-template-columns:repeat(12,minmax(0,1fr)); align-items:start; background:var(--paper); overflow:clip; }
  body.p-index main > .sec { min-width:0; margin:0; }
  body.p-index main > .sec > .wrap { width:auto; max-width:none; }
  body.p-index .hero { grid-column:1/-1; grid-row:1; }
  body.p-index .svcp { grid-column:1/8; grid-row:2; transform:rotate(-.35deg); z-index:2; }
  body.p-index .appr { grid-column:8/-1; grid-row:2; transform:rotate(.45deg); }
  body.p-index .ruler { grid-column:1/-1; grid-row:3; }
  body.p-index .galp { grid-column:1/9; grid-row:4; }
  /* Staff is taller than Gallery. Let it span the Reviews row so the review
     band occupies the space that previously rendered as a blank half-page. */
  body.p-index .stfp { grid-column:9/-1; grid-row:4 / span 2; }
  body.p-index .stfp__list { grid-template-columns:1fr; }
  body.p-index .revp { grid-column:1/9; grid-row:5; transform:rotate(-.3deg); }
  body.p-index .faqp { grid-column:5/-1; grid-row:6; }
  body.p-index .cta { grid-column:1/-1; grid-row:7; }
}

.hero__lede {
  max-width: var(--measure);
  font-size: 1.125rem;
  margin: var(--s5) 0 var(--s6);
}

.hero__acts { display: flex; flex-wrap: wrap; gap: var(--s3); align-items: center; }

/* 375px: two actions may share a row only while each stays at least 148px
   wide. Below that they stack with a 12px gap, which is what flex-wrap plus
   this min-width does without a media query. */
.hero__acts .btn { min-width: 148px; }

.hero__second { min-height: 44px; display: inline-flex; align-items: center; }

.hero__fig { margin: 0; }

.hero__frame {
  position: relative;
  border: 2px solid var(--frame);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--frame-shadow);
  /* 320px takes a 4:5 crop of the 4:3 file, 390px a 3:4, and from 768px the
     photograph is shown at its own ratio. object-fit does the cropping so no
     second file is needed for a breakpoint. */
  aspect-ratio: 4 / 5;
}

.hero__frame img { width: 100%; height: 100%; object-fit: cover; }

@media (min-width: 390px) { .hero__frame { aspect-ratio: 3 / 4; } }
@media (min-width: 768px) { .hero__frame { aspect-ratio: 4 / 3; } }

.hero__cap {
  margin-top: var(--s3);
  font-size: .8125rem;
  color: var(--acc);
}

/* the inset detail, and the magnifier that is its enhancement */

.mag { margin-top: var(--s4); margin-inline-start: var(--s5); }

.mag__box {
  display: block;
  width: 140px;
  border: 2px solid var(--frame);
  border-radius: 0;
  overflow: hidden;
  background: var(--bg);
  box-shadow: var(--frame-shadow);
}

.mag__box img { display: block; width: 100%; height: auto; }

.mag__label {
  display: block;
  padding: var(--s2) var(--s3);
  font-size: .8125rem;
  line-height: 1.35;
  min-height: 44px;
  border-top: 1px dashed var(--rule);
  color: var(--ink);
}

/* The magnifier is a <details>, so it opens on Enter or Space from the
   keyboard with no script at all. Open, the inset grows to 260px in place --
   it does not float over the photograph and it does not follow the pointer,
   because the reduced-motion arrangement has to be the same composition. */
.mag[open] .mag__box { width: min(260px, 72vw); }

.mag__box, .mag__label { transition: width var(--t); }

@media (min-width: 768px) {
  .mag { margin-inline-start: var(--s8); }
  .mag__box { width: 180px; }
  .mag[open] .mag__box { width: 320px; }
}

@media (min-width: 1024px) {
  .hero__in { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); align-items: center; }
  .hero__fig { position: relative; }
  .mag { position: absolute; inset-block-end: var(--s6); inset-inline-start: calc(var(--s6) * -1); margin: 0; }
}

/* ---- page heads ------------------------------------------------------- */

.phead { padding-block: var(--s7) var(--s6); }
.phead__lede { font-size: 1.125rem; margin: var(--s5) 0 0; }

/* ---- service preview and the services list ---------------------------- */

.svcp__intro, .galp__intro, .stfp__intro { max-width: var(--measure); margin: var(--s5) 0 var(--s6); }

.svcp__list { grid-template-columns: minmax(0, 1fr); }
.svcp__item { padding: var(--s5); background: var(--surface); border: 2px solid var(--frame); box-shadow: var(--frame-shadow); border-radius: var(--radius); }
.svcp__p { margin: var(--s3) 0; }
.svcp__link { display: inline-flex; align-items: center; min-height: 44px; font-weight: 600; }

.price__q { font-size: .8125rem; letter-spacing: .12em; text-transform: uppercase; color: var(--acc); display: block; }
.price__v { font-size: 1.5rem; }

.svc__list { display: grid; gap: 0; margin: 0; padding: 0; list-style: none; }

/* Each priced service is its own band, seamed to the next with the stitched
   rule -- this is the layered workbench bands treatment section 6 asks for on
   this page specifically, not a card grid. */
.svc__row {
  display: grid;
  gap: var(--s4);
  padding-block: var(--s6);
  border-top: 2px dashed var(--rule);
}

.svc__row:first-child { border-top: 0; }
.svc__row:nth-child(even) { background: var(--band2); margin-inline: calc(var(--gutter) * -1); padding-inline: var(--gutter); }

.svc__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--s3); }
.svc__fitlabel { font-size: .8125rem; letter-spacing: .12em; text-transform: uppercase; color: var(--acc); font-weight: 700; }
.svc__link { display: inline-flex; align-items: center; min-height: 44px; font-weight: 600; }

.how__list, .proc__list { grid-template-columns: minmax(0, 1fr); counter-reset: none; }
.how__no, .proc__no { font-size: 1.25rem; color: var(--act); margin: 0 0 var(--s2); }
.how__p, .proc__p { margin: var(--s2) 0 0; }

.note__p, .limit__p, .appr__p { margin: var(--s5) 0 0; font-size: 1.0625rem; }

/* ---- 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; }

.galp__fig, .gal__fig { margin: 0; }
.galp__fig { border: 2px solid var(--frame); border-radius: var(--radius); overflow: hidden; box-shadow: var(--frame-shadow); }
.galp__cap { display: flex; gap: var(--s3); margin-top: var(--s3); font-size: .875rem; line-height: 1.35; }

/*
 * The fabric edge. Section 17 asks for "fabric-edge masks"; this is a clip-path
 * rather than a mask-image because a polygon needs no data URI, draws the same
 * under file:// and is supported everywhere the rest of this build is. The
 * teeth are generated so the pinking stays even at any column width, and the
 * border goes with them -- a 2px rule and a cut edge cannot both be true.
 */
.gal__fig { position: relative; }

.gal__frame {
  background: var(--deep);
  overflow: hidden;
  clip-path: polygon(0.00% 2.00%, 5.00% 0%, 10.00% 2.00%, 15.00% 0%, 20.00% 2.00%, 25.00% 0%, 30.00% 2.00%, 35.00% 0%, 40.00% 2.00%, 45.00% 0%, 50.00% 2.00%, 55.00% 0%, 60.00% 2.00%, 65.00% 0%, 70.00% 2.00%, 75.00% 0%, 80.00% 2.00%, 85.00% 0%, 90.00% 2.00%, 95.00% 0%, 100.00% 2.00%, 100.00% 98.00%, 95.00% 100%, 90.00% 98.00%, 85.00% 100%, 80.00% 98.00%, 75.00% 100%, 70.00% 98.00%, 65.00% 100%, 60.00% 98.00%, 55.00% 100%, 50.00% 98.00%, 45.00% 100%, 40.00% 98.00%, 35.00% 100%, 30.00% 98.00%, 25.00% 100%, 20.00% 98.00%, 15.00% 100%, 10.00% 98.00%, 5.00% 100%, 0.00% 98.00%);
}

/*
 * The caption is a pinned alteration ticket: paper, a punched brass pin at the
 * top, a torn left rule and a ticket number above the line. It rides up over
 * the bottom of the photograph so the two read as one pinned object.
 */
.gal__cap {
  position: relative;
  display: block;
  margin: -28px var(--s4) 0;
  padding: var(--s5) var(--s4) var(--s4);
  background: var(--surface);
  border: 2px solid var(--rule);
  border-inline-start: 2px dashed var(--act);
  border-radius: 0;
  box-shadow: 3px 3px 0 var(--frame);
  font-size: .875rem;
  line-height: 1.45;
}

.gal__cap::before {
  content: "";
  position: absolute;
  inset-block-start: -9px;
  inset-inline-start: var(--s5);
  width: 16px;
  height: 16px;
  border: 2px solid var(--deep);
  border-radius: 50%;
  background: var(--hi);
}

/* the occasional pinned-card tilt section 17 allows -- every third ticket, not
   every one, so it reads as a pin that slipped rather than a pattern */
.gal__item:nth-child(3n) .gal__cap { transform: rotate(-1deg); }

.gal__no {
  display: block;
  margin-bottom: var(--s2);
  font-family: var(--font-h);
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .12em;
  color: var(--act);
}

.gal__text { display: block; }

/* ---- before / on the bench / finished (gallery) ------------------------ */

.seq__h { font-size: clamp(1.5rem, 3vw, 2.25rem); margin: 0; }
.seq__intro { margin: var(--s4) 0 var(--s6); }
.seq__list { display: grid; gap: var(--s6); margin: 0; padding: 0; list-style: none; }
.seq__step { position: relative; }

.seq__label {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding-inline: var(--s3);
  background: var(--hi);
  color: var(--deep);
  font-family: var(--font-h);
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  border-radius: 0;
}

.seq__frame {
  margin-top: var(--s3);
  border: 2px solid var(--frame);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--frame-shadow);
}

.seq__p { margin: var(--s4) 0 0; font-size: .9375rem; color: var(--muted); }

/* ---- staff ------------------------------------------------------------ */

.stf__list, .stfp__list { grid-template-columns: minmax(0, 1fr); }
.stf__card { border: 2px solid var(--frame); border-radius: var(--radius); overflow: hidden; background: var(--surface); height: 100%; box-shadow: var(--frame-shadow); }
.stf__fig { margin: 0; }
.stf__body { padding: var(--s5); }
.stf__role { color: var(--acc); font-weight: 600; margin: var(--s2) 0; }
.stf__bio { margin: 0; color: var(--muted); }

/*
 * Service-focus tags: the two parts of the list this bench actually works on,
 * drawn as the workshop system's 12px paper labels so a record reads as a
 * pinned card rather than a profile block. They are real links into the
 * Services page, so a visitor can go straight from a role to the work.
 */
.stf__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  margin: var(--s4) 0 0;
  padding: 0;
  list-style: none;
}

.stf__tag {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding: 0 var(--s3);
  border: 1px dashed var(--rule);
  border-radius: 0;
  background: var(--band2);
  color: var(--ink);
  font-family: var(--font-h);
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  text-decoration: none;
}

.stf__tag:hover, .stf__tag:focus-visible {
  border-style: solid;
  border-color: var(--act);
  color: var(--act);
}

.focus__list { display: flex; flex-wrap: wrap; gap: var(--s3); margin: var(--s5) 0 0; padding: 0; list-style: none; }
.focus__list a { display: inline-flex; align-items: center; min-height: 44px; padding-inline: var(--s4); border: 1px solid var(--rule); border-radius: var(--radius); text-decoration: none; }
.focus__list a:hover { background: var(--band2); }

/* ---- about ------------------------------------------------------------ */

.abt__cols { display: grid; gap: var(--s5); }
.prin__list { grid-template-columns: minmax(0, 1fr); }

/*
 * Pattern pieces. A pattern piece is paper with one corner cut square off, a
 * seam-allowance line dashed in from the edge and a punched hole to hang it by,
 * so that is what the card is -- drawn on the element, no extra markup, nothing
 * to load. The clip cuts the card's own edge, which is the point: a cut corner
 * has no border along the cut.
 */
.prin__item {
  position: relative;
  padding: var(--s6) var(--s5) var(--s5);
  background: var(--surface);
  clip-path: polygon(0 0, calc(100% - 22px) 0, 100% 22px, 100% 100%, 0 100%);
}

/* the seam allowance */
.prin__item::before {
  content: "";
  position: absolute;
  inset: 10px;
  border: 2px dashed var(--rule);
  pointer-events: none;
}

/* the punched hole */
.prin__item::after {
  content: "";
  position: absolute;
  inset-block-start: var(--s4);
  inset-inline-start: var(--s4);
  width: 14px;
  height: 14px;
  border: 2px solid var(--rule);
  border-radius: 50%;
  background: var(--band);
}

.prin__h { margin: 0; font-size: 1.0625rem; }
.prin__p { margin: var(--s3) 0 0; }

/*
 * The four-step measurement line: one continuous rule with a brass node at each
 * point. It runs down the column here and turns horizontal at 1024, where the
 * four steps finally sit side by side.
 */
.proc__list { position: relative; }

.proc__list::before {
  content: "";
  position: absolute;
  inset-block: 13px;
  inset-inline-start: 11px;
  width: 2px;
  background: var(--ink);
}

.proc__step {
  position: relative;
  padding-inline-start: var(--s7);
}

.proc__step::before {
  content: "";
  position: absolute;
  inset-block-start: 4px;
  inset-inline-start: 3px;
  width: 18px;
  height: 18px;
  border: 2px solid var(--deep);
  border-radius: 50%;
  background: var(--hi);
}

.proc__no {
  font-family: var(--font-h);
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
}

.place__frame { border: 2px solid var(--frame); border-radius: var(--radius); overflow: hidden; box-shadow: var(--frame-shadow); }
.place__cap { margin-top: var(--s3); font-size: .8125rem; color: var(--acc); }

/* ---- reviews ---------------------------------------------------------- */

.revp__list, .rev__list { grid-template-columns: minmax(0, 1fr); }
/*
 * Fitting tickets. Section 17 asks for handwritten-style cards "using the
 * approved body font for readability", which rules out a script face -- so the
 * handwriting is carried by the object instead of the letterforms: paper, a
 * brass eyelet punched through the top corner, a thread-coloured stitch line
 * run inside the edge, and the odd ticket pinned up a degree out of true.
 *
 * The stitch line is var(--act), the thread colour. The about page's pattern
 * pieces use a var(--rule) dashed line for the chalked seam allowance. Same
 * technique, two different marks, and they never appear on the same page.
 */
.rev__card {
  position: relative;
  height: 100%;
  padding: var(--s6) var(--s5) var(--s5);
  background: var(--surface);
  border: 2px solid var(--frame);
  border-radius: 0;
  box-shadow: 3px 3px 0 var(--frame);
}

/* the stitched border */
.rev__card::before {
  content: "";
  position: absolute;
  inset: 8px;
  border: 2px dashed var(--act);
  border-radius: 0;
  opacity: .5;
  pointer-events: none;
}

/* the punched eyelet the ticket hangs by */
.rev__card::after {
  content: "";
  position: absolute;
  inset-block-start: 14px;
  inset-inline-end: 14px;
  width: 14px;
  height: 14px;
  border: 2px solid var(--deep);
  border-radius: 50%;
  background: var(--hi);
}

/* the occasional pinned-card tilt section 17 allows -- two of six, not all six */
.rev__item:nth-child(4) .rev__card { transform: rotate(1deg); }
.rev__item:nth-child(6) .rev__card { transform: rotate(-1deg); }

.rev__no {
  position: relative;
  font-family: var(--font-h);
  font-size: .875rem;
  letter-spacing: .12em;
  color: var(--act);
  margin: 0 0 var(--s3);
}

.rev__q, .revp__q { margin: 0; position: relative; }
.rev__q p, .revp__q p { margin: 0; }

/* the one oversized lead quote */
.rev__item--lead .rev__card { padding: var(--s7) var(--s6) var(--s6); }
.rev__item--lead .rev__q p {
  font-family: var(--font-h);
  font-size: clamp(1.125rem, 2.6vw, 1.5rem);
  line-height: 1.4;
}
.rev__item--lead .rev__q { max-width: var(--measure); }

.rev__foot { position: relative; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s3); margin-top: var(--s4); padding-top: var(--s3); border-top: 1px dashed var(--rule); }
.rev__by, .revp__by { font-weight: 700; margin: 0; }

/* the service label, as a paper label rather than a plain link */
.rev__svc {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: var(--s3);
  border: 1px solid var(--rule);
  border-radius: 0;
  background: var(--band2);
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
}

.rev__svc:hover, .rev__svc:focus-visible { background: var(--hi); color: var(--deep); }

/* ---- faq -------------------------------------------------------------- */

.faqg__h { font-size: clamp(1.5rem, 3vw, 2.25rem); }
.faqg__sub { color: var(--acc); margin: var(--s2) 0 var(--s5); }

.faq__item { border-top: 2px dashed var(--rule); }
.faq__item:last-of-type { border-bottom: 2px dashed var(--rule); }

.faq__q {
  display: flex;
  align-items: center;
  min-height: 56px;
  padding: var(--s4) var(--s7) var(--s4) var(--s4);
  font-family: var(--font-h);
  font-weight: 700;
  font-size: 1.0625rem;
  cursor: pointer;
  list-style: none;
  position: relative;
}

.faq__q::-webkit-details-marker { display: none; }

/*
 * The brass marker: a piece of the workshop's hardware rather than a brass
 * coloured "+", which on this ground would have been thin to read as well as a
 * weak answer to the word marker.
 */
.faq__q::after {
  content: "+";
  position: absolute;
  inset-inline-end: var(--s4);
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 0;
  background: var(--hi);
  color: var(--deep);
  font-size: 1rem;
  line-height: 1;
}

.faq__item[open] .faq__q::after { content: "\2212"; }

/*
 * An open panel sits on paper. The inline padding is on the closed row too, so
 * opening one paints a surface instead of nudging the question sideways.
 */
.faq__item[open] {
  background: var(--surface);
  box-shadow: inset 3px 0 0 var(--hi);
}

.faq__a { padding: 0 var(--s4) var(--s5); }
.faq__a p { margin: 0; }

.faq__escape { margin: var(--s5) 0 0; padding: var(--s4); background: var(--band2); border-radius: var(--radius); }

/* ---- the home page's condensed "asked often" block ---------------------
   The four questions here are plain blocks rather than the <details> the FAQ
   page uses, so none of the .faq__* rules above reach them and the heading,
   the questions and the answers all ran together in one unbroken column.
   They take the same dashed rule and the same rhythm as the full page. */

.faqp__h { font-size: clamp(1.5rem, 3vw, 2.25rem); margin: 0 0 var(--s5); }
.faqp__item { padding: var(--s5) 0; border-top: 2px dashed var(--rule); }
.faqp__item:last-of-type { border-bottom: 2px dashed var(--rule); }
.faqp__q { margin: 0; font-size: 1.0625rem; }
.faqp__a { margin: var(--s3) 0 0; }

/* ---- contact ---------------------------------------------------------- */

.con__grid { display: grid; gap: var(--s7); }
/*
 * The pinned hours card: paper, a brass pin punched through the top edge and a
 * degree out of true. The tilt bleeds about two pixels sideways, which the
 * wrap's 16px gutter absorbs at 320 -- it cannot reach the document edge.
 */
.cd__hcard {
  position: relative;
  margin-top: var(--s6);
  padding: var(--s6) var(--s5) var(--s5);
  background: var(--surface);
  border: 2px solid var(--frame);
  border-radius: 0;
  box-shadow: 3px 3px 0 var(--frame);
  transform: rotate(-1deg);
}

.cd__hcard::before {
  content: "";
  position: absolute;
  inset-block-start: -9px;
  inset-inline-start: 50%;
  transform: translateX(-50%);
  width: 16px;
  height: 16px;
  border: 2px solid var(--deep);
  border-radius: 50%;
  background: var(--hi);
}

.cd__hh { margin: 0; }
.cd__hours { margin: var(--s4) 0 0; }
.cd__hours dt { font-size: .8125rem; letter-spacing: .12em; text-transform: uppercase; color: var(--acc); font-weight: 700; margin-top: var(--s4); }
.cd__hours dd { margin: var(--s2) 0 0; }

.field { margin-bottom: var(--s5); }
.field__opt { font-size: .8125rem; color: var(--muted); margin: var(--s2) 0 0; }
/* --act is 4.36 against --band2, measured, and this is 13px text. The same
   rust two steps darker clears 4.5 on all four of the site's surfaces. */
.field__req { font-size: .8125rem; color: var(--act); font-weight: 700; }

/*
 * The work order. The field numbers are a CSS counter, not nine typed numbers,
 * so the sequence cannot fall out of step when a field moves; and both this and
 * the 50px rule are scoped to .cform, so the footer subscribe form keeps the
 * site-wide 44px accessibility floor.
 */
.cform { counter-reset: fieldno; }

.cform .field > label::before {
  counter-increment: fieldno;
  content: counter(fieldno, decimal-leading-zero);
  display: inline-block;
  min-width: 28px;
  height: 20px;
  margin-inline-end: var(--s2);
  background: var(--hi);
  color: var(--deep);
  font-family: var(--font-h);
  font-size: .6875rem;
  font-weight: 700;
  letter-spacing: .06em;
  line-height: 20px;
  text-align: center;
  border-radius: 0;
}

.cform .field input, .cform .field select { min-height: 50px; }

/* the two pieces of copy a visitor has a legal interest in: full size, page
   ground, no decoration of any kind */
.cform__consent { margin: var(--s5) 0; font-size: 1rem; line-height: 1.6; color: var(--ink); }
.cform__status { margin: var(--s5) 0 0; min-height: 44px; font-size: 1rem; line-height: 1.6; }
.alt__in { display: grid; gap: var(--s4); justify-items: start; }

/* ---- privacy ---------------------------------------------------------- */

.pv__date { margin: var(--s5) 0 0; font-weight: 700; }

/*
 * Section 17: "a clean pattern-sheet grid with numbered clauses and one faint
 * measurement rail. Do not place cloth texture behind body text."
 *
 * The grid is the GROUND the sheet lies on -- two gradients, no image, no
 * request. The sheet itself is flat paper, so every line of body copy sits on
 * one solid colour. That is the second sentence of the direction, and it is
 * the reason the grid is on .pv and not on .pv__body.
 */
.pv {
  background-color: var(--band2);
  background-image:
    repeating-linear-gradient(to right, rgba(37, 34, 24, .10) 0 1px, transparent 1px 32px),
    repeating-linear-gradient(to bottom, rgba(37, 34, 24, .10) 0 1px, transparent 1px 32px);
}

.pv__body {
  position: relative;
  counter-reset: clause;
  padding: var(--s5) var(--s4) var(--s5) var(--s6);
  background: var(--surface);
  border: 2px solid var(--rule);
  border-radius: 0;
}

/* the measurement rail: one rule with a tick every 16px, in the sheet's left
   margin. It measures the sheet -- it never passes behind a word. */
.pv__body::before {
  content: "";
  position: absolute;
  inset-block: var(--s5);
  inset-inline-start: var(--s3);
  width: 9px;
  border-inline-start: 2px solid rgba(37, 34, 24, .28);
  background-image: repeating-linear-gradient(to bottom, rgba(37, 34, 24, .28) 0 2px, transparent 2px 16px);
  pointer-events: none;
}

.pv__sec { padding-block: var(--s6); border-top: 2px dashed var(--rule); }
.pv__sec:first-child { border-top: 0; }
.pv__h { font-size: clamp(1.25rem, 2.5vw, 1.75rem); margin-bottom: var(--s4); }

/* numbered clauses: a counter, so the sequence cannot fall out of step when a
   clause is added, moved or removed */
.pv__h::before {
  counter-increment: clause;
  content: "Clause " counter(clause, decimal-leading-zero);
  display: block;
  margin-bottom: var(--s2);
  font-family: var(--font-h);
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--act);
}

.pv__sec p + p { margin-top: var(--s4); }

/* ---- stitch-path illustration (services) ------------------------------ */
/*
 * Section 17: "one stitch-path illustration between rows three and four". It is
 * an inline SVG so that it needs no network request, no asset entry and no
 * fallback -- it draws identically with JavaScript off and under file://.
 */

.svc__stitch {
  padding-block: var(--s6);
  border-top: 2px dashed var(--rule);
}

.stitch { margin: 0; }
.stitch__svg { display: block; width: 100%; height: auto; }

.stitch__cloth path {
  fill: none;
  stroke: var(--rule);
  stroke-width: 2;
  stroke-dasharray: 10 8;
}

.stitch__thread {
  fill: none;
  stroke: var(--act);
  stroke-width: 3;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.stitch__pin { fill: none; stroke: var(--acc); stroke-width: 4; stroke-linecap: round; }
.stitch__head { fill: var(--acc); }

.stitch__cap {
  max-width: var(--measure);
  margin: var(--s4) 0 0;
  font-size: .9375rem;
  color: var(--muted);
}

/* ---- fitting ruler (home) --------------------------------------------- */
/*
 * Section 17: "a horizontal 4-step fitting ruler between Services and Gallery".
 * The rail is a real ruler edge -- 2px of ink with brass ticks every 16px and a
 * longer tick every 96px -- and the four steps hang off it. It is painted on the
 * list, so it cannot push the page wider than the viewport at 320px.
 */

.ruler__h { font-size: clamp(1.5rem, 3vw, 2.25rem); margin: 0; }
.ruler__intro { max-width: var(--measure); margin: var(--s4) 0 var(--s6); }

.ruler__list {
  position: relative;
  display: grid;
  gap: var(--s6);
  margin: 0;
  padding: var(--s6) 0 0;
  list-style: none;
  counter-reset: none;
}

.ruler__list::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  height: 14px;
  border-top: 2px solid var(--ink);
  background-image:
    repeating-linear-gradient(90deg, var(--acc) 0 2px, transparent 2px 16px),
    repeating-linear-gradient(90deg, var(--acc) 0 2px, transparent 2px 96px);
  background-size: 100% 6px, 100% 12px;
  background-repeat: no-repeat;
  background-position: 0 2px, 0 2px;
  pointer-events: none;
}

.ruler__step { position: relative; padding-top: var(--s2); }

.ruler__no {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  height: 24px;
  padding-inline: var(--s2);
  background: var(--hi);
  color: var(--deep);
  font-family: var(--font-h);
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .08em;
  border-radius: 0;
}

.ruler__sh { font-size: 1.0625rem; margin: var(--s3) 0 var(--s2); }
.ruler__p { margin: 0; color: var(--muted); font-size: .9375rem; }

/* ---- material swatches (home cta) ------------------------------------- */
/*
 * Section 17 asks for "a three-swatch material strip beside the contact CTA",
 * and for 24-40px fabric swatches site-wide. The chips are 36px and carry the
 * stitch as a dashed inner edge; the cloth names beside them are the accessible
 * content, so the strip is information rather than three coloured squares.
 */

.cta__swatches {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s4);
  margin: var(--s5) 0 0;
  padding: var(--s4);
  list-style: none;
  border: 2px dashed var(--rule);
  border-radius: var(--radius);
  background: var(--bg);
}

.swatch { display: flex; align-items: center; gap: var(--s3); }

.swatch__chip {
  flex: none;
  width: 36px;
  height: 36px;
  border: 2px solid var(--frame);
  border-radius: 0;
  box-shadow: inset 0 0 0 2px var(--surface), inset 0 0 0 3px rgba(37, 34, 24, .35);
}

.swatch__chip--wool { background: #0C1D4B; }
.swatch__chip--linen { background: #B9A36A; }
.swatch__chip--silk { background: #CFB2F0; }

.swatch__label {
  font-family: var(--font-h);
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
}

/* ---- cta and subscribe ------------------------------------------------ */

.cta__in { display: grid; gap: var(--s5); }
.cta__p { max-width: var(--measure); margin: 0; }
.cta__actions { display: flex; flex-wrap: wrap; gap: var(--s3); }
.cta__actions .btn { min-width: 148px; }

/* ---- 404 -------------------------------------------------------------- */

/*
 * Section 17: "a 'pattern piece missing' motif with one outlined garment shape
 * and three recovery links. Keep the message direct and under one viewport."
 *
 * One shape. The edge that is present is an ink cutting line; the lower corner
 * that is absent is a faint dotted ghost of where it should be. The band is
 * deliberately shallow below 768 so the whole page clears a 320x568 viewport,
 * which is measured rather than assumed.
 */
.nf { padding-block: var(--s5); }

.nf__wrap { display: grid; gap: var(--s4); }
/* the shape grows with the screen rather than in one step, so the message
   clears a 320x568 viewport without the piece becoming a token at 414 */
.nf__fig { margin: 0; width: 100%; max-width: clamp(88px, 28vw, 240px); }
.nf__svg { display: block; width: 100%; height: auto; }
.nf__msg { max-width: var(--measure); }

.nf__cut {
  fill: none;
  stroke: var(--ink);
  stroke-width: 2.5;
  stroke-dasharray: 9 7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* where the piece is not */
.nf__gone {
  fill: none;
  stroke: var(--rule);
  stroke-width: 2.5;
  stroke-dasharray: 2 8;
  stroke-linecap: round;
}

.nf__grain { fill: none; stroke: var(--act); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.nf__notch { fill: none; stroke: var(--acc); stroke-width: 3; stroke-linecap: round; }

.nf__code {
  margin: 0;
  font-family: var(--font-h);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: .18em;
  color: var(--act);
}

/* the site's h1 is clamp(2.25rem, 11vw, 3.75rem), which is two 35px lines of
   heading before the message has even started. It comes back at 768. */
.nf__h1 { margin: var(--s2) 0 0; font-size: clamp(1.75rem, 8vw, 2.75rem); }
.nf__p { margin: var(--s4) 0 0; }
.nf__links { display: flex; flex-wrap: wrap; gap: var(--s3); margin-top: var(--s4); }
.nf__links a { display: inline-flex; align-items: center; min-height: 44px; }
.nf__book { margin: var(--s4) 0 0; }

/* ---- breakpoints ------------------------------------------------------ */

/* 414px: two compact metadata columns are allowed, and nothing else changes
   -- body content and forms stay single column, which section 7 requires. */
@media (min-width: 414px) {
  .cd__hours { columns: 2; column-gap: var(--s5); }
  .cd__hours dt, .cd__hours dd { break-inside: avoid; }
  .cd__hours .cd__row { break-inside: avoid; }
}

/* 768px: the desktop identity begins. Two-column sections activate and the
   gallery goes to two columns. */
@media (min-width: 768px) {
  /* the four steps stay in one column to 1024: four ordered steps in a 2x2
     block do not read in order, and four columns at 768 leave 160px a step */
  .svcp__list, .prin__list, .how__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .galp__list, .gal__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .seq__list { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s5); }
  .stf__list, .stfp__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .revp__list, .rev__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* the lead ticket takes the full width at every multi-column width */
  .rev__item--lead { grid-column: 1 / -1; }
  .abt__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s7); }
  .svc__row { grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); gap: var(--s7); }
  .svc__head { flex-direction: column; align-items: flex-start; }
  .cta__in { grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
  /* the swatch strip joins the action column, so it stands beside the CTA copy
     rather than under it */
  .cta__swatches { grid-column: 2; margin-top: 0; }
  .ruler__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .con__grid { grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); }
  /* the pattern piece stands beside the message once there is room for it */
  .nf { padding-block: var(--s8); }
  .nf__wrap { grid-template-columns: 240px minmax(0, 1fr); gap: var(--s8); align-items: center; }
  .nf__fig { max-width: 240px; }
  .nf__h1 { font-size: clamp(3.25rem, 7vw, 7rem); }
  .nf__links { margin-top: var(--s6); }
  .nf__book { margin-top: var(--s5); }
  /* the sheet takes a wider margin once there is room for one */
  .pv__body { padding: var(--s7) var(--s6) var(--s7) var(--s8); }
  .pv__body::before { inset-inline-start: var(--s5); }
}

/* 1024px: the bands reach full depth, the gallery goes to three columns
   because these plates are portrait, and the staff row shows all four. */
@media (min-width: 1024px) {
  .svcp__list, .prin__list, .how__list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .galp__list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .gal__list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .stf__list { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .proc__list { grid-template-columns: repeat(4, minmax(0, 1fr)); }

  /* the measurement line turns and runs across the row */
  .proc__list::before {
    inset-block: auto;
    inset-block-start: 12px;
    inset-inline: 12px;
    width: auto;
    height: 2px;
  }

  .proc__step { padding-inline-start: 0; padding-block-start: var(--s6); }
  .proc__step::before { inset-block-start: 3px; inset-inline-start: 3px; }
  .ruler__list { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s5); }
  .rev__list, .revp__list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* 1600px: the content is already centred at 1320px by --max. The gallery is
   the one band allowed to run wider, to 1600px, because a full-bleed row of
   material photographs is compositional rather than accidental. */
@media (min-width: 1600px) {
  .gal__wrap { max-width: 1600px; }
}

/* 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; }
}
