/* West Tower Matchmaker.
   Brand tokens read from westtower.com's own stylesheet, 20 August 2026.
   Mobile first throughout. Every input sits at 16px or larger so iOS does not zoom
   on focus, and the layout holds down to about 260px. */

:root {
  --primary: #c59c5b;        /* gold, the brand accent and primary CTA */
  /* The brand gold is only 2.33:1 on cream, so it fails AA as TEXT. It stays the
     fill and rule colour everywhere; this darker gold is for gold-coloured words
     on a light ground. Chosen to clear 4.5:1 on BOTH page grounds, the cream and
     the warm sand panels: 5.06:1 and 4.65:1. Never use --primary for text. */
  --gold-ink: #836428;
  --secondary: #f3ebde;      /* warm sand, section grounds */
  --light-primary: #f9f5ee;  /* cream, page background and text on dark */
  --body-color: #2b2b2b;
  --dark-green: #848e7d;
  --light-green: #a6b29d;
  --dark-grey: #6a6a6a;      /* all heading text, per their system */
  --darker-grey: #42473e;    /* footer ground */
  --line: #e2d7c4;
  --radius: 8px;             /* they round every image at 8px */
  --ease: cubic-bezier(.76, 0, .24, 1);
  --head: "ivypresto-display", "Cormorant Garamond", Georgia, serif;
  --body: "new-hero", "Jost", "Helvetica Neue", Arial, sans-serif;
}

* { box-sizing: border-box; }

/* Serif faces default to oldstyle figures, which turns 100 into something that
   reads as IOO and a price into guesswork. Force lining figures everywhere a
   number carries meaning. */
.bracket-fig, .yours-fig, .slider-val, .bd-val, .bracket-day, .yours-day,
.slider-help, .r-sub, .date-echo {
  font-variant-numeric: lining-nums;
  font-feature-settings: "lnum" 1;
}

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--light-primary);
  color: var(--body-color);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.5;
  letter-spacing: .4px;
  overflow-x: hidden;
}

h1, h2, h3 {
  font-family: var(--head);
  font-weight: 300;
  color: var(--dark-grey);
  line-height: 1.2;
  letter-spacing: 1.6px;
  margin: 0 0 12px;
}

p { margin: 0 0 16px; }

a { color: inherit; }

.skip {
  position: absolute; left: -9999px;
  background: var(--primary); color: var(--light-primary);
  padding: 10px 16px; border-radius: 100px; z-index: 60;
}
.skip:focus { left: 12px; top: 12px; }

/* ------------------------------------------------------------ chrome */

.site-head {
  padding: 16px;
  text-align: center;
  background: var(--light-primary);
}
.wordmark { display: inline-block; line-height: 0; }
.wordmark img {
  width: 172px; height: auto;
  max-width: 60vw;
}

.site-foot {
  margin-top: 48px;
  padding: 34px 16px;
  background: var(--darker-grey);
  color: var(--light-primary);
  text-align: center;
  font-size: 14px;
}
.site-foot p { margin: 0 0 6px; }
.site-foot a {
  color: var(--light-primary);
  /* Was a 21px tap target; the padding lifts it over the 44px floor without
     changing how the footer reads. */
  display: inline-block;
  padding: 12px 4px;
}
.foot-mark { width: 38px; height: auto; opacity: .85; margin-bottom: 14px; }

/* Agency credit, the last line of the footer. Quiet enough to stay out of the
   venue's way and still legible: cream at .72 over the footer ground is 5.4:1,
   which clears AA with room to spare. Do not take it below .65, which is where
   it starts to fail. The padding is what lifts a 12px link over the 44px tap
   target floor this build holds every other footer link to. */
.foot-credit {
  margin: 16px 0 0;
  font-size: 12px;
  opacity: .72;
}
.foot-credit a {
  color: inherit;
  padding: 15px 6px;
}

/* Full bleed photography, the way westtower.com opens a page. */
.hero-shot {
  position: relative;
  margin: 0 0 26px;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  line-height: 0;
}
.hero-shot img {
  width: 100%;
  height: clamp(210px, 42vh, 420px);
  object-fit: cover;
  display: block;
}
.hero-cap {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 44px 20px 18px;
  /* A soft scrim so the type stays legible over any frame. */
  background: linear-gradient(to top, rgba(43, 43, 43, .62), rgba(43, 43, 43, 0));
  text-align: center;
}
.hero-cap-line {
  font-family: var(--head);
  font-size: 19px;
  font-weight: 300;
  letter-spacing: 1.6px;
  color: #fff;
  line-height: 1.25;
}

main {
  max-width: 760px;
  margin: 0 auto;
  padding: 0 16px;
}
/* The top space belongs to the content, not the page, so a hero that leads a
   screen can cancel it and meet the header edge to edge. Left on main it
   produced an empty band under the header that read as a stray divider. */
