/* ============================================================
   MUTĖ MILLINERY — components
   The skin of every component, in document order.

   Rules of the house:
   · Every colour, size, easing and duration comes from tokens.css.
     Where a transparency the tokens don't carry is needed, it is
     mixed FROM a token with color-mix() — never typed as a literal.
   · Gilt is light, not paint. Hairlines, small caps, one rule, four
     corner brackets. If a block reads as "gold", it has failed.
   · Every border is 1px. --radius is 0: Baroque squares its corners
     and ornaments them instead.
   · Layout (containers, section rhythm, grids, the hero's frame)
     lives in layout.css. This sheet styles what sits inside them.
   · Keyframes, reveals, the leaf sweep and hover transforms live in
     motion.css. Transitions are declared here so motion.css has
     something to inherit, and so the page still behaves without it.
   · Nothing here hides content that JavaScript must reveal, except
     where the markup already carries `hidden` — and those states are
     guarded so the attribute always wins.
   ============================================================ */


/* ============================================================
   ORNAMENT PLACEMENT
   base.css owns the stroke base (fill: none, stroke, linecap).
   This block owns *where* the ornaments sit and *how bright*
   they are — which is a component decision, not an atom one.

   #orn-corner is drawn for the TOP-LEFT of a 48-unit box. The
   other three are the same bracket rotated, so there is one
   symbol in the sprite instead of four. Rendered small (28–40px)
   and at --gilt-dim, four of them cost well under a percent of
   the screen; that is the whole ornament budget for a panel.

   `color` is set as well as `stroke` so that whichever way
   base.css draws the stroke — a token or currentColor — the
   parent-hover brightening below still lands.
   ============================================================ */

.orn--corner {
  position: absolute;
  z-index: 2;
  width: clamp(26px, 3.4vw, 34px);
  height: clamp(26px, 3.4vw, 34px);
  color: var(--gilt-dim);
  stroke: currentColor;
  /* 48-unit viewBox rendered at ~32px: 1.5 user units ≈ a 1px line. */
  stroke-width: 1.5;
  pointer-events: none;
  transition: color var(--dur-med) var(--ease-soft);
}

/* The bracket's own outer corner sits ~2% into its box, so an
   inset of 11px lands the stroke on a frame drawn at 12px. */
.orn--tl { top: 11px; left: 11px;  transform: rotate(0deg); }
.orn--tr { top: 11px; right: 11px; transform: rotate(90deg); }
.orn--br { bottom: 11px; right: 11px; transform: rotate(180deg); }
.orn--bl { bottom: 11px; left: 11px;  transform: rotate(270deg); }

/* The brackets come up when the thing they frame is engaged with.
   Focus-within matters: the form well is full of focusable fields. */
.plate:hover .orn--corner,
.plate:focus-within .orn--corner,
.form-well:focus-within .orn--corner {
  color: var(--gilt);
}

/* ---- The divider flourish ---------------------------------- */

/* 240×40 viewBox. Held to its natural width so the scrolls never
   stretch, centred, and given air on both sides — a fleuron with
   a section crowding it is just a squiggle. */
.orn--fleuron {
  display: block;
  width: min(240px, 62%);
  height: auto;
  aspect-ratio: 240 / 40;
  margin-inline: auto;
  margin-block: clamp(var(--sp-5), 8vw, var(--sp-7));
  color: var(--gilt-dim);
  stroke: currentColor;
  stroke-width: 1.15;
}


/* ============================================================
   NAV
   Transparent over the hero, so the wordmark reads straight off
   the varnish black. main.js adds `.is-stuck` to [data-nav]
   once the hero has travelled under the bar; only then does the
   ground and its hairline appear. Both states are declared here;
   motion.css owns nothing but the easing of the change.

   z-index 910 — above the drawer (905) so the burger stays
   reachable while the drawer is open.
   ============================================================ */

.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 910;
  height: var(--nav-h);
  background: transparent;
  transition:
    background-color var(--dur-med) var(--ease-soft),
    backdrop-filter  var(--dur-med) var(--ease-soft);
}

.nav.is-stuck {
  background: color-mix(in srgb, var(--pitch) 76%, transparent);
  -webkit-backdrop-filter: blur(18px) saturate(115%);
          backdrop-filter: blur(18px) saturate(115%);
}

/* The hairline is drawn on the bar itself rather than on a spare
   element, and only exists once the bar has a ground of its own —
   a rule floating over the hero would cut the picture in half. */
.nav::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  background: var(--pitch-line);
  opacity: 0;
  transition: opacity var(--dur-med) var(--ease-soft);
}
.nav.is-stuck::after { opacity: 1; }

.nav__inner {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  height: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ---- Brand ------------------------------------------------- */

.nav__brand {
  display: inline-flex;
  align-items: center;
  gap: 0.72rem;
  flex: none;
  color: var(--parchment);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-soft);
}
.nav__brand:hover { color: var(--gilt-hot); }
.nav__brand:focus-visible {
  outline: 1px solid var(--gilt);
  outline-offset: 6px;
}

/* The crest is a lozenge within a lozenge — the smallest piece of
   heraldry that still reads at 18px. Kept at --gilt (not dim): it
   is the one place on the bar where the leaf is meant to catch. */
.nav__crest {
  flex: none;
  width: 18px;
  height: 18px;
  color: var(--gilt);
  stroke: currentColor;
  /* 24-unit viewBox at 18px: 1.4 units ≈ a 1px line. */
  stroke-width: 1.4;
  fill: none;
  transition: color var(--dur-fast) var(--ease-soft);
}
.nav__brand:hover .nav__crest { color: var(--gilt-hot); }

.nav__word {
  display: inline-flex;
  align-items: baseline;
  gap: 0.55rem;
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 500;
  line-height: 1;
  letter-spacing: var(--track-wide);
}

/* "Millinery" is the descriptor, not the name: sans, small,
   letterspaced, and the first thing to go when the bar is tight. */
.nav__word-sub {
  font-family: var(--font-body);
  font-size: 0.5625rem;
  font-weight: 300;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  white-space: nowrap;
  color: var(--parchment-dim);
}

/* ---- Links ------------------------------------------------- */

.nav__links {
  display: flex;
  align-items: center;
  gap: clamp(1.1rem, 2.2vw, 2.1rem);
  margin-left: auto;
}

.nav__link {
  position: relative;
  padding-block: 0.45rem;
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-weight: 300;
  text-transform: uppercase;
  letter-spacing: var(--track-wide);
  white-space: nowrap;
  color: var(--parchment-dim);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-soft);
}

/* A rule that is drawn from the left rather than faded in — the
   difference between an underline and a gesture. */
.nav__link::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  background: var(--gilt);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-fast) var(--ease-out);
}
.nav__link:hover,
.nav__link:focus-visible { color: var(--parchment); }
.nav__link:hover::after,
.nav__link:focus-visible::after { transform: scaleX(1); }
.nav__link:focus-visible {
  outline: 1px solid var(--gilt);
  outline-offset: 4px;
}

.nav__cta {
  flex: none;
  margin-left: var(--sp-1);
}

