:root {
  --brand: #2563eb;
  --brand-600: #1d4ed8;
  --brand-050: #eff4ff;
  --ink: #0b1220;
  --ink-2: #475569;
  --ink-3: #94a3b8;
  --line: #e6eaf2;
  --line-2: #eef1f7;
  --bg: #f6f8fc;
  --card: #ffffff;
  --surface: #ffffff;   /* controls that sit on a card: inputs, slots, ghost buttons */
  --ok: #16a34a;
  --danger: #ef4444;
  --radius: 16px;
  --radius-sm: 10px;
  --shadow: 0 1px 2px rgba(16, 24, 40, 0.04), 0 8px 30px rgba(16, 24, 40, 0.06);
  --shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06);
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Inter, system-ui, sans-serif;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: rgba(37, 99, 235, 0.12); }
html, body { margin: 0; padding: 0; }
html {
  /* Stop iOS inflating text in landscape, and honour the notch cutouts. */
  -webkit-text-size-adjust: 100%;
}
body {
  font-family: var(--font);
  color: var(--ink);
  background: var(--bg);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}
a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ---------- layout ---------- */
.wrap { max-width: 960px; margin: 0 auto; padding: 24px; padding-bottom: calc(24px + env(safe-area-inset-bottom)); }
.center {
  min-height: 100vh;
  min-height: 100dvh; /* iOS: 100vh is the WRONG height while the URL bar is showing */
  display: grid; place-items: center;
  padding: 24px; padding-bottom: calc(24px + env(safe-area-inset-bottom));
}

/* Logo + wordmark. Both are optional per deployment (brand.js removes the element
   when there is nothing to show), so a logo that already contains the name simply
   leaves BRAND_NAME unset. */
.brandbar { display: flex; align-items: center; gap: 10px; margin-bottom: 24px; }
.brandbar img { height: 24px; width: auto; border-radius: 6px; }
.brandbar b { font-size: 15px; font-weight: 600; color: var(--ink); }
.brandbar .muted { color: var(--ink-3); font-weight: 500; }

/* Brand lockup: the mark and the name sit on ONE row and read as one object.
   The monogram carries "JP", so the word beside it completes the name rather
   than repeating it. Set in caps with open tracking, it reads as a designed
   wordmark instead of a stray line of text, and stays legible at 15px. */
.lockup { display: flex; align-items: center; gap: 11px; margin: 4px 0 20px; }
.lockup img {
  height: 38px; width: 38px; border-radius: 12px; flex: none;
  box-shadow: 0 2px 10px rgba(37, 99, 235, .32);
}
.lockup-name {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--ink);
  /* the tracking adds space after the final letter; pull it back so the lockup
     stays optically centred */
  margin-right: -.17em;
}
/* Inside the hero card the lockup is a letterhead, so it centres with the rest
   of the card instead of sitting alone on a half-empty row above it. */
.lockup-center { justify-content: center; margin: 0; }

/* Public-facing centered brand header + hero */
.pub-header { display: flex; flex-direction: column; align-items: center; gap: 10px; text-align: center; margin: 12px 0 22px; }
.pub-header img { height: 46px; width: auto; border-radius: 13px; }
.pub-header .wordmark { font-size: 17px; font-weight: 600; color: var(--ink); letter-spacing: -.01em; }
/* The assistant's ask box. It sits in the hero because it is the proof of the
   claim the heading makes: there is a model behind this, not just a form. */
.askbox { display: flex; gap: 8px; max-width: 460px; margin: 18px auto 0; }
.askbox input {
  flex: 1; min-width: 0;
  border-radius: 999px; padding: 12px 18px;
  background: var(--surface);
}
.askbox .btn { border-radius: 999px; padding-left: 20px; padding-right: 20px; flex: none; }
.askanswer {
  max-width: 460px; margin: 12px auto 0;
  padding: 14px 16px;
  border-radius: 14px;
  background: var(--brand-050);
  border: 1px solid var(--line);
  color: var(--ink);
  font-size: 14.5px; line-height: 1.5; text-align: left;
}
.askdots { display: inline-flex; gap: 5px; align-items: center; height: 20px; }
.askdots i {
  width: 7px; height: 7px; border-radius: 999px; background: var(--brand);
  animation: askblink 1.1s ease-in-out infinite;
}
.askdots i:nth-child(2) { animation-delay: .18s; }
.askdots i:nth-child(3) { animation-delay: .36s; }
@keyframes askblink { 0%, 80%, 100% { opacity: .25; } 40% { opacity: 1; } }

