@font-face{font-family:'Anton';font-style:normal;font-weight:400;font-display:swap;
  src:url('/fonts/anton-latin.woff2') format('woff2')}
@font-face{font-family:'Oswald';font-style:normal;font-weight:200 700;font-display:swap;
  src:url('/fonts/oswald-latin.woff2') format('woff2')}
@font-face{font-family:'Permanent Marker';font-style:normal;font-weight:400;font-display:swap;
  src:url('/fonts/permanent-marker-latin.woff2') format('woff2')}
:root{
  --blue:#11409c; --blue-br:#2e6ee8; --ink:#0b0d10; --muted:#4d525c;
  --ui:'Oswald',-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  --display:'Anton','Arial Black','Helvetica Neue',sans-serif;
  --script:'Permanent Marker',cursive;
  --border:#dfe3ea; --bg:#f5f7fa; --ok:#177245; --warn:#9c3a11;
}
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:var(--ui);color:var(--ink);background:var(--bg);line-height:1.55}
a{color:var(--blue-br)}
header{background:#fff;border-bottom:1px solid var(--border);padding:14px 20px;
  display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.wordmark{text-decoration:none}
.wordmark .top{display:block;font-family:var(--display);font-size:20px;letter-spacing:2px;color:var(--ink);text-transform:uppercase}
.wordmark .bottom{display:block;font-family:var(--script);font-size:16px;color:var(--blue-br);letter-spacing:3px;margin-top:2px}
.call{font-weight:700;letter-spacing:1px;text-decoration:none;color:var(--ink);font-size:15px}
.call b{color:var(--blue)}
main{max-width:760px;margin:0 auto;padding:28px 16px 80px}
h1{font-family:var(--display);font-weight:400;font-size:clamp(30px,6vw,44px);
  letter-spacing:1px;text-transform:uppercase;line-height:1.08}
h1 .script{display:block;font-family:var(--script);text-transform:none;color:var(--blue-br);
  font-size:clamp(22px,4.4vw,30px);letter-spacing:2px;margin-top:6px}
.sub{color:var(--muted);margin:10px 0 26px;font-size:15px}
.step{background:#fff;border:1px solid var(--border);border-radius:12px;padding:20px;margin-bottom:18px}
.step h2{font-family:var(--display);font-weight:400;font-size:22px;letter-spacing:1px;
  text-transform:uppercase;margin-bottom:4px}
.step .hint{color:var(--muted);font-size:13.5px;margin-bottom:14px}
.step.locked{opacity:.45;pointer-events:none}
.svc{display:flex;gap:10px;align-items:flex-start;border:1px solid var(--border);
  border-radius:8px;padding:10px 12px;margin-bottom:8px;cursor:pointer;background:#fff}
.svc:has(input:checked){border-color:var(--blue-br);background:#f2f6ff}
.svc input{margin-top:4px}
.svc .lbl{font-weight:600}
.grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}
@media(max-width:560px){.grid{grid-template-columns:1fr}}
label.f{display:block;font-size:13px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--muted)}
input[type=text],input[type=number],input[type=email],input[type=tel],select,textarea{
  width:100%;padding:11px 12px;border:1px solid var(--border);border-radius:8px;
  font-family:var(--ui);font-size:15px;margin-top:4px;background:#fff}
.btn{display:inline-block;font-family:var(--ui);font-weight:700;letter-spacing:1.2px;
  text-transform:uppercase;font-size:13px;border-radius:8px;padding:13px 26px;
  border:0;cursor:pointer;transition:.15s;background:var(--blue);color:#fff;margin-top:14px}
.btn:hover{background:var(--blue-br)}
.btn:disabled{background:#9aa7bd;cursor:not-allowed}
/* R63.J2 — every control a thumb has to hit is at least 44px tall, the figure
   Apple's HIG names and the one the field PWA's top bar was measured against.
   SCOPED TO THE NEW CONTROLS rather than applied to `.btn` and `input`
   globally: widening those would change how the LIVE booking page LOOKS, and a
   send-permission fix is not a licence to restyle a funnel that is taking real
   bookings. Measured before writing this: `.btn` renders ~42px and an input
   ~42px, so both were under by a couple of pixels rather than wildly wrong. */
.tap44{min-height:44px}
/* R63.J4 — the TEST badge. Loud on purpose: this page's screenshots are used
   as evidence, and a fixture run must never be mistaken for the live funnel by
   somebody reading one later. Rendered only when the SERVER says the tenant's
   own `is_test` column is set. */
.testbadge{position:fixed;top:0;left:0;right:0;z-index:9999;
  background:#b91c1c;color:#fff;font-family:var(--ui);font-weight:700;
  letter-spacing:2px;text-transform:uppercase;font-size:12px;
  min-height:44px;display:flex;align-items:center;justify-content:center;
  box-shadow:0 1px 6px rgba(0,0,0,.3)}
body.has-testbadge{padding-top:44px}
.price{font-family:var(--display);font-size:40px;letter-spacing:1px;color:var(--blue);margin:8px 0 2px}
.pnote{color:var(--muted);font-size:13.5px}
.slots{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:8px;margin-top:8px}
/* T29 · the date chips. Narrower than a slot because a date is a shorter
   string than a date-and-time was, which is the whole point of asking for it
   first: more of the calendar is visible at once. */
.days{display:grid;grid-template-columns:repeat(auto-fill,minmax(116px,1fr));gap:8px;margin-top:8px}
.day{border:1px solid var(--border);border-radius:8px;padding:9px 10px;background:#fff;
  cursor:pointer;font-size:14px;text-align:left;line-height:1.3;font-family:var(--ui)}
.day .dow{display:block;font-size:11.5px;letter-spacing:.7px;text-transform:uppercase;color:var(--muted)}
.day .n{display:block;font-size:11.5px;color:var(--muted);margin-top:2px}
.day.sel{border-color:var(--blue-br);background:#f2f6ff;font-weight:700}
.day.sel .dow,.day.sel .n{color:var(--blue)}
/* A full day is SHOWN and refused, not hidden. A silently missing Tuesday
   reads as "we are closed Tuesdays", which is a different and false claim. */
.day:disabled{cursor:not-allowed;background:#f5f7fa;color:#9aa7bd;border-style:dashed}
.day:disabled .dow,.day:disabled .n{color:#9aa7bd}
.moredates{background:none;border:0;padding:6px 0;margin-top:10px;cursor:pointer;
  font-family:var(--ui);font-size:13.5px;color:var(--blue-br);text-decoration:underline}
.slot{border:1px solid var(--border);border-radius:8px;padding:10px;background:#fff;
  cursor:pointer;font-size:14px;text-align:left}
.slot.sel{border-color:var(--blue-br);background:#f2f6ff;font-weight:700}
.msg{border-radius:8px;padding:12px 14px;margin-top:12px;font-size:14.5px;display:none}
.msg.err{display:block;background:#fdf0ec;border:1px solid #e8c4b4;color:var(--warn)}
.msg.ok{display:block;background:#eef7f1;border:1px solid #bfe0cc;color:var(--ok)}
.done{border-left:5px solid var(--ok)}
.done .big{font-family:var(--script);color:var(--ok);font-size:24px;margin-bottom:8px}
.countdown{font-weight:700;color:var(--warn)}
.held{background:#eef7f1;border:1px solid #bfe0cc;border-radius:8px;padding:10px 14px;
  font-size:14px;margin-bottom:14px}
/* the shared agreement module's own classes (agreement.js) */
.doc{background:#fff;border:1px solid var(--border);border-radius:12px;
  padding:22px 24px;white-space:pre-wrap;font-size:13.5px;line-height:1.6;
  max-height:52vh;overflow-y:auto;margin-bottom:20px}
/* PARTNER.F2 (owner, 2026-09-23): the clauses of a legal text are drawn as
   one <p class="clause"> each, so a broker reads eight paragraphs and not a
   wall. The gap is what makes them separate; `white-space:pre-wrap` above
   stays, because it is still what preserves a newline INSIDE a clause. */
.doc p.clause{margin:0 0 0.85em}
.doc p.clause:last-child{margin-bottom:0}
.card{background:#fff;border:1px solid var(--border);border-radius:12px;padding:18px 20px;margin-bottom:16px}
.card h2{font-family:var(--display);font-weight:400;font-size:18px;letter-spacing:1px;
  text-transform:uppercase;margin-bottom:10px}
.s11{border-left:5px solid var(--warn)}
.chk{display:flex;gap:10px;align-items:flex-start;margin:12px 0;font-size:14px}
.chk input{margin-top:4px}
.note{color:var(--muted);font-size:13px;margin-top:8px}
.mono{font-family:ui-monospace,monospace;font-size:12px;color:var(--muted);word-break:break-all}
.done .big{font-family:var(--display);font-size:22px;color:var(--ok);text-transform:uppercase;letter-spacing:1px}
footer{max-width:760px;margin:0 auto;padding:0 16px 40px;color:var(--muted);font-size:13px}
/* ─────────────────────────────────────────────────────────────────────────
   CSS.F1 — utility classes replacing inline style="" attributes.

   These exist so the booking vhost's CSP can be written `style-src 'self'`
   with NO 'unsafe-inline'. A style attribute cannot carry a nonce, so as long
   as one existed the directive had to allow ALL inline style — which is most
   of what style-src protects against.

   The classes are deliberately dull and single-purpose. `.is-hidden` is
   toggled by JS through `element.style.display`, which is CSSOM and is NOT
   restricted by style-src; an inline property set that way still wins over
   this class, so the existing show/hide code is unchanged.
   ───────────────────────────────────────────────────────────────────────── */
.is-hidden{display:none}
.span-all{grid-column:1/-1}
.mt-8{margin-top:8px}
.mt-10{margin-top:10px}
.mt-12{margin-top:12px}
.mt-14{margin-top:14px}
.w-160{max-width:160px}
.sub-label{font-weight:400;font-size:13px}
.no-underline{text-decoration:none}
/* The Phase E honeypot: off-screen rather than display:none, because some
   form-fillers deliberately skip display:none fields. */
.hp-field{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* BOOK.F9 — the picker tag. In the stylesheet, never an inline
   style attribute: CSS.F1 removed 'unsafe-inline' from style-src and
   an inline style here would be silently dropped by the CSP. */
.svc-tag{display:inline-block;margin-left:8px;padding:1px 8px;
  border:1px solid #c9d3e0;border-radius:999px;background:#eef2f7;
  color:#425466;font-size:12.5px;font-weight:600;vertical-align:middle;
  white-space:nowrap}

textarea{resize:vertical;min-height:64px;font-family:var(--ui)}
/* The one OPTIONAL field on a step where everything else is required. It must read as permission to skip, not as a second label. */
.opt{font-weight:400;text-transform:none;letter-spacing:0;opacity:.7}

/* JOUR.F4 (2026-09-08): the agreement widget's inline style attributes, moved
   here because the host's CSP (style-src 'self') refuses style attributes —
   the "Accepted" panel was visible before any acceptance. */
.init{max-width:120px}
.done{margin-top:20px}
.btn.alt{background:#4d525c}
.btn.finish{margin-left:8px}
