/* =========================================================
   Coppice (DEMO) — wood-fired tasting-menu restaurant, Manchester.

   Ported from the Caelora Framer template's design language onto a
   hand-coded token system. Measured off the live template
   (caelora.framer.website) rather than eyeballed, so the numbers below
   are its numbers:

     - MELODRAMA at weight 500 for every piece of display type, at sizes
       that are genuinely enormous: the template sets its wordmark at
       140px on a 119px line-height (0.85) and its section headings at
       130px. That negative leading is the whole look. Setting these to
       a sane 1.1 makes it a different, much politer design.
     - letter-spacing: NORMAL on all of it. A high-contrast serif at
       130px is usually tracked in; this one is not, and tightening it
       closes the counters up.
     - MANROPE for every piece of UI, small, uppercase, tracked out.
       Nothing on the page is sentence-case except body paragraphs.
     - RADIUS 0. Not Ellerby's near-square 1-2px — actually square. One
       rounded corner and the whole thing turns into a startup landing
       page.
     - A ground of #0f0f0f top to bottom. Not dark bands on white: the
       page is dark the whole way down, which is why the photography
       has to carry every bit of the light.

   ONE DEPARTURE, and it is deliberate. Caelora is pure monochrome —
   white and #b3b3b3 on black, no accent whatsoever. This build adds
   --bone, a warm off-white, for two reasons. Marram is already
   monochrome and Ellerby is already near-black-and-neutral, so a third
   colourless build stops reading as a separate site on /work. And this
   page takes money: a basket, a stepper, a sold-out state and a
   checkout all need a colour that means "this is the live one", and
   spending white on that leaves the headings nothing to be brightest.
   Bone is used sparingly and never on a large field.

   THE COMMERCE is the reason this build exists — it is the first demo
   here that takes payment rather than routing to an enquiry. Three
   things go in one basket (seats, vouchers, a private-hire deposit),
   so the basket, drawer, stepper and checkout are a real component set
   rather than a button that scrolls to a form. See script.js.

   IT IS PHOTO-LED. Seven slots, cropped at build time by
   scripts/make_coppice_images.py: a 16:9 hero, three 3:4 tiles, a 4:3
   private-dining panel and two small 16:9 blocks in the split band.
   Re-frame by editing that script's MANIFEST focus/zoom columns and
   re-running — never by hand-editing a WebP, it is overwritten on the
   next run. The originals are NOT in the repo; see the script header.

   It shipped the same day with drawn panels instead — warm ember
   fields, tonal washes and hairline art — because there were no
   licensed restaurant photographs yet. That was a stopgap, not the
   intent, exactly as Bramblewood, Hollins and Ellerby each shipped once
   and had replaced the same day. A restaurant is sold on the room and
   the plate, and no amount of gradient does that job.

   Not greyscaled: Marram is the monochrome one by design, and this page
   is near-black chrome with a single --bone note precisely so the
   photography carries all of the colour and all of the light.
   ========================================================= */

:root {
  --ink:      #0f0f0f;              /* the template's own ground      */
  --ink-2:    #161616;              /* raised surface — cards, rows   */
  --ink-3:    #1d1d1d;              /* inputs, hover                  */
  --paper:    #ffffff;
  --dim:      #b3b3b3;              /* the template's one grey        */
  --dim-2:    #7a7a7a;

  --line:     rgba(255, 255, 255, .13);
  --line-2:   rgba(255, 255, 255, .26);

  /* The one warm note. See the header — this is the single departure
     from Caelora's pure monochrome, and it earns its place by marking
     the live/purchasable state. Never use it as a large field. */
  --bone:     #e4d7c3;
  --bone-d:   #c8b795;
  --ember:    #e07a45;              /* the fire, and error text only  */

  --r:        0px;                  /* square. the signature.         */

  --wrap:     1360px;
  --gut:      28px;
  --sect:     clamp(78px, 9vw, 140px);

  --ease:     cubic-bezier(.22, 1, .36, 1);
  --fd:       "Melodrama", "Playfair Display", Georgia, serif;
  --f:        "Manrope", system-ui, -apple-system, sans-serif;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
  font-family: var(--f);
  background: var(--ink);
  color: var(--paper);
  font-size: 16px;
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
body.is-locked { overflow: hidden; }
img, svg { display: block; max-width: 100%; }
/* .recap sets `display: grid`, which outranks the UA sheet's
   [hidden] { display: none } — so the order summary stayed on screen
   through the confirmation step. Anything given `hidden` here needs to
   actually go. */
[hidden] { display: none !important; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--bone); outline-offset: 3px; }

