/* ─────────────────────────────────────────────────────────────────────────────
   ሓልዮት (Haliot) — Care & Compassion · home to home care and tele-health
   One stylesheet for the public page, the admin panel and the clinician portal.

   The look is meant to read as a careful paper record rather than a tech
   product: warm cream stock, hairline sand rules, and the badge's own colours —
   deep green ink, an orange-red accent taken from the heart, and the gold of its
   highlight — with numbered tabs on the service cards.

   Colours come from the database (`design` settings) and are written onto
   :root at runtime, so an administrator can restyle the site without a deploy.
   The values below are the fallbacks used before that request lands, and they
   are sampled from the logo itself so the two never disagree.
   ──────────────────────────────────────────────────────────────────────────── */

:root {
  --primary: #0f7200; /* the green of the ring */
  --accent: #ee5406; /* the orange-red of the heart */
  --surface: #f6eedc; /* the cream of the disc */
  --ink: #1a2416;
  --radius: 18px;

  /* The extended palette the raised shell needs. Every one of these is
     settable by the administrator (see `applyDesign` in core.js); the values
     here are what the site looks like before that request lands. */
  --deep: #073f00; /* the underside of a raised surface */
  --glow: #5fb326; /* the lit edge along its top */
  --gold: #f2a03a; /* MedCoins, and anything that means money */
  --danger: #c0300a;
  --navbar: #0a5600; /* the two bars, which are darker than the page */
  --btn-face: #178a0a; /* the face of a raised button */

  /* The wordmark on the badge is blue, and nothing else on the page was. It is
     kept for the places that need a third colour — a link inside a green panel,
     a partner button — without reaching for the accent, which means "urgent". */
  --royal: #0b4f9c;
  --royal-soft: #e4eefa;

  --paper: #fffbf1;
  --sand: #eadfc7;
  --sand-deep: #d6c6a4;
  --muted: #5f6b58;
  --primary-soft: #e7f1e2;
  --accent-soft: #fbeadf;
  --good: #2f7a2a;
  --warn: #9a6410;
  --bad: #c0300a;

  --display: 'Fraunces', 'Noto Serif Ethiopic', 'Nyala', Georgia, serif;
  --body: 'Karla', 'Noto Sans Ethiopic', 'Abyssinica SIL', system-ui, sans-serif;
  --ethiopic: 'Noto Sans Ethiopic', 'Abyssinica SIL', 'Nyala', system-ui, sans-serif;
  --ethiopic-display: 'Noto Serif Ethiopic', 'Nyala', 'Abyssinica SIL', serif;

  --shadow-low: 0 1px 2px rgba(26, 36, 22, 0.05), 0 8px 24px -18px rgba(26, 36, 22, 0.35);
  --shadow-high: 0 2px 4px rgba(26, 36, 22, 0.06), 0 28px 60px -32px rgba(26, 36, 22, 0.42);
  --band: 1200px;

  /* How far the two fixed bars stand off the page, and how much relief the
     raised surfaces have. `data-depth` on <html> scales the second one. */
  --bar-top: 64px;
  --bar-bottom: 66px;
  --lift: 1;
  --safe-bottom: env(safe-area-inset-bottom, 0px);
}

/* The administrator's depth setting. `flat` exists for anybody who finds the
   relief distracting, and for a slow device. */
html[data-depth='flat'] {
  --lift: 0;
}
html[data-depth='soft'] {
  --lift: 0.6;
}
html[data-depth='deep'] {
  --lift: 1.35;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

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

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  * {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}

body {
  margin: 0;
  background: var(--surface);
  color: var(--ink);
  font-family: var(--body);
  font-size: 1.0125rem;
  line-height: 1.62;
  /* A faint warm wash at the top so the page does not read as flat white. */
  background-image: radial-gradient(120% 60% at 50% -10%, rgba(15, 114, 0, 0.08), transparent 60%);
  background-repeat: no-repeat;
}

h1,
h2,
h3,
h4 {
  font-family: var(--display);
  font-weight: 600;
  line-height: 1.14;
  letter-spacing: -0.015em;
  margin: 0;
  text-wrap: balance;
}

p {
  margin: 0;
  text-wrap: pretty;
}

a {
  color: var(--primary);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

img {
  max-width: 100%;
  display: block;
}

/* ── nothing may be wider than the telephone it is read on ─────────────────
   Three rules, in the order they matter.

   The first is the backstop: horizontal scrolling of the page itself is never
   correct here, so it is turned off at the root. It is set on <html> and not on
   <body>, deliberately — the value propagates to the viewport either way, but
   putting it on <body> would make <body> a scroll container and every sticky
   header on the site (the top bar, the table headings, the step navigation)
   would quietly stop sticking. `clip` is the same thing without even a
   scrollport; browsers that do not know it keep the `hidden` above it.

   The second stops embedded media doing the pushing. An <img> was already
   capped; a video, a map, a Jitsi frame or an inline SVG was not.

   The third is for the strings that have no spaces in them and therefore cannot
   wrap on their own: a wallet address, a transaction hash, a long reference, a
   generated password. `anywhere` breaks them mid-string rather than letting one
   of them set the width of the page.

   A backstop is not a licence to leave overflow in the layout: everything that
   actually overflowed under 480px is fixed where it happens (the grids collapse
   with `minmax(min(…, 100%), 1fr)`, wide tables scroll inside `.tablewrap`).
   This is here so that the next component added cannot break the page. */
html {
  max-width: 100%;
  overflow-x: hidden;
  overflow-x: clip;
}

body {
  max-width: 100%;
}

video,
canvas,
svg,
iframe,
embed,
object {
  max-width: 100%;
}

pre,
code,
kbd,
samp,
.mono {
  overflow-wrap: anywhere;
}

pre {
  white-space: pre-wrap;
  max-width: 100%;
}

:focus-visible {
  outline: 2.5px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

.wrap {
  width: 100%;
  max-width: var(--band);
  margin-inline: auto;
  padding-inline: clamp(1.1rem, 4vw, 2.5rem);
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--primary);
  color: #fff;
  padding: 0.7rem 1rem;
  z-index: 90;
  border-radius: 0 0 10px 0;
}
.skip:focus {
  left: 0;
}

/* ── trilingual text ───────────────────────────────────────────────────────
   All three languages are always in the document — families read one or
   another, and hiding a translation behind a toggle only splits the audience.
   The toggle changes which one is the headline and which is the whisper, which
   is why a language change costs one class on <html> and never a re-render.

   The chosen language leads (`order: 1`). Of the other two, one follows as a
   quiet second line and the third is hidden: three stacked renditions of every
   heading turns a page into a glossary. Tigrinya and Amharic keep each other
   company; English keeps company with Tigrinya, the language of the service. */

.ti,
.am {
  font-family: var(--ethiopic);
  font-feature-settings: normal;
}
h1 .ti,
h2 .ti,
h3 .ti,
h1 .am,
h2 .am,
h3 .am,
.ti-display {
  font-family: var(--ethiopic-display);
  line-height: 1.35;
}
.en {
  font-family: var(--body);
}

.bi {
  display: flex;
  flex-direction: column;
}
.bi > .ti,
.bi > .am,
.bi > .en {
  display: block;
}

/* The third rendition, out of the way. */
html.lang-ti .bi > .am,
html.lang-am .bi > .en,
html.lang-en .bi > .am {
  display: none;
}

/* The lead. */
html.lang-ti .bi > .ti,
html.lang-am .bi > .am,
html.lang-en .bi > .en {
  order: 1;
}

/* The whisper underneath it. */
html.lang-ti .bi > .en,
html.lang-am .bi > .ti,
html.lang-en .bi > .ti {
  order: 2;
  font-size: 0.86em;
  color: var(--muted);
  font-weight: 400;
  letter-spacing: 0;
  margin-top: 0.28em;
  line-height: 1.5;
}

/* A block with no Amharic rendition — `bi(ti, en)` called with two arguments, or
   markup written before Amharic was added. The rules above would hide the English
   and whisper the Tigrinya, leaving an Amharic reader nothing legible to lead
   with, so English takes the lead instead and Tigrinya stays underneath it. */
html.lang-am .bi:not(:has(> .am)) > .en {
  display: block;
  order: 1;
  font-size: inherit;
  color: inherit;
  font-weight: inherit;
  margin-top: 0;
}

/* Interface strings the shell writes in one language only: `bi()` is for
   content, but a navbar label is a single word and gets `.only` instead. */
.only {
  display: block;
}

/* ── buttons ─────────────────────────────────────────────────────────────── */

.btn {
  --btn-bg: var(--primary);
  --btn-ink: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  padding: 0.82rem 1.35rem;
  min-height: 46px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--btn-bg);
  color: var(--btn-ink);
  font: inherit;
  font-weight: 700;
  font-size: 0.97rem;
  letter-spacing: 0.005em;
  cursor: pointer;
  text-decoration: none;
  transition: transform 0.16s ease, box-shadow 0.16s ease, background 0.16s ease;
  box-shadow: var(--shadow-low);
}
.btn:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-high);
}
.btn:active {
  transform: translateY(0);
}
.btn[disabled],
.btn[aria-busy='true'] {
  opacity: 0.62;
  cursor: progress;
  transform: none;
}
.btn.accent {
  --btn-bg: var(--accent);
}
.btn.ghost {
  --btn-bg: transparent;
  --btn-ink: var(--primary);
  border-color: var(--sand-deep);
  box-shadow: none;
}
.btn.ghost:hover {
  background: var(--paper);
}
.btn.quiet {
  --btn-bg: transparent;
  --btn-ink: var(--muted);
  border-color: transparent;
  box-shadow: none;
  padding-inline: 0.6rem;
  font-weight: 600;
}
.btn.quiet:hover {
  color: var(--ink);
  transform: none;
}
.btn.danger {
  --btn-bg: transparent;
  --btn-ink: var(--bad);
  border-color: rgba(163, 58, 42, 0.35);
  box-shadow: none;
}
.btn.small {
  padding: 0.45rem 0.85rem;
  min-height: 34px;
  font-size: 0.85rem;
}
.btn svg {
  width: 1.05em;
  height: 1.05em;
  flex: none;
}

/* ── header ──────────────────────────────────────────────────────────────── */

.top {
  position: sticky;
  top: 0;
  z-index: 40;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: blur(12px) saturate(140%);
  border-bottom: 1px solid var(--sand);
}
.top-in {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 74px;
  padding-block: 0.6rem;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  text-decoration: none;
  color: inherit;
  flex: none;
}
.brand .mark {
  width: 42px;
  height: 42px;
  flex: none;
  border-radius: 12px;
  object-fit: cover;
  background: var(--primary);
}
.brand .words {
  display: flex;
  flex-direction: column;
  line-height: 1.05;
}
.brand .name {
  font-family: var(--ethiopic-display);
  font-size: 1.32rem;
  font-weight: 700;
  color: var(--primary);
}
.brand .name-en {
  font-family: var(--display);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}

.nav {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  margin-inline-start: auto;
}
.nav a {
  padding: 0.5rem 0.75rem;
  border-radius: 999px;
  text-decoration: none;
  color: var(--muted);
  font-weight: 600;
  font-size: 0.94rem;
}
.nav a:hover {
  color: var(--ink);
  background: var(--paper);
}

.top-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex: none;
}

.langswitch {
  display: inline-flex;
  border: 1px solid var(--sand-deep);
  border-radius: 999px;
  padding: 2px;
  background: var(--paper);
}
.langswitch button {
  border: 0;
  background: transparent;
  font: inherit;
  font-size: 0.84rem;
  font-weight: 700;
  color: var(--muted);
  padding: 0.28rem 0.7rem;
  border-radius: 999px;
  cursor: pointer;
}
.langswitch button[aria-pressed='true'] {
  background: var(--primary);
  color: #fff;
}
.langswitch button:first-child {
  font-family: var(--ethiopic);
}

.menu-toggle {
  display: none;
}

@media (max-width: 940px) {
  .nav {
    position: fixed;
    inset: 74px 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    background: var(--paper);
    border-bottom: 1px solid var(--sand);
    padding: 0.6rem clamp(1.1rem, 4vw, 2.5rem) 1.2rem;
    box-shadow: var(--shadow-high);
    display: none;
  }
  .nav.open {
    display: flex;
  }
  .nav a {
    padding: 0.75rem 0.4rem;
    border-bottom: 1px solid var(--surface);
  }
  .menu-toggle {
    display: inline-flex;
    margin-inline-start: auto;
    border: 1px solid var(--sand-deep);
    border-radius: 12px;
    background: var(--paper);
    width: 42px;
    height: 42px;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: var(--primary);
  }
  .menu-toggle svg {
    width: 20px;
    height: 20px;
  }
  .top-actions .btn.hide-sm {
    display: none;
  }
}

/* ── hero ────────────────────────────────────────────────────────────────── */

.hero {
  padding-block: clamp(2.4rem, 6vw, 4.6rem) clamp(2rem, 5vw, 3.4rem);
}
.hero-in {
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
  gap: clamp(1.6rem, 4vw, 3.4rem);
  align-items: center;
}
@media (max-width: 900px) {
  .hero-in {
    grid-template-columns: minmax(0, 1fr);
  }
}

.kicker {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 1rem;
}
.kicker::before {
  content: '';
  width: 26px;
  height: 2px;
  background: var(--accent);
  border-radius: 2px;
}
.kicker .ti {
  letter-spacing: 0.02em;
  text-transform: none;
  font-size: 0.92rem;
}

.hero h1 {
  font-size: clamp(2.15rem, 5.4vw, 3.5rem);
  margin-bottom: 1rem;
}
.hero h1 .ti {
  color: var(--primary);
}
.hero .lede {
  font-size: 1.06rem;
  color: var(--muted);
  max-width: 46ch;
  margin-bottom: 1.6rem;
}
.hero .lede .ti {
  color: #3f4a47;
}

.motto {
  border-left: 3px solid var(--accent);
  padding: 0.35rem 0 0.35rem 1rem;
  margin-bottom: 1.7rem;
  font-family: var(--ethiopic-display);
  font-size: 1.06rem;
  line-height: 1.6;
  color: var(--primary);
  font-weight: 600;
}

.hero-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  margin-bottom: 2rem;
}

.hero-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 0 clamp(1.4rem, 4vw, 2.6rem);
  border-top: 1px solid var(--sand);
  padding-top: 1.2rem;
}
.hero-stats div {
  padding-block: 0.2rem;
}
.hero-stats b {
  display: block;
  font-family: var(--display);
  font-size: 1.85rem;
  font-weight: 600;
  color: var(--primary);
  line-height: 1.1;
}
.hero-stats span {
  font-size: 0.83rem;
  color: var(--muted);
  max-width: 16ch;
  display: block;
}

/* The card on the right: a "who to call" panel, which is what a worried
   family actually needs first. */
.callcard {
  position: relative;
  background: var(--primary);
  color: #f4f1ea;
  border-radius: calc(var(--radius) + 8px);
  padding: clamp(1.5rem, 3vw, 2.1rem);
  box-shadow: var(--shadow-high);
  overflow: hidden;
  isolation: isolate;
}
.callcard .art {
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0.5;
}
.callcard .art img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.callcard h2 {
  font-size: 1.18rem;
  color: #fff;
  margin-bottom: 0.2rem;
}
.callcard .hint {
  font-size: 0.9rem;
  color: rgba(244, 241, 234, 0.78);
  margin-bottom: 1.2rem;
}
.phones {
  display: grid;
  gap: 0.6rem;
  margin-bottom: 1.2rem;
}
.phone {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 0.85rem 1rem;
  border-radius: 14px;
  background: rgba(255, 253, 249, 0.1);
  border: 1px solid rgba(255, 253, 249, 0.2);
  color: #fff;
  text-decoration: none;
  font-size: 1.28rem;
  font-weight: 700;
  font-family: var(--display);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  transition: background 0.16s ease;
}
.phone:hover {
  background: rgba(255, 253, 249, 0.18);
}
.phone svg {
  width: 20px;
  height: 20px;
  flex: none;
  color: var(--accent);
}
.callcard .hours {
  font-size: 0.88rem;
  color: rgba(244, 241, 234, 0.8);
  border-top: 1px solid rgba(255, 253, 249, 0.18);
  padding-top: 1rem;
}
.callcard .hours .ti {
  display: block;
}

/* ── capability strip ────────────────────────────────────────────────────── */

.strip {
  border-block: 1px solid var(--sand);
  background: var(--paper);
}
.strip-in {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr));
  gap: clamp(1rem, 3vw, 2rem);
  padding-block: 1.9rem;
}
.strip .item {
  display: flex;
  gap: 0.85rem;
}
.strip .item svg {
  width: 22px;
  height: 22px;
  flex: none;
  color: var(--accent);
  margin-top: 0.2rem;
}
.strip .item h3 {
  font-size: 1rem;
  font-family: var(--body);
  font-weight: 700;
  margin-bottom: 0.15rem;
}
.strip .item p {
  font-size: 0.88rem;
  color: var(--muted);
}

/* ── sections ────────────────────────────────────────────────────────────── */

section[id] {
  scroll-margin-top: 92px;
}

.sec {
  padding-block: clamp(3rem, 7vw, 5rem);
}
.sec.tint {
  background: var(--paper);
  border-block: 1px solid var(--sand);
}

.sec-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 2rem;
  margin-bottom: clamp(1.6rem, 4vw, 2.6rem);
}
.sec-head h2 {
  font-size: clamp(1.7rem, 3.6vw, 2.4rem);
}
.sec-head h2 .ti {
  color: var(--primary);
}
.sec-head p {
  color: var(--muted);
  max-width: 42ch;
  font-size: 0.96rem;
}
@media (max-width: 760px) {
  .sec-head {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.8rem;
  }
}

/* ── service cards ───────────────────────────────────────────────────────── */

.services {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(288px, 100%), 1fr));
  gap: clamp(0.9rem, 2vw, 1.35rem);
}

/* The catalogue grid: three columns by five rows, fifteen services to a page.
   Explicit `repeat(3, …)` rather than `auto-fill`, because auto-fill gives four
   narrow columns on a wide monitor and the brief is a three-by-five grid.
   `minmax(0, 1fr)` and not `1fr`: a grid track's default minimum is `auto`,
   which is the content's own minimum width, so one long unbroken word — a URL,
   a service name with no spaces — pushes the track wider than its share and the
   whole grid past the viewport. This is the single most common cause of
   horizontal scroll on a phone, and the `0` is the fix. */
