/* =============================================================================
   AVB Financial Solutions — appointment booking
   Design tokens taken from angelavanbreda.co.za:
     brand orange   #FF6700   used sparingly, the way the logo uses it
     greys          #333 / #5B5B5B / #757575 / #878787
     type           Montserrat body, Poppins for uppercase headings
     radii          4–5px, never pillowy
   Light only, deliberately: the brand has no dark treatment and a financial
   services site that flips to dark reads as someone else's template.
   ============================================================================= */

:root {
  /* The brand orange, for large display type, rules and borders where it is
     decorative. #ff6700 on white measures 2.92:1 - fine for a 3px rule, far
     below the 4.5:1 WCAG AA needs for body text or a button label. */
  --orange: #ff6700;
  /* Used wherever the orange has to carry meaning as TEXT or a control:
     links, buttons, eyebrows. #b0480a on white measures 4.6:1. */
  --orange-ink: #b0480a;
  --orange-dark: #8f3a06;
  --orange-tint: #fff4ec;

  --ink: #333333;
  --ink-soft: #5b5b5b;
  --grey: #757575;
  --grey-light: #878787;

  --page: #ffffff;
  --panel: #ffffff;
  --wash: #f6f6f6;
  --rule: #e4e4e4;
  --rule-strong: #cfcfcf;

  --radius: 4px;
  --radius-lg: 6px;

  --body: 'Montserrat', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --display: 'Poppins', 'Helvetica Neue', Helvetica, Arial, sans-serif;

  --shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-lift: 0 6px 18px rgba(0, 0, 0, 0.08);
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--page);
  color: var(--ink-soft);
  font: 400 15px/1.65 var(--body);
}

a { color: var(--orange-ink); text-decoration: none; }
a:hover { color: var(--orange-dark); text-decoration: underline; }

/* ---- type ---------------------------------------------------------------- */
h1, h2, h3, h4 { color: var(--ink); margin: 0 0 12px; }

h1 {
  font-family: var(--display);
  font-weight: 700;
  font-size: 34px;
  line-height: 1.25;
  letter-spacing: -0.01em;
}
h2 { font-family: var(--display); font-weight: 600; font-size: 22px; line-height: 1.4; margin-top: 30px; }
h3 { font-family: var(--display); font-weight: 600; font-size: 16px; line-height: 1.45; }

/* The signature move from the site: uppercase, wide-tracked section labels. */
.eyebrow {
  display: block;
  font-family: var(--display);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--orange-ink);
  margin-bottom: 8px;
}
.muted { color: var(--grey); }
.small { font-size: 12.5px; line-height: 1.55; }
.error { color: #c0392b; }
.warn { color: #a35400; }
.ok { color: #1e7a4a; font-weight: 600; }

/* ---- header -------------------------------------------------------------- */
.topbar {
  display: flex; align-items: center; gap: 26px; flex-wrap: wrap;
  padding: 16px 30px;
  background: var(--page);
  border-bottom: 1px solid var(--rule);
}
.topbar .logo { display: flex; align-items: center; }
.topbar .logo img { height: 46px; width: auto; display: block; }
.topbar nav { display: flex; align-items: center; gap: 26px; margin-left: auto; flex-wrap: wrap; }
.topbar nav a {
  font-family: var(--display);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
}
.topbar nav a:hover { color: var(--orange-ink); text-decoration: none; }
.topbar .who {
  color: var(--grey-light); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
}

/* A thin orange rule under the header, echoing the stroke in the logo. */
.brandrule { height: 3px; background: var(--orange); }

/* ---- booking progress -----------------------------------------------------
   Sits directly under the header, on the brand's warm tint so it reads as part
   of the frame rather than a widget dropped on the page. The track is a proper
   bar, the markers are large enough to be read as buttons with a state, and
   the current step gets a halo so a glance lands on it. */
.progressrule {
  background: var(--orange-tint);
  border-bottom: 1px solid #f3d9c3;
}
.progressrule-inner { max-width: 1000px; margin: 0 auto; padding: 22px 26px 18px; }

.ptrack {
  position: relative;
  height: 8px;
  border-radius: 999px;
  background: #f0d5bf;
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.06);
  /* The dots are 30px wide and centred on the ends of the track, so the track
     is pulled in by half a dot to keep them inside the content edge. */
  margin: 0 15px;
}
.pfill {
  display: block; height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, #ff8a3d, var(--orange));
  box-shadow: 0 1px 3px rgba(255, 103, 0, 0.35);
  transition: width 320ms ease;
}

.pmarks {
  list-style: none;
  padding: 0;
  /* The same 15px inset as the track, so a marker's left: N% lands on the
     exact point the fill's width: N% reaches - dot and bar share one ruler.
     The marks are placed, not flowed, so the list needs its own height. */
  margin: 0 15px; height: 34px;
  /* The track is positioned and would otherwise paint over the dots that
     straddle it; lift the marks above it so the ticks and numbers show. */
  position: relative; z-index: 1;
}
.pmarks li {
  position: absolute; top: -19px;         /* lifts the dot to straddle the track */
  transform: translateX(-50%);            /* centre the dot on its point */
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  width: max-content; max-width: 40vw;
  font-family: var(--display); font-size: 10.5px; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--grey-light);
  text-align: center;
}
/* The end labels hang inward from their dots, so nothing runs off the edge. */
.pmarks li:first-child { left: 0 !important; transform: translateX(-15px); align-items: flex-start; text-align: left; }
.pmarks li:last-child  { left: auto !important; right: -15px; transform: none; align-items: flex-end; text-align: right; }

.pdot {
  /* Painted after the track (which is positioned), so every dot sits on top of
     the line - not only the current one, whose transform happens to do that. */
  position: relative; z-index: 2;
  width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--page);
  border: 2px solid #e2c3a8;
  font-size: 12px; font-weight: 700; line-height: 1;
  color: var(--grey-light);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
  transition: transform 160ms ease;
}
.pmarks li.done .pdot { background: var(--orange); border-color: var(--orange); color: #fff; font-size: 14px; }
.pmarks li.done { color: var(--grey); }
.pmarks li.now .pdot {
  background: var(--orange); border-color: #fff; color: #fff;
  box-shadow: 0 0 0 3px var(--orange), 0 3px 8px rgba(255, 103, 0, 0.35);
  transform: scale(1.08);
}
.pmarks li.now { color: var(--orange-dark); }
.pmarks li.now .plabel { font-weight: 700; }

@media (max-width: 560px) {
  /* Keep the bar and the dots; drop every label but the one you are on, which
     is the only one a phone has room to say properly. */
  .progressrule-inner { padding: 18px 18px 14px; }
  .pmarks li:not(.now) .plabel { display: none; }
  .pdot { width: 26px; height: 26px; font-size: 11px; }
  .pmarks { margin: 0 13px; height: 30px; }
  .pmarks li { top: -17px; max-width: 60vw; }
  .pmarks li:first-child { transform: translateX(-13px); }
  .pmarks li:last-child  { right: -13px; }
  .ptrack { margin: 0 13px; }
}

main { max-width: 1000px; margin: 0 auto; padding: 34px 26px 70px; }

/* ---- page intro ---------------------------------------------------------- */
.pagehead { margin-bottom: 26px; }
.pagehead p { max-width: 62ch; margin: 0; color: var(--grey); }
/* There is one venue, so it is stated rather than chosen. */
.venueline { margin-top: 10px !important; font-size: 13px; }
.venueline strong { font-family: var(--display); }
.venueline .muted { margin-left: .6em; }

/* ---- surfaces ------------------------------------------------------------ */
.card {
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: 26px;
  margin-bottom: 20px;
  box-shadow: var(--shadow);
}
.card.narrow { max-width: 460px; }
.card.danger { border-color: #d9b4ae; }

.flash {
  background: var(--orange-tint);
  border: 1px solid #f3d3bb;
  border-left: 3px solid var(--orange);
  border-radius: var(--radius);
  padding: 13px 16px;
  margin-bottom: 22px;
  color: var(--ink);
}
.callout {
  background: var(--wash);
  border-left: 3px solid var(--orange);
  padding: 14px 16px;
  border-radius: var(--radius);
}

/* ---- forms --------------------------------------------------------------- */
form label { display: block; margin: 16px 0; font-weight: 500; color: var(--ink); font-size: 13.5px; }
form label.inline {
  display: inline-flex; align-items: center; gap: 9px;
  margin-right: 18px; font-weight: 400; color: var(--ink-soft);
}
label.inline.small { font-size: 12.5px; margin-right: 12px; }

input[type=text], input[type=email], input[type=password], input[type=number],
input[type=datetime-local], input[type=date], input[type=time], input:not([type]),
select, textarea {
  display: block; width: 100%; margin-top: 7px;
  padding: 11px 13px;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  background: var(--page); color: var(--ink);
  font: 400 14px/1.5 var(--body);
  transition: border-color .12s ease, box-shadow .12s ease;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--orange);
  box-shadow: 0 0 0 3px rgba(255, 103, 0, 0.13);
}
input[type=checkbox], input[type=radio] { accent-color: var(--orange); }
.row { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }

button, .btn {
  display: inline-block;
  background: var(--orange-ink);
  color: #fff;
  border: 1px solid var(--orange-ink);
  padding: 11px 22px;
  border-radius: var(--radius);
  font-family: var(--display);
  font-weight: 600; font-size: 12.5px;
  letter-spacing: 0.09em; text-transform: uppercase;
  cursor: pointer;
  transition: background .12s ease, border-color .12s ease;
}
button:hover, .btn:hover {
  background: var(--orange-dark); border-color: var(--orange-dark);
  color: #fff; text-decoration: none;
}
button.secondary, .btn.secondary {
  background: transparent; color: var(--ink); border-color: var(--rule-strong);
}
button.secondary:hover, .btn.secondary:hover {
  background: var(--wash); color: var(--ink); border-color: var(--grey-light);
}
.btn.small, button.small { padding: 7px 14px; font-size: 11px; }

fieldset { border: 1px solid var(--rule); border-radius: var(--radius); padding: 8px 20px 20px; margin: 18px 0; }
legend {
  font-family: var(--display); font-weight: 700; font-size: 11px;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink); padding: 0 8px;
}

