/* DS-04 Craft Crew -- Cedar Row Landscapes.
 *
 * Every colour below is a token from the Landscaping recommendation of the
 * specification, contrast checked against the text it carries:
 *
 *   ink on page background             16.12:1
 *   ink on the card surface            13.11:1
 *   muted text on page background      10.23:1
 *   action label on #EDEF9F            15.46:1
 *   footer text on the plate           18.71:1
 *
 * The texture is a repeating-linear-gradient weave at two angles, drawn in
 * CSS so nothing extra has to load before the first photograph.
 */




:root {
  --bg: #111C19;
  --ink: #F2F7F6;
  --act: #EDEF9F;
  --acc: #83E2C5;
  --hi: #B0F29C;
  --band: #1F2E29;
  --band2: #253732;
  --rule: #6DB09C;
  --deep: #0B1411;
  --on-act: #101318;
  --on-deep: #FFFFFF;

  /* Section 4's spacing scale, entire. Nothing in this build uses a value
     that is not on it. */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px; --s5: 24px;
  --s6: 32px; --s7: 48px; --s8: 64px; --s9: 96px; --s10: 128px;

  --max: 1320px;
  --measure: 68ch;
  --measure-s: 52ch;
  --radius: 14px;
  --head-h:var(--catalog-font-heading);
  --band-pad: 72px;

  --font-h:var(--catalog-font-heading);
  --font-b:var(--catalog-font-body);

  --t: 220ms cubic-bezier(.2,.8,.2,1);
  --t-long: 600ms cubic-bezier(.2,.8,.2,1);

  --gutter: 16px;
}

@media (min-width: 360px) { :root { --gutter: 18px; } }
@media (min-width: 375px) { :root { --gutter: 20px; } }
@media (min-width: 414px) { :root { --gutter: 24px; } }
@media (min-width: 768px) {
  :root { --gutter: 36px; --band-pad: 80px; --head-h:var(--catalog-font-heading); }
}
@media (min-width: 1024px) {
  :root { --gutter: 48px; --band-pad: 88px; }
}

/* ---- the material ---------------------------------------------------- */