.services.catalog {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (max-width: 900px) {
  .services.catalog {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 560px) {
  .services.catalog {
    grid-template-columns: minmax(0, 1fr);
  }
}

.service {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  background: var(--paper);
  border: 1px solid var(--sand);
  border-radius: var(--radius);
  padding: 1.5rem 1.35rem 1.35rem;
  transition: border-color 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
}
.sec.tint .service {
  background: var(--surface);
}
.service:hover {
  border-color: var(--primary);
  transform: translateY(-2px);
  box-shadow: var(--shadow-low);
}
.service .no {
  position: absolute;
  top: -1px;
  right: 1.1rem;
  font-family: var(--display);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid var(--sand);
  border-top: 0;
  border-radius: 0 0 8px 8px;
  padding: 0.2rem 0.5rem 0.15rem;
}
.service .ico {
  width: 42px;
  height: 42px;
  border-radius: 12px;
  display: grid;
  place-items: center;
  background: var(--primary-soft);
  color: var(--primary);
  flex: none;
}
.service .ico svg {
  width: 22px;
  height: 22px;
}
.service h3 {
  font-size: 1.1rem;
  line-height: 1.3;
}
.service h3 .ti {
  color: var(--primary);
  font-size: 1.12rem;
}
.service p {
  font-size: 0.91rem;
  color: var(--muted);
  flex: 1;
}
.service .foot {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  padding-top: 0.35rem;
}

/* The two triggers on every card. `.stretch` is an invisible anchor covering
   the whole card so the card is still one big target; the actions sit above it
   in the stacking order so their own clicks are not swallowed by it. Both need
   `position: relative` on something — the card already has it. */
.service .stretch {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  text-decoration: none;
}
.service .actions {
  position: relative;
  z-index: 2;
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  padding-top: 0.6rem;
  border-top: 1px solid var(--sand);
  margin-top: 0.2rem;
}
.service .actions .btn {
  flex: 1 1 auto;
  justify-content: center;
  min-width: 0;
}
.service .no,
.service .ico,
.service h3,
.service p,
.service .foot {
  position: relative;
  z-index: 2;
  pointer-events: none;
}

/* ── the catalogue pager ─────────────────────────────────────────────────── */

.pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-top: 1.2rem;
}
.pagenums {
  display: flex;
  gap: 0.3rem;
  flex-wrap: wrap;
  justify-content: center;
  /* A catalogue with forty pages must not widen the page. */
  max-width: 100%;
  overflow-x: auto;
}
.pagenum {
  min-width: 36px;
  min-height: 36px;
  padding: 0.3rem 0.55rem;
  border-radius: 10px;
  border: 1px solid var(--sand);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
.pagenum:hover {
  border-color: var(--primary);
}
.pagenum.on {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}
.chips.categories {
  margin-block: 0.6rem 0.2rem;
}
.service .pick {
  border: 0;
  background: none;
  font: inherit;
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--primary);
  cursor: pointer;
  padding: 0.2rem 0;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  text-align: start;
}
.service .pick:hover {
  color: var(--accent);
}
.service .pick svg {
  width: 14px;
  height: 14px;
  transition: transform 0.16s ease;
}
.service .pick:hover svg {
  transform: translateX(3px);
}

.tag {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.22rem 0.55rem;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  border: 1px solid rgba(238, 84, 6, 0.25);
}
.tag.plain {
  background: var(--primary-soft);
  color: var(--primary);
  border-color: rgba(15, 114, 0, 0.18);
  text-transform: none;
  letter-spacing: 0.02em;
  font-family: var(--ethiopic);
}
/* The "ሓዲሽ / New" flag. Solid rather than tinted so it reads first among the
   chips, and not uppercased because Ethiopic has no case. */
.tag.new {
  background: var(--accent);
  color: #fff;
  border-color: transparent;
  text-transform: none;
  letter-spacing: 0.02em;
}

/* ── professionals ───────────────────────────────────────────────────────── */

.pros {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
  gap: clamp(0.9rem, 2vw, 1.35rem);
}

.pro {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  background: var(--paper);
  border: 1px solid var(--sand);
  border-radius: var(--radius);
  padding: 1.4rem;
}
.pro-top {
  display: flex;
  gap: 1rem;
  align-items: center;
}
.pro .avatar {
  width: 68px;
  height: 68px;
  border-radius: 50%;
  flex: none;
  object-fit: cover;
  background: var(--primary-soft);
  border: 2px solid var(--paper);
  box-shadow: 0 0 0 1px var(--sand-deep);
}
.pro .initials {
  display: grid;
  place-items: center;
  font-family: var(--display);
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--primary);
}
.pro h3 {
  font-size: 1.12rem;
}
.pro .role {
  font-size: 0.88rem;
  color: var(--accent);
  font-weight: 700;
}
.pro .where {
  font-size: 0.84rem;
  color: var(--muted);
}
.pro .bio {
  font-size: 0.9rem;
  color: var(--muted);
}
.pro .bio .ti {
  color: #3f4a47;
}
.pro .chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.pro .pro-foot {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: auto;
  padding-top: 0.4rem;
  border-top: 1px solid var(--sand);
}
.pro .closed {
  font-size: 0.82rem;
  color: var(--muted);
}

/* ── about ───────────────────────────────────────────────────────────────── */

.about-in {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
  gap: clamp(1.6rem, 5vw, 3.6rem);
  align-items: start;
}
@media (max-width: 900px) {
  .about-in {
    grid-template-columns: minmax(0, 1fr);
  }
}
.about-in .body {
  font-size: 1.02rem;
  color: #3f4a47;
  display: grid;
  gap: 1rem;
}
.promises {
  display: grid;
  gap: 0.75rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.promises li {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  background: var(--paper);
  border: 1px solid var(--sand);
  border-radius: 14px;
  padding: 0.95rem 1.1rem;
  font-size: 0.95rem;
}
.sec.tint .promises li {
  background: var(--surface);
}
.promises svg {
  width: 20px;
  height: 20px;
  flex: none;
  color: var(--good);
  margin-top: 0.18rem;
}

/* ── booking form ────────────────────────────────────────────────────────── */

.book-in {
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  gap: clamp(1.6rem, 4vw, 3.2rem);
  align-items: start;
}
@media (max-width: 900px) {
  .book-in {
    grid-template-columns: minmax(0, 1fr);
  }
}

.form {
  background: var(--paper);
  border: 1px solid var(--sand);
  border-radius: calc(var(--radius) + 6px);
  padding: clamp(1.3rem, 3vw, 2rem);
  box-shadow: var(--shadow-low);
}
.sec.tint .form {
  background: var(--surface);
}
.rows {
  display: grid;
  gap: 1rem;
}
.row2 {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 1rem;
}
@media (max-width: 620px) {
  .row2 {
    grid-template-columns: minmax(0, 1fr);
  }
}

.field {
  display: grid;
  gap: 0.35rem;
}
.field > span,
.field > label {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--ink);
}
.field .note {
  font-size: 0.78rem;
  color: var(--muted);
  font-weight: 400;
}
/* The same quiet aside used outside a field — beside a file picker, under a
   colour swatch. Kept separate from `.noterow` so a hint can never inherit the
   notification row's grid. */
.note {
  font-size: 0.78rem;
  color: var(--muted);
  font-weight: 400;
}
.field .req {
  color: var(--accent);
}

input[type='text'],
input[type='tel'],
input[type='email'],
input[type='password'],
input[type='date'],
input[type='time'],
input[type='number'],
input[type='url'],
select,
textarea {
  width: 100%;
  font: inherit;
  font-size: 0.98rem;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--sand-deep);
  border-radius: 12px;
  padding: 0.7rem 0.85rem;
  min-height: 46px;
  transition: border-color 0.16s ease, box-shadow 0.16s ease;
}
.sec.tint input,
.sec.tint select,
.sec.tint textarea {
  background: var(--paper);
}
textarea {
  min-height: 108px;
  resize: vertical;
  line-height: 1.55;
}
input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(15, 114, 0, 0.12);
}
input::placeholder,
textarea::placeholder {
  color: #9aa5a1;
}
select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%235f6b67' stroke-width='2'%3E%3Cpath d='M5 8l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.7rem center;
  background-size: 18px;
  padding-inline-end: 2.2rem;
}

.chips-pick {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.chips-pick label {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: 1px solid var(--sand-deep);
  border-radius: 999px;
  padding: 0.5rem 0.95rem;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  background: var(--surface);
  transition: all 0.16s ease;
}
.sec.tint .chips-pick label {
  background: var(--paper);
}
.chips-pick input {
  position: absolute;
  opacity: 0;
  inset: 0;
  cursor: pointer;
}
.chips-pick label:has(input:checked) {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}
.chips-pick label:has(input:focus-visible) {
  outline: 2.5px solid var(--accent);
  outline-offset: 2px;
}

.form-foot {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  margin-top: 1.4rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--sand);
}
.form-foot .small {
  font-size: 0.82rem;
  color: var(--muted);
  max-width: 34ch;
}

.notice {
  border-radius: 14px;
  padding: 0.9rem 1.1rem;
  font-size: 0.92rem;
  border: 1px solid;
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
}
.notice svg {
  width: 18px;
  height: 18px;
  flex: none;
  margin-top: 0.22rem;
}
.notice.info {
  background: var(--primary-soft);
  border-color: rgba(15, 114, 0, 0.2);
  color: #17423d;
}
.notice.good {
  background: #e8f3ec;
  border-color: rgba(47, 109, 79, 0.28);
  color: #1f5138;
}
.notice.bad {
  background: #fbeae6;
  border-color: rgba(163, 58, 42, 0.28);
  color: #7d2a1d;
}
.notice.warn {
  background: #fbf1de;
  border-color: rgba(154, 100, 16, 0.28);
  color: #6d4708;
}
.notice + .notice,
.rows .notice {
  margin: 0;
}

.done {
  text-align: center;
  padding: clamp(1.5rem, 4vw, 2.5rem) 1rem;
}
.done .ref {
  font-family: var(--display);
  font-size: 2rem;
  font-weight: 700;
  color: var(--primary);
  letter-spacing: 0.06em;
  margin-block: 0.6rem 0.3rem;
}
.done p {
  color: var(--muted);
  max-width: 44ch;
  margin-inline: auto;
}

/* ── contact & footer ────────────────────────────────────────────────────── */

.contact-in {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  gap: clamp(1.2rem, 3vw, 2.4rem);
}
.contact-in h3 {
  font-family: var(--body);
  font-size: 0.8rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.6rem;
}
.contact-in .big {
  font-family: var(--display);
  font-size: 1.35rem;
  font-weight: 600;
  color: #fff;
  text-decoration: none;
  display: block;
  font-variant-numeric: tabular-nums;
}
.contact-in .big:hover {
  color: var(--accent);
}
.contact-in p {
  color: rgba(244, 241, 234, 0.82);
  font-size: 0.94rem;
}

.dark {
  background: var(--primary);
  color: #f4f1ea;
}
.dark h2 {
  color: #fff;
}
.dark .sec-head p {
  color: rgba(244, 241, 234, 0.8);
}

.closing {
  font-family: var(--ethiopic-display);
  font-size: clamp(1.3rem, 3.4vw, 2rem);
  font-weight: 600;
  color: #fff;
  text-align: center;
  padding-block: clamp(2rem, 5vw, 3rem) 0;
}
.closing span {
  display: block;
  font-family: var(--display);
  font-size: 0.95rem;
  font-weight: 400;
  color: rgba(244, 241, 234, 0.75);
  margin-top: 0.6rem;
}

.foot {
  background: #0b3833;
  color: rgba(244, 241, 234, 0.72);
  font-size: 0.88rem;
}
.foot-in {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  align-items: center;
  justify-content: space-between;
  padding-block: 1.6rem;
  border-top: 1px solid rgba(244, 241, 234, 0.12);
}
.foot a {
  color: rgba(244, 241, 234, 0.9);
}
.foot .links {
  display: flex;
  gap: 1.2rem;
  flex-wrap: wrap;
}

/* ── states ──────────────────────────────────────────────────────────────── */

.empty {
  border: 1px dashed var(--sand-deep);
  border-radius: var(--radius);
  padding: clamp(1.6rem, 4vw, 2.6rem);
  text-align: center;
  color: var(--muted);
  background: var(--paper);
}
.empty h3 {
  font-size: 1.1rem;
  color: var(--ink);
  margin-bottom: 0.4rem;
}
.empty p {
  font-size: 0.92rem;
  max-width: 46ch;
  margin-inline: auto;
}
.dark .empty {
  background: rgba(255, 253, 249, 0.06);
  border-color: rgba(255, 253, 249, 0.25);
  color: rgba(244, 241, 234, 0.8);
}
.dark .empty h3 {
  color: #fff;
}

.skeleton {
  border-radius: var(--radius);
  background: linear-gradient(100deg, var(--sand) 20%, #f0eae0 40%, var(--sand) 60%);
  background-size: 240% 100%;
  animation: sweep 1.4s ease-in-out infinite;
  min-height: 168px;
  border: 1px solid var(--sand);
}
@keyframes sweep {
  from {
    background-position: 130% 0;
  }
  to {
    background-position: -30% 0;
  }
}

.toast-host {
  position: fixed;
  inset: auto 1rem 1rem auto;
  z-index: 80;
  display: grid;
  gap: 0.6rem;
  max-width: min(380px, calc(100vw - 2rem));
}
.toast {
  border-radius: 14px;
  padding: 0.85rem 1.05rem;
  font-size: 0.92rem;
  font-weight: 600;
  box-shadow: var(--shadow-high);
  background: var(--ink);
  color: #fff;
  animation: rise 0.22s ease;
}
.toast.good {
  background: #1f5138;
}
.toast.bad {
  background: #7d2a1d;
}
/* Saved, but with something the person needs to know — "your profile stays
   private until an administrator approves it". Neither a success nor a failure,
   and it should not be dressed as either. */
.toast.warn {
  background: #7a4a10;
}
@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
}

.sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ─────────────────────────────────────────────────────────────────────────────
   Admin panel and clinician portal
   ──────────────────────────────────────────────────────────────────────────── */

.gate {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 1.5rem;
}
.gate-card {
  width: min(430px, 100%);
  background: var(--paper);
  border: 1px solid var(--sand);
  border-radius: calc(var(--radius) + 6px);
  padding: clamp(1.5rem, 4vw, 2.3rem);
  box-shadow: var(--shadow-high);
}
.gate-card .brand {
  margin-bottom: 1.4rem;
}
.gate-card h1 {
  font-size: 1.5rem;
  margin-bottom: 0.3rem;
}
.gate-card .sub {
  color: var(--muted);
  font-size: 0.92rem;
  margin-bottom: 1.4rem;
}
.gate-tabs {
  display: flex;
  gap: 0.4rem;
  margin-bottom: 1.3rem;
  border-bottom: 1px solid var(--sand);
}
.gate-tabs button {
  border: 0;
  background: none;
  font: inherit;
  font-weight: 700;
  font-size: 0.94rem;
  color: var(--muted);
  padding: 0.55rem 0.7rem;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.gate-tabs button[aria-selected='true'] {
  color: var(--primary);
  border-bottom-color: var(--accent);
}

.shell {
  display: grid;
  grid-template-columns: 250px minmax(0, 1fr);
  min-height: 100dvh;
}
@media (max-width: 900px) {
  .shell {
    grid-template-columns: minmax(0, 1fr);
  }
}

.side {
  background: var(--primary);
  color: rgba(244, 241, 234, 0.82);
  padding: 1.4rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 1.4rem;
  position: sticky;
  top: 0;
  align-self: start;
  max-height: 100dvh;
  overflow-y: auto;
}
@media (max-width: 900px) {
  .side {
    position: static;
    max-height: none;
  }
}
.side .brand .name {
  color: #fff;
}
.side .brand .name-en {
  color: var(--accent);
}
.side nav {
  display: grid;
  gap: 0.15rem;
}
.side nav button {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  width: 100%;
  border: 0;
  background: none;
  font: inherit;
  font-weight: 600;
  font-size: 0.94rem;
  color: rgba(244, 241, 234, 0.8);
  text-align: start;
  padding: 0.62rem 0.8rem;
  border-radius: 10px;
  cursor: pointer;
}
.side nav button svg {
  width: 17px;
  height: 17px;
  flex: none;
  opacity: 0.8;
}
.side nav button:hover {
  background: rgba(255, 253, 249, 0.09);
  color: #fff;
}
.side nav button[aria-current='true'] {
  background: var(--paper);
  color: var(--primary);
  font-weight: 700;
}
.side nav button[aria-current='true'] svg {
  opacity: 1;
}
.side nav button .count {
  margin-inline-start: auto;
  font-size: 0.76rem;
  font-weight: 700;
  background: var(--accent);
  color: #fff;
  border-radius: 999px;
  padding: 0.05rem 0.45rem;
}
/* The portal's link across to the admin panel, for someone who holds both. */
.side nav .sidelink {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-weight: 600;
  font-size: 0.94rem;
  color: rgba(244, 241, 234, 0.7);
  padding: 0.62rem 0.8rem;
  border-radius: 10px;
  border-top: 1px solid rgba(255, 253, 249, 0.16);
  margin-top: 0.4rem;
  text-decoration: none;
}
.side nav .sidelink svg {
  width: 17px;
  height: 17px;
  flex: none;
}
.side nav .sidelink:hover {
  background: rgba(255, 253, 249, 0.09);
  color: #fff;
}
.side .who {
  margin-top: auto;
  font-size: 0.82rem;
  border-top: 1px solid rgba(255, 253, 249, 0.16);
  padding-top: 1rem;
  display: grid;
  gap: 0.5rem;
}
.side .who b {
  color: #fff;
  display: block;
  font-weight: 700;
  word-break: break-word;
}

.main {
  padding: clamp(1.2rem, 3vw, 2.2rem);
  min-width: 0;
}
.main > header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.5rem;
}
.main > header h1 {
  font-size: clamp(1.5rem, 3vw, 2.05rem);
}
.main > header p {
  color: var(--muted);
  font-size: 0.93rem;
  max-width: 58ch;
}
.head-actions {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.panel {
  background: var(--paper);
  border: 1px solid var(--sand);
  border-radius: var(--radius);
  padding: clamp(1.1rem, 2.5vw, 1.6rem);
  margin-bottom: 1.2rem;
}
.panel > h2 {
  font-size: 1.15rem;
  margin-bottom: 0.35rem;
}
.panel > .hint {
  color: var(--muted);
  font-size: 0.88rem;
  margin-bottom: 1.1rem;
}
.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(158px, 100%), 1fr));
  gap: 0.8rem;
  margin-bottom: 1.2rem;
}
.stat {
  background: var(--paper);
  border: 1px solid var(--sand);
  border-radius: 14px;
  padding: 1rem 1.1rem;
}
.stat b {
  display: block;
  font-family: var(--display);
  font-size: 1.8rem;
  font-weight: 600;
  line-height: 1.1;
  color: var(--primary);
}
.stat span {
  font-size: 0.82rem;
  color: var(--muted);
}
.stat.flag b {
  color: var(--accent);
}

/* A number alone does not say how close to a ceiling it is. The mint allowance
   is the one figure on the panel where that matters — an administrator wants to
   see at a glance that today is nearly spent — so it gets a bar. It turns warm
   past three quarters, which is the point at which the next mint might not fit. */
.meter {
  height: 10px;
  border-radius: 6px;
  background: rgba(26, 36, 22, 0.09);
  overflow: hidden;
}
.meter i {
  display: block;
  height: 100%;
  width: var(--done, 0%);
  border-radius: 6px;
  background: linear-gradient(90deg, var(--primary), var(--glow));
  transition: width 0.5s ease;
}
.meter.hot i {
  background: linear-gradient(90deg, var(--warn), var(--danger));
}

.tablewrap {
  /* A table that will not fit scrolls inside its own box. `min-width: 0` is the
     half of that which is easy to forget: as a grid or flex child this box
     defaults to the width of its content, so without it the table pushes the
     page wide instead of scrolling within it. */
  min-width: 0;
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--sand);
  border-radius: 14px;
  background: var(--paper);
}
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
  min-width: 620px;
}
thead th {
  text-align: start;
  font-size: 0.74rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 700;
  padding: 0.7rem 0.9rem;
  background: var(--surface);
  border-bottom: 1px solid var(--sand);
  white-space: nowrap;
  position: sticky;
  top: 0;
}
tbody td {
  padding: 0.72rem 0.9rem;
  border-bottom: 1px solid var(--surface);
  vertical-align: top;
}
tbody tr:last-child td {
  border-bottom: 0;
}
tbody tr:hover td {
  background: var(--surface);
}
td .who-name {
  font-weight: 700;
  display: block;
}
td .sub,
td small {
  color: var(--muted);
  font-size: 0.82rem;
  display: block;
}
td.num {
  text-align: end;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
td.acts {
  white-space: nowrap;
  text-align: end;
}
.mono {
  font-family: ui-monospace, 'DejaVu Sans Mono', monospace;
  font-size: 0.86em;
  letter-spacing: 0.02em;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.75rem;
  font-weight: 700;
  padding: 0.18rem 0.55rem;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--sand-deep);
  color: var(--muted);
  white-space: nowrap;
}
.pill.pending {
  background: #fbf1de;
  border-color: rgba(154, 100, 16, 0.3);
  color: var(--warn);
}
.pill.live,
.pill.confirmed,
.pill.completed,
.pill.paid {
  background: #e8f3ec;
  border-color: rgba(47, 109, 79, 0.3);
  color: var(--good);
}
.pill.off,
.pill.cancelled,
.pill.urgent {
  background: #fbeae6;
  border-color: rgba(163, 58, 42, 0.3);
  color: var(--bad);
}
.pill.assigned,
.pill.progress {
  background: var(--primary-soft);
  border-color: rgba(15, 114, 0, 0.22);
  color: var(--primary);
}