.wrap { width: min(100% - (var(--gut) * 2), var(--wrap)); margin-inline: auto; }
.sect { padding-block: var(--sect); }
.vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ---------- Display type ----------
   Melodrama 500 only. The clamps top out near the template's real
   sizes (140 / 130 / 64 / 32) and the line-heights stay under 1 on the
   two big ones, which is where the look lives. */
.d1, .d2, .d3, .d4 {
  font-family: var(--fd); font-weight: 500;
  letter-spacing: normal; text-transform: uppercase;
}
.d1 { font-size: clamp(66px, 14.5vw, 178px); line-height: .85; }
.d2 { font-size: clamp(44px, 8.4vw, 122px); line-height: .95; }
.d3 { font-size: clamp(32px, 4.3vw, 62px);  line-height: 1;   }
.d4 { font-size: clamp(23px, 2.1vw, 31px);  line-height: 1.18; text-transform: none; }

/* ---------- UI type ----------
   Everything that is not a heading or a paragraph is this: 12px
   Manrope, uppercase, tracked out. */
.eyebrow, .ui {
  font-size: 12px; font-weight: 500; letter-spacing: .14em;
  text-transform: uppercase; line-height: 1.4;
}
.eyebrow { color: var(--dim); display: block; margin-bottom: 22px; }
.lede { color: var(--dim); font-size: clamp(15px, 1.15vw, 18px); max-width: 54ch; }
.fine { color: var(--dim-2); font-size: 13px; line-height: 1.55; }
.bone { color: var(--bone); }

/* ---------- Buttons ----------
   Square, uppercase, 12px. The fill wipes up from the bottom rather
   than cross-fading, which is the template's own hover. */
.btn {
  --bg: transparent; --fg: var(--paper); --bd: var(--line-2);
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  gap: 10px; padding: 17px 30px; border: 1px solid var(--bd); background: var(--bg);
  color: var(--fg); border-radius: var(--r); cursor: pointer; overflow: hidden;
  font-size: 12px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  transition: color .35s var(--ease), border-color .35s var(--ease);
}
.btn > * { position: relative; z-index: 1; }
.btn::before {
  content: ""; position: absolute; inset: 0; background: var(--paper);
  transform: translateY(101%); transition: transform .45s var(--ease);
}
.btn:hover { color: var(--ink); border-color: var(--paper); }
.btn:hover::before { transform: translateY(0); }
.btn--fill { --bg: var(--bone); --fg: var(--ink); --bd: var(--bone); }
.btn--fill::before { background: var(--paper); }
.btn--fill:hover { color: var(--ink); border-color: var(--paper); }
.btn--sm { padding: 12px 20px; letter-spacing: .12em; }
.btn--block { width: 100%; }
.btn[disabled] { opacity: .35; pointer-events: none; }

/* A text link with the rule that draws in from the left. */
.tlink {
  display: inline-flex; align-items: center; gap: 12px; padding-bottom: 6px;
  font-size: 12px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  background-image: linear-gradient(var(--paper), var(--paper));
  background-size: 0 1px; background-position: 0 100%; background-repeat: no-repeat;
  transition: background-size .45s var(--ease);
}
.tlink:hover { background-size: 100% 1px; }

/* ---------- Photography ----------
   Every image is already cropped to its slot's exact ratio by
   scripts/make_coppice_images.py. The object-fit below is a safety net
   for odd viewports, NOT the crop — re-frame in that script's MANIFEST,
   never by hand-editing a WebP.

   The #0b0b0b ground is what shows while a lazy image is still coming,
   so the tiles never flash white on a page that is black throughout. */