body {
  background-color: var(--bg);
  /* A woven texture at two angles, 3px apart, at an opacity that survives a
     photographic print and disappears behind body text. The gradients are
     fixed-size and do not scale, so the weave stays the same physical size at
     every breakpoint -- a mulch bed does not get coarser on a large screen. */
  background-image:
    repeating-linear-gradient(45deg,
      rgba(242,247,246,.022) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(-45deg,
      rgba(242,247,246,.016) 0 1px, transparent 1px 3px);
  color: var(--ink);
  font-family: var(--font-b);
  font-size: 1rem;
  line-height: 1.6;
}

@media (min-width: 768px) { body { font-size: 1.0625rem; } }

h1, h2, h3, .mark__h, .price__v, .gal__no, .how__no {
  font-family: var(--font-h);
  font-weight: 700;
}

h1 {
  font-size: clamp(2.25rem, 11vw, 3.75rem);
  line-height: .98;
  letter-spacing: -.03em;
  margin: 0;
}

@media (min-width: 768px) {
  h1 {
    font-size: clamp(3.25rem, 7vw, 7rem);
    line-height: .94;
    letter-spacing: -.035em;
  }
}

h2 { font-size: clamp(2rem, 4vw, 4rem); line-height: 1.02; margin: 0; }
h3 { font-size: clamp(1.25rem, 2vw, 1.75rem); line-height: 1.15; margin: 0; }

.measure   { max-width: var(--measure); }
.measure-s { max-width: var(--measure-s); }

a { color: #83E2C5; }
a:hover { color: var(--act); }

:focus-visible {
  outline: 3px solid var(--act);
  outline-offset: 3px;
}

/* ---- the layered terrace bands ------------------------------------- */
/*
 * Each <section> is a band. They alternate between the page ground, a
 * recessed tint and a highlight tint, and every edge between two bands is a
 * edging rule: a dashed 2px line in the ink at low opacity, which is what
 * a run of steel bed edging looks like at arm's length. This is the layout
 * fingerprint and it is why there are no free-floating cards in this build.
 */

.sec {
  position: relative;
  padding-block: var(--band-pad);
  border-top: 2px dashed var(--rule);
}

.sec:first-of-type { border-top: 0; }

.svcp, .prin, .how, .rev, .faqg { background: var(--band); }
.appr, .note, .limit, .alt { background: var(--band2); }

/* The measurement marks: a ruler edge along the top of every recessed band,
   ticks every 16px with a longer tick every 96px. Decoration only -- it is
   aria-hidden by being a background, and it clips inside the viewport at
   320px because it is painted on the band, not on a wider child. */
.svcp::before, .prin::before, .how::before,
.rev::before, .faqg::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  height: 12px;
  background-image:
    repeating-linear-gradient(90deg,
      var(--rule) 0 1px, transparent 1px 16px),
    repeating-linear-gradient(90deg,
      var(--rule) 0 1px, transparent 1px 96px);
  background-size: 100% 6px, 100% 12px;
  background-repeat: no-repeat;
  background-position: 0 0, 0 0;
  opacity: .8;
  pointer-events: none;
}

.wrap {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ---- tool-rack header ------------------------------------------------- */
/*
 * The rail is a 4px bar under the header with two "pegs" -- the wordmark
 * hangs off the left of it and the Book action off the right. At 1024 and up
 * the nine hanging labels hang from the same rail.
 */

.hd {
  position: relative;
  background: var(--bg);
  border-bottom: 1px solid var(--rule);
}

.hd__in {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  min-height: var(--head-h);
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.mark {
  line-height: 1.05;
  text-decoration: none;
  color: var(--ink);
  padding-block: var(--s2);
}

.mark__h { font-size: 1.25rem; letter-spacing: -.015em; }

.mark__sub {
  font-size: .8125rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--acc);
  font-weight: 600;
}

/* ---- hanging label navigation ---------------------------------------- */
/*
 * Each link is a paper label on a 12px stem. The stem is a ::before on the
 * link, so it moves with the link and cannot be left behind by a wrap. The
 * label itself is at least 44px tall including the stem, which is what makes
 * the touch target legal.
 */

.nav { display: none; }

.nav__list {
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nav__link {
  position: relative;
  display: block;
  margin-top: 12px;
  padding: 6px var(--s3) 8px;
  min-height: 32px;
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 0 0 6px 6px;
  color: var(--ink);
  font-size: .875rem;
  line-height: 1.35;
  text-decoration: none;
  transition: background var(--t), border-color var(--t), transform var(--t);
}

.nav__link::before {           /* the stem the label hangs on */
  content: "";
  position: absolute;
  inset-block-start: -12px;
  inset-inline-start: 50%;
  width: 1px;
  height: 12px;
  background: var(--rule);
}

.nav__link:hover { background: var(--band2); transform: translateY(2px); }

.nav__link[aria-current="page"] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--bg);
  font-weight: 600;
}

.nav__link[aria-current="page"]::before { background: var(--ink); }

.nav__no {
  display: block;
  font-size: .75rem;
  letter-spacing: .1em;
  color: var(--acc);
}

.nav__link[aria-current="page"] .nav__no { color: var(--hi); }

@media (min-width: 1024px) {
  .nav { display: block; }
  .drawer { display: none; }
}

/* ---- the disclosure that replaces it below 1024 ---------------------- */

.drawer { position: relative; }

.drawer__toggle {
  display: flex;
  align-items: center;
  gap: var(--s2);
  min-height: 44px;
  min-width: 44px;
  padding: var(--s2) var(--s3);
  border: 2px solid var(--rule);
  border-radius: 8px;
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}

.drawer__toggle::-webkit-details-marker { display: none; }

.drawer__bars {
  width: 18px;
  height: 2px;
  background: currentColor;
  box-shadow: 0 -6px 0 currentColor, 0 6px 0 currentColor;
}

/* Below 375px the three header items -- wordmark, Book action, drawer toggle
   -- do not fit a 320px viewport with 16px gutters: 101 + 92 + 92 + 32 gaps
   + 32 padding is 349, and flex will not shrink a control that has declared a
   44px floor. The toggle drops its word and becomes a 46px square, which
   brings the row to 303 and takes the drawer panel back inside the viewport
   with it.

   The word is CLIPPED, not display:none. A `display: none` label leaves the
   summary with nothing but an aria-hidden icon, so the control loses its
   accessible name and a screen reader announces an unlabelled disclosure --
   the exact failure this rule is meant to avoid making. Clipped, it takes no
   layout space and still names the control. */
@media (max-width: 374px) {
  .drawer__word {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

.drawer__panel {
  position: absolute;
  inset-inline-end: 0;
  inset-block-start: calc(100% + var(--s2));
  z-index: 40;
  width: min(20rem, calc(100vw - (var(--gutter) * 2)));
  padding: var(--s3);
  background: var(--bg);
  border: 2px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: 0 18px 40px rgba(0,0,0,.45);
}

.drawer__link {
  display: block;
  min-height: 44px;
  padding: var(--s3);
  border-bottom: 1px dashed var(--rule);
  color: var(--ink);
  text-decoration: none;
}

.drawer__link:last-child { border-bottom: 0; }
.drawer__link[aria-current="page"] { font-weight: 700; color: var(--act); }

/* ---- actions ---------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: var(--s3) var(--s5);
  border: 2px solid transparent;
  border-radius: var(--radius);
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--t), color var(--t), border-color var(--t);
}

.btn--primary, .btn--book {
  background: var(--act);
  color: var(--on-act);
  border-color: var(--act);
}

/* Hover, focus and active all keep the label at full contrast -- section 5
   requires the Book label visible in every one of the four states, and a
   button that pales on hover is the usual way that is failed. */
.btn--primary:hover, .btn--book:hover,
.btn--primary:active, .btn--book:active {
  background: #F3F5B7;
  border-color: #F3F5B7;
  color: var(--on-act);
}

.btn--ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--ink);
}

.btn--ghost:hover { background: var(--ink); color: var(--bg); }

/* ---- maker-mark footer ------------------------------------------------ */
/*
 * A stamped plate carrying the business name sits above the footer columns,
 * the way a maker's mark is struck into the inside of a planting. The plate is
 * the darkened ink, and the footer body sits on it.
 */

.ft {
  background: var(--deep);
  color: var(--on-deep);
  border-top: 1px solid var(--rule);
  padding-block: 44px;
}

/* Section 17: 40-56px of padding on mobile, 64-96px from the desktop step. */
@media (min-width: 1024px) {
  .ft { padding-block: 76px; }
}

/*
 * Four zones. One ordered column on a phone, two at the tablet step, and at
 * 1024 the four sit side by side with a 32px gutter -- inside section 17's
 * 24-40px column gap. The brand column is widest because it carries the
 * stamped plate and the summary sentence; the page list is narrowest.
 */

.ft__in {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 24px;
}

@media (min-width: 768px) {
  .ft__in {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 32px;
  }
}

@media (min-width: 1024px) {
  .ft__in {
    grid-template-columns: 1.25fr 0.85fr 0.95fr 1.15fr;
    gap: 32px;
  }

  /*
   * 404.html has three zones, not four: it must not ship a subscribe band
   * (validate.py fails a 404 that does) and section 17 requires the four-zone
   * footer on every PRIMARY page, which 404 is not. Without its own track list
   * the three zones sat in the left three-quarters with a dead column beside
   * them.
   */
  .ft__in--compact { grid-template-columns: 1.2fr 0.9fr 1.05fr; }
}

.ft__block { min-width: 0; }

/*
 * Section 17 asks for a clear hierarchy between 12-14px labels and 16-20px
 * useful text. The labels are 13px, struck in the gold, letter-spaced like the
 * stencilled headings on a tool rack; everything a visitor actually reads is
 * 16px or the 18px wordmark.
 */

.ft__h {
  margin: 0 0 var(--s3);
  font-family: var(--font-h);
  font-size: .8125rem;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--hi);
}