/* ---- Bar breakpoints --------------------------------------- */

/* Brand + five links + a button is the tightest the bar ever gets.
   The descriptor goes first; the crest and "Mutė" still identify us. */
@media (min-width: 901px) and (max-width: 1080px) {
  .nav__word-sub { display: none; }
}

/* Scoped to `.nav` for specificity, not for reach. `.nav__cta` is
   also a `.btn`, and `.btn { display: inline-flex }` is declared
   later in this file — at equal specificity that would win over a
   bare `.nav__cta` here and leave the button on screen next to the
   burger. Two classes (0,2,0) settles it. */
@media (max-width: 900px) {
  .nav .nav__links,
  .nav .nav__cta { display: none; }
}

@media (max-width: 360px) {
  .nav__word-sub { display: none; }
}


/* ============================================================
   BURGER
   Two hairlines that cross into an X. Not three: the middle bar
   of the usual icon has to be faded out, and a fade in the
   middle of a rotation always looks like a bug.

   The button is 44×44 so it meets the touch target minimum even
   though the bars themselves are 22px wide.
   ============================================================ */

/* Shown by default and hidden on desktop by the query directly
   below, rather than the reverse. Hiding it here and switching it
   on in an EARLIER max-width query does not work: both rules have
   the same specificity, so the later one in the source wins and
   the burger stays hidden at every width — which leaves small
   screens with no navigation at all. */
.burger {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  gap: 7px;
  flex: none;
  width: 44px;
  height: 44px;
  margin-left: auto;
  margin-right: -10px;       /* optically aligns the bars to the gutter */
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
}
@media (min-width: 901px) {
  .burger { display: none; }
}

.burger:focus-visible {
  outline: 1px solid var(--gilt);
  outline-offset: 2px;
}

.burger__bar {
  display: block;
  height: 1px;
  background: var(--parchment);
  transition:
    width            var(--dur-fast) var(--ease-out),
    transform        var(--dur-fast) var(--ease-out),
    background-color var(--dur-fast) var(--ease-soft);
}
.burger__bar:nth-child(1) { width: 24px; }
.burger__bar:nth-child(2) { width: 16px; }

.burger:hover .burger__bar:nth-child(2) { width: 24px; }
.burger:hover .burger__bar { background: var(--gilt); }

/* Bars are 1px with a 7px gap, so their centres are 8px apart and
   each must travel 4px to meet in the middle. */
.burger[aria-expanded="true"] .burger__bar {
  width: 24px;
  background: var(--gilt);
}
.burger[aria-expanded="true"] .burger__bar:nth-child(1) {
  transform: translateY(4px) rotate(45deg);
}
.burger[aria-expanded="true"] .burger__bar:nth-child(2) {
  transform: translateY(-4px) rotate(-45deg);
}


/* ============================================================
   DRAWER
   A full-screen pitch overlay. The markup ships it with `hidden`;
   main.js removes the attribute and then adds .is-open, so the
   closed state below is only ever seen mid-transition.

   `[hidden] { display: none }` is restated because the rules here
   set display and would otherwise out-specify the UA sheet and
   leave the drawer permanently over the page.
   ============================================================ */

.drawer {
  position: fixed;
  inset: 0;
  z-index: 905;              /* under the nav so the burger stays live */
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--sp-5);
  padding: calc(var(--nav-h) + var(--sp-4)) var(--gutter) var(--sp-5);
  background: var(--pitch);
  overflow-y: auto;
  overscroll-behavior: contain;
  opacity: 0;
  pointer-events: none;
}
.drawer[hidden] { display: none; }

.drawer.is-open {
  opacity: 1;
  pointer-events: auto;
}

.drawer__nav {
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--pitch-line);
}

/* Display face, near-hero scale. A mobile menu is the only place on
   the site where the type gets to be this big without a picture. */
.drawer__link {
  display: block;
  padding-block: clamp(0.65rem, 2.6vw, 1rem);
  border-bottom: 1px solid var(--pitch-line);
  font-family: var(--font-display);
  font-size: clamp(2rem, 9vw, 3.2rem);
  font-weight: 400;
  line-height: 1.06;
  letter-spacing: var(--track-tight);
  color: var(--parchment);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-soft);
}
.drawer__link:hover { color: var(--gilt-hot); }
.drawer__link:focus-visible {
  outline: 1px solid var(--gilt);
  outline-offset: 3px;
}

.drawer__foot {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--pitch-line);
}

.drawer__tel {
  font-family: var(--font-body);
  font-size: var(--t-small);
  font-weight: 300;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
  color: var(--parchment);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-soft);
}
.drawer__tel:hover { color: var(--gilt-hot); }

.drawer__note {
  font-size: var(--t-micro);
  font-weight: 300;
  text-transform: uppercase;
  letter-spacing: var(--track-wide);
  color: var(--parchment-faint);
}


/* ============================================================
   BUTTONS
   Three weights, all small caps at --track-label, all square.

   --solid is NOT a gold slab. It is a gilt-bordered plate over a
   wash of about a tenth of a gilt — enough that it reads as the
   lit surface in the composition, nowhere near enough to break
   the 2% budget. The text stays parchment.

   --ghost is a hairline outline. --line is barely a button at
   all: a text link with a rule under it, for the two in-plate
   actions where a pair of bordered boxes would sink the card.

   .btn__sweep is parked off the left edge with a gilt gradient;
   motion.css rakes it across on hover. Parked, it is invisible
   inside the button's own overflow clip, so a missing motion.css
   costs the sweep and nothing else.
   ============================================================ */

.btn {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  /* The trailing letter-space is real width; pad the left to match
     or every button looks nudged to the right. */
  padding: 1.05rem 1.9rem 1.05rem calc(1.9rem + var(--track-label));
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-weight: 400;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color var(--dur-fast) var(--ease-soft),
    border-color     var(--dur-fast) var(--ease-soft),
    color            var(--dur-fast) var(--ease-soft);
}
.btn:focus-visible {
  outline: 1px solid var(--gilt);
  outline-offset: 3px;
}

.btn--solid {
  border-color: var(--gilt-dim);
  background-color: color-mix(in srgb, var(--gilt) 9%, transparent);
  color: var(--parchment);
}
.btn--solid:hover {
  border-color: var(--gilt);
  background-color: color-mix(in srgb, var(--gilt) 15%, transparent);
  color: var(--gilt-hot);
}

.btn--ghost {
  border-color: var(--pitch-line);
  color: var(--parchment);
}
.btn--ghost:hover {
  border-color: var(--gilt-dim);
  color: var(--gilt-hot);
}

/* The smallest of the three. No box: a rule, and the word. */
.btn--line {
  padding: 0.55rem 0 0.5rem;
  border: 0;
  border-bottom: 1px solid var(--gilt-dim);
  font-size: 0.6875rem;
  letter-spacing: var(--track-wide);
  color: var(--parchment-dim);
  transition:
    border-color var(--dur-fast) var(--ease-soft),
    color        var(--dur-fast) var(--ease-soft);
}
.btn--line:hover {
  border-bottom-color: var(--gilt);
  color: var(--gilt-hot);
}
.btn--line:focus-visible { outline-offset: 4px; }