.shot { position: relative; overflow: hidden; background: #0b0b0b; }
.shot > img { width: 100%; height: 100%; object-fit: cover; }

/* =========================================================
   NAV
   Caelora's is a plain fixed row, not a capsule — wordmark left, links
   centred, cart right, all 12px uppercase. It has no background at
   rest; it gains one once you leave the hero, because past that point
   it is over content rather than over a photograph.
   ========================================================= */
.nav {
  position: fixed; inset: 0 0 auto; z-index: 60;
  border-bottom: 1px solid transparent;
  transition: background .4s var(--ease), border-color .4s var(--ease), backdrop-filter .4s;
}
.nav.is-stuck {
  background: rgba(15, 15, 15, .82); border-bottom-color: var(--line);
  backdrop-filter: blur(14px) saturate(140%);
}
@supports not (backdrop-filter: blur(1px)) { .nav.is-stuck { background: #0f0f0f; } }
.nav__inner {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  gap: 24px; padding-block: 20px;
}
.brand {
  font-family: var(--fd); font-weight: 500; font-size: 25px; line-height: 1;
  text-transform: uppercase; letter-spacing: .04em;
}
.nav__links { display: flex; gap: 38px; justify-content: center; }
.nav__links a { position: relative; font-size: 12px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase; }
.nav__links a::after {
  content: ""; position: absolute; left: 0; bottom: -6px; height: 1px; width: 0;
  background: currentColor; transition: width .4s var(--ease);
}
.nav__links a:hover::after, .nav__links a[aria-current="true"]::after { width: 100%; }
.nav__end { display: flex; align-items: center; gap: 14px; justify-content: flex-end; }

/* The basket button. The count is the only always-on bone element on
   the page, which is the point — it is the live state. */
.basketbtn {
  display: inline-flex; align-items: center; gap: 9px; padding: 12px 18px;
  border: 1px solid var(--line-2); background: none; cursor: pointer;
  font-size: 12px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  transition: border-color .3s var(--ease), background .3s var(--ease);
}
.basketbtn:hover { border-color: var(--paper); background: rgba(255, 255, 255, .06); }
.basketbtn__n {
  min-width: 21px; height: 21px; padding: 0 6px; display: grid; place-items: center;
  background: var(--bone); color: var(--ink); font-size: 11px; font-weight: 700; letter-spacing: 0;
}
.basketbtn.is-bump { animation: bump .45s var(--ease); }
@keyframes bump { 40% { transform: scale(1.09); } 100% { transform: scale(1); } }

.burger {
  display: none; width: 42px; height: 42px; border: 1px solid var(--line-2);
  background: none; cursor: pointer; position: relative;
}
.burger span { position: absolute; left: 11px; width: 18px; height: 1px; background: var(--paper); transition: transform .3s var(--ease), opacity .3s; }
.burger span:nth-child(1) { top: 17px; }
.burger span:nth-child(2) { top: 23px; }
.burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(3px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2) { transform: translateY(-3px) rotate(-45deg); }

.drawer-nav {
  display: none; flex-direction: column; gap: 2px; padding: 8px 0 26px;
  border-top: 1px solid var(--line);
}
.drawer-nav a { padding: 14px 0; font-size: 13px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; border-bottom: 1px solid var(--line); }
.nav.is-open .drawer-nav { display: flex; }
.nav.is-open { background: #0f0f0f; }

/* =========================================================
   HERO
   The template's own: full-bleed art, the wordmark set enormous and
   centred across it, one line of copy under. Nothing else.
   ========================================================= */
.hero { position: relative; min-height: min(100svh, 940px); display: grid; }
.hero__bg { position: absolute; inset: 0; }
/* Top- and bottom-heavy, not left-heavy like Ellerby's, because every
   element on this hero is centred — wordmark, both buttons, the
   availability strip. The middle stays thinnest so the candle flame and
   the lit back bar still read; a flat alpha strong enough for the
   bottom strip would put the whole photograph out. */
.hero__veil {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(12,12,12,.86) 0%, rgba(12,12,12,.40) 20%, rgba(12,12,12,.16) 40%, rgba(12,12,12,.52) 74%, rgba(12,12,12,.88) 100%),
    radial-gradient(64% 42% at 50% 70%, rgba(10,10,10,.66) 0%, rgba(0,0,0,0) 100%);
}
.hero__in {
  position: relative; z-index: 3; align-self: end;
  padding-block: 132px 64px; display: grid; gap: 34px; justify-items: center; text-align: center;
}
.hero .d1 { margin-inline: auto; }
.hero__sub { max-width: 46ch; color: var(--dim); font-size: clamp(15px, 1.3vw, 19px); }
.hero__acts { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; }

/* The status strip. This is the admin doing its job in the first
   screen: what is left tonight, before anyone has scrolled. */
.hero__status {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 10px 22px; padding-top: 6px;
  font-size: 12px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase; color: var(--dim);
}
.dot { width: 7px; height: 7px; background: var(--bone); display: inline-block; margin-right: 9px; }
.dot--out { background: var(--dim-2); }

/* =========================================================
   STATEMENT — Caelora sets a mission paragraph as a 64px uppercase
   serif block. It is a heading doing a paragraph's job, and it is the
   template's second most recognisable move after the wordmark.
   ========================================================= */
.statement { border-top: 1px solid var(--line); }
.statement__grid { display: grid; grid-template-columns: 1fr; gap: 46px; }
.statement .d3 { max-width: 18ch; }
.statement__side { display: grid; gap: 26px; align-content: start; }

/* =========================================================
   TILES — the template's EARINGS / BRACELET / RING row: three tall
   panels, the label set across each in the display serif, a SEE ALL
   under it.
   ========================================================= */
.tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px; }
.tile { position: relative; aspect-ratio: 3 / 4; display: grid; align-content: end; padding: 34px; }
.tile__art { position: absolute; inset: 0; }
.tile__body { position: relative; z-index: 2; display: grid; gap: 16px; }
.tile__body::before {
  content: ""; position: absolute; inset: -34px; z-index: -1;
  background: linear-gradient(0deg, rgba(10,10,10,.86) 0%, rgba(10,10,10,.28) 58%, rgba(10,10,10,0) 100%);
}
.tile .d3 { font-size: clamp(28px, 3.2vw, 48px); }
.tile p { color: var(--dim); font-size: 14px; max-width: 30ch; }
.tile__art > * { transition: transform .9s var(--ease); }
.tile:hover .tile__art > * { transform: scale(1.05); }

/* =========================================================
   RESERVE — the commerce block, and the reason this build exists.
   A date rail, two sittings, a covers stepper, and a real remaining
   count per sitting. Everything here is square and 1px.
   ========================================================= */
.reserve { border-top: 1px solid var(--line); }
.reserve__grid { display: grid; grid-template-columns: 1fr; gap: 48px; align-items: start; }
/* min-width: 0 all the way down to the date rail. A grid item defaults
   to min-width: auto — its min-content — and fourteen 78px date squares
   make that 1254px, so the 1.25fr/.75fr split silently became 1254/147
   and the terms column collapsed to four words a line. The rail is a
   scroller; it has to be allowed to be narrower than its contents. */
.reserve__grid > *, .rbox__bd > * { min-width: 0; }
.dates { max-width: 100%; }
.rbox { border: 1px solid var(--line); background: var(--ink-2); }
.rbox__hd { display: flex; flex-wrap: wrap; gap: 16px; justify-content: space-between; align-items: baseline; padding: 26px 28px; border-bottom: 1px solid var(--line); }
.rbox__price { font-family: var(--fd); font-size: 40px; font-weight: 500; line-height: 1; }
.rbox__price span { font-family: var(--f); font-size: 12px; letter-spacing: .14em; color: var(--dim); margin-left: 8px; }
.rbox__bd { padding: 28px; display: grid; gap: 26px; }

.flabel { display: block; font-size: 12px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--dim); margin-bottom: 12px; }

/* Date rail — a horizontal scroller of squares, one per open day. */
.dates { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 8px; scrollbar-width: thin; }
.date {
  flex: 0 0 auto; width: 78px; padding: 12px 8px; border: 1px solid var(--line);
  background: none; cursor: pointer; display: grid; gap: 4px; text-align: center;
  transition: border-color .25s var(--ease), background .25s var(--ease);
}
.date b { font-family: var(--fd); font-size: 25px; font-weight: 500; line-height: 1; }
.date i { font-style: normal; font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--dim); }
.date:hover:not([disabled]) { border-color: var(--line-2); background: var(--ink-3); }
.date[aria-pressed="true"] { border-color: var(--bone); background: var(--ink-3); }
.date[aria-pressed="true"] i { color: var(--bone); }
.date[disabled] { opacity: .3; cursor: not-allowed; }