/* ---- small components ---------------------------------------------------- */
.pill {
  display: inline-block;
  font-family: var(--display); font-weight: 600;
  font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase;
  background: var(--wash); border: 1px solid var(--rule);
  border-radius: 2px; padding: 3px 9px; color: var(--grey);
}
.chip {
  display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid var(--rule-strong); border-radius: var(--radius);
  padding: 7px 13px; margin: 0 7px 7px 0; background: var(--page);
  font-size: 13px;
}
.state {
  font-family: var(--display); font-weight: 600;
  font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase;
  padding: 4px 10px; border-radius: 2px; border: 1px solid var(--rule-strong); color: var(--grey);
  display: inline-block;
}
.s-confirmed, .s-attended, .s-open { border-color: #9cc7ab; color: #1e7a4a; background: #f2f9f4; }
.s-pending_payment, .s-held, .s-verified { border-color: #f3c9a5; color: #a35400; background: var(--orange-tint); }
.s-cancelled, .s-expired, .s-no_show, .s-closed { color: var(--grey-light); }

.table { width: 100%; border-collapse: collapse; }
.table td { border-bottom: 1px solid var(--rule); padding: 15px 10px; vertical-align: top; font-size: 14px; }
.table tr:last-child td { border-bottom: 0; }
.people { list-style: none; padding: 0; margin: 0; }
.people li { padding: 13px 0; border-bottom: 1px solid var(--rule); }
.people li:last-child { border-bottom: 0; }

/* ---- slot browsing ------------------------------------------------------- */
.day { margin-bottom: 34px; }
.day h2 {
  font-family: var(--display); font-size: 12px; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink);
  margin: 0 0 14px; padding-bottom: 9px; border-bottom: 2px solid var(--rule);
}
.slotgrid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(158px, 1fr)); }
.slot {
  display: flex; flex-direction: column; gap: 3px;
  padding: 15px 16px; color: var(--ink-soft);
  background: var(--page); border: 1px solid var(--rule);
  border-radius: var(--radius);
  transition: border-color .12s ease, box-shadow .12s ease, transform .12s ease;
}
.slot:hover {
  border-color: var(--orange); text-decoration: none;
  box-shadow: var(--shadow-lift); transform: translateY(-1px);
}
.slot .time {
  font-family: var(--display); font-size: 23px; font-weight: 700;
  color: var(--ink); letter-spacing: -0.01em; line-height: 1.15;
}
.slot .muted { font-size: 12px; }
.slot .left {
  font-family: var(--display); font-size: 10px; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--orange-ink); margin-top: 7px;
}
.slot.full { opacity: 0.5; }
.slot.full:hover { border-color: var(--rule); box-shadow: none; transform: none; }
.slot.full .left { color: var(--grey-light); }
.when { color: var(--grey); margin: 6px 0; }

/* Chevrons are drawn, never typed.
   Montserrat and Poppins ship Latin plus General Punctuation; the Arrows block
   (U+2190-21FF) is in no Google Fonts subset, so a literal arrow character falls
   back and renders as a tofu box wherever no fallback font covers it. A rotated
   border cannot miss. */