.switch {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  cursor: pointer;
  font-size: 0.88rem;
  font-weight: 600;
}

/* A column of switches — the welcome card's buttons, and anywhere else a panel
   offers a list of things to show or hide. Two columns where there is room. */
.switchgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 0.6rem 1.2rem;
  padding: 0.4rem 0 0.2rem;
}
.switch input {
  appearance: none;
  width: 42px;
  height: 24px;
  border-radius: 999px;
  background: var(--sand-deep);
  position: relative;
  cursor: pointer;
  transition: background 0.16s ease;
  flex: none;
  margin: 0;
}
.switch input::after {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  transition: transform 0.16s ease;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.switch input:checked {
  background: var(--good);
}
.switch input:checked::after {
  transform: translateX(18px);
}

/* Editing happens in a side drawer so the list stays visible behind it. */
.drawer {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: none;
}
.drawer[open] {
  display: block;
}
.drawer .veil {
  position: absolute;
  inset: 0;
  background: rgba(11, 56, 51, 0.42);
  backdrop-filter: blur(2px);
  border: 0;
  padding: 0;
  width: 100%;
  cursor: pointer;
}
.drawer .sheet {
  position: absolute;
  inset-block: 0;
  inset-inline-end: 0;
  width: min(560px, 100%);
  background: var(--surface);
  border-inline-start: 1px solid var(--sand);
  box-shadow: var(--shadow-high);
  overflow-y: auto;
  padding: clamp(1.2rem, 3vw, 1.9rem);
  animation: slide 0.22s ease;
}
@keyframes slide {
  from {
    transform: translateX(24px);
    opacity: 0.6;
  }
}
.drawer .sheet > header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.3rem;
}
.drawer .sheet h2 {
  font-size: 1.3rem;
}
.drawer .sheet .sub {
  color: var(--muted);
  font-size: 0.88rem;
}
.iconbtn {
  border: 1px solid var(--sand-deep);
  background: var(--paper);
  width: 36px;
  height: 36px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  cursor: pointer;
  color: var(--muted);
  flex: none;
}
.iconbtn:hover {
  color: var(--ink);
  border-color: var(--muted);
}
.iconbtn svg {
  width: 17px;
  height: 17px;
}

.photo-row {
  display: flex;
  align-items: center;
  gap: 1rem;
}
.photo-row .avatar {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--primary-soft);
  border: 1px solid var(--sand-deep);
  flex: none;
}
.photo-row .stack {
  display: grid;
  gap: 0.35rem;
}
input[type='file'] {
  font: inherit;
  font-size: 0.86rem;
  color: var(--muted);
}
input[type='file']::file-selector-button {
  font: inherit;
  font-weight: 700;
  font-size: 0.86rem;
  border: 1px solid var(--sand-deep);
  background: var(--paper);
  color: var(--primary);
  border-radius: 999px;
  padding: 0.42rem 0.9rem;
  margin-inline-end: 0.7rem;
  cursor: pointer;
}

.filters {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
  align-items: center;
}
.filters input,
.filters select {
  min-height: 40px;
  padding-block: 0.45rem;
  font-size: 0.9rem;
  width: auto;
  min-width: 180px;
}

.grid2 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: 1.2rem;
  align-items: start;
}

.trail {
  display: grid;
  gap: 0;
  list-style: none;
  margin: 0;
  padding: 0;
}
.trail li {
  display: grid;
  grid-template-columns: 128px minmax(0, 1fr);
  gap: 1rem;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--surface);
  font-size: 0.89rem;
}
.trail li:last-child {
  border-bottom: 0;
}
.trail time {
  color: var(--muted);
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
}
.trail .act {
  font-weight: 700;
  color: var(--primary);
}
.trail .by {
  color: var(--muted);
  font-size: 0.83rem;
}
@media (max-width: 620px) {
  .trail li {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.2rem;
  }
}

.token {
  font-family: ui-monospace, 'DejaVu Sans Mono', monospace;
  font-size: 1.05rem;
  letter-spacing: 0.06em;
  background: var(--primary-soft);
  border: 1px dashed rgba(15, 114, 0, 0.35);
  border-radius: 10px;
  padding: 0.7rem 0.9rem;
  word-break: break-all;
  user-select: all;
}

/* The ten recovery codes, and the box that asks for a six-digit one. Both are
   monospaced and widely spaced because both are read off one screen and typed
   into another, often by somebody reading them aloud to somebody else. */
.codegrid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.45rem;
  margin: 0.8rem 0;
}
.codegrid code {
  font-family: ui-monospace, 'DejaVu Sans Mono', monospace;
  font-size: 0.95rem;
  letter-spacing: 0.05em;
  text-align: center;
  padding: 0.5rem 0.4rem;
  border: 1px solid var(--sand);
  border-radius: 10px;
  background: var(--surface);
  user-select: all;
  overflow-wrap: anywhere;
}
.twofa {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}
.twofa input {
  font-family: ui-monospace, 'DejaVu Sans Mono', monospace;
  font-size: 1.25rem;
  letter-spacing: 0.3em;
  text-align: center;
}
.twofa-host {
  max-width: 100%;
}
@media (max-width: 480px) {
  .codegrid {
    grid-template-columns: minmax(0, 1fr);
  }
}

.swatch-row {
  display: flex;
  gap: 0.6rem;
  align-items: center;
}
input[type='color'] {
  width: 46px;
  height: 46px;
  padding: 3px;
  border: 1px solid var(--sand-deep);
  border-radius: 12px;
  background: var(--paper);
  cursor: pointer;
}

.divider {
  height: 1px;
  background: var(--sand);
  border: 0;
  margin-block: 1.3rem;
}

.count-note {
  font-size: 0.84rem;
  color: var(--muted);
}

/* Patient details in the portal drawer: a plain definition list reads faster
   than a form for information nobody is meant to edit. */
.facts {
  display: grid;
  grid-template-columns: minmax(7rem, auto) 1fr;
  gap: 0.45rem 1rem;
  font-size: 0.92rem;
  margin: 0;
}
.facts dt {
  color: var(--muted);
  font-weight: 600;
}
.facts dd {
  margin: 0;
  font-weight: 600;
}
.facts dd a {
  color: var(--primary);
}
.phone-link {
  display: block;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--primary);
  text-decoration: none;
}
.phone-link:hover {
  text-decoration: underline;
}


/* ═══════════════════════════════════════════════════════════════════════════
   THE APPLICATION SHELL
   ───────────────────────────────────────────────────────────────────────────
   Every page except the public front page carries two fixed bars: a top bar
   with the brand, the language switch, the notification bell and the sign-in
   or sign-out icon, and a bottom bar of large tap targets. That is the shape
   of a telephone application, and it is deliberate — most of the people this
   site is for arrive on a telephone, and a bar that is always there means the
   way out of any page is always in the same place.

   Both bars are raised: a lit hairline along the top edge, a dark underside,
   and a shadow that falls away from the page. `--lift` scales all of it, so
   the administrator's `flat` setting collapses the relief without changing a
   single rule below.
   ══════════════════════════════════════════════════════════════════════════ */

body.app {
  /* Room for the two bars, plus the home-indicator strip on a modern phone. */
  padding-top: var(--bar-top);
  padding-bottom: calc(var(--bar-bottom) + var(--safe-bottom));
}

.appbar {
  position: fixed;
  left: 0;
  right: 0;
  z-index: 60;
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--navbar) 88%, #fff) 0%,
    var(--navbar) 46%,
    color-mix(in srgb, var(--navbar) 78%, #000) 100%
  );
  color: #eef5f2;
  /* The lit edge and the dark underside are what make it read as a raised
     object rather than a coloured stripe. */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, calc(0.28 * var(--lift))),
    inset 0 -1px 0 rgba(0, 0, 0, calc(0.4 * var(--lift))),
    0 calc(10px * var(--lift)) calc(30px * var(--lift)) -14px rgba(8, 48, 44, 0.75);
}
.appbar-in {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  width: 100%;
  max-width: var(--band);
  margin-inline: auto;
  padding-inline: clamp(0.6rem, 3vw, 2rem);
}

.appbar.top {
  top: 0;
  border-bottom: 0;
  backdrop-filter: none;
}
.appbar.top .appbar-in {
  min-height: var(--bar-top);
}
.appbar.bottom {
  bottom: 0;
  padding-bottom: var(--safe-bottom);
}
.appbar.bottom .appbar-in {
  min-height: var(--bar-bottom);
  justify-content: space-between;
  gap: 0.15rem;
}

/* The brand inside the dark bar, which needs its own colours. */
.appbar .brand {
  gap: 0.55rem;
  margin-inline-end: 0.35rem;
}
.appbar .brand .mark {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: #fff;
  padding: 2px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
}
.appbar .brand .name {
  color: #fff;
  font-size: 1.08rem;
}
.appbar .brand .name-en {
  color: var(--glow);
  font-size: 0.62rem;
  letter-spacing: 0.2em;
}

/* ── the animated wordmark ───────────────────────────────────────────────────
   The name in the top bar is set by the administrator, and so is the effect it
   plays: `navbar_animation` in the brand settings picks one of the classes
   below. Every one of them animates only colour, opacity or transform, so none
   of them moves the bar around or costs a layout, and all of them stop dead
   under `prefers-reduced-motion`. */

.wordmark {
  position: relative;
}
.wordmark .name {
  display: inline-block;
  will-change: auto;
}
.wordmark-sub {
  margin-top: 0.1rem;
  font-family: var(--display);
  font-size: 0.56rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
}