.step, .results { padding-top: 24px; }
.step > .hero-shot:first-child,
.results > .hero-shot:first-child { margin-top: -24px; }

/* ------------------------------------------------------------ buttons */

.btn {
  display: inline-block;
  font-family: var(--body);
  font-size: 16px;              /* 16px floor, no iOS zoom */
  font-weight: 500;
  line-height: 1.5;
  padding: 13px 26px;
  border: 0;
  border-radius: 100px;         /* their pill */
  letter-spacing: normal;       /* buttons are the one untracked element */
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background .2s var(--ease), opacity .2s var(--ease);
}
/* Ink on gold, not cream on gold. The brand gold is light enough that cream on
   it measures 2.33:1, which fails AA for any size of text, and this is the
   primary button on every step of the tool. Ink on the same gold is 5.58:1 and
   leaves the brand colour itself untouched. */
.btn-primary { background: var(--primary); color: #2b2b2b; }
.btn-primary:hover { background: #b78c48; }
.btn-quiet { background: transparent; color: var(--dark-grey); text-decoration: underline; padding-left: 0; padding-right: 0; font-size: 16px; }

/* Buttons appended as bare siblings have no whitespace between them, so two
   inline-blocks sit flush and the pill reads as overlapping the text link next
   to it. Anything inside .step-actions is already spaced by that row's gap, so
   this only applies to the loose pairs elsewhere. */
.q-body > .btn + .btn { margin-left: 16px; }
@media (max-width: 460px) {
  /* Loose button pairs stack full width on a phone. The Back and Continue row is
     excluded: the two fit side by side at any phone width, and stacking them put
     Back above Continue, which reads as the wrong thing being offered first. */
  .q-body > .btn { display: block; width: 100%; }
  .q-body > .btn + .btn { margin-left: 0; margin-top: 12px; }
  .q-body > .btn-quiet { width: auto; }
}
.btn-big { padding: 15px 34px; font-size: 17px; }
.btn:disabled { opacity: .38; cursor: default; }
.btn-primary:disabled:hover { background: var(--primary); }

/* -------------------------------------------------------------- steps */

/* Ten marks, one per question, in place of the words "Question 1 of 10". The
   count still reaches a screen reader through aria-valuetext on the bar. */
.progress {
  display: flex;
  gap: 5px;
  flex: 1 1 auto;
  min-width: 0;
  max-width: 320px;
  align-items: center;
}
.progress-seg {
  flex: 1 1 0;
  min-width: 0;
  height: 3px;
  border-radius: 100px;
  background: var(--line);
  transition: background .3s var(--ease), height .3s var(--ease);
}
.progress-seg.is-done { background: var(--primary); }
/* The one they are on is the tallest thing in the row, so position reads at a
   glance without a number. */
.progress-seg.is-now {
  background: var(--primary);
  height: 7px;
}

.step-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  margin-bottom: 22px;
}

.q-title { font-size: 27px; margin-bottom: 10px; }
.q-help { font-size: 15px; color: var(--dark-grey); margin-bottom: 20px; }
.q-body { margin-top: 18px; }

/* ------------------------------------------------------------ choices */

.choices { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 20px; }
.choices-stack { flex-direction: column; flex-wrap: nowrap; }

.choice {
  font-family: var(--body);
  font-size: 16px;
  text-align: left;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px;
  cursor: pointer;
  transition: border-color .2s var(--ease), background .2s var(--ease);
  color: var(--body-color);
}
.choice:hover { border-color: var(--primary); }
.choice.is-on { border-color: var(--primary); background: var(--secondary); }
.choice-rich { display: flex; flex-direction: column; gap: 4px; width: 100%; }
.choice-label { font-weight: 500; }
.choice-note { font-size: 14px; color: var(--dark-grey); line-height: 1.4; }
.choice.is-fixed { opacity: .8; cursor: default; }

/* -------------------------------------------------------------- forms */

.field { display: block; margin-bottom: 16px; }
.field-label { display: block; font-size: 14px; color: var(--dark-grey); margin-bottom: 6px; }

.input {
  width: 100%;
  font-family: var(--body);
  font-size: 16px;              /* never below 16px */
  line-height: 1.4;
  padding: 13px 14px;
  min-height: 50px;
  color: var(--body-color);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  -webkit-appearance: none;
  appearance: none;
}
.input:focus { outline: 2px solid var(--primary); outline-offset: 1px; }

select.input { background-image: none; }

.row { display: flex; gap: 10px; margin-bottom: 16px; }
.row .input { flex: 1 1 0; min-width: 0; }

/* iOS renders an empty date input blank, so it carries its own placeholder.
   Desktop browsers do the opposite and paint their own mm/dd/yyyy in the empty
   field, which sat underneath the overlay and read as two prompts mashed
   together. So: while the field is empty and unfocused the native text is made
   transparent and the overlay is the only prompt; the moment it gains focus the
   native fields come back and the overlay goes, so typing a date by hand still
   works. On iOS the native text is blank anyway, so this changes nothing there. */
.date-wrap { position: relative; margin-bottom: 12px; }
.date-input { min-height: 52px; text-align: left; }
.date-wrap:not(.has-value) .date-input:not(:focus)::-webkit-datetime-edit {
  color: transparent;
}
.date-placeholder {
  position: absolute;
  left: 15px; top: 50%; transform: translateY(-50%);
  font-size: 16px; color: #9a9a9a;
  pointer-events: none;
}
.date-wrap.has-value .date-placeholder { display: none; }
.date-wrap:focus-within .date-placeholder { display: none; }

/* Firefox cannot hide its native field text, so there the overlay is what goes:
   the browser's own prompt does the job on its own. */
@supports not selector(::-webkit-datetime-edit) {
  .date-placeholder { display: none; }
}
.date-echo { font-size: 15px; color: var(--dark-grey); }

/* The whole row is the label, so tapping the sentence toggles the box. It still
   needs to clear 44px in its own right: this is the consent that decides whether
   West Tower may contact them, and a mis-tap here is a compliance problem, not
   just an annoyance. */
.consent {
  display: flex; align-items: flex-start; gap: 12px;
  font-size: 14px; color: var(--dark-grey);
  margin: 4px 0 20px; line-height: 1.4;
  min-height: 44px;
  padding: 10px 0;
  cursor: pointer;
}
.consent input {
  width: 24px; height: 24px; margin: 0; flex: none;
  accent-color: var(--primary);
}

/* ------------------------------------------------------------- flags */

.flag {
  font-size: 15px;
  line-height: 1.45;
  padding: 13px 15px;
  border-radius: var(--radius);
  border-left: 3px solid var(--primary);
  background: var(--secondary);
  margin: 0 0 18px;
}
.flag-good { border-left-color: var(--light-green); }
.flag-warn { border-left-color: #b8794a; }

/* ----------------------------------------------------------- results */

.r-head { padding: 8px 0 4px; }
.r-title { font-size: 30px; letter-spacing: 1.4px; }
.r-sub { font-size: 16px; color: var(--dark-grey); }

.r-section { margin: 34px 0; }
.r-h2 { font-size: 23px; }
.r-note { font-size: 15px; color: var(--dark-grey); line-height: 1.5; }
.r-note-quiet { font-size: 14px; font-style: italic; }

/* Running order */
.runorder { list-style: none; margin: 14px 0 0; padding: 0; }
.ro-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2px;
  padding: 13px 0;
  border-bottom: 1px solid var(--line);
}
.ro-when { font-size: 13px; letter-spacing: 1.4px; text-transform: uppercase; color: var(--gold-ink); }
.ro-what { font-size: 16px; line-height: 1.45; }

/* Gallery. The heaviest thing on the page, so lazy and sized from the start. */
.gallery {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
  margin-top: 14px;
}
.shot { margin: 0; }
.shot img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: var(--radius);   /* their 8px, everywhere */
  background: var(--secondary);
}
.shot-placeholder img { opacity: .95; }