.backlink::before,
.adminbar a.leave::after {
  content: '';
  display: inline-block;
  width: .42em; height: .42em;
  border-top: 2px solid currentColor;
  border-right: 2px solid currentColor;
}
.backlink { display: inline-flex; align-items: center; }
.backlink::before { margin-right: .55em; transform: rotate(-135deg); }

/* ---- tabs and notes ------------------------------------------------------ */
.tabs { display: flex; gap: 0; border-bottom: 2px solid var(--rule); margin: 26px 0 22px; }
.tab {
  padding: 11px 20px; color: var(--grey);
  font-family: var(--display); font-weight: 600; font-size: 11.5px;
  letter-spacing: 0.12em; text-transform: uppercase;
  border-bottom: 2px solid transparent; margin-bottom: -2px;
}
.tab.on { color: var(--ink); border-bottom-color: var(--orange); }
.tab:hover { text-decoration: none; color: var(--ink); }
.note-block { margin-bottom: 22px; }
.note-block h3 {
  font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--orange-ink); font-weight: 700; margin-bottom: 7px;
}
.note-block ul { margin: 7px 0; padding-left: 19px; }
.note-block li { margin-bottom: 5px; }

/* ---- service picker ------------------------------------------------------ */
/* The box is the container; the label inside it is the service's own row, so a
   sub-option can sit in the same box without nesting one label in another. */
.service {
  border: 1px solid var(--rule); border-radius: var(--radius);
  margin-bottom: 11px; overflow: hidden;
  transition: border-color .12s ease, background .12s ease;
}
.svc-main {
  display: flex; gap: 14px; align-items: flex-start;
  padding: 17px 18px; cursor: pointer;
}
.service:hover { border-color: var(--rule-strong); }
/* Scoped to the service's OWN tick: the box must not light up because the
   sub-option inside it is ticked. */
.service:has(> .svc-main input:checked) { border-color: var(--orange); background: var(--orange-tint); }
.service input { margin-top: 4px; flex: none; }
.svc-body { display: flex; flex-direction: column; gap: 4px; }
.svc-name {
  font-family: var(--display); font-weight: 600; font-size: 15px; color: var(--ink);
}
.svc-price { margin-top: 6px; font-size: 14px; color: var(--ink); }

/* Sub-options. A service offered only as part of the one above it, so it lives
   INSIDE that service's box, under a hairline: a tick with a name beside it, no
   border of its own, no fill, no number badge. Given a box of its own it read
   as a fourth thing to weigh up, which is the opposite of what nesting is for.
   The left padding lines its name up under the parent's, so the two read as one
   decision with a detail under it. */