.ft__h--2 { margin-top: var(--s5); }

.ft__sum {
  margin: 0;
  max-width: 34ch;
  font-size: 1rem;
  line-height: 1.6;
  color: #E3ECE9;
}

.ft__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s2) var(--s4);
  font-size: 1rem;
}

/* At 1024 the list has its own column and reads straight down. */
@media (min-width: 1024px) {
  .ft__list {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s1);
  }
}

.ft__list a {
  display: inline-block;
  padding-block: 3px;
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.ft__list a:hover,
.ft__list a:focus-visible { border-bottom-color: var(--hi); }

.ft__act { margin: var(--s4) 0 0; }

.ft__act .btn { width: 100%; max-width: 232px; }

.ft__addr {
  margin: 0;
  font-style: normal;
  font-size: 1rem;
  line-height: 1.7;
}

.ft__addr a {
  text-decoration: underline;
  text-underline-offset: .2em;
  overflow-wrap: anywhere;
}

.ft__hours {
  margin: 0;
  font-size: 1rem;
}

/*
 * dt and dd are paired on one row with the hours pushed right, ruled off with
 * the same dashed accent as the marked-out edge so the block reads as a docket
 * rather than a list. It wraps to two lines at 320 instead of colliding.
 */

.ft__row {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s1) var(--s3);
  padding-block: 6px;
  border-bottom: 1px dashed rgba(176, 242, 156, .3);
}

