/* PlumberPlug: one centred column, phone first; on a desktop the same layout, larger. Public pages and the admin. */
/* Figtree is the brand's own face, held here rather than fetched from anyone else. It is swapped in when it arrives,
   so nothing waits on it, and the system face behind it keeps the same shape of page. Licence: /fonts/OFL.txt */
@font-face { font-family: Figtree; font-style: normal; font-weight: 400; font-display: swap; src: url(/fonts/figtree-latin-400-normal.woff2?v=c211a9f122f0) format("woff2"); }
@font-face { font-family: Figtree; font-style: normal; font-weight: 600; font-display: swap; src: url(/fonts/figtree-latin-600-normal.woff2?v=c211a9f122f0) format("woff2"); }
:root {
  --accent: #1f5f8b; --accent-ink: #ffffff; --accent-wash: #e3eef6;
  --bg: #f3f6f9; --card: #ffffff; --ink: #18232d; --soft: #566572; --line: #dbe3ea; --danger: #b3261e; --ok: #1f7a4d;
  --radius: 14px; --radius-lg: 22px; --shadow: 0 1px 2px rgba(24, 35, 45, 0.05), 0 10px 30px rgba(24, 35, 45, 0.07);
  --sans: Figtree, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1); --spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --field-h: 48px; --tap: 54px;
}
/* colour presets (Settings > Colour) */
[data-accent="teal"] { --accent: #11706c; --accent-wash: #dff0ef; }
[data-accent="green"] { --accent: #2f6b3f; --accent-wash: #e2efe5; }
[data-accent="orange"] { --accent: #b4520f; --accent-wash: #f8e8da; }
[data-accent="slate"] { --accent: #34495e; --accent-wash: #e5eaef; }

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body { margin: 0; background: var(--bg); color: var(--ink); font: 17px/1.55 var(--sans); }
@media (min-width: 900px) { body { font-size: 18px; } }
a { color: var(--accent); }
img, svg { display: block; max-width: 100%; }
[hidden] { display: none !important; }
:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

/* the page: a centred column of cards, the same at every width (wider and larger on a desktop) */
.page { width: 100%; max-width: 560px; margin: 0 auto; padding: clamp(16px, 4vw, 40px) 16px 40px; display: grid; gap: 16px; }
@media (min-width: 900px) { .page { max-width: 640px; gap: 20px; } }
.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow);
  padding: clamp(22px, 5vw, 40px); text-align: center; }
.mark { width: 64px; height: 64px; margin: 0 auto 14px; color: var(--accent); }
.mark svg { width: 100%; height: 100%; display: block; }   /* the drawing fills the box, so the ripple's fall line matches */
@media (min-width: 900px) { .mark { width: 76px; height: 76px; } }
.card h1 { font-size: clamp(30px, 7vw, 44px); font-weight: 750; line-height: 1.1; letter-spacing: -0.5px; margin: 0 0 10px; }
.card h2 { font-size: clamp(21px, 4.6vw, 26px); font-weight: 750; line-height: 1.2; margin: 0 0 14px; }
.blurb { color: var(--soft); margin: 0 auto 22px; max-width: 34ch; text-wrap: balance; font-size: 1.05em; }
.lead { color: var(--soft); margin: 0 auto 18px; max-width: 38ch; text-wrap: balance; }

/* STANDING RULE (docs/DESIGN.md): buttons on a centred card are centred under the text; on a phone a lone button is
   full width. Big tap targets everywhere. Checked by npm run check:centre. */
.actions { display: grid; gap: 12px; justify-items: stretch; max-width: 420px; margin: 0 auto; }
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 10px; min-height: var(--tap); padding: 0 24px;
  border-radius: 999px; border: 0; background: var(--accent); color: var(--accent-ink); font: 650 1em/1.2 var(--sans); text-decoration: none;
  cursor: pointer; transition: transform 0.25s var(--spring), box-shadow 0.25s var(--ease); -webkit-tap-highlight-color: transparent; }
.btn svg { width: 22px; height: 22px; flex: none; }
/* a long phone number or email wraps onto a second centred line instead of pushing the page sideways */
.btn { max-width: 100%; min-width: 0; padding-top: 8px; padding-bottom: 8px; text-align: center; }
.btn > span { display: inline-flex; flex-wrap: wrap; justify-content: center; column-gap: 0.35em; min-width: 0; }
.btn .sub { font-weight: 500; opacity: 0.9; overflow-wrap: anywhere; }
.btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 8px 18px rgba(24, 35, 45, 0.16); }
.btn:active { transform: scale(0.97); }
.btn:disabled { opacity: 0.5; cursor: default; }
.btn.secondary { background: var(--card); color: var(--accent); box-shadow: inset 0 0 0 2px var(--accent); }
.btn.danger { background: var(--card); color: var(--danger); box-shadow: inset 0 0 0 2px var(--danger); }

/* service area and hours: centred lines with a small icon, under the buttons */
.facts { list-style: none; margin: 22px auto 0; padding: 0; display: grid; gap: 6px; color: var(--soft); justify-items: center; max-width: 36ch; }
.facts li { text-wrap: balance; }
.facts svg { display: inline-block; width: 18px; height: 18px; vertical-align: -3px; margin-right: 6px; color: var(--accent); }   /* inline: it stays with the first word when the line wraps */
.actions + .facts { margin-top: 24px; }
.blurb + .facts { margin-top: 0; }
/* the area: a short line by the pin, then the cities and the note smaller; on a phone they fold under "Areas we serve" */
.facts .area .line { color: var(--ink); font-weight: 600; }
.facts .more { display: block; font-size: 0.86em; line-height: 1.5; margin-top: 4px; }
.facts .more .cities, .facts .more .note { display: block; }
.facts .more .cities { color: var(--ink); opacity: 0.8; }
.facts .city { white-space: nowrap; }
.facts li.area { max-width: 44ch; }
.facts:has(.area) { max-width: 44ch; }
.facts details.more summary { cursor: pointer; color: var(--accent); font-weight: 600; list-style: none; display: inline-flex; align-items: center; gap: 4px; min-height: 44px; }
.facts details.more summary::-webkit-details-marker { display: none; }
.facts details.more summary::after { content: ""; width: 7px; height: 7px; border: solid currentColor; border-width: 0 2px 2px 0; transform: rotate(45deg) translateY(-2px); transition: transform 0.2s; }
.facts details.more[open] summary::after { transform: rotate(-135deg) translateY(-1px); }
.facts details.more[open] summary { min-height: 36px; }
.facts details.more { margin-top: 0; }
/* under the name: the tagline, then what he does as one quiet line */
.hero .tagline { margin: -6px 0 8px; font-size: 17px; color: var(--ink); }
.hero .services { margin: 0 0 18px; font-size: 14.5px; color: var(--soft); line-height: 1.6; text-wrap: balance; }
@media (min-width: 900px) { .hero .tagline { font-size: 18px; } }

/* what he does and what he holds: one quiet line of ticked labels, smaller and lighter than the services line above,
   flat (no pill, no border, no shadow) so they support the name instead of competing with the Call button */
.checks { list-style: none; margin: 0 auto 20px; padding: 0; display: flex; flex-wrap: wrap; justify-content: center;
  gap: 6px 14px; font-size: 13px; color: var(--soft); }
.checks li { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.checks svg { width: 15px; height: 15px; flex: none; color: var(--accent); border-radius: 50%;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent), 0 1px 2px rgb(20 35 50 / 0.18);
  animation: pop 0.34s var(--spring) both; animation-delay: calc(var(--n, 0) * 80ms); }
@keyframes pop { from { transform: scale(0.8); opacity: 0; } to { transform: scale(1); opacity: 1; } }
/* the three stay on one line at 390 by giving up a little type size first */
@media (max-width: 430px) { .checks { font-size: 12px; gap: 4px 10px; flex-wrap: nowrap; } .checks svg { width: 14px; height: 14px; } }