.subopt {
  display: flex; gap: 10px; align-items: baseline;
  margin: 0; padding: 11px 18px 13px 46px;
  border-top: 1px solid var(--rule);
  cursor: pointer;
}
/* Inside a ticked parent the hairline would otherwise disappear into the tint. */
.service:has(> .svc-main input:checked) .subopt { border-top-color: #f0d4bd; }
.subopt input { flex: none; margin: 0; transform: translateY(1px); }
.subopt-body { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; }
.subopt-name { font-size: 14px; color: var(--ink); font-weight: 600; }
.subopt-price { font-size: 13px; color: var(--ink); }
/* The blurb goes under the name rather than after it, so a long one does not
   push the price onto a line of its own. */
.subopt-blurb { flex: 1 0 100%; }
/* Its parent is unticked, so there is nothing for it to be part of. Kept on the
   page rather than hidden: a row that vanishes and returns is harder to follow
   than one that visibly goes quiet. */
.subopt:has(input:disabled) { opacity: 0.45; cursor: default; }

/* Announced, never drawn - "part of the Health Check" after a sub-option's own
   name, where the page says it with an indent instead. */
.offscreen {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
/* On-site amounts never render through money(); they are visually distinct too,
   so an estimate can never be read as a charge. */
.estimate { color: #a35400; font-weight: 600; }

.totals { border-top: 2px solid var(--rule); margin-top: 20px; padding-top: 15px; }
.totals div { display: flex; justify-content: space-between; gap: 14px; padding: 6px 0; }
.totals div span {
  font-family: var(--display); font-size: 11px; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--grey);
}
.totals div strong { font-family: var(--display); font-size: 16px; color: var(--ink); }
.totals.big div strong { font-size: 21px; }
.lineitems { list-style: none; padding: 0; margin: 0 0 10px; }
.lineitems li {
  display: flex; justify-content: space-between; gap: 14px;
  padding: 11px 0; border-bottom: 1px solid var(--rule); font-size: 14px;
}

/* ---- details page -------------------------------------------------------- */
.cols { display: grid; gap: 22px; grid-template-columns: 1fr minmax(240px, 320px); align-items: start; }
.summary { position: sticky; top: 22px; background: var(--wash); border-color: var(--rule); }
.summary h2 {
  margin-top: 0; font-size: 11px; letter-spacing: 0.16em;
  text-transform: uppercase; font-weight: 700;
}
.prefill {
  display: flex; gap: 14px; align-items: flex-end;
  padding-bottom: 18px; margin-bottom: 4px; border-bottom: 1px solid var(--rule);
}
.prefill label { flex: 1; margin: 0; }
.idfield { margin: 16px 0; }
.idfield .label { font-weight: 500; display: block; font-size: 13.5px; color: var(--ink); }
.masked { display: flex; align-items: center; gap: 12px; margin: 8px 0; flex-wrap: wrap; }
code {
  background: var(--wash); padding: 3px 8px; border-radius: 2px;
  border: 1px solid var(--rule); font-size: 12.5px; color: var(--ink);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.consent {
  border: 1px solid var(--rule); border-radius: var(--radius);
  padding: 18px; margin: 24px 0; background: var(--wash);
}
.consent label.inline { display: flex; gap: 11px; align-items: flex-start; margin-bottom: 13px; }
.cancel { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin-top: 22px; }
.cancel input { width: auto; flex: 1 1 220px; margin-top: 0; }

/* ---- admin --------------------------------------------------------------- */

/* Persistent section bar, on every admin page so moving between sections never
   means going back to an index first. */
/* ---- admin navigation -----------------------------------------------------
   A rail down the left, present on every admin page so moving between sections
   never means going back first. Grouped by what you are trying to do, because
   ten flat items is a list you have to read rather than a menu you can scan. */
.adminshell {
  max-width: 1220px; margin: 0 auto;
  display: grid; grid-template-columns: 208px minmax(0, 1fr);
  align-items: start;
}
.adminside {
  position: sticky; top: 0;
  align-self: start;
  display: flex; flex-direction: column;
  padding: 26px 0 40px 20px;
  border-right: 1px solid var(--rule);
  min-height: 100%;
}
.adminside-label {
  font-family: var(--display); font-weight: 700; font-size: 10px;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--orange); margin-bottom: 14px;
}
.adminside-group {
  font-family: var(--display); font-size: 9.5px; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--grey-light);
  margin: 16px 0 5px;
}
.adminside-group:first-of-type { margin-top: 0; }
.adminside a {
  display: block;
  padding: 7px 12px 7px 10px;
  margin-right: 14px;
  border-radius: var(--radius);
  color: var(--ink-soft);
  font-family: var(--display); font-weight: 600; font-size: 12.5px;
  /* Deliberately not uppercase: these are names you read, and there are enough
     of them that all-caps turns the rail into a wall. */
  border-left: 3px solid transparent;
}
.adminside a:hover { background: var(--wash); color: var(--ink); text-decoration: none; }
.adminside a.on {
  background: var(--orange-tint); color: var(--orange-dark);
  border-left-color: var(--orange);
}
.adminside a.leave {
  margin-top: auto; padding-top: 18px;
  color: var(--grey-light); font-weight: 500; font-size: 12px;
}
.adminside a.leave:hover { background: none; color: var(--orange-ink); }
.adminside a.leave::after { margin-left: .5em; transform: rotate(-45deg); }

/* The rail already gives the page a left margin, so the content pane keeps its
   own padding but drops the centring it uses everywhere else. */
main.adminmain { max-width: none; margin: 0; padding: 26px 26px 70px 30px; }

@media (max-width: 820px) {
  /* No room for a rail: it becomes a scrollable strip above the content, which
     still beats wrapping onto three lines. */
  .adminshell { display: block; }
  .adminside {
    position: static;
    flex-direction: row; align-items: center; gap: 4px;
    overflow-x: auto; padding: 10px 16px;
    border-right: 0; border-bottom: 1px solid var(--rule);
    white-space: nowrap;
  }
  .adminside-label, .adminside-group { display: none; }
  .adminside a { margin-right: 0; border-left: 0; border-bottom: 3px solid transparent; }
  .adminside a.on { border-left: 0; border-bottom-color: var(--orange); }
  .adminside a.leave { margin-top: 0; padding-top: 7px; }
  main.adminmain { padding: 22px 20px 60px; }
}

/* A button that has to sit inside a line of text: it submits, so it cannot be
   an anchor, but it should not look like a control either. */
.linkish {
  display: inline; width: auto;
  background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: var(--orange-ink);
  text-decoration: underline; cursor: pointer;
}
.linkish:hover { color: var(--orange-dark); }

tr.retired td { opacity: 0.55; }
tr.retired td strong { font-weight: 500; }

/* ---- bookings -------------------------------------------------------------
   A day at a time: grouped by date, then by slot time, because that is how the
   desk actually works through them. */
.statrow { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 22px; }
.stat {
  flex: 1 1 110px; background: var(--wash); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: 12px 14px;
  font-family: var(--display); font-size: 10px; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--grey);
}
.stat span { display: block; font-size: 23px; letter-spacing: -0.01em; color: var(--ink); margin-bottom: 2px; }
.stat.owing { border-color: #f3c9a5; background: var(--orange-tint); }
.stat.owing span { color: #a35400; }

.filterbar {
  display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap;
  align-items: center; margin-bottom: 20px;
}
.filtertabs { display: flex; gap: 2px; flex-wrap: wrap; }
.filtertabs a {
  padding: 8px 14px; border: 1px solid var(--rule); border-radius: var(--radius);
  font-family: var(--display); font-size: 11px; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--grey); background: var(--page);
}
.filtertabs a:hover { text-decoration: none; color: var(--ink); border-color: var(--rule-strong); }
.filtertabs a.on { background: var(--ink); border-color: var(--ink); color: #fff; }
.filtersearch { display: flex; gap: 8px; align-items: center; }
.filtersearch input { margin-top: 0; width: 250px; }

.daygroup { margin-bottom: 30px; }
.dayhead {
  font-family: var(--display); font-size: 13px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink);
  margin: 0 0 12px; padding-bottom: 9px; border-bottom: 2px solid var(--ink);
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
}
.dayhead .muted { font-size: 11px; letter-spacing: 0.08em; }

.timegroup {
  border: 1px solid var(--rule); border-radius: var(--radius-lg);
  margin-bottom: 12px; overflow: hidden; background: var(--panel);
}
.timehead {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  padding: 11px 16px; background: var(--wash); border-bottom: 1px solid var(--rule);
}
.timehead strong { font-family: var(--display); font-size: 17px; color: var(--ink); }
.timehead .muted { font-size: 12px; }

.bookrow {
  display: grid; gap: 16px; padding: 15px 16px;
  grid-template-columns: minmax(210px, 1.4fr) minmax(170px, 1.1fr) auto auto;
  align-items: start; border-bottom: 1px solid var(--rule);
}
.bookrow:last-child { border-bottom: 0; }
.bookrow .who strong { font-size: 15px; color: var(--ink); margin-right: 7px; }
.bookrow .who a { color: var(--grey); }
.bookrow .who a:hover { color: var(--orange); }
.svcline { font-size: 13px; padding: 2px 0; color: var(--ink-soft); }
.svcline .muted, .svcline .estimate { font-size: 12px; margin-left: 4px; }
.marklabel {
  display: block; font-family: var(--display); font-size: 9.5px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--grey-light); margin-bottom: 5px;
}

/* Segmented control: bigger hit targets than loose radios, and the chosen one
   is obvious at a glance when scanning a full day. */
.seg { display: inline-flex; border: 1px solid var(--rule-strong); border-radius: var(--radius); overflow: hidden; margin-bottom: 5px; }
.seg label {
  padding: 6px 12px; font-size: 11.5px; font-weight: 600; cursor: pointer;
  color: var(--grey); background: var(--page); border-right: 1px solid var(--rule);
  display: inline-flex; align-items: center; margin: 0;
}
.seg label:last-child { border-right: 0; }
.seg label:hover { background: var(--wash); color: var(--ink); }
/* .on is rendered server-side so the state is right on first paint even without
   :has() support; :has() then makes a click respond immediately rather than
   waiting for a save and reload. */