/* Bracket */
.bracket {
  background: var(--secondary);
  border-radius: var(--radius);
  padding: 18px 16px;
  margin: 16px 0 18px;
}
.bracket-ends { display: flex; justify-content: space-between; gap: 10px; }
.bracket-end { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.bracket-end-right { text-align: right; align-items: flex-end; }
.bracket-cap { font-size: 12px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--dark-grey); }
.bracket-fig { font-family: var(--head); font-size: 25px; color: var(--dark-grey); line-height: 1.1; }
.bracket-day { font-size: 12px; color: var(--dark-grey); }

.track {
  position: relative;
  height: 3px;
  background: linear-gradient(90deg, var(--light-green), var(--primary));
  border-radius: 100px;
  margin: 16px 0 12px;
}
/* A position indicator, deliberately NOT styled like a slider thumb. The round
   white handle it used to be read as draggable, and a couple who tries to drag
   a static marker concludes the page is broken. A slim tick reads as "you are
   here" the way a map pin does. */
.track-marker {
  position: absolute; top: 50%;
  width: 3px; height: 17px;
  background: var(--primary);
  border-radius: 2px;
  transform: translate(-50%, -50%);
  transition: left .25s var(--ease);
}
.track-marker::after {
  content: "";
  position: absolute;
  left: 50%; top: -5px;
  width: 7px; height: 7px;
  background: var(--primary);
  border-radius: 50%;
  transform: translateX(-50%);
}

.yours { display: flex; flex-direction: column; gap: 1px; align-items: center; text-align: center; }
.yours-cap { font-size: 12px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--dark-grey); }
.yours-fig { font-family: var(--head); font-size: 33px; color: var(--body-color); line-height: 1.1; }
.yours-day { font-size: 13px; color: var(--dark-grey); }