/* Sittings — two rows, each showing what is actually left. */
.sittings { display: grid; gap: 8px; }
.sitting {
  display: flex; flex-wrap: wrap; gap: 8px 18px; align-items: center; justify-content: space-between;
  width: 100%; padding: 16px 18px; border: 1px solid var(--line); background: none; cursor: pointer;
  text-align: left; transition: border-color .25s var(--ease), background .25s var(--ease);
}
.sitting:hover:not([disabled]) { border-color: var(--line-2); background: var(--ink-3); }
.sitting[aria-pressed="true"] { border-color: var(--bone); background: var(--ink-3); }
.sitting[disabled] { opacity: .42; cursor: not-allowed; }
.sitting__t { font-size: 13px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; }
.sitting__n { font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: var(--dim); }
.sitting[aria-pressed="true"] .sitting__n { color: var(--bone); }

/* Stepper */
.stepper { display: inline-flex; align-items: center; border: 1px solid var(--line); }
.stepper button {
  width: 46px; height: 46px; border: 0; background: none; cursor: pointer; font-size: 18px; line-height: 1;
  transition: background .2s var(--ease);
}
.stepper button:hover:not([disabled]) { background: var(--ink-3); }
.stepper button[disabled] { opacity: .3; cursor: not-allowed; }
.stepper output { min-width: 54px; text-align: center; font-family: var(--fd); font-size: 24px; font-weight: 500; }