.ft__row:last-child { border-bottom: 0; }

/*
 * In the four-column footer the hours column is about 250px, so the long values
 * wrap under their labels and land left while "Closed" stays on its row and
 * sits right. Stacking the pair makes that one deliberate shape instead of two
 * accidental ones.
 */
@media (min-width: 1024px) {
  .ft__row {
    flex-direction: column;
    gap: 2px;
  }
}

.ft__row dt { color: #E3ECE9; }

.ft__row dd {
  margin: 0;
  font-weight: 600;
  color: var(--on-deep);
}

.ft__subp {
  margin: 0 0 var(--s4);
  max-width: 42ch;
  font-size: 1rem;
  line-height: 1.6;
  color: #E3ECE9;
}

.ft__note {
  margin: var(--s3) 0 0;
  font-size: .8125rem;
  line-height: 1.5;
  color: #B9CAC5;
}

.ft__note a { text-decoration: underline; }

.ft__foot {
  margin-top: var(--s6);
  padding-top: var(--s4);
  border-top: 1px solid rgba(109, 176, 156, .3);
}

.ft__legal {
  margin: 0;
  font-size: .8125rem;
  line-height: 1.5;
  color: #B9CAC5;
}

.ft__legal a { text-decoration: underline; }

.ft a { color: var(--on-deep); }
.ft a:hover { color: var(--hi); }

.ft__mark {
  padding: var(--s3) var(--s5);
  border: 2px solid var(--hi);
  border-radius: 6px;
  margin-bottom: var(--s4);
}

.ft__mark-h {
  font-family: var(--font-h);
  font-weight: 700;
  font-size: 1.125rem;
  letter-spacing: .02em;
}

.ft__mark-sub {
  font-size: .8125rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--hi);
}

/* ---- forms ------------------------------------------------------------ */

.field label {
  display: block;
  font-size: .875rem;
  line-height: 1.35;
  font-weight: 600;
  margin-bottom: var(--s2);
}

.field input, .field select, .field textarea {
  width: 100%;
  min-height: 44px;
  padding: var(--s3);
  border: 2px solid var(--rule);
  border-radius: 8px;
  background: #1F2E29;
  color: var(--ink);
  font: inherit;
}

.field textarea { min-height: 168px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--act);
}

/*
 * The subscribe form, section 17's fourth zone. It sits on the dark plate, so
 * its focus border takes the gold rather than the action brown, and its result
 * region reserves its own height so a reply does not shove the legal bar down.
 */

.sub-form { margin: 0; }

.sub-form__field { margin-bottom: var(--s3); }

.sub-form input:focus { border-color: var(--hi); }

.btn--sub {
  width: 100%;
  max-width: 232px;
  background: var(--hi);
  color: var(--deep);
  border-color: var(--hi);
}

.btn--sub:hover,
.btn--sub:active {
  background: #C6F7B6;
  border-color: #C6F7B6;
  color: var(--deep);
}

.sub-form__status {
  margin: var(--s3) 0 0;
  min-height: 2.9em;
  font-size: .875rem;
  line-height: 1.45;
  color: #B9CAC5;
}