.tagline { font-style: italic; color: var(--ink-2); font-size: 15px; line-height: 1.5; max-width: 460px; margin: 0 auto; }
.tagline b { color: var(--brand-600); font-weight: 600; font-style: normal; }
.warm { color: var(--ink-2); font-size: 15px; line-height: 1.55; }

/* The hold card. It carries the option most visitors need, so it is the only
   thing on the page allowed to shout: accent border, tinted ground, own tag. */
.card.featured {
  border: 1.5px solid var(--brand);
  background: linear-gradient(180deg, var(--brand-050) 0%, var(--card) 78%);
  box-shadow: 0 1px 2px rgba(37, 99, 235, .08), 0 10px 30px rgba(37, 99, 235, .10);
}
.featured-tag {
  display: inline-block;
  background: var(--brand);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .01em;
  padding: 4px 10px;
  border-radius: 999px;
}
/* Three-step explainer. Replaces a paragraph of mechanics with something a
   visitor can take in at a glance. Wraps to a column on narrow screens. */
.steps { display: flex; gap: 10px; list-style: none; margin: 16px 0 0; padding: 0; }
.steps li {
  flex: 1 1 0;
  display: flex;
  align-items: flex-start;
  gap: 9px;
  font-size: 14px;
  line-height: 1.4;
  color: var(--ink-2);
}
.steps .n {
  flex: none;
  width: 22px; height: 22px;
  border-radius: 999px;
  background: var(--brand);
  color: #fff;
  font-size: 12px; font-weight: 700;
  display: grid; place-items: center;
  margin-top: 1px;
}
.steps.stacked { flex-direction: column; gap: 12px; }
@media (max-width: 640px) { .steps { flex-direction: column; gap: 12px; } }

.dur-row { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.dur-label { font-size: 13px; font-weight: 600; color: var(--ink-2); margin-top: 18px; }
.dur { flex: 1 1 72px; text-align: center; justify-content: center; padding-left: 10px; padding-right: 10px; }
.dur:hover { text-decoration: none; }
.sec-head { margin: 0 0 12px 2px; }
.sec-label {
  font-size: 13px;
  font-weight: 700;
  color: var(--ink-2);
  letter-spacing: .04em;
  text-transform: uppercase;
}
.sec-sub { font-size: 14px; color: var(--ink-3); margin-top: 3px; }
.eyebrow-soft { font-size: 13px; font-weight: 600; color: var(--brand); letter-spacing: .01em; }

/* ---------- card ---------- */
.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.card-pad { padding: 28px; }
.split { display: grid; grid-template-columns: 320px 1fr; }
.split .aside { border-right: 1px solid var(--line); padding: 28px; }
/* The stacked/reordered phone layout replaces both of these; see the phone
   section below, where .aside becomes display:contents. */

/* ---------- typography ---------- */
h1 { font-size: 26px; letter-spacing: -0.02em; margin: 0 0 6px; }
h2 { font-size: 20px; letter-spacing: -0.01em; margin: 0 0 4px; }
h3 { font-size: 15px; margin: 0 0 8px; color: var(--ink-2); }
.eyebrow { font-size: 12px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--brand); }
.muted { color: var(--ink-2); }
.dim { color: var(--ink-3); font-size: 14px; }
.meta { display: flex; align-items: center; gap: 8px; color: var(--ink-2); font-size: 14px; margin: 6px 0; }
.meta svg { flex: none; opacity: 0.7; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font: inherit; font-weight: 600; font-size: 15px;
  padding: 11px 18px; border-radius: var(--radius-sm);
  background: var(--brand); color: #fff; border: 1px solid var(--brand);
  cursor: pointer; transition: background .15s, transform .05s;
}
.btn:hover { background: var(--brand-600); text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.55; cursor: default; }
.btn.ghost { background: var(--surface); color: var(--ink); border-color: var(--line); }
.btn.ghost:hover { background: var(--bg); }
.btn.danger { background: var(--danger); border-color: var(--danger); }
.btn.danger:hover { background: #dc2626; }
.btn.block { width: 100%; }
.btn.sm { padding: 8px 12px; font-size: 14px; }

/* ---------- forms ---------- */
label { display: block; font-size: 13px; font-weight: 600; color: var(--ink-2); margin: 14px 0 6px; }
input, select, textarea {
  /* 16px is not cosmetic: below it, iOS zooms the page in on focus and the
     visitor has to pinch back out to carry on. */
  width: 100%; font: inherit; font-size: 16px; color: var(--ink);
  padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface); transition: border-color .15s, box-shadow .15s;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-050);
}
textarea { min-height: 84px; resize: vertical; }
.row { display: flex; gap: 12px; }
.row > * { flex: 1; }
.field-hint { font-size: 12px; color: var(--ink-3); margin-top: 4px; }