/* A light travelling across the letters — the default, and the quietest. */
.wordmark.anim-shimmer .name {
  background: linear-gradient(100deg, #fff 20%, var(--gold) 42%, var(--glow) 58%, #fff 80%);
  background-size: 260% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: mark-shimmer 5.5s ease-in-out infinite;
}
@keyframes mark-shimmer {
  0%,
  100% {
    background-position: 180% 0;
  }
  50% {
    background-position: -40% 0;
  }
}

/* A slow heartbeat, in keeping with the mark. */
.wordmark.anim-pulse .name {
  animation: mark-pulse 3.2s ease-in-out infinite;
  transform-origin: left center;
}
@keyframes mark-pulse {
  0%,
  100% {
    transform: scale(1);
  }
  45% {
    transform: scale(1.06);
  }
  60% {
    transform: scale(0.99);
  }
}

/* A tilt that rocks back, like a hand waving. */
.wordmark.anim-wave .name {
  animation: mark-wave 4s ease-in-out infinite;
  transform-origin: left bottom;
}
@keyframes mark-wave {
  0%,
  70%,
  100% {
    transform: rotate(0deg);
  }
  78% {
    transform: rotate(-3.5deg);
  }
  86% {
    transform: rotate(2.5deg);
  }
  94% {
    transform: rotate(-1deg);
  }
}

/* A halo that swells and fades. */
.wordmark.anim-glow .name {
  animation: mark-glow 3.6s ease-in-out infinite;
}
@keyframes mark-glow {
  0%,
  100% {
    text-shadow: 0 0 0 rgba(95, 179, 38, 0);
  }
  50% {
    text-shadow: 0 0 14px rgba(95, 179, 38, 0.85), 0 0 26px rgba(242, 160, 58, 0.35);
  }
}

/* The name arriving from the left, once per page load rather than forever. */
.wordmark.anim-slide .name,
.wordmark.anim-slide .name-en {
  animation: mark-slide 0.75s cubic-bezier(0.2, 0.9, 0.25, 1) both;
}
.wordmark.anim-slide .name-en {
  animation-delay: 0.12s;
}
@keyframes mark-slide {
  from {
    opacity: 0;
    transform: translateX(-14px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* A cursor blinking beside the name, for the typewriter effect. */
.wordmark.anim-type .name::after {
  content: '';
  display: inline-block;
  width: 2px;
  height: 0.95em;
  margin-inline-start: 3px;
  vertical-align: -0.1em;
  background: var(--gold);
  animation: mark-caret 1.1s steps(1) infinite;
}
@keyframes mark-caret {
  0%,
  49% {
    opacity: 1;
  }
  50%,
  100% {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .wordmark .name,
  .wordmark .name-en,
  .wordmark .name::after {
    animation: none !important;
  }
  .wordmark.anim-shimmer .name {
    background: none;
    -webkit-text-fill-color: currentColor;
    color: #fff;
  }
}

/* ── the buttons on the bars ─────────────────────────────────────────────── */

.barbtn {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.16rem;
  min-width: 46px;
  min-height: 46px;
  padding: 0.34rem 0.5rem;
  border: 0;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.06);
  color: #dfeae6;
  font: inherit;
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.14s ease, background 0.14s ease, color 0.14s ease;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, calc(0.16 * var(--lift))),
    0 calc(2px * var(--lift)) calc(4px * var(--lift)) rgba(0, 0, 0, calc(0.32 * var(--lift)));
}
.barbtn svg {
  width: 21px;
  height: 21px;
  flex: none;
}
.barbtn:hover {
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  transform: translateY(-1px);
}
.barbtn:active {
  transform: translateY(1px);
  box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.4);
}
.barbtn[aria-current='page'],
.barbtn.on {
  background: linear-gradient(180deg, color-mix(in srgb, var(--glow) 34%, transparent), rgba(255, 255, 255, 0.05));
  color: #fff;
}
.barbtn[aria-current='page']::after {
  content: '';
  position: absolute;
  bottom: 3px;
  width: 16px;
  height: 3px;
  border-radius: 3px;
  background: var(--glow);
}
.appbar.bottom .barbtn {
  flex: 1 1 0;
  background: transparent;
  box-shadow: none;
}
.appbar.bottom .barbtn:hover {
  background: rgba(255, 255, 255, 0.1);
}
/* The bottom bar's middle button — booking, the thing the site is for. */
.appbar.bottom .barbtn.hot {
  flex: 0 0 auto;
  min-width: 58px;
  margin-top: -18px;
  border-radius: 50%;
  width: 58px;
  height: 58px;
  gap: 0;
  font-size: 0;
  background: radial-gradient(120% 120% at 50% 0%, color-mix(in srgb, var(--accent) 82%, #fff), var(--accent));
  color: #fff;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.5),
    0 calc(6px * var(--lift)) calc(16px * var(--lift)) -4px rgba(0, 0, 0, 0.55);
}
.appbar.bottom .barbtn.hot svg {
  width: 26px;
  height: 26px;
}
.appbar.bottom .barbtn.hot span {
  display: none;
}

/* The label under a bar icon. The shell writes one language into it. */
.barbtn span {
  display: block;
  max-width: 8ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The quick buttons embedded in the top bar — the ones that are not pages but
   actions: call the office, jump to the wallet, open the feed. */
.quickset {
  display: flex;
  align-items: center;
  gap: 0.28rem;
  margin-inline-start: auto;
}
@media (max-width: 720px) {
  .quickset .hide-sm {
    display: none;
  }
}

/* The unread count on the bell. */
.barbtn .tally {
  position: absolute;
  top: 3px;
  right: 3px;
  min-width: 17px;
  height: 17px;
  padding-inline: 4px;
  border-radius: 999px;
  background: var(--danger);
  color: #fff;
  font-size: 0.62rem;
  font-weight: 800;
  line-height: 17px;
  text-align: center;
  box-shadow: 0 0 0 2px var(--navbar);
}
.barbtn .tally[hidden] {
  display: none;
}

/* ── the panels that drop out of the top bar ─────────────────────────────── */

.barpop {
  position: fixed;
  top: calc(var(--bar-top) + 6px);
  right: clamp(0.5rem, 3vw, 2rem);
  z-index: 70;
  width: min(360px, calc(100vw - 1.4rem));
  max-height: min(70vh, 560px);
  overflow-y: auto;
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--sand);
  border-radius: 16px;
  box-shadow: var(--shadow-high);
  padding: 0.5rem;
  animation: pop 0.16s ease-out;
}
.barpop[hidden] {
  display: none;
}
@keyframes pop {
  from {
    opacity: 0;
    transform: translateY(-6px);
  }
}
.barpop h4 {
  font-family: var(--body);
  font-size: 0.76rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 0.45rem 0.6rem;
}
.barpop .langrow {
  display: grid;
  gap: 0.3rem;
}
.barpop .langrow button {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  padding: 0.62rem 0.7rem;
  border: 1px solid transparent;
  border-radius: 12px;
  background: transparent;
  font: inherit;
  font-size: 1rem;
  font-weight: 700;
  color: var(--ink);
  text-align: start;
  cursor: pointer;
}
.barpop .langrow button:hover {
  background: var(--primary-soft);
}
.barpop .langrow button[aria-pressed='true'] {
  border-color: var(--primary);
  background: var(--primary-soft);
  color: var(--primary);
}
.barpop .langrow button .tick {
  margin-inline-start: auto;
  width: 18px;
  height: 18px;
  color: var(--primary);
}
.barpop .langrow button[aria-pressed='false'] .tick {
  visibility: hidden;
}

/* One notification. The whole row is the link, because the point of the bell
   is that tapping it takes you to the thing that happened. */
.noterow {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  gap: 0.1rem 0.6rem;
  padding: 0.6rem;
  border-radius: 12px;
  text-decoration: none;
  color: inherit;
  border: 1px solid transparent;
}
.noterow:hover {
  background: var(--surface);
}
.noterow.unread {
  background: color-mix(in srgb, var(--primary-soft) 70%, transparent);
  border-color: color-mix(in srgb, var(--primary) 18%, transparent);
}
.noterow svg {
  width: 20px;
  height: 20px;
  grid-row: span 2;
  color: var(--primary);
  margin-top: 2px;
}
.noterow b {
  font-size: 0.93rem;
  font-weight: 700;
  line-height: 1.35;
}
.noterow small {
  color: var(--muted);
  font-size: 0.8rem;
}
.noterow .body {
  font-size: 0.87rem;
  color: var(--muted);
  grid-column: 2;
}
.barpop .allnotes {
  display: block;
  text-align: center;
  padding: 0.6rem;
  font-size: 0.86rem;
  font-weight: 700;
}

/* ── the quick action button and its panel ───────────────────────────────── */

/* The one coloured button in a row of grey ones. Prominence here is not a
   larger size — the bar is already tight on a phone — but being the only thing
   in it that is not the same as everything else. */
.barbtn.accent {
  background: linear-gradient(180deg, var(--accent), color-mix(in srgb, var(--accent) 74%, #000));
  color: #fff;
}
.barbtn.accent:hover {
  background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 88%, #fff), var(--accent));
  color: #fff;
}
.barbtn.accent svg {
  color: #fff;
}

.quickpop .noterow.quickaction {
  grid-template-columns: 38px minmax(0, 1fr);
  align-items: center;
  gap: 0.1rem 0.7rem;
}
.quickpop .quickaction .ring {
  grid-row: span 2;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 12px;
  background: var(--primary-soft);
  color: var(--primary);
}
.quickpop .quickaction .ring svg {
  width: 20px;
  height: 20px;
  grid-row: auto;
  margin: 0;
}
/* The emergency row reads as urgent without shouting: a warm tint and a
   coloured rule down its leading edge, not a red block that makes the other
   three look broken by comparison. */
.quickpop .quickaction.urgent {
  background: color-mix(in srgb, var(--danger) 8%, transparent);
  border-inline-start: 3px solid var(--danger);
}
.quickpop .quickaction.urgent .ring {
  background: color-mix(in srgb, var(--danger) 16%, transparent);
  color: var(--danger);
}
.quickpop .quickaction small {
  grid-column: 2;
  font-weight: 700;
  color: var(--danger);
  font-variant-numeric: tabular-nums;
}

/* ═══════════════════════════════════════════════════════════════════════════
   RAISED SURFACES AND COLOURED BUTTONS
   ══════════════════════════════════════════════════════════════════════════ */

/* The default `.btn` stays as it was — flat and quiet — and anything that
   wants relief asks for it. That way the existing panels are untouched. */
.btn.raised {
  border: 0;
  background: linear-gradient(180deg, color-mix(in srgb, var(--btn-bg) 82%, #fff), var(--btn-bg) 58%,
      color-mix(in srgb, var(--btn-bg) 86%, #000));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, calc(0.42 * var(--lift))),
    inset 0 -2px 0 rgba(0, 0, 0, calc(0.22 * var(--lift))),
    0 calc(3px * var(--lift)) 0 color-mix(in srgb, var(--btn-bg) 62%, #000),
    0 calc(8px * var(--lift)) calc(20px * var(--lift)) -8px rgba(8, 48, 44, 0.6);
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.18);
}
.btn.raised:hover {
  transform: translateY(-2px);
}
.btn.raised:active {
  transform: translateY(calc(2px * var(--lift)));
  box-shadow:
    inset 0 2px 6px rgba(0, 0, 0, 0.3),
    0 1px 0 color-mix(in srgb, var(--btn-bg) 62%, #000);
}

/* The colours a button can wear. The administrator sets the two that matter
   (`--primary`, `--accent`); these are the fixed meanings. */
.btn.tone-gold {
  --btn-bg: var(--gold);
  --btn-ink: #2b1d05;
}
.btn.tone-teal {
  --btn-bg: var(--glow);
  --btn-ink: #04241f;
}
.btn.tone-deep {
  --btn-bg: var(--deep);
}
.btn.tone-red {
  --btn-bg: var(--danger);
}
.btn.tone-face {
  --btn-bg: var(--btn-face);
}
.btn.wide {
  width: 100%;
}
.btn.big {
  padding: 1rem 1.6rem;
  min-height: 54px;
  font-size: 1.03rem;
}

/* A raised card: the same trick, in paper. */
.card3 {
  position: relative;
  background: var(--paper);
  border: 1px solid var(--sand);
  border-radius: calc(var(--radius) + 4px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    0 1px 0 var(--sand-deep),
    0 calc(14px * var(--lift)) calc(34px * var(--lift)) -20px rgba(26, 36, 22, 0.55);
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.card3.lift:hover {
  transform: translateY(-3px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    0 2px 0 var(--sand-deep),
    0 calc(24px * var(--lift)) calc(50px * var(--lift)) -22px rgba(26, 36, 22, 0.6);
}

/* ── the service buttons ─────────────────────────────────────────────────────
   Every service in the catalogue is a solid, pressable key rather than a flat
   tile: a slab standing on a coloured edge, which tilts towards the reader when
   the pointer is over it and sinks onto its edge when it is pressed. The whole
   card is the target — the invisible `.stretch` anchor already covers it — so
   the press is honest: what looks like a button behaves like one.

   These rules are stated as `.service.card3` so they win over the generic card
   above regardless of source order, and every one of them animates only
   `transform` and `box-shadow`. */

.services {
  perspective: 1200px;
}

.service.card3 {
  --edge: var(--sand-deep);
  --edge-h: 7px;
  cursor: pointer;
  transform-style: preserve-3d;
  border-color: var(--sand-deep);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    inset 0 -1px 0 rgba(26, 36, 22, 0.06),
    0 var(--edge-h) 0 var(--edge),
    0 calc(var(--edge-h) + 6px) calc(18px * var(--lift)) -6px rgba(26, 36, 22, 0.4);
  transition:
    transform 0.16s cubic-bezier(0.3, 0.9, 0.35, 1),
    box-shadow 0.16s ease,
    border-color 0.16s ease;
}

/* The tinted band on the home page sits on cream, so the slab lifts off it in
   the house green instead of in sand. */
.sec.tint .service.card3,
.service.card3.on {
  --edge: var(--deep);
}

.service.card3:hover,
.service.card3:focus-visible {
  --edge-h: 10px;
  border-color: var(--primary);
  transform: translateY(-4px) rotateX(4deg);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    0 var(--edge-h) 0 var(--edge),
    0 calc(var(--edge-h) + 10px) calc(30px * var(--lift)) -8px rgba(26, 36, 22, 0.45);
}

/* Pressed: the slab travels the full height of its own edge, so the movement
   and the shrinking shadow are the same distance. Nothing below it moves. */
.service.card3:active {
  --edge-h: 2px;
  transform: translateY(6px);
  box-shadow:
    inset 0 2px 5px rgba(26, 36, 22, 0.18),
    0 var(--edge-h) 0 var(--edge);
  transition-duration: 0.06s;
}

/* The icon plate rides slightly above the face of the key. */
.service.card3 .ico {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    0 3px 0 rgba(15, 114, 0, 0.18),
    0 6px 12px -6px rgba(26, 36, 22, 0.5);
  transition: transform 0.16s ease, box-shadow 0.16s ease;
}
.service.card3:hover .ico {
  transform: translateY(-2px) scale(1.04);
  background: var(--primary);
  color: #fff;
}
.service.card3:active .ico {
  transform: translateY(1px);
  box-shadow: inset 0 2px 4px rgba(26, 36, 22, 0.3);
}

/* A chosen service in the booking flow stays pressed, so the state reads as the
   same gesture rather than as a separate colour convention. */
.service.card3.on {
  --edge-h: 3px;
  border-color: var(--primary);
  background: var(--primary-soft);
  transform: translateY(4px);
}

/* Keyboard focus has to be visible on a control this large. */
.service.card3:focus-within {
  outline: 3px solid var(--glow);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .service.card3,
  .service.card3 .ico {
    transition: none;
  }
  .service.card3:hover,
  .service.card3:focus-visible {
    transform: none;
  }
  .service.card3:active {
    transform: translateY(3px);
  }
}

/* An interior page's heading strip. */
.pagehead {
  padding-block: clamp(1.4rem, 4vw, 2.6rem) 1.2rem;
}
.pagehead h1 {
  font-size: clamp(1.7rem, 4.4vw, 2.6rem);
}
.pagehead h1 .ti,
.pagehead h1 .am {
  color: var(--primary);
}
.pagehead .lede {
  color: var(--muted);
  max-width: 60ch;
  margin-top: 0.7rem;
}
.pagehead .crumbs {
  display: flex;
  gap: 0.4rem;
  align-items: center;
  font-size: 0.8rem;
  color: var(--muted);
  margin-bottom: 0.6rem;
}

/* ═══════════════════════════════════════════════════════════════════════════
   THE HERO STAGE — slideshow, subtitles, sound and the advert
   ══════════════════════════════════════════════════════════════════════════ */

.stage {
  position: relative;
  border-radius: calc(var(--radius) + 8px);
  overflow: hidden;
  background: var(--deep);
  aspect-ratio: 4 / 3;
  box-shadow: var(--shadow-high);
  isolation: isolate;
}
@media (max-width: 900px) {
  .stage {
    aspect-ratio: 16 / 11;
  }
}

.slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 0.9s ease;
  pointer-events: none;
}
.slide.on {
  opacity: 1;
  pointer-events: auto;
}
.slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* A slow drift, so a still photograph does not look like a stalled page. */
.slide.on img {
  animation: drift 9s ease-out both;
}
@keyframes drift {
  from {
    transform: scale(1.02);
  }
  to {
    transform: scale(1.11) translate3d(-1.5%, -1%, 0);
  }
}

.slide-cap {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  padding: clamp(1rem, 3vw, 2rem) clamp(1rem, 3vw, 2rem) clamp(2.6rem, 5vw, 3.2rem);
  color: #fff;
  background: linear-gradient(0deg, rgba(6, 30, 27, 0.92) 0%, rgba(6, 30, 27, 0.62) 45%, transparent 100%);
}
.slide.on .slide-cap {
  animation: rise 0.7s 0.15s ease-out both;
}
@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
}
.slide-cap .sub {
  font-family: var(--ethiopic-display);
  font-size: clamp(1.15rem, 2.6vw, 1.65rem);
  font-weight: 700;
  line-height: 1.3;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.5);
}
.slide-cap .cap {
  font-size: 0.95rem;
  color: #d8e6e1;
  margin-top: 0.4rem;
  max-width: 52ch;
}
.slide-cap .bi > .ti,
.slide-cap .bi > .am,
.slide-cap .bi > .en {
  color: inherit;
}
.slide-cap a.btn {
  margin-top: 0.9rem;
}

/* The controls sit on the glass: dots, a pause and a mute. */
.stagebar {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 0.75rem;
}
.stagedots {
  display: flex;
  gap: 0.35rem;
  margin-inline-end: auto;
}
.stagedots button {
  width: 26px;
  height: 6px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.38);
  cursor: pointer;
  transition: background 0.2s ease, width 0.2s ease;
}
.stagedots button[aria-pressed='true'] {
  background: #fff;
  width: 34px;
}
.glassbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 50%;
  background: rgba(8, 48, 44, 0.45);
  backdrop-filter: blur(6px);
  color: #fff;
  cursor: pointer;
}
.glassbtn svg {
  width: 18px;
  height: 18px;
}
.glassbtn:hover {
  background: rgba(8, 48, 44, 0.7);
}

/* The advert. It sits in the same stage, above the slides, and is muted until
   somebody asks for sound — an unmuted video that starts by itself is the
   fastest way to lose a visitor. */
.stage video.advert {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 2;
  background: #000;
}
.stage video.advert[hidden] {
  display: none;
}
.advert-tag {
  position: absolute;
  top: 0.7rem;
  inset-inline-start: 0.7rem;
  z-index: 3;
  padding: 0.22rem 0.6rem;
  border-radius: 999px;
  background: rgba(8, 48, 44, 0.6);
  color: #fff;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  backdrop-filter: blur(6px);
}

/* ═══════════════════════════════════════════════════════════════════════════
   THE WELCOME FLOW — language first, then what they came for
   ══════════════════════════════════════════════════════════════════════════ */

.sheet {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  padding: 1rem;
  background: rgba(6, 30, 27, 0.62);
  backdrop-filter: blur(4px);
  animation: fade 0.2s ease-out;
}
.sheet[hidden] {
  display: none;
}
@keyframes fade {
  from {
    opacity: 0;
  }
}
.sheet-card {
  width: min(620px, 100%);
  max-height: calc(100vh - 2rem);
  overflow-y: auto;
  background: var(--paper);
  border-radius: calc(var(--radius) + 8px);
  padding: clamp(1.2rem, 4vw, 2rem);
  box-shadow: 0 40px 80px -30px rgba(0, 0, 0, 0.6);
  animation: rise 0.28s ease-out both;
}
.sheet-card h2 {
  font-size: clamp(1.35rem, 3.4vw, 1.9rem);
}
.sheet-card h2 .ti,
.sheet-card h2 .am {
  color: var(--primary);
}
.sheet-card .lede {
  color: var(--muted);
  margin-top: 0.5rem;
  font-size: 0.95rem;
}
.sheet-card .sheet-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  align-items: center;
  justify-content: space-between;
  margin-top: 1.2rem;
  padding-top: 1rem;
  border-top: 1px solid var(--sand);
  font-size: 0.86rem;
  color: var(--muted);
}

/* The language choice: three big buttons, each written in its own script. */
.langpick {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.7rem;
  margin-top: 1.2rem;
}
@media (max-width: 520px) {
  .langpick {
    grid-template-columns: minmax(0, 1fr);
  }
}
.langpick button {
  padding: 1.1rem 0.6rem;
  border: 1.5px solid var(--sand-deep);
  border-radius: var(--radius);
  background: var(--surface);
  font-family: var(--ethiopic-display);
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--primary);
  cursor: pointer;
  transition: transform 0.14s ease, border-color 0.14s ease, background 0.14s ease;
  box-shadow: inset 0 1px 0 #fff, 0 calc(3px * var(--lift)) 0 var(--sand-deep);
}
.langpick button:hover {
  transform: translateY(-2px);
  border-color: var(--primary);
  background: var(--primary-soft);
}
.langpick button small {
  display: block;
  font-family: var(--body);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 0.3rem;
}

/* What did you come here for? */
.choices {
  display: grid;
  gap: 0.7rem;
  margin-top: 1.2rem;
}
.choice {
  display: grid;
  grid-template-columns: 46px minmax(0, 1fr) 20px;
  align-items: center;
  gap: 0.9rem;
  padding: 0.9rem 1rem;
  border: 1.5px solid var(--sand);
  border-radius: var(--radius);
  background: var(--surface);
  text-align: start;
  font: inherit;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.14s ease, border-color 0.14s ease, box-shadow 0.14s ease;
}
.choice:hover {
  transform: translateY(-2px);
  border-color: var(--primary);
  box-shadow: 0 calc(10px * var(--lift)) calc(24px * var(--lift)) -14px rgba(15, 114, 0, 0.6);
}
.choice .ring {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 14px;
  background: var(--primary-soft);
  color: var(--primary);
}
.choice .ring svg {
  width: 24px;
  height: 24px;
}
.choice.accent .ring {
  background: var(--accent-soft);
  color: var(--accent);
}
.choice b {
  display: block;
  font-size: 1rem;
  font-weight: 700;
}
.choice small {
  display: block;
  color: var(--muted);
  font-size: 0.86rem;
  line-height: 1.45;
}
.choice > svg:last-child {
  width: 20px;
  height: 20px;
  color: var(--muted);
}

/* ═══════════════════════════════════════════════════════════════════════════
   BOOKING — the steps, the choices, the times, the payment
   ══════════════════════════════════════════════════════════════════════════ */

.steps {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  list-style: none;
  margin: 0 0 1.4rem;
  padding: 0;
  counter-reset: step;
}
.steps li {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.4rem 0.8rem 0.4rem 0.5rem;
  border-radius: 999px;
  background: var(--paper);
  border: 1px solid var(--sand);
  font-size: 0.83rem;
  font-weight: 700;
  color: var(--muted);
  counter-increment: step;
}
.steps li::before {
  content: counter(step);
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--sand);
  color: var(--ink);
  font-size: 0.74rem;
  font-weight: 800;
}
.steps li.on {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
  box-shadow: 0 calc(3px * var(--lift)) calc(10px * var(--lift)) -4px rgba(15, 114, 0, 0.7);
}
.steps li.on::before {
  background: #fff;
  color: var(--primary);
}
.steps li.done {
  background: var(--primary-soft);
  border-color: color-mix(in srgb, var(--primary) 26%, transparent);
  color: var(--primary);
}
.steps li.done::before {
  content: '✓';
  background: var(--good);
  color: #fff;
}

/* A grid of things to pick one of: a service, a clinician, an area. */
.picker {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr));
  gap: 0.8rem;
}
.pick {
  position: relative;
  display: grid;
  gap: 0.3rem;
  padding: 1rem 1.1rem;
  border: 1.5px solid var(--sand);
  border-radius: var(--radius);
  background: var(--paper);
  text-align: start;
  font: inherit;
  color: inherit;
  cursor: pointer;
  transition: transform 0.14s ease, border-color 0.14s ease, box-shadow 0.14s ease;
}
.pick:hover {
  transform: translateY(-2px);
  border-color: var(--primary);
}
.pick[aria-pressed='true'] {
  border-color: var(--primary);
  background: var(--primary-soft);
  box-shadow: inset 0 0 0 1px var(--primary);
}
.pick[aria-pressed='true']::after {
  content: '✓';
  position: absolute;
  top: 0.7rem;
  inset-inline-end: 0.8rem;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--primary);
  color: #fff;
  font-size: 0.78rem;
  font-weight: 800;
}
.pick[disabled] {
  opacity: 0.55;
  cursor: not-allowed;
  transform: none;
}
.pick .who {
  display: flex;
  align-items: center;
  gap: 0.7rem;
}
.pick .face {
  width: 44px;
  height: 44px;
  flex: none;
  border-radius: 50%;
  object-fit: cover;
  background: var(--primary-soft);
}
.pick .cost {
  font-family: var(--display);
  font-size: 1.12rem;
  font-weight: 700;
  color: var(--primary);
}
.pick .meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  font-size: 0.8rem;
  color: var(--muted);
}

/* Times. Tabular numbers so a column of them lines up. */
.slots {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(104px, 100%), 1fr));
  gap: 0.5rem;
}
.slot {
  padding: 0.62rem 0.4rem;
  border: 1.5px solid var(--sand);
  border-radius: 12px;
  background: var(--paper);
  font: inherit;
  font-size: 0.92rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  cursor: pointer;
}
.slot:hover {
  border-color: var(--primary);
}
.slot[aria-pressed='true'] {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}
.slot[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
  text-decoration: line-through;
}
.daystrip {
  display: flex;
  gap: 0.45rem;
  overflow-x: auto;
  padding-bottom: 0.4rem;
  margin-bottom: 0.9rem;
  scrollbar-width: thin;
}
.daystrip button {
  flex: none;
  display: grid;
  gap: 0.1rem;
  min-width: 66px;
  padding: 0.55rem 0.5rem;
  border: 1.5px solid var(--sand);
  border-radius: 14px;
  background: var(--paper);
  font: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--muted);
  cursor: pointer;
}
.daystrip button b {
  font-family: var(--display);
  font-size: 1.15rem;
  color: var(--ink);
}
.daystrip button[aria-pressed='true'] {
  background: var(--primary);
  border-color: var(--primary);
  color: #dfeae6;
}
.daystrip button[aria-pressed='true'] b {
  color: #fff;
}

/* The summary rail that follows a booking down the page. */
.tally-card {
  display: grid;
  gap: 0.5rem;
}
.tally-card .line {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.92rem;
}
.tally-card .line span {
  color: var(--muted);
}
.tally-card .line b {
  font-weight: 700;
  text-align: end;
}
.tally-card .total {
  border-top: 1px solid var(--sand);
  padding-top: 0.6rem;
  font-family: var(--display);
  font-size: 1.3rem;
}
.tally-card .total b {
  color: var(--primary);
}

/* ── ways to pay ─────────────────────────────────────────────────────────── */