.sub-form__status[data-state="ok"] { color: #A8D6B7; }
.sub-form__status[data-state="error"] { color: #FFB4A2; }

/*
 * The per-field error line. forms.ts writes text into it and clears it again,
 * so it must collapse when empty or every form ships a blank gap. Like
 * .sub-form__status it had no rule at all until now: both are markup the
 * stylesheet gate cannot see, because that gate reads CSS -> HTML only.
 */

.err {
  margin: var(--s2) 0 0;
  font-size: .875rem;
  line-height: 1.4;
  font-weight: 600;
  color: #FFB4A2;
}

.err:empty { display: none; }

.ft .err { color: #FFB4A2; }

/* ---- reduced motion --------------------------------------------------- */
/*
 * Section 4's animation-off state: the magnified inset becomes an ordinary
 * adjacent crop and nothing follows the pointer. The shipped magnifier is
 * already that composition -- a <details> that grows in place, over nothing,
 * following nothing -- so the only thing left to remove is the width
 * transition, which base.css kills globally. What stays here is the one
 * effect that is genuinely motion: the nav label lifting on its stem.
 */

@media (prefers-reduced-motion: reduce) {
  .nav__link:hover { transform: none; }
}


/* ---- signature: the edged border, the staked card, the work-order row ---
 *
 * Section 17 asks each design for one signature device of its own rather than a
 * shared polish layer. This one is a marked-out bed edge: a 2px dashed rule
 * at 8px intervals struck across the footer under its ink border, the same
 * gesture a bed edge is strung out with before it is cut. It appears
 * once, on the footer, so it reads as a maker's mark rather than a texture.
 */

.ft {
  position: relative;
}

.ft::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: var(--s3);
  height: 2px;
  background: repeating-linear-gradient(90deg,
    var(--hi) 0 8px, transparent 8px 16px);
  opacity: .55;
  pointer-events: none;
}

.ft a {
  text-underline-offset: .28em;
  transition: color .2s ease;
}

/*
 * A staff card lifts and takes a quarter-degree of rotation on hover, the way a
 * card pinned to a board sits slightly off square. `:focus-within` is included
 * so the same affordance reaches a keyboard, which the pasted block never did.
 */

.stf__card {
  transition: transform .28s ease, box-shadow .28s ease, border-color .28s ease;
}

.stf__card:hover,
.stf__card:focus-within {
  transform: translateY(-3px) rotate(.25deg);
  border-color: var(--act);
  box-shadow: 0 18px 48px rgba(0, 0, 0, .35);
}

/*
 * The four planting questions on the contact form are the work order proper, as
 * distinct from the visitor's own name and message. They are ruled off with a
 * 3px action-coloured edge, the way a docket is ruled down its binding side.
 * These four elements carried the class and no rule at all until now: the
 * stylesheet gate only checks CSS -> HTML, so an unstyled class in the markup is
 * never flagged.
 */

.field--intake {
  padding: var(--s3) var(--s3) var(--s3) var(--s4);
  border-inline-start: 3px solid var(--act);
  border-radius: 0 6px 6px 0;
  background: var(--band2);
}

.field--intake label {
  font-weight: 700;
}

@media (prefers-reduced-motion: reduce) {
  .stf__card { transition: none; }
  .stf__card:hover,
  .stf__card:focus-within { transform: none; }
}

/* ---- DS-04-E001 house emblem ------------------------------------------ */
/*
 * One mark, two placements. Both hosts become a two-column grid so the
 * emblem can sit beside the existing two-line wordmark without either text
 * span moving relative to the other - the composition is unchanged, the
 * emblem is simply given its own column. The tile carries the action brown
 * and the mark is knocked out of it in white, which clears 4.5 against the
 * tile on the paper header and on the deep footer alike.
 */
.mark {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr);
  column-gap: var(--s3);
  align-items: center;
}

/* base.css resets every svg to max-width:100%, which is right for media and
   wrong for a fixed mark: inside the flexing header the emblem's column gets
   squeezed and the svg collapses to 0 wide while keeping its height. The
   track is therefore a fixed 34px and the svg opts out of the reset. */
.mark__em { grid-row: 1 / 3; display: block; width: 34px; }
.mark__em svg { display: block; width: 34px; height: 34px; max-width: none; flex: none; }
.mark__h, .mark__sub { grid-column: 2; }

.ft__mark {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  column-gap: var(--s3);
  align-items: center;
}

.ft__em { grid-row: 1 / 3; display: block; width: 30px; }
.ft__em svg { display: block; width: 30px; height: 30px; max-width: none; flex: none; }
.ft__mark-h, .ft__mark-sub { grid-column: 2; }

.em__tile { fill: var(--act); }
.em__ink { fill: var(--on-act); }
.em__thread { fill: none; stroke: var(--on-act); stroke-width: 2.6; stroke-linecap: round; }
.em__eye { fill: var(--act); }

@media (max-width: 359px) {
  /* 320 is a required width and the header has no room to spare there. */
  .mark { column-gap: var(--s2); grid-template-columns: 28px minmax(0, 1fr); }
  .mark__em, .mark__em svg { width: 28px; }
  .mark__em svg { height: 28px; }
}

/* ---- landscaping: pressed state of the action ------------------------ */
.btn--primary:active, .btn--book:active {
  background: #E5E887;
  border-color: #E5E887;
  color: var(--on-act);
}