/* Geometry and pigment only — the rake belongs to motion.css. */
.btn__sweep {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    104deg,
    transparent 0%,
    var(--gilt-ghost) 36%,
    color-mix(in srgb, var(--gilt-hot) 26%, transparent) 50%,
    var(--gilt-ghost) 64%,
    transparent 100%
  );
  transform: translateX(-105%);
}


/* ============================================================
   COLLECTION PLATES
   There is no photography on this site, and the plate is where
   that decision has to earn itself. So the frame is built as a
   Baroque still life: a tall portrait well, light entering from
   the upper left, the ground falling away to nothing at the
   bottom right, and the hat sitting in that light as an object
   rather than as a missing <img>.

   The well itself is a gilt PICTURE FRAME, not a bordered card —
   a real moulding, not a hairline:
     · `border-image` paints a diagonal light→groove→light gilt
       gradient across the moulding's full width, which is what
       reads as a convex gilt profile rather than flat gold paint.
     · An inset box-shadow draws the recessed line where the
       moulding meets the picture — the groove a real frame has
       between the gilt and the canvas.
     · A 1px outline, pulled in with a negative offset, gives the
       frame a hard outer edge against the page — outline paints
       independently of the box model, so it costs no layout.
   The four corner brackets stay as an accent sitting just inside
   the moulding (see `.plate__frame .orn--corner` below) — this is
   additive to the ornament language already used everywhere else
   on the page, not a replacement for it.

   Inside the frame, three background layers still do the "still
   life" work behind the hat itself:
     1. a warm key light, upper left
     2. a deep shadow pooled bottom right
     3. a whisper of gilt raking down the top edge
   ============================================================ */

.plate {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.plate__frame {
  position: relative;
  aspect-ratio: 4 / 5;
  border-width: clamp(9px, 1.5vw, 14px);
  border-style: solid;
  border-image-slice: 1;
  border-image-source: linear-gradient(
    135deg,
    var(--gilt-hot) 0%,
    var(--gilt) 16%,
    color-mix(in srgb, var(--gilt) 45%, var(--pitch-deep)) 42%,
    color-mix(in srgb, var(--pitch-deep) 55%, var(--gilt)) 50%,
    color-mix(in srgb, var(--gilt) 45%, var(--pitch-deep)) 58%,
    var(--gilt) 84%,
    var(--gilt-hot) 100%
  );
  outline: 1px solid var(--pitch-line);
  outline-offset: -1px;
  background-color: var(--pitch-raised);
  background-image:
    radial-gradient(118% 96% at 20% 6%,
      color-mix(in srgb, var(--parchment) 8%, transparent) 0%,
      transparent 58%),
    radial-gradient(96% 84% at 82% 104%,
      color-mix(in srgb, var(--pitch-deep) 92%, transparent) 0%,
      transparent 68%),
    linear-gradient(156deg,
      color-mix(in srgb, var(--gilt) 6%, transparent) 0%,
      transparent 40%);
  background-clip: padding-box;
  box-shadow:
    var(--shadow-plate),
    inset 0 0 0 1px var(--pitch-deep);
  transition:
    box-shadow  var(--dur-med) var(--ease-soft),
    outline-color var(--dur-med) var(--ease-soft);
}
.plate:hover .plate__frame,
.plate:focus-within .plate__frame {
  outline-color: var(--gilt);
  box-shadow:
    var(--shadow-lift),
    inset 0 0 0 1px var(--pitch-deep);
}

/* Pulled in from the ornament's default 11px inset (base rule,
   `.orn--tl` etc.) so the brackets sit just inside the new
   moulding's inner groove rather than floating deep into the
   picture the way they did against the old 1px hairline. Scoped
   here rather than changed globally — the form well's corners
   still want the wider, hairline-calibrated inset. */
.plate__frame .orn--tl,
.plate__frame .orn--tr,
.plate__frame .orn--br,
.plate__frame .orn--bl {
  width: clamp(20px, 2.6vw, 27px);
  height: clamp(20px, 2.6vw, 27px);
}
.plate__frame .orn--tl { top: 6px; left: 6px; }
.plate__frame .orn--tr { top: 6px; right: 6px; }
.plate__frame .orn--br { bottom: 6px; right: 6px; }
.plate__frame .orn--bl { bottom: 6px; left: 6px; }

/* The silhouette. A flat --gilt-dim fill (which over the raised
   pitch reads as old bronze, not gold) with two drop-shadows: a
   one-pixel lit rim up and to the left where the key light is,
   and a long soft shadow beneath so the thing has weight.

   A true gradient fill would need the gradient inside the sprite;
   this is the robust version and, at this size, indistinguishable.
   SWAP: when photography exists, replace the <svg> with an <img>
   and this rule stops applying — the frame stays as its mount. */
/* Centred with the independent `translate` property, NOT with
   `transform`. motion.css animates `transform` on this element
   (a settle on reveal, a breath on hover) and its rest state is
   `transform: none` — which would wipe out a centring translate
   and drop the hat into the bottom-right quadrant. The two
   properties compose, so each sheet keeps its own concern. */
.plate__hat {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 72%;
  max-width: none;   /* releases the 13rem guard in base.css */
  height: auto;
  translate: -50% -50%;
  /* Standing in for photography, so it carries the card: a touch
     stronger than --gilt-dim's 26%, which read as a smudge at
     this size against the varnish black. */
  fill: color-mix(in srgb, var(--gilt) 34%, transparent);
  filter:
    drop-shadow(-1px -1px 0 color-mix(in srgb, var(--gilt) 45%, transparent))
    drop-shadow(0 22px 30px color-mix(in srgb, var(--pitch-deep) 88%, transparent));
  transition: fill var(--dur-med) var(--ease-soft);
}
.plate:hover .plate__hat,
.plate:focus-within .plate__hat {
  fill: color-mix(in srgb, var(--gilt) 54%, transparent);
}

/* ---- Plate body -------------------------------------------- */

/* Declared as its own flex column rather than relying on the grid:
   the prices then take margin-top:auto and every card in the row
   rules off at the same height however long the note runs. */
.plate__body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  padding-top: var(--sp-3);
}

.plate__type {
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-weight: 300;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--parchment-faint);
}

.plate__name {
  margin-top: 0.5rem;
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 2.6vw, 2.05rem);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: var(--track-tight);
  color: var(--parchment);
  transition: color var(--dur-fast) var(--ease-soft);
}
.plate:hover .plate__name { color: var(--gilt-hot); }

.plate__note {
  margin-top: var(--sp-2);
  max-width: 34ch;
  font-size: var(--t-body);
  line-height: 1.7;
  color: var(--parchment-dim);
}

/* ---- Prices: the whole business model, in two columns -------

   Buy and Hire are a matched pair. Same size, same weight, same
   colour, same padding, one gilt hairline between them and equal
   air either side of it. Neither is a "from" price and neither is
   the fallback: a customer who came to hire must not feel handled.
   The only asymmetry allowed is the unit, and only because "/ 4
   days" is information the buy column does not have.
   ------------------------------------------------------------ */