/* Sliders */
.sliders { margin: 22px 0 8px; }
.slider { margin-bottom: 20px; }
.slider-top { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.slider-label { font-size: 15px; }
.slider-val { font-family: var(--head); font-size: 22px; color: var(--dark-grey); }
.slider-help { font-size: 13px; color: var(--dark-grey); margin: 4px 0 0; line-height: 1.4; }

.range {
  display: block;
  width: calc(100% - 26px);     /* keep the thumb inside the track at both ends */
  margin: 4px auto 0;
  /* 44px is the accessibility floor for anything you drag with a thumb, and the
     guest sliders are the main interaction on the results page. The visible track
     stays 3px; the extra height is invisible grab area around it. */
  height: 44px;
  background: transparent;
  -webkit-appearance: none;
  appearance: none;
}
.range::-webkit-slider-runnable-track { height: 3px; background: var(--line); border-radius: 100px; }
.range::-moz-range-track { height: 3px; background: var(--line); border-radius: 100px; }
.range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 26px; height: 26px; margin-top: -11.5px;
  background: var(--primary); border: 0; border-radius: 50%; cursor: pointer;
}
.range::-moz-range-thumb {
  width: 26px; height: 26px;
  background: var(--primary); border: 0; border-radius: 50%; cursor: pointer;
}

/* Breakdown */
.breakdown { margin-top: 20px; }
.bd-h { font-size: 17px; font-family: var(--body); font-weight: 500; color: var(--body-color); letter-spacing: .4px; }
.bd-list { list-style: none; margin: 10px 0 0; padding: 0; }
.bd-row {
  display: flex; justify-content: space-between; gap: 14px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
  font-size: 15px;
}
.bd-label { color: var(--dark-grey); min-width: 0; }
.bd-val { white-space: nowrap; }
.bd-row-req .bd-val { font-style: italic; color: var(--dark-grey); }
.bd-total { border-bottom: 0; border-top: 2px solid var(--primary); font-size: 17px; padding-top: 13px; }
.bd-total .bd-label { color: var(--body-color); }
.bd-total .bd-val { font-family: var(--head); font-size: 21px; }

/* Includes */
.includes { margin: 12px 0 0; padding-left: 20px; }
.includes li { margin-bottom: 9px; font-size: 15px; line-height: 1.5; }

/* Twilight door and CTA */
.r-twilight {
  margin: 34px 0;
  padding: 20px 18px;
  background: var(--secondary);
  border-radius: var(--radius);
}
.r-twilight .r-h2 { font-size: 20px; }
.r-twilight .r-note { margin-bottom: 0; }

/* The close. A filled gold card with the venue's mark at the head of it, so the
   page finishes on something composed rather than trailing off into a button.
   The gold is deliberately the only large area of brand colour on the page. */
.r-cta {
  margin: 38px 0;
  padding: 30px 22px 28px;
  background: var(--primary);
  color: var(--light-primary);
  border-radius: var(--radius);
  text-align: center;
  /* A soft inner edge, so the card reads as pressed rather than flat. */
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .16);
}
/* The white mark on the gold card. The dark one turned to mud on this ground.
   The markup already points at the white file, so nothing is overridden here. */
.r-cta-mark {
  width: 32px; height: auto;
  opacity: .95;
  margin-bottom: 16px;
}
/* Everything on the gold card is ink for the same reason as the button above:
   cream on this gold is 2.33:1. Ink reads as engraved on the gold rather than
   printed over it, which suits the card. */