.seg label.on,
.seg label:has(input:checked) { background: var(--ink); color: #fff; }
.seg label:has(input:checked):hover { background: var(--ink); color: #fff; }
.seg label input { position: absolute; opacity: 0; width: 0; height: 0; }

.savebar {
  position: sticky; bottom: 0; background: var(--page);
  border-top: 2px solid var(--rule); padding: 14px 0;
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
}

@media (max-width: 820px) {
  .bookrow { grid-template-columns: 1fr 1fr; }
  .filtersearch input { width: 100%; }
  .filtersearch { width: 100%; }
}

.adminnav { display: flex; flex-wrap: wrap; gap: 9px; margin-bottom: 26px; }
.days { padding: 8px 18px 16px; }
.preview { border-top: 2px solid var(--rule); margin-top: 22px; padding-top: 18px; }
.planlist { max-height: 250px; overflow-y: auto; font-size: 13px; columns: 2; color: var(--grey); }
.onsite { margin-bottom: 9px; }
.msgcard pre {
  white-space: pre-wrap; word-break: break-word; background: var(--wash);
  padding: 14px; border-radius: var(--radius); margin: 10px 0 0;
  border: 1px solid var(--rule); font-size: 12.5px; line-height: 1.6;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* ---- footer -------------------------------------------------------------- */
footer {
  border-top: 1px solid var(--rule);
  background: var(--wash);
  margin-top: 40px;
}
.footinner {
  max-width: 1000px; margin: 0 auto; padding: 30px 26px 40px;
  color: var(--grey); font-size: 12.5px;
  display: flex; gap: 26px; flex-wrap: wrap; justify-content: space-between;
}
.footinner .fbrand {
  font-family: var(--display); font-weight: 700; font-size: 11px;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink);
}
.footinner a { color: var(--ink-soft); }
.footinner a:hover { color: var(--orange); }

/* ---- responsive ---------------------------------------------------------- */
@media (max-width: 820px) {
  .cols { grid-template-columns: 1fr; }
  .summary { position: static; }
  .planlist { columns: 1; }
}
@media (max-width: 640px) {
  main { padding: 26px 18px 56px; }
  .prefill { flex-direction: column; align-items: stretch; }
  .footinner { flex-direction: column; gap: 14px; }
}

/* Per-row cancel/move, tucked behind a disclosure so the day view stays scannable. */
.rowactions details { margin-top: 2px; }
.rowactions summary { list-style: none; cursor: pointer; display: inline-block; }
.rowactions summary::-webkit-details-marker { display: none; }
.rowpanel {
  margin-top: 9px; padding: 11px; background: var(--wash);
  border: 1px solid var(--rule); border-radius: var(--radius); min-width: 210px;
}
.rowpanel label { margin: 0 0 8px; }
.rowpanel input, .rowpanel select { margin-top: 3px; }
.rowform { display: none; }
.slotaction .row { margin-bottom: 10px; }

/* Wide data tables (admin Clients). The column set is the point, so the table
   keeps its width and the card scrolls sideways rather than wrapping every
   cell onto four lines. */
.tablewrap { overflow-x: auto; margin: 0 -4px; padding: 0 4px; }
.datatable { min-width: 1400px; }
.datatable th {
  text-align: left; padding: 8px 10px; font-size: 10.5px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--grey); border-bottom: 1px solid var(--rule-strong);
  white-space: nowrap; font-family: var(--display); font-weight: 600;
}
.datatable td { padding: 11px 10px; }
.datatable th.num, .datatable td.num { text-align: right; }
.datatable td.nowrap { white-space: nowrap; }
.datatable td.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; white-space: nowrap; letter-spacing: 0.04em; }
.datatable tr.erased td { color: var(--grey-light); }
.revealbar { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin-bottom: 8px; }
.revealbar p { margin: 0; }

/* ---- phones ---------------------------------------------------------------
   Everything above assumes at least a small laptop. Below this width the
   admin tables turn into stacked cards, the header stops wrapping onto three
   lines, and nothing needs a sideways scroll except a genuinely wide table. */
@media (max-width: 640px) {
  /* Header: logo left, links in one tidy row beneath. The signed-in name is
     the one thing a phone has no room for. */
  .topbar { padding: 12px 16px 10px; gap: 10px; }
  .topbar .logo img { height: 36px; }
  .topbar nav { gap: 6px 14px; width: 100%; justify-content: flex-start; }
  .topbar nav a { font-size: 10.5px; letter-spacing: 0.07em; padding: 4px 0; }
  .topbar .who { display: none; }

  /* The admin strip scrolls sideways; the scrollbar itself is noise. */
  .adminside { scrollbar-width: none; -ms-overflow-style: none; }
  .adminside::-webkit-scrollbar { display: none; }
  .adminside a { padding: 8px 10px; font-size: 12px; }

  .statrow { gap: 8px; }
  .stat { flex: 1 1 calc(50% - 8px); padding: 10px 12px; }
  .stat span { font-size: 20px; }

  .card { padding: 18px 16px; }
  .filtertabs a { padding: 7px 11px; }
  .filtersearch { flex-wrap: wrap; }
  .filtersearch input { flex: 1 1 160px; }
  .savebar { gap: 10px; padding: 12px 0; }
  .savebar button, .savebar .btn { width: 100%; }

  /* Booking rows: person on top, everything else beneath in one column. */
  .bookrow { grid-template-columns: 1fr; gap: 12px; padding: 14px; }
  .timehead { padding: 10px 14px; }
  .dayhead { flex-direction: column; align-items: flex-start; gap: 2px; }

  /* Segmented controls fill the row so thumbs have something to hit. */
  .seg { display: flex; }
  .seg label { flex: 1 1 0; justify-content: center; padding: 9px 6px; }

  /* Plain data tables (availability, venues, export log): each row becomes a
     small card with the column heading printed beside its value. */
  .table.runs, .table.runs tbody, .table.runs tr, .table.runs td { display: block; width: 100%; }
  .table.runs thead { display: none; }
  .table.runs tr { padding: 10px 0; border-bottom: 1px solid var(--rule); }
  .table.runs tr:last-child { border-bottom: 0; }
  .table.runs td { border: 0; padding: 2px 0; }
  .table.runs td.nowrap { white-space: normal; }

  /* The Clients table is 17 columns; as cards it is one person per card,
     with the identity block on top and the facts as a two-column list. */
  .tablewrap { margin: 0; padding: 0; overflow: visible; }
  .datatable { min-width: 0; display: block; }
  .datatable thead { display: none; }
  .datatable tbody { display: block; }
  .datatable tr {
    display: grid; grid-template-columns: 1fr 1fr; gap: 2px 12px;
    padding: 14px 0 12px; border-bottom: 1px solid var(--rule);
  }
  .datatable tr:last-child { border-bottom: 0; }
  .datatable td { display: block; padding: 3px 0; border: 0; font-size: 13px; }
  .datatable td.person, .datatable td.mono, .datatable td.email { grid-column: 1 / -1; }
  .datatable td.person { padding-bottom: 6px; }
  .datatable td.person strong { font-size: 16px; }
  .datatable td.person br { display: none; }
  .datatable td.person .small, .datatable td.person .state { margin-left: 8px; }
  .datatable td.email br { display: none; }
  .datatable td.email .small { margin-left: 6px; }
  .datatable td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-family: var(--display); font-size: 9.5px; font-weight: 700;
    letter-spacing: 0.12em; text-transform: uppercase; color: var(--grey-light);
    margin-bottom: 1px;
  }
  .datatable td.num { text-align: left; }
  .datatable td.mono { letter-spacing: 0.06em; font-size: 14px; }
  .revealbar { flex-direction: column; align-items: stretch; }
  .revealbar button, .revealbar .btn { width: 100%; }

  /* Forms: the side-by-side pairs stack. */
  .row { grid-template-columns: 1fr; }
  .cols { grid-template-columns: 1fr; }
  h1 { font-size: 24px; }
  h2 { font-size: 19px; }
}