.plate__prices {
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin-top: auto;
  padding-top: var(--sp-3);
  border-top: 1px solid var(--pitch-line);
}

.price {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding-block: 0.15rem 0;
  min-width: 0;
}
.price:first-child  { padding-right: var(--sp-3); }
.price:last-child   { padding-left: var(--sp-3); border-left: 1px solid var(--gilt-dim); }

.price__key {
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-weight: 300;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--parchment-faint);
}

.price__val {
  margin: 0;                 /* <dd> carries a UA margin */
  font-family: var(--font-display);
  font-size: clamp(1.3rem, 2.1vw, 1.6rem);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: var(--track-tight);
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--parchment);
}

.price__unit {
  display: block;
  margin-top: 0.15rem;
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-weight: 300;
  letter-spacing: 0.06em;
  color: var(--parchment-faint);
}

/* ---- Plate actions ----------------------------------------- */

.plate__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-4);
  margin-top: var(--sp-3);
}

/* Very narrow phones: the two price columns would each be about
   nine characters wide. Stack them, and turn the vertical rule
   into a horizontal one so the pairing still reads. */
@media (max-width: 400px) {
  .plate__prices { grid-template-columns: 1fr; }
  .price:first-child { padding-right: 0; padding-bottom: var(--sp-2); }
  .price:last-child {
    padding-left: 0;
    padding-top: var(--sp-2);
    border-left: 0;
    border-top: 1px solid var(--gilt-dim);
  }
}

/* ============================================================
   ATELIER — MATERIALS
   Back on the standard dark ground (see layout.css) — this used
   to be the one inverted paper section on the page, which read
   as a flashbang scrolling into it from everywhere else that is
   near-black. Standard dark-theme tokens throughout now, same as
   every other section.
   ============================================================ */

.materials {
  margin-top: clamp(var(--sp-5), 7vw, var(--sp-6));
  padding-top: var(--sp-3);
  border-top: 1px solid var(--pitch-line);
}

.materials__title {
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--parchment-dim);
}

/* Small-caps chips, not pills. A pill would put ten rounded boxes
   on a page whose radius is zero. The separator is the lozenge
   again — one ornament, used everywhere, is the discipline. */
.materials__list {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 clamp(var(--sp-3), 3vw, var(--sp-4));
  margin-top: var(--sp-3);
  list-style: none;
  padding: 0;
}

.materials__item {
  position: relative;
  padding-block: 0.32rem;
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--parchment);
  white-space: nowrap;
}

.materials__item + .materials__item::before {
  content: "";
  position: absolute;
  top: 50%;
  left: calc(-1 * clamp(var(--sp-3), 3vw, var(--sp-4)) / 2 - 2px);
  width: 4px;
  height: 4px;
  background: var(--gilt);
  transform: translateY(-50%) rotate(45deg);
}

/* When the list wraps, an item that lands first on its line still
   carries the separator, which then floats in the left margin.
   No selector can see line breaks, so the lozenge is pulled just
   inside the gutter where a stray one reads as a flourish rather
   than a mistake. Nothing else to be done in CSS alone. */


/* ============================================================
   OCCASIONS
   Hairline-separated rows that light as you pass over them: the
   numeral warms, the name shifts a hair to the right, and a gilt
   wash wipes in from the left.

   The wash is a background-image with an animated background-size
   rather than a ::before, deliberately: layout.css makes .occ__row
   a grid, and a pseudo-element would become a grid item and
   dislocate every column in the row.
   ============================================================ */

.occ__row {
  position: relative;
  border-top: 1px solid var(--pitch-line);
  background-image: linear-gradient(
    90deg,
    var(--gilt-ghost) 0%,
    transparent 74%
  );
  background-repeat: no-repeat;
  background-size: 0% 100%;
  transition: background-size var(--dur-med) var(--ease-out);
}
.occ__row:hover,
.occ__row:focus-within { background-size: 100% 100%; }
.occ__row:last-child { border-bottom: 1px solid var(--pitch-line); }

.occ__num {
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-weight: 300;
  letter-spacing: var(--track-label);
  font-variant-numeric: tabular-nums;
  color: var(--parchment-faint);
  transition: color var(--dur-med) var(--ease-soft);
}
.occ__row:hover .occ__num { color: var(--gilt); }

.occ__name {
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2.4vw, 1.9rem);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: var(--track-tight);
  color: var(--parchment);
  transition:
    color     var(--dur-med) var(--ease-soft),
    transform var(--dur-med) var(--ease-out);
}
.occ__row:hover .occ__name {
  color: var(--gilt-hot);
  transform: translateX(0.3rem);
}

.occ__note {
  max-width: 52ch;
  font-size: var(--t-body);
  line-height: 1.75;
  color: var(--parchment-dim);
}

/* A gilt-outlined marker, small enough to be a caption and not a
   badge. Says which of the two routes this occasion usually takes
   — the buy/hire question answered in three words. */
.occ__tag {
  justify-self: start;
  align-self: start;
  display: inline-block;
  padding: 0.42rem 0.8rem 0.42rem calc(0.8rem + var(--track-label));
  border: 1px solid var(--gilt-dim);
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-weight: 300;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  white-space: nowrap;
  color: var(--parchment-dim);
  transition:
    border-color var(--dur-med) var(--ease-soft),
    color        var(--dur-med) var(--ease-soft);
}
.occ__row:hover .occ__tag {
  border-color: var(--gilt);
  color: var(--gilt-hot);
}

@media (min-width: 900px) {
  .occ__tag { justify-self: end; }
}


/* ============================================================
   WORDS — one quote at a time
   Used to have a drop-cap treatment on the long quote and a
   quieter pair underneath. Now a single rotating testimonial:
   centred, bracketed by a hairline above and below, with a row
   of dots to move between reviews. components.css owns which
   panel is visible; layout.css stacks all three in one grid
   cell so the crossfade never reflows the page.
   ============================================================ */

.quote-carousel {
  position: relative;
  padding-block: clamp(var(--sp-5), 6vw, var(--sp-6));
  border-block: 1px solid var(--gilt-dim);
  text-align: center;
}

/* `.is-active` is the ONLY thing that decides visibility, in the
   markup as shipped and after main.js has run. The first `<figure>`
   carries both `.is-active` and no `hidden`, and the other two
   carry `hidden` and nothing else — so a no-JS page is correct
   for free. When main.js runs, it strips `hidden` from all three
   (a `display: none` panel contributes no height to the grid-stack
   in layout.css, which is what keeps the crossfade from jumping)
   and from then on moves `.is-active` between panels on its own.
   Deliberately NOT keyed to `:not([hidden])` as well as `.is-active`
   — once JS removes `hidden` from every panel, a rule matching
   "not hidden" would match all three at once and the carousel
   would stop hiding anything. */
.quote {
  min-width: 0;
  opacity: 0;
  visibility: hidden;
}