.methods {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(150px, 100%), 1fr));
  gap: 0.6rem;
}
.method {
  display: grid;
  gap: 0.35rem;
  place-items: center;
  padding: 0.9rem 0.6rem;
  border: 1.5px solid var(--sand);
  border-radius: var(--radius);
  background: var(--paper);
  font: inherit;
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--ink);
  text-align: center;
  cursor: pointer;
  transition: transform 0.14s ease, border-color 0.14s ease;
}
.method:hover {
  transform: translateY(-2px);
  border-color: var(--primary);
}
.method[aria-pressed='true'] {
  border-color: var(--primary);
  background: var(--primary-soft);
  box-shadow: inset 0 0 0 1px var(--primary);
}
.method .glyph {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 12px;
  background: var(--surface);
  color: var(--primary);
}
.method .glyph svg {
  width: 22px;
  height: 22px;
}
.method img {
  width: 42px;
  height: 42px;
  object-fit: contain;
}
.method small {
  color: var(--muted);
  font-weight: 600;
  font-size: 0.76rem;
}
.method[data-kind='crypto'] .glyph,
.method[data-kind='medcoin'] .glyph {
  background: color-mix(in srgb, var(--gold) 22%, transparent);
  color: color-mix(in srgb, var(--gold) 72%, #000);
}

/* Where to send the money, once a method is chosen. */
.paylines {
  display: grid;
  gap: 0.6rem;
  margin-top: 1rem;
}
.copyrow {
  display: flex;
  align-items: center;
  /* A wallet address is longer than a narrow screen. The row wraps rather than
     squeezing the copy button off the edge, and the note below it takes a line
     of its own. */
  flex-wrap: wrap;
  gap: 0.6rem;
  max-width: 100%;
  padding: 0.7rem 0.85rem;
  border: 1px dashed var(--sand-deep);
  border-radius: 12px;
  background: var(--surface);
}
.copyrow .k {
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
.copyrow .v {
  flex: 1 1 12ch;
  min-width: 0;
  font-family: ui-monospace, 'DejaVu Sans Mono', monospace;
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  word-break: break-all;
  user-select: all;
}
.copyrow .btn {
  margin-inline-start: auto;
  flex: none;
}
.copyrow small {
  flex: 1 0 100%;
}

/* ═══════════════════════════════════════════════════════════════════════════
   APPOINTMENTS — marks, the settlement timer, contact buttons
   ══════════════════════════════════════════════════════════════════════════ */

.countdown {
  display: inline-block;
  font-family: ui-monospace, 'DejaVu Sans Mono', monospace;
  font-size: 0.88rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  padding: 0.16rem 0.5rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--warn) 16%, transparent);
  color: color-mix(in srgb, var(--warn) 85%, #000);
}
.countdown.over {
  background: color-mix(in srgb, var(--danger) 16%, transparent);
  color: var(--danger);
  animation: throb 1.6s ease-in-out infinite;
}

/* The three working cells of the administrator's appointment table: when it is
   due, whether it is paid, whether it happened. Each stacks its own parts so a
   row stays readable however long the clinician's name is, and each is given a
   floor width so the columns do not concertina as the countdown ticks from
   "2h 05m" down to "9m 58s". */
.duecell,
.paycell,
.givencell {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.3rem;
  min-width: 9.5rem;
}
.duecell small,
.paycell small,
.givencell small {
  color: var(--muted);
}
.paycell .btn {
  white-space: nowrap;
}
.givencell .switch {
  margin: 0;
}

/* ═══════════════════════════════════════════════════════════════════════════
   REGISTERING A PATIENT BY HAND, AND THE MULTI-DAY PROGRAMMES
   The credentials block is read aloud down a telephone as often as it is
   copied, so the values are monospaced and set apart from their labels rather
   than run together; and the dispatch message is shown as the plain text it
   will actually be sent as, wrapping rather than scrolling sideways.
   ══════════════════════════════════════════════════════════════════════════ */

.credgrid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.6rem;
  margin: 0.9rem 0;
}
.cred {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--sand);
  border-radius: 12px;
  background: var(--surface);
}
.cred span {
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.cred strong {
  font-size: 1rem;
  /* A username or a password may have no space in it to break at, and a value
     that cannot break is a value that pushes the whole drawer sideways. */
  overflow-wrap: anywhere;
}
.dispatch {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-width: 100%;
  margin: 0.4rem 0 0;
  padding: 0.9rem 1rem;
  border: 1px solid var(--sand);
  border-radius: 12px;
  background: var(--surface);
  font-family: ui-monospace, 'DejaVu Sans Mono', monospace;
  font-size: 0.84rem;
  line-height: 1.6;
}

.pkghead {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.6rem;
}
.pkghead h3 {
  margin: 0;
}
.pkgpills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

/* One tile per bought day. `auto-fill` with a floor rather than a fixed count
   means a five-day programme and a thirty-day one both look deliberate, and
   `minmax(0, …)` on the track keeps a long clinician email from widening the
   grid past the panel. */
.daygrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(8.5rem, 100%), 1fr));
  gap: 0.5rem;
  margin: 0.8rem 0;
}
.daybox {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
  padding: 0.55rem 0.65rem;
  border: 1px solid var(--sand);
  border-radius: 12px;
  background: var(--paper);
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.daybox:hover {
  border-color: var(--primary);
}
/* The patient's copy of the same grid. It reports rather than records, so it
   loses the pointer and the hover — nothing here is clickable. */
.daybox.flat {
  cursor: default;
}
.daybox.flat:hover {
  border-color: var(--sand);
}
.daybox.flat.done:hover {
  border-color: color-mix(in srgb, var(--good) 40%, transparent);
}
.daybox.done {
  background: color-mix(in srgb, var(--good) 12%, transparent);
  border-color: color-mix(in srgb, var(--good) 40%, transparent);
}
.daybox input {
  width: 1.15rem;
  height: 1.15rem;
  margin: 0 0 0.2rem;
  accent-color: var(--primary);
}
.daybox .dayno {
  font-weight: 700;
  font-size: 0.9rem;
}
.daybox small {
  font-size: 0.72rem;
  color: var(--muted);
  overflow-wrap: anywhere;
}

@media (max-width: 560px) {
  .credgrid {
    grid-template-columns: minmax(0, 1fr);
  }
  .daygrid {
    grid-template-columns: repeat(auto-fill, minmax(min(7rem, 100%), 1fr));
  }
}
@keyframes throb {
  50% {
    opacity: 0.55;
  }
}

.marks {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  align-items: center;
}
.markpair {
  display: grid;
  gap: 0.2rem;
  font-size: 0.8rem;
  color: var(--muted);
}
.markpair b {
  color: var(--ink);
}

/* The row of ways to reach a clinician directly. Each one is a real link:
   `tel:`, `mailto:`, and the deep links the three messengers publish. */
.contacts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}
.contacts a {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.45rem 0.8rem;
  border-radius: 999px;
  border: 1px solid var(--sand-deep);
  background: var(--paper);
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--primary);
  text-decoration: none;
  transition: transform 0.14s ease, background 0.14s ease;
}
.contacts a:hover {
  transform: translateY(-1px);
  background: var(--primary-soft);
}
.contacts a svg {
  width: 17px;
  height: 17px;
}
.contacts a[data-net='whatsapp'] {
  color: #0b7a58;
  border-color: rgba(11, 122, 88, 0.35);
}
.contacts a[data-net='telegram'] {
  color: #1668a4;
  border-color: rgba(22, 104, 164, 0.35);
}
.contacts a[data-net='imo'] {
  color: #1b5fbe;
  border-color: rgba(27, 95, 190, 0.35);
}

/* ── the availability grid a clinician fills in ──────────────────────────── */

.weekgrid {
  display: grid;
  gap: 0.5rem;
}
.weekrow {
  display: grid;
  grid-template-columns: minmax(6.5rem, auto) repeat(2, minmax(0, 1fr)) auto auto;
  gap: 0.5rem;
  align-items: center;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--sand);
  border-radius: 12px;
  background: var(--paper);
}
.weekrow .day {
  font-weight: 700;
}
.weekrow input[type='time'] {
  min-height: 40px;
  padding-block: 0.4rem;
}
.weekrow.off {
  opacity: 0.6;
  background: var(--surface);
}
@media (max-width: 700px) {
  .weekrow {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
  .weekrow .day {
    grid-column: 1 / -1;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   THE PUBLIC FEED
   ══════════════════════════════════════════════════════════════════════════ */

.feed {
  display: grid;
  gap: 1.1rem;
  max-width: 680px;
  margin-inline: auto;
}
.post {
  background: var(--paper);
  border: 1px solid var(--sand);
  border-radius: calc(var(--radius) + 2px);
  box-shadow: var(--shadow-low);
  overflow: hidden;
}
.post-head {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) auto;
  gap: 0.15rem 0.7rem;
  align-items: center;
  padding: 0.9rem 1rem 0.6rem;
}
.post-head .face {
  width: 44px;
  height: 44px;
  grid-row: span 2;
  border-radius: 50%;
  object-fit: cover;
  background: var(--primary-soft);
}
.post-head b {
  font-size: 0.98rem;
  display: flex;
  align-items: center;
  gap: 0.35rem;
}
.post-head b svg {
  width: 15px;
  height: 15px;
  color: var(--primary);
}
.post-head small {
  color: var(--muted);
  font-size: 0.8rem;
  grid-column: 2;
}
.post-body {
  padding: 0.2rem 1rem 0.9rem;
}
.post-body h3 {
  font-size: 1.12rem;
  margin-bottom: 0.4rem;
}
.post-body p {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.post-media {
  background: #0a0a0a;
}
.post-media img,
.post-media video {
  width: 100%;
  max-height: 62vh;
  object-fit: contain;
}
.post-media audio {
  width: 100%;
  padding: 0.8rem 1rem;
  background: var(--surface);
}
.post-file {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0 1rem 0.9rem;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--sand);
  border-radius: 12px;
  background: var(--surface);
  text-decoration: none;
  color: var(--primary);
  font-weight: 700;
  font-size: 0.9rem;
}
.post-file svg {
  width: 20px;
  height: 20px;
  flex: none;
}
.post-tally {
  display: flex;
  gap: 0.9rem;
  padding: 0.5rem 1rem;
  border-top: 1px solid var(--surface);
  font-size: 0.82rem;
  color: var(--muted);
}
.post-acts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border-top: 1px solid var(--sand);
}
.post-acts button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  padding: 0.7rem 0.4rem;
  border: 0;
  background: transparent;
  font: inherit;
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--muted);
  cursor: pointer;
}
.post-acts button:hover {
  background: var(--surface);
  color: var(--ink);
}
.post-acts button svg {
  width: 18px;
  height: 18px;
}
.post-acts button.liked {
  color: var(--accent);
}
.post-acts button + button {
  border-inline-start: 1px solid var(--sand);
}

.comments {
  display: grid;
  gap: 0.6rem;
  padding: 0.8rem 1rem 1rem;
  border-top: 1px solid var(--sand);
  background: var(--surface);
}
.comments[hidden] {
  display: none;
}
.comment {
  display: grid;
  gap: 0.1rem;
  padding: 0.6rem 0.8rem;
  border-radius: 14px;
  background: var(--paper);
  border: 1px solid var(--sand);
  font-size: 0.9rem;
}
.comment b {
  font-size: 0.86rem;
}
.comment small {
  color: var(--muted);
  font-size: 0.76rem;
}
.comment p {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.composer {
  display: flex;
  gap: 0.5rem;
  align-items: flex-end;
}
.composer textarea {
  min-height: 44px;
  resize: vertical;
}
.composer .btn {
  flex: none;
}

/* ═══════════════════════════════════════════════════════════════════════════
   THE CONSULTATION ROOM
   ══════════════════════════════════════════════════════════════════════════ */

.room {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(280px, 0.9fr);
  gap: 1rem;
  align-items: start;
}
@media (max-width: 940px) {
  .room {
    grid-template-columns: minmax(0, 1fr);
  }
}

.callframe {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  background: #08110f;
  min-height: 420px;
  box-shadow: var(--shadow-high);
}
.callframe iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
.callframe .placeholder {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  gap: 0.8rem;
  justify-items: center;
  padding: 2rem;
  text-align: center;
  color: #cfe0db;
}
.callframe .placeholder svg {
  width: 44px;
  height: 44px;
  color: var(--glow);
}

/* The controls under the frame, and the alternatives beside them. A call in
   Addis fails often enough that "other ways to call" is not a footnote. */
.callbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  margin-top: 0.8rem;
}
.altcall {
  display: grid;
  gap: 0.5rem;
}
.altcall .btn {
  justify-content: flex-start;
}

.chatpane {
  display: flex;
  flex-direction: column;
  height: min(70vh, 620px);
  background: var(--paper);
  border: 1px solid var(--sand);
  border-radius: var(--radius);
  overflow: hidden;
}
.chatlog {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.9rem;
  background: var(--surface);
  overscroll-behavior: contain;
}
.msg {
  max-width: 82%;
  padding: 0.55rem 0.8rem;
  border-radius: 16px 16px 16px 4px;
  background: var(--paper);
  border: 1px solid var(--sand);
  font-size: 0.92rem;
  box-shadow: var(--shadow-low);
}
.msg.mine {
  align-self: flex-end;
  border-radius: 16px 16px 4px 16px;
  background: var(--primary);
  border-color: var(--primary);
  color: #f2f7f5;
}
.msg .who {
  display: block;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  opacity: 0.75;
  margin-bottom: 0.15rem;
}
.msg p {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.msg time {
  display: block;
  font-size: 0.68rem;
  opacity: 0.65;
  margin-top: 0.2rem;
  text-align: end;
}
.msg img {
  border-radius: 10px;
  margin-top: 0.35rem;
}
.msg audio {
  width: 100%;
  margin-top: 0.35rem;
}
.chatsend {
  display: flex;
  gap: 0.45rem;
  padding: 0.6rem;
  border-top: 1px solid var(--sand);
  background: var(--paper);
}
.chatsend textarea {
  min-height: 42px;
  max-height: 120px;
  resize: none;
}
.chatsend .btn {
  flex: none;
  min-height: 42px;
  padding-inline: 0.9rem;
}

/* ═══════════════════════════════════════════════════════════════════════════
   MONEY — balances, MedCoins, the withdrawal request
   ══════════════════════════════════════════════════════════════════════════ */

.moneyrow {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr));
  gap: 0.8rem;
}
.moneybox {
  padding: 1rem 1.1rem;
  border-radius: var(--radius);
  background: var(--paper);
  border: 1px solid var(--sand);
  box-shadow: var(--shadow-low);
}
.moneybox .k {
  font-size: 0.76rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
.moneybox .v {
  font-family: var(--display);
  font-size: 1.75rem;
  font-weight: 600;
  color: var(--primary);
  line-height: 1.15;
  margin-top: 0.2rem;
}
.moneybox small {
  display: block;
  color: var(--muted);
  font-size: 0.82rem;
  margin-top: 0.25rem;
}
.moneybox.gold {
  background: linear-gradient(150deg, color-mix(in srgb, var(--gold) 20%, var(--paper)), var(--paper));
  border-color: color-mix(in srgb, var(--gold) 40%, transparent);
}
.moneybox.gold .v {
  color: color-mix(in srgb, var(--gold) 80%, #000);
}
.moneybox.confirmed .v {
  color: var(--good);
}

.coinface {
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: radial-gradient(120% 120% at 30% 20%, #f6dd9a, var(--gold));
  color: #4a3204;
  font-weight: 800;
  font-size: 0.78rem;
  box-shadow: inset 0 -2px 3px rgba(0, 0, 0, 0.25), 0 2px 4px rgba(0, 0, 0, 0.25);
}

/* ── odds and ends the new pages need ───────────────────────────────────── */

.rowbetween {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  align-items: center;
  justify-content: space-between;
}
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.22rem 0.6rem;
  border-radius: 999px;
  background: var(--primary-soft);
  color: var(--primary);
  font-size: 0.78rem;
  font-weight: 700;
}
.chip svg {
  width: 14px;
  height: 14px;
}
.chip.warm {
  background: var(--accent-soft);
  color: var(--accent);
}
.chip.gold {
  background: color-mix(in srgb, var(--gold) 22%, transparent);
  color: color-mix(in srgb, var(--gold) 80%, #000);
}
.chip.good {
  background: color-mix(in srgb, var(--good) 14%, transparent);
  color: var(--good);
}
.chip.bad {
  background: color-mix(in srgb, var(--danger) 14%, transparent);
  color: var(--danger);
}

.stack {
  display: grid;
  gap: 1rem;
}
.center-narrow {
  width: min(520px, 100%);
  margin-inline: auto;
}
.mute {
  color: var(--muted);
}
.tiny {
  font-size: 0.82rem;
}
[hidden] {
  display: none !important;
}

/* A page that is waiting for its first request. */
.skeleton {
  border-radius: 12px;
  background: linear-gradient(90deg, var(--sand) 25%, var(--surface) 50%, var(--sand) 75%);
  background-size: 240% 100%;
  animation: sweep 1.3s linear infinite;
  min-height: 14px;
}
@keyframes sweep {
  to {
    background-position: -240% 0;
  }
}

/* On a phone the top bar keeps only the essentials; the bottom bar carries
   navigation, which is the whole point of having one. */
@media (max-width: 620px) {
  :root {
    --bar-top: 58px;
  }
  /* The name stays. It used to be hidden here, which left a phone showing a
     logo and no site title at all — the one place a first-time visitor looks to
     find out where they are. Instead it shrinks and, if the name is a long one,
     truncates: `min-width: 0` is what lets a flex child shrink below its own
     content at all, and without it the words push the bar wider than the screen
     and reintroduce the horizontal scroll the reset exists to prevent. */
  .appbar.top .brand {
    min-width: 0;
    flex: 0 1 auto;
    gap: 0.5rem;
  }
  .appbar.top .brand .words {
    min-width: 0;
  }
  .appbar.top .brand .name,
  .appbar.top .brand .name-en {
    display: block;
    max-width: 42vw;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .appbar.top .brand .name {
    font-size: 1.05rem;
  }
  .appbar.top .brand .name-en {
    font-size: 0.6rem;
    letter-spacing: 0.1em;
  }
  .barbtn {
    min-width: 42px;
    padding-inline: 0.35rem;
  }
}

/* The two bars are chrome. They should never print. */
@media print {
  .appbar,
  .barpop,
  .sheet,
  .appbar.bottom {
    display: none !important;
  }
  body.app {
    padding: 0;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   CHOSEN STATES AND SMALL PARTS THE PAGES ASKED FOR

   A card that can be picked has to look picked. Without this the booking steps
   would let a reader choose a service and then show them exactly what they saw
   before, which reads as the press having failed.
   ══════════════════════════════════════════════════════════════════════════ */

.service.on,
.pro.on {
  border-color: var(--primary);
  box-shadow: inset 0 0 0 2px var(--primary), 0 calc(6px * var(--lift)) calc(18px * var(--lift)) -8px rgba(15, 114, 0, 0.55);
}
/* The service card already carries its position number in the top corner, so the
   chosen mark recolours that rather than fighting it for the same spot. */
.service.on .no {
  color: var(--good);
}
.pro {
  position: relative;
}
.pro.on::after {
  content: '✓';
  position: absolute;
  top: 0.7rem;
  inset-inline-end: 0.7rem;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--primary);
  color: #fff;
  font-size: 0.8rem;
  font-weight: 800;
}

/* A day the clinician has not posted hours for is still pressable — a
   coordinator can agree an exception — so it is dimmed, not disabled. */
.daystrip button.shut {
  opacity: 0.55;
  border-style: dashed;
}
.daystrip button.shut[aria-pressed='true'] {
  opacity: 1;
}

/* A time inside the hours the clinician actually posted. */
.slot.good {
  border-color: color-mix(in srgb, var(--good) 55%, transparent);
  background: color-mix(in srgb, var(--good) 9%, var(--paper));
}
.slot.good[aria-pressed='true'] {
  background: var(--primary);
  border-color: var(--primary);
}

/* A single consent tick sitting on its own, not inside a labelled field. */
.tickbox {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.85rem 1rem;
  border: 1.5px solid var(--sand-deep);
  border-radius: 14px;
  background: var(--paper);
  font-size: 0.92rem;
  font-weight: 600;
  cursor: pointer;
}
.tickbox input {
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: 0.1rem;
  accent-color: var(--primary);
}
.tickbox:has(input:checked) {
  border-color: var(--good);
  background: color-mix(in srgb, var(--good) 8%, var(--paper));
}

/* A button that reads as a link — used for the pressable steps in the booking
   rail, where the pill around it is already the affordance. */
button.linky {
  border: 0;
  padding: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-align: start;
}

/* The written thread sitting beside a live call is shorter than one standing on
   its own — the call is the thing being watched. */
.chatpane.compact {
  height: min(46vh, 380px);
}
.msg video {
  max-width: 100%;
  border-radius: 10px;
  margin-top: 0.35rem;
}

/* The foot of the feed: the "load more" button, or the note that says there is
   no more. */
.feed-foot {
  display: grid;
  gap: 0.6rem;
  margin-top: 1rem;
}
.center {
  text-align: center;
}

/* `.pick .face` was drawn for a photograph of a clinician, but the same row is
   used for choices that have no photograph — a service area, a way back into a
   forgotten account. Given a <span> holding an icon instead of an <img>, centre
   the icon in the same circle rather than letting it fill it. */
.pick .face:not(img) {
  display: grid;
  place-items: center;
  color: var(--primary);
}
.pick .face svg {
  width: 22px;
  height: 22px;
}

/* ═════════════════════════════════════════════════════════════════════════════
   THE APP LAYER
   Everything below turns the pages above into something that behaves like an
   application on a telephone: buttons with a real press, a logo that covers a
   navigation, glass over the fixed bars, and the small animations that tell a
   patient what a service is before they have read its name.

   It is appended rather than woven in so that it can be read as one piece, and
   so that removing it would leave the site working and merely flat.
   Its companion is /js/engine.js.
   ════════════════════════════════════════════════════════════════════════════ */

:root {
  /* One easing for everything that moves under a thumb. Slightly overshooting
     on the way out is what makes a button feel like an object. */
  --spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --glass: color-mix(in srgb, var(--paper) 72%, transparent);
  --glass-line: color-mix(in srgb, var(--sand-deep) 60%, transparent);
}

/* ── 1. Tactile buttons ──────────────────────────────────────────────────────
   A button is a solid object with a thickness. The thickness is a second shadow
   in the button's own dark colour, directly beneath it; pressing shortens it and
   moves the button down by exactly the amount it lost, so the top face travels
   and the base stays put. That is the whole trick, and it is why the press reads
   as physical rather than as a shrink. */

.btn {
  position: relative;
  isolation: isolate;
  --sink: calc(4px * var(--lift));
  --face: var(--btn-bg);
  transform: translateY(0);
  box-shadow:
    0 calc(var(--sink)) 0 0 color-mix(in srgb, var(--btn-bg) 55%, var(--deep)),
    0 calc(var(--sink) + 6px) 18px -8px rgba(8, 48, 44, calc(0.45 * var(--lift)));
  transition:
    transform 0.18s var(--spring),
    box-shadow 0.18s var(--ease),
    background 0.2s var(--ease),
    filter 0.2s var(--ease);
}

/* The lit top edge — a one-pixel highlight that says which way is up. */
.btn::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0) 45%);
  opacity: calc(0.9 * var(--lift));
  z-index: -1;
}

/* The light that follows the thumb. --px/--py are written by engine.js on
   pointerdown; without them it sits in the middle and looks like a plain sheen. */
.btn::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: radial-gradient(circle at var(--px, 50%) var(--py, 50%), rgba(255, 255, 255, 0.3), transparent 62%);
  opacity: 0;
  transition: opacity 0.2s var(--ease);
  z-index: -1;
}

.btn:hover {
  transform: translateY(calc(-1px * var(--lift)));
  box-shadow:
    0 calc(var(--sink) + 1px) 0 0 color-mix(in srgb, var(--btn-bg) 55%, var(--deep)),
    0 calc(var(--sink) + 10px) 26px -10px rgba(8, 48, 44, calc(0.5 * var(--lift)));
}

.btn:active,
.btn.pressing {
  transform: translateY(var(--sink));
  box-shadow:
    0 0 0 0 color-mix(in srgb, var(--btn-bg) 55%, var(--deep)),
    0 2px 6px -2px rgba(8, 48, 44, 0.4);
}

.btn.pressing::after {
  opacity: 1;
}

/* The flat variants keep the press but not the plinth — a ghost button with a
   thick dark base underneath it would look like a mistake. */
.btn.ghost,
.btn.quiet,
.btn.danger {
  --sink: calc(2px * var(--lift));
  box-shadow: 0 var(--sink) 0 0 color-mix(in srgb, var(--sand-deep) 70%, transparent);
}
.btn.ghost::before,
.btn.quiet::before,
.btn.danger::before {
  opacity: 0;
}

.btn[disabled],
.btn[aria-busy='true'] {
  box-shadow: none;
  transform: none;
  filter: saturate(0.7);
}

/* The colour-coded set. Each carries its own meaning, and each one's plinth is
   mixed from its own face colour so the object is one material. */
.btn.gold {
  --btn-bg: var(--gold);
  --btn-ink: #2a1c05;
}
.btn.good {
  --btn-bg: var(--good);
}
.btn.warn {
  --btn-bg: var(--warn);
}
.btn.solid-danger {
  --btn-bg: var(--danger);
  --btn-ink: #fff;
  border-color: transparent;
}
.btn.glass {
  --btn-bg: var(--glass);
  --btn-ink: var(--ink);
  backdrop-filter: blur(14px) saturate(1.3);
  -webkit-backdrop-filter: blur(14px) saturate(1.3);
  border-color: var(--glass-line);
}

/* A button that fills its row, which on a telephone is most of them. */
.btn.block {
  width: 100%;
}

/* Anything else the engine marks as pressed sinks a little, without a plinth. */
.pressing:not(.btn) {
  transform: scale(0.97);
  transition: transform 0.12s var(--ease);
}
.chip.pressing,
.pick.pressing {
  transform: scale(0.965);
}

/* ── 2. Glass over the fixed bars ────────────────────────────────────────── */

.appbar.top {
  transition:
    transform 0.28s var(--ease),
    background 0.28s var(--ease),
    box-shadow 0.28s var(--ease),
    height 0.28s var(--ease);
}
.appbar.top.shrunk {
  background: color-mix(in srgb, var(--navbar) 86%, transparent);
  backdrop-filter: blur(18px) saturate(1.4);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  box-shadow: 0 10px 30px -18px rgba(8, 48, 44, 0.7);
}
/* Reading downwards, the top bar gets out of the way. A flick up brings it back
   — see onScroll in engine.js. */
.appbar.top.tucked {
  transform: translateY(-100%);
}
.appbar.bottom {
  backdrop-filter: blur(20px) saturate(1.35);
  -webkit-backdrop-filter: blur(20px) saturate(1.35);
}

/* A bar button presses like everything else, but sinks rather than tilting —
   there is no room under it for a plinth. */
.barbtn {
  transition: transform 0.18s var(--spring), color 0.18s var(--ease), opacity 0.18s var(--ease);
}
.barbtn.pressing {
  transform: scale(0.9);
}
.barbtn.hot.pressing {
  transform: translateY(2px) scale(0.94);
}

/* ── 3. The logo loader ──────────────────────────────────────────────────────
   Raised over the page on any navigation. The logo breathes and a ring sweeps
   around it; both stop the moment the next page paints. */

.appload {
  position: fixed;
  inset: 0;
  z-index: 900;
  display: grid;
  place-items: center;
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  backdrop-filter: blur(10px) saturate(1.2);
  -webkit-backdrop-filter: blur(10px) saturate(1.2);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.18s var(--ease), visibility 0.18s;
}
.appload.on {
  opacity: 1;
  visibility: visible;
}
.appload-mark {
  position: relative;
  display: grid;
  place-items: center;
  width: 108px;
  height: 108px;
}
.appload-mark img {
  width: 62px;
  height: 62px;
  border-radius: 16px;
  animation: logo-breathe 1.1s var(--ease) infinite;
}
.appload-ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 3px solid color-mix(in srgb, var(--primary) 18%, transparent);
  border-top-color: var(--glow);
  animation: logo-spin 0.9s linear infinite;
}