/* what kind of work: small chips under the description */
.chips { list-style: none; margin: -8px auto 22px; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.chips li { padding: 4px 12px; border-radius: 999px; background: var(--accent-wash); color: var(--accent); font-size: 14px; font-weight: 650; letter-spacing: 0.2px; }
/* the line drawing along the bottom of the main card: the card keeps room for it */
.card.hero.with-art { padding-bottom: calc(clamp(22px, 5vw, 40px) + clamp(64px, 15vw, 104px)); }
.card.hero .skyline { position: absolute; left: 0; right: 0; bottom: 0; width: 100%; height: clamp(64px, 15vw, 104px); color: var(--accent); opacity: 0.32; pointer-events: none; }
/* the optional round photo in place of the drop mark */
.portrait { width: 112px; height: 112px; margin: 0 auto 16px; border-radius: 50%; padding: 4px; background: var(--card); box-shadow: 0 0 0 3px var(--accent-wash), var(--shadow); }
.portrait img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
/* work photos: one at a time on a phone, swiped and snapped; three across on a desktop, with arrows */
.card.photos { padding-left: 0; padding-right: 0; }
.card.photos h2 { padding: 0 clamp(22px, 5vw, 40px); }
.card.photos .section-sub { padding: 0 clamp(22px, 5vw, 40px); margin: -8px 0 16px; font-size: 14px; color: var(--soft); line-height: 1.5; }
.strip-wrap { position: relative; }
.strip { display: grid; grid-auto-flow: column; grid-auto-columns: 78%; gap: 12px; overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth;
  padding: 0 11% 6px; scrollbar-width: none; }
.strip::-webkit-scrollbar { display: none; }
.strip:focus-visible { outline: 3px solid var(--accent); outline-offset: -3px; }
.strip figure { margin: 0; position: relative; scroll-snap-align: center; border-radius: var(--radius); overflow: hidden; background: var(--accent-wash); aspect-ratio: 4 / 3; }
.strip img { width: 100%; height: 100%; object-fit: cover; }
.strip figcaption { position: absolute; left: 0; right: 0; bottom: 0; padding: 22px 12px 10px; color: #fff; font-weight: 650; font-size: 15px; text-align: left;
  background: linear-gradient(to top, rgba(10, 20, 28, 0.78), rgba(10, 20, 28, 0)); }
.arrow { position: absolute; top: 50%; transform: translateY(-50%); z-index: 2; width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--line);
  background: color-mix(in srgb, var(--card) 92%, transparent); color: var(--accent); display: none; place-items: center; cursor: pointer; box-shadow: var(--shadow); }
.arrow svg { width: 22px; height: 22px; }
.arrow.back { left: 6px; } .arrow.next { right: 6px; }
.arrow:disabled { opacity: 0.35; cursor: default; }
.dots { display: flex; flex-wrap: wrap; justify-content: center; gap: 2px 4px; margin-top: 10px; }
.dots a { display: grid; place-items: center; width: 24px; height: 24px; }
.dots span { width: 8px; height: 8px; border-radius: 50%; background: var(--line); transition: background 0.2s, transform 0.2s; }
.dots a[aria-current="true"] span { background: var(--accent); transform: scale(1.3); }
@media (min-width: 700px) {
  .strip { grid-auto-columns: calc((100% - 24px) / 3); padding: 0 clamp(22px, 5vw, 40px) 6px; }
  .arrow { display: grid; }
}
@media (prefers-reduced-motion: reduce) { .strip { scroll-behavior: auto; } }

/* the callback form: centred heading and button, fields full width with their labels */
.form { display: grid; gap: 14px; text-align: left; max-width: 420px; margin: 0 auto; }
.form label { display: grid; gap: 6px; font-size: 15px; font-weight: 600; color: var(--soft); }
.form label .opt { font-weight: 500; }
.pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 170px), 1fr)); gap: 14px; align-items: end; }
input, select, textarea { font: 17px/1.3 var(--sans); color: var(--ink); background: #fff; border: 1px solid var(--line); border-radius: 12px;
  padding: 11px 14px; width: 100%; min-width: 0; }