/* ---------- day navigator (public booking) ---------- */
.daynav { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 20px 0 6px; }
.daynav-label { font-weight: 700; font-size: 16px; letter-spacing: -0.01em; text-align: center; flex: 1; }
.daynav-btn { width: 50px; height: 50px; flex: none; display: inline-flex; align-items: center; justify-content: center;
  border: 2px solid var(--brand); background: var(--brand-050); border-radius: 14px; cursor: pointer;
  font-size: 26px; font-weight: 800; line-height: 1; color: var(--brand-600); box-shadow: var(--shadow-sm); transition: all .12s; }
.daynav-btn:hover:not(:disabled) { background: var(--brand); color: #fff; transform: translateY(-1px); box-shadow: 0 6px 16px rgba(37,99,235,.28); }
.daynav-btn:active:not(:disabled) { transform: translateY(0); }
.daynav-btn:disabled { opacity: .3; cursor: default; box-shadow: none; }
.noslots { padding: 28px 0; text-align: center; color: var(--ink-3); font-size: 15px; }

/* ---------- tooltips (data-tip on any element) ---------- */
[data-tip] { position: relative; }
[data-tip]:hover::after {
  content: attr(data-tip); position: absolute; bottom: calc(100% + 9px); left: 50%; transform: translateX(-50%);
  background: #0b1220; color: #fff; font-size: 12px; font-weight: 500; line-height: 1.35; text-align: center;
  padding: 7px 10px; border-radius: 8px; width: max-content; max-width: 230px; z-index: 60; pointer-events: none;
  box-shadow: 0 6px 20px rgba(11,18,32,.28); white-space: normal;
}
[data-tip]:hover::before {
  content: ''; position: absolute; bottom: calc(100% + 4px); left: 50%; transform: translateX(-50%);
  border: 5px solid transparent; border-top-color: #0b1220; z-index: 60; pointer-events: none;
}
[data-tip].tip-below:hover::after { bottom: auto; top: calc(100% + 9px); }
[data-tip].tip-below:hover::before { bottom: auto; top: calc(100% + 4px); border-top-color: transparent; border-bottom-color: #0b1220; }
/* touch devices: tooltips are hover-based, so hide the arrow cue there is fine */

/* ---------- cookie consent banner ---------- */
.cookiebar { position: fixed; left: 12px; right: 12px; bottom: 12px; max-width: 620px; margin: 0 auto;
  background: #0b1220; color: #fff; border-radius: 14px; padding: 13px 16px; display: flex; align-items: center;
  gap: 14px; justify-content: space-between; flex-wrap: wrap; box-shadow: 0 12px 34px rgba(11,18,32,.32);
  z-index: 90; font-size: 14px; line-height: 1.4; }
.cookiebar-actions { display: flex; gap: 8px; flex: none; }
.cookiebar .btn.ghost { background: transparent; color: #fff; border-color: rgba(255,255,255,.32); }
.cookiebar .btn.ghost:hover { background: rgba(255,255,255,.08); }

/* ---------- mobile ---------- */
/* ---------- phones ----------
   The booking page reorders on a phone. On a desktop the sidebar explains the
   meeting next to the picker; stacked, that same sidebar is a full screen of
   reading before the visitor reaches a single time. So the sidebar splits: what
   you are booking stays on top, the times come next, and the explainer follows
   underneath. `display: contents` drops the sidebar box so its two halves
   become siblings of the picker and can be ordered independently. */






/* ---------- slots / calendar ---------- */
.days { display: flex; flex-direction: column; gap: 22px; }
.day h3 { position: sticky; top: 0; background: var(--card); padding: 4px 0; z-index: 1; }
.slotgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 10px; }
.slot {
  padding: 12px 8px; text-align: center; font-weight: 600; font-size: 15px;
  /* A <button> does not inherit colour: without this it keeps the user-agent
     default and turns unreadable the moment the surface goes dark. */
  font-family: inherit; color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface);
  cursor: pointer; transition: border-color .12s, background .12s;
}
.slot:hover { border-color: var(--brand); color: var(--brand); }
.slot.active { background: var(--brand); border-color: var(--brand); color: #fff; }

/* ---------- loading skeletons ----------
   A grey ghost of the content that is coming reads as progress; the word
   "Loading" reads as a wait. */
@keyframes skel-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
.skel { background: var(--line-2); border-radius: 8px; animation: skel-pulse 1.4s ease-in-out infinite; }
.skel-line { height: 14px; margin-bottom: 12px; }
.skel-block { height: 120px; border-radius: var(--radius-sm); }
.skel-slots { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 10px; }
.skel-slots i {
  display: block; height: 46px; border-radius: var(--radius-sm);
  background: var(--line-2); animation: skel-pulse 1.4s ease-in-out infinite;
}
.skel-slots i:nth-child(2) { animation-delay: .1s; }
.skel-slots i:nth-child(3) { animation-delay: .2s; }
.skel-slots i:nth-child(4) { animation-delay: .3s; }
.skel-slots i:nth-child(5) { animation-delay: .4s; }
.skel-slots i:nth-child(6) { animation-delay: .5s; }

/* ---------- motion ----------
   One quiet entrance, and a press state that acknowledges the tap. Anyone who
   has asked their OS to calm down gets none of it. */
@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.card { animation: rise .28s cubic-bezier(.2, .7, .3, 1) both; }
.slot:active, .btn:active { transform: scale(.97); }
.slot { transition: border-color .12s, background .12s, transform .08s; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
  .slot:active, .btn:active { transform: none; }
}

/* ---------- pills / badges ---------- */
.pill { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600;
  padding: 4px 10px; border-radius: 999px; background: var(--brand-050); color: var(--brand-600); }
.badge { font-size: 12px; font-weight: 600; padding: 3px 9px; border-radius: 999px; }
.badge.ok { background: #ecfdf3; color: #067647; }
.badge.cancelled { background: #fef3f2; color: #b42318; }

/* ---------- misc ---------- */
.notice { padding: 12px 14px; border-radius: var(--radius-sm); font-size: 14px; margin: 14px 0; }
.notice.err { background: #fef3f2; color: #b42318; border: 1px solid #fecdca; }
.notice.ok { background: #ecfdf3; color: #067647; border: 1px solid #a6f4c5; }
.spinner { width: 18px; height: 18px; border: 2px solid rgba(255,255,255,.5); border-top-color: #fff;
  border-radius: 50%; animation: spin .7s linear infinite; display: inline-block; }
.btn.ghost .spinner, .spinner.dark { border-color: rgba(37,99,235,.25); border-top-color: var(--brand); }
@keyframes spin { to { transform: rotate(360deg); } }
.hidden { display: none !important; }
.stack > * + * { margin-top: 10px; }
hr.sep { border: none; border-top: 1px solid var(--line-2); margin: 20px 0; }
.list { border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.list .item { padding: 14px 16px; border-bottom: 1px solid var(--line-2); display: flex; justify-content: space-between; gap: 12px; align-items: center; }
.list .item:last-child { border-bottom: none; }
.tabs { display: inline-flex; gap: 4px; background: var(--line-2); padding: 4px; border-radius: 10px; margin-bottom: 16px; }
.tabs button { border: none; background: transparent; font: inherit; font-weight: 600; font-size: 14px;
  padding: 7px 14px; border-radius: 7px; cursor: pointer; color: var(--ink-2); }
.tabs button.active { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-sm); }
.topbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 22px; }
.navlinks { display: flex; gap: 6px; }
.navlinks a { padding: 8px 12px; border-radius: 8px; font-weight: 600; font-size: 14px; color: var(--ink-2); }
.navlinks a.active, .navlinks a:hover { background: var(--surface); color: var(--ink); text-decoration: none; box-shadow: var(--shadow-sm); }

/* ============================================================================
   PHONE LAYOUT
   Kept at the very end on purpose: several of these override base rules that
   are declared further up (.slotgrid especially), and at equal specificity the
   later rule wins. Putting them anywhere else silently loses.
   ============================================================================ */

@media (max-width: 760px) {
  .split { display: flex; flex-direction: column; }
  .split .aside { display: contents; }
  .split .aside-head { order: 1; padding: 20px 20px 4px; }
  .split .aside-body { order: 3; padding: 0 20px 20px; }
  .split > .card-pad { order: 2; border-top: 1px solid var(--line-2); margin-top: 14px; }
  .split .aside-body:not(:empty) { border-top: 1px solid var(--line-2); padding-top: 18px; margin-top: 4px; }
}

@media (max-width: 680px) {
  .wrap { padding: 16px; padding-bottom: calc(20px + env(safe-area-inset-bottom)); }
  .card-pad { padding: 20px; }
  .row { flex-direction: column; gap: 0; }
  .row > * { width: 100%; }
  .topbar { flex-direction: column; align-items: flex-start; gap: 12px; }
  /* ...except inside the booking steps, where the heading and its Back button
     belong on one line. Stacked, Back claims a whole row for itself. */
  #stepSlots .topbar, #stepForm .topbar {
    flex-direction: row; align-items: center; justify-content: space-between; gap: 10px;
  }
  #stepForm .topbar h2 { margin: 0; }
  .navlinks { flex-wrap: wrap; gap: 4px; }
  .navlinks a { padding: 7px 10px; font-size: 13px; }
  h1 { font-size: 22px; }
  .pub-header img { height: 40px; }
  .askbox { flex-direction: column; }
  .askbox .btn { width: 100%; }
  .lockup { margin: 2px 0 14px; }
  .lockup img { height: 34px; width: 34px; }
  .lockup-name { font-size: 14px; letter-spacing: .15em; margin-right: -.15em; }
  .tagline { font-size: 14px; }

  /* Every tap target clears 44px, the smallest thing a thumb hits reliably. */
  .slotgrid { grid-template-columns: repeat(3, 1fr); gap: 8px; }
  .slot { min-height: 48px; display: flex; align-items: center; justify-content: center; padding: 10px 4px; font-size: 15px; }
  .btn { min-height: 46px; }
  .btn.sm { min-height: 40px; }
  /* .btn.sm above is more specific than .dur, so match its specificity or the
     duration switch ends up a 40px target. */
  .btn.dur { min-height: 46px; flex: 1 1 0; }
  .daynav { margin: 16px 0 4px; }
  .daynav-btn { width: 46px; height: 46px; font-size: 24px; }
  .daynav-label { font-size: 15px; }
  .steps li { font-size: 15px; }
  .featured-tag { font-size: 11px; }

  /* The confirm button is the last thing on a long form: keep it clear of the
     home indicator so the gesture bar never sits on top of it. */
  #bookForm .btn.block { margin-bottom: env(safe-area-inset-bottom); }
  [data-tip]:hover::after, [data-tip]:hover::before { display: none; } /* avoid stuck tooltips on tap */
}

/* Only the genuinely tiny screens drop to two columns; an iPhone SE at 375px
   still fits three comfortably, and three means less scrolling. */
@media (max-width: 340px) {
  .slotgrid { grid-template-columns: repeat(2, 1fr); }
  .wrap { padding: 12px; }
  .card-pad { padding: 16px; }
  .split .aside-head { padding: 16px 16px 4px; }
  .split .aside-body { padding: 0 16px 16px; }
}

/* ============================================================================
   DARK MODE
   Last in the file, and deliberately token-only. Declared at the top it lost
   every ordering fight with the base rules below it, and slots rendered white
   text on white. Because every surface reads from a variable, recolouring the
   variables is the entire change.
   ============================================================================ */
@media (prefers-color-scheme: dark) {
  :root {
    --brand: #5b8cff;
    --brand-600: #7aa2ff;
    --brand-050: #1a2540;
    --ink: #e9edf6;
    --ink-2: #a7b2c6;
    --ink-3: #737f96;
    --line: #2a3450;
    --line-2: #212a44;
    --bg: #0c111e;
    --card: #151c2e;
    --surface: #101827;
    --shadow: 0 1px 2px rgba(0, 0, 0, .5), 0 10px 32px rgba(0, 0, 0, .40);
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .5);
  }
  .card.featured { background: linear-gradient(180deg, #1a2540 0%, var(--card) 78%); }
  .pill { background: var(--brand-050); color: var(--brand-600); }
  .slot:hover { background: var(--brand-050); }
}