.rbox__ft { border-top: 1px solid var(--line); padding: 22px 28px; display: grid; gap: 16px; }
.rbox__total { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; }
.rbox__total b { font-family: var(--fd); font-size: 34px; font-weight: 500; line-height: 1; }

/* The terms column beside the picker. This is the actual product —
   the rules that stop no-shows — so it is set as content, not fine
   print tucked in a footer. */
.terms { display: grid; gap: 2px; }
.term { padding: 22px 24px; border: 1px solid var(--line); display: grid; gap: 8px; }
.term h3 { font-size: 13px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; }
.term p { color: var(--dim); font-size: 14px; }

/* =========================================================
   MENU
   ========================================================= */
.menu { border-top: 1px solid var(--line); }
.menu__grid { display: grid; grid-template-columns: 1fr; gap: 48px; align-items: start; }
.courses { display: grid; }
.course {
  display: grid; grid-template-columns: 54px 1fr; gap: 22px; align-items: baseline;
  padding: 24px 0; border-bottom: 1px solid var(--line);
}
.course:first-child { border-top: 1px solid var(--line); }
.course__n { font-family: var(--fd); font-size: 24px; font-weight: 500; color: var(--dim-2); line-height: 1; }
.course__t { font-family: var(--fd); font-size: clamp(20px, 1.9vw, 27px); font-weight: 500; line-height: 1.2; }
.course__d { color: var(--dim); font-size: 14px; margin-top: 6px; }

/* =========================================================
   VOUCHERS — the second thing in the basket, and the one that is
   pure margin. Three fixed values plus a custom, each square.
   ========================================================= */
.vouchers { border-top: 1px solid var(--line); }
.vgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 2px; }
.vcard {
  border: 1px solid var(--line); background: var(--ink-2); padding: 30px 26px;
  display: grid; gap: 18px; align-content: start;
  transition: border-color .3s var(--ease), background .3s var(--ease);
}
.vcard:hover { border-color: var(--line-2); background: var(--ink-3); }
/* .vcard p has to come FIRST and the value has to out-specify it.
   `.vcard p` is (0,1,1) and a bare `.vcard__v` is (0,1,0), so source
   order never gets a look in — the amounts silently rendered as 14px
   grey body copy. */