input:not([type="checkbox"]):not([type="radio"]), select { height: var(--field-h); }
textarea { min-height: 96px; resize: vertical; }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }
.form .hint { margin: -6px 0 0; color: var(--soft); font-size: 14px; text-align: center; }
.form .btn { width: 100%; }
.hp { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
.turnstile { display: flex; justify-content: center; min-height: 0; }
.notice { border-radius: var(--radius); padding: 12px 14px; margin: 0 auto 16px; max-width: 420px; text-align: center; font-weight: 600; }
.notice.ok { background: #e3f3ea; color: var(--ok); }
.notice.err { background: #fbe9e7; color: var(--danger); }

.foot { text-align: center; color: var(--soft); font-size: 14px; margin: 4px 0 0; }

/* pay page */
.who { display: inline-flex; align-items: center; gap: 8px; color: var(--soft); font-weight: 600; margin: 0 auto 14px; }
.who svg { width: 26px; height: 26px; color: var(--accent); }
.amount { font-size: clamp(40px, 10vw, 56px); font-weight: 750; letter-spacing: -1px; line-height: 1.05; margin: 0 0 6px; }
.for { margin: 0 auto 4px; max-width: 34ch; text-wrap: balance; font-weight: 600; }
.ref { color: var(--soft); font-size: 15px; margin: 0 0 20px; }
.lines { display: grid; gap: 6px; margin: 0 auto 20px; max-width: 420px; padding: 14px 16px; background: var(--bg); border-radius: var(--radius); text-align: left; }
.lines div { display: flex; justify-content: space-between; gap: 12px; }
.lines dt { color: var(--soft); }
.lines dd { margin: 0; font-variant-numeric: tabular-nums; white-space: nowrap; }
.lines .total { border-top: 1px solid var(--line); padding-top: 8px; margin-top: 2px; font-weight: 700; }
.lines .total dt { color: var(--ink); }
.fine { color: var(--soft); font-size: 14px; margin: 14px auto 0; max-width: 40ch; text-wrap: balance; }
.badge { width: 72px; height: 72px; border-radius: 50%; margin: 0 auto 14px; display: grid; place-items: center; background: var(--accent-wash); color: var(--accent); }
.badge svg { width: 36px; height: 36px; }
.badge.off { background: var(--line); color: var(--soft); }

/* status pages: the mark, a title and a line, centred in the card */
.status h1 { margin-bottom: 8px; }
.status p { color: var(--soft); margin: 0 auto 20px; max-width: 34ch; text-wrap: balance; }

@media (prefers-reduced-motion: reduce) { .btn { transition: none; } }

/* ---------------- admin ---------------- */
.admin-top { background: var(--card); border-bottom: 1px solid var(--line); }
.admin-top .in { max-width: 920px; margin: 0 auto; padding: 10px 16px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; justify-content: space-between; }
.admin-top .name { display: inline-flex; align-items: center; gap: 8px; font-weight: 750; color: var(--ink); text-decoration: none; }
.admin-top .name svg { width: 26px; height: 26px; color: var(--accent); }
.admin-top nav { display: flex; gap: 4px; flex-wrap: wrap; }
.admin-top nav a { padding: 8px 12px; border-radius: 999px; color: var(--soft); text-decoration: none; font-weight: 650; font-size: 15px; white-space: nowrap; }
.admin-top nav a[aria-current="page"] { background: var(--accent-wash); color: var(--accent); }
.count { display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; background: var(--danger); color: #fff; font-size: 12px; margin-left: 4px; }
.admin { max-width: 920px; margin: 0 auto; padding: 18px 16px 64px; }
.admin h1 { font-size: clamp(26px, 4vw, 36px); font-weight: 750; margin: 8px 0 4px; }
.admin h2 { font-size: 20px; margin: 0 0 12px; }
.admin .lead { margin: 0 0 18px; text-align: left; max-width: none; }
.panel { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: clamp(16px, 3vw, 24px); box-shadow: var(--shadow); margin-bottom: 18px; }
/* STANDING RULE (docs/DESIGN.md): fields side by side line up: every row aligns its cells to the bottom, every
   single-line box is one height, and a switch row is that same height. Checked by npm run check:align. */
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); gap: 14px; align-items: end; }
.grid + .grid, .grid + label, label + .grid, .hint + .grid, .hint + label, .panel label + label { margin-top: 14px; }
.panel label, .sheet label.field { display: grid; gap: 6px; font-size: 14px; font-weight: 600; color: var(--soft); align-content: start; min-width: 0; }
.sheet label.field { margin-top: 10px; }
.panel input, .panel select, .panel textarea { font-size: 16px; }
label.check { display: flex !important; align-items: center; gap: 10px; color: var(--ink) !important; font-weight: 500 !important; font-size: 16px !important; min-height: var(--field-h); }
label.check input { width: 22px; height: 22px; flex: none; accent-color: var(--accent); }
.hint { margin: 6px 0 0; color: var(--soft); font-size: 14px; }
.row-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.btn.small { min-height: 40px; padding: 0 16px; font-size: 15px; }
.field-error { color: var(--danger); font-size: 14px; font-weight: 600; }
.field-error:empty { display: none; }
.error { color: var(--danger); font-weight: 600; margin: 10px 0 0; }
.error:empty { display: none; }
.saved { color: var(--ok); font-weight: 650; margin: 0; align-self: center; }
.setup-warn { margin: 0 0 16px; padding: 12px 14px; border-radius: 12px; background: #fbeee0; color: #6b3a12; border: 1px solid #ecc9a4; line-height: 1.5; }
.setup-warn code { font-size: 13px; background: #fff7ee; padding: 1px 5px; border-radius: 6px; word-break: break-word; }
.filters { display: flex; gap: 6px; flex-wrap: wrap; margin: 0 0 12px; }
.filters button { min-height: 40px; padding: 0 14px; border-radius: 999px; border: 1px solid var(--line); background: var(--card); font: 600 15px var(--sans); color: var(--soft); cursor: pointer; }
.filters button[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.list { display: grid; gap: 10px; }
.item { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px; display: grid; gap: 6px; }
.item .top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.item .amt { font-weight: 750; font-size: 18px; margin-left: auto; font-variant-numeric: tabular-nums; }
.item .what { font-weight: 650; }
.item .sub { color: var(--soft); font-size: 14px; }
.item .row-actions { margin-top: 6px; }
.pill { font-weight: 700; letter-spacing: 0.5px; font-size: 14px; padding: 2px 10px; border-radius: 999px; background: var(--accent-wash); color: var(--accent); }
.tag { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 12px; font-weight: 700; background: var(--line); color: var(--soft); }
.tag.pending { background: #fff3d6; color: #7a5300; }
.tag.paid { background: #e3f3ea; color: var(--ok); }
.tag.refunded, .tag.partly_refunded { background: #ece7f8; color: #4b3a8a; }
.tag.expired, .tag.cancelled { background: var(--line); color: var(--soft); }
.tag.new { background: #fbe9e7; color: var(--danger); }
.tag.called { background: #fff3d6; color: #7a5300; }
.tag.done { background: #e3f3ea; color: var(--ok); }
.empty { color: var(--soft); text-align: center; padding: 24px 0; }
/* the new link, ready to copy */
.made { border: 2px solid var(--accent); }
.linkbox { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; align-items: center; }
.linkbox input { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 14px; }
.preview { display: grid; gap: 4px; margin: 14px 0 0; padding: 12px 14px; background: var(--bg); border-radius: var(--radius); }
.preview div { display: flex; justify-content: space-between; gap: 10px; }
.preview .total { font-weight: 700; border-top: 1px solid var(--line); padding-top: 6px; margin-top: 2px; }
/* a sheet for confirmations (refund, cancel) */
dialog.sheet { border: 0; border-radius: var(--radius-lg); padding: clamp(18px, 4vw, 28px); width: min(520px, calc(100vw - 32px)); box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25); }
dialog.sheet::backdrop { background: rgba(24, 35, 45, 0.45); }
dialog.sheet h2 { margin-top: 0; }
.warn { background: #fbeee0; color: #6b3a12; border-radius: 12px; padding: 10px 12px; font-weight: 600; margin: 12px 0 0; }
.choice { display: grid; gap: 8px; margin: 12px 0 0; }
.choice label { display: flex; align-items: center; gap: 10px; color: var(--ink); font-size: 16px; font-weight: 500; min-height: 44px; }
.choice input[type="radio"] { width: 20px; height: 20px; accent-color: var(--accent); flex: none; }
@media (max-width: 520px) { .admin-top .in { justify-content: center; } }

/* rating: five big stars; picking one fills it and every star before it (row reversed so ~ selects the lower ones) */
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.stars { border: 0; margin: 0; padding: 0; min-width: 0; }
.star-row { display: flex; flex-direction: row-reverse; justify-content: center; gap: 6px; }
.star-row input { position: absolute; opacity: 0; pointer-events: none; }
.star-row label { width: 52px; height: 52px; display: grid; place-items: center; cursor: pointer; border-radius: 14px; transition: transform 0.25s var(--spring); }
.star-row label::before { content: "★"; font-size: 40px; line-height: 1; color: var(--line); transition: color 0.15s; }
.star-row input:checked ~ label::before, .star-row label:hover::before, .star-row label:hover ~ label::before { color: #f2b01e; }
.star-row input:checked + label { transform: scale(1.12); }
.star-row input:focus-visible + label { outline: 3px solid var(--accent); outline-offset: 2px; }
.stars-shown { font-size: 30px; letter-spacing: 4px; color: #f2b01e; margin: 0 0 8px; }
.stars-shown span { color: var(--line); }
.stars-line { color: #f2b01e; font-size: 20px; letter-spacing: 2px; }
/* Messages to customers: one block per email */
.email-block { border-top: 1px solid var(--line); padding-top: 16px; margin-top: 16px; }
.email-block h3 { font-size: 17px; margin: 0; }
.email-block .when { color: var(--soft); font-size: 14px; margin: 2px 0 8px; }
.mail-preview { margin-top: 12px; border: 1px dashed var(--line); border-radius: 12px; padding: 12px 14px; background: var(--bg); font-size: 15px; white-space: pre-wrap; overflow-wrap: anywhere; }
.mail-preview b { display: block; margin-bottom: 6px; white-space: normal; }
.email-block.off .mail-preview { opacity: 0.55; }

/* ---------------- motion: water and pipes (none for reduced motion) ---------------- */
.btn { position: relative; overflow: hidden; isolation: isolate; }
.btn .splash { position: absolute; border-radius: 50%; pointer-events: none; z-index: -1; background: radial-gradient(circle, rgba(255, 255, 255, 0.45) 0 30%, rgba(255, 255, 255, 0.18) 31% 60%, transparent 61%);
  transform: scale(0); animation: splash 0.65s var(--ease) forwards; }
.btn.secondary .splash, .btn.danger .splash { background: radial-gradient(circle, color-mix(in srgb, currentColor 22%, transparent) 0 30%, color-mix(in srgb, currentColor 10%, transparent) 31% 60%, transparent 61%); }
@keyframes splash { to { transform: scale(1); opacity: 0; } }

/* the mark: the tap holds still while a drop swells at the spout tip, hangs, then lets go and rings out below.
   Calm: six seconds a cycle. The still frame, which is what reduced motion and every printed piece show, is the drop
   hanging at full size, so the animation never makes it bigger than the logo itself. */
.mark.drip { position: relative; margin-bottom: 30px; }
.mark.drip svg { overflow: visible; }
.mark.drip .drop { transform-box: fill-box; transform-origin: 50% 0; animation: drip 6s var(--ease) infinite; }
/* the ripple sits on the drop's own fall line: --drop-x comes from the one place the mark is drawn */
.mark .ring { position: absolute; left: var(--drop-x, 73%); top: calc(100% + 10px); width: 26px; height: 7px; border-radius: 50%;
  border: 2px solid var(--accent); opacity: 0; transform: translateX(-50%) scale(0.2); animation: ring 6s var(--ease) infinite; }
@keyframes drip {
  0%, 42%  { transform: translateY(0) scale(1); }          /* the logo as drawn: the first frame on load */
  50%      { transform: translateY(0) scale(0.93, 1.1); }
  58%      { transform: translateY(0) scale(1); }
  74%      { transform: translateY(26px) scale(0.88, 1.16); opacity: 1; }
  82%      { transform: translateY(40px) scale(0.8, 1.2); opacity: 0; }
  83%      { transform: translateY(0) scale(0.2); opacity: 1; }   /* a new bead at the tip */
  100%     { transform: translateY(0) scale(1); }                 /* grown back to the drawn drop */
}
@keyframes ring {
  0%, 80%  { opacity: 0; transform: translateX(-50%) scale(0.2); }
  82%      { opacity: 0.75; transform: translateX(-50%) scale(0.3); }
  95%, 100% { opacity: 0; transform: translateX(-50%) scale(1.6); }
}

/* a thin pipe along the top of the main card, water flowing through it */
.card.hero { position: relative; overflow: hidden; }
.card.hero::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 5px;
  background: linear-gradient(90deg, var(--accent-wash) 0 20%, var(--accent) 35%, var(--accent-wash) 50% 70%, var(--accent) 85%, var(--accent-wash) 100%) 0 0 / 200% 100%;
  animation: flow 7s linear infinite; }
@keyframes flow { to { background-position: -200% 0; } }

/* done: the wrench gives a turn, then the check settles in */
.badge.done { position: relative; }
.badge.done > span { position: absolute; inset: 0; display: grid; place-items: center; }
.badge.done .wrench { animation: turn 0.9s var(--ease) both; }
.badge.done .tick { opacity: 0; transform: scale(0.4); animation: settle 0.45s var(--spring) 0.8s forwards; }
@keyframes turn { 0% { transform: rotate(-90deg) scale(0.6); opacity: 0; } 25% { opacity: 1; } 75% { transform: rotate(270deg) scale(1); opacity: 1; } 100% { transform: rotate(270deg) scale(0.6); opacity: 0; } }
@keyframes settle { to { opacity: 1; transform: scale(1); } }

@media (prefers-reduced-motion: reduce) {
  .mark.drip .drop, .mark .ring, .card.hero::before, .btn .splash, .checks svg { animation: none !important; }
  .mark .ring { display: none; }
  .badge.done .wrench { display: none; }
  .badge.done .tick { animation: none; opacity: 1; transform: none; }
}
/* admin: banners, the add tabs, notes, the storage meter */
.banner { border-radius: 12px; padding: 12px 14px; margin: 0 0 16px; line-height: 1.5; display: flex; flex-wrap: wrap; gap: 10px; align-items: center; justify-content: space-between; }
.banner.soft { background: #fff3d6; color: #6b4a00; border: 1px solid #f0d58f; }
.banner.red { background: #fbe9e7; color: #8c1d16; border: 1px solid #efb4ad; }
.mode-tabs { margin-bottom: 12px; }
.item .notes { background: var(--bg); border-radius: 10px; padding: 8px 10px; white-space: pre-wrap; overflow-wrap: anywhere; font-size: 15px; }
.item .notes-edit { display: grid; gap: 8px; }
.item .notes-edit textarea { min-height: 70px; }
.tag.method { background: #e6f0e9; color: #2a5a3b; }
.stripe-link { font-size: 14px; color: var(--accent); text-decoration: none; overflow-wrap: anywhere; }
.meter-box { display: grid; gap: 8px; margin: 0 0 16px; }
.meter { height: 12px; border-radius: 999px; background: var(--bg); border: 1px solid var(--line); overflow: hidden; }
.meter span { display: block; height: 100%; background: var(--ok); border-radius: 999px; min-width: 3px; }
.meter.soft span { background: #d99a17; }
.meter.red span { background: var(--danger); }
.meter-box .sub { color: var(--soft); font-size: 14px; }
.pair-inline { display: grid; grid-template-columns: minmax(0, 1fr) 84px; gap: 8px; }
.test-toggle { margin: -4px 0 12px; font-size: 15px !important; min-height: 36px !important; color: var(--soft) !important; }
/* the line under the Pay button: one line where it fits */
.fine.one-line { max-width: none; text-wrap: balance; }
.list-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 12px; margin: 0 0 10px; }
.list-head h2 { margin: 0; }
.downloads { margin: 0; color: var(--soft); font-size: 15px; display: flex; gap: 8px; align-items: center; }
.panel.search { padding: 14px 16px; }
.panel.search .row-actions { margin-top: 12px; }
details.fills summary { cursor: pointer; }
details.fills ul { margin: 6px 0 0; padding-left: 18px; }
details.fills code, .hint code { font-size: 13px; }
#site details ol { margin: 6px 0; padding-left: 20px; }
.travel-add { margin: 10px 0 0; }
.linklike { background: none; border: 0; padding: 4px 0; color: var(--accent); font: 600 15px var(--sans); cursor: pointer; min-height: 32px; }
.linklike:hover { text-decoration: underline; }

/* admin: orders (state chips, the order page, its sticky action bar and history) and customers */
.page-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 14px; }
.page-head h1 { margin: 8px 0 4px; }
.tag.st-unpaid { background: #fff3d6; color: #7a5300; }
.tag.st-link_sent { background: var(--accent-wash); color: var(--accent); }
.tag.st-link_expired { background: #fbeee0; color: #8a4a12; }
.tag.st-paid { background: #e3f3ea; color: var(--ok); }
.tag.st-refunded, .tag.st-partly_refunded { background: #ece7f8; color: #4b3a8a; }
.tag.st-cancelled { background: var(--line); color: var(--soft); }
.tag.sent { background: var(--bg); color: var(--soft); border: 1px solid var(--line); font-weight: 650; }
.tag.flag { background: #fbe9e7; color: var(--danger); }
.tag.from { background: #eef3e6; color: #4a6620; font-weight: 650; }
.tag.big { font-size: 14px; padding: 4px 12px; }
a.item.order-link { color: inherit; text-decoration: none; transition: border-color 0.15s, box-shadow 0.15s; }
a.item.order-link:hover, a.item.order-link:focus-visible { border-color: var(--accent); box-shadow: var(--shadow); }
.back { margin: 0 0 4px; }
.back a { color: var(--accent); font-weight: 650; text-decoration: none; }
.order-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; }
.order-head h1 { margin: 4px 6px 2px 0; letter-spacing: 0.5px; }
.admin > .sub, .order > .sub { color: var(--soft); margin: 4px 0 14px; }
.panel-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.panel-head h2 { margin: 0; }
.icon-btn { display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: 999px; border: 1px solid var(--line); background: var(--card); color: var(--accent); cursor: pointer; }
.icon-btn svg { width: 20px; height: 20px; }
.icon-btn:hover { border-color: var(--accent); }
.contact-lines { display: flex; flex-wrap: wrap; gap: 8px 10px; align-items: center; }
.contact-lines .who { width: 100%; font-weight: 700; font-size: 18px; color: var(--ink); }
.suggest + label, .grid.travel, .travel-add + .grid { margin-top: 14px; }
.contact-lines .sub { width: 100%; margin: 0; color: var(--soft); font-size: 14px; }
.contact-form { display: grid; gap: 12px; }
.contact-form label { margin: 0 !important; }
.panel .notes { background: var(--bg); border-radius: 10px; padding: 8px 10px; white-space: pre-wrap; overflow-wrap: anywhere; margin: 12px 0 0; }
.panel .sub a { color: var(--accent); }
.history { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.history li { padding: 10px 0 10px 18px; border-left: 2px solid var(--line); position: relative; }
.history li::before { content: ""; position: absolute; left: -6px; top: 15px; width: 10px; height: 10px; border-radius: 50%; background: var(--card); border: 2px solid var(--accent); }
.history li.flagged::before { border-color: var(--danger); }
.history .h-top { display: flex; flex-wrap: wrap; gap: 2px 10px; align-items: baseline; justify-content: space-between; }
.history .sub { color: var(--soft); font-size: 14px; overflow-wrap: anywhere; }
body.has-bar main.admin { padding-bottom: calc(110px + env(safe-area-inset-bottom)); }
.action-bar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 5; background: color-mix(in srgb, var(--card) 94%, transparent); backdrop-filter: blur(8px);
  border-top: 1px solid var(--line); box-shadow: 0 -8px 24px rgba(24, 35, 45, 0.08); padding: 10px 16px calc(10px + env(safe-area-inset-bottom)); }
/* on a phone the actions sit two by two, under the thumb; on a desktop they fit one row */
.action-bar .in { max-width: 920px; margin: 0 auto; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.action-bar .btn { min-width: 0; padding: 0 10px; }
.action-bar .btn.more { grid-column: 1 / -1; }
.action-bar .bar-hint { grid-column: 1 / -1; margin: 0; text-align: center; font-size: 13px; }
.action-bar .bar-hint button { font-size: 13px; min-height: 0; }
@media (min-width: 560px) { .action-bar .in { display: flex; gap: 10px; } .action-bar .btn { flex: 1 1 0; } .action-bar .btn.more { flex: 0 0 auto; padding: 0 18px; } }
.sheet-list { display: grid; gap: 10px; }
.sheet-list .btn { width: 100%; }
.sheet .to { margin: 0 0 6px; overflow-wrap: anywhere; }
.sheet .field span span { font-weight: 700; color: var(--ink); }
.sheet textarea, .sheet input, .sheet select { font-size: 16px; }
fieldset.taxes { border: 0; padding: 0; margin: 14px 0 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 0 18px; align-items: start; }
fieldset.taxes legend { font-size: 14px; font-weight: 600; color: var(--soft); padding: 0; margin-bottom: 2px; }
fieldset.taxes label.check { margin: 0 !important; }
.chosen { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; background: var(--accent-wash); color: var(--ink); border-radius: 12px; padding: 8px 12px; margin: 0 0 12px; }
.suggest { list-style: none; margin: 6px 0 0; padding: 4px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); box-shadow: var(--shadow); display: grid; gap: 2px; }
.suggest button { width: 100%; text-align: left; display: grid; gap: 2px; padding: 10px 12px; min-height: 48px; border: 0; border-radius: 10px; background: none; font: 16px var(--sans); color: var(--ink); cursor: pointer; }
.suggest button:hover, .suggest button:focus-visible { background: var(--accent-wash); }
.suggest .sub { color: var(--soft); font-size: 14px; }
.suggest button.new { color: var(--accent); font-weight: 650; }
.quick { margin: 0 0 16px; }
.details { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 8px 16px; margin: 0; }
.details dt { color: var(--soft); font-weight: 600; }
.details dd { margin: 0; overflow-wrap: anywhere; }
.addresses { list-style: none; margin: 0 0 12px; padding: 0; display: grid; gap: 8px; }
.addresses li { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; overflow-wrap: anywhere; }
.addresses a { color: var(--ink); }
.addresses .remove { margin-left: auto; color: var(--danger); }
.addr-add { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; }
.customer textarea#notes { width: 100%; }
.alike { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 12px; width: 100%; }
.customer section > h2, .customer .list-head { margin-top: 8px; }
.customer section { margin-bottom: 18px; }
.tag.repeat { background: #e6f0e9; color: #2a5a3b; }
.item .sub b { color: var(--ink); font-weight: 650; }
.customer #meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.stat-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 16px 28px; }
.stat-cols h2 { font-size: 16px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--soft); margin: 0 0 8px; }
.stats .hint { margin-top: 14px; }
/* Settings: chip editors and the photo tiles */
.chip-edit { margin-top: 14px; display: grid; gap: 8px; }
.chip-label { font-size: 14px; font-weight: 600; color: var(--soft); }
.chip-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.chip-list li { display: inline-flex; align-items: center; gap: 2px; padding: 2px 4px 2px 12px; border-radius: 999px; background: var(--accent-wash); color: var(--accent); font-weight: 650; font-size: 15px; }
.chip-x { width: 32px; height: 32px; border: 0; border-radius: 50%; background: none; color: inherit; font-size: 20px; line-height: 1; cursor: pointer; }
.chip-x:hover { background: rgba(0, 0, 0, 0.06); }
.chip-add { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; }
/* Print and share: the design chooser and the previews of what will come out of the printer */
.design-pick { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px; margin: 10px 0 14px; }
.design { text-align: left; background: #fff; border: 1px solid var(--line); border-radius: 12px; padding: 10px 12px; cursor: pointer; font: inherit; color: inherit; }
.design b { display: block; margin-bottom: 2px; }
.design span { font-size: 13px; color: var(--soft); }
.design.on { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.print-preview { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-items: start; }
.print-preview.wide { grid-template-columns: 1fr 1fr; }
.pp-side { background: #fff; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; line-height: 0; min-height: 60px; }
.pp-side svg { width: 100%; height: auto; display: block; }
.pp-side.small { max-width: 180px; }
/* a preview that could not be drawn says so in one line, inside its own box, with a way to try again */
.pp-error { line-height: 1.45; padding: 14px; display: grid; gap: 10px; place-items: start; }
.pp-error p { margin: 0; font-size: 13px; color: var(--soft); }
@media (max-width: 560px) { .print-preview { grid-template-columns: 1fr; } }
/* An (i) beside a label, and the small note it opens. A button, so it works on a phone as well as under a mouse. */
.with-info { display: inline-flex; align-items: center; gap: 6px; }
button.info { width: 18px; height: 18px; flex: none; border-radius: 50%; border: 1px solid var(--accent); background: none;
  color: var(--accent); font: 600 11px/1 system-ui, sans-serif; cursor: pointer; padding: 0; display: inline-flex; align-items: center; justify-content: center; }
button.info::after { content: ""; position: absolute; width: 44px; height: 44px; margin: -13px;   /* a finger-sized target */ }
label:has(> .with-info) { position: relative; }
.info-pop { position: absolute; z-index: 30; left: 0; top: calc(100% + 6px); max-width: 320px; background: var(--card, #fff);
  border: 1px solid var(--line); border-radius: 10px; box-shadow: 0 8px 24px rgb(20 35 50 / 0.16); padding: 10px 12px;
  font-size: 13px; line-height: 1.45; color: var(--soft); font-weight: 400; }
/* The domain line in Settings: quiet until the date is close, then amber, then red */
.domain-line { margin: -4px 0 14px; font-size: 14px; color: var(--soft); }
.domain-line.amber { color: #8a5a06; font-weight: 600; }
.domain-line.red { color: var(--danger, #a3301f); font-weight: 600; }
.domain-line:empty { display: none; }

/* one line a credential: the name takes the room, the two switches and the three buttons sit centred on it */
.cred-list { list-style: none; margin: 10px 0 12px; padding: 0; display: grid; gap: 12px; }
.cred-list li { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 14px; }
.cred-list li > input { flex: 1 1 220px; min-width: 0; margin: 0; }
.cred-list .check { display: inline-flex; align-items: center; gap: 6px; margin: 0; white-space: nowrap; font-size: 14px; }
.cred-list .check input { margin: 0; }
.cred-list .row-actions { margin: 0; gap: 4px; align-items: center; }
.cred-list .row-actions button { width: 32px; height: 32px; display: inline-grid; place-items: center; font-size: 15px; line-height: 1; padding: 0; border-radius: 8px; }
.cred-list .row-actions button.remove { width: auto; padding: 0 10px; }
.cred-list .row-actions button:disabled { opacity: 0.35; }
/* on a phone the controls drop under the name, left aligned */
@media (max-width: 620px) {
  .cred-list li > input { flex: 1 1 100%; }
  .cred-list li { gap: 8px 12px; }
}



/* Settings > Team: one tidy card a person. Name and title on the first row, phone and email on the second, the
   Active switch and Remove at the side. Every box carries its own small label, because a filled-in placeholder
   tells you nothing. On a phone it all stacks. */
.person-list { list-style: none; margin: 10px 0 12px; padding: 0; display: grid; gap: 12px; }
.person { border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; background: #fff;
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px 16px; align-items: start; }
.person.short { border-color: #d8b36a; background: #fffdf6; }
.person-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px; min-width: 0; align-items: start; }
.person-side { display: grid; gap: 8px; justify-items: start; }
.person-side .check { display: inline-flex; align-items: center; gap: 6px; margin: 0; white-space: nowrap; font-size: 14px; }
.person-side .check input { margin: 0; }
.person-side .row-actions { margin: 0; }
.person-flag { grid-column: 1 / -1; margin: 0; font-size: 13px; font-weight: 600; color: #8a5a06; }
.person-flag:empty { display: none; }
.person-add { display: grid; grid-template-columns: 1fr 1fr 1fr auto; gap: 10px 14px; align-items: end; margin: 10px 0 6px; }
.person-add .btn { margin-bottom: 2px; }
/* a labelled box: the label small above it, the helper and the message quiet under it */
.person .fld, .person-add .fld { display: grid; gap: 4px; margin: 0; font-size: 13px; font-weight: 600; color: var(--soft); min-width: 0; }
.person .fld > input, .person-add .fld > input { margin: 0; font-size: 16px; font-weight: 400; color: var(--ink); }
.person .fld > .hint, .person-add .fld > .hint { margin: 0; font-size: 12px; font-weight: 400; }
.person .fld > .bad, .person-add .fld > .bad { font-size: 12px; font-weight: 600; color: var(--danger, #a3301f); }
.person .fld > .bad:empty, .person-add .fld > .bad:empty { display: none; }
@media (max-width: 620px) {
  .person, .person-fields, .person-add { grid-template-columns: minmax(0, 1fr); }
  .person-side { justify-items: start; }
  .person-add .btn { justify-self: start; margin-top: 2px; }
}



/* A photo, larger: the slide as it is shown in the strip, over a dimmed page. The button is the whole slide, so a
   tap anywhere on it opens, and the pictures are never drawn past about a quarter again their own pixels. */
.lb-open { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; background: none; padding: 0;
  cursor: zoom-in; -webkit-tap-highlight-color: transparent; }
.lb-open:focus-visible { outline: 3px solid var(--accent); outline-offset: -3px; }
.lightbox { border: 0; padding: 0; background: none; max-width: 100vw; max-height: 100vh; width: 100%; height: 100%;
  overflow: auto; overscroll-behavior: contain; display: grid; place-items: center; }
.lightbox:not([open]) { display: none; }
.lightbox::backdrop { background: rgb(8 16 24 / 0.82); }
.lightbox .lb-body { margin: auto; max-width: 94vw; }
/* the slide keeps the shape it has in the strip, so a pair stays a pair and nothing is left ragged; the words sit
   on the picture, as they do on the page */
.lightbox figure { margin: 0; border-radius: var(--radius); overflow: hidden; background: #0d1620; position: relative; }
.lightbox figure img { width: 100%; height: 100%; object-fit: cover; display: block; }
.lightbox figcaption { position: absolute; left: 0; right: 0; bottom: 0; padding: 26px 16px 12px; color: #fff;
  background: linear-gradient(to top, rgb(8 16 24 / 0.78), rgb(8 16 24 / 0)); font-weight: 650; }
.lightbox figure.ba { display: grid; grid-template-columns: 1fr 1fr; column-gap: 3px; }
.lightbox figure.trio { display: grid; grid-template-columns: 1fr 1fr 1fr; column-gap: 3px; }
.lightbox figure.ba .half, .lightbox figure.trio .third { position: relative; min-width: 0; line-height: 0; }
.lightbox figure.fit img { object-fit: contain; background: #0d1620; }
.lightbox .lb-close { position: fixed; z-index: 2; top: 10px; right: 10px; width: 44px; height: 44px; border-radius: 50%;
  border: 0; background: rgb(255 255 255 / 0.92); color: var(--ink); font: 700 20px/1 system-ui, sans-serif; cursor: pointer; }
.lightbox .lb-close::before { content: "\00d7"; }
@media (max-width: 620px) { .lightbox .lb-body { max-width: 100vw; width: 100% !important; } }



/* Privacy and Terms: the home card's own head (mark, wordmark, the blue line along the top and the skyline along
   the bottom), then a column of plain words at a comfortable width. */
.policy-card .wordmark { font-size: clamp(26px, 5.5vw, 34px); margin-bottom: 4px; }
.policy-title { font-size: clamp(21px, 4.6vw, 26px); color: var(--accent); margin: 0 0 6px; }
.policy-card .section-sub { text-align: center; margin: 0 0 4px; }
.policy-card .updated { text-align: center; margin: 0 0 18px; }
.policy-body { max-width: 640px; margin: 0 auto; text-align: left; }
.policy { margin: 0 0 22px; scroll-margin-top: 16px; }
.policy h2 { font-size: 19px; color: var(--accent); margin: 26px 0 8px; text-align: left; }
.policy p { margin: 0 0 10px; color: var(--soft); line-height: 1.6; }
.policy-toc { margin: 0 0 8px; padding: 12px 16px; border-radius: 12px; background: var(--accent-wash); }
.policy-toc .toc-head { margin: 0 0 6px; font-weight: 700; color: var(--ink); font-size: 14px; }
.policy-toc ul { margin: 0; padding-left: 18px; display: grid; gap: 4px; }
.policy-toc a { color: var(--accent); }
.policy-card .reach.centre { text-align: center; margin: 22px 0 10px; }
.policy-card .actions { margin-top: 4px; }
.foot a { color: var(--soft); }


/* a separator between words, with the same air on both sides wherever it is used: a space either side of a dot is
   at the mercy of how the words end, which is how "New West· Port Moody" happens */
.dot { display: inline-block; padding: 0 0.26em; color: inherit; opacity: 0.55; }

.fine.reach { margin-top: 12px; }
.fine.reach a { color: var(--accent); font-weight: 650; }


/* Settings, read a section at a time: the sections across the top, a box to find a setting, and a bar along the
   bottom that only shows up once something has changed. */
/* On a wide screen the title and the finder share one line. On a phone the finder is simply a full-width box of its
   own under the title: one tap, nothing to open first. */
.find-head { display: block; }                       /* a phone reads it as title, then the pill, then the words */
.find-head h1 { margin-bottom: 4px; }
@media (min-width: 900px) {
  /* the pill shares the title's line only: the line under it runs the full width, on one line */
  .find-head { display: flex; flex-wrap: nowrap; align-items: center; justify-content: space-between; gap: 12px 24px; }
  .find-head h1 { margin: 8px 0 4px; }
  .find-head .settings-find { flex: 0 0 280px; margin: 0; }
}
.settings-top { display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: center; justify-content: space-between; margin: 4px 0 14px; }
.settings-nav { display: flex; flex-wrap: wrap; gap: 4px; }
.settings-nav a { padding: 8px 12px; border-radius: 999px; color: var(--soft); text-decoration: none; font-weight: 650; font-size: 15px; white-space: nowrap; min-height: 40px; display: inline-flex; align-items: center; }
.settings-nav a[aria-current="page"] { background: var(--accent-wash); color: var(--accent); }
/* one treatment for both: a rounded pill with the glass in it, beside the title on a desktop and a slim full-width
   pill under the title on a phone */
.settings-find { display: block; margin: 10px 0 0; }
.find-pill { display: flex; align-items: center; gap: 8px; height: 44px; padding: 0 14px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--card); color: var(--soft); }
.find-pill:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-wash); }
.find-pill svg { flex: none; }
.settings-find input { margin: 0; width: 100%; border: 0; background: none; padding: 0; height: 42px; font-size: 16px; box-shadow: none; }
.settings-find input:focus { outline: none; box-shadow: none; }
.settings-find input::-webkit-search-cancel-button { cursor: pointer; }
#find-count { margin: -6px 0 12px; }
.save-bar { position: sticky; bottom: 0; z-index: 5; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 8px 14px; margin: 18px -4px 0; padding: 12px 16px; border-radius: 14px; background: color-mix(in srgb, var(--card) 96%, transparent);
  backdrop-filter: blur(8px); box-shadow: 0 -2px 18px rgb(20 35 50 / 0.16); border: 1px solid var(--line); }
.save-bar .row-actions { margin: 0; }
.save-what { margin: 0; font-weight: 650; color: var(--ink); }
body.has-bar .save-bar { bottom: calc(58px + env(safe-area-inset-bottom)); }
@media (max-width: 699px) { .save-bar { bottom: calc(58px + env(safe-area-inset-bottom)); } }




/* Settings > Photos: one tile a slide, the way the page shows them. The pictures sit along the top, then one
   caption, then one row of things to do with the whole slide. */
.slide-list { list-style: none; margin: 10px 0 12px; padding: 0; display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.slide { border: 1px solid var(--line); border-radius: 12px; background: #fff; padding: 10px; display: grid; gap: 8px; align-content: start; }
.slide.drop-here { outline: 2px dashed var(--accent); outline-offset: 2px; }
.slide.off .shots { opacity: 0.4; filter: grayscale(1); }
.slide-top { position: relative; }
.slide .grip { position: absolute; left: 6px; top: 6px; z-index: 1; width: 26px; height: 26px; border-radius: 8px;
  background: rgb(255 255 255 / 0.88); color: var(--soft); display: grid; place-items: center; cursor: grab; font-size: 14px; }
.slide .shots { display: grid; gap: 2px; width: 100%; border: 0; padding: 0; background: none; border-radius: 10px; overflow: hidden; cursor: zoom-in; }
.slide .shots.n1 { grid-template-columns: 1fr; }
.slide .shots.n2 { grid-template-columns: 1fr 1fr; }
.slide .shots.n3 { grid-template-columns: 1fr 1fr 1fr; }
.slide .shots img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; background: var(--accent-wash); }
.slide .shots.n2 img { aspect-ratio: 2 / 3; }
.slide .shots.n3 img { aspect-ratio: 4 / 9; }
.slide .shots:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.slide .off-tag { position: absolute; right: 6px; top: 6px; padding: 1px 8px; border-radius: 999px;
  background: rgb(20 35 50 / 0.82); color: #fff; font-size: 11px; font-weight: 700; }
.slide-caption { margin: 0; }
.slide-caption-fixed { margin: 0; font-weight: 650; color: var(--ink); }
.slide-actions { margin: 0; gap: 10px; align-items: center; flex-wrap: wrap; }
.slide-actions .spacer { flex: 1 1 auto; }
.slide-edit { display: grid; gap: 8px; border-top: 1px solid var(--line); padding-top: 8px; }
.slide-edit .row-actions.wrap { margin: 0; flex-wrap: wrap; gap: 4px 14px; align-items: center; }
.slide-edit .sub, .slide .sub { font-size: 13px; line-height: 1.45; margin: 0; }
.slide-edit label.file-swap { display: inline-flex !important; align-items: center; margin: 0 !important;
  font-size: 15px !important; font-weight: 650 !important; }
.slide-edit .fld { gap: 2px; }
.slide-edit .fld > input { font-size: 15px; }
.slide .phone-only { display: none; }
@media (max-width: 699px) { .slide .phone-only { display: inline; } .slide .grip { display: none; } }


.sig-paste { border: 1px solid var(--line); border-radius: 12px; padding: 14px; background: #fff; margin: 10px 0; overflow-x: auto; }
.sig-paste table { margin-top: 0 !important; }

.photo-grid .pairing { display: grid; gap: 6px; margin-top: 6px; }
.photo-grid .pairing select { width: 100%; font-size: 14px; }
.photo-grid figure.paired { outline: 2px solid var(--accent-wash); outline-offset: 2px; }
/* a tile is picked up and dropped on another to move it; tapping the picture opens it larger */
.photo-grid figure[draggable="true"] { cursor: grab; }
.photo-grid figure.drop-here { outline: 2px dashed var(--accent); outline-offset: 2px; }
.photo-grid .tile-open { display: block; width: 100%; padding: 0; border: 0; background: none; cursor: zoom-in; border-radius: 10px; }
.photo-grid .tile-open:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.photo-grid .file-swap { cursor: pointer; }
/* a photo he has put away: still his, just not on the site */
.photo-grid figure.off img { opacity: 0.4; filter: grayscale(1); }
.photo-grid figure.off .off-tag { position: absolute; right: 6px; top: 6px; padding: 1px 8px; border-radius: 999px;
  background: rgb(20 35 50 / 0.82); color: #fff; font-size: 11px; font-weight: 700; }

/* Two pictures inside one slide, side by side, with nothing written over them. The slide keeps the same shape as a
   single photo, so the strip does not jump. */
.strip figure.ba { display: grid; grid-template-columns: 1fr 1fr; column-gap: 2px; }
.strip figure.ba .half { position: relative; min-width: 0; line-height: 0; }
.strip figure.trio { display: grid; grid-template-columns: 1fr 1fr 1fr; column-gap: 2px; }
.strip figure.trio .third { position: relative; min-width: 0; line-height: 0; }
/* a picture too small to fill the slide sits inside it on a soft ground, rather than being blown up or cropped */
.strip figure.fit { background: var(--accent-wash); }
.strip figure.fit img { width: 100%; height: 100%; object-fit: contain; }
.sub-head { font-size: 17px; margin: 22px 0 4px; }
.photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; margin-top: 10px; }
.photo-grid:empty { display: none; }
.photo-grid figure { margin: 0; display: grid; gap: 4px; position: relative; }
.photo-grid img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: 10px; background: var(--accent-wash); }
.photo-grid.round img { width: 112px; aspect-ratio: 1; border-radius: 50%; }
.photo-grid input { font-size: 14px !important; height: 36px !important; padding: 4px 8px; }
.photo-grid figcaption { position: absolute; left: 6px; top: 6px; padding: 0 7px; border-radius: 999px; background: rgba(255, 255, 255, 0.9); font-size: 12px; font-weight: 700; color: var(--soft); }
.file-btn { cursor: pointer; }
details.sources { margin-top: 10px; }
details.sources ul { margin: 6px 0 0; padding-left: 18px; }

/* the admin's own navigation: a top row on a desktop, a tab bar within thumb reach on a phone */
.admin-top nav a > span { display: inline; }
.admin-top nav a .ext { display: inline-block; margin-left: 5px; vertical-align: -1px; opacity: 0.8; }
.tabbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 6; display: grid; grid-template-columns: repeat(4, 1fr);
  background: color-mix(in srgb, var(--card) 95%, transparent); backdrop-filter: blur(8px); border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom); }
.tabbar a { position: relative; display: grid; justify-items: center; gap: 2px; padding: 8px 4px 6px; min-height: 58px; color: var(--soft); text-decoration: none; font-size: 12px; font-weight: 650; }
.tabbar a svg { width: 24px; height: 24px; }
.tabbar a[aria-current="page"] { color: var(--accent); }
.tabbar .count { position: absolute; top: 4px; left: 50%; margin-left: 4px; }
@media (min-width: 700px) { .tabbar { display: none; } }
/* between a small laptop and a tablet the six items and the business name will not share one line: the name keeps
   the top row and the navigation takes its own, centred, instead of crowding or spilling off the side */
@media (min-width: 700px) and (max-width: 919px) {
  .admin-top .in { gap: 6px 10px; }
  .admin-top .name { min-width: 0; }
  .admin-top .name #biz { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .admin-top nav { flex: 1 0 100%; justify-content: center; gap: 2px; }
  .admin-top nav a { padding: 7px 9px; font-size: 14px; }
}
@media (max-width: 699px) {
  .admin-top nav { display: none; }
  .admin-top .in { justify-content: center; }
  body { padding-bottom: calc(58px + env(safe-area-inset-bottom)); }
  body.has-bar .action-bar { bottom: calc(58px + env(safe-area-inset-bottom)); }
}
/* a file-picking label is a button, not a stacked field */
.panel label.file-btn { display: inline-flex !important; align-items: center; justify-content: center; gap: 10px;
  font-size: 15px !important; font-weight: 700 !important; color: var(--accent) !important; }
/* the three ways to add a photo read as one row of equal buttons, and wrap tidily on a phone */
.add-photos { flex-wrap: wrap; align-items: stretch; gap: 8px 10px; }
.add-photos .file-btn { flex: 0 1 auto; min-height: 40px; padding: 8px 16px !important; margin: 0 !important; text-align: center; }
@media (max-width: 520px) { .add-photos .file-btn { flex: 1 1 100%; } }

/* a list that is a table on a desktop and a stack of row-cards on a phone (the same cells, same order) */
.table-wrap { overflow-x: auto; }
table.rows { width: 100%; border-collapse: collapse; font-size: 15px; }
table.rows th { text-align: left; font-size: 13px; letter-spacing: .4px; text-transform: uppercase; color: var(--soft); padding: 0 12px 8px; white-space: nowrap; }
table.rows th.num, table.rows td.num { text-align: right; font-variant-numeric: tabular-nums; }
table.rows td { padding: 12px; border-top: 1px solid var(--line); background: var(--card); }
table.rows tr.row-open { cursor: pointer; }
table.rows tr.row-open:hover td, table.rows tr.row-open:focus-visible td { background: var(--accent-wash); }
table.rows tr.row-open td:first-child { border-radius: 10px 0 0 10px; }
table.rows tr.row-open td:last-child { border-radius: 0 10px 10px 0; }
table.rows .name-cell { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
table.rows a { color: var(--accent); }
@media (max-width: 699px) {
  table.rows, table.rows tbody, table.rows tr, table.rows td { display: block; width: 100%; }
  table.rows thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  table.rows tr.row-open { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); margin-bottom: 10px; padding: 6px 4px; }
  table.rows td { border: 0; padding: 6px 12px; display: flex; justify-content: space-between; align-items: baseline; gap: 12px; text-align: right; }
  table.rows td::before { content: attr(data-label); color: var(--soft); font-size: 13px; font-weight: 650; text-align: left; }
  table.rows td[data-label="Name"] { padding-top: 8px; }
  table.rows td[data-label="Name"]::before { display: none; }
  table.rows td[data-label="Name"] { justify-content: flex-start; font-size: 17px; }
  table.rows tr.row-open:hover td { background: transparent; }
  table.rows tr.empty-row { border: 0; }
}
.lines .paid-so-far dd { color: var(--ok); }
/* the payments on a work order */
.pay-rows { display: grid; gap: 10px; }
.pay-row { border: 1px solid var(--line); border-radius: var(--radius); padding: 10px 12px; display: grid; gap: 4px; }
.pay-row .pay-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pay-row .pay-top b { font-size: 18px; }
.pay-row .pay-top .sub { margin-left: auto; color: var(--soft); font-size: 14px; }
.pay-row .row-actions { margin-top: 2px; }
.pay-row .row-actions:empty { display: none; }
.tax-hint { margin: -2px 0 12px; }
.email-block .sig-warn { margin: 10px 0 0; font-weight: 500; }
.email-block .sig-warn .linklike { font-weight: 700; }
/* paying on the spot: the QR fills the screen, as high-contrast as the display allows */
.action-bar .in { flex-wrap: wrap; }
.action-bar .bar-note { width: 100%; margin: 0 0 6px; text-align: center; color: var(--soft); font-size: 14px; font-weight: 650; }
/* his own notes on a work order */
.note-add { display: grid; gap: 8px; }
.note-add textarea { min-height: 62px; }
.note-add .row-actions { margin-top: 0; align-items: center; }
.tag.notes-mark { background: #fdf3df; color: #7a5300; }
/* the pay page: what was done, and any updates he has chosen to show */
.card .done { margin: 2px auto 6px; color: var(--ink); max-width: 38ch; white-space: pre-line; }
.updates { text-align: left; max-width: 420px; margin: 0 auto 20px; padding: 12px 14px; background: var(--bg); border-radius: var(--radius); }
.updates h2 { font-size: 15px; letter-spacing: .4px; text-transform: uppercase; color: var(--soft); margin: 0 0 8px; }
.updates div { margin: 0 0 8px; }
.updates div:last-child { margin-bottom: 0; }
.updates .when { display: block; color: var(--soft); font-size: 13px; }
/* the two kinds of words on a work order */
.note-add .check { min-height: 40px; }
/* what the form says when something needs a second look */
.field-note { display: block; margin-top: 4px; color: var(--danger); font-size: 14px; font-weight: 600; text-align: left; }
.form input[aria-invalid="true"] { border-color: var(--danger); }
.qr-screen { position: fixed; inset: 0; z-index: 20; background: #fff; display: grid; align-content: center; justify-items: center; gap: 10px; padding: 20px; }
.qr-screen .qr-close { position: absolute; top: 12px; right: 12px; }
.qr-box { width: min(78vw, 78vh, 460px); }
.qr-box svg { width: 100%; height: auto; display: block; }
.qr-amount { font-size: clamp(34px, 9vw, 54px); font-weight: 750; margin: 6px 0 0; font-variant-numeric: tabular-nums; }
.qr-ref { margin: 0; color: var(--soft); font-size: 18px; letter-spacing: .5px; }
.qr-tell { margin: 4px 0 0; color: var(--soft); }
.qr-done { position: absolute; inset: 0; background: #fff; display: grid; align-content: center; justify-items: center; gap: 14px; }
.qr-done .tick { width: 120px; height: 120px; border-radius: 50%; background: var(--ok); color: #fff; font-size: 70px; line-height: 120px; text-align: center; }
.qr-done p { font-size: clamp(20px, 5.6vw, 30px); font-weight: 750; margin: 0; text-align: center; padding: 0 16px; text-wrap: balance; }
.action-bar .in { flex-wrap: wrap; }
.action-bar .bar-note { width: 100%; margin: 0 0 6px; text-align: center; color: var(--soft); font-size: 14px; font-weight: 650; }
/* his own notes on a work order */
.note-add { display: grid; gap: 8px; }
.note-add textarea { min-height: 62px; }
.note-add .row-actions { margin-top: 0; align-items: center; }
.notes-log { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 10px; }
.notes-log li { background: var(--bg); border-radius: 12px; padding: 10px 12px; }
.notes-log .note-top { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; margin-bottom: 4px; }
.notes-log .note-top .sub { margin-right: auto; font-size: 13px; }
.notes-log .note-text { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.notes-log textarea { width: 100%; margin-top: 6px; }
.tag.notes-mark { background: #fdf3df; color: #7a5300; }
/* the pay page: what was done, and any updates he has chosen to show */
.card .done { margin: 2px auto 6px; color: var(--ink); max-width: 38ch; white-space: pre-line; }
.updates { text-align: left; max-width: 420px; margin: 0 auto 20px; padding: 12px 14px; background: var(--bg); border-radius: var(--radius); }
.updates h2 { font-size: 15px; letter-spacing: .4px; text-transform: uppercase; color: var(--soft); margin: 0 0 8px; }
.updates div { margin: 0 0 8px; }
.updates div:last-child { margin-bottom: 0; }
.updates .when { display: block; color: var(--soft); font-size: 13px; }
/* the two kinds of words on a work order */
.label-tag { font-size: 12px; font-weight: 700; padding: 1px 8px; border-radius: 999px; margin-left: 6px; letter-spacing: .2px; }
.label-tag.shown { background: var(--accent-wash); color: var(--accent); }
.label-tag.private { background: #fdf3df; color: #7a5300; }
.notes-log li.shown { background: var(--accent-wash); }
.notes-log .note-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-top: 8px; }
.notes-log .note-foot .check { min-height: 36px; font-size: 15px !important; }
.notes-log .note-foot .sub { font-size: 13px; }
.note-add .check { min-height: 40px; }
.photo-grid .photo-actions { margin-top: 2px; gap: 10px; font-size: 14px; }
.photo-grid .photo-actions .linklike { font-size: 14px; }
.photo-grid .photo-actions .linklike[disabled] { opacity: 0.4; cursor: default; text-decoration: none; }
.photo-grid figure .sub { margin: 0; font-size: 12px; color: var(--soft); }
/* the sign-off, previewed as the customer will see it */
.sig-block { display: flex; gap: 10px; align-items: flex-start; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); font-size: 13px; line-height: 1.6; color: var(--soft); }
.sig-logo { border-radius: 6px; flex: none; }
.sig-rate { margin-top: 8px; color: #7b8794; }
.mail-preview .sig-block { white-space: normal; }