.quote.is-active { opacity: 1; visibility: visible; }

.quote__body { margin: 0; }

.quote__text {
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--t-lead);
  font-weight: 300;
  line-height: 1.5;
  letter-spacing: var(--track-tight);
  color: var(--parchment);
}

.quote__by {
  margin-top: var(--sp-4);
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-style: normal;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--parchment);
}

.quote__by-sub {
  display: block;
  margin-top: 0.42rem;
  font-weight: 300;
  letter-spacing: var(--track-wide);
  text-transform: none;
  color: var(--parchment-faint);
}

/* ---- Dots ---------------------------------------------------
   Small enough to read as punctuation, not as UI chrome. A
   hollow lozenge at rest, filled gilt when it names the panel
   on screen. `aria-current` carries the state; the visual and
   the semantics never have a chance to disagree. */

.quote-carousel__dot {
  width: 7px;
  height: 7px;
  padding: 0;
  border: 1px solid var(--gilt-dim);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition:
    background-color var(--dur-fast) var(--ease-soft),
    border-color      var(--dur-fast) var(--ease-soft),
    transform         var(--dur-fast) var(--ease-out);
}

.quote-carousel__dot:hover { border-color: var(--gilt); }

.quote-carousel__dot:focus-visible {
  outline: 1px solid var(--gilt);
  outline-offset: 3px;
}

.quote-carousel__dot[aria-current="true"] {
  background: var(--gilt);
  border-color: var(--gilt);
  transform: scale(1.15);
}


/* ============================================================
   THE ENQUIRY FORM
   The most important block in this sheet, because it is where
   the buy/hire promise either holds or collapses.

   THE MODE TOGGLE IS PURE CSS. The two radios sit at form level,
   before the panes, so a plain sibling combinator swaps which
   pane is in the document. No script is involved, and none is
   required: main.js adds the data-mode bookkeeping and the deep
   links from the plates ON TOP of this, never instead of it.
   ============================================================ */

.form-well {
  position: relative;
  padding: clamp(1.7rem, 4.4vw, 3.25rem);
  border: 1px solid var(--pitch-line);
  background-color: var(--pitch-raised);
  background-image: radial-gradient(
    120% 80% at 18% -6%,
    color-mix(in srgb, var(--parchment) 5%, transparent) 0%,
    transparent 62%
  );
  box-shadow: var(--shadow-plate);
  transition: border-color var(--dur-med) var(--ease-soft);
}
.form-well:focus-within { border-color: var(--gilt-dim); }

/* The inner gilt hairline, meeting the four brackets at 12px. */
.form-well::before {
  content: "";
  position: absolute;
  inset: 12px;
  border: 1px solid var(--gilt-ghost);
  pointer-events: none;
}

/* Dark native furniture: date pickers, spin buttons, scrollbars
   and the select popup all take their cue from color-scheme. */
.form {
  position: relative;
  color-scheme: dark;
}

/* ---- Mode toggle ------------------------------------------- */

.mode__legend {
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-weight: 300;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--parchment-dim);
}

/* A two-column track with one hairline frame around the pair —
   not two boxes, which would read as two separate offers. */
.mode {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin-top: var(--sp-2);
  border: 1px solid var(--pitch-line);
  background: var(--pitch-deep);
}

/* The sliding marker. First child of .mode, so it is behind the
   two labels in paint order without needing a z-index war. It is
   half the width of the track and travels its own width. */
.mode__thumb {
  position: absolute;
  inset: 0 auto 0 0;
  z-index: 0;
  width: 50%;
  background: color-mix(in srgb, var(--oxblood) 58%, var(--pitch-raised));
  box-shadow: inset 0 0 0 1px var(--gilt-dim);
  pointer-events: none;
  transition:
    transform  var(--dur-med) var(--ease-out),
    background var(--dur-med) var(--ease-soft);
}

.mode__opt {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.42rem;
  padding: clamp(0.95rem, 2.6vw, 1.3rem) clamp(0.7rem, 2.2vw, 1.4rem);
  text-align: center;
  cursor: pointer;
}

.mode__opt-title {
  font-family: var(--font-display);
  font-size: clamp(1.2rem, 2.4vw, 1.55rem);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: var(--track-tight);
  color: var(--parchment-faint);
  transition: color var(--dur-fast) var(--ease-soft);
}

.mode__opt-sub {
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-weight: 300;
  line-height: 1.4;
  letter-spacing: 0.04em;
  color: var(--parchment-faint);
  transition: color var(--dur-fast) var(--ease-soft);
}

.mode__opt:hover .mode__opt-title { color: var(--parchment-dim); }

/* ---- THE CONTRACT -----------------------------------------

   These four rules are the whole mechanism. Everything else on
   this form is decoration around them.
   ------------------------------------------------------------ */

#modeBuy:checked  ~ .form__pane--hire { display: none; }
#modeHire:checked ~ .form__pane--buy  { display: none; }

/* Thumb travel. Its own width, so 100%. */
#modeBuy:checked  ~ .mode .mode__thumb { transform: translateX(0); }
#modeHire:checked ~ .mode .mode__thumb { transform: translateX(100%); }

/* And the pigment of the thumb follows the route being chosen —
   oxblood for Acquire, malachite for Hire — so the toggle is
   quietly telling you which half of the business you are in. */
#modeHire:checked ~ .mode .mode__thumb {
  background: color-mix(in srgb, var(--malachite) 62%, var(--pitch-raised));
}

/* Checked label: parchment title, gilt sub-line. */
#modeBuy:checked  ~ .mode [for="modeBuy"] .mode__opt-title,
#modeHire:checked ~ .mode [for="modeHire"] .mode__opt-title {
  color: var(--parchment);
}
#modeBuy:checked  ~ .mode [for="modeBuy"] .mode__opt-sub,
#modeHire:checked ~ .mode [for="modeHire"] .mode__opt-sub {
  color: var(--gilt);
}

/* THE RADIOS ARE .sr-only. This is the ONLY focus ring a keyboard
   user gets on the most important control on the page. It is not
   optional and it is not decoration. Offset is negative so the
   ring sits inside the track and cannot be clipped. */
#modeBuy:focus-visible  ~ .mode [for="modeBuy"],
#modeHire:focus-visible ~ .mode [for="modeHire"] {
  outline: 1px solid var(--gilt);
  outline-offset: -5px;
}

/* Narrow phones: two columns of display type at 150px each is a
   word per line. Stack, and the thumb travels down instead. */
@media (max-width: 540px) {
  .mode { grid-template-columns: 1fr; }
  .mode__thumb {
    inset: 0 0 auto 0;
    width: auto;
    height: 50%;
  }
  #modeHire:checked ~ .mode .mode__thumb { transform: translateY(100%); }
  .mode__opt { padding-block: 1rem; }
}

/* ---- Panes ------------------------------------------------- */

/* Each pane carries its route's pigment as a left rule and a wash
   that dies out within a third of the width. Enough to say "you
   are in the hire half of the form"; not enough to be a panel. */