.vcard p { color: var(--dim); font-size: 14px; }
.vcard p.vcard__v {
  font-family: var(--fd); font-size: clamp(42px, 4.4vw, 62px);
  font-weight: 500; line-height: 1; color: var(--paper);
}
.vcard input {
  width: 100%; padding: 14px 16px; background: var(--ink); border: 1px solid var(--line);
  font-size: 15px;
}
.vcard input::placeholder { color: var(--dim-2); }

/* =========================================================
   HIRE — the third basket line: a deposit that holds the room.
   ========================================================= */
.hire { border-top: 1px solid var(--line); }
.hire__grid { display: grid; grid-template-columns: 1fr; gap: 0; border: 1px solid var(--line); }
.hire__art { position: relative; min-height: 320px; }
.hire__bd { padding: clamp(30px, 4vw, 56px); display: grid; gap: 24px; align-content: center; }
/* The grid stretches it to the column otherwise, and every other button
   on the page sizes to its label. */
.hire__bd .btn { justify-self: start; }
.hire__list { display: grid; gap: 12px; }
.hire__list li { display: grid; grid-template-columns: 14px 1fr; gap: 14px; color: var(--dim); font-size: 15px; list-style: none; }
.hire__list li::before { content: ""; width: 7px; height: 7px; background: var(--bone); margin-top: 9px; }

/* =========================================================
   SPLIT — Caelora's "JEWELRY FOR / EVERY MOMENT": two enormous lines
   with art between them.
   ========================================================= */
.split { border-top: 1px solid var(--line); overflow: hidden; }
.split__row { display: flex; align-items: center; gap: clamp(18px, 3vw, 48px); }
.split__row--b { justify-content: flex-end; }
.split__art { flex: 0 0 clamp(120px, 22vw, 320px); aspect-ratio: 16 / 9; }

/* =========================================================
   VISIT
   ========================================================= */
.visit { border-top: 1px solid var(--line); }
.visit__grid { display: grid; grid-template-columns: 1fr; gap: 40px; }
.vitem { display: grid; gap: 10px; align-content: start; padding-top: 24px; border-top: 1px solid var(--line); }
.vitem h3 { font-size: 12px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--dim); }
.vitem p, .vitem a { font-size: 16px; }
.hours { display: grid; gap: 6px; }
.hours div { display: flex; justify-content: space-between; gap: 18px; font-size: 15px; }
.hours span:last-child { color: var(--dim); }

/* =========================================================
   OUTRO + FOOTER — the template closes on the wordmark at full width.
   ========================================================= */
.outro { border-top: 1px solid var(--line); text-align: center; }
.outro__in { display: grid; gap: 30px; justify-items: center; }
.signup { display: flex; gap: 8px; width: min(100%, 460px); }
.signup input { flex: 1; padding: 16px 18px; background: var(--ink-2); border: 1px solid var(--line); font-size: 15px; }
.signup input::placeholder { color: var(--dim-2); }

.wordmark { border-top: 1px solid var(--line); padding-block: clamp(30px, 4vw, 56px); }
.wordmark span {
  display: block; font-family: var(--fd); font-weight: 500; text-transform: uppercase;
  font-size: clamp(56px, 20vw, 300px); line-height: .8; text-align: center; letter-spacing: .01em;
}

.ft { border-top: 1px solid var(--line); padding-block: 56px 34px; }
.ft__grid { display: grid; grid-template-columns: 1fr; gap: 40px; }
.ft__k { font-size: 12px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--dim-2); margin-bottom: 16px; }
/* :not(.brand) matters — the footer wordmark is an <a> inside .ft__col,
   and without it this rule out-specifies .brand and sets the 25px
   Melodrama mark in 13px Manrope. */