/* ---- print ----------------------------------------------------------------
   The day sheet gets printed and carried around the practice, so printing is a
   real output, not an afterthought. Strip the chrome, drop the ink-heavy
   backgrounds, and let content break sensibly across pages. */
@media print {
  .topbar, .adminbar, .brandrule, footer, .filterbar, .savebar,
  .adminnav, .rowactions, .noprint, button, .btn { display: none !important; }

  body { background: #fff; color: #000; font-size: 11pt; }
  main { max-width: none; padding: 0; }

  .card, .timegroup, .daygroup {
    border: 0; box-shadow: none; padding: 0; margin: 0 0 10pt;
    break-inside: avoid; page-break-inside: avoid;
  }
  .dayhead, .timehead {
    background: transparent; border-bottom: 1pt solid #000;
    break-after: avoid; page-break-after: avoid;
  }
  .statrow { gap: 6pt; }
  .stat { border: 1pt solid #999; background: transparent; flex: 0 0 auto; padding: 4pt 8pt; }

  /* A printed sheet is read away from the screen, so show the target of a link
     rather than leaving the reader with underlined text and no address. */
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 8pt; color: #444; }
  a[href^="/"]::after, a[href^="#"]::after, a[href^="mailto"]::after,
  a[href^="tel"]::after { content: ""; }

  .seg label { border: 1pt solid #999; }
  .seg label.on { background: #000 !important; color: #fff !important; }
}

/* ---- step indicator -------------------------------------------------------
   Position in the funnel, readable without colour: the mark and the weight do
   the work, so it survives greyscale and colour blindness. */
.steps {
  display: flex; flex-wrap: wrap; gap: 6px;
  list-style: none; margin: 0 0 18px; padding: 0;
  font-family: var(--display); font-size: 11px;
  letter-spacing: 0.08em; text-transform: uppercase;
}
.steps li {
  display: flex; align-items: center; gap: 6px;
  padding: 6px 11px; border: 1px solid var(--rule); border-radius: var(--radius);
  color: var(--grey-light); background: var(--page);
}
.steps li.done { color: var(--grey); border-color: var(--rule-strong); }
.steps li.now {
  color: #fff; background: var(--ink); border-color: var(--ink);
}
.step-mark { font-weight: 700; }
.step-label { font-weight: 600; }
/* Announced, never shown: the visual cue is the mark and the weight. */
.step-state {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ---- health check --------------------------------------------------------- */
.checklist { list-style: none; padding: 0; margin: 0; }
.checklist li {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 12px 0; border-bottom: 1px solid var(--rule);
}
.checklist li:last-child { border-bottom: 0; }
.check-mark {
  flex: none; width: 26px; font-family: var(--display);
  font-weight: 700; font-size: 11px; letter-spacing: 0.06em;
}
.check-mark.yes { color: #1e7a4a; }
.check-mark.no  { color: var(--danger); }
.check-body strong { display: block; color: var(--ink); }
.check-body .detail { color: var(--grey); font-size: 12.5px; }

/* ---- client-side reschedule ------------------------------------------------ */
.movegrid { display: grid; gap: 9px; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); margin: 10px 0 18px; }
.moveopt {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 12px 14px; border: 1px solid var(--rule); border-radius: var(--radius);
  cursor: pointer; margin: 0;
}
.moveopt:hover { border-color: var(--rule-strong); }
.moveopt:has(input:checked) { border-color: var(--orange-ink); background: var(--orange-tint); }
.moveopt input { margin-top: 3px; flex: none; }

/* ---- booking page actions -------------------------------------------------- */
.calendar, .bookingactions { display: flex; gap: 10px; flex-wrap: wrap; margin: 10px 0; }

/* A fully booked day collapses rather than taking the same room as bookable ones. */
.day.dayfull > summary {
  cursor: pointer; list-style: none;
  font-family: var(--display); font-size: 12px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--grey-light);
  padding-bottom: 9px; border-bottom: 2px solid var(--rule); margin-bottom: 14px;
}
.day.dayfull > summary::-webkit-details-marker { display: none; }
.day.dayfull > summary:hover { color: var(--ink); }
.slotgrid span.slot { opacity: 0.5; cursor: default; }

.contactline { margin-top: 16px; }

/* ---- "Opening Google Calendar" interstitial ------------------------------- */
.opening { text-align: center; padding-top: 36px; padding-bottom: 36px; }
.opening h1 { margin-top: 14px; }
.opening-fallback { margin-top: 22px; }
.opening-spinner {
  display: inline-block; width: 28px; height: 28px; border-radius: 50%;
  border: 3px solid var(--rule); border-top-color: var(--orange);
  animation: opening-spin 0.8s linear infinite;
}
@keyframes opening-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .opening-spinner { animation: none; } }

/* ---- promote page -------------------------------------------------------- */
.qrrow { display: flex; gap: 22px; align-items: flex-start; flex-wrap: wrap; }
.qrbox { flex: none; width: 220px; border: 1px solid var(--rule); border-radius: var(--radius); background: #fff; }
.qrbox svg { display: block; width: 100%; height: auto; }
textarea.snippet { width: 100%; font: 12px/1.5 Consolas, Menlo, monospace; color: var(--ink-soft); }

/* ---- embedded availability panel ------------------------------------------ */
body.embed main { padding: 16px 14px 30px; }
body.embed .pagehead h1 { font-size: 24px; }
body.embed .pagehead .eyebrow { display: none; }

/* ---- dashboard numbers ---------------------------------------------------- */
.statrow.numbers .stat { flex: 1 1 140px; }

/* ---- visits: stations, itineraries, the day sheet -------------------------
   A booking is a chain of legs across the stations. The same list draws it
   everywhere: the time picker, the booking pages, the emails' HTML twin. */
.svc-order {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; margin-right: 8px; border-radius: 50%;
  background: var(--ink); color: #fff; font-family: var(--display);
  font-size: 11px; font-weight: 700; vertical-align: 1px;
}
/* Its own tick, not the sub-option's: the badge belongs to the service. */
.service:has(> .svc-main input:checked) .svc-order { background: var(--orange); }

.legs-list { list-style: none; margin: 8px 0 14px; padding: 0; border: 1px solid var(--rule); border-radius: var(--radius); }
.legs-list li {
  display: grid; grid-template-columns: 96px 1fr auto; gap: 12px; align-items: center;
  padding: 11px 14px; border-bottom: 1px solid var(--rule);
}
.legs-list li:last-child { border-bottom: 0; }
.leg-time { font-family: var(--display); font-size: 15px; font-weight: 700; color: var(--ink); white-space: nowrap; }
.leg-time .muted { font-size: 11px; font-weight: 500; margin-left: 2px; }
.leg-body { display: flex; flex-direction: column; gap: 2px; }
.leg-body .svc-name { font-weight: 600; color: var(--ink); }
.leg-price { text-align: right; white-space: nowrap; font-size: 13px; }
.leg-price .muted { font-size: 11px; }

.slotgrid.visits { grid-template-columns: repeat(auto-fill, minmax(212px, 1fr)); }
.slot.visit .legs { display: flex; flex-direction: column; gap: 2px; margin-top: 6px; font-size: 12px; color: var(--ink-soft); }
.slot.visit .legs b { display: inline-block; min-width: 40px; color: var(--ink); font-weight: 600; }
.slot.visit.tight .left { color: var(--orange-ink); }
.slot.visit:not(.tight) .left { color: var(--grey); }
.slotgrid span.slot .left { color: var(--grey-light); }
.totals div:nth-child(3) strong { color: var(--ink); }

/* Generator: one row per station. */
.stationtable { border: 1px solid var(--rule); border-radius: var(--radius); margin: 8px 0 16px; overflow-x: auto; }
.stationrow {
  display: grid; grid-template-columns: 34px 1.6fr 1fr 1fr 1fr 0.7fr 0.9fr; gap: 10px; align-items: center;
  padding: 9px 12px; border-bottom: 1px solid var(--rule); min-width: 640px;
}
.stationrow:last-child { border-bottom: 0; }
.stationrow.head { background: var(--wash); font-family: var(--display); font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--grey); }
.stationrow input[type="time"], .stationrow input[type="number"] { width: 100%; margin: 0; }
.stationcols { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); margin: 10px 0; }
.stationcol h3 { font-family: var(--display); font-size: 12px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink); margin: 0 0 8px; padding-bottom: 6px; border-bottom: 2px solid var(--rule); }
.stationcol .planlist { columns: 1; }
.table.compact td { padding: 8px 6px; font-size: 13px; }
.daystations h2 { display: flex; align-items: center; gap: 12px; }
tr.breakrow td { background: var(--wash); color: var(--grey); font-family: var(--display); font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; }

/* The day sheet: the clinic's own layout, on screen. */
.sheetnav { display: flex; flex-wrap: wrap; gap: 14px 24px; align-items: center; margin: 4px 0 8px; }
.inlineform { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0; }
.inlineform label.inline { margin: 0; display: flex; gap: 8px; align-items: center; }
.inlineform select { margin: 0; }
.daysheet .station { margin-bottom: 18px; }
.daysheet .station h2 { margin-bottom: 8px; }
.table.sheet th {
  text-align: left; padding: 8px 10px; font-family: var(--display); font-size: 11px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--grey); border-bottom: 2px solid var(--rule);
}
.table.sheet td { padding: 9px 10px; font-size: 13px; }
.table.sheet td:first-child { font-family: var(--display); font-weight: 700; color: var(--ink); white-space: nowrap; width: 62px; }
.table.sheet tr.emptyrow td { color: var(--grey-light); }
.table.sheet tr.tentative td { color: var(--grey); }
.table.sheet .idcell { font-variant-numeric: tabular-nums; white-space: nowrap; }
.table.sheet .mark .seg { margin: 0; }
.table.sheet a { color: var(--ink-soft); }