@keyframes logo-breathe {
  0%,
  100% {
    transform: scale(1) rotate(0deg);
  }
  45% {
    transform: scale(1.12) rotate(-7deg);
  }
  70% {
    transform: scale(1.04) rotate(4deg);
  }
}
@keyframes logo-spin {
  to {
    transform: rotate(360deg);
  }
}

/* ── 4. Pull to refresh ──────────────────────────────────────────────────── */

.apppull {
  position: fixed;
  top: calc(var(--bar-top) - 6px);
  left: 50%;
  z-index: 700;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--paper);
  box-shadow: var(--shadow-high);
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, calc(var(--pull, 0px) - 46px));
  transition: opacity 0.15s var(--ease), transform 0.05s linear;
}
.apppull.on {
  opacity: 1;
}
.apppull-ring {
  width: 17px;
  height: 17px;
  border-radius: 50%;
  border: 2.5px solid color-mix(in srgb, var(--primary) 22%, transparent);
  border-top-color: var(--primary);
  transition: transform 0.2s var(--ease);
}
.apppull.ready .apppull-ring {
  border-top-color: var(--glow);
  transform: scale(1.18);
}
.apppull.spinning {
  opacity: 1;
  transform: translate(-50%, 12px);
}
.apppull.spinning .apppull-ring {
  animation: logo-spin 0.7s linear infinite;
}

/* ── 5. Entering and swapping views ──────────────────────────────────────── */

.view-out {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.11s var(--ease), transform 0.11s var(--ease);
}
.view-in {
  animation: view-in 0.24s var(--ease) both;
}
@keyframes view-in {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
}

.enter-up {
  animation: enter-up 0.5s var(--ease) both;
  animation-delay: var(--enter-delay, 0ms);
}
@keyframes enter-up {
  from {
    opacity: 0;
    transform: translateY(14px) scale(0.985);
  }
}

.flash-good,
.flash-warn {
  animation: flash-ring 1.1s var(--ease) 1;
}
.flash-good {
  --flash: var(--good);
}
.flash-warn {
  --flash: var(--warn);
}
@keyframes flash-ring {
  0% {
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--flash) 55%, transparent);
  }
  60% {
    box-shadow: 0 0 0 12px color-mix(in srgb, var(--flash) 0%, transparent);
  }
  100% {
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--flash) 0%, transparent);
  }
}

/* The default view transition, for browsers that have one. */
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) {
    animation: view-fade-out 0.16s var(--ease) both;
  }
  ::view-transition-new(root) {
    animation: view-in 0.24s var(--ease) both;
  }
}
@keyframes view-fade-out {
  to {
    opacity: 0;
    transform: translateY(-6px);
  }
}

/* ── 6. Glass panels ─────────────────────────────────────────────────────── */

.glasspanel {
  position: relative;
  border-radius: var(--radius);
  border: 1px solid var(--glass-line);
  background: linear-gradient(
    155deg,
    color-mix(in srgb, var(--paper) 88%, transparent),
    color-mix(in srgb, var(--primary-soft) 60%, transparent)
  );
  backdrop-filter: blur(16px) saturate(1.25);
  -webkit-backdrop-filter: blur(16px) saturate(1.25);
  box-shadow: var(--shadow-high);
  padding: 1rem 1.05rem;
}
.glasspanel::before {
  content: '';
  position: absolute;
  inset: 0 0 auto;
  height: 1px;
  border-radius: inherit;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.7), transparent);
}

/* ── 7. Home-care micro-animations ───────────────────────────────────────────
   A patient scanning a list of services reads the picture before the words, and
   more than one of them cannot read the words at all. These are drawn in CSS so
   they cost nothing to load and animate on the compositor. */

.careanim {
  position: relative;
  display: grid;
  place-items: center;
  width: 62px;
  height: 62px;
  border-radius: 20px;
  flex: none;
  background: radial-gradient(circle at 30% 25%, color-mix(in srgb, var(--glow) 26%, transparent), transparent 70%),
    var(--primary-soft);
  color: var(--primary);
  overflow: hidden;
}
.careanim svg {
  width: 30px;
  height: 30px;
  position: relative;
  z-index: 2;
}

/* The visit: a ring travelling outward, like someone arriving. */
.careanim.visit::after {
  content: '';
  position: absolute;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--primary) 45%, transparent);
  animation: care-arrive 2.4s var(--ease) infinite;
}
@keyframes care-arrive {
  0% {
    transform: scale(0.5);
    opacity: 0;
  }
  25% {
    opacity: 0.9;
  }
  100% {
    transform: scale(2.6);
    opacity: 0;
  }
}

/* The heartbeat: the icon itself beating at a resting rate, roughly 72 a
   minute, because a pulse animation on a care site should be a plausible one. */
.careanim.vital svg {
  animation: care-beat 0.83s var(--ease) infinite;
  color: var(--danger);
}
@keyframes care-beat {
  0%,
  55%,
  100% {
    transform: scale(1);
  }
  12% {
    transform: scale(1.18);
  }
  26% {
    transform: scale(1.02);
  }
  38% {
    transform: scale(1.1);
  }
}

/* The trace under a vital sign — a line sweeping left to right. */
.vitalline {
  position: relative;
  height: 26px;
  overflow: hidden;
  border-radius: 8px;
  background: color-mix(in srgb, var(--primary) 5%, transparent);
}
.vitalline svg {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 200%;
  color: var(--good);
  animation: vital-sweep 3.2s linear infinite;
}
@keyframes vital-sweep {
  to {
    transform: translateX(-50%);
  }
}

/* The medication round, the wound dressing, the elderly visit — a slow, calm
   sway rather than a pulse, because nothing about them is urgent. */
.careanim.calm svg {
  animation: care-sway 3.6s var(--ease) infinite;
}
@keyframes care-sway {
  0%,
  100% {
    transform: translateY(0) rotate(0deg);
  }
  50% {
    transform: translateY(-3px) rotate(-4deg);
  }
}

/* ── 8. Telehealth indicators ────────────────────────────────────────────────
   Three modes, three different pictures of the same idea: something is live. */

.teleind {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: 54px;
  height: 54px;
  border-radius: 18px;
  flex: none;
  background: var(--primary-soft);
  color: var(--primary);
}
.teleind svg {
  width: 26px;
  height: 26px;
  z-index: 2;
}

/* Video: a ring pulsing outward, the way a camera light does. */
.teleind.video::before,
.teleind.video::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  border: 2px solid color-mix(in srgb, var(--primary) 40%, transparent);
  animation: tele-ring 2s var(--ease) infinite;
}
.teleind.video::after {
  animation-delay: 1s;
}
@keyframes tele-ring {
  0% {
    transform: scale(0.85);
    opacity: 0;
  }
  30% {
    opacity: 0.8;
  }
  100% {
    transform: scale(1.35);
    opacity: 0;
  }
}

/* Audio: three bars of a level meter, at different rates so they never line up. */
.teleind.audio .bars {
  position: absolute;
  bottom: 7px;
  display: flex;
  gap: 3px;
  align-items: flex-end;
  height: 14px;
  z-index: 3;
}
.teleind.audio .bars i {
  display: block;
  width: 3px;
  border-radius: 2px;
  background: var(--glow);
  animation: tele-level 0.9s var(--ease) infinite;
}
.teleind.audio .bars i:nth-child(2) {
  animation-duration: 0.62s;
}
.teleind.audio .bars i:nth-child(3) {
  animation-duration: 1.15s;
}
@keyframes tele-level {
  0%,
  100% {
    height: 4px;
  }
  50% {
    height: 14px;
  }
}

/* Text: three dots typing. */
.teleind.chat .dots {
  position: absolute;
  bottom: 8px;
  display: flex;
  gap: 3px;
  z-index: 3;
}
.teleind.chat .dots i {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent);
  animation: tele-type 1.2s var(--ease) infinite;
}
.teleind.chat .dots i:nth-child(2) {
  animation-delay: 0.15s;
}
.teleind.chat .dots i:nth-child(3) {
  animation-delay: 0.3s;
}
@keyframes tele-type {
  0%,
  60%,
  100% {
    opacity: 0.25;
    transform: translateY(0);
  }
  30% {
    opacity: 1;
    transform: translateY(-3px);
  }
}

/* A clinician who is online right now. */
.livedot {
  position: relative;
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--good);
  flex: none;
}
.livedot::after {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 2px solid var(--good);
  animation: tele-ring 1.8s var(--ease) infinite;
}

/* ── 9. The cascaded booking rail ────────────────────────────────────────────
   The step number, its title, and a subtitle that says what this step is for.
   The subtitle is the part that changes on every step, so it is the part that
   animates: it slides in from the side the reader is travelling. */

.cascade {
  position: relative;
  display: grid;
  gap: 0.5rem;
  padding: 0.9rem 1rem;
  border-radius: var(--radius);
  background: linear-gradient(150deg, var(--primary), var(--deep));
  color: #fff;
  box-shadow: var(--shadow-high);
  overflow: hidden;
}
.cascade::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(80% 60% at 15% 0%, rgba(255, 255, 255, 0.16), transparent 70%);
  pointer-events: none;
}
.cascade-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  position: relative;
}
.cascade-num {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex: none;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.16);
  font-weight: 700;
  font-size: 0.9rem;
  font-variant-numeric: tabular-nums;
}
.cascade-title {
  font-family: var(--display);
  font-size: 1.12rem;
  font-weight: 600;
  line-height: 1.2;
}
/* The head is number · words · picture, and the picture sits at the far end. */
.cascade-head > div {
  min-width: 0;
  flex: 1;
}
.cascade-head .tiny {
  opacity: 0.7;
  font-variant-numeric: tabular-nums;
}
.cascade-glyph {
  margin-left: auto;
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  width: 48px;
  height: 48px;
}
.cascade-glyph.careanim svg,
.cascade-glyph.teleind svg {
  width: 24px;
  height: 24px;
}
.cascade-glyph.careanim.vital svg {
  color: #ffd9d9;
}
/* The animated subtitle. Keyed by step, so re-rendering the step replays it. */
.cascade-sub {
  position: relative;
  min-height: 1.35rem;
  font-size: 0.92rem;
  opacity: 0.88;
  animation: sub-in 0.42s var(--ease) both;
}
.cascade-sub.back {
  animation-name: sub-in-back;
}
@keyframes sub-in {
  from {
    opacity: 0;
    transform: translateX(14px);
  }
}
@keyframes sub-in-back {
  from {
    opacity: 0;
    transform: translateX(-14px);
  }
}

/* The progress line under the head, filled to the step the reader is on. */
.cascade-bar {
  position: relative;
  height: 5px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.18);
  overflow: hidden;
}
.cascade-bar i {
  display: block;
  height: 100%;
  width: var(--done, 0%);
  border-radius: 3px;
  background: linear-gradient(90deg, var(--glow), #fff);
  transition: width 0.45s var(--spring);
}
/* A moving sheen, so a long step does not look like a stalled one. */
.cascade-bar::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.35), transparent);
  transform: translateX(-100%);
  animation: bar-sheen 2.4s var(--ease) infinite;
}
@keyframes bar-sheen {
  to {
    transform: translateX(100%);
  }
}

/* The row of dots naming every step, for orientation rather than navigation. */
.cascade-dots {
  display: flex;
  gap: 0.3rem;
  flex-wrap: wrap;
}
.cascade-dots i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.28);
  transition: background 0.3s var(--ease), transform 0.3s var(--spring);
}
.cascade-dots i.done {
  background: var(--glow);
}
.cascade-dots i.now {
  background: #fff;
  transform: scale(1.5);
}
/* A step already completed can be gone back to, so its dot is a button. The
   button carries the hit area — 20px, thumb-sized — and the dot stays 7px. */