.ft__col a:not(.brand), .ft__col span { display: block; font-size: 13px; letter-spacing: .1em; text-transform: uppercase; padding: 7px 0; }
.ft__col a:not(.brand):hover { color: var(--bone); }
.ft__base {
  margin-top: 46px; padding-top: 24px; border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; gap: 12px 24px; justify-content: space-between;
}
.ft__base p { color: var(--dim-2); font-size: 12px; letter-spacing: .08em; text-transform: uppercase; }
.ft__base a { color: var(--dim); }

/* =========================================================
   BASKET DRAWER
   ========================================================= */
.scrim {
  position: fixed; inset: 0; z-index: 80; background: rgba(6, 6, 6, .72);
  opacity: 0; visibility: hidden; transition: opacity .4s var(--ease), visibility .4s;
}
.scrim.is-open { opacity: 1; visibility: visible; }

.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 90; width: min(100%, 460px);
  background: var(--ink); border-left: 1px solid var(--line);
  transform: translateX(101%); transition: transform .5s var(--ease);
  display: grid; grid-template-rows: auto 1fr auto;
}
.drawer.is-open { transform: none; }
.drawer__hd { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 24px 26px; border-bottom: 1px solid var(--line); }
.iconbtn { width: 38px; height: 38px; display: grid; place-items: center; border: 1px solid var(--line); background: none; cursor: pointer; transition: border-color .25s, background .25s; }
.iconbtn:hover { border-color: var(--paper); background: var(--ink-3); }
.drawer__bd { overflow-y: auto; padding: 8px 26px; }
.drawer__ft { padding: 22px 26px 26px; border-top: 1px solid var(--line); display: grid; gap: 16px; }

.line { display: grid; grid-template-columns: 1fr auto; gap: 6px 18px; padding: 22px 0; border-bottom: 1px solid var(--line); }
.line__t { font-family: var(--fd); font-size: 22px; font-weight: 500; line-height: 1.15; }
.line__m { grid-column: 1 / -1; color: var(--dim); font-size: 13px; }
.line__p { font-size: 15px; font-weight: 600; white-space: nowrap; }
.line__acts { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-top: 6px; }
.line__rm { background: none; border: 0; cursor: pointer; color: var(--dim-2); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; padding: 6px 0; }
.line__rm:hover { color: var(--ember); }
.stepper--sm button { width: 34px; height: 34px; font-size: 15px; }
.stepper--sm output { min-width: 40px; font-size: 17px; }

.empty { display: grid; gap: 18px; justify-items: center; text-align: center; padding: 70px 10px; }
.empty p:not(.d4) { color: var(--dim); font-size: 14px; }
.sum { display: grid; gap: 8px; }
.sum div { display: flex; justify-content: space-between; gap: 16px; font-size: 14px; color: var(--dim); }
.sum div.sum--tot { color: var(--paper); align-items: baseline; }
.sum--tot b { font-family: var(--fd); font-size: 30px; font-weight: 500; line-height: 1; }

/* =========================================================
   CHECKOUT — a full-screen sheet, three steps. It is a demo: no
   payment is taken and the panel says so at the point of paying,
   not in a footnote.
   ========================================================= */
.sheet {
  position: fixed; inset: 0; z-index: 100; background: var(--ink); overflow-y: auto;
  opacity: 0; visibility: hidden; transform: translateY(14px);
  transition: opacity .4s var(--ease), visibility .4s, transform .4s var(--ease);
}
.sheet.is-open { opacity: 1; visibility: visible; transform: none; }
.sheet__hd {
  position: sticky; top: 0; z-index: 2; background: var(--ink); border-bottom: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 20px 0;
}
.steps { display: flex; gap: 26px; }
.steps span { font-size: 12px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase; color: var(--dim-2); }
.steps span.is-on { color: var(--bone); }
.steps span.is-done { color: var(--dim); }
.sheet__grid { display: grid; grid-template-columns: 1fr; gap: 48px; padding-block: 46px 90px; align-items: start; }