@media (max-width: 700px) {
  .legs-list li { grid-template-columns: 76px 1fr; }
  .legs-list .leg-price { grid-column: 2; text-align: left; }
  .table.sheet thead { display: none; }
  .table.sheet, .table.sheet tbody, .table.sheet tr, .table.sheet td { display: block; width: 100%; }
  .table.sheet td { border-bottom: 0; padding: 3px 10px; }
  .table.sheet tr { border-bottom: 1px solid var(--rule); padding: 8px 0; }
  .table.sheet td:first-child { width: auto; }
}

/* Something that exists only on paper. The screen already has the header, the
   heading and the navigation; the printed page has none of them. */
.printonly { display: none; }

@media print {
  .sheetnav, .pagehead p, .statrow { display: none !important; }
  /* On a page that carries a day sheet the letterhead below says the business
     and the day, so the ordinary heading would only say them again. */
  body:has(.daysheet) .pagehead { display: none !important; }

  /* The printed letterhead, laid out like the first five rows of the .xlsx:
     the mark to the right, the business name, what the sheet is, the day, and
     the orange rule under all of it. Someone holding the print-out and someone
     holding the workbook should be able to see they are the same document. */
  .sheethead {
    display: grid; grid-template-columns: 1fr auto; gap: 0 12pt;
    border-bottom: 2.5pt solid var(--orange);
    padding-bottom: 5pt; margin: 0 0 12pt;
    /* Without this the rule and the mark come out blank: browsers drop
       backgrounds and trim images when printing unless told not to. */
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
    break-after: avoid; page-break-after: avoid;
  }
  .sheethead img { grid-column: 2; grid-row: 1 / span 3; align-self: center; height: 44px; width: auto; }
  .sheethead span { grid-column: 1; display: block; }
  .sheethead-brand { font-family: var(--display); font-weight: 700; font-size: 14pt; color: #000; }
  .sheethead-what {
    font-family: var(--display); font-weight: 700; font-size: 8pt;
    letter-spacing: 0.1em; text-transform: uppercase; color: var(--orange-ink);
    margin-top: 1pt;
  }
  .sheethead-day { font-size: 11pt; color: #333; margin-top: 2pt; }

  .daysheet .station { break-inside: avoid; page-break-inside: avoid; margin-bottom: 14pt; }
  /* A station with more people in it than fit on a page breaks anyway, whatever
     the rule above asks for, so the column headings are repeated on each page
     it spills onto - the same job print titles do in the workbook. The narrow
     layout hides this thead, and a printer's page can be narrow enough to
     count as narrow, so it is turned back on here rather than left to luck. */
  .table.sheet thead { display: table-header-group; }
  .daysheet .station h2 { break-after: avoid; page-break-after: avoid; }
  .table.sheet th, .table.sheet td { border-bottom: 0.5pt solid #999; padding: 4pt 6pt; font-size: 10pt; }
  .table.sheet tr.breakrow td { background: #eee !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .table.sheet .mark .seg { display: none; }
  /* A box to tick by hand; drawn, not typed, for the same reason as the chevrons. */
  .table.sheet .mark::after { content: ""; display: inline-block; width: 10pt; height: 10pt; border: 0.75pt solid #000; vertical-align: middle; }
}

/* A read-only link with its Copy button on the same line. */
.copyrow { display: flex; gap: .5rem; align-items: center; }
.copyrow input { flex: 1; min-width: 0; }
.copyrow button { flex: none; }


/* ---- visit card, scarcity, tick, empty states ----------------------------- */

/* Places left: amber at two, red at the last one. A busy card stays legible -
   dashed, tinted, badged - rather than fading into the page. */
.slot { position: relative; }
.slot .badge {
  position: absolute; top: 10px; right: 10px;
  font-family: var(--display); font-size: 9.5px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  padding: 3px 7px; border-radius: 999px; line-height: 1.2;
}
.slot .badge.few  { background: #fff3d6; color: #8a5a00; }
.slot .badge.last { background: #fde2dc; color: #a12b12; }
.slot .badge.full { background: #e9e9e9; color: #666; }
.slot.visit.few  { border-color: #f0c66a; }
.slot.visit.last { border-color: #ef8f7a; }
.slot.visit.last .time { color: #a12b12; }
.slot.full, .slotgrid span.slot {
  opacity: 1; background: #f7f6f4; border-style: dashed; border-color: #d9d5cf;
}
.slot.full .time { color: #8b8b8b; text-decoration: line-through; text-decoration-color: #c9c4bd; }
.slot.full .left, .slotgrid span.slot .left { color: #7a7a7a; }
a.slot.full:hover { border-color: var(--orange); box-shadow: var(--shadow-lift); transform: translateY(-1px); }
a.slot.full:hover .left { color: var(--orange-ink); }

/* The tick that draws itself on a brand-new booking. */
.booked-hero { display: flex; gap: 18px; align-items: center; margin-bottom: 22px; }
.booked-hero h1 { margin: 0 0 4px; }
.booked-hero p { margin: 0; }
.tick { width: 64px; height: 64px; flex: none; }
.tick circle { fill: none; stroke: var(--orange); stroke-width: 3; stroke-dasharray: 183; stroke-dashoffset: 183;
  animation: tick-draw .6s ease-out forwards; }
.tick path { fill: none; stroke: var(--orange); stroke-width: 4; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 40; stroke-dashoffset: 40; animation: tick-draw .35s ease-out .45s forwards; }
@keyframes tick-draw { to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) { .tick circle, .tick path { animation: none; stroke-dashoffset: 0; } }

/* Printing the booking page: the page is the keepsake, so only the frame goes. */
@media print { #bookingpage .bookingactions, #bookingpage .calendar { display: none !important; } }

/* An empty list says so with a little grace, not a bare "nothing". */
.empty {
  display: flex; gap: 14px; align-items: center;
  padding: 18px 6px; color: var(--grey);
}
.empty svg { width: 34px; height: 34px; flex: none; stroke: var(--orange); fill: none; stroke-width: 1.6; opacity: .8; }
.empty strong { display: block; color: var(--ink); font-weight: 600; }


/* ---- the trend strip on Today ----------------------------------------------- */
.trendrow { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); margin: 6px 0 18px; }
.trend {
  position: relative; padding: 14px 16px 12px; background: var(--page);
  border: 1px solid var(--rule); border-radius: var(--radius);
}
.trend .eyebrow { display: block; margin-bottom: 6px; }
.trend .spark { display: block; width: 100%; height: 34px; overflow: visible; }
.trend .spark polyline { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.trend strong { display: block; font-family: var(--display); font-size: 22px; margin-top: 6px; color: var(--ink); line-height: 1.1; }
.trend small { color: var(--grey); font-size: 11.5px; }
.trend-bars { display: flex; gap: 3px; align-items: flex-end; height: 22px; margin-top: 6px; }
.trend-bars span { flex: 1; height: 100%; display: flex; align-items: flex-end; background: #f5efe9; border-radius: 2px; }
.trend-bars i { display: block; width: 100%; background: var(--orange); border-radius: 2px; opacity: .85; }
.trend-bars span.ahead { background: #fbf3ec; outline: 1px dashed #e8cdb5; outline-offset: -1px; }
.trend-bars span.ahead i { opacity: .45; }
.gaps h2 { margin-top: 0; }
.table.consents td:first-child { max-width: 60ch; }


/* ---- tap-to-open hints -----------------------------------------------------
   A "?" beside the thing it explains. Hover opens it on a desktop, a tap on a
   phone, where it comes up as a sheet along the bottom instead of a bubble. */
.hint { display: inline-block; position: relative; vertical-align: middle; margin: 0 2px 0 6px; text-transform: none; letter-spacing: 0; }
.hint > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%;
  border: 1px solid var(--rule-strong); background: var(--page); color: var(--grey);
  font-family: var(--display); font-size: 11px; font-weight: 700; line-height: 1;
}
.hint > summary::-webkit-details-marker { display: none; }
.hint > summary:hover, .hint[open] > summary { background: var(--orange); border-color: var(--orange); color: #fff; }
.hint > div {
  position: absolute; z-index: 30; top: 26px; left: 0;
  width: max-content; max-width: min(340px, 80vw);
  padding: 10px 13px; border-radius: 8px;
  background: var(--ink); color: #fff;
  font-family: var(--body, inherit); font-size: 13px; font-weight: 400; line-height: 1.5;
  text-align: left; text-transform: none; letter-spacing: 0; white-space: normal;
  box-shadow: var(--shadow-lift);
}
h1 .hint, h2 .hint { vertical-align: 3px; }
@media (hover: hover) { .hint:hover > div { display: block; } .hint:not([open]):hover > summary { background: var(--orange); border-color: var(--orange); color: #fff; } }
.hint:not([open]) > div { display: none; }
@media (max-width: 560px) {
  .hint > div { position: fixed; left: 12px; right: 12px; top: auto; bottom: calc(12px + env(safe-area-inset-bottom, 0px)); max-width: none; width: auto; font-size: 14px; padding: 14px 16px; }
}

.intro { margin: 0 0 1em; }

/* A button that has to read as a link. The "send a new one" resend control is
   a POST now - as a GET link, crawlers and mail scanners were triggering it -
   but it sits mid-sentence and should not look like a call to action. */
.resendform { display: inline; margin: 0; }
button.linklike {
  display: inline; width: auto; margin: 0; padding: 0;
  background: none; border: 0; border-radius: 0;
  font: inherit; color: var(--orange-ink);
  text-decoration: underline; text-underline-offset: 2px;
  cursor: pointer;
}
button.linklike:hover { color: var(--orange-dark); }