.cascade-dots button {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.cascade-dots button:hover i,
.cascade-dots button:focus-visible i {
  transform: scale(1.4);
  background: #fff;
}

/* ── 10. The contact channel that opens after payment ─────────────────────── */

.channel {
  display: grid;
  gap: 0.55rem;
  animation: view-in 0.4s var(--ease) both;
}
.contactline {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.7rem 0.85rem;
  border-radius: 14px;
  border: 1px solid var(--sand);
  background: var(--paper);
  color: inherit;
  text-decoration: none;
  transition: transform 0.16s var(--spring), border-color 0.16s var(--ease);
}
.contactline:hover {
  border-color: var(--primary);
  transform: translateX(3px);
}
.contactline .badge {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  flex: none;
  border-radius: 12px;
  background: var(--primary-soft);
  color: var(--primary);
}
.contactline .badge svg {
  width: 20px;
  height: 20px;
}
.contactline.telegram .badge {
  background: #e6f2fa;
  color: #1c93d6;
}
.contactline.whatsapp .badge {
  background: #e6f6ec;
  color: #128c4b;
}
.contactline.imo .badge {
  background: #eae9fb;
  color: #4a45c9;
}
.contactline.phone .badge {
  background: var(--accent-soft);
  color: var(--accent);
}
.contactline .who {
  display: grid;
  gap: 0.1rem;
  min-width: 0;
}
.contactline .who b {
  font-size: 0.95rem;
}
.contactline .who span {
  font-size: 0.82rem;
  color: var(--muted);
  overflow-wrap: anywhere;
}

/* ── 11. The P2P board ───────────────────────────────────────────────────────
   Two books side by side on a desk, stacked on a telephone. Each row is one
   offer: who, at what price, for how much, and what they will take. */

.p2p-tabs {
  display: flex;
  gap: 0.35rem;
  padding: 0.28rem;
  border-radius: 999px;
  background: var(--primary-soft);
}
.p2p-tabs button {
  flex: 1;
  border: 0;
  border-radius: 999px;
  padding: 0.55rem 0.8rem;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-weight: 700;
  font-size: 0.92rem;
  cursor: pointer;
  transition: background 0.22s var(--ease), color 0.22s var(--ease), transform 0.18s var(--spring);
}
.p2p-tabs button.on {
  background: var(--paper);
  color: var(--primary);
  box-shadow: var(--shadow-low);
}
.p2p-tabs button.on.sell {
  color: var(--danger);
}
.p2p-tabs button.pressing {
  transform: scale(0.96);
}

.offer {
  display: grid;
  gap: 0.6rem;
  padding: 0.85rem 0.9rem;
  border-radius: var(--radius);
  border: 1px solid var(--sand);
  background: var(--paper);
  box-shadow: var(--shadow-low);
  transition: transform 0.18s var(--spring), box-shadow 0.18s var(--ease), border-color 0.18s var(--ease);
}
.offer:hover {
  border-color: color-mix(in srgb, var(--primary) 35%, var(--sand));
  box-shadow: var(--shadow-high);
}
.offer-top {
  display: flex;
  align-items: center;
  gap: 0.55rem;
}
.offer-agent {
  display: grid;
  gap: 0.1rem;
  min-width: 0;
  flex: 1;
}
.offer-agent b {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.98rem;
}
.offer-agent small {
  color: var(--muted);
  font-size: 0.78rem;
}
.offer-price {
  text-align: end;
  font-family: var(--display);
  font-size: 1.3rem;
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--good);
}
.offer.sell .offer-price {
  color: var(--danger);
}
.offer-price small {
  display: block;
  font-family: var(--body);
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.offer-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 0.9rem;
  font-size: 0.83rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.offer-meta b {
  color: var(--ink);
  font-weight: 600;
}
.offer-foot {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.offer-foot .btn {
  margin-inline-start: auto;
}

/* The verification badge. Gold, silver or new — earned by completed trades. */
.vbadge {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border: 1px solid transparent;
}
.vbadge svg {
  width: 12px;
  height: 12px;
}
.vbadge.gold {
  background: color-mix(in srgb, var(--gold) 18%, var(--paper));
  border-color: color-mix(in srgb, var(--gold) 50%, transparent);
  color: #7a5410;
}
.vbadge.silver {
  background: #eef1f2;
  border-color: #cfd7d9;
  color: #4b5a5e;
}
.vbadge.new {
  background: var(--primary-soft);
  border-color: color-mix(in srgb, var(--primary) 25%, transparent);
  color: var(--primary);
}

/* The completion figure — the number people actually read before trading. */
.rate-ring {
  --pct: 100;
  position: relative;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  flex: none;
  border-radius: 50%;
  background: conic-gradient(var(--good) calc(var(--pct) * 1%), color-mix(in srgb, var(--sand) 70%, transparent) 0);
  font-size: 0.68rem;
  font-weight: 800;
  color: var(--primary);
}
.rate-ring::before {
  content: '';
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: var(--paper);
}
.rate-ring span {
  position: relative;
  z-index: 2;
  font-variant-numeric: tabular-nums;
}
.rate-ring.low {
  background: conic-gradient(var(--warn) calc(var(--pct) * 1%), color-mix(in srgb, var(--sand) 70%, transparent) 0);
}

/* The price ticker at the top of the board. */
.tickers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
  gap: 0.6rem;
}
.ticker {
  display: grid;
  gap: 0.15rem;
  padding: 0.75rem 0.85rem;
  border-radius: 16px;
  background: linear-gradient(150deg, var(--primary), var(--deep));
  color: #fff;
  box-shadow: var(--shadow-low);
}
.ticker.gold {
  background: linear-gradient(150deg, #b4832a, #7a5410);
}
.ticker .sym {
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.75;
}
.ticker .val {
  font-family: var(--display);
  font-size: 1.35rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
}
.ticker .sub {
  font-size: 0.76rem;
  opacity: 0.8;
}

/* An order in flight, with the pay window running down. */
.orderline {
  display: grid;
  gap: 0.5rem;
  padding: 0.85rem 0.9rem;
  border-radius: var(--radius);
  border: 1px solid var(--sand);
  background: var(--paper);
  border-inline-start: 4px solid var(--primary);
}
.orderline.paid {
  border-inline-start-color: var(--warn);
}
.orderline.disputed {
  border-inline-start-color: var(--danger);
  background: color-mix(in srgb, var(--danger) 4%, var(--paper));
}
.orderline.released {
  border-inline-start-color: var(--good);
}
.escrow-clock {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.16rem 0.5rem;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.8rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.escrow-clock.urgent {
  background: color-mix(in srgb, var(--danger) 12%, var(--paper));
  color: var(--danger);
  animation: care-beat 1.2s var(--ease) infinite;
}

/* The locked-amount strip: what is promised versus what can be spent. */
.lockbar {
  position: relative;
  height: 6px;
  border-radius: 3px;
  background: color-mix(in srgb, var(--primary) 12%, transparent);
  overflow: hidden;
}
.lockbar i {
  display: block;
  height: 100%;
  width: var(--locked, 0%);
  background: repeating-linear-gradient(
    45deg,
    var(--warn),
    var(--warn) 5px,
    color-mix(in srgb, var(--warn) 60%, #fff) 5px,
    color-mix(in srgb, var(--warn) 60%, #fff) 10px
  );
  transition: width 0.4s var(--ease);
}

/* ── 12. Asset cards in the wallet ───────────────────────────────────────── */

.assetcard {
  position: relative;
  display: grid;
  gap: 0.45rem;
  padding: 1rem;
  border-radius: 20px;
  color: #fff;
  overflow: hidden;
  background: linear-gradient(145deg, var(--primary), var(--deep));
  box-shadow: var(--shadow-high);
}
.assetcard.medcoin {
  background: linear-gradient(145deg, #c99a30, #6f4a08);
}
.assetcard.usdt {
  background: linear-gradient(145deg, #1a8f74, #06382c);
}
.assetcard::after {
  content: '';
  position: absolute;
  right: -30px;
  top: -30px;
  width: 130px;
  height: 130px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.09);
}
.assetcard .amount {
  font-family: var(--display);
  font-size: 1.9rem;
  font-weight: 700;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
}
.assetcard .sym {
  font-size: 0.74rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  opacity: 0.8;
}
.assetcard .worth {
  font-size: 0.85rem;
  opacity: 0.85;
  font-variant-numeric: tabular-nums;
}
.assetcard .held {
  font-size: 0.78rem;
  opacity: 0.75;
}

/* A saved external address or card. */
.addrline {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.7rem 0.8rem;
  border-radius: 14px;
  border: 1px solid var(--sand);
  background: var(--paper);
}
.addrline code {
  font-size: 0.78rem;
  overflow-wrap: anywhere;
  color: var(--muted);
}
.addrline .who {
  display: grid;
  gap: 0.15rem;
  min-width: 0;
  flex: 1;
}
.addrline .who b {
  font-size: 0.92rem;
}
.addrline .marks {
  margin-left: auto;
  flex: none;
}
.netpill {
  padding: 0.12rem 0.45rem;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  background: var(--primary-soft);
  color: var(--primary);
}
.netpill.bep20 {
  background: #fdf4dd;
  color: #8a6a08;
}

/* ── 13. Small mercies ───────────────────────────────────────────────────── */

/* A number that has just changed, counted up rather than replaced. */
.tnum {
  font-variant-numeric: tabular-nums;
  transition: color 0.3s var(--ease);
}

/* Anything the engine is waiting on. */
.busy {
  position: relative;
  pointer-events: none;
}
.busy::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: color-mix(in srgb, var(--paper) 55%, transparent);
  backdrop-filter: blur(1px);
}

/* On a telephone the two fixed bars own the top and bottom of the screen; give
   a sheet and a drawer room to sit above the bottom one. */
@supports (padding: max(0px)) {
  .appbar.bottom {
    padding-bottom: max(var(--safe-bottom), 0px);
  }
}

/* Somebody who has asked for less motion gets the layout and the colour and
   none of the loops. The single-shot transitions above are already neutralised
   by the global rule near the top of this file. */
@media (prefers-reduced-motion: reduce) {
  .careanim.visit::after,
  .careanim.vital svg,
  .careanim.calm svg,
  .vitalline svg,
  .teleind.video::before,
  .teleind.video::after,
  .teleind.audio .bars i,
  .teleind.chat .dots i,
  .livedot::after,
  .cascade-bar::after,
  .appload-mark img,
  .appload-ring,
  .escrow-clock.urgent {
    animation: none;
  }
  .appload-ring {
    border-top-color: var(--glow);
  }
}

/* ── 14. Chips that are buttons ──────────────────────────────────────────────
   `.chip` was a label. On the market board and the booking rail it is a filter
   you press, so it needs a resting state, a chosen state and a cursor. */

button.chip {
  border: 1px solid transparent;
  font: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  padding: 0.34rem 0.75rem;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), transform 0.16s var(--spring),
    border-color 0.2s var(--ease);
}
button.chip:hover {
  border-color: color-mix(in srgb, var(--primary) 35%, transparent);
}
button.chip.on {
  background: var(--primary);
  color: var(--paper);
  box-shadow: 0 2px 0 0 var(--deep);
}
button.chip.on svg {
  color: inherit;
}

/* A row of chips wider than the screen scrolls sideways rather than wrapping to
   four lines and pushing the content below the fold. */
.scroll-x {
  /* The display is declared here rather than assumed: this class is used on its
     own in the markup, and without it the `gap` below does nothing and the row
     wraps instead of scrolling — which is exactly the overflow it exists to
     prevent. `max-width: 100%` keeps the scroller inside its grid track. */
  display: flex;
  align-items: center;
  gap: 0.5rem;
  max-width: 100%;
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 0.2rem;
  scroll-snap-type: x proximity;
}
.scroll-x::-webkit-scrollbar {
  display: none;
}
.scroll-x > * {
  /* A flex child shrinks by default, which in a nowrap row turns "scrolls
     sideways" into "every chip squashed". They keep their width and the row
     scrolls, which is the whole point. */
  flex: none;
  scroll-snap-align: start;
}

.wrap-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  min-width: 0;
}

/* The receipt a buyer just attached, shown back to them before they commit. */
.receipt-preview {
  display: block;
  max-height: 220px;
  width: auto;
  max-width: 100%;
  border-radius: 12px;
  border: 1px solid var(--sand);
  object-fit: contain;
  background: var(--sand-deep);
}
/* The same class also wraps a preview, for the panels that show a filename when
   the receipt was a PDF rather than a photograph. */
.receipt-preview > img {
  display: block;
  width: auto;
  max-width: 100%;
  max-height: 218px;
  border-radius: 11px;
  object-fit: contain;
}
.receipt-preview > p {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  padding: 0.6rem 0.75rem;
}
.receipt-preview > p svg {
  width: 16px;
  height: 16px;
  flex: none;
}

/* A one-line verdict under an amount box: neutral, encouraging, or wrong. */
.tiny.good {
  color: var(--good);
}
.tiny.bad {
  color: var(--danger);
}

/* ═════════════════════════════════════════════════════════════════════════════
   THE COLOUR-CODED LAYER
   Every button says what it does in colour, every page says where you are in
   colour, and the two never fight: a button's colour comes from its errand
   (paying is gold, ringing is red, confirming is green) and the page's colour
   comes from its address. Anything the code did not name wears the page's own
   colour, which is never wrong.

   The tone tokens below are the whole vocabulary. /js/paint.js writes
   `data-tone` onto buttons and `data-page-tone` onto <body>; nothing here needs
   to know which page it is on.
   ════════════════════════════════════════════════════════════════════════════ */

:root {
  /* `teal` is the house tone — the one everything unnamed falls back to — so it
     is the badge's green rather than the teal the site used to wear. The rest of
     the vocabulary is unchanged: it codes meaning, not brand. */
  --tone-teal: #147c06;
  --tone-green: #3e8f1e;
  --tone-cyan: #1583b4;
  --tone-blue: #0b4f9c; /* the blue of the wordmark on the badge */
  --tone-indigo: #4a51bd;
  --tone-violet: #7448c0;
  --tone-rose: #b8477e;
  --tone-orange: #e2601a; /* the heart */
  --tone-slate: #55666d;
}

/* One rule per colour, matched on either attribute, so a button and the page
   it sits on are painted from the same line. */
[data-tone='teal'],
[data-page-tone='teal'] {
  --tone: var(--tone-teal);
  --tone-ink: #fff;
}
[data-tone='green'],
[data-page-tone='green'] {
  --tone: var(--tone-green);
  --tone-ink: #fff;
}
[data-tone='cyan'],
[data-page-tone='cyan'] {
  --tone: var(--tone-cyan);
  --tone-ink: #fff;
}
[data-tone='blue'],
[data-page-tone='blue'] {
  --tone: var(--tone-blue);
  --tone-ink: #fff;
}
[data-tone='indigo'],
[data-page-tone='indigo'] {
  --tone: var(--tone-indigo);
  --tone-ink: #fff;
}
[data-tone='violet'],
[data-page-tone='violet'] {
  --tone: var(--tone-violet);
  --tone-ink: #fff;
}
[data-tone='rose'],
[data-page-tone='rose'] {
  --tone: var(--tone-rose);
  --tone-ink: #fff;
}
[data-tone='red'],
[data-page-tone='red'] {
  --tone: var(--danger);
  --tone-ink: #fff;
}
[data-tone='orange'],
[data-page-tone='orange'] {
  --tone: var(--tone-orange);
  --tone-ink: #fff;
}
[data-tone='gold'],
[data-page-tone='gold'] {
  --tone: var(--gold);
  --tone-ink: #2b1d05;
}
[data-tone='slate'],
[data-page-tone='slate'] {
  --tone: var(--tone-slate);
  --tone-ink: #fff;
}
[data-tone='deep'],
[data-page-tone='deep'] {
  --tone: var(--deep);
  --tone-ink: #fff;
}
/* The fallback: wear whatever colour this page is. */
[data-tone='page'] {
  --tone: var(--page, var(--primary));
  --tone-ink: var(--page-ink, #fff);
}

/* The written-out form. A handful of buttons name their colour in the markup —
   `class="btn tone-green"` — and the painter deliberately leaves those alone.
   The class carries the same two tokens as the attribute so both spellings end
   up in the same place. `.tone-gold`, `.tone-teal`, `.tone-deep`, `.tone-red`
   and `.tone-face` are older and are set on `.btn` further up. */
.tone-green {
  --tone: var(--tone-green);
  --tone-ink: #fff;
}
.tone-cyan {
  --tone: var(--tone-cyan);
  --tone-ink: #fff;
}
.tone-blue {
  --tone: var(--tone-blue);
  --tone-ink: #fff;
}
.tone-indigo {
  --tone: var(--tone-indigo);
  --tone-ink: #fff;
}
.tone-violet {
  --tone: var(--tone-violet);
  --tone-ink: #fff;
}
.tone-rose {
  --tone: var(--tone-rose);
  --tone-ink: #fff;
}
.tone-orange {
  --tone: var(--tone-orange);
  --tone-ink: #fff;
}
.tone-slate {
  --tone: var(--tone-slate);
  --tone-ink: #fff;
}
.btn.tone-green,
.btn.tone-cyan,
.btn.tone-blue,
.btn.tone-indigo,
.btn.tone-violet,
.btn.tone-rose,
.btn.tone-orange,
.btn.tone-slate {
  --btn-bg: var(--tone);
  --btn-ink: var(--tone-ink);
}

/* The page's own colour, derived once on <body> and inherited by everything
   that wants a tint of it. */
body[data-page-tone] {
  --page: var(--tone);
  --page-ink: var(--tone-ink, #fff);
  --page-soft: color-mix(in srgb, var(--tone) 12%, var(--paper));
  --page-line: color-mix(in srgb, var(--tone) 42%, var(--sand));
  --page-deep: color-mix(in srgb, var(--tone) 72%, #06211d);
}

/* A painted button. `--btn-bg` is the one variable the whole button system is
   built on, so a tone is one line and every existing effect — the plinth, the
   press, the thumb light — follows for free. */
.btn[data-tone] {
  --btn-bg: var(--tone);
  --btn-ink: var(--tone-ink, #fff);
}
/* The flat variants keep their colour as ink rather than as a face, otherwise a
   quiet button stops being quiet. */
.btn.quiet[data-tone],
.btn.ghost[data-tone] {
  --btn-bg: transparent;
  --btn-ink: color-mix(in srgb, var(--tone) 78%, var(--ink));
}
.btn.ghost[data-tone] {
  border-color: color-mix(in srgb, var(--tone) 45%, var(--sand));
}
.btn.quiet[data-tone]:hover,
.btn.ghost[data-tone]:hover {
  background: color-mix(in srgb, var(--tone) 10%, transparent);
  color: var(--tone);
}

/* ── hyperresponsive ─────────────────────────────────────────────────────────
   Three things make a control feel instant: no 300ms tap delay, no blue flash
   from the browser's own highlight, and a reaction that starts on touch rather
   than on release. The first two are these declarations; the third is
   engine.js, which adds `.pressing` on pointerdown. The transitions are short
   on purpose — a button that takes a quarter of a second to acknowledge a press
   feels broken on a slow telephone even when the page is fast. */

button,
a,
.btn,
.pick,
.choice,
.chip,
.quick-item,
.quick-trigger,
.steprail-cell,
.langpick button {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.btn {
  transition:
    transform 0.11s var(--spring),
    box-shadow 0.11s var(--ease),
    background 0.14s var(--ease),
    filter 0.14s var(--ease);
}

/* One focus ring for the whole site, in the colour of the thing focused. It is
   drawn outside the control so it never changes a layout. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 3px solid color-mix(in srgb, var(--tone, var(--page, var(--primary))) 70%, transparent);
  outline-offset: 3px;
  border-radius: 6px;
}

/* ── the page wears its colour ───────────────────────────────────────────── */

/* A hairline of the page's colour under the top bar, so the colour is visible
   even on a page made mostly of white cards. */
body[data-page-tone] .appbar.top,
body[data-page-tone] .top {
  border-bottom: 2px solid var(--page);
}
/* The wash behind the page takes the same colour, faintly. */
body[data-page-tone] {
  background-image: radial-gradient(120% 60% at 50% -10%, color-mix(in srgb, var(--page) 16%, transparent), transparent 62%);
}
/* Section and page headings are ruled and inked in it. */
body[data-page-tone] .sec-head {
  border-bottom: 1px solid var(--page-line, var(--sand));
  padding-bottom: 0.55rem;
}
body[data-page-tone] .sec-head h2 .ti,
body[data-page-tone] .sec-head h2 .am,
body[data-page-tone] .pagehead h1 .ti,
body[data-page-tone] .pagehead h1 .am {
  color: var(--page-deep, var(--primary));
}
body[data-page-tone] .pagehead .crumbs a {
  color: var(--page-deep, var(--primary));
}
/* And the current entry in the bottom bar is lit by it. */
body[data-page-tone] .barbtn.on,
body[data-page-tone] .barbtn[aria-current='page'] {
  color: color-mix(in srgb, var(--page) 60%, #fff);
}

/* ═════════════════════════════════════════════════════════════════════════════
   THE QUICK DOCK
   One glowing button halfway down the right-hand edge, on every page, opening
   into the handful of things a reader most often wants next. It breathes so it
   can be found without being hunted for, and it is placed where a thumb already
   is on a telephone held in one hand.
   ════════════════════════════════════════════════════════════════════════════ */

.quickdock {
  position: fixed;
  inset-inline-end: max(0.7rem, env(safe-area-inset-right, 0px));
  top: 50%;
  transform: translateY(-50%);
  z-index: 70;
  display: grid;
  justify-items: end;
  gap: 0.5rem;
  pointer-events: none;
}
.quickdock > * {
  pointer-events: auto;
}

.quick-items {
  display: grid;
  justify-items: end;
  gap: 0.42rem;
}
.quickdock[data-open='false'] .quick-items {
  visibility: hidden;
  pointer-events: none;
}

.quick-item {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.42rem 0.5rem 0.42rem 0.9rem;
  border: 0;
  border-radius: 999px;
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: blur(10px) saturate(1.3);
  -webkit-backdrop-filter: blur(10px) saturate(1.3);
  color: var(--ink);
  font: inherit;
  font-size: 0.86rem;
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.7) inset,
    0 10px 26px -14px rgba(8, 48, 44, 0.8);
  opacity: 0;
  transform: translateX(14px) scale(0.92);
  transition: transform 0.16s var(--spring), opacity 0.16s var(--ease);
}
.quickdock[data-open='true'] .quick-item {
  opacity: 1;
  transform: none;
  transition-delay: var(--stagger, 0ms);
}
.quick-item:hover {
  background: var(--paper);
  transform: translateX(-2px);
}
.quick-word {
  white-space: nowrap;
}
.quick-glyph {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex: none;
  border-radius: 50%;
  background: var(--tone, var(--primary));
  color: var(--tone-ink, #fff);
}
.quick-glyph svg {
  width: 16px;
  height: 16px;
}

/* The trigger. Two rings leave it every few seconds; the core holds the icon. */
.quick-trigger {
  position: relative;
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
}
.quick-core {
  position: relative;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  background: linear-gradient(160deg, color-mix(in srgb, var(--page, var(--primary)) 78%, #fff), var(--page, var(--primary)));
  color: #fff;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.5),
    0 calc(4px * var(--lift)) 0 color-mix(in srgb, var(--page, var(--primary)) 55%, #000),
    0 18px 34px -14px rgba(8, 48, 44, 0.9);
  transition: transform 0.16s var(--spring);
}
.quick-core svg {
  width: 24px;
  height: 24px;
}
.quick-trigger:hover .quick-core {
  transform: scale(1.05);
}
.quick-trigger.pressing .quick-core {
  transform: scale(0.94);
}
.quick-ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: color-mix(in srgb, var(--page, var(--primary)) 45%, transparent);
  animation: quick-bubble 3.2s var(--ease) infinite;
}
.quick-ring.two {
  animation-delay: 1.6s;
}
.quickdock[data-open='true'] .quick-ring {
  animation-play-state: paused;
  opacity: 0;
}
@keyframes quick-bubble {
  0% {
    transform: scale(0.86);
    opacity: 0.55;
  }
  70% {
    transform: scale(1.75);
    opacity: 0;
  }
  100% {
    transform: scale(1.75);
    opacity: 0;
  }
}

/* On a short screen the dock sits a little above centre so it never lands on
   the thing the reader is reading. */
@media (max-height: 560px) {
  .quickdock {
    top: 42%;
  }
}
@media print {
  .quickdock {
    display: none;
  }
}

/* ═════════════════════════════════════════════════════════════════════════════
   THE SMALL SHEETS — the first visit, and the offer to install
   ════════════════════════════════════════════════════════════════════════════ */

/* A mini sheet is a question, not a page: it takes the height of its answers
   and sits low on a telephone, near the thumb that has to answer it. */
.sheet.mini {
  place-items: end center;
  padding: 0.8rem;
}
@media (min-width: 720px) {
  .sheet.mini {
    place-items: center;
  }
}
.sheet-card.mini {
  width: min(440px, 100%);
  padding: 1.05rem 1.1rem 1.15rem;
  border-radius: calc(var(--radius) + 6px);
  border-top: 4px solid var(--page, var(--primary));
  animation: sheet-pop 0.24s var(--spring) both;
}
.sheet-card.mini h2 {
  font-size: 1.05rem;
  line-height: 1.35;
  margin: 0;
}
.sheet-card.mini .lede {
  font-size: 0.88rem;
  margin-top: 0.35rem;
}
.sheet-card.mini .sheet-foot {
  margin-top: 0.85rem;
  padding-top: 0.7rem;
}
.sheet-pair {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  align-items: center;
}
@keyframes sheet-pop {
  from {
    opacity: 0;
    transform: translateY(18px) scale(0.97);
  }
}

/* Three languages, three small buttons, one row even on a narrow telephone —
   the reader cannot read the explanation yet, so there is nothing to explain. */
.langpick.mini {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.45rem;
  margin-top: 0.75rem;
}
@media (max-width: 520px) {
  .langpick.mini {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
.langpick.mini button {
  padding: 0.65rem 0.35rem;
  font-size: 1.02rem;
  border-color: color-mix(in srgb, var(--tone, var(--primary)) 35%, var(--sand-deep));
}
.langpick.mini button small {
  font-size: 0.62rem;
  margin-top: 0.15rem;
}
.langpick button[aria-pressed='true'] {
  border-color: var(--tone, var(--primary));
  background: color-mix(in srgb, var(--tone, var(--primary)) 12%, var(--surface));
}

/* The second question: the services themselves, as small coloured buttons. */
.pickgrid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.45rem;
  margin-top: 0.75rem;
}
@media (min-width: 560px) {
  .pickgrid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
.pickgrid .pick {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr);
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.6rem;
  border-radius: 14px;
  border-color: color-mix(in srgb, var(--tone, var(--primary)) 30%, var(--sand));
  text-decoration: none;
  font-size: 0.86rem;
  font-weight: 700;
  line-height: 1.25;
}
.pickgrid .pick:hover {
  border-color: var(--tone, var(--primary));
  background: color-mix(in srgb, var(--tone, var(--primary)) 8%, var(--paper));
}
.pick-glyph {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 10px;
  background: color-mix(in srgb, var(--tone, var(--primary)) 16%, var(--paper));
  color: var(--tone, var(--primary));
}
.pick-glyph svg {
  width: 17px;
  height: 17px;
}
.pick-word {
  min-width: 0;
  overflow-wrap: anywhere;
}

.installcard .lede {
  margin: 0.4rem 0 0;
}

/* ═════════════════════════════════════════════════════════════════════════════
   THE FRONT PAGE — one screenful, then everything else
   ════════════════════════════════════════════════════════════════════════════ */

.heroblock {
  display: grid;
  gap: 1rem;
  align-content: center;
  /* As tall as the visible window and no taller. `svh` rather than `vh` because
     on a telephone `vh` measures the window with the browser's own bars hidden,
     which is a screenful the reader cannot see. The two fixed bars and the home
     indicator are already padding on <body>, so they come off here. */
  min-height: calc(100svh - var(--bar-top) - var(--bar-bottom) - var(--safe-bottom) - 0.5rem);
  padding-block: 0.9rem 2.2rem;
  position: relative;
}
@media (min-width: 940px) {
  .heroblock {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    align-items: center;
    gap: 2rem;
    padding-block: 1.4rem 2.6rem;
  }
  /* The words first in the reading order on a wide screen, the picture beside
     them; on a telephone the picture leads, because it is what a photograph is
     for. */
  .hero-words {
    order: -1;
  }
}
.hero-stage-wrap {
  min-width: 0;
}
.hero-stage-wrap .stage {
  aspect-ratio: 16 / 10;
  max-height: 42svh;
}
@media (min-width: 940px) {
  .hero-stage-wrap .stage {
    aspect-ratio: 4 / 3;
    max-height: none;
  }
}

.hero-words {
  display: grid;
  gap: 0.55rem;
  align-content: center;
  min-width: 0;
}
.hero-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  padding: 0.28rem 0.7rem;
  justify-self: start;
  border-radius: 999px;
  background: color-mix(in srgb, var(--page, var(--primary)) 12%, var(--paper));
  color: var(--page-deep, var(--primary));
  font-size: 0.76rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.hero-eyebrow svg {
  width: 14px;
  height: 14px;
}
.hero-title {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(1.85rem, 6.2vw, 3.2rem);
  line-height: 1.08;
  letter-spacing: -0.015em;
}
.hero-lede {
  margin: 0;
  color: var(--muted);
  font-size: clamp(0.95rem, 2.4vw, 1.08rem);
  max-width: 46ch;
}
.hero-acts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5rem;
  margin-top: 0.35rem;
}
@media (min-width: 560px) {
  .hero-acts {
    display: flex;
    flex-wrap: wrap;
  }
}
.hero-acts .btn {
  min-width: 0;
}
.hero-acts .btn span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* On a small screen the big buttons stop being big — four of them at 54px each
   is more than a first screen can spare. */
@media (max-width: 559px) {
  .hero-acts .btn.big {
    padding: 0.7rem 0.8rem;
    min-height: 46px;
    font-size: 0.9rem;
  }
}
.hero-trust {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem 1rem;
  margin: 0.35rem 0 0;
  padding: 0;
  list-style: none;
  color: var(--muted);
  font-size: 0.82rem;
  font-weight: 600;
}
.hero-trust li {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}
.hero-trust svg {
  width: 15px;
  height: 15px;
  color: var(--page, var(--primary));
}

/* The arrow at the bottom of the first screen: the only thing on the page whose
   job is to admit that there is more of it. */
.hero-more {
  position: absolute;
  bottom: 0.5rem;
  inset-inline: 0;
  justify-self: center;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  margin-inline: auto;
  border-radius: 50%;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  color: var(--page, var(--primary));
  box-shadow: 0 8px 20px -12px rgba(8, 48, 44, 0.8);
  animation: hero-nudge 2.4s var(--ease) infinite;
}
.hero-more svg {
  width: 18px;
  height: 18px;
  transform: rotate(90deg);
}
@keyframes hero-nudge {
  0%,
  100% {
    transform: translateY(0);
  }
  55% {
    transform: translateY(5px);
  }
}
@media (max-height: 620px) {
  .hero-more {
    display: none;
  }
}

/* ═════════════════════════════════════════════════════════════════════════════
   THE BOOKING RAIL
   Seven named stops rather than seven dots, each in its own colour, the finished
   ones pressable. Under the form, a bar that holds the way back and the running
   total above the navigation bar.
   ════════════════════════════════════════════════════════════════════════════ */

.steprail {
  display: flex;
  gap: 0.35rem;
  margin: 0.7rem 0 0;
  padding: 0 0 0.3rem;
  list-style: none;
  overflow-x: auto;
  scrollbar-width: none;
}
.steprail::-webkit-scrollbar {
  display: none;
}
.steprail li {
  flex: 0 0 auto;
}
.steprail-cell {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.34rem 0.7rem 0.34rem 0.34rem;
  border: 1.5px solid var(--sand);
  border-radius: 999px;
  background: var(--paper);
  color: var(--muted);
  font: inherit;
  font-size: 0.79rem;
  font-weight: 700;
  white-space: nowrap;
  cursor: default;
  transition: transform 0.13s var(--spring), border-color 0.16s var(--ease), color 0.16s var(--ease);
}
button.steprail-cell {
  cursor: pointer;
}
button.steprail-cell:hover {
  transform: translateY(-2px);
  border-color: var(--tone, var(--primary));
  color: var(--ink);
}
.steprail-mark {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  flex: none;
  border-radius: 50%;
  background: color-mix(in srgb, var(--tone, var(--primary)) 14%, var(--paper));
  color: var(--tone, var(--primary));
}
.steprail-mark svg {
  width: 13px;
  height: 13px;
}
.steprail li[data-state='done'] .steprail-cell {
  color: var(--ink);
  border-color: color-mix(in srgb, var(--tone) 40%, var(--sand));
}
.steprail li[data-state='done'] .steprail-mark {
  background: var(--tone);
  color: #fff;
}
.steprail li[data-state='now'] .steprail-cell {
  background: linear-gradient(180deg, color-mix(in srgb, var(--tone) 90%, #fff), var(--tone));
  border-color: transparent;
  color: var(--tone-ink, #fff);
  box-shadow: 0 calc(3px * var(--lift)) 0 color-mix(in srgb, var(--tone) 58%, #000);
}
.steprail li[data-state='now'] .steprail-mark {
  background: rgba(255, 255, 255, 0.92);
  color: var(--tone);
}
.steprail li[data-state='todo'] .steprail-cell {
  opacity: 0.72;
}

.stepnav {
  position: sticky;
  bottom: calc(var(--bar-bottom) + var(--safe-bottom) + 0.5rem);
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  margin: 1.2rem 0 0.4rem;
  padding: 0.5rem 0.6rem 0.5rem 0.5rem;
  border-radius: 999px;
  border: 1px solid var(--sand);
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: blur(12px) saturate(1.3);
  -webkit-backdrop-filter: blur(12px) saturate(1.3);
  box-shadow: 0 16px 34px -22px rgba(8, 48, 44, 0.9);
}
.stepnav-total {
  display: grid;
  justify-items: end;
  padding-inline-end: 0.5rem;
  line-height: 1.15;
}
.stepnav-total small {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--muted);
}
.stepnav-total b {
  font-size: 1rem;
  color: var(--page, var(--primary));
}

/* ═════════════════════════════════════════════════════════════════════════════
   THE PAGE TRANSITION
   Pressing a link raises the logo over the page, in the middle, with the name of
   where the reader is going written under it. It covers the wait; it does not
   cause it — the navigation was never held back for the animation.
   ════════════════════════════════════════════════════════════════════════════ */

.appload-stack {
  display: grid;
  justify-items: center;
  gap: 0.85rem;
  padding: 1.2rem 1.6rem;
}
.appload-pulse {
  position: absolute;
  inset: -10px;
  z-index: 0;
  border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--page, var(--primary)) 30%, transparent), transparent 68%);
  animation: appload-pulse 1.5s var(--ease) infinite;
}
.appload-mark img {
  position: relative;
  z-index: 1;
}
@keyframes appload-pulse {
  0% {
    transform: scale(0.82);
    opacity: 0.75;
  }
  70%,
  100% {
    transform: scale(1.4);
    opacity: 0;
  }
}
.appload-ring {
  border-top-color: var(--page, var(--glow));
}
.appload-words {
  display: grid;
  justify-items: center;
  gap: 0.15rem;
  text-align: center;
  animation: appload-words 0.3s var(--ease) both;
}
.appload-lede {
  font-size: 0.74rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.appload-where {
  font-family: var(--display);
  font-size: clamp(1.15rem, 4.5vw, 1.6rem);
  font-weight: 700;
  color: var(--page-deep, var(--primary));
  line-height: 1.15;
}
@keyframes appload-words {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
}
/* A thin bar that fills while the next page is fetched. It is honest about
   being indeterminate: it sweeps rather than claiming a percentage. */
.appload-track {
  width: min(220px, 60vw);
  height: 3px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--page, var(--primary)) 16%, transparent);
  overflow: hidden;
}
.appload-track > i {
  display: block;
  width: 40%;
  height: 100%;
  border-radius: inherit;
  background: var(--page, var(--primary));
  animation: appload-sweep 1.1s var(--ease) infinite;
}
@keyframes appload-sweep {
  from {
    transform: translateX(-105%);
  }
  to {
    transform: translateX(255%);
  }
}

/* Everything decorative above stops for a reader who has asked the operating
   system for less movement. The global damping already shortens the durations;
   these two would otherwise sit mid-animation and look broken. */
@media (prefers-reduced-motion: reduce) {
  .quick-ring,
  .hero-more,
  .appload-pulse {
    animation: none;
    opacity: 0;
  }
  .appload-track > i {
    width: 100%;
    animation: none;
  }
}

/* The four doors on the front page, and any other `.choice` row the painter has
   given a colour to: the ring takes the colour, the border takes a wash of it,
   and the arrow at the end stops being grey when the row is under the pointer. */
.choice[data-tone] {
  border-inline-start: 4px solid var(--tone);
}
.choice[data-tone]:hover {
  border-color: var(--tone);
}
.choice[data-tone] .ring {
  background: color-mix(in srgb, var(--tone) 14%, var(--paper));
  color: var(--tone);
}
.choice[data-tone]:hover > svg:last-child {
  color: var(--tone);
}

/* ═══════════════════════════════════════════════════════════════════════════
   THE NARROWEST SCREEN
   Everything above is written to fit any width. This block is the last stop
   for the one that is actually hardest — a 320-360px telephone held in one
   hand, which is what most of this site is read on.

   The rule the whole block serves: the page scrolls down and never sideways.
   A single element wider than the viewport shifts the entire layout, so what
   follows is the short list of things that are naturally wide — a brand name,
   a row of buttons, a drawer, a table, a wallet address — each given a way to
   get narrower rather than a way to push.
   ══════════════════════════════════════════════════════════════════════════ */

@media (max-width: 480px) {
  /* The gutter takes back nearly a centimetre on each side. `clamp` already
     scales it, but its floor was set for a 390px screen. */
  .wrap {
    padding-inline: 0.85rem;
  }

  /* The brand is the widest fixed thing on both bars. The mark shrinks, the
     name is allowed to shrink with it, and the transliteration under it goes:
     it is decoration, and it is the part that was setting the width. */
  .top-in {
    gap: 0.7rem;
    min-height: 62px;
  }
  .brand {
    flex: 0 1 auto;
    min-width: 0;
  }
  .brand .mark,
  .appbar .brand .mark {
    width: 32px;
    height: 32px;
  }
  .brand .words {
    min-width: 0;
  }
  .brand .name,
  .appbar .brand .name {
    font-size: 1.02rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .brand .name-en,
  .appbar .brand .name-en {
    display: none;
  }

  /* Buttons in a footer row go full width rather than wrapping into a ragged
     stack of different lengths — and a full-width button cannot overflow. */
  .form-foot,
  .sheet-foot {
    flex-wrap: wrap;
  }
  .form-foot > .btn,
  .sheet-foot > .btn {
    flex: 1 1 100%;
    justify-content: center;
  }

  /* Panels that hang off an edge take the width they are given, minus a thumb's
     width so the page behind is still visible and tappable. The full-screen
     veils (`.sheet`, `.drawer`) are left alone — they are meant to cover the
     screen; it is the card inside each of them that is sized here. */
  .barpop {
    width: min(360px, calc(100vw - 1rem));
    right: 0.5rem;
  }
  .drawer .sheet,
  .sheet-card {
    width: 100%;
    max-width: 100%;
  }

  /* A table never shrinks below the width of its own columns; it scrolls inside
     .tablewrap instead. Here it is allowed to start narrower, so that on most
     rows there is nothing to scroll at all. */
  table {
    min-width: 520px;
    font-size: 0.86rem;
  }
  thead th,
  tbody td {
    padding: 0.6rem 0.65rem;
  }

  /* Two-up grids that were still two-up at this width. */
  .credgrid,
  .row2,
  .grid2 {
    grid-template-columns: minmax(0, 1fr);
  }

  /* The strings with no spaces in them: addresses, hashes, references,
     generated passwords. They break mid-string rather than setting the width
     of the page. */
  .cred strong,
  .copyrow .v,
  .token,
  .codegrid code,
  .dispatch {
    font-size: 0.9rem;
    overflow-wrap: anywhere;
    word-break: break-word;
  }

  /* Headings are the other long word — a service title or an Ethiopic name with
     no break opportunity in it. */
  h1,
  h2,
  h3 {
    overflow-wrap: break-word;
  }
}