.r-cta-title {
  color: #241d12;
  font-size: 26px;
  margin-bottom: 10px;
}
.r-cta-note {
  color: #2b2b2b;
  font-size: 15px;
  max-width: 34ch;
  margin-left: auto;
  margin-right: auto;
}
/* Inverted against the gold card: cream fill, deep gold text at 4.62:1. */
.r-cta .btn-primary { background: var(--light-primary); color: var(--gold-ink); }
.r-cta .btn-primary:hover { background: #fff; }
/* The line height carries the tel link's padding. Without the extra room a
   padded inline link overlaps the line above it. */
.r-cta-soft { color: #3a3226; font-size: 14px; margin: 16px 0 0; line-height: 2.4; }
/* The number is the second action, so it is underlined and a real tap target
   rather than looking like part of the sentence. */
/* The number is the second action on the page and wants to be tappable. An
   inline link inside a sentence is exempt from the 44px target rule, but it is
   a phone number on a phone, so it gets as close as it can without breaking the
   sentence it sits in. */
.r-cta-tel {
  color: #241d12;
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 3px;
  white-space: nowrap;
  padding: 12px 6px;
  margin: 0 2px;
  border-radius: 4px;
}
.r-cta-tel:hover { background: rgba(255, 255, 255, .28); }

.r-foot { margin: 30px 0 10px; }
/* Stays at the 16px floor even though it is a read only field: tapping it still
   focuses, and anything under 16px makes iOS zoom the page. */
.link-field { font-size: 16px; color: var(--dark-grey); margin-bottom: 12px; }

/* Gate and preview */
.gate { text-align: center; padding: 40px 0 20px; }
.gate .r-sub { max-width: 460px; margin: 0 auto 22px; }

.preview-badge {
  position: fixed; left: 10px; bottom: 10px; z-index: 50;
  background: var(--darker-grey); color: var(--light-primary);
  font-size: 12px; letter-spacing: 1px;
  padding: 7px 13px; border-radius: 100px;
}

.toast {
  position: fixed; left: 50%; bottom: 16px;
  transform: translate(-50%, 130%);
  background: var(--darker-grey); color: var(--light-primary);
  font-size: 14px; padding: 12px 18px; border-radius: 100px;
  max-width: calc(100vw - 24px);
  transition: transform .3s var(--ease);
  z-index: 55;
}
.toast.is-on { transform: translate(-50%, 0); }

/* ------------------------------------------------------- wider screens */

@media (min-width: 620px) {
  main { padding: 0 24px; }
  .step, .results { padding-top: 34px; }
  .step > .hero-shot:first-child,
  .results > .hero-shot:first-child { margin-top: -34px; }
  .q-title { font-size: 33px; }
  .r-title { font-size: 40px; }
  .r-h2 { font-size: 27px; }
  .ro-row { grid-template-columns: 150px 1fr; gap: 16px; align-items: baseline; }
  /* Pairs stay pairs at every width; the grouping is the point. */
  .shot-group .gallery { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .bracket { padding: 24px 22px; }
  .bracket-fig { font-size: 29px; }
  .yours-fig { font-size: 40px; }
  .r-cta { padding: 40px 30px; }
  .wordmark img { width: 210px; }
  .hero-shot { margin-bottom: 34px; }
  .hero-shot img { height: clamp(280px, 46vh, 520px); }
  .hero-cap-line { font-size: 26px; }
  .hero-cap { padding: 60px 24px 26px; }
}

/* Very narrow. A client reviewed a previous build at 258px. */
@media (max-width: 340px) {
  main { padding: 0 10px; }
  .step, .results { padding-top: 18px; }
  .step > .hero-shot:first-child,
  .results > .hero-shot:first-child { margin-top: -18px; }
  .q-title { font-size: 22px; }
  .r-title { font-size: 24px; }
  .wordmark img { width: 138px; }
  .hero-shot img { height: 175px; }
  .hero-cap-line { font-size: 15px; }
  .hero-cap { padding: 30px 12px 12px; }
  .bracket { padding: 14px 11px; }
  .bracket-ends { gap: 6px; }
  .bracket-fig { font-size: 19px; }
  .bracket-day { font-size: 11px; }
  .yours-fig { font-size: 27px; }
  .gallery { grid-template-columns: 1fr 1fr; gap: 6px; }
  .btn { padding: 12px 16px; font-size: 15px; }
  .btn-big { padding: 13px 18px; font-size: 16px; }
  .bd-row { font-size: 14px; gap: 8px; }
  .r-cta { padding: 22px 13px; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* =====================================================================
   MOTION
   Everything below is suppressed wholesale by the reduced motion block at
   the end of this file, and the JS checks the same query before it runs.
   ===================================================================== */

/* Question to question. The outgoing step drops away, the incoming one rises
   into place, so the two never appear stacked on each other. */
.step, .results {
  opacity: 1;
  transform: translateY(0);
  transition: opacity .34s var(--ease), transform .34s var(--ease);
}
.step.is-entering, .results.is-entering { opacity: 0; transform: translateY(14px); }
.step.is-leaving  { opacity: 0; transform: translateY(-10px); }

/* Choices settle in one after another rather than all at once. The delay is
   capped so a long list never leaves the last option waiting. */
.step .choice {
  animation: choice-in .32s var(--ease) both;
}
.step .choice:nth-child(1) { animation-delay: .02s; }
.step .choice:nth-child(2) { animation-delay: .06s; }
.step .choice:nth-child(3) { animation-delay: .10s; }
.step .choice:nth-child(4) { animation-delay: .14s; }
.step .choice:nth-child(n+5) { animation-delay: .18s; }
@keyframes choice-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ------------------------------------------------- the crafting reveal */

.craft {
  min-height: 62vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 40px 20px;
  transition: opacity .26s var(--ease);
}
.craft.is-done { opacity: 0; }

.craft-mark {
  width: 46px; height: auto;
  margin-bottom: 22px;
  animation: mark-breathe 2.4s ease-in-out infinite;
}
@keyframes mark-breathe {
  0%, 100% { opacity: .55; transform: translateY(0); }
  50%      { opacity: 1;   transform: translateY(-4px); }
}

.craft-lead {
  font-family: var(--head);
  font-size: 23px;
  font-weight: 300;
  letter-spacing: 1.4px;
  color: var(--dark-grey);
  margin: 0 0 6px;
  max-width: 22ch;
}

/* Fixed height, so swapping the wording does not shunt the bar up and down. */
.craft-step {
  font-size: 15px;
  color: var(--dark-grey);
  margin: 0 0 20px;
  min-height: 1.5em;
  opacity: 1;
  transition: opacity .15s linear;
}
.craft-step.is-swapping { opacity: 0; }

.craft-track {
  width: min(240px, 70vw);
  height: 2px;
  background: var(--line);
  border-radius: 100px;
  overflow: hidden;
}
.craft-fill {
  width: 0;
  height: 100%;
  background: var(--primary);
  /* Matches the four steps the JS walks, so the bar finishes as the last line
     does rather than racing ahead of the words. */
  transition: width 2.5s linear;
}

/* ------------------------------------------------ results, on the way in */

.will-reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .5s var(--ease), transform .5s var(--ease);
}
.is-revealed { opacity: 1; transform: translateY(0); }

/* ------------------------------------------------------- the copy control */

.sharebox { display: flex; flex-direction: column; align-items: stretch; gap: 10px; }

/* The link is real and focusable only when the clipboard route fails, at which
   point the fallback reveals it so they can copy by hand. */
.link-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; border: 0;
  clip: rect(0 0 0 0);
  overflow: hidden;
}
.link-hidden.is-shown {
  position: static;
  width: 100%; height: auto;
  clip: auto;
  font-family: var(--body); font-size: 16px;
  padding: 13px 14px; min-height: 50px;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: #fff; color: var(--body-color);
}

.btn-copy { position: relative; }
.btn-copy.is-copied { background: var(--dark-green); }

/* Visible to a screen reader, never on screen. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  clip: rect(0 0 0 0);
  overflow: hidden;
  white-space: nowrap;
}

/* ===================================================================== */
@media (prefers-reduced-motion: reduce) {
  .step, .results, .will-reveal, .craft, .craft-step, .craft-fill {
    transition: none !important;
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .step .choice { animation: none !important; opacity: 1 !important; }
  .craft-mark { animation: none !important; opacity: 1 !important; }
}

/* ---------------------------------------------------------------------
   The A/B switcher. Tooling, not part of the venue's design, and styled to
   look like it so nobody reviewing mistakes it for a page component. Shown
   only in preview or internal review; see design-switch.js. */
.ds-switch {
  position: fixed;
  right: 12px; bottom: 12px;
  z-index: 60;
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  max-width: calc(100vw - 24px);
  padding: 8px 10px;
  border-radius: 999px;
  background: rgba(26, 28, 31, .94);
  box-shadow: 0 6px 20px rgba(0, 0, 0, .28);
  font-family: var(--body); font-size: 13px; color: #fff;
}
.ds-lab {
  font-size: 11px; letter-spacing: 1.2px; text-transform: uppercase;
  opacity: .62; padding-left: 4px;
  display: none;
}
.ds-k { font-weight: 500; }
.ds-n { display: none; }
.ds-btn {
  appearance: none;
  border: 1px solid rgba(255, 255, 255, .28);
  background: transparent; color: #fff; font: inherit;
  padding: 7px 12px;
  min-height: 44px;
  border-radius: 999px;
  cursor: pointer;
}
.ds-btn:hover { border-color: rgba(255, 255, 255, .55); }
.ds-btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.ds-on { background: var(--primary); border-color: var(--primary); color: #1a1c1f; font-weight: 500; }
.ds-note { display: none; }

/* Both fixed controls sit on the bottom edge, so the page needs room to clear
   them rather than leaving the last field permanently covered. */
body { padding-bottom: 64px; }

@media (min-width: 560px) {
  .ds-lab { display: inline; }
  .ds-n { display: inline; margin-left: 5px; }
}
@media (min-width: 900px) {
  .ds-note { display: inline; opacity: .68; padding-right: 4px; max-width: 240px; }
  body { padding-bottom: 0; }
}



/* ------------------------------------------------- results cover lockup

   The results page opens like a title card rather than a heading over a photo.
   Version A centres it and flanks the eyebrow with hairlines; version B sets it
   left against a vertical rule. Both sit on the same markup, so the two designs
   differ in composition, not in what the page says. */

/* The results hero runs taller than the one on a question, because it is
   carrying a three part lockup rather than a single caption line. */
.results .hero-shot img { height: clamp(300px, 58vh, 620px); }

.r-lock {
  padding: 60px 20px 30px;
  /* Hold the lockup to a column on a wide screen so the three parts stay a
     single composed block rather than drifting apart across the frame. */
  display: flex;
  flex-direction: column;
  align-items: center;
  /* .hero-shot sets line-height 0 to kill the inline image gap. The caption is
     inside that figure, so it has to put a real line-height back or its text
     collapses to zero height. */
  line-height: 1.4;
}

/* Eyebrow, with a rule running out either side of it. */
.r-eyebrow {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  font-family: var(--body);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 3.4px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .92);
  margin-bottom: 14px;
  line-height: 1.4;
  /* The words are one phrase. Without this the text is a shrinkable flex item
     and breaks mid line between the rules, which read as a typo. */
  white-space: nowrap;
}
.r-eyebrow::before, .r-eyebrow::after {
  content: "";
  height: 1px;
  /* The rules give up their width before the words do, and disappear entirely on
     the narrowest phones where there is no room for them. */
  flex: 0 1 clamp(0px, 8vw, 54px);
  min-width: 0;
  background: rgba(255, 255, 255, .5);
}
@media (max-width: 400px) {
  .r-eyebrow { letter-spacing: 2.4px; }
  .r-eyebrow::before, .r-eyebrow::after { display: none; }
}

.r-names {
  max-width: 20ch;
  font-family: var(--head);
  font-weight: 300;
  font-size: clamp(30px, 8.5vw, 60px);
  line-height: 1.04;
  letter-spacing: .5px;
  color: #fff;
  margin: 0;
  text-shadow: 0 2px 22px rgba(18, 16, 12, .5);
}

/* A gold hairline between the names and the date, the one piece of brand
   colour in the lockup. */
.r-date {
  position: relative;
  font-family: var(--body);
  font-size: 13px;
  letter-spacing: 2.6px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .92);
  margin: 16px 0 0;
  padding-top: 16px;
  font-variant-numeric: lining-nums;
}
.r-date::before {
  content: "";
  position: absolute;
  top: 0; left: 50%;
  transform: translateX(-50%);
  width: 42px; height: 2px;
  background: var(--primary);
}

.hero-cap.r-lock {
  background: linear-gradient(to top,
    rgba(26, 22, 18, .82) 0%,
    rgba(26, 22, 18, .45) 45%,
    rgba(26, 22, 18, .06) 100%);
}
.r-head { margin-bottom: 6px; }
.r-sub { max-width: 46ch; }

/* The lockup settles in rather than appearing fully formed. */
.results .r-eyebrow { animation: lock-in .6s var(--ease) .05s both; }
.results .r-names   { animation: lock-in .6s var(--ease) .14s both; }
.results .r-date    { animation: lock-in .6s var(--ease) .24s both; }
@keyframes lock-in {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .results .r-eyebrow, .results .r-names, .results .r-date {
    animation: none !important; opacity: 1 !important; transform: none !important;
  }
}

/* ------------------------------------------- the "because you said" groups

   Each thing they picked at question 8 gets its own small heading and a pair of
   photographs. The heading is what makes this personalisation rather than a
   gallery: it names their own answer back to them. */
.shot-group { margin-bottom: 26px; }
.shot-group:last-of-type { margin-bottom: 0; }
.shot-label {
  font-family: var(--body);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 2.2px;
  text-transform: uppercase;
  color: var(--gold-ink);
  margin: 0 0 10px;
}
.shot-group .gallery { grid-template-columns: repeat(2, 1fr); gap: 8px; }

/* When the audit review tool is running, its dock owns the bottom right corner.
   Move the design switcher along the bottom edge so both stay reachable; on a
   phone it goes left, above the preview badge, where there is room. */
/* Stacked above the Preview badge, which also lives bottom left. Three fixed
   controls on one edge, none of them on top of another. */
[data-review="on"] .ds-switch { right: auto; left: 12px; bottom: 58px; }

/* The results wrappers. Collapsed by default, so version A and narrow screens
   lay out exactly as if the markup were flat and the order rules still apply to
   the sections themselves. Version B opens them into two columns on a wide
   screen; see design-b.css. */
.r-body, .r-main, .r-rail { display: contents; }

/* =====================================================================
   THE BLEND, from the team review on 26 August 2026.

   A's white card choices, because two of the team called them out as the
   better thing on a phone. B's photograph on every question, because all
   of them liked what the imagery did for the venue. And Nicola's fix: the
   question sits ABOVE the answers at every width, never beside them, so
   the hierarchy reads in one direction.
   ===================================================================== */

.q-media {
  margin: 0 0 20px;
  line-height: 0;
}
.q-media img {
  width: 100%;
  height: auto;
  /* Restrained on a phone: enough to show the venue, not so tall that the
     answers are pushed off the screen. */
  aspect-ratio: 16 / 10;
  max-height: 190px;
  object-fit: cover;
  border-radius: var(--radius);
}

@media (min-width: 900px) {
  /* The photograph holds the left column; the question, its help line and the
     answers all sit together in the right one, so the header reads directly
     above the thing it is asking about rather than above the picture. Nicola,
     28 August 2026. */
  .step {
    display: grid;
    grid-template-columns: 300px minmax(0, 1fr);
    column-gap: 44px;
    align-items: start;
  }

  /* The progress row spans both, above everything. */
  .step > .step-meta { grid-column: 1 / -1; grid-row: 1; }

  /* The photograph runs down the left beside the whole right hand column. */
  .step > .q-media {
    grid-column: 1;
    grid-row: 2 / span 3;
    margin-bottom: 0;
  }
  .step > .q-media img {
    aspect-ratio: 4 / 5;
    max-height: 340px;
  }

  .step > .q-title { grid-column: 2; grid-row: 2; margin-top: 0; }
  .step > .q-help  { grid-column: 2; grid-row: 3; }
  .step > .q-body  { grid-column: 2; grid-row: 4; margin-top: 0; }

  /* A question with no photograph gives the whole width to the question. */
  .step:not(:has(.q-media)) > .q-title,
  .step:not(:has(.q-media)) > .q-help,
  .step:not(:has(.q-media)) > .q-body { grid-column: 1 / -1; }
}

/* ------------------------------------------------ results page ordering

   groupResults sorts the page into a main column and a rail so the two column
   desktop layout has something to work with. With the wrappers collapsed the
   rail's contents would otherwise land after the footer, so the reading order
   from section 10 of the spec is restated here explicitly rather than relying
   on where the nodes happen to sit. */
.results { display: flex; flex-direction: column; }
.results .hero-shot   { order: 1; }
.results .r-head      { order: 2; }
.results #sec-day     { order: 3; }
.results #sec-photos  { order: 4; }
.results #investment  { order: 5; }
.results #sec-includes{ order: 6; }
.results .r-twilight  { order: 7; }
.results .r-cta       { order: 8; }
.results .r-foot      { order: 9; }

@media (min-width: 900px) {
  /* Two columns: the day on the left, the price and the booking prompt in a
     rail that stays with them as they scroll. From version B, kept because it
     is the one place a wide screen earns something a phone cannot have. */
  .results .r-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 340px;
    column-gap: 44px;
    align-items: start;
    order: 3;
  }
  .results .r-main { display: block; min-width: 0; }
  .results .r-rail {
    display: block;
    position: sticky;
    top: 24px;
    align-self: start;
  }
  .results .r-rail #investment { margin-top: 0; }
  .results .r-rail .r-cta { margin: 18px 0 0; }
  .results .r-rail .yours-fig { font-size: 40px; }
  .results .r-rail .bracket-ends { display: flex; flex-direction: column; gap: 10px; }
  .results .r-rail .bracket-end-right { text-align: left; }
  .results .r-rail .bracket-fig { font-size: 22px; }
  main { max-width: 1120px; }
}


/* ---------------------------------------------- Back and Continue, as a pair

   Back used to be a text link up beside the progress bar. It now sits to the
   left of Continue, same size and shape so they read as a pair, outlined rather
   than filled so the primary action still wins. Review comment 2. */
.step-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 4px;
}
.btn-back {
  background: transparent;
  color: var(--dark-grey);
  border: 1px solid var(--line);
}
/* The filled buttons carry no border, so a bordered one sits 2px taller and the
   pair looks misaligned. A transparent border on the filled one squares them. */
.step-actions .btn-primary { border: 1px solid transparent; }
.btn-back:hover { border-color: var(--primary); color: var(--body-color); }

/* The date field. The calendar popup itself is drawn by the browser and cannot
   be styled by us, so this is everything around it: the box, the type, and the
   picker icon, which we tint to the brand gold. Review comment 4. */
.date-input {
  min-height: 52px;
  text-align: left;
  font-family: var(--body);
  letter-spacing: .4px;
  color: var(--body-color);
  cursor: pointer;
}
.date-input:hover { border-color: var(--primary); }
/* The little calendar glyph is the one part of the native control we can reach.
   The filter turns its default grey into the brand gold. */
.date-input::-webkit-calendar-picker-indicator {
  cursor: pointer;
  opacity: .75;
  filter: invert(63%) sepia(35%) saturate(560%) hue-rotate(1deg) brightness(92%) contrast(88%);
  transition: opacity .2s var(--ease);
}
.date-input:hover::-webkit-calendar-picker-indicator { opacity: 1; }

/* The standing note inside the morning question's list, between the included
   Bridal Suite and the three additions. Set as a line of the list rather than a
   card, so it reads as information and not as a fourth thing to pick. */
.choices-note {
  font-size: 14px;
  color: var(--dark-grey);
  line-height: 1.45;
  margin: 2px 0 6px;
  padding: 0 4px 0 16px;
  border-left: 2px solid var(--primary);
}

/* Guest bedrooms sit beside the quotation, not inside it. A quiet aside, so it
   reads as useful information rather than another line of cost. */
.bedrooms-note {
  margin-top: 18px;
  padding: 14px 16px;
  border-left: 3px solid var(--primary);
  background: var(--secondary);
  border-radius: var(--radius);
  font-size: 15px;
  line-height: 1.5;
}
.bedrooms-note strong {
  display: block;
  font-size: 12px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--gold-ink);
  margin-bottom: 6px;
}
.bedrooms-note p { margin: 0; }