.form__pane {
  margin-top: clamp(var(--sp-4), 5vw, var(--sp-5));
  padding-top: var(--sp-4);
  padding-left: clamp(var(--sp-3), 2.4vw, var(--sp-4));
  border-top: 1px solid var(--pitch-line);
  border-left: 1px solid var(--pitch-line);
}

.form__pane--buy {
  border-left-color: var(--oxblood);
  background-image: linear-gradient(
    100deg,
    color-mix(in srgb, var(--oxblood) 30%, transparent) 0%,
    transparent 34%
  );
}

.form__pane--hire {
  border-left-color: var(--malachite);
  background-image: linear-gradient(
    100deg,
    color-mix(in srgb, var(--malachite) 34%, transparent) 0%,
    transparent 34%
  );
}

.form__pane-label {
  margin-bottom: var(--sp-3);
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--gilt);
}

/* ---- Fields ------------------------------------------------ */

.field {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  min-width: 0;
}

/* Safe whatever column count layout.css gives .form__grid. */
.field--wide { grid-column: 1 / -1; }

.field__label {
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-weight: 300;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  /* --parchment-dim, not --parchment-faint: a label has to be read. */
  color: var(--parchment-dim);
  transition: color var(--dur-fast) var(--ease-soft);
}
.field:focus-within .field__label { color: var(--parchment); }

/* "optional" is an aside inside the label — set it apart from the
   engraved caps so it does not read as part of the field name. */
.field__opt {
  margin-left: 0.4rem;
  font-family: var(--font-display);
  font-style: italic;
  font-size: 0.95rem;
  font-weight: 400;
  text-transform: lowercase;
  letter-spacing: 0;
  color: var(--parchment-faint);
}

/* The couture detail: a rule, never a box. A form full of filled
   input slabs would put more solid rectangles on this page than
   the rest of the design contains. */
.field__input {
  display: block;
  width: 100%;
  -webkit-appearance: none;
          appearance: none;
  padding: 0.72rem 0 0.6rem;
  border: 0;
  border-bottom: 1px solid var(--pitch-line);
  border-radius: 0;
  background: transparent;
  font-family: var(--font-body);
  /* 1rem, not --t-body: anything under 16px makes iOS zoom on focus. */
  font-size: 1rem;
  font-weight: 300;
  line-height: 1.5;
  letter-spacing: 0.01em;
  color: var(--parchment);
  transition:
    border-color var(--dur-fast) var(--ease-soft),
    color        var(--dur-fast) var(--ease-soft);
}

.field__input::placeholder {
  color: var(--parchment-faint);
  opacity: 1;
}

.field__input:hover { border-bottom-color: var(--parchment-faint); }

/* The focus ring IS the rule, thickened and gilded. A default
   outline here would draw back the box we just removed — but the
   replacement has to be unmistakable, so it doubles in weight and
   changes hue, not just brightness. */
.field__input:focus,
.field__input:focus-visible {
  outline: none;
  border-bottom-color: var(--gilt);
  border-bottom-width: 2px;
  padding-bottom: calc(0.6rem - 1px);
}

.field__input:disabled {
  color: var(--parchment-faint);
  cursor: not-allowed;
}

/* Only once main.js has judged it — never on first paint. */
.field__input[aria-invalid="true"] { border-bottom-color: var(--error); }

/* Chrome's autofill slab is a blue-white rectangle that would be
   the brightest thing on the page. Overpaint it with pitch. */
.field__input:-webkit-autofill,
.field__input:-webkit-autofill:hover,
.field__input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--parchment);
  -webkit-box-shadow: 0 0 0 1000px var(--pitch-raised) inset;
  caret-color: var(--parchment);
  transition: background-color 100000s ease 0s;
}

/* ---- Select ------------------------------------------------

   The chevron is built from two 45° linear-gradients rather than
   an inline SVG data-URI. A data-URI cannot read a custom
   property, so it would have to carry a literal hex — and this
   house does not write hex outside tokens.css. The gradient pair
   costs nothing, and it can be recoloured on hover and focus,
   which a background image never could.
   ------------------------------------------------------------ */

/* Two HAIRLINES meeting at a point, not two solid triangles. The
   left 7px box carries "\", the right one "/", and because the
   boxes sit exactly 7px apart they share a corner and the stroke
   closes into a clean chevron. The earlier recipe filled each box
   with a solid 45° wedge; the two never touched and read on screen
   as a pair of broken arrowheads. */
.field__input--select {
  padding-right: 1.8rem;
  cursor: pointer;
  text-overflow: ellipsis;
  background-image:
    linear-gradient(to bottom left,
      transparent calc(50% - 0.8px), var(--parchment-dim) 50%, transparent calc(50% + 0.8px)),
    linear-gradient(to bottom right,
      transparent calc(50% - 0.8px), var(--parchment-dim) 50%, transparent calc(50% + 0.8px));
  background-size: 7px 7px;
  background-position: right 13px center, right 6px center;
  background-repeat: no-repeat;
  transition:
    border-color var(--dur-fast) var(--ease-soft),
    background-image var(--dur-fast) var(--ease-soft);
}

.field__input--select:hover,
.field__input--select:focus,
.field__input--select:focus-visible {
  background-image:
    linear-gradient(to bottom left,
      transparent calc(50% - 0.8px), var(--gilt) 50%, transparent calc(50% + 0.8px)),
    linear-gradient(to bottom right,
      transparent calc(50% - 0.8px), var(--gilt) 50%, transparent calc(50% + 0.8px));
}

/* Placeholder option: dim until a real choice is made. Scoped to
   :invalid so it only applies while the empty value is selected. */
.field__input--select:invalid { color: var(--parchment-faint); }

/* The popup is drawn by the OS. color-scheme on .form handles most
   platforms; this forces the rest. */
.field__input--select option {
  background: var(--pitch-raised);
  color: var(--parchment);
}
.field__input--select option[value=""] { color: var(--parchment-faint); }

/* ---- Textarea ---------------------------------------------- */

.field__input--area {
  min-height: 7rem;
  resize: vertical;          /* horizontal resize would break the grid */
  line-height: 1.7;
  padding-top: 0.6rem;
}

/* ---- Dates and numbers -------------------------------------

   Four of the fields on this form are dates, and a native date
   input is the one control a designer cannot fully redraw. So:
   force the picker itself dark with color-scheme, then deal with
   WebKit's calendar glyph, which ships black and is invisible on
   pitch until it is inverted.
   ------------------------------------------------------------ */

.field__input[type="date"],
.field__input[type="number"],
.field__input[type="tel"] {
  color-scheme: dark;
  font-variant-numeric: tabular-nums lining-nums;
}

/* An empty date input renders "dd/mm/yyyy" at full text colour,
   which reads as a filled field. Push it back to placeholder
   weight and let :focus / :valid bring it up. */
.field__input[type="date"]:not(:focus):invalid { color: var(--parchment-faint); }