.fields { display: grid; gap: 20px; }
.frow { display: grid; gap: 20px; }
.field { display: grid; gap: 9px; }
.field input, .field select, .field textarea {
  width: 100%; padding: 15px 16px; background: var(--ink-2); border: 1px solid var(--line);
  border-radius: var(--r); font-size: 15px; transition: border-color .25s var(--ease);
}
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--bone); outline: none; }
.field input::placeholder, .field textarea::placeholder { color: var(--dim-2); }
.field[data-bad] input, .field[data-bad] select { border-color: var(--ember); }
.field small { color: var(--ember); font-size: 12px; letter-spacing: .06em; display: none; }
.field[data-bad] small { display: block; }

.note {
  display: grid; gap: 8px; padding: 20px 22px; border: 1px solid var(--line); background: var(--ink-2);
}
.note b { font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--bone); }
.note p { color: var(--dim); font-size: 14px; }

.recap { border: 1px solid var(--line); background: var(--ink-2); padding: 26px; display: grid; gap: 20px; position: sticky; top: 96px; }
.recap__list { display: grid; gap: 14px; }
.recap__list div { display: flex; justify-content: space-between; gap: 16px; font-size: 14px; }
/* Direct child only. A bare span:last-child also caught the nested
   .fine span that carries each line's meta, and dropped nowrap on it. */
.recap__list div > span:last-child { color: var(--dim); white-space: nowrap; }

.done { display: grid; gap: 26px; justify-items: center; text-align: center; padding-block: 70px; }
.done__ref { font-family: var(--fd); font-size: clamp(34px, 5vw, 62px); font-weight: 500; line-height: 1; letter-spacing: .02em; }

/* =========================================================
   REVEAL — Caelora runs everything through Motion in JS. Rebuilt from
   observed behaviour: a 24px rise out of a small blur, staggered.
   ========================================================= */
.rev { opacity: 0; transform: translateY(24px); filter: blur(5px); }
.rev.is-in { opacity: 1; transform: none; filter: none; transition: opacity .8s var(--ease), transform .8s var(--ease), filter .8s var(--ease); }

.demobadge {
  position: fixed; left: 14px; bottom: 14px; z-index: 70;
  padding: 9px 14px; background: rgba(15, 15, 15, .9); border: 1px solid var(--line-2);
  color: var(--dim); font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  backdrop-filter: blur(8px);
}
.demobadge:hover { color: var(--paper); border-color: var(--paper); }

/* =========================================================
   RESPONSIVE
   ========================================================= */
@media (min-width: 760px) {
  .frow--2 { grid-template-columns: 1fr 1fr; }
  .visit__grid { grid-template-columns: repeat(2, 1fr); }
  .ft__grid { grid-template-columns: 1.4fr 1fr 1fr 1fr; }
}
@media (min-width: 1000px) {
  .statement__grid { grid-template-columns: 1.15fr .85fr; gap: 60px; }
  .reserve__grid { grid-template-columns: 1.25fr .75fr; gap: 56px; }
  .menu__grid { grid-template-columns: .8fr 1.2fr; gap: 64px; }
  .hire__grid { grid-template-columns: 1fr 1fr; }
  .visit__grid { grid-template-columns: repeat(4, 1fr); }
  .sheet__grid { grid-template-columns: 1.35fr .65fr; gap: 60px; }
}
@media (max-width: 999px) {
  .vgrid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 860px) {
  .nav__inner { grid-template-columns: auto 1fr; }
  .nav__links { display: none; }
  .burger { display: block; }
  .tiles { grid-template-columns: 1fr; }
  .tile { aspect-ratio: 4 / 3; }
  .split__art { display: none; }
  .split__row, .split__row--b { justify-content: flex-start; }
}
@media (max-width: 560px) {
  :root { --gut: 18px; }
  /* The demo badge is fixed bottom-left and lands on the availability
     strip at this width. Buy the strip some room rather than moving the
     badge, which sits in the same place on every demo here. */
  .hero__in { padding-bottom: 96px; }
  .vgrid { grid-template-columns: 1fr; }
  .rbox__bd, .rbox__hd, .rbox__ft { padding-inline: 20px; }
  .drawer__bd, .drawer__hd, .drawer__ft { padding-inline: 20px; }
  .steps span:not(.is-on) { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
  .rev { opacity: 1; transform: none; filter: none; }
}