.field__input[type="date"]::-webkit-calendar-picker-indicator {
  filter: invert(1) sepia(0.55) saturate(1.8) hue-rotate(-6deg);
  opacity: 0.5;
  cursor: pointer;
  transition: opacity var(--dur-fast) var(--ease-soft);
}
.field__input[type="date"]:hover::-webkit-calendar-picker-indicator,
.field__input[type="date"]:focus::-webkit-calendar-picker-indicator {
  opacity: 0.95;
}

.field__input[type="date"]::-webkit-datetime-edit { padding: 0; }
.field__input[type="date"]::-webkit-datetime-edit-fields-wrapper { padding: 0; }

.field__input[type="number"]::-webkit-inner-spin-button {
  opacity: 0.35;
  transition: opacity var(--dur-fast) var(--ease-soft);
}
.field__input[type="number"]:hover::-webkit-inner-spin-button { opacity: 0.75; }

/* ---- Hints and errors --------------------------------------

   The error paragraphs exist in the markup for all fourteen
   fields at once. If they were merely dimmed, a visitor with no
   JavaScript would meet a wall of red telling them everything is
   wrong before they had typed a character.

   So the resting state is display:none and the shown state is a
   class main.js adds to the .field. That is JS-independent in the
   correct direction: no script, no errors. The :has() rule is a
   second route to the same state for whichever hook main.js
   actually uses.
   ------------------------------------------------------------ */

.field__hint {
  max-width: 46ch;
  font-size: var(--t-micro);
  font-weight: 300;
  line-height: 1.6;
  letter-spacing: 0.02em;
  color: var(--parchment-faint);
}

.field__error {
  display: none;
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-weight: 300;
  line-height: 1.5;
  letter-spacing: 0.04em;
  color: var(--error);
}

.field.is-invalid .field__error { display: block; }
.field:has(.field__input[aria-invalid="true"]) .field__error { display: block; }
.field:has(.check__input[aria-invalid="true"]) .field__error { display: block; }

.field.is-invalid .field__input { border-bottom-color: var(--error); }
.field.is-invalid .field__label { color: var(--error); }

/* ---- Checkbox ----------------------------------------------

   The real input keeps its place in the tab order and its hit
   area; it is only made transparent, and sits exactly over the
   drawn box so a click on either lands. The box is a gilt square
   with the house lozenge inside it when checked — not a tick,
   which is the one glyph this design language does not own.
   ------------------------------------------------------------ */

.field--check {
  position: relative;
  display: block;
}

.check__input {
  position: absolute;
  top: 0.12rem;
  left: 0;
  z-index: 1;
  width: 1.15rem;
  height: 1.15rem;
  margin: 0;
  -webkit-appearance: none;
          appearance: none;
  opacity: 0;
  cursor: pointer;
}

.check__label {
  position: relative;
  display: block;
  padding-left: 2rem;
  max-width: 62ch;
  font-size: var(--t-small);
  font-weight: 300;
  line-height: 1.7;
  color: var(--parchment-dim);
  cursor: pointer;
}

.check__label strong {
  font-weight: 400;
  color: var(--parchment);
}

/* The box. */
.check__label::before {
  content: "";
  position: absolute;
  top: 0.16rem;
  left: 0;
  width: 1.15rem;
  height: 1.15rem;
  border: 1px solid var(--gilt-dim);
  background: var(--pitch-deep);
  transition:
    border-color var(--dur-fast) var(--ease-soft),
    background   var(--dur-fast) var(--ease-soft);
}

/* The lozenge, resting at nothing and opening when checked. */
.check__label::after {
  content: "";
  position: absolute;
  top: 0.5rem;
  left: 0.34rem;
  width: 0.47rem;
  height: 0.47rem;
  background: var(--gilt);
  transform: rotate(45deg) scale(0);
  transform-origin: center;
  transition: transform var(--dur-fast) var(--ease-out);
}

.check__input:hover + .check__label::before { border-color: var(--gilt); }

.check__input:checked + .check__label::before { border-color: var(--gilt); }
.check__input:checked + .check__label::after { transform: rotate(45deg) scale(1); }

/* The input is invisible, so its native ring is too. Draw the
   ring on the box the user can actually see. */
.check__input:focus-visible + .check__label::before {
  outline: 1px solid var(--gilt);
  outline-offset: 3px;
}

.field--check .field__error { padding-left: 2rem; }

/* ---- Tail: submit row -------------------------------------- */

.form__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  margin-top: clamp(var(--sp-4), 5vw, var(--sp-5));
  padding-top: var(--sp-4);
  border-top: 1px solid var(--pitch-line);
}

/* role="status", written into by main.js. Empty at rest — and an
   empty element with padding and a border is a visible artefact,
   so it removes itself until it has something to say. */
.form__summary {
  order: -1;
  flex: 1 1 100%;
  padding-left: 0.85rem;
  border-left: 1px solid var(--error);
  font-size: var(--t-small);
  line-height: 1.6;
  color: var(--error);
}
.form__summary:empty { display: none; }

.form__submit { flex: none; }

.form__fine {
  flex: 1 1 22ch;
  max-width: 42ch;
  font-size: var(--t-micro);
  font-weight: 300;
  line-height: 1.7;
  letter-spacing: 0.02em;
  color: var(--parchment-faint);
}

/* ---- Confirmation panel ------------------------------------

   Revealed by main.js removing `hidden`. Because the rule below
   sets display:flex, the UA's [hidden] would lose the specificity
   fight and the panel would sit open under the form on first
   paint. The guard is not optional.
   ------------------------------------------------------------ */

.form__done {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--sp-2);
  padding-block: clamp(var(--sp-4), 6vw, var(--sp-6));
}
.form__done[hidden] { display: none; }
.form__done:focus { outline: none; }

/* The fleuron carries its own generous vertical margin; inside the
   panel it only needs a little. */
.form__done .orn--fleuron {
  margin-block: 0 var(--sp-3);
  width: min(200px, 70%);
  color: var(--gilt);
}

.form__done-title {
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 4vw, 2.8rem);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: var(--track-tight);
  color: var(--parchment);
}

.form__done-body {
  max-width: 44ch;
  font-size: var(--t-body);
  line-height: 1.75;
  color: var(--parchment-dim);
}

.form__done .btn { margin-top: var(--sp-3); }


/* ============================================================
   FAQ
   Native <details>/<summary>, with the disclosure triangle taken
   out on both engines and replaced by a gilt plus.

   The plus becomes a minus by rotating its vertical bar onto its
   horizontal one — no fade, no second glyph, no jump. The two
   bars are 1px, like everything else on this page.
   ============================================================ */

.faq__item {
  border-top: 1px solid var(--pitch-line);
}
.faq__item:last-child { border-bottom: 1px solid var(--pitch-line); }

.faq__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding-block: clamp(1.05rem, 2.2vw, 1.5rem);
  list-style: none;
  cursor: pointer;
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 1.9vw, 1.5rem);
  font-weight: 400;
  line-height: 1.3;
  letter-spacing: var(--track-tight);
  color: var(--parchment);
  transition: color var(--dur-fast) var(--ease-soft);
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q::marker { content: ""; }
.faq__q:hover { color: var(--gilt-hot); }
.faq__q:focus-visible {
  outline: 1px solid var(--gilt);
  outline-offset: -2px;
}

.faq__item[open] .faq__q { color: var(--gilt-hot); }

.faq__icon {
  position: relative;
  flex: none;
  width: 13px;
  height: 13px;
  color: var(--gilt);
}
.faq__icon::before,
.faq__icon::after {
  content: "";
  position: absolute;
  background: currentColor;
}
.faq__icon::before {
  inset: 50% 0 auto 0;
  height: 1px;
  margin-top: -0.5px;
}
.faq__icon::after {
  inset: 0 auto 0 50%;
  width: 1px;
  margin-left: -0.5px;
  transform-origin: center;
  transition: transform var(--dur-fast) var(--ease-out);
}

/* Vertical bar rotated flat onto the horizontal one: a minus. */
.faq__item[open] .faq__icon::after { transform: rotate(90deg); }

.faq__a {
  padding-bottom: clamp(1.05rem, 2.2vw, 1.5rem);
  padding-right: clamp(0px, 4vw, 3.5rem);
  max-width: 70ch;
  font-size: var(--t-body);
  line-height: 1.8;
  color: var(--parchment-dim);
}
.faq__a p + p { margin-top: var(--sp-2); }


/* ============================================================
   FOOTER
   The deepest ground on the page, and the last piece of gilt.
   The wordmark is the .gild treatment at display scale — base.css
   owns the leaf gradient, this owns the size.

   .foot__key are <h2> elements. Left alone they would be 1.5em
   bold headings and the four columns would out-shout the
   wordmark; they are reset to engraved small caps.
   ============================================================ */

.foot {
  position: relative;
  overflow: hidden;
  padding-top: clamp(3.5rem, 8vw, 6rem);
  padding-bottom: var(--sp-4);
  border-top: 1px solid var(--pitch-line);
  background: var(--pitch-deep);
}

/* Aligned left with the wordmark beneath it, not centred: a
   centred flourish over a left-set word looks like a mistake. */
.foot__fleuron {
  margin-inline: 0;
  margin-block: 0 clamp(var(--sp-4), 5vw, var(--sp-5));
  width: min(240px, 70%);
}

.foot__word {
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 7vw, 5rem);
  font-weight: 400;
  line-height: 1;
  letter-spacing: var(--track-tight);
}

.foot__line {
  margin-top: var(--sp-2);
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.05rem, 1.6vw, 1.3rem);
  font-weight: 300;
  color: var(--parchment-dim);
}

.foot__col { min-width: 0; }

.foot__key {
  margin-bottom: var(--sp-3);
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-weight: 400;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--gilt);
}

.foot__list {
  list-style: none;
  padding: 0;
}

.foot__list li { padding-block: 0.3rem; }

.foot__list li,
.foot__list a {
  font-family: var(--font-body);
  font-size: var(--t-small);
  font-weight: 300;
  line-height: 1.6;
  color: var(--parchment-dim);
}

.foot__list a {
  position: relative;
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-soft);
}
.foot__list a::after {
  content: "";
  position: absolute;
  inset: auto 0 -2px 0;
  height: 1px;
  background: var(--gilt);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-fast) var(--ease-out);
}
.foot__list a:hover { color: var(--parchment); }
.foot__list a:hover::after,
.foot__list a:focus-visible::after { transform: scaleX(1); }
.foot__list a:focus-visible {
  outline: 1px solid var(--gilt);
  outline-offset: 3px;
}

.foot__base {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2) var(--sp-4);
  margin-top: clamp(2.5rem, 7vw, 4.5rem);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--pitch-line);
}

.foot__fine {
  font-family: var(--font-body);
  font-size: var(--t-micro);
  font-weight: 300;
  letter-spacing: 0.05em;
  color: var(--parchment-faint);
}


/* ============================================================
   RESPONSIVE TAIL
   Everything above is written mobile-first or fluid; these are
   the handful of places where a component genuinely needs a
   different shape rather than a different size.
   ============================================================ */

/* The corner brackets are 26–34px. On a phone, a plate frame is
   about 290px wide and four brackets start to crowd the hat, so
   they pull in and thin out slightly. */
@media (max-width: 560px) {
  .orn--corner { width: 24px; height: 24px; }
  .orn--tl, .orn--tr { top: 9px; }
  .orn--bl, .orn--br { bottom: 9px; }
  .orn--tl, .orn--bl { left: 9px; }
  .orn--tr, .orn--br { right: 9px; }

  .form-well::before { inset: 10px; }
}

/* Buttons at full padding put "Hire for an occasion" on two lines
   inside a 300px well. Tighten the box, keep the tracking. */
@media (max-width: 480px) {
  .btn {
    padding: 0.95rem 1.35rem 0.95rem calc(1.35rem + var(--track-label));
    white-space: normal;
    text-align: center;
  }
  .btn--line { padding: 0.5rem 0 0.45rem; white-space: nowrap; }

  .form__foot { gap: var(--sp-3); }
  .form__submit { width: 100%; }
}

/* Coarse pointers never get :hover, so every hover-only affordance
   above needs its resting state to already be legible — it is, but
   the hairlines are the marginal case. Warm them a step. */
@media (hover: none) {
  .plate__frame { border-color: color-mix(in srgb, var(--gilt) 14%, transparent); }
  .occ__tag { color: var(--parchment-dim); }
}


/* ============================================================
   FORCED-CONTRAST AND HIGH-CONTRAST PREFERENCES
   --gilt-dim is a 26% gold, which is exactly right on a varnish
   black and is the first thing to disappear for a reader who has
   asked for more contrast. Where a hairline is carrying meaning
   — a frame, a divider between two prices, a checkbox — it goes
   to full gilt. Decorative brackets are left alone; they are
   ornament, and ornament is allowed to be quiet.
   ============================================================ */

@media (prefers-contrast: more) {
  .price:last-child,
  .btn--line,
  .occ__tag,
  .check__label::before { border-color: var(--gilt); }

  .field__input { border-bottom-color: var(--parchment-faint); }
  .field__label { color: var(--parchment); }
  .field__hint,
  .form__fine,
  .foot__fine { color: var(--parchment-dim); }

  .plate__note,
  .occ__note,
  .faq__a { color: var(--parchment); }
}

/* Windows forced-colours mode replaces every colour we have chosen.
   Ornament drawn in currentColor survives; ornament drawn as a
   background does not, so the pieces that must remain legible are
   re-expressed in system colours. */
@media (forced-colors: active) {
  .orn--corner,
  .orn--fleuron,
  .nav__crest { color: CanvasText; }

  .mode__thumb {
    background: Highlight;
    box-shadow: none;
  }
  #modeBuy:checked  ~ .mode [for="modeBuy"] .mode__opt-title,
  #modeHire:checked ~ .mode [for="modeHire"] .mode__opt-title {
    color: HighlightText;
  }

  .check__label::before { border-color: CanvasText; }
  .check__label::after { background: CanvasText; }

  .faq__icon { color: CanvasText; }
  .btn { border-color: CanvasText; }
  .btn__sweep { display: none; }
}
